From 6cf583341cd6e8d7ebc7f93c2a3afb33c53a3db1 Mon Sep 17 00:00:00 2001 From: taohe Date: Sat, 13 Jun 2026 00:45:14 +0800 Subject: [PATCH 01/18] docs: add TypeScript+Bun migration plan Co-Authored-By: Claude Fable 5 --- .../2026-06-13-typescript-bun-migration.md | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 docs/superpowers/plans/2026-06-13-typescript-bun-migration.md diff --git a/docs/superpowers/plans/2026-06-13-typescript-bun-migration.md b/docs/superpowers/plans/2026-06-13-typescript-bun-migration.md new file mode 100644 index 0000000..1b180ba --- /dev/null +++ b/docs/superpowers/plans/2026-06-13-typescript-bun-migration.md @@ -0,0 +1,139 @@ +# TypeScript + Bun Migration Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Migrate the entire AgentForge project to TypeScript only — Python backend ported to Bun-native TypeScript, Electron/React frontend converted from JS/JSX to TS/TSX — with Bun as the toolchain for build, run, test, and compile (replacing uv/pytest/PyInstaller/npm/node-test, and replacing Vite with `Bun.build`). + +**Architecture:** The Python single-file backend (`taskboard.py`, 5240 lines) becomes a modular TypeScript app in `backend/` running on Bun: `bun:sqlite` for `TaskDB`, `Bun.serve` for the HTTP API on `127.0.0.1:9712`, `Bun.spawn` for agent CLI execution, `cron-parser` for cron evaluation. Chat channels port to official TS SDKs (`@slack/socket-mode`, `@larksuiteoapi/node-sdk`) or plain `fetch` (Telegram). The REST API contract is preserved exactly so the React frontend keeps working unchanged. The Electron app keeps electron-forge for DMG packaging but drops `plugin-vite`; main/preload/renderer are bundled by `Bun.build` scripts. The backend binary for packaging is produced by `bun build --compile` instead of PyInstaller. + +**Tech Stack:** Bun ≥1.3 (runtime, test runner, bundler, single-file compiler, package manager), TypeScript 5 (strict), `bun:sqlite`, `cron-parser`, `@slack/web-api` + `@slack/socket-mode`, `@larksuiteoapi/node-sdk`, Electron 40 + electron-forge (packaging only), React 19, ESLint (typescript-eslint) + Prettier. + +**Porting convention (applies to every port task):** The existing Python/JS file named in the task is the authoritative spec — translate behavior 1:1 (same route paths, status codes, JSON field names, SQL schema, timestamps format, error strings that tests assert on). The pytest file(s) named in the task define the acceptance tests: port them to `bun:test` (`describe/test/expect`, `mock()` for monkeypatching) before or alongside the implementation, and they must pass. Where Python tests monkeypatch module attributes, design the TS module with injectable dependencies (constructor params or exported setters) so tests can substitute fakes. + +--- + +## File Structure + +``` +backend/ + package.json # name agentforge-backend; deps below + tsconfig.json # strict, moduleResolution bundler, types ["bun-types"] + bunfig.toml # [test] coverage settings + taskboard.ts # entry: parses port, calls runServer (compiled by `bun build --compile`) + src/ + types.ts # TaskStatus, ScheduleType, HeartbeatScheduleType, HeartbeatDecisionType, Task, Heartbeat interfaces + util.ts # getEnv, parseComparableDatetime, normalizeDatetimeForStorage, parseJsonObject + db.ts # TaskDB (bun:sqlite, Database with WAL; sync API ≙ Python's lock semantics) + bus.ts # InboundMessage/OutboundMessage types, MessageBus, Channel (abstract), UIChannel, busNotify helper (≙ BusAwareSchedulerMixin) + executor.ts # AgentExecutor (Bun.spawn, NDJSON line streaming) + skills.ts # skill dirs, link/unlink, write/remove skill on disk, frontmatter compose/parse + scheduler.ts # TaskScheduler (2s setInterval tick, heartbeats, skill sweep, codex/claude stream parsing, weixin status helper) + api.ts # route table ≙ TaskAPIHandler do_GET/POST/PUT/DELETE incl. CORS + CSRF checks + server.ts # runServer (Bun.serve), killStaleProcessOnPort, signal handling + channels/ + agent_utils.ts # parseAgentCommand, handleAgentCommand, resolveAgent + dir_utils.ts # parseDirCommand, handleDirCommand, extractWorkingDirWithClaude, resolveWorkingDir + telegram.ts # TelegramChannel via raw Bot API fetch long-polling + slack.ts # SlackChannel via @slack/socket-mode + @slack/web-api + feishu.ts # FeishuChannel + FeishuStreamWriter via @larksuiteoapi/node-sdk WSClient + weixin.ts # WeixinChannel spawning channels/weixin_bridge (bridge converted to TS) + tests/ # ported from tests/*.py, one .test.ts per pytest file +taskboard-electron/ + src/main.ts, src/preload.ts, src/renderer.ts + src/renderer/App.tsx, main.tsx, channelsSettings.ts, dateTime.ts, traceSteps.ts (+ .test.ts) + scripts/build.ts # Bun.build for main/preload/renderer (replaces plugin-vite + vite configs) + scripts/dev.ts # watch build + spawn electron (dev mode) + scripts/build-backend.ts# bun build --compile of backend (replaces build-backend.mjs) + tsconfig.json +``` + +Deleted at the end: `taskboard.py`, `taskboard_bus.py`, `channels/*.py`, `tests/*.py`, `pyproject.toml`, `uv.lock`, `taskboard.spec`, `vite.*.config.mjs`, `scripts/build-backend.mjs`, `package-lock.json`, `__pycache__/`. + +## Pytest → bun test mapping + +| Python test file | TS test file (backend/tests/) | +|---|---| +| test_taskdb.py | taskdb.test.ts | +| test_taskboard_bus.py | bus.test.ts | +| test_execute_task.py | execute-task.test.ts | +| test_scheduler_logic.py | scheduler-logic.test.ts | +| test_scheduler_more.py | scheduler-more.test.ts | +| test_codex_streaming_events.py | codex-streaming-events.test.ts | +| test_skill_patterns.py | skill-patterns.test.ts | +| test_api_handler.py / _more.py | api-handler.test.ts / api-handler-more.test.ts | +| test_taskboard_gaps.py / gaps2.py | gaps.test.ts / gaps2.test.ts | +| test_telegram_*.py | telegram-*.test.ts | +| test_slack_*.py | slack-*.test.ts | +| test_feishu_*.py | feishu-*.test.ts | +| test_weixin_*.py | weixin-*.test.ts | +| (frontend) *.test.mjs | same dir, *.test.ts under bun test | + +Coverage: pytest gate was `fail_under = 90`. Backend `bunfig.toml` sets `[test] coverage = true, coverageThreshold = 0.9` (line coverage) scoped to `backend/src`. + +## Tasks + +### Task 1: Scaffold Bun + TS backend workspace +- [ ] `backend/package.json` with deps `cron-parser`, `@slack/web-api`, `@slack/socket-mode`, `@larksuiteoapi/node-sdk`; devDeps `typescript`, `@types/bun` (or `bun-types`). +- [ ] `backend/tsconfig.json` (strict true, module ESNext, moduleResolution bundler, noEmit). +- [ ] `backend/bunfig.toml` test coverage config (threshold enforced once suites land). +- [ ] Scripts: `"check": "tsc --noEmit && bun test"`, `"start": "bun taskboard.ts"`, `"compile": "bun build --compile ..."`. +- [ ] Smoke: `cd backend && bun install && bun x tsc --noEmit` (empty src OK) — PASS. + +### Task 2: Core — types, util, db, bus (+ tests) +Spec: `taskboard.py:117-1596` and `taskboard_bus.py` (whole file). +- [ ] Port enums/dataclasses → `src/types.ts`; helpers → `src/util.ts`. +- [ ] Port `TaskDB` → `src/db.ts` on `bun:sqlite` — identical schema/DDL, same method surface (camelCase), `transaction()` via `db.transaction`. +- [ ] Port `taskboard_bus.py` → `src/bus.ts` (queues become arrays + waiters; `getInbound(timeout)` async). +- [ ] Port `tests/test_taskdb.py` → `backend/tests/taskdb.test.ts`; `tests/test_taskboard_bus.py` → `bus.test.ts`. +- [ ] Run `bun test` — PASS; `tsc --noEmit` — clean. Commit. + +### Task 3: Executor, skills, scheduler (+ tests) +Spec: `taskboard.py:1597-3798`. +- [ ] `src/executor.ts`: `AgentExecutor.run()` — claude/codex CLI invocation, NDJSON streaming via `Bun.spawn` stdout reader. +- [ ] `src/skills.ts`: skill dirs, sanitize/link/unlink/write/remove, frontmatter compose/parse. +- [ ] `src/scheduler.ts`: `TaskScheduler` — tick loop (2s), due tasks/heartbeats, delayed scheduling, heartbeat decision parsing, skill sweep + distill, codex/claude event parsing (`_parse_and_store_event` et al.), task lifecycle (`submit/cancel/retry`, dependency DAG, `_on_task_completed/_failed`), output listeners. +- [ ] Port the six pytest files listed in the mapping table for this area; design injectable seams where pytest monkeypatches (`_run_agent_command`, `subprocess.Popen` → injectable spawn fn). +- [ ] `bun test` PASS, `tsc` clean. Commit. + +### Task 4: HTTP API + server entry (+ tests) +Spec: `taskboard.py:3799-5240`. +- [ ] `src/api.ts`: every route in `do_GET/do_POST/do_PUT/do_DELETE` with identical paths, payload validation (incl. `_validate_heartbeat_payload`), status codes, CORS allowlist + CSRF check. +- [ ] `src/server.ts`: `runServer(port=9712)` on `Bun.serve` bound to 127.0.0.1, stale-process kill, SIGINT/SIGTERM shutdown; `taskboard.ts` entry. +- [ ] Port `test_api_handler.py`, `test_api_handler_more.py` (drive `api.ts` handler with `Request` objects). +- [ ] `bun test` PASS; manual smoke `bun taskboard.ts` + `curl http://127.0.0.1:9712/api/health`. Commit. + +### Task 5: Channels (+ tests) — parallel per channel +Spec: `channels/*.py`; bus/db/scheduler APIs from Tasks 2-3. +- [ ] `agent_utils.ts`, `dir_utils.ts` + inline coverage via channel tests. +- [ ] `telegram.ts` (fetch long-poll, command parsing, forwarded-message formatting, MarkdownV2 escaping) + 4 telegram test files. +- [ ] `slack.ts` (socket mode events, mention/DM handling, commands status/cancel/resume, reactions, threads) + 2 slack test files. +- [ ] `feishu.ts` (WSClient lifecycle, stream writer with debounced card patch, trace formatting, image upload) + 6 feishu test files. +- [ ] `weixin.ts` (bridge process management, QR login flow, status) + convert `channels/weixin_bridge/index.mjs` → TS + 2 weixin test files. +- [ ] `bun test` PASS for all. Commit per channel. + +### Task 6: Electron app → TypeScript +- [ ] `src/main.js`→`main.ts` (typed; dev spawns `bun backend/taskboard.ts` from project root instead of `uv run taskboard.py`), `preload.js`→`preload.ts`, `renderer.js`→`renderer.ts`. +- [ ] `renderer/App.jsx`→`App.tsx`, `main.jsx`→`main.tsx`, `channelsSettings.mjs`/`dateTime.mjs`/`traceSteps.mjs`→`.ts`, their tests →`.test.ts` (bun test, TZ pinned in bunfig/script). +- [ ] `taskboard-electron/tsconfig.json` (strict; `jsx: react-jsx`; DOM libs). +- [ ] ESLint flat config gains typescript-eslint; Prettier globs updated to ts/tsx. +- [ ] Gate: `bun x tsc --noEmit`, `bun run lint`, `bun run format:check`, `bun test` all PASS. Commit. + +### Task 7: Bun toolchain (build/run/compile/package) +- [ ] `scripts/build.ts`: `Bun.build` — main (`target: node`, `external: ['electron']`, outdir `.bun/build`), preload (cjs), renderer (tsx + index.html, outdir `.bun/renderer`). +- [ ] `scripts/dev.ts`: watch-rebuild + launch electron, renderer reload (reuse chokidar). +- [ ] `scripts/build-backend.ts`: `bun build --compile ../backend/taskboard.ts --outfile resources/taskboard`. +- [ ] `forge.config.js`→`forge.config.ts` (or keep .js minimal): drop plugin-vite, point `main` at `.bun/build/main.js`, hook prePackage → `bun scripts/build.ts && bun scripts/build-backend.ts`. +- [ ] Remove vite configs/deps; `bun install` to produce `bun.lock`; delete `package-lock.json`. +- [ ] Gate: `bun run start` opens app against built renderer; `bun scripts/build-backend.ts` produces working binary (`./resources/taskboard` + curl health). Commit. + +### Task 8: Makefile, CI, docs, delete Python, final verification +- [ ] Makefile: `check` = `cd backend && bun run check`; `build-backend` = bun compile; install-deps = `bun install` both dirs; remove uv/pyinstaller targets. +- [ ] `.github/workflows/ci.yml`: `oven-sh/setup-bun@v2`; backend job `cd backend && bun install && bun run check`; frontend job bun install/lint/format/test/build. +- [ ] Update `AGENTS.md`, `README.md`, `README.zh.md`, `docs/` command references. +- [ ] Delete all Python sources + uv/pytest/ruff config (list in File Structure section). +- [ ] Final gate: backend `bun run check` (tsc + tests + coverage ≥90%), frontend lint/format/test/build:check, compiled binary smoke test, `git status` shows no stray Python. Commit. + +## Self-Review Notes +- Spec coverage: every Python module and test file is assigned to a task; frontend files enumerated; toolchain (build/run/compile) covered by Tasks 1, 7, 8. +- Known risk areas called out: pytest monkeypatching → injectable seams (Task 3/5); Slack/Feishu SDK API differences (Task 5); electron-forge without plugin-vite (Task 7). Each has a verification gate that must pass before moving on. +- Adaptation note: per-step full code listings are intentionally replaced by "Python source = spec + ported tests = acceptance" because the migration's source of truth already exists in-repo; embedding 24k lines of code in the plan would duplicate the spec without adding safety. From 733ef9d79541f01014d5e2ac435a173d8696b24f Mon Sep 17 00:00:00 2001 From: taohe Date: Sat, 13 Jun 2026 00:48:23 +0800 Subject: [PATCH 02/18] feat(backend): scaffold Bun+TS workspace with core types/util/log Co-Authored-By: Claude Fable 5 --- backend/bun.lock | 168 ++++++++++++++++++++++++++++++++++++ backend/bunfig.toml | 5 ++ backend/package.json | 24 ++++++ backend/src/log.ts | 59 +++++++++++++ backend/src/types.ts | 192 ++++++++++++++++++++++++++++++++++++++++++ backend/src/util.ts | 110 ++++++++++++++++++++++++ backend/tsconfig.json | 20 +++++ 7 files changed, 578 insertions(+) create mode 100644 backend/bun.lock create mode 100644 backend/bunfig.toml create mode 100644 backend/package.json create mode 100644 backend/src/log.ts create mode 100644 backend/src/types.ts create mode 100644 backend/src/util.ts create mode 100644 backend/tsconfig.json diff --git a/backend/bun.lock b/backend/bun.lock new file mode 100644 index 0000000..983586f --- /dev/null +++ b/backend/bun.lock @@ -0,0 +1,168 @@ +{ + "lockfileVersion": 1, + "configVersion": 1, + "workspaces": { + "": { + "name": "agentforge-backend", + "dependencies": { + "@larksuiteoapi/node-sdk": "^1.55.0", + "@slack/socket-mode": "^2.0.4", + "@slack/web-api": "^7.13.0", + "cron-parser": "^5.4.0", + }, + "devDependencies": { + "@types/bun": "^1.3.5", + "typescript": "^5.9.3", + }, + }, + }, + "packages": { + "@larksuiteoapi/node-sdk": ["@larksuiteoapi/node-sdk@1.66.1", "", { "dependencies": { "axios": "~1.13.3", "lodash.identity": "^3.0.0", "lodash.merge": "^4.6.2", "lodash.pickby": "^4.6.0", "protobufjs": "^7.2.6", "qs": "^6.14.2", "ws": "^8.19.0" } }, "sha512-W1rIAs/8Oc/rEYuWc0sxGvR8iLwd8p5D2RS4ODMqs8htIxK8yIa8sb22EDv/OEBqUpKXZaNLydTz7Oq8HOQROg=="], + + "@protobufjs/aspromise": ["@protobufjs/aspromise@1.1.2", "", {}, "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ=="], + + "@protobufjs/base64": ["@protobufjs/base64@1.1.2", "", {}, "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg=="], + + "@protobufjs/codegen": ["@protobufjs/codegen@2.0.5", "", {}, "sha512-zgXFLzW3Ap33e6d0Wlj4MGIm6Ce8O89n/apUaGNB/jx+hw+ruWEp7EwGUshdLKVRCxZW12fp9r40E1mQrf/34g=="], + + "@protobufjs/eventemitter": ["@protobufjs/eventemitter@1.1.1", "", {}, "sha512-vW1GmwMZNnL+gMRaovlh9yZX74kc+TTU3FObkkurpMaRtBfLP3ldjS9KQWlwZgraRE0+dheEEoAxdzcJQ8eXZg=="], + + "@protobufjs/fetch": ["@protobufjs/fetch@1.1.1", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.1" } }, "sha512-GpptLrs57adMSuHi3VNj0mAF8dwh36LMaYF6XyJ6JMWlVsc+t42tm1HSEDmOs3A8fC9yyeisgLhsTVQokOZ0zw=="], + + "@protobufjs/float": ["@protobufjs/float@1.0.2", "", {}, "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ=="], + + "@protobufjs/path": ["@protobufjs/path@1.1.2", "", {}, "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA=="], + + "@protobufjs/pool": ["@protobufjs/pool@1.1.0", "", {}, "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw=="], + + "@protobufjs/utf8": ["@protobufjs/utf8@1.1.1", "", {}, "sha512-oOAWABowe8EAbMyWKM0tYDKi8Yaox52D+HWZhAIJqQXbqe0xI/GV7FhLWqlEKreMkfDjshR5FKgi3mnle0h6Eg=="], + + "@slack/logger": ["@slack/logger@4.0.1", "", { "dependencies": { "@types/node": ">=18" } }, "sha512-6cmdPrV/RYfd2U0mDGiMK8S7OJqpCTm7enMLRR3edccsPX8j7zXTLnaEF4fhxxJJTAIOil6+qZrnUPTuaLvwrQ=="], + + "@slack/socket-mode": ["@slack/socket-mode@2.0.7", "", { "dependencies": { "@slack/logger": "^4.0.1", "@slack/web-api": "^7.15.0", "@types/node": ">=18", "@types/ws": "^8", "eventemitter3": "^5", "ws": "^8" } }, "sha512-qYy07je71WnEHgRwmw12DlAnZLi5HXmdlI2WUzUK2LH/rYXQpP6uEg462S5CwfE8FoCKUdIigHtYnOOfzZH1lQ=="], + + "@slack/types": ["@slack/types@2.21.1", "", {}, "sha512-I8vmSjNYWsaxuWPx6dz4yeh0h7vRBWbgAMK14LEmblbZ404BtrPbXs6jDPx4cYgGf8msDGF4A9opLZBu21FViQ=="], + + "@slack/web-api": ["@slack/web-api@7.17.0", "", { "dependencies": { "@slack/logger": "^4.0.1", "@slack/types": "^2.21.0", "@types/node": ">=18", "@types/retry": "0.12.0", "axios": "^1.16.0", "eventemitter3": "^5.0.1", "form-data": "^4.0.4", "is-electron": "2.2.2", "is-stream": "^2", "p-queue": "^6", "p-retry": "^4", "retry": "^0.13.1" } }, "sha512-jejr34a8B4L5AS713wOAx1LAqNkW16HVMDEa6sYBvFDc/llUBl8hXaiI4BwF+Al+Sug19Vn2O7iokTVIhVvZ1Q=="], + + "@types/bun": ["@types/bun@1.3.14", "", { "dependencies": { "bun-types": "1.3.14" } }, "sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw=="], + + "@types/node": ["@types/node@25.9.3", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-603BddQMv3pUcr4U2dhujk83N2tTDVr/34wII2B6bJy6g+8WD6yUb11jszNs0gdi4PesVWl7ABt8nYMVpnLUcg=="], + + "@types/retry": ["@types/retry@0.12.0", "", {}, "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA=="], + + "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], + + "agent-base": ["agent-base@6.0.2", "", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], + + "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], + + "axios": ["axios@1.13.6", "", { "dependencies": { "follow-redirects": "^1.15.11", "form-data": "^4.0.5", "proxy-from-env": "^1.1.0" } }, "sha512-ChTCHMouEe2kn713WHbQGcuYrr6fXTBiu460OTwWrWob16g1bXn4vtz07Ope7ewMozJAnEquLk5lWQWtBig9DQ=="], + + "bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="], + + "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], + + "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="], + + "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="], + + "cron-parser": ["cron-parser@5.5.0", "", { "dependencies": { "luxon": "^3.7.1" } }, "sha512-oML4lKUXxizYswqmxuOCpgFS8BNUJpIu6k/2HVHyaL8Ynnf3wdf9tkns0yRdJLSIjkJ+b0DXHMZEHGpMwjnPww=="], + + "debug": ["debug@4.4.3", "", { "dependencies": { "ms": "^2.1.3" }, "peerDependencies": { "supports-color": "*" }, "optionalPeers": ["supports-color"] }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="], + + "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], + + "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], + + "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], + + "es-object-atoms": ["es-object-atoms@1.1.2", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw=="], + + "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], + + "eventemitter3": ["eventemitter3@5.0.4", "", {}, "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw=="], + + "follow-redirects": ["follow-redirects@1.16.0", "", { "peerDependencies": { "debug": "*" }, "optionalPeers": ["debug"] }, "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw=="], + + "form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="], + + "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], + + "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], + + "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], + + "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], + + "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], + + "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], + + "hasown": ["hasown@2.0.4", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="], + + "https-proxy-agent": ["https-proxy-agent@5.0.1", "", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="], + + "is-electron": ["is-electron@2.2.2", "", {}, "sha512-FO/Rhvz5tuw4MCWkpMzHFKWD2LsfHzIb7i6MdPYZ/KW7AlxawyLkqdy+jPZP1WubqEADE3O4FUENlJHDfQASRg=="], + + "is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="], + + "lodash.identity": ["lodash.identity@3.0.0", "", {}, "sha512-AupTIzdLQxJS5wIYUQlgGyk2XRTfGXA+MCghDHqZk0pzUNYvd3EESS6dkChNauNYVIutcb0dfHw1ri9Q1yPV8Q=="], + + "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], + + "lodash.pickby": ["lodash.pickby@4.6.0", "", {}, "sha512-AZV+GsS/6ckvPOVQPXSiFFacKvKB4kOQu6ynt9wz0F3LO4R9Ij4K1ddYsIytDpSgLz88JHd9P+oaLeej5/Sl7Q=="], + + "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="], + + "luxon": ["luxon@3.7.2", "", {}, "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew=="], + + "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], + + "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + + "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + + "ms": ["ms@2.1.3", "", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="], + + "p-finally": ["p-finally@1.0.0", "", {}, "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow=="], + + "p-queue": ["p-queue@6.6.2", "", { "dependencies": { "eventemitter3": "^4.0.4", "p-timeout": "^3.2.0" } }, "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ=="], + + "p-retry": ["p-retry@4.6.2", "", { "dependencies": { "@types/retry": "0.12.0", "retry": "^0.13.1" } }, "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ=="], + + "p-timeout": ["p-timeout@3.2.0", "", { "dependencies": { "p-finally": "^1.0.0" } }, "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg=="], + + "protobufjs": ["protobufjs@7.6.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.5", "@protobufjs/eventemitter": "^1.1.1", "@protobufjs/fetch": "^1.1.1", "@protobufjs/float": "^1.0.2", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.1", "@types/node": ">=13.7.0", "long": "^5.3.2" } }, "sha512-RJJPTTpvFfHcWLkIa2JFWK4XvtSzS0yEWDmunqHXli1h3JlkbcQZXDZdcWxv+JK3Xsl5/UFDPZ0iGm7DAengYw=="], + + "proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="], + + "qs": ["qs@6.15.2", "", { "dependencies": { "side-channel": "^1.1.0" } }, "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw=="], + + "retry": ["retry@0.13.1", "", {}, "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg=="], + + "side-channel": ["side-channel@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4", "side-channel-list": "^1.0.1", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ=="], + + "side-channel-list": ["side-channel-list@1.0.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4" } }, "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w=="], + + "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="], + + "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="], + + "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], + + "undici-types": ["undici-types@7.24.6", "", {}, "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg=="], + + "ws": ["ws@8.21.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g=="], + + "@slack/web-api/axios": ["axios@1.17.0", "", { "dependencies": { "follow-redirects": "^1.16.0", "form-data": "^4.0.5", "https-proxy-agent": "^5.0.1", "proxy-from-env": "^2.1.0" } }, "sha512-J8SwNxprqqpbfenehxWYXE7CW+wM1BB4w3+N+g+/Wx40xM4rsLrfPmHHxSWIxJLYDgSY/HqlFPIYb2/S3rxafw=="], + + "p-queue/eventemitter3": ["eventemitter3@4.0.7", "", {}, "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="], + + "@slack/web-api/axios/proxy-from-env": ["proxy-from-env@2.1.0", "", {}, "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA=="], + } +} diff --git a/backend/bunfig.toml b/backend/bunfig.toml new file mode 100644 index 0000000..3853444 --- /dev/null +++ b/backend/bunfig.toml @@ -0,0 +1,5 @@ +# Bun test runner configuration for the AgentForge backend. +[test] +root = "tests" +coverageSkipTestFiles = true +coveragePathIgnorePatterns = ["node_modules", "tests"] diff --git a/backend/package.json b/backend/package.json new file mode 100644 index 0000000..245e1c5 --- /dev/null +++ b/backend/package.json @@ -0,0 +1,24 @@ +{ + "name": "agentforge-backend", + "version": "1.0.0", + "description": "AgentForge task board backend (Bun + TypeScript)", + "private": true, + "type": "module", + "scripts": { + "start": "bun taskboard.ts", + "check": "bunx tsc --noEmit && bun test", + "test": "bun test", + "typecheck": "bunx tsc --noEmit", + "compile": "bun build --compile taskboard.ts --outfile ../taskboard-electron/resources/taskboard" + }, + "dependencies": { + "@larksuiteoapi/node-sdk": "^1.55.0", + "@slack/socket-mode": "^2.0.4", + "@slack/web-api": "^7.13.0", + "cron-parser": "^5.4.0" + }, + "devDependencies": { + "@types/bun": "^1.3.5", + "typescript": "^5.9.3" + } +} diff --git a/backend/src/log.ts b/backend/src/log.ts new file mode 100644 index 0000000..e13e534 --- /dev/null +++ b/backend/src/log.ts @@ -0,0 +1,59 @@ +// Minimal logger matching the Python logging setup in taskboard.py: +// level from AGENTFORGE_LOG_LEVEL, "%Y-%m-%d %H:%M:%S LEVEL name: message". + +const LEVELS: Record = { + DEBUG: 10, + INFO: 20, + WARNING: 30, + ERROR: 40, +}; + +const envLevel = (process.env.AGENTFORGE_LOG_LEVEL ?? "INFO").toUpperCase(); +const ROOT_LEVEL = LEVELS[envLevel] ?? LEVELS.INFO!; + +function timestamp(): string { + const d = new Date(); + const pad = (n: number) => String(n).padStart(2, "0"); + return ( + `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ` + + `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}` + ); +} + +export class Logger { + constructor(readonly name: string) {} + + private emit(levelName: string, level: number, args: unknown[]): void { + if (level < ROOT_LEVEL) return; + const line = `${timestamp()} ${levelName} ${this.name}:`; + if (level >= LEVELS.ERROR!) console.error(line, ...args); + else if (level >= LEVELS.WARNING!) console.warn(line, ...args); + else console.log(line, ...args); + } + + debug(...args: unknown[]): void { + this.emit("DEBUG", LEVELS.DEBUG!, args); + } + + info(...args: unknown[]): void { + this.emit("INFO", LEVELS.INFO!, args); + } + + warning(...args: unknown[]): void { + this.emit("WARNING", LEVELS.WARNING!, args); + } + + error(...args: unknown[]): void { + this.emit("ERROR", LEVELS.ERROR!, args); + } + + exception(...args: unknown[]): void { + this.emit("ERROR", LEVELS.ERROR!, args); + } +} + +export function getLogger(name: string): Logger { + return new Logger(name); +} + +export const logger = getLogger("agentforge"); diff --git a/backend/src/types.ts b/backend/src/types.ts new file mode 100644 index 0000000..bb76809 --- /dev/null +++ b/backend/src/types.ts @@ -0,0 +1,192 @@ +// Core enums and models, ported from taskboard.py. +// Field and member names intentionally keep the Python snake_case spelling: +// they double as SQLite column names and REST API JSON keys. + +export const DEFAULT_AGENT = "codex"; +export const DEFAULT_TIMEOUT_SECONDS = 12000; + +export const CLAUDE_STREAM_JSON_ARGS = [ + "--output-format", + "stream-json", + "--include-partial-messages", + "--verbose", + "--permission-mode", + "bypassPermissions", +]; + +export const LIVE_OUTPUT_EVENT_TYPES = new Set([ + "assistant", + "tool_call", + "tool_result", + "command_execution", + "file_change", + "web_search", + "error", +]); + +export const SECRET_KEY_FRAGMENTS = [ + "api_key", + "apikey", + "authorization", + "auth_token", + "credential", + "password", + "secret", + "token", +] as const; + +export const GENERATED_IMAGE_MEDIA_TYPES: Record = { + ".png": "image/png", + ".jpg": "image/jpeg", + ".jpeg": "image/jpeg", + ".gif": "image/gif", + ".webp": "image/webp", +}; + +export const TaskStatus = { + PENDING: "pending", + SCHEDULED: "scheduled", + RUNNING: "running", + COMPLETED: "completed", + FAILED: "failed", + CANCELLED: "cancelled", + BLOCKED: "blocked", // has unmet upstream dependencies +} as const; +export type TaskStatus = (typeof TaskStatus)[keyof typeof TaskStatus]; + +export const ScheduleType = { + IMMEDIATE: "immediate", + DELAYED: "delayed", // run after N seconds + SCHEDULED_AT: "scheduled_at", // run at a specific datetime + CRON: "cron", // recurring cron expression +} as const; +export type ScheduleType = (typeof ScheduleType)[keyof typeof ScheduleType]; + +export const HeartbeatScheduleType = { + CRON: "cron", + INTERVAL: "interval", +} as const; +export type HeartbeatScheduleType = + (typeof HeartbeatScheduleType)[keyof typeof HeartbeatScheduleType]; + +export const HeartbeatDecisionType = { + IDLE: "idle", + TRIGGER_TASK: "trigger_task", + RESUME_TASK: "resume_task", + NOTIFY_ONLY: "notify_only", + ERROR: "error", +} as const; +export type HeartbeatDecisionType = + (typeof HeartbeatDecisionType)[keyof typeof HeartbeatDecisionType]; + +export interface PromptImage { + media_type: string; + data: string; + name?: string; +} + +export interface Task { + id: number | null; + title: string; + prompt: string; + working_dir: string; + status: TaskStatus; + schedule_type: ScheduleType; + cron_expr: string | null; // e.g. "*/30 * * * *" + delay_seconds: number | null; // e.g. 300 + next_run_at: string | null; // ISO timestamp + last_run_at: string | null; + result: string | null; + error: string | null; + run_count: number; + max_runs: number | null; // null = unlimited for cron + created_at: string | null; + updated_at: string | null; + tags: string; // comma-separated + agent: string; + question: string | null; // question the agent asked + answer: string | null; // user's answer + session_id: string | null; // agent session/thread id for resume + prompt_images: PromptImage[]; + image_paths: string[]; // list of local image file paths + dag_id: string | null; // optional DAG workflow group label + feishu_root_msg_id: string | null; // Feishu root message_id that created this task +} + +export function makeTask(partial: Partial = {}): Task { + return { + id: null, + title: "", + prompt: "", + working_dir: ".", + status: TaskStatus.PENDING, + schedule_type: ScheduleType.IMMEDIATE, + cron_expr: null, + delay_seconds: null, + next_run_at: null, + last_run_at: null, + result: null, + error: null, + run_count: 0, + max_runs: null, + created_at: null, + updated_at: null, + tags: "", + agent: DEFAULT_AGENT, + question: null, + answer: null, + session_id: null, + prompt_images: [], + image_paths: [], + dag_id: null, + feishu_root_msg_id: null, + ...partial, + }; +} + +export interface Heartbeat { + id: number | null; + name: string; + enabled: boolean; + working_dir: string; + schedule_type: HeartbeatScheduleType; + cron_expr: string | null; + interval_seconds: number | null; + check_prompt: string; + action_prompt_template: string; + default_agent: string; + cooldown_seconds: number; + next_run_at: string | null; + last_tick_at: string | null; + last_decision: string | null; + last_error: string | null; + last_triggered_at: string | null; + last_dedupe_key: string | null; + created_at: string | null; + updated_at: string | null; +} + +export function makeHeartbeat(partial: Partial = {}): Heartbeat { + return { + id: null, + name: "", + enabled: true, + working_dir: ".", + schedule_type: HeartbeatScheduleType.INTERVAL, + cron_expr: null, + interval_seconds: null, + check_prompt: "", + action_prompt_template: "", + default_agent: DEFAULT_AGENT, + cooldown_seconds: 0, + next_run_at: null, + last_tick_at: null, + last_decision: null, + last_error: null, + last_triggered_at: null, + last_dedupe_key: null, + created_at: null, + updated_at: null, + ...partial, + }; +} diff --git a/backend/src/util.ts b/backend/src/util.ts new file mode 100644 index 0000000..b4a43a7 --- /dev/null +++ b/backend/src/util.ts @@ -0,0 +1,110 @@ +// Helpers ported from taskboard.py (lines 117-187) plus the local-naive +// ISO timestamp conventions used throughout the Python backend. + +import os from "node:os"; + +/** + * Return process.env augmented with common macOS tool install paths. + * Electron (and other GUI launchers) inherit a stripped PATH that often + * misses npm globals, Homebrew, and ~/.local/bin. + */ +export function getEnv(): Record { + const env: Record = {}; + for (const [k, v] of Object.entries(process.env)) { + if (v !== undefined) env[k] = v; + } + const home = os.homedir(); + const extra = [ + `${home}/.local/bin`, + "/usr/local/bin", + "/opt/homebrew/bin", // Apple-silicon Homebrew + "/usr/local/opt/node/bin", + `${home}/.npm/bin`, + `${home}/.nvm/current/bin`, + "/usr/bin", + "/bin", + ]; + const current = env.PATH ?? ""; + env.PATH = + extra.filter((p) => !current.includes(p)).join(":") + (current ? `:${current}` : ""); + return env; +} + +/** + * Format a Date as a local-naive ISO string, matching Python's + * `datetime.now().isoformat()` storage convention (no timezone suffix, + * 6-digit fractional seconds). Strings of this shape sort lexicographically. + */ +export function dateToLocalIso(d: Date): string { + const pad = (n: number, w = 2) => String(n).padStart(w, "0"); + return ( + `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}` + + `T${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}` + + `.${pad(d.getMilliseconds(), 3)}000` + ); +} + +/** Local-naive ISO timestamp for "now" (≙ Python `datetime.now().isoformat()`). */ +export function nowIso(): string { + return dateToLocalIso(new Date()); +} + +/** + * Parse ISO datetimes and collapse aware values into local naive datetimes. + * + * The app historically stored naive local timestamps, but the Electron UI can + * submit offset-aware ISO strings for `scheduled_at`. JS Dates are epoch-based, + * so "aware → local naive" simply means: parse, and later re-serialize with + * dateToLocalIso(). Date-only strings are pinned to local midnight to match + * Python's fromisoformat semantics (plain `new Date("YYYY-MM-DD")` is UTC). + * + * Throws on unparseable input (≙ Python ValueError). + */ +export function parseComparableDatetime(value: string | null | undefined): Date | null { + if (!value) return null; + const normalized = /^\d{4}-\d{2}-\d{2}$/.test(value) ? `${value}T00:00:00` : value; + const dt = new Date(normalized); + if (Number.isNaN(dt.getTime())) { + throw new Error(`Invalid isoformat string: ${JSON.stringify(value)}`); + } + return dt; +} + +export function normalizeDatetimeForStorage(value: string | null | undefined): string | null { + if (value === null || value === undefined) return null; + let dt: Date | null; + try { + dt = parseComparableDatetime(value); + } catch { + return value; + } + return dt ? dateToLocalIso(dt) : null; +} + +/** + * Extract a JSON object from raw agent output (≙ taskboard.py + * `_parse_json_object`): strips markdown fences, then trims to the outermost + * {...} span. Throws if the result is not a JSON object. + */ +export function parseJsonObject(rawText: string): Record { + let text = (rawText || "").trim(); + if (text.startsWith("```")) { + text = text + .split(/\r?\n/) + .filter((ln) => !ln.trim().startsWith("```")) + .join("\n") + .trim(); + } + if (!text.startsWith("{")) { + const start = text.indexOf("{"); + const end = text.lastIndexOf("}"); + if (start !== -1 && end !== -1 && end > start) { + text = text.slice(start, end + 1); + } + } + const data: unknown = JSON.parse(text); + if (data === null || typeof data !== "object" || Array.isArray(data)) { + throw new Error("expected JSON object"); + } + return data as Record; +} diff --git a/backend/tsconfig.json b/backend/tsconfig.json new file mode 100644 index 0000000..8af7db9 --- /dev/null +++ b/backend/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "bundler", + "lib": ["ESNext"], + "types": ["bun"], + "strict": true, + "noUncheckedIndexedAccess": false, + "noFallthroughCasesInSwitch": true, + "forceConsistentCasingInFileNames": true, + "skipLibCheck": true, + "noEmit": true, + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "esModuleInterop": true, + "resolveJsonModule": true + }, + "include": ["taskboard.ts", "src/**/*.ts", "tests/**/*.ts"] +} From 7378f354b82c1a3f426f50bd236556ab04a3c433 Mon Sep 17 00:00:00 2001 From: taohe Date: Sat, 13 Jun 2026 01:01:47 +0800 Subject: [PATCH 03/18] feat(backend): port MessageBus/Channel/UIChannel to TypeScript with tests Co-Authored-By: Claude Fable 5 --- backend/src/bus.ts | 493 ++++++++++++++++++ backend/tests/bus.test.ts | 256 +++++++++ taskboard-electron/src/{main.js => main.ts} | 0 .../src/{preload.js => preload.ts} | 0 .../src/{renderer.js => renderer.ts} | 0 .../src/renderer/{App.jsx => App.tsx} | 0 ...ings.test.mjs => channelsSettings.test.ts} | 0 ...annelsSettings.mjs => channelsSettings.ts} | 0 .../{dateTime.test.mjs => dateTime.test.ts} | 0 .../renderer/{dateTime.mjs => dateTime.ts} | 0 .../src/renderer/{main.jsx => main.tsx} | 0 ...traceSteps.test.mjs => traceSteps.test.ts} | 0 .../{traceSteps.mjs => traceSteps.ts} | 0 13 files changed, 749 insertions(+) create mode 100644 backend/src/bus.ts create mode 100644 backend/tests/bus.test.ts rename taskboard-electron/src/{main.js => main.ts} (100%) rename taskboard-electron/src/{preload.js => preload.ts} (100%) rename taskboard-electron/src/{renderer.js => renderer.ts} (100%) rename taskboard-electron/src/renderer/{App.jsx => App.tsx} (100%) rename taskboard-electron/src/renderer/{channelsSettings.test.mjs => channelsSettings.test.ts} (100%) rename taskboard-electron/src/renderer/{channelsSettings.mjs => channelsSettings.ts} (100%) rename taskboard-electron/src/renderer/{dateTime.test.mjs => dateTime.test.ts} (100%) rename taskboard-electron/src/renderer/{dateTime.mjs => dateTime.ts} (100%) rename taskboard-electron/src/renderer/{main.jsx => main.tsx} (100%) rename taskboard-electron/src/renderer/{traceSteps.test.mjs => traceSteps.test.ts} (100%) rename taskboard-electron/src/renderer/{traceSteps.mjs => traceSteps.ts} (100%) diff --git a/backend/src/bus.ts b/backend/src/bus.ts new file mode 100644 index 0000000..22224b9 --- /dev/null +++ b/backend/src/bus.ts @@ -0,0 +1,493 @@ +// AgentForge Message Bus — ported from taskboard_bus.py. +// +// MessageBus decouples message sources (channels) from the task scheduler: +// +// ┌─────────────────────────────────┐ +// │ MessageBus │ +// │ │ +// FeishuChannel ──► │ inbound_queue (AsyncQueue) │──► TaskScheduler +// UIChannel ──► │ │ +// SlackChannel ──► │ outbound_queue (AsyncQueue) │◄── TaskScheduler._notify() +// ... ──► │ │ +// └──────────┬───────────────────────┘ +// │ subscribe_outbound() +// ▼ +// Channel.send(OutboundMessage) +// +// Naming follows the Python original exactly (snake_case methods/fields). +// Python's queue.Queue(timeout=...) is replaced by AsyncQueue: get() returns a +// Promise that resolves with the next message (resolving early when one is +// published) or null after the timeout / immediately when block=false. All +// production call sites either publish (non-blocking) or poll, so this is a +// faithful minimal equivalent. put_nowait preserves maxsize semantics by +// throwing when the queue is full, like Python's queue.Full. + +// ──────────────────────────── Message Types ──────────────────────────── + +/** Inbound message action types (enum values identical to Python). */ +export const InboundMessageType = { + CREATE_TASK: "create_task", // create a new task + RESUME_TASK: "resume_task", // resume an existing task (uses session_id) + RESPOND_TASK: "respond_task", // answer a question a task is waiting on + CANCEL_TASK: "cancel_task", // cancel a task + STATUS_QUERY: "status_query", // query task status +} as const; +export type InboundMessageType = (typeof InboundMessageType)[keyof typeof InboundMessageType]; + +/** Outbound message event types (enum values identical to Python). */ +export const OutboundMessageType = { + TASK_COMPLETED: "task_completed", + TASK_FAILED: "task_failed", + TASK_STARTED: "task_started", + TASK_UPDATED: "task_updated", + STATUS_RESPONSE: "status_response", +} as const; +export type OutboundMessageType = (typeof OutboundMessageType)[keyof typeof OutboundMessageType]; + +/** + * UTC-naive ISO timestamp, matching Python's `datetime.utcnow().isoformat()` + * used by the dataclass defaults (note: NOT the local-naive nowIso() in + * util.ts — the bus historically stamped messages in UTC). + */ +function utcNowIso(): string { + // toISOString() → "YYYY-MM-DDTHH:MM:SS.mmmZ"; pad to 6 fractional digits. + return new Date().toISOString().replace("Z", "000"); +} + +/** + * Inbound message from a Channel to the MessageBus. + * + * payload contents depend on type: + * CREATE_TASK -> {"title", "prompt", "working_dir", ...} + * RESUME_TASK -> {"task_id", "message"} + * RESPOND_TASK -> {"task_id", "answer"} + * CANCEL_TASK -> {"task_id"} + * STATUS_QUERY -> {"task_id"} + * reply_to: optional reply target (e.g. Feishu chat_id / open_id). + * metadata: channel-specific context (e.g. Feishu message_id). + */ +export interface InboundMessage { + type: InboundMessageType; + source: string; + payload: Record; + reply_to: string | null; + metadata: Record; + created_at: string; +} + +/** Factory applying the Python dataclass defaults for InboundMessage. */ +export function makeInboundMessage( + partial: Pick & Partial, +): InboundMessage { + return { + payload: {}, + reply_to: null, + metadata: {}, + created_at: utcNowIso(), + ...partial, + }; +} + +/** + * Outbound message published by the scheduler after a task finishes. + * + * payload: event payload, e.g. {"status", "result", "error", "title"}. + * source_msg: the InboundMessage that triggered this result (optional). + */ +export interface OutboundMessage { + type: OutboundMessageType; + task_id: number; + payload: Record; + source_msg: InboundMessage | null; + metadata: Record; + created_at: string; +} + +/** Factory applying the Python dataclass defaults for OutboundMessage. */ +export function makeOutboundMessage( + partial: Pick & Partial, +): OutboundMessage { + return { + payload: {}, + source_msg: null, + metadata: {}, + created_at: utcNowIso(), + ...partial, + }; +} + +// ──────────────────────────── TaskDB structural type ──────────────────────────── + +/** + * Minimal structural view of TaskDB used by this module (so bus.ts does not + * import db.ts). The bus code only ever calls get_task(). Exported for reuse + * by channels/tests. + */ +export interface TaskDBLike { + get_task(task_id: number): Record | null | undefined; +} + +// ──────────────────────────── Async Queue ──────────────────────────── + +/** + * Async-friendly replacement for Python's queue.Queue. + * - put_nowait throws when maxsize (> 0) is exceeded (≙ queue.Full). + * - get(block, timeoutSeconds) resolves with the next item, resolving early + * when one is published; resolves null on timeout or when block=false and + * the queue is empty (the Python wrappers map queue.Empty → None). + */ +export class AsyncQueue { + private items: T[] = []; + private waiters: Array<(value: T | null) => void> = []; + + constructor(private readonly maxsize: number = 0) {} + + put_nowait(item: T): void { + const waiter = this.waiters.shift(); + if (waiter) { + // Hand off directly to a blocked getter (qsize stays 0, like Python). + waiter(item); + return; + } + if (this.maxsize > 0 && this.items.length >= this.maxsize) { + throw new Error("queue full"); + } + this.items.push(item); + } + + get(block: boolean = true, timeout: number | null = null): Promise { + if (this.items.length > 0) { + return Promise.resolve(this.items.shift() as T); + } + if (!block) { + return Promise.resolve(null); + } + return new Promise((resolve) => { + let timer: ReturnType | undefined; + const waiter = (value: T | null): void => { + if (timer !== undefined) clearTimeout(timer); + resolve(value); + }; + this.waiters.push(waiter); + if (timeout !== null) { + timer = setTimeout(() => { + const idx = this.waiters.indexOf(waiter); + if (idx !== -1) this.waiters.splice(idx, 1); + resolve(null); + }, timeout * 1000); + } + }); + } + + get size(): number { + return this.items.length; + } +} + +// ──────────────────────────── Message Bus ──────────────────────────── + +export type OutboundListener = (msg: OutboundMessage) => void; + +/** + * AgentForge's message bus. + * + * Provides two queues: + * - inbound_queue: channels send task requests to the scheduler. + * - outbound_queue: the scheduler publishes task result notifications. + */ +export class MessageBus { + inbound_queue: AsyncQueue; + outbound_queue: AsyncQueue; + private _outbound_listeners: OutboundListener[] = []; + + /** maxsize: queue capacity limit; 0 means unbounded. */ + constructor(maxsize: number = 0) { + this.inbound_queue = new AsyncQueue(maxsize); + this.outbound_queue = new AsyncQueue(maxsize); + } + + // ── inbound helpers ────────────────────────────────────────── + + /** Channels call this to enqueue an inbound message. */ + publish_inbound(msg: InboundMessage): void { + this.inbound_queue.put_nowait(msg); + } + + /** The scheduler calls this to take the next inbound message (optional). */ + get_inbound(block: boolean = true, timeout: number | null = null): Promise { + return this.inbound_queue.get(block, timeout); + } + + // ── outbound helpers ───────────────────────────────────────── + + /** + * The scheduler calls this to publish a task result. The message is put on + * outbound_queue and all registered listeners are invoked synchronously. + */ + publish_outbound(msg: OutboundMessage): void { + this.outbound_queue.put_nowait(msg); + for (const listener of this._outbound_listeners) { + try { + listener(msg); + } catch (e) { + console.log(`[MessageBus] outbound listener error: ${e}`); + } + } + } + + /** Register an outbound listener (e.g. FeishuChannel's notify function). */ + subscribe_outbound(listener: OutboundListener): void { + this._outbound_listeners.push(listener); + } + + /** Remove an outbound listener (no-op when not registered). */ + unsubscribe_outbound(listener: OutboundListener): void { + const idx = this._outbound_listeners.indexOf(listener); + if (idx !== -1) this._outbound_listeners.splice(idx, 1); + } + + /** Polling channels call this to take the next outbound message. */ + get_outbound(block: boolean = true, timeout: number | null = null): Promise { + return this.outbound_queue.get(block, timeout); + } +} + +// ──────────────────────────── Channel (abstract) ──────────────────────────── + +/** + * Abstract message channel. Each concrete Channel represents an external + * system (HTTP UI, Feishu, Slack, ...). A channel: + * 1. Receives external messages, wraps them as InboundMessage onto the bus. + * 2. Pushes task results back to the external system via send(). + * + * Legacy compatibility: notify_task(task_id) reads the DB and calls send(), + * matching the original FeishuBridge.notify_task() calling convention. + */ +export abstract class Channel { + name: string; + bus: MessageBus; + db: TaskDBLike; + _running: boolean = false; + + constructor(name: string, bus: MessageBus, db: TaskDBLike) { + this.name = name; + this.bus = bus; + this.db = db; + } + + /** Push an outbound message to this channel's external system. */ + abstract send(msg: OutboundMessage): void; + + /** Start the channel's background listener. */ + abstract start(): void; + + /** Stop the channel (optional override). */ + stop(): void { + this._running = false; + } + + /** + * Legacy direct-callback interface: read the task's status, build an + * OutboundMessage, and call send(). + */ + notify_task(task_id: number): void { + const task = this.db.get_task(task_id); + if (!task) return; + const status = (task["status"] as string | undefined) ?? ""; + const type_map: Record = { + running: OutboundMessageType.TASK_STARTED, + completed: OutboundMessageType.TASK_COMPLETED, + failed: OutboundMessageType.TASK_FAILED, + }; + const msg_type = type_map[status] ?? OutboundMessageType.TASK_UPDATED; + const outbound = makeOutboundMessage({ + type: msg_type, + task_id, + payload: { + status, + result: task["result"] ?? null, + error: task["error"] ?? null, + title: task["title"] ?? null, + }, + }); + this.send(outbound); + } + + /** Convenience factory that auto-fills the source field. */ + _make_inbound( + msg_type: InboundMessageType, + payload: Record, + reply_to: string | null = null, + metadata: Record | null = null, + ): InboundMessage { + return makeInboundMessage({ + type: msg_type, + source: this.name, + payload, + reply_to, + metadata: metadata ?? {}, + }); + } +} + +// ──────────────────────────── UIChannel ──────────────────────────── + +/** + * HTTP REST API channel (wraps the existing HTTP handler + TaskScheduler). + * + * Converts browser/React HTTP requests into InboundMessages on the bus, and + * caches outbound events in memory for the /api/tasks/{id}/events polling + * endpoint. The HTTP handler still drives scheduler/db directly; this channel + * mirrors those operations as InboundMessages for a complete event trail. + */ +export class UIChannel extends Channel { + /** Outbound event cache: task_id -> OutboundMessage[] (insertion-ordered). */ + _outbound_cache: Map = new Map(); + + /** Max number of task IDs to keep in the outbound cache. */ + _CACHE_MAX_TASKS: number = 1000; + + constructor(bus: MessageBus, db: TaskDBLike) { + super("ui", bus, db); + bus.subscribe_outbound(this._on_outbound); + } + + /** UI channel receives HTTP requests passively; no polling needed. */ + start(): void { + this._running = true; + console.log("[UIChannel] Ready (HTTP REST API)"); + } + + /** Cache the outbound message for HTTP polling endpoints. */ + send(msg: OutboundMessage): void { + let entries = this._outbound_cache.get(msg.task_id); + if (!entries) { + entries = []; + this._outbound_cache.set(msg.task_id, entries); + } + entries.push(msg); + // Evict oldest task entries when the cache grows too large + while (this._outbound_cache.size > this._CACHE_MAX_TASKS) { + const oldest = this._outbound_cache.keys().next().value; + if (oldest === undefined) break; + this._outbound_cache.delete(oldest); + } + } + + /** Return a copy of all cached outbound events for a task. */ + get_cached_outbound(task_id: number): OutboundMessage[] { + return [...(this._outbound_cache.get(task_id) ?? [])]; + } + + /** + * Called by the HTTP handler after creating a task; publishes an + * InboundMessage to the bus. kwargs (≙ Python **kwargs) are merged into + * the payload. + */ + notify_task_created( + task_id: number, + prompt: string, + working_dir: string = ".", + kwargs: Record = {}, + ): void { + this.bus.publish_inbound( + this._make_inbound(InboundMessageType.CREATE_TASK, { + task_id, + prompt, + working_dir, + ...kwargs, + }), + ); + } + + /** Called by the HTTP handler after resuming a task. */ + notify_task_resumed(task_id: number, message: string): void { + this.bus.publish_inbound( + this._make_inbound(InboundMessageType.RESUME_TASK, { + task_id, + message, + }), + ); + } + + /** + * Subscription callback: write the outbound message into the local cache. + * Arrow-function property so the reference passed to subscribe_outbound is + * stable and bound (≙ Python bound method). + */ + _on_outbound = (msg: OutboundMessage): void => { + this.send(msg); + }; +} + +// ──────────────────────────── BusAwareSchedulerMixin ──────────────────────────── + +/** + * Publish an OutboundMessage to the bus based on the task's current status. + * + * override_type forces a specific message type (used when a cron task has + * already been rescheduled: the DB status is back to "scheduled" but this + * run's result should be announced as TASK_COMPLETED). + * + * Porting note: Python's BusAwareSchedulerMixin is a mixin class consumed via + * `class TaskScheduler(BusAwareSchedulerMixin)`, and taskboard.py calls + * `self._bus_notify(task_id[, override_type])` (it relies only on `self.bus` + * and `self.db`). TS has no Python-style mixins, so the logic lives in this + * standalone helper, and the small BusAwareSchedulerMixin base class below + * preserves the `extends` + `this._bus_notify(...)` ergonomics for the + * TaskScheduler port. + */ +export function bus_notify( + bus: MessageBus | null | undefined, + db: TaskDBLike, + task_id: number, + override_type: OutboundMessageType | null = null, +): void { + if (!bus) return; + try { + const task = db.get_task(task_id); + if (!task) return; + const status = (task["status"] as string | undefined) ?? ""; + let msg_type: OutboundMessageType; + if (override_type !== null) { + msg_type = override_type; + } else { + const type_map: Record = { + running: OutboundMessageType.TASK_STARTED, + completed: OutboundMessageType.TASK_COMPLETED, + failed: OutboundMessageType.TASK_FAILED, + cancelled: OutboundMessageType.TASK_UPDATED, + scheduled: OutboundMessageType.TASK_UPDATED, + pending: OutboundMessageType.TASK_UPDATED, + }; + msg_type = type_map[status] ?? OutboundMessageType.TASK_UPDATED; + } + const outbound = makeOutboundMessage({ + type: msg_type, + task_id, + payload: { + status, + result: task["result"] ?? null, + error: task["error"] ?? null, + title: task["title"] ?? null, + }, + }); + bus.publish_outbound(outbound); + } catch (e) { + console.log(`[BusAwareSchedulerMixin] _bus_notify error: ${e}`); + } +} + +/** + * Base class equivalent of the Python mixin: subclasses (TaskScheduler) + * provide `db` and optionally set `bus`, then call `this._bus_notify(...)` + * exactly as the Python code does. + */ +export abstract class BusAwareSchedulerMixin { + bus: MessageBus | null = null; + abstract db: TaskDBLike; + + _bus_notify(task_id: number, override_type: OutboundMessageType | null = null): void { + bus_notify(this.bus, this.db, task_id, override_type); + } +} diff --git a/backend/tests/bus.test.ts b/backend/tests/bus.test.ts new file mode 100644 index 0000000..fadf3ba --- /dev/null +++ b/backend/tests/bus.test.ts @@ -0,0 +1,256 @@ +// Ported from tests/test_taskboard_bus.py (bun:test). +// Python's blocking queue.get() calls become awaited promises; everything else +// is a 1:1 translation. + +import { expect, test } from "bun:test"; + +import { + BusAwareSchedulerMixin, + Channel, + InboundMessageType, + MessageBus, + makeOutboundMessage, + OutboundMessageType, + UIChannel, + type InboundMessage, + type OutboundMessage, + type TaskDBLike, +} from "../src/bus.ts"; + +class StubDB implements TaskDBLike { + tasks: Record>; + + constructor(tasks: Record> | null = null) { + this.tasks = tasks ?? {}; + } + + get_task(task_id: number): Record | null { + return this.tasks[task_id] ?? null; + } +} + +class RecordingChannel extends Channel { + sent: OutboundMessage[] = []; + + constructor(bus: MessageBus, db: TaskDBLike) { + super("test", bus, db); + } + + send(msg: OutboundMessage): void { + this.sent.push(msg); + } + + start(): void { + this._running = true; + } +} + +class FakeScheduler extends BusAwareSchedulerMixin { + db: TaskDBLike; + + constructor(db: TaskDBLike, bus: MessageBus | null = null) { + super(); + this.db = db; + this.bus = bus; + } +} + +test("test_message_bus_round_trips_inbound_and_outbound_messages", async () => { + const bus = new MessageBus(); + const inbound = new RecordingChannel(bus, new StubDB())._make_inbound( + InboundMessageType.CREATE_TASK, + { title: "hello" }, + "chat-1", + { source_message_id: "m1" }, + ); + const outbound = makeOutboundMessage({ + type: OutboundMessageType.TASK_COMPLETED, + task_id: 1, + payload: { status: "completed" }, + }); + + bus.publish_inbound(inbound); + bus.publish_outbound(outbound); + + expect(await bus.get_inbound()).toBe(inbound); + expect(await bus.get_outbound()).toBe(outbound); +}); + +test("test_message_bus_returns_none_when_queue_is_empty", async () => { + const bus = new MessageBus(); + + expect(await bus.get_inbound(false)).toBeNull(); + expect(await bus.get_outbound(false)).toBeNull(); +}); + +test("test_message_bus_notifies_and_unsubscribes_outbound_listeners", () => { + const bus = new MessageBus(); + const seen: number[] = []; + + const listener = (msg: OutboundMessage): void => { + seen.push(msg.task_id); + }; + + bus.subscribe_outbound(listener); + bus.publish_outbound( + makeOutboundMessage({ + type: OutboundMessageType.TASK_STARTED, + task_id: 7, + }), + ); + bus.unsubscribe_outbound(listener); + bus.publish_outbound( + makeOutboundMessage({ + type: OutboundMessageType.TASK_COMPLETED, + task_id: 8, + }), + ); + + expect(seen).toEqual([7]); +}); + +test("test_message_bus_tolerates_listener_errors_and_missing_unsubscribe", async () => { + const bus = new MessageBus(); + + const bad_listener = (_msg: OutboundMessage): void => { + throw new Error("boom"); + }; + + bus.subscribe_outbound(bad_listener); + bus.publish_outbound( + makeOutboundMessage({ + type: OutboundMessageType.TASK_UPDATED, + task_id: 9, + }), + ); + bus.unsubscribe_outbound(bad_listener); + bus.unsubscribe_outbound(bad_listener); + + expect((await bus.get_outbound())!.task_id).toBe(9); +}); + +test("test_channel_notify_task_maps_task_status_to_outbound_type", () => { + const bus = new MessageBus(); + const db = new StubDB({ + 1: { status: "completed", result: "ok", error: null, title: "done" }, + 2: { status: "failed", result: null, error: "boom", title: "bad" }, + }); + const channel = new RecordingChannel(bus, db); + + channel.notify_task(1); + channel.notify_task(2); + channel.notify_task(999); + + expect(channel.sent.map((msg) => msg.type)).toEqual([ + OutboundMessageType.TASK_COMPLETED, + OutboundMessageType.TASK_FAILED, + ]); + expect(channel.sent[0]!.payload["result"]).toBe("ok"); + expect(channel.sent[1]!.payload["error"]).toBe("boom"); +}); + +test("test_channel_stop_marks_channel_as_not_running", () => { + const channel = new RecordingChannel(new MessageBus(), new StubDB()); + channel.start(); + + channel.stop(); + + expect(channel._running).toBe(false); +}); + +test("test_ui_channel_caches_outbound_messages_and_inbound_notifications", async () => { + const bus = new MessageBus(); + const db = new StubDB(); + const channel = new UIChannel(bus, db); + + channel.start(); + const created = channel._make_inbound(InboundMessageType.CREATE_TASK, { + task_id: 1, + prompt: "hello", + }); + bus.publish_inbound(created); + channel.notify_task_created(1, "hello", "~/repo", { tags: "ops" }); + channel.notify_task_resumed(1, "continue"); + bus.publish_outbound( + makeOutboundMessage({ + type: OutboundMessageType.TASK_UPDATED, + task_id: 1, + payload: { status: "running" }, + }), + ); + + const inbound_messages: Array = [ + await bus.get_inbound(), + await bus.get_inbound(), + await bus.get_inbound(), + ]; + const cached = channel.get_cached_outbound(1); + + expect(channel._running).toBe(true); + expect(inbound_messages.map((msg) => msg!.type)).toEqual([ + InboundMessageType.CREATE_TASK, + InboundMessageType.CREATE_TASK, + InboundMessageType.RESUME_TASK, + ]); + expect(inbound_messages[1]!.payload["working_dir"]).toBe("~/repo"); + expect(inbound_messages[1]!.payload["tags"]).toBe("ops"); + expect(inbound_messages[2]!.payload["message"]).toBe("continue"); + expect(cached.length).toBe(1); + expect(cached[0]!.payload["status"]).toBe("running"); +}); + +test("test_ui_channel_evicts_oldest_task_cache_entries", () => { + const bus = new MessageBus(); + const channel = new UIChannel(bus, new StubDB()); + channel._CACHE_MAX_TASKS = 2; + + for (const task_id of [1, 2, 3]) { + channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_UPDATED, + task_id, + }), + ); + } + + expect([...channel._outbound_cache.keys()].sort()).toEqual([2, 3]); +}); + +test("test_bus_aware_scheduler_mixin_publishes_task_updates", async () => { + const bus = new MessageBus(); + const db = new StubDB({ + 1: { status: "completed", result: "ok", error: null, title: "done" }, + 2: { status: "running", result: null, error: null, title: "work" }, + }); + const scheduler = new FakeScheduler(db, bus); + + scheduler._bus_notify(1); + scheduler._bus_notify(2, OutboundMessageType.STATUS_RESPONSE); + scheduler._bus_notify(999); + + const first = await bus.get_outbound(); + const second = await bus.get_outbound(); + + expect(first!.type).toBe(OutboundMessageType.TASK_COMPLETED); + expect(first!.payload["title"]).toBe("done"); + expect(second!.type).toBe(OutboundMessageType.STATUS_RESPONSE); + expect(second!.payload["status"]).toBe("running"); +}); + +test("test_bus_aware_scheduler_mixin_noops_without_bus", () => { + const scheduler = new FakeScheduler(new StubDB({ 1: { status: "completed" } }), null); + + scheduler._bus_notify(1); +}); + +test("test_bus_aware_scheduler_mixin_tolerates_db_errors", () => { + class BrokenDB implements TaskDBLike { + get_task(_task_id: number): Record | null { + throw new Error("db down"); + } + } + + const scheduler = new FakeScheduler(new BrokenDB(), new MessageBus()); + + scheduler._bus_notify(1); +}); diff --git a/taskboard-electron/src/main.js b/taskboard-electron/src/main.ts similarity index 100% rename from taskboard-electron/src/main.js rename to taskboard-electron/src/main.ts diff --git a/taskboard-electron/src/preload.js b/taskboard-electron/src/preload.ts similarity index 100% rename from taskboard-electron/src/preload.js rename to taskboard-electron/src/preload.ts diff --git a/taskboard-electron/src/renderer.js b/taskboard-electron/src/renderer.ts similarity index 100% rename from taskboard-electron/src/renderer.js rename to taskboard-electron/src/renderer.ts diff --git a/taskboard-electron/src/renderer/App.jsx b/taskboard-electron/src/renderer/App.tsx similarity index 100% rename from taskboard-electron/src/renderer/App.jsx rename to taskboard-electron/src/renderer/App.tsx diff --git a/taskboard-electron/src/renderer/channelsSettings.test.mjs b/taskboard-electron/src/renderer/channelsSettings.test.ts similarity index 100% rename from taskboard-electron/src/renderer/channelsSettings.test.mjs rename to taskboard-electron/src/renderer/channelsSettings.test.ts diff --git a/taskboard-electron/src/renderer/channelsSettings.mjs b/taskboard-electron/src/renderer/channelsSettings.ts similarity index 100% rename from taskboard-electron/src/renderer/channelsSettings.mjs rename to taskboard-electron/src/renderer/channelsSettings.ts diff --git a/taskboard-electron/src/renderer/dateTime.test.mjs b/taskboard-electron/src/renderer/dateTime.test.ts similarity index 100% rename from taskboard-electron/src/renderer/dateTime.test.mjs rename to taskboard-electron/src/renderer/dateTime.test.ts diff --git a/taskboard-electron/src/renderer/dateTime.mjs b/taskboard-electron/src/renderer/dateTime.ts similarity index 100% rename from taskboard-electron/src/renderer/dateTime.mjs rename to taskboard-electron/src/renderer/dateTime.ts diff --git a/taskboard-electron/src/renderer/main.jsx b/taskboard-electron/src/renderer/main.tsx similarity index 100% rename from taskboard-electron/src/renderer/main.jsx rename to taskboard-electron/src/renderer/main.tsx diff --git a/taskboard-electron/src/renderer/traceSteps.test.mjs b/taskboard-electron/src/renderer/traceSteps.test.ts similarity index 100% rename from taskboard-electron/src/renderer/traceSteps.test.mjs rename to taskboard-electron/src/renderer/traceSteps.test.ts diff --git a/taskboard-electron/src/renderer/traceSteps.mjs b/taskboard-electron/src/renderer/traceSteps.ts similarity index 100% rename from taskboard-electron/src/renderer/traceSteps.mjs rename to taskboard-electron/src/renderer/traceSteps.ts From 7dedf7387ac3bd15f8e9dbe3b9f064d32c309816 Mon Sep 17 00:00:00 2001 From: taohe Date: Sat, 13 Jun 2026 01:01:48 +0800 Subject: [PATCH 04/18] feat(electron): convert app to TypeScript (main/preload/renderer, bun test) Co-Authored-By: Claude Fable 5 --- taskboard-electron/bun.lock | 1967 +++++++++++++++++ taskboard-electron/eslint.config.mjs | 48 +- taskboard-electron/forge.config.js | 4 +- taskboard-electron/index.html | 2 +- taskboard-electron/package.json | 13 +- taskboard-electron/src/main.ts | 48 +- taskboard-electron/src/renderer/App.tsx | 76 +- .../src/renderer/channelsSettings.test.ts | 41 +- .../src/renderer/channelsSettings.ts | 79 +- .../src/renderer/dateTime.test.ts | 19 +- taskboard-electron/src/renderer/dateTime.ts | 25 +- taskboard-electron/src/renderer/main.tsx | 2 +- .../src/renderer/traceSteps.test.ts | 76 +- taskboard-electron/src/renderer/traceSteps.ts | 73 +- taskboard-electron/src/renderer/types.ts | 88 + taskboard-electron/src/vite-env.d.ts | 1 + taskboard-electron/tsconfig.json | 18 + taskboard-electron/tsconfig.node.json | 16 + 18 files changed, 2417 insertions(+), 179 deletions(-) create mode 100644 taskboard-electron/bun.lock create mode 100644 taskboard-electron/src/renderer/types.ts create mode 100644 taskboard-electron/src/vite-env.d.ts create mode 100644 taskboard-electron/tsconfig.json create mode 100644 taskboard-electron/tsconfig.node.json diff --git a/taskboard-electron/bun.lock b/taskboard-electron/bun.lock new file mode 100644 index 0000000..45df1fb --- /dev/null +++ b/taskboard-electron/bun.lock @@ -0,0 +1,1967 @@ +{ + "lockfileVersion": 1, + "configVersion": 0, + "workspaces": { + "": { + "name": "agentforge", + "dependencies": { + "chokidar": "^5.0.0", + "electron-squirrel-startup": "^1.0.1", + "qrcode": "^1.5.4", + "react": "^19.2.4", + "react-dom": "^19.2.4", + }, + "devDependencies": { + "@electron-forge/cli": "^7.11.1", + "@electron-forge/maker-deb": "^7.11.1", + "@electron-forge/maker-dmg": "^7.11.1", + "@electron-forge/maker-rpm": "^7.11.1", + "@electron-forge/maker-squirrel": "^7.11.1", + "@electron-forge/maker-zip": "^7.11.1", + "@electron-forge/plugin-auto-unpack-natives": "^7.11.1", + "@electron-forge/plugin-fuses": "^7.11.1", + "@electron-forge/plugin-vite": "^7.11.1", + "@electron/fuses": "^1.8.0", + "@eslint/js": "^9.39.4", + "@types/bun": "^1.3.14", + "@types/node": "^25.9.3", + "@types/react": "^19.2.17", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.1.4", + "electron": "40.2.1", + "eslint": "^9.39.4", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-react": "^7.37.5", + "eslint-plugin-react-hooks": "^7.1.1", + "globals": "^17.6.0", + "prettier": "^3.8.3", + "typescript": "^6.0.3", + "typescript-eslint": "^8.61.0", + "vite": "^7.3.1", + }, + }, + }, + "packages": { + "@babel/code-frame": ["@babel/code-frame@7.29.0", "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.29.0.tgz", { "dependencies": { "@babel/helper-validator-identifier": "^7.28.5", "js-tokens": "^4.0.0", "picocolors": "^1.1.1" } }, "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw=="], + + "@babel/compat-data": ["@babel/compat-data@7.29.0", "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.29.0.tgz", {}, "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg=="], + + "@babel/core": ["@babel/core@7.29.0", "https://registry.npmmirror.com/@babel/core/-/core-7.29.0.tgz", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-compilation-targets": "^7.28.6", "@babel/helper-module-transforms": "^7.28.6", "@babel/helpers": "^7.28.6", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/traverse": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/remapping": "^2.3.5", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.3", "semver": "^6.3.1" } }, "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA=="], + + "@babel/generator": ["@babel/generator@7.29.1", "https://registry.npmmirror.com/@babel/generator/-/generator-7.29.1.tgz", { "dependencies": { "@babel/parser": "^7.29.0", "@babel/types": "^7.29.0", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" } }, "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw=="], + + "@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.28.6", "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", { "dependencies": { "@babel/compat-data": "^7.28.6", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA=="], + + "@babel/helper-globals": ["@babel/helper-globals@7.28.0", "https://registry.npmmirror.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz", {}, "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw=="], + + "@babel/helper-module-imports": ["@babel/helper-module-imports@7.28.6", "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", { "dependencies": { "@babel/traverse": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw=="], + + "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.6", "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", { "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-validator-identifier": "^7.28.5", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA=="], + + "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.28.6", "https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", {}, "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug=="], + + "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], + + "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="], + + "@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="], + + "@babel/helpers": ["@babel/helpers@7.28.6", "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.28.6.tgz", { "dependencies": { "@babel/template": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw=="], + + "@babel/parser": ["@babel/parser@7.29.0", "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.0.tgz", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": { "parser": "bin/babel-parser.js" } }, "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww=="], + + "@babel/plugin-transform-react-jsx-self": ["@babel/plugin-transform-react-jsx-self@7.27.1", "https://registry.npmmirror.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw=="], + + "@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.27.1", "https://registry.npmmirror.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw=="], + + "@babel/template": ["@babel/template@7.28.6", "https://registry.npmmirror.com/@babel/template/-/template-7.28.6.tgz", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ=="], + + "@babel/traverse": ["@babel/traverse@7.29.0", "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.29.0.tgz", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/types": "^7.29.0", "debug": "^4.3.1" } }, "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA=="], + + "@babel/types": ["@babel/types@7.29.0", "https://registry.npmmirror.com/@babel/types/-/types-7.29.0.tgz", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A=="], + + "@electron-forge/cli": ["@electron-forge/cli@7.11.1", "https://registry.npmmirror.com/@electron-forge/cli/-/cli-7.11.1.tgz", { "dependencies": { "@electron-forge/core": "7.11.1", "@electron-forge/core-utils": "7.11.1", "@electron-forge/shared-types": "7.11.1", "@electron/get": "^3.0.0", "@inquirer/prompts": "^6.0.1", "@listr2/prompt-adapter-inquirer": "^2.0.22", "chalk": "^4.0.0", "commander": "^11.1.0", "debug": "^4.3.1", "fs-extra": "^10.0.0", "listr2": "^7.0.2", "log-symbols": "^4.0.0", "semver": "^7.2.1" }, "bin": { "electron-forge": "dist/electron-forge.js", "electron-forge-vscode-nix": "script/vscode.sh", "electron-forge-vscode-win": "script/vscode.cmd" } }, "sha512-pk8AoLsr7t7LBAt0cFD06XFA6uxtPdvtLx06xeal7O9o7GHGCbj29WGwFoJ8Br/ENM0Ho868S3PrAn1PtBXt5g=="], + + "@electron-forge/core": ["@electron-forge/core@7.11.1", "https://registry.npmmirror.com/@electron-forge/core/-/core-7.11.1.tgz", { "dependencies": { "@electron-forge/core-utils": "7.11.1", "@electron-forge/maker-base": "7.11.1", "@electron-forge/plugin-base": "7.11.1", "@electron-forge/publisher-base": "7.11.1", "@electron-forge/shared-types": "7.11.1", "@electron-forge/template-base": "7.11.1", "@electron-forge/template-vite": "7.11.1", "@electron-forge/template-vite-typescript": "7.11.1", "@electron-forge/template-webpack": "7.11.1", "@electron-forge/template-webpack-typescript": "7.11.1", "@electron-forge/tracer": "7.11.1", "@electron/get": "^3.0.0", "@electron/packager": "^18.3.5", "@electron/rebuild": "^3.7.0", "@malept/cross-spawn-promise": "^2.0.0", "@vscode/sudo-prompt": "^9.3.1", "chalk": "^4.0.0", "debug": "^4.3.1", "fast-glob": "^3.2.7", "filenamify": "^4.1.0", "find-up": "^5.0.0", "fs-extra": "^10.0.0", "global-dirs": "^3.0.0", "got": "^11.8.5", "interpret": "^3.1.1", "jiti": "^2.4.2", "listr2": "^7.0.2", "lodash": "^4.17.20", "log-symbols": "^4.0.0", "node-fetch": "^2.6.7", "rechoir": "^0.8.0", "semver": "^7.2.1", "source-map-support": "^0.5.13", "username": "^5.1.0" } }, "sha512-YtuPLzggPKPabFAD2rOZFE0s7f4KaUTpGRduhSMbZUqpqD1TIPyfoDBpYiZvao3Ht8pyZeOJjbzcC0LpFs9gIQ=="], + + "@electron-forge/core-utils": ["@electron-forge/core-utils@7.11.1", "https://registry.npmmirror.com/@electron-forge/core-utils/-/core-utils-7.11.1.tgz", { "dependencies": { "@electron-forge/shared-types": "7.11.1", "@electron/rebuild": "^3.7.0", "@malept/cross-spawn-promise": "^2.0.0", "chalk": "^4.0.0", "debug": "^4.3.1", "find-up": "^5.0.0", "fs-extra": "^10.0.0", "log-symbols": "^4.0.0", "parse-author": "^2.0.0", "semver": "^7.2.1" } }, "sha512-9UxRWVsfcziBsbAA2MS0Oz4yYovQCO2BhnGIfsbKNTBtMc/RcVSxAS0NMyymce44i43p1ZC/FqWhnt1XqYw3bQ=="], + + "@electron-forge/maker-base": ["@electron-forge/maker-base@7.11.1", "https://registry.npmmirror.com/@electron-forge/maker-base/-/maker-base-7.11.1.tgz", { "dependencies": { "@electron-forge/shared-types": "7.11.1", "fs-extra": "^10.0.0", "which": "^2.0.2" } }, "sha512-yhZrCGoN6bDeiB5DHFaueZ1h84AReElEj+f0hl2Ph4UbZnO0cnLpbx+Bs+XfMLAiA+beC8muB5UDK5ysfuT9BQ=="], + + "@electron-forge/maker-deb": ["@electron-forge/maker-deb@7.11.1", "https://registry.npmmirror.com/@electron-forge/maker-deb/-/maker-deb-7.11.1.tgz", { "dependencies": { "@electron-forge/maker-base": "7.11.1", "@electron-forge/shared-types": "7.11.1" }, "optionalDependencies": { "electron-installer-debian": "^3.2.0" } }, "sha512-QTYiryQLYPDkq6pIfBmx0GQ6D8QatUkowH7rTlW5MnCUa0uumX0Xu7yGIjesuwW37fxT3Lv4xi+FSXMCm2eC1w=="], + + "@electron-forge/maker-dmg": ["@electron-forge/maker-dmg@7.11.1", "https://registry.npmmirror.com/@electron-forge/maker-dmg/-/maker-dmg-7.11.1.tgz", { "dependencies": { "@electron-forge/maker-base": "7.11.1", "@electron-forge/shared-types": "7.11.1", "fs-extra": "^10.0.0" }, "optionalDependencies": { "electron-installer-dmg": "^5.0.1" } }, "sha512-7zs5/Ewz1PcOl4N1102stFgBiFGWxU18+UPFUSd/fgf9MErBl4HBWuVNMIHyeJ/56rdfkcmTxTqE+9TBEYrZcg=="], + + "@electron-forge/maker-rpm": ["@electron-forge/maker-rpm@7.11.1", "https://registry.npmmirror.com/@electron-forge/maker-rpm/-/maker-rpm-7.11.1.tgz", { "dependencies": { "@electron-forge/maker-base": "7.11.1", "@electron-forge/shared-types": "7.11.1" }, "optionalDependencies": { "electron-installer-redhat": "^3.2.0" } }, "sha512-iEfJPRQQyaTqk2EbUfZgulChNWvxGXeYUH0xBX/r5cj1pL4vcJXt3jLMQBVn3mk/0Ytv9UWRs8R/XuNWX6sf2w=="], + + "@electron-forge/maker-squirrel": ["@electron-forge/maker-squirrel@7.11.1", "https://registry.npmmirror.com/@electron-forge/maker-squirrel/-/maker-squirrel-7.11.1.tgz", { "dependencies": { "@electron-forge/maker-base": "7.11.1", "@electron-forge/shared-types": "7.11.1", "fs-extra": "^10.0.0" }, "optionalDependencies": { "electron-winstaller": "^5.3.0" } }, "sha512-oSg7fgad6l+X0DjtRkSpMzB0AjzyDO4mb2gzM4kTodkP1ADeiMi08bxy0ZeCESqLm5+fG72cAPmEr3BAPvI1yw=="], + + "@electron-forge/maker-zip": ["@electron-forge/maker-zip@7.11.1", "https://registry.npmmirror.com/@electron-forge/maker-zip/-/maker-zip-7.11.1.tgz", { "dependencies": { "@electron-forge/maker-base": "7.11.1", "@electron-forge/shared-types": "7.11.1", "cross-zip": "^4.0.0", "fs-extra": "^10.0.0", "got": "^11.8.5" } }, "sha512-30rcp0AbJLfkFBX2hmO14LKXx7z9V61LffTVbTCFMh5vUB2kZvcA5xAhsBk2oUJWfGVxe1DuSEU0rDR9bUMHUg=="], + + "@electron-forge/plugin-auto-unpack-natives": ["@electron-forge/plugin-auto-unpack-natives@7.11.1", "https://registry.npmmirror.com/@electron-forge/plugin-auto-unpack-natives/-/plugin-auto-unpack-natives-7.11.1.tgz", { "dependencies": { "@electron-forge/plugin-base": "7.11.1", "@electron-forge/shared-types": "7.11.1" } }, "sha512-5uRM3WNv7jIeDt8pLP3V4U2puWHPGJ/3qRuSE47RKgTp5qxpZidWHSYcEJJxjoqOL/7KFwSqKSQ/a36GoZV4Fg=="], + + "@electron-forge/plugin-base": ["@electron-forge/plugin-base@7.11.1", "https://registry.npmmirror.com/@electron-forge/plugin-base/-/plugin-base-7.11.1.tgz", { "dependencies": { "@electron-forge/shared-types": "7.11.1" } }, "sha512-lKpSOV1GA3FoYiD9k05i6v4KaQVmojnRgCr7d6VL1bFp13QOtXSaAWhFI9mtSY7rGElOacX6Zt7P7rPoB8T9eQ=="], + + "@electron-forge/plugin-fuses": ["@electron-forge/plugin-fuses@7.11.1", "https://registry.npmmirror.com/@electron-forge/plugin-fuses/-/plugin-fuses-7.11.1.tgz", { "dependencies": { "@electron-forge/plugin-base": "7.11.1", "@electron-forge/shared-types": "7.11.1" }, "peerDependencies": { "@electron/fuses": "^1.0.0" } }, "sha512-Td517mHf+RjQAayFDM2kKb7NaGdRXrZfPbc7KOHlGbXthp5YTkFu2cCZGWokiqt1y1wsFaAodULhqBIg7vbbbw=="], + + "@electron-forge/plugin-vite": ["@electron-forge/plugin-vite@7.11.1", "https://registry.npmmirror.com/@electron-forge/plugin-vite/-/plugin-vite-7.11.1.tgz", { "dependencies": { "@electron-forge/plugin-base": "7.11.1", "@electron-forge/shared-types": "7.11.1", "chalk": "^4.0.0", "debug": "^4.3.1", "fs-extra": "^10.0.0", "listr2": "^7.0.2" } }, "sha512-kc/WQs/0+9VC9Q4oSSocMa02YxKDvAYxhWtNcL+qlswZMJlxe8gX7vl/yXq9AjPQxw7f3jzf7nruUPKQ+vyLLg=="], + + "@electron-forge/publisher-base": ["@electron-forge/publisher-base@7.11.1", "https://registry.npmmirror.com/@electron-forge/publisher-base/-/publisher-base-7.11.1.tgz", { "dependencies": { "@electron-forge/shared-types": "7.11.1" } }, "sha512-rXE9oMFGMtdQrixnumWYH5TTGsp99iPHZb3jI74YWq518ctCh6DlIgWlhf6ok2X0+lhWovcIb45KJucUFAQ13w=="], + + "@electron-forge/shared-types": ["@electron-forge/shared-types@7.11.1", "https://registry.npmmirror.com/@electron-forge/shared-types/-/shared-types-7.11.1.tgz", { "dependencies": { "@electron-forge/tracer": "7.11.1", "@electron/packager": "^18.3.5", "@electron/rebuild": "^3.7.0", "listr2": "^7.0.2" } }, "sha512-vvBWdAEh53UJlDGUevpaJk1+sqDMQibfrbHR+0IPA4MPyQex7/Uhv3vYH9oGHujBVAChQahjAuJt0fG6IJBLZg=="], + + "@electron-forge/template-base": ["@electron-forge/template-base@7.11.1", "https://registry.npmmirror.com/@electron-forge/template-base/-/template-base-7.11.1.tgz", { "dependencies": { "@electron-forge/core-utils": "7.11.1", "@electron-forge/shared-types": "7.11.1", "@malept/cross-spawn-promise": "^2.0.0", "debug": "^4.3.1", "fs-extra": "^10.0.0", "semver": "^7.2.1", "username": "^5.1.0" } }, "sha512-XpTaEf+EfQw+0BlSAtSpZKYIKYvKu4raNzSGHZZoSYHp+HDC7R+MlpFQmSJiGdYQzQ14C+uxO42tVjgM0DMbpw=="], + + "@electron-forge/template-vite": ["@electron-forge/template-vite@7.11.1", "https://registry.npmmirror.com/@electron-forge/template-vite/-/template-vite-7.11.1.tgz", { "dependencies": { "@electron-forge/shared-types": "7.11.1", "@electron-forge/template-base": "7.11.1", "fs-extra": "^10.0.0" } }, "sha512-Or8Lxf4awoeUZoMTKJEw5KQDIhqOFs24WhVka3yZXxc6VgVWN79KmYKYM6uM/YMQttmafhsBhY2t1Lxo1WR/ug=="], + + "@electron-forge/template-vite-typescript": ["@electron-forge/template-vite-typescript@7.11.1", "https://registry.npmmirror.com/@electron-forge/template-vite-typescript/-/template-vite-typescript-7.11.1.tgz", { "dependencies": { "@electron-forge/shared-types": "7.11.1", "@electron-forge/template-base": "7.11.1", "fs-extra": "^10.0.0" } }, "sha512-Us4AHXFb+4z+gXgZImSqMBS63oKnsQWLOhqRg321xiDzu2UcQPlwgWNb4rAEKNVC1e7LXrUNDHuBiTrQkvWXbg=="], + + "@electron-forge/template-webpack": ["@electron-forge/template-webpack@7.11.1", "https://registry.npmmirror.com/@electron-forge/template-webpack/-/template-webpack-7.11.1.tgz", { "dependencies": { "@electron-forge/shared-types": "7.11.1", "@electron-forge/template-base": "7.11.1", "fs-extra": "^10.0.0" } }, "sha512-15lbXxi+er461MPk6sbwAOyjofAHwmQjTvxNCiNpaU2naEwbj3t0SlLq/BMr5HxnVOaMmA7+lKV9afkIom+d4Q=="], + + "@electron-forge/template-webpack-typescript": ["@electron-forge/template-webpack-typescript@7.11.1", "https://registry.npmmirror.com/@electron-forge/template-webpack-typescript/-/template-webpack-typescript-7.11.1.tgz", { "dependencies": { "@electron-forge/shared-types": "7.11.1", "@electron-forge/template-base": "7.11.1", "fs-extra": "^10.0.0", "typescript": "~5.4.5", "webpack": "^5.69.1" } }, "sha512-6ExfFnFkHBz8rvRFTFg5HVGTC12uJpbVk4q8DVg0R8rhhxhqiVNh8lF2UPtZ2yT2UtGWjXNVlyP3Y3T6q6E3GQ=="], + + "@electron-forge/tracer": ["@electron-forge/tracer@7.11.1", "https://registry.npmmirror.com/@electron-forge/tracer/-/tracer-7.11.1.tgz", { "dependencies": { "chrome-trace-event": "^1.0.3" } }, "sha512-tiB6cglVQFcSw9N8GRwVwZUeB9u0DOx2Mj7aFXBUsFLUYQapvVGv51tUSy/UAW5lvmubGscYIILuVko+II3+NA=="], + + "@electron/asar": ["@electron/asar@3.4.1", "https://registry.npmmirror.com/@electron/asar/-/asar-3.4.1.tgz", { "dependencies": { "commander": "^5.0.0", "glob": "^7.1.6", "minimatch": "^3.0.4" }, "bin": { "asar": "bin/asar.js" } }, "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA=="], + + "@electron/fuses": ["@electron/fuses@1.8.0", "https://registry.npmmirror.com/@electron/fuses/-/fuses-1.8.0.tgz", { "dependencies": { "chalk": "^4.1.1", "fs-extra": "^9.0.1", "minimist": "^1.2.5" }, "bin": { "electron-fuses": "dist/bin.js" } }, "sha512-zx0EIq78WlY/lBb1uXlziZmDZI4ubcCXIMJ4uGjXzZW0nS19TjSPeXPAjzzTmKQlJUZm0SbmZhPKP7tuQ1SsEw=="], + + "@electron/get": ["@electron/get@3.1.0", "https://registry.npmmirror.com/@electron/get/-/get-3.1.0.tgz", { "dependencies": { "debug": "^4.1.1", "env-paths": "^2.2.0", "fs-extra": "^8.1.0", "got": "^11.8.5", "progress": "^2.0.3", "semver": "^6.2.0", "sumchecker": "^3.0.1" }, "optionalDependencies": { "global-agent": "^3.0.0" } }, "sha512-F+nKc0xW+kVbBRhFzaMgPy3KwmuNTYX1fx6+FxxoSnNgwYX6LD7AKBTWkU0MQ6IBoe7dz069CNkR673sPAgkCQ=="], + + "@electron/node-gyp": ["@electron/node-gyp@git+ssh://git@github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2", { "dependencies": { "env-paths": "^2.2.0", "exponential-backoff": "^3.1.1", "glob": "^8.1.0", "graceful-fs": "^4.2.6", "make-fetch-happen": "^10.2.1", "nopt": "^6.0.0", "proc-log": "^2.0.1", "semver": "^7.3.5", "tar": "^6.2.1", "which": "^2.0.2" }, "bin": { "node-gyp": "bin/node-gyp.js" } }, "06b29aafb7708acef8b3669835c8a7857ebc92d2", "sha512-lBSgDMQqt7QWMuIjS8zNAq5FI5o5RVBAcJUGWGI6GgoQITJt3msAkUrHp8YHj3RTVE+h70ndqMGqURjp3IfRyQ=="], + + "@electron/notarize": ["@electron/notarize@2.5.0", "https://registry.npmmirror.com/@electron/notarize/-/notarize-2.5.0.tgz", { "dependencies": { "debug": "^4.1.1", "fs-extra": "^9.0.1", "promise-retry": "^2.0.1" } }, "sha512-jNT8nwH1f9X5GEITXaQ8IF/KdskvIkOFfB2CvwumsveVidzpSc+mvhhTMdAGSYF3O+Nq49lJ7y+ssODRXu06+A=="], + + "@electron/osx-sign": ["@electron/osx-sign@1.3.3", "https://registry.npmmirror.com/@electron/osx-sign/-/osx-sign-1.3.3.tgz", { "dependencies": { "compare-version": "^0.1.2", "debug": "^4.3.4", "fs-extra": "^10.0.0", "isbinaryfile": "^4.0.8", "minimist": "^1.2.6", "plist": "^3.0.5" }, "bin": { "electron-osx-flat": "bin/electron-osx-flat.js", "electron-osx-sign": "bin/electron-osx-sign.js" } }, "sha512-KZ8mhXvWv2rIEgMbWZ4y33bDHyUKMXnx4M0sTyPNK/vcB81ImdeY9Ggdqy0SWbMDgmbqyQ+phgejh6V3R2QuSg=="], + + "@electron/packager": ["@electron/packager@18.4.4", "https://registry.npmmirror.com/@electron/packager/-/packager-18.4.4.tgz", { "dependencies": { "@electron/asar": "^3.2.13", "@electron/get": "^3.0.0", "@electron/notarize": "^2.1.0", "@electron/osx-sign": "^1.0.5", "@electron/universal": "^2.0.1", "@electron/windows-sign": "^1.0.0", "@malept/cross-spawn-promise": "^2.0.0", "debug": "^4.0.1", "extract-zip": "^2.0.0", "filenamify": "^4.1.0", "fs-extra": "^11.1.0", "galactus": "^1.0.0", "get-package-info": "^1.0.0", "junk": "^3.1.0", "parse-author": "^2.0.0", "plist": "^3.0.0", "prettier": "^3.4.2", "resedit": "^2.0.0", "resolve": "^1.1.6", "semver": "^7.1.3", "yargs-parser": "^21.1.1" }, "bin": { "electron-packager": "bin/electron-packager.js" } }, "sha512-fTUCmgL25WXTcFpM1M72VmFP8w3E4d+KNzWxmTDRpvwkfn/S206MAtM2cy0GF78KS9AwASMOUmlOIzCHeNxcGQ=="], + + "@electron/rebuild": ["@electron/rebuild@3.7.2", "https://registry.npmmirror.com/@electron/rebuild/-/rebuild-3.7.2.tgz", { "dependencies": { "@electron/node-gyp": "git+https://github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2", "@malept/cross-spawn-promise": "^2.0.0", "chalk": "^4.0.0", "debug": "^4.1.1", "detect-libc": "^2.0.1", "fs-extra": "^10.0.0", "got": "^11.7.0", "node-abi": "^3.45.0", "node-api-version": "^0.2.0", "ora": "^5.1.0", "read-binary-file-arch": "^1.0.6", "semver": "^7.3.5", "tar": "^6.0.5", "yargs": "^17.0.1" }, "bin": { "electron-rebuild": "lib/cli.js" } }, "sha512-19/KbIR/DAxbsCkiaGMXIdPnMCJLkcf8AvGnduJtWBs/CBwiAjY1apCqOLVxrXg+rtXFCngbXhBanWjxLUt1Mg=="], + + "@electron/universal": ["@electron/universal@2.0.3", "https://registry.npmmirror.com/@electron/universal/-/universal-2.0.3.tgz", { "dependencies": { "@electron/asar": "^3.3.1", "@malept/cross-spawn-promise": "^2.0.0", "debug": "^4.3.1", "dir-compare": "^4.2.0", "fs-extra": "^11.1.1", "minimatch": "^9.0.3", "plist": "^3.1.0" } }, "sha512-Wn9sPYIVFRFl5HmwMJkARCCf7rqK/EurkfQ/rJZ14mHP3iYTjZSIOSVonEAnhWeAXwtw7zOekGRlc6yTtZ0t+g=="], + + "@electron/windows-sign": ["@electron/windows-sign@1.2.2", "https://registry.npmmirror.com/@electron/windows-sign/-/windows-sign-1.2.2.tgz", { "dependencies": { "cross-dirname": "^0.1.0", "debug": "^4.3.4", "fs-extra": "^11.1.1", "minimist": "^1.2.8", "postject": "^1.0.0-alpha.6" }, "bin": { "electron-windows-sign": "bin/electron-windows-sign.js" } }, "sha512-dfZeox66AvdPtb2lD8OsIIQh12Tp0GNCRUDfBHIKGpbmopZto2/A8nSpYYLoedPIHpqkeblZ/k8OV0Gy7PYuyQ=="], + + "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.3", "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", { "os": "aix", "cpu": "ppc64" }, "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg=="], + + "@esbuild/android-arm": ["@esbuild/android-arm@0.27.3", "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.27.3.tgz", { "os": "android", "cpu": "arm" }, "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA=="], + + "@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.3", "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", { "os": "android", "cpu": "arm64" }, "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg=="], + + "@esbuild/android-x64": ["@esbuild/android-x64@0.27.3", "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.27.3.tgz", { "os": "android", "cpu": "x64" }, "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ=="], + + "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.3", "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", { "os": "darwin", "cpu": "arm64" }, "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg=="], + + "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.3", "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", { "os": "darwin", "cpu": "x64" }, "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg=="], + + "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.3", "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", { "os": "freebsd", "cpu": "arm64" }, "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w=="], + + "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.3", "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", { "os": "freebsd", "cpu": "x64" }, "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA=="], + + "@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.3", "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", { "os": "linux", "cpu": "arm" }, "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw=="], + + "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.3", "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", { "os": "linux", "cpu": "arm64" }, "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg=="], + + "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.3", "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", { "os": "linux", "cpu": "ia32" }, "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg=="], + + "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.3", "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", { "os": "linux", "cpu": "none" }, "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA=="], + + "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.3", "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", { "os": "linux", "cpu": "none" }, "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw=="], + + "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.3", "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", { "os": "linux", "cpu": "ppc64" }, "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA=="], + + "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.3", "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", { "os": "linux", "cpu": "none" }, "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ=="], + + "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.3", "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", { "os": "linux", "cpu": "s390x" }, "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw=="], + + "@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.3", "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", { "os": "linux", "cpu": "x64" }, "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA=="], + + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.3", "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", { "os": "none", "cpu": "arm64" }, "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA=="], + + "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.3", "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", { "os": "none", "cpu": "x64" }, "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA=="], + + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.3", "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", { "os": "openbsd", "cpu": "arm64" }, "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw=="], + + "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.3", "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", { "os": "openbsd", "cpu": "x64" }, "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ=="], + + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.3", "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", { "os": "none", "cpu": "arm64" }, "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g=="], + + "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.3", "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", { "os": "sunos", "cpu": "x64" }, "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA=="], + + "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.3", "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", { "os": "win32", "cpu": "arm64" }, "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA=="], + + "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.3", "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", { "os": "win32", "cpu": "ia32" }, "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q=="], + + "@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.3", "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", { "os": "win32", "cpu": "x64" }, "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA=="], + + "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="], + + "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="], + + "@eslint/config-array": ["@eslint/config-array@0.21.2", "", { "dependencies": { "@eslint/object-schema": "^2.1.7", "debug": "^4.3.1", "minimatch": "^3.1.5" } }, "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw=="], + + "@eslint/config-helpers": ["@eslint/config-helpers@0.4.2", "", { "dependencies": { "@eslint/core": "^0.17.0" } }, "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw=="], + + "@eslint/core": ["@eslint/core@0.17.0", "", { "dependencies": { "@types/json-schema": "^7.0.15" } }, "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ=="], + + "@eslint/eslintrc": ["@eslint/eslintrc@3.3.5", "", { "dependencies": { "ajv": "^6.14.0", "debug": "^4.3.2", "espree": "^10.0.1", "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.1", "minimatch": "^3.1.5", "strip-json-comments": "^3.1.1" } }, "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg=="], + + "@eslint/js": ["@eslint/js@9.39.4", "", {}, "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw=="], + + "@eslint/object-schema": ["@eslint/object-schema@2.1.7", "", {}, "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA=="], + + "@eslint/plugin-kit": ["@eslint/plugin-kit@0.4.1", "", { "dependencies": { "@eslint/core": "^0.17.0", "levn": "^0.4.1" } }, "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA=="], + + "@gar/promisify": ["@gar/promisify@1.1.3", "https://registry.npmmirror.com/@gar/promisify/-/promisify-1.1.3.tgz", {}, "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw=="], + + "@humanfs/core": ["@humanfs/core@0.19.2", "", { "dependencies": { "@humanfs/types": "^0.15.0" } }, "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA=="], + + "@humanfs/node": ["@humanfs/node@0.16.8", "", { "dependencies": { "@humanfs/core": "^0.19.2", "@humanfs/types": "^0.15.0", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ=="], + + "@humanfs/types": ["@humanfs/types@0.15.0", "", {}, "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q=="], + + "@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="], + + "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], + + "@inquirer/checkbox": ["@inquirer/checkbox@3.0.1", "https://registry.npmmirror.com/@inquirer/checkbox/-/checkbox-3.0.1.tgz", { "dependencies": { "@inquirer/core": "^9.2.1", "@inquirer/figures": "^1.0.6", "@inquirer/type": "^2.0.0", "ansi-escapes": "^4.3.2", "yoctocolors-cjs": "^2.1.2" } }, "sha512-0hm2nrToWUdD6/UHnel/UKGdk1//ke5zGUpHIvk5ZWmaKezlGxZkOJXNSWsdxO/rEqTkbB3lNC2J6nBElV2aAQ=="], + + "@inquirer/confirm": ["@inquirer/confirm@4.0.1", "https://registry.npmmirror.com/@inquirer/confirm/-/confirm-4.0.1.tgz", { "dependencies": { "@inquirer/core": "^9.2.1", "@inquirer/type": "^2.0.0" } }, "sha512-46yL28o2NJ9doViqOy0VDcoTzng7rAb6yPQKU7VDLqkmbCaH4JqK4yk4XqlzNWy9PVC5pG1ZUXPBQv+VqnYs2w=="], + + "@inquirer/core": ["@inquirer/core@9.2.1", "https://registry.npmmirror.com/@inquirer/core/-/core-9.2.1.tgz", { "dependencies": { "@inquirer/figures": "^1.0.6", "@inquirer/type": "^2.0.0", "@types/mute-stream": "^0.0.4", "@types/node": "^22.5.5", "@types/wrap-ansi": "^3.0.0", "ansi-escapes": "^4.3.2", "cli-width": "^4.1.0", "mute-stream": "^1.0.0", "signal-exit": "^4.1.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^6.2.0", "yoctocolors-cjs": "^2.1.2" } }, "sha512-F2VBt7W/mwqEU4bL0RnHNZmC/OxzNx9cOYxHqnXX3MP6ruYvZUZAW9imgN9+h/uBT/oP8Gh888J2OZSbjSeWcg=="], + + "@inquirer/editor": ["@inquirer/editor@3.0.1", "https://registry.npmmirror.com/@inquirer/editor/-/editor-3.0.1.tgz", { "dependencies": { "@inquirer/core": "^9.2.1", "@inquirer/type": "^2.0.0", "external-editor": "^3.1.0" } }, "sha512-VA96GPFaSOVudjKFraokEEmUQg/Lub6OXvbIEZU1SDCmBzRkHGhxoFAVaF30nyiB4m5cEbDgiI2QRacXZ2hw9Q=="], + + "@inquirer/expand": ["@inquirer/expand@3.0.1", "https://registry.npmmirror.com/@inquirer/expand/-/expand-3.0.1.tgz", { "dependencies": { "@inquirer/core": "^9.2.1", "@inquirer/type": "^2.0.0", "yoctocolors-cjs": "^2.1.2" } }, "sha512-ToG8d6RIbnVpbdPdiN7BCxZGiHOTomOX94C2FaT5KOHupV40tKEDozp12res6cMIfRKrXLJyexAZhWVHgbALSQ=="], + + "@inquirer/figures": ["@inquirer/figures@1.0.15", "https://registry.npmmirror.com/@inquirer/figures/-/figures-1.0.15.tgz", {}, "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g=="], + + "@inquirer/input": ["@inquirer/input@3.0.1", "https://registry.npmmirror.com/@inquirer/input/-/input-3.0.1.tgz", { "dependencies": { "@inquirer/core": "^9.2.1", "@inquirer/type": "^2.0.0" } }, "sha512-BDuPBmpvi8eMCxqC5iacloWqv+5tQSJlUafYWUe31ow1BVXjW2a5qe3dh4X/Z25Wp22RwvcaLCc2siHobEOfzg=="], + + "@inquirer/number": ["@inquirer/number@2.0.1", "https://registry.npmmirror.com/@inquirer/number/-/number-2.0.1.tgz", { "dependencies": { "@inquirer/core": "^9.2.1", "@inquirer/type": "^2.0.0" } }, "sha512-QpR8jPhRjSmlr/mD2cw3IR8HRO7lSVOnqUvQa8scv1Lsr3xoAMMworcYW3J13z3ppjBFBD2ef1Ci6AE5Qn8goQ=="], + + "@inquirer/password": ["@inquirer/password@3.0.1", "https://registry.npmmirror.com/@inquirer/password/-/password-3.0.1.tgz", { "dependencies": { "@inquirer/core": "^9.2.1", "@inquirer/type": "^2.0.0", "ansi-escapes": "^4.3.2" } }, "sha512-haoeEPUisD1NeE2IanLOiFr4wcTXGWrBOyAyPZi1FfLJuXOzNmxCJPgUrGYKVh+Y8hfGJenIfz5Wb/DkE9KkMQ=="], + + "@inquirer/prompts": ["@inquirer/prompts@6.0.1", "https://registry.npmmirror.com/@inquirer/prompts/-/prompts-6.0.1.tgz", { "dependencies": { "@inquirer/checkbox": "^3.0.1", "@inquirer/confirm": "^4.0.1", "@inquirer/editor": "^3.0.1", "@inquirer/expand": "^3.0.1", "@inquirer/input": "^3.0.1", "@inquirer/number": "^2.0.1", "@inquirer/password": "^3.0.1", "@inquirer/rawlist": "^3.0.1", "@inquirer/search": "^2.0.1", "@inquirer/select": "^3.0.1" } }, "sha512-yl43JD/86CIj3Mz5mvvLJqAOfIup7ncxfJ0Btnl0/v5TouVUyeEdcpknfgc+yMevS/48oH9WAkkw93m7otLb/A=="], + + "@inquirer/rawlist": ["@inquirer/rawlist@3.0.1", "https://registry.npmmirror.com/@inquirer/rawlist/-/rawlist-3.0.1.tgz", { "dependencies": { "@inquirer/core": "^9.2.1", "@inquirer/type": "^2.0.0", "yoctocolors-cjs": "^2.1.2" } }, "sha512-VgRtFIwZInUzTiPLSfDXK5jLrnpkuSOh1ctfaoygKAdPqjcjKYmGh6sCY1pb0aGnCGsmhUxoqLDUAU0ud+lGXQ=="], + + "@inquirer/search": ["@inquirer/search@2.0.1", "https://registry.npmmirror.com/@inquirer/search/-/search-2.0.1.tgz", { "dependencies": { "@inquirer/core": "^9.2.1", "@inquirer/figures": "^1.0.6", "@inquirer/type": "^2.0.0", "yoctocolors-cjs": "^2.1.2" } }, "sha512-r5hBKZk3g5MkIzLVoSgE4evypGqtOannnB3PKTG9NRZxyFRKcfzrdxXXPcoJQsxJPzvdSU2Rn7pB7lw0GCmGAg=="], + + "@inquirer/select": ["@inquirer/select@3.0.1", "https://registry.npmmirror.com/@inquirer/select/-/select-3.0.1.tgz", { "dependencies": { "@inquirer/core": "^9.2.1", "@inquirer/figures": "^1.0.6", "@inquirer/type": "^2.0.0", "ansi-escapes": "^4.3.2", "yoctocolors-cjs": "^2.1.2" } }, "sha512-lUDGUxPhdWMkN/fHy1Lk7pF3nK1fh/gqeyWXmctefhxLYxlDsc7vsPBEpxrfVGDsVdyYJsiJoD4bJ1b623cV1Q=="], + + "@inquirer/type": ["@inquirer/type@1.5.5", "https://registry.npmmirror.com/@inquirer/type/-/type-1.5.5.tgz", { "dependencies": { "mute-stream": "^1.0.0" } }, "sha512-MzICLu4yS7V8AA61sANROZ9vT1H3ooca5dSmI1FjZkzq7o/koMsRfQSzRtFo+F3Ao4Sf1C0bpLKejpKB/+j6MA=="], + + "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], + + "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "https://registry.npmmirror.com/@jridgewell/remapping/-/remapping-2.3.5.tgz", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="], + + "@jridgewell/resolve-uri": ["@jridgewell/resolve-uri@3.1.2", "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", {}, "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw=="], + + "@jridgewell/source-map": ["@jridgewell/source-map@0.3.11", "https://registry.npmmirror.com/@jridgewell/source-map/-/source-map-0.3.11.tgz", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" } }, "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA=="], + + "@jridgewell/sourcemap-codec": ["@jridgewell/sourcemap-codec@1.5.5", "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", {}, "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og=="], + + "@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.31", "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", { "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw=="], + + "@listr2/prompt-adapter-inquirer": ["@listr2/prompt-adapter-inquirer@2.0.22", "https://registry.npmmirror.com/@listr2/prompt-adapter-inquirer/-/prompt-adapter-inquirer-2.0.22.tgz", { "dependencies": { "@inquirer/type": "^1.5.5" }, "peerDependencies": { "@inquirer/prompts": ">= 3 < 8" } }, "sha512-hV36ZoY+xKL6pYOt1nPNnkciFkn89KZwqLhAFzJvYysAvL5uBQdiADZx/8bIDXIukzzwG0QlPYolgMzQUtKgpQ=="], + + "@malept/cross-spawn-promise": ["@malept/cross-spawn-promise@2.0.0", "https://registry.npmmirror.com/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz", { "dependencies": { "cross-spawn": "^7.0.1" } }, "sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg=="], + + "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], + + "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], + + "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], + + "@npmcli/fs": ["@npmcli/fs@2.1.2", "https://registry.npmmirror.com/@npmcli/fs/-/fs-2.1.2.tgz", { "dependencies": { "@gar/promisify": "^1.1.3", "semver": "^7.3.5" } }, "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ=="], + + "@npmcli/move-file": ["@npmcli/move-file@2.0.1", "https://registry.npmmirror.com/@npmcli/move-file/-/move-file-2.0.1.tgz", { "dependencies": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" } }, "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ=="], + + "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.3", "https://registry.npmmirror.com/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", {}, "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q=="], + + "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", { "os": "android", "cpu": "arm" }, "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg=="], + + "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", { "os": "android", "cpu": "arm64" }, "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q=="], + + "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", { "os": "darwin", "cpu": "arm64" }, "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg=="], + + "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", { "os": "darwin", "cpu": "x64" }, "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w=="], + + "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", { "os": "freebsd", "cpu": "arm64" }, "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA=="], + + "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", { "os": "freebsd", "cpu": "x64" }, "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg=="], + + "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", { "os": "linux", "cpu": "arm" }, "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw=="], + + "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", { "os": "linux", "cpu": "arm" }, "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA=="], + + "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", { "os": "linux", "cpu": "arm64" }, "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA=="], + + "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", { "os": "linux", "cpu": "arm64" }, "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA=="], + + "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", { "os": "linux", "cpu": "none" }, "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg=="], + + "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", { "os": "linux", "cpu": "none" }, "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q=="], + + "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", { "os": "linux", "cpu": "ppc64" }, "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA=="], + + "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", { "os": "linux", "cpu": "ppc64" }, "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA=="], + + "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", { "os": "linux", "cpu": "none" }, "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg=="], + + "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", { "os": "linux", "cpu": "none" }, "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg=="], + + "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", { "os": "linux", "cpu": "s390x" }, "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w=="], + + "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", { "os": "linux", "cpu": "x64" }, "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg=="], + + "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", { "os": "linux", "cpu": "x64" }, "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg=="], + + "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", { "os": "openbsd", "cpu": "x64" }, "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ=="], + + "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", { "os": "none", "cpu": "arm64" }, "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA=="], + + "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", { "os": "win32", "cpu": "arm64" }, "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A=="], + + "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", { "os": "win32", "cpu": "ia32" }, "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA=="], + + "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", { "os": "win32", "cpu": "x64" }, "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA=="], + + "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", { "os": "win32", "cpu": "x64" }, "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA=="], + + "@sindresorhus/is": ["@sindresorhus/is@4.6.0", "https://registry.npmmirror.com/@sindresorhus/is/-/is-4.6.0.tgz", {}, "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw=="], + + "@szmarczak/http-timer": ["@szmarczak/http-timer@4.0.6", "https://registry.npmmirror.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", { "dependencies": { "defer-to-connect": "^2.0.0" } }, "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w=="], + + "@tootallnate/once": ["@tootallnate/once@2.0.0", "https://registry.npmmirror.com/@tootallnate/once/-/once-2.0.0.tgz", {}, "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A=="], + + "@types/appdmg": ["@types/appdmg@0.5.5", "https://registry.npmmirror.com/@types/appdmg/-/appdmg-0.5.5.tgz", { "dependencies": { "@types/node": "*" } }, "sha512-G+n6DgZTZFOteITE30LnWj+HRVIGr7wMlAiLWOO02uJFWVEitaPU9JVXm9wJokkgshBawb2O1OykdcsmkkZfgg=="], + + "@types/babel__core": ["@types/babel__core@7.20.5", "https://registry.npmmirror.com/@types/babel__core/-/babel__core-7.20.5.tgz", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="], + + "@types/babel__generator": ["@types/babel__generator@7.27.0", "https://registry.npmmirror.com/@types/babel__generator/-/babel__generator-7.27.0.tgz", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="], + + "@types/babel__template": ["@types/babel__template@7.4.4", "https://registry.npmmirror.com/@types/babel__template/-/babel__template-7.4.4.tgz", { "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A=="], + + "@types/babel__traverse": ["@types/babel__traverse@7.28.0", "https://registry.npmmirror.com/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="], + + "@types/bun": ["@types/bun@1.3.14", "", { "dependencies": { "bun-types": "1.3.14" } }, "sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw=="], + + "@types/cacheable-request": ["@types/cacheable-request@6.0.3", "https://registry.npmmirror.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", { "dependencies": { "@types/http-cache-semantics": "*", "@types/keyv": "^3.1.4", "@types/node": "*", "@types/responselike": "^1.0.0" } }, "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw=="], + + "@types/eslint": ["@types/eslint@9.6.1", "https://registry.npmmirror.com/@types/eslint/-/eslint-9.6.1.tgz", { "dependencies": { "@types/estree": "*", "@types/json-schema": "*" } }, "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag=="], + + "@types/eslint-scope": ["@types/eslint-scope@3.7.7", "https://registry.npmmirror.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", { "dependencies": { "@types/eslint": "*", "@types/estree": "*" } }, "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg=="], + + "@types/estree": ["@types/estree@1.0.8", "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], + + "@types/fs-extra": ["@types/fs-extra@9.0.13", "https://registry.npmmirror.com/@types/fs-extra/-/fs-extra-9.0.13.tgz", { "dependencies": { "@types/node": "*" } }, "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA=="], + + "@types/http-cache-semantics": ["@types/http-cache-semantics@4.2.0", "https://registry.npmmirror.com/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", {}, "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q=="], + + "@types/json-schema": ["@types/json-schema@7.0.15", "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], + + "@types/keyv": ["@types/keyv@3.1.4", "https://registry.npmmirror.com/@types/keyv/-/keyv-3.1.4.tgz", { "dependencies": { "@types/node": "*" } }, "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg=="], + + "@types/mute-stream": ["@types/mute-stream@0.0.4", "https://registry.npmmirror.com/@types/mute-stream/-/mute-stream-0.0.4.tgz", { "dependencies": { "@types/node": "*" } }, "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow=="], + + "@types/node": ["@types/node@25.9.3", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-603BddQMv3pUcr4U2dhujk83N2tTDVr/34wII2B6bJy6g+8WD6yUb11jszNs0gdi4PesVWl7ABt8nYMVpnLUcg=="], + + "@types/react": ["@types/react@19.2.17", "", { "dependencies": { "csstype": "^3.2.2" } }, "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw=="], + + "@types/react-dom": ["@types/react-dom@19.2.3", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ=="], + + "@types/responselike": ["@types/responselike@1.0.3", "https://registry.npmmirror.com/@types/responselike/-/responselike-1.0.3.tgz", { "dependencies": { "@types/node": "*" } }, "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw=="], + + "@types/wrap-ansi": ["@types/wrap-ansi@3.0.0", "https://registry.npmmirror.com/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", {}, "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g=="], + + "@types/yauzl": ["@types/yauzl@2.10.3", "https://registry.npmmirror.com/@types/yauzl/-/yauzl-2.10.3.tgz", { "dependencies": { "@types/node": "*" } }, "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q=="], + + "@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.61.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.12.2", "@typescript-eslint/scope-manager": "8.61.0", "@typescript-eslint/type-utils": "8.61.0", "@typescript-eslint/utils": "8.61.0", "@typescript-eslint/visitor-keys": "8.61.0", "ignore": "^7.0.5", "natural-compare": "^1.4.0", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.61.0", "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-bFNvl9ZczlVb+wR2Akszf3gHfKVj/8WanXaGJ3UstTA7brNKg0cNdk6X1Psu5V7MZ2oQtzZKOEzIUehaoxbDGw=="], + + "@typescript-eslint/parser": ["@typescript-eslint/parser@8.61.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.61.0", "@typescript-eslint/types": "8.61.0", "@typescript-eslint/typescript-estree": "8.61.0", "@typescript-eslint/visitor-keys": "8.61.0", "debug": "^4.4.3" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-5B7PfA2e1NQGCnDHd/0lW7W3gvp3d59Ryw54FYO8Uswxo9f6ikw3AZV+Xj/TvpImmpsiYyUqAfhC6kJID1jF6w=="], + + "@typescript-eslint/project-service": ["@typescript-eslint/project-service@8.61.0", "", { "dependencies": { "@typescript-eslint/tsconfig-utils": "^8.61.0", "@typescript-eslint/types": "^8.61.0", "debug": "^4.4.3" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-DV42F7MLJO6Rax7SK1yg43tcnEfGUrurSpSxKuVX+a3RCTzBlH3fuxprrOJXKCJGAaw82xXocikJ0uQaqwXgGA=="], + + "@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.61.0", "", { "dependencies": { "@typescript-eslint/types": "8.61.0", "@typescript-eslint/visitor-keys": "8.61.0" } }, "sha512-IWdXFHFSb6mlC3HPc7QsLDm5zYEbUla6trDEHf32D3/dnuUyXd87plScSNXSbm0/RxMvObpI17sv/EDTGrGZkA=="], + + "@typescript-eslint/tsconfig-utils": ["@typescript-eslint/tsconfig-utils@8.61.0", "", { "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-O5Amvdv9ztMpxpf+vmFULGG78IE6Qwdr3bCGvqwG4nwc9H2qXkOYJJnRbRHyMkQTjv1d03olqwwwzHLMqpFePQ=="], + + "@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.61.0", "", { "dependencies": { "@typescript-eslint/types": "8.61.0", "@typescript-eslint/typescript-estree": "8.61.0", "@typescript-eslint/utils": "8.61.0", "debug": "^4.4.3", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-TuBiQYIkd97yBfInHCTKVYMbX4kvEmpOEuixIuzCU9p8BGT1SfyyO0d0IfDMbPIHcjn/hWnusUX5e8v5Xg+X8A=="], + + "@typescript-eslint/types": ["@typescript-eslint/types@8.61.0", "", {}, "sha512-9QTQpZ5Iin4CdIodfbDQFSeiSJKidgYJYug1P9CC2xWgUTvlmixViqDZNciMjwLBZyJnG4tGmPl97rVAFb1AJg=="], + + "@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.61.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.61.0", "@typescript-eslint/tsconfig-utils": "8.61.0", "@typescript-eslint/types": "8.61.0", "@typescript-eslint/visitor-keys": "8.61.0", "debug": "^4.4.3", "minimatch": "^10.2.2", "semver": "^7.7.3", "tinyglobby": "^0.2.15", "ts-api-utils": "^2.5.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.1.0" } }, "sha512-42zatd5qSvvcV1JdDBCLxYRznvP4eIHpPoZXdkPFnAmanA4FuZ5dibSnCBggY8hQnqajPpoGjXFdZ7fIJKQnlA=="], + + "@typescript-eslint/utils": ["@typescript-eslint/utils@8.61.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.9.1", "@typescript-eslint/scope-manager": "8.61.0", "@typescript-eslint/types": "8.61.0", "@typescript-eslint/typescript-estree": "8.61.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-3bzFt7ImFMW/jVYwJamDoe/dMOdFLSC6pom6rRjdh4SZJEYupyMzem8e7vKZLclLfpHjlwSAXOUxtKxGXUiLqA=="], + + "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.61.0", "", { "dependencies": { "@typescript-eslint/types": "8.61.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ=="], + + "@vitejs/plugin-react": ["@vitejs/plugin-react@5.1.4", "https://registry.npmmirror.com/@vitejs/plugin-react/-/plugin-react-5.1.4.tgz", { "dependencies": { "@babel/core": "^7.29.0", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-rc.3", "@types/babel__core": "^7.20.5", "react-refresh": "^0.18.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-VIcFLdRi/VYRU8OL/puL7QXMYafHmqOnwTZY50U1JPlCNj30PxCMx65c494b1K9be9hX83KVt0+gTEwTWLqToA=="], + + "@vscode/sudo-prompt": ["@vscode/sudo-prompt@9.3.2", "https://registry.npmmirror.com/@vscode/sudo-prompt/-/sudo-prompt-9.3.2.tgz", {}, "sha512-gcXoCN00METUNFeQOFJ+C9xUI0DKB+0EGMVg7wbVYRHBw2Eq3fKisDZOkRdOz3kqXRKOENMfShPOmypw1/8nOw=="], + + "@webassemblyjs/ast": ["@webassemblyjs/ast@1.14.1", "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.14.1.tgz", { "dependencies": { "@webassemblyjs/helper-numbers": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ=="], + + "@webassemblyjs/floating-point-hex-parser": ["@webassemblyjs/floating-point-hex-parser@1.13.2", "https://registry.npmmirror.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", {}, "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA=="], + + "@webassemblyjs/helper-api-error": ["@webassemblyjs/helper-api-error@1.13.2", "https://registry.npmmirror.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", {}, "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ=="], + + "@webassemblyjs/helper-buffer": ["@webassemblyjs/helper-buffer@1.14.1", "https://registry.npmmirror.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", {}, "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA=="], + + "@webassemblyjs/helper-numbers": ["@webassemblyjs/helper-numbers@1.13.2", "https://registry.npmmirror.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", { "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.13.2", "@webassemblyjs/helper-api-error": "1.13.2", "@xtuc/long": "4.2.2" } }, "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA=="], + + "@webassemblyjs/helper-wasm-bytecode": ["@webassemblyjs/helper-wasm-bytecode@1.13.2", "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", {}, "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA=="], + + "@webassemblyjs/helper-wasm-section": ["@webassemblyjs/helper-wasm-section@1.14.1", "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/wasm-gen": "1.14.1" } }, "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw=="], + + "@webassemblyjs/ieee754": ["@webassemblyjs/ieee754@1.13.2", "https://registry.npmmirror.com/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", { "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw=="], + + "@webassemblyjs/leb128": ["@webassemblyjs/leb128@1.13.2", "https://registry.npmmirror.com/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", { "dependencies": { "@xtuc/long": "4.2.2" } }, "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw=="], + + "@webassemblyjs/utf8": ["@webassemblyjs/utf8@1.13.2", "https://registry.npmmirror.com/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", {}, "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ=="], + + "@webassemblyjs/wasm-edit": ["@webassemblyjs/wasm-edit@1.14.1", "https://registry.npmmirror.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/helper-wasm-section": "1.14.1", "@webassemblyjs/wasm-gen": "1.14.1", "@webassemblyjs/wasm-opt": "1.14.1", "@webassemblyjs/wasm-parser": "1.14.1", "@webassemblyjs/wast-printer": "1.14.1" } }, "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ=="], + + "@webassemblyjs/wasm-gen": ["@webassemblyjs/wasm-gen@1.14.1", "https://registry.npmmirror.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/ieee754": "1.13.2", "@webassemblyjs/leb128": "1.13.2", "@webassemblyjs/utf8": "1.13.2" } }, "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg=="], + + "@webassemblyjs/wasm-opt": ["@webassemblyjs/wasm-opt@1.14.1", "https://registry.npmmirror.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-buffer": "1.14.1", "@webassemblyjs/wasm-gen": "1.14.1", "@webassemblyjs/wasm-parser": "1.14.1" } }, "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw=="], + + "@webassemblyjs/wasm-parser": ["@webassemblyjs/wasm-parser@1.14.1", "https://registry.npmmirror.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@webassemblyjs/helper-api-error": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2", "@webassemblyjs/ieee754": "1.13.2", "@webassemblyjs/leb128": "1.13.2", "@webassemblyjs/utf8": "1.13.2" } }, "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ=="], + + "@webassemblyjs/wast-printer": ["@webassemblyjs/wast-printer@1.14.1", "https://registry.npmmirror.com/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", { "dependencies": { "@webassemblyjs/ast": "1.14.1", "@xtuc/long": "4.2.2" } }, "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw=="], + + "@xmldom/xmldom": ["@xmldom/xmldom@0.8.11", "https://registry.npmmirror.com/@xmldom/xmldom/-/xmldom-0.8.11.tgz", {}, "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw=="], + + "@xtuc/ieee754": ["@xtuc/ieee754@1.2.0", "https://registry.npmmirror.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz", {}, "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA=="], + + "@xtuc/long": ["@xtuc/long@4.2.2", "https://registry.npmmirror.com/@xtuc/long/-/long-4.2.2.tgz", {}, "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="], + + "abbrev": ["abbrev@1.1.1", "https://registry.npmmirror.com/abbrev/-/abbrev-1.1.1.tgz", {}, "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="], + + "acorn": ["acorn@8.16.0", "https://registry.npmmirror.com/acorn/-/acorn-8.16.0.tgz", { "bin": "bin/acorn" }, "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw=="], + + "acorn-import-phases": ["acorn-import-phases@1.0.4", "https://registry.npmmirror.com/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", { "peerDependencies": { "acorn": "^8.14.0" } }, "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ=="], + + "acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="], + + "agent-base": ["agent-base@6.0.2", "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz", { "dependencies": { "debug": "4" } }, "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ=="], + + "agentkeepalive": ["agentkeepalive@4.6.0", "https://registry.npmmirror.com/agentkeepalive/-/agentkeepalive-4.6.0.tgz", { "dependencies": { "humanize-ms": "^1.2.1" } }, "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ=="], + + "aggregate-error": ["aggregate-error@3.1.0", "https://registry.npmmirror.com/aggregate-error/-/aggregate-error-3.1.0.tgz", { "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" } }, "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA=="], + + "ajv": ["ajv@6.15.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw=="], + + "ajv-formats": ["ajv-formats@2.1.1", "https://registry.npmmirror.com/ajv-formats/-/ajv-formats-2.1.1.tgz", { "dependencies": { "ajv": "^8.0.0" }, "peerDependencies": { "ajv": "^8.0.0" } }, "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA=="], + + "ajv-keywords": ["ajv-keywords@5.1.0", "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz", { "dependencies": { "fast-deep-equal": "^3.1.3" }, "peerDependencies": { "ajv": "^8.8.2" } }, "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw=="], + + "ansi-escapes": ["ansi-escapes@4.3.2", "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz", { "dependencies": { "type-fest": "^0.21.3" } }, "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ=="], + + "ansi-regex": ["ansi-regex@6.2.2", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.2.2.tgz", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], + + "ansi-styles": ["ansi-styles@4.3.0", "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], + + "appdmg": ["appdmg@0.6.6", "https://registry.npmmirror.com/appdmg/-/appdmg-0.6.6.tgz", { "dependencies": { "async": "^1.4.2", "ds-store": "^0.1.5", "execa": "^1.0.0", "fs-temp": "^1.0.0", "fs-xattr": "^0.3.0", "image-size": "^0.7.4", "is-my-json-valid": "^2.20.0", "minimist": "^1.1.3", "parse-color": "^1.0.0", "path-exists": "^4.0.0", "repeat-string": "^1.5.4" }, "os": "darwin", "bin": "bin/appdmg.js" }, "sha512-GRmFKlCG+PWbcYF4LUNonTYmy0GjguDy6Jh9WP8mpd0T6j80XIJyXBiWlD0U+MLNhqV9Nhx49Gl9GpVToulpLg=="], + + "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], + + "array-buffer-byte-length": ["array-buffer-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "is-array-buffer": "^3.0.5" } }, "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw=="], + + "array-includes": ["array-includes@3.1.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.0", "es-object-atoms": "^1.1.1", "get-intrinsic": "^1.3.0", "is-string": "^1.1.1", "math-intrinsics": "^1.1.0" } }, "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ=="], + + "array.prototype.findlast": ["array.prototype.findlast@1.2.5", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ=="], + + "array.prototype.flat": ["array.prototype.flat@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg=="], + + "array.prototype.flatmap": ["array.prototype.flatmap@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg=="], + + "array.prototype.tosorted": ["array.prototype.tosorted@1.1.4", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.3", "es-errors": "^1.3.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA=="], + + "arraybuffer.prototype.slice": ["arraybuffer.prototype.slice@1.0.4", "", { "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "is-array-buffer": "^3.0.4" } }, "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ=="], + + "async": ["async@1.5.2", "https://registry.npmmirror.com/async/-/async-1.5.2.tgz", {}, "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w=="], + + "async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="], + + "at-least-node": ["at-least-node@1.0.0", "https://registry.npmmirror.com/at-least-node/-/at-least-node-1.0.0.tgz", {}, "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg=="], + + "author-regex": ["author-regex@1.0.0", "https://registry.npmmirror.com/author-regex/-/author-regex-1.0.0.tgz", {}, "sha512-KbWgR8wOYRAPekEmMXrYYdc7BRyhn2Ftk7KWfMUnQ43hFdojWEFRxhhRUm3/OFEdPa1r0KAvTTg9YQK57xTe0g=="], + + "available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="], + + "balanced-match": ["balanced-match@1.0.2", "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], + + "base32-encode": ["base32-encode@1.2.0", "https://registry.npmmirror.com/base32-encode/-/base32-encode-1.2.0.tgz", { "dependencies": { "to-data-view": "^1.1.0" } }, "sha512-cHFU8XeRyx0GgmoWi5qHMCVRiqU6J3MHWxVgun7jggCBUpVzm1Ir7M9dYr2whjSNc3tFeXfQ/oZjQu/4u55h9A=="], + + "base64-js": ["base64-js@1.5.1", "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], + + "baseline-browser-mapping": ["baseline-browser-mapping@2.10.0", "https://registry.npmmirror.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", { "bin": "dist/cli.cjs" }, "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA=="], + + "bl": ["bl@4.1.0", "https://registry.npmmirror.com/bl/-/bl-4.1.0.tgz", { "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" } }, "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w=="], + + "bluebird": ["bluebird@3.7.2", "https://registry.npmmirror.com/bluebird/-/bluebird-3.7.2.tgz", {}, "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="], + + "boolean": ["boolean@3.2.0", "https://registry.npmmirror.com/boolean/-/boolean-3.2.0.tgz", {}, "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw=="], + + "bplist-creator": ["bplist-creator@0.0.8", "https://registry.npmmirror.com/bplist-creator/-/bplist-creator-0.0.8.tgz", { "dependencies": { "stream-buffers": "~2.2.0" } }, "sha512-Za9JKzD6fjLC16oX2wsXfc+qBEhJBJB1YPInoAQpMLhDuj5aVOv1baGeIQSq1Fr3OCqzvsoQcSBSwGId/Ja2PA=="], + + "brace-expansion": ["brace-expansion@1.1.12", "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.12.tgz", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], + + "braces": ["braces@3.0.3", "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], + + "browserslist": ["browserslist@4.28.1", "https://registry.npmmirror.com/browserslist/-/browserslist-4.28.1.tgz", { "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", "electron-to-chromium": "^1.5.263", "node-releases": "^2.0.27", "update-browserslist-db": "^1.2.0" }, "bin": "cli.js" }, "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA=="], + + "buffer": ["buffer@5.7.1", "https://registry.npmmirror.com/buffer/-/buffer-5.7.1.tgz", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ=="], + + "buffer-crc32": ["buffer-crc32@0.2.13", "https://registry.npmmirror.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz", {}, "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ=="], + + "buffer-from": ["buffer-from@1.1.2", "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], + + "bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="], + + "cacache": ["cacache@16.1.3", "https://registry.npmmirror.com/cacache/-/cacache-16.1.3.tgz", { "dependencies": { "@npmcli/fs": "^2.1.0", "@npmcli/move-file": "^2.0.0", "chownr": "^2.0.0", "fs-minipass": "^2.1.0", "glob": "^8.0.1", "infer-owner": "^1.0.4", "lru-cache": "^7.7.1", "minipass": "^3.1.6", "minipass-collect": "^1.0.2", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "mkdirp": "^1.0.4", "p-map": "^4.0.0", "promise-inflight": "^1.0.1", "rimraf": "^3.0.2", "ssri": "^9.0.0", "tar": "^6.1.11", "unique-filename": "^2.0.0" } }, "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ=="], + + "cacheable-lookup": ["cacheable-lookup@5.0.4", "https://registry.npmmirror.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", {}, "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA=="], + + "cacheable-request": ["cacheable-request@7.0.4", "https://registry.npmmirror.com/cacheable-request/-/cacheable-request-7.0.4.tgz", { "dependencies": { "clone-response": "^1.0.2", "get-stream": "^5.1.0", "http-cache-semantics": "^4.0.0", "keyv": "^4.0.0", "lowercase-keys": "^2.0.0", "normalize-url": "^6.0.1", "responselike": "^2.0.0" } }, "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg=="], + + "call-bind": ["call-bind@1.0.9", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "get-intrinsic": "^1.3.0", "set-function-length": "^1.2.2" } }, "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ=="], + + "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], + + "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="], + + "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], + + "camelcase": ["camelcase@5.3.1", "", {}, "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="], + + "caniuse-lite": ["caniuse-lite@1.0.30001776", "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001776.tgz", {}, "sha512-sg01JDPzZ9jGshqKSckOQthXnYwOEP50jeVFhaSFbZcOy05TiuuaffDOfcwtCisJ9kNQuLBFibYywv2Bgm9osw=="], + + "chalk": ["chalk@4.1.2", "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], + + "chardet": ["chardet@0.7.0", "https://registry.npmmirror.com/chardet/-/chardet-0.7.0.tgz", {}, "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA=="], + + "chokidar": ["chokidar@5.0.0", "https://registry.npmmirror.com/chokidar/-/chokidar-5.0.0.tgz", { "dependencies": { "readdirp": "^5.0.0" } }, "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw=="], + + "chownr": ["chownr@2.0.0", "https://registry.npmmirror.com/chownr/-/chownr-2.0.0.tgz", {}, "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="], + + "chrome-trace-event": ["chrome-trace-event@1.0.4", "https://registry.npmmirror.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", {}, "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ=="], + + "clean-stack": ["clean-stack@2.2.0", "https://registry.npmmirror.com/clean-stack/-/clean-stack-2.2.0.tgz", {}, "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A=="], + + "cli-cursor": ["cli-cursor@4.0.0", "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-4.0.0.tgz", { "dependencies": { "restore-cursor": "^4.0.0" } }, "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg=="], + + "cli-spinners": ["cli-spinners@2.9.2", "https://registry.npmmirror.com/cli-spinners/-/cli-spinners-2.9.2.tgz", {}, "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg=="], + + "cli-truncate": ["cli-truncate@3.1.0", "https://registry.npmmirror.com/cli-truncate/-/cli-truncate-3.1.0.tgz", { "dependencies": { "slice-ansi": "^5.0.0", "string-width": "^5.0.0" } }, "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA=="], + + "cli-width": ["cli-width@4.1.0", "https://registry.npmmirror.com/cli-width/-/cli-width-4.1.0.tgz", {}, "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ=="], + + "cliui": ["cliui@6.0.0", "", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^6.2.0" } }, "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ=="], + + "clone": ["clone@1.0.4", "https://registry.npmmirror.com/clone/-/clone-1.0.4.tgz", {}, "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg=="], + + "clone-response": ["clone-response@1.0.3", "https://registry.npmmirror.com/clone-response/-/clone-response-1.0.3.tgz", { "dependencies": { "mimic-response": "^1.0.0" } }, "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA=="], + + "color-convert": ["color-convert@2.0.1", "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", { "dependencies": { "color-name": "~1.1.4" } }, "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ=="], + + "color-name": ["color-name@1.1.4", "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], + + "colorette": ["colorette@2.0.20", "https://registry.npmmirror.com/colorette/-/colorette-2.0.20.tgz", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="], + + "commander": ["commander@11.1.0", "https://registry.npmmirror.com/commander/-/commander-11.1.0.tgz", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="], + + "compare-version": ["compare-version@0.1.2", "https://registry.npmmirror.com/compare-version/-/compare-version-0.1.2.tgz", {}, "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A=="], + + "concat-map": ["concat-map@0.0.1", "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], + + "convert-source-map": ["convert-source-map@2.0.0", "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], + + "cross-dirname": ["cross-dirname@0.1.0", "https://registry.npmmirror.com/cross-dirname/-/cross-dirname-0.1.0.tgz", {}, "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q=="], + + "cross-spawn": ["cross-spawn@7.0.6", "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], + + "cross-zip": ["cross-zip@4.0.1", "https://registry.npmmirror.com/cross-zip/-/cross-zip-4.0.1.tgz", {}, "sha512-n63i0lZ0rvQ6FXiGQ+/JFCKAUyPFhLQYJIqKaa+tSJtfKeULF/IDNDAbdnSIxgS4NTuw2b0+lj8LzfITuq+ZxQ=="], + + "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], + + "data-view-buffer": ["data-view-buffer@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ=="], + + "data-view-byte-length": ["data-view-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ=="], + + "data-view-byte-offset": ["data-view-byte-offset@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ=="], + + "debug": ["debug@4.4.3", "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz", { "dependencies": { "ms": "^2.1.3" } }, "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA=="], + + "decamelize": ["decamelize@1.2.0", "", {}, "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA=="], + + "decompress-response": ["decompress-response@6.0.0", "https://registry.npmmirror.com/decompress-response/-/decompress-response-6.0.0.tgz", { "dependencies": { "mimic-response": "^3.1.0" } }, "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ=="], + + "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], + + "defaults": ["defaults@1.0.4", "https://registry.npmmirror.com/defaults/-/defaults-1.0.4.tgz", { "dependencies": { "clone": "^1.0.2" } }, "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A=="], + + "defer-to-connect": ["defer-to-connect@2.0.1", "https://registry.npmmirror.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz", {}, "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg=="], + + "define-data-property": ["define-data-property@1.1.4", "https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.4.tgz", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="], + + "define-properties": ["define-properties@1.2.1", "https://registry.npmmirror.com/define-properties/-/define-properties-1.2.1.tgz", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="], + + "detect-libc": ["detect-libc@2.1.2", "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.1.2.tgz", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], + + "detect-node": ["detect-node@2.1.0", "https://registry.npmmirror.com/detect-node/-/detect-node-2.1.0.tgz", {}, "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g=="], + + "dijkstrajs": ["dijkstrajs@1.0.3", "", {}, "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA=="], + + "dir-compare": ["dir-compare@4.2.0", "https://registry.npmmirror.com/dir-compare/-/dir-compare-4.2.0.tgz", { "dependencies": { "minimatch": "^3.0.5", "p-limit": "^3.1.0 " } }, "sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ=="], + + "doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="], + + "ds-store": ["ds-store@0.1.6", "https://registry.npmmirror.com/ds-store/-/ds-store-0.1.6.tgz", { "dependencies": { "bplist-creator": "~0.0.3", "macos-alias": "~0.2.5", "tn1150": "^0.1.0" } }, "sha512-kY21M6Lz+76OS3bnCzjdsJSF7LBpLYGCVfavW8TgQD2XkcqIZ86W0y9qUDZu6fp7SIZzqosMDW2zi7zVFfv4hw=="], + + "dunder-proto": ["dunder-proto@1.0.1", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" } }, "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A=="], + + "eastasianwidth": ["eastasianwidth@0.2.0", "https://registry.npmmirror.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz", {}, "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA=="], + + "electron": ["electron@40.2.1", "https://registry.npmmirror.com/electron/-/electron-40.2.1.tgz", { "dependencies": { "@electron/get": "^2.0.0", "@types/node": "^24.9.0", "extract-zip": "^2.0.1" }, "bin": "cli.js" }, "sha512-0zOeyN8LB1KHIjVV5jyMmQmkqx3J8OkkVlab3p7vOM28jI46blxW7M52Tcdi6X2m5o2jj8ejOlAh5+boL3w8aQ=="], + + "electron-installer-common": ["electron-installer-common@0.10.4", "https://registry.npmmirror.com/electron-installer-common/-/electron-installer-common-0.10.4.tgz", { "dependencies": { "@electron/asar": "^3.2.5", "@malept/cross-spawn-promise": "^1.0.0", "debug": "^4.1.1", "fs-extra": "^9.0.0", "glob": "^7.1.4", "lodash": "^4.17.15", "parse-author": "^2.0.0", "semver": "^7.1.1", "tmp-promise": "^3.0.2" }, "optionalDependencies": { "@types/fs-extra": "^9.0.1" } }, "sha512-8gMNPXfAqUE5CfXg8RL0vXpLE9HAaPkgLXVoHE3BMUzogMWenf4LmwQ27BdCUrEhkjrKl+igs2IHJibclR3z3Q=="], + + "electron-installer-debian": ["electron-installer-debian@3.2.0", "https://registry.npmmirror.com/electron-installer-debian/-/electron-installer-debian-3.2.0.tgz", { "dependencies": { "@malept/cross-spawn-promise": "^1.0.0", "debug": "^4.1.1", "electron-installer-common": "^0.10.2", "fs-extra": "^9.0.0", "get-folder-size": "^2.0.1", "lodash": "^4.17.4", "word-wrap": "^1.2.3", "yargs": "^16.0.2" }, "os": [ "linux", "darwin", ], "bin": "src/cli.js" }, "sha512-58ZrlJ1HQY80VucsEIG9tQ//HrTlG6sfofA3nRGr6TmkX661uJyu4cMPPh6kXW+aHdq/7+q25KyQhDrXvRL7jw=="], + + "electron-installer-dmg": ["electron-installer-dmg@5.0.1", "https://registry.npmmirror.com/electron-installer-dmg/-/electron-installer-dmg-5.0.1.tgz", { "dependencies": { "@types/appdmg": "^0.5.5", "debug": "^4.3.2", "minimist": "^1.2.7" }, "optionalDependencies": { "appdmg": "^0.6.4" }, "bin": "dist/electron-installer-dmg-bin.js" }, "sha512-qOa1aAQdX57C+vzhDk3549dd/PRlNL4F8y736MTD1a43qptD+PvHY97Bo9gSf+OZ8iUWE7BrYSpk/FgLUe40EA=="], + + "electron-installer-redhat": ["electron-installer-redhat@3.4.0", "https://registry.npmmirror.com/electron-installer-redhat/-/electron-installer-redhat-3.4.0.tgz", { "dependencies": { "@malept/cross-spawn-promise": "^1.0.0", "debug": "^4.1.1", "electron-installer-common": "^0.10.2", "fs-extra": "^9.0.0", "lodash": "^4.17.15", "word-wrap": "^1.2.3", "yargs": "^16.0.2" }, "os": [ "linux", "darwin", ], "bin": "src/cli.js" }, "sha512-gEISr3U32Sgtj+fjxUAlSDo3wyGGq6OBx7rF5UdpIgbnpUvMN4W5uYb0ThpnAZ42VEJh/3aODQXHbFS4f5J3Iw=="], + + "electron-squirrel-startup": ["electron-squirrel-startup@1.0.1", "https://registry.npmmirror.com/electron-squirrel-startup/-/electron-squirrel-startup-1.0.1.tgz", { "dependencies": { "debug": "^2.2.0" } }, "sha512-sTfFIHGku+7PsHLJ7v0dRcZNkALrV+YEozINTW8X1nM//e5O3L+rfYuvSW00lmGHnYmUjARZulD8F2V8ISI9RA=="], + + "electron-to-chromium": ["electron-to-chromium@1.5.307", "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.307.tgz", {}, "sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg=="], + + "electron-winstaller": ["electron-winstaller@5.4.0", "https://registry.npmmirror.com/electron-winstaller/-/electron-winstaller-5.4.0.tgz", { "dependencies": { "@electron/asar": "^3.2.1", "debug": "^4.1.1", "fs-extra": "^7.0.1", "lodash": "^4.17.21", "temp": "^0.9.0" }, "optionalDependencies": { "@electron/windows-sign": "^1.1.2" } }, "sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg=="], + + "emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "encode-utf8": ["encode-utf8@1.0.3", "https://registry.npmmirror.com/encode-utf8/-/encode-utf8-1.0.3.tgz", {}, "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw=="], + + "encoding": ["encoding@0.1.13", "", { "dependencies": { "iconv-lite": "^0.6.2" } }, "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A=="], + + "end-of-stream": ["end-of-stream@1.4.5", "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.5.tgz", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="], + + "enhanced-resolve": ["enhanced-resolve@5.20.0", "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-5.20.0.tgz", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.3.0" } }, "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ=="], + + "env-paths": ["env-paths@2.2.1", "https://registry.npmmirror.com/env-paths/-/env-paths-2.2.1.tgz", {}, "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A=="], + + "err-code": ["err-code@2.0.3", "https://registry.npmmirror.com/err-code/-/err-code-2.0.3.tgz", {}, "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA=="], + + "error-ex": ["error-ex@1.3.4", "https://registry.npmmirror.com/error-ex/-/error-ex-1.3.4.tgz", { "dependencies": { "is-arrayish": "^0.2.1" } }, "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ=="], + + "es-abstract": ["es-abstract@1.24.2", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.3.0", "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.19" } }, "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg=="], + + "es-define-property": ["es-define-property@1.0.1", "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], + + "es-errors": ["es-errors@1.3.0", "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], + + "es-iterator-helpers": ["es-iterator-helpers@1.3.2", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.2", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.1.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.3.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "iterator.prototype": "^1.1.5", "math-intrinsics": "^1.1.0" } }, "sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw=="], + + "es-module-lexer": ["es-module-lexer@2.0.0", "https://registry.npmmirror.com/es-module-lexer/-/es-module-lexer-2.0.0.tgz", {}, "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw=="], + + "es-object-atoms": ["es-object-atoms@1.1.2", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw=="], + + "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], + + "es-shim-unscopables": ["es-shim-unscopables@1.1.0", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw=="], + + "es-to-primitive": ["es-to-primitive@1.3.0", "", { "dependencies": { "is-callable": "^1.2.7", "is-date-object": "^1.0.5", "is-symbol": "^1.0.4" } }, "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g=="], + + "es6-error": ["es6-error@4.1.1", "https://registry.npmmirror.com/es6-error/-/es6-error-4.1.1.tgz", {}, "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg=="], + + "esbuild": ["esbuild@0.27.3", "https://registry.npmmirror.com/esbuild/-/esbuild-0.27.3.tgz", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.3", "@esbuild/android-arm": "0.27.3", "@esbuild/android-arm64": "0.27.3", "@esbuild/android-x64": "0.27.3", "@esbuild/darwin-arm64": "0.27.3", "@esbuild/darwin-x64": "0.27.3", "@esbuild/freebsd-arm64": "0.27.3", "@esbuild/freebsd-x64": "0.27.3", "@esbuild/linux-arm": "0.27.3", "@esbuild/linux-arm64": "0.27.3", "@esbuild/linux-ia32": "0.27.3", "@esbuild/linux-loong64": "0.27.3", "@esbuild/linux-mips64el": "0.27.3", "@esbuild/linux-ppc64": "0.27.3", "@esbuild/linux-riscv64": "0.27.3", "@esbuild/linux-s390x": "0.27.3", "@esbuild/linux-x64": "0.27.3", "@esbuild/netbsd-arm64": "0.27.3", "@esbuild/netbsd-x64": "0.27.3", "@esbuild/openbsd-arm64": "0.27.3", "@esbuild/openbsd-x64": "0.27.3", "@esbuild/openharmony-arm64": "0.27.3", "@esbuild/sunos-x64": "0.27.3", "@esbuild/win32-arm64": "0.27.3", "@esbuild/win32-ia32": "0.27.3", "@esbuild/win32-x64": "0.27.3" }, "bin": "bin/esbuild" }, "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg=="], + + "escalade": ["escalade@3.2.0", "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], + + "escape-string-regexp": ["escape-string-regexp@4.0.0", "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], + + "eslint": ["eslint@9.39.4", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.2", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.5", "@eslint/js": "9.39.4", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.14.0", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.5", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "bin": "bin/eslint.js" }, "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ=="], + + "eslint-config-prettier": ["eslint-config-prettier@10.1.8", "", { "peerDependencies": { "eslint": ">=7.0.0" }, "bin": "bin/cli.js" }, "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w=="], + + "eslint-plugin-react": ["eslint-plugin-react@7.37.5", "", { "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.3", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.9", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA=="], + + "eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@7.1.1", "", { "dependencies": { "@babel/core": "^7.24.4", "@babel/parser": "^7.24.4", "hermes-parser": "^0.25.1", "zod": "^3.25.0 || ^4.0.0", "zod-validation-error": "^3.5.0 || ^4.0.0" }, "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" } }, "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g=="], + + "eslint-scope": ["eslint-scope@8.4.0", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg=="], + + "eslint-visitor-keys": ["eslint-visitor-keys@4.2.1", "", {}, "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ=="], + + "espree": ["espree@10.4.0", "", { "dependencies": { "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^4.2.1" } }, "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ=="], + + "esquery": ["esquery@1.7.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g=="], + + "esrecurse": ["esrecurse@4.3.0", "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="], + + "estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + + "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], + + "eventemitter3": ["eventemitter3@5.0.4", "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-5.0.4.tgz", {}, "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw=="], + + "events": ["events@3.3.0", "https://registry.npmmirror.com/events/-/events-3.3.0.tgz", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="], + + "execa": ["execa@1.0.0", "https://registry.npmmirror.com/execa/-/execa-1.0.0.tgz", { "dependencies": { "cross-spawn": "^6.0.0", "get-stream": "^4.0.0", "is-stream": "^1.1.0", "npm-run-path": "^2.0.0", "p-finally": "^1.0.0", "signal-exit": "^3.0.0", "strip-eof": "^1.0.0" } }, "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA=="], + + "exponential-backoff": ["exponential-backoff@3.1.3", "https://registry.npmmirror.com/exponential-backoff/-/exponential-backoff-3.1.3.tgz", {}, "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA=="], + + "external-editor": ["external-editor@3.1.0", "https://registry.npmmirror.com/external-editor/-/external-editor-3.1.0.tgz", { "dependencies": { "chardet": "^0.7.0", "iconv-lite": "^0.4.24", "tmp": "^0.0.33" } }, "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew=="], + + "extract-zip": ["extract-zip@2.0.1", "https://registry.npmmirror.com/extract-zip/-/extract-zip-2.0.1.tgz", { "dependencies": { "debug": "^4.1.1", "get-stream": "^5.1.0", "yauzl": "^2.10.0" }, "optionalDependencies": { "@types/yauzl": "^2.9.1" }, "bin": "cli.js" }, "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg=="], + + "fast-deep-equal": ["fast-deep-equal@3.1.3", "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], + + "fast-glob": ["fast-glob@3.3.3", "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.3.tgz", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], + + "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], + + "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], + + "fast-uri": ["fast-uri@3.1.0", "https://registry.npmmirror.com/fast-uri/-/fast-uri-3.1.0.tgz", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="], + + "fastq": ["fastq@1.20.1", "https://registry.npmmirror.com/fastq/-/fastq-1.20.1.tgz", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw=="], + + "fd-slicer": ["fd-slicer@1.1.0", "https://registry.npmmirror.com/fd-slicer/-/fd-slicer-1.1.0.tgz", { "dependencies": { "pend": "~1.2.0" } }, "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g=="], + + "fdir": ["fdir@6.5.0", "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", { "peerDependencies": { "picomatch": "^3 || ^4" } }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], + + "file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="], + + "filename-reserved-regex": ["filename-reserved-regex@2.0.0", "https://registry.npmmirror.com/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", {}, "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ=="], + + "filenamify": ["filenamify@4.3.0", "https://registry.npmmirror.com/filenamify/-/filenamify-4.3.0.tgz", { "dependencies": { "filename-reserved-regex": "^2.0.0", "strip-outer": "^1.0.1", "trim-repeated": "^1.0.0" } }, "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg=="], + + "fill-range": ["fill-range@7.1.1", "https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], + + "find-up": ["find-up@5.0.0", "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="], + + "flat-cache": ["flat-cache@4.0.1", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.4" } }, "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw=="], + + "flatted": ["flatted@3.4.2", "", {}, "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA=="], + + "flora-colossus": ["flora-colossus@2.0.0", "https://registry.npmmirror.com/flora-colossus/-/flora-colossus-2.0.0.tgz", { "dependencies": { "debug": "^4.3.4", "fs-extra": "^10.1.0" } }, "sha512-dz4HxH6pOvbUzZpZ/yXhafjbR2I8cenK5xL0KtBFb7U2ADsR+OwXifnxZjij/pZWF775uSCMzWVd+jDik2H2IA=="], + + "fmix": ["fmix@0.1.0", "https://registry.npmmirror.com/fmix/-/fmix-0.1.0.tgz", { "dependencies": { "imul": "^1.0.0" } }, "sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w=="], + + "for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="], + + "fs-extra": ["fs-extra@10.1.0", "https://registry.npmmirror.com/fs-extra/-/fs-extra-10.1.0.tgz", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ=="], + + "fs-minipass": ["fs-minipass@2.1.0", "https://registry.npmmirror.com/fs-minipass/-/fs-minipass-2.1.0.tgz", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg=="], + + "fs-temp": ["fs-temp@1.2.1", "https://registry.npmmirror.com/fs-temp/-/fs-temp-1.2.1.tgz", { "dependencies": { "random-path": "^0.1.0" } }, "sha512-okTwLB7/Qsq82G6iN5zZJFsOfZtx2/pqrA7Hk/9fvy+c+eJS9CvgGXT2uNxwnI14BDY9L/jQPkaBgSvlKfSW9w=="], + + "fs-xattr": ["fs-xattr@0.3.1", "https://registry.npmmirror.com/fs-xattr/-/fs-xattr-0.3.1.tgz", { "os": "!win32" }, "sha512-UVqkrEW0GfDabw4C3HOrFlxKfx0eeigfRne69FxSBdHIP8Qt5Sq6Pu3RM9KmMlkygtC4pPKkj5CiPO5USnj2GA=="], + + "fs.realpath": ["fs.realpath@1.0.0", "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], + + "fsevents": ["fsevents@2.3.3", "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], + + "function-bind": ["function-bind@1.1.2", "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], + + "function.prototype.name": ["function.prototype.name@1.1.8", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "functions-have-names": "^1.2.3", "hasown": "^2.0.2", "is-callable": "^1.2.7" } }, "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q=="], + + "functions-have-names": ["functions-have-names@1.2.3", "", {}, "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="], + + "galactus": ["galactus@1.0.0", "https://registry.npmmirror.com/galactus/-/galactus-1.0.0.tgz", { "dependencies": { "debug": "^4.3.4", "flora-colossus": "^2.0.0", "fs-extra": "^10.1.0" } }, "sha512-R1fam6D4CyKQGNlvJne4dkNF+PvUUl7TAJInvTGa9fti9qAv95quQz29GXapA4d8Ec266mJJxFVh82M4GIIGDQ=="], + + "gar": ["gar@1.0.4", "https://registry.npmmirror.com/gar/-/gar-1.0.4.tgz", {}, "sha512-w4n9cPWyP7aHxKxYHFQMegj7WIAsL/YX/C4Bs5Rr8s1H9M1rNtRWRsw+ovYMkXDQ5S4ZbYHsHAPmevPjPgw44w=="], + + "generate-function": ["generate-function@2.3.1", "https://registry.npmmirror.com/generate-function/-/generate-function-2.3.1.tgz", { "dependencies": { "is-property": "^1.0.2" } }, "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ=="], + + "generate-object-property": ["generate-object-property@1.2.0", "https://registry.npmmirror.com/generate-object-property/-/generate-object-property-1.2.0.tgz", { "dependencies": { "is-property": "^1.0.0" } }, "sha512-TuOwZWgJ2VAMEGJvAyPWvpqxSANF0LDpmyHauMjFYzaACvn+QTT/AZomvPCzVBV7yDN3OmwHQ5OvHaeLKre3JQ=="], + + "generator-function": ["generator-function@2.0.1", "", {}, "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g=="], + + "gensync": ["gensync@1.0.0-beta.2", "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="], + + "get-caller-file": ["get-caller-file@2.0.5", "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], + + "get-folder-size": ["get-folder-size@2.0.1", "https://registry.npmmirror.com/get-folder-size/-/get-folder-size-2.0.1.tgz", { "dependencies": { "gar": "^1.0.4", "tiny-each-async": "2.0.3" }, "bin": "bin/get-folder-size" }, "sha512-+CEb+GDCM7tkOS2wdMKTn9vU7DgnKUTuDlehkNJKNSovdCOVxs14OfKCk4cvSaR3za4gj+OBdl9opPN9xrJ0zA=="], + + "get-intrinsic": ["get-intrinsic@1.3.0", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "math-intrinsics": "^1.1.0" } }, "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ=="], + + "get-package-info": ["get-package-info@1.0.0", "https://registry.npmmirror.com/get-package-info/-/get-package-info-1.0.0.tgz", { "dependencies": { "bluebird": "^3.1.1", "debug": "^2.2.0", "lodash.get": "^4.0.0", "read-pkg-up": "^2.0.0" } }, "sha512-SCbprXGAPdIhKAXiG+Mk6yeoFH61JlYunqdFQFHDtLjJlDjFf6x07dsS8acO+xWt52jpdVo49AlVDnUVK1sDNw=="], + + "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], + + "get-stream": ["get-stream@5.2.0", "https://registry.npmmirror.com/get-stream/-/get-stream-5.2.0.tgz", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="], + + "get-symbol-description": ["get-symbol-description@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6" } }, "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg=="], + + "glob": ["glob@7.2.3", "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], + + "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], + + "glob-to-regexp": ["glob-to-regexp@0.4.1", "https://registry.npmmirror.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", {}, "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="], + + "global-agent": ["global-agent@3.0.0", "https://registry.npmmirror.com/global-agent/-/global-agent-3.0.0.tgz", { "dependencies": { "boolean": "^3.0.1", "es6-error": "^4.1.1", "matcher": "^3.0.0", "roarr": "^2.15.3", "semver": "^7.3.2", "serialize-error": "^7.0.1" } }, "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q=="], + + "global-dirs": ["global-dirs@3.0.1", "https://registry.npmmirror.com/global-dirs/-/global-dirs-3.0.1.tgz", { "dependencies": { "ini": "2.0.0" } }, "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA=="], + + "globals": ["globals@17.6.0", "", {}, "sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA=="], + + "globalthis": ["globalthis@1.0.4", "https://registry.npmmirror.com/globalthis/-/globalthis-1.0.4.tgz", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="], + + "gopd": ["gopd@1.2.0", "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], + + "got": ["got@11.8.6", "https://registry.npmmirror.com/got/-/got-11.8.6.tgz", { "dependencies": { "@sindresorhus/is": "^4.0.0", "@szmarczak/http-timer": "^4.0.5", "@types/cacheable-request": "^6.0.1", "@types/responselike": "^1.0.0", "cacheable-lookup": "^5.0.3", "cacheable-request": "^7.0.2", "decompress-response": "^6.0.0", "http2-wrapper": "^1.0.0-beta.5.2", "lowercase-keys": "^2.0.0", "p-cancelable": "^2.0.0", "responselike": "^2.0.0" } }, "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g=="], + + "graceful-fs": ["graceful-fs@4.2.11", "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], + + "has-bigints": ["has-bigints@1.1.0", "", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="], + + "has-flag": ["has-flag@4.0.0", "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], + + "has-property-descriptors": ["has-property-descriptors@1.0.2", "https://registry.npmmirror.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="], + + "has-proto": ["has-proto@1.2.0", "", { "dependencies": { "dunder-proto": "^1.0.0" } }, "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ=="], + + "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], + + "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], + + "hasown": ["hasown@2.0.4", "", { "dependencies": { "function-bind": "^1.1.2" } }, "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A=="], + + "hermes-estree": ["hermes-estree@0.25.1", "", {}, "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw=="], + + "hermes-parser": ["hermes-parser@0.25.1", "", { "dependencies": { "hermes-estree": "0.25.1" } }, "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA=="], + + "hosted-git-info": ["hosted-git-info@2.8.9", "https://registry.npmmirror.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz", {}, "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw=="], + + "http-cache-semantics": ["http-cache-semantics@4.2.0", "https://registry.npmmirror.com/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", {}, "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ=="], + + "http-proxy-agent": ["http-proxy-agent@5.0.0", "https://registry.npmmirror.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", { "dependencies": { "@tootallnate/once": "2", "agent-base": "6", "debug": "4" } }, "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w=="], + + "http2-wrapper": ["http2-wrapper@1.0.3", "https://registry.npmmirror.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz", { "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.0.0" } }, "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg=="], + + "https-proxy-agent": ["https-proxy-agent@5.0.1", "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", { "dependencies": { "agent-base": "6", "debug": "4" } }, "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA=="], + + "humanize-ms": ["humanize-ms@1.2.1", "https://registry.npmmirror.com/humanize-ms/-/humanize-ms-1.2.1.tgz", { "dependencies": { "ms": "^2.0.0" } }, "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ=="], + + "iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="], + + "ieee754": ["ieee754@1.2.1", "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], + + "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], + + "image-size": ["image-size@0.7.5", "https://registry.npmmirror.com/image-size/-/image-size-0.7.5.tgz", { "bin": "bin/image-size.js" }, "sha512-Hiyv+mXHfFEP7LzUL/llg9RwFxxY+o9N3JVLIeG5E7iFIFAalxvRU9UZthBdYDEVnzHMgjnKJPPpay5BWf1g9g=="], + + "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], + + "imul": ["imul@1.0.1", "https://registry.npmmirror.com/imul/-/imul-1.0.1.tgz", {}, "sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA=="], + + "imurmurhash": ["imurmurhash@0.1.4", "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], + + "indent-string": ["indent-string@4.0.0", "https://registry.npmmirror.com/indent-string/-/indent-string-4.0.0.tgz", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="], + + "infer-owner": ["infer-owner@1.0.4", "https://registry.npmmirror.com/infer-owner/-/infer-owner-1.0.4.tgz", {}, "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A=="], + + "inflight": ["inflight@1.0.6", "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="], + + "inherits": ["inherits@2.0.4", "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz", {}, "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="], + + "ini": ["ini@2.0.0", "https://registry.npmmirror.com/ini/-/ini-2.0.0.tgz", {}, "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA=="], + + "internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="], + + "interpret": ["interpret@3.1.1", "https://registry.npmmirror.com/interpret/-/interpret-3.1.1.tgz", {}, "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ=="], + + "ip-address": ["ip-address@10.1.0", "https://registry.npmmirror.com/ip-address/-/ip-address-10.1.0.tgz", {}, "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q=="], + + "is-array-buffer": ["is-array-buffer@3.0.5", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A=="], + + "is-arrayish": ["is-arrayish@0.2.1", "https://registry.npmmirror.com/is-arrayish/-/is-arrayish-0.2.1.tgz", {}, "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="], + + "is-async-function": ["is-async-function@2.1.1", "", { "dependencies": { "async-function": "^1.0.0", "call-bound": "^1.0.3", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ=="], + + "is-bigint": ["is-bigint@1.1.0", "", { "dependencies": { "has-bigints": "^1.0.2" } }, "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ=="], + + "is-boolean-object": ["is-boolean-object@1.2.2", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A=="], + + "is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="], + + "is-core-module": ["is-core-module@2.16.2", "", { "dependencies": { "hasown": "^2.0.3" } }, "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA=="], + + "is-data-view": ["is-data-view@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" } }, "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw=="], + + "is-date-object": ["is-date-object@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg=="], + + "is-extglob": ["is-extglob@2.1.1", "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], + + "is-finalizationregistry": ["is-finalizationregistry@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg=="], + + "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + + "is-generator-function": ["is-generator-function@1.1.2", "", { "dependencies": { "call-bound": "^1.0.4", "generator-function": "^2.0.0", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA=="], + + "is-glob": ["is-glob@4.0.3", "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], + + "is-interactive": ["is-interactive@1.0.0", "https://registry.npmmirror.com/is-interactive/-/is-interactive-1.0.0.tgz", {}, "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w=="], + + "is-lambda": ["is-lambda@1.0.1", "https://registry.npmmirror.com/is-lambda/-/is-lambda-1.0.1.tgz", {}, "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ=="], + + "is-map": ["is-map@2.0.3", "", {}, "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw=="], + + "is-my-ip-valid": ["is-my-ip-valid@1.0.1", "https://registry.npmmirror.com/is-my-ip-valid/-/is-my-ip-valid-1.0.1.tgz", {}, "sha512-jxc8cBcOWbNK2i2aTkCZP6i7wkHF1bqKFrwEHuN5Jtg5BSaZHUZQ/JTOJwoV41YvHnOaRyWWh72T/KvfNz9DJg=="], + + "is-my-json-valid": ["is-my-json-valid@2.20.6", "https://registry.npmmirror.com/is-my-json-valid/-/is-my-json-valid-2.20.6.tgz", { "dependencies": { "generate-function": "^2.0.0", "generate-object-property": "^1.1.0", "is-my-ip-valid": "^1.0.0", "jsonpointer": "^5.0.0", "xtend": "^4.0.0" } }, "sha512-1JQwulVNjx8UqkPE/bqDaxtH4PXCe/2VRh/y3p99heOV87HG4Id5/VfDswd+YiAfHcRTfDlWgISycnHuhZq1aw=="], + + "is-negative-zero": ["is-negative-zero@2.0.3", "", {}, "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw=="], + + "is-number": ["is-number@7.0.0", "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], + + "is-number-object": ["is-number-object@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw=="], + + "is-property": ["is-property@1.0.2", "https://registry.npmmirror.com/is-property/-/is-property-1.0.2.tgz", {}, "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g=="], + + "is-regex": ["is-regex@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g=="], + + "is-set": ["is-set@2.0.3", "", {}, "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg=="], + + "is-shared-array-buffer": ["is-shared-array-buffer@1.0.4", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A=="], + + "is-stream": ["is-stream@1.1.0", "https://registry.npmmirror.com/is-stream/-/is-stream-1.1.0.tgz", {}, "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ=="], + + "is-string": ["is-string@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA=="], + + "is-symbol": ["is-symbol@1.1.1", "", { "dependencies": { "call-bound": "^1.0.2", "has-symbols": "^1.1.0", "safe-regex-test": "^1.1.0" } }, "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w=="], + + "is-typed-array": ["is-typed-array@1.1.15", "", { "dependencies": { "which-typed-array": "^1.1.16" } }, "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ=="], + + "is-unicode-supported": ["is-unicode-supported@0.1.0", "https://registry.npmmirror.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", {}, "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw=="], + + "is-weakmap": ["is-weakmap@2.0.2", "", {}, "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w=="], + + "is-weakref": ["is-weakref@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew=="], + + "is-weakset": ["is-weakset@2.0.4", "", { "dependencies": { "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ=="], + + "isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], + + "isbinaryfile": ["isbinaryfile@4.0.10", "https://registry.npmmirror.com/isbinaryfile/-/isbinaryfile-4.0.10.tgz", {}, "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw=="], + + "isexe": ["isexe@2.0.0", "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], + + "iterator.prototype": ["iterator.prototype@1.1.5", "", { "dependencies": { "define-data-property": "^1.1.4", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "get-proto": "^1.0.0", "has-symbols": "^1.1.0", "set-function-name": "^2.0.2" } }, "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g=="], + + "jest-worker": ["jest-worker@27.5.1", "https://registry.npmmirror.com/jest-worker/-/jest-worker-27.5.1.tgz", { "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" } }, "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg=="], + + "jiti": ["jiti@2.6.1", "https://registry.npmmirror.com/jiti/-/jiti-2.6.1.tgz", { "bin": "lib/jiti-cli.mjs" }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], + + "js-tokens": ["js-tokens@4.0.0", "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], + + "js-yaml": ["js-yaml@4.2.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": "bin/js-yaml.js" }, "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw=="], + + "jsesc": ["jsesc@3.1.0", "https://registry.npmmirror.com/jsesc/-/jsesc-3.1.0.tgz", { "bin": "bin/jsesc" }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], + + "json-buffer": ["json-buffer@3.0.1", "https://registry.npmmirror.com/json-buffer/-/json-buffer-3.0.1.tgz", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="], + + "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "https://registry.npmmirror.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="], + + "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + + "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="], + + "json-stringify-safe": ["json-stringify-safe@5.0.1", "https://registry.npmmirror.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", {}, "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="], + + "json5": ["json5@2.2.3", "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz", { "bin": "lib/cli.js" }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], + + "jsonfile": ["jsonfile@6.2.0", "https://registry.npmmirror.com/jsonfile/-/jsonfile-6.2.0.tgz", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg=="], + + "jsonpointer": ["jsonpointer@5.0.1", "https://registry.npmmirror.com/jsonpointer/-/jsonpointer-5.0.1.tgz", {}, "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ=="], + + "jsx-ast-utils": ["jsx-ast-utils@3.3.5", "", { "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", "object.assign": "^4.1.4", "object.values": "^1.1.6" } }, "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ=="], + + "junk": ["junk@3.1.0", "https://registry.npmmirror.com/junk/-/junk-3.1.0.tgz", {}, "sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ=="], + + "keyv": ["keyv@4.5.4", "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], + + "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], + + "listr2": ["listr2@7.0.2", "https://registry.npmmirror.com/listr2/-/listr2-7.0.2.tgz", { "dependencies": { "cli-truncate": "^3.1.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", "log-update": "^5.0.1", "rfdc": "^1.3.0", "wrap-ansi": "^8.1.0" } }, "sha512-rJysbR9GKIalhTbVL2tYbF2hVyDnrf7pFUZBwjPaMIdadYHmeT+EVi/Bu3qd7ETQPahTotg2WRCatXwRBW554g=="], + + "load-json-file": ["load-json-file@2.0.0", "https://registry.npmmirror.com/load-json-file/-/load-json-file-2.0.0.tgz", { "dependencies": { "graceful-fs": "^4.1.2", "parse-json": "^2.2.0", "pify": "^2.0.0", "strip-bom": "^3.0.0" } }, "sha512-3p6ZOGNbiX4CdvEd1VcE6yi78UrGNpjHO33noGwHCnT/o2fyllJDepsm8+mFFv/DvtwFHht5HIHSyOy5a+ChVQ=="], + + "loader-runner": ["loader-runner@4.3.1", "https://registry.npmmirror.com/loader-runner/-/loader-runner-4.3.1.tgz", {}, "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q=="], + + "locate-path": ["locate-path@6.0.0", "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], + + "lodash": ["lodash@4.17.23", "https://registry.npmmirror.com/lodash/-/lodash-4.17.23.tgz", {}, "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w=="], + + "lodash.get": ["lodash.get@4.4.2", "https://registry.npmmirror.com/lodash.get/-/lodash.get-4.4.2.tgz", {}, "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ=="], + + "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], + + "log-symbols": ["log-symbols@4.1.0", "https://registry.npmmirror.com/log-symbols/-/log-symbols-4.1.0.tgz", { "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" } }, "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg=="], + + "log-update": ["log-update@5.0.1", "https://registry.npmmirror.com/log-update/-/log-update-5.0.1.tgz", { "dependencies": { "ansi-escapes": "^5.0.0", "cli-cursor": "^4.0.0", "slice-ansi": "^5.0.0", "strip-ansi": "^7.0.1", "wrap-ansi": "^8.0.1" } }, "sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw=="], + + "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": "cli.js" }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="], + + "lowercase-keys": ["lowercase-keys@2.0.0", "https://registry.npmmirror.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz", {}, "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA=="], + + "lru-cache": ["lru-cache@5.1.1", "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], + + "macos-alias": ["macos-alias@0.2.12", "https://registry.npmmirror.com/macos-alias/-/macos-alias-0.2.12.tgz", { "dependencies": { "nan": "^2.4.0" }, "os": "darwin" }, "sha512-yiLHa7cfJcGRFq4FrR4tMlpNHb4Vy4mWnpajlSSIFM5k4Lv8/7BbbDLzCAVogWNl0LlLhizRp1drXv0hK9h0Yw=="], + + "make-fetch-happen": ["make-fetch-happen@10.2.1", "https://registry.npmmirror.com/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", { "dependencies": { "agentkeepalive": "^4.2.1", "cacache": "^16.1.0", "http-cache-semantics": "^4.1.0", "http-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0", "is-lambda": "^1.0.1", "lru-cache": "^7.7.1", "minipass": "^3.1.6", "minipass-collect": "^1.0.2", "minipass-fetch": "^2.0.3", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.4", "negotiator": "^0.6.3", "promise-retry": "^2.0.1", "socks-proxy-agent": "^7.0.0", "ssri": "^9.0.0" } }, "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w=="], + + "map-age-cleaner": ["map-age-cleaner@0.1.3", "https://registry.npmmirror.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", { "dependencies": { "p-defer": "^1.0.0" } }, "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w=="], + + "matcher": ["matcher@3.0.0", "https://registry.npmmirror.com/matcher/-/matcher-3.0.0.tgz", { "dependencies": { "escape-string-regexp": "^4.0.0" } }, "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng=="], + + "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], + + "mem": ["mem@4.3.0", "https://registry.npmmirror.com/mem/-/mem-4.3.0.tgz", { "dependencies": { "map-age-cleaner": "^0.1.1", "mimic-fn": "^2.0.0", "p-is-promise": "^2.0.0" } }, "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w=="], + + "merge-stream": ["merge-stream@2.0.0", "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz", {}, "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="], + + "merge2": ["merge2@1.4.1", "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], + + "micromatch": ["micromatch@4.0.8", "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.8.tgz", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], + + "mime-db": ["mime-db@1.52.0", "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], + + "mime-types": ["mime-types@2.1.35", "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], + + "mimic-fn": ["mimic-fn@2.1.0", "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz", {}, "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="], + + "mimic-response": ["mimic-response@3.1.0", "https://registry.npmmirror.com/mimic-response/-/mimic-response-3.1.0.tgz", {}, "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ=="], + + "minimatch": ["minimatch@3.1.5", "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.5.tgz", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w=="], + + "minimist": ["minimist@1.2.8", "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="], + + "minipass": ["minipass@5.0.0", "https://registry.npmmirror.com/minipass/-/minipass-5.0.0.tgz", {}, "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ=="], + + "minipass-collect": ["minipass-collect@1.0.2", "https://registry.npmmirror.com/minipass-collect/-/minipass-collect-1.0.2.tgz", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA=="], + + "minipass-fetch": ["minipass-fetch@2.1.2", "https://registry.npmmirror.com/minipass-fetch/-/minipass-fetch-2.1.2.tgz", { "dependencies": { "minipass": "^3.1.6", "minipass-sized": "^1.0.3", "minizlib": "^2.1.2" }, "optionalDependencies": { "encoding": "^0.1.13" } }, "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA=="], + + "minipass-flush": ["minipass-flush@1.0.5", "https://registry.npmmirror.com/minipass-flush/-/minipass-flush-1.0.5.tgz", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw=="], + + "minipass-pipeline": ["minipass-pipeline@1.2.4", "https://registry.npmmirror.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A=="], + + "minipass-sized": ["minipass-sized@1.0.3", "https://registry.npmmirror.com/minipass-sized/-/minipass-sized-1.0.3.tgz", { "dependencies": { "minipass": "^3.0.0" } }, "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g=="], + + "minizlib": ["minizlib@2.1.2", "https://registry.npmmirror.com/minizlib/-/minizlib-2.1.2.tgz", { "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" } }, "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg=="], + + "mkdirp": ["mkdirp@0.5.6", "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz", { "dependencies": { "minimist": "^1.2.6" }, "bin": "bin/cmd.js" }, "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw=="], + + "ms": ["ms@2.1.3", "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", {}, "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="], + + "murmur-32": ["murmur-32@0.2.0", "https://registry.npmmirror.com/murmur-32/-/murmur-32-0.2.0.tgz", { "dependencies": { "encode-utf8": "^1.0.3", "fmix": "^0.1.0", "imul": "^1.0.0" } }, "sha512-ZkcWZudylwF+ir3Ld1n7gL6bI2mQAzXvSobPwVtu8aYi2sbXeipeSkdcanRLzIofLcM5F53lGaKm2dk7orBi7Q=="], + + "mute-stream": ["mute-stream@1.0.0", "https://registry.npmmirror.com/mute-stream/-/mute-stream-1.0.0.tgz", {}, "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA=="], + + "nan": ["nan@2.25.0", "https://registry.npmmirror.com/nan/-/nan-2.25.0.tgz", {}, "sha512-0M90Ag7Xn5KMLLZ7zliPWP3rT90P6PN+IzVFS0VqmnPktBk3700xUVv8Ikm9EUaUE5SDWdp/BIxdENzVznpm1g=="], + + "nanoid": ["nanoid@3.3.11", "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz", { "bin": "bin/nanoid.cjs" }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], + + "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], + + "negotiator": ["negotiator@0.6.4", "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.4.tgz", {}, "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w=="], + + "neo-async": ["neo-async@2.6.2", "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz", {}, "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="], + + "nice-try": ["nice-try@1.0.5", "https://registry.npmmirror.com/nice-try/-/nice-try-1.0.5.tgz", {}, "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="], + + "node-abi": ["node-abi@3.87.0", "https://registry.npmmirror.com/node-abi/-/node-abi-3.87.0.tgz", { "dependencies": { "semver": "^7.3.5" } }, "sha512-+CGM1L1CgmtheLcBuleyYOn7NWPVu0s0EJH2C4puxgEZb9h8QpR9G2dBfZJOAUhi7VQxuBPMd0hiISWcTyiYyQ=="], + + "node-api-version": ["node-api-version@0.2.1", "https://registry.npmmirror.com/node-api-version/-/node-api-version-0.2.1.tgz", { "dependencies": { "semver": "^7.3.5" } }, "sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q=="], + + "node-exports-info": ["node-exports-info@1.6.0", "", { "dependencies": { "array.prototype.flatmap": "^1.3.3", "es-errors": "^1.3.0", "object.entries": "^1.1.9", "semver": "^6.3.1" } }, "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw=="], + + "node-fetch": ["node-fetch@2.7.0", "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.7.0.tgz", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" } }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], + + "node-releases": ["node-releases@2.0.36", "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.36.tgz", {}, "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA=="], + + "nopt": ["nopt@6.0.0", "https://registry.npmmirror.com/nopt/-/nopt-6.0.0.tgz", { "dependencies": { "abbrev": "^1.0.0" }, "bin": "bin/nopt.js" }, "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g=="], + + "normalize-package-data": ["normalize-package-data@2.5.0", "https://registry.npmmirror.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz", { "dependencies": { "hosted-git-info": "^2.1.4", "resolve": "^1.10.0", "semver": "2 || 3 || 4 || 5", "validate-npm-package-license": "^3.0.1" } }, "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA=="], + + "normalize-url": ["normalize-url@6.1.0", "https://registry.npmmirror.com/normalize-url/-/normalize-url-6.1.0.tgz", {}, "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A=="], + + "npm-run-path": ["npm-run-path@2.0.2", "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-2.0.2.tgz", { "dependencies": { "path-key": "^2.0.0" } }, "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw=="], + + "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], + + "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="], + + "object-keys": ["object-keys@1.1.1", "https://registry.npmmirror.com/object-keys/-/object-keys-1.1.1.tgz", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="], + + "object.assign": ["object.assign@4.1.7", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0", "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw=="], + + "object.entries": ["object.entries@1.1.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-object-atoms": "^1.1.1" } }, "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw=="], + + "object.fromentries": ["object.fromentries@2.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-object-atoms": "^1.0.0" } }, "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ=="], + + "object.values": ["object.values@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA=="], + + "once": ["once@1.4.0", "https://registry.npmmirror.com/once/-/once-1.4.0.tgz", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], + + "onetime": ["onetime@5.1.2", "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz", { "dependencies": { "mimic-fn": "^2.1.0" } }, "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg=="], + + "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], + + "ora": ["ora@5.4.1", "https://registry.npmmirror.com/ora/-/ora-5.4.1.tgz", { "dependencies": { "bl": "^4.1.0", "chalk": "^4.1.0", "cli-cursor": "^3.1.0", "cli-spinners": "^2.5.0", "is-interactive": "^1.0.0", "is-unicode-supported": "^0.1.0", "log-symbols": "^4.1.0", "strip-ansi": "^6.0.0", "wcwidth": "^1.0.1" } }, "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ=="], + + "os-tmpdir": ["os-tmpdir@1.0.2", "https://registry.npmmirror.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz", {}, "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g=="], + + "own-keys": ["own-keys@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg=="], + + "p-cancelable": ["p-cancelable@2.1.1", "https://registry.npmmirror.com/p-cancelable/-/p-cancelable-2.1.1.tgz", {}, "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg=="], + + "p-defer": ["p-defer@1.0.0", "https://registry.npmmirror.com/p-defer/-/p-defer-1.0.0.tgz", {}, "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw=="], + + "p-finally": ["p-finally@1.0.0", "https://registry.npmmirror.com/p-finally/-/p-finally-1.0.0.tgz", {}, "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow=="], + + "p-is-promise": ["p-is-promise@2.1.0", "https://registry.npmmirror.com/p-is-promise/-/p-is-promise-2.1.0.tgz", {}, "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg=="], + + "p-limit": ["p-limit@3.1.0", "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], + + "p-locate": ["p-locate@5.0.0", "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="], + + "p-map": ["p-map@4.0.0", "https://registry.npmmirror.com/p-map/-/p-map-4.0.0.tgz", { "dependencies": { "aggregate-error": "^3.0.0" } }, "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ=="], + + "p-try": ["p-try@2.2.0", "", {}, "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="], + + "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], + + "parse-author": ["parse-author@2.0.0", "https://registry.npmmirror.com/parse-author/-/parse-author-2.0.0.tgz", { "dependencies": { "author-regex": "^1.0.0" } }, "sha512-yx5DfvkN8JsHL2xk2Os9oTia467qnvRgey4ahSm2X8epehBLx/gWLcy5KI+Y36ful5DzGbCS6RazqZGgy1gHNw=="], + + "parse-color": ["parse-color@1.0.0", "https://registry.npmmirror.com/parse-color/-/parse-color-1.0.0.tgz", { "dependencies": { "color-convert": "~0.5.0" } }, "sha512-fuDHYgFHJGbpGMgw9skY/bj3HL/Jrn4l/5rSspy00DoT4RyLnDcRvPxdZ+r6OFwIsgAuhDh4I09tAId4mI12bw=="], + + "parse-json": ["parse-json@2.2.0", "https://registry.npmmirror.com/parse-json/-/parse-json-2.2.0.tgz", { "dependencies": { "error-ex": "^1.2.0" } }, "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ=="], + + "path-exists": ["path-exists@4.0.0", "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="], + + "path-is-absolute": ["path-is-absolute@1.0.1", "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="], + + "path-key": ["path-key@3.1.1", "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], + + "path-parse": ["path-parse@1.0.7", "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz", {}, "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="], + + "path-type": ["path-type@2.0.0", "https://registry.npmmirror.com/path-type/-/path-type-2.0.0.tgz", { "dependencies": { "pify": "^2.0.0" } }, "sha512-dUnb5dXUf+kzhC/W/F4e5/SkluXIFf5VUHolW1Eg1irn1hGWjPGdsRcvYJ1nD6lhk8Ir7VM0bHJKsYTx8Jx9OQ=="], + + "pe-library": ["pe-library@1.0.1", "https://registry.npmmirror.com/pe-library/-/pe-library-1.0.1.tgz", {}, "sha512-nh39Mo1eGWmZS7y+mK/dQIqg7S1lp38DpRxkyoHf0ZcUs/HDc+yyTjuOtTvSMZHmfSLuSQaX945u05Y2Q6UWZg=="], + + "pend": ["pend@1.2.0", "https://registry.npmmirror.com/pend/-/pend-1.2.0.tgz", {}, "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="], + + "picocolors": ["picocolors@1.1.1", "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], + + "picomatch": ["picomatch@4.0.3", "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + + "pify": ["pify@2.3.0", "https://registry.npmmirror.com/pify/-/pify-2.3.0.tgz", {}, "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog=="], + + "plist": ["plist@3.1.0", "https://registry.npmmirror.com/plist/-/plist-3.1.0.tgz", { "dependencies": { "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" } }, "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ=="], + + "pngjs": ["pngjs@5.0.0", "", {}, "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw=="], + + "possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="], + + "postcss": ["postcss@8.5.8", "https://registry.npmmirror.com/postcss/-/postcss-8.5.8.tgz", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg=="], + + "postject": ["postject@1.0.0-alpha.6", "https://registry.npmmirror.com/postject/-/postject-1.0.0-alpha.6.tgz", { "dependencies": { "commander": "^9.4.0" }, "bin": "dist/cli.js" }, "sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A=="], + + "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], + + "prettier": ["prettier@3.8.3", "", { "bin": "bin/prettier.cjs" }, "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw=="], + + "proc-log": ["proc-log@2.0.1", "https://registry.npmmirror.com/proc-log/-/proc-log-2.0.1.tgz", {}, "sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw=="], + + "progress": ["progress@2.0.3", "https://registry.npmmirror.com/progress/-/progress-2.0.3.tgz", {}, "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="], + + "promise-inflight": ["promise-inflight@1.0.1", "https://registry.npmmirror.com/promise-inflight/-/promise-inflight-1.0.1.tgz", {}, "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g=="], + + "promise-retry": ["promise-retry@2.0.1", "https://registry.npmmirror.com/promise-retry/-/promise-retry-2.0.1.tgz", { "dependencies": { "err-code": "^2.0.2", "retry": "^0.12.0" } }, "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g=="], + + "prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], + + "pump": ["pump@3.0.4", "https://registry.npmmirror.com/pump/-/pump-3.0.4.tgz", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA=="], + + "punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="], + + "qrcode": ["qrcode@1.5.4", "", { "dependencies": { "dijkstrajs": "^1.0.1", "pngjs": "^5.0.0", "yargs": "^15.3.1" }, "bin": "bin/qrcode" }, "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg=="], + + "queue-microtask": ["queue-microtask@1.2.3", "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="], + + "quick-lru": ["quick-lru@5.1.1", "https://registry.npmmirror.com/quick-lru/-/quick-lru-5.1.1.tgz", {}, "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA=="], + + "random-path": ["random-path@0.1.2", "https://registry.npmmirror.com/random-path/-/random-path-0.1.2.tgz", { "dependencies": { "base32-encode": "^0.1.0 || ^1.0.0", "murmur-32": "^0.1.0 || ^0.2.0" } }, "sha512-4jY0yoEaQ5v9StCl5kZbNIQlg1QheIDBrdkDn53EynpPb9FgO6//p3X/tgMnrC45XN6QZCzU1Xz/+pSSsJBpRw=="], + + "react": ["react@19.2.4", "https://registry.npmmirror.com/react/-/react-19.2.4.tgz", {}, "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ=="], + + "react-dom": ["react-dom@19.2.4", "https://registry.npmmirror.com/react-dom/-/react-dom-19.2.4.tgz", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.4" } }, "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ=="], + + "react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], + + "react-refresh": ["react-refresh@0.18.0", "https://registry.npmmirror.com/react-refresh/-/react-refresh-0.18.0.tgz", {}, "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw=="], + + "read-binary-file-arch": ["read-binary-file-arch@1.0.6", "https://registry.npmmirror.com/read-binary-file-arch/-/read-binary-file-arch-1.0.6.tgz", { "dependencies": { "debug": "^4.3.4" }, "bin": "cli.js" }, "sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg=="], + + "read-pkg": ["read-pkg@2.0.0", "https://registry.npmmirror.com/read-pkg/-/read-pkg-2.0.0.tgz", { "dependencies": { "load-json-file": "^2.0.0", "normalize-package-data": "^2.3.2", "path-type": "^2.0.0" } }, "sha512-eFIBOPW7FGjzBuk3hdXEuNSiTZS/xEMlH49HxMyzb0hyPfu4EhVjT2DH32K1hSSmVq4sebAWnZuuY5auISUTGA=="], + + "read-pkg-up": ["read-pkg-up@2.0.0", "https://registry.npmmirror.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz", { "dependencies": { "find-up": "^2.0.0", "read-pkg": "^2.0.0" } }, "sha512-1orxQfbWGUiTn9XsPlChs6rLie/AV9jwZTGmu2NZw/CUDJQchXJFYE0Fq5j7+n558T1JhDWLdhyd1Zj+wLY//w=="], + + "readable-stream": ["readable-stream@3.6.2", "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz", { "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" } }, "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA=="], + + "readdirp": ["readdirp@5.0.0", "https://registry.npmmirror.com/readdirp/-/readdirp-5.0.0.tgz", {}, "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ=="], + + "rechoir": ["rechoir@0.8.0", "https://registry.npmmirror.com/rechoir/-/rechoir-0.8.0.tgz", { "dependencies": { "resolve": "^1.20.0" } }, "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ=="], + + "reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="], + + "regexp.prototype.flags": ["regexp.prototype.flags@1.5.4", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", "get-proto": "^1.0.1", "gopd": "^1.2.0", "set-function-name": "^2.0.2" } }, "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA=="], + + "repeat-string": ["repeat-string@1.6.1", "https://registry.npmmirror.com/repeat-string/-/repeat-string-1.6.1.tgz", {}, "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w=="], + + "require-directory": ["require-directory@2.1.1", "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="], + + "require-from-string": ["require-from-string@2.0.2", "https://registry.npmmirror.com/require-from-string/-/require-from-string-2.0.2.tgz", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], + + "require-main-filename": ["require-main-filename@2.0.0", "", {}, "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="], + + "resedit": ["resedit@2.0.3", "https://registry.npmmirror.com/resedit/-/resedit-2.0.3.tgz", { "dependencies": { "pe-library": "^1.0.1" } }, "sha512-oTeemxwoMuxxTYxXUwjkrOPfngTQehlv0/HoYFNkB4uzsP1Un1A9nI8JQKGOFkxpqkC7qkMs0lUsGrvUlbLNUA=="], + + "resolve": ["resolve@2.0.0-next.7", "", { "dependencies": { "es-errors": "^1.3.0", "is-core-module": "^2.16.2", "node-exports-info": "^1.6.0", "object-keys": "^1.1.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": "bin/resolve" }, "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ=="], + + "resolve-alpn": ["resolve-alpn@1.2.1", "https://registry.npmmirror.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz", {}, "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g=="], + + "resolve-from": ["resolve-from@4.0.0", "", {}, "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="], + + "responselike": ["responselike@2.0.1", "https://registry.npmmirror.com/responselike/-/responselike-2.0.1.tgz", { "dependencies": { "lowercase-keys": "^2.0.0" } }, "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw=="], + + "restore-cursor": ["restore-cursor@4.0.0", "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-4.0.0.tgz", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg=="], + + "retry": ["retry@0.12.0", "https://registry.npmmirror.com/retry/-/retry-0.12.0.tgz", {}, "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow=="], + + "reusify": ["reusify@1.1.0", "https://registry.npmmirror.com/reusify/-/reusify-1.1.0.tgz", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], + + "rfdc": ["rfdc@1.4.1", "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz", {}, "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA=="], + + "rimraf": ["rimraf@2.6.3", "https://registry.npmmirror.com/rimraf/-/rimraf-2.6.3.tgz", { "dependencies": { "glob": "^7.1.3" }, "bin": "bin.js" }, "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA=="], + + "roarr": ["roarr@2.15.4", "https://registry.npmmirror.com/roarr/-/roarr-2.15.4.tgz", { "dependencies": { "boolean": "^3.0.1", "detect-node": "^2.0.4", "globalthis": "^1.0.1", "json-stringify-safe": "^5.0.1", "semver-compare": "^1.0.0", "sprintf-js": "^1.1.2" } }, "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A=="], + + "rollup": ["rollup@4.59.0", "https://registry.npmmirror.com/rollup/-/rollup-4.59.0.tgz", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.59.0", "@rollup/rollup-android-arm64": "4.59.0", "@rollup/rollup-darwin-arm64": "4.59.0", "@rollup/rollup-darwin-x64": "4.59.0", "@rollup/rollup-freebsd-arm64": "4.59.0", "@rollup/rollup-freebsd-x64": "4.59.0", "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", "@rollup/rollup-linux-arm-musleabihf": "4.59.0", "@rollup/rollup-linux-arm64-gnu": "4.59.0", "@rollup/rollup-linux-arm64-musl": "4.59.0", "@rollup/rollup-linux-loong64-gnu": "4.59.0", "@rollup/rollup-linux-loong64-musl": "4.59.0", "@rollup/rollup-linux-ppc64-gnu": "4.59.0", "@rollup/rollup-linux-ppc64-musl": "4.59.0", "@rollup/rollup-linux-riscv64-gnu": "4.59.0", "@rollup/rollup-linux-riscv64-musl": "4.59.0", "@rollup/rollup-linux-s390x-gnu": "4.59.0", "@rollup/rollup-linux-x64-gnu": "4.59.0", "@rollup/rollup-linux-x64-musl": "4.59.0", "@rollup/rollup-openbsd-x64": "4.59.0", "@rollup/rollup-openharmony-arm64": "4.59.0", "@rollup/rollup-win32-arm64-msvc": "4.59.0", "@rollup/rollup-win32-ia32-msvc": "4.59.0", "@rollup/rollup-win32-x64-gnu": "4.59.0", "@rollup/rollup-win32-x64-msvc": "4.59.0", "fsevents": "~2.3.2" }, "bin": "dist/bin/rollup" }, "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg=="], + + "run-parallel": ["run-parallel@1.2.0", "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], + + "safe-array-concat": ["safe-array-concat@1.1.4", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "get-intrinsic": "^1.3.0", "has-symbols": "^1.1.0", "isarray": "^2.0.5" } }, "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg=="], + + "safe-buffer": ["safe-buffer@5.2.1", "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], + + "safe-push-apply": ["safe-push-apply@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "isarray": "^2.0.5" } }, "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA=="], + + "safe-regex-test": ["safe-regex-test@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" } }, "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw=="], + + "safer-buffer": ["safer-buffer@2.1.2", "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], + + "scheduler": ["scheduler@0.27.0", "https://registry.npmmirror.com/scheduler/-/scheduler-0.27.0.tgz", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], + + "schema-utils": ["schema-utils@4.3.3", "https://registry.npmmirror.com/schema-utils/-/schema-utils-4.3.3.tgz", { "dependencies": { "@types/json-schema": "^7.0.9", "ajv": "^8.9.0", "ajv-formats": "^2.1.1", "ajv-keywords": "^5.1.0" } }, "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA=="], + + "semver": ["semver@7.7.4", "https://registry.npmmirror.com/semver/-/semver-7.7.4.tgz", { "bin": "bin/semver.js" }, "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA=="], + + "semver-compare": ["semver-compare@1.0.0", "https://registry.npmmirror.com/semver-compare/-/semver-compare-1.0.0.tgz", {}, "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow=="], + + "serialize-error": ["serialize-error@7.0.1", "https://registry.npmmirror.com/serialize-error/-/serialize-error-7.0.1.tgz", { "dependencies": { "type-fest": "^0.13.1" } }, "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw=="], + + "set-blocking": ["set-blocking@2.0.0", "", {}, "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw=="], + + "set-function-length": ["set-function-length@1.2.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="], + + "set-function-name": ["set-function-name@2.0.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", "has-property-descriptors": "^1.0.2" } }, "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ=="], + + "set-proto": ["set-proto@1.0.0", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0" } }, "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw=="], + + "shebang-command": ["shebang-command@2.0.0", "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], + + "shebang-regex": ["shebang-regex@3.0.0", "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], + + "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="], + + "side-channel-list": ["side-channel-list@1.0.1", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.4" } }, "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w=="], + + "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="], + + "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="], + + "signal-exit": ["signal-exit@3.0.7", "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], + + "slice-ansi": ["slice-ansi@5.0.0", "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-5.0.0.tgz", { "dependencies": { "ansi-styles": "^6.0.0", "is-fullwidth-code-point": "^4.0.0" } }, "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ=="], + + "smart-buffer": ["smart-buffer@4.2.0", "https://registry.npmmirror.com/smart-buffer/-/smart-buffer-4.2.0.tgz", {}, "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="], + + "socks": ["socks@2.8.7", "https://registry.npmmirror.com/socks/-/socks-2.8.7.tgz", { "dependencies": { "ip-address": "^10.0.1", "smart-buffer": "^4.2.0" } }, "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A=="], + + "socks-proxy-agent": ["socks-proxy-agent@7.0.0", "https://registry.npmmirror.com/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", { "dependencies": { "agent-base": "^6.0.2", "debug": "^4.3.3", "socks": "^2.6.2" } }, "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww=="], + + "source-map": ["source-map@0.6.1", "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], + + "source-map-js": ["source-map-js@1.2.1", "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], + + "source-map-support": ["source-map-support@0.5.21", "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="], + + "spdx-correct": ["spdx-correct@3.2.0", "https://registry.npmmirror.com/spdx-correct/-/spdx-correct-3.2.0.tgz", { "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA=="], + + "spdx-exceptions": ["spdx-exceptions@2.5.0", "https://registry.npmmirror.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", {}, "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w=="], + + "spdx-expression-parse": ["spdx-expression-parse@3.0.1", "https://registry.npmmirror.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", { "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q=="], + + "spdx-license-ids": ["spdx-license-ids@3.0.23", "https://registry.npmmirror.com/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", {}, "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw=="], + + "sprintf-js": ["sprintf-js@1.1.3", "https://registry.npmmirror.com/sprintf-js/-/sprintf-js-1.1.3.tgz", {}, "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="], + + "ssri": ["ssri@9.0.1", "https://registry.npmmirror.com/ssri/-/ssri-9.0.1.tgz", { "dependencies": { "minipass": "^3.1.1" } }, "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q=="], + + "stop-iteration-iterator": ["stop-iteration-iterator@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "internal-slot": "^1.1.0" } }, "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ=="], + + "stream-buffers": ["stream-buffers@2.2.0", "https://registry.npmmirror.com/stream-buffers/-/stream-buffers-2.2.0.tgz", {}, "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg=="], + + "string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "string.prototype.matchall": ["string.prototype.matchall@4.0.12", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "regexp.prototype.flags": "^1.5.3", "set-function-name": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA=="], + + "string.prototype.repeat": ["string.prototype.repeat@1.0.0", "", { "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" } }, "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w=="], + + "string.prototype.trim": ["string.prototype.trim@1.2.10", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-data-property": "^1.1.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-object-atoms": "^1.0.0", "has-property-descriptors": "^1.0.2" } }, "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA=="], + + "string.prototype.trimend": ["string.prototype.trimend@1.0.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ=="], + + "string.prototype.trimstart": ["string.prototype.trimstart@1.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg=="], + + "string_decoder": ["string_decoder@1.3.0", "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], + + "strip-ansi": ["strip-ansi@7.2.0", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.2.0.tgz", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], + + "strip-bom": ["strip-bom@3.0.0", "https://registry.npmmirror.com/strip-bom/-/strip-bom-3.0.0.tgz", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="], + + "strip-eof": ["strip-eof@1.0.0", "https://registry.npmmirror.com/strip-eof/-/strip-eof-1.0.0.tgz", {}, "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q=="], + + "strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], + + "strip-outer": ["strip-outer@1.0.1", "https://registry.npmmirror.com/strip-outer/-/strip-outer-1.0.1.tgz", { "dependencies": { "escape-string-regexp": "^1.0.2" } }, "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg=="], + + "sumchecker": ["sumchecker@3.0.1", "https://registry.npmmirror.com/sumchecker/-/sumchecker-3.0.1.tgz", { "dependencies": { "debug": "^4.1.0" } }, "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg=="], + + "supports-color": ["supports-color@7.2.0", "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], + + "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], + + "tapable": ["tapable@2.3.0", "https://registry.npmmirror.com/tapable/-/tapable-2.3.0.tgz", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="], + + "tar": ["tar@6.2.1", "https://registry.npmmirror.com/tar/-/tar-6.2.1.tgz", { "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" } }, "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A=="], + + "temp": ["temp@0.9.4", "https://registry.npmmirror.com/temp/-/temp-0.9.4.tgz", { "dependencies": { "mkdirp": "^0.5.1", "rimraf": "~2.6.2" } }, "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA=="], + + "terser": ["terser@5.46.0", "https://registry.npmmirror.com/terser/-/terser-5.46.0.tgz", { "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.15.0", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": "bin/terser" }, "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg=="], + + "terser-webpack-plugin": ["terser-webpack-plugin@5.3.17", "https://registry.npmmirror.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.17.tgz", { "dependencies": { "@jridgewell/trace-mapping": "^0.3.25", "jest-worker": "^27.4.5", "schema-utils": "^4.3.0", "terser": "^5.31.1" }, "peerDependencies": { "webpack": "^5.1.0" } }, "sha512-YR7PtUp6GMU91BgSJmlaX/rS2lGDbAF7D+Wtq7hRO+MiljNmodYvqslzCFiYVAgW+Qoaaia/QUIP4lGXufjdZw=="], + + "tiny-each-async": ["tiny-each-async@2.0.3", "https://registry.npmmirror.com/tiny-each-async/-/tiny-each-async-2.0.3.tgz", {}, "sha512-5ROII7nElnAirvFn8g7H7MtpfV1daMcyfTGQwsn/x2VtyV+VPiO5CjReCJtWLvoKTDEDmZocf3cNPraiMnBXLA=="], + + "tinyglobby": ["tinyglobby@0.2.15", "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.15.tgz", { "dependencies": { "fdir": "^6.5.0", "picomatch": "^4.0.3" } }, "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ=="], + + "tmp": ["tmp@0.0.33", "https://registry.npmmirror.com/tmp/-/tmp-0.0.33.tgz", { "dependencies": { "os-tmpdir": "~1.0.2" } }, "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw=="], + + "tmp-promise": ["tmp-promise@3.0.3", "https://registry.npmmirror.com/tmp-promise/-/tmp-promise-3.0.3.tgz", { "dependencies": { "tmp": "^0.2.0" } }, "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ=="], + + "tn1150": ["tn1150@0.1.0", "https://registry.npmmirror.com/tn1150/-/tn1150-0.1.0.tgz", { "dependencies": { "unorm": "^1.4.1" } }, "sha512-DbplOfQFkqG5IHcDyyrs/lkvSr3mPUVsFf/RbDppOshs22yTPnSJWEe6FkYd1txAwU/zcnR905ar2fi4kwF29w=="], + + "to-data-view": ["to-data-view@1.1.0", "https://registry.npmmirror.com/to-data-view/-/to-data-view-1.1.0.tgz", {}, "sha512-1eAdufMg6mwgmlojAx3QeMnzB/BTVp7Tbndi3U7ftcT2zCZadjxkkmLmd97zmaxWi+sgGcgWrokmpEoy0Dn0vQ=="], + + "to-regex-range": ["to-regex-range@5.0.1", "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", { "dependencies": { "is-number": "^7.0.0" } }, "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ=="], + + "tr46": ["tr46@0.0.3", "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], + + "trim-repeated": ["trim-repeated@1.0.0", "https://registry.npmmirror.com/trim-repeated/-/trim-repeated-1.0.0.tgz", { "dependencies": { "escape-string-regexp": "^1.0.2" } }, "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg=="], + + "ts-api-utils": ["ts-api-utils@2.5.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA=="], + + "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], + + "type-fest": ["type-fest@0.13.1", "https://registry.npmmirror.com/type-fest/-/type-fest-0.13.1.tgz", {}, "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg=="], + + "typed-array-buffer": ["typed-array-buffer@1.0.3", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-typed-array": "^1.1.14" } }, "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw=="], + + "typed-array-byte-length": ["typed-array-byte-length@1.0.3", "", { "dependencies": { "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.14" } }, "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg=="], + + "typed-array-byte-offset": ["typed-array-byte-offset@1.0.4", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.15", "reflect.getprototypeof": "^1.0.9" } }, "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ=="], + + "typed-array-length": ["typed-array-length@1.0.8", "", { "dependencies": { "call-bind": "^1.0.9", "for-each": "^0.3.5", "gopd": "^1.2.0", "is-typed-array": "^1.1.15", "possible-typed-array-names": "^1.1.0", "reflect.getprototypeof": "^1.0.10" } }, "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g=="], + + "typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="], + + "typescript-eslint": ["typescript-eslint@8.61.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.61.0", "@typescript-eslint/parser": "8.61.0", "@typescript-eslint/typescript-estree": "8.61.0", "@typescript-eslint/utils": "8.61.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", "typescript": ">=4.8.4 <6.1.0" } }, "sha512-8y31Rd0eGTrDKqhy6vT0HtzhN+YLjQizwX3aA3hPXP/ynSfnrBXcQY5IzsP9/DM7+klX4IUncZZjkchP0z+rUw=="], + + "unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="], + + "undici-types": ["undici-types@7.24.6", "", {}, "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg=="], + + "unique-filename": ["unique-filename@2.0.1", "https://registry.npmmirror.com/unique-filename/-/unique-filename-2.0.1.tgz", { "dependencies": { "unique-slug": "^3.0.0" } }, "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A=="], + + "unique-slug": ["unique-slug@3.0.0", "https://registry.npmmirror.com/unique-slug/-/unique-slug-3.0.0.tgz", { "dependencies": { "imurmurhash": "^0.1.4" } }, "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w=="], + + "universalify": ["universalify@2.0.1", "https://registry.npmmirror.com/universalify/-/universalify-2.0.1.tgz", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], + + "unorm": ["unorm@1.6.0", "https://registry.npmmirror.com/unorm/-/unorm-1.6.0.tgz", {}, "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA=="], + + "update-browserslist-db": ["update-browserslist-db@1.2.3", "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": "cli.js" }, "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w=="], + + "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], + + "username": ["username@5.1.0", "https://registry.npmmirror.com/username/-/username-5.1.0.tgz", { "dependencies": { "execa": "^1.0.0", "mem": "^4.3.0" } }, "sha512-PCKbdWw85JsYMvmCv5GH3kXmM66rCd9m1hBEDutPNv94b/pqCMT4NtcKyeWYvLFiE8b+ha1Jdl8XAaUdPn5QTg=="], + + "util-deprecate": ["util-deprecate@1.0.2", "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], + + "validate-npm-package-license": ["validate-npm-package-license@3.0.4", "https://registry.npmmirror.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", { "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew=="], + + "vite": ["vite@7.3.1", "https://registry.npmmirror.com/vite/-/vite-7.3.1.tgz", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "tsx", "yaml"], "bin": "bin/vite.js" }, "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA=="], + + "watchpack": ["watchpack@2.5.1", "https://registry.npmmirror.com/watchpack/-/watchpack-2.5.1.tgz", { "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" } }, "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg=="], + + "wcwidth": ["wcwidth@1.0.1", "https://registry.npmmirror.com/wcwidth/-/wcwidth-1.0.1.tgz", { "dependencies": { "defaults": "^1.0.3" } }, "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg=="], + + "webidl-conversions": ["webidl-conversions@3.0.1", "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz", {}, "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="], + + "webpack": ["webpack@5.105.4", "https://registry.npmmirror.com/webpack/-/webpack-5.105.4.tgz", { "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", "@types/json-schema": "^7.0.15", "@webassemblyjs/ast": "^1.14.1", "@webassemblyjs/wasm-edit": "^1.14.1", "@webassemblyjs/wasm-parser": "^1.14.1", "acorn": "^8.16.0", "acorn-import-phases": "^1.0.3", "browserslist": "^4.28.1", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.20.0", "es-module-lexer": "^2.0.0", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.3.1", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^4.3.3", "tapable": "^2.3.0", "terser-webpack-plugin": "^5.3.17", "watchpack": "^2.5.1", "webpack-sources": "^3.3.4" }, "bin": "bin/webpack.js" }, "sha512-jTywjboN9aHxFlToqb0K0Zs9SbBoW4zRUlGzI2tYNxVYcEi/IPpn+Xi4ye5jTLvX2YeLuic/IvxNot+Q1jMoOw=="], + + "webpack-sources": ["webpack-sources@3.3.4", "https://registry.npmmirror.com/webpack-sources/-/webpack-sources-3.3.4.tgz", {}, "sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q=="], + + "whatwg-url": ["whatwg-url@5.0.0", "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz", { "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" } }, "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw=="], + + "which": ["which@2.0.2", "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], + + "which-boxed-primitive": ["which-boxed-primitive@1.1.1", "", { "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", "is-number-object": "^1.1.1", "is-string": "^1.1.1", "is-symbol": "^1.1.1" } }, "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA=="], + + "which-builtin-type": ["which-builtin-type@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "function.prototype.name": "^1.1.6", "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.1.0", "is-finalizationregistry": "^1.1.0", "is-generator-function": "^1.0.10", "is-regex": "^1.2.1", "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.1.0", "which-collection": "^1.0.2", "which-typed-array": "^1.1.16" } }, "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q=="], + + "which-collection": ["which-collection@1.0.2", "", { "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", "is-weakmap": "^2.0.2", "is-weakset": "^2.0.3" } }, "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw=="], + + "which-module": ["which-module@2.0.1", "", {}, "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ=="], + + "which-typed-array": ["which-typed-array@1.1.21", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.9", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-zbRA8cVm6io/d5W8uIe2hblzN76/Wm3v/yiythQvr+dpBWeqhPSWIDNj4zOyHi4zKbMK6DN34Xsr9jPHJERAEw=="], + + "word-wrap": ["word-wrap@1.2.5", "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.5.tgz", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], + + "wrap-ansi": ["wrap-ansi@8.1.0", "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], + + "wrappy": ["wrappy@1.0.2", "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz", {}, "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="], + + "xmlbuilder": ["xmlbuilder@15.1.1", "https://registry.npmmirror.com/xmlbuilder/-/xmlbuilder-15.1.1.tgz", {}, "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg=="], + + "xtend": ["xtend@4.0.2", "https://registry.npmmirror.com/xtend/-/xtend-4.0.2.tgz", {}, "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="], + + "y18n": ["y18n@4.0.3", "", {}, "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="], + + "yallist": ["yallist@4.0.0", "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "yargs": ["yargs@15.4.1", "", { "dependencies": { "cliui": "^6.0.0", "decamelize": "^1.2.0", "find-up": "^4.1.0", "get-caller-file": "^2.0.1", "require-directory": "^2.1.1", "require-main-filename": "^2.0.0", "set-blocking": "^2.0.0", "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", "yargs-parser": "^18.1.2" } }, "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A=="], + + "yargs-parser": ["yargs-parser@18.1.3", "", { "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" } }, "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ=="], + + "yauzl": ["yauzl@2.10.0", "https://registry.npmmirror.com/yauzl/-/yauzl-2.10.0.tgz", { "dependencies": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } }, "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g=="], + + "yocto-queue": ["yocto-queue@0.1.0", "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], + + "yoctocolors-cjs": ["yoctocolors-cjs@2.1.3", "https://registry.npmmirror.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz", {}, "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw=="], + + "zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], + + "zod-validation-error": ["zod-validation-error@4.0.2", "", { "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ=="], + + "@babel/core/semver": ["semver@6.3.1", "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "@babel/helper-compilation-targets/semver": ["semver@6.3.1", "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "@electron-forge/template-webpack-typescript/typescript": ["typescript@5.4.5", "https://registry.npmmirror.com/typescript/-/typescript-5.4.5.tgz", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ=="], + + "@electron/asar/commander": ["commander@5.1.0", "https://registry.npmmirror.com/commander/-/commander-5.1.0.tgz", {}, "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg=="], + + "@electron/fuses/fs-extra": ["fs-extra@9.1.0", "https://registry.npmmirror.com/fs-extra/-/fs-extra-9.1.0.tgz", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="], + + "@electron/get/fs-extra": ["fs-extra@8.1.0", "https://registry.npmmirror.com/fs-extra/-/fs-extra-8.1.0.tgz", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="], + + "@electron/get/semver": ["semver@6.3.1", "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "@electron/node-gyp/glob": ["glob@8.1.0", "https://registry.npmmirror.com/glob/-/glob-8.1.0.tgz", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^5.0.1", "once": "^1.3.0" } }, "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ=="], + + "@electron/notarize/fs-extra": ["fs-extra@9.1.0", "https://registry.npmmirror.com/fs-extra/-/fs-extra-9.1.0.tgz", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="], + + "@electron/packager/fs-extra": ["fs-extra@11.3.4", "https://registry.npmmirror.com/fs-extra/-/fs-extra-11.3.4.tgz", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA=="], + + "@electron/packager/resolve": ["resolve@1.22.11", "https://registry.npmmirror.com/resolve/-/resolve-1.22.11.tgz", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": "bin/resolve" }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="], + + "@electron/packager/yargs-parser": ["yargs-parser@21.1.1", "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-21.1.1.tgz", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], + + "@electron/rebuild/yargs": ["yargs@17.7.2", "https://registry.npmmirror.com/yargs/-/yargs-17.7.2.tgz", { "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" } }, "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w=="], + + "@electron/universal/fs-extra": ["fs-extra@11.3.4", "https://registry.npmmirror.com/fs-extra/-/fs-extra-11.3.4.tgz", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA=="], + + "@electron/universal/minimatch": ["minimatch@9.0.9", "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.9.tgz", { "dependencies": { "brace-expansion": "^2.0.2" } }, "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg=="], + + "@electron/windows-sign/fs-extra": ["fs-extra@11.3.4", "https://registry.npmmirror.com/fs-extra/-/fs-extra-11.3.4.tgz", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA=="], + + "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], + + "@eslint/eslintrc/ajv": ["ajv@6.15.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw=="], + + "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], + + "@inquirer/checkbox/@inquirer/type": ["@inquirer/type@2.0.0", "https://registry.npmmirror.com/@inquirer/type/-/type-2.0.0.tgz", { "dependencies": { "mute-stream": "^1.0.0" } }, "sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag=="], + + "@inquirer/confirm/@inquirer/type": ["@inquirer/type@2.0.0", "https://registry.npmmirror.com/@inquirer/type/-/type-2.0.0.tgz", { "dependencies": { "mute-stream": "^1.0.0" } }, "sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag=="], + + "@inquirer/core/@inquirer/type": ["@inquirer/type@2.0.0", "https://registry.npmmirror.com/@inquirer/type/-/type-2.0.0.tgz", { "dependencies": { "mute-stream": "^1.0.0" } }, "sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag=="], + + "@inquirer/core/@types/node": ["@types/node@22.19.13", "https://registry.npmmirror.com/@types/node/-/node-22.19.13.tgz", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-akNQMv0wW5uyRpD2v2IEyRSZiR+BeGuoB6L310EgGObO44HSMNT8z1xzio28V8qOrgYaopIDNA18YgdXd+qTiw=="], + + "@inquirer/core/signal-exit": ["signal-exit@4.1.0", "https://registry.npmmirror.com/signal-exit/-/signal-exit-4.1.0.tgz", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], + + "@inquirer/core/strip-ansi": ["strip-ansi@6.0.1", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "@inquirer/core/wrap-ansi": ["wrap-ansi@6.2.0", "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="], + + "@inquirer/editor/@inquirer/type": ["@inquirer/type@2.0.0", "https://registry.npmmirror.com/@inquirer/type/-/type-2.0.0.tgz", { "dependencies": { "mute-stream": "^1.0.0" } }, "sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag=="], + + "@inquirer/expand/@inquirer/type": ["@inquirer/type@2.0.0", "https://registry.npmmirror.com/@inquirer/type/-/type-2.0.0.tgz", { "dependencies": { "mute-stream": "^1.0.0" } }, "sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag=="], + + "@inquirer/input/@inquirer/type": ["@inquirer/type@2.0.0", "https://registry.npmmirror.com/@inquirer/type/-/type-2.0.0.tgz", { "dependencies": { "mute-stream": "^1.0.0" } }, "sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag=="], + + "@inquirer/number/@inquirer/type": ["@inquirer/type@2.0.0", "https://registry.npmmirror.com/@inquirer/type/-/type-2.0.0.tgz", { "dependencies": { "mute-stream": "^1.0.0" } }, "sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag=="], + + "@inquirer/password/@inquirer/type": ["@inquirer/type@2.0.0", "https://registry.npmmirror.com/@inquirer/type/-/type-2.0.0.tgz", { "dependencies": { "mute-stream": "^1.0.0" } }, "sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag=="], + + "@inquirer/rawlist/@inquirer/type": ["@inquirer/type@2.0.0", "https://registry.npmmirror.com/@inquirer/type/-/type-2.0.0.tgz", { "dependencies": { "mute-stream": "^1.0.0" } }, "sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag=="], + + "@inquirer/search/@inquirer/type": ["@inquirer/type@2.0.0", "https://registry.npmmirror.com/@inquirer/type/-/type-2.0.0.tgz", { "dependencies": { "mute-stream": "^1.0.0" } }, "sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag=="], + + "@inquirer/select/@inquirer/type": ["@inquirer/type@2.0.0", "https://registry.npmmirror.com/@inquirer/type/-/type-2.0.0.tgz", { "dependencies": { "mute-stream": "^1.0.0" } }, "sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag=="], + + "@npmcli/move-file/mkdirp": ["mkdirp@1.0.4", "https://registry.npmmirror.com/mkdirp/-/mkdirp-1.0.4.tgz", { "bin": "bin/cmd.js" }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="], + + "@npmcli/move-file/rimraf": ["rimraf@3.0.2", "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", { "dependencies": { "glob": "^7.1.3" }, "bin": "bin.js" }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="], + + "@types/appdmg/@types/node": ["@types/node@22.19.13", "https://registry.npmmirror.com/@types/node/-/node-22.19.13.tgz", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-akNQMv0wW5uyRpD2v2IEyRSZiR+BeGuoB6L310EgGObO44HSMNT8z1xzio28V8qOrgYaopIDNA18YgdXd+qTiw=="], + + "@types/cacheable-request/@types/node": ["@types/node@22.19.13", "https://registry.npmmirror.com/@types/node/-/node-22.19.13.tgz", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-akNQMv0wW5uyRpD2v2IEyRSZiR+BeGuoB6L310EgGObO44HSMNT8z1xzio28V8qOrgYaopIDNA18YgdXd+qTiw=="], + + "@types/fs-extra/@types/node": ["@types/node@22.19.13", "https://registry.npmmirror.com/@types/node/-/node-22.19.13.tgz", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-akNQMv0wW5uyRpD2v2IEyRSZiR+BeGuoB6L310EgGObO44HSMNT8z1xzio28V8qOrgYaopIDNA18YgdXd+qTiw=="], + + "@types/keyv/@types/node": ["@types/node@22.19.13", "https://registry.npmmirror.com/@types/node/-/node-22.19.13.tgz", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-akNQMv0wW5uyRpD2v2IEyRSZiR+BeGuoB6L310EgGObO44HSMNT8z1xzio28V8qOrgYaopIDNA18YgdXd+qTiw=="], + + "@types/mute-stream/@types/node": ["@types/node@22.19.13", "https://registry.npmmirror.com/@types/node/-/node-22.19.13.tgz", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-akNQMv0wW5uyRpD2v2IEyRSZiR+BeGuoB6L310EgGObO44HSMNT8z1xzio28V8qOrgYaopIDNA18YgdXd+qTiw=="], + + "@types/responselike/@types/node": ["@types/node@22.19.13", "https://registry.npmmirror.com/@types/node/-/node-22.19.13.tgz", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-akNQMv0wW5uyRpD2v2IEyRSZiR+BeGuoB6L310EgGObO44HSMNT8z1xzio28V8qOrgYaopIDNA18YgdXd+qTiw=="], + + "@types/yauzl/@types/node": ["@types/node@22.19.13", "https://registry.npmmirror.com/@types/node/-/node-22.19.13.tgz", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-akNQMv0wW5uyRpD2v2IEyRSZiR+BeGuoB6L310EgGObO44HSMNT8z1xzio28V8qOrgYaopIDNA18YgdXd+qTiw=="], + + "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], + + "@typescript-eslint/typescript-estree/minimatch": ["minimatch@10.2.5", "", { "dependencies": { "brace-expansion": "^5.0.5" } }, "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg=="], + + "@typescript-eslint/visitor-keys/eslint-visitor-keys": ["eslint-visitor-keys@5.0.1", "", {}, "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA=="], + + "ajv-formats/ajv": ["ajv@8.18.0", "https://registry.npmmirror.com/ajv/-/ajv-8.18.0.tgz", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A=="], + + "ajv-keywords/ajv": ["ajv@8.18.0", "https://registry.npmmirror.com/ajv/-/ajv-8.18.0.tgz", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A=="], + + "ansi-escapes/type-fest": ["type-fest@0.21.3", "https://registry.npmmirror.com/type-fest/-/type-fest-0.21.3.tgz", {}, "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w=="], + + "cacache/glob": ["glob@8.1.0", "https://registry.npmmirror.com/glob/-/glob-8.1.0.tgz", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^5.0.1", "once": "^1.3.0" } }, "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ=="], + + "cacache/lru-cache": ["lru-cache@7.18.3", "https://registry.npmmirror.com/lru-cache/-/lru-cache-7.18.3.tgz", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="], + + "cacache/minipass": ["minipass@3.3.6", "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "cacache/mkdirp": ["mkdirp@1.0.4", "https://registry.npmmirror.com/mkdirp/-/mkdirp-1.0.4.tgz", { "bin": "bin/cmd.js" }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="], + + "cacache/rimraf": ["rimraf@3.0.2", "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", { "dependencies": { "glob": "^7.1.3" }, "bin": "bin.js" }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="], + + "cacheable-request/get-stream": ["get-stream@5.2.0", "https://registry.npmmirror.com/get-stream/-/get-stream-5.2.0.tgz", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="], + + "cli-truncate/string-width": ["string-width@5.1.2", "https://registry.npmmirror.com/string-width/-/string-width-5.1.2.tgz", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + + "cliui/strip-ansi": ["strip-ansi@6.0.1", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "cliui/wrap-ansi": ["wrap-ansi@6.2.0", "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="], + + "clone-response/mimic-response": ["mimic-response@1.0.1", "https://registry.npmmirror.com/mimic-response/-/mimic-response-1.0.1.tgz", {}, "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ=="], + + "electron/@electron/get": ["@electron/get@2.0.3", "https://registry.npmmirror.com/@electron/get/-/get-2.0.3.tgz", { "dependencies": { "debug": "^4.1.1", "env-paths": "^2.2.0", "fs-extra": "^8.1.0", "got": "^11.8.5", "progress": "^2.0.3", "semver": "^6.2.0", "sumchecker": "^3.0.1" }, "optionalDependencies": { "global-agent": "^3.0.0" } }, "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ=="], + + "electron/@types/node": ["@types/node@24.11.0", "https://registry.npmmirror.com/@types/node/-/node-24.11.0.tgz", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-fPxQqz4VTgPI/IQ+lj9r0h+fDR66bzoeMGHp8ASee+32OSGIkeASsoZuJixsQoVef1QJbeubcPBxKk22QVoWdw=="], + + "electron-installer-common/@malept/cross-spawn-promise": ["@malept/cross-spawn-promise@1.1.1", "https://registry.npmmirror.com/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", { "dependencies": { "cross-spawn": "^7.0.1" } }, "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ=="], + + "electron-installer-common/fs-extra": ["fs-extra@9.1.0", "https://registry.npmmirror.com/fs-extra/-/fs-extra-9.1.0.tgz", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="], + + "electron-installer-debian/@malept/cross-spawn-promise": ["@malept/cross-spawn-promise@1.1.1", "https://registry.npmmirror.com/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", { "dependencies": { "cross-spawn": "^7.0.1" } }, "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ=="], + + "electron-installer-debian/fs-extra": ["fs-extra@9.1.0", "https://registry.npmmirror.com/fs-extra/-/fs-extra-9.1.0.tgz", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="], + + "electron-installer-debian/yargs": ["yargs@16.2.0", "https://registry.npmmirror.com/yargs/-/yargs-16.2.0.tgz", { "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" } }, "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw=="], + + "electron-installer-redhat/@malept/cross-spawn-promise": ["@malept/cross-spawn-promise@1.1.1", "https://registry.npmmirror.com/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", { "dependencies": { "cross-spawn": "^7.0.1" } }, "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ=="], + + "electron-installer-redhat/fs-extra": ["fs-extra@9.1.0", "https://registry.npmmirror.com/fs-extra/-/fs-extra-9.1.0.tgz", { "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ=="], + + "electron-installer-redhat/yargs": ["yargs@16.2.0", "https://registry.npmmirror.com/yargs/-/yargs-16.2.0.tgz", { "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", "string-width": "^4.2.0", "y18n": "^5.0.5", "yargs-parser": "^20.2.2" } }, "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw=="], + + "electron-squirrel-startup/debug": ["debug@2.6.9", "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "electron-winstaller/fs-extra": ["fs-extra@7.0.1", "https://registry.npmmirror.com/fs-extra/-/fs-extra-7.0.1.tgz", { "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw=="], + + "eslint-plugin-react/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "eslint-scope/estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + + "esquery/estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + + "esrecurse/estraverse": ["estraverse@5.3.0", "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + + "execa/cross-spawn": ["cross-spawn@6.0.6", "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-6.0.6.tgz", { "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" } }, "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw=="], + + "execa/get-stream": ["get-stream@4.1.0", "https://registry.npmmirror.com/get-stream/-/get-stream-4.1.0.tgz", { "dependencies": { "pump": "^3.0.0" } }, "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w=="], + + "external-editor/iconv-lite": ["iconv-lite@0.4.24", "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.4.24.tgz", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3" } }, "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA=="], + + "fast-glob/glob-parent": ["glob-parent@5.1.2", "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + + "fs-minipass/minipass": ["minipass@3.3.6", "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "get-package-info/debug": ["debug@2.6.9", "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", { "dependencies": { "ms": "2.0.0" } }, "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA=="], + + "jest-worker/@types/node": ["@types/node@22.19.13", "https://registry.npmmirror.com/@types/node/-/node-22.19.13.tgz", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-akNQMv0wW5uyRpD2v2IEyRSZiR+BeGuoB6L310EgGObO44HSMNT8z1xzio28V8qOrgYaopIDNA18YgdXd+qTiw=="], + + "jest-worker/supports-color": ["supports-color@8.1.1", "https://registry.npmmirror.com/supports-color/-/supports-color-8.1.1.tgz", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q=="], + + "log-update/ansi-escapes": ["ansi-escapes@5.0.0", "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-5.0.0.tgz", { "dependencies": { "type-fest": "^1.0.2" } }, "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA=="], + + "log-update/wrap-ansi": ["wrap-ansi@8.1.0", "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], + + "lru-cache/yallist": ["yallist@3.1.1", "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], + + "make-fetch-happen/lru-cache": ["lru-cache@7.18.3", "https://registry.npmmirror.com/lru-cache/-/lru-cache-7.18.3.tgz", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="], + + "make-fetch-happen/minipass": ["minipass@3.3.6", "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "micromatch/picomatch": ["picomatch@2.3.1", "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], + + "minipass-collect/minipass": ["minipass@3.3.6", "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "minipass-fetch/minipass": ["minipass@3.3.6", "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "minipass-flush/minipass": ["minipass@3.3.6", "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "minipass-pipeline/minipass": ["minipass@3.3.6", "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "minipass-sized/minipass": ["minipass@3.3.6", "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "minizlib/minipass": ["minipass@3.3.6", "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "minizlib/yallist": ["yallist@4.0.0", "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "node-exports-info/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "normalize-package-data/resolve": ["resolve@1.22.11", "https://registry.npmmirror.com/resolve/-/resolve-1.22.11.tgz", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": "bin/resolve" }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="], + + "normalize-package-data/semver": ["semver@5.7.2", "https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz", { "bin": "bin/semver" }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], + + "npm-run-path/path-key": ["path-key@2.0.1", "https://registry.npmmirror.com/path-key/-/path-key-2.0.1.tgz", {}, "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="], + + "ora/cli-cursor": ["cli-cursor@3.1.0", "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-3.1.0.tgz", { "dependencies": { "restore-cursor": "^3.1.0" } }, "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw=="], + + "ora/strip-ansi": ["strip-ansi@6.0.1", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "parse-color/color-convert": ["color-convert@0.5.3", "https://registry.npmmirror.com/color-convert/-/color-convert-0.5.3.tgz", {}, "sha512-RwBeO/B/vZR3dfKL1ye/vx8MHZ40ugzpyfeVG5GsiuGnrlMWe2o8wxBbLCpw9CsxV+wHuzYlCiWnybrIA0ling=="], + + "postject/commander": ["commander@9.5.0", "https://registry.npmmirror.com/commander/-/commander-9.5.0.tgz", {}, "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ=="], + + "read-pkg-up/find-up": ["find-up@2.1.0", "https://registry.npmmirror.com/find-up/-/find-up-2.1.0.tgz", { "dependencies": { "locate-path": "^2.0.0" } }, "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ=="], + + "rechoir/resolve": ["resolve@1.22.11", "https://registry.npmmirror.com/resolve/-/resolve-1.22.11.tgz", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": "bin/resolve" }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="], + + "restore-cursor/signal-exit": ["signal-exit@3.0.7", "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], + + "schema-utils/ajv": ["ajv@8.18.0", "https://registry.npmmirror.com/ajv/-/ajv-8.18.0.tgz", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A=="], + + "slice-ansi/ansi-styles": ["ansi-styles@6.2.3", "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.3.tgz", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + + "slice-ansi/is-fullwidth-code-point": ["is-fullwidth-code-point@4.0.0", "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", {}, "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ=="], + + "ssri/minipass": ["minipass@3.3.6", "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], + + "string-width/strip-ansi": ["strip-ansi@6.0.1", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "strip-outer/escape-string-regexp": ["escape-string-regexp@1.0.5", "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], + + "tar/mkdirp": ["mkdirp@1.0.4", "https://registry.npmmirror.com/mkdirp/-/mkdirp-1.0.4.tgz", { "bin": "bin/cmd.js" }, "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="], + + "terser/commander": ["commander@2.20.3", "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], + + "tinyglobby/fdir": ["fdir@6.5.0", "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", { "peerDependencies": { "picomatch": "^3 || ^4" } }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], + + "tinyglobby/picomatch": ["picomatch@4.0.3", "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], + + "tmp-promise/tmp": ["tmp@0.2.5", "https://registry.npmmirror.com/tmp/-/tmp-0.2.5.tgz", {}, "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow=="], + + "trim-repeated/escape-string-regexp": ["escape-string-regexp@1.0.5", "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], + + "webpack/eslint-scope": ["eslint-scope@5.1.1", "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-5.1.1.tgz", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" } }, "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw=="], + + "wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.3.tgz", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + + "wrap-ansi/string-width": ["string-width@5.1.2", "https://registry.npmmirror.com/string-width/-/string-width-5.1.2.tgz", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + + "wrap-ansi/strip-ansi": ["strip-ansi@7.2.0", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.2.0.tgz", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], + + "yargs/find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="], + + "@electron/get/fs-extra/jsonfile": ["jsonfile@4.0.0", "https://registry.npmmirror.com/jsonfile/-/jsonfile-4.0.0.tgz", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], + + "@electron/get/fs-extra/universalify": ["universalify@0.1.2", "https://registry.npmmirror.com/universalify/-/universalify-0.1.2.tgz", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], + + "@electron/node-gyp/glob/minimatch": ["minimatch@5.1.9", "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.9.tgz", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw=="], + + "@electron/rebuild/yargs/cliui": ["cliui@8.0.1", "https://registry.npmmirror.com/cliui/-/cliui-8.0.1.tgz", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], + + "@electron/rebuild/yargs/string-width": ["string-width@4.2.3", "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "@electron/rebuild/yargs/y18n": ["y18n@5.0.8", "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], + + "@electron/rebuild/yargs/yargs-parser": ["yargs-parser@21.1.1", "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-21.1.1.tgz", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], + + "@electron/universal/minimatch/brace-expansion": ["brace-expansion@2.0.2", "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.2.tgz", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + + "@eslint/eslintrc/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], + + "@inquirer/core/@types/node/undici-types": ["undici-types@6.21.0", "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], + + "@inquirer/core/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "@inquirer/core/wrap-ansi/string-width": ["string-width@4.2.3", "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "@types/appdmg/@types/node/undici-types": ["undici-types@6.21.0", "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], + + "@types/cacheable-request/@types/node/undici-types": ["undici-types@6.21.0", "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], + + "@types/fs-extra/@types/node/undici-types": ["undici-types@6.21.0", "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], + + "@types/keyv/@types/node/undici-types": ["undici-types@6.21.0", "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], + + "@types/mute-stream/@types/node/undici-types": ["undici-types@6.21.0", "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], + + "@types/responselike/@types/node/undici-types": ["undici-types@6.21.0", "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], + + "@types/yauzl/@types/node/undici-types": ["undici-types@6.21.0", "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], + + "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@5.0.6", "", { "dependencies": { "balanced-match": "^4.0.2" } }, "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g=="], + + "ajv-formats/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], + + "ajv-keywords/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], + + "cacache/glob/minimatch": ["minimatch@5.1.9", "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.9.tgz", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw=="], + + "cacache/minipass/yallist": ["yallist@4.0.0", "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "cacache/rimraf/glob": ["glob@7.2.3", "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], + + "cli-truncate/string-width/emoji-regex": ["emoji-regex@9.2.2", "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + + "cli-truncate/string-width/strip-ansi": ["strip-ansi@7.2.0", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.2.0.tgz", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], + + "cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "cliui/wrap-ansi/string-width": ["string-width@4.2.3", "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "electron-installer-debian/yargs/cliui": ["cliui@7.0.4", "https://registry.npmmirror.com/cliui/-/cliui-7.0.4.tgz", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ=="], + + "electron-installer-debian/yargs/string-width": ["string-width@4.2.3", "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "electron-installer-debian/yargs/y18n": ["y18n@5.0.8", "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], + + "electron-installer-debian/yargs/yargs-parser": ["yargs-parser@20.2.9", "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-20.2.9.tgz", {}, "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="], + + "electron-installer-redhat/yargs/cliui": ["cliui@7.0.4", "https://registry.npmmirror.com/cliui/-/cliui-7.0.4.tgz", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ=="], + + "electron-installer-redhat/yargs/string-width": ["string-width@4.2.3", "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "electron-installer-redhat/yargs/y18n": ["y18n@5.0.8", "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], + + "electron-installer-redhat/yargs/yargs-parser": ["yargs-parser@20.2.9", "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-20.2.9.tgz", {}, "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="], + + "electron-squirrel-startup/debug/ms": ["ms@2.0.0", "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + + "electron-winstaller/fs-extra/jsonfile": ["jsonfile@4.0.0", "https://registry.npmmirror.com/jsonfile/-/jsonfile-4.0.0.tgz", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], + + "electron-winstaller/fs-extra/universalify": ["universalify@0.1.2", "https://registry.npmmirror.com/universalify/-/universalify-0.1.2.tgz", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], + + "electron/@electron/get/fs-extra": ["fs-extra@8.1.0", "https://registry.npmmirror.com/fs-extra/-/fs-extra-8.1.0.tgz", { "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g=="], + + "electron/@electron/get/semver": ["semver@6.3.1", "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + + "electron/@types/node/undici-types": ["undici-types@7.16.0", "https://registry.npmmirror.com/undici-types/-/undici-types-7.16.0.tgz", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + + "execa/cross-spawn/path-key": ["path-key@2.0.1", "https://registry.npmmirror.com/path-key/-/path-key-2.0.1.tgz", {}, "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw=="], + + "execa/cross-spawn/semver": ["semver@5.7.2", "https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz", { "bin": "bin/semver" }, "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g=="], + + "execa/cross-spawn/shebang-command": ["shebang-command@1.2.0", "https://registry.npmmirror.com/shebang-command/-/shebang-command-1.2.0.tgz", { "dependencies": { "shebang-regex": "^1.0.0" } }, "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg=="], + + "execa/cross-spawn/which": ["which@1.3.1", "https://registry.npmmirror.com/which/-/which-1.3.1.tgz", { "dependencies": { "isexe": "^2.0.0" }, "bin": "bin/which" }, "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ=="], + + "fs-minipass/minipass/yallist": ["yallist@4.0.0", "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "get-package-info/debug/ms": ["ms@2.0.0", "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], + + "jest-worker/@types/node/undici-types": ["undici-types@6.21.0", "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], + + "log-update/ansi-escapes/type-fest": ["type-fest@1.4.0", "https://registry.npmmirror.com/type-fest/-/type-fest-1.4.0.tgz", {}, "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA=="], + + "log-update/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.3.tgz", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], + + "log-update/wrap-ansi/string-width": ["string-width@5.1.2", "https://registry.npmmirror.com/string-width/-/string-width-5.1.2.tgz", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], + + "make-fetch-happen/minipass/yallist": ["yallist@4.0.0", "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "minipass-collect/minipass/yallist": ["yallist@4.0.0", "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "minipass-fetch/minipass/yallist": ["yallist@4.0.0", "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "minipass-flush/minipass/yallist": ["yallist@4.0.0", "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "minipass-pipeline/minipass/yallist": ["yallist@4.0.0", "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "minipass-sized/minipass/yallist": ["yallist@4.0.0", "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "minizlib/minipass/yallist": ["yallist@4.0.0", "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "ora/cli-cursor/restore-cursor": ["restore-cursor@3.1.0", "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-3.1.0.tgz", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA=="], + + "ora/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "read-pkg-up/find-up/locate-path": ["locate-path@2.0.0", "https://registry.npmmirror.com/locate-path/-/locate-path-2.0.0.tgz", { "dependencies": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" } }, "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA=="], + + "schema-utils/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], + + "ssri/minipass/yallist": ["yallist@4.0.0", "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], + + "string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "webpack/eslint-scope/estraverse": ["estraverse@4.3.0", "https://registry.npmmirror.com/estraverse/-/estraverse-4.3.0.tgz", {}, "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="], + + "wrap-ansi/string-width/emoji-regex": ["emoji-regex@9.2.2", "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + + "wrap-ansi/string-width/strip-ansi": ["strip-ansi@7.2.0", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.2.0.tgz", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], + + "wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.2.2.tgz", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], + + "yargs/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], + + "@electron/node-gyp/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.2.tgz", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + + "@electron/rebuild/yargs/cliui/string-width": ["string-width@4.2.3", "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], + + "@electron/rebuild/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "@electron/rebuild/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + + "@electron/rebuild/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "@electron/rebuild/yargs/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + + "@electron/rebuild/yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "@inquirer/core/wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "@inquirer/core/wrap-ansi/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + + "@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], + + "cacache/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.2.tgz", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], + + "cli-truncate/string-width/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.2.2.tgz", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], + + "cliui/wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "cliui/wrap-ansi/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + + "electron-installer-debian/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "electron-installer-debian/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + + "electron-installer-debian/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "electron-installer-debian/yargs/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + + "electron-installer-debian/yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "electron-installer-redhat/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "electron-installer-redhat/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], + + "electron-installer-redhat/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "electron-installer-redhat/yargs/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + + "electron-installer-redhat/yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], + + "electron/@electron/get/fs-extra/jsonfile": ["jsonfile@4.0.0", "https://registry.npmmirror.com/jsonfile/-/jsonfile-4.0.0.tgz", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], + + "electron/@electron/get/fs-extra/universalify": ["universalify@0.1.2", "https://registry.npmmirror.com/universalify/-/universalify-0.1.2.tgz", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], + + "execa/cross-spawn/shebang-command/shebang-regex": ["shebang-regex@1.0.0", "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-1.0.0.tgz", {}, "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ=="], + + "log-update/wrap-ansi/string-width/emoji-regex": ["emoji-regex@9.2.2", "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], + + "log-update/wrap-ansi/string-width/strip-ansi": ["strip-ansi@7.2.0", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.2.0.tgz", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], + + "ora/cli-cursor/restore-cursor/signal-exit": ["signal-exit@3.0.7", "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], + + "read-pkg-up/find-up/locate-path/p-locate": ["p-locate@2.0.0", "https://registry.npmmirror.com/p-locate/-/p-locate-2.0.0.tgz", { "dependencies": { "p-limit": "^1.1.0" } }, "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg=="], + + "read-pkg-up/find-up/locate-path/path-exists": ["path-exists@3.0.0", "https://registry.npmmirror.com/path-exists/-/path-exists-3.0.0.tgz", {}, "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ=="], + + "wrap-ansi/string-width/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.2.2.tgz", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], + + "yargs/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], + + "@electron/rebuild/yargs/cliui/string-width/emoji-regex": ["emoji-regex@8.0.0", "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], + + "@electron/rebuild/yargs/cliui/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], + + "@electron/rebuild/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "@electron/rebuild/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "electron-installer-debian/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "electron-installer-debian/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "electron-installer-redhat/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "electron-installer-redhat/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], + + "log-update/wrap-ansi/string-width/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.2.2.tgz", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], + + "read-pkg-up/find-up/locate-path/p-locate/p-limit": ["p-limit@1.3.0", "https://registry.npmmirror.com/p-limit/-/p-limit-1.3.0.tgz", { "dependencies": { "p-try": "^1.0.0" } }, "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q=="], + + "yargs/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], + + "read-pkg-up/find-up/locate-path/p-locate/p-limit/p-try": ["p-try@1.0.0", "https://registry.npmmirror.com/p-try/-/p-try-1.0.0.tgz", {}, "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww=="], + } +} diff --git a/taskboard-electron/eslint.config.mjs b/taskboard-electron/eslint.config.mjs index 851d496..1991f59 100644 --- a/taskboard-electron/eslint.config.mjs +++ b/taskboard-electron/eslint.config.mjs @@ -1,10 +1,11 @@ import js from "@eslint/js"; import globals from "globals"; +import tseslint from "typescript-eslint"; import react from "eslint-plugin-react"; import reactHooks from "eslint-plugin-react-hooks"; import prettier from "eslint-config-prettier"; -export default [ +export default tseslint.config( { ignores: [ ".vite/**", @@ -19,6 +20,12 @@ export default [ js.configs.recommended, + // TypeScript sources (main, preload, renderer, tests). + ...tseslint.configs.recommended.map((config) => ({ + ...config, + files: ["src/**/*.{ts,tsx}"], + })), + // Project-wide tweaks: allow `_`-prefixed throwaways and intentional empty // catches; permit full-width spaces inside Chinese JSX copy. { @@ -39,11 +46,29 @@ export default [ }, }, + // Pragmatic migration posture: the codebase leans on `any` while strict + // typing is layered in incrementally. + { + files: ["src/**/*.{ts,tsx}"], + rules: { + "@typescript-eslint/no-explicit-any": "off", + "no-unused-vars": "off", + "@typescript-eslint/no-unused-vars": [ + "error", + { + argsIgnorePattern: "^_", + varsIgnorePattern: "^_", + caughtErrorsIgnorePattern: "^_", + }, + ], + }, + }, + // Node-side code: Electron main/preload, build scripts, Forge/Vite configs. { files: [ - "src/main.js", - "src/preload.js", + "src/main.ts", + "src/preload.ts", "scripts/**/*.mjs", "forge.config.js", "*.config.js", @@ -60,9 +85,18 @@ export default [ }, }, + // The preload script intentionally uses CommonJS `require` (Electron preload + // context); main.ts keeps a lazy `require` for a synchronous child_process call. + { + files: ["src/main.ts", "src/preload.ts"], + rules: { + "@typescript-eslint/no-require-imports": "off", + }, + }, + // Renderer code: browser context + React/JSX. { - files: ["src/renderer.js", "src/renderer/**/*.{js,jsx,mjs}"], + files: ["src/renderer.ts", "src/renderer/**/*.{ts,tsx}"], plugins: { react, "react-hooks": reactHooks }, languageOptions: { ecmaVersion: 2024, @@ -82,9 +116,9 @@ export default [ }, }, - // Renderer unit tests run under `node --test`, so they need Node globals too. + // Renderer unit tests run under `bun test`, so they need Node globals too. { - files: ["src/renderer/**/*.test.mjs"], + files: ["src/renderer/**/*.test.ts"], languageOptions: { globals: { ...globals.node }, }, @@ -92,4 +126,4 @@ export default [ // Keep ESLint clear of anything Prettier owns (formatting). prettier, -]; +); diff --git a/taskboard-electron/forge.config.js b/taskboard-electron/forge.config.js index c941224..7584340 100644 --- a/taskboard-electron/forge.config.js +++ b/taskboard-electron/forge.config.js @@ -36,12 +36,12 @@ module.exports = { config: { build: [ { - entry: "src/main.js", + entry: "src/main.ts", config: "vite.main.config.mjs", target: "main", }, { - entry: "src/preload.js", + entry: "src/preload.ts", config: "vite.preload.config.mjs", target: "preload", }, diff --git a/taskboard-electron/index.html b/taskboard-electron/index.html index f0bed60..4997c85 100644 --- a/taskboard-electron/index.html +++ b/taskboard-electron/index.html @@ -6,6 +6,6 @@
- + diff --git a/taskboard-electron/package.json b/taskboard-electron/package.json index a5562cb..ab2eb0a 100644 --- a/taskboard-electron/package.json +++ b/taskboard-electron/package.json @@ -12,11 +12,12 @@ "package": "electron-forge package", "make": "electron-forge make", "publish": "electron-forge publish", - "test": "TZ=Asia/Shanghai node --test src/renderer/*.test.mjs", + "test": "TZ=Asia/Shanghai bun test src/renderer/", + "typecheck": "tsc --noEmit -p tsconfig.json && tsc --noEmit -p tsconfig.node.json", "lint": "eslint .", "lint:fix": "eslint . --fix", - "format": "prettier --write \"src/**/*.{js,jsx,mjs}\" \"scripts/**/*.mjs\" \"*.config.js\" \"vite.*.config.mjs\" \"eslint.config.mjs\"", - "format:check": "prettier --check \"src/**/*.{js,jsx,mjs}\" \"scripts/**/*.mjs\" \"*.config.js\" \"vite.*.config.mjs\" \"eslint.config.mjs\"", + "format": "prettier --write \"src/**/*.{ts,tsx}\" \"scripts/**/*.mjs\" \"*.config.js\" \"vite.*.config.mjs\" \"eslint.config.mjs\"", + "format:check": "prettier --check \"src/**/*.{ts,tsx}\" \"scripts/**/*.mjs\" \"*.config.js\" \"vite.*.config.mjs\" \"eslint.config.mjs\"", "build:check": "SKIP_BACKEND_BUILD=1 vite build --config vite.renderer.config.mjs --outDir .vite/build-check --emptyOutDir" }, "keywords": [], @@ -34,6 +35,10 @@ "@electron-forge/plugin-vite": "^7.11.1", "@electron/fuses": "^1.8.0", "@eslint/js": "^9.39.4", + "@types/bun": "^1.3.14", + "@types/node": "^25.9.3", + "@types/react": "^19.2.17", + "@types/react-dom": "^19.2.3", "@vitejs/plugin-react": "^5.1.4", "electron": "40.2.1", "eslint": "^9.39.4", @@ -42,6 +47,8 @@ "eslint-plugin-react-hooks": "^7.1.1", "globals": "^17.6.0", "prettier": "^3.8.3", + "typescript": "^6.0.3", + "typescript-eslint": "^8.61.0", "vite": "^7.3.1" }, "dependencies": { diff --git a/taskboard-electron/src/main.ts b/taskboard-electron/src/main.ts index 3842536..54947a3 100644 --- a/taskboard-electron/src/main.ts +++ b/taskboard-electron/src/main.ts @@ -1,18 +1,28 @@ import { app, BrowserWindow, dialog, ipcMain, powerSaveBlocker } from "electron"; import path from "node:path"; import http from "node:http"; -import { spawn } from "node:child_process"; +import { spawn, type ChildProcess } from "node:child_process"; import started from "electron-squirrel-startup"; -import chokidar from "chokidar"; +import chokidar, { type FSWatcher } from "chokidar"; + +// Injected by the electron-forge Vite plugin at build time. +declare const MAIN_WINDOW_VITE_DEV_SERVER_URL: string | undefined; +declare const MAIN_WINDOW_VITE_NAME: string; + +interface PythonCommand { + cmd: string; + args: string[]; + cwd: string | undefined; +} if (started) { app.quit(); } -let pythonProcess = null; -let pythonWatcher = null; +let pythonProcess: ChildProcess | null = null; +let pythonWatcher: FSWatcher | undefined; -function getPythonCommand() { +function getPythonCommand(): PythonCommand { if (app.isPackaged) { const binaryPath = path.join(process.resourcesPath, "taskboard"); return { cmd: binaryPath, args: [], cwd: undefined }; @@ -24,8 +34,8 @@ function getPythonCommand() { } } -function waitForBackend(port, timeoutMs) { - return new Promise((resolve, reject) => { +function waitForBackend(port: number, timeoutMs: number): Promise { + return new Promise((resolve, reject) => { const start = Date.now(); const check = () => { const req = http.get(`http://127.0.0.1:${port}/api/health`, (res) => { @@ -54,13 +64,13 @@ function waitForBackend(port, timeoutMs) { }); } -function killPortSync(port) { +function killPortSync(port: number): void { // Best-effort: kill any process already holding the port before we spawn try { const { execSync } = require("node:child_process"); const out = execSync(`lsof -ti :${port}`, { encoding: "utf8" }).trim(); if (out) { - out.split("\n").forEach((pid) => { + out.split("\n").forEach((pid: string) => { try { process.kill(Number(pid), "SIGKILL"); } catch (_) {} @@ -74,14 +84,14 @@ function killPortSync(port) { // macOS apps launched from Finder/Dock inherit a minimal PATH (no Homebrew), // so the Python backend can't find tools like `node` (needed by the Weixin // bridge). Prepend the common install dirs so child processes resolve them. -function augmentedPath() { +function augmentedPath(): string { const extra = ["/opt/homebrew/bin", "/usr/local/bin", "/usr/bin", "/bin"]; const current = process.env.PATH || ""; const merged = [...extra, ...current.split(":")].filter(Boolean); return [...new Set(merged)].join(":"); } -function startPythonBackend() { +function startPythonBackend(): Promise { killPortSync(9712); const { cmd, args, cwd } = getPythonCommand(); pythonProcess = spawn(cmd, args, { @@ -103,7 +113,7 @@ function startPythonBackend() { return waitForBackend(9712, 15000); } -function stopPythonBackend() { +function stopPythonBackend(): void { if (!pythonProcess) return; const proc = pythonProcess; pythonProcess = null; @@ -114,7 +124,7 @@ function stopPythonBackend() { } } -function setupPythonHotReload() { +function setupPythonHotReload(): FSWatcher | undefined { if (app.isPackaged) return; // 生产环境不启用热重载 const projectRoot = path.resolve(path.join(app.getAppPath(), "..")); @@ -130,10 +140,10 @@ function setupPythonHotReload() { console.log("[Hot Reload] Watcher ready, monitoring:", projectRoot); }); - let restartTimeout = null; + let restartTimeout: NodeJS.Timeout | null = null; let isRestarting = false; // 重启锁 - const scheduleRestart = (filePath, eventType) => { + const scheduleRestart = (filePath: string, eventType: string) => { // Restart for .py/.toml files in the project root or in the channels/ directory. // Files in other subdirectories are ignored to avoid restarting when a running // task modifies files (e.g. README.md, todo.md in working directories). @@ -177,11 +187,11 @@ function setupPythonHotReload() { }, 500); // 500ms 延迟,避免文件保存时的多次触发 }; - watcher.on("change", (filePath) => scheduleRestart(filePath, "changed")); - watcher.on("add", (filePath) => scheduleRestart(filePath, "added")); - watcher.on("unlink", (filePath) => scheduleRestart(filePath, "removed")); + watcher.on("change", (filePath: string) => scheduleRestart(filePath, "changed")); + watcher.on("add", (filePath: string) => scheduleRestart(filePath, "added")); + watcher.on("unlink", (filePath: string) => scheduleRestart(filePath, "removed")); - watcher.on("error", (error) => { + watcher.on("error", (error: unknown) => { console.error("[Hot Reload] File watcher error:", error); }); diff --git a/taskboard-electron/src/renderer/App.tsx b/taskboard-electron/src/renderer/App.tsx index 31daae5..1c2291b 100644 --- a/taskboard-electron/src/renderer/App.tsx +++ b/taskboard-electron/src/renderer/App.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect, useCallback, useRef } from "react"; +import { useState, useEffect, useCallback, useRef, type CSSProperties } from "react"; import QRCode from "qrcode"; import { formatDateTimeLocalInput, @@ -6,19 +6,19 @@ import { formatTaskTime, parseTaskDateTime, serializeDateTimeLocalInput, -} from "./dateTime.mjs"; +} from "./dateTime.ts"; import { buildChannelsSavePayload, createInitialChannelsState, isWeixinQrImageSource, mergeChannelsStatus, -} from "./channelsSettings.mjs"; -import { buildExecutionSteps } from "./traceSteps.mjs"; +} from "./channelsSettings.ts"; +import { buildExecutionSteps } from "./traceSteps.ts"; const API = "http://127.0.0.1:9712/api"; // ─── Theme ─── -const THEMES = { +const THEMES: Record> = { dark: { bg: "#0a0a0f", surface: "#12121a", @@ -745,7 +745,7 @@ async function fetchSkillPatterns() { return res.json(); } -async function triggerSkillSweep(agent) { +async function triggerSkillSweep(agent?: string) { const res = await fetch(`${API}/skills/sweep`, { method: "POST", headers: await csrfHeaders(), @@ -756,7 +756,7 @@ async function triggerSkillSweep(agent) { return payload; } -async function triggerSkillDraft(id, agent) { +async function triggerSkillDraft(id, agent?: string) { const res = await fetch(`${API}/skill-patterns/${id}/draft`, { method: "POST", headers: await csrfHeaders(), @@ -1380,7 +1380,7 @@ function HeartbeatBadge({ enabled }) { ); } -function HeartbeatModal({ onClose, onSubmit, initialData, defaultAgent, mode = "create" }) { +function HeartbeatModal({ onClose, onSubmit, initialData, defaultAgent, mode = "create" }: any) { const savedDir = localStorage.getItem("agentforge_working_dir") || "~/papers"; const [form, setForm] = useState(() => ({ name: initialData?.name || "", @@ -1397,7 +1397,7 @@ function HeartbeatModal({ onClose, onSubmit, initialData, defaultAgent, mode = " const set = (k, v) => setForm((prev) => ({ ...prev, [k]: v })); - const inputStyle = { + const inputStyle: CSSProperties = { width: "100%", padding: "10px 14px", borderRadius: 8, @@ -1775,10 +1775,10 @@ function HeartbeatCard({ heartbeat, onAction, onViewDetail }) { } function HeartbeatDetailPanel({ heartbeat, ticks, onClose }) { - const [selectedTickId, setSelectedTickId] = useState(null); + const [selectedTickId, setSelectedTickId] = useState(null); const [tickOutput, setTickOutput] = useState(""); const [tickRunning, setTickRunning] = useState(false); - const outputRef = useRef(null); + const outputRef = useRef(null); useEffect(() => { setSelectedTickId(ticks[0]?.id || null); @@ -2166,10 +2166,10 @@ function NewTaskModal({ onClose, onSubmit, initialData, mode = "create" }) { const handleImageSelect = (e) => { const files = Array.from(e.target.files || []); - files.forEach((file) => { + files.forEach((file: any) => { const reader = new FileReader(); reader.onload = (ev) => { - const dataUrl = ev.target.result; // "data:image/jpeg;base64,..." + const dataUrl = ev.target.result as string; // "data:image/jpeg;base64,..." const [meta, data] = dataUrl.split(","); const media_type = meta.match(/:(.*?);/)?.[1] || "image/jpeg"; setPromptImages((prev) => [ @@ -2193,7 +2193,7 @@ function NewTaskModal({ onClose, onSubmit, initialData, mode = "create" }) { .filter((r) => r.task_id) .map((r) => ({ task_id: r.task_id, inject_result: r.inject_result })); - const data = { + const data: any = { ...form, title: form.title || form.prompt.slice(0, 60), delay_seconds: form.schedule_type === "delayed" ? parseInt(form.delay_seconds) || 60 : null, @@ -2219,7 +2219,7 @@ function NewTaskModal({ onClose, onSubmit, initialData, mode = "create" }) { onSubmit(data); }; - const inputStyle = { + const inputStyle: CSSProperties = { width: "100%", padding: "10px 14px", borderRadius: 8, @@ -2673,7 +2673,7 @@ function NewTaskModal({ onClose, onSubmit, initialData, mode = "create" }) { ); } -function DetailPanel({ task, onClose, onResume }) { +function DetailPanel({ task, onClose, onResume }: any) { // `task` is always truthy here — the only caller renders this inside // `{detail && }`. Hooks must stay // unconditional, so do not early-return before them. @@ -2681,14 +2681,14 @@ function DetailPanel({ task, onClose, onResume }) { const [resumeText, setResumeText] = useState(""); const [resumeError, setResumeError] = useState(""); const [resumeSent, setResumeSent] = useState(false); - const [messages, setMessages] = useState([]); - const [events, setEvents] = useState([]); + const [messages, setMessages] = useState([]); + const [events, setEvents] = useState([]); const [showMessages, setShowMessages] = useState(false); const [showEvents, setShowEvents] = useState(false); const [showLiveOutput, setShowLiveOutput] = useState(true); - const liveOutputRef = useRef(null); - const messagesRef = useRef(null); - const eventsRef = useRef(null); + const liveOutputRef = useRef(null); + const messagesRef = useRef(null); + const eventsRef = useRef(null); useEffect(() => { if (task.status !== "running") { @@ -3385,10 +3385,10 @@ function SettingsModal({ ...initialFeishu, }); const [feishuSaving, setFeishuSaving] = useState(false); - const [feishuMsg, setFeishuMsg] = useState(null); // {ok, text} + const [feishuMsg, setFeishuMsg] = useState(null); // {ok, text} const [channels, setChannels] = useState(createInitialChannelsState(initialChannelsStatus)); const [channelsSaving, setChannelsSaving] = useState(false); - const [channelsMsg, setChannelsMsg] = useState(null); + const [channelsMsg, setChannelsMsg] = useState(null); const [weixinQrSrc, setWeixinQrSrc] = useState(""); const [weixinActionBusy, setWeixinActionBusy] = useState(false); const [collapsedChannels, setCollapsedChannels] = useState({ @@ -3535,7 +3535,7 @@ function SettingsModal({ } }; - const fieldStyle = { + const fieldStyle: CSSProperties = { width: "100%", padding: "10px 14px", borderRadius: 8, @@ -5095,7 +5095,7 @@ function SkillPatternCard({ p, tasks, onDraft, onApprove, onDismiss }) { function SkillRegistryCard({ s, tasks, onToggle, onDelete }) { const [expanded, setExpanded] = useState(false); - const [content, setContent] = useState(null); + const [content, setContent] = useState(null); const [loading, setLoading] = useState(false); let sourceTaskIds = []; @@ -5392,32 +5392,32 @@ function SkillsView({ } export default function App() { - const [tasks, setTasks] = useState([]); - const [heartbeats, setHeartbeats] = useState([]); - const [heartbeatTicks, setHeartbeatTicks] = useState([]); + const [tasks, setTasks] = useState([]); + const [heartbeats, setHeartbeats] = useState([]); + const [heartbeatTicks, setHeartbeatTicks] = useState([]); const [skillData, setSkillData] = useState({ patterns: [], sweep: { running: false, last: null }, }); - const [skills, setSkills] = useState([]); + const [skills, setSkills] = useState([]); const [activeView, setActiveView] = useState("tasks"); const [showNew, setShowNew] = useState(false); const [showNewHeartbeat, setShowNewHeartbeat] = useState(false); const [showSettings, setShowSettings] = useState(false); - const [detail, setDetail] = useState(null); - const [heartbeatDetail, setHeartbeatDetail] = useState(null); + const [detail, setDetail] = useState(null); + const [heartbeatDetail, setHeartbeatDetail] = useState(null); const [connected, setConnected] = useState(false); const [filter, setFilter] = useState(""); const [taskTimeout, setTaskTimeout] = useState(DEFAULT_TIMEOUT_SECONDS); const [defaultAgent, setDefaultAgent] = useState(DEFAULT_AGENT); - const [feishuSettings, setFeishuSettings] = useState({}); - const [channelsStatus, setChannelsStatus] = useState({}); + const [feishuSettings, setFeishuSettings] = useState({}); + const [channelsStatus, setChannelsStatus] = useState({}); const [backendReady, setBackendReady] = useState(false); - const [backendError, setBackendError] = useState(null); - const [apiError, setApiError] = useState(null); - const [editingTask, setEditingTask] = useState(null); - const [forkingTask, setForkingTask] = useState(null); - const [editingHeartbeat, setEditingHeartbeat] = useState(null); + const [backendError, setBackendError] = useState(null); + const [apiError, setApiError] = useState(null); + const [editingTask, setEditingTask] = useState(null); + const [forkingTask, setForkingTask] = useState(null); + const [editingHeartbeat, setEditingHeartbeat] = useState(null); // ─── Color mode ─── const [colorMode, setColorMode] = useState(() => localStorage.getItem("colorMode") || "system"); diff --git a/taskboard-electron/src/renderer/channelsSettings.test.ts b/taskboard-electron/src/renderer/channelsSettings.test.ts index bfe6834..bc45dd2 100644 --- a/taskboard-electron/src/renderer/channelsSettings.test.ts +++ b/taskboard-electron/src/renderer/channelsSettings.test.ts @@ -1,17 +1,17 @@ -import test from "node:test"; -import assert from "node:assert/strict"; +import { test, expect } from "bun:test"; import { buildChannelsSavePayload, createInitialChannelsState, mergeChannelsStatus, isWeixinQrImageSource, -} from "./channelsSettings.mjs"; + type WeixinChannelState, +} from "./channelsSettings.ts"; test("createInitialChannelsState includes weixin defaults", () => { const state = createInitialChannelsState(); - assert.deepEqual(state.weixin, { + expect(state.weixin).toEqual({ enabled: false, configured: false, running: false, @@ -37,11 +37,11 @@ test("mergeChannelsStatus overlays weixin status onto existing state", () => { }, }); - assert.equal(merged.weixin.enabled, true); - assert.equal(merged.weixin.running, true); - assert.equal(merged.weixin.default_working_dir, "/tmp/repo"); - assert.equal(merged.weixin.base_url, "https://example.test"); - assert.equal(merged.weixin.account_id, "wx-demo"); + expect(merged.weixin.enabled).toBe(true); + expect(merged.weixin.running).toBe(true); + expect(merged.weixin.default_working_dir).toBe("/tmp/repo"); + expect(merged.weixin.base_url).toBe("https://example.test"); + expect(merged.weixin.account_id).toBe("wx-demo"); }); test("buildChannelsSavePayload serializes weixin settings for the API", () => { @@ -54,24 +54,23 @@ test("buildChannelsSavePayload serializes weixin settings for the API", () => { default_working_dir: "~/workspace/agentforge", base_url: "https://ilinkai.weixin.qq.com", account_id: "wx-primary", - }, + } as WeixinChannelState, }); - assert.equal(payload.weixin_enabled, "true"); - assert.equal(payload.weixin_default_working_dir, "~/workspace/agentforge"); - assert.equal(payload.weixin_base_url, "https://ilinkai.weixin.qq.com"); - assert.equal(payload.weixin_account_id, "wx-primary"); + expect(payload.weixin_enabled).toBe("true"); + expect(payload.weixin_default_working_dir).toBe("~/workspace/agentforge"); + expect(payload.weixin_base_url).toBe("https://ilinkai.weixin.qq.com"); + expect(payload.weixin_account_id).toBe("wx-primary"); }); test("isWeixinQrImageSource recognizes real image sources only", () => { - assert.equal(isWeixinQrImageSource("data:image/png;base64,abc"), true); - assert.equal(isWeixinQrImageSource("https://example.test/qr.png"), true); - assert.equal( + expect(isWeixinQrImageSource("data:image/png;base64,abc")).toBe(true); + expect(isWeixinQrImageSource("https://example.test/qr.png")).toBe(true); + expect( isWeixinQrImageSource( "https://liteapp.weixin.qq.com/q/7GiQu1?qrcode=7a9bf9b71b5bc24cac576b5098adb5b4&b", ), - false, - ); - assert.equal(isWeixinQrImageSource("otpauth://totp/example"), false); - assert.equal(isWeixinQrImageSource("wxp://some-qr-payload"), false); + ).toBe(false); + expect(isWeixinQrImageSource("otpauth://totp/example")).toBe(false); + expect(isWeixinQrImageSource("wxp://some-qr-payload")).toBe(false); }); diff --git a/taskboard-electron/src/renderer/channelsSettings.ts b/taskboard-electron/src/renderer/channelsSettings.ts index a9de1ed..2605580 100644 --- a/taskboard-electron/src/renderer/channelsSettings.ts +++ b/taskboard-electron/src/renderer/channelsSettings.ts @@ -1,4 +1,68 @@ -const DEFAULT_CHANNELS_STATE = { +export interface TelegramChannelState { + enabled: boolean; + configured: boolean; + running: boolean; + default_working_dir: string; + default_chat_id: string; + bot_token: string; + allowed_users: string; +} + +export interface SlackChannelState { + enabled: boolean; + configured: boolean; + running: boolean; + default_working_dir: string; + default_channel: string; + default_user: string; + bot_token: string; + app_token: string; +} + +export interface WeixinChannelState { + enabled: boolean; + configured: boolean; + running: boolean; + default_working_dir: string; + base_url: string; + account_id: string; + login_status: string; + qr_code_url: string; + last_error: string; + user_id: string; +} + +export interface ChannelsState { + telegram: TelegramChannelState; + slack: SlackChannelState; + weixin: WeixinChannelState; +} + +export interface ChannelsStatusUpdate { + telegram?: Partial; + slack?: Partial; + weixin?: Partial; +} + +export interface ChannelsSavePayload { + telegram_enabled: string; + telegram_bot_token: string; + telegram_allowed_users: string; + telegram_default_working_dir: string; + telegram_default_chat_id: string; + slack_enabled: string; + slack_bot_token: string; + slack_app_token: string; + slack_default_working_dir: string; + slack_default_channel: string; + slack_default_user: string; + weixin_enabled: string; + weixin_default_working_dir: string; + weixin_base_url: string; + weixin_account_id: string; +} + +const DEFAULT_CHANNELS_STATE: ChannelsState = { telegram: { enabled: false, configured: false, @@ -32,7 +96,7 @@ const DEFAULT_CHANNELS_STATE = { }, }; -function cloneState(state) { +function cloneState(state: ChannelsState): ChannelsState { return { telegram: { ...state.telegram }, slack: { ...state.slack }, @@ -40,12 +104,15 @@ function cloneState(state) { }; } -export function createInitialChannelsState(initial = {}) { +export function createInitialChannelsState(initial: ChannelsStatusUpdate = {}): ChannelsState { const base = cloneState(DEFAULT_CHANNELS_STATE); return mergeChannelsStatus(base, initial); } -export function mergeChannelsStatus(current, status = {}) { +export function mergeChannelsStatus( + current: ChannelsState, + status: ChannelsStatusUpdate = {}, +): ChannelsState { return { telegram: { ...current.telegram, ...(status.telegram || {}) }, slack: { ...current.slack, ...(status.slack || {}) }, @@ -53,7 +120,7 @@ export function mergeChannelsStatus(current, status = {}) { }; } -export function buildChannelsSavePayload(channels) { +export function buildChannelsSavePayload(channels: ChannelsState): ChannelsSavePayload { return { telegram_enabled: channels.telegram.enabled ? "true" : "false", telegram_bot_token: channels.telegram.bot_token, @@ -73,7 +140,7 @@ export function buildChannelsSavePayload(channels) { }; } -export function isWeixinQrImageSource(value) { +export function isWeixinQrImageSource(value: string | null | undefined): boolean { const normalized = (value || "").trim(); if (!normalized) return false; if (normalized.startsWith("data:image/")) return true; diff --git a/taskboard-electron/src/renderer/dateTime.test.ts b/taskboard-electron/src/renderer/dateTime.test.ts index 264e1b2..170fc34 100644 --- a/taskboard-electron/src/renderer/dateTime.test.ts +++ b/taskboard-electron/src/renderer/dateTime.test.ts @@ -1,26 +1,25 @@ -import test from "node:test"; -import assert from "node:assert/strict"; +import { test, expect } from "bun:test"; import { formatDateTimeLocalInput, parseTaskDateTime, serializeDateTimeLocalInput, -} from "./dateTime.mjs"; +} from "./dateTime.ts"; test("parseTaskDateTime keeps naive timestamps in local wall time", () => { const parsed = parseTaskDateTime("2026-03-19T18:04:00"); - assert.equal(parsed.getFullYear(), 2026); - assert.equal(parsed.getMonth(), 2); - assert.equal(parsed.getDate(), 19); - assert.equal(parsed.getHours(), 18); - assert.equal(parsed.getMinutes(), 4); + expect(parsed.getFullYear()).toBe(2026); + expect(parsed.getMonth()).toBe(2); + expect(parsed.getDate()).toBe(19); + expect(parsed.getHours()).toBe(18); + expect(parsed.getMinutes()).toBe(4); }); test("formatDateTimeLocalInput converts aware timestamps into local datetime-local values", () => { - assert.equal(formatDateTimeLocalInput("2026-03-19T10:04:00+00:00"), "2026-03-19T18:04"); + expect(formatDateTimeLocalInput("2026-03-19T10:04:00+00:00")).toBe("2026-03-19T18:04"); }); test("serializeDateTimeLocalInput preserves local wall time without forcing UTC", () => { - assert.equal(serializeDateTimeLocalInput("2026-03-19T18:04"), "2026-03-19T18:04:00"); + expect(serializeDateTimeLocalInput("2026-03-19T18:04")).toBe("2026-03-19T18:04:00"); }); diff --git a/taskboard-electron/src/renderer/dateTime.ts b/taskboard-electron/src/renderer/dateTime.ts index b71758f..03752d6 100644 --- a/taskboard-electron/src/renderer/dateTime.ts +++ b/taskboard-electron/src/renderer/dateTime.ts @@ -1,12 +1,21 @@ -function pad(value) { +interface LocalDateTimeParts { + year: number; + month: number; + day: number; + hour: number; + minute: number; + second: number; +} + +function pad(value: number | string): string { return String(value).padStart(2, "0"); } -function hasExplicitTimezone(value) { +function hasExplicitTimezone(value: string): boolean { return /(?:Z|[+-]\d{2}:\d{2})$/i.test(value); } -function parseLocalDateTimeParts(value) { +function parseLocalDateTimeParts(value: unknown): LocalDateTimeParts | null { const match = String(value) .trim() .match(/^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2})(?::(\d{2})(?:\.\d+)?)?$/); @@ -22,7 +31,7 @@ function parseLocalDateTimeParts(value) { }; } -export function parseTaskDateTime(value) { +export function parseTaskDateTime(value: unknown): Date | null { if (!value) return null; const raw = String(value).trim(); if (!raw) return null; @@ -49,17 +58,17 @@ export function parseTaskDateTime(value) { return Number.isNaN(fallback.getTime()) ? null : fallback; } -export function formatTaskDateTime(value, options) { +export function formatTaskDateTime(value: unknown, options?: Intl.DateTimeFormatOptions): string { const date = parseTaskDateTime(value); return date ? date.toLocaleString(undefined, options) : ""; } -export function formatTaskTime(value, options) { +export function formatTaskTime(value: unknown, options?: Intl.DateTimeFormatOptions): string { const date = parseTaskDateTime(value); return date ? date.toLocaleTimeString(undefined, options) : ""; } -export function formatDateTimeLocalInput(value) { +export function formatDateTimeLocalInput(value: unknown): string { const date = parseTaskDateTime(value); if (!date) return ""; return [ @@ -75,7 +84,7 @@ export function formatDateTimeLocalInput(value) { ].join(""); } -export function serializeDateTimeLocalInput(value) { +export function serializeDateTimeLocalInput(value: unknown): string | null { const parts = parseLocalDateTimeParts(value); if (!parts) return null; return [ diff --git a/taskboard-electron/src/renderer/main.tsx b/taskboard-electron/src/renderer/main.tsx index 637e43b..16986ae 100644 --- a/taskboard-electron/src/renderer/main.tsx +++ b/taskboard-electron/src/renderer/main.tsx @@ -1,6 +1,6 @@ import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; -import App from "./App.jsx"; +import App from "./App.tsx"; createRoot(document.getElementById("root")).render( diff --git a/taskboard-electron/src/renderer/traceSteps.test.ts b/taskboard-electron/src/renderer/traceSteps.test.ts index ea90874..c9574bd 100644 --- a/taskboard-electron/src/renderer/traceSteps.test.ts +++ b/taskboard-electron/src/renderer/traceSteps.test.ts @@ -1,7 +1,6 @@ -import test from "node:test"; -import assert from "node:assert/strict"; +import { test, expect } from "bun:test"; -import { buildExecutionSteps } from "./traceSteps.mjs"; +import { buildExecutionSteps } from "./traceSteps.ts"; test("buildExecutionSteps sorts events oldest first and merges adjacent thinking chunks", () => { const steps = buildExecutionSteps([ @@ -25,12 +24,12 @@ test("buildExecutionSteps sorts events oldest first and merges adjacent thinking }, ]); - assert.equal(steps.length, 2); - assert.equal(steps[0].type, "thinking"); - assert.equal(steps[0].title, "Reading context"); - assert.equal(steps[0].detail, "Reading context"); - assert.equal(steps[1].type, "tool_call"); - assert.equal(steps[1].title, "Call tool: Bash"); + expect(steps.length).toBe(2); + expect(steps[0].type).toBe("thinking"); + expect(steps[0].title).toBe("Reading context"); + expect(steps[0].detail).toBe("Reading context"); + expect(steps[1].type).toBe("tool_call"); + expect(steps[1].title).toBe("Call tool: Bash"); }); test("buildExecutionSteps formats command execution details", () => { @@ -48,17 +47,14 @@ test("buildExecutionSteps formats command execution details", () => { }, ]); - assert.equal(steps.length, 1); - assert.equal(steps[0].title, "Run command: npm test"); - assert.deepEqual( - steps[0].rows.map((row) => [row.label, row.value]), - [ - ["Command", "npm test"], - ["Output", "12 passed"], - ["Exit", "0"], - ["Status", "completed"], - ], - ); + expect(steps.length).toBe(1); + expect(steps[0].title).toBe("Run command: npm test"); + expect(steps[0].rows.map((row) => [row.label, row.value])).toEqual([ + ["Command", "npm test"], + ["Output", "12 passed"], + ["Exit", "0"], + ["Status", "completed"], + ]); }); test("buildExecutionSteps keeps tool result errors readable", () => { @@ -75,11 +71,11 @@ test("buildExecutionSteps keeps tool result errors readable", () => { }, ]); - assert.equal(steps.length, 1); - assert.equal(steps[0].type, "tool_result"); - assert.equal(steps[0].title, "Tool error: toolu_1"); - assert.equal(steps[0].rows[0].label, "Tool Error"); - assert.equal(steps[0].rows[1].value, "permission denied"); + expect(steps.length).toBe(1); + expect(steps[0].type).toBe("tool_result"); + expect(steps[0].title).toBe("Tool error: toolu_1"); + expect(steps[0].rows[0].label).toBe("Tool Error"); + expect(steps[0].rows[1].value).toBe("permission denied"); }); test("buildExecutionSteps summarizes generated image events", () => { @@ -95,16 +91,13 @@ test("buildExecutionSteps summarizes generated image events", () => { }, ]); - assert.equal(steps.length, 1); - assert.equal(steps[0].type, "generated_image"); - assert.equal(steps[0].title, "Generated image: result.png"); - assert.deepEqual( - steps[0].rows.map((row) => [row.label, row.value]), - [ - ["Path", "/Users/example/.codex/generated_images/thread/result.png"], - ["Media", "image/png"], - ], - ); + expect(steps.length).toBe(1); + expect(steps[0].type).toBe("generated_image"); + expect(steps[0].title).toBe("Generated image: result.png"); + expect(steps[0].rows.map((row) => [row.label, row.value])).toEqual([ + ["Path", "/Users/example/.codex/generated_images/thread/result.png"], + ["Media", "image/png"], + ]); }); test("buildExecutionSteps preserves renderable image_content previews", () => { @@ -120,12 +113,9 @@ test("buildExecutionSteps preserves renderable image_content previews", () => { }, ]); - assert.equal(steps.length, 1); - assert.equal(steps[0].type, "image_content"); - assert.equal(steps[0].title, "Image output"); - assert.equal(steps[0].imageSrc, "data:image/png;base64,aW1hZ2U="); - assert.deepEqual( - steps[0].rows.map((row) => [row.label, row.value]), - [["Media", "image/png"]], - ); + expect(steps.length).toBe(1); + expect(steps[0].type).toBe("image_content"); + expect(steps[0].title).toBe("Image output"); + expect(steps[0].imageSrc).toBe("data:image/png;base64,aW1hZ2U="); + expect(steps[0].rows.map((row) => [row.label, row.value])).toEqual([["Media", "image/png"]]); }); diff --git a/taskboard-electron/src/renderer/traceSteps.ts b/taskboard-electron/src/renderer/traceSteps.ts index 8f63af1..7b6590d 100644 --- a/taskboard-electron/src/renderer/traceSteps.ts +++ b/taskboard-electron/src/renderer/traceSteps.ts @@ -8,16 +8,45 @@ export const TRACE_EVENT_TYPES = new Set([ const THINKING_PREFIX = "[thinking] "; -function compact(rows) { - return rows.filter(Boolean); +export interface TraceRow { + label: string; + value: string; } -function row(label, value) { +export type TracePayload = Record; + +export interface TraceEventInput { + id?: number; + event_type?: string; + type?: string; + content?: string; + timestamp?: string; +} + +export interface ExecutionStep { + id: string; + eventIds: number[]; + rawEventType: string; + timestamp: string; + rows: TraceRow[]; + detail: string; + count: number; + type: string; + title: string; + imageSrc?: string; + number?: number; +} + +function compact(rows: Array): TraceRow[] { + return rows.filter(Boolean) as TraceRow[]; +} + +function row(label: string, value: unknown): TraceRow | null { const formatted = formatTraceValue(value); return formatted === "" ? null : { label, value: formatted }; } -export function parseTracePayload(content) { +export function parseTracePayload(content: string): TracePayload | null { try { const payload = JSON.parse(content); return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : null; @@ -26,13 +55,17 @@ export function parseTracePayload(content) { } } -export function formatTraceValue(value) { +export function formatTraceValue(value: unknown): string { if (value === undefined || value === null) return ""; if (typeof value === "string") return value; return JSON.stringify(value, null, 2); } -export function buildTraceRows(eventType, payload, rawContent = "") { +export function buildTraceRows( + eventType: string, + payload: TracePayload, + rawContent = "", +): TraceRow[] { if (eventType === "tool_call") { const name = payload.server ? `${payload.server}.${payload.name || payload.tool || "unknown"}` @@ -65,7 +98,7 @@ export function buildTraceRows(eventType, payload, rawContent = "") { if (eventType === "file_change") { const changes = Array.isArray(payload.changes) ? payload.changes - .map((change) => { + .map((change: any) => { if (!change || typeof change !== "object") return formatTraceValue(change); const kind = change.kind || change.type || "changed"; const path = change.path || change.file || ""; @@ -87,9 +120,9 @@ export function buildTraceRows(eventType, payload, rawContent = "") { return [{ label: eventType, value: rawContent }]; } -export function buildExecutionSteps(events) { +export function buildExecutionSteps(events: TraceEventInput[] | null | undefined): ExecutionStep[] { const sortedEvents = [...(events || [])].sort(compareEventsChronologically); - const steps = []; + const steps: ExecutionStep[] = []; for (const event of sortedEvents) { const step = eventToStep(event); @@ -114,13 +147,13 @@ export function buildExecutionSteps(events) { })); } -function compareEventsChronologically(a, b) { +function compareEventsChronologically(a: TraceEventInput, b: TraceEventInput): number { const timestampComparison = String(a.timestamp || "").localeCompare(String(b.timestamp || "")); if (timestampComparison !== 0) return timestampComparison; return Number(a.id || 0) - Number(b.id || 0); } -function eventToStep(event) { +function eventToStep(event: TraceEventInput): ExecutionStep | null { const eventType = event.event_type || event.type || "unknown"; const content = event.content || ""; const base = { @@ -128,7 +161,7 @@ function eventToStep(event) { eventIds: event.id ? [event.id] : [], rawEventType: eventType, timestamp: event.timestamp || "", - rows: [], + rows: [] as TraceRow[], detail: content, count: 1, }; @@ -219,7 +252,7 @@ function eventToStep(event) { }; } -function titleForTraceEvent(eventType, payload) { +function titleForTraceEvent(eventType: string, payload: TracePayload): string { if (eventType === "tool_call") { const name = payload.server ? `${payload.server}.${payload.name || payload.tool || "unknown"}` @@ -243,7 +276,7 @@ function titleForTraceEvent(eventType, payload) { if (eventType === "file_change") { const changes = Array.isArray(payload.changes) ? payload.changes : []; const firstPath = changes.find( - (change) => change && typeof change === "object" && (change.path || change.file), + (change: any) => change && typeof change === "object" && (change.path || change.file), ); return firstPath ? `Change file: ${firstPath.path || firstPath.file}` : "Change files"; } @@ -251,16 +284,16 @@ function titleForTraceEvent(eventType, payload) { return eventType; } -function canMergeSteps(previous, next) { - return ( +function canMergeSteps(previous: ExecutionStep | undefined, next: ExecutionStep): boolean { + return Boolean( previous && previous.type === next.type && (next.type === "thinking" || next.type === "assistant") && - previous.rawEventType === next.rawEventType + previous.rawEventType === next.rawEventType, ); } -function appendDetail(previous, next) { +function appendDetail(previous: string, next: string): string { if (!previous) return next || ""; if (!next) return previous; if ( @@ -274,7 +307,7 @@ function appendDetail(previous, next) { return `${previous}\n${next}`; } -function summarizeTitle(text, prefix = "") { +function summarizeTitle(text: unknown, prefix = ""): string { const normalized = String(text || "") .replace(/\s+/g, " ") .trim(); @@ -283,7 +316,7 @@ function summarizeTitle(text, prefix = "") { return prefix ? `${prefix}: ${title}` : title; } -function basename(value) { +function basename(value: unknown): string { const parts = String(value || "") .split(/[\\/]/) .filter(Boolean); diff --git a/taskboard-electron/src/renderer/types.ts b/taskboard-electron/src/renderer/types.ts new file mode 100644 index 0000000..9a04328 --- /dev/null +++ b/taskboard-electron/src/renderer/types.ts @@ -0,0 +1,88 @@ +// Shared types for the renderer: backend REST payloads (snake_case JSON from +// taskboard.py) and the Electron context-bridge surface. + +export type TaskStatus = + | "pending" + | "scheduled" + | "blocked" + | "running" + | "completed" + | "failed" + | "cancelled"; + +export type ScheduleType = "immediate" | "delayed" | "scheduled_at" | "cron"; + +export interface Task { + id: number; + title: string; + prompt: string; + working_dir: string; + status: TaskStatus | string; + schedule_type: ScheduleType | string; + cron_expr: string | null; + delay_seconds: number | null; + next_run_at: string | null; + last_run_at: string | null; + result: string | null; + error: string | null; + run_count: number; + max_runs: number | null; + created_at: string; + updated_at: string; + tags: string; + agent: string; + question: string | null; + answer: string | null; +} + +export interface TaskRun { + id: number; + task_id: number; + started_at: string; + finished_at: string | null; + status: string | null; + result: string | null; + error: string | null; + raw_output?: string | null; +} + +export interface TaskOutputEvent { + id: number; + task_id: number; + run_id: number; + event_type: string; + content: string; + timestamp: string; +} + +export interface Heartbeat { + id: number; + name: string; + enabled: number | boolean; + working_dir: string; + schedule_type: string; + cron_expr: string | null; + interval_seconds: number | null; + check_prompt: string; + action_prompt_template: string; + default_agent: string; + cooldown_seconds: number; + next_run_at: string | null; + last_tick_at: string | null; + last_decision: string | null; + last_error: string | null; + last_triggered_at: string | null; + last_dedupe_key: string | null; + created_at: string; + updated_at: string; +} + +export interface ElectronAPI { + selectDirectory: () => Promise; +} + +declare global { + interface Window { + electronAPI?: ElectronAPI; + } +} diff --git a/taskboard-electron/src/vite-env.d.ts b/taskboard-electron/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/taskboard-electron/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/taskboard-electron/tsconfig.json b/taskboard-electron/tsconfig.json new file mode 100644 index 0000000..29bf262 --- /dev/null +++ b/taskboard-electron/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "bundler", + "lib": ["ESNext", "DOM", "DOM.Iterable"], + "jsx": "react-jsx", + "strict": false, + "noImplicitAny": false, + "skipLibCheck": true, + "noEmit": true, + "allowImportingTsExtensions": true, + "esModuleInterop": true, + "isolatedModules": true, + "types": ["bun"] + }, + "include": ["src/renderer.ts", "src/renderer/**/*", "src/vite-env.d.ts"] +} diff --git a/taskboard-electron/tsconfig.node.json b/taskboard-electron/tsconfig.node.json new file mode 100644 index 0000000..9e6b863 --- /dev/null +++ b/taskboard-electron/tsconfig.node.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "ESNext", + "module": "ESNext", + "moduleResolution": "bundler", + "lib": ["ESNext"], + "strict": false, + "noImplicitAny": false, + "skipLibCheck": true, + "noEmit": true, + "allowImportingTsExtensions": true, + "esModuleInterop": true, + "types": ["node"] + }, + "include": ["src/main.ts", "src/preload.ts"] +} From 62b1adc167b7c4f1f871553d2dd257607b585e38 Mon Sep 17 00:00:00 2001 From: taohe Date: Sat, 13 Jun 2026 01:05:55 +0800 Subject: [PATCH 05/18] feat(backend): port TaskDB to bun:sqlite with full test suite Co-Authored-By: Claude Fable 5 --- backend/src/db.ts | 1362 ++++++++++++++++++++++++++++++++++ backend/tests/taskdb.test.ts | 326 ++++++++ 2 files changed, 1688 insertions(+) create mode 100644 backend/src/db.ts create mode 100644 backend/tests/taskdb.test.ts diff --git a/backend/src/db.ts b/backend/src/db.ts new file mode 100644 index 0000000..1f3324e --- /dev/null +++ b/backend/src/db.ts @@ -0,0 +1,1362 @@ +// TaskDB: SQLite persistence layer, ported from taskboard.py (class TaskDB). +// Method names, SQL, column names and defaults intentionally mirror the Python +// source. Bun is single-threaded, so Python's RLock has no TS equivalent. + +import { Database } from "bun:sqlite"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import { CronExpressionParser } from "cron-parser"; +import { logger } from "./log.ts"; +import { + dateToLocalIso, + normalizeDatetimeForStorage, + nowIso, + parseComparableDatetime, +} from "./util.ts"; +import { HeartbeatScheduleType, type Heartbeat, type Task } from "./types.ts"; + +type Row = Record; + +function expandUser(p: string): string { + return p.startsWith("~") ? path.join(os.homedir(), p.slice(1)) : p; +} + +export class TaskDB { + db_path: string; + conn: Database; + + constructor(db_path: string = "~/.agentforge/tasks.db") { + this.db_path = expandUser(db_path); + fs.mkdirSync(path.dirname(this.db_path), { recursive: true }); + this.conn = new Database(this.db_path, { create: true }); + this._init_db(); + } + + /** Run a migration statement, ignoring "column already exists" errors. */ + private _migrate(sql: string): void { + try { + this.conn.run(sql); + } catch { + // Column already exists + } + } + + private _init_db(): void { + this.conn.run(` + CREATE TABLE IF NOT EXISTS tasks ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + title TEXT NOT NULL, + prompt TEXT NOT NULL, + working_dir TEXT DEFAULT '.', + status TEXT DEFAULT 'pending', + schedule_type TEXT DEFAULT 'immediate', + cron_expr TEXT, + delay_seconds INTEGER, + next_run_at TEXT, + last_run_at TEXT, + result TEXT, + error TEXT, + run_count INTEGER DEFAULT 0, + max_runs INTEGER, + created_at TEXT DEFAULT (datetime('now')), + updated_at TEXT DEFAULT (datetime('now')), + tags TEXT DEFAULT '', + agent TEXT DEFAULT 'codex', + question TEXT, + answer TEXT + ) + `); + // Migrations for existing DBs (each is a no-op when the column exists) + this._migrate("ALTER TABLE tasks ADD COLUMN agent TEXT DEFAULT 'codex'"); + // question/answer share one try block, mirroring Python: if `question` + // already exists the `answer` migration is skipped in the same way. + try { + this.conn.run("ALTER TABLE tasks ADD COLUMN question TEXT"); + this.conn.run("ALTER TABLE tasks ADD COLUMN answer TEXT"); + } catch { + // Columns already exist + } + this._migrate("ALTER TABLE tasks ADD COLUMN session_id TEXT"); + this._migrate("ALTER TABLE tasks ADD COLUMN prompt_images TEXT DEFAULT '[]'"); + this._migrate("ALTER TABLE tasks ADD COLUMN image_paths TEXT DEFAULT '[]'"); + this._migrate("ALTER TABLE tasks ADD COLUMN notify_slack_channel TEXT"); + this._migrate("ALTER TABLE tasks ADD COLUMN notify_telegram_chat_id TEXT"); + + this.conn.run(` + CREATE TABLE IF NOT EXISTS settings ( + key TEXT PRIMARY KEY, + value TEXT + ) + `); + this.conn.run(` + CREATE TABLE IF NOT EXISTS task_runs ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + task_id INTEGER NOT NULL, + started_at TEXT DEFAULT (datetime('now')), + finished_at TEXT, + status TEXT, + result TEXT, + error TEXT, + raw_output TEXT, + FOREIGN KEY (task_id) REFERENCES tasks(id) + ) + `); + this._migrate("ALTER TABLE task_runs ADD COLUMN raw_output TEXT"); + + this.conn.run(` + CREATE TABLE IF NOT EXISTS heartbeats ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + enabled INTEGER NOT NULL DEFAULT 1, + working_dir TEXT DEFAULT '.', + schedule_type TEXT NOT NULL, + cron_expr TEXT, + interval_seconds INTEGER, + check_prompt TEXT NOT NULL, + action_prompt_template TEXT DEFAULT '', + default_agent TEXT DEFAULT 'codex', + cooldown_seconds INTEGER DEFAULT 0, + next_run_at TEXT, + last_tick_at TEXT, + last_decision TEXT, + last_error TEXT, + last_triggered_at TEXT, + last_dedupe_key TEXT, + created_at TEXT DEFAULT (datetime('now')), + updated_at TEXT DEFAULT (datetime('now')) + ) + `); + this.conn.run(` + CREATE INDEX IF NOT EXISTS idx_heartbeats_next_run + ON heartbeats(enabled, next_run_at) + `); + this.conn.run(` + CREATE TABLE IF NOT EXISTS heartbeat_ticks ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + heartbeat_id INTEGER NOT NULL, + started_at TEXT NOT NULL, + finished_at TEXT, + status TEXT NOT NULL, + decision_type TEXT, + decision_payload TEXT, + task_id INTEGER, + raw_output TEXT, + error TEXT, + FOREIGN KEY (heartbeat_id) REFERENCES heartbeats(id), + FOREIGN KEY (task_id) REFERENCES tasks(id) + ) + `); + this.conn.run(` + CREATE INDEX IF NOT EXISTS idx_heartbeat_ticks_heartbeat_id + ON heartbeat_ticks(heartbeat_id, started_at DESC) + `); + this._migrate("ALTER TABLE heartbeat_ticks ADD COLUMN raw_output TEXT"); + this.conn.run(` + CREATE TABLE IF NOT EXISTS heartbeat_dedup ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + heartbeat_id INTEGER NOT NULL, + dedupe_key TEXT NOT NULL, + task_id INTEGER, + triggered_at TEXT NOT NULL, + FOREIGN KEY (heartbeat_id) REFERENCES heartbeats(id), + FOREIGN KEY (task_id) REFERENCES tasks(id), + UNIQUE(heartbeat_id, dedupe_key) + ) + `); + this.conn.run(` + CREATE INDEX IF NOT EXISTS idx_heartbeat_dedup_heartbeat_id + ON heartbeat_dedup(heartbeat_id, triggered_at DESC) + `); + + // Structured output recording + this.conn.run(` + CREATE TABLE IF NOT EXISTS task_output_events ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + task_id INTEGER NOT NULL, + run_id INTEGER NOT NULL, + event_type TEXT NOT NULL, + content TEXT NOT NULL, + timestamp TEXT DEFAULT (datetime('now')), + FOREIGN KEY (task_id) REFERENCES tasks(id), + FOREIGN KEY (run_id) REFERENCES task_runs(id) + ) + `); + this.conn.run(` + CREATE INDEX IF NOT EXISTS idx_task_output_events_task_id + ON task_output_events(task_id) + `); + this.conn.run(` + CREATE INDEX IF NOT EXISTS idx_task_output_events_run_id + ON task_output_events(run_id) + `); + this.conn.run(` + CREATE INDEX IF NOT EXISTS idx_task_output_events_timestamp + ON task_output_events(timestamp) + `); + + // DAG dependency table + this.conn.run(` + CREATE TABLE IF NOT EXISTS task_dependencies ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + task_id INTEGER NOT NULL, + depends_on_task_id INTEGER NOT NULL, + inject_result INTEGER DEFAULT 0, + created_at TEXT DEFAULT (datetime('now')), + FOREIGN KEY (task_id) REFERENCES tasks(id), + FOREIGN KEY (depends_on_task_id) REFERENCES tasks(id), + UNIQUE(task_id, depends_on_task_id) + ) + `); + this.conn.run(` + CREATE INDEX IF NOT EXISTS idx_task_deps_task_id + ON task_dependencies(task_id) + `); + this.conn.run(` + CREATE INDEX IF NOT EXISTS idx_task_deps_depends_on + ON task_dependencies(depends_on_task_id) + `); + + // Skill Library: cross-run pattern ledger. The sweep agent tallies + // recurring task patterns here (dedup by semantic pattern_key); once a + // pattern crosses the recurrence threshold it becomes a skill candidate. + this.conn.run(` + CREATE TABLE IF NOT EXISTS skill_patterns ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + pattern_key TEXT NOT NULL UNIQUE, + kind TEXT NOT NULL DEFAULT 'recipe', + summary TEXT NOT NULL DEFAULT '', + recurrence_count INTEGER NOT NULL DEFAULT 1, + first_seen TEXT DEFAULT (datetime('now')), + last_seen TEXT DEFAULT (datetime('now')), + contributing_task_ids TEXT NOT NULL DEFAULT '[]', + contributing_run_ids TEXT NOT NULL DEFAULT '[]', + status TEXT NOT NULL DEFAULT 'tracking', + promoted_skill_id INTEGER, + created_at TEXT DEFAULT (datetime('now')), + updated_at TEXT DEFAULT (datetime('now')) + ) + `); + this.conn.run(` + CREATE INDEX IF NOT EXISTS idx_skill_patterns_status + ON skill_patterns(status, recurrence_count DESC) + `); + // Migration: per-run idempotency ledger so a run is only ever counted + // once (lets the manual sweep re-scan recent runs without inflating counts). + this._migrate( + "ALTER TABLE skill_patterns ADD COLUMN contributing_run_ids TEXT NOT NULL DEFAULT '[]'", + ); + // Backfill run-id sets for pre-existing patterns from their tasks' completed + // runs, so a re-scan dedups against real run ids instead of re-counting them. + try { + const legacy = this.conn + .query( + "SELECT id, contributing_task_ids FROM skill_patterns " + + "WHERE contributing_run_ids IN ('[]', '') OR contributing_run_ids IS NULL", + ) + .all() as Row[]; + for (const row of legacy) { + let tids: any[]; + try { + const parsed = JSON.parse(row["contributing_task_ids"]); + tids = Array.isArray(parsed) ? parsed : []; + } catch { + tids = []; + } + if (!tids.length) continue; + const placeholders = tids.map(() => "?").join(","); + const runRows = this.conn + .query( + `SELECT id FROM task_runs WHERE status = 'completed' AND task_id IN (${placeholders})`, + ) + .all(...tids) as Row[]; + const run_ids = runRows.map((r) => r["id"]); + if (run_ids.length) { + this.conn + .query("UPDATE skill_patterns SET contributing_run_ids = ? WHERE id = ?") + .run(JSON.stringify(run_ids), row["id"]); + } + } + } catch { + // table shape predates the run-id ledger; ignore + } + + // Skill Library: registry of distilled, approved skills. The canonical + // SKILL.md lives at `path` (~/.claude/skills//SKILL.md) and is + // symlinked into ~/.agents/skills for codex. `enabled` toggles whether + // the symlinks exist (i.e. whether agents load it). + this.conn.run(` + CREATE TABLE IF NOT EXISTS skills ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL UNIQUE, + description TEXT NOT NULL DEFAULT '', + path TEXT NOT NULL, + source_pattern_key TEXT, + source_task_ids TEXT, + kind TEXT, + enabled INTEGER NOT NULL DEFAULT 1, + created_at TEXT DEFAULT (datetime('now')) + ) + `); + // Skill Library: one pending draft per candidate pattern (agent-distilled + // SKILL.md awaiting human review/approval). + this.conn.run(` + CREATE TABLE IF NOT EXISTS skill_drafts ( + pattern_id INTEGER PRIMARY KEY, + name TEXT DEFAULT '', + description TEXT DEFAULT '', + kind TEXT DEFAULT 'recipe', + body TEXT DEFAULT '', + status TEXT NOT NULL DEFAULT 'drafting', + error TEXT, + worthy INTEGER, + worthiness_reason TEXT DEFAULT '', + updated_at TEXT DEFAULT (datetime('now')), + FOREIGN KEY (pattern_id) REFERENCES skill_patterns(id) + ) + `); + // Migration: add skill-creator worthiness judgment to existing draft tables + for (const [col, decl] of [ + ["worthy", "INTEGER"], + ["worthiness_reason", "TEXT DEFAULT ''"], + ] as const) { + this._migrate(`ALTER TABLE skill_drafts ADD COLUMN ${col} ${decl}`); + } + + this._migrate("ALTER TABLE tasks ADD COLUMN dag_id TEXT"); + // Migration: add feishu_root_msg_id column for post-restart resume + this._migrate("ALTER TABLE tasks ADD COLUMN feishu_root_msg_id TEXT"); + + // On startup, reset any tasks left in 'running' state — they were + // interrupted by a process kill (e.g. hot reload) and will never + // self-transition to completed/failed without this reset. + const now = nowIso(); + this.conn + .query( + ` + UPDATE tasks + SET status = 'failed', + error = 'Interrupted: process was restarted while task was running', + updated_at = ? + WHERE status = 'running' + `, + ) + .run(now); + // Also close out any open task_runs rows that have no finished_at + this.conn + .query( + ` + UPDATE task_runs + SET status = 'failed', + finished_at = ?, + error = 'Interrupted: process was restarted while task was running' + WHERE finished_at IS NULL + `, + ) + .run(now); + } + + /** + * Run statements in an explicit transaction. + * + * On success the transaction is committed; on any exception it is rolled + * back and the exception re-raised. Callers must NOT issue COMMIT or + * ROLLBACK themselves inside the callback. + */ + transaction(fn: () => T): T { + this.conn.run("BEGIN"); + try { + const result = fn(); + this.conn.run("COMMIT"); + return result; + } catch (e) { + this.conn.run("ROLLBACK"); + throw e; + } + } + + add_task(task: Task): number { + const now = nowIso(); + logger.debug(`add_task called with image_paths: ${JSON.stringify(task.image_paths)}`); + const image_paths_json = JSON.stringify(task.image_paths); + logger.debug(`image_paths JSON: ${image_paths_json}`); + const cur = this.conn + .query( + ` + INSERT INTO tasks (title, prompt, working_dir, status, schedule_type, + cron_expr, delay_seconds, next_run_at, max_runs, created_at, updated_at, tags, agent, prompt_images, image_paths, dag_id, feishu_root_msg_id) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `, + ) + .run( + task.title, + task.prompt, + task.working_dir, + task.status, + task.schedule_type, + task.cron_expr, + task.delay_seconds, + task.next_run_at, + task.max_runs, + now, + now, + task.tags, + task.agent, + JSON.stringify(task.prompt_images), + image_paths_json, + task.dag_id, + task.feishu_root_msg_id, + ); + const task_id = Number(cur.lastInsertRowid); + logger.debug(`Task ${task_id} inserted with image_paths`); + return task_id; + } + + /** Look up the most recent task created from a given Feishu root message ID. */ + get_task_by_feishu_root_msg(root_msg_id: string): Row | null { + const row = this.conn + .query("SELECT * FROM tasks WHERE feishu_root_msg_id = ? ORDER BY id DESC LIMIT 1") + .get(root_msg_id) as Row | null; + return row ? { ...row } : null; + } + + get_setting(key: string, defaultValue: string | null = null): string | null { + const row = this.conn.query("SELECT value FROM settings WHERE key = ?").get(key) as Row | null; + return row ? row["value"] : defaultValue; + } + + set_setting(key: string, value: string): void { + this.conn.query("INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)").run(key, value); + } + + private _deserialize_heartbeat(row: Row): Row { + const d: Row = { ...row }; + d["enabled"] = Boolean(d["enabled"]); + return d; + } + + _compute_heartbeat_next_run_at(heartbeat: Heartbeat, now: Date | null = null): string { + const base = now ?? new Date(); + if (heartbeat.schedule_type === HeartbeatScheduleType.CRON) { + if (!heartbeat.cron_expr) { + throw new Error("cron heartbeat requires cron_expr"); + } + return dateToLocalIso( + CronExpressionParser.parse(heartbeat.cron_expr, { currentDate: base }).next().toDate(), + ); + } + if (heartbeat.schedule_type === HeartbeatScheduleType.INTERVAL) { + if (!heartbeat.interval_seconds || heartbeat.interval_seconds <= 0) { + throw new Error("interval heartbeat requires interval_seconds > 0"); + } + return dateToLocalIso( + new Date(base.getTime() + Math.trunc(heartbeat.interval_seconds) * 1000), + ); + } + throw new Error(`Unsupported heartbeat schedule_type: ${heartbeat.schedule_type}`); + } + + add_heartbeat(heartbeat: Heartbeat): number { + const now = nowIso(); + if (heartbeat.next_run_at === null) { + heartbeat.next_run_at = this._compute_heartbeat_next_run_at(heartbeat, new Date()); + } + const cur = this.conn + .query( + ` + INSERT INTO heartbeats ( + name, enabled, working_dir, schedule_type, cron_expr, + interval_seconds, check_prompt, action_prompt_template, + default_agent, cooldown_seconds, next_run_at, last_tick_at, + last_decision, last_error, last_triggered_at, last_dedupe_key, + created_at, updated_at + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `, + ) + .run( + heartbeat.name, + heartbeat.enabled ? 1 : 0, + heartbeat.working_dir, + heartbeat.schedule_type, + heartbeat.cron_expr, + heartbeat.interval_seconds, + heartbeat.check_prompt, + heartbeat.action_prompt_template, + heartbeat.default_agent, + heartbeat.cooldown_seconds, + heartbeat.next_run_at, + heartbeat.last_tick_at, + heartbeat.last_decision, + heartbeat.last_error, + heartbeat.last_triggered_at, + heartbeat.last_dedupe_key, + now, + now, + ); + return Number(cur.lastInsertRowid); + } + + static readonly ALLOWED_HEARTBEAT_COLUMNS: ReadonlySet = new Set([ + "name", + "enabled", + "working_dir", + "schedule_type", + "cron_expr", + "interval_seconds", + "check_prompt", + "action_prompt_template", + "default_agent", + "cooldown_seconds", + "next_run_at", + "last_tick_at", + "last_decision", + "last_error", + "last_triggered_at", + "last_dedupe_key", + "updated_at", + ]); + + update_heartbeat(heartbeat_id: number, kwargs: Record): void { + const invalid = Object.keys(kwargs).filter( + (k) => !TaskDB.ALLOWED_HEARTBEAT_COLUMNS.has(k), + ); + if (invalid.length) { + throw new Error(`Invalid heartbeat column(s): ${JSON.stringify(invalid)}`); + } + const updates: Record = { ...kwargs }; + updates["updated_at"] = nowIso(); + const sets = Object.keys(updates) + .map((k) => `${k} = ?`) + .join(", "); + const vals = [...Object.values(updates), heartbeat_id]; + this.conn.query(`UPDATE heartbeats SET ${sets} WHERE id = ?`).run(...(vals as any[])); + } + + get_heartbeat(heartbeat_id: number): Row | null { + const row = this.conn + .query("SELECT * FROM heartbeats WHERE id = ?") + .get(heartbeat_id) as Row | null; + return row ? this._deserialize_heartbeat(row) : null; + } + + get_all_heartbeats(): Row[] { + const rows = this.conn + .query("SELECT * FROM heartbeats ORDER BY created_at DESC") + .all() as Row[]; + return rows.map((r) => this._deserialize_heartbeat(r)); + } + + get_due_heartbeats(): Row[] { + const rows = this.conn + .query( + ` + SELECT * FROM heartbeats + WHERE enabled = 1 + AND next_run_at IS NOT NULL + `, + ) + .all() as Row[]; + const now = new Date(); + const due: Row[] = []; + for (const row of rows) { + const heartbeat = this._deserialize_heartbeat(row); + let next_run_at: Date | null; + try { + next_run_at = parseComparableDatetime(heartbeat["next_run_at"]); + } catch { + continue; + } + if (next_run_at && next_run_at.getTime() <= now.getTime()) { + due.push(heartbeat); + } + } + return due; + } + + delete_heartbeat(heartbeat_id: number): void { + this.transaction(() => { + this.conn.query("DELETE FROM heartbeat_ticks WHERE heartbeat_id = ?").run(heartbeat_id); + this.conn.query("DELETE FROM heartbeat_dedup WHERE heartbeat_id = ?").run(heartbeat_id); + this.conn.query("DELETE FROM heartbeats WHERE id = ?").run(heartbeat_id); + }); + } + + add_heartbeat_tick(heartbeat_id: number): number { + const cur = this.conn + .query( + ` + INSERT INTO heartbeat_ticks (heartbeat_id, started_at, status) + VALUES (?, ?, 'running') + `, + ) + .run(heartbeat_id, nowIso()); + return Number(cur.lastInsertRowid); + } + + finish_heartbeat_tick( + tick_id: number, + status: string, + decision_type: string | null = null, + decision_payload: Record | null = null, + task_id: number | null = null, + raw_output: string | null = null, + error: string | null = null, + ): void { + const payload_json = decision_payload !== null ? JSON.stringify(decision_payload) : null; + this.conn + .query( + ` + UPDATE heartbeat_ticks + SET finished_at = ?, status = ?, decision_type = ?, decision_payload = ?, task_id = ?, raw_output = ?, error = ? + WHERE id = ? + `, + ) + .run(nowIso(), status, decision_type, payload_json, task_id, raw_output, error, tick_id); + } + + get_heartbeat_ticks(heartbeat_id: number, limit: number = 50): Row[] { + const rows = this.conn + .query( + ` + SELECT * FROM heartbeat_ticks + WHERE heartbeat_id = ? + ORDER BY started_at DESC + LIMIT ? + `, + ) + .all(heartbeat_id, limit) as Row[]; + return rows.map((r) => ({ ...r })); + } + + get_heartbeat_tick(heartbeat_id: number, tick_id: number): Row | null { + const row = this.conn + .query( + ` + SELECT * FROM heartbeat_ticks + WHERE heartbeat_id = ? AND id = ? + `, + ) + .get(heartbeat_id, tick_id) as Row | null; + return row ? { ...row } : null; + } + + get_latest_heartbeat_tick(heartbeat_id: number): Row | null { + const row = this.conn + .query( + ` + SELECT * FROM heartbeat_ticks + WHERE heartbeat_id = ? + ORDER BY started_at DESC + LIMIT 1 + `, + ) + .get(heartbeat_id) as Row | null; + return row ? { ...row } : null; + } + + get_heartbeat_dedup(heartbeat_id: number, dedupe_key: string): Row | null { + const row = this.conn + .query( + ` + SELECT * FROM heartbeat_dedup + WHERE heartbeat_id = ? AND dedupe_key = ? + `, + ) + .get(heartbeat_id, dedupe_key) as Row | null; + return row ? { ...row } : null; + } + + upsert_heartbeat_dedup(heartbeat_id: number, dedupe_key: string, task_id: number | null): void { + const now = nowIso(); + this.conn + .query( + ` + INSERT INTO heartbeat_dedup (heartbeat_id, dedupe_key, task_id, triggered_at) + VALUES (?, ?, ?, ?) + ON CONFLICT(heartbeat_id, dedupe_key) + DO UPDATE SET task_id = excluded.task_id, triggered_at = excluded.triggered_at + `, + ) + .run(heartbeat_id, dedupe_key, task_id, now); + } + + static readonly ALLOWED_TASK_COLUMNS: ReadonlySet = new Set([ + "title", + "prompt", + "working_dir", + "status", + "schedule_type", + "cron_expr", + "delay_seconds", + "next_run_at", + "last_run_at", + "result", + "error", + "run_count", + "max_runs", + "updated_at", + "tags", + "agent", + "question", + "answer", + "session_id", + "prompt_images", + "image_paths", + "dag_id", + ]); + + update_task(task_id: number, kwargs: Record): void { + const invalid = Object.keys(kwargs).filter((k) => !TaskDB.ALLOWED_TASK_COLUMNS.has(k)); + if (invalid.length) { + throw new Error(`Invalid task column(s): ${JSON.stringify(invalid)}`); + } + const updates: Record = { ...kwargs }; + if ("next_run_at" in updates) { + updates["next_run_at"] = normalizeDatetimeForStorage( + updates["next_run_at"] as string | null | undefined, + ); + } + updates["updated_at"] = nowIso(); + const sets = Object.keys(updates) + .map((k) => `${k} = ?`) + .join(", "); + const vals = [...Object.values(updates), task_id]; + this.conn.query(`UPDATE tasks SET ${sets} WHERE id = ?`).run(...(vals as any[])); + } + + private _deserialize_task(row: Row): Row { + const d: Row = { ...row }; + // Deserialize prompt_images + const raw = d["prompt_images"]; + if (typeof raw === "string") { + try { + d["prompt_images"] = JSON.parse(raw); + } catch { + d["prompt_images"] = []; + } + } else if (d["prompt_images"] === null || d["prompt_images"] === undefined) { + d["prompt_images"] = []; + } + // Deserialize image_paths + const raw_paths = d["image_paths"]; + if (typeof raw_paths === "string") { + try { + d["image_paths"] = JSON.parse(raw_paths); + } catch { + d["image_paths"] = []; + } + } else if (d["image_paths"] === null || d["image_paths"] === undefined) { + d["image_paths"] = []; + } + return d; + } + + get_task(task_id: number): Row | null { + const row = this.conn.query("SELECT * FROM tasks WHERE id = ?").get(task_id) as Row | null; + return row ? this._deserialize_task(row) : null; + } + + get_all_tasks(): Row[] { + const rows = this.conn.query("SELECT * FROM tasks ORDER BY created_at DESC").all() as Row[]; + return rows.map((r) => this._deserialize_task(r)); + } + + get_due_tasks(): Row[] { + const rows = this.conn + .query( + ` + SELECT * FROM tasks + WHERE status IN ('pending', 'scheduled') + `, + ) + .all() as Row[]; + const now = new Date(); + const due: Row[] = []; + for (const row of rows) { + const task = this._deserialize_task(row); + let next_run_at: Date | null; + try { + next_run_at = parseComparableDatetime(task["next_run_at"]); + } catch { + continue; + } + if (next_run_at === null || next_run_at.getTime() <= now.getTime()) { + due.push(task); + } + } + return due; + } + + add_run(task_id: number): number { + const cur = this.conn + .query("INSERT INTO task_runs (task_id, status) VALUES (?, 'running')") + .run(task_id); + return Number(cur.lastInsertRowid); + } + + finish_run( + run_id: number, + status: string, + result: string | null = null, + error: string | null = null, + raw_output: string | null = null, + ): void { + this.conn + .query( + ` + UPDATE task_runs SET finished_at = datetime('now'), + status = ?, result = ?, error = ?, raw_output = ? + WHERE id = ? + `, + ) + .run(status, result, error, raw_output, run_id); + } + + /** Atomically finish a run record and update the parent task in one transaction. */ + finish_run_and_update_task( + run_id: number, + run_status: string, + task_id: number, + task_updates: Record, + run_result: string | null = null, + run_error: string | null = null, + raw_output: string | null = null, + ): void { + const updates: Record = { ...task_updates }; + updates["updated_at"] = nowIso(); + const sets = Object.keys(updates) + .map((k) => `${k} = ?`) + .join(", "); + const vals = [...Object.values(updates), task_id]; + this.transaction(() => { + this.conn + .query( + ` + UPDATE task_runs SET finished_at = datetime('now'), + status = ?, result = ?, error = ?, raw_output = ? + WHERE id = ? + `, + ) + .run(run_status, run_result, run_error, raw_output, run_id); + this.conn.query(`UPDATE tasks SET ${sets} WHERE id = ?`).run(...(vals as any[])); + }); + } + + get_task_runs(task_id: number, limit: number = 20): Row[] { + const rows = this.conn + .query( + ` + SELECT * FROM task_runs WHERE task_id = ? + ORDER BY started_at DESC LIMIT ? + `, + ) + .all(task_id, limit) as Row[]; + return rows.map((r) => ({ ...r })); + } + + /** Add a new output event to the database. */ + add_output_event(task_id: number, run_id: number, event_type: string, content: string): void { + this.conn + .query( + ` + INSERT INTO task_output_events (task_id, run_id, event_type, content) + VALUES (?, ?, ?, ?) + `, + ) + .run(task_id, run_id, event_type, content); + } + + /** Get output events for a task, ordered by timestamp. */ + get_output_events(task_id: number, limit: number = 1000, offset: number = 0): Row[] { + const rows = this.conn + .query( + ` + SELECT * FROM task_output_events + WHERE task_id = ? + ORDER BY timestamp DESC + LIMIT ? OFFSET ? + `, + ) + .all(task_id, limit, offset) as Row[]; + return rows.map((r) => ({ ...r })); + } + + /** Get output events for a specific run. */ + get_run_output_events(run_id: number, limit: number = 1000): Row[] { + const rows = this.conn + .query( + ` + SELECT * FROM task_output_events + WHERE run_id = ? + ORDER BY timestamp ASC + LIMIT ? + `, + ) + .all(run_id, limit) as Row[]; + return rows.map((r) => ({ ...r })); + } + + // ── Skill Library: pattern ledger ────────────────────────────────────── + + /** + * Completed task runs finished after `watermark`, oldest first. + * + * Joined with task metadata so the sweep agent can read what each run did. + * Ordering ASC + limit makes the watermark advance incrementally so a large + * backlog is processed across several sweeps rather than all at once. + */ + get_completed_runs_since(watermark: string, limit: number = 50): Row[] { + const rows = this.conn + .query( + ` + SELECT r.id AS run_id, r.task_id, r.finished_at, r.result, + t.title, t.prompt, t.working_dir, t.agent + FROM task_runs r + JOIN tasks t ON t.id = r.task_id + WHERE r.status = 'completed' + AND r.finished_at IS NOT NULL + AND r.finished_at > ? + ORDER BY r.finished_at ASC + LIMIT ? + `, + ) + .all(watermark || "", limit) as Row[]; + return rows.map((r) => ({ ...r })); + } + + /** The most recent completed runs regardless of watermark (manual re-scan). */ + get_recent_completed_runs(limit: number = 100): Row[] { + const rows = this.conn + .query( + ` + SELECT r.id AS run_id, r.task_id, r.finished_at, r.result, + t.title, t.prompt, t.working_dir, t.agent + FROM task_runs r + JOIN tasks t ON t.id = r.task_id + WHERE r.status = 'completed' AND r.finished_at IS NOT NULL + ORDER BY r.finished_at DESC + LIMIT ? + `, + ) + .all(limit) as Row[]; + // Return oldest-first so watermark math stays consistent. + return rows.reverse().map((r) => ({ ...r })); + } + + /** + * Record one observation of a pattern. Dedup by exact pattern_key. + * + * Semantic matching is done by the sweep agent (it reuses an existing key). + * Counting is idempotent per run: if `run_id` was already counted for this + * pattern, only the summary/last_seen refresh — recurrence does NOT bump. + * This lets the manual sweep re-scan recent runs without inflating counts. + * When run_id is None (legacy / unknown), fall back to bumping per call. + */ + upsert_skill_pattern( + pattern_key: string, + kind: string, + summary: string, + task_id: number | null, + run_id: number | null = null, + ): number | null { + pattern_key = (pattern_key || "").trim(); + if (!pattern_key) { + return null; + } + kind = kind === "recipe" || kind === "pitfall" ? kind : "recipe"; + const now = nowIso(); + const row = this.conn + .query( + "SELECT id, contributing_task_ids, contributing_run_ids " + + "FROM skill_patterns WHERE pattern_key = ?", + ) + .get(pattern_key) as Row | null; + if (row) { + let tids: any[]; + try { + const parsed = JSON.parse(row["contributing_task_ids"]); + tids = Array.isArray(parsed) ? [...parsed] : []; + } catch { + tids = []; + } + let rids: any[]; + try { + const parsed = JSON.parse(row["contributing_run_ids"] || "[]"); + rids = Array.isArray(parsed) ? [...parsed] : []; + } catch { + rids = []; + } + const already_counted = run_id !== null && rids.includes(run_id); + if (task_id !== null && !tids.includes(task_id)) { + tids.push(task_id); + } + if (run_id !== null && !rids.includes(run_id)) { + rids.push(run_id); + } + // Bump only for a genuinely new observation. + const bump = already_counted ? 0 : 1; + this.conn + .query( + ` + UPDATE skill_patterns + SET recurrence_count = recurrence_count + ?, + last_seen = ?, + updated_at = ?, + summary = CASE WHEN ? != '' THEN ? ELSE summary END, + contributing_task_ids = ?, + contributing_run_ids = ? + WHERE id = ? + `, + ) + .run( + bump, + now, + now, + summary || "", + summary || "", + JSON.stringify(tids), + JSON.stringify(rids), + row["id"], + ); + return Number(row["id"]); + } + const tids = task_id !== null ? [task_id] : []; + const rids = run_id !== null ? [run_id] : []; + const cur = this.conn + .query( + ` + INSERT INTO skill_patterns + (pattern_key, kind, summary, recurrence_count, + first_seen, last_seen, contributing_task_ids, contributing_run_ids, status) + VALUES (?, ?, ?, 1, ?, ?, ?, ?, 'tracking') + `, + ) + .run(pattern_key, kind, summary || "", now, now, JSON.stringify(tids), JSON.stringify(rids)); + return Number(cur.lastInsertRowid); + } + + get_skill_patterns(limit: number = 200): Row[] { + const rows = this.conn + .query( + ` + SELECT p.*, d.status AS draft_status, d.name AS draft_name, + d.description AS draft_description, d.kind AS draft_kind, + d.body AS draft_body, d.error AS draft_error, + d.worthy AS draft_worthy, d.worthiness_reason AS draft_worthiness_reason + FROM skill_patterns p + LEFT JOIN skill_drafts d ON d.pattern_id = p.id + ORDER BY p.recurrence_count DESC, p.last_seen DESC + LIMIT ? + `, + ) + .all(limit) as Row[]; + return rows.map((r) => ({ ...r })); + } + + get_skill_pattern(pattern_id: number): Row | null { + const row = this.conn + .query("SELECT * FROM skill_patterns WHERE id = ?") + .get(pattern_id) as Row | null; + return row ? { ...row } : null; + } + + /** Current recurrence_count for a pattern_key (0 if it doesn't exist yet). */ + get_skill_pattern_recurrence(pattern_key: string): number { + pattern_key = (pattern_key || "").trim(); + if (!pattern_key) { + return 0; + } + const row = this.conn + .query("SELECT recurrence_count FROM skill_patterns WHERE pattern_key = ?") + .get(pattern_key) as Row | null; + return row ? row["recurrence_count"] : 0; + } + + /** + * True if the pattern's recurrences cluster within `window_days`. + * + * Tolerant: if timestamps can't be parsed, don't block promotion. + */ + static _within_window(first_seen: string, last_seen: string, window_days: number): boolean { + let f: Date | null; + let ls: Date | null; + try { + f = parseComparableDatetime(first_seen); + ls = parseComparableDatetime(last_seen); + } catch { + return true; + } + if (f === null || ls === null) { + return true; + } + // ≙ Python timedelta.days (floor division of the difference) + return Math.floor((ls.getTime() - f.getTime()) / 86_400_000) <= window_days; + } + + /** + * Promote 'tracking' patterns that cross the threshold to 'candidate'. + * + * Threshold (borrowed from pskoett self-improvement): recurrence >= 3 AND + * >= 2 distinct tasks AND recurrences within a 30-day window. Returns the + * number newly marked. + */ + refresh_skill_candidates( + min_recurrence: number = 3, + min_tasks: number = 2, + window_days: number = 30, + ): number { + let marked = 0; + const now = nowIso(); + const rows = this.conn + .query( + ` + SELECT id, recurrence_count, contributing_task_ids, first_seen, last_seen + FROM skill_patterns WHERE status = 'tracking' + `, + ) + .all() as Row[]; + for (const r of rows) { + if (r["recurrence_count"] < min_recurrence) { + continue; + } + let tids: any[]; + try { + const parsed = JSON.parse(r["contributing_task_ids"]); + tids = Array.isArray(parsed) ? parsed : []; + } catch { + tids = []; + } + if (new Set(tids).size < min_tasks) { + continue; + } + if (!TaskDB._within_window(r["first_seen"], r["last_seen"], window_days)) { + continue; + } + this.conn + .query("UPDATE skill_patterns SET status = 'candidate', updated_at = ? WHERE id = ?") + .run(now, r["id"]); + marked += 1; + } + return marked; + } + + set_skill_pattern_status( + pattern_id: number, + status: string, + promoted_skill_id: number | null = null, + ): void { + this.conn + .query( + ` + UPDATE skill_patterns + SET status = ?, promoted_skill_id = ?, updated_at = ? + WHERE id = ? + `, + ) + .run(status, promoted_skill_id, nowIso(), pattern_id); + } + + // ── Skill drafts ─────────────────────────────────────────────────────── + upsert_skill_draft( + pattern_id: number, + status: string, + name: string = "", + description: string = "", + kind: string = "recipe", + body: string = "", + error: string | null = null, + worthy: boolean | null = null, + worthiness_reason: string = "", + ): void { + this.conn + .query( + ` + INSERT INTO skill_drafts + (pattern_id, name, description, kind, body, status, error, + worthy, worthiness_reason, updated_at) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + ON CONFLICT(pattern_id) DO UPDATE SET + name = excluded.name, + description = excluded.description, + kind = excluded.kind, + body = excluded.body, + status = excluded.status, + error = excluded.error, + worthy = excluded.worthy, + worthiness_reason = excluded.worthiness_reason, + updated_at = excluded.updated_at + `, + ) + .run( + pattern_id, + name, + description, + kind, + body, + status, + error, + worthy === null ? null : worthy ? 1 : 0, + worthiness_reason, + nowIso(), + ); + } + + get_skill_draft(pattern_id: number): Row | null { + const row = this.conn + .query("SELECT * FROM skill_drafts WHERE pattern_id = ?") + .get(pattern_id) as Row | null; + return row ? { ...row } : null; + } + + delete_skill_draft(pattern_id: number): void { + this.conn.query("DELETE FROM skill_drafts WHERE pattern_id = ?").run(pattern_id); + } + + // ── Skill registry ───────────────────────────────────────────────────── + // `path` shadows the node:path import inside this method (unused here). + add_skill( + name: string, + description: string, + path: string, + source_pattern_key: string | null = null, + source_task_ids: string | null = null, + kind: string | null = null, + ): number | null { + const cur = this.conn + .query( + ` + INSERT INTO skills (name, description, path, source_pattern_key, source_task_ids, kind, enabled) + VALUES (?, ?, ?, ?, ?, ?, 1) + ON CONFLICT(name) DO UPDATE SET + description = excluded.description, + path = excluded.path, + source_pattern_key = excluded.source_pattern_key, + source_task_ids = excluded.source_task_ids, + kind = excluded.kind, + enabled = 1 + `, + ) + .run(name, description, path, source_pattern_key, source_task_ids, kind); + if (cur.lastInsertRowid) { + return Number(cur.lastInsertRowid); + } + const row = this.conn.query("SELECT id FROM skills WHERE name = ?").get(name) as Row | null; + return row ? Number(row["id"]) : null; + } + + get_skills(): Row[] { + const rows = this.conn.query("SELECT * FROM skills ORDER BY created_at DESC").all() as Row[]; + return rows.map((r) => ({ ...r })); + } + + get_skill(skill_id: number): Row | null { + const row = this.conn.query("SELECT * FROM skills WHERE id = ?").get(skill_id) as Row | null; + return row ? { ...row } : null; + } + + set_skill_enabled(skill_id: number, enabled: boolean): void { + this.conn.query("UPDATE skills SET enabled = ? WHERE id = ?").run(enabled ? 1 : 0, skill_id); + } + + delete_skill(skill_id: number): void { + this.conn.query("DELETE FROM skills WHERE id = ?").run(skill_id); + } + + add_dependency(task_id: number, depends_on_task_id: number, inject_result: boolean = false): void { + this.conn + .query( + ` + INSERT OR IGNORE INTO task_dependencies (task_id, depends_on_task_id, inject_result) + VALUES (?, ?, ?) + `, + ) + .run(task_id, depends_on_task_id, inject_result ? 1 : 0); + } + + /** + * Insert multiple dependency rows for task_id in a single transaction. + * + * dep_list: list of objects with keys task_id (upstream) and inject_result. + * Rolls back all inserts if any one fails. + */ + add_dependencies_batch( + task_id: number, + dep_list: Array<{ task_id: number; inject_result: unknown }>, + ): void { + this.transaction(() => { + for (const dep of dep_list) { + this.conn + .query( + ` + INSERT OR IGNORE INTO task_dependencies (task_id, depends_on_task_id, inject_result) + VALUES (?, ?, ?) + `, + ) + .run(task_id, dep.task_id, dep.inject_result ? 1 : 0); + } + }); + } + + remove_dependency(task_id: number, depends_on_task_id: number): void { + this.conn + .query( + ` + DELETE FROM task_dependencies WHERE task_id = ? AND depends_on_task_id = ? + `, + ) + .run(task_id, depends_on_task_id); + } + + /** Remove all upstream dependencies for a task. */ + clear_dependencies(task_id: number): void { + this.conn.query("DELETE FROM task_dependencies WHERE task_id = ?").run(task_id); + } + + /** Return upstream tasks that task_id depends on. */ + get_dependencies(task_id: number): Row[] { + const rows = this.conn + .query( + ` + SELECT td.*, t.title as depends_on_title, t.status as depends_on_status + FROM task_dependencies td + JOIN tasks t ON t.id = td.depends_on_task_id + WHERE td.task_id = ? + `, + ) + .all(task_id) as Row[]; + return rows.map((r) => ({ ...r })); + } + + /** Return downstream tasks that depend on task_id. */ + get_dependents(task_id: number): Row[] { + const rows = this.conn + .query( + ` + SELECT td.*, t.title as task_title, t.status as task_status + FROM task_dependencies td + JOIN tasks t ON t.id = td.task_id + WHERE td.depends_on_task_id = ? + `, + ) + .all(task_id) as Row[]; + return rows.map((r) => ({ ...r })); + } + + get_dag_tasks(dag_id: string): Row[] { + const rows = this.conn + .query("SELECT * FROM tasks WHERE dag_id = ? ORDER BY created_at ASC") + .all(dag_id) as Row[]; + return rows.map((r) => this._deserialize_task(r)); + } + + delete_task(task_id: number): void { + this.transaction(() => { + this.conn.query("DELETE FROM task_output_events WHERE task_id = ?").run(task_id); + this.conn.query("DELETE FROM task_runs WHERE task_id = ?").run(task_id); + this.conn + .query("DELETE FROM task_dependencies WHERE task_id = ? OR depends_on_task_id = ?") + .run(task_id, task_id); + this.conn.query("DELETE FROM tasks WHERE id = ?").run(task_id); + }); + } +} diff --git a/backend/tests/taskdb.test.ts b/backend/tests/taskdb.test.ts new file mode 100644 index 0000000..2e8ac75 --- /dev/null +++ b/backend/tests/taskdb.test.ts @@ -0,0 +1,326 @@ +// Direct unit tests for TaskDB internals not exercised by HTTP CRUD tests. +// +// Covers: settings, run history, output events, completed-run queries used by +// the skill sweep, skill_patterns ledger (idempotent recurrence counting), +// draft upsert/clear, candidate refresh windowing, dependency rows, and +// cascading delete. Constructs TaskDB directly against a tmp-dir SQLite file. +// +// Ported from tests/test_taskdb.py; test() descriptions keep the Python +// test function names. + +import { afterEach, beforeEach, describe, expect, test } from "bun:test"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import { TaskDB } from "../src/db.ts"; +import { ScheduleType, makeTask } from "../src/types.ts"; +import { dateToLocalIso } from "../src/util.ts"; + +describe("TaskDB", () => { + let tmpDir: string; + let db: TaskDB; + + beforeEach(() => { + tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "agentforge-test-")); + db = new TaskDB(path.join(tmpDir, "taskdb-test.db")); + }); + + afterEach(() => { + db.conn.close(); + fs.rmSync(tmpDir, { recursive: true, force: true }); + }); + + // ── completed-run queries (skill sweep inputs) helper ───────────────────── + function finishWithTimestamp(run_id: number, finished_at: string): void { + db.conn + .query("UPDATE task_runs SET status='completed', finished_at=? WHERE id=?") + .run(finished_at, run_id); + } + + // ── settings ─────────────────────────────────────────────────────────────── + test("test_settings_get_default_and_set_overwrite", () => { + expect(db.get_setting("missing")).toBeNull(); + expect(db.get_setting("missing", "fallback")).toBe("fallback"); + db.set_setting("k", "v1"); + expect(db.get_setting("k")).toBe("v1"); + db.set_setting("k", "v2"); // INSERT OR REPLACE + expect(db.get_setting("k")).toBe("v2"); + }); + + // ── run history ──────────────────────────────────────────────────────────── + test("test_run_lifecycle_and_ordering", () => { + const tid = db.add_task(makeTask({ title: "t", prompt: "p", working_dir: "." })); + const run1 = db.add_run(tid); + db.finish_run(run1, "completed", "ok", null, "raw1"); + const run2 = db.add_run(tid); + db.finish_run(run2, "failed", null, "boom"); + + const runs = db.get_task_runs(tid); + expect(new Set(runs.map((r) => r["status"]))).toEqual(new Set(["completed", "failed"])); + expect(new Set(runs.map((r) => r["id"]))).toEqual(new Set([run1, run2])); + const completed = runs.find((r) => r["id"] === run1)!; + expect(completed["result"]).toBe("ok"); + expect(completed["raw_output"]).toBe("raw1"); + expect(completed["finished_at"]).not.toBeNull(); + }); + + test("test_finish_run_and_update_task_is_atomic", () => { + const tid = db.add_task(makeTask({ title: "t", prompt: "p", working_dir: "." })); + const rid = db.add_run(tid); + + db.finish_run_and_update_task( + rid, + "completed", + tid, + { status: "completed", result: "done", run_count: 1 }, + "done", + ); + + const run = db.get_task_runs(tid)[0]!; + expect(run["status"]).toBe("completed"); + expect(run["result"]).toBe("done"); + const task = db.get_task(tid)!; + expect(task["status"]).toBe("completed"); + expect(task["result"]).toBe("done"); + expect(task["run_count"]).toBe(1); + }); + + // ── output events ────────────────────────────────────────────────────────── + test("test_output_events_per_task_and_per_run", () => { + const tid = db.add_task(makeTask({ title: "t", prompt: "p", working_dir: "." })); + const run1 = db.add_run(tid); + const run2 = db.add_run(tid); + db.add_output_event(tid, run1, "assistant", "hello"); + db.add_output_event(tid, run1, "result", "done"); + db.add_output_event(tid, run2, "assistant", "second run"); + + const all_events = db.get_output_events(tid); + expect(all_events.length).toBe(3); + + // offset/limit paging (events ordered DESC by timestamp) + const page = db.get_output_events(tid, 1, 0); + expect(page.length).toBe(1); + + const run1_events = db.get_run_output_events(run1); + expect(run1_events.map((e) => e["content"])).toEqual(["hello", "done"]); // ASC order + const run2_events = db.get_run_output_events(run2); + expect(run2_events.map((e) => e["content"])).toEqual(["second run"]); + }); + + // ── completed-run queries (skill sweep inputs) ───────────────────────────── + test("test_get_completed_runs_since_watermark", () => { + const tid = db.add_task(makeTask({ title: "t", prompt: "p", working_dir: "." })); + const old = db.add_run(tid); + const newer = db.add_run(tid); + finishWithTimestamp(old, "2020-01-01T00:00:00"); + finishWithTimestamp(newer, "2025-01-01T00:00:00"); + + const after = db.get_completed_runs_since("2023-01-01T00:00:00"); + expect(after.map((r) => r["run_id"])).toEqual([newer]); + // joined task metadata is present + expect(after[0]!["title"]).toBe("t"); + expect(after[0]!["prompt"]).toBe("p"); + + const everything = db.get_completed_runs_since(""); + expect(everything.map((r) => r["run_id"])).toEqual([old, newer]); // oldest first + }); + + test("test_get_recent_completed_runs_oldest_first_with_limit", () => { + const tid = db.add_task(makeTask({ title: "t", prompt: "p", working_dir: "." })); + const r1 = db.add_run(tid); + const r2 = db.add_run(tid); + const r3 = db.add_run(tid); + finishWithTimestamp(r1, "2024-01-01T00:00:00"); + finishWithTimestamp(r2, "2024-01-02T00:00:00"); + finishWithTimestamp(r3, "2024-01-03T00:00:00"); + + const recent = db.get_recent_completed_runs(2); + // picks the 2 newest, returns them oldest-first + expect(recent.map((r) => r["run_id"])).toEqual([r2, r3]); + }); + + // ── skill_patterns ledger ────────────────────────────────────────────────── + test("test_upsert_skill_pattern_blank_key_returns_none", () => { + expect(db.upsert_skill_pattern(" ", "recipe", "s", 1)).toBeNull(); + }); + + test("test_upsert_skill_pattern_idempotent_per_run", () => { + const pid = db.upsert_skill_pattern("k", "recipe", "first", 1, 10)!; + expect(db.get_skill_pattern_recurrence("k")).toBe(1); + + // same run_id again → no recurrence bump, but summary refreshes + const same = db.upsert_skill_pattern("k", "recipe", "updated", 1, 10); + expect(same).toBe(pid); + expect(db.get_skill_pattern_recurrence("k")).toBe(1); + expect(db.get_skill_pattern(pid)!["summary"]).toBe("updated"); + + // new run_id → recurrence bumps and task list grows + db.upsert_skill_pattern("k", "recipe", "", 2, 11); + expect(db.get_skill_pattern_recurrence("k")).toBe(2); + const pattern = db.get_skill_pattern(pid)!; + expect([...JSON.parse(pattern["contributing_task_ids"])].sort()).toEqual([1, 2]); + expect([...JSON.parse(pattern["contributing_run_ids"])].sort()).toEqual([10, 11]); + // empty summary must NOT clobber the prior one + expect(pattern["summary"]).toBe("updated"); + }); + + test("test_upsert_skill_pattern_no_run_id_bumps_each_call", () => { + db.upsert_skill_pattern("legacy", "recipe", "s", 1); + db.upsert_skill_pattern("legacy", "recipe", "s", 1); + expect(db.get_skill_pattern_recurrence("legacy")).toBe(2); + }); + + test("test_upsert_skill_pattern_invalid_kind_falls_back", () => { + const pid = db.upsert_skill_pattern("k", "nonsense-kind", "s", 1)!; + expect(db.get_skill_pattern(pid)!["kind"]).toBe("recipe"); + }); + + test("test_get_skill_pattern_recurrence_unknown_is_zero", () => { + expect(db.get_skill_pattern_recurrence("does-not-exist")).toBe(0); + expect(db.get_skill_pattern_recurrence("")).toBe(0); + }); + + test("test_within_window", () => { + const first = "2024-01-01T00:00:00"; + const inside = "2024-01-20T00:00:00"; + const outside = "2024-03-01T00:00:00"; + expect(TaskDB._within_window(first, inside, 30)).toBe(true); + expect(TaskDB._within_window(first, outside, 30)).toBe(false); + // unparseable timestamps don't block promotion + expect(TaskDB._within_window("garbage", "garbage", 30)).toBe(true); + }); + + test("test_set_skill_pattern_status_with_promoted_id", () => { + const pid = db.upsert_skill_pattern("k", "recipe", "s", 1)!; + db.set_skill_pattern_status(pid, "promoted", 42); + const row = db.get_skill_pattern(pid)!; + expect(row["status"]).toBe("promoted"); + expect(row["promoted_skill_id"]).toBe(42); + }); + + // ── skill drafts ─────────────────────────────────────────────────────────── + test("test_skill_draft_upsert_conflict_and_delete", () => { + const pid = db.upsert_skill_pattern("k", "recipe", "s", 1)!; + db.upsert_skill_draft(pid, "drafting", "", "", "recipe"); + expect(db.get_skill_draft(pid)!["status"]).toBe("drafting"); + + // ON CONFLICT(pattern_id) updates in place + db.upsert_skill_draft(pid, "ready", "my-skill", "", "recipe", "b", null, true, "reusable"); + const draft = db.get_skill_draft(pid)!; + expect(draft["status"]).toBe("ready"); + expect(draft["name"]).toBe("my-skill"); + expect(draft["worthy"]).toBe(1); + + db.delete_skill_draft(pid); + expect(db.get_skill_draft(pid)).toBeNull(); + }); + + test("test_skill_draft_worthy_none_stored_as_null", () => { + const pid = db.upsert_skill_pattern("k", "recipe", "s", 1)!; + db.upsert_skill_draft(pid, "ready", "", "", "recipe", "", null, null); + expect(db.get_skill_draft(pid)!["worthy"]).toBeNull(); + }); + + // ── dependencies / DAG ───────────────────────────────────────────────────── + test("test_dependency_crud_and_views", () => { + const up = db.add_task(makeTask({ title: "up", prompt: "p", working_dir: "." })); + const down = db.add_task(makeTask({ title: "down", prompt: "p", working_dir: "." })); + + db.add_dependency(down, up, true); + // duplicate insert is ignored + db.add_dependency(down, up, true); + + const deps = db.get_dependencies(down); + expect(deps.length).toBe(1); + expect(deps[0]!["depends_on_task_id"]).toBe(up); + expect(deps[0]!["depends_on_title"]).toBe("up"); + expect(deps[0]!["inject_result"]).toBe(1); + + const dependents = db.get_dependents(up); + expect(dependents.length).toBe(1); + expect(dependents[0]!["task_id"]).toBe(down); + expect(dependents[0]!["task_title"]).toBe("down"); + + db.remove_dependency(down, up); + expect(db.get_dependencies(down)).toEqual([]); + }); + + test("test_add_dependencies_batch_and_clear", () => { + const a = db.add_task(makeTask({ title: "a", prompt: "p", working_dir: "." })); + const b = db.add_task(makeTask({ title: "b", prompt: "p", working_dir: "." })); + const down = db.add_task(makeTask({ title: "d", prompt: "p", working_dir: "." })); + + db.add_dependencies_batch(down, [ + { task_id: a, inject_result: true }, + { task_id: b, inject_result: false }, + ]); + const deps = db.get_dependencies(down); + expect(new Set(deps.map((d) => d["depends_on_task_id"]))).toEqual(new Set([a, b])); + + db.clear_dependencies(down); + expect(db.get_dependencies(down)).toEqual([]); + }); + + test("test_get_dag_tasks_filters_by_dag_id", () => { + db.add_task(makeTask({ title: "x", prompt: "p", working_dir: ".", dag_id: "flow-1" })); + db.add_task(makeTask({ title: "y", prompt: "p", working_dir: ".", dag_id: "flow-1" })); + db.add_task(makeTask({ title: "z", prompt: "p", working_dir: ".", dag_id: "other" })); + + const flow = db.get_dag_tasks("flow-1"); + expect(new Set(flow.map((t) => t["title"]))).toEqual(new Set(["x", "y"])); + }); + + // ── cascading delete ─────────────────────────────────────────────────────── + test("test_delete_task_removes_runs_events_and_deps", () => { + const up = db.add_task(makeTask({ title: "up", prompt: "p", working_dir: "." })); + const tid = db.add_task(makeTask({ title: "t", prompt: "p", working_dir: "." })); + db.add_dependency(tid, up); + const rid = db.add_run(tid); + db.add_output_event(tid, rid, "assistant", "hi"); + + db.delete_task(tid); + + expect(db.get_task(tid)).toBeNull(); + expect(db.get_task_runs(tid)).toEqual([]); + expect(db.get_output_events(tid)).toEqual([]); + // the dependency row referencing the deleted task is gone too + expect(db.get_dependents(up)).toEqual([]); + }); + + // ── due-task selection ───────────────────────────────────────────────────── + test("test_get_due_tasks_selects_only_ready", () => { + const now = new Date(); + const past = dateToLocalIso(new Date(now.getTime() - 5 * 60 * 1000)); + const future = dateToLocalIso(new Date(now.getTime() + 60 * 60 * 1000)); + + const immediate = db.add_task(makeTask({ title: "now", prompt: "p", working_dir: "." })); + const due_scheduled = db.add_task( + makeTask({ + title: "due", + prompt: "p", + working_dir: ".", + schedule_type: ScheduleType.SCHEDULED_AT, + next_run_at: past, + }), + ); + db.update_task(due_scheduled, { status: "scheduled" }); + const not_yet = db.add_task( + makeTask({ + title: "later", + prompt: "p", + working_dir: ".", + schedule_type: ScheduleType.SCHEDULED_AT, + next_run_at: future, + }), + ); + db.update_task(not_yet, { status: "scheduled" }); + const running = db.add_task(makeTask({ title: "running", prompt: "p", working_dir: "." })); + db.update_task(running, { status: "running" }); + + const due_ids = new Set(db.get_due_tasks().map((t) => t["id"])); + expect(due_ids.has(immediate)).toBe(true); // pending + no next_run_at + expect(due_ids.has(due_scheduled)).toBe(true); // scheduled in the past + expect(due_ids.has(not_yet)).toBe(false); // future + expect(due_ids.has(running)).toBe(false); // not pending/scheduled + }); +}); From b4899977daf9235b5e5a532705adaba92b00445d Mon Sep 17 00:00:00 2001 From: taohe Date: Sat, 13 Jun 2026 01:08:48 +0800 Subject: [PATCH 06/18] build(electron): replace Vite/npm toolchain with Bun build pipeline - Bun.build bundles main/preload/renderer (scripts/build.ts), watch+reload dev runner (scripts/dev.ts) - backend binary compiled via bun build --compile (scripts/build-backend.ts) - forge.config: drop plugin-vite, ship .bun/ output via packager ignore rules - main.ts: spawn bun backend in dev, watch backend/*.ts for hot reload, load Bun-built renderer - remove vite configs/deps, package-lock.json, dead renderer.ts template entry Co-Authored-By: Claude Fable 5 --- .../.bun/renderer/chunk-nbmpy57s.js | 19805 ++++++++++++++++ .../.bun/renderer/chunk-nbmpy57s.js.map | 52 + taskboard-electron/.bun/renderer/index.html | 11 + taskboard-electron/bun.lock | 259 +- taskboard-electron/eslint.config.mjs | 25 +- taskboard-electron/forge.config.js | 37 +- taskboard-electron/index.html | 2 +- taskboard-electron/package-lock.json | 11832 --------- taskboard-electron/package.json | 23 +- taskboard-electron/scripts/build-backend.mjs | 22 - taskboard-electron/scripts/build-backend.ts | 27 + taskboard-electron/scripts/build.ts | 66 + taskboard-electron/scripts/dev.ts | 69 + taskboard-electron/src/main.ts | 146 +- taskboard-electron/src/renderer.ts | 31 - taskboard-electron/src/vite-env.d.ts | 1 - taskboard-electron/test_hot_reload.mjs | 329 - taskboard-electron/tsconfig.json | 2 +- taskboard-electron/vite.main.config.mjs | 8 - taskboard-electron/vite.preload.config.mjs | 4 - taskboard-electron/vite.renderer.config.mjs | 14 - 21 files changed, 20151 insertions(+), 12614 deletions(-) create mode 100644 taskboard-electron/.bun/renderer/chunk-nbmpy57s.js create mode 100644 taskboard-electron/.bun/renderer/chunk-nbmpy57s.js.map create mode 100644 taskboard-electron/.bun/renderer/index.html delete mode 100644 taskboard-electron/package-lock.json delete mode 100644 taskboard-electron/scripts/build-backend.mjs create mode 100644 taskboard-electron/scripts/build-backend.ts create mode 100644 taskboard-electron/scripts/build.ts create mode 100644 taskboard-electron/scripts/dev.ts delete mode 100644 taskboard-electron/src/renderer.ts delete mode 100644 taskboard-electron/src/vite-env.d.ts delete mode 100644 taskboard-electron/test_hot_reload.mjs delete mode 100644 taskboard-electron/vite.main.config.mjs delete mode 100644 taskboard-electron/vite.preload.config.mjs delete mode 100644 taskboard-electron/vite.renderer.config.mjs diff --git a/taskboard-electron/.bun/renderer/chunk-nbmpy57s.js b/taskboard-electron/.bun/renderer/chunk-nbmpy57s.js new file mode 100644 index 0000000..50dacc4 --- /dev/null +++ b/taskboard-electron/.bun/renderer/chunk-nbmpy57s.js @@ -0,0 +1,19805 @@ +var __create = Object.create; +var __getProtoOf = Object.getPrototypeOf; +var __defProp = Object.defineProperty; +var __getOwnPropNames = Object.getOwnPropertyNames; +var __hasOwnProp = Object.prototype.hasOwnProperty; +function __accessProp(key) { + return this[key]; +} +var __toESMCache_node; +var __toESMCache_esm; +var __toESM = (mod, isNodeMode, target) => { + var canCache = mod != null && typeof mod === "object"; + if (canCache) { + var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap; + var cached = cache.get(mod); + if (cached) + return cached; + } + target = mod != null ? __create(__getProtoOf(mod)) : {}; + const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target; + for (let key of __getOwnPropNames(mod)) + if (!__hasOwnProp.call(to, key)) + __defProp(to, key, { + get: __accessProp.bind(mod, key), + enumerable: true + }); + if (canCache) + cache.set(mod, to); + return to; +}; +var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports); +var __returnValue = (v) => v; +function __exportSetter(name, newValue) { + this[name] = __returnValue.bind(null, newValue); +} +var __export = (target, all) => { + for (var name in all) + __defProp(target, name, { + get: all[name], + enumerable: true, + configurable: true, + set: __exportSetter.bind(all, name) + }); +}; +var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res); + +// node_modules/react/cjs/react.production.js +var exports_react_production = {}; +__export(exports_react_production, { + version: () => $version, + useTransition: () => $useTransition, + useSyncExternalStore: () => $useSyncExternalStore, + useState: () => $useState, + useRef: () => $useRef, + useReducer: () => $useReducer, + useOptimistic: () => $useOptimistic, + useMemo: () => $useMemo, + useLayoutEffect: () => $useLayoutEffect, + useInsertionEffect: () => $useInsertionEffect, + useImperativeHandle: () => $useImperativeHandle, + useId: () => $useId, + useEffectEvent: () => $useEffectEvent, + useEffect: () => $useEffect, + useDeferredValue: () => $useDeferredValue, + useDebugValue: () => $useDebugValue, + useContext: () => $useContext, + useCallback: () => $useCallback, + useActionState: () => $useActionState, + use: () => $use, + unstable_useCacheRefresh: () => $unstable_useCacheRefresh, + startTransition: () => $startTransition, + memo: () => $memo, + lazy: () => $lazy, + isValidElement: () => $isValidElement, + forwardRef: () => $forwardRef, + createRef: () => $createRef, + createElement: () => $createElement, + createContext: () => $createContext, + cloneElement: () => $cloneElement, + cacheSignal: () => $cacheSignal, + cache: () => $cache, + __COMPILER_RUNTIME: () => $__COMPILER_RUNTIME, + __CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE: () => $__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, + Suspense: () => $Suspense, + StrictMode: () => $StrictMode, + PureComponent: () => $PureComponent, + Profiler: () => $Profiler, + Fragment: () => $Fragment, + Component: () => $Component, + Children: () => $Children, + Activity: () => $Activity +}); +function getIteratorFn(maybeIterable) { + if (maybeIterable === null || typeof maybeIterable !== "object") + return null; + maybeIterable = MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL] || maybeIterable["@@iterator"]; + return typeof maybeIterable === "function" ? maybeIterable : null; +} +function Component(props, context, updater) { + this.props = props; + this.context = context; + this.refs = emptyObject; + this.updater = updater || ReactNoopUpdateQueue; +} +function ComponentDummy() {} +function PureComponent(props, context, updater) { + this.props = props; + this.context = context; + this.refs = emptyObject; + this.updater = updater || ReactNoopUpdateQueue; +} +function noop() {} +function ReactElement(type, key, props) { + var refProp = props.ref; + return { + $$typeof: REACT_ELEMENT_TYPE, + type, + key, + ref: refProp !== undefined ? refProp : null, + props + }; +} +function cloneAndReplaceKey(oldElement, newKey) { + return ReactElement(oldElement.type, newKey, oldElement.props); +} +function isValidElement(object) { + return typeof object === "object" && object !== null && object.$$typeof === REACT_ELEMENT_TYPE; +} +function escape(key) { + var escaperLookup = { "=": "=0", ":": "=2" }; + return "$" + key.replace(/[=:]/g, function(match) { + return escaperLookup[match]; + }); +} +function getElementKey(element, index) { + return typeof element === "object" && element !== null && element.key != null ? escape("" + element.key) : index.toString(36); +} +function resolveThenable(thenable) { + switch (thenable.status) { + case "fulfilled": + return thenable.value; + case "rejected": + throw thenable.reason; + default: + switch (typeof thenable.status === "string" ? thenable.then(noop, noop) : (thenable.status = "pending", thenable.then(function(fulfilledValue) { + thenable.status === "pending" && (thenable.status = "fulfilled", thenable.value = fulfilledValue); + }, function(error) { + thenable.status === "pending" && (thenable.status = "rejected", thenable.reason = error); + })), thenable.status) { + case "fulfilled": + return thenable.value; + case "rejected": + throw thenable.reason; + } + } + throw thenable; +} +function mapIntoArray(children, array, escapedPrefix, nameSoFar, callback) { + var type = typeof children; + if (type === "undefined" || type === "boolean") + children = null; + var invokeCallback = false; + if (children === null) + invokeCallback = true; + else + switch (type) { + case "bigint": + case "string": + case "number": + invokeCallback = true; + break; + case "object": + switch (children.$$typeof) { + case REACT_ELEMENT_TYPE: + case REACT_PORTAL_TYPE: + invokeCallback = true; + break; + case REACT_LAZY_TYPE: + return invokeCallback = children._init, mapIntoArray(invokeCallback(children._payload), array, escapedPrefix, nameSoFar, callback); + } + } + if (invokeCallback) + return callback = callback(children), invokeCallback = nameSoFar === "" ? "." + getElementKey(children, 0) : nameSoFar, isArrayImpl(callback) ? (escapedPrefix = "", invokeCallback != null && (escapedPrefix = invokeCallback.replace(userProvidedKeyEscapeRegex, "$&/") + "/"), mapIntoArray(callback, array, escapedPrefix, "", function(c) { + return c; + })) : callback != null && (isValidElement(callback) && (callback = cloneAndReplaceKey(callback, escapedPrefix + (callback.key == null || children && children.key === callback.key ? "" : ("" + callback.key).replace(userProvidedKeyEscapeRegex, "$&/") + "/") + invokeCallback)), array.push(callback)), 1; + invokeCallback = 0; + var nextNamePrefix = nameSoFar === "" ? "." : nameSoFar + ":"; + if (isArrayImpl(children)) + for (var i = 0;i < children.length; i++) + nameSoFar = children[i], type = nextNamePrefix + getElementKey(nameSoFar, i), invokeCallback += mapIntoArray(nameSoFar, array, escapedPrefix, type, callback); + else if (i = getIteratorFn(children), typeof i === "function") + for (children = i.call(children), i = 0;!(nameSoFar = children.next()).done; ) + nameSoFar = nameSoFar.value, type = nextNamePrefix + getElementKey(nameSoFar, i++), invokeCallback += mapIntoArray(nameSoFar, array, escapedPrefix, type, callback); + else if (type === "object") { + if (typeof children.then === "function") + return mapIntoArray(resolveThenable(children), array, escapedPrefix, nameSoFar, callback); + array = String(children); + throw Error("Objects are not valid as a React child (found: " + (array === "[object Object]" ? "object with keys {" + Object.keys(children).join(", ") + "}" : array) + "). If you meant to render a collection of children, use an array instead."); + } + return invokeCallback; +} +function mapChildren(children, func, context) { + if (children == null) + return children; + var result = [], count = 0; + mapIntoArray(children, result, "", "", function(child) { + return func.call(context, child, count++); + }); + return result; +} +function lazyInitializer(payload) { + if (payload._status === -1) { + var ctor = payload._result; + ctor = ctor(); + ctor.then(function(moduleObject) { + if (payload._status === 0 || payload._status === -1) + payload._status = 1, payload._result = moduleObject; + }, function(error) { + if (payload._status === 0 || payload._status === -1) + payload._status = 2, payload._result = error; + }); + payload._status === -1 && (payload._status = 0, payload._result = ctor); + } + if (payload._status === 1) + return payload._result.default; + throw payload._result; +} +var REACT_ELEMENT_TYPE, REACT_PORTAL_TYPE, REACT_FRAGMENT_TYPE, REACT_STRICT_MODE_TYPE, REACT_PROFILER_TYPE, REACT_CONSUMER_TYPE, REACT_CONTEXT_TYPE, REACT_FORWARD_REF_TYPE, REACT_SUSPENSE_TYPE, REACT_MEMO_TYPE, REACT_LAZY_TYPE, REACT_ACTIVITY_TYPE, MAYBE_ITERATOR_SYMBOL, ReactNoopUpdateQueue, assign, emptyObject, pureComponentPrototype, isArrayImpl, ReactSharedInternals, hasOwnProperty, userProvidedKeyEscapeRegex, reportGlobalError, Children, $Activity, $Children, $Component, $Fragment, $Profiler, $PureComponent, $StrictMode, $Suspense, $__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, $__COMPILER_RUNTIME, $cache = function(fn) { + return function() { + return fn.apply(null, arguments); + }; +}, $cacheSignal = function() { + return null; +}, $cloneElement = function(element, config, children) { + if (element === null || element === undefined) + throw Error("The argument must be a React element, but you passed " + element + "."); + var props = assign({}, element.props), key = element.key; + if (config != null) + for (propName in config.key !== undefined && (key = "" + config.key), config) + !hasOwnProperty.call(config, propName) || propName === "key" || propName === "__self" || propName === "__source" || propName === "ref" && config.ref === undefined || (props[propName] = config[propName]); + var propName = arguments.length - 2; + if (propName === 1) + props.children = children; + else if (1 < propName) { + for (var childArray = Array(propName), i = 0;i < propName; i++) + childArray[i] = arguments[i + 2]; + props.children = childArray; + } + return ReactElement(element.type, key, props); +}, $createContext = function(defaultValue) { + defaultValue = { + $$typeof: REACT_CONTEXT_TYPE, + _currentValue: defaultValue, + _currentValue2: defaultValue, + _threadCount: 0, + Provider: null, + Consumer: null + }; + defaultValue.Provider = defaultValue; + defaultValue.Consumer = { + $$typeof: REACT_CONSUMER_TYPE, + _context: defaultValue + }; + return defaultValue; +}, $createElement = function(type, config, children) { + var propName, props = {}, key = null; + if (config != null) + for (propName in config.key !== undefined && (key = "" + config.key), config) + hasOwnProperty.call(config, propName) && propName !== "key" && propName !== "__self" && propName !== "__source" && (props[propName] = config[propName]); + var childrenLength = arguments.length - 2; + if (childrenLength === 1) + props.children = children; + else if (1 < childrenLength) { + for (var childArray = Array(childrenLength), i = 0;i < childrenLength; i++) + childArray[i] = arguments[i + 2]; + props.children = childArray; + } + if (type && type.defaultProps) + for (propName in childrenLength = type.defaultProps, childrenLength) + props[propName] === undefined && (props[propName] = childrenLength[propName]); + return ReactElement(type, key, props); +}, $createRef = function() { + return { current: null }; +}, $forwardRef = function(render) { + return { $$typeof: REACT_FORWARD_REF_TYPE, render }; +}, $isValidElement, $lazy = function(ctor) { + return { + $$typeof: REACT_LAZY_TYPE, + _payload: { _status: -1, _result: ctor }, + _init: lazyInitializer + }; +}, $memo = function(type, compare) { + return { + $$typeof: REACT_MEMO_TYPE, + type, + compare: compare === undefined ? null : compare + }; +}, $startTransition = function(scope) { + var prevTransition = ReactSharedInternals.T, currentTransition = {}; + ReactSharedInternals.T = currentTransition; + try { + var returnValue = scope(), onStartTransitionFinish = ReactSharedInternals.S; + onStartTransitionFinish !== null && onStartTransitionFinish(currentTransition, returnValue); + typeof returnValue === "object" && returnValue !== null && typeof returnValue.then === "function" && returnValue.then(noop, reportGlobalError); + } catch (error) { + reportGlobalError(error); + } finally { + prevTransition !== null && currentTransition.types !== null && (prevTransition.types = currentTransition.types), ReactSharedInternals.T = prevTransition; + } +}, $unstable_useCacheRefresh = function() { + return ReactSharedInternals.H.useCacheRefresh(); +}, $use = function(usable) { + return ReactSharedInternals.H.use(usable); +}, $useActionState = function(action, initialState, permalink) { + return ReactSharedInternals.H.useActionState(action, initialState, permalink); +}, $useCallback = function(callback, deps) { + return ReactSharedInternals.H.useCallback(callback, deps); +}, $useContext = function(Context) { + return ReactSharedInternals.H.useContext(Context); +}, $useDebugValue = function() {}, $useDeferredValue = function(value, initialValue) { + return ReactSharedInternals.H.useDeferredValue(value, initialValue); +}, $useEffect = function(create, deps) { + return ReactSharedInternals.H.useEffect(create, deps); +}, $useEffectEvent = function(callback) { + return ReactSharedInternals.H.useEffectEvent(callback); +}, $useId = function() { + return ReactSharedInternals.H.useId(); +}, $useImperativeHandle = function(ref, create, deps) { + return ReactSharedInternals.H.useImperativeHandle(ref, create, deps); +}, $useInsertionEffect = function(create, deps) { + return ReactSharedInternals.H.useInsertionEffect(create, deps); +}, $useLayoutEffect = function(create, deps) { + return ReactSharedInternals.H.useLayoutEffect(create, deps); +}, $useMemo = function(create, deps) { + return ReactSharedInternals.H.useMemo(create, deps); +}, $useOptimistic = function(passthrough, reducer) { + return ReactSharedInternals.H.useOptimistic(passthrough, reducer); +}, $useReducer = function(reducer, initialArg, init) { + return ReactSharedInternals.H.useReducer(reducer, initialArg, init); +}, $useRef = function(initialValue) { + return ReactSharedInternals.H.useRef(initialValue); +}, $useState = function(initialState) { + return ReactSharedInternals.H.useState(initialState); +}, $useSyncExternalStore = function(subscribe, getSnapshot, getServerSnapshot) { + return ReactSharedInternals.H.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot); +}, $useTransition = function() { + return ReactSharedInternals.H.useTransition(); +}, $version = "19.2.4"; +var init_react_production = __esm(() => { + REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"); + REACT_PORTAL_TYPE = Symbol.for("react.portal"); + REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"); + REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"); + REACT_PROFILER_TYPE = Symbol.for("react.profiler"); + REACT_CONSUMER_TYPE = Symbol.for("react.consumer"); + REACT_CONTEXT_TYPE = Symbol.for("react.context"); + REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"); + REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"); + REACT_MEMO_TYPE = Symbol.for("react.memo"); + REACT_LAZY_TYPE = Symbol.for("react.lazy"); + REACT_ACTIVITY_TYPE = Symbol.for("react.activity"); + MAYBE_ITERATOR_SYMBOL = Symbol.iterator; + ReactNoopUpdateQueue = { + isMounted: function() { + return false; + }, + enqueueForceUpdate: function() {}, + enqueueReplaceState: function() {}, + enqueueSetState: function() {} + }; + assign = Object.assign; + emptyObject = {}; + Component.prototype.isReactComponent = {}; + Component.prototype.setState = function(partialState, callback) { + if (typeof partialState !== "object" && typeof partialState !== "function" && partialState != null) + throw Error("takes an object of state variables to update or a function which returns an object of state variables."); + this.updater.enqueueSetState(this, partialState, callback, "setState"); + }; + Component.prototype.forceUpdate = function(callback) { + this.updater.enqueueForceUpdate(this, callback, "forceUpdate"); + }; + ComponentDummy.prototype = Component.prototype; + pureComponentPrototype = PureComponent.prototype = new ComponentDummy; + pureComponentPrototype.constructor = PureComponent; + assign(pureComponentPrototype, Component.prototype); + pureComponentPrototype.isPureReactComponent = true; + isArrayImpl = Array.isArray; + ReactSharedInternals = { H: null, A: null, T: null, S: null }; + hasOwnProperty = Object.prototype.hasOwnProperty; + userProvidedKeyEscapeRegex = /\/+/g; + reportGlobalError = typeof reportError === "function" ? reportError : function(error) { + if (typeof window === "object" && typeof window.ErrorEvent === "function") { + var event = new window.ErrorEvent("error", { + bubbles: true, + cancelable: true, + message: typeof error === "object" && error !== null && typeof error.message === "string" ? String(error.message) : String(error), + error + }); + if (!window.dispatchEvent(event)) + return; + } else if (typeof process === "object" && typeof process.emit === "function") { + process.emit("uncaughtException", error); + return; + } + console.error(error); + }; + Children = { + map: mapChildren, + forEach: function(children, forEachFunc, forEachContext) { + mapChildren(children, function() { + forEachFunc.apply(this, arguments); + }, forEachContext); + }, + count: function(children) { + var n = 0; + mapChildren(children, function() { + n++; + }); + return n; + }, + toArray: function(children) { + return mapChildren(children, function(child) { + return child; + }) || []; + }, + only: function(children) { + if (!isValidElement(children)) + throw Error("React.Children.only expected to receive a single React element child."); + return children; + } + }; + $Activity = REACT_ACTIVITY_TYPE; + $Children = Children; + $Component = Component; + $Fragment = REACT_FRAGMENT_TYPE; + $Profiler = REACT_PROFILER_TYPE; + $PureComponent = PureComponent; + $StrictMode = REACT_STRICT_MODE_TYPE; + $Suspense = REACT_SUSPENSE_TYPE; + $__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE = ReactSharedInternals; + $__COMPILER_RUNTIME = { + __proto__: null, + c: function(size) { + return ReactSharedInternals.H.useMemoCache(size); + } + }; + $isValidElement = isValidElement; +}); + +// node_modules/react/index.js +var require_react = __commonJS((exports, module) => { + init_react_production(); + if (true) { + module.exports = exports_react_production; + } +}); + +// node_modules/scheduler/cjs/scheduler.production.js +var exports_scheduler_production = {}; +__export(exports_scheduler_production, { + unstable_wrapCallback: () => $unstable_wrapCallback, + unstable_shouldYield: () => $unstable_shouldYield, + unstable_scheduleCallback: () => $unstable_scheduleCallback, + unstable_runWithPriority: () => $unstable_runWithPriority, + unstable_requestPaint: () => $unstable_requestPaint, + unstable_now: () => $unstable_now, + unstable_next: () => $unstable_next, + unstable_getCurrentPriorityLevel: () => $unstable_getCurrentPriorityLevel, + unstable_forceFrameRate: () => $unstable_forceFrameRate, + unstable_cancelCallback: () => $unstable_cancelCallback, + unstable_UserBlockingPriority: () => $unstable_UserBlockingPriority, + unstable_Profiling: () => $unstable_Profiling, + unstable_NormalPriority: () => $unstable_NormalPriority, + unstable_LowPriority: () => $unstable_LowPriority, + unstable_ImmediatePriority: () => $unstable_ImmediatePriority, + unstable_IdlePriority: () => $unstable_IdlePriority +}); +function push(heap, node) { + var index = heap.length; + heap.push(node); + a: + for (;0 < index; ) { + var parentIndex = index - 1 >>> 1, parent = heap[parentIndex]; + if (0 < compare(parent, node)) + heap[parentIndex] = node, heap[index] = parent, index = parentIndex; + else + break a; + } +} +function peek(heap) { + return heap.length === 0 ? null : heap[0]; +} +function pop(heap) { + if (heap.length === 0) + return null; + var first = heap[0], last = heap.pop(); + if (last !== first) { + heap[0] = last; + a: + for (var index = 0, length = heap.length, halfLength = length >>> 1;index < halfLength; ) { + var leftIndex = 2 * (index + 1) - 1, left = heap[leftIndex], rightIndex = leftIndex + 1, right = heap[rightIndex]; + if (0 > compare(left, last)) + rightIndex < length && 0 > compare(right, left) ? (heap[index] = right, heap[rightIndex] = last, index = rightIndex) : (heap[index] = left, heap[leftIndex] = last, index = leftIndex); + else if (rightIndex < length && 0 > compare(right, last)) + heap[index] = right, heap[rightIndex] = last, index = rightIndex; + else + break a; + } + } + return first; +} +function compare(a, b) { + var diff = a.sortIndex - b.sortIndex; + return diff !== 0 ? diff : a.id - b.id; +} +function advanceTimers(currentTime) { + for (var timer = peek(timerQueue);timer !== null; ) { + if (timer.callback === null) + pop(timerQueue); + else if (timer.startTime <= currentTime) + pop(timerQueue), timer.sortIndex = timer.expirationTime, push(taskQueue, timer); + else + break; + timer = peek(timerQueue); + } +} +function handleTimeout(currentTime) { + isHostTimeoutScheduled = false; + advanceTimers(currentTime); + if (!isHostCallbackScheduled) + if (peek(taskQueue) !== null) + isHostCallbackScheduled = true, isMessageLoopRunning || (isMessageLoopRunning = true, schedulePerformWorkUntilDeadline()); + else { + var firstTimer = peek(timerQueue); + firstTimer !== null && requestHostTimeout(handleTimeout, firstTimer.startTime - currentTime); + } +} +function shouldYieldToHost() { + return needsPaint ? true : $unstable_now() - startTime < frameInterval ? false : true; +} +function performWorkUntilDeadline() { + needsPaint = false; + if (isMessageLoopRunning) { + var currentTime = $unstable_now(); + startTime = currentTime; + var hasMoreWork = true; + try { + a: { + isHostCallbackScheduled = false; + isHostTimeoutScheduled && (isHostTimeoutScheduled = false, localClearTimeout(taskTimeoutID), taskTimeoutID = -1); + isPerformingWork = true; + var previousPriorityLevel = currentPriorityLevel; + try { + b: { + advanceTimers(currentTime); + for (currentTask = peek(taskQueue);currentTask !== null && !(currentTask.expirationTime > currentTime && shouldYieldToHost()); ) { + var callback = currentTask.callback; + if (typeof callback === "function") { + currentTask.callback = null; + currentPriorityLevel = currentTask.priorityLevel; + var continuationCallback = callback(currentTask.expirationTime <= currentTime); + currentTime = $unstable_now(); + if (typeof continuationCallback === "function") { + currentTask.callback = continuationCallback; + advanceTimers(currentTime); + hasMoreWork = true; + break b; + } + currentTask === peek(taskQueue) && pop(taskQueue); + advanceTimers(currentTime); + } else + pop(taskQueue); + currentTask = peek(taskQueue); + } + if (currentTask !== null) + hasMoreWork = true; + else { + var firstTimer = peek(timerQueue); + firstTimer !== null && requestHostTimeout(handleTimeout, firstTimer.startTime - currentTime); + hasMoreWork = false; + } + } + break a; + } finally { + currentTask = null, currentPriorityLevel = previousPriorityLevel, isPerformingWork = false; + } + hasMoreWork = undefined; + } + } finally { + hasMoreWork ? schedulePerformWorkUntilDeadline() : isMessageLoopRunning = false; + } + } +} +function requestHostTimeout(callback, ms) { + taskTimeoutID = localSetTimeout(function() { + callback($unstable_now()); + }, ms); +} +var $unstable_now = undefined, localPerformance, localDate, initialTime, taskQueue, timerQueue, taskIdCounter = 1, currentTask = null, currentPriorityLevel = 3, isPerformingWork = false, isHostCallbackScheduled = false, isHostTimeoutScheduled = false, needsPaint = false, localSetTimeout, localClearTimeout, localSetImmediate, isMessageLoopRunning = false, taskTimeoutID = -1, frameInterval = 5, startTime = -1, schedulePerformWorkUntilDeadline, channel, port, $unstable_IdlePriority = 5, $unstable_ImmediatePriority = 1, $unstable_LowPriority = 4, $unstable_NormalPriority = 3, $unstable_Profiling = null, $unstable_UserBlockingPriority = 2, $unstable_cancelCallback = function(task) { + task.callback = null; +}, $unstable_forceFrameRate = function(fps) { + 0 > fps || 125 < fps ? console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported") : frameInterval = 0 < fps ? Math.floor(1000 / fps) : 5; +}, $unstable_getCurrentPriorityLevel = function() { + return currentPriorityLevel; +}, $unstable_next = function(eventHandler) { + switch (currentPriorityLevel) { + case 1: + case 2: + case 3: + var priorityLevel = 3; + break; + default: + priorityLevel = currentPriorityLevel; + } + var previousPriorityLevel = currentPriorityLevel; + currentPriorityLevel = priorityLevel; + try { + return eventHandler(); + } finally { + currentPriorityLevel = previousPriorityLevel; + } +}, $unstable_requestPaint = function() { + needsPaint = true; +}, $unstable_runWithPriority = function(priorityLevel, eventHandler) { + switch (priorityLevel) { + case 1: + case 2: + case 3: + case 4: + case 5: + break; + default: + priorityLevel = 3; + } + var previousPriorityLevel = currentPriorityLevel; + currentPriorityLevel = priorityLevel; + try { + return eventHandler(); + } finally { + currentPriorityLevel = previousPriorityLevel; + } +}, $unstable_scheduleCallback = function(priorityLevel, callback, options) { + var currentTime = $unstable_now(); + typeof options === "object" && options !== null ? (options = options.delay, options = typeof options === "number" && 0 < options ? currentTime + options : currentTime) : options = currentTime; + switch (priorityLevel) { + case 1: + var timeout = -1; + break; + case 2: + timeout = 250; + break; + case 5: + timeout = 1073741823; + break; + case 4: + timeout = 1e4; + break; + default: + timeout = 5000; + } + timeout = options + timeout; + priorityLevel = { + id: taskIdCounter++, + callback, + priorityLevel, + startTime: options, + expirationTime: timeout, + sortIndex: -1 + }; + options > currentTime ? (priorityLevel.sortIndex = options, push(timerQueue, priorityLevel), peek(taskQueue) === null && priorityLevel === peek(timerQueue) && (isHostTimeoutScheduled ? (localClearTimeout(taskTimeoutID), taskTimeoutID = -1) : isHostTimeoutScheduled = true, requestHostTimeout(handleTimeout, options - currentTime))) : (priorityLevel.sortIndex = timeout, push(taskQueue, priorityLevel), isHostCallbackScheduled || isPerformingWork || (isHostCallbackScheduled = true, isMessageLoopRunning || (isMessageLoopRunning = true, schedulePerformWorkUntilDeadline()))); + return priorityLevel; +}, $unstable_shouldYield, $unstable_wrapCallback = function(callback) { + var parentPriorityLevel = currentPriorityLevel; + return function() { + var previousPriorityLevel = currentPriorityLevel; + currentPriorityLevel = parentPriorityLevel; + try { + return callback.apply(this, arguments); + } finally { + currentPriorityLevel = previousPriorityLevel; + } + }; +}; +var init_scheduler_production = __esm(() => { + if (typeof performance === "object" && typeof performance.now === "function") { + localPerformance = performance; + $unstable_now = function() { + return localPerformance.now(); + }; + } else { + localDate = Date, initialTime = localDate.now(); + $unstable_now = function() { + return localDate.now() - initialTime; + }; + } + taskQueue = []; + timerQueue = []; + localSetTimeout = typeof setTimeout === "function" ? setTimeout : null; + localClearTimeout = typeof clearTimeout === "function" ? clearTimeout : null; + localSetImmediate = typeof setImmediate !== "undefined" ? setImmediate : null; + if (typeof localSetImmediate === "function") + schedulePerformWorkUntilDeadline = function() { + localSetImmediate(performWorkUntilDeadline); + }; + else if (typeof MessageChannel !== "undefined") { + channel = new MessageChannel, port = channel.port2; + channel.port1.onmessage = performWorkUntilDeadline; + schedulePerformWorkUntilDeadline = function() { + port.postMessage(null); + }; + } else + schedulePerformWorkUntilDeadline = function() { + localSetTimeout(performWorkUntilDeadline, 0); + }; + $unstable_shouldYield = shouldYieldToHost; +}); + +// node_modules/scheduler/index.js +var require_scheduler = __commonJS((exports, module) => { + init_scheduler_production(); + if (true) { + module.exports = exports_scheduler_production; + } +}); + +// node_modules/react-dom/cjs/react-dom.production.js +var exports_react_dom_production = {}; +__export(exports_react_dom_production, { + version: () => $version2, + useFormStatus: () => $useFormStatus, + useFormState: () => $useFormState, + unstable_batchedUpdates: () => $unstable_batchedUpdates, + requestFormReset: () => $requestFormReset, + preloadModule: () => $preloadModule, + preload: () => $preload, + preinitModule: () => $preinitModule, + preinit: () => $preinit, + prefetchDNS: () => $prefetchDNS, + preconnect: () => $preconnect, + flushSync: () => $flushSync, + createPortal: () => $createPortal, + __DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE: () => $__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE +}); +function formatProdErrorMessage(code) { + var url = "https://react.dev/errors/" + code; + if (1 < arguments.length) { + url += "?args[]=" + encodeURIComponent(arguments[1]); + for (var i = 2;i < arguments.length; i++) + url += "&args[]=" + encodeURIComponent(arguments[i]); + } + return "Minified React error #" + code + "; visit " + url + " for the full message or use the non-minified dev environment for full errors and additional helpful warnings."; +} +function noop2() {} +function createPortal$1(children, containerInfo, implementation) { + var key = 3 < arguments.length && arguments[3] !== undefined ? arguments[3] : null; + return { + $$typeof: REACT_PORTAL_TYPE2, + key: key == null ? null : "" + key, + children, + containerInfo, + implementation + }; +} +function getCrossOriginStringAs(as, input) { + if (as === "font") + return ""; + if (typeof input === "string") + return input === "use-credentials" ? input : ""; +} +var React, Internals, REACT_PORTAL_TYPE2, ReactSharedInternals2, $__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, $createPortal = function(children, container) { + var key = 2 < arguments.length && arguments[2] !== undefined ? arguments[2] : null; + if (!container || container.nodeType !== 1 && container.nodeType !== 9 && container.nodeType !== 11) + throw Error(formatProdErrorMessage(299)); + return createPortal$1(children, container, null, key); +}, $flushSync = function(fn) { + var previousTransition = ReactSharedInternals2.T, previousUpdatePriority = Internals.p; + try { + if (ReactSharedInternals2.T = null, Internals.p = 2, fn) + return fn(); + } finally { + ReactSharedInternals2.T = previousTransition, Internals.p = previousUpdatePriority, Internals.d.f(); + } +}, $preconnect = function(href, options) { + typeof href === "string" && (options ? (options = options.crossOrigin, options = typeof options === "string" ? options === "use-credentials" ? options : "" : undefined) : options = null, Internals.d.C(href, options)); +}, $prefetchDNS = function(href) { + typeof href === "string" && Internals.d.D(href); +}, $preinit = function(href, options) { + if (typeof href === "string" && options && typeof options.as === "string") { + var as = options.as, crossOrigin = getCrossOriginStringAs(as, options.crossOrigin), integrity = typeof options.integrity === "string" ? options.integrity : undefined, fetchPriority = typeof options.fetchPriority === "string" ? options.fetchPriority : undefined; + as === "style" ? Internals.d.S(href, typeof options.precedence === "string" ? options.precedence : undefined, { + crossOrigin, + integrity, + fetchPriority + }) : as === "script" && Internals.d.X(href, { + crossOrigin, + integrity, + fetchPriority, + nonce: typeof options.nonce === "string" ? options.nonce : undefined + }); + } +}, $preinitModule = function(href, options) { + if (typeof href === "string") + if (typeof options === "object" && options !== null) { + if (options.as == null || options.as === "script") { + var crossOrigin = getCrossOriginStringAs(options.as, options.crossOrigin); + Internals.d.M(href, { + crossOrigin, + integrity: typeof options.integrity === "string" ? options.integrity : undefined, + nonce: typeof options.nonce === "string" ? options.nonce : undefined + }); + } + } else + options == null && Internals.d.M(href); +}, $preload = function(href, options) { + if (typeof href === "string" && typeof options === "object" && options !== null && typeof options.as === "string") { + var as = options.as, crossOrigin = getCrossOriginStringAs(as, options.crossOrigin); + Internals.d.L(href, as, { + crossOrigin, + integrity: typeof options.integrity === "string" ? options.integrity : undefined, + nonce: typeof options.nonce === "string" ? options.nonce : undefined, + type: typeof options.type === "string" ? options.type : undefined, + fetchPriority: typeof options.fetchPriority === "string" ? options.fetchPriority : undefined, + referrerPolicy: typeof options.referrerPolicy === "string" ? options.referrerPolicy : undefined, + imageSrcSet: typeof options.imageSrcSet === "string" ? options.imageSrcSet : undefined, + imageSizes: typeof options.imageSizes === "string" ? options.imageSizes : undefined, + media: typeof options.media === "string" ? options.media : undefined + }); + } +}, $preloadModule = function(href, options) { + if (typeof href === "string") + if (options) { + var crossOrigin = getCrossOriginStringAs(options.as, options.crossOrigin); + Internals.d.m(href, { + as: typeof options.as === "string" && options.as !== "script" ? options.as : undefined, + crossOrigin, + integrity: typeof options.integrity === "string" ? options.integrity : undefined + }); + } else + Internals.d.m(href); +}, $requestFormReset = function(form) { + Internals.d.r(form); +}, $unstable_batchedUpdates = function(fn, a) { + return fn(a); +}, $useFormState = function(action, initialState, permalink) { + return ReactSharedInternals2.H.useFormState(action, initialState, permalink); +}, $useFormStatus = function() { + return ReactSharedInternals2.H.useHostTransitionStatus(); +}, $version2 = "19.2.4"; +var init_react_dom_production = __esm(() => { + React = __toESM(require_react(), 1); + Internals = { + d: { + f: noop2, + r: function() { + throw Error(formatProdErrorMessage(522)); + }, + D: noop2, + C: noop2, + L: noop2, + m: noop2, + X: noop2, + S: noop2, + M: noop2 + }, + p: 0, + findDOMNode: null + }; + REACT_PORTAL_TYPE2 = Symbol.for("react.portal"); + ReactSharedInternals2 = React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE; + $__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE = Internals; +}); + +// node_modules/react-dom/index.js +var require_react_dom = __commonJS((exports, module) => { + init_react_dom_production(); + function checkDCE() { + if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === "undefined" || typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE !== "function") { + return; + } + if (false) {} + try { + __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(checkDCE); + } catch (err) { + console.error(err); + } + } + if (true) { + checkDCE(); + module.exports = exports_react_dom_production; + } +}); + +// node_modules/react-dom/cjs/react-dom-client.production.js +var exports_react_dom_client_production = {}; +__export(exports_react_dom_client_production, { + version: () => $version3, + hydrateRoot: () => $hydrateRoot, + createRoot: () => $createRoot +}); +function formatProdErrorMessage2(code) { + var url = "https://react.dev/errors/" + code; + if (1 < arguments.length) { + url += "?args[]=" + encodeURIComponent(arguments[1]); + for (var i = 2;i < arguments.length; i++) + url += "&args[]=" + encodeURIComponent(arguments[i]); + } + return "Minified React error #" + code + "; visit " + url + " for the full message or use the non-minified dev environment for full errors and additional helpful warnings."; +} +function isValidContainer(node) { + return !(!node || node.nodeType !== 1 && node.nodeType !== 9 && node.nodeType !== 11); +} +function getNearestMountedFiber(fiber) { + var node = fiber, nearestMounted = fiber; + if (fiber.alternate) + for (;node.return; ) + node = node.return; + else { + fiber = node; + do + node = fiber, (node.flags & 4098) !== 0 && (nearestMounted = node.return), fiber = node.return; + while (fiber); + } + return node.tag === 3 ? nearestMounted : null; +} +function getSuspenseInstanceFromFiber(fiber) { + if (fiber.tag === 13) { + var suspenseState = fiber.memoizedState; + suspenseState === null && (fiber = fiber.alternate, fiber !== null && (suspenseState = fiber.memoizedState)); + if (suspenseState !== null) + return suspenseState.dehydrated; + } + return null; +} +function getActivityInstanceFromFiber(fiber) { + if (fiber.tag === 31) { + var activityState = fiber.memoizedState; + activityState === null && (fiber = fiber.alternate, fiber !== null && (activityState = fiber.memoizedState)); + if (activityState !== null) + return activityState.dehydrated; + } + return null; +} +function assertIsMounted(fiber) { + if (getNearestMountedFiber(fiber) !== fiber) + throw Error(formatProdErrorMessage2(188)); +} +function findCurrentFiberUsingSlowPath(fiber) { + var alternate = fiber.alternate; + if (!alternate) { + alternate = getNearestMountedFiber(fiber); + if (alternate === null) + throw Error(formatProdErrorMessage2(188)); + return alternate !== fiber ? null : fiber; + } + for (var a = fiber, b = alternate;; ) { + var parentA = a.return; + if (parentA === null) + break; + var parentB = parentA.alternate; + if (parentB === null) { + b = parentA.return; + if (b !== null) { + a = b; + continue; + } + break; + } + if (parentA.child === parentB.child) { + for (parentB = parentA.child;parentB; ) { + if (parentB === a) + return assertIsMounted(parentA), fiber; + if (parentB === b) + return assertIsMounted(parentA), alternate; + parentB = parentB.sibling; + } + throw Error(formatProdErrorMessage2(188)); + } + if (a.return !== b.return) + a = parentA, b = parentB; + else { + for (var didFindChild = false, child$0 = parentA.child;child$0; ) { + if (child$0 === a) { + didFindChild = true; + a = parentA; + b = parentB; + break; + } + if (child$0 === b) { + didFindChild = true; + b = parentA; + a = parentB; + break; + } + child$0 = child$0.sibling; + } + if (!didFindChild) { + for (child$0 = parentB.child;child$0; ) { + if (child$0 === a) { + didFindChild = true; + a = parentB; + b = parentA; + break; + } + if (child$0 === b) { + didFindChild = true; + b = parentB; + a = parentA; + break; + } + child$0 = child$0.sibling; + } + if (!didFindChild) + throw Error(formatProdErrorMessage2(189)); + } + } + if (a.alternate !== b) + throw Error(formatProdErrorMessage2(190)); + } + if (a.tag !== 3) + throw Error(formatProdErrorMessage2(188)); + return a.stateNode.current === a ? fiber : alternate; +} +function findCurrentHostFiberImpl(node) { + var tag = node.tag; + if (tag === 5 || tag === 26 || tag === 27 || tag === 6) + return node; + for (node = node.child;node !== null; ) { + tag = findCurrentHostFiberImpl(node); + if (tag !== null) + return tag; + node = node.sibling; + } + return null; +} +function getIteratorFn2(maybeIterable) { + if (maybeIterable === null || typeof maybeIterable !== "object") + return null; + maybeIterable = MAYBE_ITERATOR_SYMBOL2 && maybeIterable[MAYBE_ITERATOR_SYMBOL2] || maybeIterable["@@iterator"]; + return typeof maybeIterable === "function" ? maybeIterable : null; +} +function getComponentNameFromType(type) { + if (type == null) + return null; + if (typeof type === "function") + return type.$$typeof === REACT_CLIENT_REFERENCE ? null : type.displayName || type.name || null; + if (typeof type === "string") + return type; + switch (type) { + case REACT_FRAGMENT_TYPE2: + return "Fragment"; + case REACT_PROFILER_TYPE2: + return "Profiler"; + case REACT_STRICT_MODE_TYPE2: + return "StrictMode"; + case REACT_SUSPENSE_TYPE2: + return "Suspense"; + case REACT_SUSPENSE_LIST_TYPE: + return "SuspenseList"; + case REACT_ACTIVITY_TYPE2: + return "Activity"; + } + if (typeof type === "object") + switch (type.$$typeof) { + case REACT_PORTAL_TYPE3: + return "Portal"; + case REACT_CONTEXT_TYPE2: + return type.displayName || "Context"; + case REACT_CONSUMER_TYPE2: + return (type._context.displayName || "Context") + ".Consumer"; + case REACT_FORWARD_REF_TYPE2: + var innerType = type.render; + type = type.displayName; + type || (type = innerType.displayName || innerType.name || "", type = type !== "" ? "ForwardRef(" + type + ")" : "ForwardRef"); + return type; + case REACT_MEMO_TYPE2: + return innerType = type.displayName || null, innerType !== null ? innerType : getComponentNameFromType(type.type) || "Memo"; + case REACT_LAZY_TYPE2: + innerType = type._payload; + type = type._init; + try { + return getComponentNameFromType(type(innerType)); + } catch (x) {} + } + return null; +} +function createCursor(defaultValue) { + return { current: defaultValue }; +} +function pop2(cursor) { + 0 > index || (cursor.current = valueStack[index], valueStack[index] = null, index--); +} +function push2(cursor, value) { + index++; + valueStack[index] = cursor.current; + cursor.current = value; +} +function pushHostContainer(fiber, nextRootInstance) { + push2(rootInstanceStackCursor, nextRootInstance); + push2(contextFiberStackCursor, fiber); + push2(contextStackCursor, null); + switch (nextRootInstance.nodeType) { + case 9: + case 11: + fiber = (fiber = nextRootInstance.documentElement) ? (fiber = fiber.namespaceURI) ? getOwnHostContext(fiber) : 0 : 0; + break; + default: + if (fiber = nextRootInstance.tagName, nextRootInstance = nextRootInstance.namespaceURI) + nextRootInstance = getOwnHostContext(nextRootInstance), fiber = getChildHostContextProd(nextRootInstance, fiber); + else + switch (fiber) { + case "svg": + fiber = 1; + break; + case "math": + fiber = 2; + break; + default: + fiber = 0; + } + } + pop2(contextStackCursor); + push2(contextStackCursor, fiber); +} +function popHostContainer() { + pop2(contextStackCursor); + pop2(contextFiberStackCursor); + pop2(rootInstanceStackCursor); +} +function pushHostContext(fiber) { + fiber.memoizedState !== null && push2(hostTransitionProviderCursor, fiber); + var context = contextStackCursor.current; + var JSCompiler_inline_result = getChildHostContextProd(context, fiber.type); + context !== JSCompiler_inline_result && (push2(contextFiberStackCursor, fiber), push2(contextStackCursor, JSCompiler_inline_result)); +} +function popHostContext(fiber) { + contextFiberStackCursor.current === fiber && (pop2(contextStackCursor), pop2(contextFiberStackCursor)); + hostTransitionProviderCursor.current === fiber && (pop2(hostTransitionProviderCursor), HostTransitionContext._currentValue = sharedNotPendingObject); +} +function describeBuiltInComponentFrame(name) { + if (prefix === undefined) + try { + throw Error(); + } catch (x) { + var match = x.stack.trim().match(/\n( *(at )?)/); + prefix = match && match[1] || ""; + suffix = -1 < x.stack.indexOf(` + at`) ? " ()" : -1 < x.stack.indexOf("@") ? "@unknown:0:0" : ""; + } + return ` +` + prefix + name + suffix; +} +function describeNativeComponentFrame(fn, construct) { + if (!fn || reentry) + return ""; + reentry = true; + var previousPrepareStackTrace = Error.prepareStackTrace; + Error.prepareStackTrace = undefined; + try { + var RunInRootFrame = { + DetermineComponentFrameRoot: function() { + try { + if (construct) { + var Fake = function() { + throw Error(); + }; + Object.defineProperty(Fake.prototype, "props", { + set: function() { + throw Error(); + } + }); + if (typeof Reflect === "object" && Reflect.construct) { + try { + Reflect.construct(Fake, []); + } catch (x) { + var control = x; + } + Reflect.construct(fn, [], Fake); + } else { + try { + Fake.call(); + } catch (x$1) { + control = x$1; + } + fn.call(Fake.prototype); + } + } else { + try { + throw Error(); + } catch (x$2) { + control = x$2; + } + (Fake = fn()) && typeof Fake.catch === "function" && Fake.catch(function() {}); + } + } catch (sample) { + if (sample && control && typeof sample.stack === "string") + return [sample.stack, control.stack]; + } + return [null, null]; + } + }; + RunInRootFrame.DetermineComponentFrameRoot.displayName = "DetermineComponentFrameRoot"; + var namePropDescriptor = Object.getOwnPropertyDescriptor(RunInRootFrame.DetermineComponentFrameRoot, "name"); + namePropDescriptor && namePropDescriptor.configurable && Object.defineProperty(RunInRootFrame.DetermineComponentFrameRoot, "name", { value: "DetermineComponentFrameRoot" }); + var _RunInRootFrame$Deter = RunInRootFrame.DetermineComponentFrameRoot(), sampleStack = _RunInRootFrame$Deter[0], controlStack = _RunInRootFrame$Deter[1]; + if (sampleStack && controlStack) { + var sampleLines = sampleStack.split(` +`), controlLines = controlStack.split(` +`); + for (namePropDescriptor = RunInRootFrame = 0;RunInRootFrame < sampleLines.length && !sampleLines[RunInRootFrame].includes("DetermineComponentFrameRoot"); ) + RunInRootFrame++; + for (;namePropDescriptor < controlLines.length && !controlLines[namePropDescriptor].includes("DetermineComponentFrameRoot"); ) + namePropDescriptor++; + if (RunInRootFrame === sampleLines.length || namePropDescriptor === controlLines.length) + for (RunInRootFrame = sampleLines.length - 1, namePropDescriptor = controlLines.length - 1;1 <= RunInRootFrame && 0 <= namePropDescriptor && sampleLines[RunInRootFrame] !== controlLines[namePropDescriptor]; ) + namePropDescriptor--; + for (;1 <= RunInRootFrame && 0 <= namePropDescriptor; RunInRootFrame--, namePropDescriptor--) + if (sampleLines[RunInRootFrame] !== controlLines[namePropDescriptor]) { + if (RunInRootFrame !== 1 || namePropDescriptor !== 1) { + do + if (RunInRootFrame--, namePropDescriptor--, 0 > namePropDescriptor || sampleLines[RunInRootFrame] !== controlLines[namePropDescriptor]) { + var frame = ` +` + sampleLines[RunInRootFrame].replace(" at new ", " at "); + fn.displayName && frame.includes("") && (frame = frame.replace("", fn.displayName)); + return frame; + } + while (1 <= RunInRootFrame && 0 <= namePropDescriptor); + } + break; + } + } + } finally { + reentry = false, Error.prepareStackTrace = previousPrepareStackTrace; + } + return (previousPrepareStackTrace = fn ? fn.displayName || fn.name : "") ? describeBuiltInComponentFrame(previousPrepareStackTrace) : ""; +} +function describeFiber(fiber, childFiber) { + switch (fiber.tag) { + case 26: + case 27: + case 5: + return describeBuiltInComponentFrame(fiber.type); + case 16: + return describeBuiltInComponentFrame("Lazy"); + case 13: + return fiber.child !== childFiber && childFiber !== null ? describeBuiltInComponentFrame("Suspense Fallback") : describeBuiltInComponentFrame("Suspense"); + case 19: + return describeBuiltInComponentFrame("SuspenseList"); + case 0: + case 15: + return describeNativeComponentFrame(fiber.type, false); + case 11: + return describeNativeComponentFrame(fiber.type.render, false); + case 1: + return describeNativeComponentFrame(fiber.type, true); + case 31: + return describeBuiltInComponentFrame("Activity"); + default: + return ""; + } +} +function getStackByFiberInDevAndProd(workInProgress) { + try { + var info = "", previous = null; + do + info += describeFiber(workInProgress, previous), previous = workInProgress, workInProgress = workInProgress.return; + while (workInProgress); + return info; + } catch (x) { + return ` +Error generating stack: ` + x.message + ` +` + x.stack; + } +} +function setIsStrictModeForDevtools(newIsStrictMode) { + typeof log$1 === "function" && unstable_setDisableYieldValue2(newIsStrictMode); + if (injectedHook && typeof injectedHook.setStrictMode === "function") + try { + injectedHook.setStrictMode(rendererID, newIsStrictMode); + } catch (err) {} +} +function clz32Fallback(x) { + x >>>= 0; + return x === 0 ? 32 : 31 - (log2(x) / LN2 | 0) | 0; +} +function getHighestPriorityLanes(lanes) { + var pendingSyncLanes = lanes & 42; + if (pendingSyncLanes !== 0) + return pendingSyncLanes; + switch (lanes & -lanes) { + 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: + return 64; + case 128: + return 128; + case 256: + case 512: + case 1024: + case 2048: + case 4096: + case 8192: + case 16384: + case 32768: + case 65536: + case 131072: + return lanes & 261888; + case 262144: + case 524288: + case 1048576: + case 2097152: + return lanes & 3932160; + case 4194304: + case 8388608: + case 16777216: + case 33554432: + return lanes & 62914560; + case 67108864: + return 67108864; + case 134217728: + return 134217728; + case 268435456: + return 268435456; + case 536870912: + return 536870912; + case 1073741824: + return 0; + default: + return lanes; + } +} +function getNextLanes(root, wipLanes, rootHasPendingCommit) { + var pendingLanes = root.pendingLanes; + if (pendingLanes === 0) + return 0; + var nextLanes = 0, suspendedLanes = root.suspendedLanes, pingedLanes = root.pingedLanes; + root = root.warmLanes; + var nonIdlePendingLanes = pendingLanes & 134217727; + nonIdlePendingLanes !== 0 ? (pendingLanes = nonIdlePendingLanes & ~suspendedLanes, pendingLanes !== 0 ? nextLanes = getHighestPriorityLanes(pendingLanes) : (pingedLanes &= nonIdlePendingLanes, pingedLanes !== 0 ? nextLanes = getHighestPriorityLanes(pingedLanes) : rootHasPendingCommit || (rootHasPendingCommit = nonIdlePendingLanes & ~root, rootHasPendingCommit !== 0 && (nextLanes = getHighestPriorityLanes(rootHasPendingCommit))))) : (nonIdlePendingLanes = pendingLanes & ~suspendedLanes, nonIdlePendingLanes !== 0 ? nextLanes = getHighestPriorityLanes(nonIdlePendingLanes) : pingedLanes !== 0 ? nextLanes = getHighestPriorityLanes(pingedLanes) : rootHasPendingCommit || (rootHasPendingCommit = pendingLanes & ~root, rootHasPendingCommit !== 0 && (nextLanes = getHighestPriorityLanes(rootHasPendingCommit)))); + return nextLanes === 0 ? 0 : wipLanes !== 0 && wipLanes !== nextLanes && (wipLanes & suspendedLanes) === 0 && (suspendedLanes = nextLanes & -nextLanes, rootHasPendingCommit = wipLanes & -wipLanes, suspendedLanes >= rootHasPendingCommit || suspendedLanes === 32 && (rootHasPendingCommit & 4194048) !== 0) ? wipLanes : nextLanes; +} +function checkIfRootIsPrerendering(root, renderLanes) { + return (root.pendingLanes & ~(root.suspendedLanes & ~root.pingedLanes) & renderLanes) === 0; +} +function computeExpirationTime(lane, currentTime) { + switch (lane) { + case 1: + case 2: + case 4: + case 8: + case 64: + return currentTime + 250; + case 16: + case 32: + 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 currentTime + 5000; + case 4194304: + case 8388608: + case 16777216: + case 33554432: + return -1; + case 67108864: + case 134217728: + case 268435456: + case 536870912: + case 1073741824: + return -1; + default: + return -1; + } +} +function claimNextRetryLane() { + var lane = nextRetryLane; + nextRetryLane <<= 1; + (nextRetryLane & 62914560) === 0 && (nextRetryLane = 4194304); + return lane; +} +function createLaneMap(initial) { + for (var laneMap = [], i = 0;31 > i; i++) + laneMap.push(initial); + return laneMap; +} +function markRootUpdated$1(root, updateLane) { + root.pendingLanes |= updateLane; + updateLane !== 268435456 && (root.suspendedLanes = 0, root.pingedLanes = 0, root.warmLanes = 0); +} +function markRootFinished(root, finishedLanes, remainingLanes, spawnedLane, updatedLanes, suspendedRetryLanes) { + var previouslyPendingLanes = root.pendingLanes; + root.pendingLanes = remainingLanes; + root.suspendedLanes = 0; + root.pingedLanes = 0; + root.warmLanes = 0; + root.expiredLanes &= remainingLanes; + root.entangledLanes &= remainingLanes; + root.errorRecoveryDisabledLanes &= remainingLanes; + root.shellSuspendCounter = 0; + var { entanglements, expirationTimes, hiddenUpdates } = root; + for (remainingLanes = previouslyPendingLanes & ~remainingLanes;0 < remainingLanes; ) { + var index$7 = 31 - clz32(remainingLanes), lane = 1 << index$7; + entanglements[index$7] = 0; + expirationTimes[index$7] = -1; + var hiddenUpdatesForLane = hiddenUpdates[index$7]; + if (hiddenUpdatesForLane !== null) + for (hiddenUpdates[index$7] = null, index$7 = 0;index$7 < hiddenUpdatesForLane.length; index$7++) { + var update = hiddenUpdatesForLane[index$7]; + update !== null && (update.lane &= -536870913); + } + remainingLanes &= ~lane; + } + spawnedLane !== 0 && markSpawnedDeferredLane(root, spawnedLane, 0); + suspendedRetryLanes !== 0 && updatedLanes === 0 && root.tag !== 0 && (root.suspendedLanes |= suspendedRetryLanes & ~(previouslyPendingLanes & ~finishedLanes)); +} +function markSpawnedDeferredLane(root, spawnedLane, entangledLanes) { + root.pendingLanes |= spawnedLane; + root.suspendedLanes &= ~spawnedLane; + var spawnedLaneIndex = 31 - clz32(spawnedLane); + root.entangledLanes |= spawnedLane; + root.entanglements[spawnedLaneIndex] = root.entanglements[spawnedLaneIndex] | 1073741824 | entangledLanes & 261930; +} +function markRootEntangled(root, entangledLanes) { + var rootEntangledLanes = root.entangledLanes |= entangledLanes; + for (root = root.entanglements;rootEntangledLanes; ) { + var index$8 = 31 - clz32(rootEntangledLanes), lane = 1 << index$8; + lane & entangledLanes | root[index$8] & entangledLanes && (root[index$8] |= entangledLanes); + rootEntangledLanes &= ~lane; + } +} +function getBumpedLaneForHydration(root, renderLanes) { + var renderLane = renderLanes & -renderLanes; + renderLane = (renderLane & 42) !== 0 ? 1 : getBumpedLaneForHydrationByLane(renderLane); + return (renderLane & (root.suspendedLanes | renderLanes)) !== 0 ? 0 : renderLane; +} +function getBumpedLaneForHydrationByLane(lane) { + switch (lane) { + case 2: + lane = 1; + break; + case 8: + lane = 4; + break; + case 32: + lane = 16; + break; + 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: + lane = 128; + break; + case 268435456: + lane = 134217728; + break; + default: + lane = 0; + } + return lane; +} +function lanesToEventPriority(lanes) { + lanes &= -lanes; + return 2 < lanes ? 8 < lanes ? (lanes & 134217727) !== 0 ? 32 : 268435456 : 8 : 2; +} +function resolveUpdatePriority() { + var updatePriority = ReactDOMSharedInternals.p; + if (updatePriority !== 0) + return updatePriority; + updatePriority = window.event; + return updatePriority === undefined ? 32 : getEventPriority(updatePriority.type); +} +function runWithPriority(priority, fn) { + var previousPriority = ReactDOMSharedInternals.p; + try { + return ReactDOMSharedInternals.p = priority, fn(); + } finally { + ReactDOMSharedInternals.p = previousPriority; + } +} +function detachDeletedInstance(node) { + delete node[internalInstanceKey]; + delete node[internalPropsKey]; + delete node[internalEventHandlersKey]; + delete node[internalEventHandlerListenersKey]; + delete node[internalEventHandlesSetKey]; +} +function getClosestInstanceFromNode(targetNode) { + var targetInst = targetNode[internalInstanceKey]; + if (targetInst) + return targetInst; + for (var parentNode = targetNode.parentNode;parentNode; ) { + if (targetInst = parentNode[internalContainerInstanceKey] || parentNode[internalInstanceKey]) { + parentNode = targetInst.alternate; + if (targetInst.child !== null || parentNode !== null && parentNode.child !== null) + for (targetNode = getParentHydrationBoundary(targetNode);targetNode !== null; ) { + if (parentNode = targetNode[internalInstanceKey]) + return parentNode; + targetNode = getParentHydrationBoundary(targetNode); + } + return targetInst; + } + targetNode = parentNode; + parentNode = targetNode.parentNode; + } + return null; +} +function getInstanceFromNode(node) { + if (node = node[internalInstanceKey] || node[internalContainerInstanceKey]) { + var tag = node.tag; + if (tag === 5 || tag === 6 || tag === 13 || tag === 31 || tag === 26 || tag === 27 || tag === 3) + return node; + } + return null; +} +function getNodeFromInstance(inst) { + var tag = inst.tag; + if (tag === 5 || tag === 26 || tag === 27 || tag === 6) + return inst.stateNode; + throw Error(formatProdErrorMessage2(33)); +} +function getResourcesFromRoot(root) { + var resources = root[internalRootNodeResourcesKey]; + resources || (resources = root[internalRootNodeResourcesKey] = { hoistableStyles: new Map, hoistableScripts: new Map }); + return resources; +} +function markNodeAsHoistable(node) { + node[internalHoistableMarker] = true; +} +function registerTwoPhaseEvent(registrationName, dependencies) { + registerDirectEvent(registrationName, dependencies); + registerDirectEvent(registrationName + "Capture", dependencies); +} +function registerDirectEvent(registrationName, dependencies) { + registrationNameDependencies[registrationName] = dependencies; + for (registrationName = 0;registrationName < dependencies.length; registrationName++) + allNativeEvents.add(dependencies[registrationName]); +} +function isAttributeNameSafe(attributeName) { + if (hasOwnProperty2.call(validatedAttributeNameCache, attributeName)) + return true; + if (hasOwnProperty2.call(illegalAttributeNameCache, attributeName)) + return false; + if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) + return validatedAttributeNameCache[attributeName] = true; + illegalAttributeNameCache[attributeName] = true; + return false; +} +function setValueForAttribute(node, name, value) { + if (isAttributeNameSafe(name)) + if (value === null) + node.removeAttribute(name); + else { + switch (typeof value) { + case "undefined": + case "function": + case "symbol": + node.removeAttribute(name); + return; + case "boolean": + var prefix$10 = name.toLowerCase().slice(0, 5); + if (prefix$10 !== "data-" && prefix$10 !== "aria-") { + node.removeAttribute(name); + return; + } + } + node.setAttribute(name, "" + value); + } +} +function setValueForKnownAttribute(node, name, value) { + if (value === null) + node.removeAttribute(name); + else { + switch (typeof value) { + case "undefined": + case "function": + case "symbol": + case "boolean": + node.removeAttribute(name); + return; + } + node.setAttribute(name, "" + value); + } +} +function setValueForNamespacedAttribute(node, namespace, name, value) { + if (value === null) + node.removeAttribute(name); + else { + switch (typeof value) { + case "undefined": + case "function": + case "symbol": + case "boolean": + node.removeAttribute(name); + return; + } + node.setAttributeNS(namespace, name, "" + value); + } +} +function getToStringValue(value) { + switch (typeof value) { + case "bigint": + case "boolean": + case "number": + case "string": + case "undefined": + return value; + case "object": + return value; + default: + return ""; + } +} +function isCheckable(elem) { + var type = elem.type; + return (elem = elem.nodeName) && elem.toLowerCase() === "input" && (type === "checkbox" || type === "radio"); +} +function trackValueOnNode(node, valueField, currentValue) { + var descriptor = Object.getOwnPropertyDescriptor(node.constructor.prototype, valueField); + if (!node.hasOwnProperty(valueField) && typeof descriptor !== "undefined" && typeof descriptor.get === "function" && typeof descriptor.set === "function") { + var { get, set } = descriptor; + Object.defineProperty(node, valueField, { + configurable: true, + get: function() { + return get.call(this); + }, + set: function(value) { + currentValue = "" + value; + set.call(this, value); + } + }); + Object.defineProperty(node, valueField, { + enumerable: descriptor.enumerable + }); + return { + getValue: function() { + return currentValue; + }, + setValue: function(value) { + currentValue = "" + value; + }, + stopTracking: function() { + node._valueTracker = null; + delete node[valueField]; + } + }; + } +} +function track(node) { + if (!node._valueTracker) { + var valueField = isCheckable(node) ? "checked" : "value"; + node._valueTracker = trackValueOnNode(node, valueField, "" + node[valueField]); + } +} +function updateValueIfChanged(node) { + if (!node) + return false; + var tracker = node._valueTracker; + if (!tracker) + return true; + var lastValue = tracker.getValue(); + var value = ""; + node && (value = isCheckable(node) ? node.checked ? "true" : "false" : node.value); + node = value; + return node !== lastValue ? (tracker.setValue(node), true) : false; +} +function getActiveElement(doc) { + doc = doc || (typeof document !== "undefined" ? document : undefined); + if (typeof doc === "undefined") + return null; + try { + return doc.activeElement || doc.body; + } catch (e) { + return doc.body; + } +} +function escapeSelectorAttributeValueInsideDoubleQuotes(value) { + return value.replace(escapeSelectorAttributeValueInsideDoubleQuotesRegex, function(ch) { + return "\\" + ch.charCodeAt(0).toString(16) + " "; + }); +} +function updateInput(element, value, defaultValue, lastDefaultValue, checked, defaultChecked, type, name) { + element.name = ""; + type != null && typeof type !== "function" && typeof type !== "symbol" && typeof type !== "boolean" ? element.type = type : element.removeAttribute("type"); + if (value != null) + if (type === "number") { + if (value === 0 && element.value === "" || element.value != value) + element.value = "" + getToStringValue(value); + } else + element.value !== "" + getToStringValue(value) && (element.value = "" + getToStringValue(value)); + else + type !== "submit" && type !== "reset" || element.removeAttribute("value"); + value != null ? setDefaultValue(element, type, getToStringValue(value)) : defaultValue != null ? setDefaultValue(element, type, getToStringValue(defaultValue)) : lastDefaultValue != null && element.removeAttribute("value"); + checked == null && defaultChecked != null && (element.defaultChecked = !!defaultChecked); + checked != null && (element.checked = checked && typeof checked !== "function" && typeof checked !== "symbol"); + name != null && typeof name !== "function" && typeof name !== "symbol" && typeof name !== "boolean" ? element.name = "" + getToStringValue(name) : element.removeAttribute("name"); +} +function initInput(element, value, defaultValue, checked, defaultChecked, type, name, isHydrating) { + type != null && typeof type !== "function" && typeof type !== "symbol" && typeof type !== "boolean" && (element.type = type); + if (value != null || defaultValue != null) { + if (!(type !== "submit" && type !== "reset" || value !== undefined && value !== null)) { + track(element); + return; + } + defaultValue = defaultValue != null ? "" + getToStringValue(defaultValue) : ""; + value = value != null ? "" + getToStringValue(value) : defaultValue; + isHydrating || value === element.value || (element.value = value); + element.defaultValue = value; + } + checked = checked != null ? checked : defaultChecked; + checked = typeof checked !== "function" && typeof checked !== "symbol" && !!checked; + element.checked = isHydrating ? element.checked : !!checked; + element.defaultChecked = !!checked; + name != null && typeof name !== "function" && typeof name !== "symbol" && typeof name !== "boolean" && (element.name = name); + track(element); +} +function setDefaultValue(node, type, value) { + type === "number" && getActiveElement(node.ownerDocument) === node || node.defaultValue === "" + value || (node.defaultValue = "" + value); +} +function updateOptions(node, multiple, propValue, setDefaultSelected) { + node = node.options; + if (multiple) { + multiple = {}; + for (var i = 0;i < propValue.length; i++) + multiple["$" + propValue[i]] = true; + for (propValue = 0;propValue < node.length; propValue++) + i = multiple.hasOwnProperty("$" + node[propValue].value), node[propValue].selected !== i && (node[propValue].selected = i), i && setDefaultSelected && (node[propValue].defaultSelected = true); + } else { + propValue = "" + getToStringValue(propValue); + multiple = null; + for (i = 0;i < node.length; i++) { + if (node[i].value === propValue) { + node[i].selected = true; + setDefaultSelected && (node[i].defaultSelected = true); + return; + } + multiple !== null || node[i].disabled || (multiple = node[i]); + } + multiple !== null && (multiple.selected = true); + } +} +function updateTextarea(element, value, defaultValue) { + if (value != null && (value = "" + getToStringValue(value), value !== element.value && (element.value = value), defaultValue == null)) { + element.defaultValue !== value && (element.defaultValue = value); + return; + } + element.defaultValue = defaultValue != null ? "" + getToStringValue(defaultValue) : ""; +} +function initTextarea(element, value, defaultValue, children) { + if (value == null) { + if (children != null) { + if (defaultValue != null) + throw Error(formatProdErrorMessage2(92)); + if (isArrayImpl2(children)) { + if (1 < children.length) + throw Error(formatProdErrorMessage2(93)); + children = children[0]; + } + defaultValue = children; + } + defaultValue == null && (defaultValue = ""); + value = defaultValue; + } + defaultValue = getToStringValue(value); + element.defaultValue = defaultValue; + children = element.textContent; + children === defaultValue && children !== "" && children !== null && (element.value = children); + track(element); +} +function setTextContent(node, text) { + if (text) { + var firstChild = node.firstChild; + if (firstChild && firstChild === node.lastChild && firstChild.nodeType === 3) { + firstChild.nodeValue = text; + return; + } + } + node.textContent = text; +} +function setValueForStyle(style, styleName, value) { + var isCustomProperty = styleName.indexOf("--") === 0; + value == null || typeof value === "boolean" || value === "" ? isCustomProperty ? style.setProperty(styleName, "") : styleName === "float" ? style.cssFloat = "" : style[styleName] = "" : isCustomProperty ? style.setProperty(styleName, value) : typeof value !== "number" || value === 0 || unitlessNumbers.has(styleName) ? styleName === "float" ? style.cssFloat = value : style[styleName] = ("" + value).trim() : style[styleName] = value + "px"; +} +function setValueForStyles(node, styles, prevStyles) { + if (styles != null && typeof styles !== "object") + throw Error(formatProdErrorMessage2(62)); + node = node.style; + if (prevStyles != null) { + for (var styleName in prevStyles) + !prevStyles.hasOwnProperty(styleName) || styles != null && styles.hasOwnProperty(styleName) || (styleName.indexOf("--") === 0 ? node.setProperty(styleName, "") : styleName === "float" ? node.cssFloat = "" : node[styleName] = ""); + for (var styleName$16 in styles) + styleName = styles[styleName$16], styles.hasOwnProperty(styleName$16) && prevStyles[styleName$16] !== styleName && setValueForStyle(node, styleName$16, styleName); + } else + for (var styleName$17 in styles) + styles.hasOwnProperty(styleName$17) && setValueForStyle(node, styleName$17, styles[styleName$17]); +} +function isCustomElement(tagName) { + if (tagName.indexOf("-") === -1) + return false; + switch (tagName) { + 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 false; + default: + return true; + } +} +function sanitizeURL(url) { + return isJavaScriptProtocol.test("" + url) ? "javascript:throw new Error('React has blocked a javascript: URL as a security precaution.')" : url; +} +function noop$1() {} +function getEventTarget(nativeEvent) { + nativeEvent = nativeEvent.target || nativeEvent.srcElement || window; + nativeEvent.correspondingUseElement && (nativeEvent = nativeEvent.correspondingUseElement); + return nativeEvent.nodeType === 3 ? nativeEvent.parentNode : nativeEvent; +} +function restoreStateOfTarget(target) { + var internalInstance = getInstanceFromNode(target); + if (internalInstance && (target = internalInstance.stateNode)) { + var props = target[internalPropsKey] || null; + a: + switch (target = internalInstance.stateNode, internalInstance.type) { + case "input": + updateInput(target, props.value, props.defaultValue, props.defaultValue, props.checked, props.defaultChecked, props.type, props.name); + internalInstance = props.name; + if (props.type === "radio" && internalInstance != null) { + for (props = target;props.parentNode; ) + props = props.parentNode; + props = props.querySelectorAll('input[name="' + escapeSelectorAttributeValueInsideDoubleQuotes("" + internalInstance) + '"][type="radio"]'); + for (internalInstance = 0;internalInstance < props.length; internalInstance++) { + var otherNode = props[internalInstance]; + if (otherNode !== target && otherNode.form === target.form) { + var otherProps = otherNode[internalPropsKey] || null; + if (!otherProps) + throw Error(formatProdErrorMessage2(90)); + updateInput(otherNode, otherProps.value, otherProps.defaultValue, otherProps.defaultValue, otherProps.checked, otherProps.defaultChecked, otherProps.type, otherProps.name); + } + } + for (internalInstance = 0;internalInstance < props.length; internalInstance++) + otherNode = props[internalInstance], otherNode.form === target.form && updateValueIfChanged(otherNode); + } + break a; + case "textarea": + updateTextarea(target, props.value, props.defaultValue); + break a; + case "select": + internalInstance = props.value, internalInstance != null && updateOptions(target, !!props.multiple, internalInstance, false); + } + } +} +function batchedUpdates$1(fn, a, b) { + if (isInsideEventHandler) + return fn(a, b); + isInsideEventHandler = true; + try { + var JSCompiler_inline_result = fn(a); + return JSCompiler_inline_result; + } finally { + if (isInsideEventHandler = false, restoreTarget !== null || restoreQueue !== null) { + if (flushSyncWork$1(), restoreTarget && (a = restoreTarget, fn = restoreQueue, restoreQueue = restoreTarget = null, restoreStateOfTarget(a), fn)) + for (a = 0;a < fn.length; a++) + restoreStateOfTarget(fn[a]); + } + } +} +function getListener(inst, registrationName) { + var stateNode = inst.stateNode; + if (stateNode === null) + return null; + var props = stateNode[internalPropsKey] || null; + if (props === null) + return null; + stateNode = props[registrationName]; + a: + switch (registrationName) { + case "onClick": + case "onClickCapture": + case "onDoubleClick": + case "onDoubleClickCapture": + case "onMouseDown": + case "onMouseDownCapture": + case "onMouseMove": + case "onMouseMoveCapture": + case "onMouseUp": + case "onMouseUpCapture": + case "onMouseEnter": + (props = !props.disabled) || (inst = inst.type, props = !(inst === "button" || inst === "input" || inst === "select" || inst === "textarea")); + inst = !props; + break a; + default: + inst = false; + } + if (inst) + return null; + if (stateNode && typeof stateNode !== "function") + throw Error(formatProdErrorMessage2(231, registrationName, typeof stateNode)); + return stateNode; +} +function getData() { + if (fallbackText) + return fallbackText; + var start, startValue = startText, startLength = startValue.length, end, endValue = "value" in root ? root.value : root.textContent, endLength = endValue.length; + for (start = 0;start < startLength && startValue[start] === endValue[start]; start++) + ; + var minEnd = startLength - start; + for (end = 1;end <= minEnd && startValue[startLength - end] === endValue[endLength - end]; end++) + ; + return fallbackText = endValue.slice(start, 1 < end ? 1 - end : undefined); +} +function getEventCharCode(nativeEvent) { + var keyCode = nativeEvent.keyCode; + "charCode" in nativeEvent ? (nativeEvent = nativeEvent.charCode, nativeEvent === 0 && keyCode === 13 && (nativeEvent = 13)) : nativeEvent = keyCode; + nativeEvent === 10 && (nativeEvent = 13); + return 32 <= nativeEvent || nativeEvent === 13 ? nativeEvent : 0; +} +function functionThatReturnsTrue() { + return true; +} +function functionThatReturnsFalse() { + return false; +} +function createSyntheticEvent(Interface) { + function SyntheticBaseEvent(reactName, reactEventType, targetInst, nativeEvent, nativeEventTarget) { + this._reactName = reactName; + this._targetInst = targetInst; + this.type = reactEventType; + this.nativeEvent = nativeEvent; + this.target = nativeEventTarget; + this.currentTarget = null; + for (var propName in Interface) + Interface.hasOwnProperty(propName) && (reactName = Interface[propName], this[propName] = reactName ? reactName(nativeEvent) : nativeEvent[propName]); + this.isDefaultPrevented = (nativeEvent.defaultPrevented != null ? nativeEvent.defaultPrevented : nativeEvent.returnValue === false) ? functionThatReturnsTrue : functionThatReturnsFalse; + this.isPropagationStopped = functionThatReturnsFalse; + return this; + } + assign2(SyntheticBaseEvent.prototype, { + preventDefault: function() { + this.defaultPrevented = true; + var event = this.nativeEvent; + event && (event.preventDefault ? event.preventDefault() : typeof event.returnValue !== "unknown" && (event.returnValue = false), this.isDefaultPrevented = functionThatReturnsTrue); + }, + stopPropagation: function() { + var event = this.nativeEvent; + event && (event.stopPropagation ? event.stopPropagation() : typeof event.cancelBubble !== "unknown" && (event.cancelBubble = true), this.isPropagationStopped = functionThatReturnsTrue); + }, + persist: function() {}, + isPersistent: functionThatReturnsTrue + }); + return SyntheticBaseEvent; +} +function modifierStateGetter(keyArg) { + var nativeEvent = this.nativeEvent; + return nativeEvent.getModifierState ? nativeEvent.getModifierState(keyArg) : (keyArg = modifierKeyToProp[keyArg]) ? !!nativeEvent[keyArg] : false; +} +function getEventModifierState() { + return modifierStateGetter; +} +function isFallbackCompositionEnd(domEventName, nativeEvent) { + switch (domEventName) { + case "keyup": + return END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1; + case "keydown": + return nativeEvent.keyCode !== 229; + case "keypress": + case "mousedown": + case "focusout": + return true; + default: + return false; + } +} +function getDataFromCustomEvent(nativeEvent) { + nativeEvent = nativeEvent.detail; + return typeof nativeEvent === "object" && "data" in nativeEvent ? nativeEvent.data : null; +} +function getNativeBeforeInputChars(domEventName, nativeEvent) { + switch (domEventName) { + case "compositionend": + return getDataFromCustomEvent(nativeEvent); + case "keypress": + if (nativeEvent.which !== 32) + return null; + hasSpaceKeypress = true; + return SPACEBAR_CHAR; + case "textInput": + return domEventName = nativeEvent.data, domEventName === SPACEBAR_CHAR && hasSpaceKeypress ? null : domEventName; + default: + return null; + } +} +function getFallbackBeforeInputChars(domEventName, nativeEvent) { + if (isComposing) + return domEventName === "compositionend" || !canUseCompositionEvent && isFallbackCompositionEnd(domEventName, nativeEvent) ? (domEventName = getData(), fallbackText = startText = root = null, isComposing = false, domEventName) : null; + switch (domEventName) { + case "paste": + return null; + case "keypress": + if (!(nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) || nativeEvent.ctrlKey && nativeEvent.altKey) { + if (nativeEvent.char && 1 < nativeEvent.char.length) + return nativeEvent.char; + if (nativeEvent.which) + return String.fromCharCode(nativeEvent.which); + } + return null; + case "compositionend": + return useFallbackCompositionData && nativeEvent.locale !== "ko" ? null : nativeEvent.data; + default: + return null; + } +} +function isTextInputElement(elem) { + var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase(); + return nodeName === "input" ? !!supportedInputTypes[elem.type] : nodeName === "textarea" ? true : false; +} +function createAndAccumulateChangeEvent(dispatchQueue, inst, nativeEvent, target) { + restoreTarget ? restoreQueue ? restoreQueue.push(target) : restoreQueue = [target] : restoreTarget = target; + inst = accumulateTwoPhaseListeners(inst, "onChange"); + 0 < inst.length && (nativeEvent = new SyntheticEvent("onChange", "change", null, nativeEvent, target), dispatchQueue.push({ event: nativeEvent, listeners: inst })); +} +function runEventInBatch(dispatchQueue) { + processDispatchQueue(dispatchQueue, 0); +} +function getInstIfValueChanged(targetInst) { + var targetNode = getNodeFromInstance(targetInst); + if (updateValueIfChanged(targetNode)) + return targetInst; +} +function getTargetInstForChangeEvent(domEventName, targetInst) { + if (domEventName === "change") + return targetInst; +} +function stopWatchingForValueChange() { + activeElement$1 && (activeElement$1.detachEvent("onpropertychange", handlePropertyChange), activeElementInst$1 = activeElement$1 = null); +} +function handlePropertyChange(nativeEvent) { + if (nativeEvent.propertyName === "value" && getInstIfValueChanged(activeElementInst$1)) { + var dispatchQueue = []; + createAndAccumulateChangeEvent(dispatchQueue, activeElementInst$1, nativeEvent, getEventTarget(nativeEvent)); + batchedUpdates$1(runEventInBatch, dispatchQueue); + } +} +function handleEventsForInputEventPolyfill(domEventName, target, targetInst) { + domEventName === "focusin" ? (stopWatchingForValueChange(), activeElement$1 = target, activeElementInst$1 = targetInst, activeElement$1.attachEvent("onpropertychange", handlePropertyChange)) : domEventName === "focusout" && stopWatchingForValueChange(); +} +function getTargetInstForInputEventPolyfill(domEventName) { + if (domEventName === "selectionchange" || domEventName === "keyup" || domEventName === "keydown") + return getInstIfValueChanged(activeElementInst$1); +} +function getTargetInstForClickEvent(domEventName, targetInst) { + if (domEventName === "click") + return getInstIfValueChanged(targetInst); +} +function getTargetInstForInputOrChangeEvent(domEventName, targetInst) { + if (domEventName === "input" || domEventName === "change") + return getInstIfValueChanged(targetInst); +} +function is(x, y) { + return x === y && (x !== 0 || 1 / x === 1 / y) || x !== x && y !== y; +} +function shallowEqual(objA, objB) { + if (objectIs(objA, objB)) + return true; + if (typeof objA !== "object" || objA === null || typeof objB !== "object" || objB === null) + return false; + var keysA = Object.keys(objA), keysB = Object.keys(objB); + if (keysA.length !== keysB.length) + return false; + for (keysB = 0;keysB < keysA.length; keysB++) { + var currentKey = keysA[keysB]; + if (!hasOwnProperty2.call(objB, currentKey) || !objectIs(objA[currentKey], objB[currentKey])) + return false; + } + return true; +} +function getLeafNode(node) { + for (;node && node.firstChild; ) + node = node.firstChild; + return node; +} +function getNodeForCharacterOffset(root2, offset) { + var node = getLeafNode(root2); + root2 = 0; + for (var nodeEnd;node; ) { + if (node.nodeType === 3) { + nodeEnd = root2 + node.textContent.length; + if (root2 <= offset && nodeEnd >= offset) + return { node, offset: offset - root2 }; + root2 = nodeEnd; + } + a: { + for (;node; ) { + if (node.nextSibling) { + node = node.nextSibling; + break a; + } + node = node.parentNode; + } + node = undefined; + } + node = getLeafNode(node); + } +} +function containsNode(outerNode, innerNode) { + return outerNode && innerNode ? outerNode === innerNode ? true : outerNode && outerNode.nodeType === 3 ? false : innerNode && innerNode.nodeType === 3 ? containsNode(outerNode, innerNode.parentNode) : ("contains" in outerNode) ? outerNode.contains(innerNode) : outerNode.compareDocumentPosition ? !!(outerNode.compareDocumentPosition(innerNode) & 16) : false : false; +} +function getActiveElementDeep(containerInfo) { + containerInfo = containerInfo != null && containerInfo.ownerDocument != null && containerInfo.ownerDocument.defaultView != null ? containerInfo.ownerDocument.defaultView : window; + for (var element = getActiveElement(containerInfo.document);element instanceof containerInfo.HTMLIFrameElement; ) { + try { + var JSCompiler_inline_result = typeof element.contentWindow.location.href === "string"; + } catch (err) { + JSCompiler_inline_result = false; + } + if (JSCompiler_inline_result) + containerInfo = element.contentWindow; + else + break; + element = getActiveElement(containerInfo.document); + } + return element; +} +function hasSelectionCapabilities(elem) { + var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase(); + return nodeName && (nodeName === "input" && (elem.type === "text" || elem.type === "search" || elem.type === "tel" || elem.type === "url" || elem.type === "password") || nodeName === "textarea" || elem.contentEditable === "true"); +} +function constructSelectEvent(dispatchQueue, nativeEvent, nativeEventTarget) { + var doc = nativeEventTarget.window === nativeEventTarget ? nativeEventTarget.document : nativeEventTarget.nodeType === 9 ? nativeEventTarget : nativeEventTarget.ownerDocument; + mouseDown || activeElement == null || activeElement !== getActiveElement(doc) || (doc = activeElement, ("selectionStart" in doc) && hasSelectionCapabilities(doc) ? doc = { start: doc.selectionStart, end: doc.selectionEnd } : (doc = (doc.ownerDocument && doc.ownerDocument.defaultView || window).getSelection(), doc = { + anchorNode: doc.anchorNode, + anchorOffset: doc.anchorOffset, + focusNode: doc.focusNode, + focusOffset: doc.focusOffset + }), lastSelection && shallowEqual(lastSelection, doc) || (lastSelection = doc, doc = accumulateTwoPhaseListeners(activeElementInst, "onSelect"), 0 < doc.length && (nativeEvent = new SyntheticEvent("onSelect", "select", null, nativeEvent, nativeEventTarget), dispatchQueue.push({ event: nativeEvent, listeners: doc }), nativeEvent.target = activeElement))); +} +function makePrefixMap(styleProp, eventName) { + var prefixes = {}; + prefixes[styleProp.toLowerCase()] = eventName.toLowerCase(); + prefixes["Webkit" + styleProp] = "webkit" + eventName; + prefixes["Moz" + styleProp] = "moz" + eventName; + return prefixes; +} +function getVendorPrefixedEventName(eventName) { + if (prefixedEventNames[eventName]) + return prefixedEventNames[eventName]; + if (!vendorPrefixes[eventName]) + return eventName; + var prefixMap = vendorPrefixes[eventName], styleProp; + for (styleProp in prefixMap) + if (prefixMap.hasOwnProperty(styleProp) && styleProp in style) + return prefixedEventNames[eventName] = prefixMap[styleProp]; + return eventName; +} +function registerSimpleEvent(domEventName, reactName) { + topLevelEventsToReactNames.set(domEventName, reactName); + registerTwoPhaseEvent(reactName, [domEventName]); +} +function finishQueueingConcurrentUpdates() { + for (var endIndex = concurrentQueuesIndex, i = concurrentlyUpdatedLanes = concurrentQueuesIndex = 0;i < endIndex; ) { + var fiber = concurrentQueues[i]; + concurrentQueues[i++] = null; + var queue = concurrentQueues[i]; + concurrentQueues[i++] = null; + var update = concurrentQueues[i]; + concurrentQueues[i++] = null; + var lane = concurrentQueues[i]; + concurrentQueues[i++] = null; + if (queue !== null && update !== null) { + var pending = queue.pending; + pending === null ? update.next = update : (update.next = pending.next, pending.next = update); + queue.pending = update; + } + lane !== 0 && markUpdateLaneFromFiberToRoot(fiber, update, lane); + } +} +function enqueueUpdate$1(fiber, queue, update, lane) { + concurrentQueues[concurrentQueuesIndex++] = fiber; + concurrentQueues[concurrentQueuesIndex++] = queue; + concurrentQueues[concurrentQueuesIndex++] = update; + concurrentQueues[concurrentQueuesIndex++] = lane; + concurrentlyUpdatedLanes |= lane; + fiber.lanes |= lane; + fiber = fiber.alternate; + fiber !== null && (fiber.lanes |= lane); +} +function enqueueConcurrentHookUpdate(fiber, queue, update, lane) { + enqueueUpdate$1(fiber, queue, update, lane); + return getRootForUpdatedFiber(fiber); +} +function enqueueConcurrentRenderForLane(fiber, lane) { + enqueueUpdate$1(fiber, null, null, lane); + return getRootForUpdatedFiber(fiber); +} +function markUpdateLaneFromFiberToRoot(sourceFiber, update, lane) { + sourceFiber.lanes |= lane; + var alternate = sourceFiber.alternate; + alternate !== null && (alternate.lanes |= lane); + for (var isHidden = false, parent = sourceFiber.return;parent !== null; ) + parent.childLanes |= lane, alternate = parent.alternate, alternate !== null && (alternate.childLanes |= lane), parent.tag === 22 && (sourceFiber = parent.stateNode, sourceFiber === null || sourceFiber._visibility & 1 || (isHidden = true)), sourceFiber = parent, parent = parent.return; + return sourceFiber.tag === 3 ? (parent = sourceFiber.stateNode, isHidden && update !== null && (isHidden = 31 - clz32(lane), sourceFiber = parent.hiddenUpdates, alternate = sourceFiber[isHidden], alternate === null ? sourceFiber[isHidden] = [update] : alternate.push(update), update.lane = lane | 536870912), parent) : null; +} +function getRootForUpdatedFiber(sourceFiber) { + if (50 < nestedUpdateCount) + throw nestedUpdateCount = 0, rootWithNestedUpdates = null, Error(formatProdErrorMessage2(185)); + for (var parent = sourceFiber.return;parent !== null; ) + sourceFiber = parent, parent = sourceFiber.return; + return sourceFiber.tag === 3 ? sourceFiber.stateNode : null; +} +function FiberNode(tag, pendingProps, key, mode) { + this.tag = tag; + this.key = key; + this.sibling = this.child = this.return = this.stateNode = this.type = this.elementType = null; + this.index = 0; + this.refCleanup = this.ref = null; + this.pendingProps = pendingProps; + this.dependencies = this.memoizedState = this.updateQueue = this.memoizedProps = null; + this.mode = mode; + this.subtreeFlags = this.flags = 0; + this.deletions = null; + this.childLanes = this.lanes = 0; + this.alternate = null; +} +function createFiberImplClass(tag, pendingProps, key, mode) { + return new FiberNode(tag, pendingProps, key, mode); +} +function shouldConstruct(Component2) { + Component2 = Component2.prototype; + return !(!Component2 || !Component2.isReactComponent); +} +function createWorkInProgress(current, pendingProps) { + var workInProgress = current.alternate; + workInProgress === null ? (workInProgress = createFiberImplClass(current.tag, pendingProps, current.key, current.mode), workInProgress.elementType = current.elementType, workInProgress.type = current.type, workInProgress.stateNode = current.stateNode, workInProgress.alternate = current, current.alternate = workInProgress) : (workInProgress.pendingProps = pendingProps, workInProgress.type = current.type, workInProgress.flags = 0, workInProgress.subtreeFlags = 0, workInProgress.deletions = null); + workInProgress.flags = current.flags & 65011712; + workInProgress.childLanes = current.childLanes; + workInProgress.lanes = current.lanes; + workInProgress.child = current.child; + workInProgress.memoizedProps = current.memoizedProps; + workInProgress.memoizedState = current.memoizedState; + workInProgress.updateQueue = current.updateQueue; + pendingProps = current.dependencies; + workInProgress.dependencies = pendingProps === null ? null : { lanes: pendingProps.lanes, firstContext: pendingProps.firstContext }; + workInProgress.sibling = current.sibling; + workInProgress.index = current.index; + workInProgress.ref = current.ref; + workInProgress.refCleanup = current.refCleanup; + return workInProgress; +} +function resetWorkInProgress(workInProgress, renderLanes) { + workInProgress.flags &= 65011714; + var current = workInProgress.alternate; + current === null ? (workInProgress.childLanes = 0, workInProgress.lanes = renderLanes, workInProgress.child = null, workInProgress.subtreeFlags = 0, workInProgress.memoizedProps = null, workInProgress.memoizedState = null, workInProgress.updateQueue = null, workInProgress.dependencies = null, workInProgress.stateNode = null) : (workInProgress.childLanes = current.childLanes, workInProgress.lanes = current.lanes, workInProgress.child = current.child, workInProgress.subtreeFlags = 0, workInProgress.deletions = null, workInProgress.memoizedProps = current.memoizedProps, workInProgress.memoizedState = current.memoizedState, workInProgress.updateQueue = current.updateQueue, workInProgress.type = current.type, renderLanes = current.dependencies, workInProgress.dependencies = renderLanes === null ? null : { + lanes: renderLanes.lanes, + firstContext: renderLanes.firstContext + }); + return workInProgress; +} +function createFiberFromTypeAndProps(type, key, pendingProps, owner, mode, lanes) { + var fiberTag = 0; + owner = type; + if (typeof type === "function") + shouldConstruct(type) && (fiberTag = 1); + else if (typeof type === "string") + fiberTag = isHostHoistableType(type, pendingProps, contextStackCursor.current) ? 26 : type === "html" || type === "head" || type === "body" ? 27 : 5; + else + a: + switch (type) { + case REACT_ACTIVITY_TYPE2: + return type = createFiberImplClass(31, pendingProps, key, mode), type.elementType = REACT_ACTIVITY_TYPE2, type.lanes = lanes, type; + case REACT_FRAGMENT_TYPE2: + return createFiberFromFragment(pendingProps.children, mode, lanes, key); + case REACT_STRICT_MODE_TYPE2: + fiberTag = 8; + mode |= 24; + break; + case REACT_PROFILER_TYPE2: + return type = createFiberImplClass(12, pendingProps, key, mode | 2), type.elementType = REACT_PROFILER_TYPE2, type.lanes = lanes, type; + case REACT_SUSPENSE_TYPE2: + return type = createFiberImplClass(13, pendingProps, key, mode), type.elementType = REACT_SUSPENSE_TYPE2, type.lanes = lanes, type; + case REACT_SUSPENSE_LIST_TYPE: + return type = createFiberImplClass(19, pendingProps, key, mode), type.elementType = REACT_SUSPENSE_LIST_TYPE, type.lanes = lanes, type; + default: + if (typeof type === "object" && type !== null) + switch (type.$$typeof) { + case REACT_CONTEXT_TYPE2: + fiberTag = 10; + break a; + case REACT_CONSUMER_TYPE2: + fiberTag = 9; + break a; + case REACT_FORWARD_REF_TYPE2: + fiberTag = 11; + break a; + case REACT_MEMO_TYPE2: + fiberTag = 14; + break a; + case REACT_LAZY_TYPE2: + fiberTag = 16; + owner = null; + break a; + } + fiberTag = 29; + pendingProps = Error(formatProdErrorMessage2(130, type === null ? "null" : typeof type, "")); + owner = null; + } + key = createFiberImplClass(fiberTag, pendingProps, key, mode); + key.elementType = type; + key.type = owner; + key.lanes = lanes; + return key; +} +function createFiberFromFragment(elements, mode, lanes, key) { + elements = createFiberImplClass(7, elements, key, mode); + elements.lanes = lanes; + return elements; +} +function createFiberFromText(content, mode, lanes) { + content = createFiberImplClass(6, content, null, mode); + content.lanes = lanes; + return content; +} +function createFiberFromDehydratedFragment(dehydratedNode) { + var fiber = createFiberImplClass(18, null, null, 0); + fiber.stateNode = dehydratedNode; + return fiber; +} +function createFiberFromPortal(portal, mode, lanes) { + mode = createFiberImplClass(4, portal.children !== null ? portal.children : [], portal.key, mode); + mode.lanes = lanes; + mode.stateNode = { + containerInfo: portal.containerInfo, + pendingChildren: null, + implementation: portal.implementation + }; + return mode; +} +function createCapturedValueAtFiber(value, source) { + if (typeof value === "object" && value !== null) { + var existing = CapturedStacks.get(value); + if (existing !== undefined) + return existing; + source = { + value, + source, + stack: getStackByFiberInDevAndProd(source) + }; + CapturedStacks.set(value, source); + return source; + } + return { + value, + source, + stack: getStackByFiberInDevAndProd(source) + }; +} +function pushTreeFork(workInProgress, totalChildren) { + forkStack[forkStackIndex++] = treeForkCount; + forkStack[forkStackIndex++] = treeForkProvider; + treeForkProvider = workInProgress; + treeForkCount = totalChildren; +} +function pushTreeId(workInProgress, totalChildren, index2) { + idStack[idStackIndex++] = treeContextId; + idStack[idStackIndex++] = treeContextOverflow; + idStack[idStackIndex++] = treeContextProvider; + treeContextProvider = workInProgress; + var baseIdWithLeadingBit = treeContextId; + workInProgress = treeContextOverflow; + var baseLength = 32 - clz32(baseIdWithLeadingBit) - 1; + baseIdWithLeadingBit &= ~(1 << baseLength); + index2 += 1; + var length = 32 - clz32(totalChildren) + baseLength; + if (30 < length) { + var numberOfOverflowBits = baseLength - baseLength % 5; + length = (baseIdWithLeadingBit & (1 << numberOfOverflowBits) - 1).toString(32); + baseIdWithLeadingBit >>= numberOfOverflowBits; + baseLength -= numberOfOverflowBits; + treeContextId = 1 << 32 - clz32(totalChildren) + baseLength | index2 << baseLength | baseIdWithLeadingBit; + treeContextOverflow = length + workInProgress; + } else + treeContextId = 1 << length | index2 << baseLength | baseIdWithLeadingBit, treeContextOverflow = workInProgress; +} +function pushMaterializedTreeId(workInProgress) { + workInProgress.return !== null && (pushTreeFork(workInProgress, 1), pushTreeId(workInProgress, 1, 0)); +} +function popTreeContext(workInProgress) { + for (;workInProgress === treeForkProvider; ) + treeForkProvider = forkStack[--forkStackIndex], forkStack[forkStackIndex] = null, treeForkCount = forkStack[--forkStackIndex], forkStack[forkStackIndex] = null; + for (;workInProgress === treeContextProvider; ) + treeContextProvider = idStack[--idStackIndex], idStack[idStackIndex] = null, treeContextOverflow = idStack[--idStackIndex], idStack[idStackIndex] = null, treeContextId = idStack[--idStackIndex], idStack[idStackIndex] = null; +} +function restoreSuspendedTreeContext(workInProgress, suspendedContext) { + idStack[idStackIndex++] = treeContextId; + idStack[idStackIndex++] = treeContextOverflow; + idStack[idStackIndex++] = treeContextProvider; + treeContextId = suspendedContext.id; + treeContextOverflow = suspendedContext.overflow; + treeContextProvider = workInProgress; +} +function throwOnHydrationMismatch(fiber) { + var error = Error(formatProdErrorMessage2(418, 1 < arguments.length && arguments[1] !== undefined && arguments[1] ? "text" : "HTML", "")); + queueHydrationError(createCapturedValueAtFiber(error, fiber)); + throw HydrationMismatchException; +} +function prepareToHydrateHostInstance(fiber) { + var { stateNode: instance, type, memoizedProps: props } = fiber; + instance[internalInstanceKey] = fiber; + instance[internalPropsKey] = props; + switch (type) { + case "dialog": + listenToNonDelegatedEvent("cancel", instance); + listenToNonDelegatedEvent("close", instance); + break; + case "iframe": + case "object": + case "embed": + listenToNonDelegatedEvent("load", instance); + break; + case "video": + case "audio": + for (type = 0;type < mediaEventTypes.length; type++) + listenToNonDelegatedEvent(mediaEventTypes[type], instance); + break; + case "source": + listenToNonDelegatedEvent("error", instance); + break; + case "img": + case "image": + case "link": + listenToNonDelegatedEvent("error", instance); + listenToNonDelegatedEvent("load", instance); + break; + case "details": + listenToNonDelegatedEvent("toggle", instance); + break; + case "input": + listenToNonDelegatedEvent("invalid", instance); + initInput(instance, props.value, props.defaultValue, props.checked, props.defaultChecked, props.type, props.name, true); + break; + case "select": + listenToNonDelegatedEvent("invalid", instance); + break; + case "textarea": + listenToNonDelegatedEvent("invalid", instance), initTextarea(instance, props.value, props.defaultValue, props.children); + } + type = props.children; + typeof type !== "string" && typeof type !== "number" && typeof type !== "bigint" || instance.textContent === "" + type || props.suppressHydrationWarning === true || checkForUnmatchedText(instance.textContent, type) ? (props.popover != null && (listenToNonDelegatedEvent("beforetoggle", instance), listenToNonDelegatedEvent("toggle", instance)), props.onScroll != null && listenToNonDelegatedEvent("scroll", instance), props.onScrollEnd != null && listenToNonDelegatedEvent("scrollend", instance), props.onClick != null && (instance.onclick = noop$1), instance = true) : instance = false; + instance || throwOnHydrationMismatch(fiber, true); +} +function popToNextHostParent(fiber) { + for (hydrationParentFiber = fiber.return;hydrationParentFiber; ) + switch (hydrationParentFiber.tag) { + case 5: + case 31: + case 13: + rootOrSingletonContext = false; + return; + case 27: + case 3: + rootOrSingletonContext = true; + return; + default: + hydrationParentFiber = hydrationParentFiber.return; + } +} +function popHydrationState(fiber) { + if (fiber !== hydrationParentFiber) + return false; + if (!isHydrating) + return popToNextHostParent(fiber), isHydrating = true, false; + var tag = fiber.tag, JSCompiler_temp; + if (JSCompiler_temp = tag !== 3 && tag !== 27) { + if (JSCompiler_temp = tag === 5) + JSCompiler_temp = fiber.type, JSCompiler_temp = !(JSCompiler_temp !== "form" && JSCompiler_temp !== "button") || shouldSetTextContent(fiber.type, fiber.memoizedProps); + JSCompiler_temp = !JSCompiler_temp; + } + JSCompiler_temp && nextHydratableInstance && throwOnHydrationMismatch(fiber); + popToNextHostParent(fiber); + if (tag === 13) { + fiber = fiber.memoizedState; + fiber = fiber !== null ? fiber.dehydrated : null; + if (!fiber) + throw Error(formatProdErrorMessage2(317)); + nextHydratableInstance = getNextHydratableInstanceAfterHydrationBoundary(fiber); + } else if (tag === 31) { + fiber = fiber.memoizedState; + fiber = fiber !== null ? fiber.dehydrated : null; + if (!fiber) + throw Error(formatProdErrorMessage2(317)); + nextHydratableInstance = getNextHydratableInstanceAfterHydrationBoundary(fiber); + } else + tag === 27 ? (tag = nextHydratableInstance, isSingletonScope(fiber.type) ? (fiber = previousHydratableOnEnteringScopedSingleton, previousHydratableOnEnteringScopedSingleton = null, nextHydratableInstance = fiber) : nextHydratableInstance = tag) : nextHydratableInstance = hydrationParentFiber ? getNextHydratable(fiber.stateNode.nextSibling) : null; + return true; +} +function resetHydrationState() { + nextHydratableInstance = hydrationParentFiber = null; + isHydrating = false; +} +function upgradeHydrationErrorsToRecoverable() { + var queuedErrors = hydrationErrors; + queuedErrors !== null && (workInProgressRootRecoverableErrors === null ? workInProgressRootRecoverableErrors = queuedErrors : workInProgressRootRecoverableErrors.push.apply(workInProgressRootRecoverableErrors, queuedErrors), hydrationErrors = null); + return queuedErrors; +} +function queueHydrationError(error) { + hydrationErrors === null ? hydrationErrors = [error] : hydrationErrors.push(error); +} +function pushProvider(providerFiber, context, nextValue) { + push2(valueCursor, context._currentValue); + context._currentValue = nextValue; +} +function popProvider(context) { + context._currentValue = valueCursor.current; + pop2(valueCursor); +} +function scheduleContextWorkOnParentPath(parent, renderLanes, propagationRoot) { + for (;parent !== null; ) { + var alternate = parent.alternate; + (parent.childLanes & renderLanes) !== renderLanes ? (parent.childLanes |= renderLanes, alternate !== null && (alternate.childLanes |= renderLanes)) : alternate !== null && (alternate.childLanes & renderLanes) !== renderLanes && (alternate.childLanes |= renderLanes); + if (parent === propagationRoot) + break; + parent = parent.return; + } +} +function propagateContextChanges(workInProgress, contexts, renderLanes, forcePropagateEntireTree) { + var fiber = workInProgress.child; + fiber !== null && (fiber.return = workInProgress); + for (;fiber !== null; ) { + var list = fiber.dependencies; + if (list !== null) { + var nextFiber = fiber.child; + list = list.firstContext; + a: + for (;list !== null; ) { + var dependency = list; + list = fiber; + for (var i = 0;i < contexts.length; i++) + if (dependency.context === contexts[i]) { + list.lanes |= renderLanes; + dependency = list.alternate; + dependency !== null && (dependency.lanes |= renderLanes); + scheduleContextWorkOnParentPath(list.return, renderLanes, workInProgress); + forcePropagateEntireTree || (nextFiber = null); + break a; + } + list = dependency.next; + } + } else if (fiber.tag === 18) { + nextFiber = fiber.return; + if (nextFiber === null) + throw Error(formatProdErrorMessage2(341)); + nextFiber.lanes |= renderLanes; + list = nextFiber.alternate; + list !== null && (list.lanes |= renderLanes); + scheduleContextWorkOnParentPath(nextFiber, renderLanes, workInProgress); + nextFiber = null; + } else + nextFiber = fiber.child; + if (nextFiber !== null) + nextFiber.return = fiber; + else + for (nextFiber = fiber;nextFiber !== null; ) { + if (nextFiber === workInProgress) { + nextFiber = null; + break; + } + fiber = nextFiber.sibling; + if (fiber !== null) { + fiber.return = nextFiber.return; + nextFiber = fiber; + break; + } + nextFiber = nextFiber.return; + } + fiber = nextFiber; + } +} +function propagateParentContextChanges(current, workInProgress, renderLanes, forcePropagateEntireTree) { + current = null; + for (var parent = workInProgress, isInsidePropagationBailout = false;parent !== null; ) { + if (!isInsidePropagationBailout) { + if ((parent.flags & 524288) !== 0) + isInsidePropagationBailout = true; + else if ((parent.flags & 262144) !== 0) + break; + } + if (parent.tag === 10) { + var currentParent = parent.alternate; + if (currentParent === null) + throw Error(formatProdErrorMessage2(387)); + currentParent = currentParent.memoizedProps; + if (currentParent !== null) { + var context = parent.type; + objectIs(parent.pendingProps.value, currentParent.value) || (current !== null ? current.push(context) : current = [context]); + } + } else if (parent === hostTransitionProviderCursor.current) { + currentParent = parent.alternate; + if (currentParent === null) + throw Error(formatProdErrorMessage2(387)); + currentParent.memoizedState.memoizedState !== parent.memoizedState.memoizedState && (current !== null ? current.push(HostTransitionContext) : current = [HostTransitionContext]); + } + parent = parent.return; + } + current !== null && propagateContextChanges(workInProgress, current, renderLanes, forcePropagateEntireTree); + workInProgress.flags |= 262144; +} +function checkIfContextChanged(currentDependencies) { + for (currentDependencies = currentDependencies.firstContext;currentDependencies !== null; ) { + if (!objectIs(currentDependencies.context._currentValue, currentDependencies.memoizedValue)) + return true; + currentDependencies = currentDependencies.next; + } + return false; +} +function prepareToReadContext(workInProgress) { + currentlyRenderingFiber$1 = workInProgress; + lastContextDependency = null; + workInProgress = workInProgress.dependencies; + workInProgress !== null && (workInProgress.firstContext = null); +} +function readContext(context) { + return readContextForConsumer(currentlyRenderingFiber$1, context); +} +function readContextDuringReconciliation(consumer, context) { + currentlyRenderingFiber$1 === null && prepareToReadContext(consumer); + return readContextForConsumer(consumer, context); +} +function readContextForConsumer(consumer, context) { + var value = context._currentValue; + context = { context, memoizedValue: value, next: null }; + if (lastContextDependency === null) { + if (consumer === null) + throw Error(formatProdErrorMessage2(308)); + lastContextDependency = context; + consumer.dependencies = { lanes: 0, firstContext: context }; + consumer.flags |= 524288; + } else + lastContextDependency = lastContextDependency.next = context; + return value; +} +function createCache() { + return { + controller: new AbortControllerLocal, + data: new Map, + refCount: 0 + }; +} +function releaseCache(cache) { + cache.refCount--; + cache.refCount === 0 && scheduleCallback$2(NormalPriority, function() { + cache.controller.abort(); + }); +} +function entangleAsyncAction(transition, thenable) { + if (currentEntangledListeners === null) { + var entangledListeners = currentEntangledListeners = []; + currentEntangledPendingCount = 0; + currentEntangledLane = requestTransitionLane(); + currentEntangledActionThenable = { + status: "pending", + value: undefined, + then: function(resolve) { + entangledListeners.push(resolve); + } + }; + } + currentEntangledPendingCount++; + thenable.then(pingEngtangledActionScope, pingEngtangledActionScope); + return thenable; +} +function pingEngtangledActionScope() { + if (--currentEntangledPendingCount === 0 && currentEntangledListeners !== null) { + currentEntangledActionThenable !== null && (currentEntangledActionThenable.status = "fulfilled"); + var listeners = currentEntangledListeners; + currentEntangledListeners = null; + currentEntangledLane = 0; + currentEntangledActionThenable = null; + for (var i = 0;i < listeners.length; i++) + (0, listeners[i])(); + } +} +function chainThenableValue(thenable, result) { + var listeners = [], thenableWithOverride = { + status: "pending", + value: null, + reason: null, + then: function(resolve) { + listeners.push(resolve); + } + }; + thenable.then(function() { + thenableWithOverride.status = "fulfilled"; + thenableWithOverride.value = result; + for (var i = 0;i < listeners.length; i++) + (0, listeners[i])(result); + }, function(error) { + thenableWithOverride.status = "rejected"; + thenableWithOverride.reason = error; + for (error = 0;error < listeners.length; error++) + (0, listeners[error])(undefined); + }); + return thenableWithOverride; +} +function peekCacheFromPool() { + var cacheResumedFromPreviousRender = resumedCache.current; + return cacheResumedFromPreviousRender !== null ? cacheResumedFromPreviousRender : workInProgressRoot.pooledCache; +} +function pushTransition(offscreenWorkInProgress, prevCachePool) { + prevCachePool === null ? push2(resumedCache, resumedCache.current) : push2(resumedCache, prevCachePool.pool); +} +function getSuspendedCache() { + var cacheFromPool = peekCacheFromPool(); + return cacheFromPool === null ? null : { parent: CacheContext._currentValue, pool: cacheFromPool }; +} +function isThenableResolved(thenable) { + thenable = thenable.status; + return thenable === "fulfilled" || thenable === "rejected"; +} +function trackUsedThenable(thenableState, thenable, index2) { + index2 = thenableState[index2]; + index2 === undefined ? thenableState.push(thenable) : index2 !== thenable && (thenable.then(noop$1, noop$1), thenable = index2); + switch (thenable.status) { + case "fulfilled": + return thenable.value; + case "rejected": + throw thenableState = thenable.reason, checkIfUseWrappedInAsyncCatch(thenableState), thenableState; + default: + if (typeof thenable.status === "string") + thenable.then(noop$1, noop$1); + else { + thenableState = workInProgressRoot; + if (thenableState !== null && 100 < thenableState.shellSuspendCounter) + throw Error(formatProdErrorMessage2(482)); + thenableState = thenable; + thenableState.status = "pending"; + thenableState.then(function(fulfilledValue) { + if (thenable.status === "pending") { + var fulfilledThenable = thenable; + fulfilledThenable.status = "fulfilled"; + fulfilledThenable.value = fulfilledValue; + } + }, function(error) { + if (thenable.status === "pending") { + var rejectedThenable = thenable; + rejectedThenable.status = "rejected"; + rejectedThenable.reason = error; + } + }); + } + switch (thenable.status) { + case "fulfilled": + return thenable.value; + case "rejected": + throw thenableState = thenable.reason, checkIfUseWrappedInAsyncCatch(thenableState), thenableState; + } + suspendedThenable = thenable; + throw SuspenseException; + } +} +function resolveLazy(lazyType) { + try { + var init = lazyType._init; + return init(lazyType._payload); + } catch (x) { + if (x !== null && typeof x === "object" && typeof x.then === "function") + throw suspendedThenable = x, SuspenseException; + throw x; + } +} +function getSuspendedThenable() { + if (suspendedThenable === null) + throw Error(formatProdErrorMessage2(459)); + var thenable = suspendedThenable; + suspendedThenable = null; + return thenable; +} +function checkIfUseWrappedInAsyncCatch(rejectedReason) { + if (rejectedReason === SuspenseException || rejectedReason === SuspenseActionException) + throw Error(formatProdErrorMessage2(483)); +} +function unwrapThenable(thenable) { + var index2 = thenableIndexCounter$1; + thenableIndexCounter$1 += 1; + thenableState$1 === null && (thenableState$1 = []); + return trackUsedThenable(thenableState$1, thenable, index2); +} +function coerceRef(workInProgress, element) { + element = element.props.ref; + workInProgress.ref = element !== undefined ? element : null; +} +function throwOnInvalidObjectTypeImpl(returnFiber, newChild) { + if (newChild.$$typeof === REACT_LEGACY_ELEMENT_TYPE) + throw Error(formatProdErrorMessage2(525)); + returnFiber = Object.prototype.toString.call(newChild); + throw Error(formatProdErrorMessage2(31, returnFiber === "[object Object]" ? "object with keys {" + Object.keys(newChild).join(", ") + "}" : returnFiber)); +} +function createChildReconciler(shouldTrackSideEffects) { + function deleteChild(returnFiber, childToDelete) { + if (shouldTrackSideEffects) { + var deletions = returnFiber.deletions; + deletions === null ? (returnFiber.deletions = [childToDelete], returnFiber.flags |= 16) : deletions.push(childToDelete); + } + } + function deleteRemainingChildren(returnFiber, currentFirstChild) { + if (!shouldTrackSideEffects) + return null; + for (;currentFirstChild !== null; ) + deleteChild(returnFiber, currentFirstChild), currentFirstChild = currentFirstChild.sibling; + return null; + } + function mapRemainingChildren(currentFirstChild) { + for (var existingChildren = new Map;currentFirstChild !== null; ) + currentFirstChild.key !== null ? existingChildren.set(currentFirstChild.key, currentFirstChild) : existingChildren.set(currentFirstChild.index, currentFirstChild), currentFirstChild = currentFirstChild.sibling; + return existingChildren; + } + function useFiber(fiber, pendingProps) { + fiber = createWorkInProgress(fiber, pendingProps); + fiber.index = 0; + fiber.sibling = null; + return fiber; + } + function placeChild(newFiber, lastPlacedIndex, newIndex) { + newFiber.index = newIndex; + if (!shouldTrackSideEffects) + return newFiber.flags |= 1048576, lastPlacedIndex; + newIndex = newFiber.alternate; + if (newIndex !== null) + return newIndex = newIndex.index, newIndex < lastPlacedIndex ? (newFiber.flags |= 67108866, lastPlacedIndex) : newIndex; + newFiber.flags |= 67108866; + return lastPlacedIndex; + } + function placeSingleChild(newFiber) { + shouldTrackSideEffects && newFiber.alternate === null && (newFiber.flags |= 67108866); + return newFiber; + } + function updateTextNode(returnFiber, current, textContent, lanes) { + if (current === null || current.tag !== 6) + return current = createFiberFromText(textContent, returnFiber.mode, lanes), current.return = returnFiber, current; + current = useFiber(current, textContent); + current.return = returnFiber; + return current; + } + function updateElement(returnFiber, current, element, lanes) { + var elementType = element.type; + if (elementType === REACT_FRAGMENT_TYPE2) + return updateFragment(returnFiber, current, element.props.children, lanes, element.key); + if (current !== null && (current.elementType === elementType || typeof elementType === "object" && elementType !== null && elementType.$$typeof === REACT_LAZY_TYPE2 && resolveLazy(elementType) === current.type)) + return current = useFiber(current, element.props), coerceRef(current, element), current.return = returnFiber, current; + current = createFiberFromTypeAndProps(element.type, element.key, element.props, null, returnFiber.mode, lanes); + coerceRef(current, element); + current.return = returnFiber; + return current; + } + function updatePortal(returnFiber, current, portal, lanes) { + if (current === null || current.tag !== 4 || current.stateNode.containerInfo !== portal.containerInfo || current.stateNode.implementation !== portal.implementation) + return current = createFiberFromPortal(portal, returnFiber.mode, lanes), current.return = returnFiber, current; + current = useFiber(current, portal.children || []); + current.return = returnFiber; + return current; + } + function updateFragment(returnFiber, current, fragment, lanes, key) { + if (current === null || current.tag !== 7) + return current = createFiberFromFragment(fragment, returnFiber.mode, lanes, key), current.return = returnFiber, current; + current = useFiber(current, fragment); + current.return = returnFiber; + return current; + } + function createChild(returnFiber, newChild, lanes) { + if (typeof newChild === "string" && newChild !== "" || typeof newChild === "number" || typeof newChild === "bigint") + return newChild = createFiberFromText("" + newChild, returnFiber.mode, lanes), newChild.return = returnFiber, newChild; + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE2: + return lanes = createFiberFromTypeAndProps(newChild.type, newChild.key, newChild.props, null, returnFiber.mode, lanes), coerceRef(lanes, newChild), lanes.return = returnFiber, lanes; + case REACT_PORTAL_TYPE3: + return newChild = createFiberFromPortal(newChild, returnFiber.mode, lanes), newChild.return = returnFiber, newChild; + case REACT_LAZY_TYPE2: + return newChild = resolveLazy(newChild), createChild(returnFiber, newChild, lanes); + } + if (isArrayImpl2(newChild) || getIteratorFn2(newChild)) + return newChild = createFiberFromFragment(newChild, returnFiber.mode, lanes, null), newChild.return = returnFiber, newChild; + if (typeof newChild.then === "function") + return createChild(returnFiber, unwrapThenable(newChild), lanes); + if (newChild.$$typeof === REACT_CONTEXT_TYPE2) + return createChild(returnFiber, readContextDuringReconciliation(returnFiber, newChild), lanes); + throwOnInvalidObjectTypeImpl(returnFiber, newChild); + } + return null; + } + function updateSlot(returnFiber, oldFiber, newChild, lanes) { + var key = oldFiber !== null ? oldFiber.key : null; + if (typeof newChild === "string" && newChild !== "" || typeof newChild === "number" || typeof newChild === "bigint") + return key !== null ? null : updateTextNode(returnFiber, oldFiber, "" + newChild, lanes); + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE2: + return newChild.key === key ? updateElement(returnFiber, oldFiber, newChild, lanes) : null; + case REACT_PORTAL_TYPE3: + return newChild.key === key ? updatePortal(returnFiber, oldFiber, newChild, lanes) : null; + case REACT_LAZY_TYPE2: + return newChild = resolveLazy(newChild), updateSlot(returnFiber, oldFiber, newChild, lanes); + } + if (isArrayImpl2(newChild) || getIteratorFn2(newChild)) + return key !== null ? null : updateFragment(returnFiber, oldFiber, newChild, lanes, null); + if (typeof newChild.then === "function") + return updateSlot(returnFiber, oldFiber, unwrapThenable(newChild), lanes); + if (newChild.$$typeof === REACT_CONTEXT_TYPE2) + return updateSlot(returnFiber, oldFiber, readContextDuringReconciliation(returnFiber, newChild), lanes); + throwOnInvalidObjectTypeImpl(returnFiber, newChild); + } + return null; + } + function updateFromMap(existingChildren, returnFiber, newIdx, newChild, lanes) { + if (typeof newChild === "string" && newChild !== "" || typeof newChild === "number" || typeof newChild === "bigint") + return existingChildren = existingChildren.get(newIdx) || null, updateTextNode(returnFiber, existingChildren, "" + newChild, lanes); + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE2: + return existingChildren = existingChildren.get(newChild.key === null ? newIdx : newChild.key) || null, updateElement(returnFiber, existingChildren, newChild, lanes); + case REACT_PORTAL_TYPE3: + return existingChildren = existingChildren.get(newChild.key === null ? newIdx : newChild.key) || null, updatePortal(returnFiber, existingChildren, newChild, lanes); + case REACT_LAZY_TYPE2: + return newChild = resolveLazy(newChild), updateFromMap(existingChildren, returnFiber, newIdx, newChild, lanes); + } + if (isArrayImpl2(newChild) || getIteratorFn2(newChild)) + return existingChildren = existingChildren.get(newIdx) || null, updateFragment(returnFiber, existingChildren, newChild, lanes, null); + if (typeof newChild.then === "function") + return updateFromMap(existingChildren, returnFiber, newIdx, unwrapThenable(newChild), lanes); + if (newChild.$$typeof === REACT_CONTEXT_TYPE2) + return updateFromMap(existingChildren, returnFiber, newIdx, readContextDuringReconciliation(returnFiber, newChild), lanes); + throwOnInvalidObjectTypeImpl(returnFiber, newChild); + } + return null; + } + function reconcileChildrenArray(returnFiber, currentFirstChild, newChildren, lanes) { + for (var resultingFirstChild = null, previousNewFiber = null, oldFiber = currentFirstChild, newIdx = currentFirstChild = 0, nextOldFiber = null;oldFiber !== null && newIdx < newChildren.length; newIdx++) { + oldFiber.index > newIdx ? (nextOldFiber = oldFiber, oldFiber = null) : nextOldFiber = oldFiber.sibling; + var newFiber = updateSlot(returnFiber, oldFiber, newChildren[newIdx], lanes); + if (newFiber === null) { + oldFiber === null && (oldFiber = nextOldFiber); + break; + } + shouldTrackSideEffects && oldFiber && newFiber.alternate === null && deleteChild(returnFiber, oldFiber); + currentFirstChild = placeChild(newFiber, currentFirstChild, newIdx); + previousNewFiber === null ? resultingFirstChild = newFiber : previousNewFiber.sibling = newFiber; + previousNewFiber = newFiber; + oldFiber = nextOldFiber; + } + if (newIdx === newChildren.length) + return deleteRemainingChildren(returnFiber, oldFiber), isHydrating && pushTreeFork(returnFiber, newIdx), resultingFirstChild; + if (oldFiber === null) { + for (;newIdx < newChildren.length; newIdx++) + oldFiber = createChild(returnFiber, newChildren[newIdx], lanes), oldFiber !== null && (currentFirstChild = placeChild(oldFiber, currentFirstChild, newIdx), previousNewFiber === null ? resultingFirstChild = oldFiber : previousNewFiber.sibling = oldFiber, previousNewFiber = oldFiber); + isHydrating && pushTreeFork(returnFiber, newIdx); + return resultingFirstChild; + } + for (oldFiber = mapRemainingChildren(oldFiber);newIdx < newChildren.length; newIdx++) + nextOldFiber = updateFromMap(oldFiber, returnFiber, newIdx, newChildren[newIdx], lanes), nextOldFiber !== null && (shouldTrackSideEffects && nextOldFiber.alternate !== null && oldFiber.delete(nextOldFiber.key === null ? newIdx : nextOldFiber.key), currentFirstChild = placeChild(nextOldFiber, currentFirstChild, newIdx), previousNewFiber === null ? resultingFirstChild = nextOldFiber : previousNewFiber.sibling = nextOldFiber, previousNewFiber = nextOldFiber); + shouldTrackSideEffects && oldFiber.forEach(function(child) { + return deleteChild(returnFiber, child); + }); + isHydrating && pushTreeFork(returnFiber, newIdx); + return resultingFirstChild; + } + function reconcileChildrenIterator(returnFiber, currentFirstChild, newChildren, lanes) { + if (newChildren == null) + throw Error(formatProdErrorMessage2(151)); + for (var resultingFirstChild = null, previousNewFiber = null, oldFiber = currentFirstChild, newIdx = currentFirstChild = 0, nextOldFiber = null, step = newChildren.next();oldFiber !== null && !step.done; newIdx++, step = newChildren.next()) { + oldFiber.index > newIdx ? (nextOldFiber = oldFiber, oldFiber = null) : nextOldFiber = oldFiber.sibling; + var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes); + if (newFiber === null) { + oldFiber === null && (oldFiber = nextOldFiber); + break; + } + shouldTrackSideEffects && oldFiber && newFiber.alternate === null && deleteChild(returnFiber, oldFiber); + currentFirstChild = placeChild(newFiber, currentFirstChild, newIdx); + previousNewFiber === null ? resultingFirstChild = newFiber : previousNewFiber.sibling = newFiber; + previousNewFiber = newFiber; + oldFiber = nextOldFiber; + } + if (step.done) + return deleteRemainingChildren(returnFiber, oldFiber), isHydrating && pushTreeFork(returnFiber, newIdx), resultingFirstChild; + if (oldFiber === null) { + for (;!step.done; newIdx++, step = newChildren.next()) + step = createChild(returnFiber, step.value, lanes), step !== null && (currentFirstChild = placeChild(step, currentFirstChild, newIdx), previousNewFiber === null ? resultingFirstChild = step : previousNewFiber.sibling = step, previousNewFiber = step); + isHydrating && pushTreeFork(returnFiber, newIdx); + return resultingFirstChild; + } + for (oldFiber = mapRemainingChildren(oldFiber);!step.done; newIdx++, step = newChildren.next()) + step = updateFromMap(oldFiber, returnFiber, newIdx, step.value, lanes), step !== null && (shouldTrackSideEffects && step.alternate !== null && oldFiber.delete(step.key === null ? newIdx : step.key), currentFirstChild = placeChild(step, currentFirstChild, newIdx), previousNewFiber === null ? resultingFirstChild = step : previousNewFiber.sibling = step, previousNewFiber = step); + shouldTrackSideEffects && oldFiber.forEach(function(child) { + return deleteChild(returnFiber, child); + }); + isHydrating && pushTreeFork(returnFiber, newIdx); + return resultingFirstChild; + } + function reconcileChildFibersImpl(returnFiber, currentFirstChild, newChild, lanes) { + typeof newChild === "object" && newChild !== null && newChild.type === REACT_FRAGMENT_TYPE2 && newChild.key === null && (newChild = newChild.props.children); + if (typeof newChild === "object" && newChild !== null) { + switch (newChild.$$typeof) { + case REACT_ELEMENT_TYPE2: + a: { + for (var key = newChild.key;currentFirstChild !== null; ) { + if (currentFirstChild.key === key) { + key = newChild.type; + if (key === REACT_FRAGMENT_TYPE2) { + if (currentFirstChild.tag === 7) { + deleteRemainingChildren(returnFiber, currentFirstChild.sibling); + lanes = useFiber(currentFirstChild, newChild.props.children); + lanes.return = returnFiber; + returnFiber = lanes; + break a; + } + } else if (currentFirstChild.elementType === key || typeof key === "object" && key !== null && key.$$typeof === REACT_LAZY_TYPE2 && resolveLazy(key) === currentFirstChild.type) { + deleteRemainingChildren(returnFiber, currentFirstChild.sibling); + lanes = useFiber(currentFirstChild, newChild.props); + coerceRef(lanes, newChild); + lanes.return = returnFiber; + returnFiber = lanes; + break a; + } + deleteRemainingChildren(returnFiber, currentFirstChild); + break; + } else + deleteChild(returnFiber, currentFirstChild); + currentFirstChild = currentFirstChild.sibling; + } + newChild.type === REACT_FRAGMENT_TYPE2 ? (lanes = createFiberFromFragment(newChild.props.children, returnFiber.mode, lanes, newChild.key), lanes.return = returnFiber, returnFiber = lanes) : (lanes = createFiberFromTypeAndProps(newChild.type, newChild.key, newChild.props, null, returnFiber.mode, lanes), coerceRef(lanes, newChild), lanes.return = returnFiber, returnFiber = lanes); + } + return placeSingleChild(returnFiber); + case REACT_PORTAL_TYPE3: + a: { + for (key = newChild.key;currentFirstChild !== null; ) { + if (currentFirstChild.key === key) + if (currentFirstChild.tag === 4 && currentFirstChild.stateNode.containerInfo === newChild.containerInfo && currentFirstChild.stateNode.implementation === newChild.implementation) { + deleteRemainingChildren(returnFiber, currentFirstChild.sibling); + lanes = useFiber(currentFirstChild, newChild.children || []); + lanes.return = returnFiber; + returnFiber = lanes; + break a; + } else { + deleteRemainingChildren(returnFiber, currentFirstChild); + break; + } + else + deleteChild(returnFiber, currentFirstChild); + currentFirstChild = currentFirstChild.sibling; + } + lanes = createFiberFromPortal(newChild, returnFiber.mode, lanes); + lanes.return = returnFiber; + returnFiber = lanes; + } + return placeSingleChild(returnFiber); + case REACT_LAZY_TYPE2: + return newChild = resolveLazy(newChild), reconcileChildFibersImpl(returnFiber, currentFirstChild, newChild, lanes); + } + if (isArrayImpl2(newChild)) + return reconcileChildrenArray(returnFiber, currentFirstChild, newChild, lanes); + if (getIteratorFn2(newChild)) { + key = getIteratorFn2(newChild); + if (typeof key !== "function") + throw Error(formatProdErrorMessage2(150)); + newChild = key.call(newChild); + return reconcileChildrenIterator(returnFiber, currentFirstChild, newChild, lanes); + } + if (typeof newChild.then === "function") + return reconcileChildFibersImpl(returnFiber, currentFirstChild, unwrapThenable(newChild), lanes); + if (newChild.$$typeof === REACT_CONTEXT_TYPE2) + return reconcileChildFibersImpl(returnFiber, currentFirstChild, readContextDuringReconciliation(returnFiber, newChild), lanes); + throwOnInvalidObjectTypeImpl(returnFiber, newChild); + } + return typeof newChild === "string" && newChild !== "" || typeof newChild === "number" || typeof newChild === "bigint" ? (newChild = "" + newChild, currentFirstChild !== null && currentFirstChild.tag === 6 ? (deleteRemainingChildren(returnFiber, currentFirstChild.sibling), lanes = useFiber(currentFirstChild, newChild), lanes.return = returnFiber, returnFiber = lanes) : (deleteRemainingChildren(returnFiber, currentFirstChild), lanes = createFiberFromText(newChild, returnFiber.mode, lanes), lanes.return = returnFiber, returnFiber = lanes), placeSingleChild(returnFiber)) : deleteRemainingChildren(returnFiber, currentFirstChild); + } + return function(returnFiber, currentFirstChild, newChild, lanes) { + try { + thenableIndexCounter$1 = 0; + var firstChildFiber = reconcileChildFibersImpl(returnFiber, currentFirstChild, newChild, lanes); + thenableState$1 = null; + return firstChildFiber; + } catch (x) { + if (x === SuspenseException || x === SuspenseActionException) + throw x; + var fiber = createFiberImplClass(29, x, null, returnFiber.mode); + fiber.lanes = lanes; + fiber.return = returnFiber; + return fiber; + } finally {} + }; +} +function initializeUpdateQueue(fiber) { + fiber.updateQueue = { + baseState: fiber.memoizedState, + firstBaseUpdate: null, + lastBaseUpdate: null, + shared: { pending: null, lanes: 0, hiddenCallbacks: null }, + callbacks: null + }; +} +function cloneUpdateQueue(current, workInProgress) { + current = current.updateQueue; + workInProgress.updateQueue === current && (workInProgress.updateQueue = { + baseState: current.baseState, + firstBaseUpdate: current.firstBaseUpdate, + lastBaseUpdate: current.lastBaseUpdate, + shared: current.shared, + callbacks: null + }); +} +function createUpdate(lane) { + return { lane, tag: 0, payload: null, callback: null, next: null }; +} +function enqueueUpdate(fiber, update, lane) { + var updateQueue = fiber.updateQueue; + if (updateQueue === null) + return null; + updateQueue = updateQueue.shared; + if ((executionContext & 2) !== 0) { + var pending = updateQueue.pending; + pending === null ? update.next = update : (update.next = pending.next, pending.next = update); + updateQueue.pending = update; + update = getRootForUpdatedFiber(fiber); + markUpdateLaneFromFiberToRoot(fiber, null, lane); + return update; + } + enqueueUpdate$1(fiber, updateQueue, update, lane); + return getRootForUpdatedFiber(fiber); +} +function entangleTransitions(root2, fiber, lane) { + fiber = fiber.updateQueue; + if (fiber !== null && (fiber = fiber.shared, (lane & 4194048) !== 0)) { + var queueLanes = fiber.lanes; + queueLanes &= root2.pendingLanes; + lane |= queueLanes; + fiber.lanes = lane; + markRootEntangled(root2, lane); + } +} +function enqueueCapturedUpdate(workInProgress, capturedUpdate) { + var { updateQueue: queue, alternate: current } = workInProgress; + if (current !== null && (current = current.updateQueue, queue === current)) { + var newFirst = null, newLast = null; + queue = queue.firstBaseUpdate; + if (queue !== null) { + do { + var clone = { + lane: queue.lane, + tag: queue.tag, + payload: queue.payload, + callback: null, + next: null + }; + newLast === null ? newFirst = newLast = clone : newLast = newLast.next = clone; + queue = queue.next; + } while (queue !== null); + newLast === null ? newFirst = newLast = capturedUpdate : newLast = newLast.next = capturedUpdate; + } else + newFirst = newLast = capturedUpdate; + queue = { + baseState: current.baseState, + firstBaseUpdate: newFirst, + lastBaseUpdate: newLast, + shared: current.shared, + callbacks: current.callbacks + }; + workInProgress.updateQueue = queue; + return; + } + workInProgress = queue.lastBaseUpdate; + workInProgress === null ? queue.firstBaseUpdate = capturedUpdate : workInProgress.next = capturedUpdate; + queue.lastBaseUpdate = capturedUpdate; +} +function suspendIfUpdateReadFromEntangledAsyncAction() { + if (didReadFromEntangledAsyncAction) { + var entangledActionThenable = currentEntangledActionThenable; + if (entangledActionThenable !== null) + throw entangledActionThenable; + } +} +function processUpdateQueue(workInProgress$jscomp$0, props, instance$jscomp$0, renderLanes) { + didReadFromEntangledAsyncAction = false; + var queue = workInProgress$jscomp$0.updateQueue; + hasForceUpdate = false; + var { firstBaseUpdate, lastBaseUpdate } = queue, pendingQueue = queue.shared.pending; + if (pendingQueue !== null) { + queue.shared.pending = null; + var lastPendingUpdate = pendingQueue, firstPendingUpdate = lastPendingUpdate.next; + lastPendingUpdate.next = null; + lastBaseUpdate === null ? firstBaseUpdate = firstPendingUpdate : lastBaseUpdate.next = firstPendingUpdate; + lastBaseUpdate = lastPendingUpdate; + var current = workInProgress$jscomp$0.alternate; + current !== null && (current = current.updateQueue, pendingQueue = current.lastBaseUpdate, pendingQueue !== lastBaseUpdate && (pendingQueue === null ? current.firstBaseUpdate = firstPendingUpdate : pendingQueue.next = firstPendingUpdate, current.lastBaseUpdate = lastPendingUpdate)); + } + if (firstBaseUpdate !== null) { + var newState = queue.baseState; + lastBaseUpdate = 0; + current = firstPendingUpdate = lastPendingUpdate = null; + pendingQueue = firstBaseUpdate; + do { + var updateLane = pendingQueue.lane & -536870913, isHiddenUpdate = updateLane !== pendingQueue.lane; + if (isHiddenUpdate ? (workInProgressRootRenderLanes & updateLane) === updateLane : (renderLanes & updateLane) === updateLane) { + updateLane !== 0 && updateLane === currentEntangledLane && (didReadFromEntangledAsyncAction = true); + current !== null && (current = current.next = { + lane: 0, + tag: pendingQueue.tag, + payload: pendingQueue.payload, + callback: null, + next: null + }); + a: { + var workInProgress = workInProgress$jscomp$0, update = pendingQueue; + updateLane = props; + var instance = instance$jscomp$0; + switch (update.tag) { + case 1: + workInProgress = update.payload; + if (typeof workInProgress === "function") { + newState = workInProgress.call(instance, newState, updateLane); + break a; + } + newState = workInProgress; + break a; + case 3: + workInProgress.flags = workInProgress.flags & -65537 | 128; + case 0: + workInProgress = update.payload; + updateLane = typeof workInProgress === "function" ? workInProgress.call(instance, newState, updateLane) : workInProgress; + if (updateLane === null || updateLane === undefined) + break a; + newState = assign2({}, newState, updateLane); + break a; + case 2: + hasForceUpdate = true; + } + } + updateLane = pendingQueue.callback; + updateLane !== null && (workInProgress$jscomp$0.flags |= 64, isHiddenUpdate && (workInProgress$jscomp$0.flags |= 8192), isHiddenUpdate = queue.callbacks, isHiddenUpdate === null ? queue.callbacks = [updateLane] : isHiddenUpdate.push(updateLane)); + } else + isHiddenUpdate = { + lane: updateLane, + tag: pendingQueue.tag, + payload: pendingQueue.payload, + callback: pendingQueue.callback, + next: null + }, current === null ? (firstPendingUpdate = current = isHiddenUpdate, lastPendingUpdate = newState) : current = current.next = isHiddenUpdate, lastBaseUpdate |= updateLane; + pendingQueue = pendingQueue.next; + if (pendingQueue === null) + if (pendingQueue = queue.shared.pending, pendingQueue === null) + break; + else + isHiddenUpdate = pendingQueue, pendingQueue = isHiddenUpdate.next, isHiddenUpdate.next = null, queue.lastBaseUpdate = isHiddenUpdate, queue.shared.pending = null; + } while (1); + current === null && (lastPendingUpdate = newState); + queue.baseState = lastPendingUpdate; + queue.firstBaseUpdate = firstPendingUpdate; + queue.lastBaseUpdate = current; + firstBaseUpdate === null && (queue.shared.lanes = 0); + workInProgressRootSkippedLanes |= lastBaseUpdate; + workInProgress$jscomp$0.lanes = lastBaseUpdate; + workInProgress$jscomp$0.memoizedState = newState; + } +} +function callCallback(callback, context) { + if (typeof callback !== "function") + throw Error(formatProdErrorMessage2(191, callback)); + callback.call(context); +} +function commitCallbacks(updateQueue, context) { + var callbacks = updateQueue.callbacks; + if (callbacks !== null) + for (updateQueue.callbacks = null, updateQueue = 0;updateQueue < callbacks.length; updateQueue++) + callCallback(callbacks[updateQueue], context); +} +function pushHiddenContext(fiber, context) { + fiber = entangledRenderLanes; + push2(prevEntangledRenderLanesCursor, fiber); + push2(currentTreeHiddenStackCursor, context); + entangledRenderLanes = fiber | context.baseLanes; +} +function reuseHiddenContextOnStack() { + push2(prevEntangledRenderLanesCursor, entangledRenderLanes); + push2(currentTreeHiddenStackCursor, currentTreeHiddenStackCursor.current); +} +function popHiddenContext() { + entangledRenderLanes = prevEntangledRenderLanesCursor.current; + pop2(currentTreeHiddenStackCursor); + pop2(prevEntangledRenderLanesCursor); +} +function pushPrimaryTreeSuspenseHandler(handler) { + var current = handler.alternate; + push2(suspenseStackCursor, suspenseStackCursor.current & 1); + push2(suspenseHandlerStackCursor, handler); + shellBoundary === null && (current === null || currentTreeHiddenStackCursor.current !== null ? shellBoundary = handler : current.memoizedState !== null && (shellBoundary = handler)); +} +function pushDehydratedActivitySuspenseHandler(fiber) { + push2(suspenseStackCursor, suspenseStackCursor.current); + push2(suspenseHandlerStackCursor, fiber); + shellBoundary === null && (shellBoundary = fiber); +} +function pushOffscreenSuspenseHandler(fiber) { + fiber.tag === 22 ? (push2(suspenseStackCursor, suspenseStackCursor.current), push2(suspenseHandlerStackCursor, fiber), shellBoundary === null && (shellBoundary = fiber)) : reuseSuspenseHandlerOnStack(fiber); +} +function reuseSuspenseHandlerOnStack() { + push2(suspenseStackCursor, suspenseStackCursor.current); + push2(suspenseHandlerStackCursor, suspenseHandlerStackCursor.current); +} +function popSuspenseHandler(fiber) { + pop2(suspenseHandlerStackCursor); + shellBoundary === fiber && (shellBoundary = null); + pop2(suspenseStackCursor); +} +function findFirstSuspended(row) { + for (var node = row;node !== null; ) { + if (node.tag === 13) { + var state = node.memoizedState; + if (state !== null && (state = state.dehydrated, state === null || isSuspenseInstancePending(state) || isSuspenseInstanceFallback(state))) + return node; + } else if (node.tag === 19 && (node.memoizedProps.revealOrder === "forwards" || node.memoizedProps.revealOrder === "backwards" || node.memoizedProps.revealOrder === "unstable_legacy-backwards" || node.memoizedProps.revealOrder === "together")) { + if ((node.flags & 128) !== 0) + return node; + } else if (node.child !== null) { + node.child.return = node; + node = node.child; + continue; + } + if (node === row) + break; + for (;node.sibling === null; ) { + if (node.return === null || node.return === row) + return null; + node = node.return; + } + node.sibling.return = node.return; + node = node.sibling; + } + return null; +} +function throwInvalidHookError() { + throw Error(formatProdErrorMessage2(321)); +} +function areHookInputsEqual(nextDeps, prevDeps) { + if (prevDeps === null) + return false; + for (var i = 0;i < prevDeps.length && i < nextDeps.length; i++) + if (!objectIs(nextDeps[i], prevDeps[i])) + return false; + return true; +} +function renderWithHooks(current, workInProgress, Component2, props, secondArg, nextRenderLanes) { + renderLanes = nextRenderLanes; + currentlyRenderingFiber = workInProgress; + workInProgress.memoizedState = null; + workInProgress.updateQueue = null; + workInProgress.lanes = 0; + ReactSharedInternals3.H = current === null || current.memoizedState === null ? HooksDispatcherOnMount : HooksDispatcherOnUpdate; + shouldDoubleInvokeUserFnsInHooksDEV = false; + nextRenderLanes = Component2(props, secondArg); + shouldDoubleInvokeUserFnsInHooksDEV = false; + didScheduleRenderPhaseUpdateDuringThisPass && (nextRenderLanes = renderWithHooksAgain(workInProgress, Component2, props, secondArg)); + finishRenderingHooks(current); + return nextRenderLanes; +} +function finishRenderingHooks(current) { + ReactSharedInternals3.H = ContextOnlyDispatcher; + var didRenderTooFewHooks = currentHook !== null && currentHook.next !== null; + renderLanes = 0; + workInProgressHook = currentHook = currentlyRenderingFiber = null; + didScheduleRenderPhaseUpdate = false; + thenableIndexCounter = 0; + thenableState = null; + if (didRenderTooFewHooks) + throw Error(formatProdErrorMessage2(300)); + current === null || didReceiveUpdate || (current = current.dependencies, current !== null && checkIfContextChanged(current) && (didReceiveUpdate = true)); +} +function renderWithHooksAgain(workInProgress, Component2, props, secondArg) { + currentlyRenderingFiber = workInProgress; + var numberOfReRenders = 0; + do { + didScheduleRenderPhaseUpdateDuringThisPass && (thenableState = null); + thenableIndexCounter = 0; + didScheduleRenderPhaseUpdateDuringThisPass = false; + if (25 <= numberOfReRenders) + throw Error(formatProdErrorMessage2(301)); + numberOfReRenders += 1; + workInProgressHook = currentHook = null; + if (workInProgress.updateQueue != null) { + var children = workInProgress.updateQueue; + children.lastEffect = null; + children.events = null; + children.stores = null; + children.memoCache != null && (children.memoCache.index = 0); + } + ReactSharedInternals3.H = HooksDispatcherOnRerender; + children = Component2(props, secondArg); + } while (didScheduleRenderPhaseUpdateDuringThisPass); + return children; +} +function TransitionAwareHostComponent() { + var dispatcher = ReactSharedInternals3.H, maybeThenable = dispatcher.useState()[0]; + maybeThenable = typeof maybeThenable.then === "function" ? useThenable(maybeThenable) : maybeThenable; + dispatcher = dispatcher.useState()[0]; + (currentHook !== null ? currentHook.memoizedState : null) !== dispatcher && (currentlyRenderingFiber.flags |= 1024); + return maybeThenable; +} +function checkDidRenderIdHook() { + var didRenderIdHook = localIdCounter !== 0; + localIdCounter = 0; + return didRenderIdHook; +} +function bailoutHooks(current, workInProgress, lanes) { + workInProgress.updateQueue = current.updateQueue; + workInProgress.flags &= -2053; + current.lanes &= ~lanes; +} +function resetHooksOnUnwind(workInProgress) { + if (didScheduleRenderPhaseUpdate) { + for (workInProgress = workInProgress.memoizedState;workInProgress !== null; ) { + var queue = workInProgress.queue; + queue !== null && (queue.pending = null); + workInProgress = workInProgress.next; + } + didScheduleRenderPhaseUpdate = false; + } + renderLanes = 0; + workInProgressHook = currentHook = currentlyRenderingFiber = null; + didScheduleRenderPhaseUpdateDuringThisPass = false; + thenableIndexCounter = localIdCounter = 0; + thenableState = null; +} +function mountWorkInProgressHook() { + var hook = { + memoizedState: null, + baseState: null, + baseQueue: null, + queue: null, + next: null + }; + workInProgressHook === null ? currentlyRenderingFiber.memoizedState = workInProgressHook = hook : workInProgressHook = workInProgressHook.next = hook; + return workInProgressHook; +} +function updateWorkInProgressHook() { + if (currentHook === null) { + var nextCurrentHook = currentlyRenderingFiber.alternate; + nextCurrentHook = nextCurrentHook !== null ? nextCurrentHook.memoizedState : null; + } else + nextCurrentHook = currentHook.next; + var nextWorkInProgressHook = workInProgressHook === null ? currentlyRenderingFiber.memoizedState : workInProgressHook.next; + if (nextWorkInProgressHook !== null) + workInProgressHook = nextWorkInProgressHook, currentHook = nextCurrentHook; + else { + if (nextCurrentHook === null) { + if (currentlyRenderingFiber.alternate === null) + throw Error(formatProdErrorMessage2(467)); + throw Error(formatProdErrorMessage2(310)); + } + currentHook = nextCurrentHook; + nextCurrentHook = { + memoizedState: currentHook.memoizedState, + baseState: currentHook.baseState, + baseQueue: currentHook.baseQueue, + queue: currentHook.queue, + next: null + }; + workInProgressHook === null ? currentlyRenderingFiber.memoizedState = workInProgressHook = nextCurrentHook : workInProgressHook = workInProgressHook.next = nextCurrentHook; + } + return workInProgressHook; +} +function createFunctionComponentUpdateQueue() { + return { lastEffect: null, events: null, stores: null, memoCache: null }; +} +function useThenable(thenable) { + var index2 = thenableIndexCounter; + thenableIndexCounter += 1; + thenableState === null && (thenableState = []); + thenable = trackUsedThenable(thenableState, thenable, index2); + index2 = currentlyRenderingFiber; + (workInProgressHook === null ? index2.memoizedState : workInProgressHook.next) === null && (index2 = index2.alternate, ReactSharedInternals3.H = index2 === null || index2.memoizedState === null ? HooksDispatcherOnMount : HooksDispatcherOnUpdate); + return thenable; +} +function use(usable) { + if (usable !== null && typeof usable === "object") { + if (typeof usable.then === "function") + return useThenable(usable); + if (usable.$$typeof === REACT_CONTEXT_TYPE2) + return readContext(usable); + } + throw Error(formatProdErrorMessage2(438, String(usable))); +} +function useMemoCache(size) { + var memoCache = null, updateQueue = currentlyRenderingFiber.updateQueue; + updateQueue !== null && (memoCache = updateQueue.memoCache); + if (memoCache == null) { + var current = currentlyRenderingFiber.alternate; + current !== null && (current = current.updateQueue, current !== null && (current = current.memoCache, current != null && (memoCache = { + data: current.data.map(function(array) { + return array.slice(); + }), + index: 0 + }))); + } + memoCache == null && (memoCache = { data: [], index: 0 }); + updateQueue === null && (updateQueue = createFunctionComponentUpdateQueue(), currentlyRenderingFiber.updateQueue = updateQueue); + updateQueue.memoCache = memoCache; + updateQueue = memoCache.data[memoCache.index]; + if (updateQueue === undefined) + for (updateQueue = memoCache.data[memoCache.index] = Array(size), current = 0;current < size; current++) + updateQueue[current] = REACT_MEMO_CACHE_SENTINEL; + memoCache.index++; + return updateQueue; +} +function basicStateReducer(state, action) { + return typeof action === "function" ? action(state) : action; +} +function updateReducer(reducer) { + var hook = updateWorkInProgressHook(); + return updateReducerImpl(hook, currentHook, reducer); +} +function updateReducerImpl(hook, current, reducer) { + var queue = hook.queue; + if (queue === null) + throw Error(formatProdErrorMessage2(311)); + queue.lastRenderedReducer = reducer; + var baseQueue = hook.baseQueue, pendingQueue = queue.pending; + if (pendingQueue !== null) { + if (baseQueue !== null) { + var baseFirst = baseQueue.next; + baseQueue.next = pendingQueue.next; + pendingQueue.next = baseFirst; + } + current.baseQueue = baseQueue = pendingQueue; + queue.pending = null; + } + pendingQueue = hook.baseState; + if (baseQueue === null) + hook.memoizedState = pendingQueue; + else { + current = baseQueue.next; + var newBaseQueueFirst = baseFirst = null, newBaseQueueLast = null, update = current, didReadFromEntangledAsyncAction$60 = false; + do { + var updateLane = update.lane & -536870913; + if (updateLane !== update.lane ? (workInProgressRootRenderLanes & updateLane) === updateLane : (renderLanes & updateLane) === updateLane) { + var revertLane = update.revertLane; + if (revertLane === 0) + newBaseQueueLast !== null && (newBaseQueueLast = newBaseQueueLast.next = { + lane: 0, + revertLane: 0, + gesture: null, + action: update.action, + hasEagerState: update.hasEagerState, + eagerState: update.eagerState, + next: null + }), updateLane === currentEntangledLane && (didReadFromEntangledAsyncAction$60 = true); + else if ((renderLanes & revertLane) === revertLane) { + update = update.next; + revertLane === currentEntangledLane && (didReadFromEntangledAsyncAction$60 = true); + continue; + } else + updateLane = { + lane: 0, + revertLane: update.revertLane, + gesture: null, + action: update.action, + hasEagerState: update.hasEagerState, + eagerState: update.eagerState, + next: null + }, newBaseQueueLast === null ? (newBaseQueueFirst = newBaseQueueLast = updateLane, baseFirst = pendingQueue) : newBaseQueueLast = newBaseQueueLast.next = updateLane, currentlyRenderingFiber.lanes |= revertLane, workInProgressRootSkippedLanes |= revertLane; + updateLane = update.action; + shouldDoubleInvokeUserFnsInHooksDEV && reducer(pendingQueue, updateLane); + pendingQueue = update.hasEagerState ? update.eagerState : reducer(pendingQueue, updateLane); + } else + revertLane = { + lane: updateLane, + revertLane: update.revertLane, + gesture: update.gesture, + action: update.action, + hasEagerState: update.hasEagerState, + eagerState: update.eagerState, + next: null + }, newBaseQueueLast === null ? (newBaseQueueFirst = newBaseQueueLast = revertLane, baseFirst = pendingQueue) : newBaseQueueLast = newBaseQueueLast.next = revertLane, currentlyRenderingFiber.lanes |= updateLane, workInProgressRootSkippedLanes |= updateLane; + update = update.next; + } while (update !== null && update !== current); + newBaseQueueLast === null ? baseFirst = pendingQueue : newBaseQueueLast.next = newBaseQueueFirst; + if (!objectIs(pendingQueue, hook.memoizedState) && (didReceiveUpdate = true, didReadFromEntangledAsyncAction$60 && (reducer = currentEntangledActionThenable, reducer !== null))) + throw reducer; + hook.memoizedState = pendingQueue; + hook.baseState = baseFirst; + hook.baseQueue = newBaseQueueLast; + queue.lastRenderedState = pendingQueue; + } + baseQueue === null && (queue.lanes = 0); + return [hook.memoizedState, queue.dispatch]; +} +function rerenderReducer(reducer) { + var hook = updateWorkInProgressHook(), queue = hook.queue; + if (queue === null) + throw Error(formatProdErrorMessage2(311)); + queue.lastRenderedReducer = reducer; + var { dispatch, pending: lastRenderPhaseUpdate } = queue, newState = hook.memoizedState; + if (lastRenderPhaseUpdate !== null) { + queue.pending = null; + var update = lastRenderPhaseUpdate = lastRenderPhaseUpdate.next; + do + newState = reducer(newState, update.action), update = update.next; + while (update !== lastRenderPhaseUpdate); + objectIs(newState, hook.memoizedState) || (didReceiveUpdate = true); + hook.memoizedState = newState; + hook.baseQueue === null && (hook.baseState = newState); + queue.lastRenderedState = newState; + } + return [newState, dispatch]; +} +function updateSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) { + var fiber = currentlyRenderingFiber, hook = updateWorkInProgressHook(), isHydrating$jscomp$0 = isHydrating; + if (isHydrating$jscomp$0) { + if (getServerSnapshot === undefined) + throw Error(formatProdErrorMessage2(407)); + getServerSnapshot = getServerSnapshot(); + } else + getServerSnapshot = getSnapshot(); + var snapshotChanged = !objectIs((currentHook || hook).memoizedState, getServerSnapshot); + snapshotChanged && (hook.memoizedState = getServerSnapshot, didReceiveUpdate = true); + hook = hook.queue; + updateEffect(subscribeToStore.bind(null, fiber, hook, subscribe), [ + subscribe + ]); + if (hook.getSnapshot !== getSnapshot || snapshotChanged || workInProgressHook !== null && workInProgressHook.memoizedState.tag & 1) { + fiber.flags |= 2048; + pushSimpleEffect(9, { destroy: undefined }, updateStoreInstance.bind(null, fiber, hook, getServerSnapshot, getSnapshot), null); + if (workInProgressRoot === null) + throw Error(formatProdErrorMessage2(349)); + isHydrating$jscomp$0 || (renderLanes & 127) !== 0 || pushStoreConsistencyCheck(fiber, getSnapshot, getServerSnapshot); + } + return getServerSnapshot; +} +function pushStoreConsistencyCheck(fiber, getSnapshot, renderedSnapshot) { + fiber.flags |= 16384; + fiber = { getSnapshot, value: renderedSnapshot }; + getSnapshot = currentlyRenderingFiber.updateQueue; + getSnapshot === null ? (getSnapshot = createFunctionComponentUpdateQueue(), currentlyRenderingFiber.updateQueue = getSnapshot, getSnapshot.stores = [fiber]) : (renderedSnapshot = getSnapshot.stores, renderedSnapshot === null ? getSnapshot.stores = [fiber] : renderedSnapshot.push(fiber)); +} +function updateStoreInstance(fiber, inst, nextSnapshot, getSnapshot) { + inst.value = nextSnapshot; + inst.getSnapshot = getSnapshot; + checkIfSnapshotChanged(inst) && forceStoreRerender(fiber); +} +function subscribeToStore(fiber, inst, subscribe) { + return subscribe(function() { + checkIfSnapshotChanged(inst) && forceStoreRerender(fiber); + }); +} +function checkIfSnapshotChanged(inst) { + var latestGetSnapshot = inst.getSnapshot; + inst = inst.value; + try { + var nextValue = latestGetSnapshot(); + return !objectIs(inst, nextValue); + } catch (error) { + return true; + } +} +function forceStoreRerender(fiber) { + var root2 = enqueueConcurrentRenderForLane(fiber, 2); + root2 !== null && scheduleUpdateOnFiber(root2, fiber, 2); +} +function mountStateImpl(initialState) { + var hook = mountWorkInProgressHook(); + if (typeof initialState === "function") { + var initialStateInitializer = initialState; + initialState = initialStateInitializer(); + if (shouldDoubleInvokeUserFnsInHooksDEV) { + setIsStrictModeForDevtools(true); + try { + initialStateInitializer(); + } finally { + setIsStrictModeForDevtools(false); + } + } + } + hook.memoizedState = hook.baseState = initialState; + hook.queue = { + pending: null, + lanes: 0, + dispatch: null, + lastRenderedReducer: basicStateReducer, + lastRenderedState: initialState + }; + return hook; +} +function updateOptimisticImpl(hook, current, passthrough, reducer) { + hook.baseState = passthrough; + return updateReducerImpl(hook, currentHook, typeof reducer === "function" ? reducer : basicStateReducer); +} +function dispatchActionState(fiber, actionQueue, setPendingState, setState, payload) { + if (isRenderPhaseUpdate(fiber)) + throw Error(formatProdErrorMessage2(485)); + fiber = actionQueue.action; + if (fiber !== null) { + var actionNode = { + payload, + action: fiber, + next: null, + isTransition: true, + status: "pending", + value: null, + reason: null, + listeners: [], + then: function(listener) { + actionNode.listeners.push(listener); + } + }; + ReactSharedInternals3.T !== null ? setPendingState(true) : actionNode.isTransition = false; + setState(actionNode); + setPendingState = actionQueue.pending; + setPendingState === null ? (actionNode.next = actionQueue.pending = actionNode, runActionStateAction(actionQueue, actionNode)) : (actionNode.next = setPendingState.next, actionQueue.pending = setPendingState.next = actionNode); + } +} +function runActionStateAction(actionQueue, node) { + var { action, payload } = node, prevState = actionQueue.state; + if (node.isTransition) { + var prevTransition = ReactSharedInternals3.T, currentTransition = {}; + ReactSharedInternals3.T = currentTransition; + try { + var returnValue = action(prevState, payload), onStartTransitionFinish = ReactSharedInternals3.S; + onStartTransitionFinish !== null && onStartTransitionFinish(currentTransition, returnValue); + handleActionReturnValue(actionQueue, node, returnValue); + } catch (error) { + onActionError(actionQueue, node, error); + } finally { + prevTransition !== null && currentTransition.types !== null && (prevTransition.types = currentTransition.types), ReactSharedInternals3.T = prevTransition; + } + } else + try { + prevTransition = action(prevState, payload), handleActionReturnValue(actionQueue, node, prevTransition); + } catch (error$66) { + onActionError(actionQueue, node, error$66); + } +} +function handleActionReturnValue(actionQueue, node, returnValue) { + returnValue !== null && typeof returnValue === "object" && typeof returnValue.then === "function" ? returnValue.then(function(nextState) { + onActionSuccess(actionQueue, node, nextState); + }, function(error) { + return onActionError(actionQueue, node, error); + }) : onActionSuccess(actionQueue, node, returnValue); +} +function onActionSuccess(actionQueue, actionNode, nextState) { + actionNode.status = "fulfilled"; + actionNode.value = nextState; + notifyActionListeners(actionNode); + actionQueue.state = nextState; + actionNode = actionQueue.pending; + actionNode !== null && (nextState = actionNode.next, nextState === actionNode ? actionQueue.pending = null : (nextState = nextState.next, actionNode.next = nextState, runActionStateAction(actionQueue, nextState))); +} +function onActionError(actionQueue, actionNode, error) { + var last = actionQueue.pending; + actionQueue.pending = null; + if (last !== null) { + last = last.next; + do + actionNode.status = "rejected", actionNode.reason = error, notifyActionListeners(actionNode), actionNode = actionNode.next; + while (actionNode !== last); + } + actionQueue.action = null; +} +function notifyActionListeners(actionNode) { + actionNode = actionNode.listeners; + for (var i = 0;i < actionNode.length; i++) + (0, actionNode[i])(); +} +function actionStateReducer(oldState, newState) { + return newState; +} +function mountActionState(action, initialStateProp) { + if (isHydrating) { + var ssrFormState = workInProgressRoot.formState; + if (ssrFormState !== null) { + a: { + var JSCompiler_inline_result = currentlyRenderingFiber; + if (isHydrating) { + if (nextHydratableInstance) { + b: { + var JSCompiler_inline_result$jscomp$0 = nextHydratableInstance; + for (var inRootOrSingleton = rootOrSingletonContext;JSCompiler_inline_result$jscomp$0.nodeType !== 8; ) { + if (!inRootOrSingleton) { + JSCompiler_inline_result$jscomp$0 = null; + break b; + } + JSCompiler_inline_result$jscomp$0 = getNextHydratable(JSCompiler_inline_result$jscomp$0.nextSibling); + if (JSCompiler_inline_result$jscomp$0 === null) { + JSCompiler_inline_result$jscomp$0 = null; + break b; + } + } + inRootOrSingleton = JSCompiler_inline_result$jscomp$0.data; + JSCompiler_inline_result$jscomp$0 = inRootOrSingleton === "F!" || inRootOrSingleton === "F" ? JSCompiler_inline_result$jscomp$0 : null; + } + if (JSCompiler_inline_result$jscomp$0) { + nextHydratableInstance = getNextHydratable(JSCompiler_inline_result$jscomp$0.nextSibling); + JSCompiler_inline_result = JSCompiler_inline_result$jscomp$0.data === "F!"; + break a; + } + } + throwOnHydrationMismatch(JSCompiler_inline_result); + } + JSCompiler_inline_result = false; + } + JSCompiler_inline_result && (initialStateProp = ssrFormState[0]); + } + } + ssrFormState = mountWorkInProgressHook(); + ssrFormState.memoizedState = ssrFormState.baseState = initialStateProp; + JSCompiler_inline_result = { + pending: null, + lanes: 0, + dispatch: null, + lastRenderedReducer: actionStateReducer, + lastRenderedState: initialStateProp + }; + ssrFormState.queue = JSCompiler_inline_result; + ssrFormState = dispatchSetState.bind(null, currentlyRenderingFiber, JSCompiler_inline_result); + JSCompiler_inline_result.dispatch = ssrFormState; + JSCompiler_inline_result = mountStateImpl(false); + inRootOrSingleton = dispatchOptimisticSetState.bind(null, currentlyRenderingFiber, false, JSCompiler_inline_result.queue); + JSCompiler_inline_result = mountWorkInProgressHook(); + JSCompiler_inline_result$jscomp$0 = { + state: initialStateProp, + dispatch: null, + action, + pending: null + }; + JSCompiler_inline_result.queue = JSCompiler_inline_result$jscomp$0; + ssrFormState = dispatchActionState.bind(null, currentlyRenderingFiber, JSCompiler_inline_result$jscomp$0, inRootOrSingleton, ssrFormState); + JSCompiler_inline_result$jscomp$0.dispatch = ssrFormState; + JSCompiler_inline_result.memoizedState = action; + return [initialStateProp, ssrFormState, false]; +} +function updateActionState(action) { + var stateHook = updateWorkInProgressHook(); + return updateActionStateImpl(stateHook, currentHook, action); +} +function updateActionStateImpl(stateHook, currentStateHook, action) { + currentStateHook = updateReducerImpl(stateHook, currentStateHook, actionStateReducer)[0]; + stateHook = updateReducer(basicStateReducer)[0]; + if (typeof currentStateHook === "object" && currentStateHook !== null && typeof currentStateHook.then === "function") + try { + var state = useThenable(currentStateHook); + } catch (x) { + if (x === SuspenseException) + throw SuspenseActionException; + throw x; + } + else + state = currentStateHook; + currentStateHook = updateWorkInProgressHook(); + var actionQueue = currentStateHook.queue, dispatch = actionQueue.dispatch; + action !== currentStateHook.memoizedState && (currentlyRenderingFiber.flags |= 2048, pushSimpleEffect(9, { destroy: undefined }, actionStateActionEffect.bind(null, actionQueue, action), null)); + return [state, dispatch, stateHook]; +} +function actionStateActionEffect(actionQueue, action) { + actionQueue.action = action; +} +function rerenderActionState(action) { + var stateHook = updateWorkInProgressHook(), currentStateHook = currentHook; + if (currentStateHook !== null) + return updateActionStateImpl(stateHook, currentStateHook, action); + updateWorkInProgressHook(); + stateHook = stateHook.memoizedState; + currentStateHook = updateWorkInProgressHook(); + var dispatch = currentStateHook.queue.dispatch; + currentStateHook.memoizedState = action; + return [stateHook, dispatch, false]; +} +function pushSimpleEffect(tag, inst, create, deps) { + tag = { tag, create, deps, inst, next: null }; + inst = currentlyRenderingFiber.updateQueue; + inst === null && (inst = createFunctionComponentUpdateQueue(), currentlyRenderingFiber.updateQueue = inst); + create = inst.lastEffect; + create === null ? inst.lastEffect = tag.next = tag : (deps = create.next, create.next = tag, tag.next = deps, inst.lastEffect = tag); + return tag; +} +function updateRef() { + return updateWorkInProgressHook().memoizedState; +} +function mountEffectImpl(fiberFlags, hookFlags, create, deps) { + var hook = mountWorkInProgressHook(); + currentlyRenderingFiber.flags |= fiberFlags; + hook.memoizedState = pushSimpleEffect(1 | hookFlags, { destroy: undefined }, create, deps === undefined ? null : deps); +} +function updateEffectImpl(fiberFlags, hookFlags, create, deps) { + var hook = updateWorkInProgressHook(); + deps = deps === undefined ? null : deps; + var inst = hook.memoizedState.inst; + currentHook !== null && deps !== null && areHookInputsEqual(deps, currentHook.memoizedState.deps) ? hook.memoizedState = pushSimpleEffect(hookFlags, inst, create, deps) : (currentlyRenderingFiber.flags |= fiberFlags, hook.memoizedState = pushSimpleEffect(1 | hookFlags, inst, create, deps)); +} +function mountEffect(create, deps) { + mountEffectImpl(8390656, 8, create, deps); +} +function updateEffect(create, deps) { + updateEffectImpl(2048, 8, create, deps); +} +function useEffectEventImpl(payload) { + currentlyRenderingFiber.flags |= 4; + var componentUpdateQueue = currentlyRenderingFiber.updateQueue; + if (componentUpdateQueue === null) + componentUpdateQueue = createFunctionComponentUpdateQueue(), currentlyRenderingFiber.updateQueue = componentUpdateQueue, componentUpdateQueue.events = [payload]; + else { + var events = componentUpdateQueue.events; + events === null ? componentUpdateQueue.events = [payload] : events.push(payload); + } +} +function updateEvent(callback) { + var ref = updateWorkInProgressHook().memoizedState; + useEffectEventImpl({ ref, nextImpl: callback }); + return function() { + if ((executionContext & 2) !== 0) + throw Error(formatProdErrorMessage2(440)); + return ref.impl.apply(undefined, arguments); + }; +} +function updateInsertionEffect(create, deps) { + return updateEffectImpl(4, 2, create, deps); +} +function updateLayoutEffect(create, deps) { + return updateEffectImpl(4, 4, create, deps); +} +function imperativeHandleEffect(create, ref) { + if (typeof ref === "function") { + create = create(); + var refCleanup = ref(create); + return function() { + typeof refCleanup === "function" ? refCleanup() : ref(null); + }; + } + if (ref !== null && ref !== undefined) + return create = create(), ref.current = create, function() { + ref.current = null; + }; +} +function updateImperativeHandle(ref, create, deps) { + deps = deps !== null && deps !== undefined ? deps.concat([ref]) : null; + updateEffectImpl(4, 4, imperativeHandleEffect.bind(null, create, ref), deps); +} +function mountDebugValue() {} +function updateCallback(callback, deps) { + var hook = updateWorkInProgressHook(); + deps = deps === undefined ? null : deps; + var prevState = hook.memoizedState; + if (deps !== null && areHookInputsEqual(deps, prevState[1])) + return prevState[0]; + hook.memoizedState = [callback, deps]; + return callback; +} +function updateMemo(nextCreate, deps) { + var hook = updateWorkInProgressHook(); + deps = deps === undefined ? null : deps; + var prevState = hook.memoizedState; + if (deps !== null && areHookInputsEqual(deps, prevState[1])) + return prevState[0]; + prevState = nextCreate(); + if (shouldDoubleInvokeUserFnsInHooksDEV) { + setIsStrictModeForDevtools(true); + try { + nextCreate(); + } finally { + setIsStrictModeForDevtools(false); + } + } + hook.memoizedState = [prevState, deps]; + return prevState; +} +function mountDeferredValueImpl(hook, value, initialValue) { + if (initialValue === undefined || (renderLanes & 1073741824) !== 0 && (workInProgressRootRenderLanes & 261930) === 0) + return hook.memoizedState = value; + hook.memoizedState = initialValue; + hook = requestDeferredLane(); + currentlyRenderingFiber.lanes |= hook; + workInProgressRootSkippedLanes |= hook; + return initialValue; +} +function updateDeferredValueImpl(hook, prevValue, value, initialValue) { + if (objectIs(value, prevValue)) + return value; + if (currentTreeHiddenStackCursor.current !== null) + return hook = mountDeferredValueImpl(hook, value, initialValue), objectIs(hook, prevValue) || (didReceiveUpdate = true), hook; + if ((renderLanes & 42) === 0 || (renderLanes & 1073741824) !== 0 && (workInProgressRootRenderLanes & 261930) === 0) + return didReceiveUpdate = true, hook.memoizedState = value; + hook = requestDeferredLane(); + currentlyRenderingFiber.lanes |= hook; + workInProgressRootSkippedLanes |= hook; + return prevValue; +} +function startTransition(fiber, queue, pendingState, finishedState, callback) { + var previousPriority = ReactDOMSharedInternals.p; + ReactDOMSharedInternals.p = previousPriority !== 0 && 8 > previousPriority ? previousPriority : 8; + var prevTransition = ReactSharedInternals3.T, currentTransition = {}; + ReactSharedInternals3.T = currentTransition; + dispatchOptimisticSetState(fiber, false, queue, pendingState); + try { + var returnValue = callback(), onStartTransitionFinish = ReactSharedInternals3.S; + onStartTransitionFinish !== null && onStartTransitionFinish(currentTransition, returnValue); + if (returnValue !== null && typeof returnValue === "object" && typeof returnValue.then === "function") { + var thenableForFinishedState = chainThenableValue(returnValue, finishedState); + dispatchSetStateInternal(fiber, queue, thenableForFinishedState, requestUpdateLane(fiber)); + } else + dispatchSetStateInternal(fiber, queue, finishedState, requestUpdateLane(fiber)); + } catch (error) { + dispatchSetStateInternal(fiber, queue, { then: function() {}, status: "rejected", reason: error }, requestUpdateLane()); + } finally { + ReactDOMSharedInternals.p = previousPriority, prevTransition !== null && currentTransition.types !== null && (prevTransition.types = currentTransition.types), ReactSharedInternals3.T = prevTransition; + } +} +function noop3() {} +function startHostTransition(formFiber, pendingState, action, formData) { + if (formFiber.tag !== 5) + throw Error(formatProdErrorMessage2(476)); + var queue = ensureFormComponentIsStateful(formFiber).queue; + startTransition(formFiber, queue, pendingState, sharedNotPendingObject, action === null ? noop3 : function() { + requestFormReset$1(formFiber); + return action(formData); + }); +} +function ensureFormComponentIsStateful(formFiber) { + var existingStateHook = formFiber.memoizedState; + if (existingStateHook !== null) + return existingStateHook; + existingStateHook = { + memoizedState: sharedNotPendingObject, + baseState: sharedNotPendingObject, + baseQueue: null, + queue: { + pending: null, + lanes: 0, + dispatch: null, + lastRenderedReducer: basicStateReducer, + lastRenderedState: sharedNotPendingObject + }, + next: null + }; + var initialResetState = {}; + existingStateHook.next = { + memoizedState: initialResetState, + baseState: initialResetState, + baseQueue: null, + queue: { + pending: null, + lanes: 0, + dispatch: null, + lastRenderedReducer: basicStateReducer, + lastRenderedState: initialResetState + }, + next: null + }; + formFiber.memoizedState = existingStateHook; + formFiber = formFiber.alternate; + formFiber !== null && (formFiber.memoizedState = existingStateHook); + return existingStateHook; +} +function requestFormReset$1(formFiber) { + var stateHook = ensureFormComponentIsStateful(formFiber); + stateHook.next === null && (stateHook = formFiber.alternate.memoizedState); + dispatchSetStateInternal(formFiber, stateHook.next.queue, {}, requestUpdateLane()); +} +function useHostTransitionStatus() { + return readContext(HostTransitionContext); +} +function updateId() { + return updateWorkInProgressHook().memoizedState; +} +function updateRefresh() { + return updateWorkInProgressHook().memoizedState; +} +function refreshCache(fiber) { + for (var provider = fiber.return;provider !== null; ) { + switch (provider.tag) { + case 24: + case 3: + var lane = requestUpdateLane(); + fiber = createUpdate(lane); + var root$69 = enqueueUpdate(provider, fiber, lane); + root$69 !== null && (scheduleUpdateOnFiber(root$69, provider, lane), entangleTransitions(root$69, provider, lane)); + provider = { cache: createCache() }; + fiber.payload = provider; + return; + } + provider = provider.return; + } +} +function dispatchReducerAction(fiber, queue, action) { + var lane = requestUpdateLane(); + action = { + lane, + revertLane: 0, + gesture: null, + action, + hasEagerState: false, + eagerState: null, + next: null + }; + isRenderPhaseUpdate(fiber) ? enqueueRenderPhaseUpdate(queue, action) : (action = enqueueConcurrentHookUpdate(fiber, queue, action, lane), action !== null && (scheduleUpdateOnFiber(action, fiber, lane), entangleTransitionUpdate(action, queue, lane))); +} +function dispatchSetState(fiber, queue, action) { + var lane = requestUpdateLane(); + dispatchSetStateInternal(fiber, queue, action, lane); +} +function dispatchSetStateInternal(fiber, queue, action, lane) { + var update = { + lane, + revertLane: 0, + gesture: null, + action, + hasEagerState: false, + eagerState: null, + next: null + }; + if (isRenderPhaseUpdate(fiber)) + enqueueRenderPhaseUpdate(queue, update); + else { + var alternate = fiber.alternate; + if (fiber.lanes === 0 && (alternate === null || alternate.lanes === 0) && (alternate = queue.lastRenderedReducer, alternate !== null)) + try { + var currentState = queue.lastRenderedState, eagerState = alternate(currentState, action); + update.hasEagerState = true; + update.eagerState = eagerState; + if (objectIs(eagerState, currentState)) + return enqueueUpdate$1(fiber, queue, update, 0), workInProgressRoot === null && finishQueueingConcurrentUpdates(), false; + } catch (error) {} finally {} + action = enqueueConcurrentHookUpdate(fiber, queue, update, lane); + if (action !== null) + return scheduleUpdateOnFiber(action, fiber, lane), entangleTransitionUpdate(action, queue, lane), true; + } + return false; +} +function dispatchOptimisticSetState(fiber, throwIfDuringRender, queue, action) { + action = { + lane: 2, + revertLane: requestTransitionLane(), + gesture: null, + action, + hasEagerState: false, + eagerState: null, + next: null + }; + if (isRenderPhaseUpdate(fiber)) { + if (throwIfDuringRender) + throw Error(formatProdErrorMessage2(479)); + } else + throwIfDuringRender = enqueueConcurrentHookUpdate(fiber, queue, action, 2), throwIfDuringRender !== null && scheduleUpdateOnFiber(throwIfDuringRender, fiber, 2); +} +function isRenderPhaseUpdate(fiber) { + var alternate = fiber.alternate; + return fiber === currentlyRenderingFiber || alternate !== null && alternate === currentlyRenderingFiber; +} +function enqueueRenderPhaseUpdate(queue, update) { + didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate = true; + var pending = queue.pending; + pending === null ? update.next = update : (update.next = pending.next, pending.next = update); + queue.pending = update; +} +function entangleTransitionUpdate(root2, queue, lane) { + if ((lane & 4194048) !== 0) { + var queueLanes = queue.lanes; + queueLanes &= root2.pendingLanes; + lane |= queueLanes; + queue.lanes = lane; + markRootEntangled(root2, lane); + } +} +function applyDerivedStateFromProps(workInProgress, ctor, getDerivedStateFromProps, nextProps) { + ctor = workInProgress.memoizedState; + getDerivedStateFromProps = getDerivedStateFromProps(nextProps, ctor); + getDerivedStateFromProps = getDerivedStateFromProps === null || getDerivedStateFromProps === undefined ? ctor : assign2({}, ctor, getDerivedStateFromProps); + workInProgress.memoizedState = getDerivedStateFromProps; + workInProgress.lanes === 0 && (workInProgress.updateQueue.baseState = getDerivedStateFromProps); +} +function checkShouldComponentUpdate(workInProgress, ctor, oldProps, newProps, oldState, newState, nextContext) { + workInProgress = workInProgress.stateNode; + return typeof workInProgress.shouldComponentUpdate === "function" ? workInProgress.shouldComponentUpdate(newProps, newState, nextContext) : ctor.prototype && ctor.prototype.isPureReactComponent ? !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState) : true; +} +function callComponentWillReceiveProps(workInProgress, instance, newProps, nextContext) { + workInProgress = instance.state; + typeof instance.componentWillReceiveProps === "function" && instance.componentWillReceiveProps(newProps, nextContext); + typeof instance.UNSAFE_componentWillReceiveProps === "function" && instance.UNSAFE_componentWillReceiveProps(newProps, nextContext); + instance.state !== workInProgress && classComponentUpdater.enqueueReplaceState(instance, instance.state, null); +} +function resolveClassComponentProps(Component2, baseProps) { + var newProps = baseProps; + if ("ref" in baseProps) { + newProps = {}; + for (var propName in baseProps) + propName !== "ref" && (newProps[propName] = baseProps[propName]); + } + if (Component2 = Component2.defaultProps) { + newProps === baseProps && (newProps = assign2({}, newProps)); + for (var propName$73 in Component2) + newProps[propName$73] === undefined && (newProps[propName$73] = Component2[propName$73]); + } + return newProps; +} +function defaultOnUncaughtError(error) { + reportGlobalError2(error); +} +function defaultOnCaughtError(error) { + console.error(error); +} +function defaultOnRecoverableError(error) { + reportGlobalError2(error); +} +function logUncaughtError(root2, errorInfo) { + try { + var onUncaughtError = root2.onUncaughtError; + onUncaughtError(errorInfo.value, { componentStack: errorInfo.stack }); + } catch (e$74) { + setTimeout(function() { + throw e$74; + }); + } +} +function logCaughtError(root2, boundary, errorInfo) { + try { + var onCaughtError = root2.onCaughtError; + onCaughtError(errorInfo.value, { + componentStack: errorInfo.stack, + errorBoundary: boundary.tag === 1 ? boundary.stateNode : null + }); + } catch (e$75) { + setTimeout(function() { + throw e$75; + }); + } +} +function createRootErrorUpdate(root2, errorInfo, lane) { + lane = createUpdate(lane); + lane.tag = 3; + lane.payload = { element: null }; + lane.callback = function() { + logUncaughtError(root2, errorInfo); + }; + return lane; +} +function createClassErrorUpdate(lane) { + lane = createUpdate(lane); + lane.tag = 3; + return lane; +} +function initializeClassErrorUpdate(update, root2, fiber, errorInfo) { + var getDerivedStateFromError = fiber.type.getDerivedStateFromError; + if (typeof getDerivedStateFromError === "function") { + var error = errorInfo.value; + update.payload = function() { + return getDerivedStateFromError(error); + }; + update.callback = function() { + logCaughtError(root2, fiber, errorInfo); + }; + } + var inst = fiber.stateNode; + inst !== null && typeof inst.componentDidCatch === "function" && (update.callback = function() { + logCaughtError(root2, fiber, errorInfo); + typeof getDerivedStateFromError !== "function" && (legacyErrorBoundariesThatAlreadyFailed === null ? legacyErrorBoundariesThatAlreadyFailed = new Set([this]) : legacyErrorBoundariesThatAlreadyFailed.add(this)); + var stack = errorInfo.stack; + this.componentDidCatch(errorInfo.value, { + componentStack: stack !== null ? stack : "" + }); + }); +} +function throwException(root2, returnFiber, sourceFiber, value, rootRenderLanes) { + sourceFiber.flags |= 32768; + if (value !== null && typeof value === "object" && typeof value.then === "function") { + returnFiber = sourceFiber.alternate; + returnFiber !== null && propagateParentContextChanges(returnFiber, sourceFiber, rootRenderLanes, true); + sourceFiber = suspenseHandlerStackCursor.current; + if (sourceFiber !== null) { + switch (sourceFiber.tag) { + case 31: + case 13: + return shellBoundary === null ? renderDidSuspendDelayIfPossible() : sourceFiber.alternate === null && workInProgressRootExitStatus === 0 && (workInProgressRootExitStatus = 3), sourceFiber.flags &= -257, sourceFiber.flags |= 65536, sourceFiber.lanes = rootRenderLanes, value === noopSuspenseyCommitThenable ? sourceFiber.flags |= 16384 : (returnFiber = sourceFiber.updateQueue, returnFiber === null ? sourceFiber.updateQueue = new Set([value]) : returnFiber.add(value), attachPingListener(root2, value, rootRenderLanes)), false; + case 22: + return sourceFiber.flags |= 65536, value === noopSuspenseyCommitThenable ? sourceFiber.flags |= 16384 : (returnFiber = sourceFiber.updateQueue, returnFiber === null ? (returnFiber = { + transitions: null, + markerInstances: null, + retryQueue: new Set([value]) + }, sourceFiber.updateQueue = returnFiber) : (sourceFiber = returnFiber.retryQueue, sourceFiber === null ? returnFiber.retryQueue = new Set([value]) : sourceFiber.add(value)), attachPingListener(root2, value, rootRenderLanes)), false; + } + throw Error(formatProdErrorMessage2(435, sourceFiber.tag)); + } + attachPingListener(root2, value, rootRenderLanes); + renderDidSuspendDelayIfPossible(); + return false; + } + if (isHydrating) + return returnFiber = suspenseHandlerStackCursor.current, returnFiber !== null ? ((returnFiber.flags & 65536) === 0 && (returnFiber.flags |= 256), returnFiber.flags |= 65536, returnFiber.lanes = rootRenderLanes, value !== HydrationMismatchException && (root2 = Error(formatProdErrorMessage2(422), { cause: value }), queueHydrationError(createCapturedValueAtFiber(root2, sourceFiber)))) : (value !== HydrationMismatchException && (returnFiber = Error(formatProdErrorMessage2(423), { + cause: value + }), queueHydrationError(createCapturedValueAtFiber(returnFiber, sourceFiber))), root2 = root2.current.alternate, root2.flags |= 65536, rootRenderLanes &= -rootRenderLanes, root2.lanes |= rootRenderLanes, value = createCapturedValueAtFiber(value, sourceFiber), rootRenderLanes = createRootErrorUpdate(root2.stateNode, value, rootRenderLanes), enqueueCapturedUpdate(root2, rootRenderLanes), workInProgressRootExitStatus !== 4 && (workInProgressRootExitStatus = 2)), false; + var wrapperError = Error(formatProdErrorMessage2(520), { cause: value }); + wrapperError = createCapturedValueAtFiber(wrapperError, sourceFiber); + workInProgressRootConcurrentErrors === null ? workInProgressRootConcurrentErrors = [wrapperError] : workInProgressRootConcurrentErrors.push(wrapperError); + workInProgressRootExitStatus !== 4 && (workInProgressRootExitStatus = 2); + if (returnFiber === null) + return true; + value = createCapturedValueAtFiber(value, sourceFiber); + sourceFiber = returnFiber; + do { + switch (sourceFiber.tag) { + case 3: + return sourceFiber.flags |= 65536, root2 = rootRenderLanes & -rootRenderLanes, sourceFiber.lanes |= root2, root2 = createRootErrorUpdate(sourceFiber.stateNode, value, root2), enqueueCapturedUpdate(sourceFiber, root2), false; + case 1: + if (returnFiber = sourceFiber.type, wrapperError = sourceFiber.stateNode, (sourceFiber.flags & 128) === 0 && (typeof returnFiber.getDerivedStateFromError === "function" || wrapperError !== null && typeof wrapperError.componentDidCatch === "function" && (legacyErrorBoundariesThatAlreadyFailed === null || !legacyErrorBoundariesThatAlreadyFailed.has(wrapperError)))) + return sourceFiber.flags |= 65536, rootRenderLanes &= -rootRenderLanes, sourceFiber.lanes |= rootRenderLanes, rootRenderLanes = createClassErrorUpdate(rootRenderLanes), initializeClassErrorUpdate(rootRenderLanes, root2, sourceFiber, value), enqueueCapturedUpdate(sourceFiber, rootRenderLanes), false; + } + sourceFiber = sourceFiber.return; + } while (sourceFiber !== null); + return false; +} +function reconcileChildren(current, workInProgress, nextChildren, renderLanes2) { + workInProgress.child = current === null ? mountChildFibers(workInProgress, null, nextChildren, renderLanes2) : reconcileChildFibers(workInProgress, current.child, nextChildren, renderLanes2); +} +function updateForwardRef(current, workInProgress, Component2, nextProps, renderLanes2) { + Component2 = Component2.render; + var ref = workInProgress.ref; + if ("ref" in nextProps) { + var propsWithoutRef = {}; + for (var key in nextProps) + key !== "ref" && (propsWithoutRef[key] = nextProps[key]); + } else + propsWithoutRef = nextProps; + prepareToReadContext(workInProgress); + nextProps = renderWithHooks(current, workInProgress, Component2, propsWithoutRef, ref, renderLanes2); + key = checkDidRenderIdHook(); + if (current !== null && !didReceiveUpdate) + return bailoutHooks(current, workInProgress, renderLanes2), bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes2); + isHydrating && key && pushMaterializedTreeId(workInProgress); + workInProgress.flags |= 1; + reconcileChildren(current, workInProgress, nextProps, renderLanes2); + return workInProgress.child; +} +function updateMemoComponent(current, workInProgress, Component2, nextProps, renderLanes2) { + if (current === null) { + var type = Component2.type; + if (typeof type === "function" && !shouldConstruct(type) && type.defaultProps === undefined && Component2.compare === null) + return workInProgress.tag = 15, workInProgress.type = type, updateSimpleMemoComponent(current, workInProgress, type, nextProps, renderLanes2); + current = createFiberFromTypeAndProps(Component2.type, null, nextProps, workInProgress, workInProgress.mode, renderLanes2); + current.ref = workInProgress.ref; + current.return = workInProgress; + return workInProgress.child = current; + } + type = current.child; + if (!checkScheduledUpdateOrContext(current, renderLanes2)) { + var prevProps = type.memoizedProps; + Component2 = Component2.compare; + Component2 = Component2 !== null ? Component2 : shallowEqual; + if (Component2(prevProps, nextProps) && current.ref === workInProgress.ref) + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes2); + } + workInProgress.flags |= 1; + current = createWorkInProgress(type, nextProps); + current.ref = workInProgress.ref; + current.return = workInProgress; + return workInProgress.child = current; +} +function updateSimpleMemoComponent(current, workInProgress, Component2, nextProps, renderLanes2) { + if (current !== null) { + var prevProps = current.memoizedProps; + if (shallowEqual(prevProps, nextProps) && current.ref === workInProgress.ref) + if (didReceiveUpdate = false, workInProgress.pendingProps = nextProps = prevProps, checkScheduledUpdateOrContext(current, renderLanes2)) + (current.flags & 131072) !== 0 && (didReceiveUpdate = true); + else + return workInProgress.lanes = current.lanes, bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes2); + } + return updateFunctionComponent(current, workInProgress, Component2, nextProps, renderLanes2); +} +function updateOffscreenComponent(current, workInProgress, renderLanes2, nextProps) { + var nextChildren = nextProps.children, prevState = current !== null ? current.memoizedState : null; + current === null && workInProgress.stateNode === null && (workInProgress.stateNode = { + _visibility: 1, + _pendingMarkers: null, + _retryCache: null, + _transitions: null + }); + if (nextProps.mode === "hidden") { + if ((workInProgress.flags & 128) !== 0) { + prevState = prevState !== null ? prevState.baseLanes | renderLanes2 : renderLanes2; + if (current !== null) { + nextProps = workInProgress.child = current.child; + for (nextChildren = 0;nextProps !== null; ) + nextChildren = nextChildren | nextProps.lanes | nextProps.childLanes, nextProps = nextProps.sibling; + nextProps = nextChildren & ~prevState; + } else + nextProps = 0, workInProgress.child = null; + return deferHiddenOffscreenComponent(current, workInProgress, prevState, renderLanes2, nextProps); + } + if ((renderLanes2 & 536870912) !== 0) + workInProgress.memoizedState = { baseLanes: 0, cachePool: null }, current !== null && pushTransition(workInProgress, prevState !== null ? prevState.cachePool : null), prevState !== null ? pushHiddenContext(workInProgress, prevState) : reuseHiddenContextOnStack(), pushOffscreenSuspenseHandler(workInProgress); + else + return nextProps = workInProgress.lanes = 536870912, deferHiddenOffscreenComponent(current, workInProgress, prevState !== null ? prevState.baseLanes | renderLanes2 : renderLanes2, renderLanes2, nextProps); + } else + prevState !== null ? (pushTransition(workInProgress, prevState.cachePool), pushHiddenContext(workInProgress, prevState), reuseSuspenseHandlerOnStack(workInProgress), workInProgress.memoizedState = null) : (current !== null && pushTransition(workInProgress, null), reuseHiddenContextOnStack(), reuseSuspenseHandlerOnStack(workInProgress)); + reconcileChildren(current, workInProgress, nextChildren, renderLanes2); + return workInProgress.child; +} +function bailoutOffscreenComponent(current, workInProgress) { + current !== null && current.tag === 22 || workInProgress.stateNode !== null || (workInProgress.stateNode = { + _visibility: 1, + _pendingMarkers: null, + _retryCache: null, + _transitions: null + }); + return workInProgress.sibling; +} +function deferHiddenOffscreenComponent(current, workInProgress, nextBaseLanes, renderLanes2, remainingChildLanes) { + var JSCompiler_inline_result = peekCacheFromPool(); + JSCompiler_inline_result = JSCompiler_inline_result === null ? null : { parent: CacheContext._currentValue, pool: JSCompiler_inline_result }; + workInProgress.memoizedState = { + baseLanes: nextBaseLanes, + cachePool: JSCompiler_inline_result + }; + current !== null && pushTransition(workInProgress, null); + reuseHiddenContextOnStack(); + pushOffscreenSuspenseHandler(workInProgress); + current !== null && propagateParentContextChanges(current, workInProgress, renderLanes2, true); + workInProgress.childLanes = remainingChildLanes; + return null; +} +function mountActivityChildren(workInProgress, nextProps) { + nextProps = mountWorkInProgressOffscreenFiber({ mode: nextProps.mode, children: nextProps.children }, workInProgress.mode); + nextProps.ref = workInProgress.ref; + workInProgress.child = nextProps; + nextProps.return = workInProgress; + return nextProps; +} +function retryActivityComponentWithoutHydrating(current, workInProgress, renderLanes2) { + reconcileChildFibers(workInProgress, current.child, null, renderLanes2); + current = mountActivityChildren(workInProgress, workInProgress.pendingProps); + current.flags |= 2; + popSuspenseHandler(workInProgress); + workInProgress.memoizedState = null; + return current; +} +function updateActivityComponent(current, workInProgress, renderLanes2) { + var nextProps = workInProgress.pendingProps, didSuspend = (workInProgress.flags & 128) !== 0; + workInProgress.flags &= -129; + if (current === null) { + if (isHydrating) { + if (nextProps.mode === "hidden") + return current = mountActivityChildren(workInProgress, nextProps), workInProgress.lanes = 536870912, bailoutOffscreenComponent(null, current); + pushDehydratedActivitySuspenseHandler(workInProgress); + (current = nextHydratableInstance) ? (current = canHydrateHydrationBoundary(current, rootOrSingletonContext), current = current !== null && current.data === "&" ? current : null, current !== null && (workInProgress.memoizedState = { + dehydrated: current, + treeContext: treeContextProvider !== null ? { id: treeContextId, overflow: treeContextOverflow } : null, + retryLane: 536870912, + hydrationErrors: null + }, renderLanes2 = createFiberFromDehydratedFragment(current), renderLanes2.return = workInProgress, workInProgress.child = renderLanes2, hydrationParentFiber = workInProgress, nextHydratableInstance = null)) : current = null; + if (current === null) + throw throwOnHydrationMismatch(workInProgress); + workInProgress.lanes = 536870912; + return null; + } + return mountActivityChildren(workInProgress, nextProps); + } + var prevState = current.memoizedState; + if (prevState !== null) { + var dehydrated = prevState.dehydrated; + pushDehydratedActivitySuspenseHandler(workInProgress); + if (didSuspend) + if (workInProgress.flags & 256) + workInProgress.flags &= -257, workInProgress = retryActivityComponentWithoutHydrating(current, workInProgress, renderLanes2); + else if (workInProgress.memoizedState !== null) + workInProgress.child = current.child, workInProgress.flags |= 128, workInProgress = null; + else + throw Error(formatProdErrorMessage2(558)); + else if (didReceiveUpdate || propagateParentContextChanges(current, workInProgress, renderLanes2, false), didSuspend = (renderLanes2 & current.childLanes) !== 0, didReceiveUpdate || didSuspend) { + nextProps = workInProgressRoot; + if (nextProps !== null && (dehydrated = getBumpedLaneForHydration(nextProps, renderLanes2), dehydrated !== 0 && dehydrated !== prevState.retryLane)) + throw prevState.retryLane = dehydrated, enqueueConcurrentRenderForLane(current, dehydrated), scheduleUpdateOnFiber(nextProps, current, dehydrated), SelectiveHydrationException; + renderDidSuspendDelayIfPossible(); + workInProgress = retryActivityComponentWithoutHydrating(current, workInProgress, renderLanes2); + } else + current = prevState.treeContext, nextHydratableInstance = getNextHydratable(dehydrated.nextSibling), hydrationParentFiber = workInProgress, isHydrating = true, hydrationErrors = null, rootOrSingletonContext = false, current !== null && restoreSuspendedTreeContext(workInProgress, current), workInProgress = mountActivityChildren(workInProgress, nextProps), workInProgress.flags |= 4096; + return workInProgress; + } + current = createWorkInProgress(current.child, { + mode: nextProps.mode, + children: nextProps.children + }); + current.ref = workInProgress.ref; + workInProgress.child = current; + current.return = workInProgress; + return current; +} +function markRef(current, workInProgress) { + var ref = workInProgress.ref; + if (ref === null) + current !== null && current.ref !== null && (workInProgress.flags |= 4194816); + else { + if (typeof ref !== "function" && typeof ref !== "object") + throw Error(formatProdErrorMessage2(284)); + if (current === null || current.ref !== ref) + workInProgress.flags |= 4194816; + } +} +function updateFunctionComponent(current, workInProgress, Component2, nextProps, renderLanes2) { + prepareToReadContext(workInProgress); + Component2 = renderWithHooks(current, workInProgress, Component2, nextProps, undefined, renderLanes2); + nextProps = checkDidRenderIdHook(); + if (current !== null && !didReceiveUpdate) + return bailoutHooks(current, workInProgress, renderLanes2), bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes2); + isHydrating && nextProps && pushMaterializedTreeId(workInProgress); + workInProgress.flags |= 1; + reconcileChildren(current, workInProgress, Component2, renderLanes2); + return workInProgress.child; +} +function replayFunctionComponent(current, workInProgress, nextProps, Component2, secondArg, renderLanes2) { + prepareToReadContext(workInProgress); + workInProgress.updateQueue = null; + nextProps = renderWithHooksAgain(workInProgress, Component2, nextProps, secondArg); + finishRenderingHooks(current); + Component2 = checkDidRenderIdHook(); + if (current !== null && !didReceiveUpdate) + return bailoutHooks(current, workInProgress, renderLanes2), bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes2); + isHydrating && Component2 && pushMaterializedTreeId(workInProgress); + workInProgress.flags |= 1; + reconcileChildren(current, workInProgress, nextProps, renderLanes2); + return workInProgress.child; +} +function updateClassComponent(current, workInProgress, Component2, nextProps, renderLanes2) { + prepareToReadContext(workInProgress); + if (workInProgress.stateNode === null) { + var context = emptyContextObject, contextType = Component2.contextType; + typeof contextType === "object" && contextType !== null && (context = readContext(contextType)); + context = new Component2(nextProps, context); + workInProgress.memoizedState = context.state !== null && context.state !== undefined ? context.state : null; + context.updater = classComponentUpdater; + workInProgress.stateNode = context; + context._reactInternals = workInProgress; + context = workInProgress.stateNode; + context.props = nextProps; + context.state = workInProgress.memoizedState; + context.refs = {}; + initializeUpdateQueue(workInProgress); + contextType = Component2.contextType; + context.context = typeof contextType === "object" && contextType !== null ? readContext(contextType) : emptyContextObject; + context.state = workInProgress.memoizedState; + contextType = Component2.getDerivedStateFromProps; + typeof contextType === "function" && (applyDerivedStateFromProps(workInProgress, Component2, contextType, nextProps), context.state = workInProgress.memoizedState); + typeof Component2.getDerivedStateFromProps === "function" || typeof context.getSnapshotBeforeUpdate === "function" || typeof context.UNSAFE_componentWillMount !== "function" && typeof context.componentWillMount !== "function" || (contextType = context.state, typeof context.componentWillMount === "function" && context.componentWillMount(), typeof context.UNSAFE_componentWillMount === "function" && context.UNSAFE_componentWillMount(), contextType !== context.state && classComponentUpdater.enqueueReplaceState(context, context.state, null), processUpdateQueue(workInProgress, nextProps, context, renderLanes2), suspendIfUpdateReadFromEntangledAsyncAction(), context.state = workInProgress.memoizedState); + typeof context.componentDidMount === "function" && (workInProgress.flags |= 4194308); + nextProps = true; + } else if (current === null) { + context = workInProgress.stateNode; + var unresolvedOldProps = workInProgress.memoizedProps, oldProps = resolveClassComponentProps(Component2, unresolvedOldProps); + context.props = oldProps; + var oldContext = context.context, contextType$jscomp$0 = Component2.contextType; + contextType = emptyContextObject; + typeof contextType$jscomp$0 === "object" && contextType$jscomp$0 !== null && (contextType = readContext(contextType$jscomp$0)); + var getDerivedStateFromProps = Component2.getDerivedStateFromProps; + contextType$jscomp$0 = typeof getDerivedStateFromProps === "function" || typeof context.getSnapshotBeforeUpdate === "function"; + unresolvedOldProps = workInProgress.pendingProps !== unresolvedOldProps; + contextType$jscomp$0 || typeof context.UNSAFE_componentWillReceiveProps !== "function" && typeof context.componentWillReceiveProps !== "function" || (unresolvedOldProps || oldContext !== contextType) && callComponentWillReceiveProps(workInProgress, context, nextProps, contextType); + hasForceUpdate = false; + var oldState = workInProgress.memoizedState; + context.state = oldState; + processUpdateQueue(workInProgress, nextProps, context, renderLanes2); + suspendIfUpdateReadFromEntangledAsyncAction(); + oldContext = workInProgress.memoizedState; + unresolvedOldProps || oldState !== oldContext || hasForceUpdate ? (typeof getDerivedStateFromProps === "function" && (applyDerivedStateFromProps(workInProgress, Component2, getDerivedStateFromProps, nextProps), oldContext = workInProgress.memoizedState), (oldProps = hasForceUpdate || checkShouldComponentUpdate(workInProgress, Component2, oldProps, nextProps, oldState, oldContext, contextType)) ? (contextType$jscomp$0 || typeof context.UNSAFE_componentWillMount !== "function" && typeof context.componentWillMount !== "function" || (typeof context.componentWillMount === "function" && context.componentWillMount(), typeof context.UNSAFE_componentWillMount === "function" && context.UNSAFE_componentWillMount()), typeof context.componentDidMount === "function" && (workInProgress.flags |= 4194308)) : (typeof context.componentDidMount === "function" && (workInProgress.flags |= 4194308), workInProgress.memoizedProps = nextProps, workInProgress.memoizedState = oldContext), context.props = nextProps, context.state = oldContext, context.context = contextType, nextProps = oldProps) : (typeof context.componentDidMount === "function" && (workInProgress.flags |= 4194308), nextProps = false); + } else { + context = workInProgress.stateNode; + cloneUpdateQueue(current, workInProgress); + contextType = workInProgress.memoizedProps; + contextType$jscomp$0 = resolveClassComponentProps(Component2, contextType); + context.props = contextType$jscomp$0; + getDerivedStateFromProps = workInProgress.pendingProps; + oldState = context.context; + oldContext = Component2.contextType; + oldProps = emptyContextObject; + typeof oldContext === "object" && oldContext !== null && (oldProps = readContext(oldContext)); + unresolvedOldProps = Component2.getDerivedStateFromProps; + (oldContext = typeof unresolvedOldProps === "function" || typeof context.getSnapshotBeforeUpdate === "function") || typeof context.UNSAFE_componentWillReceiveProps !== "function" && typeof context.componentWillReceiveProps !== "function" || (contextType !== getDerivedStateFromProps || oldState !== oldProps) && callComponentWillReceiveProps(workInProgress, context, nextProps, oldProps); + hasForceUpdate = false; + oldState = workInProgress.memoizedState; + context.state = oldState; + processUpdateQueue(workInProgress, nextProps, context, renderLanes2); + suspendIfUpdateReadFromEntangledAsyncAction(); + var newState = workInProgress.memoizedState; + contextType !== getDerivedStateFromProps || oldState !== newState || hasForceUpdate || current !== null && current.dependencies !== null && checkIfContextChanged(current.dependencies) ? (typeof unresolvedOldProps === "function" && (applyDerivedStateFromProps(workInProgress, Component2, unresolvedOldProps, nextProps), newState = workInProgress.memoizedState), (contextType$jscomp$0 = hasForceUpdate || checkShouldComponentUpdate(workInProgress, Component2, contextType$jscomp$0, nextProps, oldState, newState, oldProps) || current !== null && current.dependencies !== null && checkIfContextChanged(current.dependencies)) ? (oldContext || typeof context.UNSAFE_componentWillUpdate !== "function" && typeof context.componentWillUpdate !== "function" || (typeof context.componentWillUpdate === "function" && context.componentWillUpdate(nextProps, newState, oldProps), typeof context.UNSAFE_componentWillUpdate === "function" && context.UNSAFE_componentWillUpdate(nextProps, newState, oldProps)), typeof context.componentDidUpdate === "function" && (workInProgress.flags |= 4), typeof context.getSnapshotBeforeUpdate === "function" && (workInProgress.flags |= 1024)) : (typeof context.componentDidUpdate !== "function" || contextType === current.memoizedProps && oldState === current.memoizedState || (workInProgress.flags |= 4), typeof context.getSnapshotBeforeUpdate !== "function" || contextType === current.memoizedProps && oldState === current.memoizedState || (workInProgress.flags |= 1024), workInProgress.memoizedProps = nextProps, workInProgress.memoizedState = newState), context.props = nextProps, context.state = newState, context.context = oldProps, nextProps = contextType$jscomp$0) : (typeof context.componentDidUpdate !== "function" || contextType === current.memoizedProps && oldState === current.memoizedState || (workInProgress.flags |= 4), typeof context.getSnapshotBeforeUpdate !== "function" || contextType === current.memoizedProps && oldState === current.memoizedState || (workInProgress.flags |= 1024), nextProps = false); + } + context = nextProps; + markRef(current, workInProgress); + nextProps = (workInProgress.flags & 128) !== 0; + context || nextProps ? (context = workInProgress.stateNode, Component2 = nextProps && typeof Component2.getDerivedStateFromError !== "function" ? null : context.render(), workInProgress.flags |= 1, current !== null && nextProps ? (workInProgress.child = reconcileChildFibers(workInProgress, current.child, null, renderLanes2), workInProgress.child = reconcileChildFibers(workInProgress, null, Component2, renderLanes2)) : reconcileChildren(current, workInProgress, Component2, renderLanes2), workInProgress.memoizedState = context.state, current = workInProgress.child) : current = bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes2); + return current; +} +function mountHostRootWithoutHydrating(current, workInProgress, nextChildren, renderLanes2) { + resetHydrationState(); + workInProgress.flags |= 256; + reconcileChildren(current, workInProgress, nextChildren, renderLanes2); + return workInProgress.child; +} +function mountSuspenseOffscreenState(renderLanes2) { + return { baseLanes: renderLanes2, cachePool: getSuspendedCache() }; +} +function getRemainingWorkInPrimaryTree(current, primaryTreeDidDefer, renderLanes2) { + current = current !== null ? current.childLanes & ~renderLanes2 : 0; + primaryTreeDidDefer && (current |= workInProgressDeferredLane); + return current; +} +function updateSuspenseComponent(current, workInProgress, renderLanes2) { + var nextProps = workInProgress.pendingProps, showFallback = false, didSuspend = (workInProgress.flags & 128) !== 0, JSCompiler_temp; + (JSCompiler_temp = didSuspend) || (JSCompiler_temp = current !== null && current.memoizedState === null ? false : (suspenseStackCursor.current & 2) !== 0); + JSCompiler_temp && (showFallback = true, workInProgress.flags &= -129); + JSCompiler_temp = (workInProgress.flags & 32) !== 0; + workInProgress.flags &= -33; + if (current === null) { + if (isHydrating) { + showFallback ? pushPrimaryTreeSuspenseHandler(workInProgress) : reuseSuspenseHandlerOnStack(workInProgress); + (current = nextHydratableInstance) ? (current = canHydrateHydrationBoundary(current, rootOrSingletonContext), current = current !== null && current.data !== "&" ? current : null, current !== null && (workInProgress.memoizedState = { + dehydrated: current, + treeContext: treeContextProvider !== null ? { id: treeContextId, overflow: treeContextOverflow } : null, + retryLane: 536870912, + hydrationErrors: null + }, renderLanes2 = createFiberFromDehydratedFragment(current), renderLanes2.return = workInProgress, workInProgress.child = renderLanes2, hydrationParentFiber = workInProgress, nextHydratableInstance = null)) : current = null; + if (current === null) + throw throwOnHydrationMismatch(workInProgress); + isSuspenseInstanceFallback(current) ? workInProgress.lanes = 32 : workInProgress.lanes = 536870912; + return null; + } + var nextPrimaryChildren = nextProps.children; + nextProps = nextProps.fallback; + if (showFallback) + return reuseSuspenseHandlerOnStack(workInProgress), showFallback = workInProgress.mode, nextPrimaryChildren = mountWorkInProgressOffscreenFiber({ mode: "hidden", children: nextPrimaryChildren }, showFallback), nextProps = createFiberFromFragment(nextProps, showFallback, renderLanes2, null), nextPrimaryChildren.return = workInProgress, nextProps.return = workInProgress, nextPrimaryChildren.sibling = nextProps, workInProgress.child = nextPrimaryChildren, nextProps = workInProgress.child, nextProps.memoizedState = mountSuspenseOffscreenState(renderLanes2), nextProps.childLanes = getRemainingWorkInPrimaryTree(current, JSCompiler_temp, renderLanes2), workInProgress.memoizedState = SUSPENDED_MARKER, bailoutOffscreenComponent(null, nextProps); + pushPrimaryTreeSuspenseHandler(workInProgress); + return mountSuspensePrimaryChildren(workInProgress, nextPrimaryChildren); + } + var prevState = current.memoizedState; + if (prevState !== null && (nextPrimaryChildren = prevState.dehydrated, nextPrimaryChildren !== null)) { + if (didSuspend) + workInProgress.flags & 256 ? (pushPrimaryTreeSuspenseHandler(workInProgress), workInProgress.flags &= -257, workInProgress = retrySuspenseComponentWithoutHydrating(current, workInProgress, renderLanes2)) : workInProgress.memoizedState !== null ? (reuseSuspenseHandlerOnStack(workInProgress), workInProgress.child = current.child, workInProgress.flags |= 128, workInProgress = null) : (reuseSuspenseHandlerOnStack(workInProgress), nextPrimaryChildren = nextProps.fallback, showFallback = workInProgress.mode, nextProps = mountWorkInProgressOffscreenFiber({ mode: "visible", children: nextProps.children }, showFallback), nextPrimaryChildren = createFiberFromFragment(nextPrimaryChildren, showFallback, renderLanes2, null), nextPrimaryChildren.flags |= 2, nextProps.return = workInProgress, nextPrimaryChildren.return = workInProgress, nextProps.sibling = nextPrimaryChildren, workInProgress.child = nextProps, reconcileChildFibers(workInProgress, current.child, null, renderLanes2), nextProps = workInProgress.child, nextProps.memoizedState = mountSuspenseOffscreenState(renderLanes2), nextProps.childLanes = getRemainingWorkInPrimaryTree(current, JSCompiler_temp, renderLanes2), workInProgress.memoizedState = SUSPENDED_MARKER, workInProgress = bailoutOffscreenComponent(null, nextProps)); + else if (pushPrimaryTreeSuspenseHandler(workInProgress), isSuspenseInstanceFallback(nextPrimaryChildren)) { + JSCompiler_temp = nextPrimaryChildren.nextSibling && nextPrimaryChildren.nextSibling.dataset; + if (JSCompiler_temp) + var digest = JSCompiler_temp.dgst; + JSCompiler_temp = digest; + nextProps = Error(formatProdErrorMessage2(419)); + nextProps.stack = ""; + nextProps.digest = JSCompiler_temp; + queueHydrationError({ value: nextProps, source: null, stack: null }); + workInProgress = retrySuspenseComponentWithoutHydrating(current, workInProgress, renderLanes2); + } else if (didReceiveUpdate || propagateParentContextChanges(current, workInProgress, renderLanes2, false), JSCompiler_temp = (renderLanes2 & current.childLanes) !== 0, didReceiveUpdate || JSCompiler_temp) { + JSCompiler_temp = workInProgressRoot; + if (JSCompiler_temp !== null && (nextProps = getBumpedLaneForHydration(JSCompiler_temp, renderLanes2), nextProps !== 0 && nextProps !== prevState.retryLane)) + throw prevState.retryLane = nextProps, enqueueConcurrentRenderForLane(current, nextProps), scheduleUpdateOnFiber(JSCompiler_temp, current, nextProps), SelectiveHydrationException; + isSuspenseInstancePending(nextPrimaryChildren) || renderDidSuspendDelayIfPossible(); + workInProgress = retrySuspenseComponentWithoutHydrating(current, workInProgress, renderLanes2); + } else + isSuspenseInstancePending(nextPrimaryChildren) ? (workInProgress.flags |= 192, workInProgress.child = current.child, workInProgress = null) : (current = prevState.treeContext, nextHydratableInstance = getNextHydratable(nextPrimaryChildren.nextSibling), hydrationParentFiber = workInProgress, isHydrating = true, hydrationErrors = null, rootOrSingletonContext = false, current !== null && restoreSuspendedTreeContext(workInProgress, current), workInProgress = mountSuspensePrimaryChildren(workInProgress, nextProps.children), workInProgress.flags |= 4096); + return workInProgress; + } + if (showFallback) + return reuseSuspenseHandlerOnStack(workInProgress), nextPrimaryChildren = nextProps.fallback, showFallback = workInProgress.mode, prevState = current.child, digest = prevState.sibling, nextProps = createWorkInProgress(prevState, { + mode: "hidden", + children: nextProps.children + }), nextProps.subtreeFlags = prevState.subtreeFlags & 65011712, digest !== null ? nextPrimaryChildren = createWorkInProgress(digest, nextPrimaryChildren) : (nextPrimaryChildren = createFiberFromFragment(nextPrimaryChildren, showFallback, renderLanes2, null), nextPrimaryChildren.flags |= 2), nextPrimaryChildren.return = workInProgress, nextProps.return = workInProgress, nextProps.sibling = nextPrimaryChildren, workInProgress.child = nextProps, bailoutOffscreenComponent(null, nextProps), nextProps = workInProgress.child, nextPrimaryChildren = current.child.memoizedState, nextPrimaryChildren === null ? nextPrimaryChildren = mountSuspenseOffscreenState(renderLanes2) : (showFallback = nextPrimaryChildren.cachePool, showFallback !== null ? (prevState = CacheContext._currentValue, showFallback = showFallback.parent !== prevState ? { parent: prevState, pool: prevState } : showFallback) : showFallback = getSuspendedCache(), nextPrimaryChildren = { + baseLanes: nextPrimaryChildren.baseLanes | renderLanes2, + cachePool: showFallback + }), nextProps.memoizedState = nextPrimaryChildren, nextProps.childLanes = getRemainingWorkInPrimaryTree(current, JSCompiler_temp, renderLanes2), workInProgress.memoizedState = SUSPENDED_MARKER, bailoutOffscreenComponent(current.child, nextProps); + pushPrimaryTreeSuspenseHandler(workInProgress); + renderLanes2 = current.child; + current = renderLanes2.sibling; + renderLanes2 = createWorkInProgress(renderLanes2, { + mode: "visible", + children: nextProps.children + }); + renderLanes2.return = workInProgress; + renderLanes2.sibling = null; + current !== null && (JSCompiler_temp = workInProgress.deletions, JSCompiler_temp === null ? (workInProgress.deletions = [current], workInProgress.flags |= 16) : JSCompiler_temp.push(current)); + workInProgress.child = renderLanes2; + workInProgress.memoizedState = null; + return renderLanes2; +} +function mountSuspensePrimaryChildren(workInProgress, primaryChildren) { + primaryChildren = mountWorkInProgressOffscreenFiber({ mode: "visible", children: primaryChildren }, workInProgress.mode); + primaryChildren.return = workInProgress; + return workInProgress.child = primaryChildren; +} +function mountWorkInProgressOffscreenFiber(offscreenProps, mode) { + offscreenProps = createFiberImplClass(22, offscreenProps, null, mode); + offscreenProps.lanes = 0; + return offscreenProps; +} +function retrySuspenseComponentWithoutHydrating(current, workInProgress, renderLanes2) { + reconcileChildFibers(workInProgress, current.child, null, renderLanes2); + current = mountSuspensePrimaryChildren(workInProgress, workInProgress.pendingProps.children); + current.flags |= 2; + workInProgress.memoizedState = null; + return current; +} +function scheduleSuspenseWorkOnFiber(fiber, renderLanes2, propagationRoot) { + fiber.lanes |= renderLanes2; + var alternate = fiber.alternate; + alternate !== null && (alternate.lanes |= renderLanes2); + scheduleContextWorkOnParentPath(fiber.return, renderLanes2, propagationRoot); +} +function initSuspenseListRenderState(workInProgress, isBackwards, tail, lastContentRow, tailMode, treeForkCount2) { + var renderState = workInProgress.memoizedState; + renderState === null ? workInProgress.memoizedState = { + isBackwards, + rendering: null, + renderingStartTime: 0, + last: lastContentRow, + tail, + tailMode, + treeForkCount: treeForkCount2 + } : (renderState.isBackwards = isBackwards, renderState.rendering = null, renderState.renderingStartTime = 0, renderState.last = lastContentRow, renderState.tail = tail, renderState.tailMode = tailMode, renderState.treeForkCount = treeForkCount2); +} +function updateSuspenseListComponent(current, workInProgress, renderLanes2) { + var nextProps = workInProgress.pendingProps, revealOrder = nextProps.revealOrder, tailMode = nextProps.tail; + nextProps = nextProps.children; + var suspenseContext = suspenseStackCursor.current, shouldForceFallback = (suspenseContext & 2) !== 0; + shouldForceFallback ? (suspenseContext = suspenseContext & 1 | 2, workInProgress.flags |= 128) : suspenseContext &= 1; + push2(suspenseStackCursor, suspenseContext); + reconcileChildren(current, workInProgress, nextProps, renderLanes2); + nextProps = isHydrating ? treeForkCount : 0; + if (!shouldForceFallback && current !== null && (current.flags & 128) !== 0) + a: + for (current = workInProgress.child;current !== null; ) { + if (current.tag === 13) + current.memoizedState !== null && scheduleSuspenseWorkOnFiber(current, renderLanes2, workInProgress); + else if (current.tag === 19) + scheduleSuspenseWorkOnFiber(current, renderLanes2, workInProgress); + else if (current.child !== null) { + current.child.return = current; + current = current.child; + continue; + } + if (current === workInProgress) + break a; + for (;current.sibling === null; ) { + if (current.return === null || current.return === workInProgress) + break a; + current = current.return; + } + current.sibling.return = current.return; + current = current.sibling; + } + switch (revealOrder) { + case "forwards": + renderLanes2 = workInProgress.child; + for (revealOrder = null;renderLanes2 !== null; ) + current = renderLanes2.alternate, current !== null && findFirstSuspended(current) === null && (revealOrder = renderLanes2), renderLanes2 = renderLanes2.sibling; + renderLanes2 = revealOrder; + renderLanes2 === null ? (revealOrder = workInProgress.child, workInProgress.child = null) : (revealOrder = renderLanes2.sibling, renderLanes2.sibling = null); + initSuspenseListRenderState(workInProgress, false, revealOrder, renderLanes2, tailMode, nextProps); + break; + case "backwards": + case "unstable_legacy-backwards": + renderLanes2 = null; + revealOrder = workInProgress.child; + for (workInProgress.child = null;revealOrder !== null; ) { + current = revealOrder.alternate; + if (current !== null && findFirstSuspended(current) === null) { + workInProgress.child = revealOrder; + break; + } + current = revealOrder.sibling; + revealOrder.sibling = renderLanes2; + renderLanes2 = revealOrder; + revealOrder = current; + } + initSuspenseListRenderState(workInProgress, true, renderLanes2, null, tailMode, nextProps); + break; + case "together": + initSuspenseListRenderState(workInProgress, false, null, null, undefined, nextProps); + break; + default: + workInProgress.memoizedState = null; + } + return workInProgress.child; +} +function bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes2) { + current !== null && (workInProgress.dependencies = current.dependencies); + workInProgressRootSkippedLanes |= workInProgress.lanes; + if ((renderLanes2 & workInProgress.childLanes) === 0) + if (current !== null) { + if (propagateParentContextChanges(current, workInProgress, renderLanes2, false), (renderLanes2 & workInProgress.childLanes) === 0) + return null; + } else + return null; + if (current !== null && workInProgress.child !== current.child) + throw Error(formatProdErrorMessage2(153)); + if (workInProgress.child !== null) { + current = workInProgress.child; + renderLanes2 = createWorkInProgress(current, current.pendingProps); + workInProgress.child = renderLanes2; + for (renderLanes2.return = workInProgress;current.sibling !== null; ) + current = current.sibling, renderLanes2 = renderLanes2.sibling = createWorkInProgress(current, current.pendingProps), renderLanes2.return = workInProgress; + renderLanes2.sibling = null; + } + return workInProgress.child; +} +function checkScheduledUpdateOrContext(current, renderLanes2) { + if ((current.lanes & renderLanes2) !== 0) + return true; + current = current.dependencies; + return current !== null && checkIfContextChanged(current) ? true : false; +} +function attemptEarlyBailoutIfNoScheduledUpdate(current, workInProgress, renderLanes2) { + switch (workInProgress.tag) { + case 3: + pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); + pushProvider(workInProgress, CacheContext, current.memoizedState.cache); + resetHydrationState(); + break; + case 27: + case 5: + pushHostContext(workInProgress); + break; + case 4: + pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); + break; + case 10: + pushProvider(workInProgress, workInProgress.type, workInProgress.memoizedProps.value); + break; + case 31: + if (workInProgress.memoizedState !== null) + return workInProgress.flags |= 128, pushDehydratedActivitySuspenseHandler(workInProgress), null; + break; + case 13: + var state$102 = workInProgress.memoizedState; + if (state$102 !== null) { + if (state$102.dehydrated !== null) + return pushPrimaryTreeSuspenseHandler(workInProgress), workInProgress.flags |= 128, null; + if ((renderLanes2 & workInProgress.child.childLanes) !== 0) + return updateSuspenseComponent(current, workInProgress, renderLanes2); + pushPrimaryTreeSuspenseHandler(workInProgress); + current = bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes2); + return current !== null ? current.sibling : null; + } + pushPrimaryTreeSuspenseHandler(workInProgress); + break; + case 19: + var didSuspendBefore = (current.flags & 128) !== 0; + state$102 = (renderLanes2 & workInProgress.childLanes) !== 0; + state$102 || (propagateParentContextChanges(current, workInProgress, renderLanes2, false), state$102 = (renderLanes2 & workInProgress.childLanes) !== 0); + if (didSuspendBefore) { + if (state$102) + return updateSuspenseListComponent(current, workInProgress, renderLanes2); + workInProgress.flags |= 128; + } + didSuspendBefore = workInProgress.memoizedState; + didSuspendBefore !== null && (didSuspendBefore.rendering = null, didSuspendBefore.tail = null, didSuspendBefore.lastEffect = null); + push2(suspenseStackCursor, suspenseStackCursor.current); + if (state$102) + break; + else + return null; + case 22: + return workInProgress.lanes = 0, updateOffscreenComponent(current, workInProgress, renderLanes2, workInProgress.pendingProps); + case 24: + pushProvider(workInProgress, CacheContext, current.memoizedState.cache); + } + return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes2); +} +function beginWork(current, workInProgress, renderLanes2) { + if (current !== null) + if (current.memoizedProps !== workInProgress.pendingProps) + didReceiveUpdate = true; + else { + if (!checkScheduledUpdateOrContext(current, renderLanes2) && (workInProgress.flags & 128) === 0) + return didReceiveUpdate = false, attemptEarlyBailoutIfNoScheduledUpdate(current, workInProgress, renderLanes2); + didReceiveUpdate = (current.flags & 131072) !== 0 ? true : false; + } + else + didReceiveUpdate = false, isHydrating && (workInProgress.flags & 1048576) !== 0 && pushTreeId(workInProgress, treeForkCount, workInProgress.index); + workInProgress.lanes = 0; + switch (workInProgress.tag) { + case 16: + a: { + var props = workInProgress.pendingProps; + current = resolveLazy(workInProgress.elementType); + workInProgress.type = current; + if (typeof current === "function") + shouldConstruct(current) ? (props = resolveClassComponentProps(current, props), workInProgress.tag = 1, workInProgress = updateClassComponent(null, workInProgress, current, props, renderLanes2)) : (workInProgress.tag = 0, workInProgress = updateFunctionComponent(null, workInProgress, current, props, renderLanes2)); + else { + if (current !== undefined && current !== null) { + var $$typeof = current.$$typeof; + if ($$typeof === REACT_FORWARD_REF_TYPE2) { + workInProgress.tag = 11; + workInProgress = updateForwardRef(null, workInProgress, current, props, renderLanes2); + break a; + } else if ($$typeof === REACT_MEMO_TYPE2) { + workInProgress.tag = 14; + workInProgress = updateMemoComponent(null, workInProgress, current, props, renderLanes2); + break a; + } + } + workInProgress = getComponentNameFromType(current) || current; + throw Error(formatProdErrorMessage2(306, workInProgress, "")); + } + } + return workInProgress; + case 0: + return updateFunctionComponent(current, workInProgress, workInProgress.type, workInProgress.pendingProps, renderLanes2); + case 1: + return props = workInProgress.type, $$typeof = resolveClassComponentProps(props, workInProgress.pendingProps), updateClassComponent(current, workInProgress, props, $$typeof, renderLanes2); + case 3: + a: { + pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo); + if (current === null) + throw Error(formatProdErrorMessage2(387)); + props = workInProgress.pendingProps; + var prevState = workInProgress.memoizedState; + $$typeof = prevState.element; + cloneUpdateQueue(current, workInProgress); + processUpdateQueue(workInProgress, props, null, renderLanes2); + var nextState = workInProgress.memoizedState; + props = nextState.cache; + pushProvider(workInProgress, CacheContext, props); + props !== prevState.cache && propagateContextChanges(workInProgress, [CacheContext], renderLanes2, true); + suspendIfUpdateReadFromEntangledAsyncAction(); + props = nextState.element; + if (prevState.isDehydrated) + if (prevState = { + element: props, + isDehydrated: false, + cache: nextState.cache + }, workInProgress.updateQueue.baseState = prevState, workInProgress.memoizedState = prevState, workInProgress.flags & 256) { + workInProgress = mountHostRootWithoutHydrating(current, workInProgress, props, renderLanes2); + break a; + } else if (props !== $$typeof) { + $$typeof = createCapturedValueAtFiber(Error(formatProdErrorMessage2(424)), workInProgress); + queueHydrationError($$typeof); + workInProgress = mountHostRootWithoutHydrating(current, workInProgress, props, renderLanes2); + break a; + } else { + current = workInProgress.stateNode.containerInfo; + switch (current.nodeType) { + case 9: + current = current.body; + break; + default: + current = current.nodeName === "HTML" ? current.ownerDocument.body : current; + } + nextHydratableInstance = getNextHydratable(current.firstChild); + hydrationParentFiber = workInProgress; + isHydrating = true; + hydrationErrors = null; + rootOrSingletonContext = true; + renderLanes2 = mountChildFibers(workInProgress, null, props, renderLanes2); + for (workInProgress.child = renderLanes2;renderLanes2; ) + renderLanes2.flags = renderLanes2.flags & -3 | 4096, renderLanes2 = renderLanes2.sibling; + } + else { + resetHydrationState(); + if (props === $$typeof) { + workInProgress = bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes2); + break a; + } + reconcileChildren(current, workInProgress, props, renderLanes2); + } + workInProgress = workInProgress.child; + } + return workInProgress; + case 26: + return markRef(current, workInProgress), current === null ? (renderLanes2 = getResource(workInProgress.type, null, workInProgress.pendingProps, null)) ? workInProgress.memoizedState = renderLanes2 : isHydrating || (renderLanes2 = workInProgress.type, current = workInProgress.pendingProps, props = getOwnerDocumentFromRootContainer(rootInstanceStackCursor.current).createElement(renderLanes2), props[internalInstanceKey] = workInProgress, props[internalPropsKey] = current, setInitialProperties(props, renderLanes2, current), markNodeAsHoistable(props), workInProgress.stateNode = props) : workInProgress.memoizedState = getResource(workInProgress.type, current.memoizedProps, workInProgress.pendingProps, current.memoizedState), null; + case 27: + return pushHostContext(workInProgress), current === null && isHydrating && (props = workInProgress.stateNode = resolveSingletonInstance(workInProgress.type, workInProgress.pendingProps, rootInstanceStackCursor.current), hydrationParentFiber = workInProgress, rootOrSingletonContext = true, $$typeof = nextHydratableInstance, isSingletonScope(workInProgress.type) ? (previousHydratableOnEnteringScopedSingleton = $$typeof, nextHydratableInstance = getNextHydratable(props.firstChild)) : nextHydratableInstance = $$typeof), reconcileChildren(current, workInProgress, workInProgress.pendingProps.children, renderLanes2), markRef(current, workInProgress), current === null && (workInProgress.flags |= 4194304), workInProgress.child; + case 5: + if (current === null && isHydrating) { + if ($$typeof = props = nextHydratableInstance) + props = canHydrateInstance(props, workInProgress.type, workInProgress.pendingProps, rootOrSingletonContext), props !== null ? (workInProgress.stateNode = props, hydrationParentFiber = workInProgress, nextHydratableInstance = getNextHydratable(props.firstChild), rootOrSingletonContext = false, $$typeof = true) : $$typeof = false; + $$typeof || throwOnHydrationMismatch(workInProgress); + } + pushHostContext(workInProgress); + $$typeof = workInProgress.type; + prevState = workInProgress.pendingProps; + nextState = current !== null ? current.memoizedProps : null; + props = prevState.children; + shouldSetTextContent($$typeof, prevState) ? props = null : nextState !== null && shouldSetTextContent($$typeof, nextState) && (workInProgress.flags |= 32); + workInProgress.memoizedState !== null && ($$typeof = renderWithHooks(current, workInProgress, TransitionAwareHostComponent, null, null, renderLanes2), HostTransitionContext._currentValue = $$typeof); + markRef(current, workInProgress); + reconcileChildren(current, workInProgress, props, renderLanes2); + return workInProgress.child; + case 6: + if (current === null && isHydrating) { + if (current = renderLanes2 = nextHydratableInstance) + renderLanes2 = canHydrateTextInstance(renderLanes2, workInProgress.pendingProps, rootOrSingletonContext), renderLanes2 !== null ? (workInProgress.stateNode = renderLanes2, hydrationParentFiber = workInProgress, nextHydratableInstance = null, current = true) : current = false; + current || throwOnHydrationMismatch(workInProgress); + } + return null; + case 13: + return updateSuspenseComponent(current, workInProgress, renderLanes2); + case 4: + return pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo), props = workInProgress.pendingProps, current === null ? workInProgress.child = reconcileChildFibers(workInProgress, null, props, renderLanes2) : reconcileChildren(current, workInProgress, props, renderLanes2), workInProgress.child; + case 11: + return updateForwardRef(current, workInProgress, workInProgress.type, workInProgress.pendingProps, renderLanes2); + case 7: + return reconcileChildren(current, workInProgress, workInProgress.pendingProps, renderLanes2), workInProgress.child; + case 8: + return reconcileChildren(current, workInProgress, workInProgress.pendingProps.children, renderLanes2), workInProgress.child; + case 12: + return reconcileChildren(current, workInProgress, workInProgress.pendingProps.children, renderLanes2), workInProgress.child; + case 10: + return props = workInProgress.pendingProps, pushProvider(workInProgress, workInProgress.type, props.value), reconcileChildren(current, workInProgress, props.children, renderLanes2), workInProgress.child; + case 9: + return $$typeof = workInProgress.type._context, props = workInProgress.pendingProps.children, prepareToReadContext(workInProgress), $$typeof = readContext($$typeof), props = props($$typeof), workInProgress.flags |= 1, reconcileChildren(current, workInProgress, props, renderLanes2), workInProgress.child; + case 14: + return updateMemoComponent(current, workInProgress, workInProgress.type, workInProgress.pendingProps, renderLanes2); + case 15: + return updateSimpleMemoComponent(current, workInProgress, workInProgress.type, workInProgress.pendingProps, renderLanes2); + case 19: + return updateSuspenseListComponent(current, workInProgress, renderLanes2); + case 31: + return updateActivityComponent(current, workInProgress, renderLanes2); + case 22: + return updateOffscreenComponent(current, workInProgress, renderLanes2, workInProgress.pendingProps); + case 24: + return prepareToReadContext(workInProgress), props = readContext(CacheContext), current === null ? ($$typeof = peekCacheFromPool(), $$typeof === null && ($$typeof = workInProgressRoot, prevState = createCache(), $$typeof.pooledCache = prevState, prevState.refCount++, prevState !== null && ($$typeof.pooledCacheLanes |= renderLanes2), $$typeof = prevState), workInProgress.memoizedState = { parent: props, cache: $$typeof }, initializeUpdateQueue(workInProgress), pushProvider(workInProgress, CacheContext, $$typeof)) : ((current.lanes & renderLanes2) !== 0 && (cloneUpdateQueue(current, workInProgress), processUpdateQueue(workInProgress, null, null, renderLanes2), suspendIfUpdateReadFromEntangledAsyncAction()), $$typeof = current.memoizedState, prevState = workInProgress.memoizedState, $$typeof.parent !== props ? ($$typeof = { parent: props, cache: props }, workInProgress.memoizedState = $$typeof, workInProgress.lanes === 0 && (workInProgress.memoizedState = workInProgress.updateQueue.baseState = $$typeof), pushProvider(workInProgress, CacheContext, props)) : (props = prevState.cache, pushProvider(workInProgress, CacheContext, props), props !== $$typeof.cache && propagateContextChanges(workInProgress, [CacheContext], renderLanes2, true))), reconcileChildren(current, workInProgress, workInProgress.pendingProps.children, renderLanes2), workInProgress.child; + case 29: + throw workInProgress.pendingProps; + } + throw Error(formatProdErrorMessage2(156, workInProgress.tag)); +} +function markUpdate(workInProgress) { + workInProgress.flags |= 4; +} +function preloadInstanceAndSuspendIfNeeded(workInProgress, type, oldProps, newProps, renderLanes2) { + if (type = (workInProgress.mode & 32) !== 0) + type = false; + if (type) { + if (workInProgress.flags |= 16777216, (renderLanes2 & 335544128) === renderLanes2) + if (workInProgress.stateNode.complete) + workInProgress.flags |= 8192; + else if (shouldRemainOnPreviousScreen()) + workInProgress.flags |= 8192; + else + throw suspendedThenable = noopSuspenseyCommitThenable, SuspenseyCommitException; + } else + workInProgress.flags &= -16777217; +} +function preloadResourceAndSuspendIfNeeded(workInProgress, resource) { + if (resource.type !== "stylesheet" || (resource.state.loading & 4) !== 0) + workInProgress.flags &= -16777217; + else if (workInProgress.flags |= 16777216, !preloadResource(resource)) + if (shouldRemainOnPreviousScreen()) + workInProgress.flags |= 8192; + else + throw suspendedThenable = noopSuspenseyCommitThenable, SuspenseyCommitException; +} +function scheduleRetryEffect(workInProgress, retryQueue) { + retryQueue !== null && (workInProgress.flags |= 4); + workInProgress.flags & 16384 && (retryQueue = workInProgress.tag !== 22 ? claimNextRetryLane() : 536870912, workInProgress.lanes |= retryQueue, workInProgressSuspendedRetryLanes |= retryQueue); +} +function cutOffTailIfNeeded(renderState, hasRenderedATailFallback) { + if (!isHydrating) + switch (renderState.tailMode) { + case "hidden": + hasRenderedATailFallback = renderState.tail; + for (var lastTailNode = null;hasRenderedATailFallback !== null; ) + hasRenderedATailFallback.alternate !== null && (lastTailNode = hasRenderedATailFallback), hasRenderedATailFallback = hasRenderedATailFallback.sibling; + lastTailNode === null ? renderState.tail = null : lastTailNode.sibling = null; + break; + case "collapsed": + lastTailNode = renderState.tail; + for (var lastTailNode$106 = null;lastTailNode !== null; ) + lastTailNode.alternate !== null && (lastTailNode$106 = lastTailNode), lastTailNode = lastTailNode.sibling; + lastTailNode$106 === null ? hasRenderedATailFallback || renderState.tail === null ? renderState.tail = null : renderState.tail.sibling = null : lastTailNode$106.sibling = null; + } +} +function bubbleProperties(completedWork) { + var didBailout = completedWork.alternate !== null && completedWork.alternate.child === completedWork.child, newChildLanes = 0, subtreeFlags = 0; + if (didBailout) + for (var child$107 = completedWork.child;child$107 !== null; ) + newChildLanes |= child$107.lanes | child$107.childLanes, subtreeFlags |= child$107.subtreeFlags & 65011712, subtreeFlags |= child$107.flags & 65011712, child$107.return = completedWork, child$107 = child$107.sibling; + else + for (child$107 = completedWork.child;child$107 !== null; ) + newChildLanes |= child$107.lanes | child$107.childLanes, subtreeFlags |= child$107.subtreeFlags, subtreeFlags |= child$107.flags, child$107.return = completedWork, child$107 = child$107.sibling; + completedWork.subtreeFlags |= subtreeFlags; + completedWork.childLanes = newChildLanes; + return didBailout; +} +function completeWork(current, workInProgress, renderLanes2) { + var newProps = workInProgress.pendingProps; + popTreeContext(workInProgress); + switch (workInProgress.tag) { + case 16: + case 15: + case 0: + case 11: + case 7: + case 8: + case 12: + case 9: + case 14: + return bubbleProperties(workInProgress), null; + case 1: + return bubbleProperties(workInProgress), null; + case 3: + renderLanes2 = workInProgress.stateNode; + newProps = null; + current !== null && (newProps = current.memoizedState.cache); + workInProgress.memoizedState.cache !== newProps && (workInProgress.flags |= 2048); + popProvider(CacheContext); + popHostContainer(); + renderLanes2.pendingContext && (renderLanes2.context = renderLanes2.pendingContext, renderLanes2.pendingContext = null); + if (current === null || current.child === null) + popHydrationState(workInProgress) ? markUpdate(workInProgress) : current === null || current.memoizedState.isDehydrated && (workInProgress.flags & 256) === 0 || (workInProgress.flags |= 1024, upgradeHydrationErrorsToRecoverable()); + bubbleProperties(workInProgress); + return null; + case 26: + var { type, memoizedState: nextResource } = workInProgress; + current === null ? (markUpdate(workInProgress), nextResource !== null ? (bubbleProperties(workInProgress), preloadResourceAndSuspendIfNeeded(workInProgress, nextResource)) : (bubbleProperties(workInProgress), preloadInstanceAndSuspendIfNeeded(workInProgress, type, null, newProps, renderLanes2))) : nextResource ? nextResource !== current.memoizedState ? (markUpdate(workInProgress), bubbleProperties(workInProgress), preloadResourceAndSuspendIfNeeded(workInProgress, nextResource)) : (bubbleProperties(workInProgress), workInProgress.flags &= -16777217) : (current = current.memoizedProps, current !== newProps && markUpdate(workInProgress), bubbleProperties(workInProgress), preloadInstanceAndSuspendIfNeeded(workInProgress, type, current, newProps, renderLanes2)); + return null; + case 27: + popHostContext(workInProgress); + renderLanes2 = rootInstanceStackCursor.current; + type = workInProgress.type; + if (current !== null && workInProgress.stateNode != null) + current.memoizedProps !== newProps && markUpdate(workInProgress); + else { + if (!newProps) { + if (workInProgress.stateNode === null) + throw Error(formatProdErrorMessage2(166)); + bubbleProperties(workInProgress); + return null; + } + current = contextStackCursor.current; + popHydrationState(workInProgress) ? prepareToHydrateHostInstance(workInProgress, current) : (current = resolveSingletonInstance(type, newProps, renderLanes2), workInProgress.stateNode = current, markUpdate(workInProgress)); + } + bubbleProperties(workInProgress); + return null; + case 5: + popHostContext(workInProgress); + type = workInProgress.type; + if (current !== null && workInProgress.stateNode != null) + current.memoizedProps !== newProps && markUpdate(workInProgress); + else { + if (!newProps) { + if (workInProgress.stateNode === null) + throw Error(formatProdErrorMessage2(166)); + bubbleProperties(workInProgress); + return null; + } + nextResource = contextStackCursor.current; + if (popHydrationState(workInProgress)) + prepareToHydrateHostInstance(workInProgress, nextResource); + else { + var ownerDocument = getOwnerDocumentFromRootContainer(rootInstanceStackCursor.current); + switch (nextResource) { + case 1: + nextResource = ownerDocument.createElementNS("http://www.w3.org/2000/svg", type); + break; + case 2: + nextResource = ownerDocument.createElementNS("http://www.w3.org/1998/Math/MathML", type); + break; + default: + switch (type) { + case "svg": + nextResource = ownerDocument.createElementNS("http://www.w3.org/2000/svg", type); + break; + case "math": + nextResource = ownerDocument.createElementNS("http://www.w3.org/1998/Math/MathML", type); + break; + case "script": + nextResource = ownerDocument.createElement("div"); + nextResource.innerHTML = ""; + nextResource = nextResource.removeChild(nextResource.firstChild); + break; + case "select": + nextResource = typeof newProps.is === "string" ? ownerDocument.createElement("select", { + is: newProps.is + }) : ownerDocument.createElement("select"); + newProps.multiple ? nextResource.multiple = true : newProps.size && (nextResource.size = newProps.size); + break; + default: + nextResource = typeof newProps.is === "string" ? ownerDocument.createElement(type, { is: newProps.is }) : ownerDocument.createElement(type); + } + } + nextResource[internalInstanceKey] = workInProgress; + nextResource[internalPropsKey] = newProps; + a: + for (ownerDocument = workInProgress.child;ownerDocument !== null; ) { + if (ownerDocument.tag === 5 || ownerDocument.tag === 6) + nextResource.appendChild(ownerDocument.stateNode); + else if (ownerDocument.tag !== 4 && ownerDocument.tag !== 27 && ownerDocument.child !== null) { + ownerDocument.child.return = ownerDocument; + ownerDocument = ownerDocument.child; + continue; + } + if (ownerDocument === workInProgress) + break a; + for (;ownerDocument.sibling === null; ) { + if (ownerDocument.return === null || ownerDocument.return === workInProgress) + break a; + ownerDocument = ownerDocument.return; + } + ownerDocument.sibling.return = ownerDocument.return; + ownerDocument = ownerDocument.sibling; + } + workInProgress.stateNode = nextResource; + a: + switch (setInitialProperties(nextResource, type, newProps), type) { + case "button": + case "input": + case "select": + case "textarea": + newProps = !!newProps.autoFocus; + break a; + case "img": + newProps = true; + break a; + default: + newProps = false; + } + newProps && markUpdate(workInProgress); + } + } + bubbleProperties(workInProgress); + preloadInstanceAndSuspendIfNeeded(workInProgress, workInProgress.type, current === null ? null : current.memoizedProps, workInProgress.pendingProps, renderLanes2); + return null; + case 6: + if (current && workInProgress.stateNode != null) + current.memoizedProps !== newProps && markUpdate(workInProgress); + else { + if (typeof newProps !== "string" && workInProgress.stateNode === null) + throw Error(formatProdErrorMessage2(166)); + current = rootInstanceStackCursor.current; + if (popHydrationState(workInProgress)) { + current = workInProgress.stateNode; + renderLanes2 = workInProgress.memoizedProps; + newProps = null; + type = hydrationParentFiber; + if (type !== null) + switch (type.tag) { + case 27: + case 5: + newProps = type.memoizedProps; + } + current[internalInstanceKey] = workInProgress; + current = current.nodeValue === renderLanes2 || newProps !== null && newProps.suppressHydrationWarning === true || checkForUnmatchedText(current.nodeValue, renderLanes2) ? true : false; + current || throwOnHydrationMismatch(workInProgress, true); + } else + current = getOwnerDocumentFromRootContainer(current).createTextNode(newProps), current[internalInstanceKey] = workInProgress, workInProgress.stateNode = current; + } + bubbleProperties(workInProgress); + return null; + case 31: + renderLanes2 = workInProgress.memoizedState; + if (current === null || current.memoizedState !== null) { + newProps = popHydrationState(workInProgress); + if (renderLanes2 !== null) { + if (current === null) { + if (!newProps) + throw Error(formatProdErrorMessage2(318)); + current = workInProgress.memoizedState; + current = current !== null ? current.dehydrated : null; + if (!current) + throw Error(formatProdErrorMessage2(557)); + current[internalInstanceKey] = workInProgress; + } else + resetHydrationState(), (workInProgress.flags & 128) === 0 && (workInProgress.memoizedState = null), workInProgress.flags |= 4; + bubbleProperties(workInProgress); + current = false; + } else + renderLanes2 = upgradeHydrationErrorsToRecoverable(), current !== null && current.memoizedState !== null && (current.memoizedState.hydrationErrors = renderLanes2), current = true; + if (!current) { + if (workInProgress.flags & 256) + return popSuspenseHandler(workInProgress), workInProgress; + popSuspenseHandler(workInProgress); + return null; + } + if ((workInProgress.flags & 128) !== 0) + throw Error(formatProdErrorMessage2(558)); + } + bubbleProperties(workInProgress); + return null; + case 13: + newProps = workInProgress.memoizedState; + if (current === null || current.memoizedState !== null && current.memoizedState.dehydrated !== null) { + type = popHydrationState(workInProgress); + if (newProps !== null && newProps.dehydrated !== null) { + if (current === null) { + if (!type) + throw Error(formatProdErrorMessage2(318)); + type = workInProgress.memoizedState; + type = type !== null ? type.dehydrated : null; + if (!type) + throw Error(formatProdErrorMessage2(317)); + type[internalInstanceKey] = workInProgress; + } else + resetHydrationState(), (workInProgress.flags & 128) === 0 && (workInProgress.memoizedState = null), workInProgress.flags |= 4; + bubbleProperties(workInProgress); + type = false; + } else + type = upgradeHydrationErrorsToRecoverable(), current !== null && current.memoizedState !== null && (current.memoizedState.hydrationErrors = type), type = true; + if (!type) { + if (workInProgress.flags & 256) + return popSuspenseHandler(workInProgress), workInProgress; + popSuspenseHandler(workInProgress); + return null; + } + } + popSuspenseHandler(workInProgress); + if ((workInProgress.flags & 128) !== 0) + return workInProgress.lanes = renderLanes2, workInProgress; + renderLanes2 = newProps !== null; + current = current !== null && current.memoizedState !== null; + renderLanes2 && (newProps = workInProgress.child, type = null, newProps.alternate !== null && newProps.alternate.memoizedState !== null && newProps.alternate.memoizedState.cachePool !== null && (type = newProps.alternate.memoizedState.cachePool.pool), nextResource = null, newProps.memoizedState !== null && newProps.memoizedState.cachePool !== null && (nextResource = newProps.memoizedState.cachePool.pool), nextResource !== type && (newProps.flags |= 2048)); + renderLanes2 !== current && renderLanes2 && (workInProgress.child.flags |= 8192); + scheduleRetryEffect(workInProgress, workInProgress.updateQueue); + bubbleProperties(workInProgress); + return null; + case 4: + return popHostContainer(), current === null && listenToAllSupportedEvents(workInProgress.stateNode.containerInfo), bubbleProperties(workInProgress), null; + case 10: + return popProvider(workInProgress.type), bubbleProperties(workInProgress), null; + case 19: + pop2(suspenseStackCursor); + newProps = workInProgress.memoizedState; + if (newProps === null) + return bubbleProperties(workInProgress), null; + type = (workInProgress.flags & 128) !== 0; + nextResource = newProps.rendering; + if (nextResource === null) + if (type) + cutOffTailIfNeeded(newProps, false); + else { + if (workInProgressRootExitStatus !== 0 || current !== null && (current.flags & 128) !== 0) + for (current = workInProgress.child;current !== null; ) { + nextResource = findFirstSuspended(current); + if (nextResource !== null) { + workInProgress.flags |= 128; + cutOffTailIfNeeded(newProps, false); + current = nextResource.updateQueue; + workInProgress.updateQueue = current; + scheduleRetryEffect(workInProgress, current); + workInProgress.subtreeFlags = 0; + current = renderLanes2; + for (renderLanes2 = workInProgress.child;renderLanes2 !== null; ) + resetWorkInProgress(renderLanes2, current), renderLanes2 = renderLanes2.sibling; + push2(suspenseStackCursor, suspenseStackCursor.current & 1 | 2); + isHydrating && pushTreeFork(workInProgress, newProps.treeForkCount); + return workInProgress.child; + } + current = current.sibling; + } + newProps.tail !== null && now() > workInProgressRootRenderTargetTime && (workInProgress.flags |= 128, type = true, cutOffTailIfNeeded(newProps, false), workInProgress.lanes = 4194304); + } + else { + if (!type) + if (current = findFirstSuspended(nextResource), current !== null) { + if (workInProgress.flags |= 128, type = true, current = current.updateQueue, workInProgress.updateQueue = current, scheduleRetryEffect(workInProgress, current), cutOffTailIfNeeded(newProps, true), newProps.tail === null && newProps.tailMode === "hidden" && !nextResource.alternate && !isHydrating) + return bubbleProperties(workInProgress), null; + } else + 2 * now() - newProps.renderingStartTime > workInProgressRootRenderTargetTime && renderLanes2 !== 536870912 && (workInProgress.flags |= 128, type = true, cutOffTailIfNeeded(newProps, false), workInProgress.lanes = 4194304); + newProps.isBackwards ? (nextResource.sibling = workInProgress.child, workInProgress.child = nextResource) : (current = newProps.last, current !== null ? current.sibling = nextResource : workInProgress.child = nextResource, newProps.last = nextResource); + } + if (newProps.tail !== null) + return current = newProps.tail, newProps.rendering = current, newProps.tail = current.sibling, newProps.renderingStartTime = now(), current.sibling = null, renderLanes2 = suspenseStackCursor.current, push2(suspenseStackCursor, type ? renderLanes2 & 1 | 2 : renderLanes2 & 1), isHydrating && pushTreeFork(workInProgress, newProps.treeForkCount), current; + bubbleProperties(workInProgress); + return null; + case 22: + case 23: + return popSuspenseHandler(workInProgress), popHiddenContext(), newProps = workInProgress.memoizedState !== null, current !== null ? current.memoizedState !== null !== newProps && (workInProgress.flags |= 8192) : newProps && (workInProgress.flags |= 8192), newProps ? (renderLanes2 & 536870912) !== 0 && (workInProgress.flags & 128) === 0 && (bubbleProperties(workInProgress), workInProgress.subtreeFlags & 6 && (workInProgress.flags |= 8192)) : bubbleProperties(workInProgress), renderLanes2 = workInProgress.updateQueue, renderLanes2 !== null && scheduleRetryEffect(workInProgress, renderLanes2.retryQueue), renderLanes2 = null, current !== null && current.memoizedState !== null && current.memoizedState.cachePool !== null && (renderLanes2 = current.memoizedState.cachePool.pool), newProps = null, workInProgress.memoizedState !== null && workInProgress.memoizedState.cachePool !== null && (newProps = workInProgress.memoizedState.cachePool.pool), newProps !== renderLanes2 && (workInProgress.flags |= 2048), current !== null && pop2(resumedCache), null; + case 24: + return renderLanes2 = null, current !== null && (renderLanes2 = current.memoizedState.cache), workInProgress.memoizedState.cache !== renderLanes2 && (workInProgress.flags |= 2048), popProvider(CacheContext), bubbleProperties(workInProgress), null; + case 25: + return null; + case 30: + return null; + } + throw Error(formatProdErrorMessage2(156, workInProgress.tag)); +} +function unwindWork(current, workInProgress) { + popTreeContext(workInProgress); + switch (workInProgress.tag) { + case 1: + return current = workInProgress.flags, current & 65536 ? (workInProgress.flags = current & -65537 | 128, workInProgress) : null; + case 3: + return popProvider(CacheContext), popHostContainer(), current = workInProgress.flags, (current & 65536) !== 0 && (current & 128) === 0 ? (workInProgress.flags = current & -65537 | 128, workInProgress) : null; + case 26: + case 27: + case 5: + return popHostContext(workInProgress), null; + case 31: + if (workInProgress.memoizedState !== null) { + popSuspenseHandler(workInProgress); + if (workInProgress.alternate === null) + throw Error(formatProdErrorMessage2(340)); + resetHydrationState(); + } + current = workInProgress.flags; + return current & 65536 ? (workInProgress.flags = current & -65537 | 128, workInProgress) : null; + case 13: + popSuspenseHandler(workInProgress); + current = workInProgress.memoizedState; + if (current !== null && current.dehydrated !== null) { + if (workInProgress.alternate === null) + throw Error(formatProdErrorMessage2(340)); + resetHydrationState(); + } + current = workInProgress.flags; + return current & 65536 ? (workInProgress.flags = current & -65537 | 128, workInProgress) : null; + case 19: + return pop2(suspenseStackCursor), null; + case 4: + return popHostContainer(), null; + case 10: + return popProvider(workInProgress.type), null; + case 22: + case 23: + return popSuspenseHandler(workInProgress), popHiddenContext(), current !== null && pop2(resumedCache), current = workInProgress.flags, current & 65536 ? (workInProgress.flags = current & -65537 | 128, workInProgress) : null; + case 24: + return popProvider(CacheContext), null; + case 25: + return null; + default: + return null; + } +} +function unwindInterruptedWork(current, interruptedWork) { + popTreeContext(interruptedWork); + switch (interruptedWork.tag) { + case 3: + popProvider(CacheContext); + popHostContainer(); + break; + case 26: + case 27: + case 5: + popHostContext(interruptedWork); + break; + case 4: + popHostContainer(); + break; + case 31: + interruptedWork.memoizedState !== null && popSuspenseHandler(interruptedWork); + break; + case 13: + popSuspenseHandler(interruptedWork); + break; + case 19: + pop2(suspenseStackCursor); + break; + case 10: + popProvider(interruptedWork.type); + break; + case 22: + case 23: + popSuspenseHandler(interruptedWork); + popHiddenContext(); + current !== null && pop2(resumedCache); + break; + case 24: + popProvider(CacheContext); + } +} +function commitHookEffectListMount(flags, finishedWork) { + try { + var updateQueue = finishedWork.updateQueue, lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; + if (lastEffect !== null) { + var firstEffect = lastEffect.next; + updateQueue = firstEffect; + do { + if ((updateQueue.tag & flags) === flags) { + lastEffect = undefined; + var { create, inst } = updateQueue; + lastEffect = create(); + inst.destroy = lastEffect; + } + updateQueue = updateQueue.next; + } while (updateQueue !== firstEffect); + } + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } +} +function commitHookEffectListUnmount(flags, finishedWork, nearestMountedAncestor$jscomp$0) { + try { + var updateQueue = finishedWork.updateQueue, lastEffect = updateQueue !== null ? updateQueue.lastEffect : null; + if (lastEffect !== null) { + var firstEffect = lastEffect.next; + updateQueue = firstEffect; + do { + if ((updateQueue.tag & flags) === flags) { + var inst = updateQueue.inst, destroy = inst.destroy; + if (destroy !== undefined) { + inst.destroy = undefined; + lastEffect = finishedWork; + var nearestMountedAncestor = nearestMountedAncestor$jscomp$0, destroy_ = destroy; + try { + destroy_(); + } catch (error) { + captureCommitPhaseError(lastEffect, nearestMountedAncestor, error); + } + } + } + updateQueue = updateQueue.next; + } while (updateQueue !== firstEffect); + } + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } +} +function commitClassCallbacks(finishedWork) { + var updateQueue = finishedWork.updateQueue; + if (updateQueue !== null) { + var instance = finishedWork.stateNode; + try { + commitCallbacks(updateQueue, instance); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + } +} +function safelyCallComponentWillUnmount(current, nearestMountedAncestor, instance) { + instance.props = resolveClassComponentProps(current.type, current.memoizedProps); + instance.state = current.memoizedState; + try { + instance.componentWillUnmount(); + } catch (error) { + captureCommitPhaseError(current, nearestMountedAncestor, error); + } +} +function safelyAttachRef(current, nearestMountedAncestor) { + try { + var ref = current.ref; + if (ref !== null) { + switch (current.tag) { + case 26: + case 27: + case 5: + var instanceToUse = current.stateNode; + break; + case 30: + instanceToUse = current.stateNode; + break; + default: + instanceToUse = current.stateNode; + } + typeof ref === "function" ? current.refCleanup = ref(instanceToUse) : ref.current = instanceToUse; + } + } catch (error) { + captureCommitPhaseError(current, nearestMountedAncestor, error); + } +} +function safelyDetachRef(current, nearestMountedAncestor) { + var { ref, refCleanup } = current; + if (ref !== null) + if (typeof refCleanup === "function") + try { + refCleanup(); + } catch (error) { + captureCommitPhaseError(current, nearestMountedAncestor, error); + } finally { + current.refCleanup = null, current = current.alternate, current != null && (current.refCleanup = null); + } + else if (typeof ref === "function") + try { + ref(null); + } catch (error$140) { + captureCommitPhaseError(current, nearestMountedAncestor, error$140); + } + else + ref.current = null; +} +function commitHostMount(finishedWork) { + var { type, memoizedProps: props, stateNode: instance } = finishedWork; + try { + a: + switch (type) { + case "button": + case "input": + case "select": + case "textarea": + props.autoFocus && instance.focus(); + break a; + case "img": + props.src ? instance.src = props.src : props.srcSet && (instance.srcset = props.srcSet); + } + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } +} +function commitHostUpdate(finishedWork, newProps, oldProps) { + try { + var domElement = finishedWork.stateNode; + updateProperties(domElement, finishedWork.type, oldProps, newProps); + domElement[internalPropsKey] = newProps; + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } +} +function isHostParent(fiber) { + return fiber.tag === 5 || fiber.tag === 3 || fiber.tag === 26 || fiber.tag === 27 && isSingletonScope(fiber.type) || fiber.tag === 4; +} +function getHostSibling(fiber) { + a: + for (;; ) { + for (;fiber.sibling === null; ) { + if (fiber.return === null || isHostParent(fiber.return)) + return null; + fiber = fiber.return; + } + fiber.sibling.return = fiber.return; + for (fiber = fiber.sibling;fiber.tag !== 5 && fiber.tag !== 6 && fiber.tag !== 18; ) { + if (fiber.tag === 27 && isSingletonScope(fiber.type)) + continue a; + if (fiber.flags & 2) + continue a; + if (fiber.child === null || fiber.tag === 4) + continue a; + else + fiber.child.return = fiber, fiber = fiber.child; + } + if (!(fiber.flags & 2)) + return fiber.stateNode; + } +} +function insertOrAppendPlacementNodeIntoContainer(node, before, parent) { + var tag = node.tag; + if (tag === 5 || tag === 6) + node = node.stateNode, before ? (parent.nodeType === 9 ? parent.body : parent.nodeName === "HTML" ? parent.ownerDocument.body : parent).insertBefore(node, before) : (before = parent.nodeType === 9 ? parent.body : parent.nodeName === "HTML" ? parent.ownerDocument.body : parent, before.appendChild(node), parent = parent._reactRootContainer, parent !== null && parent !== undefined || before.onclick !== null || (before.onclick = noop$1)); + else if (tag !== 4 && (tag === 27 && isSingletonScope(node.type) && (parent = node.stateNode, before = null), node = node.child, node !== null)) + for (insertOrAppendPlacementNodeIntoContainer(node, before, parent), node = node.sibling;node !== null; ) + insertOrAppendPlacementNodeIntoContainer(node, before, parent), node = node.sibling; +} +function insertOrAppendPlacementNode(node, before, parent) { + var tag = node.tag; + if (tag === 5 || tag === 6) + node = node.stateNode, before ? parent.insertBefore(node, before) : parent.appendChild(node); + else if (tag !== 4 && (tag === 27 && isSingletonScope(node.type) && (parent = node.stateNode), node = node.child, node !== null)) + for (insertOrAppendPlacementNode(node, before, parent), node = node.sibling;node !== null; ) + insertOrAppendPlacementNode(node, before, parent), node = node.sibling; +} +function commitHostSingletonAcquisition(finishedWork) { + var { stateNode: singleton, memoizedProps: props } = finishedWork; + try { + for (var type = finishedWork.type, attributes = singleton.attributes;attributes.length; ) + singleton.removeAttributeNode(attributes[0]); + setInitialProperties(singleton, type, props); + singleton[internalInstanceKey] = finishedWork; + singleton[internalPropsKey] = props; + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } +} +function commitBeforeMutationEffects(root2, firstChild) { + root2 = root2.containerInfo; + eventsEnabled = _enabled; + root2 = getActiveElementDeep(root2); + if (hasSelectionCapabilities(root2)) { + if ("selectionStart" in root2) + var JSCompiler_temp = { + start: root2.selectionStart, + end: root2.selectionEnd + }; + else + a: { + JSCompiler_temp = (JSCompiler_temp = root2.ownerDocument) && JSCompiler_temp.defaultView || window; + var selection = JSCompiler_temp.getSelection && JSCompiler_temp.getSelection(); + if (selection && selection.rangeCount !== 0) { + JSCompiler_temp = selection.anchorNode; + var { anchorOffset, focusNode } = selection; + selection = selection.focusOffset; + try { + JSCompiler_temp.nodeType, focusNode.nodeType; + } catch (e$20) { + JSCompiler_temp = null; + break a; + } + var length = 0, start = -1, end = -1, indexWithinAnchor = 0, indexWithinFocus = 0, node = root2, parentNode = null; + b: + for (;; ) { + for (var next;; ) { + node !== JSCompiler_temp || anchorOffset !== 0 && node.nodeType !== 3 || (start = length + anchorOffset); + node !== focusNode || selection !== 0 && node.nodeType !== 3 || (end = length + selection); + node.nodeType === 3 && (length += node.nodeValue.length); + if ((next = node.firstChild) === null) + break; + parentNode = node; + node = next; + } + for (;; ) { + if (node === root2) + break b; + parentNode === JSCompiler_temp && ++indexWithinAnchor === anchorOffset && (start = length); + parentNode === focusNode && ++indexWithinFocus === selection && (end = length); + if ((next = node.nextSibling) !== null) + break; + node = parentNode; + parentNode = node.parentNode; + } + node = next; + } + JSCompiler_temp = start === -1 || end === -1 ? null : { start, end }; + } else + JSCompiler_temp = null; + } + JSCompiler_temp = JSCompiler_temp || { start: 0, end: 0 }; + } else + JSCompiler_temp = null; + selectionInformation = { focusedElem: root2, selectionRange: JSCompiler_temp }; + _enabled = false; + for (nextEffect = firstChild;nextEffect !== null; ) + if (firstChild = nextEffect, root2 = firstChild.child, (firstChild.subtreeFlags & 1028) !== 0 && root2 !== null) + root2.return = firstChild, nextEffect = root2; + else + for (;nextEffect !== null; ) { + firstChild = nextEffect; + focusNode = firstChild.alternate; + root2 = firstChild.flags; + switch (firstChild.tag) { + case 0: + if ((root2 & 4) !== 0 && (root2 = firstChild.updateQueue, root2 = root2 !== null ? root2.events : null, root2 !== null)) + for (JSCompiler_temp = 0;JSCompiler_temp < root2.length; JSCompiler_temp++) + anchorOffset = root2[JSCompiler_temp], anchorOffset.ref.impl = anchorOffset.nextImpl; + break; + case 11: + case 15: + break; + case 1: + if ((root2 & 1024) !== 0 && focusNode !== null) { + root2 = undefined; + JSCompiler_temp = firstChild; + anchorOffset = focusNode.memoizedProps; + focusNode = focusNode.memoizedState; + selection = JSCompiler_temp.stateNode; + try { + var resolvedPrevProps = resolveClassComponentProps(JSCompiler_temp.type, anchorOffset); + root2 = selection.getSnapshotBeforeUpdate(resolvedPrevProps, focusNode); + selection.__reactInternalSnapshotBeforeUpdate = root2; + } catch (error) { + captureCommitPhaseError(JSCompiler_temp, JSCompiler_temp.return, error); + } + } + break; + case 3: + if ((root2 & 1024) !== 0) { + if (root2 = firstChild.stateNode.containerInfo, JSCompiler_temp = root2.nodeType, JSCompiler_temp === 9) + clearContainerSparingly(root2); + else if (JSCompiler_temp === 1) + switch (root2.nodeName) { + case "HEAD": + case "HTML": + case "BODY": + clearContainerSparingly(root2); + break; + default: + root2.textContent = ""; + } + } + break; + case 5: + case 26: + case 27: + case 6: + case 4: + case 17: + break; + default: + if ((root2 & 1024) !== 0) + throw Error(formatProdErrorMessage2(163)); + } + root2 = firstChild.sibling; + if (root2 !== null) { + root2.return = firstChild.return; + nextEffect = root2; + break; + } + nextEffect = firstChild.return; + } +} +function commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) { + var flags = finishedWork.flags; + switch (finishedWork.tag) { + case 0: + case 11: + case 15: + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + flags & 4 && commitHookEffectListMount(5, finishedWork); + break; + case 1: + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + if (flags & 4) + if (finishedRoot = finishedWork.stateNode, current === null) + try { + finishedRoot.componentDidMount(); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + else { + var prevProps = resolveClassComponentProps(finishedWork.type, current.memoizedProps); + current = current.memoizedState; + try { + finishedRoot.componentDidUpdate(prevProps, current, finishedRoot.__reactInternalSnapshotBeforeUpdate); + } catch (error$139) { + captureCommitPhaseError(finishedWork, finishedWork.return, error$139); + } + } + flags & 64 && commitClassCallbacks(finishedWork); + flags & 512 && safelyAttachRef(finishedWork, finishedWork.return); + break; + case 3: + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + if (flags & 64 && (finishedRoot = finishedWork.updateQueue, finishedRoot !== null)) { + current = null; + if (finishedWork.child !== null) + switch (finishedWork.child.tag) { + case 27: + case 5: + current = finishedWork.child.stateNode; + break; + case 1: + current = finishedWork.child.stateNode; + } + try { + commitCallbacks(finishedRoot, current); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + } + break; + case 27: + current === null && flags & 4 && commitHostSingletonAcquisition(finishedWork); + case 26: + case 5: + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + current === null && flags & 4 && commitHostMount(finishedWork); + flags & 512 && safelyAttachRef(finishedWork, finishedWork.return); + break; + case 12: + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + break; + case 31: + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + flags & 4 && commitActivityHydrationCallbacks(finishedRoot, finishedWork); + break; + case 13: + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + flags & 4 && commitSuspenseHydrationCallbacks(finishedRoot, finishedWork); + flags & 64 && (finishedRoot = finishedWork.memoizedState, finishedRoot !== null && (finishedRoot = finishedRoot.dehydrated, finishedRoot !== null && (finishedWork = retryDehydratedSuspenseBoundary.bind(null, finishedWork), registerSuspenseInstanceRetry(finishedRoot, finishedWork)))); + break; + case 22: + flags = finishedWork.memoizedState !== null || offscreenSubtreeIsHidden; + if (!flags) { + current = current !== null && current.memoizedState !== null || offscreenSubtreeWasHidden; + prevProps = offscreenSubtreeIsHidden; + var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; + offscreenSubtreeIsHidden = flags; + (offscreenSubtreeWasHidden = current) && !prevOffscreenSubtreeWasHidden ? recursivelyTraverseReappearLayoutEffects(finishedRoot, finishedWork, (finishedWork.subtreeFlags & 8772) !== 0) : recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + offscreenSubtreeIsHidden = prevProps; + offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; + } + break; + case 30: + break; + default: + recursivelyTraverseLayoutEffects(finishedRoot, finishedWork); + } +} +function detachFiberAfterEffects(fiber) { + var alternate = fiber.alternate; + alternate !== null && (fiber.alternate = null, detachFiberAfterEffects(alternate)); + fiber.child = null; + fiber.deletions = null; + fiber.sibling = null; + fiber.tag === 5 && (alternate = fiber.stateNode, alternate !== null && detachDeletedInstance(alternate)); + fiber.stateNode = null; + fiber.return = null; + fiber.dependencies = null; + fiber.memoizedProps = null; + fiber.memoizedState = null; + fiber.pendingProps = null; + fiber.stateNode = null; + fiber.updateQueue = null; +} +function recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, parent) { + for (parent = parent.child;parent !== null; ) + commitDeletionEffectsOnFiber(finishedRoot, nearestMountedAncestor, parent), parent = parent.sibling; +} +function commitDeletionEffectsOnFiber(finishedRoot, nearestMountedAncestor, deletedFiber) { + if (injectedHook && typeof injectedHook.onCommitFiberUnmount === "function") + try { + injectedHook.onCommitFiberUnmount(rendererID, deletedFiber); + } catch (err) {} + switch (deletedFiber.tag) { + case 26: + offscreenSubtreeWasHidden || safelyDetachRef(deletedFiber, nearestMountedAncestor); + recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber); + deletedFiber.memoizedState ? deletedFiber.memoizedState.count-- : deletedFiber.stateNode && (deletedFiber = deletedFiber.stateNode, deletedFiber.parentNode.removeChild(deletedFiber)); + break; + case 27: + offscreenSubtreeWasHidden || safelyDetachRef(deletedFiber, nearestMountedAncestor); + var prevHostParent = hostParent, prevHostParentIsContainer = hostParentIsContainer; + isSingletonScope(deletedFiber.type) && (hostParent = deletedFiber.stateNode, hostParentIsContainer = false); + recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber); + releaseSingletonInstance(deletedFiber.stateNode); + hostParent = prevHostParent; + hostParentIsContainer = prevHostParentIsContainer; + break; + case 5: + offscreenSubtreeWasHidden || safelyDetachRef(deletedFiber, nearestMountedAncestor); + case 6: + prevHostParent = hostParent; + prevHostParentIsContainer = hostParentIsContainer; + hostParent = null; + recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber); + hostParent = prevHostParent; + hostParentIsContainer = prevHostParentIsContainer; + if (hostParent !== null) + if (hostParentIsContainer) + try { + (hostParent.nodeType === 9 ? hostParent.body : hostParent.nodeName === "HTML" ? hostParent.ownerDocument.body : hostParent).removeChild(deletedFiber.stateNode); + } catch (error) { + captureCommitPhaseError(deletedFiber, nearestMountedAncestor, error); + } + else + try { + hostParent.removeChild(deletedFiber.stateNode); + } catch (error) { + captureCommitPhaseError(deletedFiber, nearestMountedAncestor, error); + } + break; + case 18: + hostParent !== null && (hostParentIsContainer ? (finishedRoot = hostParent, clearHydrationBoundary(finishedRoot.nodeType === 9 ? finishedRoot.body : finishedRoot.nodeName === "HTML" ? finishedRoot.ownerDocument.body : finishedRoot, deletedFiber.stateNode), retryIfBlockedOn(finishedRoot)) : clearHydrationBoundary(hostParent, deletedFiber.stateNode)); + break; + case 4: + prevHostParent = hostParent; + prevHostParentIsContainer = hostParentIsContainer; + hostParent = deletedFiber.stateNode.containerInfo; + hostParentIsContainer = true; + recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber); + hostParent = prevHostParent; + hostParentIsContainer = prevHostParentIsContainer; + break; + case 0: + case 11: + case 14: + case 15: + commitHookEffectListUnmount(2, deletedFiber, nearestMountedAncestor); + offscreenSubtreeWasHidden || commitHookEffectListUnmount(4, deletedFiber, nearestMountedAncestor); + recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber); + break; + case 1: + offscreenSubtreeWasHidden || (safelyDetachRef(deletedFiber, nearestMountedAncestor), prevHostParent = deletedFiber.stateNode, typeof prevHostParent.componentWillUnmount === "function" && safelyCallComponentWillUnmount(deletedFiber, nearestMountedAncestor, prevHostParent)); + recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber); + break; + case 21: + recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber); + break; + case 22: + offscreenSubtreeWasHidden = (prevHostParent = offscreenSubtreeWasHidden) || deletedFiber.memoizedState !== null; + recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber); + offscreenSubtreeWasHidden = prevHostParent; + break; + default: + recursivelyTraverseDeletionEffects(finishedRoot, nearestMountedAncestor, deletedFiber); + } +} +function commitActivityHydrationCallbacks(finishedRoot, finishedWork) { + if (finishedWork.memoizedState === null && (finishedRoot = finishedWork.alternate, finishedRoot !== null && (finishedRoot = finishedRoot.memoizedState, finishedRoot !== null))) { + finishedRoot = finishedRoot.dehydrated; + try { + retryIfBlockedOn(finishedRoot); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + } +} +function commitSuspenseHydrationCallbacks(finishedRoot, finishedWork) { + if (finishedWork.memoizedState === null && (finishedRoot = finishedWork.alternate, finishedRoot !== null && (finishedRoot = finishedRoot.memoizedState, finishedRoot !== null && (finishedRoot = finishedRoot.dehydrated, finishedRoot !== null)))) + try { + retryIfBlockedOn(finishedRoot); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } +} +function getRetryCache(finishedWork) { + switch (finishedWork.tag) { + case 31: + case 13: + case 19: + var retryCache = finishedWork.stateNode; + retryCache === null && (retryCache = finishedWork.stateNode = new PossiblyWeakSet); + return retryCache; + case 22: + return finishedWork = finishedWork.stateNode, retryCache = finishedWork._retryCache, retryCache === null && (retryCache = finishedWork._retryCache = new PossiblyWeakSet), retryCache; + default: + throw Error(formatProdErrorMessage2(435, finishedWork.tag)); + } +} +function attachSuspenseRetryListeners(finishedWork, wakeables) { + var retryCache = getRetryCache(finishedWork); + wakeables.forEach(function(wakeable) { + if (!retryCache.has(wakeable)) { + retryCache.add(wakeable); + var retry = resolveRetryWakeable.bind(null, finishedWork, wakeable); + wakeable.then(retry, retry); + } + }); +} +function recursivelyTraverseMutationEffects(root$jscomp$0, parentFiber) { + var deletions = parentFiber.deletions; + if (deletions !== null) + for (var i = 0;i < deletions.length; i++) { + var childToDelete = deletions[i], root2 = root$jscomp$0, returnFiber = parentFiber, parent = returnFiber; + a: + for (;parent !== null; ) { + switch (parent.tag) { + case 27: + if (isSingletonScope(parent.type)) { + hostParent = parent.stateNode; + hostParentIsContainer = false; + break a; + } + break; + case 5: + hostParent = parent.stateNode; + hostParentIsContainer = false; + break a; + case 3: + case 4: + hostParent = parent.stateNode.containerInfo; + hostParentIsContainer = true; + break a; + } + parent = parent.return; + } + if (hostParent === null) + throw Error(formatProdErrorMessage2(160)); + commitDeletionEffectsOnFiber(root2, returnFiber, childToDelete); + hostParent = null; + hostParentIsContainer = false; + root2 = childToDelete.alternate; + root2 !== null && (root2.return = null); + childToDelete.return = null; + } + if (parentFiber.subtreeFlags & 13886) + for (parentFiber = parentFiber.child;parentFiber !== null; ) + commitMutationEffectsOnFiber(parentFiber, root$jscomp$0), parentFiber = parentFiber.sibling; +} +function commitMutationEffectsOnFiber(finishedWork, root2) { + var { alternate: current, flags } = finishedWork; + switch (finishedWork.tag) { + case 0: + case 11: + case 14: + case 15: + recursivelyTraverseMutationEffects(root2, finishedWork); + commitReconciliationEffects(finishedWork); + flags & 4 && (commitHookEffectListUnmount(3, finishedWork, finishedWork.return), commitHookEffectListMount(3, finishedWork), commitHookEffectListUnmount(5, finishedWork, finishedWork.return)); + break; + case 1: + recursivelyTraverseMutationEffects(root2, finishedWork); + commitReconciliationEffects(finishedWork); + flags & 512 && (offscreenSubtreeWasHidden || current === null || safelyDetachRef(current, current.return)); + flags & 64 && offscreenSubtreeIsHidden && (finishedWork = finishedWork.updateQueue, finishedWork !== null && (flags = finishedWork.callbacks, flags !== null && (current = finishedWork.shared.hiddenCallbacks, finishedWork.shared.hiddenCallbacks = current === null ? flags : current.concat(flags)))); + break; + case 26: + var hoistableRoot = currentHoistableRoot; + recursivelyTraverseMutationEffects(root2, finishedWork); + commitReconciliationEffects(finishedWork); + flags & 512 && (offscreenSubtreeWasHidden || current === null || safelyDetachRef(current, current.return)); + if (flags & 4) { + var currentResource = current !== null ? current.memoizedState : null; + flags = finishedWork.memoizedState; + if (current === null) + if (flags === null) + if (finishedWork.stateNode === null) { + a: { + flags = finishedWork.type; + current = finishedWork.memoizedProps; + hoistableRoot = hoistableRoot.ownerDocument || hoistableRoot; + b: + switch (flags) { + case "title": + currentResource = hoistableRoot.getElementsByTagName("title")[0]; + if (!currentResource || currentResource[internalHoistableMarker] || currentResource[internalInstanceKey] || currentResource.namespaceURI === "http://www.w3.org/2000/svg" || currentResource.hasAttribute("itemprop")) + currentResource = hoistableRoot.createElement(flags), hoistableRoot.head.insertBefore(currentResource, hoistableRoot.querySelector("head > title")); + setInitialProperties(currentResource, flags, current); + currentResource[internalInstanceKey] = finishedWork; + markNodeAsHoistable(currentResource); + flags = currentResource; + break a; + case "link": + var maybeNodes = getHydratableHoistableCache("link", "href", hoistableRoot).get(flags + (current.href || "")); + if (maybeNodes) { + for (var i = 0;i < maybeNodes.length; i++) + if (currentResource = maybeNodes[i], currentResource.getAttribute("href") === (current.href == null || current.href === "" ? null : current.href) && currentResource.getAttribute("rel") === (current.rel == null ? null : current.rel) && currentResource.getAttribute("title") === (current.title == null ? null : current.title) && currentResource.getAttribute("crossorigin") === (current.crossOrigin == null ? null : current.crossOrigin)) { + maybeNodes.splice(i, 1); + break b; + } + } + currentResource = hoistableRoot.createElement(flags); + setInitialProperties(currentResource, flags, current); + hoistableRoot.head.appendChild(currentResource); + break; + case "meta": + if (maybeNodes = getHydratableHoistableCache("meta", "content", hoistableRoot).get(flags + (current.content || ""))) { + for (i = 0;i < maybeNodes.length; i++) + if (currentResource = maybeNodes[i], currentResource.getAttribute("content") === (current.content == null ? null : "" + current.content) && currentResource.getAttribute("name") === (current.name == null ? null : current.name) && currentResource.getAttribute("property") === (current.property == null ? null : current.property) && currentResource.getAttribute("http-equiv") === (current.httpEquiv == null ? null : current.httpEquiv) && currentResource.getAttribute("charset") === (current.charSet == null ? null : current.charSet)) { + maybeNodes.splice(i, 1); + break b; + } + } + currentResource = hoistableRoot.createElement(flags); + setInitialProperties(currentResource, flags, current); + hoistableRoot.head.appendChild(currentResource); + break; + default: + throw Error(formatProdErrorMessage2(468, flags)); + } + currentResource[internalInstanceKey] = finishedWork; + markNodeAsHoistable(currentResource); + flags = currentResource; + } + finishedWork.stateNode = flags; + } else + mountHoistable(hoistableRoot, finishedWork.type, finishedWork.stateNode); + else + finishedWork.stateNode = acquireResource(hoistableRoot, flags, finishedWork.memoizedProps); + else + currentResource !== flags ? (currentResource === null ? current.stateNode !== null && (current = current.stateNode, current.parentNode.removeChild(current)) : currentResource.count--, flags === null ? mountHoistable(hoistableRoot, finishedWork.type, finishedWork.stateNode) : acquireResource(hoistableRoot, flags, finishedWork.memoizedProps)) : flags === null && finishedWork.stateNode !== null && commitHostUpdate(finishedWork, finishedWork.memoizedProps, current.memoizedProps); + } + break; + case 27: + recursivelyTraverseMutationEffects(root2, finishedWork); + commitReconciliationEffects(finishedWork); + flags & 512 && (offscreenSubtreeWasHidden || current === null || safelyDetachRef(current, current.return)); + current !== null && flags & 4 && commitHostUpdate(finishedWork, finishedWork.memoizedProps, current.memoizedProps); + break; + case 5: + recursivelyTraverseMutationEffects(root2, finishedWork); + commitReconciliationEffects(finishedWork); + flags & 512 && (offscreenSubtreeWasHidden || current === null || safelyDetachRef(current, current.return)); + if (finishedWork.flags & 32) { + hoistableRoot = finishedWork.stateNode; + try { + setTextContent(hoistableRoot, ""); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + } + flags & 4 && finishedWork.stateNode != null && (hoistableRoot = finishedWork.memoizedProps, commitHostUpdate(finishedWork, hoistableRoot, current !== null ? current.memoizedProps : hoistableRoot)); + flags & 1024 && (needsFormReset = true); + break; + case 6: + recursivelyTraverseMutationEffects(root2, finishedWork); + commitReconciliationEffects(finishedWork); + if (flags & 4) { + if (finishedWork.stateNode === null) + throw Error(formatProdErrorMessage2(162)); + flags = finishedWork.memoizedProps; + current = finishedWork.stateNode; + try { + current.nodeValue = flags; + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + } + break; + case 3: + tagCaches = null; + hoistableRoot = currentHoistableRoot; + currentHoistableRoot = getHoistableRoot(root2.containerInfo); + recursivelyTraverseMutationEffects(root2, finishedWork); + currentHoistableRoot = hoistableRoot; + commitReconciliationEffects(finishedWork); + if (flags & 4 && current !== null && current.memoizedState.isDehydrated) + try { + retryIfBlockedOn(root2.containerInfo); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + needsFormReset && (needsFormReset = false, recursivelyResetForms(finishedWork)); + break; + case 4: + flags = currentHoistableRoot; + currentHoistableRoot = getHoistableRoot(finishedWork.stateNode.containerInfo); + recursivelyTraverseMutationEffects(root2, finishedWork); + commitReconciliationEffects(finishedWork); + currentHoistableRoot = flags; + break; + case 12: + recursivelyTraverseMutationEffects(root2, finishedWork); + commitReconciliationEffects(finishedWork); + break; + case 31: + recursivelyTraverseMutationEffects(root2, finishedWork); + commitReconciliationEffects(finishedWork); + flags & 4 && (flags = finishedWork.updateQueue, flags !== null && (finishedWork.updateQueue = null, attachSuspenseRetryListeners(finishedWork, flags))); + break; + case 13: + recursivelyTraverseMutationEffects(root2, finishedWork); + commitReconciliationEffects(finishedWork); + finishedWork.child.flags & 8192 && finishedWork.memoizedState !== null !== (current !== null && current.memoizedState !== null) && (globalMostRecentFallbackTime = now()); + flags & 4 && (flags = finishedWork.updateQueue, flags !== null && (finishedWork.updateQueue = null, attachSuspenseRetryListeners(finishedWork, flags))); + break; + case 22: + hoistableRoot = finishedWork.memoizedState !== null; + var wasHidden = current !== null && current.memoizedState !== null, prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden, prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden; + offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden || hoistableRoot; + offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden || wasHidden; + recursivelyTraverseMutationEffects(root2, finishedWork); + offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden; + offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden; + commitReconciliationEffects(finishedWork); + if (flags & 8192) + a: + for (root2 = finishedWork.stateNode, root2._visibility = hoistableRoot ? root2._visibility & -2 : root2._visibility | 1, hoistableRoot && (current === null || wasHidden || offscreenSubtreeIsHidden || offscreenSubtreeWasHidden || recursivelyTraverseDisappearLayoutEffects(finishedWork)), current = null, root2 = finishedWork;; ) { + if (root2.tag === 5 || root2.tag === 26) { + if (current === null) { + wasHidden = current = root2; + try { + if (currentResource = wasHidden.stateNode, hoistableRoot) + maybeNodes = currentResource.style, typeof maybeNodes.setProperty === "function" ? maybeNodes.setProperty("display", "none", "important") : maybeNodes.display = "none"; + else { + i = wasHidden.stateNode; + var styleProp = wasHidden.memoizedProps.style, display = styleProp !== undefined && styleProp !== null && styleProp.hasOwnProperty("display") ? styleProp.display : null; + i.style.display = display == null || typeof display === "boolean" ? "" : ("" + display).trim(); + } + } catch (error) { + captureCommitPhaseError(wasHidden, wasHidden.return, error); + } + } + } else if (root2.tag === 6) { + if (current === null) { + wasHidden = root2; + try { + wasHidden.stateNode.nodeValue = hoistableRoot ? "" : wasHidden.memoizedProps; + } catch (error) { + captureCommitPhaseError(wasHidden, wasHidden.return, error); + } + } + } else if (root2.tag === 18) { + if (current === null) { + wasHidden = root2; + try { + var instance = wasHidden.stateNode; + hoistableRoot ? hideOrUnhideDehydratedBoundary(instance, true) : hideOrUnhideDehydratedBoundary(wasHidden.stateNode, false); + } catch (error) { + captureCommitPhaseError(wasHidden, wasHidden.return, error); + } + } + } else if ((root2.tag !== 22 && root2.tag !== 23 || root2.memoizedState === null || root2 === finishedWork) && root2.child !== null) { + root2.child.return = root2; + root2 = root2.child; + continue; + } + if (root2 === finishedWork) + break a; + for (;root2.sibling === null; ) { + if (root2.return === null || root2.return === finishedWork) + break a; + current === root2 && (current = null); + root2 = root2.return; + } + current === root2 && (current = null); + root2.sibling.return = root2.return; + root2 = root2.sibling; + } + flags & 4 && (flags = finishedWork.updateQueue, flags !== null && (current = flags.retryQueue, current !== null && (flags.retryQueue = null, attachSuspenseRetryListeners(finishedWork, current)))); + break; + case 19: + recursivelyTraverseMutationEffects(root2, finishedWork); + commitReconciliationEffects(finishedWork); + flags & 4 && (flags = finishedWork.updateQueue, flags !== null && (finishedWork.updateQueue = null, attachSuspenseRetryListeners(finishedWork, flags))); + break; + case 30: + break; + case 21: + break; + default: + recursivelyTraverseMutationEffects(root2, finishedWork), commitReconciliationEffects(finishedWork); + } +} +function commitReconciliationEffects(finishedWork) { + var flags = finishedWork.flags; + if (flags & 2) { + try { + for (var hostParentFiber, parentFiber = finishedWork.return;parentFiber !== null; ) { + if (isHostParent(parentFiber)) { + hostParentFiber = parentFiber; + break; + } + parentFiber = parentFiber.return; + } + if (hostParentFiber == null) + throw Error(formatProdErrorMessage2(160)); + switch (hostParentFiber.tag) { + case 27: + var parent = hostParentFiber.stateNode, before = getHostSibling(finishedWork); + insertOrAppendPlacementNode(finishedWork, before, parent); + break; + case 5: + var parent$141 = hostParentFiber.stateNode; + hostParentFiber.flags & 32 && (setTextContent(parent$141, ""), hostParentFiber.flags &= -33); + var before$142 = getHostSibling(finishedWork); + insertOrAppendPlacementNode(finishedWork, before$142, parent$141); + break; + case 3: + case 4: + var parent$143 = hostParentFiber.stateNode.containerInfo, before$144 = getHostSibling(finishedWork); + insertOrAppendPlacementNodeIntoContainer(finishedWork, before$144, parent$143); + break; + default: + throw Error(formatProdErrorMessage2(161)); + } + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + finishedWork.flags &= -3; + } + flags & 4096 && (finishedWork.flags &= -4097); +} +function recursivelyResetForms(parentFiber) { + if (parentFiber.subtreeFlags & 1024) + for (parentFiber = parentFiber.child;parentFiber !== null; ) { + var fiber = parentFiber; + recursivelyResetForms(fiber); + fiber.tag === 5 && fiber.flags & 1024 && fiber.stateNode.reset(); + parentFiber = parentFiber.sibling; + } +} +function recursivelyTraverseLayoutEffects(root2, parentFiber) { + if (parentFiber.subtreeFlags & 8772) + for (parentFiber = parentFiber.child;parentFiber !== null; ) + commitLayoutEffectOnFiber(root2, parentFiber.alternate, parentFiber), parentFiber = parentFiber.sibling; +} +function recursivelyTraverseDisappearLayoutEffects(parentFiber) { + for (parentFiber = parentFiber.child;parentFiber !== null; ) { + var finishedWork = parentFiber; + switch (finishedWork.tag) { + case 0: + case 11: + case 14: + case 15: + commitHookEffectListUnmount(4, finishedWork, finishedWork.return); + recursivelyTraverseDisappearLayoutEffects(finishedWork); + break; + case 1: + safelyDetachRef(finishedWork, finishedWork.return); + var instance = finishedWork.stateNode; + typeof instance.componentWillUnmount === "function" && safelyCallComponentWillUnmount(finishedWork, finishedWork.return, instance); + recursivelyTraverseDisappearLayoutEffects(finishedWork); + break; + case 27: + releaseSingletonInstance(finishedWork.stateNode); + case 26: + case 5: + safelyDetachRef(finishedWork, finishedWork.return); + recursivelyTraverseDisappearLayoutEffects(finishedWork); + break; + case 22: + finishedWork.memoizedState === null && recursivelyTraverseDisappearLayoutEffects(finishedWork); + break; + case 30: + recursivelyTraverseDisappearLayoutEffects(finishedWork); + break; + default: + recursivelyTraverseDisappearLayoutEffects(finishedWork); + } + parentFiber = parentFiber.sibling; + } +} +function recursivelyTraverseReappearLayoutEffects(finishedRoot$jscomp$0, parentFiber, includeWorkInProgressEffects) { + includeWorkInProgressEffects = includeWorkInProgressEffects && (parentFiber.subtreeFlags & 8772) !== 0; + for (parentFiber = parentFiber.child;parentFiber !== null; ) { + var current = parentFiber.alternate, finishedRoot = finishedRoot$jscomp$0, finishedWork = parentFiber, flags = finishedWork.flags; + switch (finishedWork.tag) { + case 0: + case 11: + case 15: + recursivelyTraverseReappearLayoutEffects(finishedRoot, finishedWork, includeWorkInProgressEffects); + commitHookEffectListMount(4, finishedWork); + break; + case 1: + recursivelyTraverseReappearLayoutEffects(finishedRoot, finishedWork, includeWorkInProgressEffects); + current = finishedWork; + finishedRoot = current.stateNode; + if (typeof finishedRoot.componentDidMount === "function") + try { + finishedRoot.componentDidMount(); + } catch (error) { + captureCommitPhaseError(current, current.return, error); + } + current = finishedWork; + finishedRoot = current.updateQueue; + if (finishedRoot !== null) { + var instance = current.stateNode; + try { + var hiddenCallbacks = finishedRoot.shared.hiddenCallbacks; + if (hiddenCallbacks !== null) + for (finishedRoot.shared.hiddenCallbacks = null, finishedRoot = 0;finishedRoot < hiddenCallbacks.length; finishedRoot++) + callCallback(hiddenCallbacks[finishedRoot], instance); + } catch (error) { + captureCommitPhaseError(current, current.return, error); + } + } + includeWorkInProgressEffects && flags & 64 && commitClassCallbacks(finishedWork); + safelyAttachRef(finishedWork, finishedWork.return); + break; + case 27: + commitHostSingletonAcquisition(finishedWork); + case 26: + case 5: + recursivelyTraverseReappearLayoutEffects(finishedRoot, finishedWork, includeWorkInProgressEffects); + includeWorkInProgressEffects && current === null && flags & 4 && commitHostMount(finishedWork); + safelyAttachRef(finishedWork, finishedWork.return); + break; + case 12: + recursivelyTraverseReappearLayoutEffects(finishedRoot, finishedWork, includeWorkInProgressEffects); + break; + case 31: + recursivelyTraverseReappearLayoutEffects(finishedRoot, finishedWork, includeWorkInProgressEffects); + includeWorkInProgressEffects && flags & 4 && commitActivityHydrationCallbacks(finishedRoot, finishedWork); + break; + case 13: + recursivelyTraverseReappearLayoutEffects(finishedRoot, finishedWork, includeWorkInProgressEffects); + includeWorkInProgressEffects && flags & 4 && commitSuspenseHydrationCallbacks(finishedRoot, finishedWork); + break; + case 22: + finishedWork.memoizedState === null && recursivelyTraverseReappearLayoutEffects(finishedRoot, finishedWork, includeWorkInProgressEffects); + safelyAttachRef(finishedWork, finishedWork.return); + break; + case 30: + break; + default: + recursivelyTraverseReappearLayoutEffects(finishedRoot, finishedWork, includeWorkInProgressEffects); + } + parentFiber = parentFiber.sibling; + } +} +function commitOffscreenPassiveMountEffects(current, finishedWork) { + var previousCache = null; + current !== null && current.memoizedState !== null && current.memoizedState.cachePool !== null && (previousCache = current.memoizedState.cachePool.pool); + current = null; + finishedWork.memoizedState !== null && finishedWork.memoizedState.cachePool !== null && (current = finishedWork.memoizedState.cachePool.pool); + current !== previousCache && (current != null && current.refCount++, previousCache != null && releaseCache(previousCache)); +} +function commitCachePassiveMountEffect(current, finishedWork) { + current = null; + finishedWork.alternate !== null && (current = finishedWork.alternate.memoizedState.cache); + finishedWork = finishedWork.memoizedState.cache; + finishedWork !== current && (finishedWork.refCount++, current != null && releaseCache(current)); +} +function recursivelyTraversePassiveMountEffects(root2, parentFiber, committedLanes, committedTransitions) { + if (parentFiber.subtreeFlags & 10256) + for (parentFiber = parentFiber.child;parentFiber !== null; ) + commitPassiveMountOnFiber(root2, parentFiber, committedLanes, committedTransitions), parentFiber = parentFiber.sibling; +} +function commitPassiveMountOnFiber(finishedRoot, finishedWork, committedLanes, committedTransitions) { + var flags = finishedWork.flags; + switch (finishedWork.tag) { + case 0: + case 11: + case 15: + recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork, committedLanes, committedTransitions); + flags & 2048 && commitHookEffectListMount(9, finishedWork); + break; + case 1: + recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork, committedLanes, committedTransitions); + break; + case 3: + recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork, committedLanes, committedTransitions); + flags & 2048 && (finishedRoot = null, finishedWork.alternate !== null && (finishedRoot = finishedWork.alternate.memoizedState.cache), finishedWork = finishedWork.memoizedState.cache, finishedWork !== finishedRoot && (finishedWork.refCount++, finishedRoot != null && releaseCache(finishedRoot))); + break; + case 12: + if (flags & 2048) { + recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork, committedLanes, committedTransitions); + finishedRoot = finishedWork.stateNode; + try { + var _finishedWork$memoize2 = finishedWork.memoizedProps, id = _finishedWork$memoize2.id, onPostCommit = _finishedWork$memoize2.onPostCommit; + typeof onPostCommit === "function" && onPostCommit(id, finishedWork.alternate === null ? "mount" : "update", finishedRoot.passiveEffectDuration, -0); + } catch (error) { + captureCommitPhaseError(finishedWork, finishedWork.return, error); + } + } else + recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork, committedLanes, committedTransitions); + break; + case 31: + recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork, committedLanes, committedTransitions); + break; + case 13: + recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork, committedLanes, committedTransitions); + break; + case 23: + break; + case 22: + _finishedWork$memoize2 = finishedWork.stateNode; + id = finishedWork.alternate; + finishedWork.memoizedState !== null ? _finishedWork$memoize2._visibility & 2 ? recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork, committedLanes, committedTransitions) : recursivelyTraverseAtomicPassiveEffects(finishedRoot, finishedWork) : _finishedWork$memoize2._visibility & 2 ? recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork, committedLanes, committedTransitions) : (_finishedWork$memoize2._visibility |= 2, recursivelyTraverseReconnectPassiveEffects(finishedRoot, finishedWork, committedLanes, committedTransitions, (finishedWork.subtreeFlags & 10256) !== 0 || false)); + flags & 2048 && commitOffscreenPassiveMountEffects(id, finishedWork); + break; + case 24: + recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork, committedLanes, committedTransitions); + flags & 2048 && commitCachePassiveMountEffect(finishedWork.alternate, finishedWork); + break; + default: + recursivelyTraversePassiveMountEffects(finishedRoot, finishedWork, committedLanes, committedTransitions); + } +} +function recursivelyTraverseReconnectPassiveEffects(finishedRoot$jscomp$0, parentFiber, committedLanes$jscomp$0, committedTransitions$jscomp$0, includeWorkInProgressEffects) { + includeWorkInProgressEffects = includeWorkInProgressEffects && ((parentFiber.subtreeFlags & 10256) !== 0 || false); + for (parentFiber = parentFiber.child;parentFiber !== null; ) { + var finishedRoot = finishedRoot$jscomp$0, finishedWork = parentFiber, committedLanes = committedLanes$jscomp$0, committedTransitions = committedTransitions$jscomp$0, flags = finishedWork.flags; + switch (finishedWork.tag) { + case 0: + case 11: + case 15: + recursivelyTraverseReconnectPassiveEffects(finishedRoot, finishedWork, committedLanes, committedTransitions, includeWorkInProgressEffects); + commitHookEffectListMount(8, finishedWork); + break; + case 23: + break; + case 22: + var instance = finishedWork.stateNode; + finishedWork.memoizedState !== null ? instance._visibility & 2 ? recursivelyTraverseReconnectPassiveEffects(finishedRoot, finishedWork, committedLanes, committedTransitions, includeWorkInProgressEffects) : recursivelyTraverseAtomicPassiveEffects(finishedRoot, finishedWork) : (instance._visibility |= 2, recursivelyTraverseReconnectPassiveEffects(finishedRoot, finishedWork, committedLanes, committedTransitions, includeWorkInProgressEffects)); + includeWorkInProgressEffects && flags & 2048 && commitOffscreenPassiveMountEffects(finishedWork.alternate, finishedWork); + break; + case 24: + recursivelyTraverseReconnectPassiveEffects(finishedRoot, finishedWork, committedLanes, committedTransitions, includeWorkInProgressEffects); + includeWorkInProgressEffects && flags & 2048 && commitCachePassiveMountEffect(finishedWork.alternate, finishedWork); + break; + default: + recursivelyTraverseReconnectPassiveEffects(finishedRoot, finishedWork, committedLanes, committedTransitions, includeWorkInProgressEffects); + } + parentFiber = parentFiber.sibling; + } +} +function recursivelyTraverseAtomicPassiveEffects(finishedRoot$jscomp$0, parentFiber) { + if (parentFiber.subtreeFlags & 10256) + for (parentFiber = parentFiber.child;parentFiber !== null; ) { + var finishedRoot = finishedRoot$jscomp$0, finishedWork = parentFiber, flags = finishedWork.flags; + switch (finishedWork.tag) { + case 22: + recursivelyTraverseAtomicPassiveEffects(finishedRoot, finishedWork); + flags & 2048 && commitOffscreenPassiveMountEffects(finishedWork.alternate, finishedWork); + break; + case 24: + recursivelyTraverseAtomicPassiveEffects(finishedRoot, finishedWork); + flags & 2048 && commitCachePassiveMountEffect(finishedWork.alternate, finishedWork); + break; + default: + recursivelyTraverseAtomicPassiveEffects(finishedRoot, finishedWork); + } + parentFiber = parentFiber.sibling; + } +} +function recursivelyAccumulateSuspenseyCommit(parentFiber, committedLanes, suspendedState) { + if (parentFiber.subtreeFlags & suspenseyCommitFlag) + for (parentFiber = parentFiber.child;parentFiber !== null; ) + accumulateSuspenseyCommitOnFiber(parentFiber, committedLanes, suspendedState), parentFiber = parentFiber.sibling; +} +function accumulateSuspenseyCommitOnFiber(fiber, committedLanes, suspendedState) { + switch (fiber.tag) { + case 26: + recursivelyAccumulateSuspenseyCommit(fiber, committedLanes, suspendedState); + fiber.flags & suspenseyCommitFlag && fiber.memoizedState !== null && suspendResource(suspendedState, currentHoistableRoot, fiber.memoizedState, fiber.memoizedProps); + break; + case 5: + recursivelyAccumulateSuspenseyCommit(fiber, committedLanes, suspendedState); + break; + case 3: + case 4: + var previousHoistableRoot = currentHoistableRoot; + currentHoistableRoot = getHoistableRoot(fiber.stateNode.containerInfo); + recursivelyAccumulateSuspenseyCommit(fiber, committedLanes, suspendedState); + currentHoistableRoot = previousHoistableRoot; + break; + case 22: + fiber.memoizedState === null && (previousHoistableRoot = fiber.alternate, previousHoistableRoot !== null && previousHoistableRoot.memoizedState !== null ? (previousHoistableRoot = suspenseyCommitFlag, suspenseyCommitFlag = 16777216, recursivelyAccumulateSuspenseyCommit(fiber, committedLanes, suspendedState), suspenseyCommitFlag = previousHoistableRoot) : recursivelyAccumulateSuspenseyCommit(fiber, committedLanes, suspendedState)); + break; + default: + recursivelyAccumulateSuspenseyCommit(fiber, committedLanes, suspendedState); + } +} +function detachAlternateSiblings(parentFiber) { + var previousFiber = parentFiber.alternate; + if (previousFiber !== null && (parentFiber = previousFiber.child, parentFiber !== null)) { + previousFiber.child = null; + do + previousFiber = parentFiber.sibling, parentFiber.sibling = null, parentFiber = previousFiber; + while (parentFiber !== null); + } +} +function recursivelyTraversePassiveUnmountEffects(parentFiber) { + var deletions = parentFiber.deletions; + if ((parentFiber.flags & 16) !== 0) { + if (deletions !== null) + for (var i = 0;i < deletions.length; i++) { + var childToDelete = deletions[i]; + nextEffect = childToDelete; + commitPassiveUnmountEffectsInsideOfDeletedTree_begin(childToDelete, parentFiber); + } + detachAlternateSiblings(parentFiber); + } + if (parentFiber.subtreeFlags & 10256) + for (parentFiber = parentFiber.child;parentFiber !== null; ) + commitPassiveUnmountOnFiber(parentFiber), parentFiber = parentFiber.sibling; +} +function commitPassiveUnmountOnFiber(finishedWork) { + switch (finishedWork.tag) { + case 0: + case 11: + case 15: + recursivelyTraversePassiveUnmountEffects(finishedWork); + finishedWork.flags & 2048 && commitHookEffectListUnmount(9, finishedWork, finishedWork.return); + break; + case 3: + recursivelyTraversePassiveUnmountEffects(finishedWork); + break; + case 12: + recursivelyTraversePassiveUnmountEffects(finishedWork); + break; + case 22: + var instance = finishedWork.stateNode; + finishedWork.memoizedState !== null && instance._visibility & 2 && (finishedWork.return === null || finishedWork.return.tag !== 13) ? (instance._visibility &= -3, recursivelyTraverseDisconnectPassiveEffects(finishedWork)) : recursivelyTraversePassiveUnmountEffects(finishedWork); + break; + default: + recursivelyTraversePassiveUnmountEffects(finishedWork); + } +} +function recursivelyTraverseDisconnectPassiveEffects(parentFiber) { + var deletions = parentFiber.deletions; + if ((parentFiber.flags & 16) !== 0) { + if (deletions !== null) + for (var i = 0;i < deletions.length; i++) { + var childToDelete = deletions[i]; + nextEffect = childToDelete; + commitPassiveUnmountEffectsInsideOfDeletedTree_begin(childToDelete, parentFiber); + } + detachAlternateSiblings(parentFiber); + } + for (parentFiber = parentFiber.child;parentFiber !== null; ) { + deletions = parentFiber; + switch (deletions.tag) { + case 0: + case 11: + case 15: + commitHookEffectListUnmount(8, deletions, deletions.return); + recursivelyTraverseDisconnectPassiveEffects(deletions); + break; + case 22: + i = deletions.stateNode; + i._visibility & 2 && (i._visibility &= -3, recursivelyTraverseDisconnectPassiveEffects(deletions)); + break; + default: + recursivelyTraverseDisconnectPassiveEffects(deletions); + } + parentFiber = parentFiber.sibling; + } +} +function commitPassiveUnmountEffectsInsideOfDeletedTree_begin(deletedSubtreeRoot, nearestMountedAncestor) { + for (;nextEffect !== null; ) { + var fiber = nextEffect; + switch (fiber.tag) { + case 0: + case 11: + case 15: + commitHookEffectListUnmount(8, fiber, nearestMountedAncestor); + break; + case 23: + case 22: + if (fiber.memoizedState !== null && fiber.memoizedState.cachePool !== null) { + var cache = fiber.memoizedState.cachePool.pool; + cache != null && cache.refCount++; + } + break; + case 24: + releaseCache(fiber.memoizedState.cache); + } + cache = fiber.child; + if (cache !== null) + cache.return = fiber, nextEffect = cache; + else + a: + for (fiber = deletedSubtreeRoot;nextEffect !== null; ) { + cache = nextEffect; + var { sibling, return: returnFiber } = cache; + detachFiberAfterEffects(cache); + if (cache === fiber) { + nextEffect = null; + break a; + } + if (sibling !== null) { + sibling.return = returnFiber; + nextEffect = sibling; + break a; + } + nextEffect = returnFiber; + } + } +} +function requestUpdateLane() { + return (executionContext & 2) !== 0 && workInProgressRootRenderLanes !== 0 ? workInProgressRootRenderLanes & -workInProgressRootRenderLanes : ReactSharedInternals3.T !== null ? requestTransitionLane() : resolveUpdatePriority(); +} +function requestDeferredLane() { + if (workInProgressDeferredLane === 0) + if ((workInProgressRootRenderLanes & 536870912) === 0 || isHydrating) { + var lane = nextTransitionDeferredLane; + nextTransitionDeferredLane <<= 1; + (nextTransitionDeferredLane & 3932160) === 0 && (nextTransitionDeferredLane = 262144); + workInProgressDeferredLane = lane; + } else + workInProgressDeferredLane = 536870912; + lane = suspenseHandlerStackCursor.current; + lane !== null && (lane.flags |= 32); + return workInProgressDeferredLane; +} +function scheduleUpdateOnFiber(root2, fiber, lane) { + if (root2 === workInProgressRoot && (workInProgressSuspendedReason === 2 || workInProgressSuspendedReason === 9) || root2.cancelPendingCommit !== null) + prepareFreshStack(root2, 0), markRootSuspended(root2, workInProgressRootRenderLanes, workInProgressDeferredLane, false); + markRootUpdated$1(root2, lane); + if ((executionContext & 2) === 0 || root2 !== workInProgressRoot) + root2 === workInProgressRoot && ((executionContext & 2) === 0 && (workInProgressRootInterleavedUpdatedLanes |= lane), workInProgressRootExitStatus === 4 && markRootSuspended(root2, workInProgressRootRenderLanes, workInProgressDeferredLane, false)), ensureRootIsScheduled(root2); +} +function performWorkOnRoot(root$jscomp$0, lanes, forceSync) { + if ((executionContext & 6) !== 0) + throw Error(formatProdErrorMessage2(327)); + var shouldTimeSlice = !forceSync && (lanes & 127) === 0 && (lanes & root$jscomp$0.expiredLanes) === 0 || checkIfRootIsPrerendering(root$jscomp$0, lanes), exitStatus = shouldTimeSlice ? renderRootConcurrent(root$jscomp$0, lanes) : renderRootSync(root$jscomp$0, lanes, true), renderWasConcurrent = shouldTimeSlice; + do { + if (exitStatus === 0) { + workInProgressRootIsPrerendering && !shouldTimeSlice && markRootSuspended(root$jscomp$0, lanes, 0, false); + break; + } else { + forceSync = root$jscomp$0.current.alternate; + if (renderWasConcurrent && !isRenderConsistentWithExternalStores(forceSync)) { + exitStatus = renderRootSync(root$jscomp$0, lanes, false); + renderWasConcurrent = false; + continue; + } + if (exitStatus === 2) { + renderWasConcurrent = lanes; + if (root$jscomp$0.errorRecoveryDisabledLanes & renderWasConcurrent) + var JSCompiler_inline_result = 0; + else + JSCompiler_inline_result = root$jscomp$0.pendingLanes & -536870913, JSCompiler_inline_result = JSCompiler_inline_result !== 0 ? JSCompiler_inline_result : JSCompiler_inline_result & 536870912 ? 536870912 : 0; + if (JSCompiler_inline_result !== 0) { + lanes = JSCompiler_inline_result; + a: { + var root2 = root$jscomp$0; + exitStatus = workInProgressRootConcurrentErrors; + var wasRootDehydrated = root2.current.memoizedState.isDehydrated; + wasRootDehydrated && (prepareFreshStack(root2, JSCompiler_inline_result).flags |= 256); + JSCompiler_inline_result = renderRootSync(root2, JSCompiler_inline_result, false); + if (JSCompiler_inline_result !== 2) { + if (workInProgressRootDidAttachPingListener && !wasRootDehydrated) { + root2.errorRecoveryDisabledLanes |= renderWasConcurrent; + workInProgressRootInterleavedUpdatedLanes |= renderWasConcurrent; + exitStatus = 4; + break a; + } + renderWasConcurrent = workInProgressRootRecoverableErrors; + workInProgressRootRecoverableErrors = exitStatus; + renderWasConcurrent !== null && (workInProgressRootRecoverableErrors === null ? workInProgressRootRecoverableErrors = renderWasConcurrent : workInProgressRootRecoverableErrors.push.apply(workInProgressRootRecoverableErrors, renderWasConcurrent)); + } + exitStatus = JSCompiler_inline_result; + } + renderWasConcurrent = false; + if (exitStatus !== 2) + continue; + } + } + if (exitStatus === 1) { + prepareFreshStack(root$jscomp$0, 0); + markRootSuspended(root$jscomp$0, lanes, 0, true); + break; + } + a: { + shouldTimeSlice = root$jscomp$0; + renderWasConcurrent = exitStatus; + switch (renderWasConcurrent) { + case 0: + case 1: + throw Error(formatProdErrorMessage2(345)); + case 4: + if ((lanes & 4194048) !== lanes) + break; + case 6: + markRootSuspended(shouldTimeSlice, lanes, workInProgressDeferredLane, !workInProgressRootDidSkipSuspendedSiblings); + break a; + case 2: + workInProgressRootRecoverableErrors = null; + break; + case 3: + case 5: + break; + default: + throw Error(formatProdErrorMessage2(329)); + } + if ((lanes & 62914560) === lanes && (exitStatus = globalMostRecentFallbackTime + 300 - now(), 10 < exitStatus)) { + markRootSuspended(shouldTimeSlice, lanes, workInProgressDeferredLane, !workInProgressRootDidSkipSuspendedSiblings); + if (getNextLanes(shouldTimeSlice, 0, true) !== 0) + break a; + pendingEffectsLanes = lanes; + shouldTimeSlice.timeoutHandle = scheduleTimeout(commitRootWhenReady.bind(null, shouldTimeSlice, forceSync, workInProgressRootRecoverableErrors, workInProgressTransitions, workInProgressRootDidIncludeRecursiveRenderUpdate, lanes, workInProgressDeferredLane, workInProgressRootInterleavedUpdatedLanes, workInProgressSuspendedRetryLanes, workInProgressRootDidSkipSuspendedSiblings, renderWasConcurrent, "Throttled", -0, 0), exitStatus); + break a; + } + commitRootWhenReady(shouldTimeSlice, forceSync, workInProgressRootRecoverableErrors, workInProgressTransitions, workInProgressRootDidIncludeRecursiveRenderUpdate, lanes, workInProgressDeferredLane, workInProgressRootInterleavedUpdatedLanes, workInProgressSuspendedRetryLanes, workInProgressRootDidSkipSuspendedSiblings, renderWasConcurrent, null, -0, 0); + } + } + break; + } while (1); + ensureRootIsScheduled(root$jscomp$0); +} +function commitRootWhenReady(root2, finishedWork, recoverableErrors, transitions, didIncludeRenderPhaseUpdate, lanes, spawnedLane, updatedLanes, suspendedRetryLanes, didSkipSuspendedSiblings, exitStatus, suspendedCommitReason, completedRenderStartTime, completedRenderEndTime) { + root2.timeoutHandle = -1; + suspendedCommitReason = finishedWork.subtreeFlags; + if (suspendedCommitReason & 8192 || (suspendedCommitReason & 16785408) === 16785408) { + suspendedCommitReason = { + stylesheets: null, + count: 0, + imgCount: 0, + imgBytes: 0, + suspenseyImages: [], + waitingForImages: true, + waitingForViewTransition: false, + unsuspend: noop$1 + }; + accumulateSuspenseyCommitOnFiber(finishedWork, lanes, suspendedCommitReason); + var timeoutOffset = (lanes & 62914560) === lanes ? globalMostRecentFallbackTime - now() : (lanes & 4194048) === lanes ? globalMostRecentTransitionTime - now() : 0; + timeoutOffset = waitForCommitToBeReady(suspendedCommitReason, timeoutOffset); + if (timeoutOffset !== null) { + pendingEffectsLanes = lanes; + root2.cancelPendingCommit = timeoutOffset(commitRoot.bind(null, root2, finishedWork, lanes, recoverableErrors, transitions, didIncludeRenderPhaseUpdate, spawnedLane, updatedLanes, suspendedRetryLanes, exitStatus, suspendedCommitReason, null, completedRenderStartTime, completedRenderEndTime)); + markRootSuspended(root2, lanes, spawnedLane, !didSkipSuspendedSiblings); + return; + } + } + commitRoot(root2, finishedWork, lanes, recoverableErrors, transitions, didIncludeRenderPhaseUpdate, spawnedLane, updatedLanes, suspendedRetryLanes); +} +function isRenderConsistentWithExternalStores(finishedWork) { + for (var node = finishedWork;; ) { + var tag = node.tag; + if ((tag === 0 || tag === 11 || tag === 15) && node.flags & 16384 && (tag = node.updateQueue, tag !== null && (tag = tag.stores, tag !== null))) + for (var i = 0;i < tag.length; i++) { + var check = tag[i], getSnapshot = check.getSnapshot; + check = check.value; + try { + if (!objectIs(getSnapshot(), check)) + return false; + } catch (error) { + return false; + } + } + tag = node.child; + if (node.subtreeFlags & 16384 && tag !== null) + tag.return = node, node = tag; + else { + if (node === finishedWork) + break; + for (;node.sibling === null; ) { + if (node.return === null || node.return === finishedWork) + return true; + node = node.return; + } + node.sibling.return = node.return; + node = node.sibling; + } + } + return true; +} +function markRootSuspended(root2, suspendedLanes, spawnedLane, didAttemptEntireTree) { + suspendedLanes &= ~workInProgressRootPingedLanes; + suspendedLanes &= ~workInProgressRootInterleavedUpdatedLanes; + root2.suspendedLanes |= suspendedLanes; + root2.pingedLanes &= ~suspendedLanes; + didAttemptEntireTree && (root2.warmLanes |= suspendedLanes); + didAttemptEntireTree = root2.expirationTimes; + for (var lanes = suspendedLanes;0 < lanes; ) { + var index$6 = 31 - clz32(lanes), lane = 1 << index$6; + didAttemptEntireTree[index$6] = -1; + lanes &= ~lane; + } + spawnedLane !== 0 && markSpawnedDeferredLane(root2, spawnedLane, suspendedLanes); +} +function flushSyncWork$1() { + return (executionContext & 6) === 0 ? (flushSyncWorkAcrossRoots_impl(0, false), false) : true; +} +function resetWorkInProgressStack() { + if (workInProgress !== null) { + if (workInProgressSuspendedReason === 0) + var interruptedWork = workInProgress.return; + else + interruptedWork = workInProgress, lastContextDependency = currentlyRenderingFiber$1 = null, resetHooksOnUnwind(interruptedWork), thenableState$1 = null, thenableIndexCounter$1 = 0, interruptedWork = workInProgress; + for (;interruptedWork !== null; ) + unwindInterruptedWork(interruptedWork.alternate, interruptedWork), interruptedWork = interruptedWork.return; + workInProgress = null; + } +} +function prepareFreshStack(root2, lanes) { + var timeoutHandle = root2.timeoutHandle; + timeoutHandle !== -1 && (root2.timeoutHandle = -1, cancelTimeout(timeoutHandle)); + timeoutHandle = root2.cancelPendingCommit; + timeoutHandle !== null && (root2.cancelPendingCommit = null, timeoutHandle()); + pendingEffectsLanes = 0; + resetWorkInProgressStack(); + workInProgressRoot = root2; + workInProgress = timeoutHandle = createWorkInProgress(root2.current, null); + workInProgressRootRenderLanes = lanes; + workInProgressSuspendedReason = 0; + workInProgressThrownValue = null; + workInProgressRootDidSkipSuspendedSiblings = false; + workInProgressRootIsPrerendering = checkIfRootIsPrerendering(root2, lanes); + workInProgressRootDidAttachPingListener = false; + workInProgressSuspendedRetryLanes = workInProgressDeferredLane = workInProgressRootPingedLanes = workInProgressRootInterleavedUpdatedLanes = workInProgressRootSkippedLanes = workInProgressRootExitStatus = 0; + workInProgressRootRecoverableErrors = workInProgressRootConcurrentErrors = null; + workInProgressRootDidIncludeRecursiveRenderUpdate = false; + (lanes & 8) !== 0 && (lanes |= lanes & 32); + var allEntangledLanes = root2.entangledLanes; + if (allEntangledLanes !== 0) + for (root2 = root2.entanglements, allEntangledLanes &= lanes;0 < allEntangledLanes; ) { + var index$4 = 31 - clz32(allEntangledLanes), lane = 1 << index$4; + lanes |= root2[index$4]; + allEntangledLanes &= ~lane; + } + entangledRenderLanes = lanes; + finishQueueingConcurrentUpdates(); + return timeoutHandle; +} +function handleThrow(root2, thrownValue) { + currentlyRenderingFiber = null; + ReactSharedInternals3.H = ContextOnlyDispatcher; + thrownValue === SuspenseException || thrownValue === SuspenseActionException ? (thrownValue = getSuspendedThenable(), workInProgressSuspendedReason = 3) : thrownValue === SuspenseyCommitException ? (thrownValue = getSuspendedThenable(), workInProgressSuspendedReason = 4) : workInProgressSuspendedReason = thrownValue === SelectiveHydrationException ? 8 : thrownValue !== null && typeof thrownValue === "object" && typeof thrownValue.then === "function" ? 6 : 1; + workInProgressThrownValue = thrownValue; + workInProgress === null && (workInProgressRootExitStatus = 1, logUncaughtError(root2, createCapturedValueAtFiber(thrownValue, root2.current))); +} +function shouldRemainOnPreviousScreen() { + var handler = suspenseHandlerStackCursor.current; + return handler === null ? true : (workInProgressRootRenderLanes & 4194048) === workInProgressRootRenderLanes ? shellBoundary === null ? true : false : (workInProgressRootRenderLanes & 62914560) === workInProgressRootRenderLanes || (workInProgressRootRenderLanes & 536870912) !== 0 ? handler === shellBoundary : false; +} +function pushDispatcher() { + var prevDispatcher = ReactSharedInternals3.H; + ReactSharedInternals3.H = ContextOnlyDispatcher; + return prevDispatcher === null ? ContextOnlyDispatcher : prevDispatcher; +} +function pushAsyncDispatcher() { + var prevAsyncDispatcher = ReactSharedInternals3.A; + ReactSharedInternals3.A = DefaultAsyncDispatcher; + return prevAsyncDispatcher; +} +function renderDidSuspendDelayIfPossible() { + workInProgressRootExitStatus = 4; + workInProgressRootDidSkipSuspendedSiblings || (workInProgressRootRenderLanes & 4194048) !== workInProgressRootRenderLanes && suspenseHandlerStackCursor.current !== null || (workInProgressRootIsPrerendering = true); + (workInProgressRootSkippedLanes & 134217727) === 0 && (workInProgressRootInterleavedUpdatedLanes & 134217727) === 0 || workInProgressRoot === null || markRootSuspended(workInProgressRoot, workInProgressRootRenderLanes, workInProgressDeferredLane, false); +} +function renderRootSync(root2, lanes, shouldYieldForPrerendering) { + var prevExecutionContext = executionContext; + executionContext |= 2; + var prevDispatcher = pushDispatcher(), prevAsyncDispatcher = pushAsyncDispatcher(); + if (workInProgressRoot !== root2 || workInProgressRootRenderLanes !== lanes) + workInProgressTransitions = null, prepareFreshStack(root2, lanes); + lanes = false; + var exitStatus = workInProgressRootExitStatus; + a: + do + try { + if (workInProgressSuspendedReason !== 0 && workInProgress !== null) { + var unitOfWork = workInProgress, thrownValue = workInProgressThrownValue; + switch (workInProgressSuspendedReason) { + case 8: + resetWorkInProgressStack(); + exitStatus = 6; + break a; + case 3: + case 2: + case 9: + case 6: + suspenseHandlerStackCursor.current === null && (lanes = true); + var reason = workInProgressSuspendedReason; + workInProgressSuspendedReason = 0; + workInProgressThrownValue = null; + throwAndUnwindWorkLoop(root2, unitOfWork, thrownValue, reason); + if (shouldYieldForPrerendering && workInProgressRootIsPrerendering) { + exitStatus = 0; + break a; + } + break; + default: + reason = workInProgressSuspendedReason, workInProgressSuspendedReason = 0, workInProgressThrownValue = null, throwAndUnwindWorkLoop(root2, unitOfWork, thrownValue, reason); + } + } + workLoopSync(); + exitStatus = workInProgressRootExitStatus; + break; + } catch (thrownValue$165) { + handleThrow(root2, thrownValue$165); + } + while (1); + lanes && root2.shellSuspendCounter++; + lastContextDependency = currentlyRenderingFiber$1 = null; + executionContext = prevExecutionContext; + ReactSharedInternals3.H = prevDispatcher; + ReactSharedInternals3.A = prevAsyncDispatcher; + workInProgress === null && (workInProgressRoot = null, workInProgressRootRenderLanes = 0, finishQueueingConcurrentUpdates()); + return exitStatus; +} +function workLoopSync() { + for (;workInProgress !== null; ) + performUnitOfWork(workInProgress); +} +function renderRootConcurrent(root2, lanes) { + var prevExecutionContext = executionContext; + executionContext |= 2; + var prevDispatcher = pushDispatcher(), prevAsyncDispatcher = pushAsyncDispatcher(); + workInProgressRoot !== root2 || workInProgressRootRenderLanes !== lanes ? (workInProgressTransitions = null, workInProgressRootRenderTargetTime = now() + 500, prepareFreshStack(root2, lanes)) : workInProgressRootIsPrerendering = checkIfRootIsPrerendering(root2, lanes); + a: + do + try { + if (workInProgressSuspendedReason !== 0 && workInProgress !== null) { + lanes = workInProgress; + var thrownValue = workInProgressThrownValue; + b: + switch (workInProgressSuspendedReason) { + case 1: + workInProgressSuspendedReason = 0; + workInProgressThrownValue = null; + throwAndUnwindWorkLoop(root2, lanes, thrownValue, 1); + break; + case 2: + case 9: + if (isThenableResolved(thrownValue)) { + workInProgressSuspendedReason = 0; + workInProgressThrownValue = null; + replaySuspendedUnitOfWork(lanes); + break; + } + lanes = function() { + workInProgressSuspendedReason !== 2 && workInProgressSuspendedReason !== 9 || workInProgressRoot !== root2 || (workInProgressSuspendedReason = 7); + ensureRootIsScheduled(root2); + }; + thrownValue.then(lanes, lanes); + break a; + case 3: + workInProgressSuspendedReason = 7; + break a; + case 4: + workInProgressSuspendedReason = 5; + break a; + case 7: + isThenableResolved(thrownValue) ? (workInProgressSuspendedReason = 0, workInProgressThrownValue = null, replaySuspendedUnitOfWork(lanes)) : (workInProgressSuspendedReason = 0, workInProgressThrownValue = null, throwAndUnwindWorkLoop(root2, lanes, thrownValue, 7)); + break; + case 5: + var resource = null; + switch (workInProgress.tag) { + case 26: + resource = workInProgress.memoizedState; + case 5: + case 27: + var hostFiber = workInProgress; + if (resource ? preloadResource(resource) : hostFiber.stateNode.complete) { + workInProgressSuspendedReason = 0; + workInProgressThrownValue = null; + var sibling = hostFiber.sibling; + if (sibling !== null) + workInProgress = sibling; + else { + var returnFiber = hostFiber.return; + returnFiber !== null ? (workInProgress = returnFiber, completeUnitOfWork(returnFiber)) : workInProgress = null; + } + break b; + } + } + workInProgressSuspendedReason = 0; + workInProgressThrownValue = null; + throwAndUnwindWorkLoop(root2, lanes, thrownValue, 5); + break; + case 6: + workInProgressSuspendedReason = 0; + workInProgressThrownValue = null; + throwAndUnwindWorkLoop(root2, lanes, thrownValue, 6); + break; + case 8: + resetWorkInProgressStack(); + workInProgressRootExitStatus = 6; + break a; + default: + throw Error(formatProdErrorMessage2(462)); + } + } + workLoopConcurrentByScheduler(); + break; + } catch (thrownValue$167) { + handleThrow(root2, thrownValue$167); + } + while (1); + lastContextDependency = currentlyRenderingFiber$1 = null; + ReactSharedInternals3.H = prevDispatcher; + ReactSharedInternals3.A = prevAsyncDispatcher; + executionContext = prevExecutionContext; + if (workInProgress !== null) + return 0; + workInProgressRoot = null; + workInProgressRootRenderLanes = 0; + finishQueueingConcurrentUpdates(); + return workInProgressRootExitStatus; +} +function workLoopConcurrentByScheduler() { + for (;workInProgress !== null && !shouldYield(); ) + performUnitOfWork(workInProgress); +} +function performUnitOfWork(unitOfWork) { + var next = beginWork(unitOfWork.alternate, unitOfWork, entangledRenderLanes); + unitOfWork.memoizedProps = unitOfWork.pendingProps; + next === null ? completeUnitOfWork(unitOfWork) : workInProgress = next; +} +function replaySuspendedUnitOfWork(unitOfWork) { + var next = unitOfWork; + var current = next.alternate; + switch (next.tag) { + case 15: + case 0: + next = replayFunctionComponent(current, next, next.pendingProps, next.type, undefined, workInProgressRootRenderLanes); + break; + case 11: + next = replayFunctionComponent(current, next, next.pendingProps, next.type.render, next.ref, workInProgressRootRenderLanes); + break; + case 5: + resetHooksOnUnwind(next); + default: + unwindInterruptedWork(current, next), next = workInProgress = resetWorkInProgress(next, entangledRenderLanes), next = beginWork(current, next, entangledRenderLanes); + } + unitOfWork.memoizedProps = unitOfWork.pendingProps; + next === null ? completeUnitOfWork(unitOfWork) : workInProgress = next; +} +function throwAndUnwindWorkLoop(root2, unitOfWork, thrownValue, suspendedReason) { + lastContextDependency = currentlyRenderingFiber$1 = null; + resetHooksOnUnwind(unitOfWork); + thenableState$1 = null; + thenableIndexCounter$1 = 0; + var returnFiber = unitOfWork.return; + try { + if (throwException(root2, returnFiber, unitOfWork, thrownValue, workInProgressRootRenderLanes)) { + workInProgressRootExitStatus = 1; + logUncaughtError(root2, createCapturedValueAtFiber(thrownValue, root2.current)); + workInProgress = null; + return; + } + } catch (error) { + if (returnFiber !== null) + throw workInProgress = returnFiber, error; + workInProgressRootExitStatus = 1; + logUncaughtError(root2, createCapturedValueAtFiber(thrownValue, root2.current)); + workInProgress = null; + return; + } + if (unitOfWork.flags & 32768) { + if (isHydrating || suspendedReason === 1) + root2 = true; + else if (workInProgressRootIsPrerendering || (workInProgressRootRenderLanes & 536870912) !== 0) + root2 = false; + else if (workInProgressRootDidSkipSuspendedSiblings = root2 = true, suspendedReason === 2 || suspendedReason === 9 || suspendedReason === 3 || suspendedReason === 6) + suspendedReason = suspenseHandlerStackCursor.current, suspendedReason !== null && suspendedReason.tag === 13 && (suspendedReason.flags |= 16384); + unwindUnitOfWork(unitOfWork, root2); + } else + completeUnitOfWork(unitOfWork); +} +function completeUnitOfWork(unitOfWork) { + var completedWork = unitOfWork; + do { + if ((completedWork.flags & 32768) !== 0) { + unwindUnitOfWork(completedWork, workInProgressRootDidSkipSuspendedSiblings); + return; + } + unitOfWork = completedWork.return; + var next = completeWork(completedWork.alternate, completedWork, entangledRenderLanes); + if (next !== null) { + workInProgress = next; + return; + } + completedWork = completedWork.sibling; + if (completedWork !== null) { + workInProgress = completedWork; + return; + } + workInProgress = completedWork = unitOfWork; + } while (completedWork !== null); + workInProgressRootExitStatus === 0 && (workInProgressRootExitStatus = 5); +} +function unwindUnitOfWork(unitOfWork, skipSiblings) { + do { + var next = unwindWork(unitOfWork.alternate, unitOfWork); + if (next !== null) { + next.flags &= 32767; + workInProgress = next; + return; + } + next = unitOfWork.return; + next !== null && (next.flags |= 32768, next.subtreeFlags = 0, next.deletions = null); + if (!skipSiblings && (unitOfWork = unitOfWork.sibling, unitOfWork !== null)) { + workInProgress = unitOfWork; + return; + } + workInProgress = unitOfWork = next; + } while (unitOfWork !== null); + workInProgressRootExitStatus = 6; + workInProgress = null; +} +function commitRoot(root2, finishedWork, lanes, recoverableErrors, transitions, didIncludeRenderPhaseUpdate, spawnedLane, updatedLanes, suspendedRetryLanes) { + root2.cancelPendingCommit = null; + do + flushPendingEffects(); + while (pendingEffectsStatus !== 0); + if ((executionContext & 6) !== 0) + throw Error(formatProdErrorMessage2(327)); + if (finishedWork !== null) { + if (finishedWork === root2.current) + throw Error(formatProdErrorMessage2(177)); + didIncludeRenderPhaseUpdate = finishedWork.lanes | finishedWork.childLanes; + didIncludeRenderPhaseUpdate |= concurrentlyUpdatedLanes; + markRootFinished(root2, lanes, didIncludeRenderPhaseUpdate, spawnedLane, updatedLanes, suspendedRetryLanes); + root2 === workInProgressRoot && (workInProgress = workInProgressRoot = null, workInProgressRootRenderLanes = 0); + pendingFinishedWork = finishedWork; + pendingEffectsRoot = root2; + pendingEffectsLanes = lanes; + pendingEffectsRemainingLanes = didIncludeRenderPhaseUpdate; + pendingPassiveTransitions = transitions; + pendingRecoverableErrors = recoverableErrors; + (finishedWork.subtreeFlags & 10256) !== 0 || (finishedWork.flags & 10256) !== 0 ? (root2.callbackNode = null, root2.callbackPriority = 0, scheduleCallback$1(NormalPriority$1, function() { + flushPassiveEffects(); + return null; + })) : (root2.callbackNode = null, root2.callbackPriority = 0); + recoverableErrors = (finishedWork.flags & 13878) !== 0; + if ((finishedWork.subtreeFlags & 13878) !== 0 || recoverableErrors) { + recoverableErrors = ReactSharedInternals3.T; + ReactSharedInternals3.T = null; + transitions = ReactDOMSharedInternals.p; + ReactDOMSharedInternals.p = 2; + spawnedLane = executionContext; + executionContext |= 4; + try { + commitBeforeMutationEffects(root2, finishedWork, lanes); + } finally { + executionContext = spawnedLane, ReactDOMSharedInternals.p = transitions, ReactSharedInternals3.T = recoverableErrors; + } + } + pendingEffectsStatus = 1; + flushMutationEffects(); + flushLayoutEffects(); + flushSpawnedWork(); + } +} +function flushMutationEffects() { + if (pendingEffectsStatus === 1) { + pendingEffectsStatus = 0; + var root2 = pendingEffectsRoot, finishedWork = pendingFinishedWork, rootMutationHasEffect = (finishedWork.flags & 13878) !== 0; + if ((finishedWork.subtreeFlags & 13878) !== 0 || rootMutationHasEffect) { + rootMutationHasEffect = ReactSharedInternals3.T; + ReactSharedInternals3.T = null; + var previousPriority = ReactDOMSharedInternals.p; + ReactDOMSharedInternals.p = 2; + var prevExecutionContext = executionContext; + executionContext |= 4; + try { + commitMutationEffectsOnFiber(finishedWork, root2); + var priorSelectionInformation = selectionInformation, curFocusedElem = getActiveElementDeep(root2.containerInfo), priorFocusedElem = priorSelectionInformation.focusedElem, priorSelectionRange = priorSelectionInformation.selectionRange; + if (curFocusedElem !== priorFocusedElem && priorFocusedElem && priorFocusedElem.ownerDocument && containsNode(priorFocusedElem.ownerDocument.documentElement, priorFocusedElem)) { + if (priorSelectionRange !== null && hasSelectionCapabilities(priorFocusedElem)) { + var { start, end } = priorSelectionRange; + end === undefined && (end = start); + if ("selectionStart" in priorFocusedElem) + priorFocusedElem.selectionStart = start, priorFocusedElem.selectionEnd = Math.min(end, priorFocusedElem.value.length); + else { + var doc = priorFocusedElem.ownerDocument || document, win = doc && doc.defaultView || window; + if (win.getSelection) { + var selection = win.getSelection(), length = priorFocusedElem.textContent.length, start$jscomp$0 = Math.min(priorSelectionRange.start, length), end$jscomp$0 = priorSelectionRange.end === undefined ? start$jscomp$0 : Math.min(priorSelectionRange.end, length); + !selection.extend && start$jscomp$0 > end$jscomp$0 && (curFocusedElem = end$jscomp$0, end$jscomp$0 = start$jscomp$0, start$jscomp$0 = curFocusedElem); + var startMarker = getNodeForCharacterOffset(priorFocusedElem, start$jscomp$0), endMarker = getNodeForCharacterOffset(priorFocusedElem, end$jscomp$0); + if (startMarker && endMarker && (selection.rangeCount !== 1 || selection.anchorNode !== startMarker.node || selection.anchorOffset !== startMarker.offset || selection.focusNode !== endMarker.node || selection.focusOffset !== endMarker.offset)) { + var range = doc.createRange(); + range.setStart(startMarker.node, startMarker.offset); + selection.removeAllRanges(); + start$jscomp$0 > end$jscomp$0 ? (selection.addRange(range), selection.extend(endMarker.node, endMarker.offset)) : (range.setEnd(endMarker.node, endMarker.offset), selection.addRange(range)); + } + } + } + } + doc = []; + for (selection = priorFocusedElem;selection = selection.parentNode; ) + selection.nodeType === 1 && doc.push({ + element: selection, + left: selection.scrollLeft, + top: selection.scrollTop + }); + typeof priorFocusedElem.focus === "function" && priorFocusedElem.focus(); + for (priorFocusedElem = 0;priorFocusedElem < doc.length; priorFocusedElem++) { + var info = doc[priorFocusedElem]; + info.element.scrollLeft = info.left; + info.element.scrollTop = info.top; + } + } + _enabled = !!eventsEnabled; + selectionInformation = eventsEnabled = null; + } finally { + executionContext = prevExecutionContext, ReactDOMSharedInternals.p = previousPriority, ReactSharedInternals3.T = rootMutationHasEffect; + } + } + root2.current = finishedWork; + pendingEffectsStatus = 2; + } +} +function flushLayoutEffects() { + if (pendingEffectsStatus === 2) { + pendingEffectsStatus = 0; + var root2 = pendingEffectsRoot, finishedWork = pendingFinishedWork, rootHasLayoutEffect = (finishedWork.flags & 8772) !== 0; + if ((finishedWork.subtreeFlags & 8772) !== 0 || rootHasLayoutEffect) { + rootHasLayoutEffect = ReactSharedInternals3.T; + ReactSharedInternals3.T = null; + var previousPriority = ReactDOMSharedInternals.p; + ReactDOMSharedInternals.p = 2; + var prevExecutionContext = executionContext; + executionContext |= 4; + try { + commitLayoutEffectOnFiber(root2, finishedWork.alternate, finishedWork); + } finally { + executionContext = prevExecutionContext, ReactDOMSharedInternals.p = previousPriority, ReactSharedInternals3.T = rootHasLayoutEffect; + } + } + pendingEffectsStatus = 3; + } +} +function flushSpawnedWork() { + if (pendingEffectsStatus === 4 || pendingEffectsStatus === 3) { + pendingEffectsStatus = 0; + requestPaint(); + var root2 = pendingEffectsRoot, finishedWork = pendingFinishedWork, lanes = pendingEffectsLanes, recoverableErrors = pendingRecoverableErrors; + (finishedWork.subtreeFlags & 10256) !== 0 || (finishedWork.flags & 10256) !== 0 ? pendingEffectsStatus = 5 : (pendingEffectsStatus = 0, pendingFinishedWork = pendingEffectsRoot = null, releaseRootPooledCache(root2, root2.pendingLanes)); + var remainingLanes = root2.pendingLanes; + remainingLanes === 0 && (legacyErrorBoundariesThatAlreadyFailed = null); + lanesToEventPriority(lanes); + finishedWork = finishedWork.stateNode; + if (injectedHook && typeof injectedHook.onCommitFiberRoot === "function") + try { + injectedHook.onCommitFiberRoot(rendererID, finishedWork, undefined, (finishedWork.current.flags & 128) === 128); + } catch (err) {} + if (recoverableErrors !== null) { + finishedWork = ReactSharedInternals3.T; + remainingLanes = ReactDOMSharedInternals.p; + ReactDOMSharedInternals.p = 2; + ReactSharedInternals3.T = null; + try { + for (var onRecoverableError = root2.onRecoverableError, i = 0;i < recoverableErrors.length; i++) { + var recoverableError = recoverableErrors[i]; + onRecoverableError(recoverableError.value, { + componentStack: recoverableError.stack + }); + } + } finally { + ReactSharedInternals3.T = finishedWork, ReactDOMSharedInternals.p = remainingLanes; + } + } + (pendingEffectsLanes & 3) !== 0 && flushPendingEffects(); + ensureRootIsScheduled(root2); + remainingLanes = root2.pendingLanes; + (lanes & 261930) !== 0 && (remainingLanes & 42) !== 0 ? root2 === rootWithNestedUpdates ? nestedUpdateCount++ : (nestedUpdateCount = 0, rootWithNestedUpdates = root2) : nestedUpdateCount = 0; + flushSyncWorkAcrossRoots_impl(0, false); + } +} +function releaseRootPooledCache(root2, remainingLanes) { + (root2.pooledCacheLanes &= remainingLanes) === 0 && (remainingLanes = root2.pooledCache, remainingLanes != null && (root2.pooledCache = null, releaseCache(remainingLanes))); +} +function flushPendingEffects() { + flushMutationEffects(); + flushLayoutEffects(); + flushSpawnedWork(); + return flushPassiveEffects(); +} +function flushPassiveEffects() { + if (pendingEffectsStatus !== 5) + return false; + var root2 = pendingEffectsRoot, remainingLanes = pendingEffectsRemainingLanes; + pendingEffectsRemainingLanes = 0; + var renderPriority = lanesToEventPriority(pendingEffectsLanes), prevTransition = ReactSharedInternals3.T, previousPriority = ReactDOMSharedInternals.p; + try { + ReactDOMSharedInternals.p = 32 > renderPriority ? 32 : renderPriority; + ReactSharedInternals3.T = null; + renderPriority = pendingPassiveTransitions; + pendingPassiveTransitions = null; + var root$jscomp$0 = pendingEffectsRoot, lanes = pendingEffectsLanes; + pendingEffectsStatus = 0; + pendingFinishedWork = pendingEffectsRoot = null; + pendingEffectsLanes = 0; + if ((executionContext & 6) !== 0) + throw Error(formatProdErrorMessage2(331)); + var prevExecutionContext = executionContext; + executionContext |= 4; + commitPassiveUnmountOnFiber(root$jscomp$0.current); + commitPassiveMountOnFiber(root$jscomp$0, root$jscomp$0.current, lanes, renderPriority); + executionContext = prevExecutionContext; + flushSyncWorkAcrossRoots_impl(0, false); + if (injectedHook && typeof injectedHook.onPostCommitFiberRoot === "function") + try { + injectedHook.onPostCommitFiberRoot(rendererID, root$jscomp$0); + } catch (err) {} + return true; + } finally { + ReactDOMSharedInternals.p = previousPriority, ReactSharedInternals3.T = prevTransition, releaseRootPooledCache(root2, remainingLanes); + } +} +function captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) { + sourceFiber = createCapturedValueAtFiber(error, sourceFiber); + sourceFiber = createRootErrorUpdate(rootFiber.stateNode, sourceFiber, 2); + rootFiber = enqueueUpdate(rootFiber, sourceFiber, 2); + rootFiber !== null && (markRootUpdated$1(rootFiber, 2), ensureRootIsScheduled(rootFiber)); +} +function captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error) { + if (sourceFiber.tag === 3) + captureCommitPhaseErrorOnRoot(sourceFiber, sourceFiber, error); + else + for (;nearestMountedAncestor !== null; ) { + if (nearestMountedAncestor.tag === 3) { + captureCommitPhaseErrorOnRoot(nearestMountedAncestor, sourceFiber, error); + break; + } else if (nearestMountedAncestor.tag === 1) { + var instance = nearestMountedAncestor.stateNode; + if (typeof nearestMountedAncestor.type.getDerivedStateFromError === "function" || typeof instance.componentDidCatch === "function" && (legacyErrorBoundariesThatAlreadyFailed === null || !legacyErrorBoundariesThatAlreadyFailed.has(instance))) { + sourceFiber = createCapturedValueAtFiber(error, sourceFiber); + error = createClassErrorUpdate(2); + instance = enqueueUpdate(nearestMountedAncestor, error, 2); + instance !== null && (initializeClassErrorUpdate(error, instance, nearestMountedAncestor, sourceFiber), markRootUpdated$1(instance, 2), ensureRootIsScheduled(instance)); + break; + } + } + nearestMountedAncestor = nearestMountedAncestor.return; + } +} +function attachPingListener(root2, wakeable, lanes) { + var pingCache = root2.pingCache; + if (pingCache === null) { + pingCache = root2.pingCache = new PossiblyWeakMap; + var threadIDs = new Set; + pingCache.set(wakeable, threadIDs); + } else + threadIDs = pingCache.get(wakeable), threadIDs === undefined && (threadIDs = new Set, pingCache.set(wakeable, threadIDs)); + threadIDs.has(lanes) || (workInProgressRootDidAttachPingListener = true, threadIDs.add(lanes), root2 = pingSuspendedRoot.bind(null, root2, wakeable, lanes), wakeable.then(root2, root2)); +} +function pingSuspendedRoot(root2, wakeable, pingedLanes) { + var pingCache = root2.pingCache; + pingCache !== null && pingCache.delete(wakeable); + root2.pingedLanes |= root2.suspendedLanes & pingedLanes; + root2.warmLanes &= ~pingedLanes; + workInProgressRoot === root2 && (workInProgressRootRenderLanes & pingedLanes) === pingedLanes && (workInProgressRootExitStatus === 4 || workInProgressRootExitStatus === 3 && (workInProgressRootRenderLanes & 62914560) === workInProgressRootRenderLanes && 300 > now() - globalMostRecentFallbackTime ? (executionContext & 2) === 0 && prepareFreshStack(root2, 0) : workInProgressRootPingedLanes |= pingedLanes, workInProgressSuspendedRetryLanes === workInProgressRootRenderLanes && (workInProgressSuspendedRetryLanes = 0)); + ensureRootIsScheduled(root2); +} +function retryTimedOutBoundary(boundaryFiber, retryLane) { + retryLane === 0 && (retryLane = claimNextRetryLane()); + boundaryFiber = enqueueConcurrentRenderForLane(boundaryFiber, retryLane); + boundaryFiber !== null && (markRootUpdated$1(boundaryFiber, retryLane), ensureRootIsScheduled(boundaryFiber)); +} +function retryDehydratedSuspenseBoundary(boundaryFiber) { + var suspenseState = boundaryFiber.memoizedState, retryLane = 0; + suspenseState !== null && (retryLane = suspenseState.retryLane); + retryTimedOutBoundary(boundaryFiber, retryLane); +} +function resolveRetryWakeable(boundaryFiber, wakeable) { + var retryLane = 0; + switch (boundaryFiber.tag) { + case 31: + case 13: + var retryCache = boundaryFiber.stateNode; + var suspenseState = boundaryFiber.memoizedState; + suspenseState !== null && (retryLane = suspenseState.retryLane); + break; + case 19: + retryCache = boundaryFiber.stateNode; + break; + case 22: + retryCache = boundaryFiber.stateNode._retryCache; + break; + default: + throw Error(formatProdErrorMessage2(314)); + } + retryCache !== null && retryCache.delete(wakeable); + retryTimedOutBoundary(boundaryFiber, retryLane); +} +function scheduleCallback$1(priorityLevel, callback) { + return scheduleCallback$3(priorityLevel, callback); +} +function ensureRootIsScheduled(root2) { + root2 !== lastScheduledRoot && root2.next === null && (lastScheduledRoot === null ? firstScheduledRoot = lastScheduledRoot = root2 : lastScheduledRoot = lastScheduledRoot.next = root2); + mightHavePendingSyncWork = true; + didScheduleMicrotask || (didScheduleMicrotask = true, scheduleImmediateRootScheduleTask()); +} +function flushSyncWorkAcrossRoots_impl(syncTransitionLanes, onlyLegacy) { + if (!isFlushingWork && mightHavePendingSyncWork) { + isFlushingWork = true; + do { + var didPerformSomeWork = false; + for (var root$170 = firstScheduledRoot;root$170 !== null; ) { + if (!onlyLegacy) + if (syncTransitionLanes !== 0) { + var pendingLanes = root$170.pendingLanes; + if (pendingLanes === 0) + var JSCompiler_inline_result = 0; + else { + var { suspendedLanes, pingedLanes } = root$170; + JSCompiler_inline_result = (1 << 31 - clz32(42 | syncTransitionLanes) + 1) - 1; + JSCompiler_inline_result &= pendingLanes & ~(suspendedLanes & ~pingedLanes); + JSCompiler_inline_result = JSCompiler_inline_result & 201326741 ? JSCompiler_inline_result & 201326741 | 1 : JSCompiler_inline_result ? JSCompiler_inline_result | 2 : 0; + } + JSCompiler_inline_result !== 0 && (didPerformSomeWork = true, performSyncWorkOnRoot(root$170, JSCompiler_inline_result)); + } else + JSCompiler_inline_result = workInProgressRootRenderLanes, JSCompiler_inline_result = getNextLanes(root$170, root$170 === workInProgressRoot ? JSCompiler_inline_result : 0, root$170.cancelPendingCommit !== null || root$170.timeoutHandle !== -1), (JSCompiler_inline_result & 3) === 0 || checkIfRootIsPrerendering(root$170, JSCompiler_inline_result) || (didPerformSomeWork = true, performSyncWorkOnRoot(root$170, JSCompiler_inline_result)); + root$170 = root$170.next; + } + } while (didPerformSomeWork); + isFlushingWork = false; + } +} +function processRootScheduleInImmediateTask() { + processRootScheduleInMicrotask(); +} +function processRootScheduleInMicrotask() { + mightHavePendingSyncWork = didScheduleMicrotask = false; + var syncTransitionLanes = 0; + currentEventTransitionLane !== 0 && shouldAttemptEagerTransition() && (syncTransitionLanes = currentEventTransitionLane); + for (var currentTime = now(), prev = null, root2 = firstScheduledRoot;root2 !== null; ) { + var next = root2.next, nextLanes = scheduleTaskForRootDuringMicrotask(root2, currentTime); + if (nextLanes === 0) + root2.next = null, prev === null ? firstScheduledRoot = next : prev.next = next, next === null && (lastScheduledRoot = prev); + else if (prev = root2, syncTransitionLanes !== 0 || (nextLanes & 3) !== 0) + mightHavePendingSyncWork = true; + root2 = next; + } + pendingEffectsStatus !== 0 && pendingEffectsStatus !== 5 || flushSyncWorkAcrossRoots_impl(syncTransitionLanes, false); + currentEventTransitionLane !== 0 && (currentEventTransitionLane = 0); +} +function scheduleTaskForRootDuringMicrotask(root2, currentTime) { + for (var { suspendedLanes, pingedLanes, expirationTimes } = root2, lanes = root2.pendingLanes & -62914561;0 < lanes; ) { + var index$5 = 31 - clz32(lanes), lane = 1 << index$5, expirationTime = expirationTimes[index$5]; + if (expirationTime === -1) { + if ((lane & suspendedLanes) === 0 || (lane & pingedLanes) !== 0) + expirationTimes[index$5] = computeExpirationTime(lane, currentTime); + } else + expirationTime <= currentTime && (root2.expiredLanes |= lane); + lanes &= ~lane; + } + currentTime = workInProgressRoot; + suspendedLanes = workInProgressRootRenderLanes; + suspendedLanes = getNextLanes(root2, root2 === currentTime ? suspendedLanes : 0, root2.cancelPendingCommit !== null || root2.timeoutHandle !== -1); + pingedLanes = root2.callbackNode; + if (suspendedLanes === 0 || root2 === currentTime && (workInProgressSuspendedReason === 2 || workInProgressSuspendedReason === 9) || root2.cancelPendingCommit !== null) + return pingedLanes !== null && pingedLanes !== null && cancelCallback$1(pingedLanes), root2.callbackNode = null, root2.callbackPriority = 0; + if ((suspendedLanes & 3) === 0 || checkIfRootIsPrerendering(root2, suspendedLanes)) { + currentTime = suspendedLanes & -suspendedLanes; + if (currentTime === root2.callbackPriority) + return currentTime; + pingedLanes !== null && cancelCallback$1(pingedLanes); + switch (lanesToEventPriority(suspendedLanes)) { + case 2: + case 8: + suspendedLanes = UserBlockingPriority; + break; + case 32: + suspendedLanes = NormalPriority$1; + break; + case 268435456: + suspendedLanes = IdlePriority; + break; + default: + suspendedLanes = NormalPriority$1; + } + pingedLanes = performWorkOnRootViaSchedulerTask.bind(null, root2); + suspendedLanes = scheduleCallback$3(suspendedLanes, pingedLanes); + root2.callbackPriority = currentTime; + root2.callbackNode = suspendedLanes; + return currentTime; + } + pingedLanes !== null && pingedLanes !== null && cancelCallback$1(pingedLanes); + root2.callbackPriority = 2; + root2.callbackNode = null; + return 2; +} +function performWorkOnRootViaSchedulerTask(root2, didTimeout) { + if (pendingEffectsStatus !== 0 && pendingEffectsStatus !== 5) + return root2.callbackNode = null, root2.callbackPriority = 0, null; + var originalCallbackNode = root2.callbackNode; + if (flushPendingEffects() && root2.callbackNode !== originalCallbackNode) + return null; + var workInProgressRootRenderLanes$jscomp$0 = workInProgressRootRenderLanes; + workInProgressRootRenderLanes$jscomp$0 = getNextLanes(root2, root2 === workInProgressRoot ? workInProgressRootRenderLanes$jscomp$0 : 0, root2.cancelPendingCommit !== null || root2.timeoutHandle !== -1); + if (workInProgressRootRenderLanes$jscomp$0 === 0) + return null; + performWorkOnRoot(root2, workInProgressRootRenderLanes$jscomp$0, didTimeout); + scheduleTaskForRootDuringMicrotask(root2, now()); + return root2.callbackNode != null && root2.callbackNode === originalCallbackNode ? performWorkOnRootViaSchedulerTask.bind(null, root2) : null; +} +function performSyncWorkOnRoot(root2, lanes) { + if (flushPendingEffects()) + return null; + performWorkOnRoot(root2, lanes, true); +} +function scheduleImmediateRootScheduleTask() { + scheduleMicrotask(function() { + (executionContext & 6) !== 0 ? scheduleCallback$3(ImmediatePriority, processRootScheduleInImmediateTask) : processRootScheduleInMicrotask(); + }); +} +function requestTransitionLane() { + if (currentEventTransitionLane === 0) { + var actionScopeLane = currentEntangledLane; + actionScopeLane === 0 && (actionScopeLane = nextTransitionUpdateLane, nextTransitionUpdateLane <<= 1, (nextTransitionUpdateLane & 261888) === 0 && (nextTransitionUpdateLane = 256)); + currentEventTransitionLane = actionScopeLane; + } + return currentEventTransitionLane; +} +function coerceFormActionProp(actionProp) { + return actionProp == null || typeof actionProp === "symbol" || typeof actionProp === "boolean" ? null : typeof actionProp === "function" ? actionProp : sanitizeURL("" + actionProp); +} +function createFormDataWithSubmitter(form, submitter) { + var temp = submitter.ownerDocument.createElement("input"); + temp.name = submitter.name; + temp.value = submitter.value; + form.id && temp.setAttribute("form", form.id); + submitter.parentNode.insertBefore(temp, submitter); + form = new FormData(form); + temp.parentNode.removeChild(temp); + return form; +} +function extractEvents$1(dispatchQueue, domEventName, maybeTargetInst, nativeEvent, nativeEventTarget) { + if (domEventName === "submit" && maybeTargetInst && maybeTargetInst.stateNode === nativeEventTarget) { + var action = coerceFormActionProp((nativeEventTarget[internalPropsKey] || null).action), submitter = nativeEvent.submitter; + submitter && (domEventName = (domEventName = submitter[internalPropsKey] || null) ? coerceFormActionProp(domEventName.formAction) : submitter.getAttribute("formAction"), domEventName !== null && (action = domEventName, submitter = null)); + var event = new SyntheticEvent("action", "action", null, nativeEvent, nativeEventTarget); + dispatchQueue.push({ + event, + listeners: [ + { + instance: null, + listener: function() { + if (nativeEvent.defaultPrevented) { + if (currentEventTransitionLane !== 0) { + var formData = submitter ? createFormDataWithSubmitter(nativeEventTarget, submitter) : new FormData(nativeEventTarget); + startHostTransition(maybeTargetInst, { + pending: true, + data: formData, + method: nativeEventTarget.method, + action + }, null, formData); + } + } else + typeof action === "function" && (event.preventDefault(), formData = submitter ? createFormDataWithSubmitter(nativeEventTarget, submitter) : new FormData(nativeEventTarget), startHostTransition(maybeTargetInst, { + pending: true, + data: formData, + method: nativeEventTarget.method, + action + }, action, formData)); + }, + currentTarget: nativeEventTarget + } + ] + }); + } +} +function processDispatchQueue(dispatchQueue, eventSystemFlags) { + eventSystemFlags = (eventSystemFlags & 4) !== 0; + for (var i = 0;i < dispatchQueue.length; i++) { + var _dispatchQueue$i = dispatchQueue[i], event = _dispatchQueue$i.event; + _dispatchQueue$i = _dispatchQueue$i.listeners; + a: { + var previousInstance = undefined; + if (eventSystemFlags) + for (var i$jscomp$0 = _dispatchQueue$i.length - 1;0 <= i$jscomp$0; i$jscomp$0--) { + var _dispatchListeners$i = _dispatchQueue$i[i$jscomp$0], instance = _dispatchListeners$i.instance, currentTarget = _dispatchListeners$i.currentTarget; + _dispatchListeners$i = _dispatchListeners$i.listener; + if (instance !== previousInstance && event.isPropagationStopped()) + break a; + previousInstance = _dispatchListeners$i; + event.currentTarget = currentTarget; + try { + previousInstance(event); + } catch (error) { + reportGlobalError2(error); + } + event.currentTarget = null; + previousInstance = instance; + } + else + for (i$jscomp$0 = 0;i$jscomp$0 < _dispatchQueue$i.length; i$jscomp$0++) { + _dispatchListeners$i = _dispatchQueue$i[i$jscomp$0]; + instance = _dispatchListeners$i.instance; + currentTarget = _dispatchListeners$i.currentTarget; + _dispatchListeners$i = _dispatchListeners$i.listener; + if (instance !== previousInstance && event.isPropagationStopped()) + break a; + previousInstance = _dispatchListeners$i; + event.currentTarget = currentTarget; + try { + previousInstance(event); + } catch (error) { + reportGlobalError2(error); + } + event.currentTarget = null; + previousInstance = instance; + } + } + } +} +function listenToNonDelegatedEvent(domEventName, targetElement) { + var JSCompiler_inline_result = targetElement[internalEventHandlersKey]; + JSCompiler_inline_result === undefined && (JSCompiler_inline_result = targetElement[internalEventHandlersKey] = new Set); + var listenerSetKey = domEventName + "__bubble"; + JSCompiler_inline_result.has(listenerSetKey) || (addTrappedEventListener(targetElement, domEventName, 2, false), JSCompiler_inline_result.add(listenerSetKey)); +} +function listenToNativeEvent(domEventName, isCapturePhaseListener, target) { + var eventSystemFlags = 0; + isCapturePhaseListener && (eventSystemFlags |= 4); + addTrappedEventListener(target, domEventName, eventSystemFlags, isCapturePhaseListener); +} +function listenToAllSupportedEvents(rootContainerElement) { + if (!rootContainerElement[listeningMarker]) { + rootContainerElement[listeningMarker] = true; + allNativeEvents.forEach(function(domEventName) { + domEventName !== "selectionchange" && (nonDelegatedEvents.has(domEventName) || listenToNativeEvent(domEventName, false, rootContainerElement), listenToNativeEvent(domEventName, true, rootContainerElement)); + }); + var ownerDocument = rootContainerElement.nodeType === 9 ? rootContainerElement : rootContainerElement.ownerDocument; + ownerDocument === null || ownerDocument[listeningMarker] || (ownerDocument[listeningMarker] = true, listenToNativeEvent("selectionchange", false, ownerDocument)); + } +} +function addTrappedEventListener(targetContainer, domEventName, eventSystemFlags, isCapturePhaseListener) { + switch (getEventPriority(domEventName)) { + case 2: + var listenerWrapper = dispatchDiscreteEvent; + break; + case 8: + listenerWrapper = dispatchContinuousEvent; + break; + default: + listenerWrapper = dispatchEvent; + } + eventSystemFlags = listenerWrapper.bind(null, domEventName, eventSystemFlags, targetContainer); + listenerWrapper = undefined; + !passiveBrowserEventsSupported || domEventName !== "touchstart" && domEventName !== "touchmove" && domEventName !== "wheel" || (listenerWrapper = true); + isCapturePhaseListener ? listenerWrapper !== undefined ? targetContainer.addEventListener(domEventName, eventSystemFlags, { + capture: true, + passive: listenerWrapper + }) : targetContainer.addEventListener(domEventName, eventSystemFlags, true) : listenerWrapper !== undefined ? targetContainer.addEventListener(domEventName, eventSystemFlags, { + passive: listenerWrapper + }) : targetContainer.addEventListener(domEventName, eventSystemFlags, false); +} +function dispatchEventForPluginEventSystem(domEventName, eventSystemFlags, nativeEvent, targetInst$jscomp$0, targetContainer) { + var ancestorInst = targetInst$jscomp$0; + if ((eventSystemFlags & 1) === 0 && (eventSystemFlags & 2) === 0 && targetInst$jscomp$0 !== null) + a: + for (;; ) { + if (targetInst$jscomp$0 === null) + return; + var nodeTag = targetInst$jscomp$0.tag; + if (nodeTag === 3 || nodeTag === 4) { + var container = targetInst$jscomp$0.stateNode.containerInfo; + if (container === targetContainer) + break; + if (nodeTag === 4) + for (nodeTag = targetInst$jscomp$0.return;nodeTag !== null; ) { + var grandTag = nodeTag.tag; + if ((grandTag === 3 || grandTag === 4) && nodeTag.stateNode.containerInfo === targetContainer) + return; + nodeTag = nodeTag.return; + } + for (;container !== null; ) { + nodeTag = getClosestInstanceFromNode(container); + if (nodeTag === null) + return; + grandTag = nodeTag.tag; + if (grandTag === 5 || grandTag === 6 || grandTag === 26 || grandTag === 27) { + targetInst$jscomp$0 = ancestorInst = nodeTag; + continue a; + } + container = container.parentNode; + } + } + targetInst$jscomp$0 = targetInst$jscomp$0.return; + } + batchedUpdates$1(function() { + var targetInst = ancestorInst, nativeEventTarget = getEventTarget(nativeEvent), dispatchQueue = []; + a: { + var reactName = topLevelEventsToReactNames.get(domEventName); + if (reactName !== undefined) { + var SyntheticEventCtor = SyntheticEvent, reactEventType = domEventName; + switch (domEventName) { + case "keypress": + if (getEventCharCode(nativeEvent) === 0) + break a; + case "keydown": + case "keyup": + SyntheticEventCtor = SyntheticKeyboardEvent; + break; + case "focusin": + reactEventType = "focus"; + SyntheticEventCtor = SyntheticFocusEvent; + break; + case "focusout": + reactEventType = "blur"; + SyntheticEventCtor = SyntheticFocusEvent; + break; + case "beforeblur": + case "afterblur": + SyntheticEventCtor = SyntheticFocusEvent; + break; + case "click": + if (nativeEvent.button === 2) + break a; + case "auxclick": + case "dblclick": + case "mousedown": + case "mousemove": + case "mouseup": + case "mouseout": + case "mouseover": + case "contextmenu": + SyntheticEventCtor = SyntheticMouseEvent; + break; + case "drag": + case "dragend": + case "dragenter": + case "dragexit": + case "dragleave": + case "dragover": + case "dragstart": + case "drop": + SyntheticEventCtor = SyntheticDragEvent; + break; + case "touchcancel": + case "touchend": + case "touchmove": + case "touchstart": + SyntheticEventCtor = SyntheticTouchEvent; + break; + case ANIMATION_END: + case ANIMATION_ITERATION: + case ANIMATION_START: + SyntheticEventCtor = SyntheticAnimationEvent; + break; + case TRANSITION_END: + SyntheticEventCtor = SyntheticTransitionEvent; + break; + case "scroll": + case "scrollend": + SyntheticEventCtor = SyntheticUIEvent; + break; + case "wheel": + SyntheticEventCtor = SyntheticWheelEvent; + break; + case "copy": + case "cut": + case "paste": + SyntheticEventCtor = SyntheticClipboardEvent; + break; + case "gotpointercapture": + case "lostpointercapture": + case "pointercancel": + case "pointerdown": + case "pointermove": + case "pointerout": + case "pointerover": + case "pointerup": + SyntheticEventCtor = SyntheticPointerEvent; + break; + case "toggle": + case "beforetoggle": + SyntheticEventCtor = SyntheticToggleEvent; + } + var inCapturePhase = (eventSystemFlags & 4) !== 0, accumulateTargetOnly = !inCapturePhase && (domEventName === "scroll" || domEventName === "scrollend"), reactEventName = inCapturePhase ? reactName !== null ? reactName + "Capture" : null : reactName; + inCapturePhase = []; + for (var instance = targetInst, lastHostComponent;instance !== null; ) { + var _instance = instance; + lastHostComponent = _instance.stateNode; + _instance = _instance.tag; + _instance !== 5 && _instance !== 26 && _instance !== 27 || lastHostComponent === null || reactEventName === null || (_instance = getListener(instance, reactEventName), _instance != null && inCapturePhase.push(createDispatchListener(instance, _instance, lastHostComponent))); + if (accumulateTargetOnly) + break; + instance = instance.return; + } + 0 < inCapturePhase.length && (reactName = new SyntheticEventCtor(reactName, reactEventType, null, nativeEvent, nativeEventTarget), dispatchQueue.push({ event: reactName, listeners: inCapturePhase })); + } + } + if ((eventSystemFlags & 7) === 0) { + a: { + reactName = domEventName === "mouseover" || domEventName === "pointerover"; + SyntheticEventCtor = domEventName === "mouseout" || domEventName === "pointerout"; + if (reactName && nativeEvent !== currentReplayingEvent && (reactEventType = nativeEvent.relatedTarget || nativeEvent.fromElement) && (getClosestInstanceFromNode(reactEventType) || reactEventType[internalContainerInstanceKey])) + break a; + if (SyntheticEventCtor || reactName) { + reactName = nativeEventTarget.window === nativeEventTarget ? nativeEventTarget : (reactName = nativeEventTarget.ownerDocument) ? reactName.defaultView || reactName.parentWindow : window; + if (SyntheticEventCtor) { + if (reactEventType = nativeEvent.relatedTarget || nativeEvent.toElement, SyntheticEventCtor = targetInst, reactEventType = reactEventType ? getClosestInstanceFromNode(reactEventType) : null, reactEventType !== null && (accumulateTargetOnly = getNearestMountedFiber(reactEventType), inCapturePhase = reactEventType.tag, reactEventType !== accumulateTargetOnly || inCapturePhase !== 5 && inCapturePhase !== 27 && inCapturePhase !== 6)) + reactEventType = null; + } else + SyntheticEventCtor = null, reactEventType = targetInst; + if (SyntheticEventCtor !== reactEventType) { + inCapturePhase = SyntheticMouseEvent; + _instance = "onMouseLeave"; + reactEventName = "onMouseEnter"; + instance = "mouse"; + if (domEventName === "pointerout" || domEventName === "pointerover") + inCapturePhase = SyntheticPointerEvent, _instance = "onPointerLeave", reactEventName = "onPointerEnter", instance = "pointer"; + accumulateTargetOnly = SyntheticEventCtor == null ? reactName : getNodeFromInstance(SyntheticEventCtor); + lastHostComponent = reactEventType == null ? reactName : getNodeFromInstance(reactEventType); + reactName = new inCapturePhase(_instance, instance + "leave", SyntheticEventCtor, nativeEvent, nativeEventTarget); + reactName.target = accumulateTargetOnly; + reactName.relatedTarget = lastHostComponent; + _instance = null; + getClosestInstanceFromNode(nativeEventTarget) === targetInst && (inCapturePhase = new inCapturePhase(reactEventName, instance + "enter", reactEventType, nativeEvent, nativeEventTarget), inCapturePhase.target = lastHostComponent, inCapturePhase.relatedTarget = accumulateTargetOnly, _instance = inCapturePhase); + accumulateTargetOnly = _instance; + if (SyntheticEventCtor && reactEventType) + b: { + inCapturePhase = getParent; + reactEventName = SyntheticEventCtor; + instance = reactEventType; + lastHostComponent = 0; + for (_instance = reactEventName;_instance; _instance = inCapturePhase(_instance)) + lastHostComponent++; + _instance = 0; + for (var tempB = instance;tempB; tempB = inCapturePhase(tempB)) + _instance++; + for (;0 < lastHostComponent - _instance; ) + reactEventName = inCapturePhase(reactEventName), lastHostComponent--; + for (;0 < _instance - lastHostComponent; ) + instance = inCapturePhase(instance), _instance--; + for (;lastHostComponent--; ) { + if (reactEventName === instance || instance !== null && reactEventName === instance.alternate) { + inCapturePhase = reactEventName; + break b; + } + reactEventName = inCapturePhase(reactEventName); + instance = inCapturePhase(instance); + } + inCapturePhase = null; + } + else + inCapturePhase = null; + SyntheticEventCtor !== null && accumulateEnterLeaveListenersForEvent(dispatchQueue, reactName, SyntheticEventCtor, inCapturePhase, false); + reactEventType !== null && accumulateTargetOnly !== null && accumulateEnterLeaveListenersForEvent(dispatchQueue, accumulateTargetOnly, reactEventType, inCapturePhase, true); + } + } + } + a: { + reactName = targetInst ? getNodeFromInstance(targetInst) : window; + SyntheticEventCtor = reactName.nodeName && reactName.nodeName.toLowerCase(); + if (SyntheticEventCtor === "select" || SyntheticEventCtor === "input" && reactName.type === "file") + var getTargetInstFunc = getTargetInstForChangeEvent; + else if (isTextInputElement(reactName)) + if (isInputEventSupported) + getTargetInstFunc = getTargetInstForInputOrChangeEvent; + else { + getTargetInstFunc = getTargetInstForInputEventPolyfill; + var handleEventFunc = handleEventsForInputEventPolyfill; + } + else + SyntheticEventCtor = reactName.nodeName, !SyntheticEventCtor || SyntheticEventCtor.toLowerCase() !== "input" || reactName.type !== "checkbox" && reactName.type !== "radio" ? targetInst && isCustomElement(targetInst.elementType) && (getTargetInstFunc = getTargetInstForChangeEvent) : getTargetInstFunc = getTargetInstForClickEvent; + if (getTargetInstFunc && (getTargetInstFunc = getTargetInstFunc(domEventName, targetInst))) { + createAndAccumulateChangeEvent(dispatchQueue, getTargetInstFunc, nativeEvent, nativeEventTarget); + break a; + } + handleEventFunc && handleEventFunc(domEventName, reactName, targetInst); + domEventName === "focusout" && targetInst && reactName.type === "number" && targetInst.memoizedProps.value != null && setDefaultValue(reactName, "number", reactName.value); + } + handleEventFunc = targetInst ? getNodeFromInstance(targetInst) : window; + switch (domEventName) { + case "focusin": + if (isTextInputElement(handleEventFunc) || handleEventFunc.contentEditable === "true") + activeElement = handleEventFunc, activeElementInst = targetInst, lastSelection = null; + break; + case "focusout": + lastSelection = activeElementInst = activeElement = null; + break; + case "mousedown": + mouseDown = true; + break; + case "contextmenu": + case "mouseup": + case "dragend": + mouseDown = false; + constructSelectEvent(dispatchQueue, nativeEvent, nativeEventTarget); + break; + case "selectionchange": + if (skipSelectionChangeEvent) + break; + case "keydown": + case "keyup": + constructSelectEvent(dispatchQueue, nativeEvent, nativeEventTarget); + } + var fallbackData; + if (canUseCompositionEvent) + b: { + switch (domEventName) { + case "compositionstart": + var eventType = "onCompositionStart"; + break b; + case "compositionend": + eventType = "onCompositionEnd"; + break b; + case "compositionupdate": + eventType = "onCompositionUpdate"; + break b; + } + eventType = undefined; + } + else + isComposing ? isFallbackCompositionEnd(domEventName, nativeEvent) && (eventType = "onCompositionEnd") : domEventName === "keydown" && nativeEvent.keyCode === 229 && (eventType = "onCompositionStart"); + eventType && (useFallbackCompositionData && nativeEvent.locale !== "ko" && (isComposing || eventType !== "onCompositionStart" ? eventType === "onCompositionEnd" && isComposing && (fallbackData = getData()) : (root = nativeEventTarget, startText = ("value" in root) ? root.value : root.textContent, isComposing = true)), handleEventFunc = accumulateTwoPhaseListeners(targetInst, eventType), 0 < handleEventFunc.length && (eventType = new SyntheticCompositionEvent(eventType, domEventName, null, nativeEvent, nativeEventTarget), dispatchQueue.push({ event: eventType, listeners: handleEventFunc }), fallbackData ? eventType.data = fallbackData : (fallbackData = getDataFromCustomEvent(nativeEvent), fallbackData !== null && (eventType.data = fallbackData)))); + if (fallbackData = canUseTextInputEvent ? getNativeBeforeInputChars(domEventName, nativeEvent) : getFallbackBeforeInputChars(domEventName, nativeEvent)) + eventType = accumulateTwoPhaseListeners(targetInst, "onBeforeInput"), 0 < eventType.length && (handleEventFunc = new SyntheticCompositionEvent("onBeforeInput", "beforeinput", null, nativeEvent, nativeEventTarget), dispatchQueue.push({ + event: handleEventFunc, + listeners: eventType + }), handleEventFunc.data = fallbackData); + extractEvents$1(dispatchQueue, domEventName, targetInst, nativeEvent, nativeEventTarget); + } + processDispatchQueue(dispatchQueue, eventSystemFlags); + }); +} +function createDispatchListener(instance, listener, currentTarget) { + return { + instance, + listener, + currentTarget + }; +} +function accumulateTwoPhaseListeners(targetFiber, reactName) { + for (var captureName = reactName + "Capture", listeners = [];targetFiber !== null; ) { + var _instance2 = targetFiber, stateNode = _instance2.stateNode; + _instance2 = _instance2.tag; + _instance2 !== 5 && _instance2 !== 26 && _instance2 !== 27 || stateNode === null || (_instance2 = getListener(targetFiber, captureName), _instance2 != null && listeners.unshift(createDispatchListener(targetFiber, _instance2, stateNode)), _instance2 = getListener(targetFiber, reactName), _instance2 != null && listeners.push(createDispatchListener(targetFiber, _instance2, stateNode))); + if (targetFiber.tag === 3) + return listeners; + targetFiber = targetFiber.return; + } + return []; +} +function getParent(inst) { + if (inst === null) + return null; + do + inst = inst.return; + while (inst && inst.tag !== 5 && inst.tag !== 27); + return inst ? inst : null; +} +function accumulateEnterLeaveListenersForEvent(dispatchQueue, event, target, common, inCapturePhase) { + for (var registrationName = event._reactName, listeners = [];target !== null && target !== common; ) { + var _instance3 = target, alternate = _instance3.alternate, stateNode = _instance3.stateNode; + _instance3 = _instance3.tag; + if (alternate !== null && alternate === common) + break; + _instance3 !== 5 && _instance3 !== 26 && _instance3 !== 27 || stateNode === null || (alternate = stateNode, inCapturePhase ? (stateNode = getListener(target, registrationName), stateNode != null && listeners.unshift(createDispatchListener(target, stateNode, alternate))) : inCapturePhase || (stateNode = getListener(target, registrationName), stateNode != null && listeners.push(createDispatchListener(target, stateNode, alternate)))); + target = target.return; + } + listeners.length !== 0 && dispatchQueue.push({ event, listeners }); +} +function normalizeMarkupForTextOrAttribute(markup) { + return (typeof markup === "string" ? markup : "" + markup).replace(NORMALIZE_NEWLINES_REGEX, ` +`).replace(NORMALIZE_NULL_AND_REPLACEMENT_REGEX, ""); +} +function checkForUnmatchedText(serverText, clientText) { + clientText = normalizeMarkupForTextOrAttribute(clientText); + return normalizeMarkupForTextOrAttribute(serverText) === clientText ? true : false; +} +function setProp(domElement, tag, key, value, props, prevValue) { + switch (key) { + case "children": + typeof value === "string" ? tag === "body" || tag === "textarea" && value === "" || setTextContent(domElement, value) : (typeof value === "number" || typeof value === "bigint") && tag !== "body" && setTextContent(domElement, "" + value); + break; + case "className": + setValueForKnownAttribute(domElement, "class", value); + break; + case "tabIndex": + setValueForKnownAttribute(domElement, "tabindex", value); + break; + case "dir": + case "role": + case "viewBox": + case "width": + case "height": + setValueForKnownAttribute(domElement, key, value); + break; + case "style": + setValueForStyles(domElement, value, prevValue); + break; + case "data": + if (tag !== "object") { + setValueForKnownAttribute(domElement, "data", value); + break; + } + case "src": + case "href": + if (value === "" && (tag !== "a" || key !== "href")) { + domElement.removeAttribute(key); + break; + } + if (value == null || typeof value === "function" || typeof value === "symbol" || typeof value === "boolean") { + domElement.removeAttribute(key); + break; + } + value = sanitizeURL("" + value); + domElement.setAttribute(key, value); + break; + case "action": + case "formAction": + if (typeof value === "function") { + domElement.setAttribute(key, "javascript:throw new Error('A React form was unexpectedly submitted. If you called form.submit() manually, consider using form.requestSubmit() instead. If you\\'re trying to use event.stopPropagation() in a submit event handler, consider also calling event.preventDefault().')"); + break; + } else + typeof prevValue === "function" && (key === "formAction" ? (tag !== "input" && setProp(domElement, tag, "name", props.name, props, null), setProp(domElement, tag, "formEncType", props.formEncType, props, null), setProp(domElement, tag, "formMethod", props.formMethod, props, null), setProp(domElement, tag, "formTarget", props.formTarget, props, null)) : (setProp(domElement, tag, "encType", props.encType, props, null), setProp(domElement, tag, "method", props.method, props, null), setProp(domElement, tag, "target", props.target, props, null))); + if (value == null || typeof value === "symbol" || typeof value === "boolean") { + domElement.removeAttribute(key); + break; + } + value = sanitizeURL("" + value); + domElement.setAttribute(key, value); + break; + case "onClick": + value != null && (domElement.onclick = noop$1); + break; + case "onScroll": + value != null && listenToNonDelegatedEvent("scroll", domElement); + break; + case "onScrollEnd": + value != null && listenToNonDelegatedEvent("scrollend", domElement); + break; + case "dangerouslySetInnerHTML": + if (value != null) { + if (typeof value !== "object" || !("__html" in value)) + throw Error(formatProdErrorMessage2(61)); + key = value.__html; + if (key != null) { + if (props.children != null) + throw Error(formatProdErrorMessage2(60)); + domElement.innerHTML = key; + } + } + break; + case "multiple": + domElement.multiple = value && typeof value !== "function" && typeof value !== "symbol"; + break; + case "muted": + domElement.muted = value && typeof value !== "function" && typeof value !== "symbol"; + break; + case "suppressContentEditableWarning": + case "suppressHydrationWarning": + case "defaultValue": + case "defaultChecked": + case "innerHTML": + case "ref": + break; + case "autoFocus": + break; + case "xlinkHref": + if (value == null || typeof value === "function" || typeof value === "boolean" || typeof value === "symbol") { + domElement.removeAttribute("xlink:href"); + break; + } + key = sanitizeURL("" + value); + domElement.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", key); + break; + case "contentEditable": + case "spellCheck": + case "draggable": + case "value": + case "autoReverse": + case "externalResourcesRequired": + case "focusable": + case "preserveAlpha": + value != null && typeof value !== "function" && typeof value !== "symbol" ? domElement.setAttribute(key, "" + value) : domElement.removeAttribute(key); + break; + case "inert": + case "allowFullScreen": + case "async": + case "autoPlay": + case "controls": + case "default": + case "defer": + case "disabled": + case "disablePictureInPicture": + case "disableRemotePlayback": + case "formNoValidate": + case "hidden": + case "loop": + case "noModule": + case "noValidate": + case "open": + case "playsInline": + case "readOnly": + case "required": + case "reversed": + case "scoped": + case "seamless": + case "itemScope": + value && typeof value !== "function" && typeof value !== "symbol" ? domElement.setAttribute(key, "") : domElement.removeAttribute(key); + break; + case "capture": + case "download": + value === true ? domElement.setAttribute(key, "") : value !== false && value != null && typeof value !== "function" && typeof value !== "symbol" ? domElement.setAttribute(key, value) : domElement.removeAttribute(key); + break; + case "cols": + case "rows": + case "size": + case "span": + value != null && typeof value !== "function" && typeof value !== "symbol" && !isNaN(value) && 1 <= value ? domElement.setAttribute(key, value) : domElement.removeAttribute(key); + break; + case "rowSpan": + case "start": + value == null || typeof value === "function" || typeof value === "symbol" || isNaN(value) ? domElement.removeAttribute(key) : domElement.setAttribute(key, value); + break; + case "popover": + listenToNonDelegatedEvent("beforetoggle", domElement); + listenToNonDelegatedEvent("toggle", domElement); + setValueForAttribute(domElement, "popover", value); + break; + case "xlinkActuate": + setValueForNamespacedAttribute(domElement, "http://www.w3.org/1999/xlink", "xlink:actuate", value); + break; + case "xlinkArcrole": + setValueForNamespacedAttribute(domElement, "http://www.w3.org/1999/xlink", "xlink:arcrole", value); + break; + case "xlinkRole": + setValueForNamespacedAttribute(domElement, "http://www.w3.org/1999/xlink", "xlink:role", value); + break; + case "xlinkShow": + setValueForNamespacedAttribute(domElement, "http://www.w3.org/1999/xlink", "xlink:show", value); + break; + case "xlinkTitle": + setValueForNamespacedAttribute(domElement, "http://www.w3.org/1999/xlink", "xlink:title", value); + break; + case "xlinkType": + setValueForNamespacedAttribute(domElement, "http://www.w3.org/1999/xlink", "xlink:type", value); + break; + case "xmlBase": + setValueForNamespacedAttribute(domElement, "http://www.w3.org/XML/1998/namespace", "xml:base", value); + break; + case "xmlLang": + setValueForNamespacedAttribute(domElement, "http://www.w3.org/XML/1998/namespace", "xml:lang", value); + break; + case "xmlSpace": + setValueForNamespacedAttribute(domElement, "http://www.w3.org/XML/1998/namespace", "xml:space", value); + break; + case "is": + setValueForAttribute(domElement, "is", value); + break; + case "innerText": + case "textContent": + break; + default: + if (!(2 < key.length) || key[0] !== "o" && key[0] !== "O" || key[1] !== "n" && key[1] !== "N") + key = aliases.get(key) || key, setValueForAttribute(domElement, key, value); + } +} +function setPropOnCustomElement(domElement, tag, key, value, props, prevValue) { + switch (key) { + case "style": + setValueForStyles(domElement, value, prevValue); + break; + case "dangerouslySetInnerHTML": + if (value != null) { + if (typeof value !== "object" || !("__html" in value)) + throw Error(formatProdErrorMessage2(61)); + key = value.__html; + if (key != null) { + if (props.children != null) + throw Error(formatProdErrorMessage2(60)); + domElement.innerHTML = key; + } + } + break; + case "children": + typeof value === "string" ? setTextContent(domElement, value) : (typeof value === "number" || typeof value === "bigint") && setTextContent(domElement, "" + value); + break; + case "onScroll": + value != null && listenToNonDelegatedEvent("scroll", domElement); + break; + case "onScrollEnd": + value != null && listenToNonDelegatedEvent("scrollend", domElement); + break; + case "onClick": + value != null && (domElement.onclick = noop$1); + break; + case "suppressContentEditableWarning": + case "suppressHydrationWarning": + case "innerHTML": + case "ref": + break; + case "innerText": + case "textContent": + break; + default: + if (!registrationNameDependencies.hasOwnProperty(key)) + a: { + if (key[0] === "o" && key[1] === "n" && (props = key.endsWith("Capture"), tag = key.slice(2, props ? key.length - 7 : undefined), prevValue = domElement[internalPropsKey] || null, prevValue = prevValue != null ? prevValue[key] : null, typeof prevValue === "function" && domElement.removeEventListener(tag, prevValue, props), typeof value === "function")) { + typeof prevValue !== "function" && prevValue !== null && (key in domElement ? domElement[key] = null : domElement.hasAttribute(key) && domElement.removeAttribute(key)); + domElement.addEventListener(tag, value, props); + break a; + } + key in domElement ? domElement[key] = value : value === true ? domElement.setAttribute(key, "") : setValueForAttribute(domElement, key, value); + } + } +} +function setInitialProperties(domElement, tag, props) { + switch (tag) { + case "div": + case "span": + case "svg": + case "path": + case "a": + case "g": + case "p": + case "li": + break; + case "img": + listenToNonDelegatedEvent("error", domElement); + listenToNonDelegatedEvent("load", domElement); + var hasSrc = false, hasSrcSet = false, propKey; + for (propKey in props) + if (props.hasOwnProperty(propKey)) { + var propValue = props[propKey]; + if (propValue != null) + switch (propKey) { + case "src": + hasSrc = true; + break; + case "srcSet": + hasSrcSet = true; + break; + case "children": + case "dangerouslySetInnerHTML": + throw Error(formatProdErrorMessage2(137, tag)); + default: + setProp(domElement, tag, propKey, propValue, props, null); + } + } + hasSrcSet && setProp(domElement, tag, "srcSet", props.srcSet, props, null); + hasSrc && setProp(domElement, tag, "src", props.src, props, null); + return; + case "input": + listenToNonDelegatedEvent("invalid", domElement); + var defaultValue = propKey = propValue = hasSrcSet = null, checked = null, defaultChecked = null; + for (hasSrc in props) + if (props.hasOwnProperty(hasSrc)) { + var propValue$184 = props[hasSrc]; + if (propValue$184 != null) + switch (hasSrc) { + case "name": + hasSrcSet = propValue$184; + break; + case "type": + propValue = propValue$184; + break; + case "checked": + checked = propValue$184; + break; + case "defaultChecked": + defaultChecked = propValue$184; + break; + case "value": + propKey = propValue$184; + break; + case "defaultValue": + defaultValue = propValue$184; + break; + case "children": + case "dangerouslySetInnerHTML": + if (propValue$184 != null) + throw Error(formatProdErrorMessage2(137, tag)); + break; + default: + setProp(domElement, tag, hasSrc, propValue$184, props, null); + } + } + initInput(domElement, propKey, defaultValue, checked, defaultChecked, propValue, hasSrcSet, false); + return; + case "select": + listenToNonDelegatedEvent("invalid", domElement); + hasSrc = propValue = propKey = null; + for (hasSrcSet in props) + if (props.hasOwnProperty(hasSrcSet) && (defaultValue = props[hasSrcSet], defaultValue != null)) + switch (hasSrcSet) { + case "value": + propKey = defaultValue; + break; + case "defaultValue": + propValue = defaultValue; + break; + case "multiple": + hasSrc = defaultValue; + default: + setProp(domElement, tag, hasSrcSet, defaultValue, props, null); + } + tag = propKey; + props = propValue; + domElement.multiple = !!hasSrc; + tag != null ? updateOptions(domElement, !!hasSrc, tag, false) : props != null && updateOptions(domElement, !!hasSrc, props, true); + return; + case "textarea": + listenToNonDelegatedEvent("invalid", domElement); + propKey = hasSrcSet = hasSrc = null; + for (propValue in props) + if (props.hasOwnProperty(propValue) && (defaultValue = props[propValue], defaultValue != null)) + switch (propValue) { + case "value": + hasSrc = defaultValue; + break; + case "defaultValue": + hasSrcSet = defaultValue; + break; + case "children": + propKey = defaultValue; + break; + case "dangerouslySetInnerHTML": + if (defaultValue != null) + throw Error(formatProdErrorMessage2(91)); + break; + default: + setProp(domElement, tag, propValue, defaultValue, props, null); + } + initTextarea(domElement, hasSrc, hasSrcSet, propKey); + return; + case "option": + for (checked in props) + if (props.hasOwnProperty(checked) && (hasSrc = props[checked], hasSrc != null)) + switch (checked) { + case "selected": + domElement.selected = hasSrc && typeof hasSrc !== "function" && typeof hasSrc !== "symbol"; + break; + default: + setProp(domElement, tag, checked, hasSrc, props, null); + } + return; + case "dialog": + listenToNonDelegatedEvent("beforetoggle", domElement); + listenToNonDelegatedEvent("toggle", domElement); + listenToNonDelegatedEvent("cancel", domElement); + listenToNonDelegatedEvent("close", domElement); + break; + case "iframe": + case "object": + listenToNonDelegatedEvent("load", domElement); + break; + case "video": + case "audio": + for (hasSrc = 0;hasSrc < mediaEventTypes.length; hasSrc++) + listenToNonDelegatedEvent(mediaEventTypes[hasSrc], domElement); + break; + case "image": + listenToNonDelegatedEvent("error", domElement); + listenToNonDelegatedEvent("load", domElement); + break; + case "details": + listenToNonDelegatedEvent("toggle", domElement); + break; + case "embed": + case "source": + case "link": + listenToNonDelegatedEvent("error", domElement), listenToNonDelegatedEvent("load", domElement); + case "area": + case "base": + case "br": + case "col": + case "hr": + case "keygen": + case "meta": + case "param": + case "track": + case "wbr": + case "menuitem": + for (defaultChecked in props) + if (props.hasOwnProperty(defaultChecked) && (hasSrc = props[defaultChecked], hasSrc != null)) + switch (defaultChecked) { + case "children": + case "dangerouslySetInnerHTML": + throw Error(formatProdErrorMessage2(137, tag)); + default: + setProp(domElement, tag, defaultChecked, hasSrc, props, null); + } + return; + default: + if (isCustomElement(tag)) { + for (propValue$184 in props) + props.hasOwnProperty(propValue$184) && (hasSrc = props[propValue$184], hasSrc !== undefined && setPropOnCustomElement(domElement, tag, propValue$184, hasSrc, props, undefined)); + return; + } + } + for (defaultValue in props) + props.hasOwnProperty(defaultValue) && (hasSrc = props[defaultValue], hasSrc != null && setProp(domElement, tag, defaultValue, hasSrc, props, null)); +} +function updateProperties(domElement, tag, lastProps, nextProps) { + switch (tag) { + case "div": + case "span": + case "svg": + case "path": + case "a": + case "g": + case "p": + case "li": + break; + case "input": + var name = null, type = null, value = null, defaultValue = null, lastDefaultValue = null, checked = null, defaultChecked = null; + for (propKey in lastProps) { + var lastProp = lastProps[propKey]; + if (lastProps.hasOwnProperty(propKey) && lastProp != null) + switch (propKey) { + case "checked": + break; + case "value": + break; + case "defaultValue": + lastDefaultValue = lastProp; + default: + nextProps.hasOwnProperty(propKey) || setProp(domElement, tag, propKey, null, nextProps, lastProp); + } + } + for (var propKey$201 in nextProps) { + var propKey = nextProps[propKey$201]; + lastProp = lastProps[propKey$201]; + if (nextProps.hasOwnProperty(propKey$201) && (propKey != null || lastProp != null)) + switch (propKey$201) { + case "type": + type = propKey; + break; + case "name": + name = propKey; + break; + case "checked": + checked = propKey; + break; + case "defaultChecked": + defaultChecked = propKey; + break; + case "value": + value = propKey; + break; + case "defaultValue": + defaultValue = propKey; + break; + case "children": + case "dangerouslySetInnerHTML": + if (propKey != null) + throw Error(formatProdErrorMessage2(137, tag)); + break; + default: + propKey !== lastProp && setProp(domElement, tag, propKey$201, propKey, nextProps, lastProp); + } + } + updateInput(domElement, value, defaultValue, lastDefaultValue, checked, defaultChecked, type, name); + return; + case "select": + propKey = value = defaultValue = propKey$201 = null; + for (type in lastProps) + if (lastDefaultValue = lastProps[type], lastProps.hasOwnProperty(type) && lastDefaultValue != null) + switch (type) { + case "value": + break; + case "multiple": + propKey = lastDefaultValue; + default: + nextProps.hasOwnProperty(type) || setProp(domElement, tag, type, null, nextProps, lastDefaultValue); + } + for (name in nextProps) + if (type = nextProps[name], lastDefaultValue = lastProps[name], nextProps.hasOwnProperty(name) && (type != null || lastDefaultValue != null)) + switch (name) { + case "value": + propKey$201 = type; + break; + case "defaultValue": + defaultValue = type; + break; + case "multiple": + value = type; + default: + type !== lastDefaultValue && setProp(domElement, tag, name, type, nextProps, lastDefaultValue); + } + tag = defaultValue; + lastProps = value; + nextProps = propKey; + propKey$201 != null ? updateOptions(domElement, !!lastProps, propKey$201, false) : !!nextProps !== !!lastProps && (tag != null ? updateOptions(domElement, !!lastProps, tag, true) : updateOptions(domElement, !!lastProps, lastProps ? [] : "", false)); + return; + case "textarea": + propKey = propKey$201 = null; + for (defaultValue in lastProps) + if (name = lastProps[defaultValue], lastProps.hasOwnProperty(defaultValue) && name != null && !nextProps.hasOwnProperty(defaultValue)) + switch (defaultValue) { + case "value": + break; + case "children": + break; + default: + setProp(domElement, tag, defaultValue, null, nextProps, name); + } + for (value in nextProps) + if (name = nextProps[value], type = lastProps[value], nextProps.hasOwnProperty(value) && (name != null || type != null)) + switch (value) { + case "value": + propKey$201 = name; + break; + case "defaultValue": + propKey = name; + break; + case "children": + break; + case "dangerouslySetInnerHTML": + if (name != null) + throw Error(formatProdErrorMessage2(91)); + break; + default: + name !== type && setProp(domElement, tag, value, name, nextProps, type); + } + updateTextarea(domElement, propKey$201, propKey); + return; + case "option": + for (var propKey$217 in lastProps) + if (propKey$201 = lastProps[propKey$217], lastProps.hasOwnProperty(propKey$217) && propKey$201 != null && !nextProps.hasOwnProperty(propKey$217)) + switch (propKey$217) { + case "selected": + domElement.selected = false; + break; + default: + setProp(domElement, tag, propKey$217, null, nextProps, propKey$201); + } + for (lastDefaultValue in nextProps) + if (propKey$201 = nextProps[lastDefaultValue], propKey = lastProps[lastDefaultValue], nextProps.hasOwnProperty(lastDefaultValue) && propKey$201 !== propKey && (propKey$201 != null || propKey != null)) + switch (lastDefaultValue) { + case "selected": + domElement.selected = propKey$201 && typeof propKey$201 !== "function" && typeof propKey$201 !== "symbol"; + break; + default: + setProp(domElement, tag, lastDefaultValue, propKey$201, nextProps, propKey); + } + return; + case "img": + case "link": + case "area": + case "base": + case "br": + case "col": + case "embed": + case "hr": + case "keygen": + case "meta": + case "param": + case "source": + case "track": + case "wbr": + case "menuitem": + for (var propKey$222 in lastProps) + propKey$201 = lastProps[propKey$222], lastProps.hasOwnProperty(propKey$222) && propKey$201 != null && !nextProps.hasOwnProperty(propKey$222) && setProp(domElement, tag, propKey$222, null, nextProps, propKey$201); + for (checked in nextProps) + if (propKey$201 = nextProps[checked], propKey = lastProps[checked], nextProps.hasOwnProperty(checked) && propKey$201 !== propKey && (propKey$201 != null || propKey != null)) + switch (checked) { + case "children": + case "dangerouslySetInnerHTML": + if (propKey$201 != null) + throw Error(formatProdErrorMessage2(137, tag)); + break; + default: + setProp(domElement, tag, checked, propKey$201, nextProps, propKey); + } + return; + default: + if (isCustomElement(tag)) { + for (var propKey$227 in lastProps) + propKey$201 = lastProps[propKey$227], lastProps.hasOwnProperty(propKey$227) && propKey$201 !== undefined && !nextProps.hasOwnProperty(propKey$227) && setPropOnCustomElement(domElement, tag, propKey$227, undefined, nextProps, propKey$201); + for (defaultChecked in nextProps) + propKey$201 = nextProps[defaultChecked], propKey = lastProps[defaultChecked], !nextProps.hasOwnProperty(defaultChecked) || propKey$201 === propKey || propKey$201 === undefined && propKey === undefined || setPropOnCustomElement(domElement, tag, defaultChecked, propKey$201, nextProps, propKey); + return; + } + } + for (var propKey$232 in lastProps) + propKey$201 = lastProps[propKey$232], lastProps.hasOwnProperty(propKey$232) && propKey$201 != null && !nextProps.hasOwnProperty(propKey$232) && setProp(domElement, tag, propKey$232, null, nextProps, propKey$201); + for (lastProp in nextProps) + propKey$201 = nextProps[lastProp], propKey = lastProps[lastProp], !nextProps.hasOwnProperty(lastProp) || propKey$201 === propKey || propKey$201 == null && propKey == null || setProp(domElement, tag, lastProp, propKey$201, nextProps, propKey); +} +function isLikelyStaticResource(initiatorType) { + switch (initiatorType) { + case "css": + case "script": + case "font": + case "img": + case "image": + case "input": + case "link": + return true; + default: + return false; + } +} +function estimateBandwidth() { + if (typeof performance.getEntriesByType === "function") { + for (var count = 0, bits = 0, resourceEntries = performance.getEntriesByType("resource"), i = 0;i < resourceEntries.length; i++) { + var entry = resourceEntries[i], transferSize = entry.transferSize, initiatorType = entry.initiatorType, duration = entry.duration; + if (transferSize && duration && isLikelyStaticResource(initiatorType)) { + initiatorType = 0; + duration = entry.responseEnd; + for (i += 1;i < resourceEntries.length; i++) { + var overlapEntry = resourceEntries[i], overlapStartTime = overlapEntry.startTime; + if (overlapStartTime > duration) + break; + var { transferSize: overlapTransferSize, initiatorType: overlapInitiatorType } = overlapEntry; + overlapTransferSize && isLikelyStaticResource(overlapInitiatorType) && (overlapEntry = overlapEntry.responseEnd, initiatorType += overlapTransferSize * (overlapEntry < duration ? 1 : (duration - overlapStartTime) / (overlapEntry - overlapStartTime))); + } + --i; + bits += 8 * (transferSize + initiatorType) / (entry.duration / 1000); + count++; + if (10 < count) + break; + } + } + if (0 < count) + return bits / count / 1e6; + } + return navigator.connection && (count = navigator.connection.downlink, typeof count === "number") ? count : 5; +} +function getOwnerDocumentFromRootContainer(rootContainerElement) { + return rootContainerElement.nodeType === 9 ? rootContainerElement : rootContainerElement.ownerDocument; +} +function getOwnHostContext(namespaceURI) { + switch (namespaceURI) { + case "http://www.w3.org/2000/svg": + return 1; + case "http://www.w3.org/1998/Math/MathML": + return 2; + default: + return 0; + } +} +function getChildHostContextProd(parentNamespace, type) { + if (parentNamespace === 0) + switch (type) { + case "svg": + return 1; + case "math": + return 2; + default: + return 0; + } + return parentNamespace === 1 && type === "foreignObject" ? 0 : parentNamespace; +} +function shouldSetTextContent(type, props) { + return type === "textarea" || type === "noscript" || typeof props.children === "string" || typeof props.children === "number" || typeof props.children === "bigint" || typeof props.dangerouslySetInnerHTML === "object" && props.dangerouslySetInnerHTML !== null && props.dangerouslySetInnerHTML.__html != null; +} +function shouldAttemptEagerTransition() { + var event = window.event; + if (event && event.type === "popstate") { + if (event === currentPopstateTransitionEvent) + return false; + currentPopstateTransitionEvent = event; + return true; + } + currentPopstateTransitionEvent = null; + return false; +} +function handleErrorInNextTick(error) { + setTimeout(function() { + throw error; + }); +} +function isSingletonScope(type) { + return type === "head"; +} +function clearHydrationBoundary(parentInstance, hydrationInstance) { + var node = hydrationInstance, depth = 0; + do { + var nextNode = node.nextSibling; + parentInstance.removeChild(node); + if (nextNode && nextNode.nodeType === 8) + if (node = nextNode.data, node === "/$" || node === "/&") { + if (depth === 0) { + parentInstance.removeChild(nextNode); + retryIfBlockedOn(hydrationInstance); + return; + } + depth--; + } else if (node === "$" || node === "$?" || node === "$~" || node === "$!" || node === "&") + depth++; + else if (node === "html") + releaseSingletonInstance(parentInstance.ownerDocument.documentElement); + else if (node === "head") { + node = parentInstance.ownerDocument.head; + releaseSingletonInstance(node); + for (var node$jscomp$0 = node.firstChild;node$jscomp$0; ) { + var { nextSibling: nextNode$jscomp$0, nodeName } = node$jscomp$0; + node$jscomp$0[internalHoistableMarker] || nodeName === "SCRIPT" || nodeName === "STYLE" || nodeName === "LINK" && node$jscomp$0.rel.toLowerCase() === "stylesheet" || node.removeChild(node$jscomp$0); + node$jscomp$0 = nextNode$jscomp$0; + } + } else + node === "body" && releaseSingletonInstance(parentInstance.ownerDocument.body); + node = nextNode; + } while (node); + retryIfBlockedOn(hydrationInstance); +} +function hideOrUnhideDehydratedBoundary(suspenseInstance, isHidden) { + var node = suspenseInstance; + suspenseInstance = 0; + do { + var nextNode = node.nextSibling; + node.nodeType === 1 ? isHidden ? (node._stashedDisplay = node.style.display, node.style.display = "none") : (node.style.display = node._stashedDisplay || "", node.getAttribute("style") === "" && node.removeAttribute("style")) : node.nodeType === 3 && (isHidden ? (node._stashedText = node.nodeValue, node.nodeValue = "") : node.nodeValue = node._stashedText || ""); + if (nextNode && nextNode.nodeType === 8) + if (node = nextNode.data, node === "/$") + if (suspenseInstance === 0) + break; + else + suspenseInstance--; + else + node !== "$" && node !== "$?" && node !== "$~" && node !== "$!" || suspenseInstance++; + node = nextNode; + } while (node); +} +function clearContainerSparingly(container) { + var nextNode = container.firstChild; + nextNode && nextNode.nodeType === 10 && (nextNode = nextNode.nextSibling); + for (;nextNode; ) { + var node = nextNode; + nextNode = nextNode.nextSibling; + switch (node.nodeName) { + case "HTML": + case "HEAD": + case "BODY": + clearContainerSparingly(node); + detachDeletedInstance(node); + continue; + case "SCRIPT": + case "STYLE": + continue; + case "LINK": + if (node.rel.toLowerCase() === "stylesheet") + continue; + } + container.removeChild(node); + } +} +function canHydrateInstance(instance, type, props, inRootOrSingleton) { + for (;instance.nodeType === 1; ) { + var anyProps = props; + if (instance.nodeName.toLowerCase() !== type.toLowerCase()) { + if (!inRootOrSingleton && (instance.nodeName !== "INPUT" || instance.type !== "hidden")) + break; + } else if (!inRootOrSingleton) + if (type === "input" && instance.type === "hidden") { + var name = anyProps.name == null ? null : "" + anyProps.name; + if (anyProps.type === "hidden" && instance.getAttribute("name") === name) + return instance; + } else + return instance; + else if (!instance[internalHoistableMarker]) + switch (type) { + case "meta": + if (!instance.hasAttribute("itemprop")) + break; + return instance; + case "link": + name = instance.getAttribute("rel"); + if (name === "stylesheet" && instance.hasAttribute("data-precedence")) + break; + else if (name !== anyProps.rel || instance.getAttribute("href") !== (anyProps.href == null || anyProps.href === "" ? null : anyProps.href) || instance.getAttribute("crossorigin") !== (anyProps.crossOrigin == null ? null : anyProps.crossOrigin) || instance.getAttribute("title") !== (anyProps.title == null ? null : anyProps.title)) + break; + return instance; + case "style": + if (instance.hasAttribute("data-precedence")) + break; + return instance; + case "script": + name = instance.getAttribute("src"); + if ((name !== (anyProps.src == null ? null : anyProps.src) || instance.getAttribute("type") !== (anyProps.type == null ? null : anyProps.type) || instance.getAttribute("crossorigin") !== (anyProps.crossOrigin == null ? null : anyProps.crossOrigin)) && name && instance.hasAttribute("async") && !instance.hasAttribute("itemprop")) + break; + return instance; + default: + return instance; + } + instance = getNextHydratable(instance.nextSibling); + if (instance === null) + break; + } + return null; +} +function canHydrateTextInstance(instance, text, inRootOrSingleton) { + if (text === "") + return null; + for (;instance.nodeType !== 3; ) { + if ((instance.nodeType !== 1 || instance.nodeName !== "INPUT" || instance.type !== "hidden") && !inRootOrSingleton) + return null; + instance = getNextHydratable(instance.nextSibling); + if (instance === null) + return null; + } + return instance; +} +function canHydrateHydrationBoundary(instance, inRootOrSingleton) { + for (;instance.nodeType !== 8; ) { + if ((instance.nodeType !== 1 || instance.nodeName !== "INPUT" || instance.type !== "hidden") && !inRootOrSingleton) + return null; + instance = getNextHydratable(instance.nextSibling); + if (instance === null) + return null; + } + return instance; +} +function isSuspenseInstancePending(instance) { + return instance.data === "$?" || instance.data === "$~"; +} +function isSuspenseInstanceFallback(instance) { + return instance.data === "$!" || instance.data === "$?" && instance.ownerDocument.readyState !== "loading"; +} +function registerSuspenseInstanceRetry(instance, callback) { + var ownerDocument = instance.ownerDocument; + if (instance.data === "$~") + instance._reactRetry = callback; + else if (instance.data !== "$?" || ownerDocument.readyState !== "loading") + callback(); + else { + var listener = function() { + callback(); + ownerDocument.removeEventListener("DOMContentLoaded", listener); + }; + ownerDocument.addEventListener("DOMContentLoaded", listener); + instance._reactRetry = listener; + } +} +function getNextHydratable(node) { + for (;node != null; node = node.nextSibling) { + var nodeType = node.nodeType; + if (nodeType === 1 || nodeType === 3) + break; + if (nodeType === 8) { + nodeType = node.data; + if (nodeType === "$" || nodeType === "$!" || nodeType === "$?" || nodeType === "$~" || nodeType === "&" || nodeType === "F!" || nodeType === "F") + break; + if (nodeType === "/$" || nodeType === "/&") + return null; + } + } + return node; +} +function getNextHydratableInstanceAfterHydrationBoundary(hydrationInstance) { + hydrationInstance = hydrationInstance.nextSibling; + for (var depth = 0;hydrationInstance; ) { + if (hydrationInstance.nodeType === 8) { + var data = hydrationInstance.data; + if (data === "/$" || data === "/&") { + if (depth === 0) + return getNextHydratable(hydrationInstance.nextSibling); + depth--; + } else + data !== "$" && data !== "$!" && data !== "$?" && data !== "$~" && data !== "&" || depth++; + } + hydrationInstance = hydrationInstance.nextSibling; + } + return null; +} +function getParentHydrationBoundary(targetInstance) { + targetInstance = targetInstance.previousSibling; + for (var depth = 0;targetInstance; ) { + if (targetInstance.nodeType === 8) { + var data = targetInstance.data; + if (data === "$" || data === "$!" || data === "$?" || data === "$~" || data === "&") { + if (depth === 0) + return targetInstance; + depth--; + } else + data !== "/$" && data !== "/&" || depth++; + } + targetInstance = targetInstance.previousSibling; + } + return null; +} +function resolveSingletonInstance(type, props, rootContainerInstance) { + props = getOwnerDocumentFromRootContainer(rootContainerInstance); + switch (type) { + case "html": + type = props.documentElement; + if (!type) + throw Error(formatProdErrorMessage2(452)); + return type; + case "head": + type = props.head; + if (!type) + throw Error(formatProdErrorMessage2(453)); + return type; + case "body": + type = props.body; + if (!type) + throw Error(formatProdErrorMessage2(454)); + return type; + default: + throw Error(formatProdErrorMessage2(451)); + } +} +function releaseSingletonInstance(instance) { + for (var attributes = instance.attributes;attributes.length; ) + instance.removeAttributeNode(attributes[0]); + detachDeletedInstance(instance); +} +function getHoistableRoot(container) { + return typeof container.getRootNode === "function" ? container.getRootNode() : container.nodeType === 9 ? container : container.ownerDocument; +} +function flushSyncWork() { + var previousWasRendering = previousDispatcher.f(), wasRendering = flushSyncWork$1(); + return previousWasRendering || wasRendering; +} +function requestFormReset(form) { + var formInst = getInstanceFromNode(form); + formInst !== null && formInst.tag === 5 && formInst.type === "form" ? requestFormReset$1(formInst) : previousDispatcher.r(form); +} +function preconnectAs(rel, href, crossOrigin) { + var ownerDocument = globalDocument; + if (ownerDocument && typeof href === "string" && href) { + var limitedEscapedHref = escapeSelectorAttributeValueInsideDoubleQuotes(href); + limitedEscapedHref = 'link[rel="' + rel + '"][href="' + limitedEscapedHref + '"]'; + typeof crossOrigin === "string" && (limitedEscapedHref += '[crossorigin="' + crossOrigin + '"]'); + preconnectsSet.has(limitedEscapedHref) || (preconnectsSet.add(limitedEscapedHref), rel = { rel, crossOrigin, href }, ownerDocument.querySelector(limitedEscapedHref) === null && (href = ownerDocument.createElement("link"), setInitialProperties(href, "link", rel), markNodeAsHoistable(href), ownerDocument.head.appendChild(href))); + } +} +function prefetchDNS(href) { + previousDispatcher.D(href); + preconnectAs("dns-prefetch", href, null); +} +function preconnect(href, crossOrigin) { + previousDispatcher.C(href, crossOrigin); + preconnectAs("preconnect", href, crossOrigin); +} +function preload(href, as, options2) { + previousDispatcher.L(href, as, options2); + var ownerDocument = globalDocument; + if (ownerDocument && href && as) { + var preloadSelector = 'link[rel="preload"][as="' + escapeSelectorAttributeValueInsideDoubleQuotes(as) + '"]'; + as === "image" ? options2 && options2.imageSrcSet ? (preloadSelector += '[imagesrcset="' + escapeSelectorAttributeValueInsideDoubleQuotes(options2.imageSrcSet) + '"]', typeof options2.imageSizes === "string" && (preloadSelector += '[imagesizes="' + escapeSelectorAttributeValueInsideDoubleQuotes(options2.imageSizes) + '"]')) : preloadSelector += '[href="' + escapeSelectorAttributeValueInsideDoubleQuotes(href) + '"]' : preloadSelector += '[href="' + escapeSelectorAttributeValueInsideDoubleQuotes(href) + '"]'; + var key = preloadSelector; + switch (as) { + case "style": + key = getStyleKey(href); + break; + case "script": + key = getScriptKey(href); + } + preloadPropsMap.has(key) || (href = assign2({ + rel: "preload", + href: as === "image" && options2 && options2.imageSrcSet ? undefined : href, + as + }, options2), preloadPropsMap.set(key, href), ownerDocument.querySelector(preloadSelector) !== null || as === "style" && ownerDocument.querySelector(getStylesheetSelectorFromKey(key)) || as === "script" && ownerDocument.querySelector(getScriptSelectorFromKey(key)) || (as = ownerDocument.createElement("link"), setInitialProperties(as, "link", href), markNodeAsHoistable(as), ownerDocument.head.appendChild(as))); + } +} +function preloadModule(href, options2) { + previousDispatcher.m(href, options2); + var ownerDocument = globalDocument; + if (ownerDocument && href) { + var as = options2 && typeof options2.as === "string" ? options2.as : "script", preloadSelector = 'link[rel="modulepreload"][as="' + escapeSelectorAttributeValueInsideDoubleQuotes(as) + '"][href="' + escapeSelectorAttributeValueInsideDoubleQuotes(href) + '"]', key = preloadSelector; + switch (as) { + case "audioworklet": + case "paintworklet": + case "serviceworker": + case "sharedworker": + case "worker": + case "script": + key = getScriptKey(href); + } + if (!preloadPropsMap.has(key) && (href = assign2({ rel: "modulepreload", href }, options2), preloadPropsMap.set(key, href), ownerDocument.querySelector(preloadSelector) === null)) { + switch (as) { + case "audioworklet": + case "paintworklet": + case "serviceworker": + case "sharedworker": + case "worker": + case "script": + if (ownerDocument.querySelector(getScriptSelectorFromKey(key))) + return; + } + as = ownerDocument.createElement("link"); + setInitialProperties(as, "link", href); + markNodeAsHoistable(as); + ownerDocument.head.appendChild(as); + } + } +} +function preinitStyle(href, precedence, options2) { + previousDispatcher.S(href, precedence, options2); + var ownerDocument = globalDocument; + if (ownerDocument && href) { + var styles = getResourcesFromRoot(ownerDocument).hoistableStyles, key = getStyleKey(href); + precedence = precedence || "default"; + var resource = styles.get(key); + if (!resource) { + var state = { loading: 0, preload: null }; + if (resource = ownerDocument.querySelector(getStylesheetSelectorFromKey(key))) + state.loading = 5; + else { + href = assign2({ rel: "stylesheet", href, "data-precedence": precedence }, options2); + (options2 = preloadPropsMap.get(key)) && adoptPreloadPropsForStylesheet(href, options2); + var link = resource = ownerDocument.createElement("link"); + markNodeAsHoistable(link); + setInitialProperties(link, "link", href); + link._p = new Promise(function(resolve, reject) { + link.onload = resolve; + link.onerror = reject; + }); + link.addEventListener("load", function() { + state.loading |= 1; + }); + link.addEventListener("error", function() { + state.loading |= 2; + }); + state.loading |= 4; + insertStylesheet(resource, precedence, ownerDocument); + } + resource = { + type: "stylesheet", + instance: resource, + count: 1, + state + }; + styles.set(key, resource); + } + } +} +function preinitScript(src, options2) { + previousDispatcher.X(src, options2); + var ownerDocument = globalDocument; + if (ownerDocument && src) { + var scripts = getResourcesFromRoot(ownerDocument).hoistableScripts, key = getScriptKey(src), resource = scripts.get(key); + resource || (resource = ownerDocument.querySelector(getScriptSelectorFromKey(key)), resource || (src = assign2({ src, async: true }, options2), (options2 = preloadPropsMap.get(key)) && adoptPreloadPropsForScript(src, options2), resource = ownerDocument.createElement("script"), markNodeAsHoistable(resource), setInitialProperties(resource, "link", src), ownerDocument.head.appendChild(resource)), resource = { + type: "script", + instance: resource, + count: 1, + state: null + }, scripts.set(key, resource)); + } +} +function preinitModuleScript(src, options2) { + previousDispatcher.M(src, options2); + var ownerDocument = globalDocument; + if (ownerDocument && src) { + var scripts = getResourcesFromRoot(ownerDocument).hoistableScripts, key = getScriptKey(src), resource = scripts.get(key); + resource || (resource = ownerDocument.querySelector(getScriptSelectorFromKey(key)), resource || (src = assign2({ src, async: true, type: "module" }, options2), (options2 = preloadPropsMap.get(key)) && adoptPreloadPropsForScript(src, options2), resource = ownerDocument.createElement("script"), markNodeAsHoistable(resource), setInitialProperties(resource, "link", src), ownerDocument.head.appendChild(resource)), resource = { + type: "script", + instance: resource, + count: 1, + state: null + }, scripts.set(key, resource)); + } +} +function getResource(type, currentProps, pendingProps, currentResource) { + var JSCompiler_inline_result = (JSCompiler_inline_result = rootInstanceStackCursor.current) ? getHoistableRoot(JSCompiler_inline_result) : null; + if (!JSCompiler_inline_result) + throw Error(formatProdErrorMessage2(446)); + switch (type) { + case "meta": + case "title": + return null; + case "style": + return typeof pendingProps.precedence === "string" && typeof pendingProps.href === "string" ? (currentProps = getStyleKey(pendingProps.href), pendingProps = getResourcesFromRoot(JSCompiler_inline_result).hoistableStyles, currentResource = pendingProps.get(currentProps), currentResource || (currentResource = { + type: "style", + instance: null, + count: 0, + state: null + }, pendingProps.set(currentProps, currentResource)), currentResource) : { type: "void", instance: null, count: 0, state: null }; + case "link": + if (pendingProps.rel === "stylesheet" && typeof pendingProps.href === "string" && typeof pendingProps.precedence === "string") { + type = getStyleKey(pendingProps.href); + var styles$243 = getResourcesFromRoot(JSCompiler_inline_result).hoistableStyles, resource$244 = styles$243.get(type); + resource$244 || (JSCompiler_inline_result = JSCompiler_inline_result.ownerDocument || JSCompiler_inline_result, resource$244 = { + type: "stylesheet", + instance: null, + count: 0, + state: { loading: 0, preload: null } + }, styles$243.set(type, resource$244), (styles$243 = JSCompiler_inline_result.querySelector(getStylesheetSelectorFromKey(type))) && !styles$243._p && (resource$244.instance = styles$243, resource$244.state.loading = 5), preloadPropsMap.has(type) || (pendingProps = { + rel: "preload", + as: "style", + href: pendingProps.href, + crossOrigin: pendingProps.crossOrigin, + integrity: pendingProps.integrity, + media: pendingProps.media, + hrefLang: pendingProps.hrefLang, + referrerPolicy: pendingProps.referrerPolicy + }, preloadPropsMap.set(type, pendingProps), styles$243 || preloadStylesheet(JSCompiler_inline_result, type, pendingProps, resource$244.state))); + if (currentProps && currentResource === null) + throw Error(formatProdErrorMessage2(528, "")); + return resource$244; + } + if (currentProps && currentResource !== null) + throw Error(formatProdErrorMessage2(529, "")); + return null; + case "script": + return currentProps = pendingProps.async, pendingProps = pendingProps.src, typeof pendingProps === "string" && currentProps && typeof currentProps !== "function" && typeof currentProps !== "symbol" ? (currentProps = getScriptKey(pendingProps), pendingProps = getResourcesFromRoot(JSCompiler_inline_result).hoistableScripts, currentResource = pendingProps.get(currentProps), currentResource || (currentResource = { + type: "script", + instance: null, + count: 0, + state: null + }, pendingProps.set(currentProps, currentResource)), currentResource) : { type: "void", instance: null, count: 0, state: null }; + default: + throw Error(formatProdErrorMessage2(444, type)); + } +} +function getStyleKey(href) { + return 'href="' + escapeSelectorAttributeValueInsideDoubleQuotes(href) + '"'; +} +function getStylesheetSelectorFromKey(key) { + return 'link[rel="stylesheet"][' + key + "]"; +} +function stylesheetPropsFromRawProps(rawProps) { + return assign2({}, rawProps, { + "data-precedence": rawProps.precedence, + precedence: null + }); +} +function preloadStylesheet(ownerDocument, key, preloadProps, state) { + ownerDocument.querySelector('link[rel="preload"][as="style"][' + key + "]") ? state.loading = 1 : (key = ownerDocument.createElement("link"), state.preload = key, key.addEventListener("load", function() { + return state.loading |= 1; + }), key.addEventListener("error", function() { + return state.loading |= 2; + }), setInitialProperties(key, "link", preloadProps), markNodeAsHoistable(key), ownerDocument.head.appendChild(key)); +} +function getScriptKey(src) { + return '[src="' + escapeSelectorAttributeValueInsideDoubleQuotes(src) + '"]'; +} +function getScriptSelectorFromKey(key) { + return "script[async]" + key; +} +function acquireResource(hoistableRoot, resource, props) { + resource.count++; + if (resource.instance === null) + switch (resource.type) { + case "style": + var instance = hoistableRoot.querySelector('style[data-href~="' + escapeSelectorAttributeValueInsideDoubleQuotes(props.href) + '"]'); + if (instance) + return resource.instance = instance, markNodeAsHoistable(instance), instance; + var styleProps = assign2({}, props, { + "data-href": props.href, + "data-precedence": props.precedence, + href: null, + precedence: null + }); + instance = (hoistableRoot.ownerDocument || hoistableRoot).createElement("style"); + markNodeAsHoistable(instance); + setInitialProperties(instance, "style", styleProps); + insertStylesheet(instance, props.precedence, hoistableRoot); + return resource.instance = instance; + case "stylesheet": + styleProps = getStyleKey(props.href); + var instance$249 = hoistableRoot.querySelector(getStylesheetSelectorFromKey(styleProps)); + if (instance$249) + return resource.state.loading |= 4, resource.instance = instance$249, markNodeAsHoistable(instance$249), instance$249; + instance = stylesheetPropsFromRawProps(props); + (styleProps = preloadPropsMap.get(styleProps)) && adoptPreloadPropsForStylesheet(instance, styleProps); + instance$249 = (hoistableRoot.ownerDocument || hoistableRoot).createElement("link"); + markNodeAsHoistable(instance$249); + var linkInstance = instance$249; + linkInstance._p = new Promise(function(resolve, reject) { + linkInstance.onload = resolve; + linkInstance.onerror = reject; + }); + setInitialProperties(instance$249, "link", instance); + resource.state.loading |= 4; + insertStylesheet(instance$249, props.precedence, hoistableRoot); + return resource.instance = instance$249; + case "script": + instance$249 = getScriptKey(props.src); + if (styleProps = hoistableRoot.querySelector(getScriptSelectorFromKey(instance$249))) + return resource.instance = styleProps, markNodeAsHoistable(styleProps), styleProps; + instance = props; + if (styleProps = preloadPropsMap.get(instance$249)) + instance = assign2({}, props), adoptPreloadPropsForScript(instance, styleProps); + hoistableRoot = hoistableRoot.ownerDocument || hoistableRoot; + styleProps = hoistableRoot.createElement("script"); + markNodeAsHoistable(styleProps); + setInitialProperties(styleProps, "link", instance); + hoistableRoot.head.appendChild(styleProps); + return resource.instance = styleProps; + case "void": + return null; + default: + throw Error(formatProdErrorMessage2(443, resource.type)); + } + else + resource.type === "stylesheet" && (resource.state.loading & 4) === 0 && (instance = resource.instance, resource.state.loading |= 4, insertStylesheet(instance, props.precedence, hoistableRoot)); + return resource.instance; +} +function insertStylesheet(instance, precedence, root2) { + for (var nodes = root2.querySelectorAll('link[rel="stylesheet"][data-precedence],style[data-precedence]'), last = nodes.length ? nodes[nodes.length - 1] : null, prior = last, i = 0;i < nodes.length; i++) { + var node = nodes[i]; + if (node.dataset.precedence === precedence) + prior = node; + else if (prior !== last) + break; + } + prior ? prior.parentNode.insertBefore(instance, prior.nextSibling) : (precedence = root2.nodeType === 9 ? root2.head : root2, precedence.insertBefore(instance, precedence.firstChild)); +} +function adoptPreloadPropsForStylesheet(stylesheetProps, preloadProps) { + stylesheetProps.crossOrigin == null && (stylesheetProps.crossOrigin = preloadProps.crossOrigin); + stylesheetProps.referrerPolicy == null && (stylesheetProps.referrerPolicy = preloadProps.referrerPolicy); + stylesheetProps.title == null && (stylesheetProps.title = preloadProps.title); +} +function adoptPreloadPropsForScript(scriptProps, preloadProps) { + scriptProps.crossOrigin == null && (scriptProps.crossOrigin = preloadProps.crossOrigin); + scriptProps.referrerPolicy == null && (scriptProps.referrerPolicy = preloadProps.referrerPolicy); + scriptProps.integrity == null && (scriptProps.integrity = preloadProps.integrity); +} +function getHydratableHoistableCache(type, keyAttribute, ownerDocument) { + if (tagCaches === null) { + var cache = new Map; + var caches = tagCaches = new Map; + caches.set(ownerDocument, cache); + } else + caches = tagCaches, cache = caches.get(ownerDocument), cache || (cache = new Map, caches.set(ownerDocument, cache)); + if (cache.has(type)) + return cache; + cache.set(type, null); + ownerDocument = ownerDocument.getElementsByTagName(type); + for (caches = 0;caches < ownerDocument.length; caches++) { + var node = ownerDocument[caches]; + if (!(node[internalHoistableMarker] || node[internalInstanceKey] || type === "link" && node.getAttribute("rel") === "stylesheet") && node.namespaceURI !== "http://www.w3.org/2000/svg") { + var nodeKey = node.getAttribute(keyAttribute) || ""; + nodeKey = type + nodeKey; + var existing = cache.get(nodeKey); + existing ? existing.push(node) : cache.set(nodeKey, [node]); + } + } + return cache; +} +function mountHoistable(hoistableRoot, type, instance) { + hoistableRoot = hoistableRoot.ownerDocument || hoistableRoot; + hoistableRoot.head.insertBefore(instance, type === "title" ? hoistableRoot.querySelector("head > title") : null); +} +function isHostHoistableType(type, props, hostContext) { + if (hostContext === 1 || props.itemProp != null) + return false; + switch (type) { + case "meta": + case "title": + return true; + case "style": + if (typeof props.precedence !== "string" || typeof props.href !== "string" || props.href === "") + break; + return true; + case "link": + if (typeof props.rel !== "string" || typeof props.href !== "string" || props.href === "" || props.onLoad || props.onError) + break; + switch (props.rel) { + case "stylesheet": + return type = props.disabled, typeof props.precedence === "string" && type == null; + default: + return true; + } + case "script": + if (props.async && typeof props.async !== "function" && typeof props.async !== "symbol" && !props.onLoad && !props.onError && props.src && typeof props.src === "string") + return true; + } + return false; +} +function preloadResource(resource) { + return resource.type === "stylesheet" && (resource.state.loading & 3) === 0 ? false : true; +} +function suspendResource(state, hoistableRoot, resource, props) { + if (resource.type === "stylesheet" && (typeof props.media !== "string" || matchMedia(props.media).matches !== false) && (resource.state.loading & 4) === 0) { + if (resource.instance === null) { + var key = getStyleKey(props.href), instance = hoistableRoot.querySelector(getStylesheetSelectorFromKey(key)); + if (instance) { + hoistableRoot = instance._p; + hoistableRoot !== null && typeof hoistableRoot === "object" && typeof hoistableRoot.then === "function" && (state.count++, state = onUnsuspend.bind(state), hoistableRoot.then(state, state)); + resource.state.loading |= 4; + resource.instance = instance; + markNodeAsHoistable(instance); + return; + } + instance = hoistableRoot.ownerDocument || hoistableRoot; + props = stylesheetPropsFromRawProps(props); + (key = preloadPropsMap.get(key)) && adoptPreloadPropsForStylesheet(props, key); + instance = instance.createElement("link"); + markNodeAsHoistable(instance); + var linkInstance = instance; + linkInstance._p = new Promise(function(resolve, reject) { + linkInstance.onload = resolve; + linkInstance.onerror = reject; + }); + setInitialProperties(instance, "link", props); + resource.instance = instance; + } + state.stylesheets === null && (state.stylesheets = new Map); + state.stylesheets.set(resource, hoistableRoot); + (hoistableRoot = resource.state.preload) && (resource.state.loading & 3) === 0 && (state.count++, resource = onUnsuspend.bind(state), hoistableRoot.addEventListener("load", resource), hoistableRoot.addEventListener("error", resource)); + } +} +function waitForCommitToBeReady(state, timeoutOffset) { + state.stylesheets && state.count === 0 && insertSuspendedStylesheets(state, state.stylesheets); + return 0 < state.count || 0 < state.imgCount ? function(commit) { + var stylesheetTimer = setTimeout(function() { + state.stylesheets && insertSuspendedStylesheets(state, state.stylesheets); + if (state.unsuspend) { + var unsuspend = state.unsuspend; + state.unsuspend = null; + unsuspend(); + } + }, 60000 + timeoutOffset); + 0 < state.imgBytes && estimatedBytesWithinLimit === 0 && (estimatedBytesWithinLimit = 62500 * estimateBandwidth()); + var imgTimer = setTimeout(function() { + state.waitingForImages = false; + if (state.count === 0 && (state.stylesheets && insertSuspendedStylesheets(state, state.stylesheets), state.unsuspend)) { + var unsuspend = state.unsuspend; + state.unsuspend = null; + unsuspend(); + } + }, (state.imgBytes > estimatedBytesWithinLimit ? 50 : 800) + timeoutOffset); + state.unsuspend = commit; + return function() { + state.unsuspend = null; + clearTimeout(stylesheetTimer); + clearTimeout(imgTimer); + }; + } : null; +} +function onUnsuspend() { + this.count--; + if (this.count === 0 && (this.imgCount === 0 || !this.waitingForImages)) { + if (this.stylesheets) + insertSuspendedStylesheets(this, this.stylesheets); + else if (this.unsuspend) { + var unsuspend = this.unsuspend; + this.unsuspend = null; + unsuspend(); + } + } +} +function insertSuspendedStylesheets(state, resources) { + state.stylesheets = null; + state.unsuspend !== null && (state.count++, precedencesByRoot = new Map, resources.forEach(insertStylesheetIntoRoot, state), precedencesByRoot = null, onUnsuspend.call(state)); +} +function insertStylesheetIntoRoot(root2, resource) { + if (!(resource.state.loading & 4)) { + var precedences = precedencesByRoot.get(root2); + if (precedences) + var last = precedences.get(null); + else { + precedences = new Map; + precedencesByRoot.set(root2, precedences); + for (var nodes = root2.querySelectorAll("link[data-precedence],style[data-precedence]"), i = 0;i < nodes.length; i++) { + var node = nodes[i]; + if (node.nodeName === "LINK" || node.getAttribute("media") !== "not all") + precedences.set(node.dataset.precedence, node), last = node; + } + last && precedences.set(null, last); + } + nodes = resource.instance; + node = nodes.getAttribute("data-precedence"); + i = precedences.get(node) || last; + i === last && precedences.set(null, nodes); + precedences.set(node, nodes); + this.count++; + last = onUnsuspend.bind(this); + nodes.addEventListener("load", last); + nodes.addEventListener("error", last); + i ? i.parentNode.insertBefore(nodes, i.nextSibling) : (root2 = root2.nodeType === 9 ? root2.head : root2, root2.insertBefore(nodes, root2.firstChild)); + resource.state.loading |= 4; + } +} +function FiberRootNode(containerInfo, tag, hydrate, identifierPrefix, onUncaughtError, onCaughtError, onRecoverableError, onDefaultTransitionIndicator, formState) { + this.tag = 1; + this.containerInfo = containerInfo; + this.pingCache = this.current = this.pendingChildren = null; + this.timeoutHandle = -1; + this.callbackNode = this.next = this.pendingContext = this.context = this.cancelPendingCommit = null; + this.callbackPriority = 0; + this.expirationTimes = createLaneMap(-1); + this.entangledLanes = this.shellSuspendCounter = this.errorRecoveryDisabledLanes = this.expiredLanes = this.warmLanes = this.pingedLanes = this.suspendedLanes = this.pendingLanes = 0; + this.entanglements = createLaneMap(0); + this.hiddenUpdates = createLaneMap(null); + this.identifierPrefix = identifierPrefix; + this.onUncaughtError = onUncaughtError; + this.onCaughtError = onCaughtError; + this.onRecoverableError = onRecoverableError; + this.pooledCache = null; + this.pooledCacheLanes = 0; + this.formState = formState; + this.incompleteTransitions = new Map; +} +function createFiberRoot(containerInfo, tag, hydrate, initialChildren, hydrationCallbacks, isStrictMode, identifierPrefix, formState, onUncaughtError, onCaughtError, onRecoverableError, onDefaultTransitionIndicator) { + containerInfo = new FiberRootNode(containerInfo, tag, hydrate, identifierPrefix, onUncaughtError, onCaughtError, onRecoverableError, onDefaultTransitionIndicator, formState); + tag = 1; + isStrictMode === true && (tag |= 24); + isStrictMode = createFiberImplClass(3, null, null, tag); + containerInfo.current = isStrictMode; + isStrictMode.stateNode = containerInfo; + tag = createCache(); + tag.refCount++; + containerInfo.pooledCache = tag; + tag.refCount++; + isStrictMode.memoizedState = { + element: initialChildren, + isDehydrated: hydrate, + cache: tag + }; + initializeUpdateQueue(isStrictMode); + return containerInfo; +} +function getContextForSubtree(parentComponent) { + if (!parentComponent) + return emptyContextObject; + parentComponent = emptyContextObject; + return parentComponent; +} +function updateContainerImpl(rootFiber, lane, element, container, parentComponent, callback) { + parentComponent = getContextForSubtree(parentComponent); + container.context === null ? container.context = parentComponent : container.pendingContext = parentComponent; + container = createUpdate(lane); + container.payload = { element }; + callback = callback === undefined ? null : callback; + callback !== null && (container.callback = callback); + element = enqueueUpdate(rootFiber, container, lane); + element !== null && (scheduleUpdateOnFiber(element, rootFiber, lane), entangleTransitions(element, rootFiber, lane)); +} +function markRetryLaneImpl(fiber, retryLane) { + fiber = fiber.memoizedState; + if (fiber !== null && fiber.dehydrated !== null) { + var a = fiber.retryLane; + fiber.retryLane = a !== 0 && a < retryLane ? a : retryLane; + } +} +function markRetryLaneIfNotHydrated(fiber, retryLane) { + markRetryLaneImpl(fiber, retryLane); + (fiber = fiber.alternate) && markRetryLaneImpl(fiber, retryLane); +} +function attemptContinuousHydration(fiber) { + if (fiber.tag === 13 || fiber.tag === 31) { + var root2 = enqueueConcurrentRenderForLane(fiber, 67108864); + root2 !== null && scheduleUpdateOnFiber(root2, fiber, 67108864); + markRetryLaneIfNotHydrated(fiber, 67108864); + } +} +function attemptHydrationAtCurrentPriority(fiber) { + if (fiber.tag === 13 || fiber.tag === 31) { + var lane = requestUpdateLane(); + lane = getBumpedLaneForHydrationByLane(lane); + var root2 = enqueueConcurrentRenderForLane(fiber, lane); + root2 !== null && scheduleUpdateOnFiber(root2, fiber, lane); + markRetryLaneIfNotHydrated(fiber, lane); + } +} +function dispatchDiscreteEvent(domEventName, eventSystemFlags, container, nativeEvent) { + var prevTransition = ReactSharedInternals3.T; + ReactSharedInternals3.T = null; + var previousPriority = ReactDOMSharedInternals.p; + try { + ReactDOMSharedInternals.p = 2, dispatchEvent(domEventName, eventSystemFlags, container, nativeEvent); + } finally { + ReactDOMSharedInternals.p = previousPriority, ReactSharedInternals3.T = prevTransition; + } +} +function dispatchContinuousEvent(domEventName, eventSystemFlags, container, nativeEvent) { + var prevTransition = ReactSharedInternals3.T; + ReactSharedInternals3.T = null; + var previousPriority = ReactDOMSharedInternals.p; + try { + ReactDOMSharedInternals.p = 8, dispatchEvent(domEventName, eventSystemFlags, container, nativeEvent); + } finally { + ReactDOMSharedInternals.p = previousPriority, ReactSharedInternals3.T = prevTransition; + } +} +function dispatchEvent(domEventName, eventSystemFlags, targetContainer, nativeEvent) { + if (_enabled) { + var blockedOn = findInstanceBlockingEvent(nativeEvent); + if (blockedOn === null) + dispatchEventForPluginEventSystem(domEventName, eventSystemFlags, nativeEvent, return_targetInst, targetContainer), clearIfContinuousEvent(domEventName, nativeEvent); + else if (queueIfContinuousEvent(blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent)) + nativeEvent.stopPropagation(); + else if (clearIfContinuousEvent(domEventName, nativeEvent), eventSystemFlags & 4 && -1 < discreteReplayableEvents.indexOf(domEventName)) { + for (;blockedOn !== null; ) { + var fiber = getInstanceFromNode(blockedOn); + if (fiber !== null) + switch (fiber.tag) { + case 3: + fiber = fiber.stateNode; + if (fiber.current.memoizedState.isDehydrated) { + var lanes = getHighestPriorityLanes(fiber.pendingLanes); + if (lanes !== 0) { + var root2 = fiber; + root2.pendingLanes |= 2; + for (root2.entangledLanes |= 2;lanes; ) { + var lane = 1 << 31 - clz32(lanes); + root2.entanglements[1] |= lane; + lanes &= ~lane; + } + ensureRootIsScheduled(fiber); + (executionContext & 6) === 0 && (workInProgressRootRenderTargetTime = now() + 500, flushSyncWorkAcrossRoots_impl(0, false)); + } + } + break; + case 31: + case 13: + root2 = enqueueConcurrentRenderForLane(fiber, 2), root2 !== null && scheduleUpdateOnFiber(root2, fiber, 2), flushSyncWork$1(), markRetryLaneIfNotHydrated(fiber, 2); + } + fiber = findInstanceBlockingEvent(nativeEvent); + fiber === null && dispatchEventForPluginEventSystem(domEventName, eventSystemFlags, nativeEvent, return_targetInst, targetContainer); + if (fiber === blockedOn) + break; + blockedOn = fiber; + } + blockedOn !== null && nativeEvent.stopPropagation(); + } else + dispatchEventForPluginEventSystem(domEventName, eventSystemFlags, nativeEvent, null, targetContainer); + } +} +function findInstanceBlockingEvent(nativeEvent) { + nativeEvent = getEventTarget(nativeEvent); + return findInstanceBlockingTarget(nativeEvent); +} +function findInstanceBlockingTarget(targetNode) { + return_targetInst = null; + targetNode = getClosestInstanceFromNode(targetNode); + if (targetNode !== null) { + var nearestMounted = getNearestMountedFiber(targetNode); + if (nearestMounted === null) + targetNode = null; + else { + var tag = nearestMounted.tag; + if (tag === 13) { + targetNode = getSuspenseInstanceFromFiber(nearestMounted); + if (targetNode !== null) + return targetNode; + targetNode = null; + } else if (tag === 31) { + targetNode = getActivityInstanceFromFiber(nearestMounted); + if (targetNode !== null) + return targetNode; + targetNode = null; + } else if (tag === 3) { + if (nearestMounted.stateNode.current.memoizedState.isDehydrated) + return nearestMounted.tag === 3 ? nearestMounted.stateNode.containerInfo : null; + targetNode = null; + } else + nearestMounted !== targetNode && (targetNode = null); + } + } + return_targetInst = targetNode; + return null; +} +function getEventPriority(domEventName) { + switch (domEventName) { + case "beforetoggle": + case "cancel": + case "click": + case "close": + case "contextmenu": + case "copy": + case "cut": + case "auxclick": + case "dblclick": + case "dragend": + case "dragstart": + case "drop": + case "focusin": + case "focusout": + case "input": + case "invalid": + case "keydown": + case "keypress": + case "keyup": + case "mousedown": + case "mouseup": + case "paste": + case "pause": + case "play": + case "pointercancel": + case "pointerdown": + case "pointerup": + case "ratechange": + case "reset": + case "resize": + case "seeked": + case "submit": + case "toggle": + case "touchcancel": + case "touchend": + case "touchstart": + case "volumechange": + case "change": + case "selectionchange": + case "textInput": + case "compositionstart": + case "compositionend": + case "compositionupdate": + case "beforeblur": + case "afterblur": + case "beforeinput": + case "blur": + case "fullscreenchange": + case "focus": + case "hashchange": + case "popstate": + case "select": + case "selectstart": + return 2; + case "drag": + case "dragenter": + case "dragexit": + case "dragleave": + case "dragover": + case "mousemove": + case "mouseout": + case "mouseover": + case "pointermove": + case "pointerout": + case "pointerover": + case "scroll": + case "touchmove": + case "wheel": + case "mouseenter": + case "mouseleave": + case "pointerenter": + case "pointerleave": + return 8; + case "message": + switch (getCurrentPriorityLevel()) { + case ImmediatePriority: + return 2; + case UserBlockingPriority: + return 8; + case NormalPriority$1: + case LowPriority: + return 32; + case IdlePriority: + return 268435456; + default: + return 32; + } + default: + return 32; + } +} +function clearIfContinuousEvent(domEventName, nativeEvent) { + switch (domEventName) { + case "focusin": + case "focusout": + queuedFocus = null; + break; + case "dragenter": + case "dragleave": + queuedDrag = null; + break; + case "mouseover": + case "mouseout": + queuedMouse = null; + break; + case "pointerover": + case "pointerout": + queuedPointers.delete(nativeEvent.pointerId); + break; + case "gotpointercapture": + case "lostpointercapture": + queuedPointerCaptures.delete(nativeEvent.pointerId); + } +} +function accumulateOrCreateContinuousQueuedReplayableEvent(existingQueuedEvent, blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent) { + if (existingQueuedEvent === null || existingQueuedEvent.nativeEvent !== nativeEvent) + return existingQueuedEvent = { + blockedOn, + domEventName, + eventSystemFlags, + nativeEvent, + targetContainers: [targetContainer] + }, blockedOn !== null && (blockedOn = getInstanceFromNode(blockedOn), blockedOn !== null && attemptContinuousHydration(blockedOn)), existingQueuedEvent; + existingQueuedEvent.eventSystemFlags |= eventSystemFlags; + blockedOn = existingQueuedEvent.targetContainers; + targetContainer !== null && blockedOn.indexOf(targetContainer) === -1 && blockedOn.push(targetContainer); + return existingQueuedEvent; +} +function queueIfContinuousEvent(blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent) { + switch (domEventName) { + case "focusin": + return queuedFocus = accumulateOrCreateContinuousQueuedReplayableEvent(queuedFocus, blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent), true; + case "dragenter": + return queuedDrag = accumulateOrCreateContinuousQueuedReplayableEvent(queuedDrag, blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent), true; + case "mouseover": + return queuedMouse = accumulateOrCreateContinuousQueuedReplayableEvent(queuedMouse, blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent), true; + case "pointerover": + var pointerId = nativeEvent.pointerId; + queuedPointers.set(pointerId, accumulateOrCreateContinuousQueuedReplayableEvent(queuedPointers.get(pointerId) || null, blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent)); + return true; + case "gotpointercapture": + return pointerId = nativeEvent.pointerId, queuedPointerCaptures.set(pointerId, accumulateOrCreateContinuousQueuedReplayableEvent(queuedPointerCaptures.get(pointerId) || null, blockedOn, domEventName, eventSystemFlags, targetContainer, nativeEvent)), true; + } + return false; +} +function attemptExplicitHydrationTarget(queuedTarget) { + var targetInst = getClosestInstanceFromNode(queuedTarget.target); + if (targetInst !== null) { + var nearestMounted = getNearestMountedFiber(targetInst); + if (nearestMounted !== null) { + if (targetInst = nearestMounted.tag, targetInst === 13) { + if (targetInst = getSuspenseInstanceFromFiber(nearestMounted), targetInst !== null) { + queuedTarget.blockedOn = targetInst; + runWithPriority(queuedTarget.priority, function() { + attemptHydrationAtCurrentPriority(nearestMounted); + }); + return; + } + } else if (targetInst === 31) { + if (targetInst = getActivityInstanceFromFiber(nearestMounted), targetInst !== null) { + queuedTarget.blockedOn = targetInst; + runWithPriority(queuedTarget.priority, function() { + attemptHydrationAtCurrentPriority(nearestMounted); + }); + return; + } + } else if (targetInst === 3 && nearestMounted.stateNode.current.memoizedState.isDehydrated) { + queuedTarget.blockedOn = nearestMounted.tag === 3 ? nearestMounted.stateNode.containerInfo : null; + return; + } + } + } + queuedTarget.blockedOn = null; +} +function attemptReplayContinuousQueuedEvent(queuedEvent) { + if (queuedEvent.blockedOn !== null) + return false; + for (var targetContainers = queuedEvent.targetContainers;0 < targetContainers.length; ) { + var nextBlockedOn = findInstanceBlockingEvent(queuedEvent.nativeEvent); + if (nextBlockedOn === null) { + nextBlockedOn = queuedEvent.nativeEvent; + var nativeEventClone = new nextBlockedOn.constructor(nextBlockedOn.type, nextBlockedOn); + currentReplayingEvent = nativeEventClone; + nextBlockedOn.target.dispatchEvent(nativeEventClone); + currentReplayingEvent = null; + } else + return targetContainers = getInstanceFromNode(nextBlockedOn), targetContainers !== null && attemptContinuousHydration(targetContainers), queuedEvent.blockedOn = nextBlockedOn, false; + targetContainers.shift(); + } + return true; +} +function attemptReplayContinuousQueuedEventInMap(queuedEvent, key, map) { + attemptReplayContinuousQueuedEvent(queuedEvent) && map.delete(key); +} +function replayUnblockedEvents() { + hasScheduledReplayAttempt = false; + queuedFocus !== null && attemptReplayContinuousQueuedEvent(queuedFocus) && (queuedFocus = null); + queuedDrag !== null && attemptReplayContinuousQueuedEvent(queuedDrag) && (queuedDrag = null); + queuedMouse !== null && attemptReplayContinuousQueuedEvent(queuedMouse) && (queuedMouse = null); + queuedPointers.forEach(attemptReplayContinuousQueuedEventInMap); + queuedPointerCaptures.forEach(attemptReplayContinuousQueuedEventInMap); +} +function scheduleCallbackIfUnblocked(queuedEvent, unblocked) { + queuedEvent.blockedOn === unblocked && (queuedEvent.blockedOn = null, hasScheduledReplayAttempt || (hasScheduledReplayAttempt = true, Scheduler.unstable_scheduleCallback(Scheduler.unstable_NormalPriority, replayUnblockedEvents))); +} +function scheduleReplayQueueIfNeeded(formReplayingQueue) { + lastScheduledReplayQueue !== formReplayingQueue && (lastScheduledReplayQueue = formReplayingQueue, Scheduler.unstable_scheduleCallback(Scheduler.unstable_NormalPriority, function() { + lastScheduledReplayQueue === formReplayingQueue && (lastScheduledReplayQueue = null); + for (var i = 0;i < formReplayingQueue.length; i += 3) { + var form = formReplayingQueue[i], submitterOrAction = formReplayingQueue[i + 1], formData = formReplayingQueue[i + 2]; + if (typeof submitterOrAction !== "function") + if (findInstanceBlockingTarget(submitterOrAction || form) === null) + continue; + else + break; + var formInst = getInstanceFromNode(form); + formInst !== null && (formReplayingQueue.splice(i, 3), i -= 3, startHostTransition(formInst, { + pending: true, + data: formData, + method: form.method, + action: submitterOrAction + }, submitterOrAction, formData)); + } + })); +} +function retryIfBlockedOn(unblocked) { + function unblock(queuedEvent) { + return scheduleCallbackIfUnblocked(queuedEvent, unblocked); + } + queuedFocus !== null && scheduleCallbackIfUnblocked(queuedFocus, unblocked); + queuedDrag !== null && scheduleCallbackIfUnblocked(queuedDrag, unblocked); + queuedMouse !== null && scheduleCallbackIfUnblocked(queuedMouse, unblocked); + queuedPointers.forEach(unblock); + queuedPointerCaptures.forEach(unblock); + for (var i = 0;i < queuedExplicitHydrationTargets.length; i++) { + var queuedTarget = queuedExplicitHydrationTargets[i]; + queuedTarget.blockedOn === unblocked && (queuedTarget.blockedOn = null); + } + for (;0 < queuedExplicitHydrationTargets.length && (i = queuedExplicitHydrationTargets[0], i.blockedOn === null); ) + attemptExplicitHydrationTarget(i), i.blockedOn === null && queuedExplicitHydrationTargets.shift(); + i = (unblocked.ownerDocument || unblocked).$$reactFormReplay; + if (i != null) + for (queuedTarget = 0;queuedTarget < i.length; queuedTarget += 3) { + var form = i[queuedTarget], submitterOrAction = i[queuedTarget + 1], formProps = form[internalPropsKey] || null; + if (typeof submitterOrAction === "function") + formProps || scheduleReplayQueueIfNeeded(i); + else if (formProps) { + var action = null; + if (submitterOrAction && submitterOrAction.hasAttribute("formAction")) + if (form = submitterOrAction, formProps = submitterOrAction[internalPropsKey] || null) + action = formProps.formAction; + else { + if (findInstanceBlockingTarget(form) !== null) + continue; + } + else + action = formProps.action; + typeof action === "function" ? i[queuedTarget + 1] = action : (i.splice(queuedTarget, 3), queuedTarget -= 3); + scheduleReplayQueueIfNeeded(i); + } + } +} +function defaultOnDefaultTransitionIndicator() { + function handleNavigate(event) { + event.canIntercept && event.info === "react-transition" && event.intercept({ + handler: function() { + return new Promise(function(resolve) { + return pendingResolve = resolve; + }); + }, + focusReset: "manual", + scroll: "manual" + }); + } + function handleNavigateComplete() { + pendingResolve !== null && (pendingResolve(), pendingResolve = null); + isCancelled || setTimeout(startFakeNavigation, 20); + } + function startFakeNavigation() { + if (!isCancelled && !navigation.transition) { + var currentEntry = navigation.currentEntry; + currentEntry && currentEntry.url != null && navigation.navigate(currentEntry.url, { + state: currentEntry.getState(), + info: "react-transition", + history: "replace" + }); + } + } + if (typeof navigation === "object") { + var isCancelled = false, pendingResolve = null; + navigation.addEventListener("navigate", handleNavigate); + navigation.addEventListener("navigatesuccess", handleNavigateComplete); + navigation.addEventListener("navigateerror", handleNavigateComplete); + setTimeout(startFakeNavigation, 100); + return function() { + isCancelled = true; + navigation.removeEventListener("navigate", handleNavigate); + navigation.removeEventListener("navigatesuccess", handleNavigateComplete); + navigation.removeEventListener("navigateerror", handleNavigateComplete); + pendingResolve !== null && (pendingResolve(), pendingResolve = null); + }; + } +} +function ReactDOMRoot(internalRoot) { + this._internalRoot = internalRoot; +} +function ReactDOMHydrationRoot(internalRoot) { + this._internalRoot = internalRoot; +} +var Scheduler, React2, ReactDOM, assign2, REACT_LEGACY_ELEMENT_TYPE, REACT_ELEMENT_TYPE2, REACT_PORTAL_TYPE3, REACT_FRAGMENT_TYPE2, REACT_STRICT_MODE_TYPE2, REACT_PROFILER_TYPE2, REACT_CONSUMER_TYPE2, REACT_CONTEXT_TYPE2, REACT_FORWARD_REF_TYPE2, REACT_SUSPENSE_TYPE2, REACT_SUSPENSE_LIST_TYPE, REACT_MEMO_TYPE2, REACT_LAZY_TYPE2, REACT_ACTIVITY_TYPE2, REACT_MEMO_CACHE_SENTINEL, MAYBE_ITERATOR_SYMBOL2, REACT_CLIENT_REFERENCE, isArrayImpl2, ReactSharedInternals3, ReactDOMSharedInternals, sharedNotPendingObject, valueStack, index = -1, contextStackCursor, contextFiberStackCursor, rootInstanceStackCursor, hostTransitionProviderCursor, prefix, suffix, reentry = false, hasOwnProperty2, scheduleCallback$3, cancelCallback$1, shouldYield, requestPaint, now, getCurrentPriorityLevel, ImmediatePriority, UserBlockingPriority, NormalPriority$1, LowPriority, IdlePriority, log$1, unstable_setDisableYieldValue2, rendererID = null, injectedHook = null, clz32, log2, LN2, nextTransitionUpdateLane = 256, nextTransitionDeferredLane = 262144, nextRetryLane = 4194304, randomKey, internalInstanceKey, internalPropsKey, internalContainerInstanceKey, internalEventHandlersKey, internalEventHandlerListenersKey, internalEventHandlesSetKey, internalRootNodeResourcesKey, internalHoistableMarker, allNativeEvents, registrationNameDependencies, VALID_ATTRIBUTE_NAME_REGEX, illegalAttributeNameCache, validatedAttributeNameCache, escapeSelectorAttributeValueInsideDoubleQuotesRegex, unitlessNumbers, aliases, isJavaScriptProtocol, currentReplayingEvent = null, restoreTarget = null, restoreQueue = null, isInsideEventHandler = false, canUseDOM, passiveBrowserEventsSupported = false, options, root = null, startText = null, fallbackText = null, EventInterface, SyntheticEvent, UIEventInterface, SyntheticUIEvent, lastMovementX, lastMovementY, lastMouseEvent, MouseEventInterface, SyntheticMouseEvent, DragEventInterface, SyntheticDragEvent, FocusEventInterface, SyntheticFocusEvent, AnimationEventInterface, SyntheticAnimationEvent, ClipboardEventInterface, SyntheticClipboardEvent, CompositionEventInterface, SyntheticCompositionEvent, normalizeKey, translateToKey, modifierKeyToProp, KeyboardEventInterface, SyntheticKeyboardEvent, PointerEventInterface, SyntheticPointerEvent, TouchEventInterface, SyntheticTouchEvent, TransitionEventInterface, SyntheticTransitionEvent, WheelEventInterface, SyntheticWheelEvent, ToggleEventInterface, SyntheticToggleEvent, END_KEYCODES, canUseCompositionEvent, documentMode = null, canUseTextInputEvent, useFallbackCompositionData, SPACEBAR_CHAR, hasSpaceKeypress = false, isComposing = false, supportedInputTypes, activeElement$1 = null, activeElementInst$1 = null, isInputEventSupported = false, JSCompiler_inline_result$jscomp$286, isSupported$jscomp$inline_427, element$jscomp$inline_428, objectIs, skipSelectionChangeEvent, activeElement = null, activeElementInst = null, lastSelection = null, mouseDown = false, vendorPrefixes, prefixedEventNames, style, ANIMATION_END, ANIMATION_ITERATION, ANIMATION_START, TRANSITION_RUN, TRANSITION_START, TRANSITION_CANCEL, TRANSITION_END, topLevelEventsToReactNames, simpleEventPluginEvents, reportGlobalError2, concurrentQueues, concurrentQueuesIndex = 0, concurrentlyUpdatedLanes = 0, emptyContextObject, CapturedStacks, forkStack, forkStackIndex = 0, treeForkProvider = null, treeForkCount = 0, idStack, idStackIndex = 0, treeContextProvider = null, treeContextId = 1, treeContextOverflow = "", hydrationParentFiber = null, nextHydratableInstance = null, isHydrating = false, hydrationErrors = null, rootOrSingletonContext = false, HydrationMismatchException, valueCursor, currentlyRenderingFiber$1 = null, lastContextDependency = null, AbortControllerLocal, scheduleCallback$2, NormalPriority, CacheContext, currentEntangledListeners = null, currentEntangledPendingCount = 0, currentEntangledLane = 0, currentEntangledActionThenable = null, prevOnStartTransitionFinish, resumedCache, SuspenseException, SuspenseyCommitException, SuspenseActionException, noopSuspenseyCommitThenable, suspendedThenable = null, thenableState$1 = null, thenableIndexCounter$1 = 0, reconcileChildFibers, mountChildFibers, hasForceUpdate = false, didReadFromEntangledAsyncAction = false, currentTreeHiddenStackCursor, prevEntangledRenderLanesCursor, suspenseHandlerStackCursor, shellBoundary = null, suspenseStackCursor, renderLanes = 0, currentlyRenderingFiber = null, currentHook = null, workInProgressHook = null, didScheduleRenderPhaseUpdate = false, didScheduleRenderPhaseUpdateDuringThisPass = false, shouldDoubleInvokeUserFnsInHooksDEV = false, localIdCounter = 0, thenableIndexCounter = 0, thenableState = null, globalClientIdCounter = 0, ContextOnlyDispatcher, HooksDispatcherOnMount, HooksDispatcherOnUpdate, HooksDispatcherOnRerender, classComponentUpdater, SelectiveHydrationException, didReceiveUpdate = false, SUSPENDED_MARKER, offscreenSubtreeIsHidden = false, offscreenSubtreeWasHidden = false, needsFormReset = false, PossiblyWeakSet, nextEffect = null, hostParent = null, hostParentIsContainer = false, currentHoistableRoot = null, suspenseyCommitFlag = 8192, DefaultAsyncDispatcher, PossiblyWeakMap, executionContext = 0, workInProgressRoot = null, workInProgress = null, workInProgressRootRenderLanes = 0, workInProgressSuspendedReason = 0, workInProgressThrownValue = null, workInProgressRootDidSkipSuspendedSiblings = false, workInProgressRootIsPrerendering = false, workInProgressRootDidAttachPingListener = false, entangledRenderLanes = 0, workInProgressRootExitStatus = 0, workInProgressRootSkippedLanes = 0, workInProgressRootInterleavedUpdatedLanes = 0, workInProgressRootPingedLanes = 0, workInProgressDeferredLane = 0, workInProgressSuspendedRetryLanes = 0, workInProgressRootConcurrentErrors = null, workInProgressRootRecoverableErrors = null, workInProgressRootDidIncludeRecursiveRenderUpdate = false, globalMostRecentFallbackTime = 0, globalMostRecentTransitionTime = 0, workInProgressRootRenderTargetTime = Infinity, workInProgressTransitions = null, legacyErrorBoundariesThatAlreadyFailed = null, pendingEffectsStatus = 0, pendingEffectsRoot = null, pendingFinishedWork = null, pendingEffectsLanes = 0, pendingEffectsRemainingLanes = 0, pendingPassiveTransitions = null, pendingRecoverableErrors = null, nestedUpdateCount = 0, rootWithNestedUpdates = null, firstScheduledRoot = null, lastScheduledRoot = null, didScheduleMicrotask = false, mightHavePendingSyncWork = false, isFlushingWork = false, currentEventTransitionLane = 0, eventName$jscomp$inline_1578, domEventName$jscomp$inline_1579, capitalizedEvent$jscomp$inline_1580, i$jscomp$inline_1577, mediaEventTypes, nonDelegatedEvents, listeningMarker, NORMALIZE_NEWLINES_REGEX, NORMALIZE_NULL_AND_REPLACEMENT_REGEX, eventsEnabled = null, selectionInformation = null, currentPopstateTransitionEvent = null, scheduleTimeout, cancelTimeout, localPromise, scheduleMicrotask, previousHydratableOnEnteringScopedSingleton = null, preloadPropsMap, preconnectsSet, previousDispatcher, globalDocument, tagCaches = null, estimatedBytesWithinLimit = 0, precedencesByRoot = null, HostTransitionContext, _enabled = true, return_targetInst = null, hasScheduledReplayAttempt = false, queuedFocus = null, queuedDrag = null, queuedMouse = null, queuedPointers, queuedPointerCaptures, queuedExplicitHydrationTargets, discreteReplayableEvents, lastScheduledReplayQueue = null, isomorphicReactPackageVersion$jscomp$inline_1840, internals$jscomp$inline_2347, hook$jscomp$inline_2348, $createRoot = function(container, options2) { + if (!isValidContainer(container)) + throw Error(formatProdErrorMessage2(299)); + var isStrictMode = false, identifierPrefix = "", onUncaughtError = defaultOnUncaughtError, onCaughtError = defaultOnCaughtError, onRecoverableError = defaultOnRecoverableError; + options2 !== null && options2 !== undefined && (options2.unstable_strictMode === true && (isStrictMode = true), options2.identifierPrefix !== undefined && (identifierPrefix = options2.identifierPrefix), options2.onUncaughtError !== undefined && (onUncaughtError = options2.onUncaughtError), options2.onCaughtError !== undefined && (onCaughtError = options2.onCaughtError), options2.onRecoverableError !== undefined && (onRecoverableError = options2.onRecoverableError)); + options2 = createFiberRoot(container, 1, false, null, null, isStrictMode, identifierPrefix, null, onUncaughtError, onCaughtError, onRecoverableError, defaultOnDefaultTransitionIndicator); + container[internalContainerInstanceKey] = options2.current; + listenToAllSupportedEvents(container); + return new ReactDOMRoot(options2); +}, $hydrateRoot = function(container, initialChildren, options2) { + if (!isValidContainer(container)) + throw Error(formatProdErrorMessage2(299)); + var isStrictMode = false, identifierPrefix = "", onUncaughtError = defaultOnUncaughtError, onCaughtError = defaultOnCaughtError, onRecoverableError = defaultOnRecoverableError, formState = null; + options2 !== null && options2 !== undefined && (options2.unstable_strictMode === true && (isStrictMode = true), options2.identifierPrefix !== undefined && (identifierPrefix = options2.identifierPrefix), options2.onUncaughtError !== undefined && (onUncaughtError = options2.onUncaughtError), options2.onCaughtError !== undefined && (onCaughtError = options2.onCaughtError), options2.onRecoverableError !== undefined && (onRecoverableError = options2.onRecoverableError), options2.formState !== undefined && (formState = options2.formState)); + initialChildren = createFiberRoot(container, 1, true, initialChildren, options2 != null ? options2 : null, isStrictMode, identifierPrefix, formState, onUncaughtError, onCaughtError, onRecoverableError, defaultOnDefaultTransitionIndicator); + initialChildren.context = getContextForSubtree(null); + options2 = initialChildren.current; + isStrictMode = requestUpdateLane(); + isStrictMode = getBumpedLaneForHydrationByLane(isStrictMode); + identifierPrefix = createUpdate(isStrictMode); + identifierPrefix.callback = null; + enqueueUpdate(options2, identifierPrefix, isStrictMode); + options2 = isStrictMode; + initialChildren.current.lanes = options2; + markRootUpdated$1(initialChildren, options2); + ensureRootIsScheduled(initialChildren); + container[internalContainerInstanceKey] = initialChildren.current; + listenToAllSupportedEvents(container); + return new ReactDOMHydrationRoot(initialChildren); +}, $version3 = "19.2.4"; +var init_react_dom_client_production = __esm(() => { + Scheduler = __toESM(require_scheduler(), 1); + React2 = __toESM(require_react(), 1); + ReactDOM = __toESM(require_react_dom(), 1); + assign2 = Object.assign; + REACT_LEGACY_ELEMENT_TYPE = Symbol.for("react.element"); + REACT_ELEMENT_TYPE2 = Symbol.for("react.transitional.element"); + REACT_PORTAL_TYPE3 = Symbol.for("react.portal"); + REACT_FRAGMENT_TYPE2 = Symbol.for("react.fragment"); + REACT_STRICT_MODE_TYPE2 = Symbol.for("react.strict_mode"); + REACT_PROFILER_TYPE2 = Symbol.for("react.profiler"); + REACT_CONSUMER_TYPE2 = Symbol.for("react.consumer"); + REACT_CONTEXT_TYPE2 = Symbol.for("react.context"); + REACT_FORWARD_REF_TYPE2 = Symbol.for("react.forward_ref"); + REACT_SUSPENSE_TYPE2 = Symbol.for("react.suspense"); + REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"); + REACT_MEMO_TYPE2 = Symbol.for("react.memo"); + REACT_LAZY_TYPE2 = Symbol.for("react.lazy"); + Symbol.for("react.scope"); + REACT_ACTIVITY_TYPE2 = Symbol.for("react.activity"); + Symbol.for("react.legacy_hidden"); + Symbol.for("react.tracing_marker"); + REACT_MEMO_CACHE_SENTINEL = Symbol.for("react.memo_cache_sentinel"); + Symbol.for("react.view_transition"); + MAYBE_ITERATOR_SYMBOL2 = Symbol.iterator; + REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"); + isArrayImpl2 = Array.isArray; + ReactSharedInternals3 = React2.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE; + ReactDOMSharedInternals = ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE; + sharedNotPendingObject = { + pending: false, + data: null, + method: null, + action: null + }; + valueStack = []; + contextStackCursor = createCursor(null); + contextFiberStackCursor = createCursor(null); + rootInstanceStackCursor = createCursor(null); + hostTransitionProviderCursor = createCursor(null); + hasOwnProperty2 = Object.prototype.hasOwnProperty; + scheduleCallback$3 = Scheduler.unstable_scheduleCallback; + cancelCallback$1 = Scheduler.unstable_cancelCallback; + shouldYield = Scheduler.unstable_shouldYield; + requestPaint = Scheduler.unstable_requestPaint; + now = Scheduler.unstable_now; + getCurrentPriorityLevel = Scheduler.unstable_getCurrentPriorityLevel; + ImmediatePriority = Scheduler.unstable_ImmediatePriority; + UserBlockingPriority = Scheduler.unstable_UserBlockingPriority; + NormalPriority$1 = Scheduler.unstable_NormalPriority; + LowPriority = Scheduler.unstable_LowPriority; + IdlePriority = Scheduler.unstable_IdlePriority; + log$1 = Scheduler.log; + unstable_setDisableYieldValue2 = Scheduler.unstable_setDisableYieldValue; + clz32 = Math.clz32 ? Math.clz32 : clz32Fallback; + log2 = Math.log; + LN2 = Math.LN2; + randomKey = Math.random().toString(36).slice(2); + internalInstanceKey = "__reactFiber$" + randomKey; + internalPropsKey = "__reactProps$" + randomKey; + internalContainerInstanceKey = "__reactContainer$" + randomKey; + internalEventHandlersKey = "__reactEvents$" + randomKey; + internalEventHandlerListenersKey = "__reactListeners$" + randomKey; + internalEventHandlesSetKey = "__reactHandles$" + randomKey; + internalRootNodeResourcesKey = "__reactResources$" + randomKey; + internalHoistableMarker = "__reactMarker$" + randomKey; + allNativeEvents = new Set; + registrationNameDependencies = {}; + VALID_ATTRIBUTE_NAME_REGEX = RegExp("^[: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]*$"); + illegalAttributeNameCache = {}; + validatedAttributeNameCache = {}; + escapeSelectorAttributeValueInsideDoubleQuotesRegex = /[\n"\\]/g; + unitlessNumbers = new Set("animationIterationCount aspectRatio borderImageOutset borderImageSlice borderImageWidth boxFlex boxFlexGroup boxOrdinalGroup columnCount columns flex flexGrow flexPositive flexShrink flexNegative flexOrder gridArea gridRow gridRowEnd gridRowSpan gridRowStart gridColumn gridColumnEnd gridColumnSpan gridColumnStart fontWeight lineClamp lineHeight opacity order orphans scale tabSize widows zIndex zoom fillOpacity floodOpacity stopOpacity strokeDasharray strokeDashoffset strokeMiterlimit strokeOpacity strokeWidth MozAnimationIterationCount MozBoxFlex MozBoxFlexGroup MozLineClamp msAnimationIterationCount msFlex msZoom msFlexGrow msFlexNegative msFlexOrder msFlexPositive msFlexShrink msGridColumn msGridColumnSpan msGridRow msGridRowSpan WebkitAnimationIterationCount WebkitBoxFlex WebKitBoxFlexGroup WebkitBoxOrdinalGroup WebkitColumnCount WebkitColumns WebkitFlex WebkitFlexGrow WebkitFlexPositive WebkitFlexShrink WebkitLineClamp".split(" ")); + aliases = new Map([ + ["acceptCharset", "accept-charset"], + ["htmlFor", "for"], + ["httpEquiv", "http-equiv"], + ["crossOrigin", "crossorigin"], + ["accentHeight", "accent-height"], + ["alignmentBaseline", "alignment-baseline"], + ["arabicForm", "arabic-form"], + ["baselineShift", "baseline-shift"], + ["capHeight", "cap-height"], + ["clipPath", "clip-path"], + ["clipRule", "clip-rule"], + ["colorInterpolation", "color-interpolation"], + ["colorInterpolationFilters", "color-interpolation-filters"], + ["colorProfile", "color-profile"], + ["colorRendering", "color-rendering"], + ["dominantBaseline", "dominant-baseline"], + ["enableBackground", "enable-background"], + ["fillOpacity", "fill-opacity"], + ["fillRule", "fill-rule"], + ["floodColor", "flood-color"], + ["floodOpacity", "flood-opacity"], + ["fontFamily", "font-family"], + ["fontSize", "font-size"], + ["fontSizeAdjust", "font-size-adjust"], + ["fontStretch", "font-stretch"], + ["fontStyle", "font-style"], + ["fontVariant", "font-variant"], + ["fontWeight", "font-weight"], + ["glyphName", "glyph-name"], + ["glyphOrientationHorizontal", "glyph-orientation-horizontal"], + ["glyphOrientationVertical", "glyph-orientation-vertical"], + ["horizAdvX", "horiz-adv-x"], + ["horizOriginX", "horiz-origin-x"], + ["imageRendering", "image-rendering"], + ["letterSpacing", "letter-spacing"], + ["lightingColor", "lighting-color"], + ["markerEnd", "marker-end"], + ["markerMid", "marker-mid"], + ["markerStart", "marker-start"], + ["overlinePosition", "overline-position"], + ["overlineThickness", "overline-thickness"], + ["paintOrder", "paint-order"], + ["panose-1", "panose-1"], + ["pointerEvents", "pointer-events"], + ["renderingIntent", "rendering-intent"], + ["shapeRendering", "shape-rendering"], + ["stopColor", "stop-color"], + ["stopOpacity", "stop-opacity"], + ["strikethroughPosition", "strikethrough-position"], + ["strikethroughThickness", "strikethrough-thickness"], + ["strokeDasharray", "stroke-dasharray"], + ["strokeDashoffset", "stroke-dashoffset"], + ["strokeLinecap", "stroke-linecap"], + ["strokeLinejoin", "stroke-linejoin"], + ["strokeMiterlimit", "stroke-miterlimit"], + ["strokeOpacity", "stroke-opacity"], + ["strokeWidth", "stroke-width"], + ["textAnchor", "text-anchor"], + ["textDecoration", "text-decoration"], + ["textRendering", "text-rendering"], + ["transformOrigin", "transform-origin"], + ["underlinePosition", "underline-position"], + ["underlineThickness", "underline-thickness"], + ["unicodeBidi", "unicode-bidi"], + ["unicodeRange", "unicode-range"], + ["unitsPerEm", "units-per-em"], + ["vAlphabetic", "v-alphabetic"], + ["vHanging", "v-hanging"], + ["vIdeographic", "v-ideographic"], + ["vMathematical", "v-mathematical"], + ["vectorEffect", "vector-effect"], + ["vertAdvY", "vert-adv-y"], + ["vertOriginX", "vert-origin-x"], + ["vertOriginY", "vert-origin-y"], + ["wordSpacing", "word-spacing"], + ["writingMode", "writing-mode"], + ["xmlnsXlink", "xmlns:xlink"], + ["xHeight", "x-height"] + ]); + isJavaScriptProtocol = /^[\u0000-\u001F ]*j[\r\n\t]*a[\r\n\t]*v[\r\n\t]*a[\r\n\t]*s[\r\n\t]*c[\r\n\t]*r[\r\n\t]*i[\r\n\t]*p[\r\n\t]*t[\r\n\t]*:/i; + canUseDOM = !(typeof window === "undefined" || typeof window.document === "undefined" || typeof window.document.createElement === "undefined"); + if (canUseDOM) + try { + options = {}; + Object.defineProperty(options, "passive", { + get: function() { + passiveBrowserEventsSupported = true; + } + }); + window.addEventListener("test", options, options); + window.removeEventListener("test", options, options); + } catch (e) { + passiveBrowserEventsSupported = false; + } + EventInterface = { + eventPhase: 0, + bubbles: 0, + cancelable: 0, + timeStamp: function(event) { + return event.timeStamp || Date.now(); + }, + defaultPrevented: 0, + isTrusted: 0 + }; + SyntheticEvent = createSyntheticEvent(EventInterface); + UIEventInterface = assign2({}, EventInterface, { view: 0, detail: 0 }); + SyntheticUIEvent = createSyntheticEvent(UIEventInterface); + MouseEventInterface = assign2({}, UIEventInterface, { + screenX: 0, + screenY: 0, + clientX: 0, + clientY: 0, + pageX: 0, + pageY: 0, + ctrlKey: 0, + shiftKey: 0, + altKey: 0, + metaKey: 0, + getModifierState: getEventModifierState, + button: 0, + buttons: 0, + relatedTarget: function(event) { + return event.relatedTarget === undefined ? event.fromElement === event.srcElement ? event.toElement : event.fromElement : event.relatedTarget; + }, + movementX: function(event) { + if ("movementX" in event) + return event.movementX; + event !== lastMouseEvent && (lastMouseEvent && event.type === "mousemove" ? (lastMovementX = event.screenX - lastMouseEvent.screenX, lastMovementY = event.screenY - lastMouseEvent.screenY) : lastMovementY = lastMovementX = 0, lastMouseEvent = event); + return lastMovementX; + }, + movementY: function(event) { + return "movementY" in event ? event.movementY : lastMovementY; + } + }); + SyntheticMouseEvent = createSyntheticEvent(MouseEventInterface); + DragEventInterface = assign2({}, MouseEventInterface, { dataTransfer: 0 }); + SyntheticDragEvent = createSyntheticEvent(DragEventInterface); + FocusEventInterface = assign2({}, UIEventInterface, { relatedTarget: 0 }); + SyntheticFocusEvent = createSyntheticEvent(FocusEventInterface); + AnimationEventInterface = assign2({}, EventInterface, { + animationName: 0, + elapsedTime: 0, + pseudoElement: 0 + }); + SyntheticAnimationEvent = createSyntheticEvent(AnimationEventInterface); + ClipboardEventInterface = assign2({}, EventInterface, { + clipboardData: function(event) { + return "clipboardData" in event ? event.clipboardData : window.clipboardData; + } + }); + SyntheticClipboardEvent = createSyntheticEvent(ClipboardEventInterface); + CompositionEventInterface = assign2({}, EventInterface, { data: 0 }); + SyntheticCompositionEvent = createSyntheticEvent(CompositionEventInterface); + normalizeKey = { + Esc: "Escape", + Spacebar: " ", + Left: "ArrowLeft", + Up: "ArrowUp", + Right: "ArrowRight", + Down: "ArrowDown", + Del: "Delete", + Win: "OS", + Menu: "ContextMenu", + Apps: "ContextMenu", + Scroll: "ScrollLock", + MozPrintableKey: "Unidentified" + }; + translateToKey = { + 8: "Backspace", + 9: "Tab", + 12: "Clear", + 13: "Enter", + 16: "Shift", + 17: "Control", + 18: "Alt", + 19: "Pause", + 20: "CapsLock", + 27: "Escape", + 32: " ", + 33: "PageUp", + 34: "PageDown", + 35: "End", + 36: "Home", + 37: "ArrowLeft", + 38: "ArrowUp", + 39: "ArrowRight", + 40: "ArrowDown", + 45: "Insert", + 46: "Delete", + 112: "F1", + 113: "F2", + 114: "F3", + 115: "F4", + 116: "F5", + 117: "F6", + 118: "F7", + 119: "F8", + 120: "F9", + 121: "F10", + 122: "F11", + 123: "F12", + 144: "NumLock", + 145: "ScrollLock", + 224: "Meta" + }; + modifierKeyToProp = { + Alt: "altKey", + Control: "ctrlKey", + Meta: "metaKey", + Shift: "shiftKey" + }; + KeyboardEventInterface = assign2({}, UIEventInterface, { + key: function(nativeEvent) { + if (nativeEvent.key) { + var key = normalizeKey[nativeEvent.key] || nativeEvent.key; + if (key !== "Unidentified") + return key; + } + return nativeEvent.type === "keypress" ? (nativeEvent = getEventCharCode(nativeEvent), nativeEvent === 13 ? "Enter" : String.fromCharCode(nativeEvent)) : nativeEvent.type === "keydown" || nativeEvent.type === "keyup" ? translateToKey[nativeEvent.keyCode] || "Unidentified" : ""; + }, + code: 0, + location: 0, + ctrlKey: 0, + shiftKey: 0, + altKey: 0, + metaKey: 0, + repeat: 0, + locale: 0, + getModifierState: getEventModifierState, + charCode: function(event) { + return event.type === "keypress" ? getEventCharCode(event) : 0; + }, + keyCode: function(event) { + return event.type === "keydown" || event.type === "keyup" ? event.keyCode : 0; + }, + which: function(event) { + return event.type === "keypress" ? getEventCharCode(event) : event.type === "keydown" || event.type === "keyup" ? event.keyCode : 0; + } + }); + SyntheticKeyboardEvent = createSyntheticEvent(KeyboardEventInterface); + PointerEventInterface = assign2({}, MouseEventInterface, { + pointerId: 0, + width: 0, + height: 0, + pressure: 0, + tangentialPressure: 0, + tiltX: 0, + tiltY: 0, + twist: 0, + pointerType: 0, + isPrimary: 0 + }); + SyntheticPointerEvent = createSyntheticEvent(PointerEventInterface); + TouchEventInterface = assign2({}, UIEventInterface, { + touches: 0, + targetTouches: 0, + changedTouches: 0, + altKey: 0, + metaKey: 0, + ctrlKey: 0, + shiftKey: 0, + getModifierState: getEventModifierState + }); + SyntheticTouchEvent = createSyntheticEvent(TouchEventInterface); + TransitionEventInterface = assign2({}, EventInterface, { + propertyName: 0, + elapsedTime: 0, + pseudoElement: 0 + }); + SyntheticTransitionEvent = createSyntheticEvent(TransitionEventInterface); + WheelEventInterface = assign2({}, MouseEventInterface, { + deltaX: function(event) { + return "deltaX" in event ? event.deltaX : ("wheelDeltaX" in event) ? -event.wheelDeltaX : 0; + }, + deltaY: function(event) { + return "deltaY" in event ? event.deltaY : ("wheelDeltaY" in event) ? -event.wheelDeltaY : ("wheelDelta" in event) ? -event.wheelDelta : 0; + }, + deltaZ: 0, + deltaMode: 0 + }); + SyntheticWheelEvent = createSyntheticEvent(WheelEventInterface); + ToggleEventInterface = assign2({}, EventInterface, { + newState: 0, + oldState: 0 + }); + SyntheticToggleEvent = createSyntheticEvent(ToggleEventInterface); + END_KEYCODES = [9, 13, 27, 32]; + canUseCompositionEvent = canUseDOM && "CompositionEvent" in window; + canUseDOM && "documentMode" in document && (documentMode = document.documentMode); + canUseTextInputEvent = canUseDOM && "TextEvent" in window && !documentMode; + useFallbackCompositionData = canUseDOM && (!canUseCompositionEvent || documentMode && 8 < documentMode && 11 >= documentMode); + SPACEBAR_CHAR = String.fromCharCode(32); + supportedInputTypes = { + color: true, + date: true, + datetime: true, + "datetime-local": true, + email: true, + month: true, + number: true, + password: true, + range: true, + search: true, + tel: true, + text: true, + time: true, + url: true, + week: true + }; + if (canUseDOM) { + if (canUseDOM) { + isSupported$jscomp$inline_427 = "oninput" in document; + if (!isSupported$jscomp$inline_427) { + element$jscomp$inline_428 = document.createElement("div"); + element$jscomp$inline_428.setAttribute("oninput", "return;"); + isSupported$jscomp$inline_427 = typeof element$jscomp$inline_428.oninput === "function"; + } + JSCompiler_inline_result$jscomp$286 = isSupported$jscomp$inline_427; + } else + JSCompiler_inline_result$jscomp$286 = false; + isInputEventSupported = JSCompiler_inline_result$jscomp$286 && (!document.documentMode || 9 < document.documentMode); + } + objectIs = typeof Object.is === "function" ? Object.is : is; + skipSelectionChangeEvent = canUseDOM && "documentMode" in document && 11 >= document.documentMode; + vendorPrefixes = { + animationend: makePrefixMap("Animation", "AnimationEnd"), + animationiteration: makePrefixMap("Animation", "AnimationIteration"), + animationstart: makePrefixMap("Animation", "AnimationStart"), + transitionrun: makePrefixMap("Transition", "TransitionRun"), + transitionstart: makePrefixMap("Transition", "TransitionStart"), + transitioncancel: makePrefixMap("Transition", "TransitionCancel"), + transitionend: makePrefixMap("Transition", "TransitionEnd") + }; + prefixedEventNames = {}; + style = {}; + canUseDOM && (style = document.createElement("div").style, ("AnimationEvent" in window) || (delete vendorPrefixes.animationend.animation, delete vendorPrefixes.animationiteration.animation, delete vendorPrefixes.animationstart.animation), ("TransitionEvent" in window) || delete vendorPrefixes.transitionend.transition); + ANIMATION_END = getVendorPrefixedEventName("animationend"); + ANIMATION_ITERATION = getVendorPrefixedEventName("animationiteration"); + ANIMATION_START = getVendorPrefixedEventName("animationstart"); + TRANSITION_RUN = getVendorPrefixedEventName("transitionrun"); + TRANSITION_START = getVendorPrefixedEventName("transitionstart"); + TRANSITION_CANCEL = getVendorPrefixedEventName("transitioncancel"); + TRANSITION_END = getVendorPrefixedEventName("transitionend"); + topLevelEventsToReactNames = new Map; + simpleEventPluginEvents = "abort auxClick beforeToggle cancel canPlay canPlayThrough click close contextMenu copy cut drag dragEnd dragEnter dragExit dragLeave dragOver dragStart drop durationChange emptied encrypted ended error gotPointerCapture input invalid keyDown keyPress keyUp load loadedData loadedMetadata loadStart lostPointerCapture mouseDown mouseMove mouseOut mouseOver mouseUp paste pause play playing pointerCancel pointerDown pointerMove pointerOut pointerOver pointerUp progress rateChange reset resize seeked seeking stalled submit suspend timeUpdate touchCancel touchEnd touchStart volumeChange scroll toggle touchMove waiting wheel".split(" "); + simpleEventPluginEvents.push("scrollEnd"); + reportGlobalError2 = typeof reportError === "function" ? reportError : function(error) { + if (typeof window === "object" && typeof window.ErrorEvent === "function") { + var event = new window.ErrorEvent("error", { + bubbles: true, + cancelable: true, + message: typeof error === "object" && error !== null && typeof error.message === "string" ? String(error.message) : String(error), + error + }); + if (!window.dispatchEvent(event)) + return; + } else if (typeof process === "object" && typeof process.emit === "function") { + process.emit("uncaughtException", error); + return; + } + console.error(error); + }; + concurrentQueues = []; + emptyContextObject = {}; + CapturedStacks = new WeakMap; + forkStack = []; + idStack = []; + HydrationMismatchException = Error(formatProdErrorMessage2(519)); + valueCursor = createCursor(null); + AbortControllerLocal = typeof AbortController !== "undefined" ? AbortController : function() { + var listeners = [], signal = this.signal = { + aborted: false, + addEventListener: function(type, listener) { + listeners.push(listener); + } + }; + this.abort = function() { + signal.aborted = true; + listeners.forEach(function(listener) { + return listener(); + }); + }; + }; + scheduleCallback$2 = Scheduler.unstable_scheduleCallback; + NormalPriority = Scheduler.unstable_NormalPriority; + CacheContext = { + $$typeof: REACT_CONTEXT_TYPE2, + Consumer: null, + Provider: null, + _currentValue: null, + _currentValue2: null, + _threadCount: 0 + }; + prevOnStartTransitionFinish = ReactSharedInternals3.S; + ReactSharedInternals3.S = function(transition, returnValue) { + globalMostRecentTransitionTime = now(); + typeof returnValue === "object" && returnValue !== null && typeof returnValue.then === "function" && entangleAsyncAction(transition, returnValue); + prevOnStartTransitionFinish !== null && prevOnStartTransitionFinish(transition, returnValue); + }; + resumedCache = createCursor(null); + SuspenseException = Error(formatProdErrorMessage2(460)); + SuspenseyCommitException = Error(formatProdErrorMessage2(474)); + SuspenseActionException = Error(formatProdErrorMessage2(542)); + noopSuspenseyCommitThenable = { then: function() {} }; + reconcileChildFibers = createChildReconciler(true); + mountChildFibers = createChildReconciler(false); + currentTreeHiddenStackCursor = createCursor(null); + prevEntangledRenderLanesCursor = createCursor(0); + suspenseHandlerStackCursor = createCursor(null); + suspenseStackCursor = createCursor(0); + ContextOnlyDispatcher = { + readContext, + use, + useCallback: throwInvalidHookError, + useContext: throwInvalidHookError, + useEffect: throwInvalidHookError, + useImperativeHandle: throwInvalidHookError, + useLayoutEffect: throwInvalidHookError, + useInsertionEffect: throwInvalidHookError, + useMemo: throwInvalidHookError, + useReducer: throwInvalidHookError, + useRef: throwInvalidHookError, + useState: throwInvalidHookError, + useDebugValue: throwInvalidHookError, + useDeferredValue: throwInvalidHookError, + useTransition: throwInvalidHookError, + useSyncExternalStore: throwInvalidHookError, + useId: throwInvalidHookError, + useHostTransitionStatus: throwInvalidHookError, + useFormState: throwInvalidHookError, + useActionState: throwInvalidHookError, + useOptimistic: throwInvalidHookError, + useMemoCache: throwInvalidHookError, + useCacheRefresh: throwInvalidHookError + }; + ContextOnlyDispatcher.useEffectEvent = throwInvalidHookError; + HooksDispatcherOnMount = { + readContext, + use, + useCallback: function(callback, deps) { + mountWorkInProgressHook().memoizedState = [ + callback, + deps === undefined ? null : deps + ]; + return callback; + }, + useContext: readContext, + useEffect: mountEffect, + useImperativeHandle: function(ref, create, deps) { + deps = deps !== null && deps !== undefined ? deps.concat([ref]) : null; + mountEffectImpl(4194308, 4, imperativeHandleEffect.bind(null, create, ref), deps); + }, + useLayoutEffect: function(create, deps) { + return mountEffectImpl(4194308, 4, create, deps); + }, + useInsertionEffect: function(create, deps) { + mountEffectImpl(4, 2, create, deps); + }, + useMemo: function(nextCreate, deps) { + var hook = mountWorkInProgressHook(); + deps = deps === undefined ? null : deps; + var nextValue = nextCreate(); + if (shouldDoubleInvokeUserFnsInHooksDEV) { + setIsStrictModeForDevtools(true); + try { + nextCreate(); + } finally { + setIsStrictModeForDevtools(false); + } + } + hook.memoizedState = [nextValue, deps]; + return nextValue; + }, + useReducer: function(reducer, initialArg, init) { + var hook = mountWorkInProgressHook(); + if (init !== undefined) { + var initialState = init(initialArg); + if (shouldDoubleInvokeUserFnsInHooksDEV) { + setIsStrictModeForDevtools(true); + try { + init(initialArg); + } finally { + setIsStrictModeForDevtools(false); + } + } + } else + initialState = initialArg; + hook.memoizedState = hook.baseState = initialState; + reducer = { + pending: null, + lanes: 0, + dispatch: null, + lastRenderedReducer: reducer, + lastRenderedState: initialState + }; + hook.queue = reducer; + reducer = reducer.dispatch = dispatchReducerAction.bind(null, currentlyRenderingFiber, reducer); + return [hook.memoizedState, reducer]; + }, + useRef: function(initialValue) { + var hook = mountWorkInProgressHook(); + initialValue = { current: initialValue }; + return hook.memoizedState = initialValue; + }, + useState: function(initialState) { + initialState = mountStateImpl(initialState); + var queue = initialState.queue, dispatch = dispatchSetState.bind(null, currentlyRenderingFiber, queue); + queue.dispatch = dispatch; + return [initialState.memoizedState, dispatch]; + }, + useDebugValue: mountDebugValue, + useDeferredValue: function(value, initialValue) { + var hook = mountWorkInProgressHook(); + return mountDeferredValueImpl(hook, value, initialValue); + }, + useTransition: function() { + var stateHook = mountStateImpl(false); + stateHook = startTransition.bind(null, currentlyRenderingFiber, stateHook.queue, true, false); + mountWorkInProgressHook().memoizedState = stateHook; + return [false, stateHook]; + }, + useSyncExternalStore: function(subscribe, getSnapshot, getServerSnapshot) { + var fiber = currentlyRenderingFiber, hook = mountWorkInProgressHook(); + if (isHydrating) { + if (getServerSnapshot === undefined) + throw Error(formatProdErrorMessage2(407)); + getServerSnapshot = getServerSnapshot(); + } else { + getServerSnapshot = getSnapshot(); + if (workInProgressRoot === null) + throw Error(formatProdErrorMessage2(349)); + (workInProgressRootRenderLanes & 127) !== 0 || pushStoreConsistencyCheck(fiber, getSnapshot, getServerSnapshot); + } + hook.memoizedState = getServerSnapshot; + var inst = { value: getServerSnapshot, getSnapshot }; + hook.queue = inst; + mountEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [ + subscribe + ]); + fiber.flags |= 2048; + pushSimpleEffect(9, { destroy: undefined }, updateStoreInstance.bind(null, fiber, inst, getServerSnapshot, getSnapshot), null); + return getServerSnapshot; + }, + useId: function() { + var hook = mountWorkInProgressHook(), identifierPrefix = workInProgressRoot.identifierPrefix; + if (isHydrating) { + var JSCompiler_inline_result = treeContextOverflow; + var idWithLeadingBit = treeContextId; + JSCompiler_inline_result = (idWithLeadingBit & ~(1 << 32 - clz32(idWithLeadingBit) - 1)).toString(32) + JSCompiler_inline_result; + identifierPrefix = "_" + identifierPrefix + "R_" + JSCompiler_inline_result; + JSCompiler_inline_result = localIdCounter++; + 0 < JSCompiler_inline_result && (identifierPrefix += "H" + JSCompiler_inline_result.toString(32)); + identifierPrefix += "_"; + } else + JSCompiler_inline_result = globalClientIdCounter++, identifierPrefix = "_" + identifierPrefix + "r_" + JSCompiler_inline_result.toString(32) + "_"; + return hook.memoizedState = identifierPrefix; + }, + useHostTransitionStatus, + useFormState: mountActionState, + useActionState: mountActionState, + useOptimistic: function(passthrough) { + var hook = mountWorkInProgressHook(); + hook.memoizedState = hook.baseState = passthrough; + var queue = { + pending: null, + lanes: 0, + dispatch: null, + lastRenderedReducer: null, + lastRenderedState: null + }; + hook.queue = queue; + hook = dispatchOptimisticSetState.bind(null, currentlyRenderingFiber, true, queue); + queue.dispatch = hook; + return [passthrough, hook]; + }, + useMemoCache, + useCacheRefresh: function() { + return mountWorkInProgressHook().memoizedState = refreshCache.bind(null, currentlyRenderingFiber); + }, + useEffectEvent: function(callback) { + var hook = mountWorkInProgressHook(), ref = { impl: callback }; + hook.memoizedState = ref; + return function() { + if ((executionContext & 2) !== 0) + throw Error(formatProdErrorMessage2(440)); + return ref.impl.apply(undefined, arguments); + }; + } + }; + HooksDispatcherOnUpdate = { + readContext, + use, + useCallback: updateCallback, + useContext: readContext, + useEffect: updateEffect, + useImperativeHandle: updateImperativeHandle, + useInsertionEffect: updateInsertionEffect, + useLayoutEffect: updateLayoutEffect, + useMemo: updateMemo, + useReducer: updateReducer, + useRef: updateRef, + useState: function() { + return updateReducer(basicStateReducer); + }, + useDebugValue: mountDebugValue, + useDeferredValue: function(value, initialValue) { + var hook = updateWorkInProgressHook(); + return updateDeferredValueImpl(hook, currentHook.memoizedState, value, initialValue); + }, + useTransition: function() { + var booleanOrThenable = updateReducer(basicStateReducer)[0], start = updateWorkInProgressHook().memoizedState; + return [ + typeof booleanOrThenable === "boolean" ? booleanOrThenable : useThenable(booleanOrThenable), + start + ]; + }, + useSyncExternalStore: updateSyncExternalStore, + useId: updateId, + useHostTransitionStatus, + useFormState: updateActionState, + useActionState: updateActionState, + useOptimistic: function(passthrough, reducer) { + var hook = updateWorkInProgressHook(); + return updateOptimisticImpl(hook, currentHook, passthrough, reducer); + }, + useMemoCache, + useCacheRefresh: updateRefresh + }; + HooksDispatcherOnUpdate.useEffectEvent = updateEvent; + HooksDispatcherOnRerender = { + readContext, + use, + useCallback: updateCallback, + useContext: readContext, + useEffect: updateEffect, + useImperativeHandle: updateImperativeHandle, + useInsertionEffect: updateInsertionEffect, + useLayoutEffect: updateLayoutEffect, + useMemo: updateMemo, + useReducer: rerenderReducer, + useRef: updateRef, + useState: function() { + return rerenderReducer(basicStateReducer); + }, + useDebugValue: mountDebugValue, + useDeferredValue: function(value, initialValue) { + var hook = updateWorkInProgressHook(); + return currentHook === null ? mountDeferredValueImpl(hook, value, initialValue) : updateDeferredValueImpl(hook, currentHook.memoizedState, value, initialValue); + }, + useTransition: function() { + var booleanOrThenable = rerenderReducer(basicStateReducer)[0], start = updateWorkInProgressHook().memoizedState; + return [ + typeof booleanOrThenable === "boolean" ? booleanOrThenable : useThenable(booleanOrThenable), + start + ]; + }, + useSyncExternalStore: updateSyncExternalStore, + useId: updateId, + useHostTransitionStatus, + useFormState: rerenderActionState, + useActionState: rerenderActionState, + useOptimistic: function(passthrough, reducer) { + var hook = updateWorkInProgressHook(); + if (currentHook !== null) + return updateOptimisticImpl(hook, currentHook, passthrough, reducer); + hook.baseState = passthrough; + return [passthrough, hook.queue.dispatch]; + }, + useMemoCache, + useCacheRefresh: updateRefresh + }; + HooksDispatcherOnRerender.useEffectEvent = updateEvent; + classComponentUpdater = { + enqueueSetState: function(inst, payload, callback) { + inst = inst._reactInternals; + var lane = requestUpdateLane(), update = createUpdate(lane); + update.payload = payload; + callback !== undefined && callback !== null && (update.callback = callback); + payload = enqueueUpdate(inst, update, lane); + payload !== null && (scheduleUpdateOnFiber(payload, inst, lane), entangleTransitions(payload, inst, lane)); + }, + enqueueReplaceState: function(inst, payload, callback) { + inst = inst._reactInternals; + var lane = requestUpdateLane(), update = createUpdate(lane); + update.tag = 1; + update.payload = payload; + callback !== undefined && callback !== null && (update.callback = callback); + payload = enqueueUpdate(inst, update, lane); + payload !== null && (scheduleUpdateOnFiber(payload, inst, lane), entangleTransitions(payload, inst, lane)); + }, + enqueueForceUpdate: function(inst, callback) { + inst = inst._reactInternals; + var lane = requestUpdateLane(), update = createUpdate(lane); + update.tag = 2; + callback !== undefined && callback !== null && (update.callback = callback); + callback = enqueueUpdate(inst, update, lane); + callback !== null && (scheduleUpdateOnFiber(callback, inst, lane), entangleTransitions(callback, inst, lane)); + } + }; + SelectiveHydrationException = Error(formatProdErrorMessage2(461)); + SUSPENDED_MARKER = { + dehydrated: null, + treeContext: null, + retryLane: 0, + hydrationErrors: null + }; + PossiblyWeakSet = typeof WeakSet === "function" ? WeakSet : Set; + DefaultAsyncDispatcher = { + getCacheForType: function(resourceType) { + var cache = readContext(CacheContext), cacheForType = cache.data.get(resourceType); + cacheForType === undefined && (cacheForType = resourceType(), cache.data.set(resourceType, cacheForType)); + return cacheForType; + }, + cacheSignal: function() { + return readContext(CacheContext).controller.signal; + } + }; + PossiblyWeakMap = typeof WeakMap === "function" ? WeakMap : Map; + for (i$jscomp$inline_1577 = 0;i$jscomp$inline_1577 < simpleEventPluginEvents.length; i$jscomp$inline_1577++) { + eventName$jscomp$inline_1578 = simpleEventPluginEvents[i$jscomp$inline_1577], domEventName$jscomp$inline_1579 = eventName$jscomp$inline_1578.toLowerCase(), capitalizedEvent$jscomp$inline_1580 = eventName$jscomp$inline_1578[0].toUpperCase() + eventName$jscomp$inline_1578.slice(1); + registerSimpleEvent(domEventName$jscomp$inline_1579, "on" + capitalizedEvent$jscomp$inline_1580); + } + registerSimpleEvent(ANIMATION_END, "onAnimationEnd"); + registerSimpleEvent(ANIMATION_ITERATION, "onAnimationIteration"); + registerSimpleEvent(ANIMATION_START, "onAnimationStart"); + registerSimpleEvent("dblclick", "onDoubleClick"); + registerSimpleEvent("focusin", "onFocus"); + registerSimpleEvent("focusout", "onBlur"); + registerSimpleEvent(TRANSITION_RUN, "onTransitionRun"); + registerSimpleEvent(TRANSITION_START, "onTransitionStart"); + registerSimpleEvent(TRANSITION_CANCEL, "onTransitionCancel"); + registerSimpleEvent(TRANSITION_END, "onTransitionEnd"); + registerDirectEvent("onMouseEnter", ["mouseout", "mouseover"]); + registerDirectEvent("onMouseLeave", ["mouseout", "mouseover"]); + registerDirectEvent("onPointerEnter", ["pointerout", "pointerover"]); + registerDirectEvent("onPointerLeave", ["pointerout", "pointerover"]); + registerTwoPhaseEvent("onChange", "change click focusin focusout input keydown keyup selectionchange".split(" ")); + registerTwoPhaseEvent("onSelect", "focusout contextmenu dragend focusin keydown keyup mousedown mouseup selectionchange".split(" ")); + registerTwoPhaseEvent("onBeforeInput", [ + "compositionend", + "keypress", + "textInput", + "paste" + ]); + registerTwoPhaseEvent("onCompositionEnd", "compositionend focusout keydown keypress keyup mousedown".split(" ")); + registerTwoPhaseEvent("onCompositionStart", "compositionstart focusout keydown keypress keyup mousedown".split(" ")); + registerTwoPhaseEvent("onCompositionUpdate", "compositionupdate focusout keydown keypress keyup mousedown".split(" ")); + mediaEventTypes = "abort canplay canplaythrough durationchange emptied encrypted ended error loadeddata loadedmetadata loadstart pause play playing progress ratechange resize seeked seeking stalled suspend timeupdate volumechange waiting".split(" "); + nonDelegatedEvents = new Set("beforetoggle cancel close invalid load scroll scrollend toggle".split(" ").concat(mediaEventTypes)); + listeningMarker = "_reactListening" + Math.random().toString(36).slice(2); + NORMALIZE_NEWLINES_REGEX = /\r\n?/g; + NORMALIZE_NULL_AND_REPLACEMENT_REGEX = /\u0000|\uFFFD/g; + scheduleTimeout = typeof setTimeout === "function" ? setTimeout : undefined; + cancelTimeout = typeof clearTimeout === "function" ? clearTimeout : undefined; + localPromise = typeof Promise === "function" ? Promise : undefined; + scheduleMicrotask = typeof queueMicrotask === "function" ? queueMicrotask : typeof localPromise !== "undefined" ? function(callback) { + return localPromise.resolve(null).then(callback).catch(handleErrorInNextTick); + } : scheduleTimeout; + preloadPropsMap = new Map; + preconnectsSet = new Set; + previousDispatcher = ReactDOMSharedInternals.d; + ReactDOMSharedInternals.d = { + f: flushSyncWork, + r: requestFormReset, + D: prefetchDNS, + C: preconnect, + L: preload, + m: preloadModule, + X: preinitScript, + S: preinitStyle, + M: preinitModuleScript + }; + globalDocument = typeof document === "undefined" ? null : document; + HostTransitionContext = { + $$typeof: REACT_CONTEXT_TYPE2, + Provider: null, + Consumer: null, + _currentValue: sharedNotPendingObject, + _currentValue2: sharedNotPendingObject, + _threadCount: 0 + }; + queuedPointers = new Map; + queuedPointerCaptures = new Map; + queuedExplicitHydrationTargets = []; + discreteReplayableEvents = "mousedown mouseup touchcancel touchend touchstart auxclick dblclick pointercancel pointerdown pointerup dragend dragstart drop compositionend compositionstart keydown keypress keyup input textInput copy cut paste click change contextmenu reset".split(" "); + ReactDOMHydrationRoot.prototype.render = ReactDOMRoot.prototype.render = function(children) { + var root2 = this._internalRoot; + if (root2 === null) + throw Error(formatProdErrorMessage2(409)); + var current = root2.current, lane = requestUpdateLane(); + updateContainerImpl(current, lane, children, root2, null, null); + }; + ReactDOMHydrationRoot.prototype.unmount = ReactDOMRoot.prototype.unmount = function() { + var root2 = this._internalRoot; + if (root2 !== null) { + this._internalRoot = null; + var container = root2.containerInfo; + updateContainerImpl(root2.current, 2, null, root2, null, null); + flushSyncWork$1(); + container[internalContainerInstanceKey] = null; + } + }; + ReactDOMHydrationRoot.prototype.unstable_scheduleHydration = function(target) { + if (target) { + var updatePriority = resolveUpdatePriority(); + target = { blockedOn: null, target, priority: updatePriority }; + for (var i = 0;i < queuedExplicitHydrationTargets.length && updatePriority !== 0 && updatePriority < queuedExplicitHydrationTargets[i].priority; i++) + ; + queuedExplicitHydrationTargets.splice(i, 0, target); + i === 0 && attemptExplicitHydrationTarget(target); + } + }; + isomorphicReactPackageVersion$jscomp$inline_1840 = React2.version; + if (isomorphicReactPackageVersion$jscomp$inline_1840 !== "19.2.4") + throw Error(formatProdErrorMessage2(527, isomorphicReactPackageVersion$jscomp$inline_1840, "19.2.4")); + ReactDOMSharedInternals.findDOMNode = function(componentOrElement) { + var fiber = componentOrElement._reactInternals; + if (fiber === undefined) { + if (typeof componentOrElement.render === "function") + throw Error(formatProdErrorMessage2(188)); + componentOrElement = Object.keys(componentOrElement).join(","); + throw Error(formatProdErrorMessage2(268, componentOrElement)); + } + componentOrElement = findCurrentFiberUsingSlowPath(fiber); + componentOrElement = componentOrElement !== null ? findCurrentHostFiberImpl(componentOrElement) : null; + componentOrElement = componentOrElement === null ? null : componentOrElement.stateNode; + return componentOrElement; + }; + internals$jscomp$inline_2347 = { + bundleType: 0, + version: "19.2.4", + rendererPackageName: "react-dom", + currentDispatcherRef: ReactSharedInternals3, + reconcilerVersion: "19.2.4" + }; + if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined") { + hook$jscomp$inline_2348 = __REACT_DEVTOOLS_GLOBAL_HOOK__; + if (!hook$jscomp$inline_2348.isDisabled && hook$jscomp$inline_2348.supportsFiber) + try { + rendererID = hook$jscomp$inline_2348.inject(internals$jscomp$inline_2347), injectedHook = hook$jscomp$inline_2348; + } catch (err) {} + } +}); + +// node_modules/react-dom/client.js +var require_client = __commonJS((exports, module) => { + init_react_dom_client_production(); + function checkDCE() { + if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === "undefined" || typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE !== "function") { + return; + } + if (false) {} + try { + __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(checkDCE); + } catch (err) { + console.error(err); + } + } + if (true) { + checkDCE(); + module.exports = exports_react_dom_client_production; + } +}); + +// node_modules/qrcode/lib/can-promise.js +var require_can_promise = __commonJS((exports, module) => { + module.exports = function() { + return typeof Promise === "function" && Promise.prototype && Promise.prototype.then; + }; +}); + +// node_modules/qrcode/lib/core/utils.js +var require_utils = __commonJS((exports) => { + var toSJISFunction; + var CODEWORDS_COUNT = [ + 0, + 26, + 44, + 70, + 100, + 134, + 172, + 196, + 242, + 292, + 346, + 404, + 466, + 532, + 581, + 655, + 733, + 815, + 901, + 991, + 1085, + 1156, + 1258, + 1364, + 1474, + 1588, + 1706, + 1828, + 1921, + 2051, + 2185, + 2323, + 2465, + 2611, + 2761, + 2876, + 3034, + 3196, + 3362, + 3532, + 3706 + ]; + exports.getSymbolSize = function getSymbolSize(version2) { + if (!version2) + throw new Error('"version" cannot be null or undefined'); + if (version2 < 1 || version2 > 40) + throw new Error('"version" should be in range from 1 to 40'); + return version2 * 4 + 17; + }; + exports.getSymbolTotalCodewords = function getSymbolTotalCodewords(version2) { + return CODEWORDS_COUNT[version2]; + }; + exports.getBCHDigit = function(data) { + let digit = 0; + while (data !== 0) { + digit++; + data >>>= 1; + } + return digit; + }; + exports.setToSJISFunction = function setToSJISFunction(f) { + if (typeof f !== "function") { + throw new Error('"toSJISFunc" is not a valid function.'); + } + toSJISFunction = f; + }; + exports.isKanjiModeEnabled = function() { + return typeof toSJISFunction !== "undefined"; + }; + exports.toSJIS = function toSJIS(kanji) { + return toSJISFunction(kanji); + }; +}); + +// node_modules/qrcode/lib/core/error-correction-level.js +var require_error_correction_level = __commonJS((exports) => { + exports.L = { bit: 1 }; + exports.M = { bit: 0 }; + exports.Q = { bit: 3 }; + exports.H = { bit: 2 }; + function fromString(string) { + if (typeof string !== "string") { + throw new Error("Param is not a string"); + } + const lcStr = string.toLowerCase(); + switch (lcStr) { + case "l": + case "low": + return exports.L; + case "m": + case "medium": + return exports.M; + case "q": + case "quartile": + return exports.Q; + case "h": + case "high": + return exports.H; + default: + throw new Error("Unknown EC Level: " + string); + } + } + exports.isValid = function isValid(level) { + return level && typeof level.bit !== "undefined" && level.bit >= 0 && level.bit < 4; + }; + exports.from = function from(value, defaultValue) { + if (exports.isValid(value)) { + return value; + } + try { + return fromString(value); + } catch (e) { + return defaultValue; + } + }; +}); + +// node_modules/qrcode/lib/core/bit-buffer.js +var require_bit_buffer = __commonJS((exports, module) => { + function BitBuffer() { + this.buffer = []; + this.length = 0; + } + BitBuffer.prototype = { + get: function(index2) { + const bufIndex = Math.floor(index2 / 8); + return (this.buffer[bufIndex] >>> 7 - index2 % 8 & 1) === 1; + }, + put: function(num, length) { + for (let i = 0;i < length; i++) { + this.putBit((num >>> length - i - 1 & 1) === 1); + } + }, + getLengthInBits: function() { + return this.length; + }, + putBit: function(bit) { + const bufIndex = Math.floor(this.length / 8); + if (this.buffer.length <= bufIndex) { + this.buffer.push(0); + } + if (bit) { + this.buffer[bufIndex] |= 128 >>> this.length % 8; + } + this.length++; + } + }; + module.exports = BitBuffer; +}); + +// node_modules/qrcode/lib/core/bit-matrix.js +var require_bit_matrix = __commonJS((exports, module) => { + function BitMatrix(size) { + if (!size || size < 1) { + throw new Error("BitMatrix size must be defined and greater than 0"); + } + this.size = size; + this.data = new Uint8Array(size * size); + this.reservedBit = new Uint8Array(size * size); + } + BitMatrix.prototype.set = function(row, col, value, reserved) { + const index2 = row * this.size + col; + this.data[index2] = value; + if (reserved) + this.reservedBit[index2] = true; + }; + BitMatrix.prototype.get = function(row, col) { + return this.data[row * this.size + col]; + }; + BitMatrix.prototype.xor = function(row, col, value) { + this.data[row * this.size + col] ^= value; + }; + BitMatrix.prototype.isReserved = function(row, col) { + return this.reservedBit[row * this.size + col]; + }; + module.exports = BitMatrix; +}); + +// node_modules/qrcode/lib/core/alignment-pattern.js +var require_alignment_pattern = __commonJS((exports) => { + var getSymbolSize = require_utils().getSymbolSize; + exports.getRowColCoords = function getRowColCoords(version2) { + if (version2 === 1) + return []; + const posCount = Math.floor(version2 / 7) + 2; + const size = getSymbolSize(version2); + const intervals = size === 145 ? 26 : Math.ceil((size - 13) / (2 * posCount - 2)) * 2; + const positions = [size - 7]; + for (let i = 1;i < posCount - 1; i++) { + positions[i] = positions[i - 1] - intervals; + } + positions.push(6); + return positions.reverse(); + }; + exports.getPositions = function getPositions(version2) { + const coords = []; + const pos = exports.getRowColCoords(version2); + const posLength = pos.length; + for (let i = 0;i < posLength; i++) { + for (let j = 0;j < posLength; j++) { + if (i === 0 && j === 0 || i === 0 && j === posLength - 1 || i === posLength - 1 && j === 0) { + continue; + } + coords.push([pos[i], pos[j]]); + } + } + return coords; + }; +}); + +// node_modules/qrcode/lib/core/finder-pattern.js +var require_finder_pattern = __commonJS((exports) => { + var getSymbolSize = require_utils().getSymbolSize; + var FINDER_PATTERN_SIZE = 7; + exports.getPositions = function getPositions(version2) { + const size = getSymbolSize(version2); + return [ + [0, 0], + [size - FINDER_PATTERN_SIZE, 0], + [0, size - FINDER_PATTERN_SIZE] + ]; + }; +}); + +// node_modules/qrcode/lib/core/mask-pattern.js +var require_mask_pattern = __commonJS((exports) => { + exports.Patterns = { + PATTERN000: 0, + PATTERN001: 1, + PATTERN010: 2, + PATTERN011: 3, + PATTERN100: 4, + PATTERN101: 5, + PATTERN110: 6, + PATTERN111: 7 + }; + var PenaltyScores = { + N1: 3, + N2: 3, + N3: 40, + N4: 10 + }; + exports.isValid = function isValid(mask) { + return mask != null && mask !== "" && !isNaN(mask) && mask >= 0 && mask <= 7; + }; + exports.from = function from(value) { + return exports.isValid(value) ? parseInt(value, 10) : undefined; + }; + exports.getPenaltyN1 = function getPenaltyN1(data) { + const size = data.size; + let points = 0; + let sameCountCol = 0; + let sameCountRow = 0; + let lastCol = null; + let lastRow = null; + for (let row = 0;row < size; row++) { + sameCountCol = sameCountRow = 0; + lastCol = lastRow = null; + for (let col = 0;col < size; col++) { + let module2 = data.get(row, col); + if (module2 === lastCol) { + sameCountCol++; + } else { + if (sameCountCol >= 5) + points += PenaltyScores.N1 + (sameCountCol - 5); + lastCol = module2; + sameCountCol = 1; + } + module2 = data.get(col, row); + if (module2 === lastRow) { + sameCountRow++; + } else { + if (sameCountRow >= 5) + points += PenaltyScores.N1 + (sameCountRow - 5); + lastRow = module2; + sameCountRow = 1; + } + } + if (sameCountCol >= 5) + points += PenaltyScores.N1 + (sameCountCol - 5); + if (sameCountRow >= 5) + points += PenaltyScores.N1 + (sameCountRow - 5); + } + return points; + }; + exports.getPenaltyN2 = function getPenaltyN2(data) { + const size = data.size; + let points = 0; + for (let row = 0;row < size - 1; row++) { + for (let col = 0;col < size - 1; col++) { + const last = data.get(row, col) + data.get(row, col + 1) + data.get(row + 1, col) + data.get(row + 1, col + 1); + if (last === 4 || last === 0) + points++; + } + } + return points * PenaltyScores.N2; + }; + exports.getPenaltyN3 = function getPenaltyN3(data) { + const size = data.size; + let points = 0; + let bitsCol = 0; + let bitsRow = 0; + for (let row = 0;row < size; row++) { + bitsCol = bitsRow = 0; + for (let col = 0;col < size; col++) { + bitsCol = bitsCol << 1 & 2047 | data.get(row, col); + if (col >= 10 && (bitsCol === 1488 || bitsCol === 93)) + points++; + bitsRow = bitsRow << 1 & 2047 | data.get(col, row); + if (col >= 10 && (bitsRow === 1488 || bitsRow === 93)) + points++; + } + } + return points * PenaltyScores.N3; + }; + exports.getPenaltyN4 = function getPenaltyN4(data) { + let darkCount = 0; + const modulesCount = data.data.length; + for (let i = 0;i < modulesCount; i++) + darkCount += data.data[i]; + const k = Math.abs(Math.ceil(darkCount * 100 / modulesCount / 5) - 10); + return k * PenaltyScores.N4; + }; + function getMaskAt(maskPattern, i, j) { + switch (maskPattern) { + case exports.Patterns.PATTERN000: + return (i + j) % 2 === 0; + case exports.Patterns.PATTERN001: + return i % 2 === 0; + case exports.Patterns.PATTERN010: + return j % 3 === 0; + case exports.Patterns.PATTERN011: + return (i + j) % 3 === 0; + case exports.Patterns.PATTERN100: + return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 === 0; + case exports.Patterns.PATTERN101: + return i * j % 2 + i * j % 3 === 0; + case exports.Patterns.PATTERN110: + return (i * j % 2 + i * j % 3) % 2 === 0; + case exports.Patterns.PATTERN111: + return (i * j % 3 + (i + j) % 2) % 2 === 0; + default: + throw new Error("bad maskPattern:" + maskPattern); + } + } + exports.applyMask = function applyMask(pattern, data) { + const size = data.size; + for (let col = 0;col < size; col++) { + for (let row = 0;row < size; row++) { + if (data.isReserved(row, col)) + continue; + data.xor(row, col, getMaskAt(pattern, row, col)); + } + } + }; + exports.getBestMask = function getBestMask(data, setupFormatFunc) { + const numPatterns = Object.keys(exports.Patterns).length; + let bestPattern = 0; + let lowerPenalty = Infinity; + for (let p = 0;p < numPatterns; p++) { + setupFormatFunc(p); + exports.applyMask(p, data); + const penalty = exports.getPenaltyN1(data) + exports.getPenaltyN2(data) + exports.getPenaltyN3(data) + exports.getPenaltyN4(data); + exports.applyMask(p, data); + if (penalty < lowerPenalty) { + lowerPenalty = penalty; + bestPattern = p; + } + } + return bestPattern; + }; +}); + +// node_modules/qrcode/lib/core/error-correction-code.js +var require_error_correction_code = __commonJS((exports) => { + var ECLevel = require_error_correction_level(); + var EC_BLOCKS_TABLE = [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 2, + 2, + 1, + 2, + 2, + 4, + 1, + 2, + 4, + 4, + 2, + 4, + 4, + 4, + 2, + 4, + 6, + 5, + 2, + 4, + 6, + 6, + 2, + 5, + 8, + 8, + 4, + 5, + 8, + 8, + 4, + 5, + 8, + 11, + 4, + 8, + 10, + 11, + 4, + 9, + 12, + 16, + 4, + 9, + 16, + 16, + 6, + 10, + 12, + 18, + 6, + 10, + 17, + 16, + 6, + 11, + 16, + 19, + 6, + 13, + 18, + 21, + 7, + 14, + 21, + 25, + 8, + 16, + 20, + 25, + 8, + 17, + 23, + 25, + 9, + 17, + 23, + 34, + 9, + 18, + 25, + 30, + 10, + 20, + 27, + 32, + 12, + 21, + 29, + 35, + 12, + 23, + 34, + 37, + 12, + 25, + 34, + 40, + 13, + 26, + 35, + 42, + 14, + 28, + 38, + 45, + 15, + 29, + 40, + 48, + 16, + 31, + 43, + 51, + 17, + 33, + 45, + 54, + 18, + 35, + 48, + 57, + 19, + 37, + 51, + 60, + 19, + 38, + 53, + 63, + 20, + 40, + 56, + 66, + 21, + 43, + 59, + 70, + 22, + 45, + 62, + 74, + 24, + 47, + 65, + 77, + 25, + 49, + 68, + 81 + ]; + var EC_CODEWORDS_TABLE = [ + 7, + 10, + 13, + 17, + 10, + 16, + 22, + 28, + 15, + 26, + 36, + 44, + 20, + 36, + 52, + 64, + 26, + 48, + 72, + 88, + 36, + 64, + 96, + 112, + 40, + 72, + 108, + 130, + 48, + 88, + 132, + 156, + 60, + 110, + 160, + 192, + 72, + 130, + 192, + 224, + 80, + 150, + 224, + 264, + 96, + 176, + 260, + 308, + 104, + 198, + 288, + 352, + 120, + 216, + 320, + 384, + 132, + 240, + 360, + 432, + 144, + 280, + 408, + 480, + 168, + 308, + 448, + 532, + 180, + 338, + 504, + 588, + 196, + 364, + 546, + 650, + 224, + 416, + 600, + 700, + 224, + 442, + 644, + 750, + 252, + 476, + 690, + 816, + 270, + 504, + 750, + 900, + 300, + 560, + 810, + 960, + 312, + 588, + 870, + 1050, + 336, + 644, + 952, + 1110, + 360, + 700, + 1020, + 1200, + 390, + 728, + 1050, + 1260, + 420, + 784, + 1140, + 1350, + 450, + 812, + 1200, + 1440, + 480, + 868, + 1290, + 1530, + 510, + 924, + 1350, + 1620, + 540, + 980, + 1440, + 1710, + 570, + 1036, + 1530, + 1800, + 570, + 1064, + 1590, + 1890, + 600, + 1120, + 1680, + 1980, + 630, + 1204, + 1770, + 2100, + 660, + 1260, + 1860, + 2220, + 720, + 1316, + 1950, + 2310, + 750, + 1372, + 2040, + 2430 + ]; + exports.getBlocksCount = function getBlocksCount(version2, errorCorrectionLevel) { + switch (errorCorrectionLevel) { + case ECLevel.L: + return EC_BLOCKS_TABLE[(version2 - 1) * 4 + 0]; + case ECLevel.M: + return EC_BLOCKS_TABLE[(version2 - 1) * 4 + 1]; + case ECLevel.Q: + return EC_BLOCKS_TABLE[(version2 - 1) * 4 + 2]; + case ECLevel.H: + return EC_BLOCKS_TABLE[(version2 - 1) * 4 + 3]; + default: + return; + } + }; + exports.getTotalCodewordsCount = function getTotalCodewordsCount(version2, errorCorrectionLevel) { + switch (errorCorrectionLevel) { + case ECLevel.L: + return EC_CODEWORDS_TABLE[(version2 - 1) * 4 + 0]; + case ECLevel.M: + return EC_CODEWORDS_TABLE[(version2 - 1) * 4 + 1]; + case ECLevel.Q: + return EC_CODEWORDS_TABLE[(version2 - 1) * 4 + 2]; + case ECLevel.H: + return EC_CODEWORDS_TABLE[(version2 - 1) * 4 + 3]; + default: + return; + } + }; +}); + +// node_modules/qrcode/lib/core/galois-field.js +var require_galois_field = __commonJS((exports) => { + var EXP_TABLE = new Uint8Array(512); + var LOG_TABLE = new Uint8Array(256); + (function initTables() { + let x = 1; + for (let i = 0;i < 255; i++) { + EXP_TABLE[i] = x; + LOG_TABLE[x] = i; + x <<= 1; + if (x & 256) { + x ^= 285; + } + } + for (let i = 255;i < 512; i++) { + EXP_TABLE[i] = EXP_TABLE[i - 255]; + } + })(); + exports.log = function log3(n) { + if (n < 1) + throw new Error("log(" + n + ")"); + return LOG_TABLE[n]; + }; + exports.exp = function exp(n) { + return EXP_TABLE[n]; + }; + exports.mul = function mul(x, y) { + if (x === 0 || y === 0) + return 0; + return EXP_TABLE[LOG_TABLE[x] + LOG_TABLE[y]]; + }; +}); + +// node_modules/qrcode/lib/core/polynomial.js +var require_polynomial = __commonJS((exports) => { + var GF = require_galois_field(); + exports.mul = function mul(p1, p2) { + const coeff = new Uint8Array(p1.length + p2.length - 1); + for (let i = 0;i < p1.length; i++) { + for (let j = 0;j < p2.length; j++) { + coeff[i + j] ^= GF.mul(p1[i], p2[j]); + } + } + return coeff; + }; + exports.mod = function mod(divident, divisor) { + let result = new Uint8Array(divident); + while (result.length - divisor.length >= 0) { + const coeff = result[0]; + for (let i = 0;i < divisor.length; i++) { + result[i] ^= GF.mul(divisor[i], coeff); + } + let offset = 0; + while (offset < result.length && result[offset] === 0) + offset++; + result = result.slice(offset); + } + return result; + }; + exports.generateECPolynomial = function generateECPolynomial(degree) { + let poly = new Uint8Array([1]); + for (let i = 0;i < degree; i++) { + poly = exports.mul(poly, new Uint8Array([1, GF.exp(i)])); + } + return poly; + }; +}); + +// node_modules/qrcode/lib/core/reed-solomon-encoder.js +var require_reed_solomon_encoder = __commonJS((exports, module) => { + var Polynomial = require_polynomial(); + function ReedSolomonEncoder(degree) { + this.genPoly = undefined; + this.degree = degree; + if (this.degree) + this.initialize(this.degree); + } + ReedSolomonEncoder.prototype.initialize = function initialize(degree) { + this.degree = degree; + this.genPoly = Polynomial.generateECPolynomial(this.degree); + }; + ReedSolomonEncoder.prototype.encode = function encode(data) { + if (!this.genPoly) { + throw new Error("Encoder not initialized"); + } + const paddedData = new Uint8Array(data.length + this.degree); + paddedData.set(data); + const remainder = Polynomial.mod(paddedData, this.genPoly); + const start = this.degree - remainder.length; + if (start > 0) { + const buff = new Uint8Array(this.degree); + buff.set(remainder, start); + return buff; + } + return remainder; + }; + module.exports = ReedSolomonEncoder; +}); + +// node_modules/qrcode/lib/core/version-check.js +var require_version_check = __commonJS((exports) => { + exports.isValid = function isValid(version2) { + return !isNaN(version2) && version2 >= 1 && version2 <= 40; + }; +}); + +// node_modules/qrcode/lib/core/regex.js +var require_regex = __commonJS((exports) => { + var numeric = "[0-9]+"; + var alphanumeric = "[A-Z $%*+\\-./:]+"; + var kanji = "(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|" + "[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|" + "[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|" + "[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+"; + kanji = kanji.replace(/u/g, "\\u"); + var byte = "(?:(?![A-Z0-9 $%*+\\-./:]|" + kanji + `)(?:.|[\r +]))+`; + exports.KANJI = new RegExp(kanji, "g"); + exports.BYTE_KANJI = new RegExp("[^A-Z0-9 $%*+\\-./:]+", "g"); + exports.BYTE = new RegExp(byte, "g"); + exports.NUMERIC = new RegExp(numeric, "g"); + exports.ALPHANUMERIC = new RegExp(alphanumeric, "g"); + var TEST_KANJI = new RegExp("^" + kanji + "$"); + var TEST_NUMERIC = new RegExp("^" + numeric + "$"); + var TEST_ALPHANUMERIC = new RegExp("^[A-Z0-9 $%*+\\-./:]+$"); + exports.testKanji = function testKanji(str) { + return TEST_KANJI.test(str); + }; + exports.testNumeric = function testNumeric(str) { + return TEST_NUMERIC.test(str); + }; + exports.testAlphanumeric = function testAlphanumeric(str) { + return TEST_ALPHANUMERIC.test(str); + }; +}); + +// node_modules/qrcode/lib/core/mode.js +var require_mode = __commonJS((exports) => { + var VersionCheck = require_version_check(); + var Regex = require_regex(); + exports.NUMERIC = { + id: "Numeric", + bit: 1 << 0, + ccBits: [10, 12, 14] + }; + exports.ALPHANUMERIC = { + id: "Alphanumeric", + bit: 1 << 1, + ccBits: [9, 11, 13] + }; + exports.BYTE = { + id: "Byte", + bit: 1 << 2, + ccBits: [8, 16, 16] + }; + exports.KANJI = { + id: "Kanji", + bit: 1 << 3, + ccBits: [8, 10, 12] + }; + exports.MIXED = { + bit: -1 + }; + exports.getCharCountIndicator = function getCharCountIndicator(mode, version2) { + if (!mode.ccBits) + throw new Error("Invalid mode: " + mode); + if (!VersionCheck.isValid(version2)) { + throw new Error("Invalid version: " + version2); + } + if (version2 >= 1 && version2 < 10) + return mode.ccBits[0]; + else if (version2 < 27) + return mode.ccBits[1]; + return mode.ccBits[2]; + }; + exports.getBestModeForData = function getBestModeForData(dataStr) { + if (Regex.testNumeric(dataStr)) + return exports.NUMERIC; + else if (Regex.testAlphanumeric(dataStr)) + return exports.ALPHANUMERIC; + else if (Regex.testKanji(dataStr)) + return exports.KANJI; + else + return exports.BYTE; + }; + exports.toString = function toString(mode) { + if (mode && mode.id) + return mode.id; + throw new Error("Invalid mode"); + }; + exports.isValid = function isValid(mode) { + return mode && mode.bit && mode.ccBits; + }; + function fromString(string) { + if (typeof string !== "string") { + throw new Error("Param is not a string"); + } + const lcStr = string.toLowerCase(); + switch (lcStr) { + case "numeric": + return exports.NUMERIC; + case "alphanumeric": + return exports.ALPHANUMERIC; + case "kanji": + return exports.KANJI; + case "byte": + return exports.BYTE; + default: + throw new Error("Unknown mode: " + string); + } + } + exports.from = function from(value, defaultValue) { + if (exports.isValid(value)) { + return value; + } + try { + return fromString(value); + } catch (e) { + return defaultValue; + } + }; +}); + +// node_modules/qrcode/lib/core/version.js +var require_version = __commonJS((exports) => { + var Utils = require_utils(); + var ECCode = require_error_correction_code(); + var ECLevel = require_error_correction_level(); + var Mode = require_mode(); + var VersionCheck = require_version_check(); + var G18 = 1 << 12 | 1 << 11 | 1 << 10 | 1 << 9 | 1 << 8 | 1 << 5 | 1 << 2 | 1 << 0; + var G18_BCH = Utils.getBCHDigit(G18); + function getBestVersionForDataLength(mode, length, errorCorrectionLevel) { + for (let currentVersion = 1;currentVersion <= 40; currentVersion++) { + if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel, mode)) { + return currentVersion; + } + } + return; + } + function getReservedBitsCount(mode, version2) { + return Mode.getCharCountIndicator(mode, version2) + 4; + } + function getTotalBitsFromDataArray(segments, version2) { + let totalBits = 0; + segments.forEach(function(data) { + const reservedBits = getReservedBitsCount(data.mode, version2); + totalBits += reservedBits + data.getBitsLength(); + }); + return totalBits; + } + function getBestVersionForMixedData(segments, errorCorrectionLevel) { + for (let currentVersion = 1;currentVersion <= 40; currentVersion++) { + const length = getTotalBitsFromDataArray(segments, currentVersion); + if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel, Mode.MIXED)) { + return currentVersion; + } + } + return; + } + exports.from = function from(value, defaultValue) { + if (VersionCheck.isValid(value)) { + return parseInt(value, 10); + } + return defaultValue; + }; + exports.getCapacity = function getCapacity(version2, errorCorrectionLevel, mode) { + if (!VersionCheck.isValid(version2)) { + throw new Error("Invalid QR Code version"); + } + if (typeof mode === "undefined") + mode = Mode.BYTE; + const totalCodewords = Utils.getSymbolTotalCodewords(version2); + const ecTotalCodewords = ECCode.getTotalCodewordsCount(version2, errorCorrectionLevel); + const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8; + if (mode === Mode.MIXED) + return dataTotalCodewordsBits; + const usableBits = dataTotalCodewordsBits - getReservedBitsCount(mode, version2); + switch (mode) { + case Mode.NUMERIC: + return Math.floor(usableBits / 10 * 3); + case Mode.ALPHANUMERIC: + return Math.floor(usableBits / 11 * 2); + case Mode.KANJI: + return Math.floor(usableBits / 13); + case Mode.BYTE: + default: + return Math.floor(usableBits / 8); + } + }; + exports.getBestVersionForData = function getBestVersionForData(data, errorCorrectionLevel) { + let seg; + const ecl = ECLevel.from(errorCorrectionLevel, ECLevel.M); + if (Array.isArray(data)) { + if (data.length > 1) { + return getBestVersionForMixedData(data, ecl); + } + if (data.length === 0) { + return 1; + } + seg = data[0]; + } else { + seg = data; + } + return getBestVersionForDataLength(seg.mode, seg.getLength(), ecl); + }; + exports.getEncodedBits = function getEncodedBits(version2) { + if (!VersionCheck.isValid(version2) || version2 < 7) { + throw new Error("Invalid QR Code version"); + } + let d = version2 << 12; + while (Utils.getBCHDigit(d) - G18_BCH >= 0) { + d ^= G18 << Utils.getBCHDigit(d) - G18_BCH; + } + return version2 << 12 | d; + }; +}); + +// node_modules/qrcode/lib/core/format-info.js +var require_format_info = __commonJS((exports) => { + var Utils = require_utils(); + var G15 = 1 << 10 | 1 << 8 | 1 << 5 | 1 << 4 | 1 << 2 | 1 << 1 | 1 << 0; + var G15_MASK = 1 << 14 | 1 << 12 | 1 << 10 | 1 << 4 | 1 << 1; + var G15_BCH = Utils.getBCHDigit(G15); + exports.getEncodedBits = function getEncodedBits(errorCorrectionLevel, mask) { + const data = errorCorrectionLevel.bit << 3 | mask; + let d = data << 10; + while (Utils.getBCHDigit(d) - G15_BCH >= 0) { + d ^= G15 << Utils.getBCHDigit(d) - G15_BCH; + } + return (data << 10 | d) ^ G15_MASK; + }; +}); + +// node_modules/qrcode/lib/core/numeric-data.js +var require_numeric_data = __commonJS((exports, module) => { + var Mode = require_mode(); + function NumericData(data) { + this.mode = Mode.NUMERIC; + this.data = data.toString(); + } + NumericData.getBitsLength = function getBitsLength(length) { + return 10 * Math.floor(length / 3) + (length % 3 ? length % 3 * 3 + 1 : 0); + }; + NumericData.prototype.getLength = function getLength() { + return this.data.length; + }; + NumericData.prototype.getBitsLength = function getBitsLength() { + return NumericData.getBitsLength(this.data.length); + }; + NumericData.prototype.write = function write(bitBuffer) { + let i, group, value; + for (i = 0;i + 3 <= this.data.length; i += 3) { + group = this.data.substr(i, 3); + value = parseInt(group, 10); + bitBuffer.put(value, 10); + } + const remainingNum = this.data.length - i; + if (remainingNum > 0) { + group = this.data.substr(i); + value = parseInt(group, 10); + bitBuffer.put(value, remainingNum * 3 + 1); + } + }; + module.exports = NumericData; +}); + +// node_modules/qrcode/lib/core/alphanumeric-data.js +var require_alphanumeric_data = __commonJS((exports, module) => { + var Mode = require_mode(); + var ALPHA_NUM_CHARS = [ + "0", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "H", + "I", + "J", + "K", + "L", + "M", + "N", + "O", + "P", + "Q", + "R", + "S", + "T", + "U", + "V", + "W", + "X", + "Y", + "Z", + " ", + "$", + "%", + "*", + "+", + "-", + ".", + "/", + ":" + ]; + function AlphanumericData(data) { + this.mode = Mode.ALPHANUMERIC; + this.data = data; + } + AlphanumericData.getBitsLength = function getBitsLength(length) { + return 11 * Math.floor(length / 2) + 6 * (length % 2); + }; + AlphanumericData.prototype.getLength = function getLength() { + return this.data.length; + }; + AlphanumericData.prototype.getBitsLength = function getBitsLength() { + return AlphanumericData.getBitsLength(this.data.length); + }; + AlphanumericData.prototype.write = function write(bitBuffer) { + let i; + for (i = 0;i + 2 <= this.data.length; i += 2) { + let value = ALPHA_NUM_CHARS.indexOf(this.data[i]) * 45; + value += ALPHA_NUM_CHARS.indexOf(this.data[i + 1]); + bitBuffer.put(value, 11); + } + if (this.data.length % 2) { + bitBuffer.put(ALPHA_NUM_CHARS.indexOf(this.data[i]), 6); + } + }; + module.exports = AlphanumericData; +}); + +// node_modules/qrcode/lib/core/byte-data.js +var require_byte_data = __commonJS((exports, module) => { + var Mode = require_mode(); + function ByteData(data) { + this.mode = Mode.BYTE; + if (typeof data === "string") { + this.data = new TextEncoder().encode(data); + } else { + this.data = new Uint8Array(data); + } + } + ByteData.getBitsLength = function getBitsLength(length) { + return length * 8; + }; + ByteData.prototype.getLength = function getLength() { + return this.data.length; + }; + ByteData.prototype.getBitsLength = function getBitsLength() { + return ByteData.getBitsLength(this.data.length); + }; + ByteData.prototype.write = function(bitBuffer) { + for (let i = 0, l = this.data.length;i < l; i++) { + bitBuffer.put(this.data[i], 8); + } + }; + module.exports = ByteData; +}); + +// node_modules/qrcode/lib/core/kanji-data.js +var require_kanji_data = __commonJS((exports, module) => { + var Mode = require_mode(); + var Utils = require_utils(); + function KanjiData(data) { + this.mode = Mode.KANJI; + this.data = data; + } + KanjiData.getBitsLength = function getBitsLength(length) { + return length * 13; + }; + KanjiData.prototype.getLength = function getLength() { + return this.data.length; + }; + KanjiData.prototype.getBitsLength = function getBitsLength() { + return KanjiData.getBitsLength(this.data.length); + }; + KanjiData.prototype.write = function(bitBuffer) { + let i; + for (i = 0;i < this.data.length; i++) { + let value = Utils.toSJIS(this.data[i]); + if (value >= 33088 && value <= 40956) { + value -= 33088; + } else if (value >= 57408 && value <= 60351) { + value -= 49472; + } else { + throw new Error("Invalid SJIS character: " + this.data[i] + ` +` + "Make sure your charset is UTF-8"); + } + value = (value >>> 8 & 255) * 192 + (value & 255); + bitBuffer.put(value, 13); + } + }; + module.exports = KanjiData; +}); + +// node_modules/dijkstrajs/dijkstra.js +var require_dijkstra = __commonJS((exports, module) => { + var dijkstra = { + single_source_shortest_paths: function(graph, s, d) { + var predecessors = {}; + var costs = {}; + costs[s] = 0; + var open = dijkstra.PriorityQueue.make(); + open.push(s, 0); + var closest, u, v, cost_of_s_to_u, adjacent_nodes, cost_of_e, cost_of_s_to_u_plus_cost_of_e, cost_of_s_to_v, first_visit; + while (!open.empty()) { + closest = open.pop(); + u = closest.value; + cost_of_s_to_u = closest.cost; + adjacent_nodes = graph[u] || {}; + for (v in adjacent_nodes) { + if (adjacent_nodes.hasOwnProperty(v)) { + cost_of_e = adjacent_nodes[v]; + cost_of_s_to_u_plus_cost_of_e = cost_of_s_to_u + cost_of_e; + cost_of_s_to_v = costs[v]; + first_visit = typeof costs[v] === "undefined"; + if (first_visit || cost_of_s_to_v > cost_of_s_to_u_plus_cost_of_e) { + costs[v] = cost_of_s_to_u_plus_cost_of_e; + open.push(v, cost_of_s_to_u_plus_cost_of_e); + predecessors[v] = u; + } + } + } + } + if (typeof d !== "undefined" && typeof costs[d] === "undefined") { + var msg = ["Could not find a path from ", s, " to ", d, "."].join(""); + throw new Error(msg); + } + return predecessors; + }, + extract_shortest_path_from_predecessor_list: function(predecessors, d) { + var nodes = []; + var u = d; + var predecessor; + while (u) { + nodes.push(u); + predecessor = predecessors[u]; + u = predecessors[u]; + } + nodes.reverse(); + return nodes; + }, + find_path: function(graph, s, d) { + var predecessors = dijkstra.single_source_shortest_paths(graph, s, d); + return dijkstra.extract_shortest_path_from_predecessor_list(predecessors, d); + }, + PriorityQueue: { + make: function(opts) { + var T = dijkstra.PriorityQueue, t = {}, key; + opts = opts || {}; + for (key in T) { + if (T.hasOwnProperty(key)) { + t[key] = T[key]; + } + } + t.queue = []; + t.sorter = opts.sorter || T.default_sorter; + return t; + }, + default_sorter: function(a, b) { + return a.cost - b.cost; + }, + push: function(value, cost) { + var item = { value, cost }; + this.queue.push(item); + this.queue.sort(this.sorter); + }, + pop: function() { + return this.queue.shift(); + }, + empty: function() { + return this.queue.length === 0; + } + } + }; + if (typeof module !== "undefined") { + module.exports = dijkstra; + } +}); + +// node_modules/qrcode/lib/core/segments.js +var require_segments = __commonJS((exports) => { + var Mode = require_mode(); + var NumericData = require_numeric_data(); + var AlphanumericData = require_alphanumeric_data(); + var ByteData = require_byte_data(); + var KanjiData = require_kanji_data(); + var Regex = require_regex(); + var Utils = require_utils(); + var dijkstra = require_dijkstra(); + function getStringByteLength(str) { + return unescape(encodeURIComponent(str)).length; + } + function getSegments(regex, mode, str) { + const segments = []; + let result; + while ((result = regex.exec(str)) !== null) { + segments.push({ + data: result[0], + index: result.index, + mode, + length: result[0].length + }); + } + return segments; + } + function getSegmentsFromString(dataStr) { + const numSegs = getSegments(Regex.NUMERIC, Mode.NUMERIC, dataStr); + const alphaNumSegs = getSegments(Regex.ALPHANUMERIC, Mode.ALPHANUMERIC, dataStr); + let byteSegs; + let kanjiSegs; + if (Utils.isKanjiModeEnabled()) { + byteSegs = getSegments(Regex.BYTE, Mode.BYTE, dataStr); + kanjiSegs = getSegments(Regex.KANJI, Mode.KANJI, dataStr); + } else { + byteSegs = getSegments(Regex.BYTE_KANJI, Mode.BYTE, dataStr); + kanjiSegs = []; + } + const segs = numSegs.concat(alphaNumSegs, byteSegs, kanjiSegs); + return segs.sort(function(s1, s2) { + return s1.index - s2.index; + }).map(function(obj) { + return { + data: obj.data, + mode: obj.mode, + length: obj.length + }; + }); + } + function getSegmentBitsLength(length, mode) { + switch (mode) { + case Mode.NUMERIC: + return NumericData.getBitsLength(length); + case Mode.ALPHANUMERIC: + return AlphanumericData.getBitsLength(length); + case Mode.KANJI: + return KanjiData.getBitsLength(length); + case Mode.BYTE: + return ByteData.getBitsLength(length); + } + } + function mergeSegments(segs) { + return segs.reduce(function(acc, curr) { + const prevSeg = acc.length - 1 >= 0 ? acc[acc.length - 1] : null; + if (prevSeg && prevSeg.mode === curr.mode) { + acc[acc.length - 1].data += curr.data; + return acc; + } + acc.push(curr); + return acc; + }, []); + } + function buildNodes(segs) { + const nodes = []; + for (let i = 0;i < segs.length; i++) { + const seg = segs[i]; + switch (seg.mode) { + case Mode.NUMERIC: + nodes.push([ + seg, + { data: seg.data, mode: Mode.ALPHANUMERIC, length: seg.length }, + { data: seg.data, mode: Mode.BYTE, length: seg.length } + ]); + break; + case Mode.ALPHANUMERIC: + nodes.push([ + seg, + { data: seg.data, mode: Mode.BYTE, length: seg.length } + ]); + break; + case Mode.KANJI: + nodes.push([ + seg, + { data: seg.data, mode: Mode.BYTE, length: getStringByteLength(seg.data) } + ]); + break; + case Mode.BYTE: + nodes.push([ + { data: seg.data, mode: Mode.BYTE, length: getStringByteLength(seg.data) } + ]); + } + } + return nodes; + } + function buildGraph(nodes, version2) { + const table = {}; + const graph = { start: {} }; + let prevNodeIds = ["start"]; + for (let i = 0;i < nodes.length; i++) { + const nodeGroup = nodes[i]; + const currentNodeIds = []; + for (let j = 0;j < nodeGroup.length; j++) { + const node = nodeGroup[j]; + const key = "" + i + j; + currentNodeIds.push(key); + table[key] = { node, lastCount: 0 }; + graph[key] = {}; + for (let n = 0;n < prevNodeIds.length; n++) { + const prevNodeId = prevNodeIds[n]; + if (table[prevNodeId] && table[prevNodeId].node.mode === node.mode) { + graph[prevNodeId][key] = getSegmentBitsLength(table[prevNodeId].lastCount + node.length, node.mode) - getSegmentBitsLength(table[prevNodeId].lastCount, node.mode); + table[prevNodeId].lastCount += node.length; + } else { + if (table[prevNodeId]) + table[prevNodeId].lastCount = node.length; + graph[prevNodeId][key] = getSegmentBitsLength(node.length, node.mode) + 4 + Mode.getCharCountIndicator(node.mode, version2); + } + } + } + prevNodeIds = currentNodeIds; + } + for (let n = 0;n < prevNodeIds.length; n++) { + graph[prevNodeIds[n]].end = 0; + } + return { map: graph, table }; + } + function buildSingleSegment(data, modesHint) { + let mode; + const bestMode = Mode.getBestModeForData(data); + mode = Mode.from(modesHint, bestMode); + if (mode !== Mode.BYTE && mode.bit < bestMode.bit) { + throw new Error('"' + data + '"' + " cannot be encoded with mode " + Mode.toString(mode) + `. + Suggested mode is: ` + Mode.toString(bestMode)); + } + if (mode === Mode.KANJI && !Utils.isKanjiModeEnabled()) { + mode = Mode.BYTE; + } + switch (mode) { + case Mode.NUMERIC: + return new NumericData(data); + case Mode.ALPHANUMERIC: + return new AlphanumericData(data); + case Mode.KANJI: + return new KanjiData(data); + case Mode.BYTE: + return new ByteData(data); + } + } + exports.fromArray = function fromArray(array) { + return array.reduce(function(acc, seg) { + if (typeof seg === "string") { + acc.push(buildSingleSegment(seg, null)); + } else if (seg.data) { + acc.push(buildSingleSegment(seg.data, seg.mode)); + } + return acc; + }, []); + }; + exports.fromString = function fromString(data, version2) { + const segs = getSegmentsFromString(data, Utils.isKanjiModeEnabled()); + const nodes = buildNodes(segs); + const graph = buildGraph(nodes, version2); + const path = dijkstra.find_path(graph.map, "start", "end"); + const optimizedSegs = []; + for (let i = 1;i < path.length - 1; i++) { + optimizedSegs.push(graph.table[path[i]].node); + } + return exports.fromArray(mergeSegments(optimizedSegs)); + }; + exports.rawSplit = function rawSplit(data) { + return exports.fromArray(getSegmentsFromString(data, Utils.isKanjiModeEnabled())); + }; +}); + +// node_modules/qrcode/lib/core/qrcode.js +var require_qrcode = __commonJS((exports) => { + var Utils = require_utils(); + var ECLevel = require_error_correction_level(); + var BitBuffer = require_bit_buffer(); + var BitMatrix = require_bit_matrix(); + var AlignmentPattern = require_alignment_pattern(); + var FinderPattern = require_finder_pattern(); + var MaskPattern = require_mask_pattern(); + var ECCode = require_error_correction_code(); + var ReedSolomonEncoder = require_reed_solomon_encoder(); + var Version = require_version(); + var FormatInfo = require_format_info(); + var Mode = require_mode(); + var Segments = require_segments(); + function setupFinderPattern(matrix, version2) { + const size = matrix.size; + const pos = FinderPattern.getPositions(version2); + for (let i = 0;i < pos.length; i++) { + const row = pos[i][0]; + const col = pos[i][1]; + for (let r = -1;r <= 7; r++) { + if (row + r <= -1 || size <= row + r) + continue; + for (let c = -1;c <= 7; c++) { + if (col + c <= -1 || size <= col + c) + continue; + if (r >= 0 && r <= 6 && (c === 0 || c === 6) || c >= 0 && c <= 6 && (r === 0 || r === 6) || r >= 2 && r <= 4 && c >= 2 && c <= 4) { + matrix.set(row + r, col + c, true, true); + } else { + matrix.set(row + r, col + c, false, true); + } + } + } + } + } + function setupTimingPattern(matrix) { + const size = matrix.size; + for (let r = 8;r < size - 8; r++) { + const value = r % 2 === 0; + matrix.set(r, 6, value, true); + matrix.set(6, r, value, true); + } + } + function setupAlignmentPattern(matrix, version2) { + const pos = AlignmentPattern.getPositions(version2); + for (let i = 0;i < pos.length; i++) { + const row = pos[i][0]; + const col = pos[i][1]; + for (let r = -2;r <= 2; r++) { + for (let c = -2;c <= 2; c++) { + if (r === -2 || r === 2 || c === -2 || c === 2 || r === 0 && c === 0) { + matrix.set(row + r, col + c, true, true); + } else { + matrix.set(row + r, col + c, false, true); + } + } + } + } + } + function setupVersionInfo(matrix, version2) { + const size = matrix.size; + const bits = Version.getEncodedBits(version2); + let row, col, mod; + for (let i = 0;i < 18; i++) { + row = Math.floor(i / 3); + col = i % 3 + size - 8 - 3; + mod = (bits >> i & 1) === 1; + matrix.set(row, col, mod, true); + matrix.set(col, row, mod, true); + } + } + function setupFormatInfo(matrix, errorCorrectionLevel, maskPattern) { + const size = matrix.size; + const bits = FormatInfo.getEncodedBits(errorCorrectionLevel, maskPattern); + let i, mod; + for (i = 0;i < 15; i++) { + mod = (bits >> i & 1) === 1; + if (i < 6) { + matrix.set(i, 8, mod, true); + } else if (i < 8) { + matrix.set(i + 1, 8, mod, true); + } else { + matrix.set(size - 15 + i, 8, mod, true); + } + if (i < 8) { + matrix.set(8, size - i - 1, mod, true); + } else if (i < 9) { + matrix.set(8, 15 - i - 1 + 1, mod, true); + } else { + matrix.set(8, 15 - i - 1, mod, true); + } + } + matrix.set(size - 8, 8, 1, true); + } + function setupData(matrix, data) { + const size = matrix.size; + let inc = -1; + let row = size - 1; + let bitIndex = 7; + let byteIndex = 0; + for (let col = size - 1;col > 0; col -= 2) { + if (col === 6) + col--; + while (true) { + for (let c = 0;c < 2; c++) { + if (!matrix.isReserved(row, col - c)) { + let dark = false; + if (byteIndex < data.length) { + dark = (data[byteIndex] >>> bitIndex & 1) === 1; + } + matrix.set(row, col - c, dark); + bitIndex--; + if (bitIndex === -1) { + byteIndex++; + bitIndex = 7; + } + } + } + row += inc; + if (row < 0 || size <= row) { + row -= inc; + inc = -inc; + break; + } + } + } + } + function createData(version2, errorCorrectionLevel, segments) { + const buffer = new BitBuffer; + segments.forEach(function(data) { + buffer.put(data.mode.bit, 4); + buffer.put(data.getLength(), Mode.getCharCountIndicator(data.mode, version2)); + data.write(buffer); + }); + const totalCodewords = Utils.getSymbolTotalCodewords(version2); + const ecTotalCodewords = ECCode.getTotalCodewordsCount(version2, errorCorrectionLevel); + const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8; + if (buffer.getLengthInBits() + 4 <= dataTotalCodewordsBits) { + buffer.put(0, 4); + } + while (buffer.getLengthInBits() % 8 !== 0) { + buffer.putBit(0); + } + const remainingByte = (dataTotalCodewordsBits - buffer.getLengthInBits()) / 8; + for (let i = 0;i < remainingByte; i++) { + buffer.put(i % 2 ? 17 : 236, 8); + } + return createCodewords(buffer, version2, errorCorrectionLevel); + } + function createCodewords(bitBuffer, version2, errorCorrectionLevel) { + const totalCodewords = Utils.getSymbolTotalCodewords(version2); + const ecTotalCodewords = ECCode.getTotalCodewordsCount(version2, errorCorrectionLevel); + const dataTotalCodewords = totalCodewords - ecTotalCodewords; + const ecTotalBlocks = ECCode.getBlocksCount(version2, errorCorrectionLevel); + const blocksInGroup2 = totalCodewords % ecTotalBlocks; + const blocksInGroup1 = ecTotalBlocks - blocksInGroup2; + const totalCodewordsInGroup1 = Math.floor(totalCodewords / ecTotalBlocks); + const dataCodewordsInGroup1 = Math.floor(dataTotalCodewords / ecTotalBlocks); + const dataCodewordsInGroup2 = dataCodewordsInGroup1 + 1; + const ecCount = totalCodewordsInGroup1 - dataCodewordsInGroup1; + const rs = new ReedSolomonEncoder(ecCount); + let offset = 0; + const dcData = new Array(ecTotalBlocks); + const ecData = new Array(ecTotalBlocks); + let maxDataSize = 0; + const buffer = new Uint8Array(bitBuffer.buffer); + for (let b = 0;b < ecTotalBlocks; b++) { + const dataSize = b < blocksInGroup1 ? dataCodewordsInGroup1 : dataCodewordsInGroup2; + dcData[b] = buffer.slice(offset, offset + dataSize); + ecData[b] = rs.encode(dcData[b]); + offset += dataSize; + maxDataSize = Math.max(maxDataSize, dataSize); + } + const data = new Uint8Array(totalCodewords); + let index2 = 0; + let i, r; + for (i = 0;i < maxDataSize; i++) { + for (r = 0;r < ecTotalBlocks; r++) { + if (i < dcData[r].length) { + data[index2++] = dcData[r][i]; + } + } + } + for (i = 0;i < ecCount; i++) { + for (r = 0;r < ecTotalBlocks; r++) { + data[index2++] = ecData[r][i]; + } + } + return data; + } + function createSymbol(data, version2, errorCorrectionLevel, maskPattern) { + let segments; + if (Array.isArray(data)) { + segments = Segments.fromArray(data); + } else if (typeof data === "string") { + let estimatedVersion = version2; + if (!estimatedVersion) { + const rawSegments = Segments.rawSplit(data); + estimatedVersion = Version.getBestVersionForData(rawSegments, errorCorrectionLevel); + } + segments = Segments.fromString(data, estimatedVersion || 40); + } else { + throw new Error("Invalid data"); + } + const bestVersion = Version.getBestVersionForData(segments, errorCorrectionLevel); + if (!bestVersion) { + throw new Error("The amount of data is too big to be stored in a QR Code"); + } + if (!version2) { + version2 = bestVersion; + } else if (version2 < bestVersion) { + throw new Error(` +` + `The chosen QR Code version cannot contain this amount of data. +` + "Minimum version required to store current data is: " + bestVersion + `. +`); + } + const dataBits = createData(version2, errorCorrectionLevel, segments); + const moduleCount = Utils.getSymbolSize(version2); + const modules = new BitMatrix(moduleCount); + setupFinderPattern(modules, version2); + setupTimingPattern(modules); + setupAlignmentPattern(modules, version2); + setupFormatInfo(modules, errorCorrectionLevel, 0); + if (version2 >= 7) { + setupVersionInfo(modules, version2); + } + setupData(modules, dataBits); + if (isNaN(maskPattern)) { + maskPattern = MaskPattern.getBestMask(modules, setupFormatInfo.bind(null, modules, errorCorrectionLevel)); + } + MaskPattern.applyMask(maskPattern, modules); + setupFormatInfo(modules, errorCorrectionLevel, maskPattern); + return { + modules, + version: version2, + errorCorrectionLevel, + maskPattern, + segments + }; + } + exports.create = function create(data, options2) { + if (typeof data === "undefined" || data === "") { + throw new Error("No input text"); + } + let errorCorrectionLevel = ECLevel.M; + let version2; + let mask; + if (typeof options2 !== "undefined") { + errorCorrectionLevel = ECLevel.from(options2.errorCorrectionLevel, ECLevel.M); + version2 = Version.from(options2.version); + mask = MaskPattern.from(options2.maskPattern); + if (options2.toSJISFunc) { + Utils.setToSJISFunction(options2.toSJISFunc); + } + } + return createSymbol(data, version2, errorCorrectionLevel, mask); + }; +}); + +// node_modules/qrcode/lib/renderer/utils.js +var require_utils2 = __commonJS((exports) => { + function hex2rgba(hex) { + if (typeof hex === "number") { + hex = hex.toString(); + } + if (typeof hex !== "string") { + throw new Error("Color should be defined as hex string"); + } + let hexCode = hex.slice().replace("#", "").split(""); + if (hexCode.length < 3 || hexCode.length === 5 || hexCode.length > 8) { + throw new Error("Invalid hex color: " + hex); + } + if (hexCode.length === 3 || hexCode.length === 4) { + hexCode = Array.prototype.concat.apply([], hexCode.map(function(c) { + return [c, c]; + })); + } + if (hexCode.length === 6) + hexCode.push("F", "F"); + const hexValue = parseInt(hexCode.join(""), 16); + return { + r: hexValue >> 24 & 255, + g: hexValue >> 16 & 255, + b: hexValue >> 8 & 255, + a: hexValue & 255, + hex: "#" + hexCode.slice(0, 6).join("") + }; + } + exports.getOptions = function getOptions(options2) { + if (!options2) + options2 = {}; + if (!options2.color) + options2.color = {}; + const margin = typeof options2.margin === "undefined" || options2.margin === null || options2.margin < 0 ? 4 : options2.margin; + const width = options2.width && options2.width >= 21 ? options2.width : undefined; + const scale = options2.scale || 4; + return { + width, + scale: width ? 4 : scale, + margin, + color: { + dark: hex2rgba(options2.color.dark || "#000000ff"), + light: hex2rgba(options2.color.light || "#ffffffff") + }, + type: options2.type, + rendererOpts: options2.rendererOpts || {} + }; + }; + exports.getScale = function getScale(qrSize, opts) { + return opts.width && opts.width >= qrSize + opts.margin * 2 ? opts.width / (qrSize + opts.margin * 2) : opts.scale; + }; + exports.getImageWidth = function getImageWidth(qrSize, opts) { + const scale = exports.getScale(qrSize, opts); + return Math.floor((qrSize + opts.margin * 2) * scale); + }; + exports.qrToImageData = function qrToImageData(imgData, qr, opts) { + const size = qr.modules.size; + const data = qr.modules.data; + const scale = exports.getScale(size, opts); + const symbolSize = Math.floor((size + opts.margin * 2) * scale); + const scaledMargin = opts.margin * scale; + const palette = [opts.color.light, opts.color.dark]; + for (let i = 0;i < symbolSize; i++) { + for (let j = 0;j < symbolSize; j++) { + let posDst = (i * symbolSize + j) * 4; + let pxColor = opts.color.light; + if (i >= scaledMargin && j >= scaledMargin && i < symbolSize - scaledMargin && j < symbolSize - scaledMargin) { + const iSrc = Math.floor((i - scaledMargin) / scale); + const jSrc = Math.floor((j - scaledMargin) / scale); + pxColor = palette[data[iSrc * size + jSrc] ? 1 : 0]; + } + imgData[posDst++] = pxColor.r; + imgData[posDst++] = pxColor.g; + imgData[posDst++] = pxColor.b; + imgData[posDst] = pxColor.a; + } + } + }; +}); + +// node_modules/qrcode/lib/renderer/canvas.js +var require_canvas = __commonJS((exports) => { + var Utils = require_utils2(); + function clearCanvas(ctx, canvas, size) { + ctx.clearRect(0, 0, canvas.width, canvas.height); + if (!canvas.style) + canvas.style = {}; + canvas.height = size; + canvas.width = size; + canvas.style.height = size + "px"; + canvas.style.width = size + "px"; + } + function getCanvasElement() { + try { + return document.createElement("canvas"); + } catch (e) { + throw new Error("You need to specify a canvas element"); + } + } + exports.render = function render(qrData, canvas, options2) { + let opts = options2; + let canvasEl = canvas; + if (typeof opts === "undefined" && (!canvas || !canvas.getContext)) { + opts = canvas; + canvas = undefined; + } + if (!canvas) { + canvasEl = getCanvasElement(); + } + opts = Utils.getOptions(opts); + const size = Utils.getImageWidth(qrData.modules.size, opts); + const ctx = canvasEl.getContext("2d"); + const image = ctx.createImageData(size, size); + Utils.qrToImageData(image.data, qrData, opts); + clearCanvas(ctx, canvasEl, size); + ctx.putImageData(image, 0, 0); + return canvasEl; + }; + exports.renderToDataURL = function renderToDataURL(qrData, canvas, options2) { + let opts = options2; + if (typeof opts === "undefined" && (!canvas || !canvas.getContext)) { + opts = canvas; + canvas = undefined; + } + if (!opts) + opts = {}; + const canvasEl = exports.render(qrData, canvas, opts); + const type = opts.type || "image/png"; + const rendererOpts = opts.rendererOpts || {}; + return canvasEl.toDataURL(type, rendererOpts.quality); + }; +}); + +// node_modules/qrcode/lib/renderer/svg-tag.js +var require_svg_tag = __commonJS((exports) => { + var Utils = require_utils2(); + function getColorAttrib(color, attrib) { + const alpha = color.a / 255; + const str = attrib + '="' + color.hex + '"'; + return alpha < 1 ? str + " " + attrib + '-opacity="' + alpha.toFixed(2).slice(1) + '"' : str; + } + function svgCmd(cmd, x, y) { + let str = cmd + x; + if (typeof y !== "undefined") + str += " " + y; + return str; + } + function qrToPath(data, size, margin) { + let path = ""; + let moveBy = 0; + let newRow = false; + let lineLength = 0; + for (let i = 0;i < data.length; i++) { + const col = Math.floor(i % size); + const row = Math.floor(i / size); + if (!col && !newRow) + newRow = true; + if (data[i]) { + lineLength++; + if (!(i > 0 && col > 0 && data[i - 1])) { + path += newRow ? svgCmd("M", col + margin, 0.5 + row + margin) : svgCmd("m", moveBy, 0); + moveBy = 0; + newRow = false; + } + if (!(col + 1 < size && data[i + 1])) { + path += svgCmd("h", lineLength); + lineLength = 0; + } + } else { + moveBy++; + } + } + return path; + } + exports.render = function render(qrData, options2, cb) { + const opts = Utils.getOptions(options2); + const size = qrData.modules.size; + const data = qrData.modules.data; + const qrcodesize = size + opts.margin * 2; + const bg = !opts.color.light.a ? "" : "'; + const path = "'; + const viewBox = 'viewBox="' + "0 0 " + qrcodesize + " " + qrcodesize + '"'; + const width = !opts.width ? "" : 'width="' + opts.width + '" height="' + opts.width + '" '; + const svgTag = '' + bg + path + ` +`; + if (typeof cb === "function") { + cb(null, svgTag); + } + return svgTag; + }; +}); + +// node_modules/qrcode/lib/browser.js +var require_browser = __commonJS((exports) => { + var canPromise = require_can_promise(); + var QRCode = require_qrcode(); + var CanvasRenderer = require_canvas(); + var SvgRenderer = require_svg_tag(); + function renderCanvas(renderFunc, canvas, text, opts, cb) { + const args = [].slice.call(arguments, 1); + const argsNum = args.length; + const isLastArgCb = typeof args[argsNum - 1] === "function"; + if (!isLastArgCb && !canPromise()) { + throw new Error("Callback required as last argument"); + } + if (isLastArgCb) { + if (argsNum < 2) { + throw new Error("Too few arguments provided"); + } + if (argsNum === 2) { + cb = text; + text = canvas; + canvas = opts = undefined; + } else if (argsNum === 3) { + if (canvas.getContext && typeof cb === "undefined") { + cb = opts; + opts = undefined; + } else { + cb = opts; + opts = text; + text = canvas; + canvas = undefined; + } + } + } else { + if (argsNum < 1) { + throw new Error("Too few arguments provided"); + } + if (argsNum === 1) { + text = canvas; + canvas = opts = undefined; + } else if (argsNum === 2 && !canvas.getContext) { + opts = text; + text = canvas; + canvas = undefined; + } + return new Promise(function(resolve, reject) { + try { + const data = QRCode.create(text, opts); + resolve(renderFunc(data, canvas, opts)); + } catch (e) { + reject(e); + } + }); + } + try { + const data = QRCode.create(text, opts); + cb(null, renderFunc(data, canvas, opts)); + } catch (e) { + cb(e); + } + } + exports.create = QRCode.create; + exports.toCanvas = renderCanvas.bind(null, CanvasRenderer.render); + exports.toDataURL = renderCanvas.bind(null, CanvasRenderer.renderToDataURL); + exports.toString = renderCanvas.bind(null, function(data, _, opts) { + return SvgRenderer.render(data, opts); + }); +}); + +// node_modules/react/cjs/react-jsx-runtime.production.js +var exports_react_jsx_runtime_production = {}; +__export(exports_react_jsx_runtime_production, { + jsxs: () => $jsxs, + jsx: () => $jsx, + Fragment: () => $Fragment2 +}); +function jsxProd(type, config, maybeKey) { + var key = null; + maybeKey !== undefined && (key = "" + maybeKey); + config.key !== undefined && (key = "" + config.key); + if ("key" in config) { + maybeKey = {}; + for (var propName in config) + propName !== "key" && (maybeKey[propName] = config[propName]); + } else + maybeKey = config; + config = maybeKey.ref; + return { + $$typeof: REACT_ELEMENT_TYPE3, + type, + key, + ref: config !== undefined ? config : null, + props: maybeKey + }; +} +var REACT_ELEMENT_TYPE3, REACT_FRAGMENT_TYPE3, $Fragment2, $jsx, $jsxs; +var init_react_jsx_runtime_production = __esm(() => { + REACT_ELEMENT_TYPE3 = Symbol.for("react.transitional.element"); + REACT_FRAGMENT_TYPE3 = Symbol.for("react.fragment"); + $Fragment2 = REACT_FRAGMENT_TYPE3; + $jsx = jsxProd; + $jsxs = jsxProd; +}); + +// node_modules/react/jsx-runtime.js +var require_jsx_runtime = __commonJS((exports, module) => { + init_react_jsx_runtime_production(); + if (true) { + module.exports = exports_react_jsx_runtime_production; + } +}); + +// src/renderer/main.tsx +var import_react2 = __toESM(require_react(), 1); +var import_client = __toESM(require_client(), 1); + +// src/renderer/App.tsx +var import_react = __toESM(require_react(), 1); +var import_qrcode = __toESM(require_browser(), 1); + +// src/renderer/dateTime.ts +function pad(value) { + return String(value).padStart(2, "0"); +} +function hasExplicitTimezone(value) { + return /(?:Z|[+-]\d{2}:\d{2})$/i.test(value); +} +function parseLocalDateTimeParts(value) { + const match = String(value).trim().match(/^(\d{4})-(\d{2})-(\d{2})[T ](\d{2}):(\d{2})(?::(\d{2})(?:\.\d+)?)?$/); + if (!match) + return null; + const [, year, month, day, hour, minute, second = "00"] = match; + return { + year: Number(year), + month: Number(month), + day: Number(day), + hour: Number(hour), + minute: Number(minute), + second: Number(second) + }; +} +function parseTaskDateTime(value) { + if (!value) + return null; + const raw = String(value).trim(); + if (!raw) + return null; + if (hasExplicitTimezone(raw)) { + const date = new Date(raw); + return Number.isNaN(date.getTime()) ? null : date; + } + const parts = parseLocalDateTimeParts(raw); + if (parts) { + return new Date(parts.year, parts.month - 1, parts.day, parts.hour, parts.minute, parts.second, 0); + } + const fallback = new Date(raw); + return Number.isNaN(fallback.getTime()) ? null : fallback; +} +function formatTaskDateTime(value, options2) { + const date = parseTaskDateTime(value); + return date ? date.toLocaleString(undefined, options2) : ""; +} +function formatTaskTime(value, options2) { + const date = parseTaskDateTime(value); + return date ? date.toLocaleTimeString(undefined, options2) : ""; +} +function formatDateTimeLocalInput(value) { + const date = parseTaskDateTime(value); + if (!date) + return ""; + return [ + date.getFullYear(), + "-", + pad(date.getMonth() + 1), + "-", + pad(date.getDate()), + "T", + pad(date.getHours()), + ":", + pad(date.getMinutes()) + ].join(""); +} +function serializeDateTimeLocalInput(value) { + const parts = parseLocalDateTimeParts(value); + if (!parts) + return null; + return [ + parts.year, + "-", + pad(parts.month), + "-", + pad(parts.day), + "T", + pad(parts.hour), + ":", + pad(parts.minute), + ":", + pad(parts.second) + ].join(""); +} + +// src/renderer/channelsSettings.ts +var DEFAULT_CHANNELS_STATE = { + telegram: { + enabled: false, + configured: false, + running: false, + default_working_dir: "~", + default_chat_id: "", + bot_token: "", + allowed_users: "" + }, + slack: { + enabled: false, + configured: false, + running: false, + default_working_dir: "~", + default_channel: "", + default_user: "", + bot_token: "", + app_token: "" + }, + weixin: { + enabled: false, + configured: false, + running: false, + default_working_dir: "~", + base_url: "https://ilinkai.weixin.qq.com", + account_id: "", + login_status: "idle", + qr_code_url: "", + last_error: "", + user_id: "" + } +}; +function cloneState(state) { + return { + telegram: { ...state.telegram }, + slack: { ...state.slack }, + weixin: { ...state.weixin } + }; +} +function createInitialChannelsState(initial = {}) { + const base = cloneState(DEFAULT_CHANNELS_STATE); + return mergeChannelsStatus(base, initial); +} +function mergeChannelsStatus(current, status = {}) { + return { + telegram: { ...current.telegram, ...status.telegram || {} }, + slack: { ...current.slack, ...status.slack || {} }, + weixin: { ...current.weixin, ...status.weixin || {} } + }; +} +function buildChannelsSavePayload(channels) { + return { + telegram_enabled: channels.telegram.enabled ? "true" : "false", + telegram_bot_token: channels.telegram.bot_token, + telegram_allowed_users: channels.telegram.allowed_users, + telegram_default_working_dir: channels.telegram.default_working_dir, + telegram_default_chat_id: channels.telegram.default_chat_id, + slack_enabled: channels.slack.enabled ? "true" : "false", + slack_bot_token: channels.slack.bot_token, + slack_app_token: channels.slack.app_token, + slack_default_working_dir: channels.slack.default_working_dir, + slack_default_channel: channels.slack.default_channel, + slack_default_user: channels.slack.default_user, + weixin_enabled: channels.weixin.enabled ? "true" : "false", + weixin_default_working_dir: channels.weixin.default_working_dir, + weixin_base_url: channels.weixin.base_url, + weixin_account_id: channels.weixin.account_id + }; +} +function isWeixinQrImageSource(value) { + const normalized = (value || "").trim(); + if (!normalized) + return false; + if (normalized.startsWith("data:image/")) + return true; + if (/\.(png|jpg|jpeg|gif|webp|svg)(\?|#|$)/i.test(normalized)) + return true; + return false; +} + +// src/renderer/traceSteps.ts +var TRACE_EVENT_TYPES = new Set([ + "tool_call", + "tool_result", + "command_execution", + "file_change", + "web_search" +]); +var THINKING_PREFIX = "[thinking] "; +function compact(rows) { + return rows.filter(Boolean); +} +function row(label, value) { + const formatted = formatTraceValue(value); + return formatted === "" ? null : { label, value: formatted }; +} +function parseTracePayload(content) { + try { + const payload = JSON.parse(content); + return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : null; + } catch { + return null; + } +} +function formatTraceValue(value) { + if (value === undefined || value === null) + return ""; + if (typeof value === "string") + return value; + return JSON.stringify(value, null, 2); +} +function buildTraceRows(eventType, payload, rawContent = "") { + if (eventType === "tool_call") { + const name = payload.server ? `${payload.server}.${payload.name || payload.tool || "unknown"}` : payload.name || payload.tool || "unknown"; + return compact([ + row("Tool", name), + row("Input", payload.input || payload.arguments), + row("Result", payload.result), + row("Status", payload.status), + row("Error", payload.error) + ]); + } + if (eventType === "tool_result") { + return compact([ + row(payload.is_error ? "Tool Error" : "Tool Result", payload.tool_use_id || "result"), + row("Content", payload.content) + ]); + } + if (eventType === "command_execution") { + return compact([ + row("Command", payload.command), + row("Output", payload.output), + row("Exit", payload.exit_code), + row("Status", payload.status) + ]); + } + if (eventType === "file_change") { + const changes = Array.isArray(payload.changes) ? payload.changes.map((change) => { + if (!change || typeof change !== "object") + return formatTraceValue(change); + const kind = change.kind || change.type || "changed"; + const path = change.path || change.file || ""; + return path ? `${kind}: ${path}` : kind; + }).join(` +`) : payload.changes; + return compact([row("Changes", changes), row("Status", payload.status)]); + } + if (eventType === "web_search") { + return compact([ + row("Query", payload.query), + row("Action", payload.action), + row("Status", payload.status) + ]); + } + return [{ label: eventType, value: rawContent }]; +} +function buildExecutionSteps(events) { + const sortedEvents = [...events || []].sort(compareEventsChronologically); + const steps = []; + for (const event of sortedEvents) { + const step = eventToStep(event); + if (!step) + continue; + const previous = steps[steps.length - 1]; + if (canMergeSteps(previous, step)) { + previous.detail = appendDetail(previous.detail, step.detail); + previous.title = summarizeTitle(previous.detail) || previous.title; + previous.eventIds.push(...step.eventIds); + previous.count += step.count; + previous.timestamp = step.timestamp; + continue; + } + steps.push(step); + } + return steps.map((step, index2) => ({ + ...step, + number: index2 + 1 + })); +} +function compareEventsChronologically(a, b) { + const timestampComparison = String(a.timestamp || "").localeCompare(String(b.timestamp || "")); + if (timestampComparison !== 0) + return timestampComparison; + return Number(a.id || 0) - Number(b.id || 0); +} +function eventToStep(event) { + const eventType = event.event_type || event.type || "unknown"; + const content = event.content || ""; + const base = { + id: event.id ? `event-${event.id}` : `${eventType}-${event.timestamp || ""}-${content.length}`, + eventIds: event.id ? [event.id] : [], + rawEventType: eventType, + timestamp: event.timestamp || "", + rows: [], + detail: content, + count: 1 + }; + if (eventType === "assistant") { + if (content.startsWith(THINKING_PREFIX)) { + const detail = content.slice(THINKING_PREFIX.length); + return { + ...base, + type: "thinking", + title: summarizeTitle(detail) || "Thinking", + detail + }; + } + return { + ...base, + type: "assistant", + title: summarizeTitle(content) || "Assistant message" + }; + } + if (eventType === "user") { + return { + ...base, + type: "user", + title: summarizeTitle(content) || "User message" + }; + } + if (eventType === "result") { + return { + ...base, + type: "result", + title: summarizeTitle(content, "Result") || "Result" + }; + } + if (eventType === "error") { + return { + ...base, + type: "error", + title: summarizeTitle(content, "Error") || "Error" + }; + } + if (eventType === "image_content") { + const payload2 = parseTracePayload(content) || {}; + const mediaType = payload2.media_type || "image/jpeg"; + const imageSrc = payload2.data ? `data:${mediaType};base64,${payload2.data}` : ""; + return { + ...base, + type: "image_content", + title: "Image output", + rows: compact([row("Media", mediaType)]), + detail: "[image]", + imageSrc + }; + } + if (eventType === "generated_image") { + const payload2 = parseTracePayload(content) || { content }; + const imagePath = payload2.path || payload2.content || ""; + return { + ...base, + type: "generated_image", + title: imagePath ? `Generated image: ${basename(imagePath)}` : "Generated image", + rows: compact([row("Path", imagePath), row("Media", payload2.media_type)]), + detail: imagePath + }; + } + if (!TRACE_EVENT_TYPES.has(eventType)) { + return { + ...base, + type: "event", + title: summarizeTitle(content, eventType) || eventType + }; + } + const payload = parseTracePayload(content) || { content }; + const rows = buildTraceRows(eventType, payload, content); + return { + ...base, + type: eventType, + title: titleForTraceEvent(eventType, payload), + rows, + detail: rows.map((item) => `${item.label}: ${item.value}`).join(` +`) + }; +} +function titleForTraceEvent(eventType, payload) { + if (eventType === "tool_call") { + const name = payload.server ? `${payload.server}.${payload.name || payload.tool || "unknown"}` : payload.name || payload.tool || "unknown"; + return `Call tool: ${name}`; + } + if (eventType === "tool_result") { + const label = payload.is_error ? "Tool error" : "Tool result"; + return `${label}: ${payload.tool_use_id || "result"}`; + } + if (eventType === "command_execution") { + return `Run command: ${payload.command || payload.content || "command"}`; + } + if (eventType === "web_search") { + return `Search web: ${payload.query || payload.content || "query"}`; + } + if (eventType === "file_change") { + const changes = Array.isArray(payload.changes) ? payload.changes : []; + const firstPath = changes.find((change) => change && typeof change === "object" && (change.path || change.file)); + return firstPath ? `Change file: ${firstPath.path || firstPath.file}` : "Change files"; + } + return eventType; +} +function canMergeSteps(previous, next) { + return Boolean(previous && previous.type === next.type && (next.type === "thinking" || next.type === "assistant") && previous.rawEventType === next.rawEventType); +} +function appendDetail(previous, next) { + if (!previous) + return next || ""; + if (!next) + return previous; + if (previous.endsWith(` +`) || previous.endsWith(" ") || next.startsWith(` +`) || next.startsWith(" ")) { + return previous + next; + } + return `${previous} +${next}`; +} +function summarizeTitle(text, prefix2 = "") { + const normalized = String(text || "").replace(/\s+/g, " ").trim(); + if (!normalized) + return prefix2; + const title = normalized.length > 120 ? `${normalized.slice(0, 117).trim()}...` : normalized; + return prefix2 ? `${prefix2}: ${title}` : title; +} +function basename(value) { + const parts = String(value || "").split(/[\\/]/).filter(Boolean); + return parts[parts.length - 1] || String(value || ""); +} + +// src/renderer/App.tsx +var jsx_runtime = __toESM(require_jsx_runtime(), 1); +var API = "http://127.0.0.1:9712/api"; +var THEMES = { + dark: { + bg: "#0a0a0f", + surface: "#12121a", + surfaceHover: "#1a1a26", + border: "#1e1e2e", + borderActive: "#2d2d44", + text: "#e2e2ef", + textMuted: "#6b6b8a", + textDim: "#44445e", + accent: "#7c6aff", + accentGlow: "rgba(124, 106, 255, 0.15)", + green: "#34d399", + greenBg: "rgba(52, 211, 153, 0.08)", + orange: "#fbbf24", + orangeBg: "rgba(251, 191, 36, 0.08)", + red: "#f87171", + redBg: "rgba(248, 113, 113, 0.08)", + blue: "#60a5fa", + blueBg: "rgba(96, 165, 250, 0.08)", + cyan: "#22d3ee", + cyanBg: "rgba(34, 211, 238, 0.08)" + }, + light: { + bg: "#f5f5fa", + surface: "#ffffff", + surfaceHover: "#eeeef7", + border: "#dcdce8", + borderActive: "#b8b8d0", + text: "#1a1a2e", + textMuted: "#6b6b8a", + textDim: "#a0a0bc", + accent: "#5b4ecc", + accentGlow: "rgba(91, 78, 204, 0.12)", + green: "#059669", + greenBg: "rgba(5, 150, 105, 0.08)", + orange: "#d97706", + orangeBg: "rgba(217, 119, 6, 0.08)", + red: "#dc2626", + redBg: "rgba(220, 38, 38, 0.08)", + blue: "#2563eb", + blueBg: "rgba(37, 99, 235, 0.08)", + cyan: "#0891b2", + cyanBg: "rgba(8, 145, 178, 0.08)" + } +}; +var theme = THEMES.dark; +function getStatusConfig() { + return { + pending: { label: "Pending", color: theme.orange, bg: theme.orangeBg, icon: "◌" }, + scheduled: { label: "Scheduled", color: theme.cyan, bg: theme.cyanBg, icon: "⏱" }, + running: { label: "Running", color: theme.blue, bg: theme.blueBg, icon: "⟳" }, + completed: { label: "Completed", color: theme.green, bg: theme.greenBg, icon: "✓" }, + failed: { label: "Failed", color: theme.red, bg: theme.redBg, icon: "✕" }, + cancelled: { + label: "Cancelled", + color: theme.textMuted, + bg: "rgba(107,107,138,0.08)", + icon: "◻" + }, + blocked: { label: "Blocked", color: theme.textMuted, bg: "rgba(107,107,138,0.1)", icon: "⊘" } + }; +} +var COLUMNS = [ + { key: "queued", label: "Queue", statuses: ["pending", "scheduled", "blocked"], icon: "⧖" }, + { key: "running", label: "Running", statuses: ["running"], icon: "▸" }, + { key: "done", label: "Done", statuses: ["completed", "failed", "cancelled"], icon: "◆" } +]; +var AGENTS = { + claude: { label: "Claude Code", icon: "⌘", color: "#7c6aff" }, + codex: { label: "Codex CLI", icon: "◈", color: "#10a37f" } +}; +var DEFAULT_AGENT = "codex"; +var DEFAULT_TIMEOUT_SECONDS = 12000; +function FormattedOutput({ content, theme: theme2 }) { + if (!content) + return null; + const parseStreamJSON = (text) => { + const lines = text.split(` +`); + const parsedLines = []; + lines.forEach((line) => { + if (!line.trim()) + return; + try { + const event = JSON.parse(line); + const eventType = event.type; + switch (eventType) { + case "user": + case "assistant": { + const isUser = eventType === "user"; + const msg = event.message || {}; + const msgContent = msg.content || []; + const prefix2 = isUser ? "\uD83D\uDC64 User: " : "\uD83E\uDD16 Assistant: "; + const color = isUser ? theme2.accent : theme2.green; + let textBuf = ""; + const flushText = () => { + if (textBuf.trim()) { + parsedLines.push({ + type: eventType, + text: prefix2 + textBuf, + style: { color, fontWeight: isUser ? "bold" : "normal" } + }); + textBuf = ""; + } + }; + for (const c of msgContent) { + if (typeof c === "string") { + textBuf += c; + } else if (c && typeof c === "object") { + if (c.type === "text") { + textBuf += c.text || ""; + } else if (c.type === "image") { + flushText(); + const src = c.source && c.source.type === "base64" ? `data:${c.source.media_type || "image/jpeg"};base64,${c.source.data}` : null; + if (src) + parsedLines.push({ type: "image", src }); + } else if (c.type === "tool_use") { + flushText(); + const rows = buildTraceRows2("tool_call", { + id: c.id, + name: c.name, + input: c.input + }, ""); + parsedLines.push({ + type: "tool_call", + text: rows.map((row2) => `${row2.label}: ${row2.value}`).join(` +`), + style: { color: theme2.cyan, fontSize: "11px", fontFamily: "monospace" } + }); + } else if (c.type === "tool_result") { + flushText(); + const rows = buildTraceRows2("tool_result", { + tool_use_id: c.tool_use_id, + content: Array.isArray(c.content) ? c.content.map((part) => part && part.type === "text" ? part.text || "" : JSON.stringify(part)).join("") : c.content, + is_error: c.is_error + }, ""); + parsedLines.push({ + type: "tool_result", + text: rows.map((row2) => `${row2.label}: ${row2.value}`).join(` +`), + style: { + color: c.is_error ? theme2.red : theme2.blue, + fontSize: "11px", + fontFamily: "monospace" + } + }); + } + } + } + flushText(); + break; + } + case "item.completed": { + const item = event.item || {}; + if (item.type === "command_execution") { + const rows = buildTraceRows2("command_execution", { + command: item.command, + output: item.aggregated_output, + exit_code: item.exit_code, + status: item.status + }, ""); + parsedLines.push({ + type: "command_execution", + text: rows.map((row2) => `${row2.label}: ${row2.value}`).join(` +`), + style: { color: theme2.orange, fontSize: "11px", fontFamily: "monospace" } + }); + } else if (item.type === "mcp_tool_call" || item.type === "collab_tool_call") { + const rows = buildTraceRows2("tool_call", { + server: item.server, + name: item.tool || item.name, + input: item.arguments || item.input, + result: item.result, + status: item.status, + error: item.error + }, ""); + parsedLines.push({ + type: "tool_call", + text: rows.map((row2) => `${row2.label}: ${row2.value}`).join(` +`), + style: { color: theme2.cyan, fontSize: "11px", fontFamily: "monospace" } + }); + } else if (item.type === "web_search") { + const rows = buildTraceRows2("web_search", item, ""); + parsedLines.push({ + type: "web_search", + text: rows.map((row2) => `${row2.label}: ${row2.value}`).join(` +`), + style: { color: theme2.cyan, fontSize: "11px", fontFamily: "monospace" } + }); + } else if (item.type === "file_change") { + const rows = buildTraceRows2("file_change", item, ""); + parsedLines.push({ + type: "file_change", + text: rows.map((row2) => `${row2.label}: ${row2.value}`).join(` +`), + style: { color: theme2.accent, fontSize: "11px", fontFamily: "monospace" } + }); + } + break; + } + case "result": + if (event.result) { + parsedLines.push({ + type: "result", + text: `✅ Result: ${event.result}`, + style: { color: theme2.green, fontWeight: "bold" } + }); + } + break; + case "error": + parsedLines.push({ + type: "error", + text: `❌ Error: ${event.error || "Unknown error"}`, + style: { color: theme2.red, fontWeight: "bold" } + }); + break; + default: + if (eventType) { + let displayText = `[${eventType}]`; + if (event.message) { + const msg = event.message; + if (msg.content && Array.isArray(msg.content)) { + const textContent = msg.content.filter((c) => typeof c === "string" || c && typeof c === "object" && c.type === "text").map((c) => typeof c === "string" ? c : c.text || "").join(""); + if (textContent.trim()) { + displayText = textContent.slice(0, 200); + } + } + } else if (event.result) { + displayText = `Result: ${event.result.slice(0, 200)}`; + } else if (event.error) { + displayText = `Error: ${event.error.slice(0, 200)}`; + } + parsedLines.push({ + type: "event", + text: displayText, + style: { color: theme2.textDim, fontSize: "11px", fontFamily: "monospace" } + }); + } + } + } catch (_error) { + if (line.trim() && !line.startsWith("{")) { + if (line.includes("error") || line.includes("Error")) { + parsedLines.push({ + type: "error", + text: line, + style: { color: theme2.red } + }); + } else if (line.includes("success") || line.includes("Success")) { + parsedLines.push({ + type: "success", + text: line, + style: { color: theme2.green } + }); + } else if (line.length > 10) { + parsedLines.push({ + type: "text", + text: line, + style: { color: theme2.textDim } + }); + } + } + } + }); + return parsedLines; + }; + const parsedContent = parseStreamJSON(content); + if (parsedContent.length === 0) { + return /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { color: theme2.textDim, fontStyle: "italic", fontSize: "12px" }, + children: "Waiting for agent output..." + }); + } + return /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontFamily: "'JetBrains Mono', monospace", fontSize: "12px", lineHeight: "1.6" }, + children: parsedContent.map((item, index2) => item.type === "image" ? /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { margin: "6px 0" }, + children: /* @__PURE__ */ jsx_runtime.jsx("img", { + src: item.src, + alt: "output image", + style: { maxWidth: "100%", borderRadius: "4px", display: "block" } + }) + }, index2) : /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + ...item.style, + whiteSpace: "pre-wrap", + wordBreak: "break-word", + marginBottom: "2px", + padding: "2px 0" + }, + children: item.text + }, index2)) + }); +} +function ExecutionTimeline({ events }) { + const [expanded, setExpanded] = import_react.useState(true); + const steps = buildExecutionSteps(events); + if (steps.length === 0) { + return /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 12, color: theme.textDim, padding: "12px 0", textAlign: "center" }, + children: "No output events recorded — events are recorded for new task runs." + }); + } + return /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + border: `1px solid ${theme.border}`, + borderRadius: 8, + overflow: "hidden", + background: theme.bg + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("button", { + onClick: () => setExpanded(!expanded), + style: { + width: "100%", + display: "flex", + justifyContent: "space-between", + alignItems: "center", + gap: 12, + padding: "10px 12px", + background: theme.surface, + border: "none", + borderBottom: expanded ? `1px solid ${theme.border}` : "none", + color: theme.text, + cursor: "pointer", + fontFamily: "'JetBrains Mono', monospace", + fontSize: 12, + textAlign: "left" + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("span", { + style: { display: "flex", alignItems: "center", gap: 8, minWidth: 0 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { color: theme.textMuted }, + children: expanded ? "⌄" : "›" + }), + /* @__PURE__ */ jsx_runtime.jsxs("span", { + children: [ + "Show ", + steps.length, + " ", + steps.length === 1 ? "step" : "steps" + ] + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("span", { + style: { color: theme.textDim, fontSize: 10, whiteSpace: "nowrap" }, + children: [ + events.length, + " events" + ] + }) + ] + }), + expanded && /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { padding: "12px 12px 14px" }, + children: steps.map((step, index2) => /* @__PURE__ */ jsx_runtime.jsx(ExecutionTimelineStep, { + step, + isLast: index2 === steps.length - 1 + }, `${step.id}-${step.number}`)) + }) + ] + }); +} +function ExecutionTimelineStep({ step, isLast }) { + const config = getExecutionStepConfig(step.type); + const detail = (step.detail || "").trim(); + const hasRows = step.rows && step.rows.length > 0; + const hasImage = Boolean(step.imageSrc); + const showDetail = detail && detail !== step.title && !hasRows && !hasImage; + return /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "grid", gridTemplateColumns: "28px 1fr", columnGap: 10 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", flexDirection: "column", alignItems: "center" }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + width: 20, + height: 20, + borderRadius: 6, + display: "flex", + alignItems: "center", + justifyContent: "center", + background: config.bg, + border: `1px solid ${config.color}55`, + color: config.color, + fontSize: 10, + fontWeight: 800, + lineHeight: 1 + }, + children: config.icon + }), + !isLast && /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { width: 1, flex: 1, minHeight: 16, background: theme.border, marginTop: 4 } + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { paddingBottom: isLast ? 0 : 14, minWidth: 0 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + display: "flex", + justifyContent: "space-between", + gap: 10, + alignItems: "baseline" + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + color: theme.text, + fontSize: 12, + lineHeight: 1.55, + wordBreak: "break-word", + minWidth: 0 + }, + children: step.title + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + color: theme.textDim, + fontSize: 9, + whiteSpace: "nowrap", + flexShrink: 0, + fontFamily: "'JetBrains Mono', monospace" + }, + children: formatTaskTime(step.timestamp) + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + display: "flex", + alignItems: "center", + gap: 8, + marginTop: 3, + marginBottom: hasRows || showDetail ? 7 : 0 + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { + color: config.color, + fontSize: 10, + fontWeight: 700, + textTransform: "uppercase", + letterSpacing: 0 + }, + children: config.label + }), + step.count > 1 && /* @__PURE__ */ jsx_runtime.jsxs("span", { + style: { color: theme.textDim, fontSize: 10 }, + children: [ + step.count, + " chunks" + ] + }) + ] + }), + hasImage && /* @__PURE__ */ jsx_runtime.jsx("img", { + src: step.imageSrc, + alt: "image output", + style: { + maxWidth: "100%", + borderRadius: 6, + display: "block", + marginTop: 7, + border: `1px solid ${theme.border}` + } + }), + hasRows && /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + display: "flex", + flexDirection: "column", + gap: 5, + background: theme.surface, + border: `1px solid ${theme.border}`, + borderRadius: 6, + padding: "8px 10px", + maxHeight: 220, + overflow: "auto" + }, + children: step.rows.map((row2, i) => /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "grid", gridTemplateColumns: "72px 1fr", gap: 8, minWidth: 0 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { color: theme.textMuted, fontWeight: 700 }, + children: row2.label + }), + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { whiteSpace: "pre-wrap", wordBreak: "break-word", color: theme.text }, + children: row2.value + }) + ] + }, i)) + }), + showDetail && /* @__PURE__ */ jsx_runtime.jsx("pre", { + style: { + margin: 0, + background: theme.surface, + border: `1px solid ${theme.border}`, + borderRadius: 6, + padding: "8px 10px", + color: theme.textMuted, + whiteSpace: "pre-wrap", + wordBreak: "break-word", + fontFamily: "'JetBrains Mono', monospace", + fontSize: 11, + lineHeight: 1.5, + maxHeight: 220, + overflow: "auto" + }, + children: detail + }) + ] + }) + ] + }); +} +function getExecutionStepConfig(type) { + switch (type) { + case "thinking": + return { label: "Thinking", icon: "⌁", color: theme.textMuted, bg: "rgba(107,107,138,0.08)" }; + case "tool_call": + return { label: "Tool Call", icon: "▣", color: theme.cyan, bg: theme.cyanBg }; + case "tool_result": + return { label: "Tool Result", icon: "↵", color: theme.blue, bg: theme.blueBg }; + case "command_execution": + return { label: "Command", icon: "$", color: theme.orange, bg: theme.orangeBg }; + case "file_change": + return { label: "File", icon: "◇", color: theme.accent, bg: theme.accentGlow }; + case "generated_image": + return { label: "Image", icon: "□", color: theme.accent, bg: theme.accentGlow }; + case "image_content": + return { label: "Image", icon: "□", color: theme.accent, bg: theme.accentGlow }; + case "web_search": + return { label: "Search", icon: "⌕", color: theme.cyan, bg: theme.cyanBg }; + case "result": + return { label: "Result", icon: "✓", color: theme.green, bg: theme.greenBg }; + case "error": + return { label: "Error", icon: "!", color: theme.red, bg: theme.redBg }; + case "user": + return { label: "User", icon: "U", color: theme.accent, bg: theme.accentGlow }; + case "assistant": + return { label: "Assistant", icon: "AI", color: theme.green, bg: theme.greenBg }; + default: + return { label: "Event", icon: "•", color: theme.textMuted, bg: "rgba(107,107,138,0.08)" }; + } +} +function formatTraceValue2(value) { + if (value === undefined || value === null) + return ""; + if (typeof value === "string") + return value; + return JSON.stringify(value, null, 2); +} +function buildTraceRows2(eventType, payload, rawContent) { + const row2 = (label, value) => { + const formatted = formatTraceValue2(value); + return formatted === "" ? null : { label, value: formatted }; + }; + const compact2 = (rows) => rows.filter(Boolean); + if (eventType === "tool_call") { + const name = payload.server ? `${payload.server}.${payload.name || payload.tool || "unknown"}` : payload.name || payload.tool || "unknown"; + return compact2([ + row2("Tool", name), + row2("Input", payload.input || payload.arguments), + row2("Result", payload.result), + row2("Status", payload.status), + row2("Error", payload.error) + ]); + } + if (eventType === "tool_result") { + return compact2([ + row2(payload.is_error ? "Tool Error" : "Tool Result", payload.tool_use_id || "result"), + row2("Content", payload.content) + ]); + } + if (eventType === "command_execution") { + return compact2([ + row2("Command", payload.command), + row2("Output", payload.output), + row2("Exit", payload.exit_code), + row2("Status", payload.status) + ]); + } + if (eventType === "file_change") { + const changes = Array.isArray(payload.changes) ? payload.changes.map((change) => { + if (!change || typeof change !== "object") + return formatTraceValue2(change); + const kind = change.kind || change.type || "changed"; + const path = change.path || change.file || ""; + return path ? `${kind}: ${path}` : kind; + }).join(` +`) : payload.changes; + return compact2([row2("Changes", changes), row2("Status", payload.status)]); + } + if (eventType === "web_search") { + return compact2([ + row2("Query", payload.query), + row2("Action", payload.action), + row2("Status", payload.status) + ]); + } + return [{ label: eventType, value: rawContent }]; +} +var _csrfTokenPromise = null; +function getCsrfToken() { + if (!_csrfTokenPromise) { + _csrfTokenPromise = fetch(`${API}/csrf-token`).then((r) => r.json()).then((d) => d.csrf_token || "").catch(() => ""); + } + return _csrfTokenPromise; +} +async function csrfHeaders(extra = {}) { + const token = await getCsrfToken(); + return { "Content-Type": "application/json", "X-CSRF-Token": token, ...extra }; +} +async function fetchTasks() { + const res = await fetch(`${API}/tasks`); + if (!res.ok) + throw new Error(`HTTP ${res.status}`); + return res.json(); +} +async function fetchHeartbeats() { + const res = await fetch(`${API}/heartbeats`); + if (!res.ok) + throw new Error(`HTTP ${res.status}`); + return res.json(); +} +async function createTask(data) { + const res = await fetch(`${API}/tasks`, { + method: "POST", + headers: await csrfHeaders(), + body: JSON.stringify(data) + }); + return res.json(); +} +async function fetchSkillPatterns() { + const res = await fetch(`${API}/skill-patterns`); + if (!res.ok) + throw new Error(`HTTP ${res.status}`); + return res.json(); +} +async function triggerSkillSweep(agent) { + const res = await fetch(`${API}/skills/sweep`, { + method: "POST", + headers: await csrfHeaders(), + body: JSON.stringify(agent ? { agent } : {}) + }); + const payload = await res.json().catch(() => ({})); + if (!res.ok) + throw new Error(payload.error || `HTTP ${res.status}`); + return payload; +} +async function triggerSkillDraft(id, agent) { + const res = await fetch(`${API}/skill-patterns/${id}/draft`, { + method: "POST", + headers: await csrfHeaders(), + body: JSON.stringify(agent ? { agent } : {}) + }); + const payload = await res.json().catch(() => ({})); + if (!res.ok) + throw new Error(payload.error || `HTTP ${res.status}`); + return payload; +} +async function approveSkill(id, data) { + const res = await fetch(`${API}/skill-patterns/${id}/approve`, { + method: "POST", + headers: await csrfHeaders(), + body: JSON.stringify(data) + }); + const payload = await res.json().catch(() => ({})); + if (!res.ok) + throw new Error(payload.error || `HTTP ${res.status}`); + return payload; +} +async function dismissSkillPattern(id) { + const res = await fetch(`${API}/skill-patterns/${id}/dismiss`, { + method: "POST", + headers: await csrfHeaders(), + body: "{}" + }); + const payload = await res.json().catch(() => ({})); + if (!res.ok) + throw new Error(payload.error || `HTTP ${res.status}`); + return payload; +} +async function fetchSkills() { + const res = await fetch(`${API}/skills`); + if (!res.ok) + throw new Error(`HTTP ${res.status}`); + return res.json(); +} +async function setSkillEnabledApi(id, enabled) { + const res = await fetch(`${API}/skills/${id}`, { + method: "PUT", + headers: await csrfHeaders(), + body: JSON.stringify({ enabled }) + }); + const payload = await res.json().catch(() => ({})); + if (!res.ok) + throw new Error(payload.error || `HTTP ${res.status}`); + return payload; +} +async function deleteSkillApi(id) { + const res = await fetch(`${API}/skills/${id}`, { + method: "DELETE", + headers: await csrfHeaders() + }); + const payload = await res.json().catch(() => ({})); + if (!res.ok) + throw new Error(payload.error || `HTTP ${res.status}`); + return payload; +} +async function createHeartbeat(data) { + const res = await fetch(`${API}/heartbeats`, { + method: "POST", + headers: await csrfHeaders(), + body: JSON.stringify(data) + }); + const payload = await res.json().catch(() => ({})); + if (!res.ok) + throw new Error(payload.error || `HTTP ${res.status}`); + return payload; +} +async function updateHeartbeat(id, data) { + const res = await fetch(`${API}/heartbeats/${id}`, { + method: "PUT", + headers: await csrfHeaders(), + body: JSON.stringify(data) + }); + const payload = await res.json().catch(() => ({})); + if (!res.ok) + throw new Error(payload.error || `HTTP ${res.status}`); + return payload; +} +async function deleteHeartbeat(id) { + const res = await fetch(`${API}/heartbeats/${id}`, { + method: "DELETE", + headers: await csrfHeaders() + }); + if (!res.ok) + throw new Error(`HTTP ${res.status}`); +} +async function runHeartbeatNow(id) { + const res = await fetch(`${API}/heartbeats/${id}/run-now`, { + method: "POST", + headers: await csrfHeaders() + }); + const payload = await res.json().catch(() => ({})); + if (!res.ok) + throw new Error(payload.error || `HTTP ${res.status}`); + return payload; +} +async function pauseHeartbeat(id) { + const res = await fetch(`${API}/heartbeats/${id}/pause`, { + method: "POST", + headers: await csrfHeaders() + }); + const payload = await res.json().catch(() => ({})); + if (!res.ok) + throw new Error(payload.error || `HTTP ${res.status}`); + return payload; +} +async function resumeHeartbeatApi(id) { + const res = await fetch(`${API}/heartbeats/${id}/resume`, { + method: "POST", + headers: await csrfHeaders() + }); + const payload = await res.json().catch(() => ({})); + if (!res.ok) + throw new Error(payload.error || `HTTP ${res.status}`); + return payload; +} +async function fetchHeartbeatTicks(id) { + const res = await fetch(`${API}/heartbeats/${id}/ticks?limit=20`); + if (!res.ok) + throw new Error(`HTTP ${res.status}`); + const payload = await res.json(); + return payload.ticks || []; +} +async function fetchHeartbeatTickOutput(heartbeatId, tickId) { + const res = await fetch(`${API}/heartbeats/${heartbeatId}/ticks/${tickId}/output`); + if (!res.ok) + throw new Error(`HTTP ${res.status}`); + return res.json(); +} +async function cancelTask(id) { + await fetch(`${API}/tasks/${id}/cancel`, { method: "POST", headers: await csrfHeaders() }); +} +async function retryTask(id) { + await fetch(`${API}/tasks/${id}/retry`, { method: "POST", headers: await csrfHeaders() }); +} +async function deleteTask(id) { + await fetch(`${API}/tasks/${id}`, { method: "DELETE", headers: await csrfHeaders() }); +} +async function updateTask(id, data) { + const res = await fetch(`${API}/tasks/${id}`, { + method: "PUT", + headers: await csrfHeaders(), + body: JSON.stringify(data) + }); + if (!res.ok) { + const err = await res.json().catch(() => ({})); + throw new Error(err.error || `HTTP ${res.status}`); + } + return res.json(); +} +async function respondToTask(id, answer) { + await fetch(`${API}/tasks/${id}/respond`, { + method: "POST", + headers: await csrfHeaders(), + body: JSON.stringify({ answer }) + }); +} +async function resumeTask(id, message) { + const res = await fetch(`${API}/tasks/${id}/resume`, { + method: "POST", + headers: await csrfHeaders(), + body: JSON.stringify({ message }) + }); + return res.json(); +} +async function fetchTaskMessages(id) { + try { + const res = await fetch(`${API}/tasks/${id}/messages`); + return res.ok ? await res.json() : []; + } catch { + return []; + } +} +async function fetchTaskEvents(id) { + try { + const res = await fetch(`${API}/tasks/${id}/events?limit=1000`); + if (res.ok) { + const data = await res.json(); + return data.events || []; + } + return []; + } catch { + return []; + } +} +async function fetchSettings() { + try { + const res = await fetch(`${API}/settings`); + return res.ok ? await res.json() : {}; + } catch { + return {}; + } +} +async function updateSettings(data) { + await fetch(`${API}/settings`, { + method: "PUT", + headers: await csrfHeaders(), + body: JSON.stringify(data) + }); +} +async function fetchFeishuSettings() { + try { + const res = await fetch(`${API}/feishu/settings`); + return res.ok ? await res.json() : {}; + } catch { + return {}; + } +} +async function updateFeishuSettings(data) { + await fetch(`${API}/feishu/settings`, { + method: "POST", + headers: await csrfHeaders(), + body: JSON.stringify(data) + }); +} +async function fetchChannelsStatus() { + try { + const res = await fetch(`${API}/channels/status`); + return res.ok ? await res.json() : {}; + } catch { + return {}; + } +} +async function updateChannelsSettings(data) { + await fetch(`${API}/channels/settings`, { + method: "POST", + headers: await csrfHeaders(), + body: JSON.stringify(data) + }); +} +async function runWeixinAction(action) { + const res = await fetch(`${API}/channels/weixin/action`, { + method: "POST", + headers: await csrfHeaders(), + body: JSON.stringify({ action }) + }); + if (!res.ok) { + const data = await res.json().catch(() => ({})); + throw new Error(data.error || `HTTP ${res.status}`); + } +} +function Tooltip({ text, children }) { + const [visible, setVisible] = import_react.useState(false); + return /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { position: "relative", display: "inline-flex" }, + onMouseEnter: () => setVisible(true), + onMouseLeave: () => setVisible(false), + children: [ + children, + visible && /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + position: "absolute", + bottom: "calc(100% + 6px)", + left: "50%", + transform: "translateX(-50%)", + background: theme.surface, + border: `1px solid ${theme.border}`, + color: theme.textMuted, + fontSize: 11, + padding: "4px 8px", + borderRadius: 6, + whiteSpace: "nowrap", + pointerEvents: "none", + boxShadow: "0 4px 12px rgba(0,0,0,0.3)", + zIndex: 9999 + }, + children: text + }) + ] + }); +} +function Badge({ status }) { + const cfg = getStatusConfig()[status] || getStatusConfig().pending; + return /* @__PURE__ */ jsx_runtime.jsxs("span", { + style: { + display: "inline-flex", + alignItems: "center", + gap: 5, + padding: "3px 10px", + borderRadius: 20, + fontSize: 11, + fontWeight: 600, + color: cfg.color, + background: cfg.bg, + letterSpacing: 0.3 + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { fontSize: 10 }, + children: cfg.icon + }), + cfg.label + ] + }); +} +function Tag({ children }) { + return /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { + padding: "2px 8px", + borderRadius: 4, + fontSize: 10, + fontWeight: 500, + background: theme.accentGlow, + color: theme.accent, + letterSpacing: 0.4 + }, + children + }); +} +function AgentBadge({ agent }) { + const cfg = AGENTS[agent] || AGENTS.claude; + return /* @__PURE__ */ jsx_runtime.jsxs("span", { + style: { + display: "inline-flex", + alignItems: "center", + gap: 4, + padding: "2px 8px", + borderRadius: 4, + fontSize: 10, + fontWeight: 600, + color: cfg.color, + background: `${cfg.color}18`, + letterSpacing: 0.3 + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { fontSize: 9 }, + children: cfg.icon + }), + cfg.label + ] + }); +} +function TaskCard({ task, onAction, onViewDetail }) { + const [hovered, setHovered] = import_react.useState(false); + const cfg = getStatusConfig()[task.status] || getStatusConfig().pending; + const tags = task.tags ? task.tags.split(",").filter(Boolean) : []; + return /* @__PURE__ */ jsx_runtime.jsxs("div", { + onMouseEnter: () => setHovered(true), + onMouseLeave: () => setHovered(false), + onClick: () => onViewDetail(task), + style: { + background: hovered ? theme.surfaceHover : theme.surface, + border: `1px solid ${hovered ? theme.borderActive : theme.border}`, + borderLeft: `3px solid ${cfg.color}`, + borderRadius: 10, + padding: "14px 16px", + cursor: "pointer", + transition: "all 0.2s ease", + transform: hovered ? "translateY(-1px)" : "none", + boxShadow: hovered ? `0 4px 20px rgba(0,0,0,0.3)` : "none" + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + display: "flex", + justifyContent: "space-between", + alignItems: "flex-start", + marginBottom: 8 + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { + fontSize: 13, + fontWeight: 600, + color: theme.text, + lineHeight: 1.4, + flex: 1, + marginRight: 8, + fontFamily: "'JetBrains Mono', 'SF Mono', monospace" + }, + children: task.title + }), + /* @__PURE__ */ jsx_runtime.jsx(Badge, { + status: task.status + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + fontSize: 12, + color: theme.textMuted, + marginBottom: 10, + lineHeight: 1.5, + overflow: "hidden", + textOverflow: "ellipsis", + display: "-webkit-box", + WebkitLineClamp: 2, + WebkitBoxOrient: "vertical" + }, + children: task.prompt + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", justifyContent: "space-between", alignItems: "center" }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", gap: 4, flexWrap: "wrap" }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx(AgentBadge, { + agent: task.agent + }), + task.schedule_type === "delayed" && /* @__PURE__ */ jsx_runtime.jsxs(Tag, { + children: [ + "⏳ ", + task.delay_seconds, + "s" + ] + }), + task.schedule_type === "scheduled_at" && task.next_run_at && /* @__PURE__ */ jsx_runtime.jsxs(Tag, { + children: [ + "\uD83D\uDCC5 ", + formatTaskDateTime(task.next_run_at) + ] + }), + task.schedule_type === "cron" && /* @__PURE__ */ jsx_runtime.jsxs(Tag, { + children: [ + "⏲ ", + task.cron_expr + ] + }), + tags.map((t, i) => /* @__PURE__ */ jsx_runtime.jsx(Tag, { + children: t.trim() + }, i)) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", gap: 4 }, + onClick: (e) => e.stopPropagation(), + children: [ + ["pending", "scheduled", "blocked"].includes(task.status) && /* @__PURE__ */ jsx_runtime.jsx(ActionBtn, { + label: "✎", + title: "Edit", + onClick: () => onAction("edit", task.id), + color: theme.blue || theme.accent + }), + ["completed", "cancelled", "failed"].includes(task.status) && /* @__PURE__ */ jsx_runtime.jsx(ActionBtn, { + label: "⑂", + title: "Fork", + onClick: () => onAction("fork", task.id), + color: theme.cyan || theme.accent + }), + task.status === "failed" && /* @__PURE__ */ jsx_runtime.jsx(ActionBtn, { + label: "↻", + title: "Retry", + onClick: () => onAction("retry", task.id), + color: theme.orange + }), + ["pending", "scheduled", "running"].includes(task.status) && /* @__PURE__ */ jsx_runtime.jsx(ActionBtn, { + label: "■", + title: "Cancel", + onClick: () => onAction("cancel", task.id), + color: theme.red + }), + /* @__PURE__ */ jsx_runtime.jsx(ActionBtn, { + label: "×", + title: "Delete", + onClick: () => onAction("delete", task.id), + color: theme.textMuted + }) + ] + }) + ] + }), + task.run_count > 0 && /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { fontSize: 10, color: theme.textDim, marginTop: 8, fontFamily: "monospace" }, + children: [ + "Runs: ", + task.run_count, + task.max_runs ? ` / ${task.max_runs}` : "", + task.last_run_at && ` · Last: ${formatTaskTime(task.last_run_at)}` + ] + }), + task.status === "blocked" && task.dependencies && task.dependencies.length > 0 && /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { fontSize: 10, color: theme.textDim, marginTop: 6, fontFamily: "monospace" }, + children: [ + "⊘ Waiting for: ", + task.dependencies.map((d) => `#${d.depends_on_task_id}`).join(", ") + ] + }), + task.dependents && task.dependents.length > 0 && task.status === "completed" && /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { fontSize: 10, color: theme.textDim, marginTop: 6, fontFamily: "monospace" }, + children: [ + "→ Unlocks: ", + task.dependents.map((id) => `#${id}`).join(", ") + ] + }), + task.dag_id && /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + fontSize: 10, + color: theme.accent, + marginTop: 4, + opacity: 0.6, + fontFamily: "monospace" + }, + children: [ + "dag: ", + task.dag_id + ] + }) + ] + }); +} +function ActionBtn({ label, title, onClick, color }) { + const [hovered, setHovered] = import_react.useState(false); + return /* @__PURE__ */ jsx_runtime.jsx("button", { + title, + onClick, + onMouseEnter: () => setHovered(true), + onMouseLeave: () => setHovered(false), + style: { + background: hovered ? `${color}22` : "transparent", + border: "none", + color, + cursor: "pointer", + width: 24, + height: 24, + borderRadius: 6, + fontSize: 14, + display: "flex", + alignItems: "center", + justifyContent: "center", + transition: "background 0.15s" + }, + children: label + }); +} +function Column({ col, tasks, onAction, onViewDetail }) { + return /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { flex: 1, minWidth: 300 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + display: "flex", + alignItems: "center", + gap: 10, + marginBottom: 16, + padding: "0 4px" + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { fontSize: 16, opacity: 0.4 }, + children: col.icon + }), + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { + fontSize: 12, + fontWeight: 700, + color: theme.textMuted, + letterSpacing: 1.5, + textTransform: "uppercase" + }, + children: col.label + }), + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { + background: theme.border, + borderRadius: 10, + padding: "2px 8px", + fontSize: 11, + color: theme.textDim, + fontWeight: 600 + }, + children: tasks.length + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", flexDirection: "column", gap: 8 }, + children: [ + tasks.map((t) => /* @__PURE__ */ jsx_runtime.jsx(TaskCard, { + task: t, + onAction, + onViewDetail + }, t.id)), + tasks.length === 0 && /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + border: `1px dashed ${theme.border}`, + borderRadius: 10, + padding: 32, + textAlign: "center", + color: theme.textDim, + fontSize: 12 + }, + children: "No tasks" + }) + ] + }) + ] + }); +} +function HeartbeatBadge({ enabled }) { + return /* @__PURE__ */ jsx_runtime.jsxs("span", { + style: { + display: "inline-flex", + alignItems: "center", + gap: 5, + padding: "3px 10px", + borderRadius: 20, + fontSize: 11, + fontWeight: 600, + color: enabled ? theme.green : theme.textMuted, + background: enabled ? theme.greenBg : "rgba(107,107,138,0.08)", + letterSpacing: 0.3 + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { fontSize: 10 }, + children: enabled ? "●" : "◌" + }), + enabled ? "Enabled" : "Paused" + ] + }); +} +function HeartbeatModal({ onClose, onSubmit, initialData, defaultAgent, mode = "create" }) { + const savedDir = localStorage.getItem("agentforge_working_dir") || "~/papers"; + const [form, setForm] = import_react.useState(() => ({ + name: initialData?.name || "", + working_dir: initialData?.working_dir || savedDir, + schedule_type: initialData?.schedule_type || "interval", + interval_seconds: initialData?.interval_seconds || 600, + cron_expr: initialData?.cron_expr || "", + check_prompt: initialData?.check_prompt || "", + action_prompt_template: initialData?.action_prompt_template || "", + default_agent: initialData?.default_agent || defaultAgent || DEFAULT_AGENT, + cooldown_seconds: initialData?.cooldown_seconds || 1800, + enabled: initialData?.enabled ?? true + })); + const set = (k, v) => setForm((prev) => ({ ...prev, [k]: v })); + const inputStyle = { + width: "100%", + padding: "10px 14px", + borderRadius: 8, + border: `1px solid ${theme.border}`, + background: theme.bg, + color: theme.text, + fontSize: 13, + outline: "none", + boxSizing: "border-box", + fontFamily: "'JetBrains Mono', 'SF Mono', monospace" + }; + const labelStyle = { + fontSize: 11, + fontWeight: 600, + color: theme.textMuted, + letterSpacing: 0.8, + textTransform: "uppercase", + marginBottom: 6, + display: "block" + }; + const handleSubmit = () => { + localStorage.setItem("agentforge_working_dir", form.working_dir); + onSubmit({ + ...form, + name: form.name || "Untitled heartbeat", + interval_seconds: form.schedule_type === "interval" ? parseInt(form.interval_seconds) || 600 : null, + cooldown_seconds: parseInt(form.cooldown_seconds) || 0, + cron_expr: form.schedule_type === "cron" ? form.cron_expr : null + }); + }; + return /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + position: "fixed", + inset: 0, + background: "rgba(0,0,0,0.7)", + display: "flex", + alignItems: "center", + justifyContent: "center", + zIndex: 1000, + backdropFilter: "blur(8px)" + }, + onClick: onClose, + children: /* @__PURE__ */ jsx_runtime.jsxs("div", { + onClick: (e) => e.stopPropagation(), + style: { + background: theme.surface, + border: `1px solid ${theme.border}`, + borderRadius: 16, + padding: 32, + width: 640, + maxHeight: "84vh", + overflow: "auto", + boxShadow: "0 24px 80px rgba(0,0,0,0.5)" + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("h2", { + style: { + margin: "0 0 24px", + fontSize: 18, + fontWeight: 700, + color: theme.text, + fontFamily: "'JetBrains Mono', monospace" + }, + children: mode === "edit" ? "Edit Heartbeat" : "New Heartbeat" + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", flexDirection: "column", gap: 16 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Name" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + style: inputStyle, + value: form.name, + onChange: (e) => set("name", e.target.value), + placeholder: "Repo review watcher" + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Working Directory" + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", gap: 8 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("input", { + style: { ...inputStyle, flex: 1 }, + value: form.working_dir, + onChange: (e) => set("working_dir", e.target.value) + }), + window.electronAPI?.selectDirectory && /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: async () => { + const dir = await window.electronAPI.selectDirectory(); + if (dir) + set("working_dir", dir); + }, + style: { + padding: "8px 14px", + borderRadius: 8, + cursor: "pointer", + border: `1px solid ${theme.border}`, + background: theme.bg, + color: theme.textMuted, + fontSize: 12, + fontWeight: 600, + whiteSpace: "nowrap" + }, + children: "Browse" + }) + ] + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Schedule Type" + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { display: "flex", gap: 8 }, + children: ["interval", "cron"].map((t) => /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: () => set("schedule_type", t), + style: { + flex: 1, + padding: "8px 12px", + borderRadius: 8, + cursor: "pointer", + border: `1px solid ${form.schedule_type === t ? theme.accent : theme.border}`, + background: form.schedule_type === t ? theme.accentGlow : "transparent", + color: form.schedule_type === t ? theme.accent : theme.textMuted, + fontSize: 12, + fontWeight: 600, + textTransform: "capitalize" + }, + children: t === "interval" ? "⟳ Interval" : "⏲ Cron" + }, t)) + }) + ] + }), + form.schedule_type === "interval" ? /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Interval (seconds)" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + type: "number", + style: inputStyle, + value: form.interval_seconds, + onChange: (e) => set("interval_seconds", e.target.value) + }) + ] + }) : /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Cron Expression" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + style: inputStyle, + value: form.cron_expr, + onChange: (e) => set("cron_expr", e.target.value), + placeholder: "*/10 * * * *" + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Decision Prompt *" + }), + /* @__PURE__ */ jsx_runtime.jsx("textarea", { + style: { ...inputStyle, height: 110, resize: "vertical" }, + value: form.check_prompt, + onChange: (e) => set("check_prompt", e.target.value), + placeholder: "Check whether there are new meaningful code changes that deserve a review task. Return JSON only." + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Triggered Task Prompt Template" + }), + /* @__PURE__ */ jsx_runtime.jsx("textarea", { + style: { ...inputStyle, height: 90, resize: "vertical" }, + value: form.action_prompt_template, + onChange: (e) => set("action_prompt_template", e.target.value), + placeholder: "Review the latest code changes and summarize bugs, regressions, and missing tests." + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Default Agent" + }), + /* @__PURE__ */ jsx_runtime.jsx("select", { + style: inputStyle, + value: form.default_agent, + onChange: (e) => set("default_agent", e.target.value), + children: Object.entries(AGENTS).map(([key, cfg]) => /* @__PURE__ */ jsx_runtime.jsx("option", { + value: key, + children: cfg.label + }, key)) + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Cooldown (seconds)" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + type: "number", + style: inputStyle, + value: form.cooldown_seconds, + onChange: (e) => set("cooldown_seconds", e.target.value) + }) + ] + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("label", { + style: { + display: "flex", + alignItems: "center", + gap: 10, + fontSize: 13, + color: theme.textMuted + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("input", { + type: "checkbox", + checked: !!form.enabled, + onChange: (e) => set("enabled", e.target.checked) + }), + "Enabled" + ] + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", gap: 10, justifyContent: "flex-end", marginTop: 24 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: onClose, + style: { + padding: "10px 20px", + borderRadius: 8, + border: `1px solid ${theme.border}`, + background: "transparent", + color: theme.textMuted, + cursor: "pointer", + fontSize: 13, + fontWeight: 600 + }, + children: "Cancel" + }), + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: handleSubmit, + style: { + padding: "10px 24px", + borderRadius: 8, + border: "none", + background: theme.accent, + color: "#fff", + cursor: "pointer", + fontSize: 13, + fontWeight: 600, + boxShadow: `0 0 20px ${theme.accentGlow}` + }, + children: mode === "edit" ? "Save" : "Create Heartbeat" + }) + ] + }) + ] + }) + }); +} +function HeartbeatCard({ heartbeat, onAction, onViewDetail }) { + const tags = []; + if (heartbeat.schedule_type === "interval" && heartbeat.interval_seconds) + tags.push(`⟳ ${heartbeat.interval_seconds}s`); + if (heartbeat.schedule_type === "cron" && heartbeat.cron_expr) + tags.push(`⏲ ${heartbeat.cron_expr}`); + if (heartbeat.last_decision) + tags.push(`Last: ${heartbeat.last_decision}`); + return /* @__PURE__ */ jsx_runtime.jsxs("div", { + onClick: () => onViewDetail(heartbeat), + style: { + background: theme.surface, + border: `1px solid ${theme.border}`, + borderRadius: 12, + padding: "16px 18px", + cursor: "pointer", + transition: "all 0.2s ease" + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", justifyContent: "space-between", gap: 16, marginBottom: 8 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { flex: 1 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + fontSize: 14, + fontWeight: 700, + color: theme.text, + fontFamily: "'JetBrains Mono', monospace", + marginBottom: 6 + }, + children: heartbeat.name + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + fontSize: 12, + color: theme.textMuted, + lineHeight: 1.5, + overflow: "hidden", + textOverflow: "ellipsis", + display: "-webkit-box", + WebkitLineClamp: 2, + WebkitBoxOrient: "vertical" + }, + children: heartbeat.check_prompt + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsx(HeartbeatBadge, { + enabled: heartbeat.enabled + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", justifyContent: "space-between", alignItems: "center", gap: 12 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", gap: 6, flexWrap: "wrap" }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx(AgentBadge, { + agent: heartbeat.default_agent + }), + tags.map((tag, idx) => /* @__PURE__ */ jsx_runtime.jsx(Tag, { + children: tag + }, idx)) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", gap: 4 }, + onClick: (e) => e.stopPropagation(), + children: [ + /* @__PURE__ */ jsx_runtime.jsx(ActionBtn, { + label: "⚡", + title: "Run now", + onClick: () => onAction("run", heartbeat.id), + color: theme.orange + }), + /* @__PURE__ */ jsx_runtime.jsx(ActionBtn, { + label: "✎", + title: "Edit", + onClick: () => onAction("edit", heartbeat.id), + color: theme.blue + }), + heartbeat.enabled ? /* @__PURE__ */ jsx_runtime.jsx(ActionBtn, { + label: "❚❚", + title: "Pause", + onClick: () => onAction("pause", heartbeat.id), + color: theme.textMuted + }) : /* @__PURE__ */ jsx_runtime.jsx(ActionBtn, { + label: "▶", + title: "Resume", + onClick: () => onAction("resume", heartbeat.id), + color: theme.green + }), + /* @__PURE__ */ jsx_runtime.jsx(ActionBtn, { + label: "×", + title: "Delete", + onClick: () => onAction("delete", heartbeat.id), + color: theme.red + }) + ] + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + fontSize: 11, + color: theme.textDim, + marginTop: 10, + fontFamily: "monospace", + lineHeight: 1.6 + }, + children: [ + "Next: ", + heartbeat.next_run_at ? formatTaskDateTime(heartbeat.next_run_at) : "n/a", + " · ", + "Triggered:", + " ", + heartbeat.last_triggered_at ? formatTaskDateTime(heartbeat.last_triggered_at) : "never" + ] + }), + heartbeat.last_error && /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { fontSize: 11, color: theme.red, marginTop: 6, lineHeight: 1.4 }, + children: [ + "Last error: ", + heartbeat.last_error + ] + }) + ] + }); +} +function HeartbeatDetailPanel({ heartbeat, ticks, onClose }) { + const [selectedTickId, setSelectedTickId] = import_react.useState(null); + const [tickOutput, setTickOutput] = import_react.useState(""); + const [tickRunning, setTickRunning] = import_react.useState(false); + const outputRef = import_react.useRef(null); + import_react.useEffect(() => { + setSelectedTickId(ticks[0]?.id || null); + }, [heartbeat.id, ticks]); + import_react.useEffect(() => { + if (!selectedTickId) { + setTickOutput(""); + setTickRunning(false); + return; + } + let cancelled = false; + const load = async () => { + try { + const data = await fetchHeartbeatTickOutput(heartbeat.id, selectedTickId); + if (cancelled) + return; + setTickOutput(data.output || ""); + setTickRunning(!!data.is_running); + } catch { + if (!cancelled) { + setTickOutput(""); + setTickRunning(false); + } + } + }; + load(); + const interval = setInterval(load, 1000); + return () => { + cancelled = true; + clearInterval(interval); + }; + }, [heartbeat.id, selectedTickId]); + import_react.useEffect(() => { + if (outputRef.current) { + outputRef.current.scrollTop = outputRef.current.scrollHeight; + } + }, [tickOutput]); + return /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + position: "fixed", + top: 0, + right: 0, + width: 520, + height: "100vh", + background: theme.surface, + borderLeft: `1px solid ${theme.border}`, + boxShadow: "-20px 0 60px rgba(0,0,0,0.4)", + zIndex: 500, + display: "flex", + flexDirection: "column" + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + padding: "22px 24px", + borderBottom: `1px solid ${theme.border}`, + display: "flex", + justifyContent: "space-between", + alignItems: "flex-start", + gap: 12 + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + fontSize: 18, + fontWeight: 700, + color: theme.text, + fontFamily: "'JetBrains Mono', monospace" + }, + children: heartbeat.name + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 12, color: theme.textMuted, marginTop: 6 }, + children: heartbeat.working_dir + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: onClose, + style: { + background: "transparent", + border: "none", + color: theme.textMuted, + cursor: "pointer", + fontSize: 22, + lineHeight: 1 + }, + children: "×" + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { padding: 24, overflow: "auto", flex: 1 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", gap: 8, flexWrap: "wrap", marginBottom: 16 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx(HeartbeatBadge, { + enabled: heartbeat.enabled + }), + /* @__PURE__ */ jsx_runtime.jsx(AgentBadge, { + agent: heartbeat.default_agent + }), + heartbeat.schedule_type === "interval" ? /* @__PURE__ */ jsx_runtime.jsxs(Tag, { + children: [ + "⟳ ", + heartbeat.interval_seconds, + "s" + ] + }) : /* @__PURE__ */ jsx_runtime.jsxs(Tag, { + children: [ + "⏲ ", + heartbeat.cron_expr + ] + }), + heartbeat.last_decision && /* @__PURE__ */ jsx_runtime.jsx(Tag, { + children: heartbeat.last_decision + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { fontSize: 12, color: theme.textMuted, lineHeight: 1.7, marginBottom: 18 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + "Next run: ", + heartbeat.next_run_at ? formatTaskDateTime(heartbeat.next_run_at) : "n/a" + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + "Last tick:", + " ", + heartbeat.last_tick_at ? formatTaskDateTime(heartbeat.last_tick_at) : "never" + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + "Last trigger:", + " ", + heartbeat.last_triggered_at ? formatTaskDateTime(heartbeat.last_triggered_at) : "never" + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + "Cooldown: ", + heartbeat.cooldown_seconds || 0, + "s" + ] + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { marginBottom: 20 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + fontSize: 11, + fontWeight: 700, + color: theme.textMuted, + letterSpacing: 0.8, + textTransform: "uppercase", + marginBottom: 8 + }, + children: "Decision Prompt" + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + fontSize: 12, + lineHeight: 1.7, + color: theme.text, + background: theme.bg, + border: `1px solid ${theme.border}`, + borderRadius: 10, + padding: 14, + whiteSpace: "pre-wrap" + }, + children: heartbeat.check_prompt + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { marginBottom: 20 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + fontSize: 11, + fontWeight: 700, + color: theme.textMuted, + letterSpacing: 0.8, + textTransform: "uppercase", + marginBottom: 8 + }, + children: "Triggered Task Template" + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + fontSize: 12, + lineHeight: 1.7, + color: theme.text, + background: theme.bg, + border: `1px solid ${theme.border}`, + borderRadius: 10, + padding: 14, + whiteSpace: "pre-wrap" + }, + children: heartbeat.action_prompt_template || "No template configured" + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + fontSize: 11, + fontWeight: 700, + color: theme.textMuted, + letterSpacing: 0.8, + textTransform: "uppercase", + marginBottom: 8 + }, + children: "Recent Ticks" + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", flexDirection: "column", gap: 8 }, + children: [ + ticks.map((tick) => { + let payload = null; + try { + payload = tick.decision_payload ? JSON.parse(tick.decision_payload) : null; + } catch {} + return /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + background: theme.bg, + border: `1px solid ${theme.border}`, + borderRadius: 10, + padding: 12, + cursor: "pointer", + boxShadow: selectedTickId === tick.id ? `0 0 0 1px ${theme.accent} inset` : "none" + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + onClick: () => setSelectedTickId(tick.id), + style: { + display: "flex", + justifyContent: "space-between", + gap: 8, + marginBottom: 6 + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 12, fontWeight: 600, color: theme.text }, + children: tick.decision_type || tick.status + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 11, color: theme.textDim, fontFamily: "monospace" }, + children: tick.started_at ? formatTaskDateTime(tick.started_at) : "" + }) + ] + }), + payload?.reason && /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 12, color: theme.textMuted, lineHeight: 1.5 }, + children: payload.reason + }), + tick.error && /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 12, color: theme.red, lineHeight: 1.5 }, + children: tick.error + }), + tick.task_id && /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + fontSize: 11, + color: theme.accent, + marginTop: 6, + fontFamily: "monospace" + }, + children: [ + "Triggered task #", + tick.task_id + ] + }) + ] + }, tick.id); + }), + ticks.length === 0 && /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + border: `1px dashed ${theme.border}`, + borderRadius: 10, + padding: 24, + textAlign: "center", + color: theme.textDim, + fontSize: 12 + }, + children: "No ticks yet" + }) + ] + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { marginTop: 20 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + display: "flex", + justifyContent: "space-between", + alignItems: "center", + marginBottom: 8 + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + fontSize: 11, + fontWeight: 700, + color: theme.textMuted, + letterSpacing: 0.8, + textTransform: "uppercase" + }, + children: "Tick Log" + }), + selectedTickId && /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + fontSize: 11, + color: tickRunning ? theme.orange : theme.textDim, + fontFamily: "monospace" + }, + children: [ + tickRunning ? "LIVE" : "Stored", + " · tick #", + selectedTickId + ] + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + ref: outputRef, + style: { + background: theme.bg, + border: `1px solid ${theme.border}`, + borderRadius: 10, + padding: 14, + minHeight: 180, + maxHeight: 320, + overflow: "auto", + fontFamily: "'JetBrains Mono', monospace", + fontSize: 12, + lineHeight: 1.6, + whiteSpace: "pre-wrap", + color: theme.text + }, + children: selectedTickId ? tickOutput || "No output captured for this tick." : "Select a tick to view its log." + }) + ] + }) + ] + }) + ] + }); +} +function NewTaskModal({ onClose, onSubmit, initialData, mode = "create" }) { + const savedDir = localStorage.getItem("agentforge_working_dir") || "~/papers"; + const [form, setForm] = import_react.useState(() => { + if (initialData) { + return { + title: initialData.title || "", + prompt: initialData.prompt || "", + working_dir: initialData.working_dir || savedDir, + schedule_type: initialData.schedule_type || "immediate", + cron_expr: initialData.cron_expr || "", + delay_seconds: initialData.delay_seconds || 60, + scheduled_at: initialData.next_run_at ? formatDateTimeLocalInput(initialData.next_run_at) : "", + max_runs: initialData.max_runs || "", + tags: initialData.tags || "", + agent: initialData.agent || DEFAULT_AGENT, + dag_id: initialData.dag_id || "" + }; + } + return { + title: "", + prompt: "", + working_dir: savedDir, + schedule_type: "immediate", + cron_expr: "", + delay_seconds: 60, + scheduled_at: "", + max_runs: "", + tags: "", + agent: DEFAULT_AGENT, + dag_id: "" + }; + }); + const [promptImages, setPromptImages] = import_react.useState(() => { + if (initialData?.prompt_images && Array.isArray(initialData.prompt_images)) { + return initialData.prompt_images.map((img) => ({ + name: img.name || "image", + media_type: img.media_type || "image/jpeg", + data: img.data || "", + preview: img.data ? `data:${img.media_type || "image/jpeg"};base64,${img.data}` : "" + })); + } + return []; + }); + const [depRows, setDepRows] = import_react.useState(() => { + if (initialData?.dependencies && Array.isArray(initialData.dependencies)) { + return initialData.dependencies.map((dep) => ({ + task_id: dep.depends_on_task_id, + inject_result: !!dep.inject_result, + _input: String(dep.depends_on_task_id) + })); + } + return []; + }); + const [scheduledAtError, setScheduledAtError] = import_react.useState(""); + const set = (k, v) => setForm((prev) => ({ ...prev, [k]: v })); + const handleImageSelect = (e) => { + const files = Array.from(e.target.files || []); + files.forEach((file) => { + const reader = new FileReader; + reader.onload = (ev) => { + const dataUrl = ev.target.result; + const [meta, data] = dataUrl.split(","); + const media_type = meta.match(/:(.*?);/)?.[1] || "image/jpeg"; + setPromptImages((prev) => [ + ...prev, + { name: file.name, media_type, data, preview: dataUrl } + ]); + }; + reader.readAsDataURL(file); + }); + e.target.value = ""; + }; + const removeImage = (idx) => setPromptImages((prev) => prev.filter((_, i) => i !== idx)); + const handleSubmit = () => { + if (!form.prompt.trim()) + return; + localStorage.setItem("agentforge_working_dir", form.working_dir); + const depends_on = depRows.filter((r) => r.task_id).map((r) => ({ task_id: r.task_id, inject_result: r.inject_result })); + const data = { + ...form, + title: form.title || form.prompt.slice(0, 60), + delay_seconds: form.schedule_type === "delayed" ? parseInt(form.delay_seconds) || 60 : null, + cron_expr: form.schedule_type === "cron" ? form.cron_expr : null, + max_runs: form.max_runs ? parseInt(form.max_runs) : null, + prompt_images: promptImages.map(({ name, media_type, data: data2 }) => ({ name, media_type, data: data2 })), + depends_on: mode === "edit" ? depends_on : depends_on.length > 0 ? depends_on : undefined, + dag_id: form.dag_id || undefined + }; + if (form.schedule_type === "scheduled_at") { + const localDate2 = parseTaskDateTime(form.scheduled_at); + const serialized = serializeDateTimeLocalInput(form.scheduled_at); + if (!form.scheduled_at || !serialized || !localDate2 || isNaN(localDate2.getTime())) { + setScheduledAtError("Please enter a valid date and time."); + return; + } + setScheduledAtError(""); + data.next_run_at = serialized; + } + onSubmit(data); + }; + const inputStyle = { + width: "100%", + padding: "10px 14px", + borderRadius: 8, + border: `1px solid ${theme.border}`, + background: theme.bg, + color: theme.text, + fontSize: 13, + outline: "none", + boxSizing: "border-box", + fontFamily: "'JetBrains Mono', 'SF Mono', monospace", + transition: "border-color 0.2s" + }; + const labelStyle = { + fontSize: 11, + fontWeight: 600, + color: theme.textMuted, + letterSpacing: 0.8, + textTransform: "uppercase", + marginBottom: 6, + display: "block" + }; + return /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + position: "fixed", + inset: 0, + background: "rgba(0,0,0,0.7)", + display: "flex", + alignItems: "center", + justifyContent: "center", + zIndex: 1000, + backdropFilter: "blur(8px)" + }, + onClick: onClose, + children: /* @__PURE__ */ jsx_runtime.jsxs("div", { + onClick: (e) => e.stopPropagation(), + style: { + background: theme.surface, + border: `1px solid ${theme.border}`, + borderRadius: 16, + padding: 32, + width: 520, + maxHeight: "80vh", + overflow: "auto", + boxShadow: "0 24px 80px rgba(0,0,0,0.5)" + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("h2", { + style: { + margin: "0 0 24px", + fontSize: 18, + fontWeight: 700, + color: theme.text, + fontFamily: "'JetBrains Mono', monospace" + }, + children: mode === "edit" ? "Edit Task" : mode === "fork" ? "Fork Task" : "New Task" + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", flexDirection: "column", gap: 16 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Title" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + style: inputStyle, + placeholder: "Task title...", + value: form.title, + onChange: (e) => set("title", e.target.value) + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Prompt *" + }), + /* @__PURE__ */ jsx_runtime.jsx("textarea", { + style: { ...inputStyle, height: 100, resize: "vertical" }, + placeholder: "The prompt to send to Claude Code...", + value: form.prompt, + onChange: (e) => set("prompt", e.target.value) + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Images (optional)" + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + display: "flex", + flexWrap: "wrap", + gap: 8, + marginBottom: promptImages.length ? 8 : 0 + }, + children: [ + promptImages.map((img, idx) => /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { position: "relative", width: 72, height: 72 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("img", { + src: img.preview, + alt: img.name, + style: { + width: 72, + height: 72, + objectFit: "cover", + borderRadius: 6, + border: `1px solid ${theme.border}` + } + }), + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: () => removeImage(idx), + style: { + position: "absolute", + top: -6, + right: -6, + width: 18, + height: 18, + borderRadius: "50%", + border: "none", + background: theme.red || "#e74c3c", + color: "#fff", + fontSize: 11, + cursor: "pointer", + lineHeight: "18px", + padding: 0, + display: "flex", + alignItems: "center", + justifyContent: "center" + }, + children: "×" + }) + ] + }, idx)), + /* @__PURE__ */ jsx_runtime.jsxs("label", { + style: { + width: 72, + height: 72, + borderRadius: 6, + border: `1px dashed ${theme.border}`, + display: "flex", + alignItems: "center", + justifyContent: "center", + cursor: "pointer", + color: theme.textDim, + fontSize: 22, + flexShrink: 0 + }, + children: [ + "+", + /* @__PURE__ */ jsx_runtime.jsx("input", { + type: "file", + accept: "image/*", + multiple: true, + style: { display: "none" }, + onChange: handleImageSelect + }) + ] + }) + ] + }), + promptImages.length > 0 && /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { fontSize: 10, color: theme.textDim }, + children: [ + promptImages.length, + " image", + promptImages.length > 1 ? "s" : "", + " attached" + ] + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Working Directory" + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", gap: 8 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("input", { + style: { ...inputStyle, flex: 1 }, + placeholder: "~/papers", + value: form.working_dir, + onChange: (e) => set("working_dir", e.target.value) + }), + window.electronAPI?.selectDirectory && /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: async () => { + const dir = await window.electronAPI.selectDirectory(); + if (dir) + set("working_dir", dir); + }, + style: { + padding: "8px 14px", + borderRadius: 8, + cursor: "pointer", + border: `1px solid ${theme.border}`, + background: theme.bg, + color: theme.textMuted, + fontSize: 12, + fontWeight: 600, + whiteSpace: "nowrap", + transition: "all 0.15s" + }, + children: "Browse" + }) + ] + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Schedule Type" + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { display: "flex", gap: 8, flexWrap: "wrap" }, + children: ["immediate", "delayed", "scheduled_at", "cron"].map((t) => /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: () => set("schedule_type", t), + style: { + flex: 1, + padding: "8px 12px", + borderRadius: 8, + cursor: "pointer", + border: `1px solid ${form.schedule_type === t ? theme.accent : theme.border}`, + background: form.schedule_type === t ? theme.accentGlow : "transparent", + color: form.schedule_type === t ? theme.accent : theme.textMuted, + fontSize: 12, + fontWeight: 600, + textTransform: "capitalize", + transition: "all 0.15s", + minWidth: 100 + }, + children: t === "immediate" ? "⚡ Immediate" : t === "delayed" ? "⏳ Delayed" : t === "scheduled_at" ? "\uD83D\uDCC5 At Time" : "⏲ Cron" + }, t)) + }) + ] + }), + form.schedule_type === "delayed" && /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Delay (seconds)" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + type: "number", + style: inputStyle, + value: form.delay_seconds, + onChange: (e) => set("delay_seconds", e.target.value) + }) + ] + }), + form.schedule_type === "scheduled_at" && /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Run At (Local Time)" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + type: "datetime-local", + style: inputStyle, + value: form.scheduled_at, + onChange: (e) => { + set("scheduled_at", e.target.value); + setScheduledAtError(""); + } + }), + scheduledAtError && /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 11, color: "#ff5f5f", marginTop: 4 }, + children: scheduledAtError + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 10, color: theme.textDim, marginTop: 4 }, + children: "Select a specific date and time to execute this task once" + }) + ] + }), + form.schedule_type === "cron" && /* @__PURE__ */ jsx_runtime.jsxs(jsx_runtime.Fragment, { + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Cron Expression" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + style: inputStyle, + placeholder: "*/30 * * * *", + value: form.cron_expr, + onChange: (e) => set("cron_expr", e.target.value) + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 10, color: theme.textDim, marginTop: 4 }, + children: 'e.g. "0 9 * * *" = daily 9am, "*/30 * * * *" = every 30 min' + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Max Runs (empty = unlimited)" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + type: "number", + style: inputStyle, + value: form.max_runs, + onChange: (e) => set("max_runs", e.target.value) + }) + ] + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Tags (comma separated)" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + style: inputStyle, + placeholder: "paper, review, arxiv", + value: form.tags, + onChange: (e) => set("tags", e.target.value) + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Dependencies (optional)" + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 10, color: theme.textDim, marginBottom: 8 }, + children: "This task will be blocked until all upstream tasks complete." + }), + depRows.map((row2, idx) => /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", gap: 6, alignItems: "center", marginBottom: 6 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("input", { + type: "number", + placeholder: "Task ID", + value: row2._input || "", + onChange: (e) => { + const val = e.target.value; + const parsed = parseInt(val); + setDepRows((prev) => prev.map((r, i) => i === idx ? { ...r, _input: val, task_id: isNaN(parsed) ? null : parsed } : r)); + }, + style: { ...inputStyle, width: 100, flex: "none" } + }), + /* @__PURE__ */ jsx_runtime.jsxs("label", { + style: { + display: "flex", + alignItems: "center", + gap: 4, + fontSize: 11, + color: theme.textMuted, + cursor: "pointer", + flex: 1 + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("input", { + type: "checkbox", + checked: row2.inject_result, + onChange: (e) => setDepRows((prev) => prev.map((r, i) => i === idx ? { ...r, inject_result: e.target.checked } : r)), + style: { accentColor: theme.accent } + }), + "Inject result into prompt" + ] + }), + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: () => setDepRows((prev) => prev.filter((_, i) => i !== idx)), + style: { + background: "transparent", + border: "none", + color: theme.red, + cursor: "pointer", + fontSize: 16, + padding: "0 4px" + }, + children: "×" + }) + ] + }, idx)), + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: () => setDepRows((prev) => [...prev, { task_id: null, inject_result: false, _input: "" }]), + style: { + padding: "5px 12px", + borderRadius: 6, + border: `1px dashed ${theme.border}`, + background: "transparent", + color: theme.textMuted, + cursor: "pointer", + fontSize: 11, + fontWeight: 600 + }, + children: "+ Add dependency" + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "DAG ID (optional)" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + style: inputStyle, + placeholder: "my-pipeline", + value: form.dag_id, + onChange: (e) => set("dag_id", e.target.value) + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 10, color: theme.textDim, marginTop: 4 }, + children: "Group tasks into a named workflow" + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Agent" + }), + /* @__PURE__ */ jsx_runtime.jsxs("select", { + style: inputStyle, + value: form.agent, + onChange: (e) => set("agent", e.target.value), + children: [ + /* @__PURE__ */ jsx_runtime.jsx("option", { + value: "claude", + children: "Claude Code (claude CLI)" + }), + /* @__PURE__ */ jsx_runtime.jsx("option", { + value: "codex", + children: "Codex CLI (openai/codex)" + }) + ] + }) + ] + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", gap: 10, marginTop: 28, justifyContent: "flex-end" }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: onClose, + style: { + padding: "10px 20px", + borderRadius: 8, + border: `1px solid ${theme.border}`, + background: "transparent", + color: theme.textMuted, + cursor: "pointer", + fontSize: 13, + fontWeight: 600 + }, + children: "Cancel" + }), + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: handleSubmit, + style: { + padding: "10px 24px", + borderRadius: 8, + border: "none", + background: theme.accent, + color: "#fff", + cursor: "pointer", + fontSize: 13, + fontWeight: 600, + boxShadow: `0 0 20px ${theme.accentGlow}` + }, + children: mode === "edit" ? "Save Changes" : mode === "fork" ? "Create Fork" : "Create Task" + }) + ] + }) + ] + }) + }); +} +function DetailPanel({ task, onClose, onResume }) { + const [liveOutput, setLiveOutput] = import_react.useState(""); + const [resumeText, setResumeText] = import_react.useState(""); + const [resumeError, setResumeError] = import_react.useState(""); + const [resumeSent, setResumeSent] = import_react.useState(false); + const [messages, setMessages] = import_react.useState([]); + const [events, setEvents] = import_react.useState([]); + const [showMessages, setShowMessages] = import_react.useState(false); + const [showEvents, setShowEvents] = import_react.useState(false); + const [showLiveOutput, setShowLiveOutput] = import_react.useState(true); + const liveOutputRef = import_react.useRef(null); + const messagesRef = import_react.useRef(null); + const eventsRef = import_react.useRef(null); + import_react.useEffect(() => { + if (task.status !== "running") { + setLiveOutput(""); + return; + } + let cancelled = false; + let lastOutputLength = 0; + const poll = async () => { + try { + const res = await fetch(`${API}/tasks/${task.id}/output`); + if (res.ok && !cancelled) { + const data = await res.json(); + const currentOutput = data.output || ""; + if (currentOutput.length > lastOutputLength) { + const newContent = currentOutput.slice(lastOutputLength); + setLiveOutput((prev) => prev + newContent); + lastOutputLength = currentOutput.length; + } + } + } catch {} + }; + poll(); + const interval = setInterval(poll, 1000); + return () => { + cancelled = true; + clearInterval(interval); + }; + }, [task.id, task.status]); + import_react.useEffect(() => { + if (liveOutputRef.current) { + liveOutputRef.current.scrollTop = liveOutputRef.current.scrollHeight; + } + }, [liveOutput]); + import_react.useEffect(() => { + if (showMessages) { + fetchTaskMessages(task.id).then(setMessages); + } + }, [task.id, showMessages]); + import_react.useEffect(() => { + if (!showEvents) + return; + let cancelled = false; + const load = async () => { + const nextEvents = await fetchTaskEvents(task.id); + if (!cancelled) + setEvents(nextEvents); + }; + load(); + if (task.status !== "running") { + return () => { + cancelled = true; + }; + } + const interval = setInterval(load, 1000); + return () => { + cancelled = true; + clearInterval(interval); + }; + }, [task.id, task.status, showEvents]); + import_react.useEffect(() => { + if (messagesRef.current) { + messagesRef.current.scrollTop = messagesRef.current.scrollHeight; + } + }, [messages]); + const handleResume = async () => { + if (!resumeText.trim()) + return; + setResumeError(""); + const result = await resumeTask(task.id, resumeText.trim()); + if (result.error) { + setResumeError(result.error); + } else { + setResumeText(""); + setResumeSent(true); + setTimeout(() => setResumeSent(false), 3000); + onResume(); + } + }; + return /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + position: "fixed", + right: 0, + top: 0, + bottom: 0, + width: 480, + background: theme.surface, + borderLeft: `1px solid ${theme.border}`, + zIndex: 999, + overflow: "auto", + padding: 28, + boxShadow: "-8px 0 40px rgba(0,0,0,0.4)" + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + display: "flex", + justifyContent: "space-between", + alignItems: "center", + marginBottom: 24 + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx(Badge, { + status: task.status + }), + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: onClose, + style: { + background: "transparent", + border: "none", + color: theme.textMuted, + fontSize: 20, + cursor: "pointer" + }, + children: "×" + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsx("h2", { + style: { + fontSize: 18, + fontWeight: 700, + color: theme.text, + margin: "0 0 8px", + fontFamily: "'JetBrains Mono', monospace" + }, + children: task.title + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { fontSize: 11, color: theme.textDim, marginBottom: 24, fontFamily: "monospace" }, + children: [ + "ID: ", + task.id, + " · Created: ", + formatTaskDateTime(task.created_at) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs(Section, { + title: "Prompt", + children: [ + /* @__PURE__ */ jsx_runtime.jsx("pre", { + style: { + background: theme.bg, + border: `1px solid ${theme.border}`, + borderRadius: 8, + padding: 14, + fontSize: 12, + color: theme.text, + whiteSpace: "pre-wrap", + wordBreak: "break-word", + margin: 0, + fontFamily: "'JetBrains Mono', monospace", + lineHeight: 1.6 + }, + children: task.prompt + }), + task.prompt_images && task.prompt_images.length > 0 && /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { marginTop: 12 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + fontSize: 10, + color: theme.textMuted, + fontWeight: 600, + letterSpacing: 0.8, + textTransform: "uppercase", + marginBottom: 8 + }, + children: [ + "Attached Images (", + task.prompt_images.length, + ")" + ] + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { display: "flex", flexWrap: "wrap", gap: 8 }, + children: task.prompt_images.map((img, i) => /* @__PURE__ */ jsx_runtime.jsx("img", { + src: `data:${img.media_type};base64,${img.data}`, + alt: img.name || `image ${i + 1}`, + style: { + width: 80, + height: 80, + objectFit: "cover", + borderRadius: 6, + border: `1px solid ${theme.border}` + } + }, i)) + }) + ] + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs(Section, { + title: "Configuration", + children: [ + /* @__PURE__ */ jsx_runtime.jsx(InfoRow, { + label: "Working Dir", + value: task.working_dir + }), + /* @__PURE__ */ jsx_runtime.jsx(InfoRow, { + label: "Agent", + value: task.agent || DEFAULT_AGENT + }), + /* @__PURE__ */ jsx_runtime.jsx(InfoRow, { + label: "Schedule", + value: task.schedule_type + }), + task.cron_expr && /* @__PURE__ */ jsx_runtime.jsx(InfoRow, { + label: "Cron", + value: task.cron_expr + }), + task.delay_seconds && /* @__PURE__ */ jsx_runtime.jsx(InfoRow, { + label: "Delay", + value: `${task.delay_seconds}s` + }), + task.next_run_at && /* @__PURE__ */ jsx_runtime.jsx(InfoRow, { + label: "Next Run", + value: formatTaskDateTime(task.next_run_at) + }), + /* @__PURE__ */ jsx_runtime.jsx(InfoRow, { + label: "Runs", + value: `${task.run_count}${task.max_runs ? ` / ${task.max_runs}` : ""}` + }), + task.dag_id && /* @__PURE__ */ jsx_runtime.jsx(InfoRow, { + label: "DAG", + value: task.dag_id + }) + ] + }), + task.dependencies && task.dependencies.length > 0 && /* @__PURE__ */ jsx_runtime.jsx(Section, { + title: "Upstream Dependencies", + children: task.dependencies.map((dep) => /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + display: "flex", + justifyContent: "space-between", + alignItems: "center", + padding: "5px 0", + borderBottom: `1px solid ${theme.border}`, + fontSize: 12 + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("span", { + style: { color: theme.text, fontFamily: "monospace" }, + children: [ + "#", + dep.depends_on_task_id, + dep.depends_on_title ? ` — ${dep.depends_on_title}` : "" + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", gap: 8, alignItems: "center" }, + children: [ + dep.inject_result ? /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { fontSize: 10, color: theme.accent }, + children: "↳ inject" + }) : null, + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { + fontSize: 10, + fontWeight: 600, + color: dep.depends_on_status === "completed" ? theme.green : dep.depends_on_status === "failed" ? theme.red : theme.orange + }, + children: dep.depends_on_status + }) + ] + }) + ] + }, dep.id)) + }), + task.dependents && task.dependents.length > 0 && /* @__PURE__ */ jsx_runtime.jsx(Section, { + title: "Downstream Tasks", + children: /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 12, color: theme.textMuted, fontFamily: "monospace" }, + children: task.dependents.map((id) => `#${id}`).join(", ") + }) + }), + task.status === "running" && /* @__PURE__ */ jsx_runtime.jsx(Section, { + title: /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", alignItems: "center", gap: 8 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("span", { + children: "Live Output" + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + display: "flex", + alignItems: "center", + gap: 6, + fontSize: 10, + color: theme.blue + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { + width: 6, + height: 6, + borderRadius: "50%", + background: theme.blue, + animation: "pulse 1.2s ease-in-out infinite" + } + }), + "live" + ] + }) + ] + }), + children: /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + background: theme.bg, + border: `1px solid ${theme.borderActive}`, + borderRadius: 8, + overflow: "hidden" + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + display: "flex", + justifyContent: "space-between", + alignItems: "center", + padding: "8px 12px", + background: theme.surface, + borderBottom: `1px solid ${theme.border}`, + fontSize: 11, + color: theme.textMuted + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", alignItems: "center", gap: 12 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("button", { + onClick: () => setShowLiveOutput(!showLiveOutput), + style: { + background: "transparent", + border: "none", + color: theme.textMuted, + fontSize: 11, + cursor: "pointer", + display: "flex", + alignItems: "center", + gap: 4 + }, + children: [ + showLiveOutput ? "▼" : "▶", + " ", + showLiveOutput ? "Hide" : "Show" + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("span", { + style: { fontFamily: "monospace" }, + children: [ + liveOutput.length.toLocaleString(), + " chars" + ] + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", alignItems: "center", gap: 8 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: () => { + navigator.clipboard.writeText(liveOutput); + }, + style: { + background: "transparent", + border: "none", + color: theme.textMuted, + fontSize: 11, + cursor: "pointer", + padding: "4px 8px", + borderRadius: 4, + fontFamily: "'JetBrains Mono', monospace" + }, + children: "\uD83D\uDCCB Copy" + }), + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: () => setLiveOutput(""), + style: { + background: "transparent", + border: "none", + color: theme.textMuted, + fontSize: 11, + cursor: "pointer", + padding: "4px 8px", + borderRadius: 4, + fontFamily: "'JetBrains Mono', monospace" + }, + children: "\uD83D\uDDD1️ Clear" + }) + ] + }) + ] + }), + showLiveOutput && /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + maxHeight: 400, + overflow: "auto", + position: "relative" + }, + ref: liveOutputRef, + children: /* @__PURE__ */ jsx_runtime.jsx("pre", { + style: { + fontSize: 12, + color: theme.text, + whiteSpace: "pre-wrap", + wordBreak: "break-word", + margin: 0, + padding: 14, + fontFamily: "'JetBrains Mono', monospace", + lineHeight: 1.6, + minHeight: 60 + }, + children: liveOutput ? /* @__PURE__ */ jsx_runtime.jsx(FormattedOutput, { + content: liveOutput, + theme + }) : /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { color: theme.textDim, fontStyle: "italic" }, + children: "Waiting for agent output..." + }) + }) + }) + ] + }) + }), + task.result && /* @__PURE__ */ jsx_runtime.jsx(Section, { + title: "Result", + children: /* @__PURE__ */ jsx_runtime.jsx("pre", { + style: { + background: theme.bg, + border: `1px solid ${theme.border}`, + borderRadius: 8, + padding: 14, + fontSize: 12, + color: theme.green, + whiteSpace: "pre-wrap", + wordBreak: "break-word", + margin: 0, + fontFamily: "'JetBrains Mono', monospace", + lineHeight: 1.6, + maxHeight: 300, + overflow: "auto" + }, + children: task.result + }) + }), + task.error && /* @__PURE__ */ jsx_runtime.jsx(Section, { + title: "Error", + children: /* @__PURE__ */ jsx_runtime.jsx("pre", { + style: { + background: theme.redBg, + border: `1px solid rgba(248,113,113,0.2)`, + borderRadius: 8, + padding: 14, + fontSize: 12, + color: theme.red, + whiteSpace: "pre-wrap", + wordBreak: "break-word", + margin: 0, + fontFamily: "'JetBrains Mono', monospace", + lineHeight: 1.6 + }, + children: task.error + }) + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { marginBottom: 20 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", gap: 8, marginBottom: 12 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: () => { + setShowMessages(!showMessages); + setShowEvents(false); + }, + style: { + flex: 1, + padding: "8px 12px", + borderRadius: 8, + background: showMessages ? theme.accentGlow : theme.surface, + color: showMessages ? theme.accent : theme.textMuted, + fontSize: 11, + fontWeight: 600, + cursor: "pointer", + border: `1px solid ${showMessages ? theme.accent : theme.border}`, + transition: "all 0.15s" + }, + children: "Conversation" + }), + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: () => { + setShowEvents(!showEvents); + setShowMessages(false); + }, + style: { + flex: 1, + padding: "8px 12px", + borderRadius: 8, + background: showEvents ? theme.accentGlow : theme.surface, + color: showEvents ? theme.accent : theme.textMuted, + fontSize: 11, + fontWeight: 600, + cursor: "pointer", + border: `1px solid ${showEvents ? theme.accent : theme.border}`, + transition: "all 0.15s" + }, + children: "Execution Events" + }) + ] + }), + showMessages && /* @__PURE__ */ jsx_runtime.jsx("div", { + ref: messagesRef, + style: { + maxHeight: 400, + overflow: "auto", + display: "flex", + flexDirection: "column", + gap: 8 + }, + children: messages.length === 0 ? /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + fontSize: 12, + color: theme.textDim, + padding: "12px 0", + textAlign: "center" + }, + children: "No conversation data — only tasks run after this feature was added have logs." + }) : messages.map((msg, i) => /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + background: msg.role === "user" ? theme.accentGlow : theme.bg, + border: `1px solid ${msg.role === "user" ? theme.accent + "33" : theme.border}`, + borderRadius: 8, + padding: "10px 14px", + borderLeft: `3px solid ${msg.role === "user" ? theme.accent : theme.green}` + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + fontSize: 10, + fontWeight: 700, + letterSpacing: 0.8, + color: msg.role === "user" ? theme.accent : theme.green, + textTransform: "uppercase", + marginBottom: 6 + }, + children: msg.role + }), + /* @__PURE__ */ jsx_runtime.jsx("pre", { + style: { + fontSize: 12, + color: theme.text, + whiteSpace: "pre-wrap", + wordBreak: "break-word", + margin: 0, + fontFamily: "'JetBrains Mono', monospace", + lineHeight: 1.6, + maxHeight: 200, + overflow: "auto" + }, + children: msg.text + }) + ] + }, i)) + }), + showEvents && /* @__PURE__ */ jsx_runtime.jsx("div", { + ref: eventsRef, + style: { maxHeight: 520, overflow: "auto" }, + children: /* @__PURE__ */ jsx_runtime.jsx(ExecutionTimeline, { + events + }) + }) + ] + }), + ["completed", "failed"].includes(task.status) && task.session_id && /* @__PURE__ */ jsx_runtime.jsxs(Section, { + title: "Resume Session", + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + fontSize: 11, + color: theme.textDim, + marginBottom: 10, + fontFamily: "monospace" + }, + children: [ + "Session: ", + task.session_id + ] + }), + /* @__PURE__ */ jsx_runtime.jsx("textarea", { + placeholder: "Send a follow-up message to continue this conversation…", + value: resumeText, + onChange: (e) => setResumeText(e.target.value), + onKeyDown: (e) => { + if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) + handleResume(); + }, + style: { + width: "100%", + padding: "10px 14px", + borderRadius: 8, + border: `1px solid ${theme.border}`, + background: theme.bg, + color: theme.text, + fontSize: 13, + outline: "none", + boxSizing: "border-box", + fontFamily: "'JetBrains Mono', 'SF Mono', monospace", + resize: "vertical", + minHeight: 80 + } + }), + resumeError && /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 11, color: theme.red, marginTop: 6 }, + children: resumeError + }), + resumeSent && /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 12, color: theme.green, marginTop: 6 }, + children: "✨ 已发送!任务正在重新唤醒,请稍候~" + }), + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: handleResume, + style: { + marginTop: 10, + padding: "8px 20px", + borderRadius: 8, + border: "none", + background: theme.accent, + color: "#fff", + cursor: "pointer", + fontSize: 13, + fontWeight: 600, + boxShadow: `0 0 20px ${theme.accentGlow}` + }, + children: "↩ Resume (⌘↵)" + }) + ] + }) + ] + }); +} +function Section({ title, children }) { + return /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { marginBottom: 20 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + fontSize: 10, + fontWeight: 700, + color: theme.textDim, + letterSpacing: 1.2, + textTransform: "uppercase", + marginBottom: 10 + }, + children: title + }), + children + ] + }); +} +function InfoRow({ label, value }) { + return /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + display: "flex", + justifyContent: "space-between", + padding: "6px 0", + borderBottom: `1px solid ${theme.border}`, + fontSize: 12 + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { color: theme.textMuted }, + children: label + }), + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { color: theme.text, fontFamily: "monospace" }, + children: value + }) + ] + }); +} +function SettingsModal({ + onClose, + timeout: initialTimeout, + defaultAgent: initialDefaultAgent, + onSave, + feishu: initialFeishu, + onFeishuSave, + channelsStatus: initialChannelsStatus, + onChannelsSave +}) { + const [tab, setTab] = import_react.useState("general"); + const [timeout, setTimeout2] = import_react.useState(initialTimeout ?? DEFAULT_TIMEOUT_SECONDS); + const [defaultAgent, setDefaultAgent] = import_react.useState(initialDefaultAgent ?? DEFAULT_AGENT); + const [skillEnabled, setSkillEnabled] = import_react.useState(false); + const [skillSweepAgent, setSkillSweepAgent] = import_react.useState(DEFAULT_AGENT); + const [skillSweepCron, setSkillSweepCron] = import_react.useState("0 3 * * *"); + const [feishu, setFeishu] = import_react.useState({ + feishu_app_id: "", + feishu_app_secret: "", + feishu_default_chat_id: "", + feishu_default_working_dir: "~", + feishu_enabled: "false", + ...initialFeishu + }); + const [feishuSaving, setFeishuSaving] = import_react.useState(false); + const [feishuMsg, setFeishuMsg] = import_react.useState(null); + const [channels, setChannels] = import_react.useState(createInitialChannelsState(initialChannelsStatus)); + const [channelsSaving, setChannelsSaving] = import_react.useState(false); + const [channelsMsg, setChannelsMsg] = import_react.useState(null); + const [weixinQrSrc, setWeixinQrSrc] = import_react.useState(""); + const [weixinActionBusy, setWeixinActionBusy] = import_react.useState(false); + const [collapsedChannels, setCollapsedChannels] = import_react.useState({ + telegram: true, + slack: true, + weixin: true + }); + import_react.useEffect(() => { + let cancelled = false; + const refreshChannels = async (preserveUserEdits = true) => { + const status = await fetchChannelsStatus(); + if (!cancelled) { + setChannels((c) => { + const merged = mergeChannelsStatus(c, status); + if (!preserveUserEdits) + return merged; + return { + telegram: { ...merged.telegram, enabled: c.telegram.enabled }, + slack: { ...merged.slack, enabled: c.slack.enabled }, + weixin: { ...merged.weixin, enabled: c.weixin.enabled } + }; + }); + } + }; + refreshChannels(false); + const intervalId = setInterval(refreshChannels, 2000); + fetchFeishuSettings().then((s) => { + if (s && Object.keys(s).length) + setFeishu((f) => ({ ...f, ...s })); + }); + fetchSettings().then((s) => { + if (s && typeof s === "object") { + if (typeof s.skill_library_enabled === "boolean") + setSkillEnabled(s.skill_library_enabled); + if (s.skill_sweep_agent) + setSkillSweepAgent(s.skill_sweep_agent); + if (s.skill_sweep_cron) + setSkillSweepCron(s.skill_sweep_cron); + } + }); + return () => { + cancelled = true; + clearInterval(intervalId); + }; + }, []); + import_react.useEffect(() => { + let cancelled = false; + const qrValue = channels.weixin?.qr_code_url || ""; + if (!qrValue) { + setWeixinQrSrc(""); + return () => { + cancelled = true; + }; + } + if (isWeixinQrImageSource(qrValue)) { + setWeixinQrSrc(qrValue); + return () => { + cancelled = true; + }; + } + import_qrcode.default.toDataURL(qrValue, { + errorCorrectionLevel: "M", + margin: 2, + width: 440 + }).then((dataUrl) => { + if (!cancelled) + setWeixinQrSrc(dataUrl); + }).catch((error) => { + console.error("Failed to generate Weixin QR code", error); + if (!cancelled) + setWeixinQrSrc(""); + }); + return () => { + cancelled = true; + }; + }, [channels.weixin?.qr_code_url]); + const handleWeixinAction = async (action) => { + setWeixinActionBusy(true); + setChannelsMsg(null); + try { + await runWeixinAction(action); + const updated = await fetchChannelsStatus(); + setChannels((c) => mergeChannelsStatus(c, updated)); + if (onChannelsSave) + onChannelsSave(updated); + setChannelsMsg({ + ok: true, + text: action === "logout" ? "Wechat logged out." : "Wechat login restarted." + }); + } catch (e) { + setChannelsMsg({ ok: false, text: String(e) }); + } finally { + setWeixinActionBusy(false); + } + }; + const handleSaveGeneral = async () => { + await updateSettings({ + timeout: parseInt(timeout) || DEFAULT_TIMEOUT_SECONDS, + default_agent: defaultAgent, + skill_library_enabled: skillEnabled ? "1" : "0", + skill_sweep_agent: skillSweepAgent, + skill_sweep_cron: skillSweepCron + }); + onSave(parseInt(timeout) || DEFAULT_TIMEOUT_SECONDS, defaultAgent); + onClose(); + }; + const handleSaveFeishu = async () => { + setFeishuSaving(true); + setFeishuMsg(null); + try { + await updateFeishuSettings(feishu); + setFeishuMsg({ ok: true, text: "Saved. Bridge restarted." }); + if (onFeishuSave) { + const updated = await fetchFeishuSettings(); + onFeishuSave(updated); + } + } catch (e) { + setFeishuMsg({ ok: false, text: String(e) }); + } finally { + setFeishuSaving(false); + } + }; + const handleSaveChannels = async () => { + setChannelsSaving(true); + setChannelsMsg(null); + try { + await updateChannelsSettings(buildChannelsSavePayload(channels)); + const updated = await fetchChannelsStatus(); + setChannels((c) => mergeChannelsStatus(c, updated)); + if (onChannelsSave) + onChannelsSave(updated); + setChannelsMsg({ ok: true, text: "Saved. Channels restarted." }); + } catch (e) { + setChannelsMsg({ ok: false, text: String(e) }); + } finally { + setChannelsSaving(false); + } + }; + const fieldStyle = { + width: "100%", + padding: "10px 14px", + borderRadius: 8, + border: `1px solid ${theme.border}`, + background: theme.bg, + color: theme.text, + fontSize: 13, + outline: "none", + boxSizing: "border-box", + fontFamily: "'JetBrains Mono', 'SF Mono', monospace" + }; + const labelStyle = { + fontSize: 11, + fontWeight: 600, + color: theme.textMuted, + letterSpacing: 0.8, + textTransform: "uppercase", + marginBottom: 8, + display: "block" + }; + const hintStyle = { fontSize: 10, color: theme.textDim, marginTop: 4 }; + const tabs = ["general", "channels", "feishu"]; + const tabLabel = { general: "General", channels: "Channels", feishu: "Feishu / Lark" }; + return /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + position: "fixed", + inset: 0, + background: "rgba(0,0,0,0.7)", + display: "flex", + alignItems: "center", + justifyContent: "center", + zIndex: 1000, + backdropFilter: "blur(8px)" + }, + onClick: onClose, + children: /* @__PURE__ */ jsx_runtime.jsxs("div", { + onClick: (e) => e.stopPropagation(), + style: { + background: theme.surface, + border: `1px solid ${theme.border}`, + borderRadius: 16, + padding: 32, + width: 480, + maxHeight: "85vh", + overflowY: "auto", + boxShadow: "0 24px 80px rgba(0,0,0,0.5)" + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("h2", { + style: { + margin: "0 0 20px", + fontSize: 18, + fontWeight: 700, + color: theme.text, + fontFamily: "'JetBrains Mono', monospace" + }, + children: "Settings" + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + display: "flex", + gap: 4, + marginBottom: 24, + borderBottom: `1px solid ${theme.border}`, + paddingBottom: 0 + }, + children: tabs.map((t) => /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: () => setTab(t), + style: { + padding: "7px 16px", + borderRadius: "8px 8px 0 0", + border: "none", + cursor: "pointer", + fontSize: 12, + fontWeight: 600, + background: tab === t ? theme.bg : "transparent", + color: tab === t ? theme.text : theme.textMuted, + borderBottom: tab === t ? `2px solid ${theme.accent}` : "2px solid transparent", + marginBottom: -1 + }, + children: tabLabel[t] + }, t)) + }), + tab === "general" && /* @__PURE__ */ jsx_runtime.jsxs(jsx_runtime.Fragment, { + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { marginBottom: 20 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Task Timeout (seconds)" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + type: "number", + min: "10", + step: "10", + value: timeout, + onChange: (e) => setTimeout2(e.target.value), + style: fieldStyle + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: hintStyle, + children: "Default: 12000s (200 min). Max time before a running task is killed." + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { marginBottom: 20 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Default Agent" + }), + /* @__PURE__ */ jsx_runtime.jsxs("select", { + value: defaultAgent, + onChange: (e) => setDefaultAgent(e.target.value), + style: fieldStyle, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("option", { + value: "claude", + children: "Claude Code (claude CLI)" + }), + /* @__PURE__ */ jsx_runtime.jsx("option", { + value: "codex", + children: "Codex CLI (openai/codex)" + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: hintStyle, + children: "Agent used for new tasks unless overridden per-task." + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + marginBottom: 20, + paddingTop: 16, + borderTop: `1px solid ${theme.border}` + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("label", { + style: { + ...labelStyle, + display: "flex", + alignItems: "center", + gap: 10, + cursor: "pointer" + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("input", { + type: "checkbox", + checked: skillEnabled, + onChange: (e) => setSkillEnabled(e.target.checked), + style: { width: 16, height: 16, cursor: "pointer" } + }), + "Skill Library 自动扫描" + ] + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: hintStyle, + children: "定时让 agent 扫描已完成任务、检测复发模式(消耗 token,默认关闭)。 手动「扫一遍」按钮不受此开关影响。" + }) + ] + }), + skillEnabled && /* @__PURE__ */ jsx_runtime.jsxs(jsx_runtime.Fragment, { + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { marginBottom: 20 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "扫描 Agent" + }), + /* @__PURE__ */ jsx_runtime.jsxs("select", { + value: skillSweepAgent, + onChange: (e) => setSkillSweepAgent(e.target.value), + style: fieldStyle, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("option", { + value: "claude", + children: "Claude Code (claude CLI)" + }), + /* @__PURE__ */ jsx_runtime.jsx("option", { + value: "codex", + children: "Codex CLI (openai/codex)" + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: hintStyle, + children: "运行 sweep 的 agent。" + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { marginBottom: 20 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "扫描节奏 (cron)" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + value: skillSweepCron, + onChange: (e) => setSkillSweepCron(e.target.value), + placeholder: "0 3 * * *", + style: { ...fieldStyle, fontFamily: "monospace" } + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: hintStyle, + children: "默认每日凌晨 3 点。增量扫描,只看上次以来的新任务。" + }) + ] + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", gap: 10, justifyContent: "flex-end" }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: onClose, + style: { + padding: "10px 20px", + borderRadius: 8, + border: `1px solid ${theme.border}`, + background: "transparent", + color: theme.textMuted, + cursor: "pointer", + fontSize: 13, + fontWeight: 600 + }, + children: "Cancel" + }), + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: handleSaveGeneral, + style: { + padding: "10px 24px", + borderRadius: 8, + border: "none", + background: theme.accent, + color: "#fff", + cursor: "pointer", + fontSize: 13, + fontWeight: 600, + boxShadow: `0 0 20px ${theme.accentGlow}` + }, + children: "Save" + }) + ] + }) + ] + }), + tab === "channels" && /* @__PURE__ */ jsx_runtime.jsxs(jsx_runtime.Fragment, { + children: [ + (() => { + const ch = channels.telegram; + const collapsed = collapsedChannels.telegram; + const statusDot = ch.running ? { bg: theme.green, label: "Connected" } : ch.configured ? { bg: theme.yellow || "#f59e0b", label: "Configured (not running)" } : { bg: theme.textDim, label: "Not configured" }; + return /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + marginBottom: 16, + borderRadius: 10, + border: `1px solid ${theme.border}`, + background: theme.bg, + overflow: "hidden" + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + display: "flex", + alignItems: "center", + justifyContent: "space-between", + padding: "12px 16px", + cursor: "pointer", + userSelect: "none" + }, + onClick: () => setCollapsedChannels((c) => ({ ...c, telegram: !c.telegram })), + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", alignItems: "center", gap: 10 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { + fontSize: 10, + color: theme.textMuted, + transition: "transform 0.2s", + transform: collapsed ? "rotate(-90deg)" : "rotate(0deg)", + display: "inline-block" + }, + children: "▼" + }), + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { + display: "inline-flex", + width: 22, + height: 22, + alignItems: "center", + justifyContent: "center", + color: "#2AABEE", + flexShrink: 0 + }, + children: /* @__PURE__ */ jsx_runtime.jsx("svg", { + viewBox: "0 0 24 24", + width: "22", + height: "22", + "aria-hidden": "true", + fill: "currentColor", + children: /* @__PURE__ */ jsx_runtime.jsx("path", { + d: "M21.4 4.6a1.2 1.2 0 0 0-1.24-.2L3.8 11.15c-.6.25-.57 1.12.05 1.33l4.6 1.62 1.62 4.6c.22.62 1.08.65 1.33.05l6.75-16.36a1.2 1.2 0 0 0-.2-1.24 1.18 1.18 0 0 0-1.22-.3Z" + }) + }) + }), + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { fontWeight: 700, fontSize: 14, color: theme.text }, + children: "Telegram" + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", alignItems: "center", gap: 6, marginLeft: 8 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { + width: 8, + height: 8, + borderRadius: "50%", + background: statusDot.bg, + display: "inline-block", + boxShadow: ch.running ? `0 0 6px ${statusDot.bg}` : "none" + } + }), + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { fontSize: 11, color: theme.textMuted }, + children: statusDot.label + }) + ] + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: (e) => { + e.stopPropagation(); + setChannels((c) => ({ + ...c, + telegram: { ...c.telegram, enabled: !c.telegram.enabled } + })); + }, + style: { + width: 44, + height: 24, + borderRadius: 12, + border: "none", + cursor: "pointer", + background: ch.enabled ? theme.accent : theme.border, + position: "relative", + transition: "background 0.2s", + flexShrink: 0 + }, + children: /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { + position: "absolute", + top: 3, + width: 18, + height: 18, + borderRadius: "50%", + background: "#fff", + transition: "left 0.2s", + left: ch.enabled ? 23 : 3 + } + }) + }) + ] + }), + !collapsed && /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { padding: "0 16px 16px" }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { marginBottom: 12 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Bot Token" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + type: "password", + value: ch.bot_token, + onChange: (e) => setChannels((c) => ({ + ...c, + telegram: { ...c.telegram, bot_token: e.target.value } + })), + placeholder: "123456:ABC-DEF...", + style: fieldStyle + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: hintStyle, + children: "Token from @BotFather" + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { marginBottom: 12 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Allowed User IDs" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + value: ch.allowed_users, + onChange: (e) => setChannels((c) => ({ + ...c, + telegram: { ...c.telegram, allowed_users: e.target.value } + })), + placeholder: "123456789,987654321 (optional)", + style: fieldStyle + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: hintStyle, + children: "Comma-separated numeric Telegram user IDs. Leave empty to allow all." + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { marginBottom: 12 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Default Working Directory" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + value: ch.default_working_dir, + onChange: (e) => setChannels((c) => ({ + ...c, + telegram: { ...c.telegram, default_working_dir: e.target.value } + })), + placeholder: "~/my-project", + style: fieldStyle + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: hintStyle, + children: "Working directory for tasks created via the Telegram bot." + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { marginBottom: 12 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Default Notification Chat ID" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + value: ch.default_chat_id, + onChange: (e) => setChannels((c) => ({ + ...c, + telegram: { ...c.telegram, default_chat_id: e.target.value } + })), + placeholder: "-1001234567890 or 123456789", + style: fieldStyle + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: hintStyle, + children: "Fallback chat for notifications from UI-created tasks (group or user chat ID)." + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + background: theme.surface, + border: `1px solid ${theme.border}`, + borderRadius: 6, + padding: "10px 12px", + fontSize: 11, + fontFamily: "monospace", + color: theme.textMuted, + lineHeight: 1.8 + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { color: theme.textDim, marginBottom: 4 }, + children: "Bot commands:" + }), + [ + "/newtask | <prompt>", + "/list", + "/status <id>", + "/cancel <id>" + ].map((cmd) => /* @__PURE__ */ jsx_runtime.jsx("div", { + children: /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { color: theme.cyan }, + children: cmd + }) + }, cmd)) + ] + }) + ] + }) + ] + }); + })(), + (() => { + const ch = channels.slack; + const collapsed = collapsedChannels.slack; + const statusDot = ch.running ? { bg: theme.green, label: "Connected" } : ch.configured ? { bg: theme.yellow || "#f59e0b", label: "Configured (not running)" } : { bg: theme.textDim, label: "Not configured" }; + return /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + marginBottom: 16, + borderRadius: 10, + border: `1px solid ${theme.border}`, + background: theme.bg, + overflow: "hidden" + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + display: "flex", + alignItems: "center", + justifyContent: "space-between", + padding: "12px 16px", + cursor: "pointer", + userSelect: "none" + }, + onClick: () => setCollapsedChannels((c) => ({ ...c, slack: !c.slack })), + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", alignItems: "center", gap: 10 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { + fontSize: 10, + color: theme.textMuted, + transition: "transform 0.2s", + transform: collapsed ? "rotate(-90deg)" : "rotate(0deg)", + display: "inline-block" + }, + children: "▼" + }), + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { + display: "inline-flex", + width: 22, + height: 22, + alignItems: "center", + justifyContent: "center", + flexShrink: 0 + }, + children: /* @__PURE__ */ jsx_runtime.jsxs("svg", { + viewBox: "0 0 24 24", + width: "22", + height: "22", + "aria-hidden": "true", + children: [ + /* @__PURE__ */ jsx_runtime.jsx("path", { + fill: "#36C5F0", + d: "M10.1 3.2A2.2 2.2 0 0 1 12.2 1h.7v5.1h-2.8V3.2Z" + }), + /* @__PURE__ */ jsx_runtime.jsx("path", { + fill: "#2EB67D", + d: "M20.8 10.1A2.2 2.2 0 0 1 23 12.2v.7h-5.1v-2.8h2.9Z" + }), + /* @__PURE__ */ jsx_runtime.jsx("path", { + fill: "#ECB22E", + d: "M13.9 20.8A2.2 2.2 0 0 1 11.8 23h-.7v-5.1h2.8v2.9Z" + }), + /* @__PURE__ */ jsx_runtime.jsx("path", { + fill: "#E01E5A", + d: "M3.2 13.9A2.2 2.2 0 0 1 1 11.8v-.7h5.1v2.8H3.2Z" + }), + /* @__PURE__ */ jsx_runtime.jsx("path", { + fill: "#36C5F0", + d: "M13.2 4.3a2.7 2.7 0 1 1 5.4 0 2.7 2.7 0 0 1-5.4 0Z" + }), + /* @__PURE__ */ jsx_runtime.jsx("path", { + fill: "#2EB67D", + d: "M16.9 13.2a2.7 2.7 0 1 1 0 5.4 2.7 2.7 0 0 1 0-5.4Z" + }), + /* @__PURE__ */ jsx_runtime.jsx("path", { + fill: "#ECB22E", + d: "M5.4 16.9a2.7 2.7 0 1 1 5.4 0 2.7 2.7 0 0 1-5.4 0Z" + }), + /* @__PURE__ */ jsx_runtime.jsx("path", { + fill: "#E01E5A", + d: "M4.3 5.4a2.7 2.7 0 1 1 0 5.4 2.7 2.7 0 0 1 0-5.4Z" + }) + ] + }) + }), + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { fontWeight: 700, fontSize: 14, color: theme.text }, + children: "Slack" + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", alignItems: "center", gap: 6, marginLeft: 8 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { + width: 8, + height: 8, + borderRadius: "50%", + background: statusDot.bg, + display: "inline-block", + boxShadow: ch.running ? `0 0 6px ${statusDot.bg}` : "none" + } + }), + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { fontSize: 11, color: theme.textMuted }, + children: statusDot.label + }) + ] + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: (e) => { + e.stopPropagation(); + setChannels((c) => ({ + ...c, + slack: { ...c.slack, enabled: !c.slack.enabled } + })); + }, + style: { + width: 44, + height: 24, + borderRadius: 12, + border: "none", + cursor: "pointer", + background: ch.enabled ? theme.accent : theme.border, + position: "relative", + transition: "background 0.2s", + flexShrink: 0 + }, + children: /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { + position: "absolute", + top: 3, + width: 18, + height: 18, + borderRadius: "50%", + background: "#fff", + transition: "left 0.2s", + left: ch.enabled ? 23 : 3 + } + }) + }) + ] + }), + !collapsed && /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { padding: "0 16px 16px" }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { marginBottom: 12 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Bot Token" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + type: "password", + value: ch.bot_token, + onChange: (e) => setChannels((c) => ({ + ...c, + slack: { ...c.slack, bot_token: e.target.value } + })), + placeholder: "xoxb-...", + style: fieldStyle + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: hintStyle, + children: "Bot token from OAuth & Permissions" + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { marginBottom: 12 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "App Token" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + type: "password", + value: ch.app_token, + onChange: (e) => setChannels((c) => ({ + ...c, + slack: { ...c.slack, app_token: e.target.value } + })), + placeholder: "xapp-...", + style: fieldStyle + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: hintStyle, + children: "App-level token for Socket Mode" + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { marginBottom: 12 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Default Working Directory" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + value: ch.default_working_dir, + onChange: (e) => setChannels((c) => ({ + ...c, + slack: { ...c.slack, default_working_dir: e.target.value } + })), + placeholder: "~/my-project", + style: fieldStyle + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: hintStyle, + children: "Working directory for tasks created via the Slack bot." + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { marginBottom: 12 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Default DM User" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + value: ch.default_user, + onChange: (e) => setChannels((c) => ({ + ...c, + slack: { ...c.slack, default_user: e.target.value } + })), + placeholder: "U0123456789", + style: fieldStyle + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: hintStyle, + children: "Slack user ID to DM when tasks have no origin thread (e.g. subtasks created via API). Find your ID in Slack profile → ⋯ → Copy member ID." + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { marginBottom: 12 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Default Notification Channel" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + value: ch.default_channel, + onChange: (e) => setChannels((c) => ({ + ...c, + slack: { ...c.slack, default_channel: e.target.value } + })), + placeholder: "#general or C0123456789", + style: fieldStyle + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: hintStyle, + children: "Optional. Fallback channel if Default DM User is not set." + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + background: theme.surface, + border: `1px solid ${theme.border}`, + borderRadius: 6, + padding: "10px 12px", + fontSize: 11, + fontFamily: "monospace", + color: theme.textMuted, + lineHeight: 1.8 + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { color: theme.textDim, marginBottom: 4 }, + children: "Bot commands:" + }), + [ + "newtask <title> | <prompt>", + "list", + "status <id>", + "cancel <id>", + "help" + ].map((cmd) => /* @__PURE__ */ jsx_runtime.jsx("div", { + children: /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { color: theme.cyan }, + children: cmd + }) + }, cmd)) + ] + }) + ] + }) + ] + }); + })(), + (() => { + const ch = channels.weixin; + const collapsed = collapsedChannels.weixin; + const statusLabelMap = { + idle: "Idle", + waiting_for_scan: "Waiting for scan", + scanned: "Scanned on phone", + connected: "Connected", + error: "Error" + }; + const statusDot = ch.running ? { bg: theme.green, label: statusLabelMap[ch.login_status] || "Connected" } : ch.login_status === "waiting_for_scan" || ch.login_status === "scanned" ? { bg: theme.orange || "#f59e0b", label: statusLabelMap[ch.login_status] } : ch.login_status === "error" ? { bg: theme.red, label: "Error" } : ch.configured ? { bg: theme.yellow || "#f59e0b", label: "Configured" } : { bg: theme.textDim, label: "Login required" }; + return /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + marginBottom: 16, + borderRadius: 10, + border: `1px solid ${theme.border}`, + background: theme.bg, + overflow: "hidden" + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + display: "flex", + alignItems: "center", + justifyContent: "space-between", + padding: "12px 16px", + cursor: "pointer", + userSelect: "none" + }, + onClick: () => setCollapsedChannels((c) => ({ ...c, weixin: !c.weixin })), + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", alignItems: "center", gap: 10 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { + fontSize: 10, + color: theme.textMuted, + transition: "transform 0.2s", + transform: collapsed ? "rotate(-90deg)" : "rotate(0deg)", + display: "inline-block" + }, + children: "▼" + }), + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { + display: "inline-flex", + width: 22, + height: 22, + alignItems: "center", + justifyContent: "center", + color: "#07C160", + flexShrink: 0 + }, + children: /* @__PURE__ */ jsx_runtime.jsxs("svg", { + viewBox: "0 0 24 24", + width: "22", + height: "22", + "aria-hidden": "true", + fill: "currentColor", + children: [ + /* @__PURE__ */ jsx_runtime.jsx("path", { + d: "M9.2 4.2c-4 0-7.2 2.6-7.2 5.9 0 1.9 1.1 3.6 2.9 4.7l-.9 2.5 2.9-1.5c.7.1 1.4.2 2.2.2 4 0 7.2-2.6 7.2-5.9S13.2 4.2 9.2 4.2Zm-2.7 4.8a.9.9 0 1 1 0-1.8.9.9 0 0 1 0 1.8Zm5.4 0a.9.9 0 1 1 0-1.8.9.9 0 0 1 0 1.8Z" + }), + /* @__PURE__ */ jsx_runtime.jsx("path", { + d: "M16.8 9.1c-3 0-5.5 2-5.5 4.5 0 2.5 2.4 4.5 5.5 4.5.6 0 1.2-.1 1.8-.2l2.4 1.2-.7-2c1.5-.8 2.5-2.1 2.5-3.6 0-2.5-2.4-4.4-5.5-4.4Zm-1.9 4a.7.7 0 1 1 0-1.4.7.7 0 0 1 0 1.4Zm3.8 0a.7.7 0 1 1 0-1.4.7.7 0 0 1 0 1.4Z", + opacity: "0.88" + }) + ] + }) + }), + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { fontWeight: 700, fontSize: 14, color: theme.text }, + children: "Wechat" + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", alignItems: "center", gap: 6, marginLeft: 8 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { + width: 8, + height: 8, + borderRadius: "50%", + background: statusDot.bg, + display: "inline-block", + boxShadow: ch.running ? `0 0 6px ${statusDot.bg}` : "none" + } + }), + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { fontSize: 11, color: theme.textMuted }, + children: statusDot.label + }) + ] + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: (e) => { + e.stopPropagation(); + setChannels((c) => ({ + ...c, + weixin: { ...c.weixin, enabled: !c.weixin.enabled } + })); + }, + style: { + width: 44, + height: 24, + borderRadius: 12, + border: "none", + cursor: "pointer", + background: ch.enabled ? theme.accent : theme.border, + position: "relative", + transition: "background 0.2s", + flexShrink: 0 + }, + children: /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { + position: "absolute", + top: 3, + width: 18, + height: 18, + borderRadius: "50%", + background: "#fff", + transition: "left 0.2s", + left: ch.enabled ? 23 : 3 + } + }) + }) + ] + }), + !collapsed && /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { padding: "0 16px 16px" }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { marginBottom: 12 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Default Working Directory" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + value: ch.default_working_dir, + onChange: (e) => setChannels((c) => ({ + ...c, + weixin: { ...c.weixin, default_working_dir: e.target.value } + })), + placeholder: "~/my-project", + style: fieldStyle + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: hintStyle, + children: "Working directory for tasks created from incoming Weixin messages." + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { marginBottom: 12 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Base URL" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + value: ch.base_url, + onChange: (e) => setChannels((c) => ({ + ...c, + weixin: { ...c.weixin, base_url: e.target.value } + })), + placeholder: "https://ilinkai.weixin.qq.com", + style: fieldStyle + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: hintStyle, + children: "Gateway API base URL used for QR login, long-polling, and sendmessage." + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { marginBottom: 12 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Account ID" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + value: ch.account_id, + onChange: (e) => setChannels((c) => ({ + ...c, + weixin: { ...c.weixin, account_id: e.target.value } + })), + placeholder: "Optional fixed account id", + style: fieldStyle + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: hintStyle, + children: "Optional. Leave empty to let the bridge adopt the account id returned by QR login." + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", gap: 8, marginBottom: 12 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: () => handleWeixinAction("reconnect"), + disabled: weixinActionBusy, + style: { + padding: "9px 14px", + borderRadius: 8, + border: `1px solid ${theme.border}`, + background: theme.surface, + color: theme.text, + cursor: weixinActionBusy ? "not-allowed" : "pointer", + fontSize: 12, + fontWeight: 600, + opacity: weixinActionBusy ? 0.6 : 1 + }, + children: "Reconnect" + }), + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: () => handleWeixinAction("logout"), + disabled: weixinActionBusy, + style: { + padding: "9px 14px", + borderRadius: 8, + border: `1px solid ${theme.red}`, + background: theme.redBg, + color: theme.red, + cursor: weixinActionBusy ? "not-allowed" : "pointer", + fontSize: 12, + fontWeight: 600, + opacity: weixinActionBusy ? 0.6 : 1 + }, + children: "Logout" + }) + ] + }), + (ch.qr_code_url || ch.login_status === "waiting_for_scan" || ch.login_status === "scanned" || ch.last_error) && /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + marginBottom: 12, + borderRadius: 8, + border: `1px solid ${theme.border}`, + background: theme.surface, + padding: 12 + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + fontSize: 12, + fontWeight: 700, + color: theme.text, + marginBottom: 8 + }, + children: "Weixin Login Status" + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + fontSize: 11, + color: theme.textMuted, + marginBottom: ch.qr_code_url ? 10 : 0 + }, + children: [ + statusLabelMap[ch.login_status] || "Idle", + ch.user_id ? ` · ${ch.user_id}` : "" + ] + }), + ch.account_id && /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { fontSize: 11, color: theme.textMuted, marginBottom: 10 }, + children: [ + "Account ID: ", + ch.account_id + ] + }), + weixinQrSrc && /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", flexDirection: "column", gap: 8 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("img", { + src: weixinQrSrc, + alt: "Weixin QR code", + style: { + width: 220, + height: 220, + objectFit: "contain", + borderRadius: 10, + border: `1px solid ${theme.border}`, + background: "#fff" + } + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: hintStyle, + children: "Open Weixin on your phone and scan this QR code. The status updates automatically." + }) + ] + }), + ch.last_error && /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { marginTop: 10, fontSize: 11, color: theme.red }, + children: ch.last_error + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + background: theme.surface, + border: `1px solid ${theme.border}`, + borderRadius: 6, + padding: "10px 12px", + fontSize: 11, + fontFamily: "monospace", + color: theme.textMuted, + lineHeight: 1.8 + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { color: theme.textDim, marginBottom: 4 }, + children: "Notes:" + }), + [ + "Enabling Weixin starts the local bridge process", + "First launch without a saved session will trigger QR login", + "Reply to a result message to resume the same task session" + ].map((note) => /* @__PURE__ */ jsx_runtime.jsx("div", { + children: /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { color: theme.cyan }, + children: note + }) + }, note)) + ] + }) + ] + }) + ] + }); + })(), + channelsMsg && /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + padding: "8px 12px", + borderRadius: 8, + marginBottom: 16, + fontSize: 12, + background: channelsMsg.ok ? theme.greenBg : theme.redBg, + color: channelsMsg.ok ? theme.green : theme.red, + border: `1px solid ${channelsMsg.ok ? theme.green : theme.red}` + }, + children: channelsMsg.text + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", gap: 10, justifyContent: "flex-end" }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: onClose, + style: { + padding: "10px 20px", + borderRadius: 8, + border: `1px solid ${theme.border}`, + background: "transparent", + color: theme.textMuted, + cursor: "pointer", + fontSize: 13, + fontWeight: 600 + }, + children: "Close" + }), + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: handleSaveChannels, + disabled: channelsSaving, + style: { + padding: "10px 24px", + borderRadius: 8, + border: "none", + background: channelsSaving ? theme.border : theme.accent, + color: channelsSaving ? theme.textMuted : "#fff", + cursor: channelsSaving ? "not-allowed" : "pointer", + fontSize: 13, + fontWeight: 600, + boxShadow: channelsSaving ? "none" : `0 0 20px ${theme.accentGlow}` + }, + children: channelsSaving ? "Saving…" : "Save" + }) + ] + }) + ] + }), + tab === "feishu" && /* @__PURE__ */ jsx_runtime.jsxs(jsx_runtime.Fragment, { + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + marginBottom: 20, + display: "flex", + alignItems: "center", + justifyContent: "space-between" + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 13, fontWeight: 600, color: theme.text }, + children: "Enable Feishu Bot" + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 11, color: theme.textMuted, marginTop: 2 }, + children: "WebSocket long-connection, no public IP required" + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: () => setFeishu((f) => ({ + ...f, + feishu_enabled: f.feishu_enabled === "true" ? "false" : "true" + })), + style: { + width: 44, + height: 24, + borderRadius: 12, + border: "none", + cursor: "pointer", + background: feishu.feishu_enabled === "true" ? theme.accent : theme.border, + position: "relative", + transition: "background 0.2s", + flexShrink: 0 + }, + children: /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { + position: "absolute", + top: 3, + width: 18, + height: 18, + borderRadius: "50%", + background: "#fff", + transition: "left 0.2s", + left: feishu.feishu_enabled === "true" ? 23 : 3 + } + }) + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", flexDirection: "column", gap: 16, marginBottom: 20 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "App ID" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + value: feishu.feishu_app_id, + onChange: (e) => setFeishu((f) => ({ ...f, feishu_app_id: e.target.value })), + placeholder: "cli_xxxxxxxxxxxxxxxx", + style: fieldStyle + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "App Secret" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + type: "password", + value: feishu.feishu_app_secret, + onChange: (e) => setFeishu((f) => ({ ...f, feishu_app_secret: e.target.value })), + placeholder: "••••••••••••••••", + style: fieldStyle + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Default Chat ID" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + value: feishu.feishu_default_chat_id, + onChange: (e) => setFeishu((f) => ({ ...f, feishu_default_chat_id: e.target.value })), + placeholder: "oc_xxxxxxxx (group) or ou_xxxxxxxx (DM)", + style: fieldStyle + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: hintStyle, + children: "Task completion notifications will be sent here." + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("label", { + style: labelStyle, + children: "Default Working Directory" + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + value: feishu.feishu_default_working_dir, + onChange: (e) => setFeishu((f) => ({ ...f, feishu_default_working_dir: e.target.value })), + placeholder: "~/my-project", + style: fieldStyle + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: hintStyle, + children: "Working directory for tasks created via the bot." + }) + ] + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + background: theme.bg, + border: `1px solid ${theme.border}`, + borderRadius: 8, + padding: "12px 14px", + marginBottom: 20, + fontSize: 11, + fontFamily: "monospace", + color: theme.textMuted, + lineHeight: 1.8 + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { color: theme.textDim, marginBottom: 6, fontFamily: "inherit" }, + children: "Bot commands:" + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { color: theme.cyan }, + children: "<any text>" + }), + " — create a new task" + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { color: theme.cyan }, + children: "/resume <id> <msg>" + }), + " — resume a task session" + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { color: theme.cyan }, + children: "/status <id>" + }), + " — query task status" + ] + }) + ] + }), + feishuMsg && /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + padding: "8px 12px", + borderRadius: 8, + marginBottom: 16, + fontSize: 12, + background: feishuMsg.ok ? theme.greenBg : theme.redBg, + color: feishuMsg.ok ? theme.green : theme.red, + border: `1px solid ${feishuMsg.ok ? theme.green : theme.red}` + }, + children: feishuMsg.text + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", gap: 10, justifyContent: "flex-end" }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: onClose, + style: { + padding: "10px 20px", + borderRadius: 8, + border: `1px solid ${theme.border}`, + background: "transparent", + color: theme.textMuted, + cursor: "pointer", + fontSize: 13, + fontWeight: 600 + }, + children: "Close" + }), + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: handleSaveFeishu, + disabled: feishuSaving, + style: { + padding: "10px 24px", + borderRadius: 8, + border: "none", + background: feishuSaving ? theme.border : theme.accent, + color: feishuSaving ? theme.textMuted : "#fff", + cursor: feishuSaving ? "not-allowed" : "pointer", + fontSize: 13, + fontWeight: 600, + boxShadow: feishuSaving ? "none" : `0 0 20px ${theme.accentGlow}` + }, + children: feishuSaving ? "Saving…" : "Save & Apply" + }) + ] + }) + ] + }) + ] + }) + }); +} +function parseSkillFrontmatter(body) { + const m = (body || "").match(/^---\s*\n([\s\S]*?)\n---/); + if (!m) + return { name: "", description: "" }; + const out = { name: "", description: "" }; + for (const line of m[1].split(` +`)) { + const i = line.indexOf(":"); + if (i === -1) + continue; + const k = line.slice(0, i).trim().toLowerCase(); + const v = line.slice(i + 1).trim(); + if (k === "name" && !out.name) + out.name = v; + if (k === "description" && !out.description) + out.description = v; + } + return out; +} +function SkillKindBadge({ kind }) { + const isPitfall = kind === "pitfall"; + return /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { + fontSize: 10, + fontWeight: 700, + padding: "2px 7px", + borderRadius: 6, + letterSpacing: 0.4, + background: isPitfall ? "rgba(239,68,68,0.15)" : "rgba(34,197,94,0.15)", + color: isPitfall ? theme.red : theme.green + }, + children: isPitfall ? "PITFALL" : "RECIPE" + }); +} +function SkillPatternCard({ p, tasks, onDraft, onApprove, onDismiss }) { + let taskIds = []; + try { + taskIds = JSON.parse(p.contributing_task_ids || "[]"); + } catch {} + const taskCount = taskIds.length; + const ready = p.recurrence_count >= 3 && taskCount >= 2; + const draftStatus = p.draft_status; + const [expanded, setExpanded] = import_react.useState(false); + const [body, setBody] = import_react.useState(p.draft_body || ""); + import_react.useEffect(() => { + if (draftStatus === "ready") + setBody(p.draft_body || ""); + }, [draftStatus, p.draft_body]); + const borderColor = p.status === "promoted" ? theme.green : p.status === "candidate" ? theme.accent : theme.border; + const muted = p.status === "dismissed"; + const btn = (bg, color) => ({ + padding: "6px 14px", + borderRadius: 7, + border: bg === "transparent" ? `1px solid ${theme.border}` : "none", + background: bg, + color, + cursor: "pointer", + fontSize: 11, + fontWeight: 700 + }); + return /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + background: theme.surface, + border: `1px solid ${borderColor}`, + borderRadius: 12, + padding: 16, + opacity: muted ? 0.5 : 1 + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", alignItems: "center", gap: 8, marginBottom: 8 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx(SkillKindBadge, { + kind: p.kind + }), + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { fontFamily: "monospace", fontSize: 12, color: theme.text, fontWeight: 700 }, + children: p.pattern_key + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { color: theme.textMuted, fontSize: 13, marginBottom: 10 }, + children: p.summary || "—" + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + display: "flex", + gap: 12, + fontSize: 11, + color: theme.textDim, + marginBottom: 10, + alignItems: "center" + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("span", { + children: [ + "复发 ", + p.recurrence_count, + "×" + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("span", { + children: [ + taskCount, + " 个任务" + ] + }), + /* @__PURE__ */ jsx_runtime.jsx("span", { + children: p.status + }), + ready && p.status !== "promoted" && /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { color: theme.accent, fontWeight: 700 }, + children: "✓ 达标" + }), + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: () => setExpanded((v) => !v), + style: { + marginLeft: "auto", + background: "transparent", + border: "none", + color: theme.accent, + cursor: "pointer", + fontSize: 11, + fontWeight: 700 + }, + children: expanded ? "收起 ▲" : "详情 ▼" + }) + ] + }), + expanded && /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + background: theme.bg, + border: `1px solid ${theme.border}`, + borderRadius: 8, + padding: 10, + marginBottom: 10, + fontSize: 11, + color: theme.textMuted + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { marginBottom: 6 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { color: theme.textDim }, + children: "首次 " + }), + (p.first_seen || "").replace("T", " ").slice(0, 19) || "—", + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { color: theme.textDim }, + children: " 最近 " + }), + (p.last_seen || "").replace("T", " ").slice(0, 19) || "—" + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { color: theme.textDim, marginBottom: 4 }, + children: [ + "贡献的任务(", + taskCount, + "):" + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", flexDirection: "column", gap: 3 }, + children: [ + taskIds.length === 0 && /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { color: theme.textDim }, + children: "—" + }), + taskIds.map((tid) => { + const t = (tasks || []).find((x) => x.id === tid); + return /* @__PURE__ */ jsx_runtime.jsxs("span", { + style: { fontFamily: "monospace" }, + children: [ + "#", + tid, + " ", + t ? t.title : /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { color: theme.textDim }, + children: "(已删除)" + }) + ] + }, tid); + }) + ] + }) + ] + }), + draftStatus === "ready" && p.draft_worthy !== null && p.draft_worthy !== undefined && /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + fontSize: 11, + padding: "7px 10px", + borderRadius: 7, + marginBottom: 8, + background: p.draft_worthy ? "rgba(34,197,94,0.12)" : "rgba(245,158,11,0.14)", + color: p.draft_worthy ? theme.green : "#f59e0b", + border: `1px solid ${p.draft_worthy ? "rgba(34,197,94,0.3)" : "rgba(245,158,11,0.35)"}` + }, + children: [ + p.draft_worthy ? "✓ agent 建议沉淀" : "⚠ agent 认为价值有限(可仍批准或驳回)", + p.draft_worthiness_reason ? `:${p.draft_worthiness_reason}` : "" + ] + }), + p.status === "promoted" && /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 12, color: theme.green, fontWeight: 700 }, + children: "✓ 已沉淀为 Skill" + }), + (p.status === "candidate" || p.status === "tracking") && draftStatus !== "ready" && draftStatus !== "drafting" && /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap" }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: () => onDraft(p.id), + style: btn(theme.accent, "#fff"), + children: draftStatus === "error" ? "重试蒸馏" : "蒸馏成 Skill" + }), + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: () => onDismiss(p.id), + style: btn("transparent", theme.textMuted), + children: "驳回" + }), + p.status === "tracking" && /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { color: theme.textDim, fontSize: 11 }, + children: "未达自动阈值,可手动蒸馏(agent 会判断是否值得)" + }), + draftStatus === "error" && /* @__PURE__ */ jsx_runtime.jsxs("span", { + style: { color: theme.red, fontSize: 11 }, + children: [ + "蒸馏失败:", + p.draft_error + ] + }) + ] + }), + draftStatus === "drafting" && /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 12, color: theme.textMuted }, + children: "蒸馏中…" + }), + draftStatus === "ready" && (() => { + const fm = parseSkillFrontmatter(body); + return /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", flexDirection: "column", gap: 10 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", alignItems: "baseline", gap: 8, flexWrap: "wrap" }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { + fontFamily: "ui-monospace, Menlo, monospace", + fontSize: 12, + fontWeight: 800, + color: theme.accent, + background: theme.accentGlow, + padding: "3px 9px", + borderRadius: 6 + }, + children: fm.name || "(无 name)" + }), + /* @__PURE__ */ jsx_runtime.jsxs("span", { + style: { fontSize: 11, color: theme.textDim }, + children: [ + "→ ~/.claude/skills/", + fm.name || "…", + "/SKILL.md" + ] + }) + ] + }), + fm.description && /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 12, color: theme.textMuted, lineHeight: 1.55 }, + children: fm.description + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + fontSize: 10.5, + color: theme.textDim, + marginBottom: 5, + fontWeight: 600, + letterSpacing: 0.3 + }, + children: "SKILL.md · 可编辑(frontmatter 决定名称与触发描述)" + }), + /* @__PURE__ */ jsx_runtime.jsx("textarea", { + value: body, + onChange: (e) => setBody(e.target.value), + rows: 16, + spellCheck: false, + style: { + width: "100%", + boxSizing: "border-box", + padding: "12px 14px", + borderRadius: 10, + border: `1px solid ${theme.border}`, + background: theme.bg, + color: theme.text, + fontSize: 12, + fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", + lineHeight: 1.65, + resize: "vertical", + outline: "none" + } + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", gap: 8 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: () => onApprove(p.id, { body }), + style: { ...btn(theme.green, "#fff"), padding: "8px 18px", fontSize: 12 }, + children: "✓ 批准并写入" + }), + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: () => onDismiss(p.id), + style: { + ...btn("transparent", theme.textMuted), + padding: "8px 18px", + fontSize: 12 + }, + children: "驳回" + }) + ] + }) + ] + }); + })() + ] + }); +} +function SkillRegistryCard({ s, tasks, onToggle, onDelete }) { + const [expanded, setExpanded] = import_react.useState(false); + const [content, setContent] = import_react.useState(null); + const [loading, setLoading] = import_react.useState(false); + let sourceTaskIds = []; + try { + sourceTaskIds = JSON.parse(s.source_task_ids || "[]"); + } catch {} + const toggleDetail = async () => { + const next = !expanded; + setExpanded(next); + if (next && content === null) { + setLoading(true); + try { + const res = await fetch(`${API}/skills/${s.id}/content`); + const d = await res.json(); + setContent(d.content ?? ""); + } catch (e) { + setContent(`(加载失败:${e.message})`); + } finally { + setLoading(false); + } + } + }; + return /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + background: theme.surface, + border: `1px solid ${theme.border}`, + borderRadius: 12, + padding: 14, + opacity: s.enabled ? 1 : 0.55 + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", alignItems: "center", gap: 8, marginBottom: 6 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx(SkillKindBadge, { + kind: s.kind + }), + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { fontFamily: "monospace", fontSize: 12, color: theme.text, fontWeight: 700 }, + children: s.name + }), + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: toggleDetail, + style: { + marginLeft: "auto", + background: "transparent", + border: "none", + color: theme.accent, + cursor: "pointer", + fontSize: 11, + fontWeight: 700 + }, + children: expanded ? "收起 ▲" : "查看 SKILL.md ▼" + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { color: theme.textMuted, fontSize: 12, marginBottom: 10, lineHeight: 1.5 }, + children: s.description || "—" + }), + expanded && /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { marginBottom: 10 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { fontSize: 11, color: theme.textDim, marginBottom: 6 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { fontFamily: "monospace" }, + children: s.path + }), + s.source_pattern_key && /* @__PURE__ */ jsx_runtime.jsxs("span", { + children: [ + " 来源 pattern:", + s.source_pattern_key + ] + }), + sourceTaskIds.length > 0 && /* @__PURE__ */ jsx_runtime.jsxs("span", { + children: [ + "来源任务:", + sourceTaskIds.map((tid) => { + const t = (tasks || []).find((x) => x.id === tid); + return `#${tid}${t ? "(" + t.title + ")" : ""}`; + }).join("、") + ] + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsx("pre", { + style: { + margin: 0, + padding: "12px 14px", + borderRadius: 10, + border: `1px solid ${theme.border}`, + background: theme.bg, + color: theme.text, + fontSize: 12, + fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace", + lineHeight: 1.6, + whiteSpace: "pre-wrap", + wordBreak: "break-word", + maxHeight: 360, + overflow: "auto" + }, + children: loading ? "加载中…" : content + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", gap: 8, alignItems: "center" }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("label", { + style: { + display: "flex", + alignItems: "center", + gap: 6, + fontSize: 11, + color: theme.textDim, + cursor: "pointer" + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("input", { + type: "checkbox", + checked: !!s.enabled, + onChange: (e) => onToggle(s.id, e.target.checked), + style: { cursor: "pointer" } + }), + s.enabled ? "已启用(claude/codex 加载中)" : "已停用(symlink 已摘除)" + ] + }), + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: () => onDelete(s.id), + style: { + marginLeft: "auto", + padding: "4px 10px", + borderRadius: 6, + border: `1px solid ${theme.border}`, + background: "transparent", + color: theme.red, + cursor: "pointer", + fontSize: 11, + fontWeight: 700 + }, + children: "删除" + }) + ] + }) + ] + }); +} +function SkillsView({ + skillData, + skills, + tasks, + onSweep, + onDraft, + onApprove, + onDismiss, + onToggleSkill, + onDeleteSkill +}) { + const patterns = (skillData.patterns || []).filter((p) => p.recurrence_count >= 2); + const sweep = skillData.sweep || {}; + const running = sweep.running; + const last = sweep.last; + let lastNote = null; + if (last) { + lastNote = last.error ? `上次扫描失败:${last.error}` : last.scanned === 0 ? `上次扫描:没有已完成的任务可分析(agent ${last.agent})` : `上次扫描:分析 ${last.scanned} 个任务、新增 ${last.new ?? 0} 次复发、候选 ${last.candidates ?? 0}(agent ${last.agent})`; + } + const [showRegistry, setShowRegistry] = import_react.useState(true); + const [showPatterns, setShowPatterns] = import_react.useState(true); + const sectionHeader = (label, count, open, toggle) => /* @__PURE__ */ jsx_runtime.jsxs("button", { + onClick: toggle, + style: { + display: "flex", + alignItems: "center", + gap: 8, + width: "100%", + background: "transparent", + border: "none", + cursor: "pointer", + color: theme.text, + fontSize: 13, + fontWeight: 700, + padding: 0, + marginBottom: 10 + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { color: theme.textDim, fontSize: 11 }, + children: open ? "▼" : "▶" + }), + label, + /* @__PURE__ */ jsx_runtime.jsxs("span", { + style: { color: theme.textDim, fontWeight: 600 }, + children: [ + "(", + count, + ")" + ] + }) + ] + }); + return /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { padding: 28, minHeight: "calc(100vh - 72px)" }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + display: "flex", + alignItems: "center", + justifyContent: "space-between", + marginBottom: 16, + gap: 12 + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { color: theme.textMuted, fontSize: 12 }, + children: [ + "跨任务复发模式账本 · 复发 ≥2 即可手动蒸馏为 Skill(达 ≥3 且跨 ≥2 任务自动标记候选)", + lastNote && /* @__PURE__ */ jsx_runtime.jsxs("span", { + style: { marginLeft: 10, color: theme.textDim }, + children: [ + "· ", + lastNote + ] + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: onSweep, + disabled: running, + style: { + padding: "8px 18px", + borderRadius: 8, + border: "none", + background: running ? theme.border : theme.accent, + color: "#fff", + cursor: running ? "default" : "pointer", + fontSize: 12, + fontWeight: 700, + letterSpacing: 0.3, + whiteSpace: "nowrap", + boxShadow: running ? "none" : `0 0 24px ${theme.accentGlow}` + }, + children: running ? "扫描中…" : "扫一遍" + }) + ] + }), + (skills || []).length > 0 && /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { marginBottom: 26 }, + children: [ + sectionHeader("已沉淀 Skills", skills.length, showRegistry, () => setShowRegistry((v) => !v)), + showRegistry && /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + display: "grid", + gridTemplateColumns: "repeat(auto-fit, minmax(360px, 1fr))", + gap: 12 + }, + children: skills.map((s) => /* @__PURE__ */ jsx_runtime.jsx(SkillRegistryCard, { + s, + tasks, + onToggle: onToggleSkill, + onDelete: onDeleteSkill + }, s.id)) + }) + ] + }), + sectionHeader("检测到的模式", patterns.length, showPatterns, () => setShowPatterns((v) => !v)), + showPatterns && (patterns.length === 0 ? /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + border: `1px dashed ${theme.border}`, + borderRadius: 12, + padding: 32, + textAlign: "center", + color: theme.textDim, + fontSize: 12 + }, + children: "还没有复发 ≥2 的模式 — 点「扫一遍」让 agent 分析最近完成的任务(复发 1 次的暂不展示)" + }) : /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + display: "grid", + gridTemplateColumns: "repeat(auto-fit, minmax(360px, 1fr))", + gap: 14 + }, + children: patterns.map((p) => /* @__PURE__ */ jsx_runtime.jsx(SkillPatternCard, { + p, + tasks, + onDraft, + onApprove, + onDismiss + }, p.id)) + })) + ] + }); +} +function App() { + const [tasks, setTasks] = import_react.useState([]); + const [heartbeats, setHeartbeats] = import_react.useState([]); + const [heartbeatTicks, setHeartbeatTicks] = import_react.useState([]); + const [skillData, setSkillData] = import_react.useState({ + patterns: [], + sweep: { running: false, last: null } + }); + const [skills, setSkills] = import_react.useState([]); + const [activeView, setActiveView] = import_react.useState("tasks"); + const [showNew, setShowNew] = import_react.useState(false); + const [showNewHeartbeat, setShowNewHeartbeat] = import_react.useState(false); + const [showSettings, setShowSettings] = import_react.useState(false); + const [detail, setDetail] = import_react.useState(null); + const [heartbeatDetail, setHeartbeatDetail] = import_react.useState(null); + const [connected, setConnected] = import_react.useState(false); + const [filter, setFilter] = import_react.useState(""); + const [taskTimeout, setTaskTimeout] = import_react.useState(DEFAULT_TIMEOUT_SECONDS); + const [defaultAgent, setDefaultAgent] = import_react.useState(DEFAULT_AGENT); + const [feishuSettings, setFeishuSettings] = import_react.useState({}); + const [channelsStatus, setChannelsStatus] = import_react.useState({}); + const [backendReady, setBackendReady] = import_react.useState(false); + const [backendError, setBackendError] = import_react.useState(null); + const [apiError, setApiError] = import_react.useState(null); + const [editingTask, setEditingTask] = import_react.useState(null); + const [forkingTask, setForkingTask] = import_react.useState(null); + const [editingHeartbeat, setEditingHeartbeat] = import_react.useState(null); + const [colorMode, setColorMode] = import_react.useState(() => localStorage.getItem("colorMode") || "system"); + const [systemDark, setSystemDark] = import_react.useState(() => window.matchMedia("(prefers-color-scheme: dark)").matches); + const resolvedMode = colorMode === "system" ? systemDark ? "dark" : "light" : colorMode; + theme = THEMES[resolvedMode]; + import_react.useEffect(() => { + localStorage.setItem("colorMode", colorMode); + document.body.style.background = THEMES[resolvedMode].bg; + }, [colorMode, resolvedMode]); + import_react.useEffect(() => { + const mq = window.matchMedia("(prefers-color-scheme: dark)"); + const handler = (e) => setSystemDark(e.matches); + mq.addEventListener("change", handler); + return () => mq.removeEventListener("change", handler); + }, []); + import_react.useEffect(() => { + let cancelled = false; + const deadline = Date.now() + 20000; + const probe = async () => { + try { + const res = await fetch(`${API}/health`, { signal: AbortSignal.timeout(800) }); + if (res.ok) { + if (!cancelled) + setBackendReady(true); + return; + } + } catch {} + if (cancelled) + return; + if (Date.now() >= deadline) { + setBackendError("Backend did not start within 20 seconds."); + return; + } + setTimeout(probe, 300); + }; + probe(); + return () => { + cancelled = true; + }; + }, []); + const poll = import_react.useCallback(async () => { + try { + const [taskData, heartbeatData, skillRes, skillsRes] = await Promise.all([ + fetchTasks(), + fetchHeartbeats(), + fetchSkillPatterns(), + fetchSkills() + ]); + setTasks(taskData); + setHeartbeats(heartbeatData); + setSkillData(skillRes); + setSkills(skillsRes.skills || []); + setConnected(true); + setApiError(null); + } catch (err) { + setConnected(false); + setApiError(`Failed to fetch tasks: ${err.message}`); + } + }, []); + import_react.useEffect(() => { + if (!backendReady) + return; + poll(); + const interval = setInterval(poll, 3000); + return () => clearInterval(interval); + }, [poll, backendReady]); + import_react.useEffect(() => { + if (!backendReady) + return; + fetchSettings().then((s) => { + if (s.timeout) + setTaskTimeout(s.timeout); + if (s.default_agent) + setDefaultAgent(s.default_agent); + }); + fetchFeishuSettings().then((s) => setFeishuSettings(s)); + fetchChannelsStatus().then((s) => setChannelsStatus(s)); + }, [backendReady]); + const handleAction = async (action, id) => { + try { + if (action === "cancel") + await cancelTask(id); + else if (action === "retry") + await retryTask(id); + else if (action === "delete") { + await deleteTask(id); + if (detail?.id === id) + setDetail(null); + } else if (action === "edit") { + const task = tasks.find((t) => t.id === id); + if (task) + setEditingTask(task); + return; + } else if (action === "fork") { + const task = tasks.find((t) => t.id === id); + if (task) + setForkingTask(task); + return; + } + poll(); + } catch (e) { + setApiError(`${action} failed: ${e.message}`); + } + }; + const handleHeartbeatAction = async (action, id) => { + try { + if (action === "run") { + await runHeartbeatNow(id); + } else if (action === "pause") { + await pauseHeartbeat(id); + } else if (action === "resume") { + await resumeHeartbeatApi(id); + } else if (action === "delete") { + await deleteHeartbeat(id); + if (heartbeatDetail?.id === id) { + setHeartbeatDetail(null); + setHeartbeatTicks([]); + } + } else if (action === "edit") { + const heartbeat = heartbeats.find((h) => h.id === id); + if (heartbeat) + setEditingHeartbeat(heartbeat); + return; + } + poll(); + if (heartbeatDetail?.id === id && action !== "delete") { + const [updatedHeartbeat, ticks] = await Promise.all([ + fetch(`${API}/heartbeats/${id}`).then((r) => r.json()), + fetchHeartbeatTicks(id) + ]); + setHeartbeatDetail(updatedHeartbeat); + setHeartbeatTicks(ticks); + } + } catch (e) { + setApiError(`Heartbeat ${action} failed: ${e.message}`); + } + }; + const handleSweep = async () => { + try { + await triggerSkillSweep(); + setSkillData((prev) => ({ ...prev, sweep: { ...prev.sweep, running: true } })); + setTimeout(poll, 1500); + } catch (e) { + setApiError(`Sweep failed: ${e.message}`); + } + }; + const handleSkillDraft = async (id) => { + try { + await triggerSkillDraft(id); + setTimeout(poll, 1500); + } catch (e) { + setApiError(`Distill failed: ${e.message}`); + } + }; + const handleSkillApprove = async (id, data) => { + try { + await approveSkill(id, data); + poll(); + } catch (e) { + setApiError(`Approve failed: ${e.message}`); + } + }; + const handleSkillDismiss = async (id) => { + try { + await dismissSkillPattern(id); + poll(); + } catch (e) { + setApiError(`Dismiss failed: ${e.message}`); + } + }; + const handleSkillToggle = async (id, enabled) => { + try { + await setSkillEnabledApi(id, enabled); + poll(); + } catch (e) { + setApiError(`Toggle skill failed: ${e.message}`); + } + }; + const handleSkillDelete = async (id) => { + try { + await deleteSkillApi(id); + poll(); + } catch (e) { + setApiError(`Delete skill failed: ${e.message}`); + } + }; + const handleCreate = async (data) => { + try { + await createTask(data); + setShowNew(false); + poll(); + } catch (e) { + setApiError(`Create task failed: ${e.message}`); + } + }; + const handleEdit = async (data) => { + try { + await updateTask(editingTask.id, data); + setEditingTask(null); + poll(); + } catch (e) { + setApiError(`Edit task failed: ${e.message}`); + } + }; + const handleFork = async (data) => { + try { + await createTask(data); + setForkingTask(null); + poll(); + } catch (e) { + setApiError(`Fork task failed: ${e.message}`); + } + }; + const handleRespond = async (id, answer) => { + try { + await respondToTask(id, answer); + poll(); + } catch (e) { + setApiError(`Respond failed: ${e.message}`); + } + }; + const handleResume = () => { + poll(); + }; + const handleCreateHeartbeat = async (data) => { + try { + await createHeartbeat(data); + setShowNewHeartbeat(false); + poll(); + } catch (e) { + setApiError(`Create heartbeat failed: ${e.message}`); + } + }; + const handleEditHeartbeat = async (data) => { + try { + await updateHeartbeat(editingHeartbeat.id, data); + setEditingHeartbeat(null); + poll(); + } catch (e) { + setApiError(`Edit heartbeat failed: ${e.message}`); + } + }; + const openHeartbeatDetail = async (heartbeat) => { + setHeartbeatDetail(heartbeat); + try { + const ticks = await fetchHeartbeatTicks(heartbeat.id); + setHeartbeatTicks(ticks); + } catch (e) { + setApiError(`Failed to fetch heartbeat ticks: ${e.message}`); + setHeartbeatTicks([]); + } + }; + const filtered = filter ? tasks.filter((t) => t.title.toLowerCase().includes(filter.toLowerCase()) || t.tags?.toLowerCase().includes(filter.toLowerCase())) : tasks; + const runningCount = tasks.filter((t) => t.status === "running").length; + const scheduledCount = tasks.filter((t) => t.status === "scheduled").length; + const enabledHeartbeatCount = heartbeats.filter((h) => h.enabled).length; + if (backendError) { + return /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + display: "flex", + flexDirection: "column", + alignItems: "center", + justifyContent: "center", + height: "100vh", + background: theme.bg, + color: theme.red, + gap: 12, + fontFamily: "inherit" + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 32 }, + children: "✕" + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 15, fontWeight: 600 }, + children: "Backend failed to start" + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 12, color: theme.textMuted, maxWidth: 400, textAlign: "center" }, + children: backendError + }) + ] + }); + } + if (!backendReady) { + return /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + display: "flex", + flexDirection: "column", + alignItems: "center", + justifyContent: "center", + height: "100vh", + background: theme.bg, + color: theme.textMuted, + gap: 16, + fontFamily: "inherit" + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + width: 32, + height: 32, + borderRadius: "50%", + border: `3px solid ${theme.border}`, + borderTopColor: theme.accent, + animation: "spin 0.8s linear infinite" + } + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 13 }, + children: "Starting backend…" + }), + /* @__PURE__ */ jsx_runtime.jsx("style", { + children: `@keyframes spin { to { transform: rotate(360deg); } }` + }) + ] + }); + } + return /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + minHeight: "100vh", + background: theme.bg, + color: theme.text, + fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif" + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("style", { + children: `@keyframes pulse { 0%,100%{opacity:1} 50%{opacity:0.3} }` + }), + apiError && /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + position: "fixed", + bottom: 24, + left: "50%", + transform: "translateX(-50%)", + zIndex: 9999, + display: "flex", + alignItems: "center", + gap: 10, + background: theme.surface, + border: `1px solid ${theme.red}`, + borderRadius: 8, + padding: "10px 16px", + boxShadow: `0 4px 24px rgba(0,0,0,0.5)`, + color: theme.red, + fontSize: 12, + fontWeight: 500, + maxWidth: 480 + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { flexShrink: 0 }, + children: "✕" + }), + /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { flex: 1 }, + children: apiError + }), + /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: () => setApiError(null), + style: { + background: "none", + border: "none", + color: theme.textMuted, + cursor: "pointer", + fontSize: 14, + lineHeight: 1, + padding: "0 0 0 8px", + flexShrink: 0 + }, + title: "Dismiss", + children: "×" + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + borderBottom: `1px solid ${theme.border}`, + padding: "16px 28px", + display: "flex", + alignItems: "center", + justifyContent: "space-between", + backdropFilter: "blur(10px)", + position: "sticky", + top: 0, + zIndex: 100, + background: `${theme.bg}ee` + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", alignItems: "center", gap: 14 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + width: 32, + height: 32, + borderRadius: 8, + background: `linear-gradient(135deg, ${theme.accent}, #a855f7)`, + display: "flex", + alignItems: "center", + justifyContent: "center", + fontSize: 16, + fontWeight: 800, + color: "#fff" + }, + children: "⌘" + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + fontSize: 15, + fontWeight: 700, + fontFamily: "'JetBrains Mono', monospace", + letterSpacing: -0.3 + }, + children: "AgentForge" + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { fontSize: 11, color: theme.textDim, marginTop: 1 }, + children: [ + connected ? /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { color: theme.green }, + children: "● Connected" + }) : /* @__PURE__ */ jsx_runtime.jsx("span", { + style: { color: theme.red }, + children: "● Disconnected — run `python taskboard.py`" + }), + connected && ` · ${runningCount} running · ${scheduledCount} scheduled · ${enabledHeartbeatCount} heartbeats` + ] + }) + ] + }) + ] + }), + /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { display: "flex", alignItems: "center", gap: 10 }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + display: "flex", + background: theme.surface, + border: `1px solid ${theme.border}`, + borderRadius: 10, + padding: 4, + gap: 4 + }, + children: [ + { key: "tasks", label: "Tasks" }, + { key: "heartbeats", label: "Heartbeats" }, + { key: "skills", label: "Skills" } + ].map((tab) => /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: () => setActiveView(tab.key), + style: { + padding: "6px 10px", + borderRadius: 8, + border: "none", + background: activeView === tab.key ? theme.accentGlow : "transparent", + color: activeView === tab.key ? theme.accent : theme.textMuted, + cursor: "pointer", + fontSize: 12, + fontWeight: 700 + }, + children: tab.label + }, tab.key)) + }), + /* @__PURE__ */ jsx_runtime.jsx("input", { + placeholder: activeView === "tasks" ? "Filter tasks..." : "Filter heartbeats...", + value: filter, + onChange: (e) => setFilter(e.target.value), + style: { + padding: "8px 14px", + borderRadius: 8, + border: `1px solid ${theme.border}`, + background: theme.surface, + color: theme.text, + fontSize: 12, + outline: "none", + width: 180 + } + }), + (() => { + const cycle = { system: "light", light: "dark", dark: "system" }; + const icons = { system: "⊙", light: "☀", dark: "☾" }; + const labels = { system: "System theme", light: "Light mode", dark: "Dark mode" }; + return /* @__PURE__ */ jsx_runtime.jsx(Tooltip, { + text: labels[colorMode], + children: /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: () => setColorMode(cycle[colorMode]), + style: { + padding: "8px 10px", + borderRadius: 8, + border: `1px solid ${theme.border}`, + background: "transparent", + color: theme.textMuted, + cursor: "pointer", + fontSize: 15, + display: "flex", + alignItems: "center", + transition: "all 0.15s" + }, + children: icons[colorMode] + }) + }); + })(), + /* @__PURE__ */ jsx_runtime.jsx(Tooltip, { + text: "Settings", + children: /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: () => setShowSettings(true), + style: { + padding: "8px 12px", + borderRadius: 8, + border: `1px solid ${theme.border}`, + background: "transparent", + color: theme.textMuted, + cursor: "pointer", + fontSize: 15, + display: "flex", + alignItems: "center", + transition: "all 0.15s" + }, + children: "⚙" + }) + }), + activeView !== "skills" && /* @__PURE__ */ jsx_runtime.jsx("button", { + onClick: () => activeView === "tasks" ? setShowNew(true) : setShowNewHeartbeat(true), + style: { + padding: "8px 18px", + borderRadius: 8, + border: "none", + background: theme.accent, + color: "#fff", + cursor: "pointer", + fontSize: 12, + fontWeight: 700, + letterSpacing: 0.3, + display: "flex", + alignItems: "center", + gap: 6, + boxShadow: `0 0 24px ${theme.accentGlow}`, + transition: "transform 0.15s" + }, + children: activeView === "tasks" ? "+ New Task" : "+ New Heartbeat" + }) + ] + }) + ] + }), + activeView === "tasks" ? /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + display: "flex", + gap: 20, + padding: 28, + minHeight: "calc(100vh - 72px)" + }, + children: COLUMNS.map((col) => /* @__PURE__ */ jsx_runtime.jsx(Column, { + col, + tasks: filtered.filter((t) => col.statuses.includes(t.status)), + onAction: handleAction, + onViewDetail: setDetail + }, col.key)) + }) : activeView === "heartbeats" ? /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { padding: 28, minHeight: "calc(100vh - 72px)" }, + children: /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + display: "grid", + gridTemplateColumns: "repeat(auto-fit, minmax(360px, 1fr))", + gap: 14 + }, + children: [ + (filter ? heartbeats.filter((h) => h.name.toLowerCase().includes(filter.toLowerCase()) || h.check_prompt.toLowerCase().includes(filter.toLowerCase())) : heartbeats).map((h) => /* @__PURE__ */ jsx_runtime.jsx(HeartbeatCard, { + heartbeat: h, + onAction: handleHeartbeatAction, + onViewDetail: openHeartbeatDetail + }, h.id)), + heartbeats.length === 0 && /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { + border: `1px dashed ${theme.border}`, + borderRadius: 12, + padding: 32, + textAlign: "center", + color: theme.textDim, + fontSize: 12, + gridColumn: "1 / -1" + }, + children: "No heartbeats yet" + }) + ] + }) + }) : /* @__PURE__ */ jsx_runtime.jsx(SkillsView, { + skillData, + skills, + tasks, + onSweep: handleSweep, + onDraft: handleSkillDraft, + onApprove: handleSkillApprove, + onDismiss: handleSkillDismiss, + onToggleSkill: handleSkillToggle, + onDeleteSkill: handleSkillDelete + }), + showNew && /* @__PURE__ */ jsx_runtime.jsx(NewTaskModal, { + onClose: () => setShowNew(false), + onSubmit: handleCreate, + initialData: { agent: defaultAgent } + }), + showNewHeartbeat && /* @__PURE__ */ jsx_runtime.jsx(HeartbeatModal, { + onClose: () => setShowNewHeartbeat(false), + onSubmit: handleCreateHeartbeat, + defaultAgent + }), + editingTask && /* @__PURE__ */ jsx_runtime.jsx(NewTaskModal, { + onClose: () => setEditingTask(null), + onSubmit: handleEdit, + initialData: editingTask, + mode: "edit" + }), + editingHeartbeat && /* @__PURE__ */ jsx_runtime.jsx(HeartbeatModal, { + onClose: () => setEditingHeartbeat(null), + onSubmit: handleEditHeartbeat, + initialData: editingHeartbeat, + defaultAgent, + mode: "edit" + }), + forkingTask && /* @__PURE__ */ jsx_runtime.jsx(NewTaskModal, { + onClose: () => setForkingTask(null), + onSubmit: handleFork, + initialData: forkingTask, + mode: "fork" + }), + showSettings && /* @__PURE__ */ jsx_runtime.jsx(SettingsModal, { + onClose: () => setShowSettings(false), + timeout: taskTimeout, + defaultAgent, + onSave: (timeout, agent) => { + setTaskTimeout(timeout); + if (agent) + setDefaultAgent(agent); + }, + feishu: feishuSettings, + onFeishuSave: (updated) => setFeishuSettings(updated), + channelsStatus, + onChannelsSave: (updated) => setChannelsStatus(updated) + }), + detail && /* @__PURE__ */ jsx_runtime.jsx(DetailPanel, { + task: tasks.find((t) => t.id === detail.id) || detail, + onClose: () => setDetail(null), + onRespond: handleRespond, + onResume: handleResume + }), + heartbeatDetail && /* @__PURE__ */ jsx_runtime.jsx(HeartbeatDetailPanel, { + heartbeat: heartbeats.find((h) => h.id === heartbeatDetail.id) || heartbeatDetail, + ticks: heartbeatTicks, + onClose: () => { + setHeartbeatDetail(null); + setHeartbeatTicks([]); + } + }), + connected && activeView === "tasks" && tasks.length === 0 && /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + position: "fixed", + bottom: 28, + left: "50%", + transform: "translateX(-50%)", + background: theme.surface, + border: `1px solid ${theme.border}`, + borderRadius: 12, + padding: "16px 24px", + maxWidth: 500, + boxShadow: "0 8px 32px rgba(0,0,0,0.3)" + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 13, color: theme.text, fontWeight: 600, marginBottom: 6 }, + children: 'Ready to go! Click "+ New Task" to create your first task.' + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 11, color: theme.textDim, lineHeight: 1.6 }, + children: "Tasks are dispatched to Claude Code in your specified working directory. Set cron schedules for recurring tasks, or delay execution." + }) + ] + }), + connected && activeView === "heartbeats" && heartbeats.length === 0 && /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + position: "fixed", + bottom: 28, + left: "50%", + transform: "translateX(-50%)", + background: theme.surface, + border: `1px solid ${theme.border}`, + borderRadius: 12, + padding: "16px 24px", + maxWidth: 560, + boxShadow: "0 8px 32px rgba(0,0,0,0.3)" + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 13, color: theme.text, fontWeight: 600, marginBottom: 6 }, + children: "Heartbeats let AgentForge check first and only create work when needed." + }), + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 11, color: theme.textDim, lineHeight: 1.6 }, + children: "Create one to run a stateless agent decision tick on an interval or cron schedule, then trigger a real task only when the signal is actionable." + }) + ] + }), + !connected && /* @__PURE__ */ jsx_runtime.jsxs("div", { + style: { + position: "fixed", + bottom: 28, + left: "50%", + transform: "translateX(-50%)", + background: theme.redBg, + border: `1px solid rgba(248,113,113,0.2)`, + borderRadius: 12, + padding: "16px 24px", + maxWidth: 520 + }, + children: [ + /* @__PURE__ */ jsx_runtime.jsx("div", { + style: { fontSize: 13, color: theme.red, fontWeight: 600, marginBottom: 4 }, + children: "Backend not running" + }), + /* @__PURE__ */ jsx_runtime.jsxs("code", { + style: { fontSize: 11, color: theme.text, lineHeight: 1.8, display: "block" }, + children: [ + "pip install croniter", + /* @__PURE__ */ jsx_runtime.jsx("br", {}), + "python taskboard.py" + ] + }) + ] + }) + ] + }); +} +var styles = ` + @keyframes pulse { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.5; } + } + + .live-output-line { + transition: color 0.2s ease; + } + + .live-output-line.error { + color: ${theme.red}; + } + + .live-output-line.success { + color: ${theme.green}; + } + + .live-output-line.warning { + color: ${theme.orange}; + } + + .live-output-line.info { + color: ${theme.blue}; + } + + .live-output-line.command { + color: ${theme.cyan}; + font-weight: bold; + } + + .live-output-line.path { + color: ${theme.accent}; + } +`; +if (typeof document !== "undefined" && !document.querySelector("#live-output-styles")) { + const styleEl = document.createElement("style"); + styleEl.id = "live-output-styles"; + styleEl.textContent = styles; + document.head.appendChild(styleEl); +} + +// src/renderer/main.tsx +var jsx_runtime2 = __toESM(require_jsx_runtime(), 1); +import_client.createRoot(document.getElementById("root")).render(/* @__PURE__ */ jsx_runtime2.jsx(import_react2.StrictMode, { + children: /* @__PURE__ */ jsx_runtime2.jsx(App, {}) +})); + +//# debugId=018A608DD777E92F64756E2164756E21 +//# sourceMappingURL=chunk-nbmpy57s.js.map diff --git a/taskboard-electron/.bun/renderer/chunk-nbmpy57s.js.map b/taskboard-electron/.bun/renderer/chunk-nbmpy57s.js.map new file mode 100644 index 0000000..fee645c --- /dev/null +++ b/taskboard-electron/.bun/renderer/chunk-nbmpy57s.js.map @@ -0,0 +1,52 @@ +{ + "version": 3, + "sources": ["../../node_modules/react/cjs/react.production.js", "../../node_modules/react/index.js", "../../node_modules/scheduler/cjs/scheduler.production.js", "../../node_modules/scheduler/index.js", "../../node_modules/react-dom/cjs/react-dom.production.js", "../../node_modules/react-dom/index.js", "../../node_modules/react-dom/cjs/react-dom-client.production.js", "../../node_modules/react-dom/client.js", "../../node_modules/qrcode/lib/can-promise.js", "../../node_modules/qrcode/lib/core/utils.js", "../../node_modules/qrcode/lib/core/error-correction-level.js", "../../node_modules/qrcode/lib/core/bit-buffer.js", "../../node_modules/qrcode/lib/core/bit-matrix.js", "../../node_modules/qrcode/lib/core/alignment-pattern.js", "../../node_modules/qrcode/lib/core/finder-pattern.js", "../../node_modules/qrcode/lib/core/mask-pattern.js", "../../node_modules/qrcode/lib/core/error-correction-code.js", "../../node_modules/qrcode/lib/core/galois-field.js", "../../node_modules/qrcode/lib/core/polynomial.js", "../../node_modules/qrcode/lib/core/reed-solomon-encoder.js", "../../node_modules/qrcode/lib/core/version-check.js", "../../node_modules/qrcode/lib/core/regex.js", "../../node_modules/qrcode/lib/core/mode.js", "../../node_modules/qrcode/lib/core/version.js", "../../node_modules/qrcode/lib/core/format-info.js", "../../node_modules/qrcode/lib/core/numeric-data.js", "../../node_modules/qrcode/lib/core/alphanumeric-data.js", "../../node_modules/qrcode/lib/core/byte-data.js", "../../node_modules/qrcode/lib/core/kanji-data.js", "../../node_modules/dijkstrajs/dijkstra.js", "../../node_modules/qrcode/lib/core/segments.js", "../../node_modules/qrcode/lib/core/qrcode.js", "../../node_modules/qrcode/lib/renderer/utils.js", "../../node_modules/qrcode/lib/renderer/canvas.js", "../../node_modules/qrcode/lib/renderer/svg-tag.js", "../../node_modules/qrcode/lib/browser.js", "../../node_modules/react/cjs/react-jsx-runtime.production.js", "../../node_modules/react/jsx-runtime.js", "../../src/renderer/main.tsx", "../../src/renderer/App.tsx", "../../src/renderer/dateTime.ts", "../../src/renderer/channelsSettings.ts", "../../src/renderer/traceSteps.ts"], + "sourcesContent": [ + "/**\n * @license React\n * react.production.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\nvar REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_PORTAL_TYPE = Symbol.for(\"react.portal\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\"),\n REACT_STRICT_MODE_TYPE = Symbol.for(\"react.strict_mode\"),\n REACT_PROFILER_TYPE = Symbol.for(\"react.profiler\"),\n REACT_CONSUMER_TYPE = Symbol.for(\"react.consumer\"),\n REACT_CONTEXT_TYPE = Symbol.for(\"react.context\"),\n REACT_FORWARD_REF_TYPE = Symbol.for(\"react.forward_ref\"),\n REACT_SUSPENSE_TYPE = Symbol.for(\"react.suspense\"),\n REACT_MEMO_TYPE = Symbol.for(\"react.memo\"),\n REACT_LAZY_TYPE = Symbol.for(\"react.lazy\"),\n REACT_ACTIVITY_TYPE = Symbol.for(\"react.activity\"),\n MAYBE_ITERATOR_SYMBOL = Symbol.iterator;\nfunction getIteratorFn(maybeIterable) {\n if (null === maybeIterable || \"object\" !== typeof maybeIterable) return null;\n maybeIterable =\n (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) ||\n maybeIterable[\"@@iterator\"];\n return \"function\" === typeof maybeIterable ? maybeIterable : null;\n}\nvar ReactNoopUpdateQueue = {\n isMounted: function () {\n return !1;\n },\n enqueueForceUpdate: function () {},\n enqueueReplaceState: function () {},\n enqueueSetState: function () {}\n },\n assign = Object.assign,\n emptyObject = {};\nfunction Component(props, context, updater) {\n this.props = props;\n this.context = context;\n this.refs = emptyObject;\n this.updater = updater || ReactNoopUpdateQueue;\n}\nComponent.prototype.isReactComponent = {};\nComponent.prototype.setState = function (partialState, callback) {\n if (\n \"object\" !== typeof partialState &&\n \"function\" !== typeof partialState &&\n null != partialState\n )\n throw Error(\n \"takes an object of state variables to update or a function which returns an object of state variables.\"\n );\n this.updater.enqueueSetState(this, partialState, callback, \"setState\");\n};\nComponent.prototype.forceUpdate = function (callback) {\n this.updater.enqueueForceUpdate(this, callback, \"forceUpdate\");\n};\nfunction ComponentDummy() {}\nComponentDummy.prototype = Component.prototype;\nfunction PureComponent(props, context, updater) {\n this.props = props;\n this.context = context;\n this.refs = emptyObject;\n this.updater = updater || ReactNoopUpdateQueue;\n}\nvar pureComponentPrototype = (PureComponent.prototype = new ComponentDummy());\npureComponentPrototype.constructor = PureComponent;\nassign(pureComponentPrototype, Component.prototype);\npureComponentPrototype.isPureReactComponent = !0;\nvar isArrayImpl = Array.isArray;\nfunction noop() {}\nvar ReactSharedInternals = { H: null, A: null, T: null, S: null },\n hasOwnProperty = Object.prototype.hasOwnProperty;\nfunction ReactElement(type, key, props) {\n var refProp = props.ref;\n return {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key,\n ref: void 0 !== refProp ? refProp : null,\n props: props\n };\n}\nfunction cloneAndReplaceKey(oldElement, newKey) {\n return ReactElement(oldElement.type, newKey, oldElement.props);\n}\nfunction isValidElement(object) {\n return (\n \"object\" === typeof object &&\n null !== object &&\n object.$$typeof === REACT_ELEMENT_TYPE\n );\n}\nfunction escape(key) {\n var escaperLookup = { \"=\": \"=0\", \":\": \"=2\" };\n return (\n \"$\" +\n key.replace(/[=:]/g, function (match) {\n return escaperLookup[match];\n })\n );\n}\nvar userProvidedKeyEscapeRegex = /\\/+/g;\nfunction getElementKey(element, index) {\n return \"object\" === typeof element && null !== element && null != element.key\n ? escape(\"\" + element.key)\n : index.toString(36);\n}\nfunction resolveThenable(thenable) {\n switch (thenable.status) {\n case \"fulfilled\":\n return thenable.value;\n case \"rejected\":\n throw thenable.reason;\n default:\n switch (\n (\"string\" === typeof thenable.status\n ? thenable.then(noop, noop)\n : ((thenable.status = \"pending\"),\n thenable.then(\n function (fulfilledValue) {\n \"pending\" === thenable.status &&\n ((thenable.status = \"fulfilled\"),\n (thenable.value = fulfilledValue));\n },\n function (error) {\n \"pending\" === thenable.status &&\n ((thenable.status = \"rejected\"), (thenable.reason = error));\n }\n )),\n thenable.status)\n ) {\n case \"fulfilled\":\n return thenable.value;\n case \"rejected\":\n throw thenable.reason;\n }\n }\n throw thenable;\n}\nfunction mapIntoArray(children, array, escapedPrefix, nameSoFar, callback) {\n var type = typeof children;\n if (\"undefined\" === type || \"boolean\" === type) children = null;\n var invokeCallback = !1;\n if (null === children) invokeCallback = !0;\n else\n switch (type) {\n case \"bigint\":\n case \"string\":\n case \"number\":\n invokeCallback = !0;\n break;\n case \"object\":\n switch (children.$$typeof) {\n case REACT_ELEMENT_TYPE:\n case REACT_PORTAL_TYPE:\n invokeCallback = !0;\n break;\n case REACT_LAZY_TYPE:\n return (\n (invokeCallback = children._init),\n mapIntoArray(\n invokeCallback(children._payload),\n array,\n escapedPrefix,\n nameSoFar,\n callback\n )\n );\n }\n }\n if (invokeCallback)\n return (\n (callback = callback(children)),\n (invokeCallback =\n \"\" === nameSoFar ? \".\" + getElementKey(children, 0) : nameSoFar),\n isArrayImpl(callback)\n ? ((escapedPrefix = \"\"),\n null != invokeCallback &&\n (escapedPrefix =\n invokeCallback.replace(userProvidedKeyEscapeRegex, \"$&/\") + \"/\"),\n mapIntoArray(callback, array, escapedPrefix, \"\", function (c) {\n return c;\n }))\n : null != callback &&\n (isValidElement(callback) &&\n (callback = cloneAndReplaceKey(\n callback,\n escapedPrefix +\n (null == callback.key ||\n (children && children.key === callback.key)\n ? \"\"\n : (\"\" + callback.key).replace(\n userProvidedKeyEscapeRegex,\n \"$&/\"\n ) + \"/\") +\n invokeCallback\n )),\n array.push(callback)),\n 1\n );\n invokeCallback = 0;\n var nextNamePrefix = \"\" === nameSoFar ? \".\" : nameSoFar + \":\";\n if (isArrayImpl(children))\n for (var i = 0; i < children.length; i++)\n (nameSoFar = children[i]),\n (type = nextNamePrefix + getElementKey(nameSoFar, i)),\n (invokeCallback += mapIntoArray(\n nameSoFar,\n array,\n escapedPrefix,\n type,\n callback\n ));\n else if (((i = getIteratorFn(children)), \"function\" === typeof i))\n for (\n children = i.call(children), i = 0;\n !(nameSoFar = children.next()).done;\n\n )\n (nameSoFar = nameSoFar.value),\n (type = nextNamePrefix + getElementKey(nameSoFar, i++)),\n (invokeCallback += mapIntoArray(\n nameSoFar,\n array,\n escapedPrefix,\n type,\n callback\n ));\n else if (\"object\" === type) {\n if (\"function\" === typeof children.then)\n return mapIntoArray(\n resolveThenable(children),\n array,\n escapedPrefix,\n nameSoFar,\n callback\n );\n array = String(children);\n throw Error(\n \"Objects are not valid as a React child (found: \" +\n (\"[object Object]\" === array\n ? \"object with keys {\" + Object.keys(children).join(\", \") + \"}\"\n : array) +\n \"). If you meant to render a collection of children, use an array instead.\"\n );\n }\n return invokeCallback;\n}\nfunction mapChildren(children, func, context) {\n if (null == children) return children;\n var result = [],\n count = 0;\n mapIntoArray(children, result, \"\", \"\", function (child) {\n return func.call(context, child, count++);\n });\n return result;\n}\nfunction lazyInitializer(payload) {\n if (-1 === payload._status) {\n var ctor = payload._result;\n ctor = ctor();\n ctor.then(\n function (moduleObject) {\n if (0 === payload._status || -1 === payload._status)\n (payload._status = 1), (payload._result = moduleObject);\n },\n function (error) {\n if (0 === payload._status || -1 === payload._status)\n (payload._status = 2), (payload._result = error);\n }\n );\n -1 === payload._status && ((payload._status = 0), (payload._result = ctor));\n }\n if (1 === payload._status) return payload._result.default;\n throw payload._result;\n}\nvar reportGlobalError =\n \"function\" === typeof reportError\n ? reportError\n : function (error) {\n if (\n \"object\" === typeof window &&\n \"function\" === typeof window.ErrorEvent\n ) {\n var event = new window.ErrorEvent(\"error\", {\n bubbles: !0,\n cancelable: !0,\n message:\n \"object\" === typeof error &&\n null !== error &&\n \"string\" === typeof error.message\n ? String(error.message)\n : String(error),\n error: error\n });\n if (!window.dispatchEvent(event)) return;\n } else if (\n \"object\" === typeof process &&\n \"function\" === typeof process.emit\n ) {\n process.emit(\"uncaughtException\", error);\n return;\n }\n console.error(error);\n },\n Children = {\n map: mapChildren,\n forEach: function (children, forEachFunc, forEachContext) {\n mapChildren(\n children,\n function () {\n forEachFunc.apply(this, arguments);\n },\n forEachContext\n );\n },\n count: function (children) {\n var n = 0;\n mapChildren(children, function () {\n n++;\n });\n return n;\n },\n toArray: function (children) {\n return (\n mapChildren(children, function (child) {\n return child;\n }) || []\n );\n },\n only: function (children) {\n if (!isValidElement(children))\n throw Error(\n \"React.Children.only expected to receive a single React element child.\"\n );\n return children;\n }\n };\nexports.Activity = REACT_ACTIVITY_TYPE;\nexports.Children = Children;\nexports.Component = Component;\nexports.Fragment = REACT_FRAGMENT_TYPE;\nexports.Profiler = REACT_PROFILER_TYPE;\nexports.PureComponent = PureComponent;\nexports.StrictMode = REACT_STRICT_MODE_TYPE;\nexports.Suspense = REACT_SUSPENSE_TYPE;\nexports.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE =\n ReactSharedInternals;\nexports.__COMPILER_RUNTIME = {\n __proto__: null,\n c: function (size) {\n return ReactSharedInternals.H.useMemoCache(size);\n }\n};\nexports.cache = function (fn) {\n return function () {\n return fn.apply(null, arguments);\n };\n};\nexports.cacheSignal = function () {\n return null;\n};\nexports.cloneElement = function (element, config, children) {\n if (null === element || void 0 === element)\n throw Error(\n \"The argument must be a React element, but you passed \" + element + \".\"\n );\n var props = assign({}, element.props),\n key = element.key;\n if (null != config)\n for (propName in (void 0 !== config.key && (key = \"\" + config.key), config))\n !hasOwnProperty.call(config, propName) ||\n \"key\" === propName ||\n \"__self\" === propName ||\n \"__source\" === propName ||\n (\"ref\" === propName && void 0 === config.ref) ||\n (props[propName] = config[propName]);\n var propName = arguments.length - 2;\n if (1 === propName) props.children = children;\n else if (1 < propName) {\n for (var childArray = Array(propName), i = 0; i < propName; i++)\n childArray[i] = arguments[i + 2];\n props.children = childArray;\n }\n return ReactElement(element.type, key, props);\n};\nexports.createContext = function (defaultValue) {\n defaultValue = {\n $$typeof: REACT_CONTEXT_TYPE,\n _currentValue: defaultValue,\n _currentValue2: defaultValue,\n _threadCount: 0,\n Provider: null,\n Consumer: null\n };\n defaultValue.Provider = defaultValue;\n defaultValue.Consumer = {\n $$typeof: REACT_CONSUMER_TYPE,\n _context: defaultValue\n };\n return defaultValue;\n};\nexports.createElement = function (type, config, children) {\n var propName,\n props = {},\n key = null;\n if (null != config)\n for (propName in (void 0 !== config.key && (key = \"\" + config.key), config))\n hasOwnProperty.call(config, propName) &&\n \"key\" !== propName &&\n \"__self\" !== propName &&\n \"__source\" !== propName &&\n (props[propName] = config[propName]);\n var childrenLength = arguments.length - 2;\n if (1 === childrenLength) props.children = children;\n else if (1 < childrenLength) {\n for (var childArray = Array(childrenLength), i = 0; i < childrenLength; i++)\n childArray[i] = arguments[i + 2];\n props.children = childArray;\n }\n if (type && type.defaultProps)\n for (propName in ((childrenLength = type.defaultProps), childrenLength))\n void 0 === props[propName] &&\n (props[propName] = childrenLength[propName]);\n return ReactElement(type, key, props);\n};\nexports.createRef = function () {\n return { current: null };\n};\nexports.forwardRef = function (render) {\n return { $$typeof: REACT_FORWARD_REF_TYPE, render: render };\n};\nexports.isValidElement = isValidElement;\nexports.lazy = function (ctor) {\n return {\n $$typeof: REACT_LAZY_TYPE,\n _payload: { _status: -1, _result: ctor },\n _init: lazyInitializer\n };\n};\nexports.memo = function (type, compare) {\n return {\n $$typeof: REACT_MEMO_TYPE,\n type: type,\n compare: void 0 === compare ? null : compare\n };\n};\nexports.startTransition = function (scope) {\n var prevTransition = ReactSharedInternals.T,\n currentTransition = {};\n ReactSharedInternals.T = currentTransition;\n try {\n var returnValue = scope(),\n onStartTransitionFinish = ReactSharedInternals.S;\n null !== onStartTransitionFinish &&\n onStartTransitionFinish(currentTransition, returnValue);\n \"object\" === typeof returnValue &&\n null !== returnValue &&\n \"function\" === typeof returnValue.then &&\n returnValue.then(noop, reportGlobalError);\n } catch (error) {\n reportGlobalError(error);\n } finally {\n null !== prevTransition &&\n null !== currentTransition.types &&\n (prevTransition.types = currentTransition.types),\n (ReactSharedInternals.T = prevTransition);\n }\n};\nexports.unstable_useCacheRefresh = function () {\n return ReactSharedInternals.H.useCacheRefresh();\n};\nexports.use = function (usable) {\n return ReactSharedInternals.H.use(usable);\n};\nexports.useActionState = function (action, initialState, permalink) {\n return ReactSharedInternals.H.useActionState(action, initialState, permalink);\n};\nexports.useCallback = function (callback, deps) {\n return ReactSharedInternals.H.useCallback(callback, deps);\n};\nexports.useContext = function (Context) {\n return ReactSharedInternals.H.useContext(Context);\n};\nexports.useDebugValue = function () {};\nexports.useDeferredValue = function (value, initialValue) {\n return ReactSharedInternals.H.useDeferredValue(value, initialValue);\n};\nexports.useEffect = function (create, deps) {\n return ReactSharedInternals.H.useEffect(create, deps);\n};\nexports.useEffectEvent = function (callback) {\n return ReactSharedInternals.H.useEffectEvent(callback);\n};\nexports.useId = function () {\n return ReactSharedInternals.H.useId();\n};\nexports.useImperativeHandle = function (ref, create, deps) {\n return ReactSharedInternals.H.useImperativeHandle(ref, create, deps);\n};\nexports.useInsertionEffect = function (create, deps) {\n return ReactSharedInternals.H.useInsertionEffect(create, deps);\n};\nexports.useLayoutEffect = function (create, deps) {\n return ReactSharedInternals.H.useLayoutEffect(create, deps);\n};\nexports.useMemo = function (create, deps) {\n return ReactSharedInternals.H.useMemo(create, deps);\n};\nexports.useOptimistic = function (passthrough, reducer) {\n return ReactSharedInternals.H.useOptimistic(passthrough, reducer);\n};\nexports.useReducer = function (reducer, initialArg, init) {\n return ReactSharedInternals.H.useReducer(reducer, initialArg, init);\n};\nexports.useRef = function (initialValue) {\n return ReactSharedInternals.H.useRef(initialValue);\n};\nexports.useState = function (initialState) {\n return ReactSharedInternals.H.useState(initialState);\n};\nexports.useSyncExternalStore = function (\n subscribe,\n getSnapshot,\n getServerSnapshot\n) {\n return ReactSharedInternals.H.useSyncExternalStore(\n subscribe,\n getSnapshot,\n getServerSnapshot\n );\n};\nexports.useTransition = function () {\n return ReactSharedInternals.H.useTransition();\n};\nexports.version = \"19.2.4\";\n", + "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react.production.js');\n} else {\n module.exports = require('./cjs/react.development.js');\n}\n", + "/**\n * @license React\n * scheduler.production.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\nfunction push(heap, node) {\n var index = heap.length;\n heap.push(node);\n a: for (; 0 < index; ) {\n var parentIndex = (index - 1) >>> 1,\n parent = heap[parentIndex];\n if (0 < compare(parent, node))\n (heap[parentIndex] = node), (heap[index] = parent), (index = parentIndex);\n else break a;\n }\n}\nfunction peek(heap) {\n return 0 === heap.length ? null : heap[0];\n}\nfunction pop(heap) {\n if (0 === heap.length) return null;\n var first = heap[0],\n last = heap.pop();\n if (last !== first) {\n heap[0] = last;\n a: for (\n var index = 0, length = heap.length, halfLength = length >>> 1;\n index < halfLength;\n\n ) {\n var leftIndex = 2 * (index + 1) - 1,\n left = heap[leftIndex],\n rightIndex = leftIndex + 1,\n right = heap[rightIndex];\n if (0 > compare(left, last))\n rightIndex < length && 0 > compare(right, left)\n ? ((heap[index] = right),\n (heap[rightIndex] = last),\n (index = rightIndex))\n : ((heap[index] = left),\n (heap[leftIndex] = last),\n (index = leftIndex));\n else if (rightIndex < length && 0 > compare(right, last))\n (heap[index] = right), (heap[rightIndex] = last), (index = rightIndex);\n else break a;\n }\n }\n return first;\n}\nfunction compare(a, b) {\n var diff = a.sortIndex - b.sortIndex;\n return 0 !== diff ? diff : a.id - b.id;\n}\nexports.unstable_now = void 0;\nif (\"object\" === typeof performance && \"function\" === typeof performance.now) {\n var localPerformance = performance;\n exports.unstable_now = function () {\n return localPerformance.now();\n };\n} else {\n var localDate = Date,\n initialTime = localDate.now();\n exports.unstable_now = function () {\n return localDate.now() - initialTime;\n };\n}\nvar taskQueue = [],\n timerQueue = [],\n taskIdCounter = 1,\n currentTask = null,\n currentPriorityLevel = 3,\n isPerformingWork = !1,\n isHostCallbackScheduled = !1,\n isHostTimeoutScheduled = !1,\n needsPaint = !1,\n localSetTimeout = \"function\" === typeof setTimeout ? setTimeout : null,\n localClearTimeout = \"function\" === typeof clearTimeout ? clearTimeout : null,\n localSetImmediate = \"undefined\" !== typeof setImmediate ? setImmediate : null;\nfunction advanceTimers(currentTime) {\n for (var timer = peek(timerQueue); null !== timer; ) {\n if (null === timer.callback) pop(timerQueue);\n else if (timer.startTime <= currentTime)\n pop(timerQueue),\n (timer.sortIndex = timer.expirationTime),\n push(taskQueue, timer);\n else break;\n timer = peek(timerQueue);\n }\n}\nfunction handleTimeout(currentTime) {\n isHostTimeoutScheduled = !1;\n advanceTimers(currentTime);\n if (!isHostCallbackScheduled)\n if (null !== peek(taskQueue))\n (isHostCallbackScheduled = !0),\n isMessageLoopRunning ||\n ((isMessageLoopRunning = !0), schedulePerformWorkUntilDeadline());\n else {\n var firstTimer = peek(timerQueue);\n null !== firstTimer &&\n requestHostTimeout(handleTimeout, firstTimer.startTime - currentTime);\n }\n}\nvar isMessageLoopRunning = !1,\n taskTimeoutID = -1,\n frameInterval = 5,\n startTime = -1;\nfunction shouldYieldToHost() {\n return needsPaint\n ? !0\n : exports.unstable_now() - startTime < frameInterval\n ? !1\n : !0;\n}\nfunction performWorkUntilDeadline() {\n needsPaint = !1;\n if (isMessageLoopRunning) {\n var currentTime = exports.unstable_now();\n startTime = currentTime;\n var hasMoreWork = !0;\n try {\n a: {\n isHostCallbackScheduled = !1;\n isHostTimeoutScheduled &&\n ((isHostTimeoutScheduled = !1),\n localClearTimeout(taskTimeoutID),\n (taskTimeoutID = -1));\n isPerformingWork = !0;\n var previousPriorityLevel = currentPriorityLevel;\n try {\n b: {\n advanceTimers(currentTime);\n for (\n currentTask = peek(taskQueue);\n null !== currentTask &&\n !(\n currentTask.expirationTime > currentTime && shouldYieldToHost()\n );\n\n ) {\n var callback = currentTask.callback;\n if (\"function\" === typeof callback) {\n currentTask.callback = null;\n currentPriorityLevel = currentTask.priorityLevel;\n var continuationCallback = callback(\n currentTask.expirationTime <= currentTime\n );\n currentTime = exports.unstable_now();\n if (\"function\" === typeof continuationCallback) {\n currentTask.callback = continuationCallback;\n advanceTimers(currentTime);\n hasMoreWork = !0;\n break b;\n }\n currentTask === peek(taskQueue) && pop(taskQueue);\n advanceTimers(currentTime);\n } else pop(taskQueue);\n currentTask = peek(taskQueue);\n }\n if (null !== currentTask) hasMoreWork = !0;\n else {\n var firstTimer = peek(timerQueue);\n null !== firstTimer &&\n requestHostTimeout(\n handleTimeout,\n firstTimer.startTime - currentTime\n );\n hasMoreWork = !1;\n }\n }\n break a;\n } finally {\n (currentTask = null),\n (currentPriorityLevel = previousPriorityLevel),\n (isPerformingWork = !1);\n }\n hasMoreWork = void 0;\n }\n } finally {\n hasMoreWork\n ? schedulePerformWorkUntilDeadline()\n : (isMessageLoopRunning = !1);\n }\n }\n}\nvar schedulePerformWorkUntilDeadline;\nif (\"function\" === typeof localSetImmediate)\n schedulePerformWorkUntilDeadline = function () {\n localSetImmediate(performWorkUntilDeadline);\n };\nelse if (\"undefined\" !== typeof MessageChannel) {\n var channel = new MessageChannel(),\n port = channel.port2;\n channel.port1.onmessage = performWorkUntilDeadline;\n schedulePerformWorkUntilDeadline = function () {\n port.postMessage(null);\n };\n} else\n schedulePerformWorkUntilDeadline = function () {\n localSetTimeout(performWorkUntilDeadline, 0);\n };\nfunction requestHostTimeout(callback, ms) {\n taskTimeoutID = localSetTimeout(function () {\n callback(exports.unstable_now());\n }, ms);\n}\nexports.unstable_IdlePriority = 5;\nexports.unstable_ImmediatePriority = 1;\nexports.unstable_LowPriority = 4;\nexports.unstable_NormalPriority = 3;\nexports.unstable_Profiling = null;\nexports.unstable_UserBlockingPriority = 2;\nexports.unstable_cancelCallback = function (task) {\n task.callback = null;\n};\nexports.unstable_forceFrameRate = function (fps) {\n 0 > fps || 125 < fps\n ? console.error(\n \"forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported\"\n )\n : (frameInterval = 0 < fps ? Math.floor(1e3 / fps) : 5);\n};\nexports.unstable_getCurrentPriorityLevel = function () {\n return currentPriorityLevel;\n};\nexports.unstable_next = function (eventHandler) {\n switch (currentPriorityLevel) {\n case 1:\n case 2:\n case 3:\n var priorityLevel = 3;\n break;\n default:\n priorityLevel = currentPriorityLevel;\n }\n var previousPriorityLevel = currentPriorityLevel;\n currentPriorityLevel = priorityLevel;\n try {\n return eventHandler();\n } finally {\n currentPriorityLevel = previousPriorityLevel;\n }\n};\nexports.unstable_requestPaint = function () {\n needsPaint = !0;\n};\nexports.unstable_runWithPriority = function (priorityLevel, eventHandler) {\n switch (priorityLevel) {\n case 1:\n case 2:\n case 3:\n case 4:\n case 5:\n break;\n default:\n priorityLevel = 3;\n }\n var previousPriorityLevel = currentPriorityLevel;\n currentPriorityLevel = priorityLevel;\n try {\n return eventHandler();\n } finally {\n currentPriorityLevel = previousPriorityLevel;\n }\n};\nexports.unstable_scheduleCallback = function (\n priorityLevel,\n callback,\n options\n) {\n var currentTime = exports.unstable_now();\n \"object\" === typeof options && null !== options\n ? ((options = options.delay),\n (options =\n \"number\" === typeof options && 0 < options\n ? currentTime + options\n : currentTime))\n : (options = currentTime);\n switch (priorityLevel) {\n case 1:\n var timeout = -1;\n break;\n case 2:\n timeout = 250;\n break;\n case 5:\n timeout = 1073741823;\n break;\n case 4:\n timeout = 1e4;\n break;\n default:\n timeout = 5e3;\n }\n timeout = options + timeout;\n priorityLevel = {\n id: taskIdCounter++,\n callback: callback,\n priorityLevel: priorityLevel,\n startTime: options,\n expirationTime: timeout,\n sortIndex: -1\n };\n options > currentTime\n ? ((priorityLevel.sortIndex = options),\n push(timerQueue, priorityLevel),\n null === peek(taskQueue) &&\n priorityLevel === peek(timerQueue) &&\n (isHostTimeoutScheduled\n ? (localClearTimeout(taskTimeoutID), (taskTimeoutID = -1))\n : (isHostTimeoutScheduled = !0),\n requestHostTimeout(handleTimeout, options - currentTime)))\n : ((priorityLevel.sortIndex = timeout),\n push(taskQueue, priorityLevel),\n isHostCallbackScheduled ||\n isPerformingWork ||\n ((isHostCallbackScheduled = !0),\n isMessageLoopRunning ||\n ((isMessageLoopRunning = !0), schedulePerformWorkUntilDeadline())));\n return priorityLevel;\n};\nexports.unstable_shouldYield = shouldYieldToHost;\nexports.unstable_wrapCallback = function (callback) {\n var parentPriorityLevel = currentPriorityLevel;\n return function () {\n var previousPriorityLevel = currentPriorityLevel;\n currentPriorityLevel = parentPriorityLevel;\n try {\n return callback.apply(this, arguments);\n } finally {\n currentPriorityLevel = previousPriorityLevel;\n }\n };\n};\n", + "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/scheduler.production.js');\n} else {\n module.exports = require('./cjs/scheduler.development.js');\n}\n", + "/**\n * @license React\n * react-dom.production.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\nvar React = require(\"react\");\nfunction formatProdErrorMessage(code) {\n var url = \"https://react.dev/errors/\" + code;\n if (1 < arguments.length) {\n url += \"?args[]=\" + encodeURIComponent(arguments[1]);\n for (var i = 2; i < arguments.length; i++)\n url += \"&args[]=\" + encodeURIComponent(arguments[i]);\n }\n return (\n \"Minified React error #\" +\n code +\n \"; visit \" +\n url +\n \" for the full message or use the non-minified dev environment for full errors and additional helpful warnings.\"\n );\n}\nfunction noop() {}\nvar Internals = {\n d: {\n f: noop,\n r: function () {\n throw Error(formatProdErrorMessage(522));\n },\n D: noop,\n C: noop,\n L: noop,\n m: noop,\n X: noop,\n S: noop,\n M: noop\n },\n p: 0,\n findDOMNode: null\n },\n REACT_PORTAL_TYPE = Symbol.for(\"react.portal\");\nfunction createPortal$1(children, containerInfo, implementation) {\n var key =\n 3 < arguments.length && void 0 !== arguments[3] ? arguments[3] : null;\n return {\n $$typeof: REACT_PORTAL_TYPE,\n key: null == key ? null : \"\" + key,\n children: children,\n containerInfo: containerInfo,\n implementation: implementation\n };\n}\nvar ReactSharedInternals =\n React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;\nfunction getCrossOriginStringAs(as, input) {\n if (\"font\" === as) return \"\";\n if (\"string\" === typeof input)\n return \"use-credentials\" === input ? input : \"\";\n}\nexports.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE =\n Internals;\nexports.createPortal = function (children, container) {\n var key =\n 2 < arguments.length && void 0 !== arguments[2] ? arguments[2] : null;\n if (\n !container ||\n (1 !== container.nodeType &&\n 9 !== container.nodeType &&\n 11 !== container.nodeType)\n )\n throw Error(formatProdErrorMessage(299));\n return createPortal$1(children, container, null, key);\n};\nexports.flushSync = function (fn) {\n var previousTransition = ReactSharedInternals.T,\n previousUpdatePriority = Internals.p;\n try {\n if (((ReactSharedInternals.T = null), (Internals.p = 2), fn)) return fn();\n } finally {\n (ReactSharedInternals.T = previousTransition),\n (Internals.p = previousUpdatePriority),\n Internals.d.f();\n }\n};\nexports.preconnect = function (href, options) {\n \"string\" === typeof href &&\n (options\n ? ((options = options.crossOrigin),\n (options =\n \"string\" === typeof options\n ? \"use-credentials\" === options\n ? options\n : \"\"\n : void 0))\n : (options = null),\n Internals.d.C(href, options));\n};\nexports.prefetchDNS = function (href) {\n \"string\" === typeof href && Internals.d.D(href);\n};\nexports.preinit = function (href, options) {\n if (\"string\" === typeof href && options && \"string\" === typeof options.as) {\n var as = options.as,\n crossOrigin = getCrossOriginStringAs(as, options.crossOrigin),\n integrity =\n \"string\" === typeof options.integrity ? options.integrity : void 0,\n fetchPriority =\n \"string\" === typeof options.fetchPriority\n ? options.fetchPriority\n : void 0;\n \"style\" === as\n ? Internals.d.S(\n href,\n \"string\" === typeof options.precedence ? options.precedence : void 0,\n {\n crossOrigin: crossOrigin,\n integrity: integrity,\n fetchPriority: fetchPriority\n }\n )\n : \"script\" === as &&\n Internals.d.X(href, {\n crossOrigin: crossOrigin,\n integrity: integrity,\n fetchPriority: fetchPriority,\n nonce: \"string\" === typeof options.nonce ? options.nonce : void 0\n });\n }\n};\nexports.preinitModule = function (href, options) {\n if (\"string\" === typeof href)\n if (\"object\" === typeof options && null !== options) {\n if (null == options.as || \"script\" === options.as) {\n var crossOrigin = getCrossOriginStringAs(\n options.as,\n options.crossOrigin\n );\n Internals.d.M(href, {\n crossOrigin: crossOrigin,\n integrity:\n \"string\" === typeof options.integrity ? options.integrity : void 0,\n nonce: \"string\" === typeof options.nonce ? options.nonce : void 0\n });\n }\n } else null == options && Internals.d.M(href);\n};\nexports.preload = function (href, options) {\n if (\n \"string\" === typeof href &&\n \"object\" === typeof options &&\n null !== options &&\n \"string\" === typeof options.as\n ) {\n var as = options.as,\n crossOrigin = getCrossOriginStringAs(as, options.crossOrigin);\n Internals.d.L(href, as, {\n crossOrigin: crossOrigin,\n integrity:\n \"string\" === typeof options.integrity ? options.integrity : void 0,\n nonce: \"string\" === typeof options.nonce ? options.nonce : void 0,\n type: \"string\" === typeof options.type ? options.type : void 0,\n fetchPriority:\n \"string\" === typeof options.fetchPriority\n ? options.fetchPriority\n : void 0,\n referrerPolicy:\n \"string\" === typeof options.referrerPolicy\n ? options.referrerPolicy\n : void 0,\n imageSrcSet:\n \"string\" === typeof options.imageSrcSet ? options.imageSrcSet : void 0,\n imageSizes:\n \"string\" === typeof options.imageSizes ? options.imageSizes : void 0,\n media: \"string\" === typeof options.media ? options.media : void 0\n });\n }\n};\nexports.preloadModule = function (href, options) {\n if (\"string\" === typeof href)\n if (options) {\n var crossOrigin = getCrossOriginStringAs(options.as, options.crossOrigin);\n Internals.d.m(href, {\n as:\n \"string\" === typeof options.as && \"script\" !== options.as\n ? options.as\n : void 0,\n crossOrigin: crossOrigin,\n integrity:\n \"string\" === typeof options.integrity ? options.integrity : void 0\n });\n } else Internals.d.m(href);\n};\nexports.requestFormReset = function (form) {\n Internals.d.r(form);\n};\nexports.unstable_batchedUpdates = function (fn, a) {\n return fn(a);\n};\nexports.useFormState = function (action, initialState, permalink) {\n return ReactSharedInternals.H.useFormState(action, initialState, permalink);\n};\nexports.useFormStatus = function () {\n return ReactSharedInternals.H.useHostTransitionStatus();\n};\nexports.version = \"19.2.4\";\n", + "'use strict';\n\nfunction checkDCE() {\n /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */\n if (\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined' ||\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE !== 'function'\n ) {\n return;\n }\n if (process.env.NODE_ENV !== 'production') {\n // This branch is unreachable because this function is only called\n // in production, but the condition is true only in development.\n // Therefore if the branch is still here, dead code elimination wasn't\n // properly applied.\n // Don't change the message. React DevTools relies on it. Also make sure\n // this message doesn't occur elsewhere in this function, or it will cause\n // a false positive.\n throw new Error('^_^');\n }\n try {\n // Verify that the code above has been dead code eliminated (DCE'd).\n __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(checkDCE);\n } catch (err) {\n // DevTools shouldn't crash React, no matter what.\n // We should still report in case we break this code.\n console.error(err);\n }\n}\n\nif (process.env.NODE_ENV === 'production') {\n // DCE check should happen before ReactDOM bundle executes so that\n // DevTools can report bad minification during injection.\n checkDCE();\n module.exports = require('./cjs/react-dom.production.js');\n} else {\n module.exports = require('./cjs/react-dom.development.js');\n}\n", + "/**\n * @license React\n * react-dom-client.production.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n/*\n Modernizr 3.0.0pre (Custom Build) | MIT\n*/\n\"use strict\";\nvar Scheduler = require(\"scheduler\"),\n React = require(\"react\"),\n ReactDOM = require(\"react-dom\");\nfunction formatProdErrorMessage(code) {\n var url = \"https://react.dev/errors/\" + code;\n if (1 < arguments.length) {\n url += \"?args[]=\" + encodeURIComponent(arguments[1]);\n for (var i = 2; i < arguments.length; i++)\n url += \"&args[]=\" + encodeURIComponent(arguments[i]);\n }\n return (\n \"Minified React error #\" +\n code +\n \"; visit \" +\n url +\n \" for the full message or use the non-minified dev environment for full errors and additional helpful warnings.\"\n );\n}\nfunction isValidContainer(node) {\n return !(\n !node ||\n (1 !== node.nodeType && 9 !== node.nodeType && 11 !== node.nodeType)\n );\n}\nfunction getNearestMountedFiber(fiber) {\n var node = fiber,\n nearestMounted = fiber;\n if (fiber.alternate) for (; node.return; ) node = node.return;\n else {\n fiber = node;\n do\n (node = fiber),\n 0 !== (node.flags & 4098) && (nearestMounted = node.return),\n (fiber = node.return);\n while (fiber);\n }\n return 3 === node.tag ? nearestMounted : null;\n}\nfunction getSuspenseInstanceFromFiber(fiber) {\n if (13 === fiber.tag) {\n var suspenseState = fiber.memoizedState;\n null === suspenseState &&\n ((fiber = fiber.alternate),\n null !== fiber && (suspenseState = fiber.memoizedState));\n if (null !== suspenseState) return suspenseState.dehydrated;\n }\n return null;\n}\nfunction getActivityInstanceFromFiber(fiber) {\n if (31 === fiber.tag) {\n var activityState = fiber.memoizedState;\n null === activityState &&\n ((fiber = fiber.alternate),\n null !== fiber && (activityState = fiber.memoizedState));\n if (null !== activityState) return activityState.dehydrated;\n }\n return null;\n}\nfunction assertIsMounted(fiber) {\n if (getNearestMountedFiber(fiber) !== fiber)\n throw Error(formatProdErrorMessage(188));\n}\nfunction findCurrentFiberUsingSlowPath(fiber) {\n var alternate = fiber.alternate;\n if (!alternate) {\n alternate = getNearestMountedFiber(fiber);\n if (null === alternate) throw Error(formatProdErrorMessage(188));\n return alternate !== fiber ? null : fiber;\n }\n for (var a = fiber, b = alternate; ; ) {\n var parentA = a.return;\n if (null === parentA) break;\n var parentB = parentA.alternate;\n if (null === parentB) {\n b = parentA.return;\n if (null !== b) {\n a = b;\n continue;\n }\n break;\n }\n if (parentA.child === parentB.child) {\n for (parentB = parentA.child; parentB; ) {\n if (parentB === a) return assertIsMounted(parentA), fiber;\n if (parentB === b) return assertIsMounted(parentA), alternate;\n parentB = parentB.sibling;\n }\n throw Error(formatProdErrorMessage(188));\n }\n if (a.return !== b.return) (a = parentA), (b = parentB);\n else {\n for (var didFindChild = !1, child$0 = parentA.child; child$0; ) {\n if (child$0 === a) {\n didFindChild = !0;\n a = parentA;\n b = parentB;\n break;\n }\n if (child$0 === b) {\n didFindChild = !0;\n b = parentA;\n a = parentB;\n break;\n }\n child$0 = child$0.sibling;\n }\n if (!didFindChild) {\n for (child$0 = parentB.child; child$0; ) {\n if (child$0 === a) {\n didFindChild = !0;\n a = parentB;\n b = parentA;\n break;\n }\n if (child$0 === b) {\n didFindChild = !0;\n b = parentB;\n a = parentA;\n break;\n }\n child$0 = child$0.sibling;\n }\n if (!didFindChild) throw Error(formatProdErrorMessage(189));\n }\n }\n if (a.alternate !== b) throw Error(formatProdErrorMessage(190));\n }\n if (3 !== a.tag) throw Error(formatProdErrorMessage(188));\n return a.stateNode.current === a ? fiber : alternate;\n}\nfunction findCurrentHostFiberImpl(node) {\n var tag = node.tag;\n if (5 === tag || 26 === tag || 27 === tag || 6 === tag) return node;\n for (node = node.child; null !== node; ) {\n tag = findCurrentHostFiberImpl(node);\n if (null !== tag) return tag;\n node = node.sibling;\n }\n return null;\n}\nvar assign = Object.assign,\n REACT_LEGACY_ELEMENT_TYPE = Symbol.for(\"react.element\"),\n REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_PORTAL_TYPE = Symbol.for(\"react.portal\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\"),\n REACT_STRICT_MODE_TYPE = Symbol.for(\"react.strict_mode\"),\n REACT_PROFILER_TYPE = Symbol.for(\"react.profiler\"),\n REACT_CONSUMER_TYPE = Symbol.for(\"react.consumer\"),\n REACT_CONTEXT_TYPE = Symbol.for(\"react.context\"),\n REACT_FORWARD_REF_TYPE = Symbol.for(\"react.forward_ref\"),\n REACT_SUSPENSE_TYPE = Symbol.for(\"react.suspense\"),\n REACT_SUSPENSE_LIST_TYPE = Symbol.for(\"react.suspense_list\"),\n REACT_MEMO_TYPE = Symbol.for(\"react.memo\"),\n REACT_LAZY_TYPE = Symbol.for(\"react.lazy\");\nSymbol.for(\"react.scope\");\nvar REACT_ACTIVITY_TYPE = Symbol.for(\"react.activity\");\nSymbol.for(\"react.legacy_hidden\");\nSymbol.for(\"react.tracing_marker\");\nvar REACT_MEMO_CACHE_SENTINEL = Symbol.for(\"react.memo_cache_sentinel\");\nSymbol.for(\"react.view_transition\");\nvar MAYBE_ITERATOR_SYMBOL = Symbol.iterator;\nfunction getIteratorFn(maybeIterable) {\n if (null === maybeIterable || \"object\" !== typeof maybeIterable) return null;\n maybeIterable =\n (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) ||\n maybeIterable[\"@@iterator\"];\n return \"function\" === typeof maybeIterable ? maybeIterable : null;\n}\nvar REACT_CLIENT_REFERENCE = Symbol.for(\"react.client.reference\");\nfunction getComponentNameFromType(type) {\n if (null == type) return null;\n if (\"function\" === typeof type)\n return type.$$typeof === REACT_CLIENT_REFERENCE\n ? null\n : type.displayName || type.name || null;\n if (\"string\" === typeof type) return type;\n switch (type) {\n case REACT_FRAGMENT_TYPE:\n return \"Fragment\";\n case REACT_PROFILER_TYPE:\n return \"Profiler\";\n case REACT_STRICT_MODE_TYPE:\n return \"StrictMode\";\n case REACT_SUSPENSE_TYPE:\n return \"Suspense\";\n case REACT_SUSPENSE_LIST_TYPE:\n return \"SuspenseList\";\n case REACT_ACTIVITY_TYPE:\n return \"Activity\";\n }\n if (\"object\" === typeof type)\n switch (type.$$typeof) {\n case REACT_PORTAL_TYPE:\n return \"Portal\";\n case REACT_CONTEXT_TYPE:\n return type.displayName || \"Context\";\n case REACT_CONSUMER_TYPE:\n return (type._context.displayName || \"Context\") + \".Consumer\";\n case REACT_FORWARD_REF_TYPE:\n var innerType = type.render;\n type = type.displayName;\n type ||\n ((type = innerType.displayName || innerType.name || \"\"),\n (type = \"\" !== type ? \"ForwardRef(\" + type + \")\" : \"ForwardRef\"));\n return type;\n case REACT_MEMO_TYPE:\n return (\n (innerType = type.displayName || null),\n null !== innerType\n ? innerType\n : getComponentNameFromType(type.type) || \"Memo\"\n );\n case REACT_LAZY_TYPE:\n innerType = type._payload;\n type = type._init;\n try {\n return getComponentNameFromType(type(innerType));\n } catch (x) {}\n }\n return null;\n}\nvar isArrayImpl = Array.isArray,\n ReactSharedInternals =\n React.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,\n ReactDOMSharedInternals =\n ReactDOM.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,\n sharedNotPendingObject = {\n pending: !1,\n data: null,\n method: null,\n action: null\n },\n valueStack = [],\n index = -1;\nfunction createCursor(defaultValue) {\n return { current: defaultValue };\n}\nfunction pop(cursor) {\n 0 > index ||\n ((cursor.current = valueStack[index]), (valueStack[index] = null), index--);\n}\nfunction push(cursor, value) {\n index++;\n valueStack[index] = cursor.current;\n cursor.current = value;\n}\nvar contextStackCursor = createCursor(null),\n contextFiberStackCursor = createCursor(null),\n rootInstanceStackCursor = createCursor(null),\n hostTransitionProviderCursor = createCursor(null);\nfunction pushHostContainer(fiber, nextRootInstance) {\n push(rootInstanceStackCursor, nextRootInstance);\n push(contextFiberStackCursor, fiber);\n push(contextStackCursor, null);\n switch (nextRootInstance.nodeType) {\n case 9:\n case 11:\n fiber = (fiber = nextRootInstance.documentElement)\n ? (fiber = fiber.namespaceURI)\n ? getOwnHostContext(fiber)\n : 0\n : 0;\n break;\n default:\n if (\n ((fiber = nextRootInstance.tagName),\n (nextRootInstance = nextRootInstance.namespaceURI))\n )\n (nextRootInstance = getOwnHostContext(nextRootInstance)),\n (fiber = getChildHostContextProd(nextRootInstance, fiber));\n else\n switch (fiber) {\n case \"svg\":\n fiber = 1;\n break;\n case \"math\":\n fiber = 2;\n break;\n default:\n fiber = 0;\n }\n }\n pop(contextStackCursor);\n push(contextStackCursor, fiber);\n}\nfunction popHostContainer() {\n pop(contextStackCursor);\n pop(contextFiberStackCursor);\n pop(rootInstanceStackCursor);\n}\nfunction pushHostContext(fiber) {\n null !== fiber.memoizedState && push(hostTransitionProviderCursor, fiber);\n var context = contextStackCursor.current;\n var JSCompiler_inline_result = getChildHostContextProd(context, fiber.type);\n context !== JSCompiler_inline_result &&\n (push(contextFiberStackCursor, fiber),\n push(contextStackCursor, JSCompiler_inline_result));\n}\nfunction popHostContext(fiber) {\n contextFiberStackCursor.current === fiber &&\n (pop(contextStackCursor), pop(contextFiberStackCursor));\n hostTransitionProviderCursor.current === fiber &&\n (pop(hostTransitionProviderCursor),\n (HostTransitionContext._currentValue = sharedNotPendingObject));\n}\nvar prefix, suffix;\nfunction describeBuiltInComponentFrame(name) {\n if (void 0 === prefix)\n try {\n throw Error();\n } catch (x) {\n var match = x.stack.trim().match(/\\n( *(at )?)/);\n prefix = (match && match[1]) || \"\";\n suffix =\n -1 < x.stack.indexOf(\"\\n at\")\n ? \" (<anonymous>)\"\n : -1 < x.stack.indexOf(\"@\")\n ? \"@unknown:0:0\"\n : \"\";\n }\n return \"\\n\" + prefix + name + suffix;\n}\nvar reentry = !1;\nfunction describeNativeComponentFrame(fn, construct) {\n if (!fn || reentry) return \"\";\n reentry = !0;\n var previousPrepareStackTrace = Error.prepareStackTrace;\n Error.prepareStackTrace = void 0;\n try {\n var RunInRootFrame = {\n DetermineComponentFrameRoot: function () {\n try {\n if (construct) {\n var Fake = function () {\n throw Error();\n };\n Object.defineProperty(Fake.prototype, \"props\", {\n set: function () {\n throw Error();\n }\n });\n if (\"object\" === typeof Reflect && Reflect.construct) {\n try {\n Reflect.construct(Fake, []);\n } catch (x) {\n var control = x;\n }\n Reflect.construct(fn, [], Fake);\n } else {\n try {\n Fake.call();\n } catch (x$1) {\n control = x$1;\n }\n fn.call(Fake.prototype);\n }\n } else {\n try {\n throw Error();\n } catch (x$2) {\n control = x$2;\n }\n (Fake = fn()) &&\n \"function\" === typeof Fake.catch &&\n Fake.catch(function () {});\n }\n } catch (sample) {\n if (sample && control && \"string\" === typeof sample.stack)\n return [sample.stack, control.stack];\n }\n return [null, null];\n }\n };\n RunInRootFrame.DetermineComponentFrameRoot.displayName =\n \"DetermineComponentFrameRoot\";\n var namePropDescriptor = Object.getOwnPropertyDescriptor(\n RunInRootFrame.DetermineComponentFrameRoot,\n \"name\"\n );\n namePropDescriptor &&\n namePropDescriptor.configurable &&\n Object.defineProperty(\n RunInRootFrame.DetermineComponentFrameRoot,\n \"name\",\n { value: \"DetermineComponentFrameRoot\" }\n );\n var _RunInRootFrame$Deter = RunInRootFrame.DetermineComponentFrameRoot(),\n sampleStack = _RunInRootFrame$Deter[0],\n controlStack = _RunInRootFrame$Deter[1];\n if (sampleStack && controlStack) {\n var sampleLines = sampleStack.split(\"\\n\"),\n controlLines = controlStack.split(\"\\n\");\n for (\n namePropDescriptor = RunInRootFrame = 0;\n RunInRootFrame < sampleLines.length &&\n !sampleLines[RunInRootFrame].includes(\"DetermineComponentFrameRoot\");\n\n )\n RunInRootFrame++;\n for (\n ;\n namePropDescriptor < controlLines.length &&\n !controlLines[namePropDescriptor].includes(\n \"DetermineComponentFrameRoot\"\n );\n\n )\n namePropDescriptor++;\n if (\n RunInRootFrame === sampleLines.length ||\n namePropDescriptor === controlLines.length\n )\n for (\n RunInRootFrame = sampleLines.length - 1,\n namePropDescriptor = controlLines.length - 1;\n 1 <= RunInRootFrame &&\n 0 <= namePropDescriptor &&\n sampleLines[RunInRootFrame] !== controlLines[namePropDescriptor];\n\n )\n namePropDescriptor--;\n for (\n ;\n 1 <= RunInRootFrame && 0 <= namePropDescriptor;\n RunInRootFrame--, namePropDescriptor--\n )\n if (sampleLines[RunInRootFrame] !== controlLines[namePropDescriptor]) {\n if (1 !== RunInRootFrame || 1 !== namePropDescriptor) {\n do\n if (\n (RunInRootFrame--,\n namePropDescriptor--,\n 0 > namePropDescriptor ||\n sampleLines[RunInRootFrame] !==\n controlLines[namePropDescriptor])\n ) {\n var frame =\n \"\\n\" +\n sampleLines[RunInRootFrame].replace(\" at new \", \" at \");\n fn.displayName &&\n frame.includes(\"<anonymous>\") &&\n (frame = frame.replace(\"<anonymous>\", fn.displayName));\n return frame;\n }\n while (1 <= RunInRootFrame && 0 <= namePropDescriptor);\n }\n break;\n }\n }\n } finally {\n (reentry = !1), (Error.prepareStackTrace = previousPrepareStackTrace);\n }\n return (previousPrepareStackTrace = fn ? fn.displayName || fn.name : \"\")\n ? describeBuiltInComponentFrame(previousPrepareStackTrace)\n : \"\";\n}\nfunction describeFiber(fiber, childFiber) {\n switch (fiber.tag) {\n case 26:\n case 27:\n case 5:\n return describeBuiltInComponentFrame(fiber.type);\n case 16:\n return describeBuiltInComponentFrame(\"Lazy\");\n case 13:\n return fiber.child !== childFiber && null !== childFiber\n ? describeBuiltInComponentFrame(\"Suspense Fallback\")\n : describeBuiltInComponentFrame(\"Suspense\");\n case 19:\n return describeBuiltInComponentFrame(\"SuspenseList\");\n case 0:\n case 15:\n return describeNativeComponentFrame(fiber.type, !1);\n case 11:\n return describeNativeComponentFrame(fiber.type.render, !1);\n case 1:\n return describeNativeComponentFrame(fiber.type, !0);\n case 31:\n return describeBuiltInComponentFrame(\"Activity\");\n default:\n return \"\";\n }\n}\nfunction getStackByFiberInDevAndProd(workInProgress) {\n try {\n var info = \"\",\n previous = null;\n do\n (info += describeFiber(workInProgress, previous)),\n (previous = workInProgress),\n (workInProgress = workInProgress.return);\n while (workInProgress);\n return info;\n } catch (x) {\n return \"\\nError generating stack: \" + x.message + \"\\n\" + x.stack;\n }\n}\nvar hasOwnProperty = Object.prototype.hasOwnProperty,\n scheduleCallback$3 = Scheduler.unstable_scheduleCallback,\n cancelCallback$1 = Scheduler.unstable_cancelCallback,\n shouldYield = Scheduler.unstable_shouldYield,\n requestPaint = Scheduler.unstable_requestPaint,\n now = Scheduler.unstable_now,\n getCurrentPriorityLevel = Scheduler.unstable_getCurrentPriorityLevel,\n ImmediatePriority = Scheduler.unstable_ImmediatePriority,\n UserBlockingPriority = Scheduler.unstable_UserBlockingPriority,\n NormalPriority$1 = Scheduler.unstable_NormalPriority,\n LowPriority = Scheduler.unstable_LowPriority,\n IdlePriority = Scheduler.unstable_IdlePriority,\n log$1 = Scheduler.log,\n unstable_setDisableYieldValue = Scheduler.unstable_setDisableYieldValue,\n rendererID = null,\n injectedHook = null;\nfunction setIsStrictModeForDevtools(newIsStrictMode) {\n \"function\" === typeof log$1 && unstable_setDisableYieldValue(newIsStrictMode);\n if (injectedHook && \"function\" === typeof injectedHook.setStrictMode)\n try {\n injectedHook.setStrictMode(rendererID, newIsStrictMode);\n } catch (err) {}\n}\nvar clz32 = Math.clz32 ? Math.clz32 : clz32Fallback,\n log = Math.log,\n LN2 = Math.LN2;\nfunction clz32Fallback(x) {\n x >>>= 0;\n return 0 === x ? 32 : (31 - ((log(x) / LN2) | 0)) | 0;\n}\nvar nextTransitionUpdateLane = 256,\n nextTransitionDeferredLane = 262144,\n nextRetryLane = 4194304;\nfunction getHighestPriorityLanes(lanes) {\n var pendingSyncLanes = lanes & 42;\n if (0 !== pendingSyncLanes) return pendingSyncLanes;\n switch (lanes & -lanes) {\n case 1:\n return 1;\n case 2:\n return 2;\n case 4:\n return 4;\n case 8:\n return 8;\n case 16:\n return 16;\n case 32:\n return 32;\n case 64:\n return 64;\n case 128:\n return 128;\n case 256:\n case 512:\n case 1024:\n case 2048:\n case 4096:\n case 8192:\n case 16384:\n case 32768:\n case 65536:\n case 131072:\n return lanes & 261888;\n case 262144:\n case 524288:\n case 1048576:\n case 2097152:\n return lanes & 3932160;\n case 4194304:\n case 8388608:\n case 16777216:\n case 33554432:\n return lanes & 62914560;\n case 67108864:\n return 67108864;\n case 134217728:\n return 134217728;\n case 268435456:\n return 268435456;\n case 536870912:\n return 536870912;\n case 1073741824:\n return 0;\n default:\n return lanes;\n }\n}\nfunction getNextLanes(root, wipLanes, rootHasPendingCommit) {\n var pendingLanes = root.pendingLanes;\n if (0 === pendingLanes) return 0;\n var nextLanes = 0,\n suspendedLanes = root.suspendedLanes,\n pingedLanes = root.pingedLanes;\n root = root.warmLanes;\n var nonIdlePendingLanes = pendingLanes & 134217727;\n 0 !== nonIdlePendingLanes\n ? ((pendingLanes = nonIdlePendingLanes & ~suspendedLanes),\n 0 !== pendingLanes\n ? (nextLanes = getHighestPriorityLanes(pendingLanes))\n : ((pingedLanes &= nonIdlePendingLanes),\n 0 !== pingedLanes\n ? (nextLanes = getHighestPriorityLanes(pingedLanes))\n : rootHasPendingCommit ||\n ((rootHasPendingCommit = nonIdlePendingLanes & ~root),\n 0 !== rootHasPendingCommit &&\n (nextLanes = getHighestPriorityLanes(rootHasPendingCommit)))))\n : ((nonIdlePendingLanes = pendingLanes & ~suspendedLanes),\n 0 !== nonIdlePendingLanes\n ? (nextLanes = getHighestPriorityLanes(nonIdlePendingLanes))\n : 0 !== pingedLanes\n ? (nextLanes = getHighestPriorityLanes(pingedLanes))\n : rootHasPendingCommit ||\n ((rootHasPendingCommit = pendingLanes & ~root),\n 0 !== rootHasPendingCommit &&\n (nextLanes = getHighestPriorityLanes(rootHasPendingCommit))));\n return 0 === nextLanes\n ? 0\n : 0 !== wipLanes &&\n wipLanes !== nextLanes &&\n 0 === (wipLanes & suspendedLanes) &&\n ((suspendedLanes = nextLanes & -nextLanes),\n (rootHasPendingCommit = wipLanes & -wipLanes),\n suspendedLanes >= rootHasPendingCommit ||\n (32 === suspendedLanes && 0 !== (rootHasPendingCommit & 4194048)))\n ? wipLanes\n : nextLanes;\n}\nfunction checkIfRootIsPrerendering(root, renderLanes) {\n return (\n 0 ===\n (root.pendingLanes &\n ~(root.suspendedLanes & ~root.pingedLanes) &\n renderLanes)\n );\n}\nfunction computeExpirationTime(lane, currentTime) {\n switch (lane) {\n case 1:\n case 2:\n case 4:\n case 8:\n case 64:\n return currentTime + 250;\n case 16:\n case 32:\n case 128:\n case 256:\n case 512:\n case 1024:\n case 2048:\n case 4096:\n case 8192:\n case 16384:\n case 32768:\n case 65536:\n case 131072:\n case 262144:\n case 524288:\n case 1048576:\n case 2097152:\n return currentTime + 5e3;\n case 4194304:\n case 8388608:\n case 16777216:\n case 33554432:\n return -1;\n case 67108864:\n case 134217728:\n case 268435456:\n case 536870912:\n case 1073741824:\n return -1;\n default:\n return -1;\n }\n}\nfunction claimNextRetryLane() {\n var lane = nextRetryLane;\n nextRetryLane <<= 1;\n 0 === (nextRetryLane & 62914560) && (nextRetryLane = 4194304);\n return lane;\n}\nfunction createLaneMap(initial) {\n for (var laneMap = [], i = 0; 31 > i; i++) laneMap.push(initial);\n return laneMap;\n}\nfunction markRootUpdated$1(root, updateLane) {\n root.pendingLanes |= updateLane;\n 268435456 !== updateLane &&\n ((root.suspendedLanes = 0), (root.pingedLanes = 0), (root.warmLanes = 0));\n}\nfunction markRootFinished(\n root,\n finishedLanes,\n remainingLanes,\n spawnedLane,\n updatedLanes,\n suspendedRetryLanes\n) {\n var previouslyPendingLanes = root.pendingLanes;\n root.pendingLanes = remainingLanes;\n root.suspendedLanes = 0;\n root.pingedLanes = 0;\n root.warmLanes = 0;\n root.expiredLanes &= remainingLanes;\n root.entangledLanes &= remainingLanes;\n root.errorRecoveryDisabledLanes &= remainingLanes;\n root.shellSuspendCounter = 0;\n var entanglements = root.entanglements,\n expirationTimes = root.expirationTimes,\n hiddenUpdates = root.hiddenUpdates;\n for (\n remainingLanes = previouslyPendingLanes & ~remainingLanes;\n 0 < remainingLanes;\n\n ) {\n var index$7 = 31 - clz32(remainingLanes),\n lane = 1 << index$7;\n entanglements[index$7] = 0;\n expirationTimes[index$7] = -1;\n var hiddenUpdatesForLane = hiddenUpdates[index$7];\n if (null !== hiddenUpdatesForLane)\n for (\n hiddenUpdates[index$7] = null, index$7 = 0;\n index$7 < hiddenUpdatesForLane.length;\n index$7++\n ) {\n var update = hiddenUpdatesForLane[index$7];\n null !== update && (update.lane &= -536870913);\n }\n remainingLanes &= ~lane;\n }\n 0 !== spawnedLane && markSpawnedDeferredLane(root, spawnedLane, 0);\n 0 !== suspendedRetryLanes &&\n 0 === updatedLanes &&\n 0 !== root.tag &&\n (root.suspendedLanes |=\n suspendedRetryLanes & ~(previouslyPendingLanes & ~finishedLanes));\n}\nfunction markSpawnedDeferredLane(root, spawnedLane, entangledLanes) {\n root.pendingLanes |= spawnedLane;\n root.suspendedLanes &= ~spawnedLane;\n var spawnedLaneIndex = 31 - clz32(spawnedLane);\n root.entangledLanes |= spawnedLane;\n root.entanglements[spawnedLaneIndex] =\n root.entanglements[spawnedLaneIndex] |\n 1073741824 |\n (entangledLanes & 261930);\n}\nfunction markRootEntangled(root, entangledLanes) {\n var rootEntangledLanes = (root.entangledLanes |= entangledLanes);\n for (root = root.entanglements; rootEntangledLanes; ) {\n var index$8 = 31 - clz32(rootEntangledLanes),\n lane = 1 << index$8;\n (lane & entangledLanes) | (root[index$8] & entangledLanes) &&\n (root[index$8] |= entangledLanes);\n rootEntangledLanes &= ~lane;\n }\n}\nfunction getBumpedLaneForHydration(root, renderLanes) {\n var renderLane = renderLanes & -renderLanes;\n renderLane =\n 0 !== (renderLane & 42) ? 1 : getBumpedLaneForHydrationByLane(renderLane);\n return 0 !== (renderLane & (root.suspendedLanes | renderLanes))\n ? 0\n : renderLane;\n}\nfunction getBumpedLaneForHydrationByLane(lane) {\n switch (lane) {\n case 2:\n lane = 1;\n break;\n case 8:\n lane = 4;\n break;\n case 32:\n lane = 16;\n break;\n case 256:\n case 512:\n case 1024:\n case 2048:\n case 4096:\n case 8192:\n case 16384:\n case 32768:\n case 65536:\n case 131072:\n case 262144:\n case 524288:\n case 1048576:\n case 2097152:\n case 4194304:\n case 8388608:\n case 16777216:\n case 33554432:\n lane = 128;\n break;\n case 268435456:\n lane = 134217728;\n break;\n default:\n lane = 0;\n }\n return lane;\n}\nfunction lanesToEventPriority(lanes) {\n lanes &= -lanes;\n return 2 < lanes\n ? 8 < lanes\n ? 0 !== (lanes & 134217727)\n ? 32\n : 268435456\n : 8\n : 2;\n}\nfunction resolveUpdatePriority() {\n var updatePriority = ReactDOMSharedInternals.p;\n if (0 !== updatePriority) return updatePriority;\n updatePriority = window.event;\n return void 0 === updatePriority ? 32 : getEventPriority(updatePriority.type);\n}\nfunction runWithPriority(priority, fn) {\n var previousPriority = ReactDOMSharedInternals.p;\n try {\n return (ReactDOMSharedInternals.p = priority), fn();\n } finally {\n ReactDOMSharedInternals.p = previousPriority;\n }\n}\nvar randomKey = Math.random().toString(36).slice(2),\n internalInstanceKey = \"__reactFiber$\" + randomKey,\n internalPropsKey = \"__reactProps$\" + randomKey,\n internalContainerInstanceKey = \"__reactContainer$\" + randomKey,\n internalEventHandlersKey = \"__reactEvents$\" + randomKey,\n internalEventHandlerListenersKey = \"__reactListeners$\" + randomKey,\n internalEventHandlesSetKey = \"__reactHandles$\" + randomKey,\n internalRootNodeResourcesKey = \"__reactResources$\" + randomKey,\n internalHoistableMarker = \"__reactMarker$\" + randomKey;\nfunction detachDeletedInstance(node) {\n delete node[internalInstanceKey];\n delete node[internalPropsKey];\n delete node[internalEventHandlersKey];\n delete node[internalEventHandlerListenersKey];\n delete node[internalEventHandlesSetKey];\n}\nfunction getClosestInstanceFromNode(targetNode) {\n var targetInst = targetNode[internalInstanceKey];\n if (targetInst) return targetInst;\n for (var parentNode = targetNode.parentNode; parentNode; ) {\n if (\n (targetInst =\n parentNode[internalContainerInstanceKey] ||\n parentNode[internalInstanceKey])\n ) {\n parentNode = targetInst.alternate;\n if (\n null !== targetInst.child ||\n (null !== parentNode && null !== parentNode.child)\n )\n for (\n targetNode = getParentHydrationBoundary(targetNode);\n null !== targetNode;\n\n ) {\n if ((parentNode = targetNode[internalInstanceKey])) return parentNode;\n targetNode = getParentHydrationBoundary(targetNode);\n }\n return targetInst;\n }\n targetNode = parentNode;\n parentNode = targetNode.parentNode;\n }\n return null;\n}\nfunction getInstanceFromNode(node) {\n if (\n (node = node[internalInstanceKey] || node[internalContainerInstanceKey])\n ) {\n var tag = node.tag;\n if (\n 5 === tag ||\n 6 === tag ||\n 13 === tag ||\n 31 === tag ||\n 26 === tag ||\n 27 === tag ||\n 3 === tag\n )\n return node;\n }\n return null;\n}\nfunction getNodeFromInstance(inst) {\n var tag = inst.tag;\n if (5 === tag || 26 === tag || 27 === tag || 6 === tag) return inst.stateNode;\n throw Error(formatProdErrorMessage(33));\n}\nfunction getResourcesFromRoot(root) {\n var resources = root[internalRootNodeResourcesKey];\n resources ||\n (resources = root[internalRootNodeResourcesKey] =\n { hoistableStyles: new Map(), hoistableScripts: new Map() });\n return resources;\n}\nfunction markNodeAsHoistable(node) {\n node[internalHoistableMarker] = !0;\n}\nvar allNativeEvents = new Set(),\n registrationNameDependencies = {};\nfunction registerTwoPhaseEvent(registrationName, dependencies) {\n registerDirectEvent(registrationName, dependencies);\n registerDirectEvent(registrationName + \"Capture\", dependencies);\n}\nfunction registerDirectEvent(registrationName, dependencies) {\n registrationNameDependencies[registrationName] = dependencies;\n for (\n registrationName = 0;\n registrationName < dependencies.length;\n registrationName++\n )\n allNativeEvents.add(dependencies[registrationName]);\n}\nvar VALID_ATTRIBUTE_NAME_REGEX = RegExp(\n \"^[: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]*$\"\n ),\n illegalAttributeNameCache = {},\n validatedAttributeNameCache = {};\nfunction isAttributeNameSafe(attributeName) {\n if (hasOwnProperty.call(validatedAttributeNameCache, attributeName))\n return !0;\n if (hasOwnProperty.call(illegalAttributeNameCache, attributeName)) return !1;\n if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName))\n return (validatedAttributeNameCache[attributeName] = !0);\n illegalAttributeNameCache[attributeName] = !0;\n return !1;\n}\nfunction setValueForAttribute(node, name, value) {\n if (isAttributeNameSafe(name))\n if (null === value) node.removeAttribute(name);\n else {\n switch (typeof value) {\n case \"undefined\":\n case \"function\":\n case \"symbol\":\n node.removeAttribute(name);\n return;\n case \"boolean\":\n var prefix$10 = name.toLowerCase().slice(0, 5);\n if (\"data-\" !== prefix$10 && \"aria-\" !== prefix$10) {\n node.removeAttribute(name);\n return;\n }\n }\n node.setAttribute(name, \"\" + value);\n }\n}\nfunction setValueForKnownAttribute(node, name, value) {\n if (null === value) node.removeAttribute(name);\n else {\n switch (typeof value) {\n case \"undefined\":\n case \"function\":\n case \"symbol\":\n case \"boolean\":\n node.removeAttribute(name);\n return;\n }\n node.setAttribute(name, \"\" + value);\n }\n}\nfunction setValueForNamespacedAttribute(node, namespace, name, value) {\n if (null === value) node.removeAttribute(name);\n else {\n switch (typeof value) {\n case \"undefined\":\n case \"function\":\n case \"symbol\":\n case \"boolean\":\n node.removeAttribute(name);\n return;\n }\n node.setAttributeNS(namespace, name, \"\" + value);\n }\n}\nfunction getToStringValue(value) {\n switch (typeof value) {\n case \"bigint\":\n case \"boolean\":\n case \"number\":\n case \"string\":\n case \"undefined\":\n return value;\n case \"object\":\n return value;\n default:\n return \"\";\n }\n}\nfunction isCheckable(elem) {\n var type = elem.type;\n return (\n (elem = elem.nodeName) &&\n \"input\" === elem.toLowerCase() &&\n (\"checkbox\" === type || \"radio\" === type)\n );\n}\nfunction trackValueOnNode(node, valueField, currentValue) {\n var descriptor = Object.getOwnPropertyDescriptor(\n node.constructor.prototype,\n valueField\n );\n if (\n !node.hasOwnProperty(valueField) &&\n \"undefined\" !== typeof descriptor &&\n \"function\" === typeof descriptor.get &&\n \"function\" === typeof descriptor.set\n ) {\n var get = descriptor.get,\n set = descriptor.set;\n Object.defineProperty(node, valueField, {\n configurable: !0,\n get: function () {\n return get.call(this);\n },\n set: function (value) {\n currentValue = \"\" + value;\n set.call(this, value);\n }\n });\n Object.defineProperty(node, valueField, {\n enumerable: descriptor.enumerable\n });\n return {\n getValue: function () {\n return currentValue;\n },\n setValue: function (value) {\n currentValue = \"\" + value;\n },\n stopTracking: function () {\n node._valueTracker = null;\n delete node[valueField];\n }\n };\n }\n}\nfunction track(node) {\n if (!node._valueTracker) {\n var valueField = isCheckable(node) ? \"checked\" : \"value\";\n node._valueTracker = trackValueOnNode(\n node,\n valueField,\n \"\" + node[valueField]\n );\n }\n}\nfunction updateValueIfChanged(node) {\n if (!node) return !1;\n var tracker = node._valueTracker;\n if (!tracker) return !0;\n var lastValue = tracker.getValue();\n var value = \"\";\n node &&\n (value = isCheckable(node)\n ? node.checked\n ? \"true\"\n : \"false\"\n : node.value);\n node = value;\n return node !== lastValue ? (tracker.setValue(node), !0) : !1;\n}\nfunction getActiveElement(doc) {\n doc = doc || (\"undefined\" !== typeof document ? document : void 0);\n if (\"undefined\" === typeof doc) return null;\n try {\n return doc.activeElement || doc.body;\n } catch (e) {\n return doc.body;\n }\n}\nvar escapeSelectorAttributeValueInsideDoubleQuotesRegex = /[\\n\"\\\\]/g;\nfunction escapeSelectorAttributeValueInsideDoubleQuotes(value) {\n return value.replace(\n escapeSelectorAttributeValueInsideDoubleQuotesRegex,\n function (ch) {\n return \"\\\\\" + ch.charCodeAt(0).toString(16) + \" \";\n }\n );\n}\nfunction updateInput(\n element,\n value,\n defaultValue,\n lastDefaultValue,\n checked,\n defaultChecked,\n type,\n name\n) {\n element.name = \"\";\n null != type &&\n \"function\" !== typeof type &&\n \"symbol\" !== typeof type &&\n \"boolean\" !== typeof type\n ? (element.type = type)\n : element.removeAttribute(\"type\");\n if (null != value)\n if (\"number\" === type) {\n if ((0 === value && \"\" === element.value) || element.value != value)\n element.value = \"\" + getToStringValue(value);\n } else\n element.value !== \"\" + getToStringValue(value) &&\n (element.value = \"\" + getToStringValue(value));\n else\n (\"submit\" !== type && \"reset\" !== type) || element.removeAttribute(\"value\");\n null != value\n ? setDefaultValue(element, type, getToStringValue(value))\n : null != defaultValue\n ? setDefaultValue(element, type, getToStringValue(defaultValue))\n : null != lastDefaultValue && element.removeAttribute(\"value\");\n null == checked &&\n null != defaultChecked &&\n (element.defaultChecked = !!defaultChecked);\n null != checked &&\n (element.checked =\n checked && \"function\" !== typeof checked && \"symbol\" !== typeof checked);\n null != name &&\n \"function\" !== typeof name &&\n \"symbol\" !== typeof name &&\n \"boolean\" !== typeof name\n ? (element.name = \"\" + getToStringValue(name))\n : element.removeAttribute(\"name\");\n}\nfunction initInput(\n element,\n value,\n defaultValue,\n checked,\n defaultChecked,\n type,\n name,\n isHydrating\n) {\n null != type &&\n \"function\" !== typeof type &&\n \"symbol\" !== typeof type &&\n \"boolean\" !== typeof type &&\n (element.type = type);\n if (null != value || null != defaultValue) {\n if (\n !(\n (\"submit\" !== type && \"reset\" !== type) ||\n (void 0 !== value && null !== value)\n )\n ) {\n track(element);\n return;\n }\n defaultValue =\n null != defaultValue ? \"\" + getToStringValue(defaultValue) : \"\";\n value = null != value ? \"\" + getToStringValue(value) : defaultValue;\n isHydrating || value === element.value || (element.value = value);\n element.defaultValue = value;\n }\n checked = null != checked ? checked : defaultChecked;\n checked =\n \"function\" !== typeof checked && \"symbol\" !== typeof checked && !!checked;\n element.checked = isHydrating ? element.checked : !!checked;\n element.defaultChecked = !!checked;\n null != name &&\n \"function\" !== typeof name &&\n \"symbol\" !== typeof name &&\n \"boolean\" !== typeof name &&\n (element.name = name);\n track(element);\n}\nfunction setDefaultValue(node, type, value) {\n (\"number\" === type && getActiveElement(node.ownerDocument) === node) ||\n node.defaultValue === \"\" + value ||\n (node.defaultValue = \"\" + value);\n}\nfunction updateOptions(node, multiple, propValue, setDefaultSelected) {\n node = node.options;\n if (multiple) {\n multiple = {};\n for (var i = 0; i < propValue.length; i++)\n multiple[\"$\" + propValue[i]] = !0;\n for (propValue = 0; propValue < node.length; propValue++)\n (i = multiple.hasOwnProperty(\"$\" + node[propValue].value)),\n node[propValue].selected !== i && (node[propValue].selected = i),\n i && setDefaultSelected && (node[propValue].defaultSelected = !0);\n } else {\n propValue = \"\" + getToStringValue(propValue);\n multiple = null;\n for (i = 0; i < node.length; i++) {\n if (node[i].value === propValue) {\n node[i].selected = !0;\n setDefaultSelected && (node[i].defaultSelected = !0);\n return;\n }\n null !== multiple || node[i].disabled || (multiple = node[i]);\n }\n null !== multiple && (multiple.selected = !0);\n }\n}\nfunction updateTextarea(element, value, defaultValue) {\n if (\n null != value &&\n ((value = \"\" + getToStringValue(value)),\n value !== element.value && (element.value = value),\n null == defaultValue)\n ) {\n element.defaultValue !== value && (element.defaultValue = value);\n return;\n }\n element.defaultValue =\n null != defaultValue ? \"\" + getToStringValue(defaultValue) : \"\";\n}\nfunction initTextarea(element, value, defaultValue, children) {\n if (null == value) {\n if (null != children) {\n if (null != defaultValue) throw Error(formatProdErrorMessage(92));\n if (isArrayImpl(children)) {\n if (1 < children.length) throw Error(formatProdErrorMessage(93));\n children = children[0];\n }\n defaultValue = children;\n }\n null == defaultValue && (defaultValue = \"\");\n value = defaultValue;\n }\n defaultValue = getToStringValue(value);\n element.defaultValue = defaultValue;\n children = element.textContent;\n children === defaultValue &&\n \"\" !== children &&\n null !== children &&\n (element.value = children);\n track(element);\n}\nfunction setTextContent(node, text) {\n if (text) {\n var firstChild = node.firstChild;\n if (\n firstChild &&\n firstChild === node.lastChild &&\n 3 === firstChild.nodeType\n ) {\n firstChild.nodeValue = text;\n return;\n }\n }\n node.textContent = text;\n}\nvar unitlessNumbers = new Set(\n \"animationIterationCount aspectRatio borderImageOutset borderImageSlice borderImageWidth boxFlex boxFlexGroup boxOrdinalGroup columnCount columns flex flexGrow flexPositive flexShrink flexNegative flexOrder gridArea gridRow gridRowEnd gridRowSpan gridRowStart gridColumn gridColumnEnd gridColumnSpan gridColumnStart fontWeight lineClamp lineHeight opacity order orphans scale tabSize widows zIndex zoom fillOpacity floodOpacity stopOpacity strokeDasharray strokeDashoffset strokeMiterlimit strokeOpacity strokeWidth MozAnimationIterationCount MozBoxFlex MozBoxFlexGroup MozLineClamp msAnimationIterationCount msFlex msZoom msFlexGrow msFlexNegative msFlexOrder msFlexPositive msFlexShrink msGridColumn msGridColumnSpan msGridRow msGridRowSpan WebkitAnimationIterationCount WebkitBoxFlex WebKitBoxFlexGroup WebkitBoxOrdinalGroup WebkitColumnCount WebkitColumns WebkitFlex WebkitFlexGrow WebkitFlexPositive WebkitFlexShrink WebkitLineClamp\".split(\n \" \"\n )\n);\nfunction setValueForStyle(style, styleName, value) {\n var isCustomProperty = 0 === styleName.indexOf(\"--\");\n null == value || \"boolean\" === typeof value || \"\" === value\n ? isCustomProperty\n ? style.setProperty(styleName, \"\")\n : \"float\" === styleName\n ? (style.cssFloat = \"\")\n : (style[styleName] = \"\")\n : isCustomProperty\n ? style.setProperty(styleName, value)\n : \"number\" !== typeof value ||\n 0 === value ||\n unitlessNumbers.has(styleName)\n ? \"float\" === styleName\n ? (style.cssFloat = value)\n : (style[styleName] = (\"\" + value).trim())\n : (style[styleName] = value + \"px\");\n}\nfunction setValueForStyles(node, styles, prevStyles) {\n if (null != styles && \"object\" !== typeof styles)\n throw Error(formatProdErrorMessage(62));\n node = node.style;\n if (null != prevStyles) {\n for (var styleName in prevStyles)\n !prevStyles.hasOwnProperty(styleName) ||\n (null != styles && styles.hasOwnProperty(styleName)) ||\n (0 === styleName.indexOf(\"--\")\n ? node.setProperty(styleName, \"\")\n : \"float\" === styleName\n ? (node.cssFloat = \"\")\n : (node[styleName] = \"\"));\n for (var styleName$16 in styles)\n (styleName = styles[styleName$16]),\n styles.hasOwnProperty(styleName$16) &&\n prevStyles[styleName$16] !== styleName &&\n setValueForStyle(node, styleName$16, styleName);\n } else\n for (var styleName$17 in styles)\n styles.hasOwnProperty(styleName$17) &&\n setValueForStyle(node, styleName$17, styles[styleName$17]);\n}\nfunction isCustomElement(tagName) {\n if (-1 === tagName.indexOf(\"-\")) return !1;\n switch (tagName) {\n case \"annotation-xml\":\n case \"color-profile\":\n case \"font-face\":\n case \"font-face-src\":\n case \"font-face-uri\":\n case \"font-face-format\":\n case \"font-face-name\":\n case \"missing-glyph\":\n return !1;\n default:\n return !0;\n }\n}\nvar aliases = new Map([\n [\"acceptCharset\", \"accept-charset\"],\n [\"htmlFor\", \"for\"],\n [\"httpEquiv\", \"http-equiv\"],\n [\"crossOrigin\", \"crossorigin\"],\n [\"accentHeight\", \"accent-height\"],\n [\"alignmentBaseline\", \"alignment-baseline\"],\n [\"arabicForm\", \"arabic-form\"],\n [\"baselineShift\", \"baseline-shift\"],\n [\"capHeight\", \"cap-height\"],\n [\"clipPath\", \"clip-path\"],\n [\"clipRule\", \"clip-rule\"],\n [\"colorInterpolation\", \"color-interpolation\"],\n [\"colorInterpolationFilters\", \"color-interpolation-filters\"],\n [\"colorProfile\", \"color-profile\"],\n [\"colorRendering\", \"color-rendering\"],\n [\"dominantBaseline\", \"dominant-baseline\"],\n [\"enableBackground\", \"enable-background\"],\n [\"fillOpacity\", \"fill-opacity\"],\n [\"fillRule\", \"fill-rule\"],\n [\"floodColor\", \"flood-color\"],\n [\"floodOpacity\", \"flood-opacity\"],\n [\"fontFamily\", \"font-family\"],\n [\"fontSize\", \"font-size\"],\n [\"fontSizeAdjust\", \"font-size-adjust\"],\n [\"fontStretch\", \"font-stretch\"],\n [\"fontStyle\", \"font-style\"],\n [\"fontVariant\", \"font-variant\"],\n [\"fontWeight\", \"font-weight\"],\n [\"glyphName\", \"glyph-name\"],\n [\"glyphOrientationHorizontal\", \"glyph-orientation-horizontal\"],\n [\"glyphOrientationVertical\", \"glyph-orientation-vertical\"],\n [\"horizAdvX\", \"horiz-adv-x\"],\n [\"horizOriginX\", \"horiz-origin-x\"],\n [\"imageRendering\", \"image-rendering\"],\n [\"letterSpacing\", \"letter-spacing\"],\n [\"lightingColor\", \"lighting-color\"],\n [\"markerEnd\", \"marker-end\"],\n [\"markerMid\", \"marker-mid\"],\n [\"markerStart\", \"marker-start\"],\n [\"overlinePosition\", \"overline-position\"],\n [\"overlineThickness\", \"overline-thickness\"],\n [\"paintOrder\", \"paint-order\"],\n [\"panose-1\", \"panose-1\"],\n [\"pointerEvents\", \"pointer-events\"],\n [\"renderingIntent\", \"rendering-intent\"],\n [\"shapeRendering\", \"shape-rendering\"],\n [\"stopColor\", \"stop-color\"],\n [\"stopOpacity\", \"stop-opacity\"],\n [\"strikethroughPosition\", \"strikethrough-position\"],\n [\"strikethroughThickness\", \"strikethrough-thickness\"],\n [\"strokeDasharray\", \"stroke-dasharray\"],\n [\"strokeDashoffset\", \"stroke-dashoffset\"],\n [\"strokeLinecap\", \"stroke-linecap\"],\n [\"strokeLinejoin\", \"stroke-linejoin\"],\n [\"strokeMiterlimit\", \"stroke-miterlimit\"],\n [\"strokeOpacity\", \"stroke-opacity\"],\n [\"strokeWidth\", \"stroke-width\"],\n [\"textAnchor\", \"text-anchor\"],\n [\"textDecoration\", \"text-decoration\"],\n [\"textRendering\", \"text-rendering\"],\n [\"transformOrigin\", \"transform-origin\"],\n [\"underlinePosition\", \"underline-position\"],\n [\"underlineThickness\", \"underline-thickness\"],\n [\"unicodeBidi\", \"unicode-bidi\"],\n [\"unicodeRange\", \"unicode-range\"],\n [\"unitsPerEm\", \"units-per-em\"],\n [\"vAlphabetic\", \"v-alphabetic\"],\n [\"vHanging\", \"v-hanging\"],\n [\"vIdeographic\", \"v-ideographic\"],\n [\"vMathematical\", \"v-mathematical\"],\n [\"vectorEffect\", \"vector-effect\"],\n [\"vertAdvY\", \"vert-adv-y\"],\n [\"vertOriginX\", \"vert-origin-x\"],\n [\"vertOriginY\", \"vert-origin-y\"],\n [\"wordSpacing\", \"word-spacing\"],\n [\"writingMode\", \"writing-mode\"],\n [\"xmlnsXlink\", \"xmlns:xlink\"],\n [\"xHeight\", \"x-height\"]\n ]),\n isJavaScriptProtocol =\n /^[\\u0000-\\u001F ]*j[\\r\\n\\t]*a[\\r\\n\\t]*v[\\r\\n\\t]*a[\\r\\n\\t]*s[\\r\\n\\t]*c[\\r\\n\\t]*r[\\r\\n\\t]*i[\\r\\n\\t]*p[\\r\\n\\t]*t[\\r\\n\\t]*:/i;\nfunction sanitizeURL(url) {\n return isJavaScriptProtocol.test(\"\" + url)\n ? \"javascript:throw new Error('React has blocked a javascript: URL as a security precaution.')\"\n : url;\n}\nfunction noop$1() {}\nvar currentReplayingEvent = null;\nfunction getEventTarget(nativeEvent) {\n nativeEvent = nativeEvent.target || nativeEvent.srcElement || window;\n nativeEvent.correspondingUseElement &&\n (nativeEvent = nativeEvent.correspondingUseElement);\n return 3 === nativeEvent.nodeType ? nativeEvent.parentNode : nativeEvent;\n}\nvar restoreTarget = null,\n restoreQueue = null;\nfunction restoreStateOfTarget(target) {\n var internalInstance = getInstanceFromNode(target);\n if (internalInstance && (target = internalInstance.stateNode)) {\n var props = target[internalPropsKey] || null;\n a: switch (((target = internalInstance.stateNode), internalInstance.type)) {\n case \"input\":\n updateInput(\n target,\n props.value,\n props.defaultValue,\n props.defaultValue,\n props.checked,\n props.defaultChecked,\n props.type,\n props.name\n );\n internalInstance = props.name;\n if (\"radio\" === props.type && null != internalInstance) {\n for (props = target; props.parentNode; ) props = props.parentNode;\n props = props.querySelectorAll(\n 'input[name=\"' +\n escapeSelectorAttributeValueInsideDoubleQuotes(\n \"\" + internalInstance\n ) +\n '\"][type=\"radio\"]'\n );\n for (\n internalInstance = 0;\n internalInstance < props.length;\n internalInstance++\n ) {\n var otherNode = props[internalInstance];\n if (otherNode !== target && otherNode.form === target.form) {\n var otherProps = otherNode[internalPropsKey] || null;\n if (!otherProps) throw Error(formatProdErrorMessage(90));\n updateInput(\n otherNode,\n otherProps.value,\n otherProps.defaultValue,\n otherProps.defaultValue,\n otherProps.checked,\n otherProps.defaultChecked,\n otherProps.type,\n otherProps.name\n );\n }\n }\n for (\n internalInstance = 0;\n internalInstance < props.length;\n internalInstance++\n )\n (otherNode = props[internalInstance]),\n otherNode.form === target.form && updateValueIfChanged(otherNode);\n }\n break a;\n case \"textarea\":\n updateTextarea(target, props.value, props.defaultValue);\n break a;\n case \"select\":\n (internalInstance = props.value),\n null != internalInstance &&\n updateOptions(target, !!props.multiple, internalInstance, !1);\n }\n }\n}\nvar isInsideEventHandler = !1;\nfunction batchedUpdates$1(fn, a, b) {\n if (isInsideEventHandler) return fn(a, b);\n isInsideEventHandler = !0;\n try {\n var JSCompiler_inline_result = fn(a);\n return JSCompiler_inline_result;\n } finally {\n if (\n ((isInsideEventHandler = !1),\n null !== restoreTarget || null !== restoreQueue)\n )\n if (\n (flushSyncWork$1(),\n restoreTarget &&\n ((a = restoreTarget),\n (fn = restoreQueue),\n (restoreQueue = restoreTarget = null),\n restoreStateOfTarget(a),\n fn))\n )\n for (a = 0; a < fn.length; a++) restoreStateOfTarget(fn[a]);\n }\n}\nfunction getListener(inst, registrationName) {\n var stateNode = inst.stateNode;\n if (null === stateNode) return null;\n var props = stateNode[internalPropsKey] || null;\n if (null === props) return null;\n stateNode = props[registrationName];\n a: switch (registrationName) {\n case \"onClick\":\n case \"onClickCapture\":\n case \"onDoubleClick\":\n case \"onDoubleClickCapture\":\n case \"onMouseDown\":\n case \"onMouseDownCapture\":\n case \"onMouseMove\":\n case \"onMouseMoveCapture\":\n case \"onMouseUp\":\n case \"onMouseUpCapture\":\n case \"onMouseEnter\":\n (props = !props.disabled) ||\n ((inst = inst.type),\n (props = !(\n \"button\" === inst ||\n \"input\" === inst ||\n \"select\" === inst ||\n \"textarea\" === inst\n )));\n inst = !props;\n break a;\n default:\n inst = !1;\n }\n if (inst) return null;\n if (stateNode && \"function\" !== typeof stateNode)\n throw Error(\n formatProdErrorMessage(231, registrationName, typeof stateNode)\n );\n return stateNode;\n}\nvar canUseDOM = !(\n \"undefined\" === typeof window ||\n \"undefined\" === typeof window.document ||\n \"undefined\" === typeof window.document.createElement\n ),\n passiveBrowserEventsSupported = !1;\nif (canUseDOM)\n try {\n var options = {};\n Object.defineProperty(options, \"passive\", {\n get: function () {\n passiveBrowserEventsSupported = !0;\n }\n });\n window.addEventListener(\"test\", options, options);\n window.removeEventListener(\"test\", options, options);\n } catch (e) {\n passiveBrowserEventsSupported = !1;\n }\nvar root = null,\n startText = null,\n fallbackText = null;\nfunction getData() {\n if (fallbackText) return fallbackText;\n var start,\n startValue = startText,\n startLength = startValue.length,\n end,\n endValue = \"value\" in root ? root.value : root.textContent,\n endLength = endValue.length;\n for (\n start = 0;\n start < startLength && startValue[start] === endValue[start];\n start++\n );\n var minEnd = startLength - start;\n for (\n end = 1;\n end <= minEnd &&\n startValue[startLength - end] === endValue[endLength - end];\n end++\n );\n return (fallbackText = endValue.slice(start, 1 < end ? 1 - end : void 0));\n}\nfunction getEventCharCode(nativeEvent) {\n var keyCode = nativeEvent.keyCode;\n \"charCode\" in nativeEvent\n ? ((nativeEvent = nativeEvent.charCode),\n 0 === nativeEvent && 13 === keyCode && (nativeEvent = 13))\n : (nativeEvent = keyCode);\n 10 === nativeEvent && (nativeEvent = 13);\n return 32 <= nativeEvent || 13 === nativeEvent ? nativeEvent : 0;\n}\nfunction functionThatReturnsTrue() {\n return !0;\n}\nfunction functionThatReturnsFalse() {\n return !1;\n}\nfunction createSyntheticEvent(Interface) {\n function SyntheticBaseEvent(\n reactName,\n reactEventType,\n targetInst,\n nativeEvent,\n nativeEventTarget\n ) {\n this._reactName = reactName;\n this._targetInst = targetInst;\n this.type = reactEventType;\n this.nativeEvent = nativeEvent;\n this.target = nativeEventTarget;\n this.currentTarget = null;\n for (var propName in Interface)\n Interface.hasOwnProperty(propName) &&\n ((reactName = Interface[propName]),\n (this[propName] = reactName\n ? reactName(nativeEvent)\n : nativeEvent[propName]));\n this.isDefaultPrevented = (\n null != nativeEvent.defaultPrevented\n ? nativeEvent.defaultPrevented\n : !1 === nativeEvent.returnValue\n )\n ? functionThatReturnsTrue\n : functionThatReturnsFalse;\n this.isPropagationStopped = functionThatReturnsFalse;\n return this;\n }\n assign(SyntheticBaseEvent.prototype, {\n preventDefault: function () {\n this.defaultPrevented = !0;\n var event = this.nativeEvent;\n event &&\n (event.preventDefault\n ? event.preventDefault()\n : \"unknown\" !== typeof event.returnValue && (event.returnValue = !1),\n (this.isDefaultPrevented = functionThatReturnsTrue));\n },\n stopPropagation: function () {\n var event = this.nativeEvent;\n event &&\n (event.stopPropagation\n ? event.stopPropagation()\n : \"unknown\" !== typeof event.cancelBubble &&\n (event.cancelBubble = !0),\n (this.isPropagationStopped = functionThatReturnsTrue));\n },\n persist: function () {},\n isPersistent: functionThatReturnsTrue\n });\n return SyntheticBaseEvent;\n}\nvar EventInterface = {\n eventPhase: 0,\n bubbles: 0,\n cancelable: 0,\n timeStamp: function (event) {\n return event.timeStamp || Date.now();\n },\n defaultPrevented: 0,\n isTrusted: 0\n },\n SyntheticEvent = createSyntheticEvent(EventInterface),\n UIEventInterface = assign({}, EventInterface, { view: 0, detail: 0 }),\n SyntheticUIEvent = createSyntheticEvent(UIEventInterface),\n lastMovementX,\n lastMovementY,\n lastMouseEvent,\n MouseEventInterface = assign({}, UIEventInterface, {\n screenX: 0,\n screenY: 0,\n clientX: 0,\n clientY: 0,\n pageX: 0,\n pageY: 0,\n ctrlKey: 0,\n shiftKey: 0,\n altKey: 0,\n metaKey: 0,\n getModifierState: getEventModifierState,\n button: 0,\n buttons: 0,\n relatedTarget: function (event) {\n return void 0 === event.relatedTarget\n ? event.fromElement === event.srcElement\n ? event.toElement\n : event.fromElement\n : event.relatedTarget;\n },\n movementX: function (event) {\n if (\"movementX\" in event) return event.movementX;\n event !== lastMouseEvent &&\n (lastMouseEvent && \"mousemove\" === event.type\n ? ((lastMovementX = event.screenX - lastMouseEvent.screenX),\n (lastMovementY = event.screenY - lastMouseEvent.screenY))\n : (lastMovementY = lastMovementX = 0),\n (lastMouseEvent = event));\n return lastMovementX;\n },\n movementY: function (event) {\n return \"movementY\" in event ? event.movementY : lastMovementY;\n }\n }),\n SyntheticMouseEvent = createSyntheticEvent(MouseEventInterface),\n DragEventInterface = assign({}, MouseEventInterface, { dataTransfer: 0 }),\n SyntheticDragEvent = createSyntheticEvent(DragEventInterface),\n FocusEventInterface = assign({}, UIEventInterface, { relatedTarget: 0 }),\n SyntheticFocusEvent = createSyntheticEvent(FocusEventInterface),\n AnimationEventInterface = assign({}, EventInterface, {\n animationName: 0,\n elapsedTime: 0,\n pseudoElement: 0\n }),\n SyntheticAnimationEvent = createSyntheticEvent(AnimationEventInterface),\n ClipboardEventInterface = assign({}, EventInterface, {\n clipboardData: function (event) {\n return \"clipboardData\" in event\n ? event.clipboardData\n : window.clipboardData;\n }\n }),\n SyntheticClipboardEvent = createSyntheticEvent(ClipboardEventInterface),\n CompositionEventInterface = assign({}, EventInterface, { data: 0 }),\n SyntheticCompositionEvent = createSyntheticEvent(CompositionEventInterface),\n normalizeKey = {\n Esc: \"Escape\",\n Spacebar: \" \",\n Left: \"ArrowLeft\",\n Up: \"ArrowUp\",\n Right: \"ArrowRight\",\n Down: \"ArrowDown\",\n Del: \"Delete\",\n Win: \"OS\",\n Menu: \"ContextMenu\",\n Apps: \"ContextMenu\",\n Scroll: \"ScrollLock\",\n MozPrintableKey: \"Unidentified\"\n },\n translateToKey = {\n 8: \"Backspace\",\n 9: \"Tab\",\n 12: \"Clear\",\n 13: \"Enter\",\n 16: \"Shift\",\n 17: \"Control\",\n 18: \"Alt\",\n 19: \"Pause\",\n 20: \"CapsLock\",\n 27: \"Escape\",\n 32: \" \",\n 33: \"PageUp\",\n 34: \"PageDown\",\n 35: \"End\",\n 36: \"Home\",\n 37: \"ArrowLeft\",\n 38: \"ArrowUp\",\n 39: \"ArrowRight\",\n 40: \"ArrowDown\",\n 45: \"Insert\",\n 46: \"Delete\",\n 112: \"F1\",\n 113: \"F2\",\n 114: \"F3\",\n 115: \"F4\",\n 116: \"F5\",\n 117: \"F6\",\n 118: \"F7\",\n 119: \"F8\",\n 120: \"F9\",\n 121: \"F10\",\n 122: \"F11\",\n 123: \"F12\",\n 144: \"NumLock\",\n 145: \"ScrollLock\",\n 224: \"Meta\"\n },\n modifierKeyToProp = {\n Alt: \"altKey\",\n Control: \"ctrlKey\",\n Meta: \"metaKey\",\n Shift: \"shiftKey\"\n };\nfunction modifierStateGetter(keyArg) {\n var nativeEvent = this.nativeEvent;\n return nativeEvent.getModifierState\n ? nativeEvent.getModifierState(keyArg)\n : (keyArg = modifierKeyToProp[keyArg])\n ? !!nativeEvent[keyArg]\n : !1;\n}\nfunction getEventModifierState() {\n return modifierStateGetter;\n}\nvar KeyboardEventInterface = assign({}, UIEventInterface, {\n key: function (nativeEvent) {\n if (nativeEvent.key) {\n var key = normalizeKey[nativeEvent.key] || nativeEvent.key;\n if (\"Unidentified\" !== key) return key;\n }\n return \"keypress\" === nativeEvent.type\n ? ((nativeEvent = getEventCharCode(nativeEvent)),\n 13 === nativeEvent ? \"Enter\" : String.fromCharCode(nativeEvent))\n : \"keydown\" === nativeEvent.type || \"keyup\" === nativeEvent.type\n ? translateToKey[nativeEvent.keyCode] || \"Unidentified\"\n : \"\";\n },\n code: 0,\n location: 0,\n ctrlKey: 0,\n shiftKey: 0,\n altKey: 0,\n metaKey: 0,\n repeat: 0,\n locale: 0,\n getModifierState: getEventModifierState,\n charCode: function (event) {\n return \"keypress\" === event.type ? getEventCharCode(event) : 0;\n },\n keyCode: function (event) {\n return \"keydown\" === event.type || \"keyup\" === event.type\n ? event.keyCode\n : 0;\n },\n which: function (event) {\n return \"keypress\" === event.type\n ? getEventCharCode(event)\n : \"keydown\" === event.type || \"keyup\" === event.type\n ? event.keyCode\n : 0;\n }\n }),\n SyntheticKeyboardEvent = createSyntheticEvent(KeyboardEventInterface),\n PointerEventInterface = assign({}, MouseEventInterface, {\n pointerId: 0,\n width: 0,\n height: 0,\n pressure: 0,\n tangentialPressure: 0,\n tiltX: 0,\n tiltY: 0,\n twist: 0,\n pointerType: 0,\n isPrimary: 0\n }),\n SyntheticPointerEvent = createSyntheticEvent(PointerEventInterface),\n TouchEventInterface = assign({}, UIEventInterface, {\n touches: 0,\n targetTouches: 0,\n changedTouches: 0,\n altKey: 0,\n metaKey: 0,\n ctrlKey: 0,\n shiftKey: 0,\n getModifierState: getEventModifierState\n }),\n SyntheticTouchEvent = createSyntheticEvent(TouchEventInterface),\n TransitionEventInterface = assign({}, EventInterface, {\n propertyName: 0,\n elapsedTime: 0,\n pseudoElement: 0\n }),\n SyntheticTransitionEvent = createSyntheticEvent(TransitionEventInterface),\n WheelEventInterface = assign({}, MouseEventInterface, {\n deltaX: function (event) {\n return \"deltaX\" in event\n ? event.deltaX\n : \"wheelDeltaX\" in event\n ? -event.wheelDeltaX\n : 0;\n },\n deltaY: function (event) {\n return \"deltaY\" in event\n ? event.deltaY\n : \"wheelDeltaY\" in event\n ? -event.wheelDeltaY\n : \"wheelDelta\" in event\n ? -event.wheelDelta\n : 0;\n },\n deltaZ: 0,\n deltaMode: 0\n }),\n SyntheticWheelEvent = createSyntheticEvent(WheelEventInterface),\n ToggleEventInterface = assign({}, EventInterface, {\n newState: 0,\n oldState: 0\n }),\n SyntheticToggleEvent = createSyntheticEvent(ToggleEventInterface),\n END_KEYCODES = [9, 13, 27, 32],\n canUseCompositionEvent = canUseDOM && \"CompositionEvent\" in window,\n documentMode = null;\ncanUseDOM &&\n \"documentMode\" in document &&\n (documentMode = document.documentMode);\nvar canUseTextInputEvent = canUseDOM && \"TextEvent\" in window && !documentMode,\n useFallbackCompositionData =\n canUseDOM &&\n (!canUseCompositionEvent ||\n (documentMode && 8 < documentMode && 11 >= documentMode)),\n SPACEBAR_CHAR = String.fromCharCode(32),\n hasSpaceKeypress = !1;\nfunction isFallbackCompositionEnd(domEventName, nativeEvent) {\n switch (domEventName) {\n case \"keyup\":\n return -1 !== END_KEYCODES.indexOf(nativeEvent.keyCode);\n case \"keydown\":\n return 229 !== nativeEvent.keyCode;\n case \"keypress\":\n case \"mousedown\":\n case \"focusout\":\n return !0;\n default:\n return !1;\n }\n}\nfunction getDataFromCustomEvent(nativeEvent) {\n nativeEvent = nativeEvent.detail;\n return \"object\" === typeof nativeEvent && \"data\" in nativeEvent\n ? nativeEvent.data\n : null;\n}\nvar isComposing = !1;\nfunction getNativeBeforeInputChars(domEventName, nativeEvent) {\n switch (domEventName) {\n case \"compositionend\":\n return getDataFromCustomEvent(nativeEvent);\n case \"keypress\":\n if (32 !== nativeEvent.which) return null;\n hasSpaceKeypress = !0;\n return SPACEBAR_CHAR;\n case \"textInput\":\n return (\n (domEventName = nativeEvent.data),\n domEventName === SPACEBAR_CHAR && hasSpaceKeypress ? null : domEventName\n );\n default:\n return null;\n }\n}\nfunction getFallbackBeforeInputChars(domEventName, nativeEvent) {\n if (isComposing)\n return \"compositionend\" === domEventName ||\n (!canUseCompositionEvent &&\n isFallbackCompositionEnd(domEventName, nativeEvent))\n ? ((domEventName = getData()),\n (fallbackText = startText = root = null),\n (isComposing = !1),\n domEventName)\n : null;\n switch (domEventName) {\n case \"paste\":\n return null;\n case \"keypress\":\n if (\n !(nativeEvent.ctrlKey || nativeEvent.altKey || nativeEvent.metaKey) ||\n (nativeEvent.ctrlKey && nativeEvent.altKey)\n ) {\n if (nativeEvent.char && 1 < nativeEvent.char.length)\n return nativeEvent.char;\n if (nativeEvent.which) return String.fromCharCode(nativeEvent.which);\n }\n return null;\n case \"compositionend\":\n return useFallbackCompositionData && \"ko\" !== nativeEvent.locale\n ? null\n : nativeEvent.data;\n default:\n return null;\n }\n}\nvar supportedInputTypes = {\n color: !0,\n date: !0,\n datetime: !0,\n \"datetime-local\": !0,\n email: !0,\n month: !0,\n number: !0,\n password: !0,\n range: !0,\n search: !0,\n tel: !0,\n text: !0,\n time: !0,\n url: !0,\n week: !0\n};\nfunction isTextInputElement(elem) {\n var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();\n return \"input\" === nodeName\n ? !!supportedInputTypes[elem.type]\n : \"textarea\" === nodeName\n ? !0\n : !1;\n}\nfunction createAndAccumulateChangeEvent(\n dispatchQueue,\n inst,\n nativeEvent,\n target\n) {\n restoreTarget\n ? restoreQueue\n ? restoreQueue.push(target)\n : (restoreQueue = [target])\n : (restoreTarget = target);\n inst = accumulateTwoPhaseListeners(inst, \"onChange\");\n 0 < inst.length &&\n ((nativeEvent = new SyntheticEvent(\n \"onChange\",\n \"change\",\n null,\n nativeEvent,\n target\n )),\n dispatchQueue.push({ event: nativeEvent, listeners: inst }));\n}\nvar activeElement$1 = null,\n activeElementInst$1 = null;\nfunction runEventInBatch(dispatchQueue) {\n processDispatchQueue(dispatchQueue, 0);\n}\nfunction getInstIfValueChanged(targetInst) {\n var targetNode = getNodeFromInstance(targetInst);\n if (updateValueIfChanged(targetNode)) return targetInst;\n}\nfunction getTargetInstForChangeEvent(domEventName, targetInst) {\n if (\"change\" === domEventName) return targetInst;\n}\nvar isInputEventSupported = !1;\nif (canUseDOM) {\n var JSCompiler_inline_result$jscomp$286;\n if (canUseDOM) {\n var isSupported$jscomp$inline_427 = \"oninput\" in document;\n if (!isSupported$jscomp$inline_427) {\n var element$jscomp$inline_428 = document.createElement(\"div\");\n element$jscomp$inline_428.setAttribute(\"oninput\", \"return;\");\n isSupported$jscomp$inline_427 =\n \"function\" === typeof element$jscomp$inline_428.oninput;\n }\n JSCompiler_inline_result$jscomp$286 = isSupported$jscomp$inline_427;\n } else JSCompiler_inline_result$jscomp$286 = !1;\n isInputEventSupported =\n JSCompiler_inline_result$jscomp$286 &&\n (!document.documentMode || 9 < document.documentMode);\n}\nfunction stopWatchingForValueChange() {\n activeElement$1 &&\n (activeElement$1.detachEvent(\"onpropertychange\", handlePropertyChange),\n (activeElementInst$1 = activeElement$1 = null));\n}\nfunction handlePropertyChange(nativeEvent) {\n if (\n \"value\" === nativeEvent.propertyName &&\n getInstIfValueChanged(activeElementInst$1)\n ) {\n var dispatchQueue = [];\n createAndAccumulateChangeEvent(\n dispatchQueue,\n activeElementInst$1,\n nativeEvent,\n getEventTarget(nativeEvent)\n );\n batchedUpdates$1(runEventInBatch, dispatchQueue);\n }\n}\nfunction handleEventsForInputEventPolyfill(domEventName, target, targetInst) {\n \"focusin\" === domEventName\n ? (stopWatchingForValueChange(),\n (activeElement$1 = target),\n (activeElementInst$1 = targetInst),\n activeElement$1.attachEvent(\"onpropertychange\", handlePropertyChange))\n : \"focusout\" === domEventName && stopWatchingForValueChange();\n}\nfunction getTargetInstForInputEventPolyfill(domEventName) {\n if (\n \"selectionchange\" === domEventName ||\n \"keyup\" === domEventName ||\n \"keydown\" === domEventName\n )\n return getInstIfValueChanged(activeElementInst$1);\n}\nfunction getTargetInstForClickEvent(domEventName, targetInst) {\n if (\"click\" === domEventName) return getInstIfValueChanged(targetInst);\n}\nfunction getTargetInstForInputOrChangeEvent(domEventName, targetInst) {\n if (\"input\" === domEventName || \"change\" === domEventName)\n return getInstIfValueChanged(targetInst);\n}\nfunction is(x, y) {\n return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y);\n}\nvar objectIs = \"function\" === typeof Object.is ? Object.is : is;\nfunction shallowEqual(objA, objB) {\n if (objectIs(objA, objB)) return !0;\n if (\n \"object\" !== typeof objA ||\n null === objA ||\n \"object\" !== typeof objB ||\n null === objB\n )\n return !1;\n var keysA = Object.keys(objA),\n keysB = Object.keys(objB);\n if (keysA.length !== keysB.length) return !1;\n for (keysB = 0; keysB < keysA.length; keysB++) {\n var currentKey = keysA[keysB];\n if (\n !hasOwnProperty.call(objB, currentKey) ||\n !objectIs(objA[currentKey], objB[currentKey])\n )\n return !1;\n }\n return !0;\n}\nfunction getLeafNode(node) {\n for (; node && node.firstChild; ) node = node.firstChild;\n return node;\n}\nfunction getNodeForCharacterOffset(root, offset) {\n var node = getLeafNode(root);\n root = 0;\n for (var nodeEnd; node; ) {\n if (3 === node.nodeType) {\n nodeEnd = root + node.textContent.length;\n if (root <= offset && nodeEnd >= offset)\n return { node: node, offset: offset - root };\n root = nodeEnd;\n }\n a: {\n for (; node; ) {\n if (node.nextSibling) {\n node = node.nextSibling;\n break a;\n }\n node = node.parentNode;\n }\n node = void 0;\n }\n node = getLeafNode(node);\n }\n}\nfunction containsNode(outerNode, innerNode) {\n return outerNode && innerNode\n ? outerNode === innerNode\n ? !0\n : outerNode && 3 === outerNode.nodeType\n ? !1\n : innerNode && 3 === innerNode.nodeType\n ? containsNode(outerNode, innerNode.parentNode)\n : \"contains\" in outerNode\n ? outerNode.contains(innerNode)\n : outerNode.compareDocumentPosition\n ? !!(outerNode.compareDocumentPosition(innerNode) & 16)\n : !1\n : !1;\n}\nfunction getActiveElementDeep(containerInfo) {\n containerInfo =\n null != containerInfo &&\n null != containerInfo.ownerDocument &&\n null != containerInfo.ownerDocument.defaultView\n ? containerInfo.ownerDocument.defaultView\n : window;\n for (\n var element = getActiveElement(containerInfo.document);\n element instanceof containerInfo.HTMLIFrameElement;\n\n ) {\n try {\n var JSCompiler_inline_result =\n \"string\" === typeof element.contentWindow.location.href;\n } catch (err) {\n JSCompiler_inline_result = !1;\n }\n if (JSCompiler_inline_result) containerInfo = element.contentWindow;\n else break;\n element = getActiveElement(containerInfo.document);\n }\n return element;\n}\nfunction hasSelectionCapabilities(elem) {\n var nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();\n return (\n nodeName &&\n ((\"input\" === nodeName &&\n (\"text\" === elem.type ||\n \"search\" === elem.type ||\n \"tel\" === elem.type ||\n \"url\" === elem.type ||\n \"password\" === elem.type)) ||\n \"textarea\" === nodeName ||\n \"true\" === elem.contentEditable)\n );\n}\nvar skipSelectionChangeEvent =\n canUseDOM && \"documentMode\" in document && 11 >= document.documentMode,\n activeElement = null,\n activeElementInst = null,\n lastSelection = null,\n mouseDown = !1;\nfunction constructSelectEvent(dispatchQueue, nativeEvent, nativeEventTarget) {\n var doc =\n nativeEventTarget.window === nativeEventTarget\n ? nativeEventTarget.document\n : 9 === nativeEventTarget.nodeType\n ? nativeEventTarget\n : nativeEventTarget.ownerDocument;\n mouseDown ||\n null == activeElement ||\n activeElement !== getActiveElement(doc) ||\n ((doc = activeElement),\n \"selectionStart\" in doc && hasSelectionCapabilities(doc)\n ? (doc = { start: doc.selectionStart, end: doc.selectionEnd })\n : ((doc = (\n (doc.ownerDocument && doc.ownerDocument.defaultView) ||\n window\n ).getSelection()),\n (doc = {\n anchorNode: doc.anchorNode,\n anchorOffset: doc.anchorOffset,\n focusNode: doc.focusNode,\n focusOffset: doc.focusOffset\n })),\n (lastSelection && shallowEqual(lastSelection, doc)) ||\n ((lastSelection = doc),\n (doc = accumulateTwoPhaseListeners(activeElementInst, \"onSelect\")),\n 0 < doc.length &&\n ((nativeEvent = new SyntheticEvent(\n \"onSelect\",\n \"select\",\n null,\n nativeEvent,\n nativeEventTarget\n )),\n dispatchQueue.push({ event: nativeEvent, listeners: doc }),\n (nativeEvent.target = activeElement))));\n}\nfunction makePrefixMap(styleProp, eventName) {\n var prefixes = {};\n prefixes[styleProp.toLowerCase()] = eventName.toLowerCase();\n prefixes[\"Webkit\" + styleProp] = \"webkit\" + eventName;\n prefixes[\"Moz\" + styleProp] = \"moz\" + eventName;\n return prefixes;\n}\nvar vendorPrefixes = {\n animationend: makePrefixMap(\"Animation\", \"AnimationEnd\"),\n animationiteration: makePrefixMap(\"Animation\", \"AnimationIteration\"),\n animationstart: makePrefixMap(\"Animation\", \"AnimationStart\"),\n transitionrun: makePrefixMap(\"Transition\", \"TransitionRun\"),\n transitionstart: makePrefixMap(\"Transition\", \"TransitionStart\"),\n transitioncancel: makePrefixMap(\"Transition\", \"TransitionCancel\"),\n transitionend: makePrefixMap(\"Transition\", \"TransitionEnd\")\n },\n prefixedEventNames = {},\n style = {};\ncanUseDOM &&\n ((style = document.createElement(\"div\").style),\n \"AnimationEvent\" in window ||\n (delete vendorPrefixes.animationend.animation,\n delete vendorPrefixes.animationiteration.animation,\n delete vendorPrefixes.animationstart.animation),\n \"TransitionEvent\" in window ||\n delete vendorPrefixes.transitionend.transition);\nfunction getVendorPrefixedEventName(eventName) {\n if (prefixedEventNames[eventName]) return prefixedEventNames[eventName];\n if (!vendorPrefixes[eventName]) return eventName;\n var prefixMap = vendorPrefixes[eventName],\n styleProp;\n for (styleProp in prefixMap)\n if (prefixMap.hasOwnProperty(styleProp) && styleProp in style)\n return (prefixedEventNames[eventName] = prefixMap[styleProp]);\n return eventName;\n}\nvar ANIMATION_END = getVendorPrefixedEventName(\"animationend\"),\n ANIMATION_ITERATION = getVendorPrefixedEventName(\"animationiteration\"),\n ANIMATION_START = getVendorPrefixedEventName(\"animationstart\"),\n TRANSITION_RUN = getVendorPrefixedEventName(\"transitionrun\"),\n TRANSITION_START = getVendorPrefixedEventName(\"transitionstart\"),\n TRANSITION_CANCEL = getVendorPrefixedEventName(\"transitioncancel\"),\n TRANSITION_END = getVendorPrefixedEventName(\"transitionend\"),\n topLevelEventsToReactNames = new Map(),\n simpleEventPluginEvents =\n \"abort auxClick beforeToggle cancel canPlay canPlayThrough click close contextMenu copy cut drag dragEnd dragEnter dragExit dragLeave dragOver dragStart drop durationChange emptied encrypted ended error gotPointerCapture input invalid keyDown keyPress keyUp load loadedData loadedMetadata loadStart lostPointerCapture mouseDown mouseMove mouseOut mouseOver mouseUp paste pause play playing pointerCancel pointerDown pointerMove pointerOut pointerOver pointerUp progress rateChange reset resize seeked seeking stalled submit suspend timeUpdate touchCancel touchEnd touchStart volumeChange scroll toggle touchMove waiting wheel\".split(\n \" \"\n );\nsimpleEventPluginEvents.push(\"scrollEnd\");\nfunction registerSimpleEvent(domEventName, reactName) {\n topLevelEventsToReactNames.set(domEventName, reactName);\n registerTwoPhaseEvent(reactName, [domEventName]);\n}\nvar reportGlobalError =\n \"function\" === typeof reportError\n ? reportError\n : function (error) {\n if (\n \"object\" === typeof window &&\n \"function\" === typeof window.ErrorEvent\n ) {\n var event = new window.ErrorEvent(\"error\", {\n bubbles: !0,\n cancelable: !0,\n message:\n \"object\" === typeof error &&\n null !== error &&\n \"string\" === typeof error.message\n ? String(error.message)\n : String(error),\n error: error\n });\n if (!window.dispatchEvent(event)) return;\n } else if (\n \"object\" === typeof process &&\n \"function\" === typeof process.emit\n ) {\n process.emit(\"uncaughtException\", error);\n return;\n }\n console.error(error);\n },\n concurrentQueues = [],\n concurrentQueuesIndex = 0,\n concurrentlyUpdatedLanes = 0;\nfunction finishQueueingConcurrentUpdates() {\n for (\n var endIndex = concurrentQueuesIndex,\n i = (concurrentlyUpdatedLanes = concurrentQueuesIndex = 0);\n i < endIndex;\n\n ) {\n var fiber = concurrentQueues[i];\n concurrentQueues[i++] = null;\n var queue = concurrentQueues[i];\n concurrentQueues[i++] = null;\n var update = concurrentQueues[i];\n concurrentQueues[i++] = null;\n var lane = concurrentQueues[i];\n concurrentQueues[i++] = null;\n if (null !== queue && null !== update) {\n var pending = queue.pending;\n null === pending\n ? (update.next = update)\n : ((update.next = pending.next), (pending.next = update));\n queue.pending = update;\n }\n 0 !== lane && markUpdateLaneFromFiberToRoot(fiber, update, lane);\n }\n}\nfunction enqueueUpdate$1(fiber, queue, update, lane) {\n concurrentQueues[concurrentQueuesIndex++] = fiber;\n concurrentQueues[concurrentQueuesIndex++] = queue;\n concurrentQueues[concurrentQueuesIndex++] = update;\n concurrentQueues[concurrentQueuesIndex++] = lane;\n concurrentlyUpdatedLanes |= lane;\n fiber.lanes |= lane;\n fiber = fiber.alternate;\n null !== fiber && (fiber.lanes |= lane);\n}\nfunction enqueueConcurrentHookUpdate(fiber, queue, update, lane) {\n enqueueUpdate$1(fiber, queue, update, lane);\n return getRootForUpdatedFiber(fiber);\n}\nfunction enqueueConcurrentRenderForLane(fiber, lane) {\n enqueueUpdate$1(fiber, null, null, lane);\n return getRootForUpdatedFiber(fiber);\n}\nfunction markUpdateLaneFromFiberToRoot(sourceFiber, update, lane) {\n sourceFiber.lanes |= lane;\n var alternate = sourceFiber.alternate;\n null !== alternate && (alternate.lanes |= lane);\n for (var isHidden = !1, parent = sourceFiber.return; null !== parent; )\n (parent.childLanes |= lane),\n (alternate = parent.alternate),\n null !== alternate && (alternate.childLanes |= lane),\n 22 === parent.tag &&\n ((sourceFiber = parent.stateNode),\n null === sourceFiber || sourceFiber._visibility & 1 || (isHidden = !0)),\n (sourceFiber = parent),\n (parent = parent.return);\n return 3 === sourceFiber.tag\n ? ((parent = sourceFiber.stateNode),\n isHidden &&\n null !== update &&\n ((isHidden = 31 - clz32(lane)),\n (sourceFiber = parent.hiddenUpdates),\n (alternate = sourceFiber[isHidden]),\n null === alternate\n ? (sourceFiber[isHidden] = [update])\n : alternate.push(update),\n (update.lane = lane | 536870912)),\n parent)\n : null;\n}\nfunction getRootForUpdatedFiber(sourceFiber) {\n if (50 < nestedUpdateCount)\n throw (\n ((nestedUpdateCount = 0),\n (rootWithNestedUpdates = null),\n Error(formatProdErrorMessage(185)))\n );\n for (var parent = sourceFiber.return; null !== parent; )\n (sourceFiber = parent), (parent = sourceFiber.return);\n return 3 === sourceFiber.tag ? sourceFiber.stateNode : null;\n}\nvar emptyContextObject = {};\nfunction FiberNode(tag, pendingProps, key, mode) {\n this.tag = tag;\n this.key = key;\n this.sibling =\n this.child =\n this.return =\n this.stateNode =\n this.type =\n this.elementType =\n null;\n this.index = 0;\n this.refCleanup = this.ref = null;\n this.pendingProps = pendingProps;\n this.dependencies =\n this.memoizedState =\n this.updateQueue =\n this.memoizedProps =\n null;\n this.mode = mode;\n this.subtreeFlags = this.flags = 0;\n this.deletions = null;\n this.childLanes = this.lanes = 0;\n this.alternate = null;\n}\nfunction createFiberImplClass(tag, pendingProps, key, mode) {\n return new FiberNode(tag, pendingProps, key, mode);\n}\nfunction shouldConstruct(Component) {\n Component = Component.prototype;\n return !(!Component || !Component.isReactComponent);\n}\nfunction createWorkInProgress(current, pendingProps) {\n var workInProgress = current.alternate;\n null === workInProgress\n ? ((workInProgress = createFiberImplClass(\n current.tag,\n pendingProps,\n current.key,\n current.mode\n )),\n (workInProgress.elementType = current.elementType),\n (workInProgress.type = current.type),\n (workInProgress.stateNode = current.stateNode),\n (workInProgress.alternate = current),\n (current.alternate = workInProgress))\n : ((workInProgress.pendingProps = pendingProps),\n (workInProgress.type = current.type),\n (workInProgress.flags = 0),\n (workInProgress.subtreeFlags = 0),\n (workInProgress.deletions = null));\n workInProgress.flags = current.flags & 65011712;\n workInProgress.childLanes = current.childLanes;\n workInProgress.lanes = current.lanes;\n workInProgress.child = current.child;\n workInProgress.memoizedProps = current.memoizedProps;\n workInProgress.memoizedState = current.memoizedState;\n workInProgress.updateQueue = current.updateQueue;\n pendingProps = current.dependencies;\n workInProgress.dependencies =\n null === pendingProps\n ? null\n : { lanes: pendingProps.lanes, firstContext: pendingProps.firstContext };\n workInProgress.sibling = current.sibling;\n workInProgress.index = current.index;\n workInProgress.ref = current.ref;\n workInProgress.refCleanup = current.refCleanup;\n return workInProgress;\n}\nfunction resetWorkInProgress(workInProgress, renderLanes) {\n workInProgress.flags &= 65011714;\n var current = workInProgress.alternate;\n null === current\n ? ((workInProgress.childLanes = 0),\n (workInProgress.lanes = renderLanes),\n (workInProgress.child = null),\n (workInProgress.subtreeFlags = 0),\n (workInProgress.memoizedProps = null),\n (workInProgress.memoizedState = null),\n (workInProgress.updateQueue = null),\n (workInProgress.dependencies = null),\n (workInProgress.stateNode = null))\n : ((workInProgress.childLanes = current.childLanes),\n (workInProgress.lanes = current.lanes),\n (workInProgress.child = current.child),\n (workInProgress.subtreeFlags = 0),\n (workInProgress.deletions = null),\n (workInProgress.memoizedProps = current.memoizedProps),\n (workInProgress.memoizedState = current.memoizedState),\n (workInProgress.updateQueue = current.updateQueue),\n (workInProgress.type = current.type),\n (renderLanes = current.dependencies),\n (workInProgress.dependencies =\n null === renderLanes\n ? null\n : {\n lanes: renderLanes.lanes,\n firstContext: renderLanes.firstContext\n }));\n return workInProgress;\n}\nfunction createFiberFromTypeAndProps(\n type,\n key,\n pendingProps,\n owner,\n mode,\n lanes\n) {\n var fiberTag = 0;\n owner = type;\n if (\"function\" === typeof type) shouldConstruct(type) && (fiberTag = 1);\n else if (\"string\" === typeof type)\n fiberTag = isHostHoistableType(\n type,\n pendingProps,\n contextStackCursor.current\n )\n ? 26\n : \"html\" === type || \"head\" === type || \"body\" === type\n ? 27\n : 5;\n else\n a: switch (type) {\n case REACT_ACTIVITY_TYPE:\n return (\n (type = createFiberImplClass(31, pendingProps, key, mode)),\n (type.elementType = REACT_ACTIVITY_TYPE),\n (type.lanes = lanes),\n type\n );\n case REACT_FRAGMENT_TYPE:\n return createFiberFromFragment(pendingProps.children, mode, lanes, key);\n case REACT_STRICT_MODE_TYPE:\n fiberTag = 8;\n mode |= 24;\n break;\n case REACT_PROFILER_TYPE:\n return (\n (type = createFiberImplClass(12, pendingProps, key, mode | 2)),\n (type.elementType = REACT_PROFILER_TYPE),\n (type.lanes = lanes),\n type\n );\n case REACT_SUSPENSE_TYPE:\n return (\n (type = createFiberImplClass(13, pendingProps, key, mode)),\n (type.elementType = REACT_SUSPENSE_TYPE),\n (type.lanes = lanes),\n type\n );\n case REACT_SUSPENSE_LIST_TYPE:\n return (\n (type = createFiberImplClass(19, pendingProps, key, mode)),\n (type.elementType = REACT_SUSPENSE_LIST_TYPE),\n (type.lanes = lanes),\n type\n );\n default:\n if (\"object\" === typeof type && null !== type)\n switch (type.$$typeof) {\n case REACT_CONTEXT_TYPE:\n fiberTag = 10;\n break a;\n case REACT_CONSUMER_TYPE:\n fiberTag = 9;\n break a;\n case REACT_FORWARD_REF_TYPE:\n fiberTag = 11;\n break a;\n case REACT_MEMO_TYPE:\n fiberTag = 14;\n break a;\n case REACT_LAZY_TYPE:\n fiberTag = 16;\n owner = null;\n break a;\n }\n fiberTag = 29;\n pendingProps = Error(\n formatProdErrorMessage(130, null === type ? \"null\" : typeof type, \"\")\n );\n owner = null;\n }\n key = createFiberImplClass(fiberTag, pendingProps, key, mode);\n key.elementType = type;\n key.type = owner;\n key.lanes = lanes;\n return key;\n}\nfunction createFiberFromFragment(elements, mode, lanes, key) {\n elements = createFiberImplClass(7, elements, key, mode);\n elements.lanes = lanes;\n return elements;\n}\nfunction createFiberFromText(content, mode, lanes) {\n content = createFiberImplClass(6, content, null, mode);\n content.lanes = lanes;\n return content;\n}\nfunction createFiberFromDehydratedFragment(dehydratedNode) {\n var fiber = createFiberImplClass(18, null, null, 0);\n fiber.stateNode = dehydratedNode;\n return fiber;\n}\nfunction createFiberFromPortal(portal, mode, lanes) {\n mode = createFiberImplClass(\n 4,\n null !== portal.children ? portal.children : [],\n portal.key,\n mode\n );\n mode.lanes = lanes;\n mode.stateNode = {\n containerInfo: portal.containerInfo,\n pendingChildren: null,\n implementation: portal.implementation\n };\n return mode;\n}\nvar CapturedStacks = new WeakMap();\nfunction createCapturedValueAtFiber(value, source) {\n if (\"object\" === typeof value && null !== value) {\n var existing = CapturedStacks.get(value);\n if (void 0 !== existing) return existing;\n source = {\n value: value,\n source: source,\n stack: getStackByFiberInDevAndProd(source)\n };\n CapturedStacks.set(value, source);\n return source;\n }\n return {\n value: value,\n source: source,\n stack: getStackByFiberInDevAndProd(source)\n };\n}\nvar forkStack = [],\n forkStackIndex = 0,\n treeForkProvider = null,\n treeForkCount = 0,\n idStack = [],\n idStackIndex = 0,\n treeContextProvider = null,\n treeContextId = 1,\n treeContextOverflow = \"\";\nfunction pushTreeFork(workInProgress, totalChildren) {\n forkStack[forkStackIndex++] = treeForkCount;\n forkStack[forkStackIndex++] = treeForkProvider;\n treeForkProvider = workInProgress;\n treeForkCount = totalChildren;\n}\nfunction pushTreeId(workInProgress, totalChildren, index) {\n idStack[idStackIndex++] = treeContextId;\n idStack[idStackIndex++] = treeContextOverflow;\n idStack[idStackIndex++] = treeContextProvider;\n treeContextProvider = workInProgress;\n var baseIdWithLeadingBit = treeContextId;\n workInProgress = treeContextOverflow;\n var baseLength = 32 - clz32(baseIdWithLeadingBit) - 1;\n baseIdWithLeadingBit &= ~(1 << baseLength);\n index += 1;\n var length = 32 - clz32(totalChildren) + baseLength;\n if (30 < length) {\n var numberOfOverflowBits = baseLength - (baseLength % 5);\n length = (\n baseIdWithLeadingBit &\n ((1 << numberOfOverflowBits) - 1)\n ).toString(32);\n baseIdWithLeadingBit >>= numberOfOverflowBits;\n baseLength -= numberOfOverflowBits;\n treeContextId =\n (1 << (32 - clz32(totalChildren) + baseLength)) |\n (index << baseLength) |\n baseIdWithLeadingBit;\n treeContextOverflow = length + workInProgress;\n } else\n (treeContextId =\n (1 << length) | (index << baseLength) | baseIdWithLeadingBit),\n (treeContextOverflow = workInProgress);\n}\nfunction pushMaterializedTreeId(workInProgress) {\n null !== workInProgress.return &&\n (pushTreeFork(workInProgress, 1), pushTreeId(workInProgress, 1, 0));\n}\nfunction popTreeContext(workInProgress) {\n for (; workInProgress === treeForkProvider; )\n (treeForkProvider = forkStack[--forkStackIndex]),\n (forkStack[forkStackIndex] = null),\n (treeForkCount = forkStack[--forkStackIndex]),\n (forkStack[forkStackIndex] = null);\n for (; workInProgress === treeContextProvider; )\n (treeContextProvider = idStack[--idStackIndex]),\n (idStack[idStackIndex] = null),\n (treeContextOverflow = idStack[--idStackIndex]),\n (idStack[idStackIndex] = null),\n (treeContextId = idStack[--idStackIndex]),\n (idStack[idStackIndex] = null);\n}\nfunction restoreSuspendedTreeContext(workInProgress, suspendedContext) {\n idStack[idStackIndex++] = treeContextId;\n idStack[idStackIndex++] = treeContextOverflow;\n idStack[idStackIndex++] = treeContextProvider;\n treeContextId = suspendedContext.id;\n treeContextOverflow = suspendedContext.overflow;\n treeContextProvider = workInProgress;\n}\nvar hydrationParentFiber = null,\n nextHydratableInstance = null,\n isHydrating = !1,\n hydrationErrors = null,\n rootOrSingletonContext = !1,\n HydrationMismatchException = Error(formatProdErrorMessage(519));\nfunction throwOnHydrationMismatch(fiber) {\n var error = Error(\n formatProdErrorMessage(\n 418,\n 1 < arguments.length && void 0 !== arguments[1] && arguments[1]\n ? \"text\"\n : \"HTML\",\n \"\"\n )\n );\n queueHydrationError(createCapturedValueAtFiber(error, fiber));\n throw HydrationMismatchException;\n}\nfunction prepareToHydrateHostInstance(fiber) {\n var instance = fiber.stateNode,\n type = fiber.type,\n props = fiber.memoizedProps;\n instance[internalInstanceKey] = fiber;\n instance[internalPropsKey] = props;\n switch (type) {\n case \"dialog\":\n listenToNonDelegatedEvent(\"cancel\", instance);\n listenToNonDelegatedEvent(\"close\", instance);\n break;\n case \"iframe\":\n case \"object\":\n case \"embed\":\n listenToNonDelegatedEvent(\"load\", instance);\n break;\n case \"video\":\n case \"audio\":\n for (type = 0; type < mediaEventTypes.length; type++)\n listenToNonDelegatedEvent(mediaEventTypes[type], instance);\n break;\n case \"source\":\n listenToNonDelegatedEvent(\"error\", instance);\n break;\n case \"img\":\n case \"image\":\n case \"link\":\n listenToNonDelegatedEvent(\"error\", instance);\n listenToNonDelegatedEvent(\"load\", instance);\n break;\n case \"details\":\n listenToNonDelegatedEvent(\"toggle\", instance);\n break;\n case \"input\":\n listenToNonDelegatedEvent(\"invalid\", instance);\n initInput(\n instance,\n props.value,\n props.defaultValue,\n props.checked,\n props.defaultChecked,\n props.type,\n props.name,\n !0\n );\n break;\n case \"select\":\n listenToNonDelegatedEvent(\"invalid\", instance);\n break;\n case \"textarea\":\n listenToNonDelegatedEvent(\"invalid\", instance),\n initTextarea(instance, props.value, props.defaultValue, props.children);\n }\n type = props.children;\n (\"string\" !== typeof type &&\n \"number\" !== typeof type &&\n \"bigint\" !== typeof type) ||\n instance.textContent === \"\" + type ||\n !0 === props.suppressHydrationWarning ||\n checkForUnmatchedText(instance.textContent, type)\n ? (null != props.popover &&\n (listenToNonDelegatedEvent(\"beforetoggle\", instance),\n listenToNonDelegatedEvent(\"toggle\", instance)),\n null != props.onScroll && listenToNonDelegatedEvent(\"scroll\", instance),\n null != props.onScrollEnd &&\n listenToNonDelegatedEvent(\"scrollend\", instance),\n null != props.onClick && (instance.onclick = noop$1),\n (instance = !0))\n : (instance = !1);\n instance || throwOnHydrationMismatch(fiber, !0);\n}\nfunction popToNextHostParent(fiber) {\n for (hydrationParentFiber = fiber.return; hydrationParentFiber; )\n switch (hydrationParentFiber.tag) {\n case 5:\n case 31:\n case 13:\n rootOrSingletonContext = !1;\n return;\n case 27:\n case 3:\n rootOrSingletonContext = !0;\n return;\n default:\n hydrationParentFiber = hydrationParentFiber.return;\n }\n}\nfunction popHydrationState(fiber) {\n if (fiber !== hydrationParentFiber) return !1;\n if (!isHydrating) return popToNextHostParent(fiber), (isHydrating = !0), !1;\n var tag = fiber.tag,\n JSCompiler_temp;\n if ((JSCompiler_temp = 3 !== tag && 27 !== tag)) {\n if ((JSCompiler_temp = 5 === tag))\n (JSCompiler_temp = fiber.type),\n (JSCompiler_temp =\n !(\"form\" !== JSCompiler_temp && \"button\" !== JSCompiler_temp) ||\n shouldSetTextContent(fiber.type, fiber.memoizedProps));\n JSCompiler_temp = !JSCompiler_temp;\n }\n JSCompiler_temp && nextHydratableInstance && throwOnHydrationMismatch(fiber);\n popToNextHostParent(fiber);\n if (13 === tag) {\n fiber = fiber.memoizedState;\n fiber = null !== fiber ? fiber.dehydrated : null;\n if (!fiber) throw Error(formatProdErrorMessage(317));\n nextHydratableInstance =\n getNextHydratableInstanceAfterHydrationBoundary(fiber);\n } else if (31 === tag) {\n fiber = fiber.memoizedState;\n fiber = null !== fiber ? fiber.dehydrated : null;\n if (!fiber) throw Error(formatProdErrorMessage(317));\n nextHydratableInstance =\n getNextHydratableInstanceAfterHydrationBoundary(fiber);\n } else\n 27 === tag\n ? ((tag = nextHydratableInstance),\n isSingletonScope(fiber.type)\n ? ((fiber = previousHydratableOnEnteringScopedSingleton),\n (previousHydratableOnEnteringScopedSingleton = null),\n (nextHydratableInstance = fiber))\n : (nextHydratableInstance = tag))\n : (nextHydratableInstance = hydrationParentFiber\n ? getNextHydratable(fiber.stateNode.nextSibling)\n : null);\n return !0;\n}\nfunction resetHydrationState() {\n nextHydratableInstance = hydrationParentFiber = null;\n isHydrating = !1;\n}\nfunction upgradeHydrationErrorsToRecoverable() {\n var queuedErrors = hydrationErrors;\n null !== queuedErrors &&\n (null === workInProgressRootRecoverableErrors\n ? (workInProgressRootRecoverableErrors = queuedErrors)\n : workInProgressRootRecoverableErrors.push.apply(\n workInProgressRootRecoverableErrors,\n queuedErrors\n ),\n (hydrationErrors = null));\n return queuedErrors;\n}\nfunction queueHydrationError(error) {\n null === hydrationErrors\n ? (hydrationErrors = [error])\n : hydrationErrors.push(error);\n}\nvar valueCursor = createCursor(null),\n currentlyRenderingFiber$1 = null,\n lastContextDependency = null;\nfunction pushProvider(providerFiber, context, nextValue) {\n push(valueCursor, context._currentValue);\n context._currentValue = nextValue;\n}\nfunction popProvider(context) {\n context._currentValue = valueCursor.current;\n pop(valueCursor);\n}\nfunction scheduleContextWorkOnParentPath(parent, renderLanes, propagationRoot) {\n for (; null !== parent; ) {\n var alternate = parent.alternate;\n (parent.childLanes & renderLanes) !== renderLanes\n ? ((parent.childLanes |= renderLanes),\n null !== alternate && (alternate.childLanes |= renderLanes))\n : null !== alternate &&\n (alternate.childLanes & renderLanes) !== renderLanes &&\n (alternate.childLanes |= renderLanes);\n if (parent === propagationRoot) break;\n parent = parent.return;\n }\n}\nfunction propagateContextChanges(\n workInProgress,\n contexts,\n renderLanes,\n forcePropagateEntireTree\n) {\n var fiber = workInProgress.child;\n null !== fiber && (fiber.return = workInProgress);\n for (; null !== fiber; ) {\n var list = fiber.dependencies;\n if (null !== list) {\n var nextFiber = fiber.child;\n list = list.firstContext;\n a: for (; null !== list; ) {\n var dependency = list;\n list = fiber;\n for (var i = 0; i < contexts.length; i++)\n if (dependency.context === contexts[i]) {\n list.lanes |= renderLanes;\n dependency = list.alternate;\n null !== dependency && (dependency.lanes |= renderLanes);\n scheduleContextWorkOnParentPath(\n list.return,\n renderLanes,\n workInProgress\n );\n forcePropagateEntireTree || (nextFiber = null);\n break a;\n }\n list = dependency.next;\n }\n } else if (18 === fiber.tag) {\n nextFiber = fiber.return;\n if (null === nextFiber) throw Error(formatProdErrorMessage(341));\n nextFiber.lanes |= renderLanes;\n list = nextFiber.alternate;\n null !== list && (list.lanes |= renderLanes);\n scheduleContextWorkOnParentPath(nextFiber, renderLanes, workInProgress);\n nextFiber = null;\n } else nextFiber = fiber.child;\n if (null !== nextFiber) nextFiber.return = fiber;\n else\n for (nextFiber = fiber; null !== nextFiber; ) {\n if (nextFiber === workInProgress) {\n nextFiber = null;\n break;\n }\n fiber = nextFiber.sibling;\n if (null !== fiber) {\n fiber.return = nextFiber.return;\n nextFiber = fiber;\n break;\n }\n nextFiber = nextFiber.return;\n }\n fiber = nextFiber;\n }\n}\nfunction propagateParentContextChanges(\n current,\n workInProgress,\n renderLanes,\n forcePropagateEntireTree\n) {\n current = null;\n for (\n var parent = workInProgress, isInsidePropagationBailout = !1;\n null !== parent;\n\n ) {\n if (!isInsidePropagationBailout)\n if (0 !== (parent.flags & 524288)) isInsidePropagationBailout = !0;\n else if (0 !== (parent.flags & 262144)) break;\n if (10 === parent.tag) {\n var currentParent = parent.alternate;\n if (null === currentParent) throw Error(formatProdErrorMessage(387));\n currentParent = currentParent.memoizedProps;\n if (null !== currentParent) {\n var context = parent.type;\n objectIs(parent.pendingProps.value, currentParent.value) ||\n (null !== current ? current.push(context) : (current = [context]));\n }\n } else if (parent === hostTransitionProviderCursor.current) {\n currentParent = parent.alternate;\n if (null === currentParent) throw Error(formatProdErrorMessage(387));\n currentParent.memoizedState.memoizedState !==\n parent.memoizedState.memoizedState &&\n (null !== current\n ? current.push(HostTransitionContext)\n : (current = [HostTransitionContext]));\n }\n parent = parent.return;\n }\n null !== current &&\n propagateContextChanges(\n workInProgress,\n current,\n renderLanes,\n forcePropagateEntireTree\n );\n workInProgress.flags |= 262144;\n}\nfunction checkIfContextChanged(currentDependencies) {\n for (\n currentDependencies = currentDependencies.firstContext;\n null !== currentDependencies;\n\n ) {\n if (\n !objectIs(\n currentDependencies.context._currentValue,\n currentDependencies.memoizedValue\n )\n )\n return !0;\n currentDependencies = currentDependencies.next;\n }\n return !1;\n}\nfunction prepareToReadContext(workInProgress) {\n currentlyRenderingFiber$1 = workInProgress;\n lastContextDependency = null;\n workInProgress = workInProgress.dependencies;\n null !== workInProgress && (workInProgress.firstContext = null);\n}\nfunction readContext(context) {\n return readContextForConsumer(currentlyRenderingFiber$1, context);\n}\nfunction readContextDuringReconciliation(consumer, context) {\n null === currentlyRenderingFiber$1 && prepareToReadContext(consumer);\n return readContextForConsumer(consumer, context);\n}\nfunction readContextForConsumer(consumer, context) {\n var value = context._currentValue;\n context = { context: context, memoizedValue: value, next: null };\n if (null === lastContextDependency) {\n if (null === consumer) throw Error(formatProdErrorMessage(308));\n lastContextDependency = context;\n consumer.dependencies = { lanes: 0, firstContext: context };\n consumer.flags |= 524288;\n } else lastContextDependency = lastContextDependency.next = context;\n return value;\n}\nvar AbortControllerLocal =\n \"undefined\" !== typeof AbortController\n ? AbortController\n : function () {\n var listeners = [],\n signal = (this.signal = {\n aborted: !1,\n addEventListener: function (type, listener) {\n listeners.push(listener);\n }\n });\n this.abort = function () {\n signal.aborted = !0;\n listeners.forEach(function (listener) {\n return listener();\n });\n };\n },\n scheduleCallback$2 = Scheduler.unstable_scheduleCallback,\n NormalPriority = Scheduler.unstable_NormalPriority,\n CacheContext = {\n $$typeof: REACT_CONTEXT_TYPE,\n Consumer: null,\n Provider: null,\n _currentValue: null,\n _currentValue2: null,\n _threadCount: 0\n };\nfunction createCache() {\n return {\n controller: new AbortControllerLocal(),\n data: new Map(),\n refCount: 0\n };\n}\nfunction releaseCache(cache) {\n cache.refCount--;\n 0 === cache.refCount &&\n scheduleCallback$2(NormalPriority, function () {\n cache.controller.abort();\n });\n}\nvar currentEntangledListeners = null,\n currentEntangledPendingCount = 0,\n currentEntangledLane = 0,\n currentEntangledActionThenable = null;\nfunction entangleAsyncAction(transition, thenable) {\n if (null === currentEntangledListeners) {\n var entangledListeners = (currentEntangledListeners = []);\n currentEntangledPendingCount = 0;\n currentEntangledLane = requestTransitionLane();\n currentEntangledActionThenable = {\n status: \"pending\",\n value: void 0,\n then: function (resolve) {\n entangledListeners.push(resolve);\n }\n };\n }\n currentEntangledPendingCount++;\n thenable.then(pingEngtangledActionScope, pingEngtangledActionScope);\n return thenable;\n}\nfunction pingEngtangledActionScope() {\n if (\n 0 === --currentEntangledPendingCount &&\n null !== currentEntangledListeners\n ) {\n null !== currentEntangledActionThenable &&\n (currentEntangledActionThenable.status = \"fulfilled\");\n var listeners = currentEntangledListeners;\n currentEntangledListeners = null;\n currentEntangledLane = 0;\n currentEntangledActionThenable = null;\n for (var i = 0; i < listeners.length; i++) (0, listeners[i])();\n }\n}\nfunction chainThenableValue(thenable, result) {\n var listeners = [],\n thenableWithOverride = {\n status: \"pending\",\n value: null,\n reason: null,\n then: function (resolve) {\n listeners.push(resolve);\n }\n };\n thenable.then(\n function () {\n thenableWithOverride.status = \"fulfilled\";\n thenableWithOverride.value = result;\n for (var i = 0; i < listeners.length; i++) (0, listeners[i])(result);\n },\n function (error) {\n thenableWithOverride.status = \"rejected\";\n thenableWithOverride.reason = error;\n for (error = 0; error < listeners.length; error++)\n (0, listeners[error])(void 0);\n }\n );\n return thenableWithOverride;\n}\nvar prevOnStartTransitionFinish = ReactSharedInternals.S;\nReactSharedInternals.S = function (transition, returnValue) {\n globalMostRecentTransitionTime = now();\n \"object\" === typeof returnValue &&\n null !== returnValue &&\n \"function\" === typeof returnValue.then &&\n entangleAsyncAction(transition, returnValue);\n null !== prevOnStartTransitionFinish &&\n prevOnStartTransitionFinish(transition, returnValue);\n};\nvar resumedCache = createCursor(null);\nfunction peekCacheFromPool() {\n var cacheResumedFromPreviousRender = resumedCache.current;\n return null !== cacheResumedFromPreviousRender\n ? cacheResumedFromPreviousRender\n : workInProgressRoot.pooledCache;\n}\nfunction pushTransition(offscreenWorkInProgress, prevCachePool) {\n null === prevCachePool\n ? push(resumedCache, resumedCache.current)\n : push(resumedCache, prevCachePool.pool);\n}\nfunction getSuspendedCache() {\n var cacheFromPool = peekCacheFromPool();\n return null === cacheFromPool\n ? null\n : { parent: CacheContext._currentValue, pool: cacheFromPool };\n}\nvar SuspenseException = Error(formatProdErrorMessage(460)),\n SuspenseyCommitException = Error(formatProdErrorMessage(474)),\n SuspenseActionException = Error(formatProdErrorMessage(542)),\n noopSuspenseyCommitThenable = { then: function () {} };\nfunction isThenableResolved(thenable) {\n thenable = thenable.status;\n return \"fulfilled\" === thenable || \"rejected\" === thenable;\n}\nfunction trackUsedThenable(thenableState, thenable, index) {\n index = thenableState[index];\n void 0 === index\n ? thenableState.push(thenable)\n : index !== thenable && (thenable.then(noop$1, noop$1), (thenable = index));\n switch (thenable.status) {\n case \"fulfilled\":\n return thenable.value;\n case \"rejected\":\n throw (\n ((thenableState = thenable.reason),\n checkIfUseWrappedInAsyncCatch(thenableState),\n thenableState)\n );\n default:\n if (\"string\" === typeof thenable.status) thenable.then(noop$1, noop$1);\n else {\n thenableState = workInProgressRoot;\n if (null !== thenableState && 100 < thenableState.shellSuspendCounter)\n throw Error(formatProdErrorMessage(482));\n thenableState = thenable;\n thenableState.status = \"pending\";\n thenableState.then(\n function (fulfilledValue) {\n if (\"pending\" === thenable.status) {\n var fulfilledThenable = thenable;\n fulfilledThenable.status = \"fulfilled\";\n fulfilledThenable.value = fulfilledValue;\n }\n },\n function (error) {\n if (\"pending\" === thenable.status) {\n var rejectedThenable = thenable;\n rejectedThenable.status = \"rejected\";\n rejectedThenable.reason = error;\n }\n }\n );\n }\n switch (thenable.status) {\n case \"fulfilled\":\n return thenable.value;\n case \"rejected\":\n throw (\n ((thenableState = thenable.reason),\n checkIfUseWrappedInAsyncCatch(thenableState),\n thenableState)\n );\n }\n suspendedThenable = thenable;\n throw SuspenseException;\n }\n}\nfunction resolveLazy(lazyType) {\n try {\n var init = lazyType._init;\n return init(lazyType._payload);\n } catch (x) {\n if (null !== x && \"object\" === typeof x && \"function\" === typeof x.then)\n throw ((suspendedThenable = x), SuspenseException);\n throw x;\n }\n}\nvar suspendedThenable = null;\nfunction getSuspendedThenable() {\n if (null === suspendedThenable) throw Error(formatProdErrorMessage(459));\n var thenable = suspendedThenable;\n suspendedThenable = null;\n return thenable;\n}\nfunction checkIfUseWrappedInAsyncCatch(rejectedReason) {\n if (\n rejectedReason === SuspenseException ||\n rejectedReason === SuspenseActionException\n )\n throw Error(formatProdErrorMessage(483));\n}\nvar thenableState$1 = null,\n thenableIndexCounter$1 = 0;\nfunction unwrapThenable(thenable) {\n var index = thenableIndexCounter$1;\n thenableIndexCounter$1 += 1;\n null === thenableState$1 && (thenableState$1 = []);\n return trackUsedThenable(thenableState$1, thenable, index);\n}\nfunction coerceRef(workInProgress, element) {\n element = element.props.ref;\n workInProgress.ref = void 0 !== element ? element : null;\n}\nfunction throwOnInvalidObjectTypeImpl(returnFiber, newChild) {\n if (newChild.$$typeof === REACT_LEGACY_ELEMENT_TYPE)\n throw Error(formatProdErrorMessage(525));\n returnFiber = Object.prototype.toString.call(newChild);\n throw Error(\n formatProdErrorMessage(\n 31,\n \"[object Object]\" === returnFiber\n ? \"object with keys {\" + Object.keys(newChild).join(\", \") + \"}\"\n : returnFiber\n )\n );\n}\nfunction createChildReconciler(shouldTrackSideEffects) {\n function deleteChild(returnFiber, childToDelete) {\n if (shouldTrackSideEffects) {\n var deletions = returnFiber.deletions;\n null === deletions\n ? ((returnFiber.deletions = [childToDelete]), (returnFiber.flags |= 16))\n : deletions.push(childToDelete);\n }\n }\n function deleteRemainingChildren(returnFiber, currentFirstChild) {\n if (!shouldTrackSideEffects) return null;\n for (; null !== currentFirstChild; )\n deleteChild(returnFiber, currentFirstChild),\n (currentFirstChild = currentFirstChild.sibling);\n return null;\n }\n function mapRemainingChildren(currentFirstChild) {\n for (var existingChildren = new Map(); null !== currentFirstChild; )\n null !== currentFirstChild.key\n ? existingChildren.set(currentFirstChild.key, currentFirstChild)\n : existingChildren.set(currentFirstChild.index, currentFirstChild),\n (currentFirstChild = currentFirstChild.sibling);\n return existingChildren;\n }\n function useFiber(fiber, pendingProps) {\n fiber = createWorkInProgress(fiber, pendingProps);\n fiber.index = 0;\n fiber.sibling = null;\n return fiber;\n }\n function placeChild(newFiber, lastPlacedIndex, newIndex) {\n newFiber.index = newIndex;\n if (!shouldTrackSideEffects)\n return (newFiber.flags |= 1048576), lastPlacedIndex;\n newIndex = newFiber.alternate;\n if (null !== newIndex)\n return (\n (newIndex = newIndex.index),\n newIndex < lastPlacedIndex\n ? ((newFiber.flags |= 67108866), lastPlacedIndex)\n : newIndex\n );\n newFiber.flags |= 67108866;\n return lastPlacedIndex;\n }\n function placeSingleChild(newFiber) {\n shouldTrackSideEffects &&\n null === newFiber.alternate &&\n (newFiber.flags |= 67108866);\n return newFiber;\n }\n function updateTextNode(returnFiber, current, textContent, lanes) {\n if (null === current || 6 !== current.tag)\n return (\n (current = createFiberFromText(textContent, returnFiber.mode, lanes)),\n (current.return = returnFiber),\n current\n );\n current = useFiber(current, textContent);\n current.return = returnFiber;\n return current;\n }\n function updateElement(returnFiber, current, element, lanes) {\n var elementType = element.type;\n if (elementType === REACT_FRAGMENT_TYPE)\n return updateFragment(\n returnFiber,\n current,\n element.props.children,\n lanes,\n element.key\n );\n if (\n null !== current &&\n (current.elementType === elementType ||\n (\"object\" === typeof elementType &&\n null !== elementType &&\n elementType.$$typeof === REACT_LAZY_TYPE &&\n resolveLazy(elementType) === current.type))\n )\n return (\n (current = useFiber(current, element.props)),\n coerceRef(current, element),\n (current.return = returnFiber),\n current\n );\n current = createFiberFromTypeAndProps(\n element.type,\n element.key,\n element.props,\n null,\n returnFiber.mode,\n lanes\n );\n coerceRef(current, element);\n current.return = returnFiber;\n return current;\n }\n function updatePortal(returnFiber, current, portal, lanes) {\n if (\n null === current ||\n 4 !== current.tag ||\n current.stateNode.containerInfo !== portal.containerInfo ||\n current.stateNode.implementation !== portal.implementation\n )\n return (\n (current = createFiberFromPortal(portal, returnFiber.mode, lanes)),\n (current.return = returnFiber),\n current\n );\n current = useFiber(current, portal.children || []);\n current.return = returnFiber;\n return current;\n }\n function updateFragment(returnFiber, current, fragment, lanes, key) {\n if (null === current || 7 !== current.tag)\n return (\n (current = createFiberFromFragment(\n fragment,\n returnFiber.mode,\n lanes,\n key\n )),\n (current.return = returnFiber),\n current\n );\n current = useFiber(current, fragment);\n current.return = returnFiber;\n return current;\n }\n function createChild(returnFiber, newChild, lanes) {\n if (\n (\"string\" === typeof newChild && \"\" !== newChild) ||\n \"number\" === typeof newChild ||\n \"bigint\" === typeof newChild\n )\n return (\n (newChild = createFiberFromText(\n \"\" + newChild,\n returnFiber.mode,\n lanes\n )),\n (newChild.return = returnFiber),\n newChild\n );\n if (\"object\" === typeof newChild && null !== newChild) {\n switch (newChild.$$typeof) {\n case REACT_ELEMENT_TYPE:\n return (\n (lanes = createFiberFromTypeAndProps(\n newChild.type,\n newChild.key,\n newChild.props,\n null,\n returnFiber.mode,\n lanes\n )),\n coerceRef(lanes, newChild),\n (lanes.return = returnFiber),\n lanes\n );\n case REACT_PORTAL_TYPE:\n return (\n (newChild = createFiberFromPortal(\n newChild,\n returnFiber.mode,\n lanes\n )),\n (newChild.return = returnFiber),\n newChild\n );\n case REACT_LAZY_TYPE:\n return (\n (newChild = resolveLazy(newChild)),\n createChild(returnFiber, newChild, lanes)\n );\n }\n if (isArrayImpl(newChild) || getIteratorFn(newChild))\n return (\n (newChild = createFiberFromFragment(\n newChild,\n returnFiber.mode,\n lanes,\n null\n )),\n (newChild.return = returnFiber),\n newChild\n );\n if (\"function\" === typeof newChild.then)\n return createChild(returnFiber, unwrapThenable(newChild), lanes);\n if (newChild.$$typeof === REACT_CONTEXT_TYPE)\n return createChild(\n returnFiber,\n readContextDuringReconciliation(returnFiber, newChild),\n lanes\n );\n throwOnInvalidObjectTypeImpl(returnFiber, newChild);\n }\n return null;\n }\n function updateSlot(returnFiber, oldFiber, newChild, lanes) {\n var key = null !== oldFiber ? oldFiber.key : null;\n if (\n (\"string\" === typeof newChild && \"\" !== newChild) ||\n \"number\" === typeof newChild ||\n \"bigint\" === typeof newChild\n )\n return null !== key\n ? null\n : updateTextNode(returnFiber, oldFiber, \"\" + newChild, lanes);\n if (\"object\" === typeof newChild && null !== newChild) {\n switch (newChild.$$typeof) {\n case REACT_ELEMENT_TYPE:\n return newChild.key === key\n ? updateElement(returnFiber, oldFiber, newChild, lanes)\n : null;\n case REACT_PORTAL_TYPE:\n return newChild.key === key\n ? updatePortal(returnFiber, oldFiber, newChild, lanes)\n : null;\n case REACT_LAZY_TYPE:\n return (\n (newChild = resolveLazy(newChild)),\n updateSlot(returnFiber, oldFiber, newChild, lanes)\n );\n }\n if (isArrayImpl(newChild) || getIteratorFn(newChild))\n return null !== key\n ? null\n : updateFragment(returnFiber, oldFiber, newChild, lanes, null);\n if (\"function\" === typeof newChild.then)\n return updateSlot(\n returnFiber,\n oldFiber,\n unwrapThenable(newChild),\n lanes\n );\n if (newChild.$$typeof === REACT_CONTEXT_TYPE)\n return updateSlot(\n returnFiber,\n oldFiber,\n readContextDuringReconciliation(returnFiber, newChild),\n lanes\n );\n throwOnInvalidObjectTypeImpl(returnFiber, newChild);\n }\n return null;\n }\n function updateFromMap(\n existingChildren,\n returnFiber,\n newIdx,\n newChild,\n lanes\n ) {\n if (\n (\"string\" === typeof newChild && \"\" !== newChild) ||\n \"number\" === typeof newChild ||\n \"bigint\" === typeof newChild\n )\n return (\n (existingChildren = existingChildren.get(newIdx) || null),\n updateTextNode(returnFiber, existingChildren, \"\" + newChild, lanes)\n );\n if (\"object\" === typeof newChild && null !== newChild) {\n switch (newChild.$$typeof) {\n case REACT_ELEMENT_TYPE:\n return (\n (existingChildren =\n existingChildren.get(\n null === newChild.key ? newIdx : newChild.key\n ) || null),\n updateElement(returnFiber, existingChildren, newChild, lanes)\n );\n case REACT_PORTAL_TYPE:\n return (\n (existingChildren =\n existingChildren.get(\n null === newChild.key ? newIdx : newChild.key\n ) || null),\n updatePortal(returnFiber, existingChildren, newChild, lanes)\n );\n case REACT_LAZY_TYPE:\n return (\n (newChild = resolveLazy(newChild)),\n updateFromMap(\n existingChildren,\n returnFiber,\n newIdx,\n newChild,\n lanes\n )\n );\n }\n if (isArrayImpl(newChild) || getIteratorFn(newChild))\n return (\n (existingChildren = existingChildren.get(newIdx) || null),\n updateFragment(returnFiber, existingChildren, newChild, lanes, null)\n );\n if (\"function\" === typeof newChild.then)\n return updateFromMap(\n existingChildren,\n returnFiber,\n newIdx,\n unwrapThenable(newChild),\n lanes\n );\n if (newChild.$$typeof === REACT_CONTEXT_TYPE)\n return updateFromMap(\n existingChildren,\n returnFiber,\n newIdx,\n readContextDuringReconciliation(returnFiber, newChild),\n lanes\n );\n throwOnInvalidObjectTypeImpl(returnFiber, newChild);\n }\n return null;\n }\n function reconcileChildrenArray(\n returnFiber,\n currentFirstChild,\n newChildren,\n lanes\n ) {\n for (\n var resultingFirstChild = null,\n previousNewFiber = null,\n oldFiber = currentFirstChild,\n newIdx = (currentFirstChild = 0),\n nextOldFiber = null;\n null !== oldFiber && newIdx < newChildren.length;\n newIdx++\n ) {\n oldFiber.index > newIdx\n ? ((nextOldFiber = oldFiber), (oldFiber = null))\n : (nextOldFiber = oldFiber.sibling);\n var newFiber = updateSlot(\n returnFiber,\n oldFiber,\n newChildren[newIdx],\n lanes\n );\n if (null === newFiber) {\n null === oldFiber && (oldFiber = nextOldFiber);\n break;\n }\n shouldTrackSideEffects &&\n oldFiber &&\n null === newFiber.alternate &&\n deleteChild(returnFiber, oldFiber);\n currentFirstChild = placeChild(newFiber, currentFirstChild, newIdx);\n null === previousNewFiber\n ? (resultingFirstChild = newFiber)\n : (previousNewFiber.sibling = newFiber);\n previousNewFiber = newFiber;\n oldFiber = nextOldFiber;\n }\n if (newIdx === newChildren.length)\n return (\n deleteRemainingChildren(returnFiber, oldFiber),\n isHydrating && pushTreeFork(returnFiber, newIdx),\n resultingFirstChild\n );\n if (null === oldFiber) {\n for (; newIdx < newChildren.length; newIdx++)\n (oldFiber = createChild(returnFiber, newChildren[newIdx], lanes)),\n null !== oldFiber &&\n ((currentFirstChild = placeChild(\n oldFiber,\n currentFirstChild,\n newIdx\n )),\n null === previousNewFiber\n ? (resultingFirstChild = oldFiber)\n : (previousNewFiber.sibling = oldFiber),\n (previousNewFiber = oldFiber));\n isHydrating && pushTreeFork(returnFiber, newIdx);\n return resultingFirstChild;\n }\n for (\n oldFiber = mapRemainingChildren(oldFiber);\n newIdx < newChildren.length;\n newIdx++\n )\n (nextOldFiber = updateFromMap(\n oldFiber,\n returnFiber,\n newIdx,\n newChildren[newIdx],\n lanes\n )),\n null !== nextOldFiber &&\n (shouldTrackSideEffects &&\n null !== nextOldFiber.alternate &&\n oldFiber.delete(\n null === nextOldFiber.key ? newIdx : nextOldFiber.key\n ),\n (currentFirstChild = placeChild(\n nextOldFiber,\n currentFirstChild,\n newIdx\n )),\n null === previousNewFiber\n ? (resultingFirstChild = nextOldFiber)\n : (previousNewFiber.sibling = nextOldFiber),\n (previousNewFiber = nextOldFiber));\n shouldTrackSideEffects &&\n oldFiber.forEach(function (child) {\n return deleteChild(returnFiber, child);\n });\n isHydrating && pushTreeFork(returnFiber, newIdx);\n return resultingFirstChild;\n }\n function reconcileChildrenIterator(\n returnFiber,\n currentFirstChild,\n newChildren,\n lanes\n ) {\n if (null == newChildren) throw Error(formatProdErrorMessage(151));\n for (\n var resultingFirstChild = null,\n previousNewFiber = null,\n oldFiber = currentFirstChild,\n newIdx = (currentFirstChild = 0),\n nextOldFiber = null,\n step = newChildren.next();\n null !== oldFiber && !step.done;\n newIdx++, step = newChildren.next()\n ) {\n oldFiber.index > newIdx\n ? ((nextOldFiber = oldFiber), (oldFiber = null))\n : (nextOldFiber = oldFiber.sibling);\n var newFiber = updateSlot(returnFiber, oldFiber, step.value, lanes);\n if (null === newFiber) {\n null === oldFiber && (oldFiber = nextOldFiber);\n break;\n }\n shouldTrackSideEffects &&\n oldFiber &&\n null === newFiber.alternate &&\n deleteChild(returnFiber, oldFiber);\n currentFirstChild = placeChild(newFiber, currentFirstChild, newIdx);\n null === previousNewFiber\n ? (resultingFirstChild = newFiber)\n : (previousNewFiber.sibling = newFiber);\n previousNewFiber = newFiber;\n oldFiber = nextOldFiber;\n }\n if (step.done)\n return (\n deleteRemainingChildren(returnFiber, oldFiber),\n isHydrating && pushTreeFork(returnFiber, newIdx),\n resultingFirstChild\n );\n if (null === oldFiber) {\n for (; !step.done; newIdx++, step = newChildren.next())\n (step = createChild(returnFiber, step.value, lanes)),\n null !== step &&\n ((currentFirstChild = placeChild(step, currentFirstChild, newIdx)),\n null === previousNewFiber\n ? (resultingFirstChild = step)\n : (previousNewFiber.sibling = step),\n (previousNewFiber = step));\n isHydrating && pushTreeFork(returnFiber, newIdx);\n return resultingFirstChild;\n }\n for (\n oldFiber = mapRemainingChildren(oldFiber);\n !step.done;\n newIdx++, step = newChildren.next()\n )\n (step = updateFromMap(oldFiber, returnFiber, newIdx, step.value, lanes)),\n null !== step &&\n (shouldTrackSideEffects &&\n null !== step.alternate &&\n oldFiber.delete(null === step.key ? newIdx : step.key),\n (currentFirstChild = placeChild(step, currentFirstChild, newIdx)),\n null === previousNewFiber\n ? (resultingFirstChild = step)\n : (previousNewFiber.sibling = step),\n (previousNewFiber = step));\n shouldTrackSideEffects &&\n oldFiber.forEach(function (child) {\n return deleteChild(returnFiber, child);\n });\n isHydrating && pushTreeFork(returnFiber, newIdx);\n return resultingFirstChild;\n }\n function reconcileChildFibersImpl(\n returnFiber,\n currentFirstChild,\n newChild,\n lanes\n ) {\n \"object\" === typeof newChild &&\n null !== newChild &&\n newChild.type === REACT_FRAGMENT_TYPE &&\n null === newChild.key &&\n (newChild = newChild.props.children);\n if (\"object\" === typeof newChild && null !== newChild) {\n switch (newChild.$$typeof) {\n case REACT_ELEMENT_TYPE:\n a: {\n for (var key = newChild.key; null !== currentFirstChild; ) {\n if (currentFirstChild.key === key) {\n key = newChild.type;\n if (key === REACT_FRAGMENT_TYPE) {\n if (7 === currentFirstChild.tag) {\n deleteRemainingChildren(\n returnFiber,\n currentFirstChild.sibling\n );\n lanes = useFiber(\n currentFirstChild,\n newChild.props.children\n );\n lanes.return = returnFiber;\n returnFiber = lanes;\n break a;\n }\n } else if (\n currentFirstChild.elementType === key ||\n (\"object\" === typeof key &&\n null !== key &&\n key.$$typeof === REACT_LAZY_TYPE &&\n resolveLazy(key) === currentFirstChild.type)\n ) {\n deleteRemainingChildren(\n returnFiber,\n currentFirstChild.sibling\n );\n lanes = useFiber(currentFirstChild, newChild.props);\n coerceRef(lanes, newChild);\n lanes.return = returnFiber;\n returnFiber = lanes;\n break a;\n }\n deleteRemainingChildren(returnFiber, currentFirstChild);\n break;\n } else deleteChild(returnFiber, currentFirstChild);\n currentFirstChild = currentFirstChild.sibling;\n }\n newChild.type === REACT_FRAGMENT_TYPE\n ? ((lanes = createFiberFromFragment(\n newChild.props.children,\n returnFiber.mode,\n lanes,\n newChild.key\n )),\n (lanes.return = returnFiber),\n (returnFiber = lanes))\n : ((lanes = createFiberFromTypeAndProps(\n newChild.type,\n newChild.key,\n newChild.props,\n null,\n returnFiber.mode,\n lanes\n )),\n coerceRef(lanes, newChild),\n (lanes.return = returnFiber),\n (returnFiber = lanes));\n }\n return placeSingleChild(returnFiber);\n case REACT_PORTAL_TYPE:\n a: {\n for (key = newChild.key; null !== currentFirstChild; ) {\n if (currentFirstChild.key === key)\n if (\n 4 === currentFirstChild.tag &&\n currentFirstChild.stateNode.containerInfo ===\n newChild.containerInfo &&\n currentFirstChild.stateNode.implementation ===\n newChild.implementation\n ) {\n deleteRemainingChildren(\n returnFiber,\n currentFirstChild.sibling\n );\n lanes = useFiber(currentFirstChild, newChild.children || []);\n lanes.return = returnFiber;\n returnFiber = lanes;\n break a;\n } else {\n deleteRemainingChildren(returnFiber, currentFirstChild);\n break;\n }\n else deleteChild(returnFiber, currentFirstChild);\n currentFirstChild = currentFirstChild.sibling;\n }\n lanes = createFiberFromPortal(newChild, returnFiber.mode, lanes);\n lanes.return = returnFiber;\n returnFiber = lanes;\n }\n return placeSingleChild(returnFiber);\n case REACT_LAZY_TYPE:\n return (\n (newChild = resolveLazy(newChild)),\n reconcileChildFibersImpl(\n returnFiber,\n currentFirstChild,\n newChild,\n lanes\n )\n );\n }\n if (isArrayImpl(newChild))\n return reconcileChildrenArray(\n returnFiber,\n currentFirstChild,\n newChild,\n lanes\n );\n if (getIteratorFn(newChild)) {\n key = getIteratorFn(newChild);\n if (\"function\" !== typeof key) throw Error(formatProdErrorMessage(150));\n newChild = key.call(newChild);\n return reconcileChildrenIterator(\n returnFiber,\n currentFirstChild,\n newChild,\n lanes\n );\n }\n if (\"function\" === typeof newChild.then)\n return reconcileChildFibersImpl(\n returnFiber,\n currentFirstChild,\n unwrapThenable(newChild),\n lanes\n );\n if (newChild.$$typeof === REACT_CONTEXT_TYPE)\n return reconcileChildFibersImpl(\n returnFiber,\n currentFirstChild,\n readContextDuringReconciliation(returnFiber, newChild),\n lanes\n );\n throwOnInvalidObjectTypeImpl(returnFiber, newChild);\n }\n return (\"string\" === typeof newChild && \"\" !== newChild) ||\n \"number\" === typeof newChild ||\n \"bigint\" === typeof newChild\n ? ((newChild = \"\" + newChild),\n null !== currentFirstChild && 6 === currentFirstChild.tag\n ? (deleteRemainingChildren(returnFiber, currentFirstChild.sibling),\n (lanes = useFiber(currentFirstChild, newChild)),\n (lanes.return = returnFiber),\n (returnFiber = lanes))\n : (deleteRemainingChildren(returnFiber, currentFirstChild),\n (lanes = createFiberFromText(newChild, returnFiber.mode, lanes)),\n (lanes.return = returnFiber),\n (returnFiber = lanes)),\n placeSingleChild(returnFiber))\n : deleteRemainingChildren(returnFiber, currentFirstChild);\n }\n return function (returnFiber, currentFirstChild, newChild, lanes) {\n try {\n thenableIndexCounter$1 = 0;\n var firstChildFiber = reconcileChildFibersImpl(\n returnFiber,\n currentFirstChild,\n newChild,\n lanes\n );\n thenableState$1 = null;\n return firstChildFiber;\n } catch (x) {\n if (x === SuspenseException || x === SuspenseActionException) throw x;\n var fiber = createFiberImplClass(29, x, null, returnFiber.mode);\n fiber.lanes = lanes;\n fiber.return = returnFiber;\n return fiber;\n } finally {\n }\n };\n}\nvar reconcileChildFibers = createChildReconciler(!0),\n mountChildFibers = createChildReconciler(!1),\n hasForceUpdate = !1;\nfunction initializeUpdateQueue(fiber) {\n fiber.updateQueue = {\n baseState: fiber.memoizedState,\n firstBaseUpdate: null,\n lastBaseUpdate: null,\n shared: { pending: null, lanes: 0, hiddenCallbacks: null },\n callbacks: null\n };\n}\nfunction cloneUpdateQueue(current, workInProgress) {\n current = current.updateQueue;\n workInProgress.updateQueue === current &&\n (workInProgress.updateQueue = {\n baseState: current.baseState,\n firstBaseUpdate: current.firstBaseUpdate,\n lastBaseUpdate: current.lastBaseUpdate,\n shared: current.shared,\n callbacks: null\n });\n}\nfunction createUpdate(lane) {\n return { lane: lane, tag: 0, payload: null, callback: null, next: null };\n}\nfunction enqueueUpdate(fiber, update, lane) {\n var updateQueue = fiber.updateQueue;\n if (null === updateQueue) return null;\n updateQueue = updateQueue.shared;\n if (0 !== (executionContext & 2)) {\n var pending = updateQueue.pending;\n null === pending\n ? (update.next = update)\n : ((update.next = pending.next), (pending.next = update));\n updateQueue.pending = update;\n update = getRootForUpdatedFiber(fiber);\n markUpdateLaneFromFiberToRoot(fiber, null, lane);\n return update;\n }\n enqueueUpdate$1(fiber, updateQueue, update, lane);\n return getRootForUpdatedFiber(fiber);\n}\nfunction entangleTransitions(root, fiber, lane) {\n fiber = fiber.updateQueue;\n if (null !== fiber && ((fiber = fiber.shared), 0 !== (lane & 4194048))) {\n var queueLanes = fiber.lanes;\n queueLanes &= root.pendingLanes;\n lane |= queueLanes;\n fiber.lanes = lane;\n markRootEntangled(root, lane);\n }\n}\nfunction enqueueCapturedUpdate(workInProgress, capturedUpdate) {\n var queue = workInProgress.updateQueue,\n current = workInProgress.alternate;\n if (\n null !== current &&\n ((current = current.updateQueue), queue === current)\n ) {\n var newFirst = null,\n newLast = null;\n queue = queue.firstBaseUpdate;\n if (null !== queue) {\n do {\n var clone = {\n lane: queue.lane,\n tag: queue.tag,\n payload: queue.payload,\n callback: null,\n next: null\n };\n null === newLast\n ? (newFirst = newLast = clone)\n : (newLast = newLast.next = clone);\n queue = queue.next;\n } while (null !== queue);\n null === newLast\n ? (newFirst = newLast = capturedUpdate)\n : (newLast = newLast.next = capturedUpdate);\n } else newFirst = newLast = capturedUpdate;\n queue = {\n baseState: current.baseState,\n firstBaseUpdate: newFirst,\n lastBaseUpdate: newLast,\n shared: current.shared,\n callbacks: current.callbacks\n };\n workInProgress.updateQueue = queue;\n return;\n }\n workInProgress = queue.lastBaseUpdate;\n null === workInProgress\n ? (queue.firstBaseUpdate = capturedUpdate)\n : (workInProgress.next = capturedUpdate);\n queue.lastBaseUpdate = capturedUpdate;\n}\nvar didReadFromEntangledAsyncAction = !1;\nfunction suspendIfUpdateReadFromEntangledAsyncAction() {\n if (didReadFromEntangledAsyncAction) {\n var entangledActionThenable = currentEntangledActionThenable;\n if (null !== entangledActionThenable) throw entangledActionThenable;\n }\n}\nfunction processUpdateQueue(\n workInProgress$jscomp$0,\n props,\n instance$jscomp$0,\n renderLanes\n) {\n didReadFromEntangledAsyncAction = !1;\n var queue = workInProgress$jscomp$0.updateQueue;\n hasForceUpdate = !1;\n var firstBaseUpdate = queue.firstBaseUpdate,\n lastBaseUpdate = queue.lastBaseUpdate,\n pendingQueue = queue.shared.pending;\n if (null !== pendingQueue) {\n queue.shared.pending = null;\n var lastPendingUpdate = pendingQueue,\n firstPendingUpdate = lastPendingUpdate.next;\n lastPendingUpdate.next = null;\n null === lastBaseUpdate\n ? (firstBaseUpdate = firstPendingUpdate)\n : (lastBaseUpdate.next = firstPendingUpdate);\n lastBaseUpdate = lastPendingUpdate;\n var current = workInProgress$jscomp$0.alternate;\n null !== current &&\n ((current = current.updateQueue),\n (pendingQueue = current.lastBaseUpdate),\n pendingQueue !== lastBaseUpdate &&\n (null === pendingQueue\n ? (current.firstBaseUpdate = firstPendingUpdate)\n : (pendingQueue.next = firstPendingUpdate),\n (current.lastBaseUpdate = lastPendingUpdate)));\n }\n if (null !== firstBaseUpdate) {\n var newState = queue.baseState;\n lastBaseUpdate = 0;\n current = firstPendingUpdate = lastPendingUpdate = null;\n pendingQueue = firstBaseUpdate;\n do {\n var updateLane = pendingQueue.lane & -536870913,\n isHiddenUpdate = updateLane !== pendingQueue.lane;\n if (\n isHiddenUpdate\n ? (workInProgressRootRenderLanes & updateLane) === updateLane\n : (renderLanes & updateLane) === updateLane\n ) {\n 0 !== updateLane &&\n updateLane === currentEntangledLane &&\n (didReadFromEntangledAsyncAction = !0);\n null !== current &&\n (current = current.next =\n {\n lane: 0,\n tag: pendingQueue.tag,\n payload: pendingQueue.payload,\n callback: null,\n next: null\n });\n a: {\n var workInProgress = workInProgress$jscomp$0,\n update = pendingQueue;\n updateLane = props;\n var instance = instance$jscomp$0;\n switch (update.tag) {\n case 1:\n workInProgress = update.payload;\n if (\"function\" === typeof workInProgress) {\n newState = workInProgress.call(instance, newState, updateLane);\n break a;\n }\n newState = workInProgress;\n break a;\n case 3:\n workInProgress.flags = (workInProgress.flags & -65537) | 128;\n case 0:\n workInProgress = update.payload;\n updateLane =\n \"function\" === typeof workInProgress\n ? workInProgress.call(instance, newState, updateLane)\n : workInProgress;\n if (null === updateLane || void 0 === updateLane) break a;\n newState = assign({}, newState, updateLane);\n break a;\n case 2:\n hasForceUpdate = !0;\n }\n }\n updateLane = pendingQueue.callback;\n null !== updateLane &&\n ((workInProgress$jscomp$0.flags |= 64),\n isHiddenUpdate && (workInProgress$jscomp$0.flags |= 8192),\n (isHiddenUpdate = queue.callbacks),\n null === isHiddenUpdate\n ? (queue.callbacks = [updateLane])\n : isHiddenUpdate.push(updateLane));\n } else\n (isHiddenUpdate = {\n lane: updateLane,\n tag: pendingQueue.tag,\n payload: pendingQueue.payload,\n callback: pendingQueue.callback,\n next: null\n }),\n null === current\n ? ((firstPendingUpdate = current = isHiddenUpdate),\n (lastPendingUpdate = newState))\n : (current = current.next = isHiddenUpdate),\n (lastBaseUpdate |= updateLane);\n pendingQueue = pendingQueue.next;\n if (null === pendingQueue)\n if (((pendingQueue = queue.shared.pending), null === pendingQueue))\n break;\n else\n (isHiddenUpdate = pendingQueue),\n (pendingQueue = isHiddenUpdate.next),\n (isHiddenUpdate.next = null),\n (queue.lastBaseUpdate = isHiddenUpdate),\n (queue.shared.pending = null);\n } while (1);\n null === current && (lastPendingUpdate = newState);\n queue.baseState = lastPendingUpdate;\n queue.firstBaseUpdate = firstPendingUpdate;\n queue.lastBaseUpdate = current;\n null === firstBaseUpdate && (queue.shared.lanes = 0);\n workInProgressRootSkippedLanes |= lastBaseUpdate;\n workInProgress$jscomp$0.lanes = lastBaseUpdate;\n workInProgress$jscomp$0.memoizedState = newState;\n }\n}\nfunction callCallback(callback, context) {\n if (\"function\" !== typeof callback)\n throw Error(formatProdErrorMessage(191, callback));\n callback.call(context);\n}\nfunction commitCallbacks(updateQueue, context) {\n var callbacks = updateQueue.callbacks;\n if (null !== callbacks)\n for (\n updateQueue.callbacks = null, updateQueue = 0;\n updateQueue < callbacks.length;\n updateQueue++\n )\n callCallback(callbacks[updateQueue], context);\n}\nvar currentTreeHiddenStackCursor = createCursor(null),\n prevEntangledRenderLanesCursor = createCursor(0);\nfunction pushHiddenContext(fiber, context) {\n fiber = entangledRenderLanes;\n push(prevEntangledRenderLanesCursor, fiber);\n push(currentTreeHiddenStackCursor, context);\n entangledRenderLanes = fiber | context.baseLanes;\n}\nfunction reuseHiddenContextOnStack() {\n push(prevEntangledRenderLanesCursor, entangledRenderLanes);\n push(currentTreeHiddenStackCursor, currentTreeHiddenStackCursor.current);\n}\nfunction popHiddenContext() {\n entangledRenderLanes = prevEntangledRenderLanesCursor.current;\n pop(currentTreeHiddenStackCursor);\n pop(prevEntangledRenderLanesCursor);\n}\nvar suspenseHandlerStackCursor = createCursor(null),\n shellBoundary = null;\nfunction pushPrimaryTreeSuspenseHandler(handler) {\n var current = handler.alternate;\n push(suspenseStackCursor, suspenseStackCursor.current & 1);\n push(suspenseHandlerStackCursor, handler);\n null === shellBoundary &&\n (null === current || null !== currentTreeHiddenStackCursor.current\n ? (shellBoundary = handler)\n : null !== current.memoizedState && (shellBoundary = handler));\n}\nfunction pushDehydratedActivitySuspenseHandler(fiber) {\n push(suspenseStackCursor, suspenseStackCursor.current);\n push(suspenseHandlerStackCursor, fiber);\n null === shellBoundary && (shellBoundary = fiber);\n}\nfunction pushOffscreenSuspenseHandler(fiber) {\n 22 === fiber.tag\n ? (push(suspenseStackCursor, suspenseStackCursor.current),\n push(suspenseHandlerStackCursor, fiber),\n null === shellBoundary && (shellBoundary = fiber))\n : reuseSuspenseHandlerOnStack(fiber);\n}\nfunction reuseSuspenseHandlerOnStack() {\n push(suspenseStackCursor, suspenseStackCursor.current);\n push(suspenseHandlerStackCursor, suspenseHandlerStackCursor.current);\n}\nfunction popSuspenseHandler(fiber) {\n pop(suspenseHandlerStackCursor);\n shellBoundary === fiber && (shellBoundary = null);\n pop(suspenseStackCursor);\n}\nvar suspenseStackCursor = createCursor(0);\nfunction findFirstSuspended(row) {\n for (var node = row; null !== node; ) {\n if (13 === node.tag) {\n var state = node.memoizedState;\n if (\n null !== state &&\n ((state = state.dehydrated),\n null === state ||\n isSuspenseInstancePending(state) ||\n isSuspenseInstanceFallback(state))\n )\n return node;\n } else if (\n 19 === node.tag &&\n (\"forwards\" === node.memoizedProps.revealOrder ||\n \"backwards\" === node.memoizedProps.revealOrder ||\n \"unstable_legacy-backwards\" === node.memoizedProps.revealOrder ||\n \"together\" === node.memoizedProps.revealOrder)\n ) {\n if (0 !== (node.flags & 128)) return node;\n } else if (null !== node.child) {\n node.child.return = node;\n node = node.child;\n continue;\n }\n if (node === row) break;\n for (; null === node.sibling; ) {\n if (null === node.return || node.return === row) return null;\n node = node.return;\n }\n node.sibling.return = node.return;\n node = node.sibling;\n }\n return null;\n}\nvar renderLanes = 0,\n currentlyRenderingFiber = null,\n currentHook = null,\n workInProgressHook = null,\n didScheduleRenderPhaseUpdate = !1,\n didScheduleRenderPhaseUpdateDuringThisPass = !1,\n shouldDoubleInvokeUserFnsInHooksDEV = !1,\n localIdCounter = 0,\n thenableIndexCounter = 0,\n thenableState = null,\n globalClientIdCounter = 0;\nfunction throwInvalidHookError() {\n throw Error(formatProdErrorMessage(321));\n}\nfunction areHookInputsEqual(nextDeps, prevDeps) {\n if (null === prevDeps) return !1;\n for (var i = 0; i < prevDeps.length && i < nextDeps.length; i++)\n if (!objectIs(nextDeps[i], prevDeps[i])) return !1;\n return !0;\n}\nfunction renderWithHooks(\n current,\n workInProgress,\n Component,\n props,\n secondArg,\n nextRenderLanes\n) {\n renderLanes = nextRenderLanes;\n currentlyRenderingFiber = workInProgress;\n workInProgress.memoizedState = null;\n workInProgress.updateQueue = null;\n workInProgress.lanes = 0;\n ReactSharedInternals.H =\n null === current || null === current.memoizedState\n ? HooksDispatcherOnMount\n : HooksDispatcherOnUpdate;\n shouldDoubleInvokeUserFnsInHooksDEV = !1;\n nextRenderLanes = Component(props, secondArg);\n shouldDoubleInvokeUserFnsInHooksDEV = !1;\n didScheduleRenderPhaseUpdateDuringThisPass &&\n (nextRenderLanes = renderWithHooksAgain(\n workInProgress,\n Component,\n props,\n secondArg\n ));\n finishRenderingHooks(current);\n return nextRenderLanes;\n}\nfunction finishRenderingHooks(current) {\n ReactSharedInternals.H = ContextOnlyDispatcher;\n var didRenderTooFewHooks = null !== currentHook && null !== currentHook.next;\n renderLanes = 0;\n workInProgressHook = currentHook = currentlyRenderingFiber = null;\n didScheduleRenderPhaseUpdate = !1;\n thenableIndexCounter = 0;\n thenableState = null;\n if (didRenderTooFewHooks) throw Error(formatProdErrorMessage(300));\n null === current ||\n didReceiveUpdate ||\n ((current = current.dependencies),\n null !== current &&\n checkIfContextChanged(current) &&\n (didReceiveUpdate = !0));\n}\nfunction renderWithHooksAgain(workInProgress, Component, props, secondArg) {\n currentlyRenderingFiber = workInProgress;\n var numberOfReRenders = 0;\n do {\n didScheduleRenderPhaseUpdateDuringThisPass && (thenableState = null);\n thenableIndexCounter = 0;\n didScheduleRenderPhaseUpdateDuringThisPass = !1;\n if (25 <= numberOfReRenders) throw Error(formatProdErrorMessage(301));\n numberOfReRenders += 1;\n workInProgressHook = currentHook = null;\n if (null != workInProgress.updateQueue) {\n var children = workInProgress.updateQueue;\n children.lastEffect = null;\n children.events = null;\n children.stores = null;\n null != children.memoCache && (children.memoCache.index = 0);\n }\n ReactSharedInternals.H = HooksDispatcherOnRerender;\n children = Component(props, secondArg);\n } while (didScheduleRenderPhaseUpdateDuringThisPass);\n return children;\n}\nfunction TransitionAwareHostComponent() {\n var dispatcher = ReactSharedInternals.H,\n maybeThenable = dispatcher.useState()[0];\n maybeThenable =\n \"function\" === typeof maybeThenable.then\n ? useThenable(maybeThenable)\n : maybeThenable;\n dispatcher = dispatcher.useState()[0];\n (null !== currentHook ? currentHook.memoizedState : null) !== dispatcher &&\n (currentlyRenderingFiber.flags |= 1024);\n return maybeThenable;\n}\nfunction checkDidRenderIdHook() {\n var didRenderIdHook = 0 !== localIdCounter;\n localIdCounter = 0;\n return didRenderIdHook;\n}\nfunction bailoutHooks(current, workInProgress, lanes) {\n workInProgress.updateQueue = current.updateQueue;\n workInProgress.flags &= -2053;\n current.lanes &= ~lanes;\n}\nfunction resetHooksOnUnwind(workInProgress) {\n if (didScheduleRenderPhaseUpdate) {\n for (\n workInProgress = workInProgress.memoizedState;\n null !== workInProgress;\n\n ) {\n var queue = workInProgress.queue;\n null !== queue && (queue.pending = null);\n workInProgress = workInProgress.next;\n }\n didScheduleRenderPhaseUpdate = !1;\n }\n renderLanes = 0;\n workInProgressHook = currentHook = currentlyRenderingFiber = null;\n didScheduleRenderPhaseUpdateDuringThisPass = !1;\n thenableIndexCounter = localIdCounter = 0;\n thenableState = null;\n}\nfunction mountWorkInProgressHook() {\n var hook = {\n memoizedState: null,\n baseState: null,\n baseQueue: null,\n queue: null,\n next: null\n };\n null === workInProgressHook\n ? (currentlyRenderingFiber.memoizedState = workInProgressHook = hook)\n : (workInProgressHook = workInProgressHook.next = hook);\n return workInProgressHook;\n}\nfunction updateWorkInProgressHook() {\n if (null === currentHook) {\n var nextCurrentHook = currentlyRenderingFiber.alternate;\n nextCurrentHook =\n null !== nextCurrentHook ? nextCurrentHook.memoizedState : null;\n } else nextCurrentHook = currentHook.next;\n var nextWorkInProgressHook =\n null === workInProgressHook\n ? currentlyRenderingFiber.memoizedState\n : workInProgressHook.next;\n if (null !== nextWorkInProgressHook)\n (workInProgressHook = nextWorkInProgressHook),\n (currentHook = nextCurrentHook);\n else {\n if (null === nextCurrentHook) {\n if (null === currentlyRenderingFiber.alternate)\n throw Error(formatProdErrorMessage(467));\n throw Error(formatProdErrorMessage(310));\n }\n currentHook = nextCurrentHook;\n nextCurrentHook = {\n memoizedState: currentHook.memoizedState,\n baseState: currentHook.baseState,\n baseQueue: currentHook.baseQueue,\n queue: currentHook.queue,\n next: null\n };\n null === workInProgressHook\n ? (currentlyRenderingFiber.memoizedState = workInProgressHook =\n nextCurrentHook)\n : (workInProgressHook = workInProgressHook.next = nextCurrentHook);\n }\n return workInProgressHook;\n}\nfunction createFunctionComponentUpdateQueue() {\n return { lastEffect: null, events: null, stores: null, memoCache: null };\n}\nfunction useThenable(thenable) {\n var index = thenableIndexCounter;\n thenableIndexCounter += 1;\n null === thenableState && (thenableState = []);\n thenable = trackUsedThenable(thenableState, thenable, index);\n index = currentlyRenderingFiber;\n null ===\n (null === workInProgressHook\n ? index.memoizedState\n : workInProgressHook.next) &&\n ((index = index.alternate),\n (ReactSharedInternals.H =\n null === index || null === index.memoizedState\n ? HooksDispatcherOnMount\n : HooksDispatcherOnUpdate));\n return thenable;\n}\nfunction use(usable) {\n if (null !== usable && \"object\" === typeof usable) {\n if (\"function\" === typeof usable.then) return useThenable(usable);\n if (usable.$$typeof === REACT_CONTEXT_TYPE) return readContext(usable);\n }\n throw Error(formatProdErrorMessage(438, String(usable)));\n}\nfunction useMemoCache(size) {\n var memoCache = null,\n updateQueue = currentlyRenderingFiber.updateQueue;\n null !== updateQueue && (memoCache = updateQueue.memoCache);\n if (null == memoCache) {\n var current = currentlyRenderingFiber.alternate;\n null !== current &&\n ((current = current.updateQueue),\n null !== current &&\n ((current = current.memoCache),\n null != current &&\n (memoCache = {\n data: current.data.map(function (array) {\n return array.slice();\n }),\n index: 0\n })));\n }\n null == memoCache && (memoCache = { data: [], index: 0 });\n null === updateQueue &&\n ((updateQueue = createFunctionComponentUpdateQueue()),\n (currentlyRenderingFiber.updateQueue = updateQueue));\n updateQueue.memoCache = memoCache;\n updateQueue = memoCache.data[memoCache.index];\n if (void 0 === updateQueue)\n for (\n updateQueue = memoCache.data[memoCache.index] = Array(size), current = 0;\n current < size;\n current++\n )\n updateQueue[current] = REACT_MEMO_CACHE_SENTINEL;\n memoCache.index++;\n return updateQueue;\n}\nfunction basicStateReducer(state, action) {\n return \"function\" === typeof action ? action(state) : action;\n}\nfunction updateReducer(reducer) {\n var hook = updateWorkInProgressHook();\n return updateReducerImpl(hook, currentHook, reducer);\n}\nfunction updateReducerImpl(hook, current, reducer) {\n var queue = hook.queue;\n if (null === queue) throw Error(formatProdErrorMessage(311));\n queue.lastRenderedReducer = reducer;\n var baseQueue = hook.baseQueue,\n pendingQueue = queue.pending;\n if (null !== pendingQueue) {\n if (null !== baseQueue) {\n var baseFirst = baseQueue.next;\n baseQueue.next = pendingQueue.next;\n pendingQueue.next = baseFirst;\n }\n current.baseQueue = baseQueue = pendingQueue;\n queue.pending = null;\n }\n pendingQueue = hook.baseState;\n if (null === baseQueue) hook.memoizedState = pendingQueue;\n else {\n current = baseQueue.next;\n var newBaseQueueFirst = (baseFirst = null),\n newBaseQueueLast = null,\n update = current,\n didReadFromEntangledAsyncAction$60 = !1;\n do {\n var updateLane = update.lane & -536870913;\n if (\n updateLane !== update.lane\n ? (workInProgressRootRenderLanes & updateLane) === updateLane\n : (renderLanes & updateLane) === updateLane\n ) {\n var revertLane = update.revertLane;\n if (0 === revertLane)\n null !== newBaseQueueLast &&\n (newBaseQueueLast = newBaseQueueLast.next =\n {\n lane: 0,\n revertLane: 0,\n gesture: null,\n action: update.action,\n hasEagerState: update.hasEagerState,\n eagerState: update.eagerState,\n next: null\n }),\n updateLane === currentEntangledLane &&\n (didReadFromEntangledAsyncAction$60 = !0);\n else if ((renderLanes & revertLane) === revertLane) {\n update = update.next;\n revertLane === currentEntangledLane &&\n (didReadFromEntangledAsyncAction$60 = !0);\n continue;\n } else\n (updateLane = {\n lane: 0,\n revertLane: update.revertLane,\n gesture: null,\n action: update.action,\n hasEagerState: update.hasEagerState,\n eagerState: update.eagerState,\n next: null\n }),\n null === newBaseQueueLast\n ? ((newBaseQueueFirst = newBaseQueueLast = updateLane),\n (baseFirst = pendingQueue))\n : (newBaseQueueLast = newBaseQueueLast.next = updateLane),\n (currentlyRenderingFiber.lanes |= revertLane),\n (workInProgressRootSkippedLanes |= revertLane);\n updateLane = update.action;\n shouldDoubleInvokeUserFnsInHooksDEV &&\n reducer(pendingQueue, updateLane);\n pendingQueue = update.hasEagerState\n ? update.eagerState\n : reducer(pendingQueue, updateLane);\n } else\n (revertLane = {\n lane: updateLane,\n revertLane: update.revertLane,\n gesture: update.gesture,\n action: update.action,\n hasEagerState: update.hasEagerState,\n eagerState: update.eagerState,\n next: null\n }),\n null === newBaseQueueLast\n ? ((newBaseQueueFirst = newBaseQueueLast = revertLane),\n (baseFirst = pendingQueue))\n : (newBaseQueueLast = newBaseQueueLast.next = revertLane),\n (currentlyRenderingFiber.lanes |= updateLane),\n (workInProgressRootSkippedLanes |= updateLane);\n update = update.next;\n } while (null !== update && update !== current);\n null === newBaseQueueLast\n ? (baseFirst = pendingQueue)\n : (newBaseQueueLast.next = newBaseQueueFirst);\n if (\n !objectIs(pendingQueue, hook.memoizedState) &&\n ((didReceiveUpdate = !0),\n didReadFromEntangledAsyncAction$60 &&\n ((reducer = currentEntangledActionThenable), null !== reducer))\n )\n throw reducer;\n hook.memoizedState = pendingQueue;\n hook.baseState = baseFirst;\n hook.baseQueue = newBaseQueueLast;\n queue.lastRenderedState = pendingQueue;\n }\n null === baseQueue && (queue.lanes = 0);\n return [hook.memoizedState, queue.dispatch];\n}\nfunction rerenderReducer(reducer) {\n var hook = updateWorkInProgressHook(),\n queue = hook.queue;\n if (null === queue) throw Error(formatProdErrorMessage(311));\n queue.lastRenderedReducer = reducer;\n var dispatch = queue.dispatch,\n lastRenderPhaseUpdate = queue.pending,\n newState = hook.memoizedState;\n if (null !== lastRenderPhaseUpdate) {\n queue.pending = null;\n var update = (lastRenderPhaseUpdate = lastRenderPhaseUpdate.next);\n do (newState = reducer(newState, update.action)), (update = update.next);\n while (update !== lastRenderPhaseUpdate);\n objectIs(newState, hook.memoizedState) || (didReceiveUpdate = !0);\n hook.memoizedState = newState;\n null === hook.baseQueue && (hook.baseState = newState);\n queue.lastRenderedState = newState;\n }\n return [newState, dispatch];\n}\nfunction updateSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) {\n var fiber = currentlyRenderingFiber,\n hook = updateWorkInProgressHook(),\n isHydrating$jscomp$0 = isHydrating;\n if (isHydrating$jscomp$0) {\n if (void 0 === getServerSnapshot) throw Error(formatProdErrorMessage(407));\n getServerSnapshot = getServerSnapshot();\n } else getServerSnapshot = getSnapshot();\n var snapshotChanged = !objectIs(\n (currentHook || hook).memoizedState,\n getServerSnapshot\n );\n snapshotChanged &&\n ((hook.memoizedState = getServerSnapshot), (didReceiveUpdate = !0));\n hook = hook.queue;\n updateEffect(subscribeToStore.bind(null, fiber, hook, subscribe), [\n subscribe\n ]);\n if (\n hook.getSnapshot !== getSnapshot ||\n snapshotChanged ||\n (null !== workInProgressHook && workInProgressHook.memoizedState.tag & 1)\n ) {\n fiber.flags |= 2048;\n pushSimpleEffect(\n 9,\n { destroy: void 0 },\n updateStoreInstance.bind(\n null,\n fiber,\n hook,\n getServerSnapshot,\n getSnapshot\n ),\n null\n );\n if (null === workInProgressRoot) throw Error(formatProdErrorMessage(349));\n isHydrating$jscomp$0 ||\n 0 !== (renderLanes & 127) ||\n pushStoreConsistencyCheck(fiber, getSnapshot, getServerSnapshot);\n }\n return getServerSnapshot;\n}\nfunction pushStoreConsistencyCheck(fiber, getSnapshot, renderedSnapshot) {\n fiber.flags |= 16384;\n fiber = { getSnapshot: getSnapshot, value: renderedSnapshot };\n getSnapshot = currentlyRenderingFiber.updateQueue;\n null === getSnapshot\n ? ((getSnapshot = createFunctionComponentUpdateQueue()),\n (currentlyRenderingFiber.updateQueue = getSnapshot),\n (getSnapshot.stores = [fiber]))\n : ((renderedSnapshot = getSnapshot.stores),\n null === renderedSnapshot\n ? (getSnapshot.stores = [fiber])\n : renderedSnapshot.push(fiber));\n}\nfunction updateStoreInstance(fiber, inst, nextSnapshot, getSnapshot) {\n inst.value = nextSnapshot;\n inst.getSnapshot = getSnapshot;\n checkIfSnapshotChanged(inst) && forceStoreRerender(fiber);\n}\nfunction subscribeToStore(fiber, inst, subscribe) {\n return subscribe(function () {\n checkIfSnapshotChanged(inst) && forceStoreRerender(fiber);\n });\n}\nfunction checkIfSnapshotChanged(inst) {\n var latestGetSnapshot = inst.getSnapshot;\n inst = inst.value;\n try {\n var nextValue = latestGetSnapshot();\n return !objectIs(inst, nextValue);\n } catch (error) {\n return !0;\n }\n}\nfunction forceStoreRerender(fiber) {\n var root = enqueueConcurrentRenderForLane(fiber, 2);\n null !== root && scheduleUpdateOnFiber(root, fiber, 2);\n}\nfunction mountStateImpl(initialState) {\n var hook = mountWorkInProgressHook();\n if (\"function\" === typeof initialState) {\n var initialStateInitializer = initialState;\n initialState = initialStateInitializer();\n if (shouldDoubleInvokeUserFnsInHooksDEV) {\n setIsStrictModeForDevtools(!0);\n try {\n initialStateInitializer();\n } finally {\n setIsStrictModeForDevtools(!1);\n }\n }\n }\n hook.memoizedState = hook.baseState = initialState;\n hook.queue = {\n pending: null,\n lanes: 0,\n dispatch: null,\n lastRenderedReducer: basicStateReducer,\n lastRenderedState: initialState\n };\n return hook;\n}\nfunction updateOptimisticImpl(hook, current, passthrough, reducer) {\n hook.baseState = passthrough;\n return updateReducerImpl(\n hook,\n currentHook,\n \"function\" === typeof reducer ? reducer : basicStateReducer\n );\n}\nfunction dispatchActionState(\n fiber,\n actionQueue,\n setPendingState,\n setState,\n payload\n) {\n if (isRenderPhaseUpdate(fiber)) throw Error(formatProdErrorMessage(485));\n fiber = actionQueue.action;\n if (null !== fiber) {\n var actionNode = {\n payload: payload,\n action: fiber,\n next: null,\n isTransition: !0,\n status: \"pending\",\n value: null,\n reason: null,\n listeners: [],\n then: function (listener) {\n actionNode.listeners.push(listener);\n }\n };\n null !== ReactSharedInternals.T\n ? setPendingState(!0)\n : (actionNode.isTransition = !1);\n setState(actionNode);\n setPendingState = actionQueue.pending;\n null === setPendingState\n ? ((actionNode.next = actionQueue.pending = actionNode),\n runActionStateAction(actionQueue, actionNode))\n : ((actionNode.next = setPendingState.next),\n (actionQueue.pending = setPendingState.next = actionNode));\n }\n}\nfunction runActionStateAction(actionQueue, node) {\n var action = node.action,\n payload = node.payload,\n prevState = actionQueue.state;\n if (node.isTransition) {\n var prevTransition = ReactSharedInternals.T,\n currentTransition = {};\n ReactSharedInternals.T = currentTransition;\n try {\n var returnValue = action(prevState, payload),\n onStartTransitionFinish = ReactSharedInternals.S;\n null !== onStartTransitionFinish &&\n onStartTransitionFinish(currentTransition, returnValue);\n handleActionReturnValue(actionQueue, node, returnValue);\n } catch (error) {\n onActionError(actionQueue, node, error);\n } finally {\n null !== prevTransition &&\n null !== currentTransition.types &&\n (prevTransition.types = currentTransition.types),\n (ReactSharedInternals.T = prevTransition);\n }\n } else\n try {\n (prevTransition = action(prevState, payload)),\n handleActionReturnValue(actionQueue, node, prevTransition);\n } catch (error$66) {\n onActionError(actionQueue, node, error$66);\n }\n}\nfunction handleActionReturnValue(actionQueue, node, returnValue) {\n null !== returnValue &&\n \"object\" === typeof returnValue &&\n \"function\" === typeof returnValue.then\n ? returnValue.then(\n function (nextState) {\n onActionSuccess(actionQueue, node, nextState);\n },\n function (error) {\n return onActionError(actionQueue, node, error);\n }\n )\n : onActionSuccess(actionQueue, node, returnValue);\n}\nfunction onActionSuccess(actionQueue, actionNode, nextState) {\n actionNode.status = \"fulfilled\";\n actionNode.value = nextState;\n notifyActionListeners(actionNode);\n actionQueue.state = nextState;\n actionNode = actionQueue.pending;\n null !== actionNode &&\n ((nextState = actionNode.next),\n nextState === actionNode\n ? (actionQueue.pending = null)\n : ((nextState = nextState.next),\n (actionNode.next = nextState),\n runActionStateAction(actionQueue, nextState)));\n}\nfunction onActionError(actionQueue, actionNode, error) {\n var last = actionQueue.pending;\n actionQueue.pending = null;\n if (null !== last) {\n last = last.next;\n do\n (actionNode.status = \"rejected\"),\n (actionNode.reason = error),\n notifyActionListeners(actionNode),\n (actionNode = actionNode.next);\n while (actionNode !== last);\n }\n actionQueue.action = null;\n}\nfunction notifyActionListeners(actionNode) {\n actionNode = actionNode.listeners;\n for (var i = 0; i < actionNode.length; i++) (0, actionNode[i])();\n}\nfunction actionStateReducer(oldState, newState) {\n return newState;\n}\nfunction mountActionState(action, initialStateProp) {\n if (isHydrating) {\n var ssrFormState = workInProgressRoot.formState;\n if (null !== ssrFormState) {\n a: {\n var JSCompiler_inline_result = currentlyRenderingFiber;\n if (isHydrating) {\n if (nextHydratableInstance) {\n b: {\n var JSCompiler_inline_result$jscomp$0 = nextHydratableInstance;\n for (\n var inRootOrSingleton = rootOrSingletonContext;\n 8 !== JSCompiler_inline_result$jscomp$0.nodeType;\n\n ) {\n if (!inRootOrSingleton) {\n JSCompiler_inline_result$jscomp$0 = null;\n break b;\n }\n JSCompiler_inline_result$jscomp$0 = getNextHydratable(\n JSCompiler_inline_result$jscomp$0.nextSibling\n );\n if (null === JSCompiler_inline_result$jscomp$0) {\n JSCompiler_inline_result$jscomp$0 = null;\n break b;\n }\n }\n inRootOrSingleton = JSCompiler_inline_result$jscomp$0.data;\n JSCompiler_inline_result$jscomp$0 =\n \"F!\" === inRootOrSingleton || \"F\" === inRootOrSingleton\n ? JSCompiler_inline_result$jscomp$0\n : null;\n }\n if (JSCompiler_inline_result$jscomp$0) {\n nextHydratableInstance = getNextHydratable(\n JSCompiler_inline_result$jscomp$0.nextSibling\n );\n JSCompiler_inline_result =\n \"F!\" === JSCompiler_inline_result$jscomp$0.data;\n break a;\n }\n }\n throwOnHydrationMismatch(JSCompiler_inline_result);\n }\n JSCompiler_inline_result = !1;\n }\n JSCompiler_inline_result && (initialStateProp = ssrFormState[0]);\n }\n }\n ssrFormState = mountWorkInProgressHook();\n ssrFormState.memoizedState = ssrFormState.baseState = initialStateProp;\n JSCompiler_inline_result = {\n pending: null,\n lanes: 0,\n dispatch: null,\n lastRenderedReducer: actionStateReducer,\n lastRenderedState: initialStateProp\n };\n ssrFormState.queue = JSCompiler_inline_result;\n ssrFormState = dispatchSetState.bind(\n null,\n currentlyRenderingFiber,\n JSCompiler_inline_result\n );\n JSCompiler_inline_result.dispatch = ssrFormState;\n JSCompiler_inline_result = mountStateImpl(!1);\n inRootOrSingleton = dispatchOptimisticSetState.bind(\n null,\n currentlyRenderingFiber,\n !1,\n JSCompiler_inline_result.queue\n );\n JSCompiler_inline_result = mountWorkInProgressHook();\n JSCompiler_inline_result$jscomp$0 = {\n state: initialStateProp,\n dispatch: null,\n action: action,\n pending: null\n };\n JSCompiler_inline_result.queue = JSCompiler_inline_result$jscomp$0;\n ssrFormState = dispatchActionState.bind(\n null,\n currentlyRenderingFiber,\n JSCompiler_inline_result$jscomp$0,\n inRootOrSingleton,\n ssrFormState\n );\n JSCompiler_inline_result$jscomp$0.dispatch = ssrFormState;\n JSCompiler_inline_result.memoizedState = action;\n return [initialStateProp, ssrFormState, !1];\n}\nfunction updateActionState(action) {\n var stateHook = updateWorkInProgressHook();\n return updateActionStateImpl(stateHook, currentHook, action);\n}\nfunction updateActionStateImpl(stateHook, currentStateHook, action) {\n currentStateHook = updateReducerImpl(\n stateHook,\n currentStateHook,\n actionStateReducer\n )[0];\n stateHook = updateReducer(basicStateReducer)[0];\n if (\n \"object\" === typeof currentStateHook &&\n null !== currentStateHook &&\n \"function\" === typeof currentStateHook.then\n )\n try {\n var state = useThenable(currentStateHook);\n } catch (x) {\n if (x === SuspenseException) throw SuspenseActionException;\n throw x;\n }\n else state = currentStateHook;\n currentStateHook = updateWorkInProgressHook();\n var actionQueue = currentStateHook.queue,\n dispatch = actionQueue.dispatch;\n action !== currentStateHook.memoizedState &&\n ((currentlyRenderingFiber.flags |= 2048),\n pushSimpleEffect(\n 9,\n { destroy: void 0 },\n actionStateActionEffect.bind(null, actionQueue, action),\n null\n ));\n return [state, dispatch, stateHook];\n}\nfunction actionStateActionEffect(actionQueue, action) {\n actionQueue.action = action;\n}\nfunction rerenderActionState(action) {\n var stateHook = updateWorkInProgressHook(),\n currentStateHook = currentHook;\n if (null !== currentStateHook)\n return updateActionStateImpl(stateHook, currentStateHook, action);\n updateWorkInProgressHook();\n stateHook = stateHook.memoizedState;\n currentStateHook = updateWorkInProgressHook();\n var dispatch = currentStateHook.queue.dispatch;\n currentStateHook.memoizedState = action;\n return [stateHook, dispatch, !1];\n}\nfunction pushSimpleEffect(tag, inst, create, deps) {\n tag = { tag: tag, create: create, deps: deps, inst: inst, next: null };\n inst = currentlyRenderingFiber.updateQueue;\n null === inst &&\n ((inst = createFunctionComponentUpdateQueue()),\n (currentlyRenderingFiber.updateQueue = inst));\n create = inst.lastEffect;\n null === create\n ? (inst.lastEffect = tag.next = tag)\n : ((deps = create.next),\n (create.next = tag),\n (tag.next = deps),\n (inst.lastEffect = tag));\n return tag;\n}\nfunction updateRef() {\n return updateWorkInProgressHook().memoizedState;\n}\nfunction mountEffectImpl(fiberFlags, hookFlags, create, deps) {\n var hook = mountWorkInProgressHook();\n currentlyRenderingFiber.flags |= fiberFlags;\n hook.memoizedState = pushSimpleEffect(\n 1 | hookFlags,\n { destroy: void 0 },\n create,\n void 0 === deps ? null : deps\n );\n}\nfunction updateEffectImpl(fiberFlags, hookFlags, create, deps) {\n var hook = updateWorkInProgressHook();\n deps = void 0 === deps ? null : deps;\n var inst = hook.memoizedState.inst;\n null !== currentHook &&\n null !== deps &&\n areHookInputsEqual(deps, currentHook.memoizedState.deps)\n ? (hook.memoizedState = pushSimpleEffect(hookFlags, inst, create, deps))\n : ((currentlyRenderingFiber.flags |= fiberFlags),\n (hook.memoizedState = pushSimpleEffect(\n 1 | hookFlags,\n inst,\n create,\n deps\n )));\n}\nfunction mountEffect(create, deps) {\n mountEffectImpl(8390656, 8, create, deps);\n}\nfunction updateEffect(create, deps) {\n updateEffectImpl(2048, 8, create, deps);\n}\nfunction useEffectEventImpl(payload) {\n currentlyRenderingFiber.flags |= 4;\n var componentUpdateQueue = currentlyRenderingFiber.updateQueue;\n if (null === componentUpdateQueue)\n (componentUpdateQueue = createFunctionComponentUpdateQueue()),\n (currentlyRenderingFiber.updateQueue = componentUpdateQueue),\n (componentUpdateQueue.events = [payload]);\n else {\n var events = componentUpdateQueue.events;\n null === events\n ? (componentUpdateQueue.events = [payload])\n : events.push(payload);\n }\n}\nfunction updateEvent(callback) {\n var ref = updateWorkInProgressHook().memoizedState;\n useEffectEventImpl({ ref: ref, nextImpl: callback });\n return function () {\n if (0 !== (executionContext & 2)) throw Error(formatProdErrorMessage(440));\n return ref.impl.apply(void 0, arguments);\n };\n}\nfunction updateInsertionEffect(create, deps) {\n return updateEffectImpl(4, 2, create, deps);\n}\nfunction updateLayoutEffect(create, deps) {\n return updateEffectImpl(4, 4, create, deps);\n}\nfunction imperativeHandleEffect(create, ref) {\n if (\"function\" === typeof ref) {\n create = create();\n var refCleanup = ref(create);\n return function () {\n \"function\" === typeof refCleanup ? refCleanup() : ref(null);\n };\n }\n if (null !== ref && void 0 !== ref)\n return (\n (create = create()),\n (ref.current = create),\n function () {\n ref.current = null;\n }\n );\n}\nfunction updateImperativeHandle(ref, create, deps) {\n deps = null !== deps && void 0 !== deps ? deps.concat([ref]) : null;\n updateEffectImpl(4, 4, imperativeHandleEffect.bind(null, create, ref), deps);\n}\nfunction mountDebugValue() {}\nfunction updateCallback(callback, deps) {\n var hook = updateWorkInProgressHook();\n deps = void 0 === deps ? null : deps;\n var prevState = hook.memoizedState;\n if (null !== deps && areHookInputsEqual(deps, prevState[1]))\n return prevState[0];\n hook.memoizedState = [callback, deps];\n return callback;\n}\nfunction updateMemo(nextCreate, deps) {\n var hook = updateWorkInProgressHook();\n deps = void 0 === deps ? null : deps;\n var prevState = hook.memoizedState;\n if (null !== deps && areHookInputsEqual(deps, prevState[1]))\n return prevState[0];\n prevState = nextCreate();\n if (shouldDoubleInvokeUserFnsInHooksDEV) {\n setIsStrictModeForDevtools(!0);\n try {\n nextCreate();\n } finally {\n setIsStrictModeForDevtools(!1);\n }\n }\n hook.memoizedState = [prevState, deps];\n return prevState;\n}\nfunction mountDeferredValueImpl(hook, value, initialValue) {\n if (\n void 0 === initialValue ||\n (0 !== (renderLanes & 1073741824) &&\n 0 === (workInProgressRootRenderLanes & 261930))\n )\n return (hook.memoizedState = value);\n hook.memoizedState = initialValue;\n hook = requestDeferredLane();\n currentlyRenderingFiber.lanes |= hook;\n workInProgressRootSkippedLanes |= hook;\n return initialValue;\n}\nfunction updateDeferredValueImpl(hook, prevValue, value, initialValue) {\n if (objectIs(value, prevValue)) return value;\n if (null !== currentTreeHiddenStackCursor.current)\n return (\n (hook = mountDeferredValueImpl(hook, value, initialValue)),\n objectIs(hook, prevValue) || (didReceiveUpdate = !0),\n hook\n );\n if (\n 0 === (renderLanes & 42) ||\n (0 !== (renderLanes & 1073741824) &&\n 0 === (workInProgressRootRenderLanes & 261930))\n )\n return (didReceiveUpdate = !0), (hook.memoizedState = value);\n hook = requestDeferredLane();\n currentlyRenderingFiber.lanes |= hook;\n workInProgressRootSkippedLanes |= hook;\n return prevValue;\n}\nfunction startTransition(fiber, queue, pendingState, finishedState, callback) {\n var previousPriority = ReactDOMSharedInternals.p;\n ReactDOMSharedInternals.p =\n 0 !== previousPriority && 8 > previousPriority ? previousPriority : 8;\n var prevTransition = ReactSharedInternals.T,\n currentTransition = {};\n ReactSharedInternals.T = currentTransition;\n dispatchOptimisticSetState(fiber, !1, queue, pendingState);\n try {\n var returnValue = callback(),\n onStartTransitionFinish = ReactSharedInternals.S;\n null !== onStartTransitionFinish &&\n onStartTransitionFinish(currentTransition, returnValue);\n if (\n null !== returnValue &&\n \"object\" === typeof returnValue &&\n \"function\" === typeof returnValue.then\n ) {\n var thenableForFinishedState = chainThenableValue(\n returnValue,\n finishedState\n );\n dispatchSetStateInternal(\n fiber,\n queue,\n thenableForFinishedState,\n requestUpdateLane(fiber)\n );\n } else\n dispatchSetStateInternal(\n fiber,\n queue,\n finishedState,\n requestUpdateLane(fiber)\n );\n } catch (error) {\n dispatchSetStateInternal(\n fiber,\n queue,\n { then: function () {}, status: \"rejected\", reason: error },\n requestUpdateLane()\n );\n } finally {\n (ReactDOMSharedInternals.p = previousPriority),\n null !== prevTransition &&\n null !== currentTransition.types &&\n (prevTransition.types = currentTransition.types),\n (ReactSharedInternals.T = prevTransition);\n }\n}\nfunction noop() {}\nfunction startHostTransition(formFiber, pendingState, action, formData) {\n if (5 !== formFiber.tag) throw Error(formatProdErrorMessage(476));\n var queue = ensureFormComponentIsStateful(formFiber).queue;\n startTransition(\n formFiber,\n queue,\n pendingState,\n sharedNotPendingObject,\n null === action\n ? noop\n : function () {\n requestFormReset$1(formFiber);\n return action(formData);\n }\n );\n}\nfunction ensureFormComponentIsStateful(formFiber) {\n var existingStateHook = formFiber.memoizedState;\n if (null !== existingStateHook) return existingStateHook;\n existingStateHook = {\n memoizedState: sharedNotPendingObject,\n baseState: sharedNotPendingObject,\n baseQueue: null,\n queue: {\n pending: null,\n lanes: 0,\n dispatch: null,\n lastRenderedReducer: basicStateReducer,\n lastRenderedState: sharedNotPendingObject\n },\n next: null\n };\n var initialResetState = {};\n existingStateHook.next = {\n memoizedState: initialResetState,\n baseState: initialResetState,\n baseQueue: null,\n queue: {\n pending: null,\n lanes: 0,\n dispatch: null,\n lastRenderedReducer: basicStateReducer,\n lastRenderedState: initialResetState\n },\n next: null\n };\n formFiber.memoizedState = existingStateHook;\n formFiber = formFiber.alternate;\n null !== formFiber && (formFiber.memoizedState = existingStateHook);\n return existingStateHook;\n}\nfunction requestFormReset$1(formFiber) {\n var stateHook = ensureFormComponentIsStateful(formFiber);\n null === stateHook.next && (stateHook = formFiber.alternate.memoizedState);\n dispatchSetStateInternal(\n formFiber,\n stateHook.next.queue,\n {},\n requestUpdateLane()\n );\n}\nfunction useHostTransitionStatus() {\n return readContext(HostTransitionContext);\n}\nfunction updateId() {\n return updateWorkInProgressHook().memoizedState;\n}\nfunction updateRefresh() {\n return updateWorkInProgressHook().memoizedState;\n}\nfunction refreshCache(fiber) {\n for (var provider = fiber.return; null !== provider; ) {\n switch (provider.tag) {\n case 24:\n case 3:\n var lane = requestUpdateLane();\n fiber = createUpdate(lane);\n var root$69 = enqueueUpdate(provider, fiber, lane);\n null !== root$69 &&\n (scheduleUpdateOnFiber(root$69, provider, lane),\n entangleTransitions(root$69, provider, lane));\n provider = { cache: createCache() };\n fiber.payload = provider;\n return;\n }\n provider = provider.return;\n }\n}\nfunction dispatchReducerAction(fiber, queue, action) {\n var lane = requestUpdateLane();\n action = {\n lane: lane,\n revertLane: 0,\n gesture: null,\n action: action,\n hasEagerState: !1,\n eagerState: null,\n next: null\n };\n isRenderPhaseUpdate(fiber)\n ? enqueueRenderPhaseUpdate(queue, action)\n : ((action = enqueueConcurrentHookUpdate(fiber, queue, action, lane)),\n null !== action &&\n (scheduleUpdateOnFiber(action, fiber, lane),\n entangleTransitionUpdate(action, queue, lane)));\n}\nfunction dispatchSetState(fiber, queue, action) {\n var lane = requestUpdateLane();\n dispatchSetStateInternal(fiber, queue, action, lane);\n}\nfunction dispatchSetStateInternal(fiber, queue, action, lane) {\n var update = {\n lane: lane,\n revertLane: 0,\n gesture: null,\n action: action,\n hasEagerState: !1,\n eagerState: null,\n next: null\n };\n if (isRenderPhaseUpdate(fiber)) enqueueRenderPhaseUpdate(queue, update);\n else {\n var alternate = fiber.alternate;\n if (\n 0 === fiber.lanes &&\n (null === alternate || 0 === alternate.lanes) &&\n ((alternate = queue.lastRenderedReducer), null !== alternate)\n )\n try {\n var currentState = queue.lastRenderedState,\n eagerState = alternate(currentState, action);\n update.hasEagerState = !0;\n update.eagerState = eagerState;\n if (objectIs(eagerState, currentState))\n return (\n enqueueUpdate$1(fiber, queue, update, 0),\n null === workInProgressRoot && finishQueueingConcurrentUpdates(),\n !1\n );\n } catch (error) {\n } finally {\n }\n action = enqueueConcurrentHookUpdate(fiber, queue, update, lane);\n if (null !== action)\n return (\n scheduleUpdateOnFiber(action, fiber, lane),\n entangleTransitionUpdate(action, queue, lane),\n !0\n );\n }\n return !1;\n}\nfunction dispatchOptimisticSetState(fiber, throwIfDuringRender, queue, action) {\n action = {\n lane: 2,\n revertLane: requestTransitionLane(),\n gesture: null,\n action: action,\n hasEagerState: !1,\n eagerState: null,\n next: null\n };\n if (isRenderPhaseUpdate(fiber)) {\n if (throwIfDuringRender) throw Error(formatProdErrorMessage(479));\n } else\n (throwIfDuringRender = enqueueConcurrentHookUpdate(\n fiber,\n queue,\n action,\n 2\n )),\n null !== throwIfDuringRender &&\n scheduleUpdateOnFiber(throwIfDuringRender, fiber, 2);\n}\nfunction isRenderPhaseUpdate(fiber) {\n var alternate = fiber.alternate;\n return (\n fiber === currentlyRenderingFiber ||\n (null !== alternate && alternate === currentlyRenderingFiber)\n );\n}\nfunction enqueueRenderPhaseUpdate(queue, update) {\n didScheduleRenderPhaseUpdateDuringThisPass = didScheduleRenderPhaseUpdate =\n !0;\n var pending = queue.pending;\n null === pending\n ? (update.next = update)\n : ((update.next = pending.next), (pending.next = update));\n queue.pending = update;\n}\nfunction entangleTransitionUpdate(root, queue, lane) {\n if (0 !== (lane & 4194048)) {\n var queueLanes = queue.lanes;\n queueLanes &= root.pendingLanes;\n lane |= queueLanes;\n queue.lanes = lane;\n markRootEntangled(root, lane);\n }\n}\nvar ContextOnlyDispatcher = {\n readContext: readContext,\n use: use,\n useCallback: throwInvalidHookError,\n useContext: throwInvalidHookError,\n useEffect: throwInvalidHookError,\n useImperativeHandle: throwInvalidHookError,\n useLayoutEffect: throwInvalidHookError,\n useInsertionEffect: throwInvalidHookError,\n useMemo: throwInvalidHookError,\n useReducer: throwInvalidHookError,\n useRef: throwInvalidHookError,\n useState: throwInvalidHookError,\n useDebugValue: throwInvalidHookError,\n useDeferredValue: throwInvalidHookError,\n useTransition: throwInvalidHookError,\n useSyncExternalStore: throwInvalidHookError,\n useId: throwInvalidHookError,\n useHostTransitionStatus: throwInvalidHookError,\n useFormState: throwInvalidHookError,\n useActionState: throwInvalidHookError,\n useOptimistic: throwInvalidHookError,\n useMemoCache: throwInvalidHookError,\n useCacheRefresh: throwInvalidHookError\n};\nContextOnlyDispatcher.useEffectEvent = throwInvalidHookError;\nvar HooksDispatcherOnMount = {\n readContext: readContext,\n use: use,\n useCallback: function (callback, deps) {\n mountWorkInProgressHook().memoizedState = [\n callback,\n void 0 === deps ? null : deps\n ];\n return callback;\n },\n useContext: readContext,\n useEffect: mountEffect,\n useImperativeHandle: function (ref, create, deps) {\n deps = null !== deps && void 0 !== deps ? deps.concat([ref]) : null;\n mountEffectImpl(\n 4194308,\n 4,\n imperativeHandleEffect.bind(null, create, ref),\n deps\n );\n },\n useLayoutEffect: function (create, deps) {\n return mountEffectImpl(4194308, 4, create, deps);\n },\n useInsertionEffect: function (create, deps) {\n mountEffectImpl(4, 2, create, deps);\n },\n useMemo: function (nextCreate, deps) {\n var hook = mountWorkInProgressHook();\n deps = void 0 === deps ? null : deps;\n var nextValue = nextCreate();\n if (shouldDoubleInvokeUserFnsInHooksDEV) {\n setIsStrictModeForDevtools(!0);\n try {\n nextCreate();\n } finally {\n setIsStrictModeForDevtools(!1);\n }\n }\n hook.memoizedState = [nextValue, deps];\n return nextValue;\n },\n useReducer: function (reducer, initialArg, init) {\n var hook = mountWorkInProgressHook();\n if (void 0 !== init) {\n var initialState = init(initialArg);\n if (shouldDoubleInvokeUserFnsInHooksDEV) {\n setIsStrictModeForDevtools(!0);\n try {\n init(initialArg);\n } finally {\n setIsStrictModeForDevtools(!1);\n }\n }\n } else initialState = initialArg;\n hook.memoizedState = hook.baseState = initialState;\n reducer = {\n pending: null,\n lanes: 0,\n dispatch: null,\n lastRenderedReducer: reducer,\n lastRenderedState: initialState\n };\n hook.queue = reducer;\n reducer = reducer.dispatch = dispatchReducerAction.bind(\n null,\n currentlyRenderingFiber,\n reducer\n );\n return [hook.memoizedState, reducer];\n },\n useRef: function (initialValue) {\n var hook = mountWorkInProgressHook();\n initialValue = { current: initialValue };\n return (hook.memoizedState = initialValue);\n },\n useState: function (initialState) {\n initialState = mountStateImpl(initialState);\n var queue = initialState.queue,\n dispatch = dispatchSetState.bind(null, currentlyRenderingFiber, queue);\n queue.dispatch = dispatch;\n return [initialState.memoizedState, dispatch];\n },\n useDebugValue: mountDebugValue,\n useDeferredValue: function (value, initialValue) {\n var hook = mountWorkInProgressHook();\n return mountDeferredValueImpl(hook, value, initialValue);\n },\n useTransition: function () {\n var stateHook = mountStateImpl(!1);\n stateHook = startTransition.bind(\n null,\n currentlyRenderingFiber,\n stateHook.queue,\n !0,\n !1\n );\n mountWorkInProgressHook().memoizedState = stateHook;\n return [!1, stateHook];\n },\n useSyncExternalStore: function (subscribe, getSnapshot, getServerSnapshot) {\n var fiber = currentlyRenderingFiber,\n hook = mountWorkInProgressHook();\n if (isHydrating) {\n if (void 0 === getServerSnapshot)\n throw Error(formatProdErrorMessage(407));\n getServerSnapshot = getServerSnapshot();\n } else {\n getServerSnapshot = getSnapshot();\n if (null === workInProgressRoot)\n throw Error(formatProdErrorMessage(349));\n 0 !== (workInProgressRootRenderLanes & 127) ||\n pushStoreConsistencyCheck(fiber, getSnapshot, getServerSnapshot);\n }\n hook.memoizedState = getServerSnapshot;\n var inst = { value: getServerSnapshot, getSnapshot: getSnapshot };\n hook.queue = inst;\n mountEffect(subscribeToStore.bind(null, fiber, inst, subscribe), [\n subscribe\n ]);\n fiber.flags |= 2048;\n pushSimpleEffect(\n 9,\n { destroy: void 0 },\n updateStoreInstance.bind(\n null,\n fiber,\n inst,\n getServerSnapshot,\n getSnapshot\n ),\n null\n );\n return getServerSnapshot;\n },\n useId: function () {\n var hook = mountWorkInProgressHook(),\n identifierPrefix = workInProgressRoot.identifierPrefix;\n if (isHydrating) {\n var JSCompiler_inline_result = treeContextOverflow;\n var idWithLeadingBit = treeContextId;\n JSCompiler_inline_result =\n (\n idWithLeadingBit & ~(1 << (32 - clz32(idWithLeadingBit) - 1))\n ).toString(32) + JSCompiler_inline_result;\n identifierPrefix =\n \"_\" + identifierPrefix + \"R_\" + JSCompiler_inline_result;\n JSCompiler_inline_result = localIdCounter++;\n 0 < JSCompiler_inline_result &&\n (identifierPrefix += \"H\" + JSCompiler_inline_result.toString(32));\n identifierPrefix += \"_\";\n } else\n (JSCompiler_inline_result = globalClientIdCounter++),\n (identifierPrefix =\n \"_\" +\n identifierPrefix +\n \"r_\" +\n JSCompiler_inline_result.toString(32) +\n \"_\");\n return (hook.memoizedState = identifierPrefix);\n },\n useHostTransitionStatus: useHostTransitionStatus,\n useFormState: mountActionState,\n useActionState: mountActionState,\n useOptimistic: function (passthrough) {\n var hook = mountWorkInProgressHook();\n hook.memoizedState = hook.baseState = passthrough;\n var queue = {\n pending: null,\n lanes: 0,\n dispatch: null,\n lastRenderedReducer: null,\n lastRenderedState: null\n };\n hook.queue = queue;\n hook = dispatchOptimisticSetState.bind(\n null,\n currentlyRenderingFiber,\n !0,\n queue\n );\n queue.dispatch = hook;\n return [passthrough, hook];\n },\n useMemoCache: useMemoCache,\n useCacheRefresh: function () {\n return (mountWorkInProgressHook().memoizedState = refreshCache.bind(\n null,\n currentlyRenderingFiber\n ));\n },\n useEffectEvent: function (callback) {\n var hook = mountWorkInProgressHook(),\n ref = { impl: callback };\n hook.memoizedState = ref;\n return function () {\n if (0 !== (executionContext & 2))\n throw Error(formatProdErrorMessage(440));\n return ref.impl.apply(void 0, arguments);\n };\n }\n },\n HooksDispatcherOnUpdate = {\n readContext: readContext,\n use: use,\n useCallback: updateCallback,\n useContext: readContext,\n useEffect: updateEffect,\n useImperativeHandle: updateImperativeHandle,\n useInsertionEffect: updateInsertionEffect,\n useLayoutEffect: updateLayoutEffect,\n useMemo: updateMemo,\n useReducer: updateReducer,\n useRef: updateRef,\n useState: function () {\n return updateReducer(basicStateReducer);\n },\n useDebugValue: mountDebugValue,\n useDeferredValue: function (value, initialValue) {\n var hook = updateWorkInProgressHook();\n return updateDeferredValueImpl(\n hook,\n currentHook.memoizedState,\n value,\n initialValue\n );\n },\n useTransition: function () {\n var booleanOrThenable = updateReducer(basicStateReducer)[0],\n start = updateWorkInProgressHook().memoizedState;\n return [\n \"boolean\" === typeof booleanOrThenable\n ? booleanOrThenable\n : useThenable(booleanOrThenable),\n start\n ];\n },\n useSyncExternalStore: updateSyncExternalStore,\n useId: updateId,\n useHostTransitionStatus: useHostTransitionStatus,\n useFormState: updateActionState,\n useActionState: updateActionState,\n useOptimistic: function (passthrough, reducer) {\n var hook = updateWorkInProgressHook();\n return updateOptimisticImpl(hook, currentHook, passthrough, reducer);\n },\n useMemoCache: useMemoCache,\n useCacheRefresh: updateRefresh\n };\nHooksDispatcherOnUpdate.useEffectEvent = updateEvent;\nvar HooksDispatcherOnRerender = {\n readContext: readContext,\n use: use,\n useCallback: updateCallback,\n useContext: readContext,\n useEffect: updateEffect,\n useImperativeHandle: updateImperativeHandle,\n useInsertionEffect: updateInsertionEffect,\n useLayoutEffect: updateLayoutEffect,\n useMemo: updateMemo,\n useReducer: rerenderReducer,\n useRef: updateRef,\n useState: function () {\n return rerenderReducer(basicStateReducer);\n },\n useDebugValue: mountDebugValue,\n useDeferredValue: function (value, initialValue) {\n var hook = updateWorkInProgressHook();\n return null === currentHook\n ? mountDeferredValueImpl(hook, value, initialValue)\n : updateDeferredValueImpl(\n hook,\n currentHook.memoizedState,\n value,\n initialValue\n );\n },\n useTransition: function () {\n var booleanOrThenable = rerenderReducer(basicStateReducer)[0],\n start = updateWorkInProgressHook().memoizedState;\n return [\n \"boolean\" === typeof booleanOrThenable\n ? booleanOrThenable\n : useThenable(booleanOrThenable),\n start\n ];\n },\n useSyncExternalStore: updateSyncExternalStore,\n useId: updateId,\n useHostTransitionStatus: useHostTransitionStatus,\n useFormState: rerenderActionState,\n useActionState: rerenderActionState,\n useOptimistic: function (passthrough, reducer) {\n var hook = updateWorkInProgressHook();\n if (null !== currentHook)\n return updateOptimisticImpl(hook, currentHook, passthrough, reducer);\n hook.baseState = passthrough;\n return [passthrough, hook.queue.dispatch];\n },\n useMemoCache: useMemoCache,\n useCacheRefresh: updateRefresh\n};\nHooksDispatcherOnRerender.useEffectEvent = updateEvent;\nfunction applyDerivedStateFromProps(\n workInProgress,\n ctor,\n getDerivedStateFromProps,\n nextProps\n) {\n ctor = workInProgress.memoizedState;\n getDerivedStateFromProps = getDerivedStateFromProps(nextProps, ctor);\n getDerivedStateFromProps =\n null === getDerivedStateFromProps || void 0 === getDerivedStateFromProps\n ? ctor\n : assign({}, ctor, getDerivedStateFromProps);\n workInProgress.memoizedState = getDerivedStateFromProps;\n 0 === workInProgress.lanes &&\n (workInProgress.updateQueue.baseState = getDerivedStateFromProps);\n}\nvar classComponentUpdater = {\n enqueueSetState: function (inst, payload, callback) {\n inst = inst._reactInternals;\n var lane = requestUpdateLane(),\n update = createUpdate(lane);\n update.payload = payload;\n void 0 !== callback && null !== callback && (update.callback = callback);\n payload = enqueueUpdate(inst, update, lane);\n null !== payload &&\n (scheduleUpdateOnFiber(payload, inst, lane),\n entangleTransitions(payload, inst, lane));\n },\n enqueueReplaceState: function (inst, payload, callback) {\n inst = inst._reactInternals;\n var lane = requestUpdateLane(),\n update = createUpdate(lane);\n update.tag = 1;\n update.payload = payload;\n void 0 !== callback && null !== callback && (update.callback = callback);\n payload = enqueueUpdate(inst, update, lane);\n null !== payload &&\n (scheduleUpdateOnFiber(payload, inst, lane),\n entangleTransitions(payload, inst, lane));\n },\n enqueueForceUpdate: function (inst, callback) {\n inst = inst._reactInternals;\n var lane = requestUpdateLane(),\n update = createUpdate(lane);\n update.tag = 2;\n void 0 !== callback && null !== callback && (update.callback = callback);\n callback = enqueueUpdate(inst, update, lane);\n null !== callback &&\n (scheduleUpdateOnFiber(callback, inst, lane),\n entangleTransitions(callback, inst, lane));\n }\n};\nfunction checkShouldComponentUpdate(\n workInProgress,\n ctor,\n oldProps,\n newProps,\n oldState,\n newState,\n nextContext\n) {\n workInProgress = workInProgress.stateNode;\n return \"function\" === typeof workInProgress.shouldComponentUpdate\n ? workInProgress.shouldComponentUpdate(newProps, newState, nextContext)\n : ctor.prototype && ctor.prototype.isPureReactComponent\n ? !shallowEqual(oldProps, newProps) || !shallowEqual(oldState, newState)\n : !0;\n}\nfunction callComponentWillReceiveProps(\n workInProgress,\n instance,\n newProps,\n nextContext\n) {\n workInProgress = instance.state;\n \"function\" === typeof instance.componentWillReceiveProps &&\n instance.componentWillReceiveProps(newProps, nextContext);\n \"function\" === typeof instance.UNSAFE_componentWillReceiveProps &&\n instance.UNSAFE_componentWillReceiveProps(newProps, nextContext);\n instance.state !== workInProgress &&\n classComponentUpdater.enqueueReplaceState(instance, instance.state, null);\n}\nfunction resolveClassComponentProps(Component, baseProps) {\n var newProps = baseProps;\n if (\"ref\" in baseProps) {\n newProps = {};\n for (var propName in baseProps)\n \"ref\" !== propName && (newProps[propName] = baseProps[propName]);\n }\n if ((Component = Component.defaultProps)) {\n newProps === baseProps && (newProps = assign({}, newProps));\n for (var propName$73 in Component)\n void 0 === newProps[propName$73] &&\n (newProps[propName$73] = Component[propName$73]);\n }\n return newProps;\n}\nfunction defaultOnUncaughtError(error) {\n reportGlobalError(error);\n}\nfunction defaultOnCaughtError(error) {\n console.error(error);\n}\nfunction defaultOnRecoverableError(error) {\n reportGlobalError(error);\n}\nfunction logUncaughtError(root, errorInfo) {\n try {\n var onUncaughtError = root.onUncaughtError;\n onUncaughtError(errorInfo.value, { componentStack: errorInfo.stack });\n } catch (e$74) {\n setTimeout(function () {\n throw e$74;\n });\n }\n}\nfunction logCaughtError(root, boundary, errorInfo) {\n try {\n var onCaughtError = root.onCaughtError;\n onCaughtError(errorInfo.value, {\n componentStack: errorInfo.stack,\n errorBoundary: 1 === boundary.tag ? boundary.stateNode : null\n });\n } catch (e$75) {\n setTimeout(function () {\n throw e$75;\n });\n }\n}\nfunction createRootErrorUpdate(root, errorInfo, lane) {\n lane = createUpdate(lane);\n lane.tag = 3;\n lane.payload = { element: null };\n lane.callback = function () {\n logUncaughtError(root, errorInfo);\n };\n return lane;\n}\nfunction createClassErrorUpdate(lane) {\n lane = createUpdate(lane);\n lane.tag = 3;\n return lane;\n}\nfunction initializeClassErrorUpdate(update, root, fiber, errorInfo) {\n var getDerivedStateFromError = fiber.type.getDerivedStateFromError;\n if (\"function\" === typeof getDerivedStateFromError) {\n var error = errorInfo.value;\n update.payload = function () {\n return getDerivedStateFromError(error);\n };\n update.callback = function () {\n logCaughtError(root, fiber, errorInfo);\n };\n }\n var inst = fiber.stateNode;\n null !== inst &&\n \"function\" === typeof inst.componentDidCatch &&\n (update.callback = function () {\n logCaughtError(root, fiber, errorInfo);\n \"function\" !== typeof getDerivedStateFromError &&\n (null === legacyErrorBoundariesThatAlreadyFailed\n ? (legacyErrorBoundariesThatAlreadyFailed = new Set([this]))\n : legacyErrorBoundariesThatAlreadyFailed.add(this));\n var stack = errorInfo.stack;\n this.componentDidCatch(errorInfo.value, {\n componentStack: null !== stack ? stack : \"\"\n });\n });\n}\nfunction throwException(\n root,\n returnFiber,\n sourceFiber,\n value,\n rootRenderLanes\n) {\n sourceFiber.flags |= 32768;\n if (\n null !== value &&\n \"object\" === typeof value &&\n \"function\" === typeof value.then\n ) {\n returnFiber = sourceFiber.alternate;\n null !== returnFiber &&\n propagateParentContextChanges(\n returnFiber,\n sourceFiber,\n rootRenderLanes,\n !0\n );\n sourceFiber = suspenseHandlerStackCursor.current;\n if (null !== sourceFiber) {\n switch (sourceFiber.tag) {\n case 31:\n case 13:\n return (\n null === shellBoundary\n ? renderDidSuspendDelayIfPossible()\n : null === sourceFiber.alternate &&\n 0 === workInProgressRootExitStatus &&\n (workInProgressRootExitStatus = 3),\n (sourceFiber.flags &= -257),\n (sourceFiber.flags |= 65536),\n (sourceFiber.lanes = rootRenderLanes),\n value === noopSuspenseyCommitThenable\n ? (sourceFiber.flags |= 16384)\n : ((returnFiber = sourceFiber.updateQueue),\n null === returnFiber\n ? (sourceFiber.updateQueue = new Set([value]))\n : returnFiber.add(value),\n attachPingListener(root, value, rootRenderLanes)),\n !1\n );\n case 22:\n return (\n (sourceFiber.flags |= 65536),\n value === noopSuspenseyCommitThenable\n ? (sourceFiber.flags |= 16384)\n : ((returnFiber = sourceFiber.updateQueue),\n null === returnFiber\n ? ((returnFiber = {\n transitions: null,\n markerInstances: null,\n retryQueue: new Set([value])\n }),\n (sourceFiber.updateQueue = returnFiber))\n : ((sourceFiber = returnFiber.retryQueue),\n null === sourceFiber\n ? (returnFiber.retryQueue = new Set([value]))\n : sourceFiber.add(value)),\n attachPingListener(root, value, rootRenderLanes)),\n !1\n );\n }\n throw Error(formatProdErrorMessage(435, sourceFiber.tag));\n }\n attachPingListener(root, value, rootRenderLanes);\n renderDidSuspendDelayIfPossible();\n return !1;\n }\n if (isHydrating)\n return (\n (returnFiber = suspenseHandlerStackCursor.current),\n null !== returnFiber\n ? (0 === (returnFiber.flags & 65536) && (returnFiber.flags |= 256),\n (returnFiber.flags |= 65536),\n (returnFiber.lanes = rootRenderLanes),\n value !== HydrationMismatchException &&\n ((root = Error(formatProdErrorMessage(422), { cause: value })),\n queueHydrationError(createCapturedValueAtFiber(root, sourceFiber))))\n : (value !== HydrationMismatchException &&\n ((returnFiber = Error(formatProdErrorMessage(423), {\n cause: value\n })),\n queueHydrationError(\n createCapturedValueAtFiber(returnFiber, sourceFiber)\n )),\n (root = root.current.alternate),\n (root.flags |= 65536),\n (rootRenderLanes &= -rootRenderLanes),\n (root.lanes |= rootRenderLanes),\n (value = createCapturedValueAtFiber(value, sourceFiber)),\n (rootRenderLanes = createRootErrorUpdate(\n root.stateNode,\n value,\n rootRenderLanes\n )),\n enqueueCapturedUpdate(root, rootRenderLanes),\n 4 !== workInProgressRootExitStatus &&\n (workInProgressRootExitStatus = 2)),\n !1\n );\n var wrapperError = Error(formatProdErrorMessage(520), { cause: value });\n wrapperError = createCapturedValueAtFiber(wrapperError, sourceFiber);\n null === workInProgressRootConcurrentErrors\n ? (workInProgressRootConcurrentErrors = [wrapperError])\n : workInProgressRootConcurrentErrors.push(wrapperError);\n 4 !== workInProgressRootExitStatus && (workInProgressRootExitStatus = 2);\n if (null === returnFiber) return !0;\n value = createCapturedValueAtFiber(value, sourceFiber);\n sourceFiber = returnFiber;\n do {\n switch (sourceFiber.tag) {\n case 3:\n return (\n (sourceFiber.flags |= 65536),\n (root = rootRenderLanes & -rootRenderLanes),\n (sourceFiber.lanes |= root),\n (root = createRootErrorUpdate(sourceFiber.stateNode, value, root)),\n enqueueCapturedUpdate(sourceFiber, root),\n !1\n );\n case 1:\n if (\n ((returnFiber = sourceFiber.type),\n (wrapperError = sourceFiber.stateNode),\n 0 === (sourceFiber.flags & 128) &&\n (\"function\" === typeof returnFiber.getDerivedStateFromError ||\n (null !== wrapperError &&\n \"function\" === typeof wrapperError.componentDidCatch &&\n (null === legacyErrorBoundariesThatAlreadyFailed ||\n !legacyErrorBoundariesThatAlreadyFailed.has(wrapperError)))))\n )\n return (\n (sourceFiber.flags |= 65536),\n (rootRenderLanes &= -rootRenderLanes),\n (sourceFiber.lanes |= rootRenderLanes),\n (rootRenderLanes = createClassErrorUpdate(rootRenderLanes)),\n initializeClassErrorUpdate(\n rootRenderLanes,\n root,\n sourceFiber,\n value\n ),\n enqueueCapturedUpdate(sourceFiber, rootRenderLanes),\n !1\n );\n }\n sourceFiber = sourceFiber.return;\n } while (null !== sourceFiber);\n return !1;\n}\nvar SelectiveHydrationException = Error(formatProdErrorMessage(461)),\n didReceiveUpdate = !1;\nfunction reconcileChildren(current, workInProgress, nextChildren, renderLanes) {\n workInProgress.child =\n null === current\n ? mountChildFibers(workInProgress, null, nextChildren, renderLanes)\n : reconcileChildFibers(\n workInProgress,\n current.child,\n nextChildren,\n renderLanes\n );\n}\nfunction updateForwardRef(\n current,\n workInProgress,\n Component,\n nextProps,\n renderLanes\n) {\n Component = Component.render;\n var ref = workInProgress.ref;\n if (\"ref\" in nextProps) {\n var propsWithoutRef = {};\n for (var key in nextProps)\n \"ref\" !== key && (propsWithoutRef[key] = nextProps[key]);\n } else propsWithoutRef = nextProps;\n prepareToReadContext(workInProgress);\n nextProps = renderWithHooks(\n current,\n workInProgress,\n Component,\n propsWithoutRef,\n ref,\n renderLanes\n );\n key = checkDidRenderIdHook();\n if (null !== current && !didReceiveUpdate)\n return (\n bailoutHooks(current, workInProgress, renderLanes),\n bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes)\n );\n isHydrating && key && pushMaterializedTreeId(workInProgress);\n workInProgress.flags |= 1;\n reconcileChildren(current, workInProgress, nextProps, renderLanes);\n return workInProgress.child;\n}\nfunction updateMemoComponent(\n current,\n workInProgress,\n Component,\n nextProps,\n renderLanes\n) {\n if (null === current) {\n var type = Component.type;\n if (\n \"function\" === typeof type &&\n !shouldConstruct(type) &&\n void 0 === type.defaultProps &&\n null === Component.compare\n )\n return (\n (workInProgress.tag = 15),\n (workInProgress.type = type),\n updateSimpleMemoComponent(\n current,\n workInProgress,\n type,\n nextProps,\n renderLanes\n )\n );\n current = createFiberFromTypeAndProps(\n Component.type,\n null,\n nextProps,\n workInProgress,\n workInProgress.mode,\n renderLanes\n );\n current.ref = workInProgress.ref;\n current.return = workInProgress;\n return (workInProgress.child = current);\n }\n type = current.child;\n if (!checkScheduledUpdateOrContext(current, renderLanes)) {\n var prevProps = type.memoizedProps;\n Component = Component.compare;\n Component = null !== Component ? Component : shallowEqual;\n if (Component(prevProps, nextProps) && current.ref === workInProgress.ref)\n return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);\n }\n workInProgress.flags |= 1;\n current = createWorkInProgress(type, nextProps);\n current.ref = workInProgress.ref;\n current.return = workInProgress;\n return (workInProgress.child = current);\n}\nfunction updateSimpleMemoComponent(\n current,\n workInProgress,\n Component,\n nextProps,\n renderLanes\n) {\n if (null !== current) {\n var prevProps = current.memoizedProps;\n if (\n shallowEqual(prevProps, nextProps) &&\n current.ref === workInProgress.ref\n )\n if (\n ((didReceiveUpdate = !1),\n (workInProgress.pendingProps = nextProps = prevProps),\n checkScheduledUpdateOrContext(current, renderLanes))\n )\n 0 !== (current.flags & 131072) && (didReceiveUpdate = !0);\n else\n return (\n (workInProgress.lanes = current.lanes),\n bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes)\n );\n }\n return updateFunctionComponent(\n current,\n workInProgress,\n Component,\n nextProps,\n renderLanes\n );\n}\nfunction updateOffscreenComponent(\n current,\n workInProgress,\n renderLanes,\n nextProps\n) {\n var nextChildren = nextProps.children,\n prevState = null !== current ? current.memoizedState : null;\n null === current &&\n null === workInProgress.stateNode &&\n (workInProgress.stateNode = {\n _visibility: 1,\n _pendingMarkers: null,\n _retryCache: null,\n _transitions: null\n });\n if (\"hidden\" === nextProps.mode) {\n if (0 !== (workInProgress.flags & 128)) {\n prevState =\n null !== prevState ? prevState.baseLanes | renderLanes : renderLanes;\n if (null !== current) {\n nextProps = workInProgress.child = current.child;\n for (nextChildren = 0; null !== nextProps; )\n (nextChildren =\n nextChildren | nextProps.lanes | nextProps.childLanes),\n (nextProps = nextProps.sibling);\n nextProps = nextChildren & ~prevState;\n } else (nextProps = 0), (workInProgress.child = null);\n return deferHiddenOffscreenComponent(\n current,\n workInProgress,\n prevState,\n renderLanes,\n nextProps\n );\n }\n if (0 !== (renderLanes & 536870912))\n (workInProgress.memoizedState = { baseLanes: 0, cachePool: null }),\n null !== current &&\n pushTransition(\n workInProgress,\n null !== prevState ? prevState.cachePool : null\n ),\n null !== prevState\n ? pushHiddenContext(workInProgress, prevState)\n : reuseHiddenContextOnStack(),\n pushOffscreenSuspenseHandler(workInProgress);\n else\n return (\n (nextProps = workInProgress.lanes = 536870912),\n deferHiddenOffscreenComponent(\n current,\n workInProgress,\n null !== prevState ? prevState.baseLanes | renderLanes : renderLanes,\n renderLanes,\n nextProps\n )\n );\n } else\n null !== prevState\n ? (pushTransition(workInProgress, prevState.cachePool),\n pushHiddenContext(workInProgress, prevState),\n reuseSuspenseHandlerOnStack(workInProgress),\n (workInProgress.memoizedState = null))\n : (null !== current && pushTransition(workInProgress, null),\n reuseHiddenContextOnStack(),\n reuseSuspenseHandlerOnStack(workInProgress));\n reconcileChildren(current, workInProgress, nextChildren, renderLanes);\n return workInProgress.child;\n}\nfunction bailoutOffscreenComponent(current, workInProgress) {\n (null !== current && 22 === current.tag) ||\n null !== workInProgress.stateNode ||\n (workInProgress.stateNode = {\n _visibility: 1,\n _pendingMarkers: null,\n _retryCache: null,\n _transitions: null\n });\n return workInProgress.sibling;\n}\nfunction deferHiddenOffscreenComponent(\n current,\n workInProgress,\n nextBaseLanes,\n renderLanes,\n remainingChildLanes\n) {\n var JSCompiler_inline_result = peekCacheFromPool();\n JSCompiler_inline_result =\n null === JSCompiler_inline_result\n ? null\n : { parent: CacheContext._currentValue, pool: JSCompiler_inline_result };\n workInProgress.memoizedState = {\n baseLanes: nextBaseLanes,\n cachePool: JSCompiler_inline_result\n };\n null !== current && pushTransition(workInProgress, null);\n reuseHiddenContextOnStack();\n pushOffscreenSuspenseHandler(workInProgress);\n null !== current &&\n propagateParentContextChanges(current, workInProgress, renderLanes, !0);\n workInProgress.childLanes = remainingChildLanes;\n return null;\n}\nfunction mountActivityChildren(workInProgress, nextProps) {\n nextProps = mountWorkInProgressOffscreenFiber(\n { mode: nextProps.mode, children: nextProps.children },\n workInProgress.mode\n );\n nextProps.ref = workInProgress.ref;\n workInProgress.child = nextProps;\n nextProps.return = workInProgress;\n return nextProps;\n}\nfunction retryActivityComponentWithoutHydrating(\n current,\n workInProgress,\n renderLanes\n) {\n reconcileChildFibers(workInProgress, current.child, null, renderLanes);\n current = mountActivityChildren(workInProgress, workInProgress.pendingProps);\n current.flags |= 2;\n popSuspenseHandler(workInProgress);\n workInProgress.memoizedState = null;\n return current;\n}\nfunction updateActivityComponent(current, workInProgress, renderLanes) {\n var nextProps = workInProgress.pendingProps,\n didSuspend = 0 !== (workInProgress.flags & 128);\n workInProgress.flags &= -129;\n if (null === current) {\n if (isHydrating) {\n if (\"hidden\" === nextProps.mode)\n return (\n (current = mountActivityChildren(workInProgress, nextProps)),\n (workInProgress.lanes = 536870912),\n bailoutOffscreenComponent(null, current)\n );\n pushDehydratedActivitySuspenseHandler(workInProgress);\n (current = nextHydratableInstance)\n ? ((current = canHydrateHydrationBoundary(\n current,\n rootOrSingletonContext\n )),\n (current = null !== current && \"&\" === current.data ? current : null),\n null !== current &&\n ((workInProgress.memoizedState = {\n dehydrated: current,\n treeContext:\n null !== treeContextProvider\n ? { id: treeContextId, overflow: treeContextOverflow }\n : null,\n retryLane: 536870912,\n hydrationErrors: null\n }),\n (renderLanes = createFiberFromDehydratedFragment(current)),\n (renderLanes.return = workInProgress),\n (workInProgress.child = renderLanes),\n (hydrationParentFiber = workInProgress),\n (nextHydratableInstance = null)))\n : (current = null);\n if (null === current) throw throwOnHydrationMismatch(workInProgress);\n workInProgress.lanes = 536870912;\n return null;\n }\n return mountActivityChildren(workInProgress, nextProps);\n }\n var prevState = current.memoizedState;\n if (null !== prevState) {\n var dehydrated = prevState.dehydrated;\n pushDehydratedActivitySuspenseHandler(workInProgress);\n if (didSuspend)\n if (workInProgress.flags & 256)\n (workInProgress.flags &= -257),\n (workInProgress = retryActivityComponentWithoutHydrating(\n current,\n workInProgress,\n renderLanes\n ));\n else if (null !== workInProgress.memoizedState)\n (workInProgress.child = current.child),\n (workInProgress.flags |= 128),\n (workInProgress = null);\n else throw Error(formatProdErrorMessage(558));\n else if (\n (didReceiveUpdate ||\n propagateParentContextChanges(current, workInProgress, renderLanes, !1),\n (didSuspend = 0 !== (renderLanes & current.childLanes)),\n didReceiveUpdate || didSuspend)\n ) {\n nextProps = workInProgressRoot;\n if (\n null !== nextProps &&\n ((dehydrated = getBumpedLaneForHydration(nextProps, renderLanes)),\n 0 !== dehydrated && dehydrated !== prevState.retryLane)\n )\n throw (\n ((prevState.retryLane = dehydrated),\n enqueueConcurrentRenderForLane(current, dehydrated),\n scheduleUpdateOnFiber(nextProps, current, dehydrated),\n SelectiveHydrationException)\n );\n renderDidSuspendDelayIfPossible();\n workInProgress = retryActivityComponentWithoutHydrating(\n current,\n workInProgress,\n renderLanes\n );\n } else\n (current = prevState.treeContext),\n (nextHydratableInstance = getNextHydratable(dehydrated.nextSibling)),\n (hydrationParentFiber = workInProgress),\n (isHydrating = !0),\n (hydrationErrors = null),\n (rootOrSingletonContext = !1),\n null !== current &&\n restoreSuspendedTreeContext(workInProgress, current),\n (workInProgress = mountActivityChildren(workInProgress, nextProps)),\n (workInProgress.flags |= 4096);\n return workInProgress;\n }\n current = createWorkInProgress(current.child, {\n mode: nextProps.mode,\n children: nextProps.children\n });\n current.ref = workInProgress.ref;\n workInProgress.child = current;\n current.return = workInProgress;\n return current;\n}\nfunction markRef(current, workInProgress) {\n var ref = workInProgress.ref;\n if (null === ref)\n null !== current &&\n null !== current.ref &&\n (workInProgress.flags |= 4194816);\n else {\n if (\"function\" !== typeof ref && \"object\" !== typeof ref)\n throw Error(formatProdErrorMessage(284));\n if (null === current || current.ref !== ref)\n workInProgress.flags |= 4194816;\n }\n}\nfunction updateFunctionComponent(\n current,\n workInProgress,\n Component,\n nextProps,\n renderLanes\n) {\n prepareToReadContext(workInProgress);\n Component = renderWithHooks(\n current,\n workInProgress,\n Component,\n nextProps,\n void 0,\n renderLanes\n );\n nextProps = checkDidRenderIdHook();\n if (null !== current && !didReceiveUpdate)\n return (\n bailoutHooks(current, workInProgress, renderLanes),\n bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes)\n );\n isHydrating && nextProps && pushMaterializedTreeId(workInProgress);\n workInProgress.flags |= 1;\n reconcileChildren(current, workInProgress, Component, renderLanes);\n return workInProgress.child;\n}\nfunction replayFunctionComponent(\n current,\n workInProgress,\n nextProps,\n Component,\n secondArg,\n renderLanes\n) {\n prepareToReadContext(workInProgress);\n workInProgress.updateQueue = null;\n nextProps = renderWithHooksAgain(\n workInProgress,\n Component,\n nextProps,\n secondArg\n );\n finishRenderingHooks(current);\n Component = checkDidRenderIdHook();\n if (null !== current && !didReceiveUpdate)\n return (\n bailoutHooks(current, workInProgress, renderLanes),\n bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes)\n );\n isHydrating && Component && pushMaterializedTreeId(workInProgress);\n workInProgress.flags |= 1;\n reconcileChildren(current, workInProgress, nextProps, renderLanes);\n return workInProgress.child;\n}\nfunction updateClassComponent(\n current,\n workInProgress,\n Component,\n nextProps,\n renderLanes\n) {\n prepareToReadContext(workInProgress);\n if (null === workInProgress.stateNode) {\n var context = emptyContextObject,\n contextType = Component.contextType;\n \"object\" === typeof contextType &&\n null !== contextType &&\n (context = readContext(contextType));\n context = new Component(nextProps, context);\n workInProgress.memoizedState =\n null !== context.state && void 0 !== context.state ? context.state : null;\n context.updater = classComponentUpdater;\n workInProgress.stateNode = context;\n context._reactInternals = workInProgress;\n context = workInProgress.stateNode;\n context.props = nextProps;\n context.state = workInProgress.memoizedState;\n context.refs = {};\n initializeUpdateQueue(workInProgress);\n contextType = Component.contextType;\n context.context =\n \"object\" === typeof contextType && null !== contextType\n ? readContext(contextType)\n : emptyContextObject;\n context.state = workInProgress.memoizedState;\n contextType = Component.getDerivedStateFromProps;\n \"function\" === typeof contextType &&\n (applyDerivedStateFromProps(\n workInProgress,\n Component,\n contextType,\n nextProps\n ),\n (context.state = workInProgress.memoizedState));\n \"function\" === typeof Component.getDerivedStateFromProps ||\n \"function\" === typeof context.getSnapshotBeforeUpdate ||\n (\"function\" !== typeof context.UNSAFE_componentWillMount &&\n \"function\" !== typeof context.componentWillMount) ||\n ((contextType = context.state),\n \"function\" === typeof context.componentWillMount &&\n context.componentWillMount(),\n \"function\" === typeof context.UNSAFE_componentWillMount &&\n context.UNSAFE_componentWillMount(),\n contextType !== context.state &&\n classComponentUpdater.enqueueReplaceState(context, context.state, null),\n processUpdateQueue(workInProgress, nextProps, context, renderLanes),\n suspendIfUpdateReadFromEntangledAsyncAction(),\n (context.state = workInProgress.memoizedState));\n \"function\" === typeof context.componentDidMount &&\n (workInProgress.flags |= 4194308);\n nextProps = !0;\n } else if (null === current) {\n context = workInProgress.stateNode;\n var unresolvedOldProps = workInProgress.memoizedProps,\n oldProps = resolveClassComponentProps(Component, unresolvedOldProps);\n context.props = oldProps;\n var oldContext = context.context,\n contextType$jscomp$0 = Component.contextType;\n contextType = emptyContextObject;\n \"object\" === typeof contextType$jscomp$0 &&\n null !== contextType$jscomp$0 &&\n (contextType = readContext(contextType$jscomp$0));\n var getDerivedStateFromProps = Component.getDerivedStateFromProps;\n contextType$jscomp$0 =\n \"function\" === typeof getDerivedStateFromProps ||\n \"function\" === typeof context.getSnapshotBeforeUpdate;\n unresolvedOldProps = workInProgress.pendingProps !== unresolvedOldProps;\n contextType$jscomp$0 ||\n (\"function\" !== typeof context.UNSAFE_componentWillReceiveProps &&\n \"function\" !== typeof context.componentWillReceiveProps) ||\n ((unresolvedOldProps || oldContext !== contextType) &&\n callComponentWillReceiveProps(\n workInProgress,\n context,\n nextProps,\n contextType\n ));\n hasForceUpdate = !1;\n var oldState = workInProgress.memoizedState;\n context.state = oldState;\n processUpdateQueue(workInProgress, nextProps, context, renderLanes);\n suspendIfUpdateReadFromEntangledAsyncAction();\n oldContext = workInProgress.memoizedState;\n unresolvedOldProps || oldState !== oldContext || hasForceUpdate\n ? (\"function\" === typeof getDerivedStateFromProps &&\n (applyDerivedStateFromProps(\n workInProgress,\n Component,\n getDerivedStateFromProps,\n nextProps\n ),\n (oldContext = workInProgress.memoizedState)),\n (oldProps =\n hasForceUpdate ||\n checkShouldComponentUpdate(\n workInProgress,\n Component,\n oldProps,\n nextProps,\n oldState,\n oldContext,\n contextType\n ))\n ? (contextType$jscomp$0 ||\n (\"function\" !== typeof context.UNSAFE_componentWillMount &&\n \"function\" !== typeof context.componentWillMount) ||\n (\"function\" === typeof context.componentWillMount &&\n context.componentWillMount(),\n \"function\" === typeof context.UNSAFE_componentWillMount &&\n context.UNSAFE_componentWillMount()),\n \"function\" === typeof context.componentDidMount &&\n (workInProgress.flags |= 4194308))\n : (\"function\" === typeof context.componentDidMount &&\n (workInProgress.flags |= 4194308),\n (workInProgress.memoizedProps = nextProps),\n (workInProgress.memoizedState = oldContext)),\n (context.props = nextProps),\n (context.state = oldContext),\n (context.context = contextType),\n (nextProps = oldProps))\n : (\"function\" === typeof context.componentDidMount &&\n (workInProgress.flags |= 4194308),\n (nextProps = !1));\n } else {\n context = workInProgress.stateNode;\n cloneUpdateQueue(current, workInProgress);\n contextType = workInProgress.memoizedProps;\n contextType$jscomp$0 = resolveClassComponentProps(Component, contextType);\n context.props = contextType$jscomp$0;\n getDerivedStateFromProps = workInProgress.pendingProps;\n oldState = context.context;\n oldContext = Component.contextType;\n oldProps = emptyContextObject;\n \"object\" === typeof oldContext &&\n null !== oldContext &&\n (oldProps = readContext(oldContext));\n unresolvedOldProps = Component.getDerivedStateFromProps;\n (oldContext =\n \"function\" === typeof unresolvedOldProps ||\n \"function\" === typeof context.getSnapshotBeforeUpdate) ||\n (\"function\" !== typeof context.UNSAFE_componentWillReceiveProps &&\n \"function\" !== typeof context.componentWillReceiveProps) ||\n ((contextType !== getDerivedStateFromProps || oldState !== oldProps) &&\n callComponentWillReceiveProps(\n workInProgress,\n context,\n nextProps,\n oldProps\n ));\n hasForceUpdate = !1;\n oldState = workInProgress.memoizedState;\n context.state = oldState;\n processUpdateQueue(workInProgress, nextProps, context, renderLanes);\n suspendIfUpdateReadFromEntangledAsyncAction();\n var newState = workInProgress.memoizedState;\n contextType !== getDerivedStateFromProps ||\n oldState !== newState ||\n hasForceUpdate ||\n (null !== current &&\n null !== current.dependencies &&\n checkIfContextChanged(current.dependencies))\n ? (\"function\" === typeof unresolvedOldProps &&\n (applyDerivedStateFromProps(\n workInProgress,\n Component,\n unresolvedOldProps,\n nextProps\n ),\n (newState = workInProgress.memoizedState)),\n (contextType$jscomp$0 =\n hasForceUpdate ||\n checkShouldComponentUpdate(\n workInProgress,\n Component,\n contextType$jscomp$0,\n nextProps,\n oldState,\n newState,\n oldProps\n ) ||\n (null !== current &&\n null !== current.dependencies &&\n checkIfContextChanged(current.dependencies)))\n ? (oldContext ||\n (\"function\" !== typeof context.UNSAFE_componentWillUpdate &&\n \"function\" !== typeof context.componentWillUpdate) ||\n (\"function\" === typeof context.componentWillUpdate &&\n context.componentWillUpdate(nextProps, newState, oldProps),\n \"function\" === typeof context.UNSAFE_componentWillUpdate &&\n context.UNSAFE_componentWillUpdate(\n nextProps,\n newState,\n oldProps\n )),\n \"function\" === typeof context.componentDidUpdate &&\n (workInProgress.flags |= 4),\n \"function\" === typeof context.getSnapshotBeforeUpdate &&\n (workInProgress.flags |= 1024))\n : (\"function\" !== typeof context.componentDidUpdate ||\n (contextType === current.memoizedProps &&\n oldState === current.memoizedState) ||\n (workInProgress.flags |= 4),\n \"function\" !== typeof context.getSnapshotBeforeUpdate ||\n (contextType === current.memoizedProps &&\n oldState === current.memoizedState) ||\n (workInProgress.flags |= 1024),\n (workInProgress.memoizedProps = nextProps),\n (workInProgress.memoizedState = newState)),\n (context.props = nextProps),\n (context.state = newState),\n (context.context = oldProps),\n (nextProps = contextType$jscomp$0))\n : (\"function\" !== typeof context.componentDidUpdate ||\n (contextType === current.memoizedProps &&\n oldState === current.memoizedState) ||\n (workInProgress.flags |= 4),\n \"function\" !== typeof context.getSnapshotBeforeUpdate ||\n (contextType === current.memoizedProps &&\n oldState === current.memoizedState) ||\n (workInProgress.flags |= 1024),\n (nextProps = !1));\n }\n context = nextProps;\n markRef(current, workInProgress);\n nextProps = 0 !== (workInProgress.flags & 128);\n context || nextProps\n ? ((context = workInProgress.stateNode),\n (Component =\n nextProps && \"function\" !== typeof Component.getDerivedStateFromError\n ? null\n : context.render()),\n (workInProgress.flags |= 1),\n null !== current && nextProps\n ? ((workInProgress.child = reconcileChildFibers(\n workInProgress,\n current.child,\n null,\n renderLanes\n )),\n (workInProgress.child = reconcileChildFibers(\n workInProgress,\n null,\n Component,\n renderLanes\n )))\n : reconcileChildren(current, workInProgress, Component, renderLanes),\n (workInProgress.memoizedState = context.state),\n (current = workInProgress.child))\n : (current = bailoutOnAlreadyFinishedWork(\n current,\n workInProgress,\n renderLanes\n ));\n return current;\n}\nfunction mountHostRootWithoutHydrating(\n current,\n workInProgress,\n nextChildren,\n renderLanes\n) {\n resetHydrationState();\n workInProgress.flags |= 256;\n reconcileChildren(current, workInProgress, nextChildren, renderLanes);\n return workInProgress.child;\n}\nvar SUSPENDED_MARKER = {\n dehydrated: null,\n treeContext: null,\n retryLane: 0,\n hydrationErrors: null\n};\nfunction mountSuspenseOffscreenState(renderLanes) {\n return { baseLanes: renderLanes, cachePool: getSuspendedCache() };\n}\nfunction getRemainingWorkInPrimaryTree(\n current,\n primaryTreeDidDefer,\n renderLanes\n) {\n current = null !== current ? current.childLanes & ~renderLanes : 0;\n primaryTreeDidDefer && (current |= workInProgressDeferredLane);\n return current;\n}\nfunction updateSuspenseComponent(current, workInProgress, renderLanes) {\n var nextProps = workInProgress.pendingProps,\n showFallback = !1,\n didSuspend = 0 !== (workInProgress.flags & 128),\n JSCompiler_temp;\n (JSCompiler_temp = didSuspend) ||\n (JSCompiler_temp =\n null !== current && null === current.memoizedState\n ? !1\n : 0 !== (suspenseStackCursor.current & 2));\n JSCompiler_temp && ((showFallback = !0), (workInProgress.flags &= -129));\n JSCompiler_temp = 0 !== (workInProgress.flags & 32);\n workInProgress.flags &= -33;\n if (null === current) {\n if (isHydrating) {\n showFallback\n ? pushPrimaryTreeSuspenseHandler(workInProgress)\n : reuseSuspenseHandlerOnStack(workInProgress);\n (current = nextHydratableInstance)\n ? ((current = canHydrateHydrationBoundary(\n current,\n rootOrSingletonContext\n )),\n (current = null !== current && \"&\" !== current.data ? current : null),\n null !== current &&\n ((workInProgress.memoizedState = {\n dehydrated: current,\n treeContext:\n null !== treeContextProvider\n ? { id: treeContextId, overflow: treeContextOverflow }\n : null,\n retryLane: 536870912,\n hydrationErrors: null\n }),\n (renderLanes = createFiberFromDehydratedFragment(current)),\n (renderLanes.return = workInProgress),\n (workInProgress.child = renderLanes),\n (hydrationParentFiber = workInProgress),\n (nextHydratableInstance = null)))\n : (current = null);\n if (null === current) throw throwOnHydrationMismatch(workInProgress);\n isSuspenseInstanceFallback(current)\n ? (workInProgress.lanes = 32)\n : (workInProgress.lanes = 536870912);\n return null;\n }\n var nextPrimaryChildren = nextProps.children;\n nextProps = nextProps.fallback;\n if (showFallback)\n return (\n reuseSuspenseHandlerOnStack(workInProgress),\n (showFallback = workInProgress.mode),\n (nextPrimaryChildren = mountWorkInProgressOffscreenFiber(\n { mode: \"hidden\", children: nextPrimaryChildren },\n showFallback\n )),\n (nextProps = createFiberFromFragment(\n nextProps,\n showFallback,\n renderLanes,\n null\n )),\n (nextPrimaryChildren.return = workInProgress),\n (nextProps.return = workInProgress),\n (nextPrimaryChildren.sibling = nextProps),\n (workInProgress.child = nextPrimaryChildren),\n (nextProps = workInProgress.child),\n (nextProps.memoizedState = mountSuspenseOffscreenState(renderLanes)),\n (nextProps.childLanes = getRemainingWorkInPrimaryTree(\n current,\n JSCompiler_temp,\n renderLanes\n )),\n (workInProgress.memoizedState = SUSPENDED_MARKER),\n bailoutOffscreenComponent(null, nextProps)\n );\n pushPrimaryTreeSuspenseHandler(workInProgress);\n return mountSuspensePrimaryChildren(workInProgress, nextPrimaryChildren);\n }\n var prevState = current.memoizedState;\n if (\n null !== prevState &&\n ((nextPrimaryChildren = prevState.dehydrated), null !== nextPrimaryChildren)\n ) {\n if (didSuspend)\n workInProgress.flags & 256\n ? (pushPrimaryTreeSuspenseHandler(workInProgress),\n (workInProgress.flags &= -257),\n (workInProgress = retrySuspenseComponentWithoutHydrating(\n current,\n workInProgress,\n renderLanes\n )))\n : null !== workInProgress.memoizedState\n ? (reuseSuspenseHandlerOnStack(workInProgress),\n (workInProgress.child = current.child),\n (workInProgress.flags |= 128),\n (workInProgress = null))\n : (reuseSuspenseHandlerOnStack(workInProgress),\n (nextPrimaryChildren = nextProps.fallback),\n (showFallback = workInProgress.mode),\n (nextProps = mountWorkInProgressOffscreenFiber(\n { mode: \"visible\", children: nextProps.children },\n showFallback\n )),\n (nextPrimaryChildren = createFiberFromFragment(\n nextPrimaryChildren,\n showFallback,\n renderLanes,\n null\n )),\n (nextPrimaryChildren.flags |= 2),\n (nextProps.return = workInProgress),\n (nextPrimaryChildren.return = workInProgress),\n (nextProps.sibling = nextPrimaryChildren),\n (workInProgress.child = nextProps),\n reconcileChildFibers(\n workInProgress,\n current.child,\n null,\n renderLanes\n ),\n (nextProps = workInProgress.child),\n (nextProps.memoizedState =\n mountSuspenseOffscreenState(renderLanes)),\n (nextProps.childLanes = getRemainingWorkInPrimaryTree(\n current,\n JSCompiler_temp,\n renderLanes\n )),\n (workInProgress.memoizedState = SUSPENDED_MARKER),\n (workInProgress = bailoutOffscreenComponent(null, nextProps)));\n else if (\n (pushPrimaryTreeSuspenseHandler(workInProgress),\n isSuspenseInstanceFallback(nextPrimaryChildren))\n ) {\n JSCompiler_temp =\n nextPrimaryChildren.nextSibling &&\n nextPrimaryChildren.nextSibling.dataset;\n if (JSCompiler_temp) var digest = JSCompiler_temp.dgst;\n JSCompiler_temp = digest;\n nextProps = Error(formatProdErrorMessage(419));\n nextProps.stack = \"\";\n nextProps.digest = JSCompiler_temp;\n queueHydrationError({ value: nextProps, source: null, stack: null });\n workInProgress = retrySuspenseComponentWithoutHydrating(\n current,\n workInProgress,\n renderLanes\n );\n } else if (\n (didReceiveUpdate ||\n propagateParentContextChanges(current, workInProgress, renderLanes, !1),\n (JSCompiler_temp = 0 !== (renderLanes & current.childLanes)),\n didReceiveUpdate || JSCompiler_temp)\n ) {\n JSCompiler_temp = workInProgressRoot;\n if (\n null !== JSCompiler_temp &&\n ((nextProps = getBumpedLaneForHydration(JSCompiler_temp, renderLanes)),\n 0 !== nextProps && nextProps !== prevState.retryLane)\n )\n throw (\n ((prevState.retryLane = nextProps),\n enqueueConcurrentRenderForLane(current, nextProps),\n scheduleUpdateOnFiber(JSCompiler_temp, current, nextProps),\n SelectiveHydrationException)\n );\n isSuspenseInstancePending(nextPrimaryChildren) ||\n renderDidSuspendDelayIfPossible();\n workInProgress = retrySuspenseComponentWithoutHydrating(\n current,\n workInProgress,\n renderLanes\n );\n } else\n isSuspenseInstancePending(nextPrimaryChildren)\n ? ((workInProgress.flags |= 192),\n (workInProgress.child = current.child),\n (workInProgress = null))\n : ((current = prevState.treeContext),\n (nextHydratableInstance = getNextHydratable(\n nextPrimaryChildren.nextSibling\n )),\n (hydrationParentFiber = workInProgress),\n (isHydrating = !0),\n (hydrationErrors = null),\n (rootOrSingletonContext = !1),\n null !== current &&\n restoreSuspendedTreeContext(workInProgress, current),\n (workInProgress = mountSuspensePrimaryChildren(\n workInProgress,\n nextProps.children\n )),\n (workInProgress.flags |= 4096));\n return workInProgress;\n }\n if (showFallback)\n return (\n reuseSuspenseHandlerOnStack(workInProgress),\n (nextPrimaryChildren = nextProps.fallback),\n (showFallback = workInProgress.mode),\n (prevState = current.child),\n (digest = prevState.sibling),\n (nextProps = createWorkInProgress(prevState, {\n mode: \"hidden\",\n children: nextProps.children\n })),\n (nextProps.subtreeFlags = prevState.subtreeFlags & 65011712),\n null !== digest\n ? (nextPrimaryChildren = createWorkInProgress(\n digest,\n nextPrimaryChildren\n ))\n : ((nextPrimaryChildren = createFiberFromFragment(\n nextPrimaryChildren,\n showFallback,\n renderLanes,\n null\n )),\n (nextPrimaryChildren.flags |= 2)),\n (nextPrimaryChildren.return = workInProgress),\n (nextProps.return = workInProgress),\n (nextProps.sibling = nextPrimaryChildren),\n (workInProgress.child = nextProps),\n bailoutOffscreenComponent(null, nextProps),\n (nextProps = workInProgress.child),\n (nextPrimaryChildren = current.child.memoizedState),\n null === nextPrimaryChildren\n ? (nextPrimaryChildren = mountSuspenseOffscreenState(renderLanes))\n : ((showFallback = nextPrimaryChildren.cachePool),\n null !== showFallback\n ? ((prevState = CacheContext._currentValue),\n (showFallback =\n showFallback.parent !== prevState\n ? { parent: prevState, pool: prevState }\n : showFallback))\n : (showFallback = getSuspendedCache()),\n (nextPrimaryChildren = {\n baseLanes: nextPrimaryChildren.baseLanes | renderLanes,\n cachePool: showFallback\n })),\n (nextProps.memoizedState = nextPrimaryChildren),\n (nextProps.childLanes = getRemainingWorkInPrimaryTree(\n current,\n JSCompiler_temp,\n renderLanes\n )),\n (workInProgress.memoizedState = SUSPENDED_MARKER),\n bailoutOffscreenComponent(current.child, nextProps)\n );\n pushPrimaryTreeSuspenseHandler(workInProgress);\n renderLanes = current.child;\n current = renderLanes.sibling;\n renderLanes = createWorkInProgress(renderLanes, {\n mode: \"visible\",\n children: nextProps.children\n });\n renderLanes.return = workInProgress;\n renderLanes.sibling = null;\n null !== current &&\n ((JSCompiler_temp = workInProgress.deletions),\n null === JSCompiler_temp\n ? ((workInProgress.deletions = [current]), (workInProgress.flags |= 16))\n : JSCompiler_temp.push(current));\n workInProgress.child = renderLanes;\n workInProgress.memoizedState = null;\n return renderLanes;\n}\nfunction mountSuspensePrimaryChildren(workInProgress, primaryChildren) {\n primaryChildren = mountWorkInProgressOffscreenFiber(\n { mode: \"visible\", children: primaryChildren },\n workInProgress.mode\n );\n primaryChildren.return = workInProgress;\n return (workInProgress.child = primaryChildren);\n}\nfunction mountWorkInProgressOffscreenFiber(offscreenProps, mode) {\n offscreenProps = createFiberImplClass(22, offscreenProps, null, mode);\n offscreenProps.lanes = 0;\n return offscreenProps;\n}\nfunction retrySuspenseComponentWithoutHydrating(\n current,\n workInProgress,\n renderLanes\n) {\n reconcileChildFibers(workInProgress, current.child, null, renderLanes);\n current = mountSuspensePrimaryChildren(\n workInProgress,\n workInProgress.pendingProps.children\n );\n current.flags |= 2;\n workInProgress.memoizedState = null;\n return current;\n}\nfunction scheduleSuspenseWorkOnFiber(fiber, renderLanes, propagationRoot) {\n fiber.lanes |= renderLanes;\n var alternate = fiber.alternate;\n null !== alternate && (alternate.lanes |= renderLanes);\n scheduleContextWorkOnParentPath(fiber.return, renderLanes, propagationRoot);\n}\nfunction initSuspenseListRenderState(\n workInProgress,\n isBackwards,\n tail,\n lastContentRow,\n tailMode,\n treeForkCount\n) {\n var renderState = workInProgress.memoizedState;\n null === renderState\n ? (workInProgress.memoizedState = {\n isBackwards: isBackwards,\n rendering: null,\n renderingStartTime: 0,\n last: lastContentRow,\n tail: tail,\n tailMode: tailMode,\n treeForkCount: treeForkCount\n })\n : ((renderState.isBackwards = isBackwards),\n (renderState.rendering = null),\n (renderState.renderingStartTime = 0),\n (renderState.last = lastContentRow),\n (renderState.tail = tail),\n (renderState.tailMode = tailMode),\n (renderState.treeForkCount = treeForkCount));\n}\nfunction updateSuspenseListComponent(current, workInProgress, renderLanes) {\n var nextProps = workInProgress.pendingProps,\n revealOrder = nextProps.revealOrder,\n tailMode = nextProps.tail;\n nextProps = nextProps.children;\n var suspenseContext = suspenseStackCursor.current,\n shouldForceFallback = 0 !== (suspenseContext & 2);\n shouldForceFallback\n ? ((suspenseContext = (suspenseContext & 1) | 2),\n (workInProgress.flags |= 128))\n : (suspenseContext &= 1);\n push(suspenseStackCursor, suspenseContext);\n reconcileChildren(current, workInProgress, nextProps, renderLanes);\n nextProps = isHydrating ? treeForkCount : 0;\n if (!shouldForceFallback && null !== current && 0 !== (current.flags & 128))\n a: for (current = workInProgress.child; null !== current; ) {\n if (13 === current.tag)\n null !== current.memoizedState &&\n scheduleSuspenseWorkOnFiber(current, renderLanes, workInProgress);\n else if (19 === current.tag)\n scheduleSuspenseWorkOnFiber(current, renderLanes, workInProgress);\n else if (null !== current.child) {\n current.child.return = current;\n current = current.child;\n continue;\n }\n if (current === workInProgress) break a;\n for (; null === current.sibling; ) {\n if (null === current.return || current.return === workInProgress)\n break a;\n current = current.return;\n }\n current.sibling.return = current.return;\n current = current.sibling;\n }\n switch (revealOrder) {\n case \"forwards\":\n renderLanes = workInProgress.child;\n for (revealOrder = null; null !== renderLanes; )\n (current = renderLanes.alternate),\n null !== current &&\n null === findFirstSuspended(current) &&\n (revealOrder = renderLanes),\n (renderLanes = renderLanes.sibling);\n renderLanes = revealOrder;\n null === renderLanes\n ? ((revealOrder = workInProgress.child), (workInProgress.child = null))\n : ((revealOrder = renderLanes.sibling), (renderLanes.sibling = null));\n initSuspenseListRenderState(\n workInProgress,\n !1,\n revealOrder,\n renderLanes,\n tailMode,\n nextProps\n );\n break;\n case \"backwards\":\n case \"unstable_legacy-backwards\":\n renderLanes = null;\n revealOrder = workInProgress.child;\n for (workInProgress.child = null; null !== revealOrder; ) {\n current = revealOrder.alternate;\n if (null !== current && null === findFirstSuspended(current)) {\n workInProgress.child = revealOrder;\n break;\n }\n current = revealOrder.sibling;\n revealOrder.sibling = renderLanes;\n renderLanes = revealOrder;\n revealOrder = current;\n }\n initSuspenseListRenderState(\n workInProgress,\n !0,\n renderLanes,\n null,\n tailMode,\n nextProps\n );\n break;\n case \"together\":\n initSuspenseListRenderState(\n workInProgress,\n !1,\n null,\n null,\n void 0,\n nextProps\n );\n break;\n default:\n workInProgress.memoizedState = null;\n }\n return workInProgress.child;\n}\nfunction bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes) {\n null !== current && (workInProgress.dependencies = current.dependencies);\n workInProgressRootSkippedLanes |= workInProgress.lanes;\n if (0 === (renderLanes & workInProgress.childLanes))\n if (null !== current) {\n if (\n (propagateParentContextChanges(\n current,\n workInProgress,\n renderLanes,\n !1\n ),\n 0 === (renderLanes & workInProgress.childLanes))\n )\n return null;\n } else return null;\n if (null !== current && workInProgress.child !== current.child)\n throw Error(formatProdErrorMessage(153));\n if (null !== workInProgress.child) {\n current = workInProgress.child;\n renderLanes = createWorkInProgress(current, current.pendingProps);\n workInProgress.child = renderLanes;\n for (renderLanes.return = workInProgress; null !== current.sibling; )\n (current = current.sibling),\n (renderLanes = renderLanes.sibling =\n createWorkInProgress(current, current.pendingProps)),\n (renderLanes.return = workInProgress);\n renderLanes.sibling = null;\n }\n return workInProgress.child;\n}\nfunction checkScheduledUpdateOrContext(current, renderLanes) {\n if (0 !== (current.lanes & renderLanes)) return !0;\n current = current.dependencies;\n return null !== current && checkIfContextChanged(current) ? !0 : !1;\n}\nfunction attemptEarlyBailoutIfNoScheduledUpdate(\n current,\n workInProgress,\n renderLanes\n) {\n switch (workInProgress.tag) {\n case 3:\n pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo);\n pushProvider(workInProgress, CacheContext, current.memoizedState.cache);\n resetHydrationState();\n break;\n case 27:\n case 5:\n pushHostContext(workInProgress);\n break;\n case 4:\n pushHostContainer(workInProgress, workInProgress.stateNode.containerInfo);\n break;\n case 10:\n pushProvider(\n workInProgress,\n workInProgress.type,\n workInProgress.memoizedProps.value\n );\n break;\n case 31:\n if (null !== workInProgress.memoizedState)\n return (\n (workInProgress.flags |= 128),\n pushDehydratedActivitySuspenseHandler(workInProgress),\n null\n );\n break;\n case 13:\n var state$102 = workInProgress.memoizedState;\n if (null !== state$102) {\n if (null !== state$102.dehydrated)\n return (\n pushPrimaryTreeSuspenseHandler(workInProgress),\n (workInProgress.flags |= 128),\n null\n );\n if (0 !== (renderLanes & workInProgress.child.childLanes))\n return updateSuspenseComponent(current, workInProgress, renderLanes);\n pushPrimaryTreeSuspenseHandler(workInProgress);\n current = bailoutOnAlreadyFinishedWork(\n current,\n workInProgress,\n renderLanes\n );\n return null !== current ? current.sibling : null;\n }\n pushPrimaryTreeSuspenseHandler(workInProgress);\n break;\n case 19:\n var didSuspendBefore = 0 !== (current.flags & 128);\n state$102 = 0 !== (renderLanes & workInProgress.childLanes);\n state$102 ||\n (propagateParentContextChanges(\n current,\n workInProgress,\n renderLanes,\n !1\n ),\n (state$102 = 0 !== (renderLanes & workInProgress.childLanes)));\n if (didSuspendBefore) {\n if (state$102)\n return updateSuspenseListComponent(\n current,\n workInProgress,\n renderLanes\n );\n workInProgress.flags |= 128;\n }\n didSuspendBefore = workInProgress.memoizedState;\n null !== didSuspendBefore &&\n ((didSuspendBefore.rendering = null),\n (didSuspendBefore.tail = null),\n (didSuspendBefore.lastEffect = null));\n push(suspenseStackCursor, suspenseStackCursor.current);\n if (state$102) break;\n else return null;\n case 22:\n return (\n (workInProgress.lanes = 0),\n updateOffscreenComponent(\n current,\n workInProgress,\n renderLanes,\n workInProgress.pendingProps\n )\n );\n case 24:\n pushProvider(workInProgress, CacheContext, current.memoizedState.cache);\n }\n return bailoutOnAlreadyFinishedWork(current, workInProgress, renderLanes);\n}\nfunction beginWork(current, workInProgress, renderLanes) {\n if (null !== current)\n if (current.memoizedProps !== workInProgress.pendingProps)\n didReceiveUpdate = !0;\n else {\n if (\n !checkScheduledUpdateOrContext(current, renderLanes) &&\n 0 === (workInProgress.flags & 128)\n )\n return (\n (didReceiveUpdate = !1),\n attemptEarlyBailoutIfNoScheduledUpdate(\n current,\n workInProgress,\n renderLanes\n )\n );\n didReceiveUpdate = 0 !== (current.flags & 131072) ? !0 : !1;\n }\n else\n (didReceiveUpdate = !1),\n isHydrating &&\n 0 !== (workInProgress.flags & 1048576) &&\n pushTreeId(workInProgress, treeForkCount, workInProgress.index);\n workInProgress.lanes = 0;\n switch (workInProgress.tag) {\n case 16:\n a: {\n var props = workInProgress.pendingProps;\n current = resolveLazy(workInProgress.elementType);\n workInProgress.type = current;\n if (\"function\" === typeof current)\n shouldConstruct(current)\n ? ((props = resolveClassComponentProps(current, props)),\n (workInProgress.tag = 1),\n (workInProgress = updateClassComponent(\n null,\n workInProgress,\n current,\n props,\n renderLanes\n )))\n : ((workInProgress.tag = 0),\n (workInProgress = updateFunctionComponent(\n null,\n workInProgress,\n current,\n props,\n renderLanes\n )));\n else {\n if (void 0 !== current && null !== current) {\n var $$typeof = current.$$typeof;\n if ($$typeof === REACT_FORWARD_REF_TYPE) {\n workInProgress.tag = 11;\n workInProgress = updateForwardRef(\n null,\n workInProgress,\n current,\n props,\n renderLanes\n );\n break a;\n } else if ($$typeof === REACT_MEMO_TYPE) {\n workInProgress.tag = 14;\n workInProgress = updateMemoComponent(\n null,\n workInProgress,\n current,\n props,\n renderLanes\n );\n break a;\n }\n }\n workInProgress = getComponentNameFromType(current) || current;\n throw Error(formatProdErrorMessage(306, workInProgress, \"\"));\n }\n }\n return workInProgress;\n case 0:\n return updateFunctionComponent(\n current,\n workInProgress,\n workInProgress.type,\n workInProgress.pendingProps,\n renderLanes\n );\n case 1:\n return (\n (props = workInProgress.type),\n ($$typeof = resolveClassComponentProps(\n props,\n workInProgress.pendingProps\n )),\n updateClassComponent(\n current,\n workInProgress,\n props,\n $$typeof,\n renderLanes\n )\n );\n case 3:\n a: {\n pushHostContainer(\n workInProgress,\n workInProgress.stateNode.containerInfo\n );\n if (null === current) throw Error(formatProdErrorMessage(387));\n props = workInProgress.pendingProps;\n var prevState = workInProgress.memoizedState;\n $$typeof = prevState.element;\n cloneUpdateQueue(current, workInProgress);\n processUpdateQueue(workInProgress, props, null, renderLanes);\n var nextState = workInProgress.memoizedState;\n props = nextState.cache;\n pushProvider(workInProgress, CacheContext, props);\n props !== prevState.cache &&\n propagateContextChanges(\n workInProgress,\n [CacheContext],\n renderLanes,\n !0\n );\n suspendIfUpdateReadFromEntangledAsyncAction();\n props = nextState.element;\n if (prevState.isDehydrated)\n if (\n ((prevState = {\n element: props,\n isDehydrated: !1,\n cache: nextState.cache\n }),\n (workInProgress.updateQueue.baseState = prevState),\n (workInProgress.memoizedState = prevState),\n workInProgress.flags & 256)\n ) {\n workInProgress = mountHostRootWithoutHydrating(\n current,\n workInProgress,\n props,\n renderLanes\n );\n break a;\n } else if (props !== $$typeof) {\n $$typeof = createCapturedValueAtFiber(\n Error(formatProdErrorMessage(424)),\n workInProgress\n );\n queueHydrationError($$typeof);\n workInProgress = mountHostRootWithoutHydrating(\n current,\n workInProgress,\n props,\n renderLanes\n );\n break a;\n } else {\n current = workInProgress.stateNode.containerInfo;\n switch (current.nodeType) {\n case 9:\n current = current.body;\n break;\n default:\n current =\n \"HTML\" === current.nodeName\n ? current.ownerDocument.body\n : current;\n }\n nextHydratableInstance = getNextHydratable(current.firstChild);\n hydrationParentFiber = workInProgress;\n isHydrating = !0;\n hydrationErrors = null;\n rootOrSingletonContext = !0;\n renderLanes = mountChildFibers(\n workInProgress,\n null,\n props,\n renderLanes\n );\n for (workInProgress.child = renderLanes; renderLanes; )\n (renderLanes.flags = (renderLanes.flags & -3) | 4096),\n (renderLanes = renderLanes.sibling);\n }\n else {\n resetHydrationState();\n if (props === $$typeof) {\n workInProgress = bailoutOnAlreadyFinishedWork(\n current,\n workInProgress,\n renderLanes\n );\n break a;\n }\n reconcileChildren(current, workInProgress, props, renderLanes);\n }\n workInProgress = workInProgress.child;\n }\n return workInProgress;\n case 26:\n return (\n markRef(current, workInProgress),\n null === current\n ? (renderLanes = getResource(\n workInProgress.type,\n null,\n workInProgress.pendingProps,\n null\n ))\n ? (workInProgress.memoizedState = renderLanes)\n : isHydrating ||\n ((renderLanes = workInProgress.type),\n (current = workInProgress.pendingProps),\n (props = getOwnerDocumentFromRootContainer(\n rootInstanceStackCursor.current\n ).createElement(renderLanes)),\n (props[internalInstanceKey] = workInProgress),\n (props[internalPropsKey] = current),\n setInitialProperties(props, renderLanes, current),\n markNodeAsHoistable(props),\n (workInProgress.stateNode = props))\n : (workInProgress.memoizedState = getResource(\n workInProgress.type,\n current.memoizedProps,\n workInProgress.pendingProps,\n current.memoizedState\n )),\n null\n );\n case 27:\n return (\n pushHostContext(workInProgress),\n null === current &&\n isHydrating &&\n ((props = workInProgress.stateNode =\n resolveSingletonInstance(\n workInProgress.type,\n workInProgress.pendingProps,\n rootInstanceStackCursor.current\n )),\n (hydrationParentFiber = workInProgress),\n (rootOrSingletonContext = !0),\n ($$typeof = nextHydratableInstance),\n isSingletonScope(workInProgress.type)\n ? ((previousHydratableOnEnteringScopedSingleton = $$typeof),\n (nextHydratableInstance = getNextHydratable(props.firstChild)))\n : (nextHydratableInstance = $$typeof)),\n reconcileChildren(\n current,\n workInProgress,\n workInProgress.pendingProps.children,\n renderLanes\n ),\n markRef(current, workInProgress),\n null === current && (workInProgress.flags |= 4194304),\n workInProgress.child\n );\n case 5:\n if (null === current && isHydrating) {\n if (($$typeof = props = nextHydratableInstance))\n (props = canHydrateInstance(\n props,\n workInProgress.type,\n workInProgress.pendingProps,\n rootOrSingletonContext\n )),\n null !== props\n ? ((workInProgress.stateNode = props),\n (hydrationParentFiber = workInProgress),\n (nextHydratableInstance = getNextHydratable(props.firstChild)),\n (rootOrSingletonContext = !1),\n ($$typeof = !0))\n : ($$typeof = !1);\n $$typeof || throwOnHydrationMismatch(workInProgress);\n }\n pushHostContext(workInProgress);\n $$typeof = workInProgress.type;\n prevState = workInProgress.pendingProps;\n nextState = null !== current ? current.memoizedProps : null;\n props = prevState.children;\n shouldSetTextContent($$typeof, prevState)\n ? (props = null)\n : null !== nextState &&\n shouldSetTextContent($$typeof, nextState) &&\n (workInProgress.flags |= 32);\n null !== workInProgress.memoizedState &&\n (($$typeof = renderWithHooks(\n current,\n workInProgress,\n TransitionAwareHostComponent,\n null,\n null,\n renderLanes\n )),\n (HostTransitionContext._currentValue = $$typeof));\n markRef(current, workInProgress);\n reconcileChildren(current, workInProgress, props, renderLanes);\n return workInProgress.child;\n case 6:\n if (null === current && isHydrating) {\n if ((current = renderLanes = nextHydratableInstance))\n (renderLanes = canHydrateTextInstance(\n renderLanes,\n workInProgress.pendingProps,\n rootOrSingletonContext\n )),\n null !== renderLanes\n ? ((workInProgress.stateNode = renderLanes),\n (hydrationParentFiber = workInProgress),\n (nextHydratableInstance = null),\n (current = !0))\n : (current = !1);\n current || throwOnHydrationMismatch(workInProgress);\n }\n return null;\n case 13:\n return updateSuspenseComponent(current, workInProgress, renderLanes);\n case 4:\n return (\n pushHostContainer(\n workInProgress,\n workInProgress.stateNode.containerInfo\n ),\n (props = workInProgress.pendingProps),\n null === current\n ? (workInProgress.child = reconcileChildFibers(\n workInProgress,\n null,\n props,\n renderLanes\n ))\n : reconcileChildren(current, workInProgress, props, renderLanes),\n workInProgress.child\n );\n case 11:\n return updateForwardRef(\n current,\n workInProgress,\n workInProgress.type,\n workInProgress.pendingProps,\n renderLanes\n );\n case 7:\n return (\n reconcileChildren(\n current,\n workInProgress,\n workInProgress.pendingProps,\n renderLanes\n ),\n workInProgress.child\n );\n case 8:\n return (\n reconcileChildren(\n current,\n workInProgress,\n workInProgress.pendingProps.children,\n renderLanes\n ),\n workInProgress.child\n );\n case 12:\n return (\n reconcileChildren(\n current,\n workInProgress,\n workInProgress.pendingProps.children,\n renderLanes\n ),\n workInProgress.child\n );\n case 10:\n return (\n (props = workInProgress.pendingProps),\n pushProvider(workInProgress, workInProgress.type, props.value),\n reconcileChildren(current, workInProgress, props.children, renderLanes),\n workInProgress.child\n );\n case 9:\n return (\n ($$typeof = workInProgress.type._context),\n (props = workInProgress.pendingProps.children),\n prepareToReadContext(workInProgress),\n ($$typeof = readContext($$typeof)),\n (props = props($$typeof)),\n (workInProgress.flags |= 1),\n reconcileChildren(current, workInProgress, props, renderLanes),\n workInProgress.child\n );\n case 14:\n return updateMemoComponent(\n current,\n workInProgress,\n workInProgress.type,\n workInProgress.pendingProps,\n renderLanes\n );\n case 15:\n return updateSimpleMemoComponent(\n current,\n workInProgress,\n workInProgress.type,\n workInProgress.pendingProps,\n renderLanes\n );\n case 19:\n return updateSuspenseListComponent(current, workInProgress, renderLanes);\n case 31:\n return updateActivityComponent(current, workInProgress, renderLanes);\n case 22:\n return updateOffscreenComponent(\n current,\n workInProgress,\n renderLanes,\n workInProgress.pendingProps\n );\n case 24:\n return (\n prepareToReadContext(workInProgress),\n (props = readContext(CacheContext)),\n null === current\n ? (($$typeof = peekCacheFromPool()),\n null === $$typeof &&\n (($$typeof = workInProgressRoot),\n (prevState = createCache()),\n ($$typeof.pooledCache = prevState),\n prevState.refCount++,\n null !== prevState && ($$typeof.pooledCacheLanes |= renderLanes),\n ($$typeof = prevState)),\n (workInProgress.memoizedState = { parent: props, cache: $$typeof }),\n initializeUpdateQueue(workInProgress),\n pushProvider(workInProgress, CacheContext, $$typeof))\n : (0 !== (current.lanes & renderLanes) &&\n (cloneUpdateQueue(current, workInProgress),\n processUpdateQueue(workInProgress, null, null, renderLanes),\n suspendIfUpdateReadFromEntangledAsyncAction()),\n ($$typeof = current.memoizedState),\n (prevState = workInProgress.memoizedState),\n $$typeof.parent !== props\n ? (($$typeof = { parent: props, cache: props }),\n (workInProgress.memoizedState = $$typeof),\n 0 === workInProgress.lanes &&\n (workInProgress.memoizedState =\n workInProgress.updateQueue.baseState =\n $$typeof),\n pushProvider(workInProgress, CacheContext, props))\n : ((props = prevState.cache),\n pushProvider(workInProgress, CacheContext, props),\n props !== $$typeof.cache &&\n propagateContextChanges(\n workInProgress,\n [CacheContext],\n renderLanes,\n !0\n ))),\n reconcileChildren(\n current,\n workInProgress,\n workInProgress.pendingProps.children,\n renderLanes\n ),\n workInProgress.child\n );\n case 29:\n throw workInProgress.pendingProps;\n }\n throw Error(formatProdErrorMessage(156, workInProgress.tag));\n}\nfunction markUpdate(workInProgress) {\n workInProgress.flags |= 4;\n}\nfunction preloadInstanceAndSuspendIfNeeded(\n workInProgress,\n type,\n oldProps,\n newProps,\n renderLanes\n) {\n if ((type = 0 !== (workInProgress.mode & 32))) type = !1;\n if (type) {\n if (\n ((workInProgress.flags |= 16777216),\n (renderLanes & 335544128) === renderLanes)\n )\n if (workInProgress.stateNode.complete) workInProgress.flags |= 8192;\n else if (shouldRemainOnPreviousScreen()) workInProgress.flags |= 8192;\n else\n throw (\n ((suspendedThenable = noopSuspenseyCommitThenable),\n SuspenseyCommitException)\n );\n } else workInProgress.flags &= -16777217;\n}\nfunction preloadResourceAndSuspendIfNeeded(workInProgress, resource) {\n if (\"stylesheet\" !== resource.type || 0 !== (resource.state.loading & 4))\n workInProgress.flags &= -16777217;\n else if (((workInProgress.flags |= 16777216), !preloadResource(resource)))\n if (shouldRemainOnPreviousScreen()) workInProgress.flags |= 8192;\n else\n throw (\n ((suspendedThenable = noopSuspenseyCommitThenable),\n SuspenseyCommitException)\n );\n}\nfunction scheduleRetryEffect(workInProgress, retryQueue) {\n null !== retryQueue && (workInProgress.flags |= 4);\n workInProgress.flags & 16384 &&\n ((retryQueue =\n 22 !== workInProgress.tag ? claimNextRetryLane() : 536870912),\n (workInProgress.lanes |= retryQueue),\n (workInProgressSuspendedRetryLanes |= retryQueue));\n}\nfunction cutOffTailIfNeeded(renderState, hasRenderedATailFallback) {\n if (!isHydrating)\n switch (renderState.tailMode) {\n case \"hidden\":\n hasRenderedATailFallback = renderState.tail;\n for (var lastTailNode = null; null !== hasRenderedATailFallback; )\n null !== hasRenderedATailFallback.alternate &&\n (lastTailNode = hasRenderedATailFallback),\n (hasRenderedATailFallback = hasRenderedATailFallback.sibling);\n null === lastTailNode\n ? (renderState.tail = null)\n : (lastTailNode.sibling = null);\n break;\n case \"collapsed\":\n lastTailNode = renderState.tail;\n for (var lastTailNode$106 = null; null !== lastTailNode; )\n null !== lastTailNode.alternate && (lastTailNode$106 = lastTailNode),\n (lastTailNode = lastTailNode.sibling);\n null === lastTailNode$106\n ? hasRenderedATailFallback || null === renderState.tail\n ? (renderState.tail = null)\n : (renderState.tail.sibling = null)\n : (lastTailNode$106.sibling = null);\n }\n}\nfunction bubbleProperties(completedWork) {\n var didBailout =\n null !== completedWork.alternate &&\n completedWork.alternate.child === completedWork.child,\n newChildLanes = 0,\n subtreeFlags = 0;\n if (didBailout)\n for (var child$107 = completedWork.child; null !== child$107; )\n (newChildLanes |= child$107.lanes | child$107.childLanes),\n (subtreeFlags |= child$107.subtreeFlags & 65011712),\n (subtreeFlags |= child$107.flags & 65011712),\n (child$107.return = completedWork),\n (child$107 = child$107.sibling);\n else\n for (child$107 = completedWork.child; null !== child$107; )\n (newChildLanes |= child$107.lanes | child$107.childLanes),\n (subtreeFlags |= child$107.subtreeFlags),\n (subtreeFlags |= child$107.flags),\n (child$107.return = completedWork),\n (child$107 = child$107.sibling);\n completedWork.subtreeFlags |= subtreeFlags;\n completedWork.childLanes = newChildLanes;\n return didBailout;\n}\nfunction completeWork(current, workInProgress, renderLanes) {\n var newProps = workInProgress.pendingProps;\n popTreeContext(workInProgress);\n switch (workInProgress.tag) {\n case 16:\n case 15:\n case 0:\n case 11:\n case 7:\n case 8:\n case 12:\n case 9:\n case 14:\n return bubbleProperties(workInProgress), null;\n case 1:\n return bubbleProperties(workInProgress), null;\n case 3:\n renderLanes = workInProgress.stateNode;\n newProps = null;\n null !== current && (newProps = current.memoizedState.cache);\n workInProgress.memoizedState.cache !== newProps &&\n (workInProgress.flags |= 2048);\n popProvider(CacheContext);\n popHostContainer();\n renderLanes.pendingContext &&\n ((renderLanes.context = renderLanes.pendingContext),\n (renderLanes.pendingContext = null));\n if (null === current || null === current.child)\n popHydrationState(workInProgress)\n ? markUpdate(workInProgress)\n : null === current ||\n (current.memoizedState.isDehydrated &&\n 0 === (workInProgress.flags & 256)) ||\n ((workInProgress.flags |= 1024),\n upgradeHydrationErrorsToRecoverable());\n bubbleProperties(workInProgress);\n return null;\n case 26:\n var type = workInProgress.type,\n nextResource = workInProgress.memoizedState;\n null === current\n ? (markUpdate(workInProgress),\n null !== nextResource\n ? (bubbleProperties(workInProgress),\n preloadResourceAndSuspendIfNeeded(workInProgress, nextResource))\n : (bubbleProperties(workInProgress),\n preloadInstanceAndSuspendIfNeeded(\n workInProgress,\n type,\n null,\n newProps,\n renderLanes\n )))\n : nextResource\n ? nextResource !== current.memoizedState\n ? (markUpdate(workInProgress),\n bubbleProperties(workInProgress),\n preloadResourceAndSuspendIfNeeded(workInProgress, nextResource))\n : (bubbleProperties(workInProgress),\n (workInProgress.flags &= -16777217))\n : ((current = current.memoizedProps),\n current !== newProps && markUpdate(workInProgress),\n bubbleProperties(workInProgress),\n preloadInstanceAndSuspendIfNeeded(\n workInProgress,\n type,\n current,\n newProps,\n renderLanes\n ));\n return null;\n case 27:\n popHostContext(workInProgress);\n renderLanes = rootInstanceStackCursor.current;\n type = workInProgress.type;\n if (null !== current && null != workInProgress.stateNode)\n current.memoizedProps !== newProps && markUpdate(workInProgress);\n else {\n if (!newProps) {\n if (null === workInProgress.stateNode)\n throw Error(formatProdErrorMessage(166));\n bubbleProperties(workInProgress);\n return null;\n }\n current = contextStackCursor.current;\n popHydrationState(workInProgress)\n ? prepareToHydrateHostInstance(workInProgress, current)\n : ((current = resolveSingletonInstance(type, newProps, renderLanes)),\n (workInProgress.stateNode = current),\n markUpdate(workInProgress));\n }\n bubbleProperties(workInProgress);\n return null;\n case 5:\n popHostContext(workInProgress);\n type = workInProgress.type;\n if (null !== current && null != workInProgress.stateNode)\n current.memoizedProps !== newProps && markUpdate(workInProgress);\n else {\n if (!newProps) {\n if (null === workInProgress.stateNode)\n throw Error(formatProdErrorMessage(166));\n bubbleProperties(workInProgress);\n return null;\n }\n nextResource = contextStackCursor.current;\n if (popHydrationState(workInProgress))\n prepareToHydrateHostInstance(workInProgress, nextResource);\n else {\n var ownerDocument = getOwnerDocumentFromRootContainer(\n rootInstanceStackCursor.current\n );\n switch (nextResource) {\n case 1:\n nextResource = ownerDocument.createElementNS(\n \"http://www.w3.org/2000/svg\",\n type\n );\n break;\n case 2:\n nextResource = ownerDocument.createElementNS(\n \"http://www.w3.org/1998/Math/MathML\",\n type\n );\n break;\n default:\n switch (type) {\n case \"svg\":\n nextResource = ownerDocument.createElementNS(\n \"http://www.w3.org/2000/svg\",\n type\n );\n break;\n case \"math\":\n nextResource = ownerDocument.createElementNS(\n \"http://www.w3.org/1998/Math/MathML\",\n type\n );\n break;\n case \"script\":\n nextResource = ownerDocument.createElement(\"div\");\n nextResource.innerHTML = \"<script>\\x3c/script>\";\n nextResource = nextResource.removeChild(\n nextResource.firstChild\n );\n break;\n case \"select\":\n nextResource =\n \"string\" === typeof newProps.is\n ? ownerDocument.createElement(\"select\", {\n is: newProps.is\n })\n : ownerDocument.createElement(\"select\");\n newProps.multiple\n ? (nextResource.multiple = !0)\n : newProps.size && (nextResource.size = newProps.size);\n break;\n default:\n nextResource =\n \"string\" === typeof newProps.is\n ? ownerDocument.createElement(type, { is: newProps.is })\n : ownerDocument.createElement(type);\n }\n }\n nextResource[internalInstanceKey] = workInProgress;\n nextResource[internalPropsKey] = newProps;\n a: for (\n ownerDocument = workInProgress.child;\n null !== ownerDocument;\n\n ) {\n if (5 === ownerDocument.tag || 6 === ownerDocument.tag)\n nextResource.appendChild(ownerDocument.stateNode);\n else if (\n 4 !== ownerDocument.tag &&\n 27 !== ownerDocument.tag &&\n null !== ownerDocument.child\n ) {\n ownerDocument.child.return = ownerDocument;\n ownerDocument = ownerDocument.child;\n continue;\n }\n if (ownerDocument === workInProgress) break a;\n for (; null === ownerDocument.sibling; ) {\n if (\n null === ownerDocument.return ||\n ownerDocument.return === workInProgress\n )\n break a;\n ownerDocument = ownerDocument.return;\n }\n ownerDocument.sibling.return = ownerDocument.return;\n ownerDocument = ownerDocument.sibling;\n }\n workInProgress.stateNode = nextResource;\n a: switch (\n (setInitialProperties(nextResource, type, newProps), type)\n ) {\n case \"button\":\n case \"input\":\n case \"select\":\n case \"textarea\":\n newProps = !!newProps.autoFocus;\n break a;\n case \"img\":\n newProps = !0;\n break a;\n default:\n newProps = !1;\n }\n newProps && markUpdate(workInProgress);\n }\n }\n bubbleProperties(workInProgress);\n preloadInstanceAndSuspendIfNeeded(\n workInProgress,\n workInProgress.type,\n null === current ? null : current.memoizedProps,\n workInProgress.pendingProps,\n renderLanes\n );\n return null;\n case 6:\n if (current && null != workInProgress.stateNode)\n current.memoizedProps !== newProps && markUpdate(workInProgress);\n else {\n if (\"string\" !== typeof newProps && null === workInProgress.stateNode)\n throw Error(formatProdErrorMessage(166));\n current = rootInstanceStackCursor.current;\n if (popHydrationState(workInProgress)) {\n current = workInProgress.stateNode;\n renderLanes = workInProgress.memoizedProps;\n newProps = null;\n type = hydrationParentFiber;\n if (null !== type)\n switch (type.tag) {\n case 27:\n case 5:\n newProps = type.memoizedProps;\n }\n current[internalInstanceKey] = workInProgress;\n current =\n current.nodeValue === renderLanes ||\n (null !== newProps && !0 === newProps.suppressHydrationWarning) ||\n checkForUnmatchedText(current.nodeValue, renderLanes)\n ? !0\n : !1;\n current || throwOnHydrationMismatch(workInProgress, !0);\n } else\n (current =\n getOwnerDocumentFromRootContainer(current).createTextNode(\n newProps\n )),\n (current[internalInstanceKey] = workInProgress),\n (workInProgress.stateNode = current);\n }\n bubbleProperties(workInProgress);\n return null;\n case 31:\n renderLanes = workInProgress.memoizedState;\n if (null === current || null !== current.memoizedState) {\n newProps = popHydrationState(workInProgress);\n if (null !== renderLanes) {\n if (null === current) {\n if (!newProps) throw Error(formatProdErrorMessage(318));\n current = workInProgress.memoizedState;\n current = null !== current ? current.dehydrated : null;\n if (!current) throw Error(formatProdErrorMessage(557));\n current[internalInstanceKey] = workInProgress;\n } else\n resetHydrationState(),\n 0 === (workInProgress.flags & 128) &&\n (workInProgress.memoizedState = null),\n (workInProgress.flags |= 4);\n bubbleProperties(workInProgress);\n current = !1;\n } else\n (renderLanes = upgradeHydrationErrorsToRecoverable()),\n null !== current &&\n null !== current.memoizedState &&\n (current.memoizedState.hydrationErrors = renderLanes),\n (current = !0);\n if (!current) {\n if (workInProgress.flags & 256)\n return popSuspenseHandler(workInProgress), workInProgress;\n popSuspenseHandler(workInProgress);\n return null;\n }\n if (0 !== (workInProgress.flags & 128))\n throw Error(formatProdErrorMessage(558));\n }\n bubbleProperties(workInProgress);\n return null;\n case 13:\n newProps = workInProgress.memoizedState;\n if (\n null === current ||\n (null !== current.memoizedState &&\n null !== current.memoizedState.dehydrated)\n ) {\n type = popHydrationState(workInProgress);\n if (null !== newProps && null !== newProps.dehydrated) {\n if (null === current) {\n if (!type) throw Error(formatProdErrorMessage(318));\n type = workInProgress.memoizedState;\n type = null !== type ? type.dehydrated : null;\n if (!type) throw Error(formatProdErrorMessage(317));\n type[internalInstanceKey] = workInProgress;\n } else\n resetHydrationState(),\n 0 === (workInProgress.flags & 128) &&\n (workInProgress.memoizedState = null),\n (workInProgress.flags |= 4);\n bubbleProperties(workInProgress);\n type = !1;\n } else\n (type = upgradeHydrationErrorsToRecoverable()),\n null !== current &&\n null !== current.memoizedState &&\n (current.memoizedState.hydrationErrors = type),\n (type = !0);\n if (!type) {\n if (workInProgress.flags & 256)\n return popSuspenseHandler(workInProgress), workInProgress;\n popSuspenseHandler(workInProgress);\n return null;\n }\n }\n popSuspenseHandler(workInProgress);\n if (0 !== (workInProgress.flags & 128))\n return (workInProgress.lanes = renderLanes), workInProgress;\n renderLanes = null !== newProps;\n current = null !== current && null !== current.memoizedState;\n renderLanes &&\n ((newProps = workInProgress.child),\n (type = null),\n null !== newProps.alternate &&\n null !== newProps.alternate.memoizedState &&\n null !== newProps.alternate.memoizedState.cachePool &&\n (type = newProps.alternate.memoizedState.cachePool.pool),\n (nextResource = null),\n null !== newProps.memoizedState &&\n null !== newProps.memoizedState.cachePool &&\n (nextResource = newProps.memoizedState.cachePool.pool),\n nextResource !== type && (newProps.flags |= 2048));\n renderLanes !== current &&\n renderLanes &&\n (workInProgress.child.flags |= 8192);\n scheduleRetryEffect(workInProgress, workInProgress.updateQueue);\n bubbleProperties(workInProgress);\n return null;\n case 4:\n return (\n popHostContainer(),\n null === current &&\n listenToAllSupportedEvents(workInProgress.stateNode.containerInfo),\n bubbleProperties(workInProgress),\n null\n );\n case 10:\n return (\n popProvider(workInProgress.type), bubbleProperties(workInProgress), null\n );\n case 19:\n pop(suspenseStackCursor);\n newProps = workInProgress.memoizedState;\n if (null === newProps) return bubbleProperties(workInProgress), null;\n type = 0 !== (workInProgress.flags & 128);\n nextResource = newProps.rendering;\n if (null === nextResource)\n if (type) cutOffTailIfNeeded(newProps, !1);\n else {\n if (\n 0 !== workInProgressRootExitStatus ||\n (null !== current && 0 !== (current.flags & 128))\n )\n for (current = workInProgress.child; null !== current; ) {\n nextResource = findFirstSuspended(current);\n if (null !== nextResource) {\n workInProgress.flags |= 128;\n cutOffTailIfNeeded(newProps, !1);\n current = nextResource.updateQueue;\n workInProgress.updateQueue = current;\n scheduleRetryEffect(workInProgress, current);\n workInProgress.subtreeFlags = 0;\n current = renderLanes;\n for (renderLanes = workInProgress.child; null !== renderLanes; )\n resetWorkInProgress(renderLanes, current),\n (renderLanes = renderLanes.sibling);\n push(\n suspenseStackCursor,\n (suspenseStackCursor.current & 1) | 2\n );\n isHydrating &&\n pushTreeFork(workInProgress, newProps.treeForkCount);\n return workInProgress.child;\n }\n current = current.sibling;\n }\n null !== newProps.tail &&\n now() > workInProgressRootRenderTargetTime &&\n ((workInProgress.flags |= 128),\n (type = !0),\n cutOffTailIfNeeded(newProps, !1),\n (workInProgress.lanes = 4194304));\n }\n else {\n if (!type)\n if (\n ((current = findFirstSuspended(nextResource)), null !== current)\n ) {\n if (\n ((workInProgress.flags |= 128),\n (type = !0),\n (current = current.updateQueue),\n (workInProgress.updateQueue = current),\n scheduleRetryEffect(workInProgress, current),\n cutOffTailIfNeeded(newProps, !0),\n null === newProps.tail &&\n \"hidden\" === newProps.tailMode &&\n !nextResource.alternate &&\n !isHydrating)\n )\n return bubbleProperties(workInProgress), null;\n } else\n 2 * now() - newProps.renderingStartTime >\n workInProgressRootRenderTargetTime &&\n 536870912 !== renderLanes &&\n ((workInProgress.flags |= 128),\n (type = !0),\n cutOffTailIfNeeded(newProps, !1),\n (workInProgress.lanes = 4194304));\n newProps.isBackwards\n ? ((nextResource.sibling = workInProgress.child),\n (workInProgress.child = nextResource))\n : ((current = newProps.last),\n null !== current\n ? (current.sibling = nextResource)\n : (workInProgress.child = nextResource),\n (newProps.last = nextResource));\n }\n if (null !== newProps.tail)\n return (\n (current = newProps.tail),\n (newProps.rendering = current),\n (newProps.tail = current.sibling),\n (newProps.renderingStartTime = now()),\n (current.sibling = null),\n (renderLanes = suspenseStackCursor.current),\n push(\n suspenseStackCursor,\n type ? (renderLanes & 1) | 2 : renderLanes & 1\n ),\n isHydrating && pushTreeFork(workInProgress, newProps.treeForkCount),\n current\n );\n bubbleProperties(workInProgress);\n return null;\n case 22:\n case 23:\n return (\n popSuspenseHandler(workInProgress),\n popHiddenContext(),\n (newProps = null !== workInProgress.memoizedState),\n null !== current\n ? (null !== current.memoizedState) !== newProps &&\n (workInProgress.flags |= 8192)\n : newProps && (workInProgress.flags |= 8192),\n newProps\n ? 0 !== (renderLanes & 536870912) &&\n 0 === (workInProgress.flags & 128) &&\n (bubbleProperties(workInProgress),\n workInProgress.subtreeFlags & 6 && (workInProgress.flags |= 8192))\n : bubbleProperties(workInProgress),\n (renderLanes = workInProgress.updateQueue),\n null !== renderLanes &&\n scheduleRetryEffect(workInProgress, renderLanes.retryQueue),\n (renderLanes = null),\n null !== current &&\n null !== current.memoizedState &&\n null !== current.memoizedState.cachePool &&\n (renderLanes = current.memoizedState.cachePool.pool),\n (newProps = null),\n null !== workInProgress.memoizedState &&\n null !== workInProgress.memoizedState.cachePool &&\n (newProps = workInProgress.memoizedState.cachePool.pool),\n newProps !== renderLanes && (workInProgress.flags |= 2048),\n null !== current && pop(resumedCache),\n null\n );\n case 24:\n return (\n (renderLanes = null),\n null !== current && (renderLanes = current.memoizedState.cache),\n workInProgress.memoizedState.cache !== renderLanes &&\n (workInProgress.flags |= 2048),\n popProvider(CacheContext),\n bubbleProperties(workInProgress),\n null\n );\n case 25:\n return null;\n case 30:\n return null;\n }\n throw Error(formatProdErrorMessage(156, workInProgress.tag));\n}\nfunction unwindWork(current, workInProgress) {\n popTreeContext(workInProgress);\n switch (workInProgress.tag) {\n case 1:\n return (\n (current = workInProgress.flags),\n current & 65536\n ? ((workInProgress.flags = (current & -65537) | 128), workInProgress)\n : null\n );\n case 3:\n return (\n popProvider(CacheContext),\n popHostContainer(),\n (current = workInProgress.flags),\n 0 !== (current & 65536) && 0 === (current & 128)\n ? ((workInProgress.flags = (current & -65537) | 128), workInProgress)\n : null\n );\n case 26:\n case 27:\n case 5:\n return popHostContext(workInProgress), null;\n case 31:\n if (null !== workInProgress.memoizedState) {\n popSuspenseHandler(workInProgress);\n if (null === workInProgress.alternate)\n throw Error(formatProdErrorMessage(340));\n resetHydrationState();\n }\n current = workInProgress.flags;\n return current & 65536\n ? ((workInProgress.flags = (current & -65537) | 128), workInProgress)\n : null;\n case 13:\n popSuspenseHandler(workInProgress);\n current = workInProgress.memoizedState;\n if (null !== current && null !== current.dehydrated) {\n if (null === workInProgress.alternate)\n throw Error(formatProdErrorMessage(340));\n resetHydrationState();\n }\n current = workInProgress.flags;\n return current & 65536\n ? ((workInProgress.flags = (current & -65537) | 128), workInProgress)\n : null;\n case 19:\n return pop(suspenseStackCursor), null;\n case 4:\n return popHostContainer(), null;\n case 10:\n return popProvider(workInProgress.type), null;\n case 22:\n case 23:\n return (\n popSuspenseHandler(workInProgress),\n popHiddenContext(),\n null !== current && pop(resumedCache),\n (current = workInProgress.flags),\n current & 65536\n ? ((workInProgress.flags = (current & -65537) | 128), workInProgress)\n : null\n );\n case 24:\n return popProvider(CacheContext), null;\n case 25:\n return null;\n default:\n return null;\n }\n}\nfunction unwindInterruptedWork(current, interruptedWork) {\n popTreeContext(interruptedWork);\n switch (interruptedWork.tag) {\n case 3:\n popProvider(CacheContext);\n popHostContainer();\n break;\n case 26:\n case 27:\n case 5:\n popHostContext(interruptedWork);\n break;\n case 4:\n popHostContainer();\n break;\n case 31:\n null !== interruptedWork.memoizedState &&\n popSuspenseHandler(interruptedWork);\n break;\n case 13:\n popSuspenseHandler(interruptedWork);\n break;\n case 19:\n pop(suspenseStackCursor);\n break;\n case 10:\n popProvider(interruptedWork.type);\n break;\n case 22:\n case 23:\n popSuspenseHandler(interruptedWork);\n popHiddenContext();\n null !== current && pop(resumedCache);\n break;\n case 24:\n popProvider(CacheContext);\n }\n}\nfunction commitHookEffectListMount(flags, finishedWork) {\n try {\n var updateQueue = finishedWork.updateQueue,\n lastEffect = null !== updateQueue ? updateQueue.lastEffect : null;\n if (null !== lastEffect) {\n var firstEffect = lastEffect.next;\n updateQueue = firstEffect;\n do {\n if ((updateQueue.tag & flags) === flags) {\n lastEffect = void 0;\n var create = updateQueue.create,\n inst = updateQueue.inst;\n lastEffect = create();\n inst.destroy = lastEffect;\n }\n updateQueue = updateQueue.next;\n } while (updateQueue !== firstEffect);\n }\n } catch (error) {\n captureCommitPhaseError(finishedWork, finishedWork.return, error);\n }\n}\nfunction commitHookEffectListUnmount(\n flags,\n finishedWork,\n nearestMountedAncestor$jscomp$0\n) {\n try {\n var updateQueue = finishedWork.updateQueue,\n lastEffect = null !== updateQueue ? updateQueue.lastEffect : null;\n if (null !== lastEffect) {\n var firstEffect = lastEffect.next;\n updateQueue = firstEffect;\n do {\n if ((updateQueue.tag & flags) === flags) {\n var inst = updateQueue.inst,\n destroy = inst.destroy;\n if (void 0 !== destroy) {\n inst.destroy = void 0;\n lastEffect = finishedWork;\n var nearestMountedAncestor = nearestMountedAncestor$jscomp$0,\n destroy_ = destroy;\n try {\n destroy_();\n } catch (error) {\n captureCommitPhaseError(\n lastEffect,\n nearestMountedAncestor,\n error\n );\n }\n }\n }\n updateQueue = updateQueue.next;\n } while (updateQueue !== firstEffect);\n }\n } catch (error) {\n captureCommitPhaseError(finishedWork, finishedWork.return, error);\n }\n}\nfunction commitClassCallbacks(finishedWork) {\n var updateQueue = finishedWork.updateQueue;\n if (null !== updateQueue) {\n var instance = finishedWork.stateNode;\n try {\n commitCallbacks(updateQueue, instance);\n } catch (error) {\n captureCommitPhaseError(finishedWork, finishedWork.return, error);\n }\n }\n}\nfunction safelyCallComponentWillUnmount(\n current,\n nearestMountedAncestor,\n instance\n) {\n instance.props = resolveClassComponentProps(\n current.type,\n current.memoizedProps\n );\n instance.state = current.memoizedState;\n try {\n instance.componentWillUnmount();\n } catch (error) {\n captureCommitPhaseError(current, nearestMountedAncestor, error);\n }\n}\nfunction safelyAttachRef(current, nearestMountedAncestor) {\n try {\n var ref = current.ref;\n if (null !== ref) {\n switch (current.tag) {\n case 26:\n case 27:\n case 5:\n var instanceToUse = current.stateNode;\n break;\n case 30:\n instanceToUse = current.stateNode;\n break;\n default:\n instanceToUse = current.stateNode;\n }\n \"function\" === typeof ref\n ? (current.refCleanup = ref(instanceToUse))\n : (ref.current = instanceToUse);\n }\n } catch (error) {\n captureCommitPhaseError(current, nearestMountedAncestor, error);\n }\n}\nfunction safelyDetachRef(current, nearestMountedAncestor) {\n var ref = current.ref,\n refCleanup = current.refCleanup;\n if (null !== ref)\n if (\"function\" === typeof refCleanup)\n try {\n refCleanup();\n } catch (error) {\n captureCommitPhaseError(current, nearestMountedAncestor, error);\n } finally {\n (current.refCleanup = null),\n (current = current.alternate),\n null != current && (current.refCleanup = null);\n }\n else if (\"function\" === typeof ref)\n try {\n ref(null);\n } catch (error$140) {\n captureCommitPhaseError(current, nearestMountedAncestor, error$140);\n }\n else ref.current = null;\n}\nfunction commitHostMount(finishedWork) {\n var type = finishedWork.type,\n props = finishedWork.memoizedProps,\n instance = finishedWork.stateNode;\n try {\n a: switch (type) {\n case \"button\":\n case \"input\":\n case \"select\":\n case \"textarea\":\n props.autoFocus && instance.focus();\n break a;\n case \"img\":\n props.src\n ? (instance.src = props.src)\n : props.srcSet && (instance.srcset = props.srcSet);\n }\n } catch (error) {\n captureCommitPhaseError(finishedWork, finishedWork.return, error);\n }\n}\nfunction commitHostUpdate(finishedWork, newProps, oldProps) {\n try {\n var domElement = finishedWork.stateNode;\n updateProperties(domElement, finishedWork.type, oldProps, newProps);\n domElement[internalPropsKey] = newProps;\n } catch (error) {\n captureCommitPhaseError(finishedWork, finishedWork.return, error);\n }\n}\nfunction isHostParent(fiber) {\n return (\n 5 === fiber.tag ||\n 3 === fiber.tag ||\n 26 === fiber.tag ||\n (27 === fiber.tag && isSingletonScope(fiber.type)) ||\n 4 === fiber.tag\n );\n}\nfunction getHostSibling(fiber) {\n a: for (;;) {\n for (; null === fiber.sibling; ) {\n if (null === fiber.return || isHostParent(fiber.return)) return null;\n fiber = fiber.return;\n }\n fiber.sibling.return = fiber.return;\n for (\n fiber = fiber.sibling;\n 5 !== fiber.tag && 6 !== fiber.tag && 18 !== fiber.tag;\n\n ) {\n if (27 === fiber.tag && isSingletonScope(fiber.type)) continue a;\n if (fiber.flags & 2) continue a;\n if (null === fiber.child || 4 === fiber.tag) continue a;\n else (fiber.child.return = fiber), (fiber = fiber.child);\n }\n if (!(fiber.flags & 2)) return fiber.stateNode;\n }\n}\nfunction insertOrAppendPlacementNodeIntoContainer(node, before, parent) {\n var tag = node.tag;\n if (5 === tag || 6 === tag)\n (node = node.stateNode),\n before\n ? (9 === parent.nodeType\n ? parent.body\n : \"HTML\" === parent.nodeName\n ? parent.ownerDocument.body\n : parent\n ).insertBefore(node, before)\n : ((before =\n 9 === parent.nodeType\n ? parent.body\n : \"HTML\" === parent.nodeName\n ? parent.ownerDocument.body\n : parent),\n before.appendChild(node),\n (parent = parent._reactRootContainer),\n (null !== parent && void 0 !== parent) ||\n null !== before.onclick ||\n (before.onclick = noop$1));\n else if (\n 4 !== tag &&\n (27 === tag &&\n isSingletonScope(node.type) &&\n ((parent = node.stateNode), (before = null)),\n (node = node.child),\n null !== node)\n )\n for (\n insertOrAppendPlacementNodeIntoContainer(node, before, parent),\n node = node.sibling;\n null !== node;\n\n )\n insertOrAppendPlacementNodeIntoContainer(node, before, parent),\n (node = node.sibling);\n}\nfunction insertOrAppendPlacementNode(node, before, parent) {\n var tag = node.tag;\n if (5 === tag || 6 === tag)\n (node = node.stateNode),\n before ? parent.insertBefore(node, before) : parent.appendChild(node);\n else if (\n 4 !== tag &&\n (27 === tag && isSingletonScope(node.type) && (parent = node.stateNode),\n (node = node.child),\n null !== node)\n )\n for (\n insertOrAppendPlacementNode(node, before, parent), node = node.sibling;\n null !== node;\n\n )\n insertOrAppendPlacementNode(node, before, parent), (node = node.sibling);\n}\nfunction commitHostSingletonAcquisition(finishedWork) {\n var singleton = finishedWork.stateNode,\n props = finishedWork.memoizedProps;\n try {\n for (\n var type = finishedWork.type, attributes = singleton.attributes;\n attributes.length;\n\n )\n singleton.removeAttributeNode(attributes[0]);\n setInitialProperties(singleton, type, props);\n singleton[internalInstanceKey] = finishedWork;\n singleton[internalPropsKey] = props;\n } catch (error) {\n captureCommitPhaseError(finishedWork, finishedWork.return, error);\n }\n}\nvar offscreenSubtreeIsHidden = !1,\n offscreenSubtreeWasHidden = !1,\n needsFormReset = !1,\n PossiblyWeakSet = \"function\" === typeof WeakSet ? WeakSet : Set,\n nextEffect = null;\nfunction commitBeforeMutationEffects(root, firstChild) {\n root = root.containerInfo;\n eventsEnabled = _enabled;\n root = getActiveElementDeep(root);\n if (hasSelectionCapabilities(root)) {\n if (\"selectionStart\" in root)\n var JSCompiler_temp = {\n start: root.selectionStart,\n end: root.selectionEnd\n };\n else\n a: {\n JSCompiler_temp =\n ((JSCompiler_temp = root.ownerDocument) &&\n JSCompiler_temp.defaultView) ||\n window;\n var selection =\n JSCompiler_temp.getSelection && JSCompiler_temp.getSelection();\n if (selection && 0 !== selection.rangeCount) {\n JSCompiler_temp = selection.anchorNode;\n var anchorOffset = selection.anchorOffset,\n focusNode = selection.focusNode;\n selection = selection.focusOffset;\n try {\n JSCompiler_temp.nodeType, focusNode.nodeType;\n } catch (e$20) {\n JSCompiler_temp = null;\n break a;\n }\n var length = 0,\n start = -1,\n end = -1,\n indexWithinAnchor = 0,\n indexWithinFocus = 0,\n node = root,\n parentNode = null;\n b: for (;;) {\n for (var next; ; ) {\n node !== JSCompiler_temp ||\n (0 !== anchorOffset && 3 !== node.nodeType) ||\n (start = length + anchorOffset);\n node !== focusNode ||\n (0 !== selection && 3 !== node.nodeType) ||\n (end = length + selection);\n 3 === node.nodeType && (length += node.nodeValue.length);\n if (null === (next = node.firstChild)) break;\n parentNode = node;\n node = next;\n }\n for (;;) {\n if (node === root) break b;\n parentNode === JSCompiler_temp &&\n ++indexWithinAnchor === anchorOffset &&\n (start = length);\n parentNode === focusNode &&\n ++indexWithinFocus === selection &&\n (end = length);\n if (null !== (next = node.nextSibling)) break;\n node = parentNode;\n parentNode = node.parentNode;\n }\n node = next;\n }\n JSCompiler_temp =\n -1 === start || -1 === end ? null : { start: start, end: end };\n } else JSCompiler_temp = null;\n }\n JSCompiler_temp = JSCompiler_temp || { start: 0, end: 0 };\n } else JSCompiler_temp = null;\n selectionInformation = { focusedElem: root, selectionRange: JSCompiler_temp };\n _enabled = !1;\n for (nextEffect = firstChild; null !== nextEffect; )\n if (\n ((firstChild = nextEffect),\n (root = firstChild.child),\n 0 !== (firstChild.subtreeFlags & 1028) && null !== root)\n )\n (root.return = firstChild), (nextEffect = root);\n else\n for (; null !== nextEffect; ) {\n firstChild = nextEffect;\n focusNode = firstChild.alternate;\n root = firstChild.flags;\n switch (firstChild.tag) {\n case 0:\n if (\n 0 !== (root & 4) &&\n ((root = firstChild.updateQueue),\n (root = null !== root ? root.events : null),\n null !== root)\n )\n for (\n JSCompiler_temp = 0;\n JSCompiler_temp < root.length;\n JSCompiler_temp++\n )\n (anchorOffset = root[JSCompiler_temp]),\n (anchorOffset.ref.impl = anchorOffset.nextImpl);\n break;\n case 11:\n case 15:\n break;\n case 1:\n if (0 !== (root & 1024) && null !== focusNode) {\n root = void 0;\n JSCompiler_temp = firstChild;\n anchorOffset = focusNode.memoizedProps;\n focusNode = focusNode.memoizedState;\n selection = JSCompiler_temp.stateNode;\n try {\n var resolvedPrevProps = resolveClassComponentProps(\n JSCompiler_temp.type,\n anchorOffset\n );\n root = selection.getSnapshotBeforeUpdate(\n resolvedPrevProps,\n focusNode\n );\n selection.__reactInternalSnapshotBeforeUpdate = root;\n } catch (error) {\n captureCommitPhaseError(\n JSCompiler_temp,\n JSCompiler_temp.return,\n error\n );\n }\n }\n break;\n case 3:\n if (0 !== (root & 1024))\n if (\n ((root = firstChild.stateNode.containerInfo),\n (JSCompiler_temp = root.nodeType),\n 9 === JSCompiler_temp)\n )\n clearContainerSparingly(root);\n else if (1 === JSCompiler_temp)\n switch (root.nodeName) {\n case \"HEAD\":\n case \"HTML\":\n case \"BODY\":\n clearContainerSparingly(root);\n break;\n default:\n root.textContent = \"\";\n }\n break;\n case 5:\n case 26:\n case 27:\n case 6:\n case 4:\n case 17:\n break;\n default:\n if (0 !== (root & 1024)) throw Error(formatProdErrorMessage(163));\n }\n root = firstChild.sibling;\n if (null !== root) {\n root.return = firstChild.return;\n nextEffect = root;\n break;\n }\n nextEffect = firstChild.return;\n }\n}\nfunction commitLayoutEffectOnFiber(finishedRoot, current, finishedWork) {\n var flags = finishedWork.flags;\n switch (finishedWork.tag) {\n case 0:\n case 11:\n case 15:\n recursivelyTraverseLayoutEffects(finishedRoot, finishedWork);\n flags & 4 && commitHookEffectListMount(5, finishedWork);\n break;\n case 1:\n recursivelyTraverseLayoutEffects(finishedRoot, finishedWork);\n if (flags & 4)\n if (((finishedRoot = finishedWork.stateNode), null === current))\n try {\n finishedRoot.componentDidMount();\n } catch (error) {\n captureCommitPhaseError(finishedWork, finishedWork.return, error);\n }\n else {\n var prevProps = resolveClassComponentProps(\n finishedWork.type,\n current.memoizedProps\n );\n current = current.memoizedState;\n try {\n finishedRoot.componentDidUpdate(\n prevProps,\n current,\n finishedRoot.__reactInternalSnapshotBeforeUpdate\n );\n } catch (error$139) {\n captureCommitPhaseError(\n finishedWork,\n finishedWork.return,\n error$139\n );\n }\n }\n flags & 64 && commitClassCallbacks(finishedWork);\n flags & 512 && safelyAttachRef(finishedWork, finishedWork.return);\n break;\n case 3:\n recursivelyTraverseLayoutEffects(finishedRoot, finishedWork);\n if (\n flags & 64 &&\n ((finishedRoot = finishedWork.updateQueue), null !== finishedRoot)\n ) {\n current = null;\n if (null !== finishedWork.child)\n switch (finishedWork.child.tag) {\n case 27:\n case 5:\n current = finishedWork.child.stateNode;\n break;\n case 1:\n current = finishedWork.child.stateNode;\n }\n try {\n commitCallbacks(finishedRoot, current);\n } catch (error) {\n captureCommitPhaseError(finishedWork, finishedWork.return, error);\n }\n }\n break;\n case 27:\n null === current &&\n flags & 4 &&\n commitHostSingletonAcquisition(finishedWork);\n case 26:\n case 5:\n recursivelyTraverseLayoutEffects(finishedRoot, finishedWork);\n null === current && flags & 4 && commitHostMount(finishedWork);\n flags & 512 && safelyAttachRef(finishedWork, finishedWork.return);\n break;\n case 12:\n recursivelyTraverseLayoutEffects(finishedRoot, finishedWork);\n break;\n case 31:\n recursivelyTraverseLayoutEffects(finishedRoot, finishedWork);\n flags & 4 && commitActivityHydrationCallbacks(finishedRoot, finishedWork);\n break;\n case 13:\n recursivelyTraverseLayoutEffects(finishedRoot, finishedWork);\n flags & 4 && commitSuspenseHydrationCallbacks(finishedRoot, finishedWork);\n flags & 64 &&\n ((finishedRoot = finishedWork.memoizedState),\n null !== finishedRoot &&\n ((finishedRoot = finishedRoot.dehydrated),\n null !== finishedRoot &&\n ((finishedWork = retryDehydratedSuspenseBoundary.bind(\n null,\n finishedWork\n )),\n registerSuspenseInstanceRetry(finishedRoot, finishedWork))));\n break;\n case 22:\n flags = null !== finishedWork.memoizedState || offscreenSubtreeIsHidden;\n if (!flags) {\n current =\n (null !== current && null !== current.memoizedState) ||\n offscreenSubtreeWasHidden;\n prevProps = offscreenSubtreeIsHidden;\n var prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden;\n offscreenSubtreeIsHidden = flags;\n (offscreenSubtreeWasHidden = current) && !prevOffscreenSubtreeWasHidden\n ? recursivelyTraverseReappearLayoutEffects(\n finishedRoot,\n finishedWork,\n 0 !== (finishedWork.subtreeFlags & 8772)\n )\n : recursivelyTraverseLayoutEffects(finishedRoot, finishedWork);\n offscreenSubtreeIsHidden = prevProps;\n offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden;\n }\n break;\n case 30:\n break;\n default:\n recursivelyTraverseLayoutEffects(finishedRoot, finishedWork);\n }\n}\nfunction detachFiberAfterEffects(fiber) {\n var alternate = fiber.alternate;\n null !== alternate &&\n ((fiber.alternate = null), detachFiberAfterEffects(alternate));\n fiber.child = null;\n fiber.deletions = null;\n fiber.sibling = null;\n 5 === fiber.tag &&\n ((alternate = fiber.stateNode),\n null !== alternate && detachDeletedInstance(alternate));\n fiber.stateNode = null;\n fiber.return = null;\n fiber.dependencies = null;\n fiber.memoizedProps = null;\n fiber.memoizedState = null;\n fiber.pendingProps = null;\n fiber.stateNode = null;\n fiber.updateQueue = null;\n}\nvar hostParent = null,\n hostParentIsContainer = !1;\nfunction recursivelyTraverseDeletionEffects(\n finishedRoot,\n nearestMountedAncestor,\n parent\n) {\n for (parent = parent.child; null !== parent; )\n commitDeletionEffectsOnFiber(finishedRoot, nearestMountedAncestor, parent),\n (parent = parent.sibling);\n}\nfunction commitDeletionEffectsOnFiber(\n finishedRoot,\n nearestMountedAncestor,\n deletedFiber\n) {\n if (injectedHook && \"function\" === typeof injectedHook.onCommitFiberUnmount)\n try {\n injectedHook.onCommitFiberUnmount(rendererID, deletedFiber);\n } catch (err) {}\n switch (deletedFiber.tag) {\n case 26:\n offscreenSubtreeWasHidden ||\n safelyDetachRef(deletedFiber, nearestMountedAncestor);\n recursivelyTraverseDeletionEffects(\n finishedRoot,\n nearestMountedAncestor,\n deletedFiber\n );\n deletedFiber.memoizedState\n ? deletedFiber.memoizedState.count--\n : deletedFiber.stateNode &&\n ((deletedFiber = deletedFiber.stateNode),\n deletedFiber.parentNode.removeChild(deletedFiber));\n break;\n case 27:\n offscreenSubtreeWasHidden ||\n safelyDetachRef(deletedFiber, nearestMountedAncestor);\n var prevHostParent = hostParent,\n prevHostParentIsContainer = hostParentIsContainer;\n isSingletonScope(deletedFiber.type) &&\n ((hostParent = deletedFiber.stateNode), (hostParentIsContainer = !1));\n recursivelyTraverseDeletionEffects(\n finishedRoot,\n nearestMountedAncestor,\n deletedFiber\n );\n releaseSingletonInstance(deletedFiber.stateNode);\n hostParent = prevHostParent;\n hostParentIsContainer = prevHostParentIsContainer;\n break;\n case 5:\n offscreenSubtreeWasHidden ||\n safelyDetachRef(deletedFiber, nearestMountedAncestor);\n case 6:\n prevHostParent = hostParent;\n prevHostParentIsContainer = hostParentIsContainer;\n hostParent = null;\n recursivelyTraverseDeletionEffects(\n finishedRoot,\n nearestMountedAncestor,\n deletedFiber\n );\n hostParent = prevHostParent;\n hostParentIsContainer = prevHostParentIsContainer;\n if (null !== hostParent)\n if (hostParentIsContainer)\n try {\n (9 === hostParent.nodeType\n ? hostParent.body\n : \"HTML\" === hostParent.nodeName\n ? hostParent.ownerDocument.body\n : hostParent\n ).removeChild(deletedFiber.stateNode);\n } catch (error) {\n captureCommitPhaseError(\n deletedFiber,\n nearestMountedAncestor,\n error\n );\n }\n else\n try {\n hostParent.removeChild(deletedFiber.stateNode);\n } catch (error) {\n captureCommitPhaseError(\n deletedFiber,\n nearestMountedAncestor,\n error\n );\n }\n break;\n case 18:\n null !== hostParent &&\n (hostParentIsContainer\n ? ((finishedRoot = hostParent),\n clearHydrationBoundary(\n 9 === finishedRoot.nodeType\n ? finishedRoot.body\n : \"HTML\" === finishedRoot.nodeName\n ? finishedRoot.ownerDocument.body\n : finishedRoot,\n deletedFiber.stateNode\n ),\n retryIfBlockedOn(finishedRoot))\n : clearHydrationBoundary(hostParent, deletedFiber.stateNode));\n break;\n case 4:\n prevHostParent = hostParent;\n prevHostParentIsContainer = hostParentIsContainer;\n hostParent = deletedFiber.stateNode.containerInfo;\n hostParentIsContainer = !0;\n recursivelyTraverseDeletionEffects(\n finishedRoot,\n nearestMountedAncestor,\n deletedFiber\n );\n hostParent = prevHostParent;\n hostParentIsContainer = prevHostParentIsContainer;\n break;\n case 0:\n case 11:\n case 14:\n case 15:\n commitHookEffectListUnmount(2, deletedFiber, nearestMountedAncestor);\n offscreenSubtreeWasHidden ||\n commitHookEffectListUnmount(4, deletedFiber, nearestMountedAncestor);\n recursivelyTraverseDeletionEffects(\n finishedRoot,\n nearestMountedAncestor,\n deletedFiber\n );\n break;\n case 1:\n offscreenSubtreeWasHidden ||\n (safelyDetachRef(deletedFiber, nearestMountedAncestor),\n (prevHostParent = deletedFiber.stateNode),\n \"function\" === typeof prevHostParent.componentWillUnmount &&\n safelyCallComponentWillUnmount(\n deletedFiber,\n nearestMountedAncestor,\n prevHostParent\n ));\n recursivelyTraverseDeletionEffects(\n finishedRoot,\n nearestMountedAncestor,\n deletedFiber\n );\n break;\n case 21:\n recursivelyTraverseDeletionEffects(\n finishedRoot,\n nearestMountedAncestor,\n deletedFiber\n );\n break;\n case 22:\n offscreenSubtreeWasHidden =\n (prevHostParent = offscreenSubtreeWasHidden) ||\n null !== deletedFiber.memoizedState;\n recursivelyTraverseDeletionEffects(\n finishedRoot,\n nearestMountedAncestor,\n deletedFiber\n );\n offscreenSubtreeWasHidden = prevHostParent;\n break;\n default:\n recursivelyTraverseDeletionEffects(\n finishedRoot,\n nearestMountedAncestor,\n deletedFiber\n );\n }\n}\nfunction commitActivityHydrationCallbacks(finishedRoot, finishedWork) {\n if (\n null === finishedWork.memoizedState &&\n ((finishedRoot = finishedWork.alternate),\n null !== finishedRoot &&\n ((finishedRoot = finishedRoot.memoizedState), null !== finishedRoot))\n ) {\n finishedRoot = finishedRoot.dehydrated;\n try {\n retryIfBlockedOn(finishedRoot);\n } catch (error) {\n captureCommitPhaseError(finishedWork, finishedWork.return, error);\n }\n }\n}\nfunction commitSuspenseHydrationCallbacks(finishedRoot, finishedWork) {\n if (\n null === finishedWork.memoizedState &&\n ((finishedRoot = finishedWork.alternate),\n null !== finishedRoot &&\n ((finishedRoot = finishedRoot.memoizedState),\n null !== finishedRoot &&\n ((finishedRoot = finishedRoot.dehydrated), null !== finishedRoot)))\n )\n try {\n retryIfBlockedOn(finishedRoot);\n } catch (error) {\n captureCommitPhaseError(finishedWork, finishedWork.return, error);\n }\n}\nfunction getRetryCache(finishedWork) {\n switch (finishedWork.tag) {\n case 31:\n case 13:\n case 19:\n var retryCache = finishedWork.stateNode;\n null === retryCache &&\n (retryCache = finishedWork.stateNode = new PossiblyWeakSet());\n return retryCache;\n case 22:\n return (\n (finishedWork = finishedWork.stateNode),\n (retryCache = finishedWork._retryCache),\n null === retryCache &&\n (retryCache = finishedWork._retryCache = new PossiblyWeakSet()),\n retryCache\n );\n default:\n throw Error(formatProdErrorMessage(435, finishedWork.tag));\n }\n}\nfunction attachSuspenseRetryListeners(finishedWork, wakeables) {\n var retryCache = getRetryCache(finishedWork);\n wakeables.forEach(function (wakeable) {\n if (!retryCache.has(wakeable)) {\n retryCache.add(wakeable);\n var retry = resolveRetryWakeable.bind(null, finishedWork, wakeable);\n wakeable.then(retry, retry);\n }\n });\n}\nfunction recursivelyTraverseMutationEffects(root$jscomp$0, parentFiber) {\n var deletions = parentFiber.deletions;\n if (null !== deletions)\n for (var i = 0; i < deletions.length; i++) {\n var childToDelete = deletions[i],\n root = root$jscomp$0,\n returnFiber = parentFiber,\n parent = returnFiber;\n a: for (; null !== parent; ) {\n switch (parent.tag) {\n case 27:\n if (isSingletonScope(parent.type)) {\n hostParent = parent.stateNode;\n hostParentIsContainer = !1;\n break a;\n }\n break;\n case 5:\n hostParent = parent.stateNode;\n hostParentIsContainer = !1;\n break a;\n case 3:\n case 4:\n hostParent = parent.stateNode.containerInfo;\n hostParentIsContainer = !0;\n break a;\n }\n parent = parent.return;\n }\n if (null === hostParent) throw Error(formatProdErrorMessage(160));\n commitDeletionEffectsOnFiber(root, returnFiber, childToDelete);\n hostParent = null;\n hostParentIsContainer = !1;\n root = childToDelete.alternate;\n null !== root && (root.return = null);\n childToDelete.return = null;\n }\n if (parentFiber.subtreeFlags & 13886)\n for (parentFiber = parentFiber.child; null !== parentFiber; )\n commitMutationEffectsOnFiber(parentFiber, root$jscomp$0),\n (parentFiber = parentFiber.sibling);\n}\nvar currentHoistableRoot = null;\nfunction commitMutationEffectsOnFiber(finishedWork, root) {\n var current = finishedWork.alternate,\n flags = finishedWork.flags;\n switch (finishedWork.tag) {\n case 0:\n case 11:\n case 14:\n case 15:\n recursivelyTraverseMutationEffects(root, finishedWork);\n commitReconciliationEffects(finishedWork);\n flags & 4 &&\n (commitHookEffectListUnmount(3, finishedWork, finishedWork.return),\n commitHookEffectListMount(3, finishedWork),\n commitHookEffectListUnmount(5, finishedWork, finishedWork.return));\n break;\n case 1:\n recursivelyTraverseMutationEffects(root, finishedWork);\n commitReconciliationEffects(finishedWork);\n flags & 512 &&\n (offscreenSubtreeWasHidden ||\n null === current ||\n safelyDetachRef(current, current.return));\n flags & 64 &&\n offscreenSubtreeIsHidden &&\n ((finishedWork = finishedWork.updateQueue),\n null !== finishedWork &&\n ((flags = finishedWork.callbacks),\n null !== flags &&\n ((current = finishedWork.shared.hiddenCallbacks),\n (finishedWork.shared.hiddenCallbacks =\n null === current ? flags : current.concat(flags)))));\n break;\n case 26:\n var hoistableRoot = currentHoistableRoot;\n recursivelyTraverseMutationEffects(root, finishedWork);\n commitReconciliationEffects(finishedWork);\n flags & 512 &&\n (offscreenSubtreeWasHidden ||\n null === current ||\n safelyDetachRef(current, current.return));\n if (flags & 4) {\n var currentResource = null !== current ? current.memoizedState : null;\n flags = finishedWork.memoizedState;\n if (null === current)\n if (null === flags)\n if (null === finishedWork.stateNode) {\n a: {\n flags = finishedWork.type;\n current = finishedWork.memoizedProps;\n hoistableRoot = hoistableRoot.ownerDocument || hoistableRoot;\n b: switch (flags) {\n case \"title\":\n currentResource =\n hoistableRoot.getElementsByTagName(\"title\")[0];\n if (\n !currentResource ||\n currentResource[internalHoistableMarker] ||\n currentResource[internalInstanceKey] ||\n \"http://www.w3.org/2000/svg\" ===\n currentResource.namespaceURI ||\n currentResource.hasAttribute(\"itemprop\")\n )\n (currentResource = hoistableRoot.createElement(flags)),\n hoistableRoot.head.insertBefore(\n currentResource,\n hoistableRoot.querySelector(\"head > title\")\n );\n setInitialProperties(currentResource, flags, current);\n currentResource[internalInstanceKey] = finishedWork;\n markNodeAsHoistable(currentResource);\n flags = currentResource;\n break a;\n case \"link\":\n var maybeNodes = getHydratableHoistableCache(\n \"link\",\n \"href\",\n hoistableRoot\n ).get(flags + (current.href || \"\"));\n if (maybeNodes)\n for (var i = 0; i < maybeNodes.length; i++)\n if (\n ((currentResource = maybeNodes[i]),\n currentResource.getAttribute(\"href\") ===\n (null == current.href || \"\" === current.href\n ? null\n : current.href) &&\n currentResource.getAttribute(\"rel\") ===\n (null == current.rel ? null : current.rel) &&\n currentResource.getAttribute(\"title\") ===\n (null == current.title ? null : current.title) &&\n currentResource.getAttribute(\"crossorigin\") ===\n (null == current.crossOrigin\n ? null\n : current.crossOrigin))\n ) {\n maybeNodes.splice(i, 1);\n break b;\n }\n currentResource = hoistableRoot.createElement(flags);\n setInitialProperties(currentResource, flags, current);\n hoistableRoot.head.appendChild(currentResource);\n break;\n case \"meta\":\n if (\n (maybeNodes = getHydratableHoistableCache(\n \"meta\",\n \"content\",\n hoistableRoot\n ).get(flags + (current.content || \"\")))\n )\n for (i = 0; i < maybeNodes.length; i++)\n if (\n ((currentResource = maybeNodes[i]),\n currentResource.getAttribute(\"content\") ===\n (null == current.content\n ? null\n : \"\" + current.content) &&\n currentResource.getAttribute(\"name\") ===\n (null == current.name ? null : current.name) &&\n currentResource.getAttribute(\"property\") ===\n (null == current.property\n ? null\n : current.property) &&\n currentResource.getAttribute(\"http-equiv\") ===\n (null == current.httpEquiv\n ? null\n : current.httpEquiv) &&\n currentResource.getAttribute(\"charset\") ===\n (null == current.charSet\n ? null\n : current.charSet))\n ) {\n maybeNodes.splice(i, 1);\n break b;\n }\n currentResource = hoistableRoot.createElement(flags);\n setInitialProperties(currentResource, flags, current);\n hoistableRoot.head.appendChild(currentResource);\n break;\n default:\n throw Error(formatProdErrorMessage(468, flags));\n }\n currentResource[internalInstanceKey] = finishedWork;\n markNodeAsHoistable(currentResource);\n flags = currentResource;\n }\n finishedWork.stateNode = flags;\n } else\n mountHoistable(\n hoistableRoot,\n finishedWork.type,\n finishedWork.stateNode\n );\n else\n finishedWork.stateNode = acquireResource(\n hoistableRoot,\n flags,\n finishedWork.memoizedProps\n );\n else\n currentResource !== flags\n ? (null === currentResource\n ? null !== current.stateNode &&\n ((current = current.stateNode),\n current.parentNode.removeChild(current))\n : currentResource.count--,\n null === flags\n ? mountHoistable(\n hoistableRoot,\n finishedWork.type,\n finishedWork.stateNode\n )\n : acquireResource(\n hoistableRoot,\n flags,\n finishedWork.memoizedProps\n ))\n : null === flags &&\n null !== finishedWork.stateNode &&\n commitHostUpdate(\n finishedWork,\n finishedWork.memoizedProps,\n current.memoizedProps\n );\n }\n break;\n case 27:\n recursivelyTraverseMutationEffects(root, finishedWork);\n commitReconciliationEffects(finishedWork);\n flags & 512 &&\n (offscreenSubtreeWasHidden ||\n null === current ||\n safelyDetachRef(current, current.return));\n null !== current &&\n flags & 4 &&\n commitHostUpdate(\n finishedWork,\n finishedWork.memoizedProps,\n current.memoizedProps\n );\n break;\n case 5:\n recursivelyTraverseMutationEffects(root, finishedWork);\n commitReconciliationEffects(finishedWork);\n flags & 512 &&\n (offscreenSubtreeWasHidden ||\n null === current ||\n safelyDetachRef(current, current.return));\n if (finishedWork.flags & 32) {\n hoistableRoot = finishedWork.stateNode;\n try {\n setTextContent(hoistableRoot, \"\");\n } catch (error) {\n captureCommitPhaseError(finishedWork, finishedWork.return, error);\n }\n }\n flags & 4 &&\n null != finishedWork.stateNode &&\n ((hoistableRoot = finishedWork.memoizedProps),\n commitHostUpdate(\n finishedWork,\n hoistableRoot,\n null !== current ? current.memoizedProps : hoistableRoot\n ));\n flags & 1024 && (needsFormReset = !0);\n break;\n case 6:\n recursivelyTraverseMutationEffects(root, finishedWork);\n commitReconciliationEffects(finishedWork);\n if (flags & 4) {\n if (null === finishedWork.stateNode)\n throw Error(formatProdErrorMessage(162));\n flags = finishedWork.memoizedProps;\n current = finishedWork.stateNode;\n try {\n current.nodeValue = flags;\n } catch (error) {\n captureCommitPhaseError(finishedWork, finishedWork.return, error);\n }\n }\n break;\n case 3:\n tagCaches = null;\n hoistableRoot = currentHoistableRoot;\n currentHoistableRoot = getHoistableRoot(root.containerInfo);\n recursivelyTraverseMutationEffects(root, finishedWork);\n currentHoistableRoot = hoistableRoot;\n commitReconciliationEffects(finishedWork);\n if (flags & 4 && null !== current && current.memoizedState.isDehydrated)\n try {\n retryIfBlockedOn(root.containerInfo);\n } catch (error) {\n captureCommitPhaseError(finishedWork, finishedWork.return, error);\n }\n needsFormReset &&\n ((needsFormReset = !1), recursivelyResetForms(finishedWork));\n break;\n case 4:\n flags = currentHoistableRoot;\n currentHoistableRoot = getHoistableRoot(\n finishedWork.stateNode.containerInfo\n );\n recursivelyTraverseMutationEffects(root, finishedWork);\n commitReconciliationEffects(finishedWork);\n currentHoistableRoot = flags;\n break;\n case 12:\n recursivelyTraverseMutationEffects(root, finishedWork);\n commitReconciliationEffects(finishedWork);\n break;\n case 31:\n recursivelyTraverseMutationEffects(root, finishedWork);\n commitReconciliationEffects(finishedWork);\n flags & 4 &&\n ((flags = finishedWork.updateQueue),\n null !== flags &&\n ((finishedWork.updateQueue = null),\n attachSuspenseRetryListeners(finishedWork, flags)));\n break;\n case 13:\n recursivelyTraverseMutationEffects(root, finishedWork);\n commitReconciliationEffects(finishedWork);\n finishedWork.child.flags & 8192 &&\n (null !== finishedWork.memoizedState) !==\n (null !== current && null !== current.memoizedState) &&\n (globalMostRecentFallbackTime = now());\n flags & 4 &&\n ((flags = finishedWork.updateQueue),\n null !== flags &&\n ((finishedWork.updateQueue = null),\n attachSuspenseRetryListeners(finishedWork, flags)));\n break;\n case 22:\n hoistableRoot = null !== finishedWork.memoizedState;\n var wasHidden = null !== current && null !== current.memoizedState,\n prevOffscreenSubtreeIsHidden = offscreenSubtreeIsHidden,\n prevOffscreenSubtreeWasHidden = offscreenSubtreeWasHidden;\n offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden || hoistableRoot;\n offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden || wasHidden;\n recursivelyTraverseMutationEffects(root, finishedWork);\n offscreenSubtreeWasHidden = prevOffscreenSubtreeWasHidden;\n offscreenSubtreeIsHidden = prevOffscreenSubtreeIsHidden;\n commitReconciliationEffects(finishedWork);\n if (flags & 8192)\n a: for (\n root = finishedWork.stateNode,\n root._visibility = hoistableRoot\n ? root._visibility & -2\n : root._visibility | 1,\n hoistableRoot &&\n (null === current ||\n wasHidden ||\n offscreenSubtreeIsHidden ||\n offscreenSubtreeWasHidden ||\n recursivelyTraverseDisappearLayoutEffects(finishedWork)),\n current = null,\n root = finishedWork;\n ;\n\n ) {\n if (5 === root.tag || 26 === root.tag) {\n if (null === current) {\n wasHidden = current = root;\n try {\n if (((currentResource = wasHidden.stateNode), hoistableRoot))\n (maybeNodes = currentResource.style),\n \"function\" === typeof maybeNodes.setProperty\n ? maybeNodes.setProperty(\"display\", \"none\", \"important\")\n : (maybeNodes.display = \"none\");\n else {\n i = wasHidden.stateNode;\n var styleProp = wasHidden.memoizedProps.style,\n display =\n void 0 !== styleProp &&\n null !== styleProp &&\n styleProp.hasOwnProperty(\"display\")\n ? styleProp.display\n : null;\n i.style.display =\n null == display || \"boolean\" === typeof display\n ? \"\"\n : (\"\" + display).trim();\n }\n } catch (error) {\n captureCommitPhaseError(wasHidden, wasHidden.return, error);\n }\n }\n } else if (6 === root.tag) {\n if (null === current) {\n wasHidden = root;\n try {\n wasHidden.stateNode.nodeValue = hoistableRoot\n ? \"\"\n : wasHidden.memoizedProps;\n } catch (error) {\n captureCommitPhaseError(wasHidden, wasHidden.return, error);\n }\n }\n } else if (18 === root.tag) {\n if (null === current) {\n wasHidden = root;\n try {\n var instance = wasHidden.stateNode;\n hoistableRoot\n ? hideOrUnhideDehydratedBoundary(instance, !0)\n : hideOrUnhideDehydratedBoundary(wasHidden.stateNode, !1);\n } catch (error) {\n captureCommitPhaseError(wasHidden, wasHidden.return, error);\n }\n }\n } else if (\n ((22 !== root.tag && 23 !== root.tag) ||\n null === root.memoizedState ||\n root === finishedWork) &&\n null !== root.child\n ) {\n root.child.return = root;\n root = root.child;\n continue;\n }\n if (root === finishedWork) break a;\n for (; null === root.sibling; ) {\n if (null === root.return || root.return === finishedWork) break a;\n current === root && (current = null);\n root = root.return;\n }\n current === root && (current = null);\n root.sibling.return = root.return;\n root = root.sibling;\n }\n flags & 4 &&\n ((flags = finishedWork.updateQueue),\n null !== flags &&\n ((current = flags.retryQueue),\n null !== current &&\n ((flags.retryQueue = null),\n attachSuspenseRetryListeners(finishedWork, current))));\n break;\n case 19:\n recursivelyTraverseMutationEffects(root, finishedWork);\n commitReconciliationEffects(finishedWork);\n flags & 4 &&\n ((flags = finishedWork.updateQueue),\n null !== flags &&\n ((finishedWork.updateQueue = null),\n attachSuspenseRetryListeners(finishedWork, flags)));\n break;\n case 30:\n break;\n case 21:\n break;\n default:\n recursivelyTraverseMutationEffects(root, finishedWork),\n commitReconciliationEffects(finishedWork);\n }\n}\nfunction commitReconciliationEffects(finishedWork) {\n var flags = finishedWork.flags;\n if (flags & 2) {\n try {\n for (\n var hostParentFiber, parentFiber = finishedWork.return;\n null !== parentFiber;\n\n ) {\n if (isHostParent(parentFiber)) {\n hostParentFiber = parentFiber;\n break;\n }\n parentFiber = parentFiber.return;\n }\n if (null == hostParentFiber) throw Error(formatProdErrorMessage(160));\n switch (hostParentFiber.tag) {\n case 27:\n var parent = hostParentFiber.stateNode,\n before = getHostSibling(finishedWork);\n insertOrAppendPlacementNode(finishedWork, before, parent);\n break;\n case 5:\n var parent$141 = hostParentFiber.stateNode;\n hostParentFiber.flags & 32 &&\n (setTextContent(parent$141, \"\"), (hostParentFiber.flags &= -33));\n var before$142 = getHostSibling(finishedWork);\n insertOrAppendPlacementNode(finishedWork, before$142, parent$141);\n break;\n case 3:\n case 4:\n var parent$143 = hostParentFiber.stateNode.containerInfo,\n before$144 = getHostSibling(finishedWork);\n insertOrAppendPlacementNodeIntoContainer(\n finishedWork,\n before$144,\n parent$143\n );\n break;\n default:\n throw Error(formatProdErrorMessage(161));\n }\n } catch (error) {\n captureCommitPhaseError(finishedWork, finishedWork.return, error);\n }\n finishedWork.flags &= -3;\n }\n flags & 4096 && (finishedWork.flags &= -4097);\n}\nfunction recursivelyResetForms(parentFiber) {\n if (parentFiber.subtreeFlags & 1024)\n for (parentFiber = parentFiber.child; null !== parentFiber; ) {\n var fiber = parentFiber;\n recursivelyResetForms(fiber);\n 5 === fiber.tag && fiber.flags & 1024 && fiber.stateNode.reset();\n parentFiber = parentFiber.sibling;\n }\n}\nfunction recursivelyTraverseLayoutEffects(root, parentFiber) {\n if (parentFiber.subtreeFlags & 8772)\n for (parentFiber = parentFiber.child; null !== parentFiber; )\n commitLayoutEffectOnFiber(root, parentFiber.alternate, parentFiber),\n (parentFiber = parentFiber.sibling);\n}\nfunction recursivelyTraverseDisappearLayoutEffects(parentFiber) {\n for (parentFiber = parentFiber.child; null !== parentFiber; ) {\n var finishedWork = parentFiber;\n switch (finishedWork.tag) {\n case 0:\n case 11:\n case 14:\n case 15:\n commitHookEffectListUnmount(4, finishedWork, finishedWork.return);\n recursivelyTraverseDisappearLayoutEffects(finishedWork);\n break;\n case 1:\n safelyDetachRef(finishedWork, finishedWork.return);\n var instance = finishedWork.stateNode;\n \"function\" === typeof instance.componentWillUnmount &&\n safelyCallComponentWillUnmount(\n finishedWork,\n finishedWork.return,\n instance\n );\n recursivelyTraverseDisappearLayoutEffects(finishedWork);\n break;\n case 27:\n releaseSingletonInstance(finishedWork.stateNode);\n case 26:\n case 5:\n safelyDetachRef(finishedWork, finishedWork.return);\n recursivelyTraverseDisappearLayoutEffects(finishedWork);\n break;\n case 22:\n null === finishedWork.memoizedState &&\n recursivelyTraverseDisappearLayoutEffects(finishedWork);\n break;\n case 30:\n recursivelyTraverseDisappearLayoutEffects(finishedWork);\n break;\n default:\n recursivelyTraverseDisappearLayoutEffects(finishedWork);\n }\n parentFiber = parentFiber.sibling;\n }\n}\nfunction recursivelyTraverseReappearLayoutEffects(\n finishedRoot$jscomp$0,\n parentFiber,\n includeWorkInProgressEffects\n) {\n includeWorkInProgressEffects =\n includeWorkInProgressEffects && 0 !== (parentFiber.subtreeFlags & 8772);\n for (parentFiber = parentFiber.child; null !== parentFiber; ) {\n var current = parentFiber.alternate,\n finishedRoot = finishedRoot$jscomp$0,\n finishedWork = parentFiber,\n flags = finishedWork.flags;\n switch (finishedWork.tag) {\n case 0:\n case 11:\n case 15:\n recursivelyTraverseReappearLayoutEffects(\n finishedRoot,\n finishedWork,\n includeWorkInProgressEffects\n );\n commitHookEffectListMount(4, finishedWork);\n break;\n case 1:\n recursivelyTraverseReappearLayoutEffects(\n finishedRoot,\n finishedWork,\n includeWorkInProgressEffects\n );\n current = finishedWork;\n finishedRoot = current.stateNode;\n if (\"function\" === typeof finishedRoot.componentDidMount)\n try {\n finishedRoot.componentDidMount();\n } catch (error) {\n captureCommitPhaseError(current, current.return, error);\n }\n current = finishedWork;\n finishedRoot = current.updateQueue;\n if (null !== finishedRoot) {\n var instance = current.stateNode;\n try {\n var hiddenCallbacks = finishedRoot.shared.hiddenCallbacks;\n if (null !== hiddenCallbacks)\n for (\n finishedRoot.shared.hiddenCallbacks = null, finishedRoot = 0;\n finishedRoot < hiddenCallbacks.length;\n finishedRoot++\n )\n callCallback(hiddenCallbacks[finishedRoot], instance);\n } catch (error) {\n captureCommitPhaseError(current, current.return, error);\n }\n }\n includeWorkInProgressEffects &&\n flags & 64 &&\n commitClassCallbacks(finishedWork);\n safelyAttachRef(finishedWork, finishedWork.return);\n break;\n case 27:\n commitHostSingletonAcquisition(finishedWork);\n case 26:\n case 5:\n recursivelyTraverseReappearLayoutEffects(\n finishedRoot,\n finishedWork,\n includeWorkInProgressEffects\n );\n includeWorkInProgressEffects &&\n null === current &&\n flags & 4 &&\n commitHostMount(finishedWork);\n safelyAttachRef(finishedWork, finishedWork.return);\n break;\n case 12:\n recursivelyTraverseReappearLayoutEffects(\n finishedRoot,\n finishedWork,\n includeWorkInProgressEffects\n );\n break;\n case 31:\n recursivelyTraverseReappearLayoutEffects(\n finishedRoot,\n finishedWork,\n includeWorkInProgressEffects\n );\n includeWorkInProgressEffects &&\n flags & 4 &&\n commitActivityHydrationCallbacks(finishedRoot, finishedWork);\n break;\n case 13:\n recursivelyTraverseReappearLayoutEffects(\n finishedRoot,\n finishedWork,\n includeWorkInProgressEffects\n );\n includeWorkInProgressEffects &&\n flags & 4 &&\n commitSuspenseHydrationCallbacks(finishedRoot, finishedWork);\n break;\n case 22:\n null === finishedWork.memoizedState &&\n recursivelyTraverseReappearLayoutEffects(\n finishedRoot,\n finishedWork,\n includeWorkInProgressEffects\n );\n safelyAttachRef(finishedWork, finishedWork.return);\n break;\n case 30:\n break;\n default:\n recursivelyTraverseReappearLayoutEffects(\n finishedRoot,\n finishedWork,\n includeWorkInProgressEffects\n );\n }\n parentFiber = parentFiber.sibling;\n }\n}\nfunction commitOffscreenPassiveMountEffects(current, finishedWork) {\n var previousCache = null;\n null !== current &&\n null !== current.memoizedState &&\n null !== current.memoizedState.cachePool &&\n (previousCache = current.memoizedState.cachePool.pool);\n current = null;\n null !== finishedWork.memoizedState &&\n null !== finishedWork.memoizedState.cachePool &&\n (current = finishedWork.memoizedState.cachePool.pool);\n current !== previousCache &&\n (null != current && current.refCount++,\n null != previousCache && releaseCache(previousCache));\n}\nfunction commitCachePassiveMountEffect(current, finishedWork) {\n current = null;\n null !== finishedWork.alternate &&\n (current = finishedWork.alternate.memoizedState.cache);\n finishedWork = finishedWork.memoizedState.cache;\n finishedWork !== current &&\n (finishedWork.refCount++, null != current && releaseCache(current));\n}\nfunction recursivelyTraversePassiveMountEffects(\n root,\n parentFiber,\n committedLanes,\n committedTransitions\n) {\n if (parentFiber.subtreeFlags & 10256)\n for (parentFiber = parentFiber.child; null !== parentFiber; )\n commitPassiveMountOnFiber(\n root,\n parentFiber,\n committedLanes,\n committedTransitions\n ),\n (parentFiber = parentFiber.sibling);\n}\nfunction commitPassiveMountOnFiber(\n finishedRoot,\n finishedWork,\n committedLanes,\n committedTransitions\n) {\n var flags = finishedWork.flags;\n switch (finishedWork.tag) {\n case 0:\n case 11:\n case 15:\n recursivelyTraversePassiveMountEffects(\n finishedRoot,\n finishedWork,\n committedLanes,\n committedTransitions\n );\n flags & 2048 && commitHookEffectListMount(9, finishedWork);\n break;\n case 1:\n recursivelyTraversePassiveMountEffects(\n finishedRoot,\n finishedWork,\n committedLanes,\n committedTransitions\n );\n break;\n case 3:\n recursivelyTraversePassiveMountEffects(\n finishedRoot,\n finishedWork,\n committedLanes,\n committedTransitions\n );\n flags & 2048 &&\n ((finishedRoot = null),\n null !== finishedWork.alternate &&\n (finishedRoot = finishedWork.alternate.memoizedState.cache),\n (finishedWork = finishedWork.memoizedState.cache),\n finishedWork !== finishedRoot &&\n (finishedWork.refCount++,\n null != finishedRoot && releaseCache(finishedRoot)));\n break;\n case 12:\n if (flags & 2048) {\n recursivelyTraversePassiveMountEffects(\n finishedRoot,\n finishedWork,\n committedLanes,\n committedTransitions\n );\n finishedRoot = finishedWork.stateNode;\n try {\n var _finishedWork$memoize2 = finishedWork.memoizedProps,\n id = _finishedWork$memoize2.id,\n onPostCommit = _finishedWork$memoize2.onPostCommit;\n \"function\" === typeof onPostCommit &&\n onPostCommit(\n id,\n null === finishedWork.alternate ? \"mount\" : \"update\",\n finishedRoot.passiveEffectDuration,\n -0\n );\n } catch (error) {\n captureCommitPhaseError(finishedWork, finishedWork.return, error);\n }\n } else\n recursivelyTraversePassiveMountEffects(\n finishedRoot,\n finishedWork,\n committedLanes,\n committedTransitions\n );\n break;\n case 31:\n recursivelyTraversePassiveMountEffects(\n finishedRoot,\n finishedWork,\n committedLanes,\n committedTransitions\n );\n break;\n case 13:\n recursivelyTraversePassiveMountEffects(\n finishedRoot,\n finishedWork,\n committedLanes,\n committedTransitions\n );\n break;\n case 23:\n break;\n case 22:\n _finishedWork$memoize2 = finishedWork.stateNode;\n id = finishedWork.alternate;\n null !== finishedWork.memoizedState\n ? _finishedWork$memoize2._visibility & 2\n ? recursivelyTraversePassiveMountEffects(\n finishedRoot,\n finishedWork,\n committedLanes,\n committedTransitions\n )\n : recursivelyTraverseAtomicPassiveEffects(finishedRoot, finishedWork)\n : _finishedWork$memoize2._visibility & 2\n ? recursivelyTraversePassiveMountEffects(\n finishedRoot,\n finishedWork,\n committedLanes,\n committedTransitions\n )\n : ((_finishedWork$memoize2._visibility |= 2),\n recursivelyTraverseReconnectPassiveEffects(\n finishedRoot,\n finishedWork,\n committedLanes,\n committedTransitions,\n 0 !== (finishedWork.subtreeFlags & 10256) || !1\n ));\n flags & 2048 && commitOffscreenPassiveMountEffects(id, finishedWork);\n break;\n case 24:\n recursivelyTraversePassiveMountEffects(\n finishedRoot,\n finishedWork,\n committedLanes,\n committedTransitions\n );\n flags & 2048 &&\n commitCachePassiveMountEffect(finishedWork.alternate, finishedWork);\n break;\n default:\n recursivelyTraversePassiveMountEffects(\n finishedRoot,\n finishedWork,\n committedLanes,\n committedTransitions\n );\n }\n}\nfunction recursivelyTraverseReconnectPassiveEffects(\n finishedRoot$jscomp$0,\n parentFiber,\n committedLanes$jscomp$0,\n committedTransitions$jscomp$0,\n includeWorkInProgressEffects\n) {\n includeWorkInProgressEffects =\n includeWorkInProgressEffects &&\n (0 !== (parentFiber.subtreeFlags & 10256) || !1);\n for (parentFiber = parentFiber.child; null !== parentFiber; ) {\n var finishedRoot = finishedRoot$jscomp$0,\n finishedWork = parentFiber,\n committedLanes = committedLanes$jscomp$0,\n committedTransitions = committedTransitions$jscomp$0,\n flags = finishedWork.flags;\n switch (finishedWork.tag) {\n case 0:\n case 11:\n case 15:\n recursivelyTraverseReconnectPassiveEffects(\n finishedRoot,\n finishedWork,\n committedLanes,\n committedTransitions,\n includeWorkInProgressEffects\n );\n commitHookEffectListMount(8, finishedWork);\n break;\n case 23:\n break;\n case 22:\n var instance = finishedWork.stateNode;\n null !== finishedWork.memoizedState\n ? instance._visibility & 2\n ? recursivelyTraverseReconnectPassiveEffects(\n finishedRoot,\n finishedWork,\n committedLanes,\n committedTransitions,\n includeWorkInProgressEffects\n )\n : recursivelyTraverseAtomicPassiveEffects(\n finishedRoot,\n finishedWork\n )\n : ((instance._visibility |= 2),\n recursivelyTraverseReconnectPassiveEffects(\n finishedRoot,\n finishedWork,\n committedLanes,\n committedTransitions,\n includeWorkInProgressEffects\n ));\n includeWorkInProgressEffects &&\n flags & 2048 &&\n commitOffscreenPassiveMountEffects(\n finishedWork.alternate,\n finishedWork\n );\n break;\n case 24:\n recursivelyTraverseReconnectPassiveEffects(\n finishedRoot,\n finishedWork,\n committedLanes,\n committedTransitions,\n includeWorkInProgressEffects\n );\n includeWorkInProgressEffects &&\n flags & 2048 &&\n commitCachePassiveMountEffect(finishedWork.alternate, finishedWork);\n break;\n default:\n recursivelyTraverseReconnectPassiveEffects(\n finishedRoot,\n finishedWork,\n committedLanes,\n committedTransitions,\n includeWorkInProgressEffects\n );\n }\n parentFiber = parentFiber.sibling;\n }\n}\nfunction recursivelyTraverseAtomicPassiveEffects(\n finishedRoot$jscomp$0,\n parentFiber\n) {\n if (parentFiber.subtreeFlags & 10256)\n for (parentFiber = parentFiber.child; null !== parentFiber; ) {\n var finishedRoot = finishedRoot$jscomp$0,\n finishedWork = parentFiber,\n flags = finishedWork.flags;\n switch (finishedWork.tag) {\n case 22:\n recursivelyTraverseAtomicPassiveEffects(finishedRoot, finishedWork);\n flags & 2048 &&\n commitOffscreenPassiveMountEffects(\n finishedWork.alternate,\n finishedWork\n );\n break;\n case 24:\n recursivelyTraverseAtomicPassiveEffects(finishedRoot, finishedWork);\n flags & 2048 &&\n commitCachePassiveMountEffect(finishedWork.alternate, finishedWork);\n break;\n default:\n recursivelyTraverseAtomicPassiveEffects(finishedRoot, finishedWork);\n }\n parentFiber = parentFiber.sibling;\n }\n}\nvar suspenseyCommitFlag = 8192;\nfunction recursivelyAccumulateSuspenseyCommit(\n parentFiber,\n committedLanes,\n suspendedState\n) {\n if (parentFiber.subtreeFlags & suspenseyCommitFlag)\n for (parentFiber = parentFiber.child; null !== parentFiber; )\n accumulateSuspenseyCommitOnFiber(\n parentFiber,\n committedLanes,\n suspendedState\n ),\n (parentFiber = parentFiber.sibling);\n}\nfunction accumulateSuspenseyCommitOnFiber(\n fiber,\n committedLanes,\n suspendedState\n) {\n switch (fiber.tag) {\n case 26:\n recursivelyAccumulateSuspenseyCommit(\n fiber,\n committedLanes,\n suspendedState\n );\n fiber.flags & suspenseyCommitFlag &&\n null !== fiber.memoizedState &&\n suspendResource(\n suspendedState,\n currentHoistableRoot,\n fiber.memoizedState,\n fiber.memoizedProps\n );\n break;\n case 5:\n recursivelyAccumulateSuspenseyCommit(\n fiber,\n committedLanes,\n suspendedState\n );\n break;\n case 3:\n case 4:\n var previousHoistableRoot = currentHoistableRoot;\n currentHoistableRoot = getHoistableRoot(fiber.stateNode.containerInfo);\n recursivelyAccumulateSuspenseyCommit(\n fiber,\n committedLanes,\n suspendedState\n );\n currentHoistableRoot = previousHoistableRoot;\n break;\n case 22:\n null === fiber.memoizedState &&\n ((previousHoistableRoot = fiber.alternate),\n null !== previousHoistableRoot &&\n null !== previousHoistableRoot.memoizedState\n ? ((previousHoistableRoot = suspenseyCommitFlag),\n (suspenseyCommitFlag = 16777216),\n recursivelyAccumulateSuspenseyCommit(\n fiber,\n committedLanes,\n suspendedState\n ),\n (suspenseyCommitFlag = previousHoistableRoot))\n : recursivelyAccumulateSuspenseyCommit(\n fiber,\n committedLanes,\n suspendedState\n ));\n break;\n default:\n recursivelyAccumulateSuspenseyCommit(\n fiber,\n committedLanes,\n suspendedState\n );\n }\n}\nfunction detachAlternateSiblings(parentFiber) {\n var previousFiber = parentFiber.alternate;\n if (\n null !== previousFiber &&\n ((parentFiber = previousFiber.child), null !== parentFiber)\n ) {\n previousFiber.child = null;\n do\n (previousFiber = parentFiber.sibling),\n (parentFiber.sibling = null),\n (parentFiber = previousFiber);\n while (null !== parentFiber);\n }\n}\nfunction recursivelyTraversePassiveUnmountEffects(parentFiber) {\n var deletions = parentFiber.deletions;\n if (0 !== (parentFiber.flags & 16)) {\n if (null !== deletions)\n for (var i = 0; i < deletions.length; i++) {\n var childToDelete = deletions[i];\n nextEffect = childToDelete;\n commitPassiveUnmountEffectsInsideOfDeletedTree_begin(\n childToDelete,\n parentFiber\n );\n }\n detachAlternateSiblings(parentFiber);\n }\n if (parentFiber.subtreeFlags & 10256)\n for (parentFiber = parentFiber.child; null !== parentFiber; )\n commitPassiveUnmountOnFiber(parentFiber),\n (parentFiber = parentFiber.sibling);\n}\nfunction commitPassiveUnmountOnFiber(finishedWork) {\n switch (finishedWork.tag) {\n case 0:\n case 11:\n case 15:\n recursivelyTraversePassiveUnmountEffects(finishedWork);\n finishedWork.flags & 2048 &&\n commitHookEffectListUnmount(9, finishedWork, finishedWork.return);\n break;\n case 3:\n recursivelyTraversePassiveUnmountEffects(finishedWork);\n break;\n case 12:\n recursivelyTraversePassiveUnmountEffects(finishedWork);\n break;\n case 22:\n var instance = finishedWork.stateNode;\n null !== finishedWork.memoizedState &&\n instance._visibility & 2 &&\n (null === finishedWork.return || 13 !== finishedWork.return.tag)\n ? ((instance._visibility &= -3),\n recursivelyTraverseDisconnectPassiveEffects(finishedWork))\n : recursivelyTraversePassiveUnmountEffects(finishedWork);\n break;\n default:\n recursivelyTraversePassiveUnmountEffects(finishedWork);\n }\n}\nfunction recursivelyTraverseDisconnectPassiveEffects(parentFiber) {\n var deletions = parentFiber.deletions;\n if (0 !== (parentFiber.flags & 16)) {\n if (null !== deletions)\n for (var i = 0; i < deletions.length; i++) {\n var childToDelete = deletions[i];\n nextEffect = childToDelete;\n commitPassiveUnmountEffectsInsideOfDeletedTree_begin(\n childToDelete,\n parentFiber\n );\n }\n detachAlternateSiblings(parentFiber);\n }\n for (parentFiber = parentFiber.child; null !== parentFiber; ) {\n deletions = parentFiber;\n switch (deletions.tag) {\n case 0:\n case 11:\n case 15:\n commitHookEffectListUnmount(8, deletions, deletions.return);\n recursivelyTraverseDisconnectPassiveEffects(deletions);\n break;\n case 22:\n i = deletions.stateNode;\n i._visibility & 2 &&\n ((i._visibility &= -3),\n recursivelyTraverseDisconnectPassiveEffects(deletions));\n break;\n default:\n recursivelyTraverseDisconnectPassiveEffects(deletions);\n }\n parentFiber = parentFiber.sibling;\n }\n}\nfunction commitPassiveUnmountEffectsInsideOfDeletedTree_begin(\n deletedSubtreeRoot,\n nearestMountedAncestor\n) {\n for (; null !== nextEffect; ) {\n var fiber = nextEffect;\n switch (fiber.tag) {\n case 0:\n case 11:\n case 15:\n commitHookEffectListUnmount(8, fiber, nearestMountedAncestor);\n break;\n case 23:\n case 22:\n if (\n null !== fiber.memoizedState &&\n null !== fiber.memoizedState.cachePool\n ) {\n var cache = fiber.memoizedState.cachePool.pool;\n null != cache && cache.refCount++;\n }\n break;\n case 24:\n releaseCache(fiber.memoizedState.cache);\n }\n cache = fiber.child;\n if (null !== cache) (cache.return = fiber), (nextEffect = cache);\n else\n a: for (fiber = deletedSubtreeRoot; null !== nextEffect; ) {\n cache = nextEffect;\n var sibling = cache.sibling,\n returnFiber = cache.return;\n detachFiberAfterEffects(cache);\n if (cache === fiber) {\n nextEffect = null;\n break a;\n }\n if (null !== sibling) {\n sibling.return = returnFiber;\n nextEffect = sibling;\n break a;\n }\n nextEffect = returnFiber;\n }\n }\n}\nvar DefaultAsyncDispatcher = {\n getCacheForType: function (resourceType) {\n var cache = readContext(CacheContext),\n cacheForType = cache.data.get(resourceType);\n void 0 === cacheForType &&\n ((cacheForType = resourceType()),\n cache.data.set(resourceType, cacheForType));\n return cacheForType;\n },\n cacheSignal: function () {\n return readContext(CacheContext).controller.signal;\n }\n },\n PossiblyWeakMap = \"function\" === typeof WeakMap ? WeakMap : Map,\n executionContext = 0,\n workInProgressRoot = null,\n workInProgress = null,\n workInProgressRootRenderLanes = 0,\n workInProgressSuspendedReason = 0,\n workInProgressThrownValue = null,\n workInProgressRootDidSkipSuspendedSiblings = !1,\n workInProgressRootIsPrerendering = !1,\n workInProgressRootDidAttachPingListener = !1,\n entangledRenderLanes = 0,\n workInProgressRootExitStatus = 0,\n workInProgressRootSkippedLanes = 0,\n workInProgressRootInterleavedUpdatedLanes = 0,\n workInProgressRootPingedLanes = 0,\n workInProgressDeferredLane = 0,\n workInProgressSuspendedRetryLanes = 0,\n workInProgressRootConcurrentErrors = null,\n workInProgressRootRecoverableErrors = null,\n workInProgressRootDidIncludeRecursiveRenderUpdate = !1,\n globalMostRecentFallbackTime = 0,\n globalMostRecentTransitionTime = 0,\n workInProgressRootRenderTargetTime = Infinity,\n workInProgressTransitions = null,\n legacyErrorBoundariesThatAlreadyFailed = null,\n pendingEffectsStatus = 0,\n pendingEffectsRoot = null,\n pendingFinishedWork = null,\n pendingEffectsLanes = 0,\n pendingEffectsRemainingLanes = 0,\n pendingPassiveTransitions = null,\n pendingRecoverableErrors = null,\n nestedUpdateCount = 0,\n rootWithNestedUpdates = null;\nfunction requestUpdateLane() {\n return 0 !== (executionContext & 2) && 0 !== workInProgressRootRenderLanes\n ? workInProgressRootRenderLanes & -workInProgressRootRenderLanes\n : null !== ReactSharedInternals.T\n ? requestTransitionLane()\n : resolveUpdatePriority();\n}\nfunction requestDeferredLane() {\n if (0 === workInProgressDeferredLane)\n if (0 === (workInProgressRootRenderLanes & 536870912) || isHydrating) {\n var lane = nextTransitionDeferredLane;\n nextTransitionDeferredLane <<= 1;\n 0 === (nextTransitionDeferredLane & 3932160) &&\n (nextTransitionDeferredLane = 262144);\n workInProgressDeferredLane = lane;\n } else workInProgressDeferredLane = 536870912;\n lane = suspenseHandlerStackCursor.current;\n null !== lane && (lane.flags |= 32);\n return workInProgressDeferredLane;\n}\nfunction scheduleUpdateOnFiber(root, fiber, lane) {\n if (\n (root === workInProgressRoot &&\n (2 === workInProgressSuspendedReason ||\n 9 === workInProgressSuspendedReason)) ||\n null !== root.cancelPendingCommit\n )\n prepareFreshStack(root, 0),\n markRootSuspended(\n root,\n workInProgressRootRenderLanes,\n workInProgressDeferredLane,\n !1\n );\n markRootUpdated$1(root, lane);\n if (0 === (executionContext & 2) || root !== workInProgressRoot)\n root === workInProgressRoot &&\n (0 === (executionContext & 2) &&\n (workInProgressRootInterleavedUpdatedLanes |= lane),\n 4 === workInProgressRootExitStatus &&\n markRootSuspended(\n root,\n workInProgressRootRenderLanes,\n workInProgressDeferredLane,\n !1\n )),\n ensureRootIsScheduled(root);\n}\nfunction performWorkOnRoot(root$jscomp$0, lanes, forceSync) {\n if (0 !== (executionContext & 6)) throw Error(formatProdErrorMessage(327));\n var shouldTimeSlice =\n (!forceSync &&\n 0 === (lanes & 127) &&\n 0 === (lanes & root$jscomp$0.expiredLanes)) ||\n checkIfRootIsPrerendering(root$jscomp$0, lanes),\n exitStatus = shouldTimeSlice\n ? renderRootConcurrent(root$jscomp$0, lanes)\n : renderRootSync(root$jscomp$0, lanes, !0),\n renderWasConcurrent = shouldTimeSlice;\n do {\n if (0 === exitStatus) {\n workInProgressRootIsPrerendering &&\n !shouldTimeSlice &&\n markRootSuspended(root$jscomp$0, lanes, 0, !1);\n break;\n } else {\n forceSync = root$jscomp$0.current.alternate;\n if (\n renderWasConcurrent &&\n !isRenderConsistentWithExternalStores(forceSync)\n ) {\n exitStatus = renderRootSync(root$jscomp$0, lanes, !1);\n renderWasConcurrent = !1;\n continue;\n }\n if (2 === exitStatus) {\n renderWasConcurrent = lanes;\n if (root$jscomp$0.errorRecoveryDisabledLanes & renderWasConcurrent)\n var JSCompiler_inline_result = 0;\n else\n (JSCompiler_inline_result = root$jscomp$0.pendingLanes & -536870913),\n (JSCompiler_inline_result =\n 0 !== JSCompiler_inline_result\n ? JSCompiler_inline_result\n : JSCompiler_inline_result & 536870912\n ? 536870912\n : 0);\n if (0 !== JSCompiler_inline_result) {\n lanes = JSCompiler_inline_result;\n a: {\n var root = root$jscomp$0;\n exitStatus = workInProgressRootConcurrentErrors;\n var wasRootDehydrated = root.current.memoizedState.isDehydrated;\n wasRootDehydrated &&\n (prepareFreshStack(root, JSCompiler_inline_result).flags |= 256);\n JSCompiler_inline_result = renderRootSync(\n root,\n JSCompiler_inline_result,\n !1\n );\n if (2 !== JSCompiler_inline_result) {\n if (\n workInProgressRootDidAttachPingListener &&\n !wasRootDehydrated\n ) {\n root.errorRecoveryDisabledLanes |= renderWasConcurrent;\n workInProgressRootInterleavedUpdatedLanes |=\n renderWasConcurrent;\n exitStatus = 4;\n break a;\n }\n renderWasConcurrent = workInProgressRootRecoverableErrors;\n workInProgressRootRecoverableErrors = exitStatus;\n null !== renderWasConcurrent &&\n (null === workInProgressRootRecoverableErrors\n ? (workInProgressRootRecoverableErrors = renderWasConcurrent)\n : workInProgressRootRecoverableErrors.push.apply(\n workInProgressRootRecoverableErrors,\n renderWasConcurrent\n ));\n }\n exitStatus = JSCompiler_inline_result;\n }\n renderWasConcurrent = !1;\n if (2 !== exitStatus) continue;\n }\n }\n if (1 === exitStatus) {\n prepareFreshStack(root$jscomp$0, 0);\n markRootSuspended(root$jscomp$0, lanes, 0, !0);\n break;\n }\n a: {\n shouldTimeSlice = root$jscomp$0;\n renderWasConcurrent = exitStatus;\n switch (renderWasConcurrent) {\n case 0:\n case 1:\n throw Error(formatProdErrorMessage(345));\n case 4:\n if ((lanes & 4194048) !== lanes) break;\n case 6:\n markRootSuspended(\n shouldTimeSlice,\n lanes,\n workInProgressDeferredLane,\n !workInProgressRootDidSkipSuspendedSiblings\n );\n break a;\n case 2:\n workInProgressRootRecoverableErrors = null;\n break;\n case 3:\n case 5:\n break;\n default:\n throw Error(formatProdErrorMessage(329));\n }\n if (\n (lanes & 62914560) === lanes &&\n ((exitStatus = globalMostRecentFallbackTime + 300 - now()),\n 10 < exitStatus)\n ) {\n markRootSuspended(\n shouldTimeSlice,\n lanes,\n workInProgressDeferredLane,\n !workInProgressRootDidSkipSuspendedSiblings\n );\n if (0 !== getNextLanes(shouldTimeSlice, 0, !0)) break a;\n pendingEffectsLanes = lanes;\n shouldTimeSlice.timeoutHandle = scheduleTimeout(\n commitRootWhenReady.bind(\n null,\n shouldTimeSlice,\n forceSync,\n workInProgressRootRecoverableErrors,\n workInProgressTransitions,\n workInProgressRootDidIncludeRecursiveRenderUpdate,\n lanes,\n workInProgressDeferredLane,\n workInProgressRootInterleavedUpdatedLanes,\n workInProgressSuspendedRetryLanes,\n workInProgressRootDidSkipSuspendedSiblings,\n renderWasConcurrent,\n \"Throttled\",\n -0,\n 0\n ),\n exitStatus\n );\n break a;\n }\n commitRootWhenReady(\n shouldTimeSlice,\n forceSync,\n workInProgressRootRecoverableErrors,\n workInProgressTransitions,\n workInProgressRootDidIncludeRecursiveRenderUpdate,\n lanes,\n workInProgressDeferredLane,\n workInProgressRootInterleavedUpdatedLanes,\n workInProgressSuspendedRetryLanes,\n workInProgressRootDidSkipSuspendedSiblings,\n renderWasConcurrent,\n null,\n -0,\n 0\n );\n }\n }\n break;\n } while (1);\n ensureRootIsScheduled(root$jscomp$0);\n}\nfunction commitRootWhenReady(\n root,\n finishedWork,\n recoverableErrors,\n transitions,\n didIncludeRenderPhaseUpdate,\n lanes,\n spawnedLane,\n updatedLanes,\n suspendedRetryLanes,\n didSkipSuspendedSiblings,\n exitStatus,\n suspendedCommitReason,\n completedRenderStartTime,\n completedRenderEndTime\n) {\n root.timeoutHandle = -1;\n suspendedCommitReason = finishedWork.subtreeFlags;\n if (\n suspendedCommitReason & 8192 ||\n 16785408 === (suspendedCommitReason & 16785408)\n ) {\n suspendedCommitReason = {\n stylesheets: null,\n count: 0,\n imgCount: 0,\n imgBytes: 0,\n suspenseyImages: [],\n waitingForImages: !0,\n waitingForViewTransition: !1,\n unsuspend: noop$1\n };\n accumulateSuspenseyCommitOnFiber(\n finishedWork,\n lanes,\n suspendedCommitReason\n );\n var timeoutOffset =\n (lanes & 62914560) === lanes\n ? globalMostRecentFallbackTime - now()\n : (lanes & 4194048) === lanes\n ? globalMostRecentTransitionTime - now()\n : 0;\n timeoutOffset = waitForCommitToBeReady(\n suspendedCommitReason,\n timeoutOffset\n );\n if (null !== timeoutOffset) {\n pendingEffectsLanes = lanes;\n root.cancelPendingCommit = timeoutOffset(\n commitRoot.bind(\n null,\n root,\n finishedWork,\n lanes,\n recoverableErrors,\n transitions,\n didIncludeRenderPhaseUpdate,\n spawnedLane,\n updatedLanes,\n suspendedRetryLanes,\n exitStatus,\n suspendedCommitReason,\n null,\n completedRenderStartTime,\n completedRenderEndTime\n )\n );\n markRootSuspended(root, lanes, spawnedLane, !didSkipSuspendedSiblings);\n return;\n }\n }\n commitRoot(\n root,\n finishedWork,\n lanes,\n recoverableErrors,\n transitions,\n didIncludeRenderPhaseUpdate,\n spawnedLane,\n updatedLanes,\n suspendedRetryLanes\n );\n}\nfunction isRenderConsistentWithExternalStores(finishedWork) {\n for (var node = finishedWork; ; ) {\n var tag = node.tag;\n if (\n (0 === tag || 11 === tag || 15 === tag) &&\n node.flags & 16384 &&\n ((tag = node.updateQueue),\n null !== tag && ((tag = tag.stores), null !== tag))\n )\n for (var i = 0; i < tag.length; i++) {\n var check = tag[i],\n getSnapshot = check.getSnapshot;\n check = check.value;\n try {\n if (!objectIs(getSnapshot(), check)) return !1;\n } catch (error) {\n return !1;\n }\n }\n tag = node.child;\n if (node.subtreeFlags & 16384 && null !== tag)\n (tag.return = node), (node = tag);\n else {\n if (node === finishedWork) break;\n for (; null === node.sibling; ) {\n if (null === node.return || node.return === finishedWork) return !0;\n node = node.return;\n }\n node.sibling.return = node.return;\n node = node.sibling;\n }\n }\n return !0;\n}\nfunction markRootSuspended(\n root,\n suspendedLanes,\n spawnedLane,\n didAttemptEntireTree\n) {\n suspendedLanes &= ~workInProgressRootPingedLanes;\n suspendedLanes &= ~workInProgressRootInterleavedUpdatedLanes;\n root.suspendedLanes |= suspendedLanes;\n root.pingedLanes &= ~suspendedLanes;\n didAttemptEntireTree && (root.warmLanes |= suspendedLanes);\n didAttemptEntireTree = root.expirationTimes;\n for (var lanes = suspendedLanes; 0 < lanes; ) {\n var index$6 = 31 - clz32(lanes),\n lane = 1 << index$6;\n didAttemptEntireTree[index$6] = -1;\n lanes &= ~lane;\n }\n 0 !== spawnedLane &&\n markSpawnedDeferredLane(root, spawnedLane, suspendedLanes);\n}\nfunction flushSyncWork$1() {\n return 0 === (executionContext & 6)\n ? (flushSyncWorkAcrossRoots_impl(0, !1), !1)\n : !0;\n}\nfunction resetWorkInProgressStack() {\n if (null !== workInProgress) {\n if (0 === workInProgressSuspendedReason)\n var interruptedWork = workInProgress.return;\n else\n (interruptedWork = workInProgress),\n (lastContextDependency = currentlyRenderingFiber$1 = null),\n resetHooksOnUnwind(interruptedWork),\n (thenableState$1 = null),\n (thenableIndexCounter$1 = 0),\n (interruptedWork = workInProgress);\n for (; null !== interruptedWork; )\n unwindInterruptedWork(interruptedWork.alternate, interruptedWork),\n (interruptedWork = interruptedWork.return);\n workInProgress = null;\n }\n}\nfunction prepareFreshStack(root, lanes) {\n var timeoutHandle = root.timeoutHandle;\n -1 !== timeoutHandle &&\n ((root.timeoutHandle = -1), cancelTimeout(timeoutHandle));\n timeoutHandle = root.cancelPendingCommit;\n null !== timeoutHandle &&\n ((root.cancelPendingCommit = null), timeoutHandle());\n pendingEffectsLanes = 0;\n resetWorkInProgressStack();\n workInProgressRoot = root;\n workInProgress = timeoutHandle = createWorkInProgress(root.current, null);\n workInProgressRootRenderLanes = lanes;\n workInProgressSuspendedReason = 0;\n workInProgressThrownValue = null;\n workInProgressRootDidSkipSuspendedSiblings = !1;\n workInProgressRootIsPrerendering = checkIfRootIsPrerendering(root, lanes);\n workInProgressRootDidAttachPingListener = !1;\n workInProgressSuspendedRetryLanes =\n workInProgressDeferredLane =\n workInProgressRootPingedLanes =\n workInProgressRootInterleavedUpdatedLanes =\n workInProgressRootSkippedLanes =\n workInProgressRootExitStatus =\n 0;\n workInProgressRootRecoverableErrors = workInProgressRootConcurrentErrors =\n null;\n workInProgressRootDidIncludeRecursiveRenderUpdate = !1;\n 0 !== (lanes & 8) && (lanes |= lanes & 32);\n var allEntangledLanes = root.entangledLanes;\n if (0 !== allEntangledLanes)\n for (\n root = root.entanglements, allEntangledLanes &= lanes;\n 0 < allEntangledLanes;\n\n ) {\n var index$4 = 31 - clz32(allEntangledLanes),\n lane = 1 << index$4;\n lanes |= root[index$4];\n allEntangledLanes &= ~lane;\n }\n entangledRenderLanes = lanes;\n finishQueueingConcurrentUpdates();\n return timeoutHandle;\n}\nfunction handleThrow(root, thrownValue) {\n currentlyRenderingFiber = null;\n ReactSharedInternals.H = ContextOnlyDispatcher;\n thrownValue === SuspenseException || thrownValue === SuspenseActionException\n ? ((thrownValue = getSuspendedThenable()),\n (workInProgressSuspendedReason = 3))\n : thrownValue === SuspenseyCommitException\n ? ((thrownValue = getSuspendedThenable()),\n (workInProgressSuspendedReason = 4))\n : (workInProgressSuspendedReason =\n thrownValue === SelectiveHydrationException\n ? 8\n : null !== thrownValue &&\n \"object\" === typeof thrownValue &&\n \"function\" === typeof thrownValue.then\n ? 6\n : 1);\n workInProgressThrownValue = thrownValue;\n null === workInProgress &&\n ((workInProgressRootExitStatus = 1),\n logUncaughtError(\n root,\n createCapturedValueAtFiber(thrownValue, root.current)\n ));\n}\nfunction shouldRemainOnPreviousScreen() {\n var handler = suspenseHandlerStackCursor.current;\n return null === handler\n ? !0\n : (workInProgressRootRenderLanes & 4194048) ===\n workInProgressRootRenderLanes\n ? null === shellBoundary\n ? !0\n : !1\n : (workInProgressRootRenderLanes & 62914560) ===\n workInProgressRootRenderLanes ||\n 0 !== (workInProgressRootRenderLanes & 536870912)\n ? handler === shellBoundary\n : !1;\n}\nfunction pushDispatcher() {\n var prevDispatcher = ReactSharedInternals.H;\n ReactSharedInternals.H = ContextOnlyDispatcher;\n return null === prevDispatcher ? ContextOnlyDispatcher : prevDispatcher;\n}\nfunction pushAsyncDispatcher() {\n var prevAsyncDispatcher = ReactSharedInternals.A;\n ReactSharedInternals.A = DefaultAsyncDispatcher;\n return prevAsyncDispatcher;\n}\nfunction renderDidSuspendDelayIfPossible() {\n workInProgressRootExitStatus = 4;\n workInProgressRootDidSkipSuspendedSiblings ||\n ((workInProgressRootRenderLanes & 4194048) !==\n workInProgressRootRenderLanes &&\n null !== suspenseHandlerStackCursor.current) ||\n (workInProgressRootIsPrerendering = !0);\n (0 === (workInProgressRootSkippedLanes & 134217727) &&\n 0 === (workInProgressRootInterleavedUpdatedLanes & 134217727)) ||\n null === workInProgressRoot ||\n markRootSuspended(\n workInProgressRoot,\n workInProgressRootRenderLanes,\n workInProgressDeferredLane,\n !1\n );\n}\nfunction renderRootSync(root, lanes, shouldYieldForPrerendering) {\n var prevExecutionContext = executionContext;\n executionContext |= 2;\n var prevDispatcher = pushDispatcher(),\n prevAsyncDispatcher = pushAsyncDispatcher();\n if (workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes)\n (workInProgressTransitions = null), prepareFreshStack(root, lanes);\n lanes = !1;\n var exitStatus = workInProgressRootExitStatus;\n a: do\n try {\n if (0 !== workInProgressSuspendedReason && null !== workInProgress) {\n var unitOfWork = workInProgress,\n thrownValue = workInProgressThrownValue;\n switch (workInProgressSuspendedReason) {\n case 8:\n resetWorkInProgressStack();\n exitStatus = 6;\n break a;\n case 3:\n case 2:\n case 9:\n case 6:\n null === suspenseHandlerStackCursor.current && (lanes = !0);\n var reason = workInProgressSuspendedReason;\n workInProgressSuspendedReason = 0;\n workInProgressThrownValue = null;\n throwAndUnwindWorkLoop(root, unitOfWork, thrownValue, reason);\n if (\n shouldYieldForPrerendering &&\n workInProgressRootIsPrerendering\n ) {\n exitStatus = 0;\n break a;\n }\n break;\n default:\n (reason = workInProgressSuspendedReason),\n (workInProgressSuspendedReason = 0),\n (workInProgressThrownValue = null),\n throwAndUnwindWorkLoop(root, unitOfWork, thrownValue, reason);\n }\n }\n workLoopSync();\n exitStatus = workInProgressRootExitStatus;\n break;\n } catch (thrownValue$165) {\n handleThrow(root, thrownValue$165);\n }\n while (1);\n lanes && root.shellSuspendCounter++;\n lastContextDependency = currentlyRenderingFiber$1 = null;\n executionContext = prevExecutionContext;\n ReactSharedInternals.H = prevDispatcher;\n ReactSharedInternals.A = prevAsyncDispatcher;\n null === workInProgress &&\n ((workInProgressRoot = null),\n (workInProgressRootRenderLanes = 0),\n finishQueueingConcurrentUpdates());\n return exitStatus;\n}\nfunction workLoopSync() {\n for (; null !== workInProgress; ) performUnitOfWork(workInProgress);\n}\nfunction renderRootConcurrent(root, lanes) {\n var prevExecutionContext = executionContext;\n executionContext |= 2;\n var prevDispatcher = pushDispatcher(),\n prevAsyncDispatcher = pushAsyncDispatcher();\n workInProgressRoot !== root || workInProgressRootRenderLanes !== lanes\n ? ((workInProgressTransitions = null),\n (workInProgressRootRenderTargetTime = now() + 500),\n prepareFreshStack(root, lanes))\n : (workInProgressRootIsPrerendering = checkIfRootIsPrerendering(\n root,\n lanes\n ));\n a: do\n try {\n if (0 !== workInProgressSuspendedReason && null !== workInProgress) {\n lanes = workInProgress;\n var thrownValue = workInProgressThrownValue;\n b: switch (workInProgressSuspendedReason) {\n case 1:\n workInProgressSuspendedReason = 0;\n workInProgressThrownValue = null;\n throwAndUnwindWorkLoop(root, lanes, thrownValue, 1);\n break;\n case 2:\n case 9:\n if (isThenableResolved(thrownValue)) {\n workInProgressSuspendedReason = 0;\n workInProgressThrownValue = null;\n replaySuspendedUnitOfWork(lanes);\n break;\n }\n lanes = function () {\n (2 !== workInProgressSuspendedReason &&\n 9 !== workInProgressSuspendedReason) ||\n workInProgressRoot !== root ||\n (workInProgressSuspendedReason = 7);\n ensureRootIsScheduled(root);\n };\n thrownValue.then(lanes, lanes);\n break a;\n case 3:\n workInProgressSuspendedReason = 7;\n break a;\n case 4:\n workInProgressSuspendedReason = 5;\n break a;\n case 7:\n isThenableResolved(thrownValue)\n ? ((workInProgressSuspendedReason = 0),\n (workInProgressThrownValue = null),\n replaySuspendedUnitOfWork(lanes))\n : ((workInProgressSuspendedReason = 0),\n (workInProgressThrownValue = null),\n throwAndUnwindWorkLoop(root, lanes, thrownValue, 7));\n break;\n case 5:\n var resource = null;\n switch (workInProgress.tag) {\n case 26:\n resource = workInProgress.memoizedState;\n case 5:\n case 27:\n var hostFiber = workInProgress;\n if (\n resource\n ? preloadResource(resource)\n : hostFiber.stateNode.complete\n ) {\n workInProgressSuspendedReason = 0;\n workInProgressThrownValue = null;\n var sibling = hostFiber.sibling;\n if (null !== sibling) workInProgress = sibling;\n else {\n var returnFiber = hostFiber.return;\n null !== returnFiber\n ? ((workInProgress = returnFiber),\n completeUnitOfWork(returnFiber))\n : (workInProgress = null);\n }\n break b;\n }\n }\n workInProgressSuspendedReason = 0;\n workInProgressThrownValue = null;\n throwAndUnwindWorkLoop(root, lanes, thrownValue, 5);\n break;\n case 6:\n workInProgressSuspendedReason = 0;\n workInProgressThrownValue = null;\n throwAndUnwindWorkLoop(root, lanes, thrownValue, 6);\n break;\n case 8:\n resetWorkInProgressStack();\n workInProgressRootExitStatus = 6;\n break a;\n default:\n throw Error(formatProdErrorMessage(462));\n }\n }\n workLoopConcurrentByScheduler();\n break;\n } catch (thrownValue$167) {\n handleThrow(root, thrownValue$167);\n }\n while (1);\n lastContextDependency = currentlyRenderingFiber$1 = null;\n ReactSharedInternals.H = prevDispatcher;\n ReactSharedInternals.A = prevAsyncDispatcher;\n executionContext = prevExecutionContext;\n if (null !== workInProgress) return 0;\n workInProgressRoot = null;\n workInProgressRootRenderLanes = 0;\n finishQueueingConcurrentUpdates();\n return workInProgressRootExitStatus;\n}\nfunction workLoopConcurrentByScheduler() {\n for (; null !== workInProgress && !shouldYield(); )\n performUnitOfWork(workInProgress);\n}\nfunction performUnitOfWork(unitOfWork) {\n var next = beginWork(unitOfWork.alternate, unitOfWork, entangledRenderLanes);\n unitOfWork.memoizedProps = unitOfWork.pendingProps;\n null === next ? completeUnitOfWork(unitOfWork) : (workInProgress = next);\n}\nfunction replaySuspendedUnitOfWork(unitOfWork) {\n var next = unitOfWork;\n var current = next.alternate;\n switch (next.tag) {\n case 15:\n case 0:\n next = replayFunctionComponent(\n current,\n next,\n next.pendingProps,\n next.type,\n void 0,\n workInProgressRootRenderLanes\n );\n break;\n case 11:\n next = replayFunctionComponent(\n current,\n next,\n next.pendingProps,\n next.type.render,\n next.ref,\n workInProgressRootRenderLanes\n );\n break;\n case 5:\n resetHooksOnUnwind(next);\n default:\n unwindInterruptedWork(current, next),\n (next = workInProgress =\n resetWorkInProgress(next, entangledRenderLanes)),\n (next = beginWork(current, next, entangledRenderLanes));\n }\n unitOfWork.memoizedProps = unitOfWork.pendingProps;\n null === next ? completeUnitOfWork(unitOfWork) : (workInProgress = next);\n}\nfunction throwAndUnwindWorkLoop(\n root,\n unitOfWork,\n thrownValue,\n suspendedReason\n) {\n lastContextDependency = currentlyRenderingFiber$1 = null;\n resetHooksOnUnwind(unitOfWork);\n thenableState$1 = null;\n thenableIndexCounter$1 = 0;\n var returnFiber = unitOfWork.return;\n try {\n if (\n throwException(\n root,\n returnFiber,\n unitOfWork,\n thrownValue,\n workInProgressRootRenderLanes\n )\n ) {\n workInProgressRootExitStatus = 1;\n logUncaughtError(\n root,\n createCapturedValueAtFiber(thrownValue, root.current)\n );\n workInProgress = null;\n return;\n }\n } catch (error) {\n if (null !== returnFiber) throw ((workInProgress = returnFiber), error);\n workInProgressRootExitStatus = 1;\n logUncaughtError(\n root,\n createCapturedValueAtFiber(thrownValue, root.current)\n );\n workInProgress = null;\n return;\n }\n if (unitOfWork.flags & 32768) {\n if (isHydrating || 1 === suspendedReason) root = !0;\n else if (\n workInProgressRootIsPrerendering ||\n 0 !== (workInProgressRootRenderLanes & 536870912)\n )\n root = !1;\n else if (\n ((workInProgressRootDidSkipSuspendedSiblings = root = !0),\n 2 === suspendedReason ||\n 9 === suspendedReason ||\n 3 === suspendedReason ||\n 6 === suspendedReason)\n )\n (suspendedReason = suspenseHandlerStackCursor.current),\n null !== suspendedReason &&\n 13 === suspendedReason.tag &&\n (suspendedReason.flags |= 16384);\n unwindUnitOfWork(unitOfWork, root);\n } else completeUnitOfWork(unitOfWork);\n}\nfunction completeUnitOfWork(unitOfWork) {\n var completedWork = unitOfWork;\n do {\n if (0 !== (completedWork.flags & 32768)) {\n unwindUnitOfWork(\n completedWork,\n workInProgressRootDidSkipSuspendedSiblings\n );\n return;\n }\n unitOfWork = completedWork.return;\n var next = completeWork(\n completedWork.alternate,\n completedWork,\n entangledRenderLanes\n );\n if (null !== next) {\n workInProgress = next;\n return;\n }\n completedWork = completedWork.sibling;\n if (null !== completedWork) {\n workInProgress = completedWork;\n return;\n }\n workInProgress = completedWork = unitOfWork;\n } while (null !== completedWork);\n 0 === workInProgressRootExitStatus && (workInProgressRootExitStatus = 5);\n}\nfunction unwindUnitOfWork(unitOfWork, skipSiblings) {\n do {\n var next = unwindWork(unitOfWork.alternate, unitOfWork);\n if (null !== next) {\n next.flags &= 32767;\n workInProgress = next;\n return;\n }\n next = unitOfWork.return;\n null !== next &&\n ((next.flags |= 32768), (next.subtreeFlags = 0), (next.deletions = null));\n if (\n !skipSiblings &&\n ((unitOfWork = unitOfWork.sibling), null !== unitOfWork)\n ) {\n workInProgress = unitOfWork;\n return;\n }\n workInProgress = unitOfWork = next;\n } while (null !== unitOfWork);\n workInProgressRootExitStatus = 6;\n workInProgress = null;\n}\nfunction commitRoot(\n root,\n finishedWork,\n lanes,\n recoverableErrors,\n transitions,\n didIncludeRenderPhaseUpdate,\n spawnedLane,\n updatedLanes,\n suspendedRetryLanes\n) {\n root.cancelPendingCommit = null;\n do flushPendingEffects();\n while (0 !== pendingEffectsStatus);\n if (0 !== (executionContext & 6)) throw Error(formatProdErrorMessage(327));\n if (null !== finishedWork) {\n if (finishedWork === root.current) throw Error(formatProdErrorMessage(177));\n didIncludeRenderPhaseUpdate = finishedWork.lanes | finishedWork.childLanes;\n didIncludeRenderPhaseUpdate |= concurrentlyUpdatedLanes;\n markRootFinished(\n root,\n lanes,\n didIncludeRenderPhaseUpdate,\n spawnedLane,\n updatedLanes,\n suspendedRetryLanes\n );\n root === workInProgressRoot &&\n ((workInProgress = workInProgressRoot = null),\n (workInProgressRootRenderLanes = 0));\n pendingFinishedWork = finishedWork;\n pendingEffectsRoot = root;\n pendingEffectsLanes = lanes;\n pendingEffectsRemainingLanes = didIncludeRenderPhaseUpdate;\n pendingPassiveTransitions = transitions;\n pendingRecoverableErrors = recoverableErrors;\n 0 !== (finishedWork.subtreeFlags & 10256) ||\n 0 !== (finishedWork.flags & 10256)\n ? ((root.callbackNode = null),\n (root.callbackPriority = 0),\n scheduleCallback$1(NormalPriority$1, function () {\n flushPassiveEffects();\n return null;\n }))\n : ((root.callbackNode = null), (root.callbackPriority = 0));\n recoverableErrors = 0 !== (finishedWork.flags & 13878);\n if (0 !== (finishedWork.subtreeFlags & 13878) || recoverableErrors) {\n recoverableErrors = ReactSharedInternals.T;\n ReactSharedInternals.T = null;\n transitions = ReactDOMSharedInternals.p;\n ReactDOMSharedInternals.p = 2;\n spawnedLane = executionContext;\n executionContext |= 4;\n try {\n commitBeforeMutationEffects(root, finishedWork, lanes);\n } finally {\n (executionContext = spawnedLane),\n (ReactDOMSharedInternals.p = transitions),\n (ReactSharedInternals.T = recoverableErrors);\n }\n }\n pendingEffectsStatus = 1;\n flushMutationEffects();\n flushLayoutEffects();\n flushSpawnedWork();\n }\n}\nfunction flushMutationEffects() {\n if (1 === pendingEffectsStatus) {\n pendingEffectsStatus = 0;\n var root = pendingEffectsRoot,\n finishedWork = pendingFinishedWork,\n rootMutationHasEffect = 0 !== (finishedWork.flags & 13878);\n if (0 !== (finishedWork.subtreeFlags & 13878) || rootMutationHasEffect) {\n rootMutationHasEffect = ReactSharedInternals.T;\n ReactSharedInternals.T = null;\n var previousPriority = ReactDOMSharedInternals.p;\n ReactDOMSharedInternals.p = 2;\n var prevExecutionContext = executionContext;\n executionContext |= 4;\n try {\n commitMutationEffectsOnFiber(finishedWork, root);\n var priorSelectionInformation = selectionInformation,\n curFocusedElem = getActiveElementDeep(root.containerInfo),\n priorFocusedElem = priorSelectionInformation.focusedElem,\n priorSelectionRange = priorSelectionInformation.selectionRange;\n if (\n curFocusedElem !== priorFocusedElem &&\n priorFocusedElem &&\n priorFocusedElem.ownerDocument &&\n containsNode(\n priorFocusedElem.ownerDocument.documentElement,\n priorFocusedElem\n )\n ) {\n if (\n null !== priorSelectionRange &&\n hasSelectionCapabilities(priorFocusedElem)\n ) {\n var start = priorSelectionRange.start,\n end = priorSelectionRange.end;\n void 0 === end && (end = start);\n if (\"selectionStart\" in priorFocusedElem)\n (priorFocusedElem.selectionStart = start),\n (priorFocusedElem.selectionEnd = Math.min(\n end,\n priorFocusedElem.value.length\n ));\n else {\n var doc = priorFocusedElem.ownerDocument || document,\n win = (doc && doc.defaultView) || window;\n if (win.getSelection) {\n var selection = win.getSelection(),\n length = priorFocusedElem.textContent.length,\n start$jscomp$0 = Math.min(priorSelectionRange.start, length),\n end$jscomp$0 =\n void 0 === priorSelectionRange.end\n ? start$jscomp$0\n : Math.min(priorSelectionRange.end, length);\n !selection.extend &&\n start$jscomp$0 > end$jscomp$0 &&\n ((curFocusedElem = end$jscomp$0),\n (end$jscomp$0 = start$jscomp$0),\n (start$jscomp$0 = curFocusedElem));\n var startMarker = getNodeForCharacterOffset(\n priorFocusedElem,\n start$jscomp$0\n ),\n endMarker = getNodeForCharacterOffset(\n priorFocusedElem,\n end$jscomp$0\n );\n if (\n startMarker &&\n endMarker &&\n (1 !== selection.rangeCount ||\n selection.anchorNode !== startMarker.node ||\n selection.anchorOffset !== startMarker.offset ||\n selection.focusNode !== endMarker.node ||\n selection.focusOffset !== endMarker.offset)\n ) {\n var range = doc.createRange();\n range.setStart(startMarker.node, startMarker.offset);\n selection.removeAllRanges();\n start$jscomp$0 > end$jscomp$0\n ? (selection.addRange(range),\n selection.extend(endMarker.node, endMarker.offset))\n : (range.setEnd(endMarker.node, endMarker.offset),\n selection.addRange(range));\n }\n }\n }\n }\n doc = [];\n for (\n selection = priorFocusedElem;\n (selection = selection.parentNode);\n\n )\n 1 === selection.nodeType &&\n doc.push({\n element: selection,\n left: selection.scrollLeft,\n top: selection.scrollTop\n });\n \"function\" === typeof priorFocusedElem.focus &&\n priorFocusedElem.focus();\n for (\n priorFocusedElem = 0;\n priorFocusedElem < doc.length;\n priorFocusedElem++\n ) {\n var info = doc[priorFocusedElem];\n info.element.scrollLeft = info.left;\n info.element.scrollTop = info.top;\n }\n }\n _enabled = !!eventsEnabled;\n selectionInformation = eventsEnabled = null;\n } finally {\n (executionContext = prevExecutionContext),\n (ReactDOMSharedInternals.p = previousPriority),\n (ReactSharedInternals.T = rootMutationHasEffect);\n }\n }\n root.current = finishedWork;\n pendingEffectsStatus = 2;\n }\n}\nfunction flushLayoutEffects() {\n if (2 === pendingEffectsStatus) {\n pendingEffectsStatus = 0;\n var root = pendingEffectsRoot,\n finishedWork = pendingFinishedWork,\n rootHasLayoutEffect = 0 !== (finishedWork.flags & 8772);\n if (0 !== (finishedWork.subtreeFlags & 8772) || rootHasLayoutEffect) {\n rootHasLayoutEffect = ReactSharedInternals.T;\n ReactSharedInternals.T = null;\n var previousPriority = ReactDOMSharedInternals.p;\n ReactDOMSharedInternals.p = 2;\n var prevExecutionContext = executionContext;\n executionContext |= 4;\n try {\n commitLayoutEffectOnFiber(root, finishedWork.alternate, finishedWork);\n } finally {\n (executionContext = prevExecutionContext),\n (ReactDOMSharedInternals.p = previousPriority),\n (ReactSharedInternals.T = rootHasLayoutEffect);\n }\n }\n pendingEffectsStatus = 3;\n }\n}\nfunction flushSpawnedWork() {\n if (4 === pendingEffectsStatus || 3 === pendingEffectsStatus) {\n pendingEffectsStatus = 0;\n requestPaint();\n var root = pendingEffectsRoot,\n finishedWork = pendingFinishedWork,\n lanes = pendingEffectsLanes,\n recoverableErrors = pendingRecoverableErrors;\n 0 !== (finishedWork.subtreeFlags & 10256) ||\n 0 !== (finishedWork.flags & 10256)\n ? (pendingEffectsStatus = 5)\n : ((pendingEffectsStatus = 0),\n (pendingFinishedWork = pendingEffectsRoot = null),\n releaseRootPooledCache(root, root.pendingLanes));\n var remainingLanes = root.pendingLanes;\n 0 === remainingLanes && (legacyErrorBoundariesThatAlreadyFailed = null);\n lanesToEventPriority(lanes);\n finishedWork = finishedWork.stateNode;\n if (injectedHook && \"function\" === typeof injectedHook.onCommitFiberRoot)\n try {\n injectedHook.onCommitFiberRoot(\n rendererID,\n finishedWork,\n void 0,\n 128 === (finishedWork.current.flags & 128)\n );\n } catch (err) {}\n if (null !== recoverableErrors) {\n finishedWork = ReactSharedInternals.T;\n remainingLanes = ReactDOMSharedInternals.p;\n ReactDOMSharedInternals.p = 2;\n ReactSharedInternals.T = null;\n try {\n for (\n var onRecoverableError = root.onRecoverableError, i = 0;\n i < recoverableErrors.length;\n i++\n ) {\n var recoverableError = recoverableErrors[i];\n onRecoverableError(recoverableError.value, {\n componentStack: recoverableError.stack\n });\n }\n } finally {\n (ReactSharedInternals.T = finishedWork),\n (ReactDOMSharedInternals.p = remainingLanes);\n }\n }\n 0 !== (pendingEffectsLanes & 3) && flushPendingEffects();\n ensureRootIsScheduled(root);\n remainingLanes = root.pendingLanes;\n 0 !== (lanes & 261930) && 0 !== (remainingLanes & 42)\n ? root === rootWithNestedUpdates\n ? nestedUpdateCount++\n : ((nestedUpdateCount = 0), (rootWithNestedUpdates = root))\n : (nestedUpdateCount = 0);\n flushSyncWorkAcrossRoots_impl(0, !1);\n }\n}\nfunction releaseRootPooledCache(root, remainingLanes) {\n 0 === (root.pooledCacheLanes &= remainingLanes) &&\n ((remainingLanes = root.pooledCache),\n null != remainingLanes &&\n ((root.pooledCache = null), releaseCache(remainingLanes)));\n}\nfunction flushPendingEffects() {\n flushMutationEffects();\n flushLayoutEffects();\n flushSpawnedWork();\n return flushPassiveEffects();\n}\nfunction flushPassiveEffects() {\n if (5 !== pendingEffectsStatus) return !1;\n var root = pendingEffectsRoot,\n remainingLanes = pendingEffectsRemainingLanes;\n pendingEffectsRemainingLanes = 0;\n var renderPriority = lanesToEventPriority(pendingEffectsLanes),\n prevTransition = ReactSharedInternals.T,\n previousPriority = ReactDOMSharedInternals.p;\n try {\n ReactDOMSharedInternals.p = 32 > renderPriority ? 32 : renderPriority;\n ReactSharedInternals.T = null;\n renderPriority = pendingPassiveTransitions;\n pendingPassiveTransitions = null;\n var root$jscomp$0 = pendingEffectsRoot,\n lanes = pendingEffectsLanes;\n pendingEffectsStatus = 0;\n pendingFinishedWork = pendingEffectsRoot = null;\n pendingEffectsLanes = 0;\n if (0 !== (executionContext & 6)) throw Error(formatProdErrorMessage(331));\n var prevExecutionContext = executionContext;\n executionContext |= 4;\n commitPassiveUnmountOnFiber(root$jscomp$0.current);\n commitPassiveMountOnFiber(\n root$jscomp$0,\n root$jscomp$0.current,\n lanes,\n renderPriority\n );\n executionContext = prevExecutionContext;\n flushSyncWorkAcrossRoots_impl(0, !1);\n if (\n injectedHook &&\n \"function\" === typeof injectedHook.onPostCommitFiberRoot\n )\n try {\n injectedHook.onPostCommitFiberRoot(rendererID, root$jscomp$0);\n } catch (err) {}\n return !0;\n } finally {\n (ReactDOMSharedInternals.p = previousPriority),\n (ReactSharedInternals.T = prevTransition),\n releaseRootPooledCache(root, remainingLanes);\n }\n}\nfunction captureCommitPhaseErrorOnRoot(rootFiber, sourceFiber, error) {\n sourceFiber = createCapturedValueAtFiber(error, sourceFiber);\n sourceFiber = createRootErrorUpdate(rootFiber.stateNode, sourceFiber, 2);\n rootFiber = enqueueUpdate(rootFiber, sourceFiber, 2);\n null !== rootFiber &&\n (markRootUpdated$1(rootFiber, 2), ensureRootIsScheduled(rootFiber));\n}\nfunction captureCommitPhaseError(sourceFiber, nearestMountedAncestor, error) {\n if (3 === sourceFiber.tag)\n captureCommitPhaseErrorOnRoot(sourceFiber, sourceFiber, error);\n else\n for (; null !== nearestMountedAncestor; ) {\n if (3 === nearestMountedAncestor.tag) {\n captureCommitPhaseErrorOnRoot(\n nearestMountedAncestor,\n sourceFiber,\n error\n );\n break;\n } else if (1 === nearestMountedAncestor.tag) {\n var instance = nearestMountedAncestor.stateNode;\n if (\n \"function\" ===\n typeof nearestMountedAncestor.type.getDerivedStateFromError ||\n (\"function\" === typeof instance.componentDidCatch &&\n (null === legacyErrorBoundariesThatAlreadyFailed ||\n !legacyErrorBoundariesThatAlreadyFailed.has(instance)))\n ) {\n sourceFiber = createCapturedValueAtFiber(error, sourceFiber);\n error = createClassErrorUpdate(2);\n instance = enqueueUpdate(nearestMountedAncestor, error, 2);\n null !== instance &&\n (initializeClassErrorUpdate(\n error,\n instance,\n nearestMountedAncestor,\n sourceFiber\n ),\n markRootUpdated$1(instance, 2),\n ensureRootIsScheduled(instance));\n break;\n }\n }\n nearestMountedAncestor = nearestMountedAncestor.return;\n }\n}\nfunction attachPingListener(root, wakeable, lanes) {\n var pingCache = root.pingCache;\n if (null === pingCache) {\n pingCache = root.pingCache = new PossiblyWeakMap();\n var threadIDs = new Set();\n pingCache.set(wakeable, threadIDs);\n } else\n (threadIDs = pingCache.get(wakeable)),\n void 0 === threadIDs &&\n ((threadIDs = new Set()), pingCache.set(wakeable, threadIDs));\n threadIDs.has(lanes) ||\n ((workInProgressRootDidAttachPingListener = !0),\n threadIDs.add(lanes),\n (root = pingSuspendedRoot.bind(null, root, wakeable, lanes)),\n wakeable.then(root, root));\n}\nfunction pingSuspendedRoot(root, wakeable, pingedLanes) {\n var pingCache = root.pingCache;\n null !== pingCache && pingCache.delete(wakeable);\n root.pingedLanes |= root.suspendedLanes & pingedLanes;\n root.warmLanes &= ~pingedLanes;\n workInProgressRoot === root &&\n (workInProgressRootRenderLanes & pingedLanes) === pingedLanes &&\n (4 === workInProgressRootExitStatus ||\n (3 === workInProgressRootExitStatus &&\n (workInProgressRootRenderLanes & 62914560) ===\n workInProgressRootRenderLanes &&\n 300 > now() - globalMostRecentFallbackTime)\n ? 0 === (executionContext & 2) && prepareFreshStack(root, 0)\n : (workInProgressRootPingedLanes |= pingedLanes),\n workInProgressSuspendedRetryLanes === workInProgressRootRenderLanes &&\n (workInProgressSuspendedRetryLanes = 0));\n ensureRootIsScheduled(root);\n}\nfunction retryTimedOutBoundary(boundaryFiber, retryLane) {\n 0 === retryLane && (retryLane = claimNextRetryLane());\n boundaryFiber = enqueueConcurrentRenderForLane(boundaryFiber, retryLane);\n null !== boundaryFiber &&\n (markRootUpdated$1(boundaryFiber, retryLane),\n ensureRootIsScheduled(boundaryFiber));\n}\nfunction retryDehydratedSuspenseBoundary(boundaryFiber) {\n var suspenseState = boundaryFiber.memoizedState,\n retryLane = 0;\n null !== suspenseState && (retryLane = suspenseState.retryLane);\n retryTimedOutBoundary(boundaryFiber, retryLane);\n}\nfunction resolveRetryWakeable(boundaryFiber, wakeable) {\n var retryLane = 0;\n switch (boundaryFiber.tag) {\n case 31:\n case 13:\n var retryCache = boundaryFiber.stateNode;\n var suspenseState = boundaryFiber.memoizedState;\n null !== suspenseState && (retryLane = suspenseState.retryLane);\n break;\n case 19:\n retryCache = boundaryFiber.stateNode;\n break;\n case 22:\n retryCache = boundaryFiber.stateNode._retryCache;\n break;\n default:\n throw Error(formatProdErrorMessage(314));\n }\n null !== retryCache && retryCache.delete(wakeable);\n retryTimedOutBoundary(boundaryFiber, retryLane);\n}\nfunction scheduleCallback$1(priorityLevel, callback) {\n return scheduleCallback$3(priorityLevel, callback);\n}\nvar firstScheduledRoot = null,\n lastScheduledRoot = null,\n didScheduleMicrotask = !1,\n mightHavePendingSyncWork = !1,\n isFlushingWork = !1,\n currentEventTransitionLane = 0;\nfunction ensureRootIsScheduled(root) {\n root !== lastScheduledRoot &&\n null === root.next &&\n (null === lastScheduledRoot\n ? (firstScheduledRoot = lastScheduledRoot = root)\n : (lastScheduledRoot = lastScheduledRoot.next = root));\n mightHavePendingSyncWork = !0;\n didScheduleMicrotask ||\n ((didScheduleMicrotask = !0), scheduleImmediateRootScheduleTask());\n}\nfunction flushSyncWorkAcrossRoots_impl(syncTransitionLanes, onlyLegacy) {\n if (!isFlushingWork && mightHavePendingSyncWork) {\n isFlushingWork = !0;\n do {\n var didPerformSomeWork = !1;\n for (var root$170 = firstScheduledRoot; null !== root$170; ) {\n if (!onlyLegacy)\n if (0 !== syncTransitionLanes) {\n var pendingLanes = root$170.pendingLanes;\n if (0 === pendingLanes) var JSCompiler_inline_result = 0;\n else {\n var suspendedLanes = root$170.suspendedLanes,\n pingedLanes = root$170.pingedLanes;\n JSCompiler_inline_result =\n (1 << (31 - clz32(42 | syncTransitionLanes) + 1)) - 1;\n JSCompiler_inline_result &=\n pendingLanes & ~(suspendedLanes & ~pingedLanes);\n JSCompiler_inline_result =\n JSCompiler_inline_result & 201326741\n ? (JSCompiler_inline_result & 201326741) | 1\n : JSCompiler_inline_result\n ? JSCompiler_inline_result | 2\n : 0;\n }\n 0 !== JSCompiler_inline_result &&\n ((didPerformSomeWork = !0),\n performSyncWorkOnRoot(root$170, JSCompiler_inline_result));\n } else\n (JSCompiler_inline_result = workInProgressRootRenderLanes),\n (JSCompiler_inline_result = getNextLanes(\n root$170,\n root$170 === workInProgressRoot ? JSCompiler_inline_result : 0,\n null !== root$170.cancelPendingCommit ||\n -1 !== root$170.timeoutHandle\n )),\n 0 === (JSCompiler_inline_result & 3) ||\n checkIfRootIsPrerendering(root$170, JSCompiler_inline_result) ||\n ((didPerformSomeWork = !0),\n performSyncWorkOnRoot(root$170, JSCompiler_inline_result));\n root$170 = root$170.next;\n }\n } while (didPerformSomeWork);\n isFlushingWork = !1;\n }\n}\nfunction processRootScheduleInImmediateTask() {\n processRootScheduleInMicrotask();\n}\nfunction processRootScheduleInMicrotask() {\n mightHavePendingSyncWork = didScheduleMicrotask = !1;\n var syncTransitionLanes = 0;\n 0 !== currentEventTransitionLane &&\n shouldAttemptEagerTransition() &&\n (syncTransitionLanes = currentEventTransitionLane);\n for (\n var currentTime = now(), prev = null, root = firstScheduledRoot;\n null !== root;\n\n ) {\n var next = root.next,\n nextLanes = scheduleTaskForRootDuringMicrotask(root, currentTime);\n if (0 === nextLanes)\n (root.next = null),\n null === prev ? (firstScheduledRoot = next) : (prev.next = next),\n null === next && (lastScheduledRoot = prev);\n else if (\n ((prev = root), 0 !== syncTransitionLanes || 0 !== (nextLanes & 3))\n )\n mightHavePendingSyncWork = !0;\n root = next;\n }\n (0 !== pendingEffectsStatus && 5 !== pendingEffectsStatus) ||\n flushSyncWorkAcrossRoots_impl(syncTransitionLanes, !1);\n 0 !== currentEventTransitionLane && (currentEventTransitionLane = 0);\n}\nfunction scheduleTaskForRootDuringMicrotask(root, currentTime) {\n for (\n var suspendedLanes = root.suspendedLanes,\n pingedLanes = root.pingedLanes,\n expirationTimes = root.expirationTimes,\n lanes = root.pendingLanes & -62914561;\n 0 < lanes;\n\n ) {\n var index$5 = 31 - clz32(lanes),\n lane = 1 << index$5,\n expirationTime = expirationTimes[index$5];\n if (-1 === expirationTime) {\n if (0 === (lane & suspendedLanes) || 0 !== (lane & pingedLanes))\n expirationTimes[index$5] = computeExpirationTime(lane, currentTime);\n } else expirationTime <= currentTime && (root.expiredLanes |= lane);\n lanes &= ~lane;\n }\n currentTime = workInProgressRoot;\n suspendedLanes = workInProgressRootRenderLanes;\n suspendedLanes = getNextLanes(\n root,\n root === currentTime ? suspendedLanes : 0,\n null !== root.cancelPendingCommit || -1 !== root.timeoutHandle\n );\n pingedLanes = root.callbackNode;\n if (\n 0 === suspendedLanes ||\n (root === currentTime &&\n (2 === workInProgressSuspendedReason ||\n 9 === workInProgressSuspendedReason)) ||\n null !== root.cancelPendingCommit\n )\n return (\n null !== pingedLanes &&\n null !== pingedLanes &&\n cancelCallback$1(pingedLanes),\n (root.callbackNode = null),\n (root.callbackPriority = 0)\n );\n if (\n 0 === (suspendedLanes & 3) ||\n checkIfRootIsPrerendering(root, suspendedLanes)\n ) {\n currentTime = suspendedLanes & -suspendedLanes;\n if (currentTime === root.callbackPriority) return currentTime;\n null !== pingedLanes && cancelCallback$1(pingedLanes);\n switch (lanesToEventPriority(suspendedLanes)) {\n case 2:\n case 8:\n suspendedLanes = UserBlockingPriority;\n break;\n case 32:\n suspendedLanes = NormalPriority$1;\n break;\n case 268435456:\n suspendedLanes = IdlePriority;\n break;\n default:\n suspendedLanes = NormalPriority$1;\n }\n pingedLanes = performWorkOnRootViaSchedulerTask.bind(null, root);\n suspendedLanes = scheduleCallback$3(suspendedLanes, pingedLanes);\n root.callbackPriority = currentTime;\n root.callbackNode = suspendedLanes;\n return currentTime;\n }\n null !== pingedLanes && null !== pingedLanes && cancelCallback$1(pingedLanes);\n root.callbackPriority = 2;\n root.callbackNode = null;\n return 2;\n}\nfunction performWorkOnRootViaSchedulerTask(root, didTimeout) {\n if (0 !== pendingEffectsStatus && 5 !== pendingEffectsStatus)\n return (root.callbackNode = null), (root.callbackPriority = 0), null;\n var originalCallbackNode = root.callbackNode;\n if (flushPendingEffects() && root.callbackNode !== originalCallbackNode)\n return null;\n var workInProgressRootRenderLanes$jscomp$0 = workInProgressRootRenderLanes;\n workInProgressRootRenderLanes$jscomp$0 = getNextLanes(\n root,\n root === workInProgressRoot ? workInProgressRootRenderLanes$jscomp$0 : 0,\n null !== root.cancelPendingCommit || -1 !== root.timeoutHandle\n );\n if (0 === workInProgressRootRenderLanes$jscomp$0) return null;\n performWorkOnRoot(root, workInProgressRootRenderLanes$jscomp$0, didTimeout);\n scheduleTaskForRootDuringMicrotask(root, now());\n return null != root.callbackNode && root.callbackNode === originalCallbackNode\n ? performWorkOnRootViaSchedulerTask.bind(null, root)\n : null;\n}\nfunction performSyncWorkOnRoot(root, lanes) {\n if (flushPendingEffects()) return null;\n performWorkOnRoot(root, lanes, !0);\n}\nfunction scheduleImmediateRootScheduleTask() {\n scheduleMicrotask(function () {\n 0 !== (executionContext & 6)\n ? scheduleCallback$3(\n ImmediatePriority,\n processRootScheduleInImmediateTask\n )\n : processRootScheduleInMicrotask();\n });\n}\nfunction requestTransitionLane() {\n if (0 === currentEventTransitionLane) {\n var actionScopeLane = currentEntangledLane;\n 0 === actionScopeLane &&\n ((actionScopeLane = nextTransitionUpdateLane),\n (nextTransitionUpdateLane <<= 1),\n 0 === (nextTransitionUpdateLane & 261888) &&\n (nextTransitionUpdateLane = 256));\n currentEventTransitionLane = actionScopeLane;\n }\n return currentEventTransitionLane;\n}\nfunction coerceFormActionProp(actionProp) {\n return null == actionProp ||\n \"symbol\" === typeof actionProp ||\n \"boolean\" === typeof actionProp\n ? null\n : \"function\" === typeof actionProp\n ? actionProp\n : sanitizeURL(\"\" + actionProp);\n}\nfunction createFormDataWithSubmitter(form, submitter) {\n var temp = submitter.ownerDocument.createElement(\"input\");\n temp.name = submitter.name;\n temp.value = submitter.value;\n form.id && temp.setAttribute(\"form\", form.id);\n submitter.parentNode.insertBefore(temp, submitter);\n form = new FormData(form);\n temp.parentNode.removeChild(temp);\n return form;\n}\nfunction extractEvents$1(\n dispatchQueue,\n domEventName,\n maybeTargetInst,\n nativeEvent,\n nativeEventTarget\n) {\n if (\n \"submit\" === domEventName &&\n maybeTargetInst &&\n maybeTargetInst.stateNode === nativeEventTarget\n ) {\n var action = coerceFormActionProp(\n (nativeEventTarget[internalPropsKey] || null).action\n ),\n submitter = nativeEvent.submitter;\n submitter &&\n ((domEventName = (domEventName = submitter[internalPropsKey] || null)\n ? coerceFormActionProp(domEventName.formAction)\n : submitter.getAttribute(\"formAction\")),\n null !== domEventName && ((action = domEventName), (submitter = null)));\n var event = new SyntheticEvent(\n \"action\",\n \"action\",\n null,\n nativeEvent,\n nativeEventTarget\n );\n dispatchQueue.push({\n event: event,\n listeners: [\n {\n instance: null,\n listener: function () {\n if (nativeEvent.defaultPrevented) {\n if (0 !== currentEventTransitionLane) {\n var formData = submitter\n ? createFormDataWithSubmitter(nativeEventTarget, submitter)\n : new FormData(nativeEventTarget);\n startHostTransition(\n maybeTargetInst,\n {\n pending: !0,\n data: formData,\n method: nativeEventTarget.method,\n action: action\n },\n null,\n formData\n );\n }\n } else\n \"function\" === typeof action &&\n (event.preventDefault(),\n (formData = submitter\n ? createFormDataWithSubmitter(nativeEventTarget, submitter)\n : new FormData(nativeEventTarget)),\n startHostTransition(\n maybeTargetInst,\n {\n pending: !0,\n data: formData,\n method: nativeEventTarget.method,\n action: action\n },\n action,\n formData\n ));\n },\n currentTarget: nativeEventTarget\n }\n ]\n });\n }\n}\nfor (\n var i$jscomp$inline_1577 = 0;\n i$jscomp$inline_1577 < simpleEventPluginEvents.length;\n i$jscomp$inline_1577++\n) {\n var eventName$jscomp$inline_1578 =\n simpleEventPluginEvents[i$jscomp$inline_1577],\n domEventName$jscomp$inline_1579 =\n eventName$jscomp$inline_1578.toLowerCase(),\n capitalizedEvent$jscomp$inline_1580 =\n eventName$jscomp$inline_1578[0].toUpperCase() +\n eventName$jscomp$inline_1578.slice(1);\n registerSimpleEvent(\n domEventName$jscomp$inline_1579,\n \"on\" + capitalizedEvent$jscomp$inline_1580\n );\n}\nregisterSimpleEvent(ANIMATION_END, \"onAnimationEnd\");\nregisterSimpleEvent(ANIMATION_ITERATION, \"onAnimationIteration\");\nregisterSimpleEvent(ANIMATION_START, \"onAnimationStart\");\nregisterSimpleEvent(\"dblclick\", \"onDoubleClick\");\nregisterSimpleEvent(\"focusin\", \"onFocus\");\nregisterSimpleEvent(\"focusout\", \"onBlur\");\nregisterSimpleEvent(TRANSITION_RUN, \"onTransitionRun\");\nregisterSimpleEvent(TRANSITION_START, \"onTransitionStart\");\nregisterSimpleEvent(TRANSITION_CANCEL, \"onTransitionCancel\");\nregisterSimpleEvent(TRANSITION_END, \"onTransitionEnd\");\nregisterDirectEvent(\"onMouseEnter\", [\"mouseout\", \"mouseover\"]);\nregisterDirectEvent(\"onMouseLeave\", [\"mouseout\", \"mouseover\"]);\nregisterDirectEvent(\"onPointerEnter\", [\"pointerout\", \"pointerover\"]);\nregisterDirectEvent(\"onPointerLeave\", [\"pointerout\", \"pointerover\"]);\nregisterTwoPhaseEvent(\n \"onChange\",\n \"change click focusin focusout input keydown keyup selectionchange\".split(\" \")\n);\nregisterTwoPhaseEvent(\n \"onSelect\",\n \"focusout contextmenu dragend focusin keydown keyup mousedown mouseup selectionchange\".split(\n \" \"\n )\n);\nregisterTwoPhaseEvent(\"onBeforeInput\", [\n \"compositionend\",\n \"keypress\",\n \"textInput\",\n \"paste\"\n]);\nregisterTwoPhaseEvent(\n \"onCompositionEnd\",\n \"compositionend focusout keydown keypress keyup mousedown\".split(\" \")\n);\nregisterTwoPhaseEvent(\n \"onCompositionStart\",\n \"compositionstart focusout keydown keypress keyup mousedown\".split(\" \")\n);\nregisterTwoPhaseEvent(\n \"onCompositionUpdate\",\n \"compositionupdate focusout keydown keypress keyup mousedown\".split(\" \")\n);\nvar mediaEventTypes =\n \"abort canplay canplaythrough durationchange emptied encrypted ended error loadeddata loadedmetadata loadstart pause play playing progress ratechange resize seeked seeking stalled suspend timeupdate volumechange waiting\".split(\n \" \"\n ),\n nonDelegatedEvents = new Set(\n \"beforetoggle cancel close invalid load scroll scrollend toggle\"\n .split(\" \")\n .concat(mediaEventTypes)\n );\nfunction processDispatchQueue(dispatchQueue, eventSystemFlags) {\n eventSystemFlags = 0 !== (eventSystemFlags & 4);\n for (var i = 0; i < dispatchQueue.length; i++) {\n var _dispatchQueue$i = dispatchQueue[i],\n event = _dispatchQueue$i.event;\n _dispatchQueue$i = _dispatchQueue$i.listeners;\n a: {\n var previousInstance = void 0;\n if (eventSystemFlags)\n for (\n var i$jscomp$0 = _dispatchQueue$i.length - 1;\n 0 <= i$jscomp$0;\n i$jscomp$0--\n ) {\n var _dispatchListeners$i = _dispatchQueue$i[i$jscomp$0],\n instance = _dispatchListeners$i.instance,\n currentTarget = _dispatchListeners$i.currentTarget;\n _dispatchListeners$i = _dispatchListeners$i.listener;\n if (instance !== previousInstance && event.isPropagationStopped())\n break a;\n previousInstance = _dispatchListeners$i;\n event.currentTarget = currentTarget;\n try {\n previousInstance(event);\n } catch (error) {\n reportGlobalError(error);\n }\n event.currentTarget = null;\n previousInstance = instance;\n }\n else\n for (\n i$jscomp$0 = 0;\n i$jscomp$0 < _dispatchQueue$i.length;\n i$jscomp$0++\n ) {\n _dispatchListeners$i = _dispatchQueue$i[i$jscomp$0];\n instance = _dispatchListeners$i.instance;\n currentTarget = _dispatchListeners$i.currentTarget;\n _dispatchListeners$i = _dispatchListeners$i.listener;\n if (instance !== previousInstance && event.isPropagationStopped())\n break a;\n previousInstance = _dispatchListeners$i;\n event.currentTarget = currentTarget;\n try {\n previousInstance(event);\n } catch (error) {\n reportGlobalError(error);\n }\n event.currentTarget = null;\n previousInstance = instance;\n }\n }\n }\n}\nfunction listenToNonDelegatedEvent(domEventName, targetElement) {\n var JSCompiler_inline_result = targetElement[internalEventHandlersKey];\n void 0 === JSCompiler_inline_result &&\n (JSCompiler_inline_result = targetElement[internalEventHandlersKey] =\n new Set());\n var listenerSetKey = domEventName + \"__bubble\";\n JSCompiler_inline_result.has(listenerSetKey) ||\n (addTrappedEventListener(targetElement, domEventName, 2, !1),\n JSCompiler_inline_result.add(listenerSetKey));\n}\nfunction listenToNativeEvent(domEventName, isCapturePhaseListener, target) {\n var eventSystemFlags = 0;\n isCapturePhaseListener && (eventSystemFlags |= 4);\n addTrappedEventListener(\n target,\n domEventName,\n eventSystemFlags,\n isCapturePhaseListener\n );\n}\nvar listeningMarker = \"_reactListening\" + Math.random().toString(36).slice(2);\nfunction listenToAllSupportedEvents(rootContainerElement) {\n if (!rootContainerElement[listeningMarker]) {\n rootContainerElement[listeningMarker] = !0;\n allNativeEvents.forEach(function (domEventName) {\n \"selectionchange\" !== domEventName &&\n (nonDelegatedEvents.has(domEventName) ||\n listenToNativeEvent(domEventName, !1, rootContainerElement),\n listenToNativeEvent(domEventName, !0, rootContainerElement));\n });\n var ownerDocument =\n 9 === rootContainerElement.nodeType\n ? rootContainerElement\n : rootContainerElement.ownerDocument;\n null === ownerDocument ||\n ownerDocument[listeningMarker] ||\n ((ownerDocument[listeningMarker] = !0),\n listenToNativeEvent(\"selectionchange\", !1, ownerDocument));\n }\n}\nfunction addTrappedEventListener(\n targetContainer,\n domEventName,\n eventSystemFlags,\n isCapturePhaseListener\n) {\n switch (getEventPriority(domEventName)) {\n case 2:\n var listenerWrapper = dispatchDiscreteEvent;\n break;\n case 8:\n listenerWrapper = dispatchContinuousEvent;\n break;\n default:\n listenerWrapper = dispatchEvent;\n }\n eventSystemFlags = listenerWrapper.bind(\n null,\n domEventName,\n eventSystemFlags,\n targetContainer\n );\n listenerWrapper = void 0;\n !passiveBrowserEventsSupported ||\n (\"touchstart\" !== domEventName &&\n \"touchmove\" !== domEventName &&\n \"wheel\" !== domEventName) ||\n (listenerWrapper = !0);\n isCapturePhaseListener\n ? void 0 !== listenerWrapper\n ? targetContainer.addEventListener(domEventName, eventSystemFlags, {\n capture: !0,\n passive: listenerWrapper\n })\n : targetContainer.addEventListener(domEventName, eventSystemFlags, !0)\n : void 0 !== listenerWrapper\n ? targetContainer.addEventListener(domEventName, eventSystemFlags, {\n passive: listenerWrapper\n })\n : targetContainer.addEventListener(domEventName, eventSystemFlags, !1);\n}\nfunction dispatchEventForPluginEventSystem(\n domEventName,\n eventSystemFlags,\n nativeEvent,\n targetInst$jscomp$0,\n targetContainer\n) {\n var ancestorInst = targetInst$jscomp$0;\n if (\n 0 === (eventSystemFlags & 1) &&\n 0 === (eventSystemFlags & 2) &&\n null !== targetInst$jscomp$0\n )\n a: for (;;) {\n if (null === targetInst$jscomp$0) return;\n var nodeTag = targetInst$jscomp$0.tag;\n if (3 === nodeTag || 4 === nodeTag) {\n var container = targetInst$jscomp$0.stateNode.containerInfo;\n if (container === targetContainer) break;\n if (4 === nodeTag)\n for (nodeTag = targetInst$jscomp$0.return; null !== nodeTag; ) {\n var grandTag = nodeTag.tag;\n if (\n (3 === grandTag || 4 === grandTag) &&\n nodeTag.stateNode.containerInfo === targetContainer\n )\n return;\n nodeTag = nodeTag.return;\n }\n for (; null !== container; ) {\n nodeTag = getClosestInstanceFromNode(container);\n if (null === nodeTag) return;\n grandTag = nodeTag.tag;\n if (\n 5 === grandTag ||\n 6 === grandTag ||\n 26 === grandTag ||\n 27 === grandTag\n ) {\n targetInst$jscomp$0 = ancestorInst = nodeTag;\n continue a;\n }\n container = container.parentNode;\n }\n }\n targetInst$jscomp$0 = targetInst$jscomp$0.return;\n }\n batchedUpdates$1(function () {\n var targetInst = ancestorInst,\n nativeEventTarget = getEventTarget(nativeEvent),\n dispatchQueue = [];\n a: {\n var reactName = topLevelEventsToReactNames.get(domEventName);\n if (void 0 !== reactName) {\n var SyntheticEventCtor = SyntheticEvent,\n reactEventType = domEventName;\n switch (domEventName) {\n case \"keypress\":\n if (0 === getEventCharCode(nativeEvent)) break a;\n case \"keydown\":\n case \"keyup\":\n SyntheticEventCtor = SyntheticKeyboardEvent;\n break;\n case \"focusin\":\n reactEventType = \"focus\";\n SyntheticEventCtor = SyntheticFocusEvent;\n break;\n case \"focusout\":\n reactEventType = \"blur\";\n SyntheticEventCtor = SyntheticFocusEvent;\n break;\n case \"beforeblur\":\n case \"afterblur\":\n SyntheticEventCtor = SyntheticFocusEvent;\n break;\n case \"click\":\n if (2 === nativeEvent.button) break a;\n case \"auxclick\":\n case \"dblclick\":\n case \"mousedown\":\n case \"mousemove\":\n case \"mouseup\":\n case \"mouseout\":\n case \"mouseover\":\n case \"contextmenu\":\n SyntheticEventCtor = SyntheticMouseEvent;\n break;\n case \"drag\":\n case \"dragend\":\n case \"dragenter\":\n case \"dragexit\":\n case \"dragleave\":\n case \"dragover\":\n case \"dragstart\":\n case \"drop\":\n SyntheticEventCtor = SyntheticDragEvent;\n break;\n case \"touchcancel\":\n case \"touchend\":\n case \"touchmove\":\n case \"touchstart\":\n SyntheticEventCtor = SyntheticTouchEvent;\n break;\n case ANIMATION_END:\n case ANIMATION_ITERATION:\n case ANIMATION_START:\n SyntheticEventCtor = SyntheticAnimationEvent;\n break;\n case TRANSITION_END:\n SyntheticEventCtor = SyntheticTransitionEvent;\n break;\n case \"scroll\":\n case \"scrollend\":\n SyntheticEventCtor = SyntheticUIEvent;\n break;\n case \"wheel\":\n SyntheticEventCtor = SyntheticWheelEvent;\n break;\n case \"copy\":\n case \"cut\":\n case \"paste\":\n SyntheticEventCtor = SyntheticClipboardEvent;\n break;\n case \"gotpointercapture\":\n case \"lostpointercapture\":\n case \"pointercancel\":\n case \"pointerdown\":\n case \"pointermove\":\n case \"pointerout\":\n case \"pointerover\":\n case \"pointerup\":\n SyntheticEventCtor = SyntheticPointerEvent;\n break;\n case \"toggle\":\n case \"beforetoggle\":\n SyntheticEventCtor = SyntheticToggleEvent;\n }\n var inCapturePhase = 0 !== (eventSystemFlags & 4),\n accumulateTargetOnly =\n !inCapturePhase &&\n (\"scroll\" === domEventName || \"scrollend\" === domEventName),\n reactEventName = inCapturePhase\n ? null !== reactName\n ? reactName + \"Capture\"\n : null\n : reactName;\n inCapturePhase = [];\n for (\n var instance = targetInst, lastHostComponent;\n null !== instance;\n\n ) {\n var _instance = instance;\n lastHostComponent = _instance.stateNode;\n _instance = _instance.tag;\n (5 !== _instance && 26 !== _instance && 27 !== _instance) ||\n null === lastHostComponent ||\n null === reactEventName ||\n ((_instance = getListener(instance, reactEventName)),\n null != _instance &&\n inCapturePhase.push(\n createDispatchListener(instance, _instance, lastHostComponent)\n ));\n if (accumulateTargetOnly) break;\n instance = instance.return;\n }\n 0 < inCapturePhase.length &&\n ((reactName = new SyntheticEventCtor(\n reactName,\n reactEventType,\n null,\n nativeEvent,\n nativeEventTarget\n )),\n dispatchQueue.push({ event: reactName, listeners: inCapturePhase }));\n }\n }\n if (0 === (eventSystemFlags & 7)) {\n a: {\n reactName =\n \"mouseover\" === domEventName || \"pointerover\" === domEventName;\n SyntheticEventCtor =\n \"mouseout\" === domEventName || \"pointerout\" === domEventName;\n if (\n reactName &&\n nativeEvent !== currentReplayingEvent &&\n (reactEventType =\n nativeEvent.relatedTarget || nativeEvent.fromElement) &&\n (getClosestInstanceFromNode(reactEventType) ||\n reactEventType[internalContainerInstanceKey])\n )\n break a;\n if (SyntheticEventCtor || reactName) {\n reactName =\n nativeEventTarget.window === nativeEventTarget\n ? nativeEventTarget\n : (reactName = nativeEventTarget.ownerDocument)\n ? reactName.defaultView || reactName.parentWindow\n : window;\n if (SyntheticEventCtor) {\n if (\n ((reactEventType =\n nativeEvent.relatedTarget || nativeEvent.toElement),\n (SyntheticEventCtor = targetInst),\n (reactEventType = reactEventType\n ? getClosestInstanceFromNode(reactEventType)\n : null),\n null !== reactEventType &&\n ((accumulateTargetOnly =\n getNearestMountedFiber(reactEventType)),\n (inCapturePhase = reactEventType.tag),\n reactEventType !== accumulateTargetOnly ||\n (5 !== inCapturePhase &&\n 27 !== inCapturePhase &&\n 6 !== inCapturePhase)))\n )\n reactEventType = null;\n } else (SyntheticEventCtor = null), (reactEventType = targetInst);\n if (SyntheticEventCtor !== reactEventType) {\n inCapturePhase = SyntheticMouseEvent;\n _instance = \"onMouseLeave\";\n reactEventName = \"onMouseEnter\";\n instance = \"mouse\";\n if (\"pointerout\" === domEventName || \"pointerover\" === domEventName)\n (inCapturePhase = SyntheticPointerEvent),\n (_instance = \"onPointerLeave\"),\n (reactEventName = \"onPointerEnter\"),\n (instance = \"pointer\");\n accumulateTargetOnly =\n null == SyntheticEventCtor\n ? reactName\n : getNodeFromInstance(SyntheticEventCtor);\n lastHostComponent =\n null == reactEventType\n ? reactName\n : getNodeFromInstance(reactEventType);\n reactName = new inCapturePhase(\n _instance,\n instance + \"leave\",\n SyntheticEventCtor,\n nativeEvent,\n nativeEventTarget\n );\n reactName.target = accumulateTargetOnly;\n reactName.relatedTarget = lastHostComponent;\n _instance = null;\n getClosestInstanceFromNode(nativeEventTarget) === targetInst &&\n ((inCapturePhase = new inCapturePhase(\n reactEventName,\n instance + \"enter\",\n reactEventType,\n nativeEvent,\n nativeEventTarget\n )),\n (inCapturePhase.target = lastHostComponent),\n (inCapturePhase.relatedTarget = accumulateTargetOnly),\n (_instance = inCapturePhase));\n accumulateTargetOnly = _instance;\n if (SyntheticEventCtor && reactEventType)\n b: {\n inCapturePhase = getParent;\n reactEventName = SyntheticEventCtor;\n instance = reactEventType;\n lastHostComponent = 0;\n for (\n _instance = reactEventName;\n _instance;\n _instance = inCapturePhase(_instance)\n )\n lastHostComponent++;\n _instance = 0;\n for (var tempB = instance; tempB; tempB = inCapturePhase(tempB))\n _instance++;\n for (; 0 < lastHostComponent - _instance; )\n (reactEventName = inCapturePhase(reactEventName)),\n lastHostComponent--;\n for (; 0 < _instance - lastHostComponent; )\n (instance = inCapturePhase(instance)), _instance--;\n for (; lastHostComponent--; ) {\n if (\n reactEventName === instance ||\n (null !== instance && reactEventName === instance.alternate)\n ) {\n inCapturePhase = reactEventName;\n break b;\n }\n reactEventName = inCapturePhase(reactEventName);\n instance = inCapturePhase(instance);\n }\n inCapturePhase = null;\n }\n else inCapturePhase = null;\n null !== SyntheticEventCtor &&\n accumulateEnterLeaveListenersForEvent(\n dispatchQueue,\n reactName,\n SyntheticEventCtor,\n inCapturePhase,\n !1\n );\n null !== reactEventType &&\n null !== accumulateTargetOnly &&\n accumulateEnterLeaveListenersForEvent(\n dispatchQueue,\n accumulateTargetOnly,\n reactEventType,\n inCapturePhase,\n !0\n );\n }\n }\n }\n a: {\n reactName = targetInst ? getNodeFromInstance(targetInst) : window;\n SyntheticEventCtor =\n reactName.nodeName && reactName.nodeName.toLowerCase();\n if (\n \"select\" === SyntheticEventCtor ||\n (\"input\" === SyntheticEventCtor && \"file\" === reactName.type)\n )\n var getTargetInstFunc = getTargetInstForChangeEvent;\n else if (isTextInputElement(reactName))\n if (isInputEventSupported)\n getTargetInstFunc = getTargetInstForInputOrChangeEvent;\n else {\n getTargetInstFunc = getTargetInstForInputEventPolyfill;\n var handleEventFunc = handleEventsForInputEventPolyfill;\n }\n else\n (SyntheticEventCtor = reactName.nodeName),\n !SyntheticEventCtor ||\n \"input\" !== SyntheticEventCtor.toLowerCase() ||\n (\"checkbox\" !== reactName.type && \"radio\" !== reactName.type)\n ? targetInst &&\n isCustomElement(targetInst.elementType) &&\n (getTargetInstFunc = getTargetInstForChangeEvent)\n : (getTargetInstFunc = getTargetInstForClickEvent);\n if (\n getTargetInstFunc &&\n (getTargetInstFunc = getTargetInstFunc(domEventName, targetInst))\n ) {\n createAndAccumulateChangeEvent(\n dispatchQueue,\n getTargetInstFunc,\n nativeEvent,\n nativeEventTarget\n );\n break a;\n }\n handleEventFunc && handleEventFunc(domEventName, reactName, targetInst);\n \"focusout\" === domEventName &&\n targetInst &&\n \"number\" === reactName.type &&\n null != targetInst.memoizedProps.value &&\n setDefaultValue(reactName, \"number\", reactName.value);\n }\n handleEventFunc = targetInst ? getNodeFromInstance(targetInst) : window;\n switch (domEventName) {\n case \"focusin\":\n if (\n isTextInputElement(handleEventFunc) ||\n \"true\" === handleEventFunc.contentEditable\n )\n (activeElement = handleEventFunc),\n (activeElementInst = targetInst),\n (lastSelection = null);\n break;\n case \"focusout\":\n lastSelection = activeElementInst = activeElement = null;\n break;\n case \"mousedown\":\n mouseDown = !0;\n break;\n case \"contextmenu\":\n case \"mouseup\":\n case \"dragend\":\n mouseDown = !1;\n constructSelectEvent(dispatchQueue, nativeEvent, nativeEventTarget);\n break;\n case \"selectionchange\":\n if (skipSelectionChangeEvent) break;\n case \"keydown\":\n case \"keyup\":\n constructSelectEvent(dispatchQueue, nativeEvent, nativeEventTarget);\n }\n var fallbackData;\n if (canUseCompositionEvent)\n b: {\n switch (domEventName) {\n case \"compositionstart\":\n var eventType = \"onCompositionStart\";\n break b;\n case \"compositionend\":\n eventType = \"onCompositionEnd\";\n break b;\n case \"compositionupdate\":\n eventType = \"onCompositionUpdate\";\n break b;\n }\n eventType = void 0;\n }\n else\n isComposing\n ? isFallbackCompositionEnd(domEventName, nativeEvent) &&\n (eventType = \"onCompositionEnd\")\n : \"keydown\" === domEventName &&\n 229 === nativeEvent.keyCode &&\n (eventType = \"onCompositionStart\");\n eventType &&\n (useFallbackCompositionData &&\n \"ko\" !== nativeEvent.locale &&\n (isComposing || \"onCompositionStart\" !== eventType\n ? \"onCompositionEnd\" === eventType &&\n isComposing &&\n (fallbackData = getData())\n : ((root = nativeEventTarget),\n (startText = \"value\" in root ? root.value : root.textContent),\n (isComposing = !0))),\n (handleEventFunc = accumulateTwoPhaseListeners(targetInst, eventType)),\n 0 < handleEventFunc.length &&\n ((eventType = new SyntheticCompositionEvent(\n eventType,\n domEventName,\n null,\n nativeEvent,\n nativeEventTarget\n )),\n dispatchQueue.push({ event: eventType, listeners: handleEventFunc }),\n fallbackData\n ? (eventType.data = fallbackData)\n : ((fallbackData = getDataFromCustomEvent(nativeEvent)),\n null !== fallbackData && (eventType.data = fallbackData))));\n if (\n (fallbackData = canUseTextInputEvent\n ? getNativeBeforeInputChars(domEventName, nativeEvent)\n : getFallbackBeforeInputChars(domEventName, nativeEvent))\n )\n (eventType = accumulateTwoPhaseListeners(targetInst, \"onBeforeInput\")),\n 0 < eventType.length &&\n ((handleEventFunc = new SyntheticCompositionEvent(\n \"onBeforeInput\",\n \"beforeinput\",\n null,\n nativeEvent,\n nativeEventTarget\n )),\n dispatchQueue.push({\n event: handleEventFunc,\n listeners: eventType\n }),\n (handleEventFunc.data = fallbackData));\n extractEvents$1(\n dispatchQueue,\n domEventName,\n targetInst,\n nativeEvent,\n nativeEventTarget\n );\n }\n processDispatchQueue(dispatchQueue, eventSystemFlags);\n });\n}\nfunction createDispatchListener(instance, listener, currentTarget) {\n return {\n instance: instance,\n listener: listener,\n currentTarget: currentTarget\n };\n}\nfunction accumulateTwoPhaseListeners(targetFiber, reactName) {\n for (\n var captureName = reactName + \"Capture\", listeners = [];\n null !== targetFiber;\n\n ) {\n var _instance2 = targetFiber,\n stateNode = _instance2.stateNode;\n _instance2 = _instance2.tag;\n (5 !== _instance2 && 26 !== _instance2 && 27 !== _instance2) ||\n null === stateNode ||\n ((_instance2 = getListener(targetFiber, captureName)),\n null != _instance2 &&\n listeners.unshift(\n createDispatchListener(targetFiber, _instance2, stateNode)\n ),\n (_instance2 = getListener(targetFiber, reactName)),\n null != _instance2 &&\n listeners.push(\n createDispatchListener(targetFiber, _instance2, stateNode)\n ));\n if (3 === targetFiber.tag) return listeners;\n targetFiber = targetFiber.return;\n }\n return [];\n}\nfunction getParent(inst) {\n if (null === inst) return null;\n do inst = inst.return;\n while (inst && 5 !== inst.tag && 27 !== inst.tag);\n return inst ? inst : null;\n}\nfunction accumulateEnterLeaveListenersForEvent(\n dispatchQueue,\n event,\n target,\n common,\n inCapturePhase\n) {\n for (\n var registrationName = event._reactName, listeners = [];\n null !== target && target !== common;\n\n ) {\n var _instance3 = target,\n alternate = _instance3.alternate,\n stateNode = _instance3.stateNode;\n _instance3 = _instance3.tag;\n if (null !== alternate && alternate === common) break;\n (5 !== _instance3 && 26 !== _instance3 && 27 !== _instance3) ||\n null === stateNode ||\n ((alternate = stateNode),\n inCapturePhase\n ? ((stateNode = getListener(target, registrationName)),\n null != stateNode &&\n listeners.unshift(\n createDispatchListener(target, stateNode, alternate)\n ))\n : inCapturePhase ||\n ((stateNode = getListener(target, registrationName)),\n null != stateNode &&\n listeners.push(\n createDispatchListener(target, stateNode, alternate)\n )));\n target = target.return;\n }\n 0 !== listeners.length &&\n dispatchQueue.push({ event: event, listeners: listeners });\n}\nvar NORMALIZE_NEWLINES_REGEX = /\\r\\n?/g,\n NORMALIZE_NULL_AND_REPLACEMENT_REGEX = /\\u0000|\\uFFFD/g;\nfunction normalizeMarkupForTextOrAttribute(markup) {\n return (\"string\" === typeof markup ? markup : \"\" + markup)\n .replace(NORMALIZE_NEWLINES_REGEX, \"\\n\")\n .replace(NORMALIZE_NULL_AND_REPLACEMENT_REGEX, \"\");\n}\nfunction checkForUnmatchedText(serverText, clientText) {\n clientText = normalizeMarkupForTextOrAttribute(clientText);\n return normalizeMarkupForTextOrAttribute(serverText) === clientText ? !0 : !1;\n}\nfunction setProp(domElement, tag, key, value, props, prevValue) {\n switch (key) {\n case \"children\":\n \"string\" === typeof value\n ? \"body\" === tag ||\n (\"textarea\" === tag && \"\" === value) ||\n setTextContent(domElement, value)\n : (\"number\" === typeof value || \"bigint\" === typeof value) &&\n \"body\" !== tag &&\n setTextContent(domElement, \"\" + value);\n break;\n case \"className\":\n setValueForKnownAttribute(domElement, \"class\", value);\n break;\n case \"tabIndex\":\n setValueForKnownAttribute(domElement, \"tabindex\", value);\n break;\n case \"dir\":\n case \"role\":\n case \"viewBox\":\n case \"width\":\n case \"height\":\n setValueForKnownAttribute(domElement, key, value);\n break;\n case \"style\":\n setValueForStyles(domElement, value, prevValue);\n break;\n case \"data\":\n if (\"object\" !== tag) {\n setValueForKnownAttribute(domElement, \"data\", value);\n break;\n }\n case \"src\":\n case \"href\":\n if (\"\" === value && (\"a\" !== tag || \"href\" !== key)) {\n domElement.removeAttribute(key);\n break;\n }\n if (\n null == value ||\n \"function\" === typeof value ||\n \"symbol\" === typeof value ||\n \"boolean\" === typeof value\n ) {\n domElement.removeAttribute(key);\n break;\n }\n value = sanitizeURL(\"\" + value);\n domElement.setAttribute(key, value);\n break;\n case \"action\":\n case \"formAction\":\n if (\"function\" === typeof value) {\n domElement.setAttribute(\n key,\n \"javascript:throw new Error('A React form was unexpectedly submitted. If you called form.submit() manually, consider using form.requestSubmit() instead. If you\\\\'re trying to use event.stopPropagation() in a submit event handler, consider also calling event.preventDefault().')\"\n );\n break;\n } else\n \"function\" === typeof prevValue &&\n (\"formAction\" === key\n ? (\"input\" !== tag &&\n setProp(domElement, tag, \"name\", props.name, props, null),\n setProp(\n domElement,\n tag,\n \"formEncType\",\n props.formEncType,\n props,\n null\n ),\n setProp(\n domElement,\n tag,\n \"formMethod\",\n props.formMethod,\n props,\n null\n ),\n setProp(\n domElement,\n tag,\n \"formTarget\",\n props.formTarget,\n props,\n null\n ))\n : (setProp(domElement, tag, \"encType\", props.encType, props, null),\n setProp(domElement, tag, \"method\", props.method, props, null),\n setProp(domElement, tag, \"target\", props.target, props, null)));\n if (\n null == value ||\n \"symbol\" === typeof value ||\n \"boolean\" === typeof value\n ) {\n domElement.removeAttribute(key);\n break;\n }\n value = sanitizeURL(\"\" + value);\n domElement.setAttribute(key, value);\n break;\n case \"onClick\":\n null != value && (domElement.onclick = noop$1);\n break;\n case \"onScroll\":\n null != value && listenToNonDelegatedEvent(\"scroll\", domElement);\n break;\n case \"onScrollEnd\":\n null != value && listenToNonDelegatedEvent(\"scrollend\", domElement);\n break;\n case \"dangerouslySetInnerHTML\":\n if (null != value) {\n if (\"object\" !== typeof value || !(\"__html\" in value))\n throw Error(formatProdErrorMessage(61));\n key = value.__html;\n if (null != key) {\n if (null != props.children) throw Error(formatProdErrorMessage(60));\n domElement.innerHTML = key;\n }\n }\n break;\n case \"multiple\":\n domElement.multiple =\n value && \"function\" !== typeof value && \"symbol\" !== typeof value;\n break;\n case \"muted\":\n domElement.muted =\n value && \"function\" !== typeof value && \"symbol\" !== typeof value;\n break;\n case \"suppressContentEditableWarning\":\n case \"suppressHydrationWarning\":\n case \"defaultValue\":\n case \"defaultChecked\":\n case \"innerHTML\":\n case \"ref\":\n break;\n case \"autoFocus\":\n break;\n case \"xlinkHref\":\n if (\n null == value ||\n \"function\" === typeof value ||\n \"boolean\" === typeof value ||\n \"symbol\" === typeof value\n ) {\n domElement.removeAttribute(\"xlink:href\");\n break;\n }\n key = sanitizeURL(\"\" + value);\n domElement.setAttributeNS(\n \"http://www.w3.org/1999/xlink\",\n \"xlink:href\",\n key\n );\n break;\n case \"contentEditable\":\n case \"spellCheck\":\n case \"draggable\":\n case \"value\":\n case \"autoReverse\":\n case \"externalResourcesRequired\":\n case \"focusable\":\n case \"preserveAlpha\":\n null != value && \"function\" !== typeof value && \"symbol\" !== typeof value\n ? domElement.setAttribute(key, \"\" + value)\n : domElement.removeAttribute(key);\n break;\n case \"inert\":\n case \"allowFullScreen\":\n case \"async\":\n case \"autoPlay\":\n case \"controls\":\n case \"default\":\n case \"defer\":\n case \"disabled\":\n case \"disablePictureInPicture\":\n case \"disableRemotePlayback\":\n case \"formNoValidate\":\n case \"hidden\":\n case \"loop\":\n case \"noModule\":\n case \"noValidate\":\n case \"open\":\n case \"playsInline\":\n case \"readOnly\":\n case \"required\":\n case \"reversed\":\n case \"scoped\":\n case \"seamless\":\n case \"itemScope\":\n value && \"function\" !== typeof value && \"symbol\" !== typeof value\n ? domElement.setAttribute(key, \"\")\n : domElement.removeAttribute(key);\n break;\n case \"capture\":\n case \"download\":\n !0 === value\n ? domElement.setAttribute(key, \"\")\n : !1 !== value &&\n null != value &&\n \"function\" !== typeof value &&\n \"symbol\" !== typeof value\n ? domElement.setAttribute(key, value)\n : domElement.removeAttribute(key);\n break;\n case \"cols\":\n case \"rows\":\n case \"size\":\n case \"span\":\n null != value &&\n \"function\" !== typeof value &&\n \"symbol\" !== typeof value &&\n !isNaN(value) &&\n 1 <= value\n ? domElement.setAttribute(key, value)\n : domElement.removeAttribute(key);\n break;\n case \"rowSpan\":\n case \"start\":\n null == value ||\n \"function\" === typeof value ||\n \"symbol\" === typeof value ||\n isNaN(value)\n ? domElement.removeAttribute(key)\n : domElement.setAttribute(key, value);\n break;\n case \"popover\":\n listenToNonDelegatedEvent(\"beforetoggle\", domElement);\n listenToNonDelegatedEvent(\"toggle\", domElement);\n setValueForAttribute(domElement, \"popover\", value);\n break;\n case \"xlinkActuate\":\n setValueForNamespacedAttribute(\n domElement,\n \"http://www.w3.org/1999/xlink\",\n \"xlink:actuate\",\n value\n );\n break;\n case \"xlinkArcrole\":\n setValueForNamespacedAttribute(\n domElement,\n \"http://www.w3.org/1999/xlink\",\n \"xlink:arcrole\",\n value\n );\n break;\n case \"xlinkRole\":\n setValueForNamespacedAttribute(\n domElement,\n \"http://www.w3.org/1999/xlink\",\n \"xlink:role\",\n value\n );\n break;\n case \"xlinkShow\":\n setValueForNamespacedAttribute(\n domElement,\n \"http://www.w3.org/1999/xlink\",\n \"xlink:show\",\n value\n );\n break;\n case \"xlinkTitle\":\n setValueForNamespacedAttribute(\n domElement,\n \"http://www.w3.org/1999/xlink\",\n \"xlink:title\",\n value\n );\n break;\n case \"xlinkType\":\n setValueForNamespacedAttribute(\n domElement,\n \"http://www.w3.org/1999/xlink\",\n \"xlink:type\",\n value\n );\n break;\n case \"xmlBase\":\n setValueForNamespacedAttribute(\n domElement,\n \"http://www.w3.org/XML/1998/namespace\",\n \"xml:base\",\n value\n );\n break;\n case \"xmlLang\":\n setValueForNamespacedAttribute(\n domElement,\n \"http://www.w3.org/XML/1998/namespace\",\n \"xml:lang\",\n value\n );\n break;\n case \"xmlSpace\":\n setValueForNamespacedAttribute(\n domElement,\n \"http://www.w3.org/XML/1998/namespace\",\n \"xml:space\",\n value\n );\n break;\n case \"is\":\n setValueForAttribute(domElement, \"is\", value);\n break;\n case \"innerText\":\n case \"textContent\":\n break;\n default:\n if (\n !(2 < key.length) ||\n (\"o\" !== key[0] && \"O\" !== key[0]) ||\n (\"n\" !== key[1] && \"N\" !== key[1])\n )\n (key = aliases.get(key) || key),\n setValueForAttribute(domElement, key, value);\n }\n}\nfunction setPropOnCustomElement(domElement, tag, key, value, props, prevValue) {\n switch (key) {\n case \"style\":\n setValueForStyles(domElement, value, prevValue);\n break;\n case \"dangerouslySetInnerHTML\":\n if (null != value) {\n if (\"object\" !== typeof value || !(\"__html\" in value))\n throw Error(formatProdErrorMessage(61));\n key = value.__html;\n if (null != key) {\n if (null != props.children) throw Error(formatProdErrorMessage(60));\n domElement.innerHTML = key;\n }\n }\n break;\n case \"children\":\n \"string\" === typeof value\n ? setTextContent(domElement, value)\n : (\"number\" === typeof value || \"bigint\" === typeof value) &&\n setTextContent(domElement, \"\" + value);\n break;\n case \"onScroll\":\n null != value && listenToNonDelegatedEvent(\"scroll\", domElement);\n break;\n case \"onScrollEnd\":\n null != value && listenToNonDelegatedEvent(\"scrollend\", domElement);\n break;\n case \"onClick\":\n null != value && (domElement.onclick = noop$1);\n break;\n case \"suppressContentEditableWarning\":\n case \"suppressHydrationWarning\":\n case \"innerHTML\":\n case \"ref\":\n break;\n case \"innerText\":\n case \"textContent\":\n break;\n default:\n if (!registrationNameDependencies.hasOwnProperty(key))\n a: {\n if (\n \"o\" === key[0] &&\n \"n\" === key[1] &&\n ((props = key.endsWith(\"Capture\")),\n (tag = key.slice(2, props ? key.length - 7 : void 0)),\n (prevValue = domElement[internalPropsKey] || null),\n (prevValue = null != prevValue ? prevValue[key] : null),\n \"function\" === typeof prevValue &&\n domElement.removeEventListener(tag, prevValue, props),\n \"function\" === typeof value)\n ) {\n \"function\" !== typeof prevValue &&\n null !== prevValue &&\n (key in domElement\n ? (domElement[key] = null)\n : domElement.hasAttribute(key) &&\n domElement.removeAttribute(key));\n domElement.addEventListener(tag, value, props);\n break a;\n }\n key in domElement\n ? (domElement[key] = value)\n : !0 === value\n ? domElement.setAttribute(key, \"\")\n : setValueForAttribute(domElement, key, value);\n }\n }\n}\nfunction setInitialProperties(domElement, tag, props) {\n switch (tag) {\n case \"div\":\n case \"span\":\n case \"svg\":\n case \"path\":\n case \"a\":\n case \"g\":\n case \"p\":\n case \"li\":\n break;\n case \"img\":\n listenToNonDelegatedEvent(\"error\", domElement);\n listenToNonDelegatedEvent(\"load\", domElement);\n var hasSrc = !1,\n hasSrcSet = !1,\n propKey;\n for (propKey in props)\n if (props.hasOwnProperty(propKey)) {\n var propValue = props[propKey];\n if (null != propValue)\n switch (propKey) {\n case \"src\":\n hasSrc = !0;\n break;\n case \"srcSet\":\n hasSrcSet = !0;\n break;\n case \"children\":\n case \"dangerouslySetInnerHTML\":\n throw Error(formatProdErrorMessage(137, tag));\n default:\n setProp(domElement, tag, propKey, propValue, props, null);\n }\n }\n hasSrcSet &&\n setProp(domElement, tag, \"srcSet\", props.srcSet, props, null);\n hasSrc && setProp(domElement, tag, \"src\", props.src, props, null);\n return;\n case \"input\":\n listenToNonDelegatedEvent(\"invalid\", domElement);\n var defaultValue = (propKey = propValue = hasSrcSet = null),\n checked = null,\n defaultChecked = null;\n for (hasSrc in props)\n if (props.hasOwnProperty(hasSrc)) {\n var propValue$184 = props[hasSrc];\n if (null != propValue$184)\n switch (hasSrc) {\n case \"name\":\n hasSrcSet = propValue$184;\n break;\n case \"type\":\n propValue = propValue$184;\n break;\n case \"checked\":\n checked = propValue$184;\n break;\n case \"defaultChecked\":\n defaultChecked = propValue$184;\n break;\n case \"value\":\n propKey = propValue$184;\n break;\n case \"defaultValue\":\n defaultValue = propValue$184;\n break;\n case \"children\":\n case \"dangerouslySetInnerHTML\":\n if (null != propValue$184)\n throw Error(formatProdErrorMessage(137, tag));\n break;\n default:\n setProp(domElement, tag, hasSrc, propValue$184, props, null);\n }\n }\n initInput(\n domElement,\n propKey,\n defaultValue,\n checked,\n defaultChecked,\n propValue,\n hasSrcSet,\n !1\n );\n return;\n case \"select\":\n listenToNonDelegatedEvent(\"invalid\", domElement);\n hasSrc = propValue = propKey = null;\n for (hasSrcSet in props)\n if (\n props.hasOwnProperty(hasSrcSet) &&\n ((defaultValue = props[hasSrcSet]), null != defaultValue)\n )\n switch (hasSrcSet) {\n case \"value\":\n propKey = defaultValue;\n break;\n case \"defaultValue\":\n propValue = defaultValue;\n break;\n case \"multiple\":\n hasSrc = defaultValue;\n default:\n setProp(domElement, tag, hasSrcSet, defaultValue, props, null);\n }\n tag = propKey;\n props = propValue;\n domElement.multiple = !!hasSrc;\n null != tag\n ? updateOptions(domElement, !!hasSrc, tag, !1)\n : null != props && updateOptions(domElement, !!hasSrc, props, !0);\n return;\n case \"textarea\":\n listenToNonDelegatedEvent(\"invalid\", domElement);\n propKey = hasSrcSet = hasSrc = null;\n for (propValue in props)\n if (\n props.hasOwnProperty(propValue) &&\n ((defaultValue = props[propValue]), null != defaultValue)\n )\n switch (propValue) {\n case \"value\":\n hasSrc = defaultValue;\n break;\n case \"defaultValue\":\n hasSrcSet = defaultValue;\n break;\n case \"children\":\n propKey = defaultValue;\n break;\n case \"dangerouslySetInnerHTML\":\n if (null != defaultValue) throw Error(formatProdErrorMessage(91));\n break;\n default:\n setProp(domElement, tag, propValue, defaultValue, props, null);\n }\n initTextarea(domElement, hasSrc, hasSrcSet, propKey);\n return;\n case \"option\":\n for (checked in props)\n if (\n props.hasOwnProperty(checked) &&\n ((hasSrc = props[checked]), null != hasSrc)\n )\n switch (checked) {\n case \"selected\":\n domElement.selected =\n hasSrc &&\n \"function\" !== typeof hasSrc &&\n \"symbol\" !== typeof hasSrc;\n break;\n default:\n setProp(domElement, tag, checked, hasSrc, props, null);\n }\n return;\n case \"dialog\":\n listenToNonDelegatedEvent(\"beforetoggle\", domElement);\n listenToNonDelegatedEvent(\"toggle\", domElement);\n listenToNonDelegatedEvent(\"cancel\", domElement);\n listenToNonDelegatedEvent(\"close\", domElement);\n break;\n case \"iframe\":\n case \"object\":\n listenToNonDelegatedEvent(\"load\", domElement);\n break;\n case \"video\":\n case \"audio\":\n for (hasSrc = 0; hasSrc < mediaEventTypes.length; hasSrc++)\n listenToNonDelegatedEvent(mediaEventTypes[hasSrc], domElement);\n break;\n case \"image\":\n listenToNonDelegatedEvent(\"error\", domElement);\n listenToNonDelegatedEvent(\"load\", domElement);\n break;\n case \"details\":\n listenToNonDelegatedEvent(\"toggle\", domElement);\n break;\n case \"embed\":\n case \"source\":\n case \"link\":\n listenToNonDelegatedEvent(\"error\", domElement),\n listenToNonDelegatedEvent(\"load\", domElement);\n case \"area\":\n case \"base\":\n case \"br\":\n case \"col\":\n case \"hr\":\n case \"keygen\":\n case \"meta\":\n case \"param\":\n case \"track\":\n case \"wbr\":\n case \"menuitem\":\n for (defaultChecked in props)\n if (\n props.hasOwnProperty(defaultChecked) &&\n ((hasSrc = props[defaultChecked]), null != hasSrc)\n )\n switch (defaultChecked) {\n case \"children\":\n case \"dangerouslySetInnerHTML\":\n throw Error(formatProdErrorMessage(137, tag));\n default:\n setProp(domElement, tag, defaultChecked, hasSrc, props, null);\n }\n return;\n default:\n if (isCustomElement(tag)) {\n for (propValue$184 in props)\n props.hasOwnProperty(propValue$184) &&\n ((hasSrc = props[propValue$184]),\n void 0 !== hasSrc &&\n setPropOnCustomElement(\n domElement,\n tag,\n propValue$184,\n hasSrc,\n props,\n void 0\n ));\n return;\n }\n }\n for (defaultValue in props)\n props.hasOwnProperty(defaultValue) &&\n ((hasSrc = props[defaultValue]),\n null != hasSrc &&\n setProp(domElement, tag, defaultValue, hasSrc, props, null));\n}\nfunction updateProperties(domElement, tag, lastProps, nextProps) {\n switch (tag) {\n case \"div\":\n case \"span\":\n case \"svg\":\n case \"path\":\n case \"a\":\n case \"g\":\n case \"p\":\n case \"li\":\n break;\n case \"input\":\n var name = null,\n type = null,\n value = null,\n defaultValue = null,\n lastDefaultValue = null,\n checked = null,\n defaultChecked = null;\n for (propKey in lastProps) {\n var lastProp = lastProps[propKey];\n if (lastProps.hasOwnProperty(propKey) && null != lastProp)\n switch (propKey) {\n case \"checked\":\n break;\n case \"value\":\n break;\n case \"defaultValue\":\n lastDefaultValue = lastProp;\n default:\n nextProps.hasOwnProperty(propKey) ||\n setProp(domElement, tag, propKey, null, nextProps, lastProp);\n }\n }\n for (var propKey$201 in nextProps) {\n var propKey = nextProps[propKey$201];\n lastProp = lastProps[propKey$201];\n if (\n nextProps.hasOwnProperty(propKey$201) &&\n (null != propKey || null != lastProp)\n )\n switch (propKey$201) {\n case \"type\":\n type = propKey;\n break;\n case \"name\":\n name = propKey;\n break;\n case \"checked\":\n checked = propKey;\n break;\n case \"defaultChecked\":\n defaultChecked = propKey;\n break;\n case \"value\":\n value = propKey;\n break;\n case \"defaultValue\":\n defaultValue = propKey;\n break;\n case \"children\":\n case \"dangerouslySetInnerHTML\":\n if (null != propKey)\n throw Error(formatProdErrorMessage(137, tag));\n break;\n default:\n propKey !== lastProp &&\n setProp(\n domElement,\n tag,\n propKey$201,\n propKey,\n nextProps,\n lastProp\n );\n }\n }\n updateInput(\n domElement,\n value,\n defaultValue,\n lastDefaultValue,\n checked,\n defaultChecked,\n type,\n name\n );\n return;\n case \"select\":\n propKey = value = defaultValue = propKey$201 = null;\n for (type in lastProps)\n if (\n ((lastDefaultValue = lastProps[type]),\n lastProps.hasOwnProperty(type) && null != lastDefaultValue)\n )\n switch (type) {\n case \"value\":\n break;\n case \"multiple\":\n propKey = lastDefaultValue;\n default:\n nextProps.hasOwnProperty(type) ||\n setProp(\n domElement,\n tag,\n type,\n null,\n nextProps,\n lastDefaultValue\n );\n }\n for (name in nextProps)\n if (\n ((type = nextProps[name]),\n (lastDefaultValue = lastProps[name]),\n nextProps.hasOwnProperty(name) &&\n (null != type || null != lastDefaultValue))\n )\n switch (name) {\n case \"value\":\n propKey$201 = type;\n break;\n case \"defaultValue\":\n defaultValue = type;\n break;\n case \"multiple\":\n value = type;\n default:\n type !== lastDefaultValue &&\n setProp(\n domElement,\n tag,\n name,\n type,\n nextProps,\n lastDefaultValue\n );\n }\n tag = defaultValue;\n lastProps = value;\n nextProps = propKey;\n null != propKey$201\n ? updateOptions(domElement, !!lastProps, propKey$201, !1)\n : !!nextProps !== !!lastProps &&\n (null != tag\n ? updateOptions(domElement, !!lastProps, tag, !0)\n : updateOptions(domElement, !!lastProps, lastProps ? [] : \"\", !1));\n return;\n case \"textarea\":\n propKey = propKey$201 = null;\n for (defaultValue in lastProps)\n if (\n ((name = lastProps[defaultValue]),\n lastProps.hasOwnProperty(defaultValue) &&\n null != name &&\n !nextProps.hasOwnProperty(defaultValue))\n )\n switch (defaultValue) {\n case \"value\":\n break;\n case \"children\":\n break;\n default:\n setProp(domElement, tag, defaultValue, null, nextProps, name);\n }\n for (value in nextProps)\n if (\n ((name = nextProps[value]),\n (type = lastProps[value]),\n nextProps.hasOwnProperty(value) && (null != name || null != type))\n )\n switch (value) {\n case \"value\":\n propKey$201 = name;\n break;\n case \"defaultValue\":\n propKey = name;\n break;\n case \"children\":\n break;\n case \"dangerouslySetInnerHTML\":\n if (null != name) throw Error(formatProdErrorMessage(91));\n break;\n default:\n name !== type &&\n setProp(domElement, tag, value, name, nextProps, type);\n }\n updateTextarea(domElement, propKey$201, propKey);\n return;\n case \"option\":\n for (var propKey$217 in lastProps)\n if (\n ((propKey$201 = lastProps[propKey$217]),\n lastProps.hasOwnProperty(propKey$217) &&\n null != propKey$201 &&\n !nextProps.hasOwnProperty(propKey$217))\n )\n switch (propKey$217) {\n case \"selected\":\n domElement.selected = !1;\n break;\n default:\n setProp(\n domElement,\n tag,\n propKey$217,\n null,\n nextProps,\n propKey$201\n );\n }\n for (lastDefaultValue in nextProps)\n if (\n ((propKey$201 = nextProps[lastDefaultValue]),\n (propKey = lastProps[lastDefaultValue]),\n nextProps.hasOwnProperty(lastDefaultValue) &&\n propKey$201 !== propKey &&\n (null != propKey$201 || null != propKey))\n )\n switch (lastDefaultValue) {\n case \"selected\":\n domElement.selected =\n propKey$201 &&\n \"function\" !== typeof propKey$201 &&\n \"symbol\" !== typeof propKey$201;\n break;\n default:\n setProp(\n domElement,\n tag,\n lastDefaultValue,\n propKey$201,\n nextProps,\n propKey\n );\n }\n return;\n case \"img\":\n case \"link\":\n case \"area\":\n case \"base\":\n case \"br\":\n case \"col\":\n case \"embed\":\n case \"hr\":\n case \"keygen\":\n case \"meta\":\n case \"param\":\n case \"source\":\n case \"track\":\n case \"wbr\":\n case \"menuitem\":\n for (var propKey$222 in lastProps)\n (propKey$201 = lastProps[propKey$222]),\n lastProps.hasOwnProperty(propKey$222) &&\n null != propKey$201 &&\n !nextProps.hasOwnProperty(propKey$222) &&\n setProp(domElement, tag, propKey$222, null, nextProps, propKey$201);\n for (checked in nextProps)\n if (\n ((propKey$201 = nextProps[checked]),\n (propKey = lastProps[checked]),\n nextProps.hasOwnProperty(checked) &&\n propKey$201 !== propKey &&\n (null != propKey$201 || null != propKey))\n )\n switch (checked) {\n case \"children\":\n case \"dangerouslySetInnerHTML\":\n if (null != propKey$201)\n throw Error(formatProdErrorMessage(137, tag));\n break;\n default:\n setProp(\n domElement,\n tag,\n checked,\n propKey$201,\n nextProps,\n propKey\n );\n }\n return;\n default:\n if (isCustomElement(tag)) {\n for (var propKey$227 in lastProps)\n (propKey$201 = lastProps[propKey$227]),\n lastProps.hasOwnProperty(propKey$227) &&\n void 0 !== propKey$201 &&\n !nextProps.hasOwnProperty(propKey$227) &&\n setPropOnCustomElement(\n domElement,\n tag,\n propKey$227,\n void 0,\n nextProps,\n propKey$201\n );\n for (defaultChecked in nextProps)\n (propKey$201 = nextProps[defaultChecked]),\n (propKey = lastProps[defaultChecked]),\n !nextProps.hasOwnProperty(defaultChecked) ||\n propKey$201 === propKey ||\n (void 0 === propKey$201 && void 0 === propKey) ||\n setPropOnCustomElement(\n domElement,\n tag,\n defaultChecked,\n propKey$201,\n nextProps,\n propKey\n );\n return;\n }\n }\n for (var propKey$232 in lastProps)\n (propKey$201 = lastProps[propKey$232]),\n lastProps.hasOwnProperty(propKey$232) &&\n null != propKey$201 &&\n !nextProps.hasOwnProperty(propKey$232) &&\n setProp(domElement, tag, propKey$232, null, nextProps, propKey$201);\n for (lastProp in nextProps)\n (propKey$201 = nextProps[lastProp]),\n (propKey = lastProps[lastProp]),\n !nextProps.hasOwnProperty(lastProp) ||\n propKey$201 === propKey ||\n (null == propKey$201 && null == propKey) ||\n setProp(domElement, tag, lastProp, propKey$201, nextProps, propKey);\n}\nfunction isLikelyStaticResource(initiatorType) {\n switch (initiatorType) {\n case \"css\":\n case \"script\":\n case \"font\":\n case \"img\":\n case \"image\":\n case \"input\":\n case \"link\":\n return !0;\n default:\n return !1;\n }\n}\nfunction estimateBandwidth() {\n if (\"function\" === typeof performance.getEntriesByType) {\n for (\n var count = 0,\n bits = 0,\n resourceEntries = performance.getEntriesByType(\"resource\"),\n i = 0;\n i < resourceEntries.length;\n i++\n ) {\n var entry = resourceEntries[i],\n transferSize = entry.transferSize,\n initiatorType = entry.initiatorType,\n duration = entry.duration;\n if (transferSize && duration && isLikelyStaticResource(initiatorType)) {\n initiatorType = 0;\n duration = entry.responseEnd;\n for (i += 1; i < resourceEntries.length; i++) {\n var overlapEntry = resourceEntries[i],\n overlapStartTime = overlapEntry.startTime;\n if (overlapStartTime > duration) break;\n var overlapTransferSize = overlapEntry.transferSize,\n overlapInitiatorType = overlapEntry.initiatorType;\n overlapTransferSize &&\n isLikelyStaticResource(overlapInitiatorType) &&\n ((overlapEntry = overlapEntry.responseEnd),\n (initiatorType +=\n overlapTransferSize *\n (overlapEntry < duration\n ? 1\n : (duration - overlapStartTime) /\n (overlapEntry - overlapStartTime))));\n }\n --i;\n bits += (8 * (transferSize + initiatorType)) / (entry.duration / 1e3);\n count++;\n if (10 < count) break;\n }\n }\n if (0 < count) return bits / count / 1e6;\n }\n return navigator.connection &&\n ((count = navigator.connection.downlink), \"number\" === typeof count)\n ? count\n : 5;\n}\nvar eventsEnabled = null,\n selectionInformation = null;\nfunction getOwnerDocumentFromRootContainer(rootContainerElement) {\n return 9 === rootContainerElement.nodeType\n ? rootContainerElement\n : rootContainerElement.ownerDocument;\n}\nfunction getOwnHostContext(namespaceURI) {\n switch (namespaceURI) {\n case \"http://www.w3.org/2000/svg\":\n return 1;\n case \"http://www.w3.org/1998/Math/MathML\":\n return 2;\n default:\n return 0;\n }\n}\nfunction getChildHostContextProd(parentNamespace, type) {\n if (0 === parentNamespace)\n switch (type) {\n case \"svg\":\n return 1;\n case \"math\":\n return 2;\n default:\n return 0;\n }\n return 1 === parentNamespace && \"foreignObject\" === type\n ? 0\n : parentNamespace;\n}\nfunction shouldSetTextContent(type, props) {\n return (\n \"textarea\" === type ||\n \"noscript\" === type ||\n \"string\" === typeof props.children ||\n \"number\" === typeof props.children ||\n \"bigint\" === typeof props.children ||\n (\"object\" === typeof props.dangerouslySetInnerHTML &&\n null !== props.dangerouslySetInnerHTML &&\n null != props.dangerouslySetInnerHTML.__html)\n );\n}\nvar currentPopstateTransitionEvent = null;\nfunction shouldAttemptEagerTransition() {\n var event = window.event;\n if (event && \"popstate\" === event.type) {\n if (event === currentPopstateTransitionEvent) return !1;\n currentPopstateTransitionEvent = event;\n return !0;\n }\n currentPopstateTransitionEvent = null;\n return !1;\n}\nvar scheduleTimeout = \"function\" === typeof setTimeout ? setTimeout : void 0,\n cancelTimeout = \"function\" === typeof clearTimeout ? clearTimeout : void 0,\n localPromise = \"function\" === typeof Promise ? Promise : void 0,\n scheduleMicrotask =\n \"function\" === typeof queueMicrotask\n ? queueMicrotask\n : \"undefined\" !== typeof localPromise\n ? function (callback) {\n return localPromise\n .resolve(null)\n .then(callback)\n .catch(handleErrorInNextTick);\n }\n : scheduleTimeout;\nfunction handleErrorInNextTick(error) {\n setTimeout(function () {\n throw error;\n });\n}\nfunction isSingletonScope(type) {\n return \"head\" === type;\n}\nfunction clearHydrationBoundary(parentInstance, hydrationInstance) {\n var node = hydrationInstance,\n depth = 0;\n do {\n var nextNode = node.nextSibling;\n parentInstance.removeChild(node);\n if (nextNode && 8 === nextNode.nodeType)\n if (((node = nextNode.data), \"/$\" === node || \"/&\" === node)) {\n if (0 === depth) {\n parentInstance.removeChild(nextNode);\n retryIfBlockedOn(hydrationInstance);\n return;\n }\n depth--;\n } else if (\n \"$\" === node ||\n \"$?\" === node ||\n \"$~\" === node ||\n \"$!\" === node ||\n \"&\" === node\n )\n depth++;\n else if (\"html\" === node)\n releaseSingletonInstance(parentInstance.ownerDocument.documentElement);\n else if (\"head\" === node) {\n node = parentInstance.ownerDocument.head;\n releaseSingletonInstance(node);\n for (var node$jscomp$0 = node.firstChild; node$jscomp$0; ) {\n var nextNode$jscomp$0 = node$jscomp$0.nextSibling,\n nodeName = node$jscomp$0.nodeName;\n node$jscomp$0[internalHoistableMarker] ||\n \"SCRIPT\" === nodeName ||\n \"STYLE\" === nodeName ||\n (\"LINK\" === nodeName &&\n \"stylesheet\" === node$jscomp$0.rel.toLowerCase()) ||\n node.removeChild(node$jscomp$0);\n node$jscomp$0 = nextNode$jscomp$0;\n }\n } else\n \"body\" === node &&\n releaseSingletonInstance(parentInstance.ownerDocument.body);\n node = nextNode;\n } while (node);\n retryIfBlockedOn(hydrationInstance);\n}\nfunction hideOrUnhideDehydratedBoundary(suspenseInstance, isHidden) {\n var node = suspenseInstance;\n suspenseInstance = 0;\n do {\n var nextNode = node.nextSibling;\n 1 === node.nodeType\n ? isHidden\n ? ((node._stashedDisplay = node.style.display),\n (node.style.display = \"none\"))\n : ((node.style.display = node._stashedDisplay || \"\"),\n \"\" === node.getAttribute(\"style\") && node.removeAttribute(\"style\"))\n : 3 === node.nodeType &&\n (isHidden\n ? ((node._stashedText = node.nodeValue), (node.nodeValue = \"\"))\n : (node.nodeValue = node._stashedText || \"\"));\n if (nextNode && 8 === nextNode.nodeType)\n if (((node = nextNode.data), \"/$\" === node))\n if (0 === suspenseInstance) break;\n else suspenseInstance--;\n else\n (\"$\" !== node && \"$?\" !== node && \"$~\" !== node && \"$!\" !== node) ||\n suspenseInstance++;\n node = nextNode;\n } while (node);\n}\nfunction clearContainerSparingly(container) {\n var nextNode = container.firstChild;\n nextNode && 10 === nextNode.nodeType && (nextNode = nextNode.nextSibling);\n for (; nextNode; ) {\n var node = nextNode;\n nextNode = nextNode.nextSibling;\n switch (node.nodeName) {\n case \"HTML\":\n case \"HEAD\":\n case \"BODY\":\n clearContainerSparingly(node);\n detachDeletedInstance(node);\n continue;\n case \"SCRIPT\":\n case \"STYLE\":\n continue;\n case \"LINK\":\n if (\"stylesheet\" === node.rel.toLowerCase()) continue;\n }\n container.removeChild(node);\n }\n}\nfunction canHydrateInstance(instance, type, props, inRootOrSingleton) {\n for (; 1 === instance.nodeType; ) {\n var anyProps = props;\n if (instance.nodeName.toLowerCase() !== type.toLowerCase()) {\n if (\n !inRootOrSingleton &&\n (\"INPUT\" !== instance.nodeName || \"hidden\" !== instance.type)\n )\n break;\n } else if (!inRootOrSingleton)\n if (\"input\" === type && \"hidden\" === instance.type) {\n var name = null == anyProps.name ? null : \"\" + anyProps.name;\n if (\n \"hidden\" === anyProps.type &&\n instance.getAttribute(\"name\") === name\n )\n return instance;\n } else return instance;\n else if (!instance[internalHoistableMarker])\n switch (type) {\n case \"meta\":\n if (!instance.hasAttribute(\"itemprop\")) break;\n return instance;\n case \"link\":\n name = instance.getAttribute(\"rel\");\n if (\"stylesheet\" === name && instance.hasAttribute(\"data-precedence\"))\n break;\n else if (\n name !== anyProps.rel ||\n instance.getAttribute(\"href\") !==\n (null == anyProps.href || \"\" === anyProps.href\n ? null\n : anyProps.href) ||\n instance.getAttribute(\"crossorigin\") !==\n (null == anyProps.crossOrigin ? null : anyProps.crossOrigin) ||\n instance.getAttribute(\"title\") !==\n (null == anyProps.title ? null : anyProps.title)\n )\n break;\n return instance;\n case \"style\":\n if (instance.hasAttribute(\"data-precedence\")) break;\n return instance;\n case \"script\":\n name = instance.getAttribute(\"src\");\n if (\n (name !== (null == anyProps.src ? null : anyProps.src) ||\n instance.getAttribute(\"type\") !==\n (null == anyProps.type ? null : anyProps.type) ||\n instance.getAttribute(\"crossorigin\") !==\n (null == anyProps.crossOrigin ? null : anyProps.crossOrigin)) &&\n name &&\n instance.hasAttribute(\"async\") &&\n !instance.hasAttribute(\"itemprop\")\n )\n break;\n return instance;\n default:\n return instance;\n }\n instance = getNextHydratable(instance.nextSibling);\n if (null === instance) break;\n }\n return null;\n}\nfunction canHydrateTextInstance(instance, text, inRootOrSingleton) {\n if (\"\" === text) return null;\n for (; 3 !== instance.nodeType; ) {\n if (\n (1 !== instance.nodeType ||\n \"INPUT\" !== instance.nodeName ||\n \"hidden\" !== instance.type) &&\n !inRootOrSingleton\n )\n return null;\n instance = getNextHydratable(instance.nextSibling);\n if (null === instance) return null;\n }\n return instance;\n}\nfunction canHydrateHydrationBoundary(instance, inRootOrSingleton) {\n for (; 8 !== instance.nodeType; ) {\n if (\n (1 !== instance.nodeType ||\n \"INPUT\" !== instance.nodeName ||\n \"hidden\" !== instance.type) &&\n !inRootOrSingleton\n )\n return null;\n instance = getNextHydratable(instance.nextSibling);\n if (null === instance) return null;\n }\n return instance;\n}\nfunction isSuspenseInstancePending(instance) {\n return \"$?\" === instance.data || \"$~\" === instance.data;\n}\nfunction isSuspenseInstanceFallback(instance) {\n return (\n \"$!\" === instance.data ||\n (\"$?\" === instance.data && \"loading\" !== instance.ownerDocument.readyState)\n );\n}\nfunction registerSuspenseInstanceRetry(instance, callback) {\n var ownerDocument = instance.ownerDocument;\n if (\"$~\" === instance.data) instance._reactRetry = callback;\n else if (\"$?\" !== instance.data || \"loading\" !== ownerDocument.readyState)\n callback();\n else {\n var listener = function () {\n callback();\n ownerDocument.removeEventListener(\"DOMContentLoaded\", listener);\n };\n ownerDocument.addEventListener(\"DOMContentLoaded\", listener);\n instance._reactRetry = listener;\n }\n}\nfunction getNextHydratable(node) {\n for (; null != node; node = node.nextSibling) {\n var nodeType = node.nodeType;\n if (1 === nodeType || 3 === nodeType) break;\n if (8 === nodeType) {\n nodeType = node.data;\n if (\n \"$\" === nodeType ||\n \"$!\" === nodeType ||\n \"$?\" === nodeType ||\n \"$~\" === nodeType ||\n \"&\" === nodeType ||\n \"F!\" === nodeType ||\n \"F\" === nodeType\n )\n break;\n if (\"/$\" === nodeType || \"/&\" === nodeType) return null;\n }\n }\n return node;\n}\nvar previousHydratableOnEnteringScopedSingleton = null;\nfunction getNextHydratableInstanceAfterHydrationBoundary(hydrationInstance) {\n hydrationInstance = hydrationInstance.nextSibling;\n for (var depth = 0; hydrationInstance; ) {\n if (8 === hydrationInstance.nodeType) {\n var data = hydrationInstance.data;\n if (\"/$\" === data || \"/&\" === data) {\n if (0 === depth)\n return getNextHydratable(hydrationInstance.nextSibling);\n depth--;\n } else\n (\"$\" !== data &&\n \"$!\" !== data &&\n \"$?\" !== data &&\n \"$~\" !== data &&\n \"&\" !== data) ||\n depth++;\n }\n hydrationInstance = hydrationInstance.nextSibling;\n }\n return null;\n}\nfunction getParentHydrationBoundary(targetInstance) {\n targetInstance = targetInstance.previousSibling;\n for (var depth = 0; targetInstance; ) {\n if (8 === targetInstance.nodeType) {\n var data = targetInstance.data;\n if (\n \"$\" === data ||\n \"$!\" === data ||\n \"$?\" === data ||\n \"$~\" === data ||\n \"&\" === data\n ) {\n if (0 === depth) return targetInstance;\n depth--;\n } else (\"/$\" !== data && \"/&\" !== data) || depth++;\n }\n targetInstance = targetInstance.previousSibling;\n }\n return null;\n}\nfunction resolveSingletonInstance(type, props, rootContainerInstance) {\n props = getOwnerDocumentFromRootContainer(rootContainerInstance);\n switch (type) {\n case \"html\":\n type = props.documentElement;\n if (!type) throw Error(formatProdErrorMessage(452));\n return type;\n case \"head\":\n type = props.head;\n if (!type) throw Error(formatProdErrorMessage(453));\n return type;\n case \"body\":\n type = props.body;\n if (!type) throw Error(formatProdErrorMessage(454));\n return type;\n default:\n throw Error(formatProdErrorMessage(451));\n }\n}\nfunction releaseSingletonInstance(instance) {\n for (var attributes = instance.attributes; attributes.length; )\n instance.removeAttributeNode(attributes[0]);\n detachDeletedInstance(instance);\n}\nvar preloadPropsMap = new Map(),\n preconnectsSet = new Set();\nfunction getHoistableRoot(container) {\n return \"function\" === typeof container.getRootNode\n ? container.getRootNode()\n : 9 === container.nodeType\n ? container\n : container.ownerDocument;\n}\nvar previousDispatcher = ReactDOMSharedInternals.d;\nReactDOMSharedInternals.d = {\n f: flushSyncWork,\n r: requestFormReset,\n D: prefetchDNS,\n C: preconnect,\n L: preload,\n m: preloadModule,\n X: preinitScript,\n S: preinitStyle,\n M: preinitModuleScript\n};\nfunction flushSyncWork() {\n var previousWasRendering = previousDispatcher.f(),\n wasRendering = flushSyncWork$1();\n return previousWasRendering || wasRendering;\n}\nfunction requestFormReset(form) {\n var formInst = getInstanceFromNode(form);\n null !== formInst && 5 === formInst.tag && \"form\" === formInst.type\n ? requestFormReset$1(formInst)\n : previousDispatcher.r(form);\n}\nvar globalDocument = \"undefined\" === typeof document ? null : document;\nfunction preconnectAs(rel, href, crossOrigin) {\n var ownerDocument = globalDocument;\n if (ownerDocument && \"string\" === typeof href && href) {\n var limitedEscapedHref =\n escapeSelectorAttributeValueInsideDoubleQuotes(href);\n limitedEscapedHref =\n 'link[rel=\"' + rel + '\"][href=\"' + limitedEscapedHref + '\"]';\n \"string\" === typeof crossOrigin &&\n (limitedEscapedHref += '[crossorigin=\"' + crossOrigin + '\"]');\n preconnectsSet.has(limitedEscapedHref) ||\n (preconnectsSet.add(limitedEscapedHref),\n (rel = { rel: rel, crossOrigin: crossOrigin, href: href }),\n null === ownerDocument.querySelector(limitedEscapedHref) &&\n ((href = ownerDocument.createElement(\"link\")),\n setInitialProperties(href, \"link\", rel),\n markNodeAsHoistable(href),\n ownerDocument.head.appendChild(href)));\n }\n}\nfunction prefetchDNS(href) {\n previousDispatcher.D(href);\n preconnectAs(\"dns-prefetch\", href, null);\n}\nfunction preconnect(href, crossOrigin) {\n previousDispatcher.C(href, crossOrigin);\n preconnectAs(\"preconnect\", href, crossOrigin);\n}\nfunction preload(href, as, options) {\n previousDispatcher.L(href, as, options);\n var ownerDocument = globalDocument;\n if (ownerDocument && href && as) {\n var preloadSelector =\n 'link[rel=\"preload\"][as=\"' +\n escapeSelectorAttributeValueInsideDoubleQuotes(as) +\n '\"]';\n \"image\" === as\n ? options && options.imageSrcSet\n ? ((preloadSelector +=\n '[imagesrcset=\"' +\n escapeSelectorAttributeValueInsideDoubleQuotes(\n options.imageSrcSet\n ) +\n '\"]'),\n \"string\" === typeof options.imageSizes &&\n (preloadSelector +=\n '[imagesizes=\"' +\n escapeSelectorAttributeValueInsideDoubleQuotes(\n options.imageSizes\n ) +\n '\"]'))\n : (preloadSelector +=\n '[href=\"' +\n escapeSelectorAttributeValueInsideDoubleQuotes(href) +\n '\"]')\n : (preloadSelector +=\n '[href=\"' +\n escapeSelectorAttributeValueInsideDoubleQuotes(href) +\n '\"]');\n var key = preloadSelector;\n switch (as) {\n case \"style\":\n key = getStyleKey(href);\n break;\n case \"script\":\n key = getScriptKey(href);\n }\n preloadPropsMap.has(key) ||\n ((href = assign(\n {\n rel: \"preload\",\n href:\n \"image\" === as && options && options.imageSrcSet ? void 0 : href,\n as: as\n },\n options\n )),\n preloadPropsMap.set(key, href),\n null !== ownerDocument.querySelector(preloadSelector) ||\n (\"style\" === as &&\n ownerDocument.querySelector(getStylesheetSelectorFromKey(key))) ||\n (\"script\" === as &&\n ownerDocument.querySelector(getScriptSelectorFromKey(key))) ||\n ((as = ownerDocument.createElement(\"link\")),\n setInitialProperties(as, \"link\", href),\n markNodeAsHoistable(as),\n ownerDocument.head.appendChild(as)));\n }\n}\nfunction preloadModule(href, options) {\n previousDispatcher.m(href, options);\n var ownerDocument = globalDocument;\n if (ownerDocument && href) {\n var as = options && \"string\" === typeof options.as ? options.as : \"script\",\n preloadSelector =\n 'link[rel=\"modulepreload\"][as=\"' +\n escapeSelectorAttributeValueInsideDoubleQuotes(as) +\n '\"][href=\"' +\n escapeSelectorAttributeValueInsideDoubleQuotes(href) +\n '\"]',\n key = preloadSelector;\n switch (as) {\n case \"audioworklet\":\n case \"paintworklet\":\n case \"serviceworker\":\n case \"sharedworker\":\n case \"worker\":\n case \"script\":\n key = getScriptKey(href);\n }\n if (\n !preloadPropsMap.has(key) &&\n ((href = assign({ rel: \"modulepreload\", href: href }, options)),\n preloadPropsMap.set(key, href),\n null === ownerDocument.querySelector(preloadSelector))\n ) {\n switch (as) {\n case \"audioworklet\":\n case \"paintworklet\":\n case \"serviceworker\":\n case \"sharedworker\":\n case \"worker\":\n case \"script\":\n if (ownerDocument.querySelector(getScriptSelectorFromKey(key)))\n return;\n }\n as = ownerDocument.createElement(\"link\");\n setInitialProperties(as, \"link\", href);\n markNodeAsHoistable(as);\n ownerDocument.head.appendChild(as);\n }\n }\n}\nfunction preinitStyle(href, precedence, options) {\n previousDispatcher.S(href, precedence, options);\n var ownerDocument = globalDocument;\n if (ownerDocument && href) {\n var styles = getResourcesFromRoot(ownerDocument).hoistableStyles,\n key = getStyleKey(href);\n precedence = precedence || \"default\";\n var resource = styles.get(key);\n if (!resource) {\n var state = { loading: 0, preload: null };\n if (\n (resource = ownerDocument.querySelector(\n getStylesheetSelectorFromKey(key)\n ))\n )\n state.loading = 5;\n else {\n href = assign(\n { rel: \"stylesheet\", href: href, \"data-precedence\": precedence },\n options\n );\n (options = preloadPropsMap.get(key)) &&\n adoptPreloadPropsForStylesheet(href, options);\n var link = (resource = ownerDocument.createElement(\"link\"));\n markNodeAsHoistable(link);\n setInitialProperties(link, \"link\", href);\n link._p = new Promise(function (resolve, reject) {\n link.onload = resolve;\n link.onerror = reject;\n });\n link.addEventListener(\"load\", function () {\n state.loading |= 1;\n });\n link.addEventListener(\"error\", function () {\n state.loading |= 2;\n });\n state.loading |= 4;\n insertStylesheet(resource, precedence, ownerDocument);\n }\n resource = {\n type: \"stylesheet\",\n instance: resource,\n count: 1,\n state: state\n };\n styles.set(key, resource);\n }\n }\n}\nfunction preinitScript(src, options) {\n previousDispatcher.X(src, options);\n var ownerDocument = globalDocument;\n if (ownerDocument && src) {\n var scripts = getResourcesFromRoot(ownerDocument).hoistableScripts,\n key = getScriptKey(src),\n resource = scripts.get(key);\n resource ||\n ((resource = ownerDocument.querySelector(getScriptSelectorFromKey(key))),\n resource ||\n ((src = assign({ src: src, async: !0 }, options)),\n (options = preloadPropsMap.get(key)) &&\n adoptPreloadPropsForScript(src, options),\n (resource = ownerDocument.createElement(\"script\")),\n markNodeAsHoistable(resource),\n setInitialProperties(resource, \"link\", src),\n ownerDocument.head.appendChild(resource)),\n (resource = {\n type: \"script\",\n instance: resource,\n count: 1,\n state: null\n }),\n scripts.set(key, resource));\n }\n}\nfunction preinitModuleScript(src, options) {\n previousDispatcher.M(src, options);\n var ownerDocument = globalDocument;\n if (ownerDocument && src) {\n var scripts = getResourcesFromRoot(ownerDocument).hoistableScripts,\n key = getScriptKey(src),\n resource = scripts.get(key);\n resource ||\n ((resource = ownerDocument.querySelector(getScriptSelectorFromKey(key))),\n resource ||\n ((src = assign({ src: src, async: !0, type: \"module\" }, options)),\n (options = preloadPropsMap.get(key)) &&\n adoptPreloadPropsForScript(src, options),\n (resource = ownerDocument.createElement(\"script\")),\n markNodeAsHoistable(resource),\n setInitialProperties(resource, \"link\", src),\n ownerDocument.head.appendChild(resource)),\n (resource = {\n type: \"script\",\n instance: resource,\n count: 1,\n state: null\n }),\n scripts.set(key, resource));\n }\n}\nfunction getResource(type, currentProps, pendingProps, currentResource) {\n var JSCompiler_inline_result = (JSCompiler_inline_result =\n rootInstanceStackCursor.current)\n ? getHoistableRoot(JSCompiler_inline_result)\n : null;\n if (!JSCompiler_inline_result) throw Error(formatProdErrorMessage(446));\n switch (type) {\n case \"meta\":\n case \"title\":\n return null;\n case \"style\":\n return \"string\" === typeof pendingProps.precedence &&\n \"string\" === typeof pendingProps.href\n ? ((currentProps = getStyleKey(pendingProps.href)),\n (pendingProps = getResourcesFromRoot(\n JSCompiler_inline_result\n ).hoistableStyles),\n (currentResource = pendingProps.get(currentProps)),\n currentResource ||\n ((currentResource = {\n type: \"style\",\n instance: null,\n count: 0,\n state: null\n }),\n pendingProps.set(currentProps, currentResource)),\n currentResource)\n : { type: \"void\", instance: null, count: 0, state: null };\n case \"link\":\n if (\n \"stylesheet\" === pendingProps.rel &&\n \"string\" === typeof pendingProps.href &&\n \"string\" === typeof pendingProps.precedence\n ) {\n type = getStyleKey(pendingProps.href);\n var styles$243 = getResourcesFromRoot(\n JSCompiler_inline_result\n ).hoistableStyles,\n resource$244 = styles$243.get(type);\n resource$244 ||\n ((JSCompiler_inline_result =\n JSCompiler_inline_result.ownerDocument || JSCompiler_inline_result),\n (resource$244 = {\n type: \"stylesheet\",\n instance: null,\n count: 0,\n state: { loading: 0, preload: null }\n }),\n styles$243.set(type, resource$244),\n (styles$243 = JSCompiler_inline_result.querySelector(\n getStylesheetSelectorFromKey(type)\n )) &&\n !styles$243._p &&\n ((resource$244.instance = styles$243),\n (resource$244.state.loading = 5)),\n preloadPropsMap.has(type) ||\n ((pendingProps = {\n rel: \"preload\",\n as: \"style\",\n href: pendingProps.href,\n crossOrigin: pendingProps.crossOrigin,\n integrity: pendingProps.integrity,\n media: pendingProps.media,\n hrefLang: pendingProps.hrefLang,\n referrerPolicy: pendingProps.referrerPolicy\n }),\n preloadPropsMap.set(type, pendingProps),\n styles$243 ||\n preloadStylesheet(\n JSCompiler_inline_result,\n type,\n pendingProps,\n resource$244.state\n )));\n if (currentProps && null === currentResource)\n throw Error(formatProdErrorMessage(528, \"\"));\n return resource$244;\n }\n if (currentProps && null !== currentResource)\n throw Error(formatProdErrorMessage(529, \"\"));\n return null;\n case \"script\":\n return (\n (currentProps = pendingProps.async),\n (pendingProps = pendingProps.src),\n \"string\" === typeof pendingProps &&\n currentProps &&\n \"function\" !== typeof currentProps &&\n \"symbol\" !== typeof currentProps\n ? ((currentProps = getScriptKey(pendingProps)),\n (pendingProps = getResourcesFromRoot(\n JSCompiler_inline_result\n ).hoistableScripts),\n (currentResource = pendingProps.get(currentProps)),\n currentResource ||\n ((currentResource = {\n type: \"script\",\n instance: null,\n count: 0,\n state: null\n }),\n pendingProps.set(currentProps, currentResource)),\n currentResource)\n : { type: \"void\", instance: null, count: 0, state: null }\n );\n default:\n throw Error(formatProdErrorMessage(444, type));\n }\n}\nfunction getStyleKey(href) {\n return 'href=\"' + escapeSelectorAttributeValueInsideDoubleQuotes(href) + '\"';\n}\nfunction getStylesheetSelectorFromKey(key) {\n return 'link[rel=\"stylesheet\"][' + key + \"]\";\n}\nfunction stylesheetPropsFromRawProps(rawProps) {\n return assign({}, rawProps, {\n \"data-precedence\": rawProps.precedence,\n precedence: null\n });\n}\nfunction preloadStylesheet(ownerDocument, key, preloadProps, state) {\n ownerDocument.querySelector('link[rel=\"preload\"][as=\"style\"][' + key + \"]\")\n ? (state.loading = 1)\n : ((key = ownerDocument.createElement(\"link\")),\n (state.preload = key),\n key.addEventListener(\"load\", function () {\n return (state.loading |= 1);\n }),\n key.addEventListener(\"error\", function () {\n return (state.loading |= 2);\n }),\n setInitialProperties(key, \"link\", preloadProps),\n markNodeAsHoistable(key),\n ownerDocument.head.appendChild(key));\n}\nfunction getScriptKey(src) {\n return '[src=\"' + escapeSelectorAttributeValueInsideDoubleQuotes(src) + '\"]';\n}\nfunction getScriptSelectorFromKey(key) {\n return \"script[async]\" + key;\n}\nfunction acquireResource(hoistableRoot, resource, props) {\n resource.count++;\n if (null === resource.instance)\n switch (resource.type) {\n case \"style\":\n var instance = hoistableRoot.querySelector(\n 'style[data-href~=\"' +\n escapeSelectorAttributeValueInsideDoubleQuotes(props.href) +\n '\"]'\n );\n if (instance)\n return (\n (resource.instance = instance),\n markNodeAsHoistable(instance),\n instance\n );\n var styleProps = assign({}, props, {\n \"data-href\": props.href,\n \"data-precedence\": props.precedence,\n href: null,\n precedence: null\n });\n instance = (hoistableRoot.ownerDocument || hoistableRoot).createElement(\n \"style\"\n );\n markNodeAsHoistable(instance);\n setInitialProperties(instance, \"style\", styleProps);\n insertStylesheet(instance, props.precedence, hoistableRoot);\n return (resource.instance = instance);\n case \"stylesheet\":\n styleProps = getStyleKey(props.href);\n var instance$249 = hoistableRoot.querySelector(\n getStylesheetSelectorFromKey(styleProps)\n );\n if (instance$249)\n return (\n (resource.state.loading |= 4),\n (resource.instance = instance$249),\n markNodeAsHoistable(instance$249),\n instance$249\n );\n instance = stylesheetPropsFromRawProps(props);\n (styleProps = preloadPropsMap.get(styleProps)) &&\n adoptPreloadPropsForStylesheet(instance, styleProps);\n instance$249 = (\n hoistableRoot.ownerDocument || hoistableRoot\n ).createElement(\"link\");\n markNodeAsHoistable(instance$249);\n var linkInstance = instance$249;\n linkInstance._p = new Promise(function (resolve, reject) {\n linkInstance.onload = resolve;\n linkInstance.onerror = reject;\n });\n setInitialProperties(instance$249, \"link\", instance);\n resource.state.loading |= 4;\n insertStylesheet(instance$249, props.precedence, hoistableRoot);\n return (resource.instance = instance$249);\n case \"script\":\n instance$249 = getScriptKey(props.src);\n if (\n (styleProps = hoistableRoot.querySelector(\n getScriptSelectorFromKey(instance$249)\n ))\n )\n return (\n (resource.instance = styleProps),\n markNodeAsHoistable(styleProps),\n styleProps\n );\n instance = props;\n if ((styleProps = preloadPropsMap.get(instance$249)))\n (instance = assign({}, props)),\n adoptPreloadPropsForScript(instance, styleProps);\n hoistableRoot = hoistableRoot.ownerDocument || hoistableRoot;\n styleProps = hoistableRoot.createElement(\"script\");\n markNodeAsHoistable(styleProps);\n setInitialProperties(styleProps, \"link\", instance);\n hoistableRoot.head.appendChild(styleProps);\n return (resource.instance = styleProps);\n case \"void\":\n return null;\n default:\n throw Error(formatProdErrorMessage(443, resource.type));\n }\n else\n \"stylesheet\" === resource.type &&\n 0 === (resource.state.loading & 4) &&\n ((instance = resource.instance),\n (resource.state.loading |= 4),\n insertStylesheet(instance, props.precedence, hoistableRoot));\n return resource.instance;\n}\nfunction insertStylesheet(instance, precedence, root) {\n for (\n var nodes = root.querySelectorAll(\n 'link[rel=\"stylesheet\"][data-precedence],style[data-precedence]'\n ),\n last = nodes.length ? nodes[nodes.length - 1] : null,\n prior = last,\n i = 0;\n i < nodes.length;\n i++\n ) {\n var node = nodes[i];\n if (node.dataset.precedence === precedence) prior = node;\n else if (prior !== last) break;\n }\n prior\n ? prior.parentNode.insertBefore(instance, prior.nextSibling)\n : ((precedence = 9 === root.nodeType ? root.head : root),\n precedence.insertBefore(instance, precedence.firstChild));\n}\nfunction adoptPreloadPropsForStylesheet(stylesheetProps, preloadProps) {\n null == stylesheetProps.crossOrigin &&\n (stylesheetProps.crossOrigin = preloadProps.crossOrigin);\n null == stylesheetProps.referrerPolicy &&\n (stylesheetProps.referrerPolicy = preloadProps.referrerPolicy);\n null == stylesheetProps.title && (stylesheetProps.title = preloadProps.title);\n}\nfunction adoptPreloadPropsForScript(scriptProps, preloadProps) {\n null == scriptProps.crossOrigin &&\n (scriptProps.crossOrigin = preloadProps.crossOrigin);\n null == scriptProps.referrerPolicy &&\n (scriptProps.referrerPolicy = preloadProps.referrerPolicy);\n null == scriptProps.integrity &&\n (scriptProps.integrity = preloadProps.integrity);\n}\nvar tagCaches = null;\nfunction getHydratableHoistableCache(type, keyAttribute, ownerDocument) {\n if (null === tagCaches) {\n var cache = new Map();\n var caches = (tagCaches = new Map());\n caches.set(ownerDocument, cache);\n } else\n (caches = tagCaches),\n (cache = caches.get(ownerDocument)),\n cache || ((cache = new Map()), caches.set(ownerDocument, cache));\n if (cache.has(type)) return cache;\n cache.set(type, null);\n ownerDocument = ownerDocument.getElementsByTagName(type);\n for (caches = 0; caches < ownerDocument.length; caches++) {\n var node = ownerDocument[caches];\n if (\n !(\n node[internalHoistableMarker] ||\n node[internalInstanceKey] ||\n (\"link\" === type && \"stylesheet\" === node.getAttribute(\"rel\"))\n ) &&\n \"http://www.w3.org/2000/svg\" !== node.namespaceURI\n ) {\n var nodeKey = node.getAttribute(keyAttribute) || \"\";\n nodeKey = type + nodeKey;\n var existing = cache.get(nodeKey);\n existing ? existing.push(node) : cache.set(nodeKey, [node]);\n }\n }\n return cache;\n}\nfunction mountHoistable(hoistableRoot, type, instance) {\n hoistableRoot = hoistableRoot.ownerDocument || hoistableRoot;\n hoistableRoot.head.insertBefore(\n instance,\n \"title\" === type ? hoistableRoot.querySelector(\"head > title\") : null\n );\n}\nfunction isHostHoistableType(type, props, hostContext) {\n if (1 === hostContext || null != props.itemProp) return !1;\n switch (type) {\n case \"meta\":\n case \"title\":\n return !0;\n case \"style\":\n if (\n \"string\" !== typeof props.precedence ||\n \"string\" !== typeof props.href ||\n \"\" === props.href\n )\n break;\n return !0;\n case \"link\":\n if (\n \"string\" !== typeof props.rel ||\n \"string\" !== typeof props.href ||\n \"\" === props.href ||\n props.onLoad ||\n props.onError\n )\n break;\n switch (props.rel) {\n case \"stylesheet\":\n return (\n (type = props.disabled),\n \"string\" === typeof props.precedence && null == type\n );\n default:\n return !0;\n }\n case \"script\":\n if (\n props.async &&\n \"function\" !== typeof props.async &&\n \"symbol\" !== typeof props.async &&\n !props.onLoad &&\n !props.onError &&\n props.src &&\n \"string\" === typeof props.src\n )\n return !0;\n }\n return !1;\n}\nfunction preloadResource(resource) {\n return \"stylesheet\" === resource.type && 0 === (resource.state.loading & 3)\n ? !1\n : !0;\n}\nfunction suspendResource(state, hoistableRoot, resource, props) {\n if (\n \"stylesheet\" === resource.type &&\n (\"string\" !== typeof props.media ||\n !1 !== matchMedia(props.media).matches) &&\n 0 === (resource.state.loading & 4)\n ) {\n if (null === resource.instance) {\n var key = getStyleKey(props.href),\n instance = hoistableRoot.querySelector(\n getStylesheetSelectorFromKey(key)\n );\n if (instance) {\n hoistableRoot = instance._p;\n null !== hoistableRoot &&\n \"object\" === typeof hoistableRoot &&\n \"function\" === typeof hoistableRoot.then &&\n (state.count++,\n (state = onUnsuspend.bind(state)),\n hoistableRoot.then(state, state));\n resource.state.loading |= 4;\n resource.instance = instance;\n markNodeAsHoistable(instance);\n return;\n }\n instance = hoistableRoot.ownerDocument || hoistableRoot;\n props = stylesheetPropsFromRawProps(props);\n (key = preloadPropsMap.get(key)) &&\n adoptPreloadPropsForStylesheet(props, key);\n instance = instance.createElement(\"link\");\n markNodeAsHoistable(instance);\n var linkInstance = instance;\n linkInstance._p = new Promise(function (resolve, reject) {\n linkInstance.onload = resolve;\n linkInstance.onerror = reject;\n });\n setInitialProperties(instance, \"link\", props);\n resource.instance = instance;\n }\n null === state.stylesheets && (state.stylesheets = new Map());\n state.stylesheets.set(resource, hoistableRoot);\n (hoistableRoot = resource.state.preload) &&\n 0 === (resource.state.loading & 3) &&\n (state.count++,\n (resource = onUnsuspend.bind(state)),\n hoistableRoot.addEventListener(\"load\", resource),\n hoistableRoot.addEventListener(\"error\", resource));\n }\n}\nvar estimatedBytesWithinLimit = 0;\nfunction waitForCommitToBeReady(state, timeoutOffset) {\n state.stylesheets &&\n 0 === state.count &&\n insertSuspendedStylesheets(state, state.stylesheets);\n return 0 < state.count || 0 < state.imgCount\n ? function (commit) {\n var stylesheetTimer = setTimeout(function () {\n state.stylesheets &&\n insertSuspendedStylesheets(state, state.stylesheets);\n if (state.unsuspend) {\n var unsuspend = state.unsuspend;\n state.unsuspend = null;\n unsuspend();\n }\n }, 6e4 + timeoutOffset);\n 0 < state.imgBytes &&\n 0 === estimatedBytesWithinLimit &&\n (estimatedBytesWithinLimit = 62500 * estimateBandwidth());\n var imgTimer = setTimeout(\n function () {\n state.waitingForImages = !1;\n if (\n 0 === state.count &&\n (state.stylesheets &&\n insertSuspendedStylesheets(state, state.stylesheets),\n state.unsuspend)\n ) {\n var unsuspend = state.unsuspend;\n state.unsuspend = null;\n unsuspend();\n }\n },\n (state.imgBytes > estimatedBytesWithinLimit ? 50 : 800) +\n timeoutOffset\n );\n state.unsuspend = commit;\n return function () {\n state.unsuspend = null;\n clearTimeout(stylesheetTimer);\n clearTimeout(imgTimer);\n };\n }\n : null;\n}\nfunction onUnsuspend() {\n this.count--;\n if (0 === this.count && (0 === this.imgCount || !this.waitingForImages))\n if (this.stylesheets) insertSuspendedStylesheets(this, this.stylesheets);\n else if (this.unsuspend) {\n var unsuspend = this.unsuspend;\n this.unsuspend = null;\n unsuspend();\n }\n}\nvar precedencesByRoot = null;\nfunction insertSuspendedStylesheets(state, resources) {\n state.stylesheets = null;\n null !== state.unsuspend &&\n (state.count++,\n (precedencesByRoot = new Map()),\n resources.forEach(insertStylesheetIntoRoot, state),\n (precedencesByRoot = null),\n onUnsuspend.call(state));\n}\nfunction insertStylesheetIntoRoot(root, resource) {\n if (!(resource.state.loading & 4)) {\n var precedences = precedencesByRoot.get(root);\n if (precedences) var last = precedences.get(null);\n else {\n precedences = new Map();\n precedencesByRoot.set(root, precedences);\n for (\n var nodes = root.querySelectorAll(\n \"link[data-precedence],style[data-precedence]\"\n ),\n i = 0;\n i < nodes.length;\n i++\n ) {\n var node = nodes[i];\n if (\n \"LINK\" === node.nodeName ||\n \"not all\" !== node.getAttribute(\"media\")\n )\n precedences.set(node.dataset.precedence, node), (last = node);\n }\n last && precedences.set(null, last);\n }\n nodes = resource.instance;\n node = nodes.getAttribute(\"data-precedence\");\n i = precedences.get(node) || last;\n i === last && precedences.set(null, nodes);\n precedences.set(node, nodes);\n this.count++;\n last = onUnsuspend.bind(this);\n nodes.addEventListener(\"load\", last);\n nodes.addEventListener(\"error\", last);\n i\n ? i.parentNode.insertBefore(nodes, i.nextSibling)\n : ((root = 9 === root.nodeType ? root.head : root),\n root.insertBefore(nodes, root.firstChild));\n resource.state.loading |= 4;\n }\n}\nvar HostTransitionContext = {\n $$typeof: REACT_CONTEXT_TYPE,\n Provider: null,\n Consumer: null,\n _currentValue: sharedNotPendingObject,\n _currentValue2: sharedNotPendingObject,\n _threadCount: 0\n};\nfunction FiberRootNode(\n containerInfo,\n tag,\n hydrate,\n identifierPrefix,\n onUncaughtError,\n onCaughtError,\n onRecoverableError,\n onDefaultTransitionIndicator,\n formState\n) {\n this.tag = 1;\n this.containerInfo = containerInfo;\n this.pingCache = this.current = this.pendingChildren = null;\n this.timeoutHandle = -1;\n this.callbackNode =\n this.next =\n this.pendingContext =\n this.context =\n this.cancelPendingCommit =\n null;\n this.callbackPriority = 0;\n this.expirationTimes = createLaneMap(-1);\n this.entangledLanes =\n this.shellSuspendCounter =\n this.errorRecoveryDisabledLanes =\n this.expiredLanes =\n this.warmLanes =\n this.pingedLanes =\n this.suspendedLanes =\n this.pendingLanes =\n 0;\n this.entanglements = createLaneMap(0);\n this.hiddenUpdates = createLaneMap(null);\n this.identifierPrefix = identifierPrefix;\n this.onUncaughtError = onUncaughtError;\n this.onCaughtError = onCaughtError;\n this.onRecoverableError = onRecoverableError;\n this.pooledCache = null;\n this.pooledCacheLanes = 0;\n this.formState = formState;\n this.incompleteTransitions = new Map();\n}\nfunction createFiberRoot(\n containerInfo,\n tag,\n hydrate,\n initialChildren,\n hydrationCallbacks,\n isStrictMode,\n identifierPrefix,\n formState,\n onUncaughtError,\n onCaughtError,\n onRecoverableError,\n onDefaultTransitionIndicator\n) {\n containerInfo = new FiberRootNode(\n containerInfo,\n tag,\n hydrate,\n identifierPrefix,\n onUncaughtError,\n onCaughtError,\n onRecoverableError,\n onDefaultTransitionIndicator,\n formState\n );\n tag = 1;\n !0 === isStrictMode && (tag |= 24);\n isStrictMode = createFiberImplClass(3, null, null, tag);\n containerInfo.current = isStrictMode;\n isStrictMode.stateNode = containerInfo;\n tag = createCache();\n tag.refCount++;\n containerInfo.pooledCache = tag;\n tag.refCount++;\n isStrictMode.memoizedState = {\n element: initialChildren,\n isDehydrated: hydrate,\n cache: tag\n };\n initializeUpdateQueue(isStrictMode);\n return containerInfo;\n}\nfunction getContextForSubtree(parentComponent) {\n if (!parentComponent) return emptyContextObject;\n parentComponent = emptyContextObject;\n return parentComponent;\n}\nfunction updateContainerImpl(\n rootFiber,\n lane,\n element,\n container,\n parentComponent,\n callback\n) {\n parentComponent = getContextForSubtree(parentComponent);\n null === container.context\n ? (container.context = parentComponent)\n : (container.pendingContext = parentComponent);\n container = createUpdate(lane);\n container.payload = { element: element };\n callback = void 0 === callback ? null : callback;\n null !== callback && (container.callback = callback);\n element = enqueueUpdate(rootFiber, container, lane);\n null !== element &&\n (scheduleUpdateOnFiber(element, rootFiber, lane),\n entangleTransitions(element, rootFiber, lane));\n}\nfunction markRetryLaneImpl(fiber, retryLane) {\n fiber = fiber.memoizedState;\n if (null !== fiber && null !== fiber.dehydrated) {\n var a = fiber.retryLane;\n fiber.retryLane = 0 !== a && a < retryLane ? a : retryLane;\n }\n}\nfunction markRetryLaneIfNotHydrated(fiber, retryLane) {\n markRetryLaneImpl(fiber, retryLane);\n (fiber = fiber.alternate) && markRetryLaneImpl(fiber, retryLane);\n}\nfunction attemptContinuousHydration(fiber) {\n if (13 === fiber.tag || 31 === fiber.tag) {\n var root = enqueueConcurrentRenderForLane(fiber, 67108864);\n null !== root && scheduleUpdateOnFiber(root, fiber, 67108864);\n markRetryLaneIfNotHydrated(fiber, 67108864);\n }\n}\nfunction attemptHydrationAtCurrentPriority(fiber) {\n if (13 === fiber.tag || 31 === fiber.tag) {\n var lane = requestUpdateLane();\n lane = getBumpedLaneForHydrationByLane(lane);\n var root = enqueueConcurrentRenderForLane(fiber, lane);\n null !== root && scheduleUpdateOnFiber(root, fiber, lane);\n markRetryLaneIfNotHydrated(fiber, lane);\n }\n}\nvar _enabled = !0;\nfunction dispatchDiscreteEvent(\n domEventName,\n eventSystemFlags,\n container,\n nativeEvent\n) {\n var prevTransition = ReactSharedInternals.T;\n ReactSharedInternals.T = null;\n var previousPriority = ReactDOMSharedInternals.p;\n try {\n (ReactDOMSharedInternals.p = 2),\n dispatchEvent(domEventName, eventSystemFlags, container, nativeEvent);\n } finally {\n (ReactDOMSharedInternals.p = previousPriority),\n (ReactSharedInternals.T = prevTransition);\n }\n}\nfunction dispatchContinuousEvent(\n domEventName,\n eventSystemFlags,\n container,\n nativeEvent\n) {\n var prevTransition = ReactSharedInternals.T;\n ReactSharedInternals.T = null;\n var previousPriority = ReactDOMSharedInternals.p;\n try {\n (ReactDOMSharedInternals.p = 8),\n dispatchEvent(domEventName, eventSystemFlags, container, nativeEvent);\n } finally {\n (ReactDOMSharedInternals.p = previousPriority),\n (ReactSharedInternals.T = prevTransition);\n }\n}\nfunction dispatchEvent(\n domEventName,\n eventSystemFlags,\n targetContainer,\n nativeEvent\n) {\n if (_enabled) {\n var blockedOn = findInstanceBlockingEvent(nativeEvent);\n if (null === blockedOn)\n dispatchEventForPluginEventSystem(\n domEventName,\n eventSystemFlags,\n nativeEvent,\n return_targetInst,\n targetContainer\n ),\n clearIfContinuousEvent(domEventName, nativeEvent);\n else if (\n queueIfContinuousEvent(\n blockedOn,\n domEventName,\n eventSystemFlags,\n targetContainer,\n nativeEvent\n )\n )\n nativeEvent.stopPropagation();\n else if (\n (clearIfContinuousEvent(domEventName, nativeEvent),\n eventSystemFlags & 4 &&\n -1 < discreteReplayableEvents.indexOf(domEventName))\n ) {\n for (; null !== blockedOn; ) {\n var fiber = getInstanceFromNode(blockedOn);\n if (null !== fiber)\n switch (fiber.tag) {\n case 3:\n fiber = fiber.stateNode;\n if (fiber.current.memoizedState.isDehydrated) {\n var lanes = getHighestPriorityLanes(fiber.pendingLanes);\n if (0 !== lanes) {\n var root = fiber;\n root.pendingLanes |= 2;\n for (root.entangledLanes |= 2; lanes; ) {\n var lane = 1 << (31 - clz32(lanes));\n root.entanglements[1] |= lane;\n lanes &= ~lane;\n }\n ensureRootIsScheduled(fiber);\n 0 === (executionContext & 6) &&\n ((workInProgressRootRenderTargetTime = now() + 500),\n flushSyncWorkAcrossRoots_impl(0, !1));\n }\n }\n break;\n case 31:\n case 13:\n (root = enqueueConcurrentRenderForLane(fiber, 2)),\n null !== root && scheduleUpdateOnFiber(root, fiber, 2),\n flushSyncWork$1(),\n markRetryLaneIfNotHydrated(fiber, 2);\n }\n fiber = findInstanceBlockingEvent(nativeEvent);\n null === fiber &&\n dispatchEventForPluginEventSystem(\n domEventName,\n eventSystemFlags,\n nativeEvent,\n return_targetInst,\n targetContainer\n );\n if (fiber === blockedOn) break;\n blockedOn = fiber;\n }\n null !== blockedOn && nativeEvent.stopPropagation();\n } else\n dispatchEventForPluginEventSystem(\n domEventName,\n eventSystemFlags,\n nativeEvent,\n null,\n targetContainer\n );\n }\n}\nfunction findInstanceBlockingEvent(nativeEvent) {\n nativeEvent = getEventTarget(nativeEvent);\n return findInstanceBlockingTarget(nativeEvent);\n}\nvar return_targetInst = null;\nfunction findInstanceBlockingTarget(targetNode) {\n return_targetInst = null;\n targetNode = getClosestInstanceFromNode(targetNode);\n if (null !== targetNode) {\n var nearestMounted = getNearestMountedFiber(targetNode);\n if (null === nearestMounted) targetNode = null;\n else {\n var tag = nearestMounted.tag;\n if (13 === tag) {\n targetNode = getSuspenseInstanceFromFiber(nearestMounted);\n if (null !== targetNode) return targetNode;\n targetNode = null;\n } else if (31 === tag) {\n targetNode = getActivityInstanceFromFiber(nearestMounted);\n if (null !== targetNode) return targetNode;\n targetNode = null;\n } else if (3 === tag) {\n if (nearestMounted.stateNode.current.memoizedState.isDehydrated)\n return 3 === nearestMounted.tag\n ? nearestMounted.stateNode.containerInfo\n : null;\n targetNode = null;\n } else nearestMounted !== targetNode && (targetNode = null);\n }\n }\n return_targetInst = targetNode;\n return null;\n}\nfunction getEventPriority(domEventName) {\n switch (domEventName) {\n case \"beforetoggle\":\n case \"cancel\":\n case \"click\":\n case \"close\":\n case \"contextmenu\":\n case \"copy\":\n case \"cut\":\n case \"auxclick\":\n case \"dblclick\":\n case \"dragend\":\n case \"dragstart\":\n case \"drop\":\n case \"focusin\":\n case \"focusout\":\n case \"input\":\n case \"invalid\":\n case \"keydown\":\n case \"keypress\":\n case \"keyup\":\n case \"mousedown\":\n case \"mouseup\":\n case \"paste\":\n case \"pause\":\n case \"play\":\n case \"pointercancel\":\n case \"pointerdown\":\n case \"pointerup\":\n case \"ratechange\":\n case \"reset\":\n case \"resize\":\n case \"seeked\":\n case \"submit\":\n case \"toggle\":\n case \"touchcancel\":\n case \"touchend\":\n case \"touchstart\":\n case \"volumechange\":\n case \"change\":\n case \"selectionchange\":\n case \"textInput\":\n case \"compositionstart\":\n case \"compositionend\":\n case \"compositionupdate\":\n case \"beforeblur\":\n case \"afterblur\":\n case \"beforeinput\":\n case \"blur\":\n case \"fullscreenchange\":\n case \"focus\":\n case \"hashchange\":\n case \"popstate\":\n case \"select\":\n case \"selectstart\":\n return 2;\n case \"drag\":\n case \"dragenter\":\n case \"dragexit\":\n case \"dragleave\":\n case \"dragover\":\n case \"mousemove\":\n case \"mouseout\":\n case \"mouseover\":\n case \"pointermove\":\n case \"pointerout\":\n case \"pointerover\":\n case \"scroll\":\n case \"touchmove\":\n case \"wheel\":\n case \"mouseenter\":\n case \"mouseleave\":\n case \"pointerenter\":\n case \"pointerleave\":\n return 8;\n case \"message\":\n switch (getCurrentPriorityLevel()) {\n case ImmediatePriority:\n return 2;\n case UserBlockingPriority:\n return 8;\n case NormalPriority$1:\n case LowPriority:\n return 32;\n case IdlePriority:\n return 268435456;\n default:\n return 32;\n }\n default:\n return 32;\n }\n}\nvar hasScheduledReplayAttempt = !1,\n queuedFocus = null,\n queuedDrag = null,\n queuedMouse = null,\n queuedPointers = new Map(),\n queuedPointerCaptures = new Map(),\n queuedExplicitHydrationTargets = [],\n discreteReplayableEvents =\n \"mousedown mouseup touchcancel touchend touchstart auxclick dblclick pointercancel pointerdown pointerup dragend dragstart drop compositionend compositionstart keydown keypress keyup input textInput copy cut paste click change contextmenu reset\".split(\n \" \"\n );\nfunction clearIfContinuousEvent(domEventName, nativeEvent) {\n switch (domEventName) {\n case \"focusin\":\n case \"focusout\":\n queuedFocus = null;\n break;\n case \"dragenter\":\n case \"dragleave\":\n queuedDrag = null;\n break;\n case \"mouseover\":\n case \"mouseout\":\n queuedMouse = null;\n break;\n case \"pointerover\":\n case \"pointerout\":\n queuedPointers.delete(nativeEvent.pointerId);\n break;\n case \"gotpointercapture\":\n case \"lostpointercapture\":\n queuedPointerCaptures.delete(nativeEvent.pointerId);\n }\n}\nfunction accumulateOrCreateContinuousQueuedReplayableEvent(\n existingQueuedEvent,\n blockedOn,\n domEventName,\n eventSystemFlags,\n targetContainer,\n nativeEvent\n) {\n if (\n null === existingQueuedEvent ||\n existingQueuedEvent.nativeEvent !== nativeEvent\n )\n return (\n (existingQueuedEvent = {\n blockedOn: blockedOn,\n domEventName: domEventName,\n eventSystemFlags: eventSystemFlags,\n nativeEvent: nativeEvent,\n targetContainers: [targetContainer]\n }),\n null !== blockedOn &&\n ((blockedOn = getInstanceFromNode(blockedOn)),\n null !== blockedOn && attemptContinuousHydration(blockedOn)),\n existingQueuedEvent\n );\n existingQueuedEvent.eventSystemFlags |= eventSystemFlags;\n blockedOn = existingQueuedEvent.targetContainers;\n null !== targetContainer &&\n -1 === blockedOn.indexOf(targetContainer) &&\n blockedOn.push(targetContainer);\n return existingQueuedEvent;\n}\nfunction queueIfContinuousEvent(\n blockedOn,\n domEventName,\n eventSystemFlags,\n targetContainer,\n nativeEvent\n) {\n switch (domEventName) {\n case \"focusin\":\n return (\n (queuedFocus = accumulateOrCreateContinuousQueuedReplayableEvent(\n queuedFocus,\n blockedOn,\n domEventName,\n eventSystemFlags,\n targetContainer,\n nativeEvent\n )),\n !0\n );\n case \"dragenter\":\n return (\n (queuedDrag = accumulateOrCreateContinuousQueuedReplayableEvent(\n queuedDrag,\n blockedOn,\n domEventName,\n eventSystemFlags,\n targetContainer,\n nativeEvent\n )),\n !0\n );\n case \"mouseover\":\n return (\n (queuedMouse = accumulateOrCreateContinuousQueuedReplayableEvent(\n queuedMouse,\n blockedOn,\n domEventName,\n eventSystemFlags,\n targetContainer,\n nativeEvent\n )),\n !0\n );\n case \"pointerover\":\n var pointerId = nativeEvent.pointerId;\n queuedPointers.set(\n pointerId,\n accumulateOrCreateContinuousQueuedReplayableEvent(\n queuedPointers.get(pointerId) || null,\n blockedOn,\n domEventName,\n eventSystemFlags,\n targetContainer,\n nativeEvent\n )\n );\n return !0;\n case \"gotpointercapture\":\n return (\n (pointerId = nativeEvent.pointerId),\n queuedPointerCaptures.set(\n pointerId,\n accumulateOrCreateContinuousQueuedReplayableEvent(\n queuedPointerCaptures.get(pointerId) || null,\n blockedOn,\n domEventName,\n eventSystemFlags,\n targetContainer,\n nativeEvent\n )\n ),\n !0\n );\n }\n return !1;\n}\nfunction attemptExplicitHydrationTarget(queuedTarget) {\n var targetInst = getClosestInstanceFromNode(queuedTarget.target);\n if (null !== targetInst) {\n var nearestMounted = getNearestMountedFiber(targetInst);\n if (null !== nearestMounted)\n if (((targetInst = nearestMounted.tag), 13 === targetInst)) {\n if (\n ((targetInst = getSuspenseInstanceFromFiber(nearestMounted)),\n null !== targetInst)\n ) {\n queuedTarget.blockedOn = targetInst;\n runWithPriority(queuedTarget.priority, function () {\n attemptHydrationAtCurrentPriority(nearestMounted);\n });\n return;\n }\n } else if (31 === targetInst) {\n if (\n ((targetInst = getActivityInstanceFromFiber(nearestMounted)),\n null !== targetInst)\n ) {\n queuedTarget.blockedOn = targetInst;\n runWithPriority(queuedTarget.priority, function () {\n attemptHydrationAtCurrentPriority(nearestMounted);\n });\n return;\n }\n } else if (\n 3 === targetInst &&\n nearestMounted.stateNode.current.memoizedState.isDehydrated\n ) {\n queuedTarget.blockedOn =\n 3 === nearestMounted.tag\n ? nearestMounted.stateNode.containerInfo\n : null;\n return;\n }\n }\n queuedTarget.blockedOn = null;\n}\nfunction attemptReplayContinuousQueuedEvent(queuedEvent) {\n if (null !== queuedEvent.blockedOn) return !1;\n for (\n var targetContainers = queuedEvent.targetContainers;\n 0 < targetContainers.length;\n\n ) {\n var nextBlockedOn = findInstanceBlockingEvent(queuedEvent.nativeEvent);\n if (null === nextBlockedOn) {\n nextBlockedOn = queuedEvent.nativeEvent;\n var nativeEventClone = new nextBlockedOn.constructor(\n nextBlockedOn.type,\n nextBlockedOn\n );\n currentReplayingEvent = nativeEventClone;\n nextBlockedOn.target.dispatchEvent(nativeEventClone);\n currentReplayingEvent = null;\n } else\n return (\n (targetContainers = getInstanceFromNode(nextBlockedOn)),\n null !== targetContainers &&\n attemptContinuousHydration(targetContainers),\n (queuedEvent.blockedOn = nextBlockedOn),\n !1\n );\n targetContainers.shift();\n }\n return !0;\n}\nfunction attemptReplayContinuousQueuedEventInMap(queuedEvent, key, map) {\n attemptReplayContinuousQueuedEvent(queuedEvent) && map.delete(key);\n}\nfunction replayUnblockedEvents() {\n hasScheduledReplayAttempt = !1;\n null !== queuedFocus &&\n attemptReplayContinuousQueuedEvent(queuedFocus) &&\n (queuedFocus = null);\n null !== queuedDrag &&\n attemptReplayContinuousQueuedEvent(queuedDrag) &&\n (queuedDrag = null);\n null !== queuedMouse &&\n attemptReplayContinuousQueuedEvent(queuedMouse) &&\n (queuedMouse = null);\n queuedPointers.forEach(attemptReplayContinuousQueuedEventInMap);\n queuedPointerCaptures.forEach(attemptReplayContinuousQueuedEventInMap);\n}\nfunction scheduleCallbackIfUnblocked(queuedEvent, unblocked) {\n queuedEvent.blockedOn === unblocked &&\n ((queuedEvent.blockedOn = null),\n hasScheduledReplayAttempt ||\n ((hasScheduledReplayAttempt = !0),\n Scheduler.unstable_scheduleCallback(\n Scheduler.unstable_NormalPriority,\n replayUnblockedEvents\n )));\n}\nvar lastScheduledReplayQueue = null;\nfunction scheduleReplayQueueIfNeeded(formReplayingQueue) {\n lastScheduledReplayQueue !== formReplayingQueue &&\n ((lastScheduledReplayQueue = formReplayingQueue),\n Scheduler.unstable_scheduleCallback(\n Scheduler.unstable_NormalPriority,\n function () {\n lastScheduledReplayQueue === formReplayingQueue &&\n (lastScheduledReplayQueue = null);\n for (var i = 0; i < formReplayingQueue.length; i += 3) {\n var form = formReplayingQueue[i],\n submitterOrAction = formReplayingQueue[i + 1],\n formData = formReplayingQueue[i + 2];\n if (\"function\" !== typeof submitterOrAction)\n if (null === findInstanceBlockingTarget(submitterOrAction || form))\n continue;\n else break;\n var formInst = getInstanceFromNode(form);\n null !== formInst &&\n (formReplayingQueue.splice(i, 3),\n (i -= 3),\n startHostTransition(\n formInst,\n {\n pending: !0,\n data: formData,\n method: form.method,\n action: submitterOrAction\n },\n submitterOrAction,\n formData\n ));\n }\n }\n ));\n}\nfunction retryIfBlockedOn(unblocked) {\n function unblock(queuedEvent) {\n return scheduleCallbackIfUnblocked(queuedEvent, unblocked);\n }\n null !== queuedFocus && scheduleCallbackIfUnblocked(queuedFocus, unblocked);\n null !== queuedDrag && scheduleCallbackIfUnblocked(queuedDrag, unblocked);\n null !== queuedMouse && scheduleCallbackIfUnblocked(queuedMouse, unblocked);\n queuedPointers.forEach(unblock);\n queuedPointerCaptures.forEach(unblock);\n for (var i = 0; i < queuedExplicitHydrationTargets.length; i++) {\n var queuedTarget = queuedExplicitHydrationTargets[i];\n queuedTarget.blockedOn === unblocked && (queuedTarget.blockedOn = null);\n }\n for (\n ;\n 0 < queuedExplicitHydrationTargets.length &&\n ((i = queuedExplicitHydrationTargets[0]), null === i.blockedOn);\n\n )\n attemptExplicitHydrationTarget(i),\n null === i.blockedOn && queuedExplicitHydrationTargets.shift();\n i = (unblocked.ownerDocument || unblocked).$$reactFormReplay;\n if (null != i)\n for (queuedTarget = 0; queuedTarget < i.length; queuedTarget += 3) {\n var form = i[queuedTarget],\n submitterOrAction = i[queuedTarget + 1],\n formProps = form[internalPropsKey] || null;\n if (\"function\" === typeof submitterOrAction)\n formProps || scheduleReplayQueueIfNeeded(i);\n else if (formProps) {\n var action = null;\n if (submitterOrAction && submitterOrAction.hasAttribute(\"formAction\"))\n if (\n ((form = submitterOrAction),\n (formProps = submitterOrAction[internalPropsKey] || null))\n )\n action = formProps.formAction;\n else {\n if (null !== findInstanceBlockingTarget(form)) continue;\n }\n else action = formProps.action;\n \"function\" === typeof action\n ? (i[queuedTarget + 1] = action)\n : (i.splice(queuedTarget, 3), (queuedTarget -= 3));\n scheduleReplayQueueIfNeeded(i);\n }\n }\n}\nfunction defaultOnDefaultTransitionIndicator() {\n function handleNavigate(event) {\n event.canIntercept &&\n \"react-transition\" === event.info &&\n event.intercept({\n handler: function () {\n return new Promise(function (resolve) {\n return (pendingResolve = resolve);\n });\n },\n focusReset: \"manual\",\n scroll: \"manual\"\n });\n }\n function handleNavigateComplete() {\n null !== pendingResolve && (pendingResolve(), (pendingResolve = null));\n isCancelled || setTimeout(startFakeNavigation, 20);\n }\n function startFakeNavigation() {\n if (!isCancelled && !navigation.transition) {\n var currentEntry = navigation.currentEntry;\n currentEntry &&\n null != currentEntry.url &&\n navigation.navigate(currentEntry.url, {\n state: currentEntry.getState(),\n info: \"react-transition\",\n history: \"replace\"\n });\n }\n }\n if (\"object\" === typeof navigation) {\n var isCancelled = !1,\n pendingResolve = null;\n navigation.addEventListener(\"navigate\", handleNavigate);\n navigation.addEventListener(\"navigatesuccess\", handleNavigateComplete);\n navigation.addEventListener(\"navigateerror\", handleNavigateComplete);\n setTimeout(startFakeNavigation, 100);\n return function () {\n isCancelled = !0;\n navigation.removeEventListener(\"navigate\", handleNavigate);\n navigation.removeEventListener(\"navigatesuccess\", handleNavigateComplete);\n navigation.removeEventListener(\"navigateerror\", handleNavigateComplete);\n null !== pendingResolve && (pendingResolve(), (pendingResolve = null));\n };\n }\n}\nfunction ReactDOMRoot(internalRoot) {\n this._internalRoot = internalRoot;\n}\nReactDOMHydrationRoot.prototype.render = ReactDOMRoot.prototype.render =\n function (children) {\n var root = this._internalRoot;\n if (null === root) throw Error(formatProdErrorMessage(409));\n var current = root.current,\n lane = requestUpdateLane();\n updateContainerImpl(current, lane, children, root, null, null);\n };\nReactDOMHydrationRoot.prototype.unmount = ReactDOMRoot.prototype.unmount =\n function () {\n var root = this._internalRoot;\n if (null !== root) {\n this._internalRoot = null;\n var container = root.containerInfo;\n updateContainerImpl(root.current, 2, null, root, null, null);\n flushSyncWork$1();\n container[internalContainerInstanceKey] = null;\n }\n };\nfunction ReactDOMHydrationRoot(internalRoot) {\n this._internalRoot = internalRoot;\n}\nReactDOMHydrationRoot.prototype.unstable_scheduleHydration = function (target) {\n if (target) {\n var updatePriority = resolveUpdatePriority();\n target = { blockedOn: null, target: target, priority: updatePriority };\n for (\n var i = 0;\n i < queuedExplicitHydrationTargets.length &&\n 0 !== updatePriority &&\n updatePriority < queuedExplicitHydrationTargets[i].priority;\n i++\n );\n queuedExplicitHydrationTargets.splice(i, 0, target);\n 0 === i && attemptExplicitHydrationTarget(target);\n }\n};\nvar isomorphicReactPackageVersion$jscomp$inline_1840 = React.version;\nif (\n \"19.2.4\" !==\n isomorphicReactPackageVersion$jscomp$inline_1840\n)\n throw Error(\n formatProdErrorMessage(\n 527,\n isomorphicReactPackageVersion$jscomp$inline_1840,\n \"19.2.4\"\n )\n );\nReactDOMSharedInternals.findDOMNode = function (componentOrElement) {\n var fiber = componentOrElement._reactInternals;\n if (void 0 === fiber) {\n if (\"function\" === typeof componentOrElement.render)\n throw Error(formatProdErrorMessage(188));\n componentOrElement = Object.keys(componentOrElement).join(\",\");\n throw Error(formatProdErrorMessage(268, componentOrElement));\n }\n componentOrElement = findCurrentFiberUsingSlowPath(fiber);\n componentOrElement =\n null !== componentOrElement\n ? findCurrentHostFiberImpl(componentOrElement)\n : null;\n componentOrElement =\n null === componentOrElement ? null : componentOrElement.stateNode;\n return componentOrElement;\n};\nvar internals$jscomp$inline_2347 = {\n bundleType: 0,\n version: \"19.2.4\",\n rendererPackageName: \"react-dom\",\n currentDispatcherRef: ReactSharedInternals,\n reconcilerVersion: \"19.2.4\"\n};\nif (\"undefined\" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) {\n var hook$jscomp$inline_2348 = __REACT_DEVTOOLS_GLOBAL_HOOK__;\n if (\n !hook$jscomp$inline_2348.isDisabled &&\n hook$jscomp$inline_2348.supportsFiber\n )\n try {\n (rendererID = hook$jscomp$inline_2348.inject(\n internals$jscomp$inline_2347\n )),\n (injectedHook = hook$jscomp$inline_2348);\n } catch (err) {}\n}\nexports.createRoot = function (container, options) {\n if (!isValidContainer(container)) throw Error(formatProdErrorMessage(299));\n var isStrictMode = !1,\n identifierPrefix = \"\",\n onUncaughtError = defaultOnUncaughtError,\n onCaughtError = defaultOnCaughtError,\n onRecoverableError = defaultOnRecoverableError;\n null !== options &&\n void 0 !== options &&\n (!0 === options.unstable_strictMode && (isStrictMode = !0),\n void 0 !== options.identifierPrefix &&\n (identifierPrefix = options.identifierPrefix),\n void 0 !== options.onUncaughtError &&\n (onUncaughtError = options.onUncaughtError),\n void 0 !== options.onCaughtError && (onCaughtError = options.onCaughtError),\n void 0 !== options.onRecoverableError &&\n (onRecoverableError = options.onRecoverableError));\n options = createFiberRoot(\n container,\n 1,\n !1,\n null,\n null,\n isStrictMode,\n identifierPrefix,\n null,\n onUncaughtError,\n onCaughtError,\n onRecoverableError,\n defaultOnDefaultTransitionIndicator\n );\n container[internalContainerInstanceKey] = options.current;\n listenToAllSupportedEvents(container);\n return new ReactDOMRoot(options);\n};\nexports.hydrateRoot = function (container, initialChildren, options) {\n if (!isValidContainer(container)) throw Error(formatProdErrorMessage(299));\n var isStrictMode = !1,\n identifierPrefix = \"\",\n onUncaughtError = defaultOnUncaughtError,\n onCaughtError = defaultOnCaughtError,\n onRecoverableError = defaultOnRecoverableError,\n formState = null;\n null !== options &&\n void 0 !== options &&\n (!0 === options.unstable_strictMode && (isStrictMode = !0),\n void 0 !== options.identifierPrefix &&\n (identifierPrefix = options.identifierPrefix),\n void 0 !== options.onUncaughtError &&\n (onUncaughtError = options.onUncaughtError),\n void 0 !== options.onCaughtError && (onCaughtError = options.onCaughtError),\n void 0 !== options.onRecoverableError &&\n (onRecoverableError = options.onRecoverableError),\n void 0 !== options.formState && (formState = options.formState));\n initialChildren = createFiberRoot(\n container,\n 1,\n !0,\n initialChildren,\n null != options ? options : null,\n isStrictMode,\n identifierPrefix,\n formState,\n onUncaughtError,\n onCaughtError,\n onRecoverableError,\n defaultOnDefaultTransitionIndicator\n );\n initialChildren.context = getContextForSubtree(null);\n options = initialChildren.current;\n isStrictMode = requestUpdateLane();\n isStrictMode = getBumpedLaneForHydrationByLane(isStrictMode);\n identifierPrefix = createUpdate(isStrictMode);\n identifierPrefix.callback = null;\n enqueueUpdate(options, identifierPrefix, isStrictMode);\n options = isStrictMode;\n initialChildren.current.lanes = options;\n markRootUpdated$1(initialChildren, options);\n ensureRootIsScheduled(initialChildren);\n container[internalContainerInstanceKey] = initialChildren.current;\n listenToAllSupportedEvents(container);\n return new ReactDOMHydrationRoot(initialChildren);\n};\nexports.version = \"19.2.4\";\n", + "'use strict';\n\nfunction checkDCE() {\n /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */\n if (\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined' ||\n typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE !== 'function'\n ) {\n return;\n }\n if (process.env.NODE_ENV !== 'production') {\n // This branch is unreachable because this function is only called\n // in production, but the condition is true only in development.\n // Therefore if the branch is still here, dead code elimination wasn't\n // properly applied.\n // Don't change the message. React DevTools relies on it. Also make sure\n // this message doesn't occur elsewhere in this function, or it will cause\n // a false positive.\n throw new Error('^_^');\n }\n try {\n // Verify that the code above has been dead code eliminated (DCE'd).\n __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(checkDCE);\n } catch (err) {\n // DevTools shouldn't crash React, no matter what.\n // We should still report in case we break this code.\n console.error(err);\n }\n}\n\nif (process.env.NODE_ENV === 'production') {\n // DCE check should happen before ReactDOM bundle executes so that\n // DevTools can report bad minification during injection.\n checkDCE();\n module.exports = require('./cjs/react-dom-client.production.js');\n} else {\n module.exports = require('./cjs/react-dom-client.development.js');\n}\n", + "// can-promise has a crash in some versions of react native that dont have\n// standard global objects\n// https://github.com/soldair/node-qrcode/issues/157\n\nmodule.exports = function () {\n return typeof Promise === 'function' && Promise.prototype && Promise.prototype.then\n}\n", + "let toSJISFunction\nconst CODEWORDS_COUNT = [\n 0, // Not used\n 26, 44, 70, 100, 134, 172, 196, 242, 292, 346,\n 404, 466, 532, 581, 655, 733, 815, 901, 991, 1085,\n 1156, 1258, 1364, 1474, 1588, 1706, 1828, 1921, 2051, 2185,\n 2323, 2465, 2611, 2761, 2876, 3034, 3196, 3362, 3532, 3706\n]\n\n/**\n * Returns the QR Code size for the specified version\n *\n * @param {Number} version QR Code version\n * @return {Number} size of QR code\n */\nexports.getSymbolSize = function getSymbolSize (version) {\n if (!version) throw new Error('\"version\" cannot be null or undefined')\n if (version < 1 || version > 40) throw new Error('\"version\" should be in range from 1 to 40')\n return version * 4 + 17\n}\n\n/**\n * Returns the total number of codewords used to store data and EC information.\n *\n * @param {Number} version QR Code version\n * @return {Number} Data length in bits\n */\nexports.getSymbolTotalCodewords = function getSymbolTotalCodewords (version) {\n return CODEWORDS_COUNT[version]\n}\n\n/**\n * Encode data with Bose-Chaudhuri-Hocquenghem\n *\n * @param {Number} data Value to encode\n * @return {Number} Encoded value\n */\nexports.getBCHDigit = function (data) {\n let digit = 0\n\n while (data !== 0) {\n digit++\n data >>>= 1\n }\n\n return digit\n}\n\nexports.setToSJISFunction = function setToSJISFunction (f) {\n if (typeof f !== 'function') {\n throw new Error('\"toSJISFunc\" is not a valid function.')\n }\n\n toSJISFunction = f\n}\n\nexports.isKanjiModeEnabled = function () {\n return typeof toSJISFunction !== 'undefined'\n}\n\nexports.toSJIS = function toSJIS (kanji) {\n return toSJISFunction(kanji)\n}\n", + "exports.L = { bit: 1 }\nexports.M = { bit: 0 }\nexports.Q = { bit: 3 }\nexports.H = { bit: 2 }\n\nfunction fromString (string) {\n if (typeof string !== 'string') {\n throw new Error('Param is not a string')\n }\n\n const lcStr = string.toLowerCase()\n\n switch (lcStr) {\n case 'l':\n case 'low':\n return exports.L\n\n case 'm':\n case 'medium':\n return exports.M\n\n case 'q':\n case 'quartile':\n return exports.Q\n\n case 'h':\n case 'high':\n return exports.H\n\n default:\n throw new Error('Unknown EC Level: ' + string)\n }\n}\n\nexports.isValid = function isValid (level) {\n return level && typeof level.bit !== 'undefined' &&\n level.bit >= 0 && level.bit < 4\n}\n\nexports.from = function from (value, defaultValue) {\n if (exports.isValid(value)) {\n return value\n }\n\n try {\n return fromString(value)\n } catch (e) {\n return defaultValue\n }\n}\n", + "function BitBuffer () {\n this.buffer = []\n this.length = 0\n}\n\nBitBuffer.prototype = {\n\n get: function (index) {\n const bufIndex = Math.floor(index / 8)\n return ((this.buffer[bufIndex] >>> (7 - index % 8)) & 1) === 1\n },\n\n put: function (num, length) {\n for (let i = 0; i < length; i++) {\n this.putBit(((num >>> (length - i - 1)) & 1) === 1)\n }\n },\n\n getLengthInBits: function () {\n return this.length\n },\n\n putBit: function (bit) {\n const bufIndex = Math.floor(this.length / 8)\n if (this.buffer.length <= bufIndex) {\n this.buffer.push(0)\n }\n\n if (bit) {\n this.buffer[bufIndex] |= (0x80 >>> (this.length % 8))\n }\n\n this.length++\n }\n}\n\nmodule.exports = BitBuffer\n", + "/**\n * Helper class to handle QR Code symbol modules\n *\n * @param {Number} size Symbol size\n */\nfunction BitMatrix (size) {\n if (!size || size < 1) {\n throw new Error('BitMatrix size must be defined and greater than 0')\n }\n\n this.size = size\n this.data = new Uint8Array(size * size)\n this.reservedBit = new Uint8Array(size * size)\n}\n\n/**\n * Set bit value at specified location\n * If reserved flag is set, this bit will be ignored during masking process\n *\n * @param {Number} row\n * @param {Number} col\n * @param {Boolean} value\n * @param {Boolean} reserved\n */\nBitMatrix.prototype.set = function (row, col, value, reserved) {\n const index = row * this.size + col\n this.data[index] = value\n if (reserved) this.reservedBit[index] = true\n}\n\n/**\n * Returns bit value at specified location\n *\n * @param {Number} row\n * @param {Number} col\n * @return {Boolean}\n */\nBitMatrix.prototype.get = function (row, col) {\n return this.data[row * this.size + col]\n}\n\n/**\n * Applies xor operator at specified location\n * (used during masking process)\n *\n * @param {Number} row\n * @param {Number} col\n * @param {Boolean} value\n */\nBitMatrix.prototype.xor = function (row, col, value) {\n this.data[row * this.size + col] ^= value\n}\n\n/**\n * Check if bit at specified location is reserved\n *\n * @param {Number} row\n * @param {Number} col\n * @return {Boolean}\n */\nBitMatrix.prototype.isReserved = function (row, col) {\n return this.reservedBit[row * this.size + col]\n}\n\nmodule.exports = BitMatrix\n", + "/**\n * Alignment pattern are fixed reference pattern in defined positions\n * in a matrix symbology, which enables the decode software to re-synchronise\n * the coordinate mapping of the image modules in the event of moderate amounts\n * of distortion of the image.\n *\n * Alignment patterns are present only in QR Code symbols of version 2 or larger\n * and their number depends on the symbol version.\n */\n\nconst getSymbolSize = require('./utils').getSymbolSize\n\n/**\n * Calculate the row/column coordinates of the center module of each alignment pattern\n * for the specified QR Code version.\n *\n * The alignment patterns are positioned symmetrically on either side of the diagonal\n * running from the top left corner of the symbol to the bottom right corner.\n *\n * Since positions are simmetrical only half of the coordinates are returned.\n * Each item of the array will represent in turn the x and y coordinate.\n * @see {@link getPositions}\n *\n * @param {Number} version QR Code version\n * @return {Array} Array of coordinate\n */\nexports.getRowColCoords = function getRowColCoords (version) {\n if (version === 1) return []\n\n const posCount = Math.floor(version / 7) + 2\n const size = getSymbolSize(version)\n const intervals = size === 145 ? 26 : Math.ceil((size - 13) / (2 * posCount - 2)) * 2\n const positions = [size - 7] // Last coord is always (size - 7)\n\n for (let i = 1; i < posCount - 1; i++) {\n positions[i] = positions[i - 1] - intervals\n }\n\n positions.push(6) // First coord is always 6\n\n return positions.reverse()\n}\n\n/**\n * Returns an array containing the positions of each alignment pattern.\n * Each array's element represent the center point of the pattern as (x, y) coordinates\n *\n * Coordinates are calculated expanding the row/column coordinates returned by {@link getRowColCoords}\n * and filtering out the items that overlaps with finder pattern\n *\n * @example\n * For a Version 7 symbol {@link getRowColCoords} returns values 6, 22 and 38.\n * The alignment patterns, therefore, are to be centered on (row, column)\n * positions (6,22), (22,6), (22,22), (22,38), (38,22), (38,38).\n * Note that the coordinates (6,6), (6,38), (38,6) are occupied by finder patterns\n * and are not therefore used for alignment patterns.\n *\n * let pos = getPositions(7)\n * // [[6,22], [22,6], [22,22], [22,38], [38,22], [38,38]]\n *\n * @param {Number} version QR Code version\n * @return {Array} Array of coordinates\n */\nexports.getPositions = function getPositions (version) {\n const coords = []\n const pos = exports.getRowColCoords(version)\n const posLength = pos.length\n\n for (let i = 0; i < posLength; i++) {\n for (let j = 0; j < posLength; j++) {\n // Skip if position is occupied by finder patterns\n if ((i === 0 && j === 0) || // top-left\n (i === 0 && j === posLength - 1) || // bottom-left\n (i === posLength - 1 && j === 0)) { // top-right\n continue\n }\n\n coords.push([pos[i], pos[j]])\n }\n }\n\n return coords\n}\n", + "const getSymbolSize = require('./utils').getSymbolSize\nconst FINDER_PATTERN_SIZE = 7\n\n/**\n * Returns an array containing the positions of each finder pattern.\n * Each array's element represent the top-left point of the pattern as (x, y) coordinates\n *\n * @param {Number} version QR Code version\n * @return {Array} Array of coordinates\n */\nexports.getPositions = function getPositions (version) {\n const size = getSymbolSize(version)\n\n return [\n // top-left\n [0, 0],\n // top-right\n [size - FINDER_PATTERN_SIZE, 0],\n // bottom-left\n [0, size - FINDER_PATTERN_SIZE]\n ]\n}\n", + "/**\n * Data mask pattern reference\n * @type {Object}\n */\nexports.Patterns = {\n PATTERN000: 0,\n PATTERN001: 1,\n PATTERN010: 2,\n PATTERN011: 3,\n PATTERN100: 4,\n PATTERN101: 5,\n PATTERN110: 6,\n PATTERN111: 7\n}\n\n/**\n * Weighted penalty scores for the undesirable features\n * @type {Object}\n */\nconst PenaltyScores = {\n N1: 3,\n N2: 3,\n N3: 40,\n N4: 10\n}\n\n/**\n * Check if mask pattern value is valid\n *\n * @param {Number} mask Mask pattern\n * @return {Boolean} true if valid, false otherwise\n */\nexports.isValid = function isValid (mask) {\n return mask != null && mask !== '' && !isNaN(mask) && mask >= 0 && mask <= 7\n}\n\n/**\n * Returns mask pattern from a value.\n * If value is not valid, returns undefined\n *\n * @param {Number|String} value Mask pattern value\n * @return {Number} Valid mask pattern or undefined\n */\nexports.from = function from (value) {\n return exports.isValid(value) ? parseInt(value, 10) : undefined\n}\n\n/**\n* Find adjacent modules in row/column with the same color\n* and assign a penalty value.\n*\n* Points: N1 + i\n* i is the amount by which the number of adjacent modules of the same color exceeds 5\n*/\nexports.getPenaltyN1 = function getPenaltyN1 (data) {\n const size = data.size\n let points = 0\n let sameCountCol = 0\n let sameCountRow = 0\n let lastCol = null\n let lastRow = null\n\n for (let row = 0; row < size; row++) {\n sameCountCol = sameCountRow = 0\n lastCol = lastRow = null\n\n for (let col = 0; col < size; col++) {\n let module = data.get(row, col)\n if (module === lastCol) {\n sameCountCol++\n } else {\n if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5)\n lastCol = module\n sameCountCol = 1\n }\n\n module = data.get(col, row)\n if (module === lastRow) {\n sameCountRow++\n } else {\n if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5)\n lastRow = module\n sameCountRow = 1\n }\n }\n\n if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5)\n if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5)\n }\n\n return points\n}\n\n/**\n * Find 2x2 blocks with the same color and assign a penalty value\n *\n * Points: N2 * (m - 1) * (n - 1)\n */\nexports.getPenaltyN2 = function getPenaltyN2 (data) {\n const size = data.size\n let points = 0\n\n for (let row = 0; row < size - 1; row++) {\n for (let col = 0; col < size - 1; col++) {\n const last = data.get(row, col) +\n data.get(row, col + 1) +\n data.get(row + 1, col) +\n data.get(row + 1, col + 1)\n\n if (last === 4 || last === 0) points++\n }\n }\n\n return points * PenaltyScores.N2\n}\n\n/**\n * Find 1:1:3:1:1 ratio (dark:light:dark:light:dark) pattern in row/column,\n * preceded or followed by light area 4 modules wide\n *\n * Points: N3 * number of pattern found\n */\nexports.getPenaltyN3 = function getPenaltyN3 (data) {\n const size = data.size\n let points = 0\n let bitsCol = 0\n let bitsRow = 0\n\n for (let row = 0; row < size; row++) {\n bitsCol = bitsRow = 0\n for (let col = 0; col < size; col++) {\n bitsCol = ((bitsCol << 1) & 0x7FF) | data.get(row, col)\n if (col >= 10 && (bitsCol === 0x5D0 || bitsCol === 0x05D)) points++\n\n bitsRow = ((bitsRow << 1) & 0x7FF) | data.get(col, row)\n if (col >= 10 && (bitsRow === 0x5D0 || bitsRow === 0x05D)) points++\n }\n }\n\n return points * PenaltyScores.N3\n}\n\n/**\n * Calculate proportion of dark modules in entire symbol\n *\n * Points: N4 * k\n *\n * k is the rating of the deviation of the proportion of dark modules\n * in the symbol from 50% in steps of 5%\n */\nexports.getPenaltyN4 = function getPenaltyN4 (data) {\n let darkCount = 0\n const modulesCount = data.data.length\n\n for (let i = 0; i < modulesCount; i++) darkCount += data.data[i]\n\n const k = Math.abs(Math.ceil((darkCount * 100 / modulesCount) / 5) - 10)\n\n return k * PenaltyScores.N4\n}\n\n/**\n * Return mask value at given position\n *\n * @param {Number} maskPattern Pattern reference value\n * @param {Number} i Row\n * @param {Number} j Column\n * @return {Boolean} Mask value\n */\nfunction getMaskAt (maskPattern, i, j) {\n switch (maskPattern) {\n case exports.Patterns.PATTERN000: return (i + j) % 2 === 0\n case exports.Patterns.PATTERN001: return i % 2 === 0\n case exports.Patterns.PATTERN010: return j % 3 === 0\n case exports.Patterns.PATTERN011: return (i + j) % 3 === 0\n case exports.Patterns.PATTERN100: return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 === 0\n case exports.Patterns.PATTERN101: return (i * j) % 2 + (i * j) % 3 === 0\n case exports.Patterns.PATTERN110: return ((i * j) % 2 + (i * j) % 3) % 2 === 0\n case exports.Patterns.PATTERN111: return ((i * j) % 3 + (i + j) % 2) % 2 === 0\n\n default: throw new Error('bad maskPattern:' + maskPattern)\n }\n}\n\n/**\n * Apply a mask pattern to a BitMatrix\n *\n * @param {Number} pattern Pattern reference number\n * @param {BitMatrix} data BitMatrix data\n */\nexports.applyMask = function applyMask (pattern, data) {\n const size = data.size\n\n for (let col = 0; col < size; col++) {\n for (let row = 0; row < size; row++) {\n if (data.isReserved(row, col)) continue\n data.xor(row, col, getMaskAt(pattern, row, col))\n }\n }\n}\n\n/**\n * Returns the best mask pattern for data\n *\n * @param {BitMatrix} data\n * @return {Number} Mask pattern reference number\n */\nexports.getBestMask = function getBestMask (data, setupFormatFunc) {\n const numPatterns = Object.keys(exports.Patterns).length\n let bestPattern = 0\n let lowerPenalty = Infinity\n\n for (let p = 0; p < numPatterns; p++) {\n setupFormatFunc(p)\n exports.applyMask(p, data)\n\n // Calculate penalty\n const penalty =\n exports.getPenaltyN1(data) +\n exports.getPenaltyN2(data) +\n exports.getPenaltyN3(data) +\n exports.getPenaltyN4(data)\n\n // Undo previously applied mask\n exports.applyMask(p, data)\n\n if (penalty < lowerPenalty) {\n lowerPenalty = penalty\n bestPattern = p\n }\n }\n\n return bestPattern\n}\n", + "const ECLevel = require('./error-correction-level')\r\n\r\nconst EC_BLOCKS_TABLE = [\r\n// L M Q H\r\n 1, 1, 1, 1,\r\n 1, 1, 1, 1,\r\n 1, 1, 2, 2,\r\n 1, 2, 2, 4,\r\n 1, 2, 4, 4,\r\n 2, 4, 4, 4,\r\n 2, 4, 6, 5,\r\n 2, 4, 6, 6,\r\n 2, 5, 8, 8,\r\n 4, 5, 8, 8,\r\n 4, 5, 8, 11,\r\n 4, 8, 10, 11,\r\n 4, 9, 12, 16,\r\n 4, 9, 16, 16,\r\n 6, 10, 12, 18,\r\n 6, 10, 17, 16,\r\n 6, 11, 16, 19,\r\n 6, 13, 18, 21,\r\n 7, 14, 21, 25,\r\n 8, 16, 20, 25,\r\n 8, 17, 23, 25,\r\n 9, 17, 23, 34,\r\n 9, 18, 25, 30,\r\n 10, 20, 27, 32,\r\n 12, 21, 29, 35,\r\n 12, 23, 34, 37,\r\n 12, 25, 34, 40,\r\n 13, 26, 35, 42,\r\n 14, 28, 38, 45,\r\n 15, 29, 40, 48,\r\n 16, 31, 43, 51,\r\n 17, 33, 45, 54,\r\n 18, 35, 48, 57,\r\n 19, 37, 51, 60,\r\n 19, 38, 53, 63,\r\n 20, 40, 56, 66,\r\n 21, 43, 59, 70,\r\n 22, 45, 62, 74,\r\n 24, 47, 65, 77,\r\n 25, 49, 68, 81\r\n]\r\n\r\nconst EC_CODEWORDS_TABLE = [\r\n// L M Q H\r\n 7, 10, 13, 17,\r\n 10, 16, 22, 28,\r\n 15, 26, 36, 44,\r\n 20, 36, 52, 64,\r\n 26, 48, 72, 88,\r\n 36, 64, 96, 112,\r\n 40, 72, 108, 130,\r\n 48, 88, 132, 156,\r\n 60, 110, 160, 192,\r\n 72, 130, 192, 224,\r\n 80, 150, 224, 264,\r\n 96, 176, 260, 308,\r\n 104, 198, 288, 352,\r\n 120, 216, 320, 384,\r\n 132, 240, 360, 432,\r\n 144, 280, 408, 480,\r\n 168, 308, 448, 532,\r\n 180, 338, 504, 588,\r\n 196, 364, 546, 650,\r\n 224, 416, 600, 700,\r\n 224, 442, 644, 750,\r\n 252, 476, 690, 816,\r\n 270, 504, 750, 900,\r\n 300, 560, 810, 960,\r\n 312, 588, 870, 1050,\r\n 336, 644, 952, 1110,\r\n 360, 700, 1020, 1200,\r\n 390, 728, 1050, 1260,\r\n 420, 784, 1140, 1350,\r\n 450, 812, 1200, 1440,\r\n 480, 868, 1290, 1530,\r\n 510, 924, 1350, 1620,\r\n 540, 980, 1440, 1710,\r\n 570, 1036, 1530, 1800,\r\n 570, 1064, 1590, 1890,\r\n 600, 1120, 1680, 1980,\r\n 630, 1204, 1770, 2100,\r\n 660, 1260, 1860, 2220,\r\n 720, 1316, 1950, 2310,\r\n 750, 1372, 2040, 2430\r\n]\r\n\r\n/**\r\n * Returns the number of error correction block that the QR Code should contain\r\n * for the specified version and error correction level.\r\n *\r\n * @param {Number} version QR Code version\r\n * @param {Number} errorCorrectionLevel Error correction level\r\n * @return {Number} Number of error correction blocks\r\n */\r\nexports.getBlocksCount = function getBlocksCount (version, errorCorrectionLevel) {\r\n switch (errorCorrectionLevel) {\r\n case ECLevel.L:\r\n return EC_BLOCKS_TABLE[(version - 1) * 4 + 0]\r\n case ECLevel.M:\r\n return EC_BLOCKS_TABLE[(version - 1) * 4 + 1]\r\n case ECLevel.Q:\r\n return EC_BLOCKS_TABLE[(version - 1) * 4 + 2]\r\n case ECLevel.H:\r\n return EC_BLOCKS_TABLE[(version - 1) * 4 + 3]\r\n default:\r\n return undefined\r\n }\r\n}\r\n\r\n/**\r\n * Returns the number of error correction codewords to use for the specified\r\n * version and error correction level.\r\n *\r\n * @param {Number} version QR Code version\r\n * @param {Number} errorCorrectionLevel Error correction level\r\n * @return {Number} Number of error correction codewords\r\n */\r\nexports.getTotalCodewordsCount = function getTotalCodewordsCount (version, errorCorrectionLevel) {\r\n switch (errorCorrectionLevel) {\r\n case ECLevel.L:\r\n return EC_CODEWORDS_TABLE[(version - 1) * 4 + 0]\r\n case ECLevel.M:\r\n return EC_CODEWORDS_TABLE[(version - 1) * 4 + 1]\r\n case ECLevel.Q:\r\n return EC_CODEWORDS_TABLE[(version - 1) * 4 + 2]\r\n case ECLevel.H:\r\n return EC_CODEWORDS_TABLE[(version - 1) * 4 + 3]\r\n default:\r\n return undefined\r\n }\r\n}\r\n", + "const EXP_TABLE = new Uint8Array(512)\nconst LOG_TABLE = new Uint8Array(256)\n/**\n * Precompute the log and anti-log tables for faster computation later\n *\n * For each possible value in the galois field 2^8, we will pre-compute\n * the logarithm and anti-logarithm (exponential) of this value\n *\n * ref {@link https://en.wikiversity.org/wiki/Reed%E2%80%93Solomon_codes_for_coders#Introduction_to_mathematical_fields}\n */\n;(function initTables () {\n let x = 1\n for (let i = 0; i < 255; i++) {\n EXP_TABLE[i] = x\n LOG_TABLE[x] = i\n\n x <<= 1 // multiply by 2\n\n // The QR code specification says to use byte-wise modulo 100011101 arithmetic.\n // This means that when a number is 256 or larger, it should be XORed with 0x11D.\n if (x & 0x100) { // similar to x >= 256, but a lot faster (because 0x100 == 256)\n x ^= 0x11D\n }\n }\n\n // Optimization: double the size of the anti-log table so that we don't need to mod 255 to\n // stay inside the bounds (because we will mainly use this table for the multiplication of\n // two GF numbers, no more).\n // @see {@link mul}\n for (let i = 255; i < 512; i++) {\n EXP_TABLE[i] = EXP_TABLE[i - 255]\n }\n}())\n\n/**\n * Returns log value of n inside Galois Field\n *\n * @param {Number} n\n * @return {Number}\n */\nexports.log = function log (n) {\n if (n < 1) throw new Error('log(' + n + ')')\n return LOG_TABLE[n]\n}\n\n/**\n * Returns anti-log value of n inside Galois Field\n *\n * @param {Number} n\n * @return {Number}\n */\nexports.exp = function exp (n) {\n return EXP_TABLE[n]\n}\n\n/**\n * Multiplies two number inside Galois Field\n *\n * @param {Number} x\n * @param {Number} y\n * @return {Number}\n */\nexports.mul = function mul (x, y) {\n if (x === 0 || y === 0) return 0\n\n // should be EXP_TABLE[(LOG_TABLE[x] + LOG_TABLE[y]) % 255] if EXP_TABLE wasn't oversized\n // @see {@link initTables}\n return EXP_TABLE[LOG_TABLE[x] + LOG_TABLE[y]]\n}\n", + "const GF = require('./galois-field')\n\n/**\n * Multiplies two polynomials inside Galois Field\n *\n * @param {Uint8Array} p1 Polynomial\n * @param {Uint8Array} p2 Polynomial\n * @return {Uint8Array} Product of p1 and p2\n */\nexports.mul = function mul (p1, p2) {\n const coeff = new Uint8Array(p1.length + p2.length - 1)\n\n for (let i = 0; i < p1.length; i++) {\n for (let j = 0; j < p2.length; j++) {\n coeff[i + j] ^= GF.mul(p1[i], p2[j])\n }\n }\n\n return coeff\n}\n\n/**\n * Calculate the remainder of polynomials division\n *\n * @param {Uint8Array} divident Polynomial\n * @param {Uint8Array} divisor Polynomial\n * @return {Uint8Array} Remainder\n */\nexports.mod = function mod (divident, divisor) {\n let result = new Uint8Array(divident)\n\n while ((result.length - divisor.length) >= 0) {\n const coeff = result[0]\n\n for (let i = 0; i < divisor.length; i++) {\n result[i] ^= GF.mul(divisor[i], coeff)\n }\n\n // remove all zeros from buffer head\n let offset = 0\n while (offset < result.length && result[offset] === 0) offset++\n result = result.slice(offset)\n }\n\n return result\n}\n\n/**\n * Generate an irreducible generator polynomial of specified degree\n * (used by Reed-Solomon encoder)\n *\n * @param {Number} degree Degree of the generator polynomial\n * @return {Uint8Array} Buffer containing polynomial coefficients\n */\nexports.generateECPolynomial = function generateECPolynomial (degree) {\n let poly = new Uint8Array([1])\n for (let i = 0; i < degree; i++) {\n poly = exports.mul(poly, new Uint8Array([1, GF.exp(i)]))\n }\n\n return poly\n}\n", + "const Polynomial = require('./polynomial')\n\nfunction ReedSolomonEncoder (degree) {\n this.genPoly = undefined\n this.degree = degree\n\n if (this.degree) this.initialize(this.degree)\n}\n\n/**\n * Initialize the encoder.\n * The input param should correspond to the number of error correction codewords.\n *\n * @param {Number} degree\n */\nReedSolomonEncoder.prototype.initialize = function initialize (degree) {\n // create an irreducible generator polynomial\n this.degree = degree\n this.genPoly = Polynomial.generateECPolynomial(this.degree)\n}\n\n/**\n * Encodes a chunk of data\n *\n * @param {Uint8Array} data Buffer containing input data\n * @return {Uint8Array} Buffer containing encoded data\n */\nReedSolomonEncoder.prototype.encode = function encode (data) {\n if (!this.genPoly) {\n throw new Error('Encoder not initialized')\n }\n\n // Calculate EC for this data block\n // extends data size to data+genPoly size\n const paddedData = new Uint8Array(data.length + this.degree)\n paddedData.set(data)\n\n // The error correction codewords are the remainder after dividing the data codewords\n // by a generator polynomial\n const remainder = Polynomial.mod(paddedData, this.genPoly)\n\n // return EC data blocks (last n byte, where n is the degree of genPoly)\n // If coefficients number in remainder are less than genPoly degree,\n // pad with 0s to the left to reach the needed number of coefficients\n const start = this.degree - remainder.length\n if (start > 0) {\n const buff = new Uint8Array(this.degree)\n buff.set(remainder, start)\n\n return buff\n }\n\n return remainder\n}\n\nmodule.exports = ReedSolomonEncoder\n", + "/**\n * Check if QR Code version is valid\n *\n * @param {Number} version QR Code version\n * @return {Boolean} true if valid version, false otherwise\n */\nexports.isValid = function isValid (version) {\n return !isNaN(version) && version >= 1 && version <= 40\n}\n", + "const numeric = '[0-9]+'\nconst alphanumeric = '[A-Z $%*+\\\\-./:]+'\nlet kanji = '(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|' +\n '[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|' +\n '[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|' +\n '[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+'\nkanji = kanji.replace(/u/g, '\\\\u')\n\nconst byte = '(?:(?![A-Z0-9 $%*+\\\\-./:]|' + kanji + ')(?:.|[\\r\\n]))+'\n\nexports.KANJI = new RegExp(kanji, 'g')\nexports.BYTE_KANJI = new RegExp('[^A-Z0-9 $%*+\\\\-./:]+', 'g')\nexports.BYTE = new RegExp(byte, 'g')\nexports.NUMERIC = new RegExp(numeric, 'g')\nexports.ALPHANUMERIC = new RegExp(alphanumeric, 'g')\n\nconst TEST_KANJI = new RegExp('^' + kanji + '$')\nconst TEST_NUMERIC = new RegExp('^' + numeric + '$')\nconst TEST_ALPHANUMERIC = new RegExp('^[A-Z0-9 $%*+\\\\-./:]+$')\n\nexports.testKanji = function testKanji (str) {\n return TEST_KANJI.test(str)\n}\n\nexports.testNumeric = function testNumeric (str) {\n return TEST_NUMERIC.test(str)\n}\n\nexports.testAlphanumeric = function testAlphanumeric (str) {\n return TEST_ALPHANUMERIC.test(str)\n}\n", + "const VersionCheck = require('./version-check')\nconst Regex = require('./regex')\n\n/**\n * Numeric mode encodes data from the decimal digit set (0 - 9)\n * (byte values 30HEX to 39HEX).\n * Normally, 3 data characters are represented by 10 bits.\n *\n * @type {Object}\n */\nexports.NUMERIC = {\n id: 'Numeric',\n bit: 1 << 0,\n ccBits: [10, 12, 14]\n}\n\n/**\n * Alphanumeric mode encodes data from a set of 45 characters,\n * i.e. 10 numeric digits (0 - 9),\n * 26 alphabetic characters (A - Z),\n * and 9 symbols (SP, $, %, *, +, -, ., /, :).\n * Normally, two input characters are represented by 11 bits.\n *\n * @type {Object}\n */\nexports.ALPHANUMERIC = {\n id: 'Alphanumeric',\n bit: 1 << 1,\n ccBits: [9, 11, 13]\n}\n\n/**\n * In byte mode, data is encoded at 8 bits per character.\n *\n * @type {Object}\n */\nexports.BYTE = {\n id: 'Byte',\n bit: 1 << 2,\n ccBits: [8, 16, 16]\n}\n\n/**\n * The Kanji mode efficiently encodes Kanji characters in accordance with\n * the Shift JIS system based on JIS X 0208.\n * The Shift JIS values are shifted from the JIS X 0208 values.\n * JIS X 0208 gives details of the shift coded representation.\n * Each two-byte character value is compacted to a 13-bit binary codeword.\n *\n * @type {Object}\n */\nexports.KANJI = {\n id: 'Kanji',\n bit: 1 << 3,\n ccBits: [8, 10, 12]\n}\n\n/**\n * Mixed mode will contain a sequences of data in a combination of any of\n * the modes described above\n *\n * @type {Object}\n */\nexports.MIXED = {\n bit: -1\n}\n\n/**\n * Returns the number of bits needed to store the data length\n * according to QR Code specifications.\n *\n * @param {Mode} mode Data mode\n * @param {Number} version QR Code version\n * @return {Number} Number of bits\n */\nexports.getCharCountIndicator = function getCharCountIndicator (mode, version) {\n if (!mode.ccBits) throw new Error('Invalid mode: ' + mode)\n\n if (!VersionCheck.isValid(version)) {\n throw new Error('Invalid version: ' + version)\n }\n\n if (version >= 1 && version < 10) return mode.ccBits[0]\n else if (version < 27) return mode.ccBits[1]\n return mode.ccBits[2]\n}\n\n/**\n * Returns the most efficient mode to store the specified data\n *\n * @param {String} dataStr Input data string\n * @return {Mode} Best mode\n */\nexports.getBestModeForData = function getBestModeForData (dataStr) {\n if (Regex.testNumeric(dataStr)) return exports.NUMERIC\n else if (Regex.testAlphanumeric(dataStr)) return exports.ALPHANUMERIC\n else if (Regex.testKanji(dataStr)) return exports.KANJI\n else return exports.BYTE\n}\n\n/**\n * Return mode name as string\n *\n * @param {Mode} mode Mode object\n * @returns {String} Mode name\n */\nexports.toString = function toString (mode) {\n if (mode && mode.id) return mode.id\n throw new Error('Invalid mode')\n}\n\n/**\n * Check if input param is a valid mode object\n *\n * @param {Mode} mode Mode object\n * @returns {Boolean} True if valid mode, false otherwise\n */\nexports.isValid = function isValid (mode) {\n return mode && mode.bit && mode.ccBits\n}\n\n/**\n * Get mode object from its name\n *\n * @param {String} string Mode name\n * @returns {Mode} Mode object\n */\nfunction fromString (string) {\n if (typeof string !== 'string') {\n throw new Error('Param is not a string')\n }\n\n const lcStr = string.toLowerCase()\n\n switch (lcStr) {\n case 'numeric':\n return exports.NUMERIC\n case 'alphanumeric':\n return exports.ALPHANUMERIC\n case 'kanji':\n return exports.KANJI\n case 'byte':\n return exports.BYTE\n default:\n throw new Error('Unknown mode: ' + string)\n }\n}\n\n/**\n * Returns mode from a value.\n * If value is not a valid mode, returns defaultValue\n *\n * @param {Mode|String} value Encoding mode\n * @param {Mode} defaultValue Fallback value\n * @return {Mode} Encoding mode\n */\nexports.from = function from (value, defaultValue) {\n if (exports.isValid(value)) {\n return value\n }\n\n try {\n return fromString(value)\n } catch (e) {\n return defaultValue\n }\n}\n", + "const Utils = require('./utils')\nconst ECCode = require('./error-correction-code')\nconst ECLevel = require('./error-correction-level')\nconst Mode = require('./mode')\nconst VersionCheck = require('./version-check')\n\n// Generator polynomial used to encode version information\nconst G18 = (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0)\nconst G18_BCH = Utils.getBCHDigit(G18)\n\nfunction getBestVersionForDataLength (mode, length, errorCorrectionLevel) {\n for (let currentVersion = 1; currentVersion <= 40; currentVersion++) {\n if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel, mode)) {\n return currentVersion\n }\n }\n\n return undefined\n}\n\nfunction getReservedBitsCount (mode, version) {\n // Character count indicator + mode indicator bits\n return Mode.getCharCountIndicator(mode, version) + 4\n}\n\nfunction getTotalBitsFromDataArray (segments, version) {\n let totalBits = 0\n\n segments.forEach(function (data) {\n const reservedBits = getReservedBitsCount(data.mode, version)\n totalBits += reservedBits + data.getBitsLength()\n })\n\n return totalBits\n}\n\nfunction getBestVersionForMixedData (segments, errorCorrectionLevel) {\n for (let currentVersion = 1; currentVersion <= 40; currentVersion++) {\n const length = getTotalBitsFromDataArray(segments, currentVersion)\n if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel, Mode.MIXED)) {\n return currentVersion\n }\n }\n\n return undefined\n}\n\n/**\n * Returns version number from a value.\n * If value is not a valid version, returns defaultValue\n *\n * @param {Number|String} value QR Code version\n * @param {Number} defaultValue Fallback value\n * @return {Number} QR Code version number\n */\nexports.from = function from (value, defaultValue) {\n if (VersionCheck.isValid(value)) {\n return parseInt(value, 10)\n }\n\n return defaultValue\n}\n\n/**\n * Returns how much data can be stored with the specified QR code version\n * and error correction level\n *\n * @param {Number} version QR Code version (1-40)\n * @param {Number} errorCorrectionLevel Error correction level\n * @param {Mode} mode Data mode\n * @return {Number} Quantity of storable data\n */\nexports.getCapacity = function getCapacity (version, errorCorrectionLevel, mode) {\n if (!VersionCheck.isValid(version)) {\n throw new Error('Invalid QR Code version')\n }\n\n // Use Byte mode as default\n if (typeof mode === 'undefined') mode = Mode.BYTE\n\n // Total codewords for this QR code version (Data + Error correction)\n const totalCodewords = Utils.getSymbolTotalCodewords(version)\n\n // Total number of error correction codewords\n const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel)\n\n // Total number of data codewords\n const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8\n\n if (mode === Mode.MIXED) return dataTotalCodewordsBits\n\n const usableBits = dataTotalCodewordsBits - getReservedBitsCount(mode, version)\n\n // Return max number of storable codewords\n switch (mode) {\n case Mode.NUMERIC:\n return Math.floor((usableBits / 10) * 3)\n\n case Mode.ALPHANUMERIC:\n return Math.floor((usableBits / 11) * 2)\n\n case Mode.KANJI:\n return Math.floor(usableBits / 13)\n\n case Mode.BYTE:\n default:\n return Math.floor(usableBits / 8)\n }\n}\n\n/**\n * Returns the minimum version needed to contain the amount of data\n *\n * @param {Segment} data Segment of data\n * @param {Number} [errorCorrectionLevel=H] Error correction level\n * @param {Mode} mode Data mode\n * @return {Number} QR Code version\n */\nexports.getBestVersionForData = function getBestVersionForData (data, errorCorrectionLevel) {\n let seg\n\n const ecl = ECLevel.from(errorCorrectionLevel, ECLevel.M)\n\n if (Array.isArray(data)) {\n if (data.length > 1) {\n return getBestVersionForMixedData(data, ecl)\n }\n\n if (data.length === 0) {\n return 1\n }\n\n seg = data[0]\n } else {\n seg = data\n }\n\n return getBestVersionForDataLength(seg.mode, seg.getLength(), ecl)\n}\n\n/**\n * Returns version information with relative error correction bits\n *\n * The version information is included in QR Code symbols of version 7 or larger.\n * It consists of an 18-bit sequence containing 6 data bits,\n * with 12 error correction bits calculated using the (18, 6) Golay code.\n *\n * @param {Number} version QR Code version\n * @return {Number} Encoded version info bits\n */\nexports.getEncodedBits = function getEncodedBits (version) {\n if (!VersionCheck.isValid(version) || version < 7) {\n throw new Error('Invalid QR Code version')\n }\n\n let d = version << 12\n\n while (Utils.getBCHDigit(d) - G18_BCH >= 0) {\n d ^= (G18 << (Utils.getBCHDigit(d) - G18_BCH))\n }\n\n return (version << 12) | d\n}\n", + "const Utils = require('./utils')\n\nconst G15 = (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0)\nconst G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1)\nconst G15_BCH = Utils.getBCHDigit(G15)\n\n/**\n * Returns format information with relative error correction bits\n *\n * The format information is a 15-bit sequence containing 5 data bits,\n * with 10 error correction bits calculated using the (15, 5) BCH code.\n *\n * @param {Number} errorCorrectionLevel Error correction level\n * @param {Number} mask Mask pattern\n * @return {Number} Encoded format information bits\n */\nexports.getEncodedBits = function getEncodedBits (errorCorrectionLevel, mask) {\n const data = ((errorCorrectionLevel.bit << 3) | mask)\n let d = data << 10\n\n while (Utils.getBCHDigit(d) - G15_BCH >= 0) {\n d ^= (G15 << (Utils.getBCHDigit(d) - G15_BCH))\n }\n\n // xor final data with mask pattern in order to ensure that\n // no combination of Error Correction Level and data mask pattern\n // will result in an all-zero data string\n return ((data << 10) | d) ^ G15_MASK\n}\n", + "const Mode = require('./mode')\n\nfunction NumericData (data) {\n this.mode = Mode.NUMERIC\n this.data = data.toString()\n}\n\nNumericData.getBitsLength = function getBitsLength (length) {\n return 10 * Math.floor(length / 3) + ((length % 3) ? ((length % 3) * 3 + 1) : 0)\n}\n\nNumericData.prototype.getLength = function getLength () {\n return this.data.length\n}\n\nNumericData.prototype.getBitsLength = function getBitsLength () {\n return NumericData.getBitsLength(this.data.length)\n}\n\nNumericData.prototype.write = function write (bitBuffer) {\n let i, group, value\n\n // The input data string is divided into groups of three digits,\n // and each group is converted to its 10-bit binary equivalent.\n for (i = 0; i + 3 <= this.data.length; i += 3) {\n group = this.data.substr(i, 3)\n value = parseInt(group, 10)\n\n bitBuffer.put(value, 10)\n }\n\n // If the number of input digits is not an exact multiple of three,\n // the final one or two digits are converted to 4 or 7 bits respectively.\n const remainingNum = this.data.length - i\n if (remainingNum > 0) {\n group = this.data.substr(i)\n value = parseInt(group, 10)\n\n bitBuffer.put(value, remainingNum * 3 + 1)\n }\n}\n\nmodule.exports = NumericData\n", + "const Mode = require('./mode')\n\n/**\n * Array of characters available in alphanumeric mode\n *\n * As per QR Code specification, to each character\n * is assigned a value from 0 to 44 which in this case coincides\n * with the array index\n *\n * @type {Array}\n */\nconst ALPHA_NUM_CHARS = [\n '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',\n 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',\n 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',\n ' ', '$', '%', '*', '+', '-', '.', '/', ':'\n]\n\nfunction AlphanumericData (data) {\n this.mode = Mode.ALPHANUMERIC\n this.data = data\n}\n\nAlphanumericData.getBitsLength = function getBitsLength (length) {\n return 11 * Math.floor(length / 2) + 6 * (length % 2)\n}\n\nAlphanumericData.prototype.getLength = function getLength () {\n return this.data.length\n}\n\nAlphanumericData.prototype.getBitsLength = function getBitsLength () {\n return AlphanumericData.getBitsLength(this.data.length)\n}\n\nAlphanumericData.prototype.write = function write (bitBuffer) {\n let i\n\n // Input data characters are divided into groups of two characters\n // and encoded as 11-bit binary codes.\n for (i = 0; i + 2 <= this.data.length; i += 2) {\n // The character value of the first character is multiplied by 45\n let value = ALPHA_NUM_CHARS.indexOf(this.data[i]) * 45\n\n // The character value of the second digit is added to the product\n value += ALPHA_NUM_CHARS.indexOf(this.data[i + 1])\n\n // The sum is then stored as 11-bit binary number\n bitBuffer.put(value, 11)\n }\n\n // If the number of input data characters is not a multiple of two,\n // the character value of the final character is encoded as a 6-bit binary number.\n if (this.data.length % 2) {\n bitBuffer.put(ALPHA_NUM_CHARS.indexOf(this.data[i]), 6)\n }\n}\n\nmodule.exports = AlphanumericData\n", + "const Mode = require('./mode')\n\nfunction ByteData (data) {\n this.mode = Mode.BYTE\n if (typeof (data) === 'string') {\n this.data = new TextEncoder().encode(data)\n } else {\n this.data = new Uint8Array(data)\n }\n}\n\nByteData.getBitsLength = function getBitsLength (length) {\n return length * 8\n}\n\nByteData.prototype.getLength = function getLength () {\n return this.data.length\n}\n\nByteData.prototype.getBitsLength = function getBitsLength () {\n return ByteData.getBitsLength(this.data.length)\n}\n\nByteData.prototype.write = function (bitBuffer) {\n for (let i = 0, l = this.data.length; i < l; i++) {\n bitBuffer.put(this.data[i], 8)\n }\n}\n\nmodule.exports = ByteData\n", + "const Mode = require('./mode')\nconst Utils = require('./utils')\n\nfunction KanjiData (data) {\n this.mode = Mode.KANJI\n this.data = data\n}\n\nKanjiData.getBitsLength = function getBitsLength (length) {\n return length * 13\n}\n\nKanjiData.prototype.getLength = function getLength () {\n return this.data.length\n}\n\nKanjiData.prototype.getBitsLength = function getBitsLength () {\n return KanjiData.getBitsLength(this.data.length)\n}\n\nKanjiData.prototype.write = function (bitBuffer) {\n let i\n\n // In the Shift JIS system, Kanji characters are represented by a two byte combination.\n // These byte values are shifted from the JIS X 0208 values.\n // JIS X 0208 gives details of the shift coded representation.\n for (i = 0; i < this.data.length; i++) {\n let value = Utils.toSJIS(this.data[i])\n\n // For characters with Shift JIS values from 0x8140 to 0x9FFC:\n if (value >= 0x8140 && value <= 0x9FFC) {\n // Subtract 0x8140 from Shift JIS value\n value -= 0x8140\n\n // For characters with Shift JIS values from 0xE040 to 0xEBBF\n } else if (value >= 0xE040 && value <= 0xEBBF) {\n // Subtract 0xC140 from Shift JIS value\n value -= 0xC140\n } else {\n throw new Error(\n 'Invalid SJIS character: ' + this.data[i] + '\\n' +\n 'Make sure your charset is UTF-8')\n }\n\n // Multiply most significant byte of result by 0xC0\n // and add least significant byte to product\n value = (((value >>> 8) & 0xff) * 0xC0) + (value & 0xff)\n\n // Convert result to a 13-bit binary string\n bitBuffer.put(value, 13)\n }\n}\n\nmodule.exports = KanjiData\n", + "'use strict';\n\n/******************************************************************************\n * Created 2008-08-19.\n *\n * Dijkstra path-finding functions. Adapted from the Dijkstar Python project.\n *\n * Copyright (C) 2008\n * Wyatt Baldwin <self@wyattbaldwin.com>\n * All rights reserved\n *\n * Licensed under the MIT license.\n *\n * http://www.opensource.org/licenses/mit-license.php\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n * THE SOFTWARE.\n *****************************************************************************/\nvar dijkstra = {\n single_source_shortest_paths: function(graph, s, d) {\n // Predecessor map for each node that has been encountered.\n // node ID => predecessor node ID\n var predecessors = {};\n\n // Costs of shortest paths from s to all nodes encountered.\n // node ID => cost\n var costs = {};\n costs[s] = 0;\n\n // Costs of shortest paths from s to all nodes encountered; differs from\n // `costs` in that it provides easy access to the node that currently has\n // the known shortest path from s.\n // XXX: Do we actually need both `costs` and `open`?\n var open = dijkstra.PriorityQueue.make();\n open.push(s, 0);\n\n var closest,\n u, v,\n cost_of_s_to_u,\n adjacent_nodes,\n cost_of_e,\n cost_of_s_to_u_plus_cost_of_e,\n cost_of_s_to_v,\n first_visit;\n while (!open.empty()) {\n // In the nodes remaining in graph that have a known cost from s,\n // find the node, u, that currently has the shortest path from s.\n closest = open.pop();\n u = closest.value;\n cost_of_s_to_u = closest.cost;\n\n // Get nodes adjacent to u...\n adjacent_nodes = graph[u] || {};\n\n // ...and explore the edges that connect u to those nodes, updating\n // the cost of the shortest paths to any or all of those nodes as\n // necessary. v is the node across the current edge from u.\n for (v in adjacent_nodes) {\n if (adjacent_nodes.hasOwnProperty(v)) {\n // Get the cost of the edge running from u to v.\n cost_of_e = adjacent_nodes[v];\n\n // Cost of s to u plus the cost of u to v across e--this is *a*\n // cost from s to v that may or may not be less than the current\n // known cost to v.\n cost_of_s_to_u_plus_cost_of_e = cost_of_s_to_u + cost_of_e;\n\n // If we haven't visited v yet OR if the current known cost from s to\n // v is greater than the new cost we just found (cost of s to u plus\n // cost of u to v across e), update v's cost in the cost list and\n // update v's predecessor in the predecessor list (it's now u).\n cost_of_s_to_v = costs[v];\n first_visit = (typeof costs[v] === 'undefined');\n if (first_visit || cost_of_s_to_v > cost_of_s_to_u_plus_cost_of_e) {\n costs[v] = cost_of_s_to_u_plus_cost_of_e;\n open.push(v, cost_of_s_to_u_plus_cost_of_e);\n predecessors[v] = u;\n }\n }\n }\n }\n\n if (typeof d !== 'undefined' && typeof costs[d] === 'undefined') {\n var msg = ['Could not find a path from ', s, ' to ', d, '.'].join('');\n throw new Error(msg);\n }\n\n return predecessors;\n },\n\n extract_shortest_path_from_predecessor_list: function(predecessors, d) {\n var nodes = [];\n var u = d;\n var predecessor;\n while (u) {\n nodes.push(u);\n predecessor = predecessors[u];\n u = predecessors[u];\n }\n nodes.reverse();\n return nodes;\n },\n\n find_path: function(graph, s, d) {\n var predecessors = dijkstra.single_source_shortest_paths(graph, s, d);\n return dijkstra.extract_shortest_path_from_predecessor_list(\n predecessors, d);\n },\n\n /**\n * A very naive priority queue implementation.\n */\n PriorityQueue: {\n make: function (opts) {\n var T = dijkstra.PriorityQueue,\n t = {},\n key;\n opts = opts || {};\n for (key in T) {\n if (T.hasOwnProperty(key)) {\n t[key] = T[key];\n }\n }\n t.queue = [];\n t.sorter = opts.sorter || T.default_sorter;\n return t;\n },\n\n default_sorter: function (a, b) {\n return a.cost - b.cost;\n },\n\n /**\n * Add a new item to the queue and ensure the highest priority element\n * is at the front of the queue.\n */\n push: function (value, cost) {\n var item = {value: value, cost: cost};\n this.queue.push(item);\n this.queue.sort(this.sorter);\n },\n\n /**\n * Return the highest priority element in the queue.\n */\n pop: function () {\n return this.queue.shift();\n },\n\n empty: function () {\n return this.queue.length === 0;\n }\n }\n};\n\n\n// node.js module exports\nif (typeof module !== 'undefined') {\n module.exports = dijkstra;\n}\n", + "const Mode = require('./mode')\nconst NumericData = require('./numeric-data')\nconst AlphanumericData = require('./alphanumeric-data')\nconst ByteData = require('./byte-data')\nconst KanjiData = require('./kanji-data')\nconst Regex = require('./regex')\nconst Utils = require('./utils')\nconst dijkstra = require('dijkstrajs')\n\n/**\n * Returns UTF8 byte length\n *\n * @param {String} str Input string\n * @return {Number} Number of byte\n */\nfunction getStringByteLength (str) {\n return unescape(encodeURIComponent(str)).length\n}\n\n/**\n * Get a list of segments of the specified mode\n * from a string\n *\n * @param {Mode} mode Segment mode\n * @param {String} str String to process\n * @return {Array} Array of object with segments data\n */\nfunction getSegments (regex, mode, str) {\n const segments = []\n let result\n\n while ((result = regex.exec(str)) !== null) {\n segments.push({\n data: result[0],\n index: result.index,\n mode: mode,\n length: result[0].length\n })\n }\n\n return segments\n}\n\n/**\n * Extracts a series of segments with the appropriate\n * modes from a string\n *\n * @param {String} dataStr Input string\n * @return {Array} Array of object with segments data\n */\nfunction getSegmentsFromString (dataStr) {\n const numSegs = getSegments(Regex.NUMERIC, Mode.NUMERIC, dataStr)\n const alphaNumSegs = getSegments(Regex.ALPHANUMERIC, Mode.ALPHANUMERIC, dataStr)\n let byteSegs\n let kanjiSegs\n\n if (Utils.isKanjiModeEnabled()) {\n byteSegs = getSegments(Regex.BYTE, Mode.BYTE, dataStr)\n kanjiSegs = getSegments(Regex.KANJI, Mode.KANJI, dataStr)\n } else {\n byteSegs = getSegments(Regex.BYTE_KANJI, Mode.BYTE, dataStr)\n kanjiSegs = []\n }\n\n const segs = numSegs.concat(alphaNumSegs, byteSegs, kanjiSegs)\n\n return segs\n .sort(function (s1, s2) {\n return s1.index - s2.index\n })\n .map(function (obj) {\n return {\n data: obj.data,\n mode: obj.mode,\n length: obj.length\n }\n })\n}\n\n/**\n * Returns how many bits are needed to encode a string of\n * specified length with the specified mode\n *\n * @param {Number} length String length\n * @param {Mode} mode Segment mode\n * @return {Number} Bit length\n */\nfunction getSegmentBitsLength (length, mode) {\n switch (mode) {\n case Mode.NUMERIC:\n return NumericData.getBitsLength(length)\n case Mode.ALPHANUMERIC:\n return AlphanumericData.getBitsLength(length)\n case Mode.KANJI:\n return KanjiData.getBitsLength(length)\n case Mode.BYTE:\n return ByteData.getBitsLength(length)\n }\n}\n\n/**\n * Merges adjacent segments which have the same mode\n *\n * @param {Array} segs Array of object with segments data\n * @return {Array} Array of object with segments data\n */\nfunction mergeSegments (segs) {\n return segs.reduce(function (acc, curr) {\n const prevSeg = acc.length - 1 >= 0 ? acc[acc.length - 1] : null\n if (prevSeg && prevSeg.mode === curr.mode) {\n acc[acc.length - 1].data += curr.data\n return acc\n }\n\n acc.push(curr)\n return acc\n }, [])\n}\n\n/**\n * Generates a list of all possible nodes combination which\n * will be used to build a segments graph.\n *\n * Nodes are divided by groups. Each group will contain a list of all the modes\n * in which is possible to encode the given text.\n *\n * For example the text '12345' can be encoded as Numeric, Alphanumeric or Byte.\n * The group for '12345' will contain then 3 objects, one for each\n * possible encoding mode.\n *\n * Each node represents a possible segment.\n *\n * @param {Array} segs Array of object with segments data\n * @return {Array} Array of object with segments data\n */\nfunction buildNodes (segs) {\n const nodes = []\n for (let i = 0; i < segs.length; i++) {\n const seg = segs[i]\n\n switch (seg.mode) {\n case Mode.NUMERIC:\n nodes.push([seg,\n { data: seg.data, mode: Mode.ALPHANUMERIC, length: seg.length },\n { data: seg.data, mode: Mode.BYTE, length: seg.length }\n ])\n break\n case Mode.ALPHANUMERIC:\n nodes.push([seg,\n { data: seg.data, mode: Mode.BYTE, length: seg.length }\n ])\n break\n case Mode.KANJI:\n nodes.push([seg,\n { data: seg.data, mode: Mode.BYTE, length: getStringByteLength(seg.data) }\n ])\n break\n case Mode.BYTE:\n nodes.push([\n { data: seg.data, mode: Mode.BYTE, length: getStringByteLength(seg.data) }\n ])\n }\n }\n\n return nodes\n}\n\n/**\n * Builds a graph from a list of nodes.\n * All segments in each node group will be connected with all the segments of\n * the next group and so on.\n *\n * At each connection will be assigned a weight depending on the\n * segment's byte length.\n *\n * @param {Array} nodes Array of object with segments data\n * @param {Number} version QR Code version\n * @return {Object} Graph of all possible segments\n */\nfunction buildGraph (nodes, version) {\n const table = {}\n const graph = { start: {} }\n let prevNodeIds = ['start']\n\n for (let i = 0; i < nodes.length; i++) {\n const nodeGroup = nodes[i]\n const currentNodeIds = []\n\n for (let j = 0; j < nodeGroup.length; j++) {\n const node = nodeGroup[j]\n const key = '' + i + j\n\n currentNodeIds.push(key)\n table[key] = { node: node, lastCount: 0 }\n graph[key] = {}\n\n for (let n = 0; n < prevNodeIds.length; n++) {\n const prevNodeId = prevNodeIds[n]\n\n if (table[prevNodeId] && table[prevNodeId].node.mode === node.mode) {\n graph[prevNodeId][key] =\n getSegmentBitsLength(table[prevNodeId].lastCount + node.length, node.mode) -\n getSegmentBitsLength(table[prevNodeId].lastCount, node.mode)\n\n table[prevNodeId].lastCount += node.length\n } else {\n if (table[prevNodeId]) table[prevNodeId].lastCount = node.length\n\n graph[prevNodeId][key] = getSegmentBitsLength(node.length, node.mode) +\n 4 + Mode.getCharCountIndicator(node.mode, version) // switch cost\n }\n }\n }\n\n prevNodeIds = currentNodeIds\n }\n\n for (let n = 0; n < prevNodeIds.length; n++) {\n graph[prevNodeIds[n]].end = 0\n }\n\n return { map: graph, table: table }\n}\n\n/**\n * Builds a segment from a specified data and mode.\n * If a mode is not specified, the more suitable will be used.\n *\n * @param {String} data Input data\n * @param {Mode | String} modesHint Data mode\n * @return {Segment} Segment\n */\nfunction buildSingleSegment (data, modesHint) {\n let mode\n const bestMode = Mode.getBestModeForData(data)\n\n mode = Mode.from(modesHint, bestMode)\n\n // Make sure data can be encoded\n if (mode !== Mode.BYTE && mode.bit < bestMode.bit) {\n throw new Error('\"' + data + '\"' +\n ' cannot be encoded with mode ' + Mode.toString(mode) +\n '.\\n Suggested mode is: ' + Mode.toString(bestMode))\n }\n\n // Use Mode.BYTE if Kanji support is disabled\n if (mode === Mode.KANJI && !Utils.isKanjiModeEnabled()) {\n mode = Mode.BYTE\n }\n\n switch (mode) {\n case Mode.NUMERIC:\n return new NumericData(data)\n\n case Mode.ALPHANUMERIC:\n return new AlphanumericData(data)\n\n case Mode.KANJI:\n return new KanjiData(data)\n\n case Mode.BYTE:\n return new ByteData(data)\n }\n}\n\n/**\n * Builds a list of segments from an array.\n * Array can contain Strings or Objects with segment's info.\n *\n * For each item which is a string, will be generated a segment with the given\n * string and the more appropriate encoding mode.\n *\n * For each item which is an object, will be generated a segment with the given\n * data and mode.\n * Objects must contain at least the property \"data\".\n * If property \"mode\" is not present, the more suitable mode will be used.\n *\n * @param {Array} array Array of objects with segments data\n * @return {Array} Array of Segments\n */\nexports.fromArray = function fromArray (array) {\n return array.reduce(function (acc, seg) {\n if (typeof seg === 'string') {\n acc.push(buildSingleSegment(seg, null))\n } else if (seg.data) {\n acc.push(buildSingleSegment(seg.data, seg.mode))\n }\n\n return acc\n }, [])\n}\n\n/**\n * Builds an optimized sequence of segments from a string,\n * which will produce the shortest possible bitstream.\n *\n * @param {String} data Input string\n * @param {Number} version QR Code version\n * @return {Array} Array of segments\n */\nexports.fromString = function fromString (data, version) {\n const segs = getSegmentsFromString(data, Utils.isKanjiModeEnabled())\n\n const nodes = buildNodes(segs)\n const graph = buildGraph(nodes, version)\n const path = dijkstra.find_path(graph.map, 'start', 'end')\n\n const optimizedSegs = []\n for (let i = 1; i < path.length - 1; i++) {\n optimizedSegs.push(graph.table[path[i]].node)\n }\n\n return exports.fromArray(mergeSegments(optimizedSegs))\n}\n\n/**\n * Splits a string in various segments with the modes which\n * best represent their content.\n * The produced segments are far from being optimized.\n * The output of this function is only used to estimate a QR Code version\n * which may contain the data.\n *\n * @param {string} data Input string\n * @return {Array} Array of segments\n */\nexports.rawSplit = function rawSplit (data) {\n return exports.fromArray(\n getSegmentsFromString(data, Utils.isKanjiModeEnabled())\n )\n}\n", + "const Utils = require('./utils')\nconst ECLevel = require('./error-correction-level')\nconst BitBuffer = require('./bit-buffer')\nconst BitMatrix = require('./bit-matrix')\nconst AlignmentPattern = require('./alignment-pattern')\nconst FinderPattern = require('./finder-pattern')\nconst MaskPattern = require('./mask-pattern')\nconst ECCode = require('./error-correction-code')\nconst ReedSolomonEncoder = require('./reed-solomon-encoder')\nconst Version = require('./version')\nconst FormatInfo = require('./format-info')\nconst Mode = require('./mode')\nconst Segments = require('./segments')\n\n/**\n * QRCode for JavaScript\n *\n * modified by Ryan Day for nodejs support\n * Copyright (c) 2011 Ryan Day\n *\n * Licensed under the MIT license:\n * http://www.opensource.org/licenses/mit-license.php\n *\n//---------------------------------------------------------------------\n// QRCode for JavaScript\n//\n// Copyright (c) 2009 Kazuhiko Arase\n//\n// URL: http://www.d-project.com/\n//\n// Licensed under the MIT license:\n// http://www.opensource.org/licenses/mit-license.php\n//\n// The word \"QR Code\" is registered trademark of\n// DENSO WAVE INCORPORATED\n// http://www.denso-wave.com/qrcode/faqpatent-e.html\n//\n//---------------------------------------------------------------------\n*/\n\n/**\n * Add finder patterns bits to matrix\n *\n * @param {BitMatrix} matrix Modules matrix\n * @param {Number} version QR Code version\n */\nfunction setupFinderPattern (matrix, version) {\n const size = matrix.size\n const pos = FinderPattern.getPositions(version)\n\n for (let i = 0; i < pos.length; i++) {\n const row = pos[i][0]\n const col = pos[i][1]\n\n for (let r = -1; r <= 7; r++) {\n if (row + r <= -1 || size <= row + r) continue\n\n for (let c = -1; c <= 7; c++) {\n if (col + c <= -1 || size <= col + c) continue\n\n if ((r >= 0 && r <= 6 && (c === 0 || c === 6)) ||\n (c >= 0 && c <= 6 && (r === 0 || r === 6)) ||\n (r >= 2 && r <= 4 && c >= 2 && c <= 4)) {\n matrix.set(row + r, col + c, true, true)\n } else {\n matrix.set(row + r, col + c, false, true)\n }\n }\n }\n }\n}\n\n/**\n * Add timing pattern bits to matrix\n *\n * Note: this function must be called before {@link setupAlignmentPattern}\n *\n * @param {BitMatrix} matrix Modules matrix\n */\nfunction setupTimingPattern (matrix) {\n const size = matrix.size\n\n for (let r = 8; r < size - 8; r++) {\n const value = r % 2 === 0\n matrix.set(r, 6, value, true)\n matrix.set(6, r, value, true)\n }\n}\n\n/**\n * Add alignment patterns bits to matrix\n *\n * Note: this function must be called after {@link setupTimingPattern}\n *\n * @param {BitMatrix} matrix Modules matrix\n * @param {Number} version QR Code version\n */\nfunction setupAlignmentPattern (matrix, version) {\n const pos = AlignmentPattern.getPositions(version)\n\n for (let i = 0; i < pos.length; i++) {\n const row = pos[i][0]\n const col = pos[i][1]\n\n for (let r = -2; r <= 2; r++) {\n for (let c = -2; c <= 2; c++) {\n if (r === -2 || r === 2 || c === -2 || c === 2 ||\n (r === 0 && c === 0)) {\n matrix.set(row + r, col + c, true, true)\n } else {\n matrix.set(row + r, col + c, false, true)\n }\n }\n }\n }\n}\n\n/**\n * Add version info bits to matrix\n *\n * @param {BitMatrix} matrix Modules matrix\n * @param {Number} version QR Code version\n */\nfunction setupVersionInfo (matrix, version) {\n const size = matrix.size\n const bits = Version.getEncodedBits(version)\n let row, col, mod\n\n for (let i = 0; i < 18; i++) {\n row = Math.floor(i / 3)\n col = i % 3 + size - 8 - 3\n mod = ((bits >> i) & 1) === 1\n\n matrix.set(row, col, mod, true)\n matrix.set(col, row, mod, true)\n }\n}\n\n/**\n * Add format info bits to matrix\n *\n * @param {BitMatrix} matrix Modules matrix\n * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level\n * @param {Number} maskPattern Mask pattern reference value\n */\nfunction setupFormatInfo (matrix, errorCorrectionLevel, maskPattern) {\n const size = matrix.size\n const bits = FormatInfo.getEncodedBits(errorCorrectionLevel, maskPattern)\n let i, mod\n\n for (i = 0; i < 15; i++) {\n mod = ((bits >> i) & 1) === 1\n\n // vertical\n if (i < 6) {\n matrix.set(i, 8, mod, true)\n } else if (i < 8) {\n matrix.set(i + 1, 8, mod, true)\n } else {\n matrix.set(size - 15 + i, 8, mod, true)\n }\n\n // horizontal\n if (i < 8) {\n matrix.set(8, size - i - 1, mod, true)\n } else if (i < 9) {\n matrix.set(8, 15 - i - 1 + 1, mod, true)\n } else {\n matrix.set(8, 15 - i - 1, mod, true)\n }\n }\n\n // fixed module\n matrix.set(size - 8, 8, 1, true)\n}\n\n/**\n * Add encoded data bits to matrix\n *\n * @param {BitMatrix} matrix Modules matrix\n * @param {Uint8Array} data Data codewords\n */\nfunction setupData (matrix, data) {\n const size = matrix.size\n let inc = -1\n let row = size - 1\n let bitIndex = 7\n let byteIndex = 0\n\n for (let col = size - 1; col > 0; col -= 2) {\n if (col === 6) col--\n\n while (true) {\n for (let c = 0; c < 2; c++) {\n if (!matrix.isReserved(row, col - c)) {\n let dark = false\n\n if (byteIndex < data.length) {\n dark = (((data[byteIndex] >>> bitIndex) & 1) === 1)\n }\n\n matrix.set(row, col - c, dark)\n bitIndex--\n\n if (bitIndex === -1) {\n byteIndex++\n bitIndex = 7\n }\n }\n }\n\n row += inc\n\n if (row < 0 || size <= row) {\n row -= inc\n inc = -inc\n break\n }\n }\n }\n}\n\n/**\n * Create encoded codewords from data input\n *\n * @param {Number} version QR Code version\n * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level\n * @param {ByteData} data Data input\n * @return {Uint8Array} Buffer containing encoded codewords\n */\nfunction createData (version, errorCorrectionLevel, segments) {\n // Prepare data buffer\n const buffer = new BitBuffer()\n\n segments.forEach(function (data) {\n // prefix data with mode indicator (4 bits)\n buffer.put(data.mode.bit, 4)\n\n // Prefix data with character count indicator.\n // The character count indicator is a string of bits that represents the\n // number of characters that are being encoded.\n // The character count indicator must be placed after the mode indicator\n // and must be a certain number of bits long, depending on the QR version\n // and data mode\n // @see {@link Mode.getCharCountIndicator}.\n buffer.put(data.getLength(), Mode.getCharCountIndicator(data.mode, version))\n\n // add binary data sequence to buffer\n data.write(buffer)\n })\n\n // Calculate required number of bits\n const totalCodewords = Utils.getSymbolTotalCodewords(version)\n const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel)\n const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8\n\n // Add a terminator.\n // If the bit string is shorter than the total number of required bits,\n // a terminator of up to four 0s must be added to the right side of the string.\n // If the bit string is more than four bits shorter than the required number of bits,\n // add four 0s to the end.\n if (buffer.getLengthInBits() + 4 <= dataTotalCodewordsBits) {\n buffer.put(0, 4)\n }\n\n // If the bit string is fewer than four bits shorter, add only the number of 0s that\n // are needed to reach the required number of bits.\n\n // After adding the terminator, if the number of bits in the string is not a multiple of 8,\n // pad the string on the right with 0s to make the string's length a multiple of 8.\n while (buffer.getLengthInBits() % 8 !== 0) {\n buffer.putBit(0)\n }\n\n // Add pad bytes if the string is still shorter than the total number of required bits.\n // Extend the buffer to fill the data capacity of the symbol corresponding to\n // the Version and Error Correction Level by adding the Pad Codewords 11101100 (0xEC)\n // and 00010001 (0x11) alternately.\n const remainingByte = (dataTotalCodewordsBits - buffer.getLengthInBits()) / 8\n for (let i = 0; i < remainingByte; i++) {\n buffer.put(i % 2 ? 0x11 : 0xEC, 8)\n }\n\n return createCodewords(buffer, version, errorCorrectionLevel)\n}\n\n/**\n * Encode input data with Reed-Solomon and return codewords with\n * relative error correction bits\n *\n * @param {BitBuffer} bitBuffer Data to encode\n * @param {Number} version QR Code version\n * @param {ErrorCorrectionLevel} errorCorrectionLevel Error correction level\n * @return {Uint8Array} Buffer containing encoded codewords\n */\nfunction createCodewords (bitBuffer, version, errorCorrectionLevel) {\n // Total codewords for this QR code version (Data + Error correction)\n const totalCodewords = Utils.getSymbolTotalCodewords(version)\n\n // Total number of error correction codewords\n const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel)\n\n // Total number of data codewords\n const dataTotalCodewords = totalCodewords - ecTotalCodewords\n\n // Total number of blocks\n const ecTotalBlocks = ECCode.getBlocksCount(version, errorCorrectionLevel)\n\n // Calculate how many blocks each group should contain\n const blocksInGroup2 = totalCodewords % ecTotalBlocks\n const blocksInGroup1 = ecTotalBlocks - blocksInGroup2\n\n const totalCodewordsInGroup1 = Math.floor(totalCodewords / ecTotalBlocks)\n\n const dataCodewordsInGroup1 = Math.floor(dataTotalCodewords / ecTotalBlocks)\n const dataCodewordsInGroup2 = dataCodewordsInGroup1 + 1\n\n // Number of EC codewords is the same for both groups\n const ecCount = totalCodewordsInGroup1 - dataCodewordsInGroup1\n\n // Initialize a Reed-Solomon encoder with a generator polynomial of degree ecCount\n const rs = new ReedSolomonEncoder(ecCount)\n\n let offset = 0\n const dcData = new Array(ecTotalBlocks)\n const ecData = new Array(ecTotalBlocks)\n let maxDataSize = 0\n const buffer = new Uint8Array(bitBuffer.buffer)\n\n // Divide the buffer into the required number of blocks\n for (let b = 0; b < ecTotalBlocks; b++) {\n const dataSize = b < blocksInGroup1 ? dataCodewordsInGroup1 : dataCodewordsInGroup2\n\n // extract a block of data from buffer\n dcData[b] = buffer.slice(offset, offset + dataSize)\n\n // Calculate EC codewords for this data block\n ecData[b] = rs.encode(dcData[b])\n\n offset += dataSize\n maxDataSize = Math.max(maxDataSize, dataSize)\n }\n\n // Create final data\n // Interleave the data and error correction codewords from each block\n const data = new Uint8Array(totalCodewords)\n let index = 0\n let i, r\n\n // Add data codewords\n for (i = 0; i < maxDataSize; i++) {\n for (r = 0; r < ecTotalBlocks; r++) {\n if (i < dcData[r].length) {\n data[index++] = dcData[r][i]\n }\n }\n }\n\n // Apped EC codewords\n for (i = 0; i < ecCount; i++) {\n for (r = 0; r < ecTotalBlocks; r++) {\n data[index++] = ecData[r][i]\n }\n }\n\n return data\n}\n\n/**\n * Build QR Code symbol\n *\n * @param {String} data Input string\n * @param {Number} version QR Code version\n * @param {ErrorCorretionLevel} errorCorrectionLevel Error level\n * @param {MaskPattern} maskPattern Mask pattern\n * @return {Object} Object containing symbol data\n */\nfunction createSymbol (data, version, errorCorrectionLevel, maskPattern) {\n let segments\n\n if (Array.isArray(data)) {\n segments = Segments.fromArray(data)\n } else if (typeof data === 'string') {\n let estimatedVersion = version\n\n if (!estimatedVersion) {\n const rawSegments = Segments.rawSplit(data)\n\n // Estimate best version that can contain raw splitted segments\n estimatedVersion = Version.getBestVersionForData(rawSegments, errorCorrectionLevel)\n }\n\n // Build optimized segments\n // If estimated version is undefined, try with the highest version\n segments = Segments.fromString(data, estimatedVersion || 40)\n } else {\n throw new Error('Invalid data')\n }\n\n // Get the min version that can contain data\n const bestVersion = Version.getBestVersionForData(segments, errorCorrectionLevel)\n\n // If no version is found, data cannot be stored\n if (!bestVersion) {\n throw new Error('The amount of data is too big to be stored in a QR Code')\n }\n\n // If not specified, use min version as default\n if (!version) {\n version = bestVersion\n\n // Check if the specified version can contain the data\n } else if (version < bestVersion) {\n throw new Error('\\n' +\n 'The chosen QR Code version cannot contain this amount of data.\\n' +\n 'Minimum version required to store current data is: ' + bestVersion + '.\\n'\n )\n }\n\n const dataBits = createData(version, errorCorrectionLevel, segments)\n\n // Allocate matrix buffer\n const moduleCount = Utils.getSymbolSize(version)\n const modules = new BitMatrix(moduleCount)\n\n // Add function modules\n setupFinderPattern(modules, version)\n setupTimingPattern(modules)\n setupAlignmentPattern(modules, version)\n\n // Add temporary dummy bits for format info just to set them as reserved.\n // This is needed to prevent these bits from being masked by {@link MaskPattern.applyMask}\n // since the masking operation must be performed only on the encoding region.\n // These blocks will be replaced with correct values later in code.\n setupFormatInfo(modules, errorCorrectionLevel, 0)\n\n if (version >= 7) {\n setupVersionInfo(modules, version)\n }\n\n // Add data codewords\n setupData(modules, dataBits)\n\n if (isNaN(maskPattern)) {\n // Find best mask pattern\n maskPattern = MaskPattern.getBestMask(modules,\n setupFormatInfo.bind(null, modules, errorCorrectionLevel))\n }\n\n // Apply mask pattern\n MaskPattern.applyMask(maskPattern, modules)\n\n // Replace format info bits with correct values\n setupFormatInfo(modules, errorCorrectionLevel, maskPattern)\n\n return {\n modules: modules,\n version: version,\n errorCorrectionLevel: errorCorrectionLevel,\n maskPattern: maskPattern,\n segments: segments\n }\n}\n\n/**\n * QR Code\n *\n * @param {String | Array} data Input data\n * @param {Object} options Optional configurations\n * @param {Number} options.version QR Code version\n * @param {String} options.errorCorrectionLevel Error correction level\n * @param {Function} options.toSJISFunc Helper func to convert utf8 to sjis\n */\nexports.create = function create (data, options) {\n if (typeof data === 'undefined' || data === '') {\n throw new Error('No input text')\n }\n\n let errorCorrectionLevel = ECLevel.M\n let version\n let mask\n\n if (typeof options !== 'undefined') {\n // Use higher error correction level as default\n errorCorrectionLevel = ECLevel.from(options.errorCorrectionLevel, ECLevel.M)\n version = Version.from(options.version)\n mask = MaskPattern.from(options.maskPattern)\n\n if (options.toSJISFunc) {\n Utils.setToSJISFunction(options.toSJISFunc)\n }\n }\n\n return createSymbol(data, version, errorCorrectionLevel, mask)\n}\n", + "function hex2rgba (hex) {\n if (typeof hex === 'number') {\n hex = hex.toString()\n }\n\n if (typeof hex !== 'string') {\n throw new Error('Color should be defined as hex string')\n }\n\n let hexCode = hex.slice().replace('#', '').split('')\n if (hexCode.length < 3 || hexCode.length === 5 || hexCode.length > 8) {\n throw new Error('Invalid hex color: ' + hex)\n }\n\n // Convert from short to long form (fff -> ffffff)\n if (hexCode.length === 3 || hexCode.length === 4) {\n hexCode = Array.prototype.concat.apply([], hexCode.map(function (c) {\n return [c, c]\n }))\n }\n\n // Add default alpha value\n if (hexCode.length === 6) hexCode.push('F', 'F')\n\n const hexValue = parseInt(hexCode.join(''), 16)\n\n return {\n r: (hexValue >> 24) & 255,\n g: (hexValue >> 16) & 255,\n b: (hexValue >> 8) & 255,\n a: hexValue & 255,\n hex: '#' + hexCode.slice(0, 6).join('')\n }\n}\n\nexports.getOptions = function getOptions (options) {\n if (!options) options = {}\n if (!options.color) options.color = {}\n\n const margin = typeof options.margin === 'undefined' ||\n options.margin === null ||\n options.margin < 0\n ? 4\n : options.margin\n\n const width = options.width && options.width >= 21 ? options.width : undefined\n const scale = options.scale || 4\n\n return {\n width: width,\n scale: width ? 4 : scale,\n margin: margin,\n color: {\n dark: hex2rgba(options.color.dark || '#000000ff'),\n light: hex2rgba(options.color.light || '#ffffffff')\n },\n type: options.type,\n rendererOpts: options.rendererOpts || {}\n }\n}\n\nexports.getScale = function getScale (qrSize, opts) {\n return opts.width && opts.width >= qrSize + opts.margin * 2\n ? opts.width / (qrSize + opts.margin * 2)\n : opts.scale\n}\n\nexports.getImageWidth = function getImageWidth (qrSize, opts) {\n const scale = exports.getScale(qrSize, opts)\n return Math.floor((qrSize + opts.margin * 2) * scale)\n}\n\nexports.qrToImageData = function qrToImageData (imgData, qr, opts) {\n const size = qr.modules.size\n const data = qr.modules.data\n const scale = exports.getScale(size, opts)\n const symbolSize = Math.floor((size + opts.margin * 2) * scale)\n const scaledMargin = opts.margin * scale\n const palette = [opts.color.light, opts.color.dark]\n\n for (let i = 0; i < symbolSize; i++) {\n for (let j = 0; j < symbolSize; j++) {\n let posDst = (i * symbolSize + j) * 4\n let pxColor = opts.color.light\n\n if (i >= scaledMargin && j >= scaledMargin &&\n i < symbolSize - scaledMargin && j < symbolSize - scaledMargin) {\n const iSrc = Math.floor((i - scaledMargin) / scale)\n const jSrc = Math.floor((j - scaledMargin) / scale)\n pxColor = palette[data[iSrc * size + jSrc] ? 1 : 0]\n }\n\n imgData[posDst++] = pxColor.r\n imgData[posDst++] = pxColor.g\n imgData[posDst++] = pxColor.b\n imgData[posDst] = pxColor.a\n }\n }\n}\n", + "const Utils = require('./utils')\n\nfunction clearCanvas (ctx, canvas, size) {\n ctx.clearRect(0, 0, canvas.width, canvas.height)\n\n if (!canvas.style) canvas.style = {}\n canvas.height = size\n canvas.width = size\n canvas.style.height = size + 'px'\n canvas.style.width = size + 'px'\n}\n\nfunction getCanvasElement () {\n try {\n return document.createElement('canvas')\n } catch (e) {\n throw new Error('You need to specify a canvas element')\n }\n}\n\nexports.render = function render (qrData, canvas, options) {\n let opts = options\n let canvasEl = canvas\n\n if (typeof opts === 'undefined' && (!canvas || !canvas.getContext)) {\n opts = canvas\n canvas = undefined\n }\n\n if (!canvas) {\n canvasEl = getCanvasElement()\n }\n\n opts = Utils.getOptions(opts)\n const size = Utils.getImageWidth(qrData.modules.size, opts)\n\n const ctx = canvasEl.getContext('2d')\n const image = ctx.createImageData(size, size)\n Utils.qrToImageData(image.data, qrData, opts)\n\n clearCanvas(ctx, canvasEl, size)\n ctx.putImageData(image, 0, 0)\n\n return canvasEl\n}\n\nexports.renderToDataURL = function renderToDataURL (qrData, canvas, options) {\n let opts = options\n\n if (typeof opts === 'undefined' && (!canvas || !canvas.getContext)) {\n opts = canvas\n canvas = undefined\n }\n\n if (!opts) opts = {}\n\n const canvasEl = exports.render(qrData, canvas, opts)\n\n const type = opts.type || 'image/png'\n const rendererOpts = opts.rendererOpts || {}\n\n return canvasEl.toDataURL(type, rendererOpts.quality)\n}\n", + "const Utils = require('./utils')\n\nfunction getColorAttrib (color, attrib) {\n const alpha = color.a / 255\n const str = attrib + '=\"' + color.hex + '\"'\n\n return alpha < 1\n ? str + ' ' + attrib + '-opacity=\"' + alpha.toFixed(2).slice(1) + '\"'\n : str\n}\n\nfunction svgCmd (cmd, x, y) {\n let str = cmd + x\n if (typeof y !== 'undefined') str += ' ' + y\n\n return str\n}\n\nfunction qrToPath (data, size, margin) {\n let path = ''\n let moveBy = 0\n let newRow = false\n let lineLength = 0\n\n for (let i = 0; i < data.length; i++) {\n const col = Math.floor(i % size)\n const row = Math.floor(i / size)\n\n if (!col && !newRow) newRow = true\n\n if (data[i]) {\n lineLength++\n\n if (!(i > 0 && col > 0 && data[i - 1])) {\n path += newRow\n ? svgCmd('M', col + margin, 0.5 + row + margin)\n : svgCmd('m', moveBy, 0)\n\n moveBy = 0\n newRow = false\n }\n\n if (!(col + 1 < size && data[i + 1])) {\n path += svgCmd('h', lineLength)\n lineLength = 0\n }\n } else {\n moveBy++\n }\n }\n\n return path\n}\n\nexports.render = function render (qrData, options, cb) {\n const opts = Utils.getOptions(options)\n const size = qrData.modules.size\n const data = qrData.modules.data\n const qrcodesize = size + opts.margin * 2\n\n const bg = !opts.color.light.a\n ? ''\n : '<path ' + getColorAttrib(opts.color.light, 'fill') +\n ' d=\"M0 0h' + qrcodesize + 'v' + qrcodesize + 'H0z\"/>'\n\n const path =\n '<path ' + getColorAttrib(opts.color.dark, 'stroke') +\n ' d=\"' + qrToPath(data, size, opts.margin) + '\"/>'\n\n const viewBox = 'viewBox=\"' + '0 0 ' + qrcodesize + ' ' + qrcodesize + '\"'\n\n const width = !opts.width ? '' : 'width=\"' + opts.width + '\" height=\"' + opts.width + '\" '\n\n const svgTag = '<svg xmlns=\"http://www.w3.org/2000/svg\" ' + width + viewBox + ' shape-rendering=\"crispEdges\">' + bg + path + '</svg>\\n'\n\n if (typeof cb === 'function') {\n cb(null, svgTag)\n }\n\n return svgTag\n}\n", + "\nconst canPromise = require('./can-promise')\n\nconst QRCode = require('./core/qrcode')\nconst CanvasRenderer = require('./renderer/canvas')\nconst SvgRenderer = require('./renderer/svg-tag.js')\n\nfunction renderCanvas (renderFunc, canvas, text, opts, cb) {\n const args = [].slice.call(arguments, 1)\n const argsNum = args.length\n const isLastArgCb = typeof args[argsNum - 1] === 'function'\n\n if (!isLastArgCb && !canPromise()) {\n throw new Error('Callback required as last argument')\n }\n\n if (isLastArgCb) {\n if (argsNum < 2) {\n throw new Error('Too few arguments provided')\n }\n\n if (argsNum === 2) {\n cb = text\n text = canvas\n canvas = opts = undefined\n } else if (argsNum === 3) {\n if (canvas.getContext && typeof cb === 'undefined') {\n cb = opts\n opts = undefined\n } else {\n cb = opts\n opts = text\n text = canvas\n canvas = undefined\n }\n }\n } else {\n if (argsNum < 1) {\n throw new Error('Too few arguments provided')\n }\n\n if (argsNum === 1) {\n text = canvas\n canvas = opts = undefined\n } else if (argsNum === 2 && !canvas.getContext) {\n opts = text\n text = canvas\n canvas = undefined\n }\n\n return new Promise(function (resolve, reject) {\n try {\n const data = QRCode.create(text, opts)\n resolve(renderFunc(data, canvas, opts))\n } catch (e) {\n reject(e)\n }\n })\n }\n\n try {\n const data = QRCode.create(text, opts)\n cb(null, renderFunc(data, canvas, opts))\n } catch (e) {\n cb(e)\n }\n}\n\nexports.create = QRCode.create\nexports.toCanvas = renderCanvas.bind(null, CanvasRenderer.render)\nexports.toDataURL = renderCanvas.bind(null, CanvasRenderer.renderToDataURL)\n\n// only svg for now.\nexports.toString = renderCanvas.bind(null, function (data, _, opts) {\n return SvgRenderer.render(data, opts)\n})\n", + "/**\n * @license React\n * react-jsx-runtime.production.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\nvar REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\");\nfunction jsxProd(type, config, maybeKey) {\n var key = null;\n void 0 !== maybeKey && (key = \"\" + maybeKey);\n void 0 !== config.key && (key = \"\" + config.key);\n if (\"key\" in config) {\n maybeKey = {};\n for (var propName in config)\n \"key\" !== propName && (maybeKey[propName] = config[propName]);\n } else maybeKey = config;\n config = maybeKey.ref;\n return {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key,\n ref: void 0 !== config ? config : null,\n props: maybeKey\n };\n}\nexports.Fragment = REACT_FRAGMENT_TYPE;\nexports.jsx = jsxProd;\nexports.jsxs = jsxProd;\n", + "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react-jsx-runtime.production.js');\n} else {\n module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n", + "import { StrictMode } from \"react\";\nimport { createRoot } from \"react-dom/client\";\nimport App from \"./App.tsx\";\n\ncreateRoot(document.getElementById(\"root\")).render(\n <StrictMode>\n <App />\n </StrictMode>,\n);\n", + "import { useState, useEffect, useCallback, useRef, type CSSProperties } from \"react\";\nimport QRCode from \"qrcode\";\nimport {\n formatDateTimeLocalInput,\n formatTaskDateTime,\n formatTaskTime,\n parseTaskDateTime,\n serializeDateTimeLocalInput,\n} from \"./dateTime.ts\";\nimport {\n buildChannelsSavePayload,\n createInitialChannelsState,\n isWeixinQrImageSource,\n mergeChannelsStatus,\n} from \"./channelsSettings.ts\";\nimport { buildExecutionSteps } from \"./traceSteps.ts\";\n\nconst API = \"http://127.0.0.1:9712/api\";\n\n// ─── Theme ───\nconst THEMES: Record<string, Record<string, string>> = {\n dark: {\n bg: \"#0a0a0f\",\n surface: \"#12121a\",\n surfaceHover: \"#1a1a26\",\n border: \"#1e1e2e\",\n borderActive: \"#2d2d44\",\n text: \"#e2e2ef\",\n textMuted: \"#6b6b8a\",\n textDim: \"#44445e\",\n accent: \"#7c6aff\",\n accentGlow: \"rgba(124, 106, 255, 0.15)\",\n green: \"#34d399\",\n greenBg: \"rgba(52, 211, 153, 0.08)\",\n orange: \"#fbbf24\",\n orangeBg: \"rgba(251, 191, 36, 0.08)\",\n red: \"#f87171\",\n redBg: \"rgba(248, 113, 113, 0.08)\",\n blue: \"#60a5fa\",\n blueBg: \"rgba(96, 165, 250, 0.08)\",\n cyan: \"#22d3ee\",\n cyanBg: \"rgba(34, 211, 238, 0.08)\",\n },\n light: {\n bg: \"#f5f5fa\",\n surface: \"#ffffff\",\n surfaceHover: \"#eeeef7\",\n border: \"#dcdce8\",\n borderActive: \"#b8b8d0\",\n text: \"#1a1a2e\",\n textMuted: \"#6b6b8a\",\n textDim: \"#a0a0bc\",\n accent: \"#5b4ecc\",\n accentGlow: \"rgba(91, 78, 204, 0.12)\",\n green: \"#059669\",\n greenBg: \"rgba(5, 150, 105, 0.08)\",\n orange: \"#d97706\",\n orangeBg: \"rgba(217, 119, 6, 0.08)\",\n red: \"#dc2626\",\n redBg: \"rgba(220, 38, 38, 0.08)\",\n blue: \"#2563eb\",\n blueBg: \"rgba(37, 99, 235, 0.08)\",\n cyan: \"#0891b2\",\n cyanBg: \"rgba(8, 145, 178, 0.08)\",\n },\n};\n\n// Mutable module-level theme reference — updated before each App render\nlet theme = THEMES.dark;\n\nfunction getStatusConfig() {\n return {\n pending: { label: \"Pending\", color: theme.orange, bg: theme.orangeBg, icon: \"◌\" },\n scheduled: { label: \"Scheduled\", color: theme.cyan, bg: theme.cyanBg, icon: \"⏱\" },\n running: { label: \"Running\", color: theme.blue, bg: theme.blueBg, icon: \"⟳\" },\n completed: { label: \"Completed\", color: theme.green, bg: theme.greenBg, icon: \"✓\" },\n failed: { label: \"Failed\", color: theme.red, bg: theme.redBg, icon: \"✕\" },\n cancelled: {\n label: \"Cancelled\",\n color: theme.textMuted,\n bg: \"rgba(107,107,138,0.08)\",\n icon: \"◻\",\n },\n blocked: { label: \"Blocked\", color: theme.textMuted, bg: \"rgba(107,107,138,0.1)\", icon: \"⊘\" },\n };\n}\n\nconst COLUMNS = [\n { key: \"queued\", label: \"Queue\", statuses: [\"pending\", \"scheduled\", \"blocked\"], icon: \"⧖\" },\n { key: \"running\", label: \"Running\", statuses: [\"running\"], icon: \"▸\" },\n { key: \"done\", label: \"Done\", statuses: [\"completed\", \"failed\", \"cancelled\"], icon: \"◆\" },\n];\n\nconst AGENTS = {\n claude: { label: \"Claude Code\", icon: \"⌘\", color: \"#7c6aff\" },\n codex: { label: \"Codex CLI\", icon: \"◈\", color: \"#10a37f\" },\n};\nconst DEFAULT_AGENT = \"codex\";\nconst DEFAULT_TIMEOUT_SECONDS = 12000;\n\n// ─── Formatted Output Component ───\nfunction FormattedOutput({ content, theme }) {\n if (!content) return null;\n\n // 解析JSON流数据,只显示关键信息\n const parseStreamJSON = (text) => {\n const lines = text.split(\"\\n\");\n const parsedLines = [];\n\n lines.forEach((line) => {\n if (!line.trim()) return;\n\n try {\n const event = JSON.parse(line);\n const eventType = event.type;\n\n switch (eventType) {\n case \"user\":\n case \"assistant\": {\n const isUser = eventType === \"user\";\n const msg = event.message || {};\n const msgContent = msg.content || [];\n const prefix = isUser ? \"👤 User: \" : \"🤖 Assistant: \";\n const color = isUser ? theme.accent : theme.green;\n let textBuf = \"\";\n const flushText = () => {\n if (textBuf.trim()) {\n parsedLines.push({\n type: eventType,\n text: prefix + textBuf,\n style: { color, fontWeight: isUser ? \"bold\" : \"normal\" },\n });\n textBuf = \"\";\n }\n };\n for (const c of msgContent) {\n if (typeof c === \"string\") {\n textBuf += c;\n } else if (c && typeof c === \"object\") {\n if (c.type === \"text\") {\n textBuf += c.text || \"\";\n } else if (c.type === \"image\") {\n flushText();\n const src =\n c.source && c.source.type === \"base64\"\n ? `data:${c.source.media_type || \"image/jpeg\"};base64,${c.source.data}`\n : null;\n if (src) parsedLines.push({ type: \"image\", src });\n } else if (c.type === \"tool_use\") {\n flushText();\n const rows = buildTraceRows(\n \"tool_call\",\n {\n id: c.id,\n name: c.name,\n input: c.input,\n },\n \"\",\n );\n parsedLines.push({\n type: \"tool_call\",\n text: rows.map((row) => `${row.label}: ${row.value}`).join(\"\\n\"),\n style: { color: theme.cyan, fontSize: \"11px\", fontFamily: \"monospace\" },\n });\n } else if (c.type === \"tool_result\") {\n flushText();\n const rows = buildTraceRows(\n \"tool_result\",\n {\n tool_use_id: c.tool_use_id,\n content: Array.isArray(c.content)\n ? c.content\n .map((part) =>\n part && part.type === \"text\" ? part.text || \"\" : JSON.stringify(part),\n )\n .join(\"\")\n : c.content,\n is_error: c.is_error,\n },\n \"\",\n );\n parsedLines.push({\n type: \"tool_result\",\n text: rows.map((row) => `${row.label}: ${row.value}`).join(\"\\n\"),\n style: {\n color: c.is_error ? theme.red : theme.blue,\n fontSize: \"11px\",\n fontFamily: \"monospace\",\n },\n });\n }\n }\n }\n flushText();\n break;\n }\n\n case \"item.completed\": {\n const item = event.item || {};\n if (item.type === \"command_execution\") {\n const rows = buildTraceRows(\n \"command_execution\",\n {\n command: item.command,\n output: item.aggregated_output,\n exit_code: item.exit_code,\n status: item.status,\n },\n \"\",\n );\n parsedLines.push({\n type: \"command_execution\",\n text: rows.map((row) => `${row.label}: ${row.value}`).join(\"\\n\"),\n style: { color: theme.orange, fontSize: \"11px\", fontFamily: \"monospace\" },\n });\n } else if (item.type === \"mcp_tool_call\" || item.type === \"collab_tool_call\") {\n const rows = buildTraceRows(\n \"tool_call\",\n {\n server: item.server,\n name: item.tool || item.name,\n input: item.arguments || item.input,\n result: item.result,\n status: item.status,\n error: item.error,\n },\n \"\",\n );\n parsedLines.push({\n type: \"tool_call\",\n text: rows.map((row) => `${row.label}: ${row.value}`).join(\"\\n\"),\n style: { color: theme.cyan, fontSize: \"11px\", fontFamily: \"monospace\" },\n });\n } else if (item.type === \"web_search\") {\n const rows = buildTraceRows(\"web_search\", item, \"\");\n parsedLines.push({\n type: \"web_search\",\n text: rows.map((row) => `${row.label}: ${row.value}`).join(\"\\n\"),\n style: { color: theme.cyan, fontSize: \"11px\", fontFamily: \"monospace\" },\n });\n } else if (item.type === \"file_change\") {\n const rows = buildTraceRows(\"file_change\", item, \"\");\n parsedLines.push({\n type: \"file_change\",\n text: rows.map((row) => `${row.label}: ${row.value}`).join(\"\\n\"),\n style: { color: theme.accent, fontSize: \"11px\", fontFamily: \"monospace\" },\n });\n }\n break;\n }\n\n case \"result\":\n // 最终结果\n if (event.result) {\n parsedLines.push({\n type: \"result\",\n text: `✅ Result: ${event.result}`,\n style: { color: theme.green, fontWeight: \"bold\" },\n });\n }\n break;\n\n case \"error\":\n // 错误信息\n parsedLines.push({\n type: \"error\",\n text: `❌ Error: ${event.error || \"Unknown error\"}`,\n style: { color: theme.red, fontWeight: \"bold\" },\n });\n break;\n\n default:\n // 其他事件类型 - 显示更多信息\n if (eventType) {\n let displayText = `[${eventType}]`;\n // 尝试显示事件中的关键信息\n if (event.message) {\n const msg = event.message;\n if (msg.content && Array.isArray(msg.content)) {\n const textContent = msg.content\n .filter(\n (c) =>\n typeof c === \"string\" || (c && typeof c === \"object\" && c.type === \"text\"),\n )\n .map((c) => (typeof c === \"string\" ? c : c.text || \"\"))\n .join(\"\");\n if (textContent.trim()) {\n displayText = textContent.slice(0, 200);\n }\n }\n } else if (event.result) {\n displayText = `Result: ${event.result.slice(0, 200)}`;\n } else if (event.error) {\n displayText = `Error: ${event.error.slice(0, 200)}`;\n }\n\n parsedLines.push({\n type: \"event\",\n text: displayText,\n style: { color: theme.textDim, fontSize: \"11px\", fontFamily: \"monospace\" },\n });\n }\n }\n } catch (_error) {\n // 如果不是有效的JSON,可能是普通文本输出\n if (line.trim() && !line.startsWith(\"{\")) {\n // 只显示有意义的非JSON行\n if (line.includes(\"error\") || line.includes(\"Error\")) {\n parsedLines.push({\n type: \"error\",\n text: line,\n style: { color: theme.red },\n });\n } else if (line.includes(\"success\") || line.includes(\"Success\")) {\n parsedLines.push({\n type: \"success\",\n text: line,\n style: { color: theme.green },\n });\n } else if (line.length > 10) {\n // 只显示较长的非JSON行\n parsedLines.push({\n type: \"text\",\n text: line,\n style: { color: theme.textDim },\n });\n }\n }\n }\n });\n\n return parsedLines;\n };\n\n const parsedContent = parseStreamJSON(content);\n\n if (parsedContent.length === 0) {\n return (\n <div style={{ color: theme.textDim, fontStyle: \"italic\", fontSize: \"12px\" }}>\n Waiting for agent output...\n </div>\n );\n }\n\n return (\n <div style={{ fontFamily: \"'JetBrains Mono', monospace\", fontSize: \"12px\", lineHeight: \"1.6\" }}>\n {parsedContent.map((item, index) =>\n item.type === \"image\" ? (\n <div key={index} style={{ margin: \"6px 0\" }}>\n <img\n src={item.src}\n alt=\"output image\"\n style={{ maxWidth: \"100%\", borderRadius: \"4px\", display: \"block\" }}\n />\n </div>\n ) : (\n <div\n key={index}\n style={{\n ...item.style,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n marginBottom: \"2px\",\n padding: \"2px 0\",\n }}\n >\n {item.text}\n </div>\n ),\n )}\n </div>\n );\n}\n\nfunction ExecutionTimeline({ events }) {\n const [expanded, setExpanded] = useState(true);\n const steps = buildExecutionSteps(events);\n\n if (steps.length === 0) {\n return (\n <div style={{ fontSize: 12, color: theme.textDim, padding: \"12px 0\", textAlign: \"center\" }}>\n No output events recorded — events are recorded for new task runs.\n </div>\n );\n }\n\n return (\n <div\n style={{\n border: `1px solid ${theme.border}`,\n borderRadius: 8,\n overflow: \"hidden\",\n background: theme.bg,\n }}\n >\n <button\n onClick={() => setExpanded(!expanded)}\n style={{\n width: \"100%\",\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n gap: 12,\n padding: \"10px 12px\",\n background: theme.surface,\n border: \"none\",\n borderBottom: expanded ? `1px solid ${theme.border}` : \"none\",\n color: theme.text,\n cursor: \"pointer\",\n fontFamily: \"'JetBrains Mono', monospace\",\n fontSize: 12,\n textAlign: \"left\",\n }}\n >\n <span style={{ display: \"flex\", alignItems: \"center\", gap: 8, minWidth: 0 }}>\n <span style={{ color: theme.textMuted }}>{expanded ? \"⌄\" : \"›\"}</span>\n <span>\n Show {steps.length} {steps.length === 1 ? \"step\" : \"steps\"}\n </span>\n </span>\n <span style={{ color: theme.textDim, fontSize: 10, whiteSpace: \"nowrap\" }}>\n {events.length} events\n </span>\n </button>\n\n {expanded && (\n <div style={{ padding: \"12px 12px 14px\" }}>\n {steps.map((step, index) => (\n <ExecutionTimelineStep\n key={`${step.id}-${step.number}`}\n step={step}\n isLast={index === steps.length - 1}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction ExecutionTimelineStep({ step, isLast }) {\n const config = getExecutionStepConfig(step.type);\n const detail = (step.detail || \"\").trim();\n const hasRows = step.rows && step.rows.length > 0;\n const hasImage = Boolean(step.imageSrc);\n const showDetail = detail && detail !== step.title && !hasRows && !hasImage;\n\n return (\n <div style={{ display: \"grid\", gridTemplateColumns: \"28px 1fr\", columnGap: 10 }}>\n <div style={{ display: \"flex\", flexDirection: \"column\", alignItems: \"center\" }}>\n <div\n style={{\n width: 20,\n height: 20,\n borderRadius: 6,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: config.bg,\n border: `1px solid ${config.color}55`,\n color: config.color,\n fontSize: 10,\n fontWeight: 800,\n lineHeight: 1,\n }}\n >\n {config.icon}\n </div>\n {!isLast && (\n <div\n style={{ width: 1, flex: 1, minHeight: 16, background: theme.border, marginTop: 4 }}\n />\n )}\n </div>\n\n <div style={{ paddingBottom: isLast ? 0 : 14, minWidth: 0 }}>\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n gap: 10,\n alignItems: \"baseline\",\n }}\n >\n <div\n style={{\n color: theme.text,\n fontSize: 12,\n lineHeight: 1.55,\n wordBreak: \"break-word\",\n minWidth: 0,\n }}\n >\n {step.title}\n </div>\n <div\n style={{\n color: theme.textDim,\n fontSize: 9,\n whiteSpace: \"nowrap\",\n flexShrink: 0,\n fontFamily: \"'JetBrains Mono', monospace\",\n }}\n >\n {formatTaskTime(step.timestamp)}\n </div>\n </div>\n\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n marginTop: 3,\n marginBottom: hasRows || showDetail ? 7 : 0,\n }}\n >\n <span\n style={{\n color: config.color,\n fontSize: 10,\n fontWeight: 700,\n textTransform: \"uppercase\",\n letterSpacing: 0,\n }}\n >\n {config.label}\n </span>\n {step.count > 1 && (\n <span style={{ color: theme.textDim, fontSize: 10 }}>{step.count} chunks</span>\n )}\n </div>\n\n {hasImage && (\n <img\n src={step.imageSrc}\n alt=\"image output\"\n style={{\n maxWidth: \"100%\",\n borderRadius: 6,\n display: \"block\",\n marginTop: 7,\n border: `1px solid ${theme.border}`,\n }}\n />\n )}\n\n {hasRows && (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n gap: 5,\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 6,\n padding: \"8px 10px\",\n maxHeight: 220,\n overflow: \"auto\",\n }}\n >\n {step.rows.map((row, i) => (\n <div\n key={i}\n style={{ display: \"grid\", gridTemplateColumns: \"72px 1fr\", gap: 8, minWidth: 0 }}\n >\n <span style={{ color: theme.textMuted, fontWeight: 700 }}>{row.label}</span>\n <span\n style={{ whiteSpace: \"pre-wrap\", wordBreak: \"break-word\", color: theme.text }}\n >\n {row.value}\n </span>\n </div>\n ))}\n </div>\n )}\n\n {showDetail && (\n <pre\n style={{\n margin: 0,\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 6,\n padding: \"8px 10px\",\n color: theme.textMuted,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n fontFamily: \"'JetBrains Mono', monospace\",\n fontSize: 11,\n lineHeight: 1.5,\n maxHeight: 220,\n overflow: \"auto\",\n }}\n >\n {detail}\n </pre>\n )}\n </div>\n </div>\n );\n}\n\nfunction getExecutionStepConfig(type) {\n switch (type) {\n case \"thinking\":\n return { label: \"Thinking\", icon: \"⌁\", color: theme.textMuted, bg: \"rgba(107,107,138,0.08)\" };\n case \"tool_call\":\n return { label: \"Tool Call\", icon: \"▣\", color: theme.cyan, bg: theme.cyanBg };\n case \"tool_result\":\n return { label: \"Tool Result\", icon: \"↵\", color: theme.blue, bg: theme.blueBg };\n case \"command_execution\":\n return { label: \"Command\", icon: \"$\", color: theme.orange, bg: theme.orangeBg };\n case \"file_change\":\n return { label: \"File\", icon: \"◇\", color: theme.accent, bg: theme.accentGlow };\n case \"generated_image\":\n return { label: \"Image\", icon: \"□\", color: theme.accent, bg: theme.accentGlow };\n case \"image_content\":\n return { label: \"Image\", icon: \"□\", color: theme.accent, bg: theme.accentGlow };\n case \"web_search\":\n return { label: \"Search\", icon: \"⌕\", color: theme.cyan, bg: theme.cyanBg };\n case \"result\":\n return { label: \"Result\", icon: \"✓\", color: theme.green, bg: theme.greenBg };\n case \"error\":\n return { label: \"Error\", icon: \"!\", color: theme.red, bg: theme.redBg };\n case \"user\":\n return { label: \"User\", icon: \"U\", color: theme.accent, bg: theme.accentGlow };\n case \"assistant\":\n return { label: \"Assistant\", icon: \"AI\", color: theme.green, bg: theme.greenBg };\n default:\n return { label: \"Event\", icon: \"•\", color: theme.textMuted, bg: \"rgba(107,107,138,0.08)\" };\n }\n}\n\nfunction formatTraceValue(value) {\n if (value === undefined || value === null) return \"\";\n if (typeof value === \"string\") return value;\n return JSON.stringify(value, null, 2);\n}\n\nfunction buildTraceRows(eventType, payload, rawContent) {\n const row = (label, value) => {\n const formatted = formatTraceValue(value);\n return formatted === \"\" ? null : { label, value: formatted };\n };\n const compact = (rows) => rows.filter(Boolean);\n\n if (eventType === \"tool_call\") {\n const name = payload.server\n ? `${payload.server}.${payload.name || payload.tool || \"unknown\"}`\n : payload.name || payload.tool || \"unknown\";\n return compact([\n row(\"Tool\", name),\n row(\"Input\", payload.input || payload.arguments),\n row(\"Result\", payload.result),\n row(\"Status\", payload.status),\n row(\"Error\", payload.error),\n ]);\n }\n\n if (eventType === \"tool_result\") {\n return compact([\n row(payload.is_error ? \"Tool Error\" : \"Tool Result\", payload.tool_use_id || \"result\"),\n row(\"Content\", payload.content),\n ]);\n }\n\n if (eventType === \"command_execution\") {\n return compact([\n row(\"Command\", payload.command),\n row(\"Output\", payload.output),\n row(\"Exit\", payload.exit_code),\n row(\"Status\", payload.status),\n ]);\n }\n\n if (eventType === \"file_change\") {\n const changes = Array.isArray(payload.changes)\n ? payload.changes\n .map((change) => {\n if (!change || typeof change !== \"object\") return formatTraceValue(change);\n const kind = change.kind || change.type || \"changed\";\n const path = change.path || change.file || \"\";\n return path ? `${kind}: ${path}` : kind;\n })\n .join(\"\\n\")\n : payload.changes;\n return compact([row(\"Changes\", changes), row(\"Status\", payload.status)]);\n }\n\n if (eventType === \"web_search\") {\n return compact([\n row(\"Query\", payload.query),\n row(\"Action\", payload.action),\n row(\"Status\", payload.status),\n ]);\n }\n\n return [{ label: eventType, value: rawContent }];\n}\n\n// ─── CSRF token ───\n// Fetched once at startup; reused for all state-changing requests.\nlet _csrfTokenPromise = null;\nfunction getCsrfToken() {\n if (!_csrfTokenPromise) {\n _csrfTokenPromise = fetch(`${API}/csrf-token`)\n .then((r) => r.json())\n .then((d) => d.csrf_token || \"\")\n .catch(() => \"\");\n }\n return _csrfTokenPromise;\n}\n\nasync function csrfHeaders(extra = {}) {\n const token = await getCsrfToken();\n return { \"Content-Type\": \"application/json\", \"X-CSRF-Token\": token, ...extra };\n}\n\n// ─── API helpers ───\nasync function fetchTasks() {\n const res = await fetch(`${API}/tasks`);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n return res.json();\n}\n\nasync function fetchHeartbeats() {\n const res = await fetch(`${API}/heartbeats`);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n return res.json();\n}\n\nasync function createTask(data) {\n const res = await fetch(`${API}/tasks`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify(data),\n });\n return res.json();\n}\n\nasync function fetchSkillPatterns() {\n const res = await fetch(`${API}/skill-patterns`);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n return res.json();\n}\n\nasync function triggerSkillSweep(agent?: string) {\n const res = await fetch(`${API}/skills/sweep`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify(agent ? { agent } : {}),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function triggerSkillDraft(id, agent?: string) {\n const res = await fetch(`${API}/skill-patterns/${id}/draft`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify(agent ? { agent } : {}),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function approveSkill(id, data) {\n const res = await fetch(`${API}/skill-patterns/${id}/approve`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify(data),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function dismissSkillPattern(id) {\n const res = await fetch(`${API}/skill-patterns/${id}/dismiss`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: \"{}\",\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function fetchSkills() {\n const res = await fetch(`${API}/skills`);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n return res.json();\n}\n\nasync function setSkillEnabledApi(id, enabled) {\n const res = await fetch(`${API}/skills/${id}`, {\n method: \"PUT\",\n headers: await csrfHeaders(),\n body: JSON.stringify({ enabled }),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function deleteSkillApi(id) {\n const res = await fetch(`${API}/skills/${id}`, {\n method: \"DELETE\",\n headers: await csrfHeaders(),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function createHeartbeat(data) {\n const res = await fetch(`${API}/heartbeats`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify(data),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function updateHeartbeat(id, data) {\n const res = await fetch(`${API}/heartbeats/${id}`, {\n method: \"PUT\",\n headers: await csrfHeaders(),\n body: JSON.stringify(data),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function deleteHeartbeat(id) {\n const res = await fetch(`${API}/heartbeats/${id}`, {\n method: \"DELETE\",\n headers: await csrfHeaders(),\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n}\n\nasync function runHeartbeatNow(id) {\n const res = await fetch(`${API}/heartbeats/${id}/run-now`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function pauseHeartbeat(id) {\n const res = await fetch(`${API}/heartbeats/${id}/pause`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function resumeHeartbeatApi(id) {\n const res = await fetch(`${API}/heartbeats/${id}/resume`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function fetchHeartbeatTicks(id) {\n const res = await fetch(`${API}/heartbeats/${id}/ticks?limit=20`);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const payload = await res.json();\n return payload.ticks || [];\n}\n\nasync function fetchHeartbeatTickOutput(heartbeatId, tickId) {\n const res = await fetch(`${API}/heartbeats/${heartbeatId}/ticks/${tickId}/output`);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n return res.json();\n}\n\nasync function cancelTask(id) {\n await fetch(`${API}/tasks/${id}/cancel`, { method: \"POST\", headers: await csrfHeaders() });\n}\n\nasync function retryTask(id) {\n await fetch(`${API}/tasks/${id}/retry`, { method: \"POST\", headers: await csrfHeaders() });\n}\n\nasync function deleteTask(id) {\n await fetch(`${API}/tasks/${id}`, { method: \"DELETE\", headers: await csrfHeaders() });\n}\n\nasync function updateTask(id, data) {\n const res = await fetch(`${API}/tasks/${id}`, {\n method: \"PUT\",\n headers: await csrfHeaders(),\n body: JSON.stringify(data),\n });\n if (!res.ok) {\n const err = await res.json().catch(() => ({}));\n throw new Error(err.error || `HTTP ${res.status}`);\n }\n return res.json();\n}\n\nasync function respondToTask(id, answer) {\n await fetch(`${API}/tasks/${id}/respond`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify({ answer }),\n });\n}\n\nasync function resumeTask(id, message) {\n const res = await fetch(`${API}/tasks/${id}/resume`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify({ message }),\n });\n return res.json();\n}\n\nasync function fetchTaskMessages(id) {\n try {\n const res = await fetch(`${API}/tasks/${id}/messages`);\n return res.ok ? await res.json() : [];\n } catch {\n return [];\n }\n}\n\nasync function fetchTaskEvents(id) {\n try {\n const res = await fetch(`${API}/tasks/${id}/events?limit=1000`);\n if (res.ok) {\n const data = await res.json();\n return data.events || [];\n }\n return [];\n } catch {\n return [];\n }\n}\n\nasync function fetchSettings() {\n try {\n const res = await fetch(`${API}/settings`);\n return res.ok ? await res.json() : {};\n } catch {\n return {};\n }\n}\n\nasync function updateSettings(data) {\n await fetch(`${API}/settings`, {\n method: \"PUT\",\n headers: await csrfHeaders(),\n body: JSON.stringify(data),\n });\n}\n\nasync function fetchFeishuSettings() {\n try {\n const res = await fetch(`${API}/feishu/settings`);\n return res.ok ? await res.json() : {};\n } catch {\n return {};\n }\n}\n\nasync function updateFeishuSettings(data) {\n await fetch(`${API}/feishu/settings`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify(data),\n });\n}\n\nasync function fetchChannelsStatus() {\n try {\n const res = await fetch(`${API}/channels/status`);\n return res.ok ? await res.json() : {};\n } catch {\n return {};\n }\n}\n\nasync function updateChannelsSettings(data) {\n await fetch(`${API}/channels/settings`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify(data),\n });\n}\n\nasync function runWeixinAction(action) {\n const res = await fetch(`${API}/channels/weixin/action`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify({ action }),\n });\n if (!res.ok) {\n const data = await res.json().catch(() => ({}));\n throw new Error(data.error || `HTTP ${res.status}`);\n }\n}\n\n// ─── Components ───\n\nfunction Tooltip({ text, children }) {\n const [visible, setVisible] = useState(false);\n return (\n <div\n style={{ position: \"relative\", display: \"inline-flex\" }}\n onMouseEnter={() => setVisible(true)}\n onMouseLeave={() => setVisible(false)}\n >\n {children}\n {visible && (\n <div\n style={{\n position: \"absolute\",\n bottom: \"calc(100% + 6px)\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n color: theme.textMuted,\n fontSize: 11,\n padding: \"4px 8px\",\n borderRadius: 6,\n whiteSpace: \"nowrap\",\n pointerEvents: \"none\",\n boxShadow: \"0 4px 12px rgba(0,0,0,0.3)\",\n zIndex: 9999,\n }}\n >\n {text}\n </div>\n )}\n </div>\n );\n}\n\nfunction Badge({ status }) {\n const cfg = getStatusConfig()[status] || getStatusConfig().pending;\n return (\n <span\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 5,\n padding: \"3px 10px\",\n borderRadius: 20,\n fontSize: 11,\n fontWeight: 600,\n color: cfg.color,\n background: cfg.bg,\n letterSpacing: 0.3,\n }}\n >\n <span style={{ fontSize: 10 }}>{cfg.icon}</span>\n {cfg.label}\n </span>\n );\n}\n\nfunction Tag({ children }) {\n return (\n <span\n style={{\n padding: \"2px 8px\",\n borderRadius: 4,\n fontSize: 10,\n fontWeight: 500,\n background: theme.accentGlow,\n color: theme.accent,\n letterSpacing: 0.4,\n }}\n >\n {children}\n </span>\n );\n}\n\nfunction AgentBadge({ agent }) {\n const cfg = AGENTS[agent] || AGENTS.claude;\n return (\n <span\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 4,\n padding: \"2px 8px\",\n borderRadius: 4,\n fontSize: 10,\n fontWeight: 600,\n color: cfg.color,\n background: `${cfg.color}18`,\n letterSpacing: 0.3,\n }}\n >\n <span style={{ fontSize: 9 }}>{cfg.icon}</span>\n {cfg.label}\n </span>\n );\n}\n\nfunction TaskCard({ task, onAction, onViewDetail }) {\n const [hovered, setHovered] = useState(false);\n const cfg = getStatusConfig()[task.status] || getStatusConfig().pending;\n const tags = task.tags ? task.tags.split(\",\").filter(Boolean) : [];\n\n return (\n <div\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n onClick={() => onViewDetail(task)}\n style={{\n background: hovered ? theme.surfaceHover : theme.surface,\n border: `1px solid ${hovered ? theme.borderActive : theme.border}`,\n borderLeft: `3px solid ${cfg.color}`,\n borderRadius: 10,\n padding: \"14px 16px\",\n cursor: \"pointer\",\n transition: \"all 0.2s ease\",\n transform: hovered ? \"translateY(-1px)\" : \"none\",\n boxShadow: hovered ? `0 4px 20px rgba(0,0,0,0.3)` : \"none\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"flex-start\",\n marginBottom: 8,\n }}\n >\n <span\n style={{\n fontSize: 13,\n fontWeight: 600,\n color: theme.text,\n lineHeight: 1.4,\n flex: 1,\n marginRight: 8,\n fontFamily: \"'JetBrains Mono', 'SF Mono', monospace\",\n }}\n >\n {task.title}\n </span>\n <Badge status={task.status} />\n </div>\n\n <div\n style={{\n fontSize: 12,\n color: theme.textMuted,\n marginBottom: 10,\n lineHeight: 1.5,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n display: \"-webkit-box\",\n WebkitLineClamp: 2,\n WebkitBoxOrient: \"vertical\",\n }}\n >\n {task.prompt}\n </div>\n\n <div style={{ display: \"flex\", justifyContent: \"space-between\", alignItems: \"center\" }}>\n <div style={{ display: \"flex\", gap: 4, flexWrap: \"wrap\" }}>\n <AgentBadge agent={task.agent} />\n {task.schedule_type === \"delayed\" && <Tag>⏳ {task.delay_seconds}s</Tag>}\n {task.schedule_type === \"scheduled_at\" && task.next_run_at && (\n <Tag>📅 {formatTaskDateTime(task.next_run_at)}</Tag>\n )}\n {task.schedule_type === \"cron\" && <Tag>⏲ {task.cron_expr}</Tag>}\n {tags.map((t, i) => (\n <Tag key={i}>{t.trim()}</Tag>\n ))}\n </div>\n\n <div style={{ display: \"flex\", gap: 4 }} onClick={(e) => e.stopPropagation()}>\n {[\"pending\", \"scheduled\", \"blocked\"].includes(task.status) && (\n <ActionBtn\n label=\"✎\"\n title=\"Edit\"\n onClick={() => onAction(\"edit\", task.id)}\n color={theme.blue || theme.accent}\n />\n )}\n {[\"completed\", \"cancelled\", \"failed\"].includes(task.status) && (\n <ActionBtn\n label=\"⑂\"\n title=\"Fork\"\n onClick={() => onAction(\"fork\", task.id)}\n color={theme.cyan || theme.accent}\n />\n )}\n {task.status === \"failed\" && (\n <ActionBtn\n label=\"↻\"\n title=\"Retry\"\n onClick={() => onAction(\"retry\", task.id)}\n color={theme.orange}\n />\n )}\n {[\"pending\", \"scheduled\", \"running\"].includes(task.status) && (\n <ActionBtn\n label=\"■\"\n title=\"Cancel\"\n onClick={() => onAction(\"cancel\", task.id)}\n color={theme.red}\n />\n )}\n <ActionBtn\n label=\"×\"\n title=\"Delete\"\n onClick={() => onAction(\"delete\", task.id)}\n color={theme.textMuted}\n />\n </div>\n </div>\n\n {task.run_count > 0 && (\n <div style={{ fontSize: 10, color: theme.textDim, marginTop: 8, fontFamily: \"monospace\" }}>\n Runs: {task.run_count}\n {task.max_runs ? ` / ${task.max_runs}` : \"\"}\n {task.last_run_at && ` · Last: ${formatTaskTime(task.last_run_at)}`}\n </div>\n )}\n\n {/* DAG info */}\n {task.status === \"blocked\" && task.dependencies && task.dependencies.length > 0 && (\n <div style={{ fontSize: 10, color: theme.textDim, marginTop: 6, fontFamily: \"monospace\" }}>\n ⊘ Waiting for: {task.dependencies.map((d) => `#${d.depends_on_task_id}`).join(\", \")}\n </div>\n )}\n {task.dependents && task.dependents.length > 0 && task.status === \"completed\" && (\n <div style={{ fontSize: 10, color: theme.textDim, marginTop: 6, fontFamily: \"monospace\" }}>\n → Unlocks: {task.dependents.map((id) => `#${id}`).join(\", \")}\n </div>\n )}\n {task.dag_id && (\n <div\n style={{\n fontSize: 10,\n color: theme.accent,\n marginTop: 4,\n opacity: 0.6,\n fontFamily: \"monospace\",\n }}\n >\n dag: {task.dag_id}\n </div>\n )}\n </div>\n );\n}\n\nfunction ActionBtn({ label, title, onClick, color }) {\n const [hovered, setHovered] = useState(false);\n return (\n <button\n title={title}\n onClick={onClick}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n style={{\n background: hovered ? `${color}22` : \"transparent\",\n border: \"none\",\n color: color,\n cursor: \"pointer\",\n width: 24,\n height: 24,\n borderRadius: 6,\n fontSize: 14,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"background 0.15s\",\n }}\n >\n {label}\n </button>\n );\n}\n\nfunction Column({ col, tasks, onAction, onViewDetail }) {\n return (\n <div style={{ flex: 1, minWidth: 300 }}>\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n marginBottom: 16,\n padding: \"0 4px\",\n }}\n >\n <span style={{ fontSize: 16, opacity: 0.4 }}>{col.icon}</span>\n <span\n style={{\n fontSize: 12,\n fontWeight: 700,\n color: theme.textMuted,\n letterSpacing: 1.5,\n textTransform: \"uppercase\",\n }}\n >\n {col.label}\n </span>\n <span\n style={{\n background: theme.border,\n borderRadius: 10,\n padding: \"2px 8px\",\n fontSize: 11,\n color: theme.textDim,\n fontWeight: 600,\n }}\n >\n {tasks.length}\n </span>\n </div>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 8 }}>\n {tasks.map((t) => (\n <TaskCard key={t.id} task={t} onAction={onAction} onViewDetail={onViewDetail} />\n ))}\n {tasks.length === 0 && (\n <div\n style={{\n border: `1px dashed ${theme.border}`,\n borderRadius: 10,\n padding: 32,\n textAlign: \"center\",\n color: theme.textDim,\n fontSize: 12,\n }}\n >\n No tasks\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction HeartbeatBadge({ enabled }) {\n return (\n <span\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 5,\n padding: \"3px 10px\",\n borderRadius: 20,\n fontSize: 11,\n fontWeight: 600,\n color: enabled ? theme.green : theme.textMuted,\n background: enabled ? theme.greenBg : \"rgba(107,107,138,0.08)\",\n letterSpacing: 0.3,\n }}\n >\n <span style={{ fontSize: 10 }}>{enabled ? \"●\" : \"◌\"}</span>\n {enabled ? \"Enabled\" : \"Paused\"}\n </span>\n );\n}\n\nfunction HeartbeatModal({ onClose, onSubmit, initialData, defaultAgent, mode = \"create\" }: any) {\n const savedDir = localStorage.getItem(\"agentforge_working_dir\") || \"~/papers\";\n const [form, setForm] = useState(() => ({\n name: initialData?.name || \"\",\n working_dir: initialData?.working_dir || savedDir,\n schedule_type: initialData?.schedule_type || \"interval\",\n interval_seconds: initialData?.interval_seconds || 600,\n cron_expr: initialData?.cron_expr || \"\",\n check_prompt: initialData?.check_prompt || \"\",\n action_prompt_template: initialData?.action_prompt_template || \"\",\n default_agent: initialData?.default_agent || defaultAgent || DEFAULT_AGENT,\n cooldown_seconds: initialData?.cooldown_seconds || 1800,\n enabled: initialData?.enabled ?? true,\n }));\n\n const set = (k, v) => setForm((prev) => ({ ...prev, [k]: v }));\n\n const inputStyle: CSSProperties = {\n width: \"100%\",\n padding: \"10px 14px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n color: theme.text,\n fontSize: 13,\n outline: \"none\",\n boxSizing: \"border-box\",\n fontFamily: \"'JetBrains Mono', 'SF Mono', monospace\",\n };\n const labelStyle = {\n fontSize: 11,\n fontWeight: 600,\n color: theme.textMuted,\n letterSpacing: 0.8,\n textTransform: \"uppercase\",\n marginBottom: 6,\n display: \"block\",\n };\n\n const handleSubmit = () => {\n localStorage.setItem(\"agentforge_working_dir\", form.working_dir);\n onSubmit({\n ...form,\n name: form.name || \"Untitled heartbeat\",\n interval_seconds:\n form.schedule_type === \"interval\" ? parseInt(form.interval_seconds) || 600 : null,\n cooldown_seconds: parseInt(form.cooldown_seconds) || 0,\n cron_expr: form.schedule_type === \"cron\" ? form.cron_expr : null,\n });\n };\n\n return (\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n background: \"rgba(0,0,0,0.7)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex: 1000,\n backdropFilter: \"blur(8px)\",\n }}\n onClick={onClose}\n >\n <div\n onClick={(e) => e.stopPropagation()}\n style={{\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 16,\n padding: 32,\n width: 640,\n maxHeight: \"84vh\",\n overflow: \"auto\",\n boxShadow: \"0 24px 80px rgba(0,0,0,0.5)\",\n }}\n >\n <h2\n style={{\n margin: \"0 0 24px\",\n fontSize: 18,\n fontWeight: 700,\n color: theme.text,\n fontFamily: \"'JetBrains Mono', monospace\",\n }}\n >\n {mode === \"edit\" ? \"Edit Heartbeat\" : \"New Heartbeat\"}\n </h2>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 16 }}>\n <div>\n <label style={labelStyle}>Name</label>\n <input\n style={inputStyle}\n value={form.name}\n onChange={(e) => set(\"name\", e.target.value)}\n placeholder=\"Repo review watcher\"\n />\n </div>\n <div>\n <label style={labelStyle}>Working Directory</label>\n <div style={{ display: \"flex\", gap: 8 }}>\n <input\n style={{ ...inputStyle, flex: 1 }}\n value={form.working_dir}\n onChange={(e) => set(\"working_dir\", e.target.value)}\n />\n {window.electronAPI?.selectDirectory && (\n <button\n onClick={async () => {\n const dir = await window.electronAPI.selectDirectory();\n if (dir) set(\"working_dir\", dir);\n }}\n style={{\n padding: \"8px 14px\",\n borderRadius: 8,\n cursor: \"pointer\",\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n color: theme.textMuted,\n fontSize: 12,\n fontWeight: 600,\n whiteSpace: \"nowrap\",\n }}\n >\n Browse\n </button>\n )}\n </div>\n </div>\n <div>\n <label style={labelStyle}>Schedule Type</label>\n <div style={{ display: \"flex\", gap: 8 }}>\n {[\"interval\", \"cron\"].map((t) => (\n <button\n key={t}\n onClick={() => set(\"schedule_type\", t)}\n style={{\n flex: 1,\n padding: \"8px 12px\",\n borderRadius: 8,\n cursor: \"pointer\",\n border: `1px solid ${form.schedule_type === t ? theme.accent : theme.border}`,\n background: form.schedule_type === t ? theme.accentGlow : \"transparent\",\n color: form.schedule_type === t ? theme.accent : theme.textMuted,\n fontSize: 12,\n fontWeight: 600,\n textTransform: \"capitalize\",\n }}\n >\n {t === \"interval\" ? \"⟳ Interval\" : \"⏲ Cron\"}\n </button>\n ))}\n </div>\n </div>\n {form.schedule_type === \"interval\" ? (\n <div>\n <label style={labelStyle}>Interval (seconds)</label>\n <input\n type=\"number\"\n style={inputStyle}\n value={form.interval_seconds}\n onChange={(e) => set(\"interval_seconds\", e.target.value)}\n />\n </div>\n ) : (\n <div>\n <label style={labelStyle}>Cron Expression</label>\n <input\n style={inputStyle}\n value={form.cron_expr}\n onChange={(e) => set(\"cron_expr\", e.target.value)}\n placeholder=\"*/10 * * * *\"\n />\n </div>\n )}\n <div>\n <label style={labelStyle}>Decision Prompt *</label>\n <textarea\n style={{ ...inputStyle, height: 110, resize: \"vertical\" }}\n value={form.check_prompt}\n onChange={(e) => set(\"check_prompt\", e.target.value)}\n placeholder=\"Check whether there are new meaningful code changes that deserve a review task. Return JSON only.\"\n />\n </div>\n <div>\n <label style={labelStyle}>Triggered Task Prompt Template</label>\n <textarea\n style={{ ...inputStyle, height: 90, resize: \"vertical\" }}\n value={form.action_prompt_template}\n onChange={(e) => set(\"action_prompt_template\", e.target.value)}\n placeholder=\"Review the latest code changes and summarize bugs, regressions, and missing tests.\"\n />\n </div>\n <div style={{ display: \"grid\", gridTemplateColumns: \"1fr 1fr\", gap: 12 }}>\n <div>\n <label style={labelStyle}>Default Agent</label>\n <select\n style={inputStyle}\n value={form.default_agent}\n onChange={(e) => set(\"default_agent\", e.target.value)}\n >\n {Object.entries(AGENTS).map(([key, cfg]) => (\n <option key={key} value={key}>\n {cfg.label}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label style={labelStyle}>Cooldown (seconds)</label>\n <input\n type=\"number\"\n style={inputStyle}\n value={form.cooldown_seconds}\n onChange={(e) => set(\"cooldown_seconds\", e.target.value)}\n />\n </div>\n </div>\n <label\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n fontSize: 13,\n color: theme.textMuted,\n }}\n >\n <input\n type=\"checkbox\"\n checked={!!form.enabled}\n onChange={(e) => set(\"enabled\", e.target.checked)}\n />\n Enabled\n </label>\n </div>\n <div style={{ display: \"flex\", gap: 10, justifyContent: \"flex-end\", marginTop: 24 }}>\n <button\n onClick={onClose}\n style={{\n padding: \"10px 20px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: \"transparent\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n }}\n >\n Cancel\n </button>\n <button\n onClick={handleSubmit}\n style={{\n padding: \"10px 24px\",\n borderRadius: 8,\n border: \"none\",\n background: theme.accent,\n color: \"#fff\",\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n boxShadow: `0 0 20px ${theme.accentGlow}`,\n }}\n >\n {mode === \"edit\" ? \"Save\" : \"Create Heartbeat\"}\n </button>\n </div>\n </div>\n </div>\n );\n}\n\nfunction HeartbeatCard({ heartbeat, onAction, onViewDetail }) {\n const tags = [];\n if (heartbeat.schedule_type === \"interval\" && heartbeat.interval_seconds)\n tags.push(`⟳ ${heartbeat.interval_seconds}s`);\n if (heartbeat.schedule_type === \"cron\" && heartbeat.cron_expr)\n tags.push(`⏲ ${heartbeat.cron_expr}`);\n if (heartbeat.last_decision) tags.push(`Last: ${heartbeat.last_decision}`);\n\n return (\n <div\n onClick={() => onViewDetail(heartbeat)}\n style={{\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 12,\n padding: \"16px 18px\",\n cursor: \"pointer\",\n transition: \"all 0.2s ease\",\n }}\n >\n <div style={{ display: \"flex\", justifyContent: \"space-between\", gap: 16, marginBottom: 8 }}>\n <div style={{ flex: 1 }}>\n <div\n style={{\n fontSize: 14,\n fontWeight: 700,\n color: theme.text,\n fontFamily: \"'JetBrains Mono', monospace\",\n marginBottom: 6,\n }}\n >\n {heartbeat.name}\n </div>\n <div\n style={{\n fontSize: 12,\n color: theme.textMuted,\n lineHeight: 1.5,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n display: \"-webkit-box\",\n WebkitLineClamp: 2,\n WebkitBoxOrient: \"vertical\",\n }}\n >\n {heartbeat.check_prompt}\n </div>\n </div>\n <HeartbeatBadge enabled={heartbeat.enabled} />\n </div>\n\n <div\n style={{ display: \"flex\", justifyContent: \"space-between\", alignItems: \"center\", gap: 12 }}\n >\n <div style={{ display: \"flex\", gap: 6, flexWrap: \"wrap\" }}>\n <AgentBadge agent={heartbeat.default_agent} />\n {tags.map((tag, idx) => (\n <Tag key={idx}>{tag}</Tag>\n ))}\n </div>\n <div style={{ display: \"flex\", gap: 4 }} onClick={(e) => e.stopPropagation()}>\n <ActionBtn\n label=\"⚡\"\n title=\"Run now\"\n onClick={() => onAction(\"run\", heartbeat.id)}\n color={theme.orange}\n />\n <ActionBtn\n label=\"✎\"\n title=\"Edit\"\n onClick={() => onAction(\"edit\", heartbeat.id)}\n color={theme.blue}\n />\n {heartbeat.enabled ? (\n <ActionBtn\n label=\"❚❚\"\n title=\"Pause\"\n onClick={() => onAction(\"pause\", heartbeat.id)}\n color={theme.textMuted}\n />\n ) : (\n <ActionBtn\n label=\"▶\"\n title=\"Resume\"\n onClick={() => onAction(\"resume\", heartbeat.id)}\n color={theme.green}\n />\n )}\n <ActionBtn\n label=\"×\"\n title=\"Delete\"\n onClick={() => onAction(\"delete\", heartbeat.id)}\n color={theme.red}\n />\n </div>\n </div>\n\n <div\n style={{\n fontSize: 11,\n color: theme.textDim,\n marginTop: 10,\n fontFamily: \"monospace\",\n lineHeight: 1.6,\n }}\n >\n Next: {heartbeat.next_run_at ? formatTaskDateTime(heartbeat.next_run_at) : \"n/a\"}\n {\" · \"}\n Triggered:{\" \"}\n {heartbeat.last_triggered_at ? formatTaskDateTime(heartbeat.last_triggered_at) : \"never\"}\n </div>\n {heartbeat.last_error && (\n <div style={{ fontSize: 11, color: theme.red, marginTop: 6, lineHeight: 1.4 }}>\n Last error: {heartbeat.last_error}\n </div>\n )}\n </div>\n );\n}\n\nfunction HeartbeatDetailPanel({ heartbeat, ticks, onClose }) {\n const [selectedTickId, setSelectedTickId] = useState<any>(null);\n const [tickOutput, setTickOutput] = useState(\"\");\n const [tickRunning, setTickRunning] = useState(false);\n const outputRef = useRef<any>(null);\n\n useEffect(() => {\n setSelectedTickId(ticks[0]?.id || null);\n }, [heartbeat.id, ticks]);\n\n useEffect(() => {\n if (!selectedTickId) {\n setTickOutput(\"\");\n setTickRunning(false);\n return;\n }\n let cancelled = false;\n const load = async () => {\n try {\n const data = await fetchHeartbeatTickOutput(heartbeat.id, selectedTickId);\n if (cancelled) return;\n setTickOutput(data.output || \"\");\n setTickRunning(!!data.is_running);\n } catch {\n if (!cancelled) {\n setTickOutput(\"\");\n setTickRunning(false);\n }\n }\n };\n load();\n const interval = setInterval(load, 1000);\n return () => {\n cancelled = true;\n clearInterval(interval);\n };\n }, [heartbeat.id, selectedTickId]);\n\n useEffect(() => {\n if (outputRef.current) {\n outputRef.current.scrollTop = outputRef.current.scrollHeight;\n }\n }, [tickOutput]);\n\n return (\n <div\n style={{\n position: \"fixed\",\n top: 0,\n right: 0,\n width: 520,\n height: \"100vh\",\n background: theme.surface,\n borderLeft: `1px solid ${theme.border}`,\n boxShadow: \"-20px 0 60px rgba(0,0,0,0.4)\",\n zIndex: 500,\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n <div\n style={{\n padding: \"22px 24px\",\n borderBottom: `1px solid ${theme.border}`,\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"flex-start\",\n gap: 12,\n }}\n >\n <div>\n <div\n style={{\n fontSize: 18,\n fontWeight: 700,\n color: theme.text,\n fontFamily: \"'JetBrains Mono', monospace\",\n }}\n >\n {heartbeat.name}\n </div>\n <div style={{ fontSize: 12, color: theme.textMuted, marginTop: 6 }}>\n {heartbeat.working_dir}\n </div>\n </div>\n <button\n onClick={onClose}\n style={{\n background: \"transparent\",\n border: \"none\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 22,\n lineHeight: 1,\n }}\n >\n ×\n </button>\n </div>\n <div style={{ padding: 24, overflow: \"auto\", flex: 1 }}>\n <div style={{ display: \"flex\", gap: 8, flexWrap: \"wrap\", marginBottom: 16 }}>\n <HeartbeatBadge enabled={heartbeat.enabled} />\n <AgentBadge agent={heartbeat.default_agent} />\n {heartbeat.schedule_type === \"interval\" ? (\n <Tag>⟳ {heartbeat.interval_seconds}s</Tag>\n ) : (\n <Tag>⏲ {heartbeat.cron_expr}</Tag>\n )}\n {heartbeat.last_decision && <Tag>{heartbeat.last_decision}</Tag>}\n </div>\n <div style={{ fontSize: 12, color: theme.textMuted, lineHeight: 1.7, marginBottom: 18 }}>\n <div>\n Next run: {heartbeat.next_run_at ? formatTaskDateTime(heartbeat.next_run_at) : \"n/a\"}\n </div>\n <div>\n Last tick:{\" \"}\n {heartbeat.last_tick_at ? formatTaskDateTime(heartbeat.last_tick_at) : \"never\"}\n </div>\n <div>\n Last trigger:{\" \"}\n {heartbeat.last_triggered_at\n ? formatTaskDateTime(heartbeat.last_triggered_at)\n : \"never\"}\n </div>\n <div>Cooldown: {heartbeat.cooldown_seconds || 0}s</div>\n </div>\n <div style={{ marginBottom: 20 }}>\n <div\n style={{\n fontSize: 11,\n fontWeight: 700,\n color: theme.textMuted,\n letterSpacing: 0.8,\n textTransform: \"uppercase\",\n marginBottom: 8,\n }}\n >\n Decision Prompt\n </div>\n <div\n style={{\n fontSize: 12,\n lineHeight: 1.7,\n color: theme.text,\n background: theme.bg,\n border: `1px solid ${theme.border}`,\n borderRadius: 10,\n padding: 14,\n whiteSpace: \"pre-wrap\",\n }}\n >\n {heartbeat.check_prompt}\n </div>\n </div>\n <div style={{ marginBottom: 20 }}>\n <div\n style={{\n fontSize: 11,\n fontWeight: 700,\n color: theme.textMuted,\n letterSpacing: 0.8,\n textTransform: \"uppercase\",\n marginBottom: 8,\n }}\n >\n Triggered Task Template\n </div>\n <div\n style={{\n fontSize: 12,\n lineHeight: 1.7,\n color: theme.text,\n background: theme.bg,\n border: `1px solid ${theme.border}`,\n borderRadius: 10,\n padding: 14,\n whiteSpace: \"pre-wrap\",\n }}\n >\n {heartbeat.action_prompt_template || \"No template configured\"}\n </div>\n </div>\n <div>\n <div\n style={{\n fontSize: 11,\n fontWeight: 700,\n color: theme.textMuted,\n letterSpacing: 0.8,\n textTransform: \"uppercase\",\n marginBottom: 8,\n }}\n >\n Recent Ticks\n </div>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 8 }}>\n {ticks.map((tick) => {\n let payload = null;\n try {\n payload = tick.decision_payload ? JSON.parse(tick.decision_payload) : null;\n } catch {}\n return (\n <div\n key={tick.id}\n style={{\n background: theme.bg,\n border: `1px solid ${theme.border}`,\n borderRadius: 10,\n padding: 12,\n cursor: \"pointer\",\n boxShadow:\n selectedTickId === tick.id ? `0 0 0 1px ${theme.accent} inset` : \"none\",\n }}\n >\n <div\n onClick={() => setSelectedTickId(tick.id)}\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n gap: 8,\n marginBottom: 6,\n }}\n >\n <div style={{ fontSize: 12, fontWeight: 600, color: theme.text }}>\n {tick.decision_type || tick.status}\n </div>\n <div style={{ fontSize: 11, color: theme.textDim, fontFamily: \"monospace\" }}>\n {tick.started_at ? formatTaskDateTime(tick.started_at) : \"\"}\n </div>\n </div>\n {payload?.reason && (\n <div style={{ fontSize: 12, color: theme.textMuted, lineHeight: 1.5 }}>\n {payload.reason}\n </div>\n )}\n {tick.error && (\n <div style={{ fontSize: 12, color: theme.red, lineHeight: 1.5 }}>\n {tick.error}\n </div>\n )}\n {tick.task_id && (\n <div\n style={{\n fontSize: 11,\n color: theme.accent,\n marginTop: 6,\n fontFamily: \"monospace\",\n }}\n >\n Triggered task #{tick.task_id}\n </div>\n )}\n </div>\n );\n })}\n {ticks.length === 0 && (\n <div\n style={{\n border: `1px dashed ${theme.border}`,\n borderRadius: 10,\n padding: 24,\n textAlign: \"center\",\n color: theme.textDim,\n fontSize: 12,\n }}\n >\n No ticks yet\n </div>\n )}\n </div>\n </div>\n <div style={{ marginTop: 20 }}>\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n marginBottom: 8,\n }}\n >\n <div\n style={{\n fontSize: 11,\n fontWeight: 700,\n color: theme.textMuted,\n letterSpacing: 0.8,\n textTransform: \"uppercase\",\n }}\n >\n Tick Log\n </div>\n {selectedTickId && (\n <div\n style={{\n fontSize: 11,\n color: tickRunning ? theme.orange : theme.textDim,\n fontFamily: \"monospace\",\n }}\n >\n {tickRunning ? \"LIVE\" : \"Stored\"} · tick #{selectedTickId}\n </div>\n )}\n </div>\n <div\n ref={outputRef}\n style={{\n background: theme.bg,\n border: `1px solid ${theme.border}`,\n borderRadius: 10,\n padding: 14,\n minHeight: 180,\n maxHeight: 320,\n overflow: \"auto\",\n fontFamily: \"'JetBrains Mono', monospace\",\n fontSize: 12,\n lineHeight: 1.6,\n whiteSpace: \"pre-wrap\",\n color: theme.text,\n }}\n >\n {selectedTickId\n ? tickOutput || \"No output captured for this tick.\"\n : \"Select a tick to view its log.\"}\n </div>\n </div>\n </div>\n </div>\n );\n}\n\nfunction NewTaskModal({ onClose, onSubmit, initialData, mode = \"create\" }) {\n const savedDir = localStorage.getItem(\"agentforge_working_dir\") || \"~/papers\";\n const [form, setForm] = useState(() => {\n if (initialData) {\n return {\n title: initialData.title || \"\",\n prompt: initialData.prompt || \"\",\n working_dir: initialData.working_dir || savedDir,\n schedule_type: initialData.schedule_type || \"immediate\",\n cron_expr: initialData.cron_expr || \"\",\n delay_seconds: initialData.delay_seconds || 60,\n scheduled_at: initialData.next_run_at\n ? formatDateTimeLocalInput(initialData.next_run_at)\n : \"\",\n max_runs: initialData.max_runs || \"\",\n tags: initialData.tags || \"\",\n agent: initialData.agent || DEFAULT_AGENT,\n dag_id: initialData.dag_id || \"\",\n };\n }\n return {\n title: \"\",\n prompt: \"\",\n working_dir: savedDir,\n schedule_type: \"immediate\",\n cron_expr: \"\",\n delay_seconds: 60,\n scheduled_at: \"\",\n max_runs: \"\",\n tags: \"\",\n agent: DEFAULT_AGENT,\n dag_id: \"\",\n };\n });\n const [promptImages, setPromptImages] = useState(() => {\n if (initialData?.prompt_images && Array.isArray(initialData.prompt_images)) {\n return initialData.prompt_images.map((img) => ({\n name: img.name || \"image\",\n media_type: img.media_type || \"image/jpeg\",\n data: img.data || \"\",\n preview: img.data ? `data:${img.media_type || \"image/jpeg\"};base64,${img.data}` : \"\",\n }));\n }\n return [];\n });\n // DAG dependencies: [{task_id, inject_result, _input}] — _input is the text box value\n const [depRows, setDepRows] = useState(() => {\n if (initialData?.dependencies && Array.isArray(initialData.dependencies)) {\n return initialData.dependencies.map((dep) => ({\n task_id: dep.depends_on_task_id,\n inject_result: !!dep.inject_result,\n _input: String(dep.depends_on_task_id),\n }));\n }\n return [];\n });\n const [scheduledAtError, setScheduledAtError] = useState(\"\");\n\n const set = (k, v) => setForm((prev) => ({ ...prev, [k]: v }));\n\n const handleImageSelect = (e) => {\n const files = Array.from(e.target.files || []);\n files.forEach((file: any) => {\n const reader = new FileReader();\n reader.onload = (ev) => {\n const dataUrl = ev.target.result as string; // \"data:image/jpeg;base64,...\"\n const [meta, data] = dataUrl.split(\",\");\n const media_type = meta.match(/:(.*?);/)?.[1] || \"image/jpeg\";\n setPromptImages((prev) => [\n ...prev,\n { name: file.name, media_type, data, preview: dataUrl },\n ]);\n };\n reader.readAsDataURL(file);\n });\n e.target.value = \"\";\n };\n\n const removeImage = (idx) => setPromptImages((prev) => prev.filter((_, i) => i !== idx));\n\n const handleSubmit = () => {\n if (!form.prompt.trim()) return;\n localStorage.setItem(\"agentforge_working_dir\", form.working_dir);\n\n // Build depends_on list (only valid numeric IDs)\n const depends_on = depRows\n .filter((r) => r.task_id)\n .map((r) => ({ task_id: r.task_id, inject_result: r.inject_result }));\n\n const data: any = {\n ...form,\n title: form.title || form.prompt.slice(0, 60),\n delay_seconds: form.schedule_type === \"delayed\" ? parseInt(form.delay_seconds) || 60 : null,\n cron_expr: form.schedule_type === \"cron\" ? form.cron_expr : null,\n max_runs: form.max_runs ? parseInt(form.max_runs) : null,\n prompt_images: promptImages.map(({ name, media_type, data }) => ({ name, media_type, data })),\n depends_on: mode === \"edit\" ? depends_on : depends_on.length > 0 ? depends_on : undefined,\n dag_id: form.dag_id || undefined,\n };\n\n // Handle scheduled_at: convert datetime-local to ISO timestamp\n if (form.schedule_type === \"scheduled_at\") {\n const localDate = parseTaskDateTime(form.scheduled_at);\n const serialized = serializeDateTimeLocalInput(form.scheduled_at);\n if (!form.scheduled_at || !serialized || !localDate || isNaN(localDate.getTime())) {\n setScheduledAtError(\"Please enter a valid date and time.\");\n return;\n }\n setScheduledAtError(\"\");\n data.next_run_at = serialized;\n }\n\n onSubmit(data);\n };\n\n const inputStyle: CSSProperties = {\n width: \"100%\",\n padding: \"10px 14px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n color: theme.text,\n fontSize: 13,\n outline: \"none\",\n boxSizing: \"border-box\",\n fontFamily: \"'JetBrains Mono', 'SF Mono', monospace\",\n transition: \"border-color 0.2s\",\n };\n\n const labelStyle = {\n fontSize: 11,\n fontWeight: 600,\n color: theme.textMuted,\n letterSpacing: 0.8,\n textTransform: \"uppercase\",\n marginBottom: 6,\n display: \"block\",\n };\n\n return (\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n background: \"rgba(0,0,0,0.7)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex: 1000,\n backdropFilter: \"blur(8px)\",\n }}\n onClick={onClose}\n >\n <div\n onClick={(e) => e.stopPropagation()}\n style={{\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 16,\n padding: 32,\n width: 520,\n maxHeight: \"80vh\",\n overflow: \"auto\",\n boxShadow: \"0 24px 80px rgba(0,0,0,0.5)\",\n }}\n >\n <h2\n style={{\n margin: \"0 0 24px\",\n fontSize: 18,\n fontWeight: 700,\n color: theme.text,\n fontFamily: \"'JetBrains Mono', monospace\",\n }}\n >\n {mode === \"edit\" ? \"Edit Task\" : mode === \"fork\" ? \"Fork Task\" : \"New Task\"}\n </h2>\n\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 16 }}>\n <div>\n <label style={labelStyle}>Title</label>\n <input\n style={inputStyle}\n placeholder=\"Task title...\"\n value={form.title}\n onChange={(e) => set(\"title\", e.target.value)}\n />\n </div>\n\n <div>\n <label style={labelStyle}>Prompt *</label>\n <textarea\n style={{ ...inputStyle, height: 100, resize: \"vertical\" }}\n placeholder=\"The prompt to send to Claude Code...\"\n value={form.prompt}\n onChange={(e) => set(\"prompt\", e.target.value)}\n />\n </div>\n\n <div>\n <label style={labelStyle}>Images (optional)</label>\n <div\n style={{\n display: \"flex\",\n flexWrap: \"wrap\",\n gap: 8,\n marginBottom: promptImages.length ? 8 : 0,\n }}\n >\n {promptImages.map((img, idx) => (\n <div key={idx} style={{ position: \"relative\", width: 72, height: 72 }}>\n <img\n src={img.preview}\n alt={img.name}\n style={{\n width: 72,\n height: 72,\n objectFit: \"cover\",\n borderRadius: 6,\n border: `1px solid ${theme.border}`,\n }}\n />\n <button\n onClick={() => removeImage(idx)}\n style={{\n position: \"absolute\",\n top: -6,\n right: -6,\n width: 18,\n height: 18,\n borderRadius: \"50%\",\n border: \"none\",\n background: theme.red || \"#e74c3c\",\n color: \"#fff\",\n fontSize: 11,\n cursor: \"pointer\",\n lineHeight: \"18px\",\n padding: 0,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n >\n ×\n </button>\n </div>\n ))}\n <label\n style={{\n width: 72,\n height: 72,\n borderRadius: 6,\n border: `1px dashed ${theme.border}`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"pointer\",\n color: theme.textDim,\n fontSize: 22,\n flexShrink: 0,\n }}\n >\n +\n <input\n type=\"file\"\n accept=\"image/*\"\n multiple\n style={{ display: \"none\" }}\n onChange={handleImageSelect}\n />\n </label>\n </div>\n {promptImages.length > 0 && (\n <div style={{ fontSize: 10, color: theme.textDim }}>\n {promptImages.length} image{promptImages.length > 1 ? \"s\" : \"\"} attached\n </div>\n )}\n </div>\n\n <div>\n <label style={labelStyle}>Working Directory</label>\n <div style={{ display: \"flex\", gap: 8 }}>\n <input\n style={{ ...inputStyle, flex: 1 }}\n placeholder=\"~/papers\"\n value={form.working_dir}\n onChange={(e) => set(\"working_dir\", e.target.value)}\n />\n {window.electronAPI?.selectDirectory && (\n <button\n onClick={async () => {\n const dir = await window.electronAPI.selectDirectory();\n if (dir) set(\"working_dir\", dir);\n }}\n style={{\n padding: \"8px 14px\",\n borderRadius: 8,\n cursor: \"pointer\",\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n color: theme.textMuted,\n fontSize: 12,\n fontWeight: 600,\n whiteSpace: \"nowrap\",\n transition: \"all 0.15s\",\n }}\n >\n Browse\n </button>\n )}\n </div>\n </div>\n\n <div>\n <label style={labelStyle}>Schedule Type</label>\n <div style={{ display: \"flex\", gap: 8, flexWrap: \"wrap\" }}>\n {[\"immediate\", \"delayed\", \"scheduled_at\", \"cron\"].map((t) => (\n <button\n key={t}\n onClick={() => set(\"schedule_type\", t)}\n style={{\n flex: 1,\n padding: \"8px 12px\",\n borderRadius: 8,\n cursor: \"pointer\",\n border: `1px solid ${form.schedule_type === t ? theme.accent : theme.border}`,\n background: form.schedule_type === t ? theme.accentGlow : \"transparent\",\n color: form.schedule_type === t ? theme.accent : theme.textMuted,\n fontSize: 12,\n fontWeight: 600,\n textTransform: \"capitalize\",\n transition: \"all 0.15s\",\n minWidth: 100,\n }}\n >\n {t === \"immediate\"\n ? \"⚡ Immediate\"\n : t === \"delayed\"\n ? \"⏳ Delayed\"\n : t === \"scheduled_at\"\n ? \"📅 At Time\"\n : \"⏲ Cron\"}\n </button>\n ))}\n </div>\n </div>\n\n {form.schedule_type === \"delayed\" && (\n <div>\n <label style={labelStyle}>Delay (seconds)</label>\n <input\n type=\"number\"\n style={inputStyle}\n value={form.delay_seconds}\n onChange={(e) => set(\"delay_seconds\", e.target.value)}\n />\n </div>\n )}\n\n {form.schedule_type === \"scheduled_at\" && (\n <div>\n <label style={labelStyle}>Run At (Local Time)</label>\n <input\n type=\"datetime-local\"\n style={inputStyle}\n value={form.scheduled_at}\n onChange={(e) => {\n set(\"scheduled_at\", e.target.value);\n setScheduledAtError(\"\");\n }}\n />\n {scheduledAtError && (\n <div style={{ fontSize: 11, color: \"#ff5f5f\", marginTop: 4 }}>\n {scheduledAtError}\n </div>\n )}\n <div style={{ fontSize: 10, color: theme.textDim, marginTop: 4 }}>\n Select a specific date and time to execute this task once\n </div>\n </div>\n )}\n\n {form.schedule_type === \"cron\" && (\n <>\n <div>\n <label style={labelStyle}>Cron Expression</label>\n <input\n style={inputStyle}\n placeholder=\"*/30 * * * *\"\n value={form.cron_expr}\n onChange={(e) => set(\"cron_expr\", e.target.value)}\n />\n <div style={{ fontSize: 10, color: theme.textDim, marginTop: 4 }}>\n e.g. \"0 9 * * *\" = daily 9am, \"*/30 * * * *\" = every 30 min\n </div>\n </div>\n <div>\n <label style={labelStyle}>Max Runs (empty = unlimited)</label>\n <input\n type=\"number\"\n style={inputStyle}\n value={form.max_runs}\n onChange={(e) => set(\"max_runs\", e.target.value)}\n />\n </div>\n </>\n )}\n\n <div>\n <label style={labelStyle}>Tags (comma separated)</label>\n <input\n style={inputStyle}\n placeholder=\"paper, review, arxiv\"\n value={form.tags}\n onChange={(e) => set(\"tags\", e.target.value)}\n />\n </div>\n\n {/* ── DAG Dependencies ── */}\n <div>\n <label style={labelStyle}>Dependencies (optional)</label>\n <div style={{ fontSize: 10, color: theme.textDim, marginBottom: 8 }}>\n This task will be blocked until all upstream tasks complete.\n </div>\n {depRows.map((row, idx) => (\n <div\n key={idx}\n style={{ display: \"flex\", gap: 6, alignItems: \"center\", marginBottom: 6 }}\n >\n <input\n type=\"number\"\n placeholder=\"Task ID\"\n value={row._input || \"\"}\n onChange={(e) => {\n const val = e.target.value;\n const parsed = parseInt(val);\n setDepRows((prev) =>\n prev.map((r, i) =>\n i === idx\n ? { ...r, _input: val, task_id: isNaN(parsed) ? null : parsed }\n : r,\n ),\n );\n }}\n style={{ ...inputStyle, width: 100, flex: \"none\" }}\n />\n <label\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 4,\n fontSize: 11,\n color: theme.textMuted,\n cursor: \"pointer\",\n flex: 1,\n }}\n >\n <input\n type=\"checkbox\"\n checked={row.inject_result}\n onChange={(e) =>\n setDepRows((prev) =>\n prev.map((r, i) =>\n i === idx ? { ...r, inject_result: e.target.checked } : r,\n ),\n )\n }\n style={{ accentColor: theme.accent }}\n />\n Inject result into prompt\n </label>\n <button\n onClick={() => setDepRows((prev) => prev.filter((_, i) => i !== idx))}\n style={{\n background: \"transparent\",\n border: \"none\",\n color: theme.red,\n cursor: \"pointer\",\n fontSize: 16,\n padding: \"0 4px\",\n }}\n >\n ×\n </button>\n </div>\n ))}\n <button\n onClick={() =>\n setDepRows((prev) => [...prev, { task_id: null, inject_result: false, _input: \"\" }])\n }\n style={{\n padding: \"5px 12px\",\n borderRadius: 6,\n border: `1px dashed ${theme.border}`,\n background: \"transparent\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 11,\n fontWeight: 600,\n }}\n >\n + Add dependency\n </button>\n </div>\n\n <div>\n <label style={labelStyle}>DAG ID (optional)</label>\n <input\n style={inputStyle}\n placeholder=\"my-pipeline\"\n value={form.dag_id}\n onChange={(e) => set(\"dag_id\", e.target.value)}\n />\n <div style={{ fontSize: 10, color: theme.textDim, marginTop: 4 }}>\n Group tasks into a named workflow\n </div>\n </div>\n\n <div>\n <label style={labelStyle}>Agent</label>\n <select\n style={inputStyle}\n value={form.agent}\n onChange={(e) => set(\"agent\", e.target.value)}\n >\n <option value=\"claude\">Claude Code (claude CLI)</option>\n <option value=\"codex\">Codex CLI (openai/codex)</option>\n </select>\n </div>\n </div>\n\n <div style={{ display: \"flex\", gap: 10, marginTop: 28, justifyContent: \"flex-end\" }}>\n <button\n onClick={onClose}\n style={{\n padding: \"10px 20px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: \"transparent\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n }}\n >\n Cancel\n </button>\n <button\n onClick={handleSubmit}\n style={{\n padding: \"10px 24px\",\n borderRadius: 8,\n border: \"none\",\n background: theme.accent,\n color: \"#fff\",\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n boxShadow: `0 0 20px ${theme.accentGlow}`,\n }}\n >\n {mode === \"edit\" ? \"Save Changes\" : mode === \"fork\" ? \"Create Fork\" : \"Create Task\"}\n </button>\n </div>\n </div>\n </div>\n );\n}\n\nfunction DetailPanel({ task, onClose, onResume }: any) {\n // `task` is always truthy here — the only caller renders this inside\n // `{detail && <DetailPanel task={... || detail} />}`. Hooks must stay\n // unconditional, so do not early-return before them.\n const [liveOutput, setLiveOutput] = useState(\"\");\n const [resumeText, setResumeText] = useState(\"\");\n const [resumeError, setResumeError] = useState(\"\");\n const [resumeSent, setResumeSent] = useState(false);\n const [messages, setMessages] = useState<any[]>([]);\n const [events, setEvents] = useState<any[]>([]);\n const [showMessages, setShowMessages] = useState(false);\n const [showEvents, setShowEvents] = useState(false);\n const [showLiveOutput, setShowLiveOutput] = useState(true);\n const liveOutputRef = useRef<any>(null);\n const messagesRef = useRef<any>(null);\n const eventsRef = useRef<any>(null);\n\n useEffect(() => {\n if (task.status !== \"running\") {\n setLiveOutput(\"\");\n return;\n }\n let cancelled = false;\n let lastOutputLength = 0;\n const poll = async () => {\n try {\n const res = await fetch(`${API}/tasks/${task.id}/output`);\n if (res.ok && !cancelled) {\n const data = await res.json();\n const currentOutput = data.output || \"\";\n // 增量更新:只添加新内容\n if (currentOutput.length > lastOutputLength) {\n const newContent = currentOutput.slice(lastOutputLength);\n setLiveOutput((prev) => prev + newContent);\n lastOutputLength = currentOutput.length;\n }\n }\n } catch {}\n };\n poll();\n const interval = setInterval(poll, 1000); // 缩短轮询间隔到1秒\n return () => {\n cancelled = true;\n clearInterval(interval);\n };\n }, [task.id, task.status]);\n\n useEffect(() => {\n if (liveOutputRef.current) {\n liveOutputRef.current.scrollTop = liveOutputRef.current.scrollHeight;\n }\n }, [liveOutput]);\n\n useEffect(() => {\n if (showMessages) {\n fetchTaskMessages(task.id).then(setMessages);\n }\n }, [task.id, showMessages]);\n\n useEffect(() => {\n if (!showEvents) return;\n let cancelled = false;\n const load = async () => {\n const nextEvents = await fetchTaskEvents(task.id);\n if (!cancelled) setEvents(nextEvents);\n };\n load();\n if (task.status !== \"running\") {\n return () => {\n cancelled = true;\n };\n }\n const interval = setInterval(load, 1000);\n return () => {\n cancelled = true;\n clearInterval(interval);\n };\n }, [task.id, task.status, showEvents]);\n\n useEffect(() => {\n if (messagesRef.current) {\n messagesRef.current.scrollTop = messagesRef.current.scrollHeight;\n }\n }, [messages]);\n\n const handleResume = async () => {\n if (!resumeText.trim()) return;\n setResumeError(\"\");\n const result = await resumeTask(task.id, resumeText.trim());\n if (result.error) {\n setResumeError(result.error);\n } else {\n setResumeText(\"\");\n setResumeSent(true);\n setTimeout(() => setResumeSent(false), 3000);\n onResume();\n }\n };\n\n return (\n <div\n style={{\n position: \"fixed\",\n right: 0,\n top: 0,\n bottom: 0,\n width: 480,\n background: theme.surface,\n borderLeft: `1px solid ${theme.border}`,\n zIndex: 999,\n overflow: \"auto\",\n padding: 28,\n boxShadow: \"-8px 0 40px rgba(0,0,0,0.4)\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n marginBottom: 24,\n }}\n >\n <Badge status={task.status} />\n <button\n onClick={onClose}\n style={{\n background: \"transparent\",\n border: \"none\",\n color: theme.textMuted,\n fontSize: 20,\n cursor: \"pointer\",\n }}\n >\n ×\n </button>\n </div>\n\n <h2\n style={{\n fontSize: 18,\n fontWeight: 700,\n color: theme.text,\n margin: \"0 0 8px\",\n fontFamily: \"'JetBrains Mono', monospace\",\n }}\n >\n {task.title}\n </h2>\n\n <div\n style={{ fontSize: 11, color: theme.textDim, marginBottom: 24, fontFamily: \"monospace\" }}\n >\n ID: {task.id} · Created: {formatTaskDateTime(task.created_at)}\n </div>\n\n <Section title=\"Prompt\">\n <pre\n style={{\n background: theme.bg,\n border: `1px solid ${theme.border}`,\n borderRadius: 8,\n padding: 14,\n fontSize: 12,\n color: theme.text,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n margin: 0,\n fontFamily: \"'JetBrains Mono', monospace\",\n lineHeight: 1.6,\n }}\n >\n {task.prompt}\n </pre>\n {task.prompt_images && task.prompt_images.length > 0 && (\n <div style={{ marginTop: 12 }}>\n <div\n style={{\n fontSize: 10,\n color: theme.textMuted,\n fontWeight: 600,\n letterSpacing: 0.8,\n textTransform: \"uppercase\",\n marginBottom: 8,\n }}\n >\n Attached Images ({task.prompt_images.length})\n </div>\n <div style={{ display: \"flex\", flexWrap: \"wrap\", gap: 8 }}>\n {task.prompt_images.map((img, i) => (\n <img\n key={i}\n src={`data:${img.media_type};base64,${img.data}`}\n alt={img.name || `image ${i + 1}`}\n style={{\n width: 80,\n height: 80,\n objectFit: \"cover\",\n borderRadius: 6,\n border: `1px solid ${theme.border}`,\n }}\n />\n ))}\n </div>\n </div>\n )}\n </Section>\n\n <Section title=\"Configuration\">\n <InfoRow label=\"Working Dir\" value={task.working_dir} />\n <InfoRow label=\"Agent\" value={task.agent || DEFAULT_AGENT} />\n <InfoRow label=\"Schedule\" value={task.schedule_type} />\n {task.cron_expr && <InfoRow label=\"Cron\" value={task.cron_expr} />}\n {task.delay_seconds && <InfoRow label=\"Delay\" value={`${task.delay_seconds}s`} />}\n {task.next_run_at && (\n <InfoRow label=\"Next Run\" value={formatTaskDateTime(task.next_run_at)} />\n )}\n <InfoRow\n label=\"Runs\"\n value={`${task.run_count}${task.max_runs ? ` / ${task.max_runs}` : \"\"}`}\n />\n {task.dag_id && <InfoRow label=\"DAG\" value={task.dag_id} />}\n </Section>\n\n {/* DAG dependency info */}\n {task.dependencies && task.dependencies.length > 0 && (\n <Section title=\"Upstream Dependencies\">\n {task.dependencies.map((dep) => (\n <div\n key={dep.id}\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n padding: \"5px 0\",\n borderBottom: `1px solid ${theme.border}`,\n fontSize: 12,\n }}\n >\n <span style={{ color: theme.text, fontFamily: \"monospace\" }}>\n #{dep.depends_on_task_id}\n {dep.depends_on_title ? ` — ${dep.depends_on_title}` : \"\"}\n </span>\n <div style={{ display: \"flex\", gap: 8, alignItems: \"center\" }}>\n {dep.inject_result ? (\n <span style={{ fontSize: 10, color: theme.accent }}>↳ inject</span>\n ) : null}\n <span\n style={{\n fontSize: 10,\n fontWeight: 600,\n color:\n dep.depends_on_status === \"completed\"\n ? theme.green\n : dep.depends_on_status === \"failed\"\n ? theme.red\n : theme.orange,\n }}\n >\n {dep.depends_on_status}\n </span>\n </div>\n </div>\n ))}\n </Section>\n )}\n\n {task.dependents && task.dependents.length > 0 && (\n <Section title=\"Downstream Tasks\">\n <div style={{ fontSize: 12, color: theme.textMuted, fontFamily: \"monospace\" }}>\n {task.dependents.map((id) => `#${id}`).join(\", \")}\n </div>\n </Section>\n )}\n\n {task.status === \"running\" && (\n <Section\n title={\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8 }}>\n <span>Live Output</span>\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n fontSize: 10,\n color: theme.blue,\n }}\n >\n <span\n style={{\n width: 6,\n height: 6,\n borderRadius: \"50%\",\n background: theme.blue,\n animation: \"pulse 1.2s ease-in-out infinite\",\n }}\n />\n live\n </div>\n </div>\n }\n >\n <div\n style={{\n background: theme.bg,\n border: `1px solid ${theme.borderActive}`,\n borderRadius: 8,\n overflow: \"hidden\",\n }}\n >\n {/* 工具栏 */}\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n padding: \"8px 12px\",\n background: theme.surface,\n borderBottom: `1px solid ${theme.border}`,\n fontSize: 11,\n color: theme.textMuted,\n }}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 12 }}>\n <button\n onClick={() => setShowLiveOutput(!showLiveOutput)}\n style={{\n background: \"transparent\",\n border: \"none\",\n color: theme.textMuted,\n fontSize: 11,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n gap: 4,\n }}\n >\n {showLiveOutput ? \"▼\" : \"▶\"} {showLiveOutput ? \"Hide\" : \"Show\"}\n </button>\n <span style={{ fontFamily: \"monospace\" }}>\n {liveOutput.length.toLocaleString()} chars\n </span>\n </div>\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8 }}>\n <button\n onClick={() => {\n navigator.clipboard.writeText(liveOutput);\n }}\n style={{\n background: \"transparent\",\n border: \"none\",\n color: theme.textMuted,\n fontSize: 11,\n cursor: \"pointer\",\n padding: \"4px 8px\",\n borderRadius: 4,\n fontFamily: \"'JetBrains Mono', monospace\",\n }}\n >\n 📋 Copy\n </button>\n <button\n onClick={() => setLiveOutput(\"\")}\n style={{\n background: \"transparent\",\n border: \"none\",\n color: theme.textMuted,\n fontSize: 11,\n cursor: \"pointer\",\n padding: \"4px 8px\",\n borderRadius: 4,\n fontFamily: \"'JetBrains Mono', monospace\",\n }}\n >\n 🗑️ Clear\n </button>\n </div>\n </div>\n\n {/* 输出内容区域 */}\n {showLiveOutput && (\n <div\n style={{\n maxHeight: 400,\n overflow: \"auto\",\n position: \"relative\",\n }}\n ref={liveOutputRef}\n >\n <pre\n style={{\n fontSize: 12,\n color: theme.text,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n margin: 0,\n padding: 14,\n fontFamily: \"'JetBrains Mono', monospace\",\n lineHeight: 1.6,\n minHeight: 60,\n }}\n >\n {liveOutput ? (\n <FormattedOutput content={liveOutput} theme={theme} />\n ) : (\n <span style={{ color: theme.textDim, fontStyle: \"italic\" }}>\n Waiting for agent output...\n </span>\n )}\n </pre>\n </div>\n )}\n </div>\n </Section>\n )}\n\n {task.result && (\n <Section title=\"Result\">\n <pre\n style={{\n background: theme.bg,\n border: `1px solid ${theme.border}`,\n borderRadius: 8,\n padding: 14,\n fontSize: 12,\n color: theme.green,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n margin: 0,\n fontFamily: \"'JetBrains Mono', monospace\",\n lineHeight: 1.6,\n maxHeight: 300,\n overflow: \"auto\",\n }}\n >\n {task.result}\n </pre>\n </Section>\n )}\n\n {task.error && (\n <Section title=\"Error\">\n <pre\n style={{\n background: theme.redBg,\n border: `1px solid rgba(248,113,113,0.2)`,\n borderRadius: 8,\n padding: 14,\n fontSize: 12,\n color: theme.red,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n margin: 0,\n fontFamily: \"'JetBrains Mono', monospace\",\n lineHeight: 1.6,\n }}\n >\n {task.error}\n </pre>\n </Section>\n )}\n\n {/* Output History Tabs */}\n <div style={{ marginBottom: 20 }}>\n <div style={{ display: \"flex\", gap: 8, marginBottom: 12 }}>\n <button\n onClick={() => {\n setShowMessages(!showMessages);\n setShowEvents(false);\n }}\n style={{\n flex: 1,\n padding: \"8px 12px\",\n borderRadius: 8,\n background: showMessages ? theme.accentGlow : theme.surface,\n color: showMessages ? theme.accent : theme.textMuted,\n fontSize: 11,\n fontWeight: 600,\n cursor: \"pointer\",\n border: `1px solid ${showMessages ? theme.accent : theme.border}`,\n transition: \"all 0.15s\",\n }}\n >\n Conversation\n </button>\n <button\n onClick={() => {\n setShowEvents(!showEvents);\n setShowMessages(false);\n }}\n style={{\n flex: 1,\n padding: \"8px 12px\",\n borderRadius: 8,\n background: showEvents ? theme.accentGlow : theme.surface,\n color: showEvents ? theme.accent : theme.textMuted,\n fontSize: 11,\n fontWeight: 600,\n cursor: \"pointer\",\n border: `1px solid ${showEvents ? theme.accent : theme.border}`,\n transition: \"all 0.15s\",\n }}\n >\n Execution Events\n </button>\n </div>\n\n {/* Conversation History */}\n {showMessages && (\n <div\n ref={messagesRef}\n style={{\n maxHeight: 400,\n overflow: \"auto\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: 8,\n }}\n >\n {messages.length === 0 ? (\n <div\n style={{\n fontSize: 12,\n color: theme.textDim,\n padding: \"12px 0\",\n textAlign: \"center\",\n }}\n >\n No conversation data — only tasks run after this feature was added have logs.\n </div>\n ) : (\n messages.map((msg, i) => (\n <div\n key={i}\n style={{\n background: msg.role === \"user\" ? theme.accentGlow : theme.bg,\n border: `1px solid ${msg.role === \"user\" ? theme.accent + \"33\" : theme.border}`,\n borderRadius: 8,\n padding: \"10px 14px\",\n borderLeft: `3px solid ${msg.role === \"user\" ? theme.accent : theme.green}`,\n }}\n >\n <div\n style={{\n fontSize: 10,\n fontWeight: 700,\n letterSpacing: 0.8,\n color: msg.role === \"user\" ? theme.accent : theme.green,\n textTransform: \"uppercase\",\n marginBottom: 6,\n }}\n >\n {msg.role}\n </div>\n <pre\n style={{\n fontSize: 12,\n color: theme.text,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n margin: 0,\n fontFamily: \"'JetBrains Mono', monospace\",\n lineHeight: 1.6,\n maxHeight: 200,\n overflow: \"auto\",\n }}\n >\n {msg.text}\n </pre>\n </div>\n ))\n )}\n </div>\n )}\n\n {/* Execution Events History */}\n {showEvents && (\n <div ref={eventsRef} style={{ maxHeight: 520, overflow: \"auto\" }}>\n <ExecutionTimeline events={events} />\n </div>\n )}\n </div>\n\n {/* Resume completed/failed session */}\n {[\"completed\", \"failed\"].includes(task.status) && task.session_id && (\n <Section title=\"Resume Session\">\n <div\n style={{\n fontSize: 11,\n color: theme.textDim,\n marginBottom: 10,\n fontFamily: \"monospace\",\n }}\n >\n Session: {task.session_id}\n </div>\n <textarea\n placeholder=\"Send a follow-up message to continue this conversation…\"\n value={resumeText}\n onChange={(e) => setResumeText(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && (e.metaKey || e.ctrlKey)) handleResume();\n }}\n style={{\n width: \"100%\",\n padding: \"10px 14px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n color: theme.text,\n fontSize: 13,\n outline: \"none\",\n boxSizing: \"border-box\",\n fontFamily: \"'JetBrains Mono', 'SF Mono', monospace\",\n resize: \"vertical\",\n minHeight: 80,\n }}\n />\n {resumeError && (\n <div style={{ fontSize: 11, color: theme.red, marginTop: 6 }}>{resumeError}</div>\n )}\n {resumeSent && (\n <div style={{ fontSize: 12, color: theme.green, marginTop: 6 }}>\n ✨ 已发送!任务正在重新唤醒,请稍候~\n </div>\n )}\n <button\n onClick={handleResume}\n style={{\n marginTop: 10,\n padding: \"8px 20px\",\n borderRadius: 8,\n border: \"none\",\n background: theme.accent,\n color: \"#fff\",\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n boxShadow: `0 0 20px ${theme.accentGlow}`,\n }}\n >\n ↩ Resume (⌘↵)\n </button>\n </Section>\n )}\n </div>\n );\n}\n\nfunction Section({ title, children }) {\n return (\n <div style={{ marginBottom: 20 }}>\n <div\n style={{\n fontSize: 10,\n fontWeight: 700,\n color: theme.textDim,\n letterSpacing: 1.2,\n textTransform: \"uppercase\",\n marginBottom: 10,\n }}\n >\n {title}\n </div>\n {children}\n </div>\n );\n}\n\nfunction InfoRow({ label, value }) {\n return (\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n padding: \"6px 0\",\n borderBottom: `1px solid ${theme.border}`,\n fontSize: 12,\n }}\n >\n <span style={{ color: theme.textMuted }}>{label}</span>\n <span style={{ color: theme.text, fontFamily: \"monospace\" }}>{value}</span>\n </div>\n );\n}\n\nfunction SettingsModal({\n onClose,\n timeout: initialTimeout,\n defaultAgent: initialDefaultAgent,\n onSave,\n feishu: initialFeishu,\n onFeishuSave,\n channelsStatus: initialChannelsStatus,\n onChannelsSave,\n}) {\n const [tab, setTab] = useState(\"general\");\n const [timeout, setTimeout] = useState(initialTimeout ?? DEFAULT_TIMEOUT_SECONDS);\n const [defaultAgent, setDefaultAgent] = useState(initialDefaultAgent ?? DEFAULT_AGENT);\n const [skillEnabled, setSkillEnabled] = useState(false);\n const [skillSweepAgent, setSkillSweepAgent] = useState(DEFAULT_AGENT);\n const [skillSweepCron, setSkillSweepCron] = useState(\"0 3 * * *\");\n const [feishu, setFeishu] = useState({\n feishu_app_id: \"\",\n feishu_app_secret: \"\",\n feishu_default_chat_id: \"\",\n feishu_default_working_dir: \"~\",\n feishu_enabled: \"false\",\n ...initialFeishu,\n });\n const [feishuSaving, setFeishuSaving] = useState(false);\n const [feishuMsg, setFeishuMsg] = useState<any>(null); // {ok, text}\n const [channels, setChannels] = useState(createInitialChannelsState(initialChannelsStatus));\n const [channelsSaving, setChannelsSaving] = useState(false);\n const [channelsMsg, setChannelsMsg] = useState<any>(null);\n const [weixinQrSrc, setWeixinQrSrc] = useState(\"\");\n const [weixinActionBusy, setWeixinActionBusy] = useState(false);\n const [collapsedChannels, setCollapsedChannels] = useState({\n telegram: true,\n slack: true,\n weixin: true,\n });\n\n // Refresh all channel settings when the modal opens so bot-side /dir changes are visible\n useEffect(() => {\n let cancelled = false;\n const refreshChannels = async (preserveUserEdits = true) => {\n const status = await fetchChannelsStatus();\n if (!cancelled) {\n setChannels((c) => {\n const merged = mergeChannelsStatus(c, status);\n if (!preserveUserEdits) return merged;\n // During background polling, keep user-edited config fields untouched\n // so toggling enabled / editing URLs isn't overwritten before Save.\n return {\n telegram: { ...merged.telegram, enabled: c.telegram.enabled },\n slack: { ...merged.slack, enabled: c.slack.enabled },\n weixin: { ...merged.weixin, enabled: c.weixin.enabled },\n };\n });\n }\n };\n refreshChannels(false); // initial load: full merge to populate fields\n const intervalId = setInterval(refreshChannels, 2000); // polling: preserve edits\n fetchFeishuSettings().then((s) => {\n if (s && Object.keys(s).length) setFeishu((f) => ({ ...f, ...s }));\n });\n fetchSettings().then((s) => {\n if (s && typeof s === \"object\") {\n if (typeof s.skill_library_enabled === \"boolean\") setSkillEnabled(s.skill_library_enabled);\n if (s.skill_sweep_agent) setSkillSweepAgent(s.skill_sweep_agent);\n if (s.skill_sweep_cron) setSkillSweepCron(s.skill_sweep_cron);\n }\n });\n return () => {\n cancelled = true;\n clearInterval(intervalId);\n };\n }, []);\n\n useEffect(() => {\n let cancelled = false;\n const qrValue = channels.weixin?.qr_code_url || \"\";\n if (!qrValue) {\n setWeixinQrSrc(\"\");\n return () => {\n cancelled = true;\n };\n }\n\n if (isWeixinQrImageSource(qrValue)) {\n setWeixinQrSrc(qrValue);\n return () => {\n cancelled = true;\n };\n }\n\n QRCode.toDataURL(qrValue, {\n errorCorrectionLevel: \"M\",\n margin: 2,\n width: 440,\n })\n .then((dataUrl) => {\n if (!cancelled) setWeixinQrSrc(dataUrl);\n })\n .catch((error) => {\n console.error(\"Failed to generate Weixin QR code\", error);\n if (!cancelled) setWeixinQrSrc(\"\");\n });\n\n return () => {\n cancelled = true;\n };\n }, [channels.weixin?.qr_code_url]);\n\n const handleWeixinAction = async (action) => {\n setWeixinActionBusy(true);\n setChannelsMsg(null);\n try {\n await runWeixinAction(action);\n const updated = await fetchChannelsStatus();\n setChannels((c) => mergeChannelsStatus(c, updated));\n if (onChannelsSave) onChannelsSave(updated);\n setChannelsMsg({\n ok: true,\n text: action === \"logout\" ? \"Wechat logged out.\" : \"Wechat login restarted.\",\n });\n } catch (e) {\n setChannelsMsg({ ok: false, text: String(e) });\n } finally {\n setWeixinActionBusy(false);\n }\n };\n\n const handleSaveGeneral = async () => {\n await updateSettings({\n timeout: parseInt(timeout) || DEFAULT_TIMEOUT_SECONDS,\n default_agent: defaultAgent,\n skill_library_enabled: skillEnabled ? \"1\" : \"0\",\n skill_sweep_agent: skillSweepAgent,\n skill_sweep_cron: skillSweepCron,\n });\n onSave(parseInt(timeout) || DEFAULT_TIMEOUT_SECONDS, defaultAgent);\n onClose();\n };\n\n const handleSaveFeishu = async () => {\n setFeishuSaving(true);\n setFeishuMsg(null);\n try {\n await updateFeishuSettings(feishu);\n setFeishuMsg({ ok: true, text: \"Saved. Bridge restarted.\" });\n // Reload settings after save\n if (onFeishuSave) {\n const updated = await fetchFeishuSettings();\n onFeishuSave(updated);\n }\n } catch (e) {\n setFeishuMsg({ ok: false, text: String(e) });\n } finally {\n setFeishuSaving(false);\n }\n };\n\n const handleSaveChannels = async () => {\n setChannelsSaving(true);\n setChannelsMsg(null);\n try {\n await updateChannelsSettings(buildChannelsSavePayload(channels));\n // Reload channel status after save to reflect new running state\n const updated = await fetchChannelsStatus();\n setChannels((c) => mergeChannelsStatus(c, updated));\n if (onChannelsSave) onChannelsSave(updated);\n setChannelsMsg({ ok: true, text: \"Saved. Channels restarted.\" });\n } catch (e) {\n setChannelsMsg({ ok: false, text: String(e) });\n } finally {\n setChannelsSaving(false);\n }\n };\n\n const fieldStyle: CSSProperties = {\n width: \"100%\",\n padding: \"10px 14px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n color: theme.text,\n fontSize: 13,\n outline: \"none\",\n boxSizing: \"border-box\",\n fontFamily: \"'JetBrains Mono', 'SF Mono', monospace\",\n };\n const labelStyle = {\n fontSize: 11,\n fontWeight: 600,\n color: theme.textMuted,\n letterSpacing: 0.8,\n textTransform: \"uppercase\",\n marginBottom: 8,\n display: \"block\",\n };\n const hintStyle = { fontSize: 10, color: theme.textDim, marginTop: 4 };\n\n const tabs = [\"general\", \"channels\", \"feishu\"];\n const tabLabel = { general: \"General\", channels: \"Channels\", feishu: \"Feishu / Lark\" };\n\n return (\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n background: \"rgba(0,0,0,0.7)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex: 1000,\n backdropFilter: \"blur(8px)\",\n }}\n onClick={onClose}\n >\n <div\n onClick={(e) => e.stopPropagation()}\n style={{\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 16,\n padding: 32,\n width: 480,\n maxHeight: \"85vh\",\n overflowY: \"auto\",\n boxShadow: \"0 24px 80px rgba(0,0,0,0.5)\",\n }}\n >\n <h2\n style={{\n margin: \"0 0 20px\",\n fontSize: 18,\n fontWeight: 700,\n color: theme.text,\n fontFamily: \"'JetBrains Mono', monospace\",\n }}\n >\n Settings\n </h2>\n\n {/* Tab bar */}\n <div\n style={{\n display: \"flex\",\n gap: 4,\n marginBottom: 24,\n borderBottom: `1px solid ${theme.border}`,\n paddingBottom: 0,\n }}\n >\n {tabs.map((t) => (\n <button\n key={t}\n onClick={() => setTab(t)}\n style={{\n padding: \"7px 16px\",\n borderRadius: \"8px 8px 0 0\",\n border: \"none\",\n cursor: \"pointer\",\n fontSize: 12,\n fontWeight: 600,\n background: tab === t ? theme.bg : \"transparent\",\n color: tab === t ? theme.text : theme.textMuted,\n borderBottom: tab === t ? `2px solid ${theme.accent}` : \"2px solid transparent\",\n marginBottom: -1,\n }}\n >\n {tabLabel[t]}\n </button>\n ))}\n </div>\n\n {/* ── General tab ── */}\n {tab === \"general\" && (\n <>\n <div style={{ marginBottom: 20 }}>\n <label style={labelStyle}>Task Timeout (seconds)</label>\n <input\n type=\"number\"\n min=\"10\"\n step=\"10\"\n value={timeout}\n onChange={(e) => setTimeout(e.target.value)}\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Default: 12000s (200 min). Max time before a running task is killed.\n </div>\n </div>\n <div style={{ marginBottom: 20 }}>\n <label style={labelStyle}>Default Agent</label>\n <select\n value={defaultAgent}\n onChange={(e) => setDefaultAgent(e.target.value)}\n style={fieldStyle}\n >\n <option value=\"claude\">Claude Code (claude CLI)</option>\n <option value=\"codex\">Codex CLI (openai/codex)</option>\n </select>\n <div style={hintStyle}>Agent used for new tasks unless overridden per-task.</div>\n </div>\n\n {/* ── Skill Library ── */}\n <div\n style={{\n marginBottom: 20,\n paddingTop: 16,\n borderTop: `1px solid ${theme.border}`,\n }}\n >\n <label\n style={{\n ...labelStyle,\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n cursor: \"pointer\",\n }}\n >\n <input\n type=\"checkbox\"\n checked={skillEnabled}\n onChange={(e) => setSkillEnabled(e.target.checked)}\n style={{ width: 16, height: 16, cursor: \"pointer\" }}\n />\n Skill Library 自动扫描\n </label>\n <div style={hintStyle}>\n 定时让 agent 扫描已完成任务、检测复发模式(消耗 token,默认关闭)。\n 手动「扫一遍」按钮不受此开关影响。\n </div>\n </div>\n {skillEnabled && (\n <>\n <div style={{ marginBottom: 20 }}>\n <label style={labelStyle}>扫描 Agent</label>\n <select\n value={skillSweepAgent}\n onChange={(e) => setSkillSweepAgent(e.target.value)}\n style={fieldStyle}\n >\n <option value=\"claude\">Claude Code (claude CLI)</option>\n <option value=\"codex\">Codex CLI (openai/codex)</option>\n </select>\n <div style={hintStyle}>运行 sweep 的 agent。</div>\n </div>\n <div style={{ marginBottom: 20 }}>\n <label style={labelStyle}>扫描节奏 (cron)</label>\n <input\n value={skillSweepCron}\n onChange={(e) => setSkillSweepCron(e.target.value)}\n placeholder=\"0 3 * * *\"\n style={{ ...fieldStyle, fontFamily: \"monospace\" }}\n />\n <div style={hintStyle}>默认每日凌晨 3 点。增量扫描,只看上次以来的新任务。</div>\n </div>\n </>\n )}\n\n <div style={{ display: \"flex\", gap: 10, justifyContent: \"flex-end\" }}>\n <button\n onClick={onClose}\n style={{\n padding: \"10px 20px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: \"transparent\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n }}\n >\n Cancel\n </button>\n <button\n onClick={handleSaveGeneral}\n style={{\n padding: \"10px 24px\",\n borderRadius: 8,\n border: \"none\",\n background: theme.accent,\n color: \"#fff\",\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n boxShadow: `0 0 20px ${theme.accentGlow}`,\n }}\n >\n Save\n </button>\n </div>\n </>\n )}\n\n {/* ── Channels tab ── */}\n {tab === \"channels\" && (\n <>\n {/* ── Telegram ── */}\n {(() => {\n const ch = channels.telegram;\n const collapsed = collapsedChannels.telegram;\n const statusDot = ch.running\n ? { bg: theme.green, label: \"Connected\" }\n : ch.configured\n ? { bg: theme.yellow || \"#f59e0b\", label: \"Configured (not running)\" }\n : { bg: theme.textDim, label: \"Not configured\" };\n return (\n <div\n style={{\n marginBottom: 16,\n borderRadius: 10,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n overflow: \"hidden\",\n }}\n >\n {/* Header row - clickable to collapse */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n padding: \"12px 16px\",\n cursor: \"pointer\",\n userSelect: \"none\",\n }}\n onClick={() => setCollapsedChannels((c) => ({ ...c, telegram: !c.telegram }))}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 10 }}>\n <span\n style={{\n fontSize: 10,\n color: theme.textMuted,\n transition: \"transform 0.2s\",\n transform: collapsed ? \"rotate(-90deg)\" : \"rotate(0deg)\",\n display: \"inline-block\",\n }}\n >\n {\"▼\"}\n </span>\n <span\n style={{\n display: \"inline-flex\",\n width: 22,\n height: 22,\n alignItems: \"center\",\n justifyContent: \"center\",\n color: \"#2AABEE\",\n flexShrink: 0,\n }}\n >\n <svg\n viewBox=\"0 0 24 24\"\n width=\"22\"\n height=\"22\"\n aria-hidden=\"true\"\n fill=\"currentColor\"\n >\n <path d=\"M21.4 4.6a1.2 1.2 0 0 0-1.24-.2L3.8 11.15c-.6.25-.57 1.12.05 1.33l4.6 1.62 1.62 4.6c.22.62 1.08.65 1.33.05l6.75-16.36a1.2 1.2 0 0 0-.2-1.24 1.18 1.18 0 0 0-1.22-.3Z\" />\n </svg>\n </span>\n <span style={{ fontWeight: 700, fontSize: 14, color: theme.text }}>\n Telegram\n </span>\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 6, marginLeft: 8 }}>\n <span\n style={{\n width: 8,\n height: 8,\n borderRadius: \"50%\",\n background: statusDot.bg,\n display: \"inline-block\",\n boxShadow: ch.running ? `0 0 6px ${statusDot.bg}` : \"none\",\n }}\n />\n <span style={{ fontSize: 11, color: theme.textMuted }}>\n {statusDot.label}\n </span>\n </div>\n </div>\n <button\n onClick={(e) => {\n e.stopPropagation();\n setChannels((c) => ({\n ...c,\n telegram: { ...c.telegram, enabled: !c.telegram.enabled },\n }));\n }}\n style={{\n width: 44,\n height: 24,\n borderRadius: 12,\n border: \"none\",\n cursor: \"pointer\",\n background: ch.enabled ? theme.accent : theme.border,\n position: \"relative\",\n transition: \"background 0.2s\",\n flexShrink: 0,\n }}\n >\n <span\n style={{\n position: \"absolute\",\n top: 3,\n width: 18,\n height: 18,\n borderRadius: \"50%\",\n background: \"#fff\",\n transition: \"left 0.2s\",\n left: ch.enabled ? 23 : 3,\n }}\n />\n </button>\n </div>\n\n {/* Collapsible body */}\n {!collapsed && (\n <div style={{ padding: \"0 16px 16px\" }}>\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Bot Token</label>\n <input\n type=\"password\"\n value={ch.bot_token}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n telegram: { ...c.telegram, bot_token: e.target.value },\n }))\n }\n placeholder=\"123456:ABC-DEF...\"\n style={fieldStyle}\n />\n <div style={hintStyle}>Token from @BotFather</div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Allowed User IDs</label>\n <input\n value={ch.allowed_users}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n telegram: { ...c.telegram, allowed_users: e.target.value },\n }))\n }\n placeholder=\"123456789,987654321 (optional)\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Comma-separated numeric Telegram user IDs. Leave empty to allow all.\n </div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Default Working Directory</label>\n <input\n value={ch.default_working_dir}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n telegram: { ...c.telegram, default_working_dir: e.target.value },\n }))\n }\n placeholder=\"~/my-project\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Working directory for tasks created via the Telegram bot.\n </div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Default Notification Chat ID</label>\n <input\n value={ch.default_chat_id}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n telegram: { ...c.telegram, default_chat_id: e.target.value },\n }))\n }\n placeholder=\"-1001234567890 or 123456789\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Fallback chat for notifications from UI-created tasks (group or user chat\n ID).\n </div>\n </div>\n\n <div\n style={{\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 6,\n padding: \"10px 12px\",\n fontSize: 11,\n fontFamily: \"monospace\",\n color: theme.textMuted,\n lineHeight: 1.8,\n }}\n >\n <div style={{ color: theme.textDim, marginBottom: 4 }}>Bot commands:</div>\n {[\n \"/newtask <title> | <prompt>\",\n \"/list\",\n \"/status <id>\",\n \"/cancel <id>\",\n ].map((cmd) => (\n <div key={cmd}>\n <span style={{ color: theme.cyan }}>{cmd}</span>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n );\n })()}\n\n {/* ── Slack ── */}\n {(() => {\n const ch = channels.slack;\n const collapsed = collapsedChannels.slack;\n const statusDot = ch.running\n ? { bg: theme.green, label: \"Connected\" }\n : ch.configured\n ? { bg: theme.yellow || \"#f59e0b\", label: \"Configured (not running)\" }\n : { bg: theme.textDim, label: \"Not configured\" };\n return (\n <div\n style={{\n marginBottom: 16,\n borderRadius: 10,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n overflow: \"hidden\",\n }}\n >\n {/* Header row - clickable to collapse */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n padding: \"12px 16px\",\n cursor: \"pointer\",\n userSelect: \"none\",\n }}\n onClick={() => setCollapsedChannels((c) => ({ ...c, slack: !c.slack }))}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 10 }}>\n <span\n style={{\n fontSize: 10,\n color: theme.textMuted,\n transition: \"transform 0.2s\",\n transform: collapsed ? \"rotate(-90deg)\" : \"rotate(0deg)\",\n display: \"inline-block\",\n }}\n >\n {\"▼\"}\n </span>\n <span\n style={{\n display: \"inline-flex\",\n width: 22,\n height: 22,\n alignItems: \"center\",\n justifyContent: \"center\",\n flexShrink: 0,\n }}\n >\n <svg viewBox=\"0 0 24 24\" width=\"22\" height=\"22\" aria-hidden=\"true\">\n <path\n fill=\"#36C5F0\"\n d=\"M10.1 3.2A2.2 2.2 0 0 1 12.2 1h.7v5.1h-2.8V3.2Z\"\n />\n <path\n fill=\"#2EB67D\"\n d=\"M20.8 10.1A2.2 2.2 0 0 1 23 12.2v.7h-5.1v-2.8h2.9Z\"\n />\n <path\n fill=\"#ECB22E\"\n d=\"M13.9 20.8A2.2 2.2 0 0 1 11.8 23h-.7v-5.1h2.8v2.9Z\"\n />\n <path\n fill=\"#E01E5A\"\n d=\"M3.2 13.9A2.2 2.2 0 0 1 1 11.8v-.7h5.1v2.8H3.2Z\"\n />\n <path\n fill=\"#36C5F0\"\n d=\"M13.2 4.3a2.7 2.7 0 1 1 5.4 0 2.7 2.7 0 0 1-5.4 0Z\"\n />\n <path\n fill=\"#2EB67D\"\n d=\"M16.9 13.2a2.7 2.7 0 1 1 0 5.4 2.7 2.7 0 0 1 0-5.4Z\"\n />\n <path\n fill=\"#ECB22E\"\n d=\"M5.4 16.9a2.7 2.7 0 1 1 5.4 0 2.7 2.7 0 0 1-5.4 0Z\"\n />\n <path\n fill=\"#E01E5A\"\n d=\"M4.3 5.4a2.7 2.7 0 1 1 0 5.4 2.7 2.7 0 0 1 0-5.4Z\"\n />\n </svg>\n </span>\n <span style={{ fontWeight: 700, fontSize: 14, color: theme.text }}>\n Slack\n </span>\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 6, marginLeft: 8 }}>\n <span\n style={{\n width: 8,\n height: 8,\n borderRadius: \"50%\",\n background: statusDot.bg,\n display: \"inline-block\",\n boxShadow: ch.running ? `0 0 6px ${statusDot.bg}` : \"none\",\n }}\n />\n <span style={{ fontSize: 11, color: theme.textMuted }}>\n {statusDot.label}\n </span>\n </div>\n </div>\n <button\n onClick={(e) => {\n e.stopPropagation();\n setChannels((c) => ({\n ...c,\n slack: { ...c.slack, enabled: !c.slack.enabled },\n }));\n }}\n style={{\n width: 44,\n height: 24,\n borderRadius: 12,\n border: \"none\",\n cursor: \"pointer\",\n background: ch.enabled ? theme.accent : theme.border,\n position: \"relative\",\n transition: \"background 0.2s\",\n flexShrink: 0,\n }}\n >\n <span\n style={{\n position: \"absolute\",\n top: 3,\n width: 18,\n height: 18,\n borderRadius: \"50%\",\n background: \"#fff\",\n transition: \"left 0.2s\",\n left: ch.enabled ? 23 : 3,\n }}\n />\n </button>\n </div>\n\n {/* Collapsible body */}\n {!collapsed && (\n <div style={{ padding: \"0 16px 16px\" }}>\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Bot Token</label>\n <input\n type=\"password\"\n value={ch.bot_token}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n slack: { ...c.slack, bot_token: e.target.value },\n }))\n }\n placeholder=\"xoxb-...\"\n style={fieldStyle}\n />\n <div style={hintStyle}>Bot token from OAuth & Permissions</div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>App Token</label>\n <input\n type=\"password\"\n value={ch.app_token}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n slack: { ...c.slack, app_token: e.target.value },\n }))\n }\n placeholder=\"xapp-...\"\n style={fieldStyle}\n />\n <div style={hintStyle}>App-level token for Socket Mode</div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Default Working Directory</label>\n <input\n value={ch.default_working_dir}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n slack: { ...c.slack, default_working_dir: e.target.value },\n }))\n }\n placeholder=\"~/my-project\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Working directory for tasks created via the Slack bot.\n </div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Default DM User</label>\n <input\n value={ch.default_user}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n slack: { ...c.slack, default_user: e.target.value },\n }))\n }\n placeholder=\"U0123456789\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Slack user ID to DM when tasks have no origin thread (e.g. subtasks\n created via API). Find your ID in Slack profile → ⋯ → Copy member ID.\n </div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Default Notification Channel</label>\n <input\n value={ch.default_channel}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n slack: { ...c.slack, default_channel: e.target.value },\n }))\n }\n placeholder=\"#general or C0123456789\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Optional. Fallback channel if Default DM User is not set.\n </div>\n </div>\n\n <div\n style={{\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 6,\n padding: \"10px 12px\",\n fontSize: 11,\n fontFamily: \"monospace\",\n color: theme.textMuted,\n lineHeight: 1.8,\n }}\n >\n <div style={{ color: theme.textDim, marginBottom: 4 }}>Bot commands:</div>\n {[\n \"newtask <title> | <prompt>\",\n \"list\",\n \"status <id>\",\n \"cancel <id>\",\n \"help\",\n ].map((cmd) => (\n <div key={cmd}>\n <span style={{ color: theme.cyan }}>{cmd}</span>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n );\n })()}\n\n {/* ── Weixin ── */}\n {(() => {\n const ch = channels.weixin;\n const collapsed = collapsedChannels.weixin;\n const statusLabelMap = {\n idle: \"Idle\",\n waiting_for_scan: \"Waiting for scan\",\n scanned: \"Scanned on phone\",\n connected: \"Connected\",\n error: \"Error\",\n };\n const statusDot = ch.running\n ? { bg: theme.green, label: statusLabelMap[ch.login_status] || \"Connected\" }\n : ch.login_status === \"waiting_for_scan\" || ch.login_status === \"scanned\"\n ? { bg: theme.orange || \"#f59e0b\", label: statusLabelMap[ch.login_status] }\n : ch.login_status === \"error\"\n ? { bg: theme.red, label: \"Error\" }\n : ch.configured\n ? { bg: theme.yellow || \"#f59e0b\", label: \"Configured\" }\n : { bg: theme.textDim, label: \"Login required\" };\n return (\n <div\n style={{\n marginBottom: 16,\n borderRadius: 10,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n overflow: \"hidden\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n padding: \"12px 16px\",\n cursor: \"pointer\",\n userSelect: \"none\",\n }}\n onClick={() => setCollapsedChannels((c) => ({ ...c, weixin: !c.weixin }))}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 10 }}>\n <span\n style={{\n fontSize: 10,\n color: theme.textMuted,\n transition: \"transform 0.2s\",\n transform: collapsed ? \"rotate(-90deg)\" : \"rotate(0deg)\",\n display: \"inline-block\",\n }}\n >\n {\"▼\"}\n </span>\n <span\n style={{\n display: \"inline-flex\",\n width: 22,\n height: 22,\n alignItems: \"center\",\n justifyContent: \"center\",\n color: \"#07C160\",\n flexShrink: 0,\n }}\n >\n <svg\n viewBox=\"0 0 24 24\"\n width=\"22\"\n height=\"22\"\n aria-hidden=\"true\"\n fill=\"currentColor\"\n >\n <path d=\"M9.2 4.2c-4 0-7.2 2.6-7.2 5.9 0 1.9 1.1 3.6 2.9 4.7l-.9 2.5 2.9-1.5c.7.1 1.4.2 2.2.2 4 0 7.2-2.6 7.2-5.9S13.2 4.2 9.2 4.2Zm-2.7 4.8a.9.9 0 1 1 0-1.8.9.9 0 0 1 0 1.8Zm5.4 0a.9.9 0 1 1 0-1.8.9.9 0 0 1 0 1.8Z\" />\n <path\n d=\"M16.8 9.1c-3 0-5.5 2-5.5 4.5 0 2.5 2.4 4.5 5.5 4.5.6 0 1.2-.1 1.8-.2l2.4 1.2-.7-2c1.5-.8 2.5-2.1 2.5-3.6 0-2.5-2.4-4.4-5.5-4.4Zm-1.9 4a.7.7 0 1 1 0-1.4.7.7 0 0 1 0 1.4Zm3.8 0a.7.7 0 1 1 0-1.4.7.7 0 0 1 0 1.4Z\"\n opacity=\"0.88\"\n />\n </svg>\n </span>\n <span style={{ fontWeight: 700, fontSize: 14, color: theme.text }}>\n Wechat\n </span>\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 6, marginLeft: 8 }}>\n <span\n style={{\n width: 8,\n height: 8,\n borderRadius: \"50%\",\n background: statusDot.bg,\n display: \"inline-block\",\n boxShadow: ch.running ? `0 0 6px ${statusDot.bg}` : \"none\",\n }}\n />\n <span style={{ fontSize: 11, color: theme.textMuted }}>\n {statusDot.label}\n </span>\n </div>\n </div>\n <button\n onClick={(e) => {\n e.stopPropagation();\n setChannels((c) => ({\n ...c,\n weixin: { ...c.weixin, enabled: !c.weixin.enabled },\n }));\n }}\n style={{\n width: 44,\n height: 24,\n borderRadius: 12,\n border: \"none\",\n cursor: \"pointer\",\n background: ch.enabled ? theme.accent : theme.border,\n position: \"relative\",\n transition: \"background 0.2s\",\n flexShrink: 0,\n }}\n >\n <span\n style={{\n position: \"absolute\",\n top: 3,\n width: 18,\n height: 18,\n borderRadius: \"50%\",\n background: \"#fff\",\n transition: \"left 0.2s\",\n left: ch.enabled ? 23 : 3,\n }}\n />\n </button>\n </div>\n\n {!collapsed && (\n <div style={{ padding: \"0 16px 16px\" }}>\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Default Working Directory</label>\n <input\n value={ch.default_working_dir}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n weixin: { ...c.weixin, default_working_dir: e.target.value },\n }))\n }\n placeholder=\"~/my-project\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Working directory for tasks created from incoming Weixin messages.\n </div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Base URL</label>\n <input\n value={ch.base_url}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n weixin: { ...c.weixin, base_url: e.target.value },\n }))\n }\n placeholder=\"https://ilinkai.weixin.qq.com\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Gateway API base URL used for QR login, long-polling, and sendmessage.\n </div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Account ID</label>\n <input\n value={ch.account_id}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n weixin: { ...c.weixin, account_id: e.target.value },\n }))\n }\n placeholder=\"Optional fixed account id\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Optional. Leave empty to let the bridge adopt the account id returned by\n QR login.\n </div>\n </div>\n\n <div style={{ display: \"flex\", gap: 8, marginBottom: 12 }}>\n <button\n onClick={() => handleWeixinAction(\"reconnect\")}\n disabled={weixinActionBusy}\n style={{\n padding: \"9px 14px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: theme.surface,\n color: theme.text,\n cursor: weixinActionBusy ? \"not-allowed\" : \"pointer\",\n fontSize: 12,\n fontWeight: 600,\n opacity: weixinActionBusy ? 0.6 : 1,\n }}\n >\n Reconnect\n </button>\n <button\n onClick={() => handleWeixinAction(\"logout\")}\n disabled={weixinActionBusy}\n style={{\n padding: \"9px 14px\",\n borderRadius: 8,\n border: `1px solid ${theme.red}`,\n background: theme.redBg,\n color: theme.red,\n cursor: weixinActionBusy ? \"not-allowed\" : \"pointer\",\n fontSize: 12,\n fontWeight: 600,\n opacity: weixinActionBusy ? 0.6 : 1,\n }}\n >\n Logout\n </button>\n </div>\n\n {(ch.qr_code_url ||\n ch.login_status === \"waiting_for_scan\" ||\n ch.login_status === \"scanned\" ||\n ch.last_error) && (\n <div\n style={{\n marginBottom: 12,\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: theme.surface,\n padding: 12,\n }}\n >\n <div\n style={{\n fontSize: 12,\n fontWeight: 700,\n color: theme.text,\n marginBottom: 8,\n }}\n >\n Weixin Login Status\n </div>\n <div\n style={{\n fontSize: 11,\n color: theme.textMuted,\n marginBottom: ch.qr_code_url ? 10 : 0,\n }}\n >\n {statusLabelMap[ch.login_status] || \"Idle\"}\n {ch.user_id ? ` · ${ch.user_id}` : \"\"}\n </div>\n {ch.account_id && (\n <div style={{ fontSize: 11, color: theme.textMuted, marginBottom: 10 }}>\n Account ID: {ch.account_id}\n </div>\n )}\n {weixinQrSrc && (\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 8 }}>\n <img\n src={weixinQrSrc}\n alt=\"Weixin QR code\"\n style={{\n width: 220,\n height: 220,\n objectFit: \"contain\",\n borderRadius: 10,\n border: `1px solid ${theme.border}`,\n background: \"#fff\",\n }}\n />\n <div style={hintStyle}>\n Open Weixin on your phone and scan this QR code. The status updates\n automatically.\n </div>\n </div>\n )}\n {ch.last_error && (\n <div style={{ marginTop: 10, fontSize: 11, color: theme.red }}>\n {ch.last_error}\n </div>\n )}\n </div>\n )}\n\n <div\n style={{\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 6,\n padding: \"10px 12px\",\n fontSize: 11,\n fontFamily: \"monospace\",\n color: theme.textMuted,\n lineHeight: 1.8,\n }}\n >\n <div style={{ color: theme.textDim, marginBottom: 4 }}>Notes:</div>\n {[\n \"Enabling Weixin starts the local bridge process\",\n \"First launch without a saved session will trigger QR login\",\n \"Reply to a result message to resume the same task session\",\n ].map((note) => (\n <div key={note}>\n <span style={{ color: theme.cyan }}>{note}</span>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n );\n })()}\n\n {channelsMsg && (\n <div\n style={{\n padding: \"8px 12px\",\n borderRadius: 8,\n marginBottom: 16,\n fontSize: 12,\n background: channelsMsg.ok ? theme.greenBg : theme.redBg,\n color: channelsMsg.ok ? theme.green : theme.red,\n border: `1px solid ${channelsMsg.ok ? theme.green : theme.red}`,\n }}\n >\n {channelsMsg.text}\n </div>\n )}\n\n <div style={{ display: \"flex\", gap: 10, justifyContent: \"flex-end\" }}>\n <button\n onClick={onClose}\n style={{\n padding: \"10px 20px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: \"transparent\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n }}\n >\n Close\n </button>\n <button\n onClick={handleSaveChannels}\n disabled={channelsSaving}\n style={{\n padding: \"10px 24px\",\n borderRadius: 8,\n border: \"none\",\n background: channelsSaving ? theme.border : theme.accent,\n color: channelsSaving ? theme.textMuted : \"#fff\",\n cursor: channelsSaving ? \"not-allowed\" : \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n boxShadow: channelsSaving ? \"none\" : `0 0 20px ${theme.accentGlow}`,\n }}\n >\n {channelsSaving ? \"Saving…\" : \"Save\"}\n </button>\n </div>\n </>\n )}\n\n {/* ── Feishu tab ── */}\n {tab === \"feishu\" && (\n <>\n {/* Enable toggle */}\n <div\n style={{\n marginBottom: 20,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n }}\n >\n <div>\n <div style={{ fontSize: 13, fontWeight: 600, color: theme.text }}>\n Enable Feishu Bot\n </div>\n <div style={{ fontSize: 11, color: theme.textMuted, marginTop: 2 }}>\n WebSocket long-connection, no public IP required\n </div>\n </div>\n <button\n onClick={() =>\n setFeishu((f) => ({\n ...f,\n feishu_enabled: f.feishu_enabled === \"true\" ? \"false\" : \"true\",\n }))\n }\n style={{\n width: 44,\n height: 24,\n borderRadius: 12,\n border: \"none\",\n cursor: \"pointer\",\n background: feishu.feishu_enabled === \"true\" ? theme.accent : theme.border,\n position: \"relative\",\n transition: \"background 0.2s\",\n flexShrink: 0,\n }}\n >\n <span\n style={{\n position: \"absolute\",\n top: 3,\n width: 18,\n height: 18,\n borderRadius: \"50%\",\n background: \"#fff\",\n transition: \"left 0.2s\",\n left: feishu.feishu_enabled === \"true\" ? 23 : 3,\n }}\n />\n </button>\n </div>\n\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 16, marginBottom: 20 }}>\n <div>\n <label style={labelStyle}>App ID</label>\n <input\n value={feishu.feishu_app_id}\n onChange={(e) => setFeishu((f) => ({ ...f, feishu_app_id: e.target.value }))}\n placeholder=\"cli_xxxxxxxxxxxxxxxx\"\n style={fieldStyle}\n />\n </div>\n <div>\n <label style={labelStyle}>App Secret</label>\n <input\n type=\"password\"\n value={feishu.feishu_app_secret}\n onChange={(e) => setFeishu((f) => ({ ...f, feishu_app_secret: e.target.value }))}\n placeholder=\"••••••••••••••••\"\n style={fieldStyle}\n />\n </div>\n <div>\n <label style={labelStyle}>Default Chat ID</label>\n <input\n value={feishu.feishu_default_chat_id}\n onChange={(e) =>\n setFeishu((f) => ({ ...f, feishu_default_chat_id: e.target.value }))\n }\n placeholder=\"oc_xxxxxxxx (group) or ou_xxxxxxxx (DM)\"\n style={fieldStyle}\n />\n <div style={hintStyle}>Task completion notifications will be sent here.</div>\n </div>\n <div>\n <label style={labelStyle}>Default Working Directory</label>\n <input\n value={feishu.feishu_default_working_dir}\n onChange={(e) =>\n setFeishu((f) => ({ ...f, feishu_default_working_dir: e.target.value }))\n }\n placeholder=\"~/my-project\"\n style={fieldStyle}\n />\n <div style={hintStyle}>Working directory for tasks created via the bot.</div>\n </div>\n </div>\n\n {/* Bot commands cheatsheet */}\n <div\n style={{\n background: theme.bg,\n border: `1px solid ${theme.border}`,\n borderRadius: 8,\n padding: \"12px 14px\",\n marginBottom: 20,\n fontSize: 11,\n fontFamily: \"monospace\",\n color: theme.textMuted,\n lineHeight: 1.8,\n }}\n >\n <div style={{ color: theme.textDim, marginBottom: 6, fontFamily: \"inherit\" }}>\n Bot commands:\n </div>\n <div>\n <span style={{ color: theme.cyan }}><any text></span> — create a new task\n </div>\n <div>\n <span style={{ color: theme.cyan }}>/resume <id> <msg></span> — resume a\n task session\n </div>\n <div>\n <span style={{ color: theme.cyan }}>/status <id></span> — query task status\n </div>\n </div>\n\n {feishuMsg && (\n <div\n style={{\n padding: \"8px 12px\",\n borderRadius: 8,\n marginBottom: 16,\n fontSize: 12,\n background: feishuMsg.ok ? theme.greenBg : theme.redBg,\n color: feishuMsg.ok ? theme.green : theme.red,\n border: `1px solid ${feishuMsg.ok ? theme.green : theme.red}`,\n }}\n >\n {feishuMsg.text}\n </div>\n )}\n\n <div style={{ display: \"flex\", gap: 10, justifyContent: \"flex-end\" }}>\n <button\n onClick={onClose}\n style={{\n padding: \"10px 20px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: \"transparent\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n }}\n >\n Close\n </button>\n <button\n onClick={handleSaveFeishu}\n disabled={feishuSaving}\n style={{\n padding: \"10px 24px\",\n borderRadius: 8,\n border: \"none\",\n background: feishuSaving ? theme.border : theme.accent,\n color: feishuSaving ? theme.textMuted : \"#fff\",\n cursor: feishuSaving ? \"not-allowed\" : \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n boxShadow: feishuSaving ? \"none\" : `0 0 20px ${theme.accentGlow}`,\n }}\n >\n {feishuSaving ? \"Saving…\" : \"Save & Apply\"}\n </button>\n </div>\n </>\n )}\n </div>\n </div>\n );\n}\n\n// ─── App ───\n\nfunction parseSkillFrontmatter(body) {\n const m = (body || \"\").match(/^---\\s*\\n([\\s\\S]*?)\\n---/);\n if (!m) return { name: \"\", description: \"\" };\n const out = { name: \"\", description: \"\" };\n for (const line of m[1].split(\"\\n\")) {\n const i = line.indexOf(\":\");\n if (i === -1) continue;\n const k = line.slice(0, i).trim().toLowerCase();\n const v = line.slice(i + 1).trim();\n if (k === \"name\" && !out.name) out.name = v;\n if (k === \"description\" && !out.description) out.description = v;\n }\n return out;\n}\n\nfunction SkillKindBadge({ kind }) {\n const isPitfall = kind === \"pitfall\";\n return (\n <span\n style={{\n fontSize: 10,\n fontWeight: 700,\n padding: \"2px 7px\",\n borderRadius: 6,\n letterSpacing: 0.4,\n background: isPitfall ? \"rgba(239,68,68,0.15)\" : \"rgba(34,197,94,0.15)\",\n color: isPitfall ? theme.red : theme.green,\n }}\n >\n {isPitfall ? \"PITFALL\" : \"RECIPE\"}\n </span>\n );\n}\n\nfunction SkillPatternCard({ p, tasks, onDraft, onApprove, onDismiss }) {\n let taskIds = [];\n try {\n taskIds = JSON.parse(p.contributing_task_ids || \"[]\");\n } catch {\n /* ignore */\n }\n const taskCount = taskIds.length;\n const ready = p.recurrence_count >= 3 && taskCount >= 2;\n const draftStatus = p.draft_status;\n const [expanded, setExpanded] = useState(false);\n const [body, setBody] = useState(p.draft_body || \"\");\n // The full SKILL.md is the single source of truth (name + description live in\n // its frontmatter). Sync the buffer when a fresh draft arrives.\n useEffect(() => {\n if (draftStatus === \"ready\") setBody(p.draft_body || \"\");\n }, [draftStatus, p.draft_body]);\n\n const borderColor =\n p.status === \"promoted\" ? theme.green : p.status === \"candidate\" ? theme.accent : theme.border;\n const muted = p.status === \"dismissed\";\n\n const btn = (bg, color) => ({\n padding: \"6px 14px\",\n borderRadius: 7,\n border: bg === \"transparent\" ? `1px solid ${theme.border}` : \"none\",\n background: bg,\n color,\n cursor: \"pointer\",\n fontSize: 11,\n fontWeight: 700,\n });\n\n return (\n <div\n style={{\n background: theme.surface,\n border: `1px solid ${borderColor}`,\n borderRadius: 12,\n padding: 16,\n opacity: muted ? 0.5 : 1,\n }}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8, marginBottom: 8 }}>\n <SkillKindBadge kind={p.kind} />\n <span style={{ fontFamily: \"monospace\", fontSize: 12, color: theme.text, fontWeight: 700 }}>\n {p.pattern_key}\n </span>\n </div>\n <div style={{ color: theme.textMuted, fontSize: 13, marginBottom: 10 }}>\n {p.summary || \"—\"}\n </div>\n <div\n style={{\n display: \"flex\",\n gap: 12,\n fontSize: 11,\n color: theme.textDim,\n marginBottom: 10,\n alignItems: \"center\",\n }}\n >\n <span>复发 {p.recurrence_count}×</span>\n <span>{taskCount} 个任务</span>\n <span>{p.status}</span>\n {ready && p.status !== \"promoted\" && (\n <span style={{ color: theme.accent, fontWeight: 700 }}>✓ 达标</span>\n )}\n <button\n onClick={() => setExpanded((v) => !v)}\n style={{\n marginLeft: \"auto\",\n background: \"transparent\",\n border: \"none\",\n color: theme.accent,\n cursor: \"pointer\",\n fontSize: 11,\n fontWeight: 700,\n }}\n >\n {expanded ? \"收起 ▲\" : \"详情 ▼\"}\n </button>\n </div>\n\n {expanded && (\n <div\n style={{\n background: theme.bg,\n border: `1px solid ${theme.border}`,\n borderRadius: 8,\n padding: 10,\n marginBottom: 10,\n fontSize: 11,\n color: theme.textMuted,\n }}\n >\n <div style={{ marginBottom: 6 }}>\n <span style={{ color: theme.textDim }}>首次 </span>\n {(p.first_seen || \"\").replace(\"T\", \" \").slice(0, 19) || \"—\"}\n <span style={{ color: theme.textDim }}> 最近 </span>\n {(p.last_seen || \"\").replace(\"T\", \" \").slice(0, 19) || \"—\"}\n </div>\n <div style={{ color: theme.textDim, marginBottom: 4 }}>贡献的任务({taskCount}):</div>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 3 }}>\n {taskIds.length === 0 && <span style={{ color: theme.textDim }}>—</span>}\n {taskIds.map((tid) => {\n const t = (tasks || []).find((x) => x.id === tid);\n return (\n <span key={tid} style={{ fontFamily: \"monospace\" }}>\n #{tid} {t ? t.title : <span style={{ color: theme.textDim }}>(已删除)</span>}\n </span>\n );\n })}\n </div>\n </div>\n )}\n\n {draftStatus === \"ready\" && p.draft_worthy !== null && p.draft_worthy !== undefined && (\n <div\n style={{\n fontSize: 11,\n padding: \"7px 10px\",\n borderRadius: 7,\n marginBottom: 8,\n background: p.draft_worthy ? \"rgba(34,197,94,0.12)\" : \"rgba(245,158,11,0.14)\",\n color: p.draft_worthy ? theme.green : \"#f59e0b\",\n border: `1px solid ${p.draft_worthy ? \"rgba(34,197,94,0.3)\" : \"rgba(245,158,11,0.35)\"}`,\n }}\n >\n {p.draft_worthy ? \"✓ agent 建议沉淀\" : \"⚠ agent 认为价值有限(可仍批准或驳回)\"}\n {p.draft_worthiness_reason ? `:${p.draft_worthiness_reason}` : \"\"}\n </div>\n )}\n\n {p.status === \"promoted\" && (\n <div style={{ fontSize: 12, color: theme.green, fontWeight: 700 }}>✓ 已沉淀为 Skill</div>\n )}\n\n {(p.status === \"candidate\" || p.status === \"tracking\") &&\n draftStatus !== \"ready\" &&\n draftStatus !== \"drafting\" && (\n <div style={{ display: \"flex\", gap: 8, alignItems: \"center\", flexWrap: \"wrap\" }}>\n <button onClick={() => onDraft(p.id)} style={btn(theme.accent, \"#fff\")}>\n {draftStatus === \"error\" ? \"重试蒸馏\" : \"蒸馏成 Skill\"}\n </button>\n <button onClick={() => onDismiss(p.id)} style={btn(\"transparent\", theme.textMuted)}>\n 驳回\n </button>\n {p.status === \"tracking\" && (\n <span style={{ color: theme.textDim, fontSize: 11 }}>\n 未达自动阈值,可手动蒸馏(agent 会判断是否值得)\n </span>\n )}\n {draftStatus === \"error\" && (\n <span style={{ color: theme.red, fontSize: 11 }}>蒸馏失败:{p.draft_error}</span>\n )}\n </div>\n )}\n\n {draftStatus === \"drafting\" && (\n <div style={{ fontSize: 12, color: theme.textMuted }}>蒸馏中…</div>\n )}\n\n {draftStatus === \"ready\" &&\n (() => {\n const fm = parseSkillFrontmatter(body);\n return (\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 10 }}>\n {/* preview header */}\n <div style={{ display: \"flex\", alignItems: \"baseline\", gap: 8, flexWrap: \"wrap\" }}>\n <span\n style={{\n fontFamily: \"ui-monospace, Menlo, monospace\",\n fontSize: 12,\n fontWeight: 800,\n color: theme.accent,\n background: theme.accentGlow,\n padding: \"3px 9px\",\n borderRadius: 6,\n }}\n >\n {fm.name || \"(无 name)\"}\n </span>\n <span style={{ fontSize: 11, color: theme.textDim }}>\n → ~/.claude/skills/{fm.name || \"…\"}/SKILL.md\n </span>\n </div>\n {fm.description && (\n <div style={{ fontSize: 12, color: theme.textMuted, lineHeight: 1.55 }}>\n {fm.description}\n </div>\n )}\n {/* editor */}\n <div>\n <div\n style={{\n fontSize: 10.5,\n color: theme.textDim,\n marginBottom: 5,\n fontWeight: 600,\n letterSpacing: 0.3,\n }}\n >\n SKILL.md · 可编辑(frontmatter 决定名称与触发描述)\n </div>\n <textarea\n value={body}\n onChange={(e) => setBody(e.target.value)}\n rows={16}\n spellCheck={false}\n style={{\n width: \"100%\",\n boxSizing: \"border-box\",\n padding: \"12px 14px\",\n borderRadius: 10,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n color: theme.text,\n fontSize: 12,\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, monospace\",\n lineHeight: 1.65,\n resize: \"vertical\",\n outline: \"none\",\n }}\n />\n </div>\n <div style={{ display: \"flex\", gap: 8 }}>\n <button\n onClick={() => onApprove(p.id, { body })}\n style={{ ...btn(theme.green, \"#fff\"), padding: \"8px 18px\", fontSize: 12 }}\n >\n ✓ 批准并写入\n </button>\n <button\n onClick={() => onDismiss(p.id)}\n style={{\n ...btn(\"transparent\", theme.textMuted),\n padding: \"8px 18px\",\n fontSize: 12,\n }}\n >\n 驳回\n </button>\n </div>\n </div>\n );\n })()}\n </div>\n );\n}\n\nfunction SkillRegistryCard({ s, tasks, onToggle, onDelete }) {\n const [expanded, setExpanded] = useState(false);\n const [content, setContent] = useState<any>(null);\n const [loading, setLoading] = useState(false);\n\n let sourceTaskIds = [];\n try {\n sourceTaskIds = JSON.parse(s.source_task_ids || \"[]\");\n } catch {\n /* ignore */\n }\n\n const toggleDetail = async () => {\n const next = !expanded;\n setExpanded(next);\n if (next && content === null) {\n setLoading(true);\n try {\n const res = await fetch(`${API}/skills/${s.id}/content`);\n const d = await res.json();\n setContent(d.content ?? \"\");\n } catch (e) {\n setContent(`(加载失败:${e.message})`);\n } finally {\n setLoading(false);\n }\n }\n };\n\n return (\n <div\n style={{\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 12,\n padding: 14,\n opacity: s.enabled ? 1 : 0.55,\n }}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8, marginBottom: 6 }}>\n <SkillKindBadge kind={s.kind} />\n <span style={{ fontFamily: \"monospace\", fontSize: 12, color: theme.text, fontWeight: 700 }}>\n {s.name}\n </span>\n <button\n onClick={toggleDetail}\n style={{\n marginLeft: \"auto\",\n background: \"transparent\",\n border: \"none\",\n color: theme.accent,\n cursor: \"pointer\",\n fontSize: 11,\n fontWeight: 700,\n }}\n >\n {expanded ? \"收起 ▲\" : \"查看 SKILL.md ▼\"}\n </button>\n </div>\n <div style={{ color: theme.textMuted, fontSize: 12, marginBottom: 10, lineHeight: 1.5 }}>\n {s.description || \"—\"}\n </div>\n\n {expanded && (\n <div style={{ marginBottom: 10 }}>\n <div style={{ fontSize: 11, color: theme.textDim, marginBottom: 6 }}>\n <span style={{ fontFamily: \"monospace\" }}>{s.path}</span>\n {s.source_pattern_key && <span> 来源 pattern:{s.source_pattern_key}</span>}\n {sourceTaskIds.length > 0 && (\n <span>\n  来源任务:\n {sourceTaskIds\n .map((tid) => {\n const t = (tasks || []).find((x) => x.id === tid);\n return `#${tid}${t ? \"(\" + t.title + \")\" : \"\"}`;\n })\n .join(\"、\")}\n </span>\n )}\n </div>\n <pre\n style={{\n margin: 0,\n padding: \"12px 14px\",\n borderRadius: 10,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n color: theme.text,\n fontSize: 12,\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, monospace\",\n lineHeight: 1.6,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n maxHeight: 360,\n overflow: \"auto\",\n }}\n >\n {loading ? \"加载中…\" : content}\n </pre>\n </div>\n )}\n\n <div style={{ display: \"flex\", gap: 8, alignItems: \"center\" }}>\n <label\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n fontSize: 11,\n color: theme.textDim,\n cursor: \"pointer\",\n }}\n >\n <input\n type=\"checkbox\"\n checked={!!s.enabled}\n onChange={(e) => onToggle(s.id, e.target.checked)}\n style={{ cursor: \"pointer\" }}\n />\n {s.enabled ? \"已启用(claude/codex 加载中)\" : \"已停用(symlink 已摘除)\"}\n </label>\n <button\n onClick={() => onDelete(s.id)}\n style={{\n marginLeft: \"auto\",\n padding: \"4px 10px\",\n borderRadius: 6,\n border: `1px solid ${theme.border}`,\n background: \"transparent\",\n color: theme.red,\n cursor: \"pointer\",\n fontSize: 11,\n fontWeight: 700,\n }}\n >\n 删除\n </button>\n </div>\n </div>\n );\n}\n\nfunction SkillsView({\n skillData,\n skills,\n tasks,\n onSweep,\n onDraft,\n onApprove,\n onDismiss,\n onToggleSkill,\n onDeleteSkill,\n}) {\n // Only recurrence >= 2 is worth surfacing; single-occurrence rows are noise.\n // (The backend still tracks them so the count can accumulate across sweeps.)\n const patterns = (skillData.patterns || []).filter((p) => p.recurrence_count >= 2);\n const sweep = skillData.sweep || {};\n const running = sweep.running;\n const last = sweep.last;\n let lastNote = null;\n if (last) {\n lastNote = last.error\n ? `上次扫描失败:${last.error}`\n : last.scanned === 0\n ? `上次扫描:没有已完成的任务可分析(agent ${last.agent})`\n : `上次扫描:分析 ${last.scanned} 个任务、新增 ${last.new ?? 0} 次复发、候选 ${last.candidates ?? 0}(agent ${last.agent})`;\n }\n const [showRegistry, setShowRegistry] = useState(true);\n const [showPatterns, setShowPatterns] = useState(true);\n\n const sectionHeader = (label, count, open, toggle) => (\n <button\n onClick={toggle}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n width: \"100%\",\n background: \"transparent\",\n border: \"none\",\n cursor: \"pointer\",\n color: theme.text,\n fontSize: 13,\n fontWeight: 700,\n padding: 0,\n marginBottom: 10,\n }}\n >\n <span style={{ color: theme.textDim, fontSize: 11 }}>{open ? \"▼\" : \"▶\"}</span>\n {label}\n <span style={{ color: theme.textDim, fontWeight: 600 }}>({count})</span>\n </button>\n );\n\n return (\n <div style={{ padding: 28, minHeight: \"calc(100vh - 72px)\" }}>\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n marginBottom: 16,\n gap: 12,\n }}\n >\n <div style={{ color: theme.textMuted, fontSize: 12 }}>\n 跨任务复发模式账本 · 复发 ≥2 即可手动蒸馏为 Skill(达 ≥3 且跨 ≥2 任务自动标记候选)\n {lastNote && <span style={{ marginLeft: 10, color: theme.textDim }}>· {lastNote}</span>}\n </div>\n <button\n onClick={onSweep}\n disabled={running}\n style={{\n padding: \"8px 18px\",\n borderRadius: 8,\n border: \"none\",\n background: running ? theme.border : theme.accent,\n color: \"#fff\",\n cursor: running ? \"default\" : \"pointer\",\n fontSize: 12,\n fontWeight: 700,\n letterSpacing: 0.3,\n whiteSpace: \"nowrap\",\n boxShadow: running ? \"none\" : `0 0 24px ${theme.accentGlow}`,\n }}\n >\n {running ? \"扫描中…\" : \"扫一遍\"}\n </button>\n </div>\n\n {(skills || []).length > 0 && (\n <div style={{ marginBottom: 26 }}>\n {sectionHeader(\"已沉淀 Skills\", skills.length, showRegistry, () =>\n setShowRegistry((v) => !v),\n )}\n {showRegistry && (\n <div\n style={{\n display: \"grid\",\n gridTemplateColumns: \"repeat(auto-fit, minmax(360px, 1fr))\",\n gap: 12,\n }}\n >\n {skills.map((s) => (\n <SkillRegistryCard\n key={s.id}\n s={s}\n tasks={tasks}\n onToggle={onToggleSkill}\n onDelete={onDeleteSkill}\n />\n ))}\n </div>\n )}\n </div>\n )}\n\n {sectionHeader(\"检测到的模式\", patterns.length, showPatterns, () =>\n setShowPatterns((v) => !v),\n )}\n {showPatterns &&\n (patterns.length === 0 ? (\n <div\n style={{\n border: `1px dashed ${theme.border}`,\n borderRadius: 12,\n padding: 32,\n textAlign: \"center\",\n color: theme.textDim,\n fontSize: 12,\n }}\n >\n 还没有复发 ≥2 的模式 — 点「扫一遍」让 agent 分析最近完成的任务(复发 1 次的暂不展示)\n </div>\n ) : (\n <div\n style={{\n display: \"grid\",\n gridTemplateColumns: \"repeat(auto-fit, minmax(360px, 1fr))\",\n gap: 14,\n }}\n >\n {patterns.map((p) => (\n <SkillPatternCard\n key={p.id}\n p={p}\n tasks={tasks}\n onDraft={onDraft}\n onApprove={onApprove}\n onDismiss={onDismiss}\n />\n ))}\n </div>\n ))}\n </div>\n );\n}\n\nexport default function App() {\n const [tasks, setTasks] = useState<any[]>([]);\n const [heartbeats, setHeartbeats] = useState<any[]>([]);\n const [heartbeatTicks, setHeartbeatTicks] = useState<any[]>([]);\n const [skillData, setSkillData] = useState({\n patterns: [],\n sweep: { running: false, last: null },\n });\n const [skills, setSkills] = useState<any[]>([]);\n const [activeView, setActiveView] = useState(\"tasks\");\n const [showNew, setShowNew] = useState(false);\n const [showNewHeartbeat, setShowNewHeartbeat] = useState(false);\n const [showSettings, setShowSettings] = useState(false);\n const [detail, setDetail] = useState<any>(null);\n const [heartbeatDetail, setHeartbeatDetail] = useState<any>(null);\n const [connected, setConnected] = useState(false);\n const [filter, setFilter] = useState(\"\");\n const [taskTimeout, setTaskTimeout] = useState(DEFAULT_TIMEOUT_SECONDS);\n const [defaultAgent, setDefaultAgent] = useState(DEFAULT_AGENT);\n const [feishuSettings, setFeishuSettings] = useState<any>({});\n const [channelsStatus, setChannelsStatus] = useState<any>({});\n const [backendReady, setBackendReady] = useState(false);\n const [backendError, setBackendError] = useState<any>(null);\n const [apiError, setApiError] = useState<any>(null);\n const [editingTask, setEditingTask] = useState<any>(null);\n const [forkingTask, setForkingTask] = useState<any>(null);\n const [editingHeartbeat, setEditingHeartbeat] = useState<any>(null);\n\n // ─── Color mode ───\n const [colorMode, setColorMode] = useState(() => localStorage.getItem(\"colorMode\") || \"system\");\n const [systemDark, setSystemDark] = useState(\n () => window.matchMedia(\"(prefers-color-scheme: dark)\").matches,\n );\n const resolvedMode = colorMode === \"system\" ? (systemDark ? \"dark\" : \"light\") : colorMode;\n theme = THEMES[resolvedMode];\n\n useEffect(() => {\n localStorage.setItem(\"colorMode\", colorMode);\n document.body.style.background = THEMES[resolvedMode].bg;\n }, [colorMode, resolvedMode]);\n\n useEffect(() => {\n const mq = window.matchMedia(\"(prefers-color-scheme: dark)\");\n const handler = (e) => setSystemDark(e.matches);\n mq.addEventListener(\"change\", handler);\n return () => mq.removeEventListener(\"change\", handler);\n }, []);\n\n useEffect(() => {\n let cancelled = false;\n const deadline = Date.now() + 20000;\n const probe = async () => {\n try {\n const res = await fetch(`${API}/health`, { signal: AbortSignal.timeout(800) });\n if (res.ok) {\n if (!cancelled) setBackendReady(true);\n return;\n }\n } catch {\n /* not ready yet */\n }\n if (cancelled) return;\n if (Date.now() >= deadline) {\n setBackendError(\"Backend did not start within 20 seconds.\");\n return;\n }\n setTimeout(probe, 300);\n };\n probe();\n return () => {\n cancelled = true;\n };\n }, []);\n\n const poll = useCallback(async () => {\n try {\n const [taskData, heartbeatData, skillRes, skillsRes] = await Promise.all([\n fetchTasks(),\n fetchHeartbeats(),\n fetchSkillPatterns(),\n fetchSkills(),\n ]);\n setTasks(taskData);\n setHeartbeats(heartbeatData);\n setSkillData(skillRes);\n setSkills(skillsRes.skills || []);\n setConnected(true);\n setApiError(null);\n } catch (err) {\n setConnected(false);\n setApiError(`Failed to fetch tasks: ${err.message}`);\n }\n }, []);\n\n useEffect(() => {\n if (!backendReady) return;\n poll();\n const interval = setInterval(poll, 3000);\n return () => clearInterval(interval);\n }, [poll, backendReady]);\n\n useEffect(() => {\n if (!backendReady) return;\n fetchSettings().then((s) => {\n if (s.timeout) setTaskTimeout(s.timeout);\n if (s.default_agent) setDefaultAgent(s.default_agent);\n });\n fetchFeishuSettings().then((s) => setFeishuSettings(s));\n fetchChannelsStatus().then((s) => setChannelsStatus(s));\n }, [backendReady]);\n\n const handleAction = async (action, id) => {\n try {\n if (action === \"cancel\") await cancelTask(id);\n else if (action === \"retry\") await retryTask(id);\n else if (action === \"delete\") {\n await deleteTask(id);\n if (detail?.id === id) setDetail(null);\n } else if (action === \"edit\") {\n const task = tasks.find((t) => t.id === id);\n if (task) setEditingTask(task);\n return;\n } else if (action === \"fork\") {\n const task = tasks.find((t) => t.id === id);\n if (task) setForkingTask(task);\n return;\n }\n poll();\n } catch (e) {\n setApiError(`${action} failed: ${e.message}`);\n }\n };\n\n const handleHeartbeatAction = async (action, id) => {\n try {\n if (action === \"run\") {\n await runHeartbeatNow(id);\n } else if (action === \"pause\") {\n await pauseHeartbeat(id);\n } else if (action === \"resume\") {\n await resumeHeartbeatApi(id);\n } else if (action === \"delete\") {\n await deleteHeartbeat(id);\n if (heartbeatDetail?.id === id) {\n setHeartbeatDetail(null);\n setHeartbeatTicks([]);\n }\n } else if (action === \"edit\") {\n const heartbeat = heartbeats.find((h) => h.id === id);\n if (heartbeat) setEditingHeartbeat(heartbeat);\n return;\n }\n poll();\n if (heartbeatDetail?.id === id && action !== \"delete\") {\n const [updatedHeartbeat, ticks] = await Promise.all([\n fetch(`${API}/heartbeats/${id}`).then((r) => r.json()),\n fetchHeartbeatTicks(id),\n ]);\n setHeartbeatDetail(updatedHeartbeat);\n setHeartbeatTicks(ticks);\n }\n } catch (e) {\n setApiError(`Heartbeat ${action} failed: ${e.message}`);\n }\n };\n\n const handleSweep = async () => {\n try {\n await triggerSkillSweep();\n // Optimistically reflect the running state; poll picks up the real status.\n setSkillData((prev) => ({ ...prev, sweep: { ...prev.sweep, running: true } }));\n setTimeout(poll, 1500);\n } catch (e) {\n setApiError(`Sweep failed: ${e.message}`);\n }\n };\n\n const handleSkillDraft = async (id) => {\n try {\n await triggerSkillDraft(id);\n setTimeout(poll, 1500);\n } catch (e) {\n setApiError(`Distill failed: ${e.message}`);\n }\n };\n\n const handleSkillApprove = async (id, data) => {\n try {\n await approveSkill(id, data);\n poll();\n } catch (e) {\n setApiError(`Approve failed: ${e.message}`);\n }\n };\n\n const handleSkillDismiss = async (id) => {\n try {\n await dismissSkillPattern(id);\n poll();\n } catch (e) {\n setApiError(`Dismiss failed: ${e.message}`);\n }\n };\n\n const handleSkillToggle = async (id, enabled) => {\n try {\n await setSkillEnabledApi(id, enabled);\n poll();\n } catch (e) {\n setApiError(`Toggle skill failed: ${e.message}`);\n }\n };\n\n const handleSkillDelete = async (id) => {\n try {\n await deleteSkillApi(id);\n poll();\n } catch (e) {\n setApiError(`Delete skill failed: ${e.message}`);\n }\n };\n\n const handleCreate = async (data) => {\n try {\n await createTask(data);\n setShowNew(false);\n poll();\n } catch (e) {\n setApiError(`Create task failed: ${e.message}`);\n }\n };\n\n const handleEdit = async (data) => {\n try {\n await updateTask(editingTask.id, data);\n setEditingTask(null);\n poll();\n } catch (e) {\n setApiError(`Edit task failed: ${e.message}`);\n }\n };\n\n const handleFork = async (data) => {\n try {\n await createTask(data);\n setForkingTask(null);\n poll();\n } catch (e) {\n setApiError(`Fork task failed: ${e.message}`);\n }\n };\n\n const handleRespond = async (id, answer) => {\n try {\n await respondToTask(id, answer);\n poll();\n } catch (e) {\n setApiError(`Respond failed: ${e.message}`);\n }\n };\n\n const handleResume = () => {\n poll();\n };\n\n const handleCreateHeartbeat = async (data) => {\n try {\n await createHeartbeat(data);\n setShowNewHeartbeat(false);\n poll();\n } catch (e) {\n setApiError(`Create heartbeat failed: ${e.message}`);\n }\n };\n\n const handleEditHeartbeat = async (data) => {\n try {\n await updateHeartbeat(editingHeartbeat.id, data);\n setEditingHeartbeat(null);\n poll();\n } catch (e) {\n setApiError(`Edit heartbeat failed: ${e.message}`);\n }\n };\n\n const openHeartbeatDetail = async (heartbeat) => {\n setHeartbeatDetail(heartbeat);\n try {\n const ticks = await fetchHeartbeatTicks(heartbeat.id);\n setHeartbeatTicks(ticks);\n } catch (e) {\n setApiError(`Failed to fetch heartbeat ticks: ${e.message}`);\n setHeartbeatTicks([]);\n }\n };\n\n const filtered = filter\n ? tasks.filter(\n (t) =>\n t.title.toLowerCase().includes(filter.toLowerCase()) ||\n t.tags?.toLowerCase().includes(filter.toLowerCase()),\n )\n : tasks;\n\n const runningCount = tasks.filter((t) => t.status === \"running\").length;\n const scheduledCount = tasks.filter((t) => t.status === \"scheduled\").length;\n const enabledHeartbeatCount = heartbeats.filter((h) => h.enabled).length;\n\n if (backendError) {\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"100vh\",\n background: theme.bg,\n color: theme.red,\n gap: 12,\n fontFamily: \"inherit\",\n }}\n >\n <div style={{ fontSize: 32 }}>✕</div>\n <div style={{ fontSize: 15, fontWeight: 600 }}>Backend failed to start</div>\n <div style={{ fontSize: 12, color: theme.textMuted, maxWidth: 400, textAlign: \"center\" }}>\n {backendError}\n </div>\n </div>\n );\n }\n\n if (!backendReady) {\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"100vh\",\n background: theme.bg,\n color: theme.textMuted,\n gap: 16,\n fontFamily: \"inherit\",\n }}\n >\n <div\n style={{\n width: 32,\n height: 32,\n borderRadius: \"50%\",\n border: `3px solid ${theme.border}`,\n borderTopColor: theme.accent,\n animation: \"spin 0.8s linear infinite\",\n }}\n />\n <div style={{ fontSize: 13 }}>Starting backend…</div>\n <style>{`@keyframes spin { to { transform: rotate(360deg); } }`}</style>\n </div>\n );\n }\n\n return (\n <div\n style={{\n minHeight: \"100vh\",\n background: theme.bg,\n color: theme.text,\n fontFamily: \"-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n }}\n >\n <style>{`@keyframes pulse { 0%,100%{opacity:1} 50%{opacity:0.3} }`}</style>\n {/* API error toast */}\n {apiError && (\n <div\n style={{\n position: \"fixed\",\n bottom: 24,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n zIndex: 9999,\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n background: theme.surface,\n border: `1px solid ${theme.red}`,\n borderRadius: 8,\n padding: \"10px 16px\",\n boxShadow: `0 4px 24px rgba(0,0,0,0.5)`,\n color: theme.red,\n fontSize: 12,\n fontWeight: 500,\n maxWidth: 480,\n }}\n >\n <span style={{ flexShrink: 0 }}>✕</span>\n <span style={{ flex: 1 }}>{apiError}</span>\n <button\n onClick={() => setApiError(null)}\n style={{\n background: \"none\",\n border: \"none\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 14,\n lineHeight: 1,\n padding: \"0 0 0 8px\",\n flexShrink: 0,\n }}\n title=\"Dismiss\"\n >\n ×\n </button>\n </div>\n )}\n {/* Header */}\n <div\n style={{\n borderBottom: `1px solid ${theme.border}`,\n padding: \"16px 28px\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n backdropFilter: \"blur(10px)\",\n position: \"sticky\",\n top: 0,\n zIndex: 100,\n background: `${theme.bg}ee`,\n }}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 14 }}>\n <div\n style={{\n width: 32,\n height: 32,\n borderRadius: 8,\n background: `linear-gradient(135deg, ${theme.accent}, #a855f7)`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontSize: 16,\n fontWeight: 800,\n color: \"#fff\",\n }}\n >\n ⌘\n </div>\n <div>\n <div\n style={{\n fontSize: 15,\n fontWeight: 700,\n fontFamily: \"'JetBrains Mono', monospace\",\n letterSpacing: -0.3,\n }}\n >\n AgentForge\n </div>\n <div style={{ fontSize: 11, color: theme.textDim, marginTop: 1 }}>\n {connected ? (\n <span style={{ color: theme.green }}>● Connected</span>\n ) : (\n <span style={{ color: theme.red }}>● Disconnected — run `python taskboard.py`</span>\n )}\n {connected &&\n ` · ${runningCount} running · ${scheduledCount} scheduled · ${enabledHeartbeatCount} heartbeats`}\n </div>\n </div>\n </div>\n\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 10 }}>\n <div\n style={{\n display: \"flex\",\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 10,\n padding: 4,\n gap: 4,\n }}\n >\n {[\n { key: \"tasks\", label: \"Tasks\" },\n { key: \"heartbeats\", label: \"Heartbeats\" },\n { key: \"skills\", label: \"Skills\" },\n ].map((tab) => (\n <button\n key={tab.key}\n onClick={() => setActiveView(tab.key)}\n style={{\n padding: \"6px 10px\",\n borderRadius: 8,\n border: \"none\",\n background: activeView === tab.key ? theme.accentGlow : \"transparent\",\n color: activeView === tab.key ? theme.accent : theme.textMuted,\n cursor: \"pointer\",\n fontSize: 12,\n fontWeight: 700,\n }}\n >\n {tab.label}\n </button>\n ))}\n </div>\n <input\n placeholder={activeView === \"tasks\" ? \"Filter tasks...\" : \"Filter heartbeats...\"}\n value={filter}\n onChange={(e) => setFilter(e.target.value)}\n style={{\n padding: \"8px 14px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: theme.surface,\n color: theme.text,\n fontSize: 12,\n outline: \"none\",\n width: 180,\n }}\n />\n {/* Color mode toggle */}\n {(() => {\n const cycle = { system: \"light\", light: \"dark\", dark: \"system\" };\n const icons = { system: \"⊙\", light: \"☀\", dark: \"☾\" };\n const labels = { system: \"System theme\", light: \"Light mode\", dark: \"Dark mode\" };\n return (\n <Tooltip text={labels[colorMode]}>\n <button\n onClick={() => setColorMode(cycle[colorMode])}\n style={{\n padding: \"8px 10px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: \"transparent\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 15,\n display: \"flex\",\n alignItems: \"center\",\n transition: \"all 0.15s\",\n }}\n >\n {icons[colorMode]}\n </button>\n </Tooltip>\n );\n })()}\n <Tooltip text=\"Settings\">\n <button\n onClick={() => setShowSettings(true)}\n style={{\n padding: \"8px 12px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: \"transparent\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 15,\n display: \"flex\",\n alignItems: \"center\",\n transition: \"all 0.15s\",\n }}\n >\n ⚙\n </button>\n </Tooltip>\n {activeView !== \"skills\" && (\n <button\n onClick={() =>\n activeView === \"tasks\" ? setShowNew(true) : setShowNewHeartbeat(true)\n }\n style={{\n padding: \"8px 18px\",\n borderRadius: 8,\n border: \"none\",\n background: theme.accent,\n color: \"#fff\",\n cursor: \"pointer\",\n fontSize: 12,\n fontWeight: 700,\n letterSpacing: 0.3,\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n boxShadow: `0 0 24px ${theme.accentGlow}`,\n transition: \"transform 0.15s\",\n }}\n >\n {activeView === \"tasks\" ? \"+ New Task\" : \"+ New Heartbeat\"}\n </button>\n )}\n </div>\n </div>\n\n {activeView === \"tasks\" ? (\n <div\n style={{\n display: \"flex\",\n gap: 20,\n padding: 28,\n minHeight: \"calc(100vh - 72px)\",\n }}\n >\n {COLUMNS.map((col) => (\n <Column\n key={col.key}\n col={col}\n tasks={filtered.filter((t) => col.statuses.includes(t.status))}\n onAction={handleAction}\n onViewDetail={setDetail}\n />\n ))}\n </div>\n ) : activeView === \"heartbeats\" ? (\n <div style={{ padding: 28, minHeight: \"calc(100vh - 72px)\" }}>\n <div\n style={{\n display: \"grid\",\n gridTemplateColumns: \"repeat(auto-fit, minmax(360px, 1fr))\",\n gap: 14,\n }}\n >\n {(filter\n ? heartbeats.filter(\n (h) =>\n h.name.toLowerCase().includes(filter.toLowerCase()) ||\n h.check_prompt.toLowerCase().includes(filter.toLowerCase()),\n )\n : heartbeats\n ).map((h) => (\n <HeartbeatCard\n key={h.id}\n heartbeat={h}\n onAction={handleHeartbeatAction}\n onViewDetail={openHeartbeatDetail}\n />\n ))}\n {heartbeats.length === 0 && (\n <div\n style={{\n border: `1px dashed ${theme.border}`,\n borderRadius: 12,\n padding: 32,\n textAlign: \"center\",\n color: theme.textDim,\n fontSize: 12,\n gridColumn: \"1 / -1\",\n }}\n >\n No heartbeats yet\n </div>\n )}\n </div>\n </div>\n ) : (\n <SkillsView\n skillData={skillData}\n skills={skills}\n tasks={tasks}\n onSweep={handleSweep}\n onDraft={handleSkillDraft}\n onApprove={handleSkillApprove}\n onDismiss={handleSkillDismiss}\n onToggleSkill={handleSkillToggle}\n onDeleteSkill={handleSkillDelete}\n />\n )}\n\n {/* Modals */}\n {showNew && (\n <NewTaskModal\n onClose={() => setShowNew(false)}\n onSubmit={handleCreate}\n initialData={{ agent: defaultAgent }}\n />\n )}\n {showNewHeartbeat && (\n <HeartbeatModal\n onClose={() => setShowNewHeartbeat(false)}\n onSubmit={handleCreateHeartbeat}\n defaultAgent={defaultAgent}\n />\n )}\n {editingTask && (\n <NewTaskModal\n onClose={() => setEditingTask(null)}\n onSubmit={handleEdit}\n initialData={editingTask}\n mode=\"edit\"\n />\n )}\n {editingHeartbeat && (\n <HeartbeatModal\n onClose={() => setEditingHeartbeat(null)}\n onSubmit={handleEditHeartbeat}\n initialData={editingHeartbeat}\n defaultAgent={defaultAgent}\n mode=\"edit\"\n />\n )}\n {forkingTask && (\n <NewTaskModal\n onClose={() => setForkingTask(null)}\n onSubmit={handleFork}\n initialData={forkingTask}\n mode=\"fork\"\n />\n )}\n {showSettings && (\n <SettingsModal\n onClose={() => setShowSettings(false)}\n timeout={taskTimeout}\n defaultAgent={defaultAgent}\n onSave={(timeout, agent) => {\n setTaskTimeout(timeout);\n if (agent) setDefaultAgent(agent);\n }}\n feishu={feishuSettings}\n onFeishuSave={(updated) => setFeishuSettings(updated)}\n channelsStatus={channelsStatus}\n onChannelsSave={(updated) => setChannelsStatus(updated)}\n />\n )}\n {detail && (\n <DetailPanel\n task={tasks.find((t) => t.id === detail.id) || detail}\n onClose={() => setDetail(null)}\n onRespond={handleRespond}\n onResume={handleResume}\n />\n )}\n {heartbeatDetail && (\n <HeartbeatDetailPanel\n heartbeat={heartbeats.find((h) => h.id === heartbeatDetail.id) || heartbeatDetail}\n ticks={heartbeatTicks}\n onClose={() => {\n setHeartbeatDetail(null);\n setHeartbeatTicks([]);\n }}\n />\n )}\n\n {/* Startup guide when no tasks */}\n {connected && activeView === \"tasks\" && tasks.length === 0 && (\n <div\n style={{\n position: \"fixed\",\n bottom: 28,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 12,\n padding: \"16px 24px\",\n maxWidth: 500,\n boxShadow: \"0 8px 32px rgba(0,0,0,0.3)\",\n }}\n >\n <div style={{ fontSize: 13, color: theme.text, fontWeight: 600, marginBottom: 6 }}>\n Ready to go! Click \"+ New Task\" to create your first task.\n </div>\n <div style={{ fontSize: 11, color: theme.textDim, lineHeight: 1.6 }}>\n Tasks are dispatched to Claude Code in your specified working directory. Set cron\n schedules for recurring tasks, or delay execution.\n </div>\n </div>\n )}\n {connected && activeView === \"heartbeats\" && heartbeats.length === 0 && (\n <div\n style={{\n position: \"fixed\",\n bottom: 28,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 12,\n padding: \"16px 24px\",\n maxWidth: 560,\n boxShadow: \"0 8px 32px rgba(0,0,0,0.3)\",\n }}\n >\n <div style={{ fontSize: 13, color: theme.text, fontWeight: 600, marginBottom: 6 }}>\n Heartbeats let AgentForge check first and only create work when needed.\n </div>\n <div style={{ fontSize: 11, color: theme.textDim, lineHeight: 1.6 }}>\n Create one to run a stateless agent decision tick on an interval or cron schedule, then\n trigger a real task only when the signal is actionable.\n </div>\n </div>\n )}\n\n {!connected && (\n <div\n style={{\n position: \"fixed\",\n bottom: 28,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n background: theme.redBg,\n border: `1px solid rgba(248,113,113,0.2)`,\n borderRadius: 12,\n padding: \"16px 24px\",\n maxWidth: 520,\n }}\n >\n <div style={{ fontSize: 13, color: theme.red, fontWeight: 600, marginBottom: 4 }}>\n Backend not running\n </div>\n <code style={{ fontSize: 11, color: theme.text, lineHeight: 1.8, display: \"block\" }}>\n pip install croniter\n <br />\n python taskboard.py\n </code>\n </div>\n )}\n </div>\n );\n}\n\n// CSS动画定义\nconst styles = `\n @keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n\n .live-output-line {\n transition: color 0.2s ease;\n }\n\n .live-output-line.error {\n color: ${theme.red};\n }\n\n .live-output-line.success {\n color: ${theme.green};\n }\n\n .live-output-line.warning {\n color: ${theme.orange};\n }\n\n .live-output-line.info {\n color: ${theme.blue};\n }\n\n .live-output-line.command {\n color: ${theme.cyan};\n font-weight: bold;\n }\n\n .live-output-line.path {\n color: ${theme.accent};\n }\n`;\n\n// 注入样式\nif (typeof document !== \"undefined\" && !document.querySelector(\"#live-output-styles\")) {\n const styleEl = document.createElement(\"style\");\n styleEl.id = \"live-output-styles\";\n styleEl.textContent = styles;\n document.head.appendChild(styleEl);\n}\n", + "interface LocalDateTimeParts {\n year: number;\n month: number;\n day: number;\n hour: number;\n minute: number;\n second: number;\n}\n\nfunction pad(value: number | string): string {\n return String(value).padStart(2, \"0\");\n}\n\nfunction hasExplicitTimezone(value: string): boolean {\n return /(?:Z|[+-]\\d{2}:\\d{2})$/i.test(value);\n}\n\nfunction parseLocalDateTimeParts(value: unknown): LocalDateTimeParts | null {\n const match = String(value)\n .trim()\n .match(/^(\\d{4})-(\\d{2})-(\\d{2})[T ](\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.\\d+)?)?$/);\n if (!match) return null;\n const [, year, month, day, hour, minute, second = \"00\"] = match;\n return {\n year: Number(year),\n month: Number(month),\n day: Number(day),\n hour: Number(hour),\n minute: Number(minute),\n second: Number(second),\n };\n}\n\nexport function parseTaskDateTime(value: unknown): Date | null {\n if (!value) return null;\n const raw = String(value).trim();\n if (!raw) return null;\n\n if (hasExplicitTimezone(raw)) {\n const date = new Date(raw);\n return Number.isNaN(date.getTime()) ? null : date;\n }\n\n const parts = parseLocalDateTimeParts(raw);\n if (parts) {\n return new Date(\n parts.year,\n parts.month - 1,\n parts.day,\n parts.hour,\n parts.minute,\n parts.second,\n 0,\n );\n }\n\n const fallback = new Date(raw);\n return Number.isNaN(fallback.getTime()) ? null : fallback;\n}\n\nexport function formatTaskDateTime(value: unknown, options?: Intl.DateTimeFormatOptions): string {\n const date = parseTaskDateTime(value);\n return date ? date.toLocaleString(undefined, options) : \"\";\n}\n\nexport function formatTaskTime(value: unknown, options?: Intl.DateTimeFormatOptions): string {\n const date = parseTaskDateTime(value);\n return date ? date.toLocaleTimeString(undefined, options) : \"\";\n}\n\nexport function formatDateTimeLocalInput(value: unknown): string {\n const date = parseTaskDateTime(value);\n if (!date) return \"\";\n return [\n date.getFullYear(),\n \"-\",\n pad(date.getMonth() + 1),\n \"-\",\n pad(date.getDate()),\n \"T\",\n pad(date.getHours()),\n \":\",\n pad(date.getMinutes()),\n ].join(\"\");\n}\n\nexport function serializeDateTimeLocalInput(value: unknown): string | null {\n const parts = parseLocalDateTimeParts(value);\n if (!parts) return null;\n return [\n parts.year,\n \"-\",\n pad(parts.month),\n \"-\",\n pad(parts.day),\n \"T\",\n pad(parts.hour),\n \":\",\n pad(parts.minute),\n \":\",\n pad(parts.second),\n ].join(\"\");\n}\n", + "export interface TelegramChannelState {\n enabled: boolean;\n configured: boolean;\n running: boolean;\n default_working_dir: string;\n default_chat_id: string;\n bot_token: string;\n allowed_users: string;\n}\n\nexport interface SlackChannelState {\n enabled: boolean;\n configured: boolean;\n running: boolean;\n default_working_dir: string;\n default_channel: string;\n default_user: string;\n bot_token: string;\n app_token: string;\n}\n\nexport interface WeixinChannelState {\n enabled: boolean;\n configured: boolean;\n running: boolean;\n default_working_dir: string;\n base_url: string;\n account_id: string;\n login_status: string;\n qr_code_url: string;\n last_error: string;\n user_id: string;\n}\n\nexport interface ChannelsState {\n telegram: TelegramChannelState;\n slack: SlackChannelState;\n weixin: WeixinChannelState;\n}\n\nexport interface ChannelsStatusUpdate {\n telegram?: Partial<TelegramChannelState>;\n slack?: Partial<SlackChannelState>;\n weixin?: Partial<WeixinChannelState>;\n}\n\nexport interface ChannelsSavePayload {\n telegram_enabled: string;\n telegram_bot_token: string;\n telegram_allowed_users: string;\n telegram_default_working_dir: string;\n telegram_default_chat_id: string;\n slack_enabled: string;\n slack_bot_token: string;\n slack_app_token: string;\n slack_default_working_dir: string;\n slack_default_channel: string;\n slack_default_user: string;\n weixin_enabled: string;\n weixin_default_working_dir: string;\n weixin_base_url: string;\n weixin_account_id: string;\n}\n\nconst DEFAULT_CHANNELS_STATE: ChannelsState = {\n telegram: {\n enabled: false,\n configured: false,\n running: false,\n default_working_dir: \"~\",\n default_chat_id: \"\",\n bot_token: \"\",\n allowed_users: \"\",\n },\n slack: {\n enabled: false,\n configured: false,\n running: false,\n default_working_dir: \"~\",\n default_channel: \"\",\n default_user: \"\",\n bot_token: \"\",\n app_token: \"\",\n },\n weixin: {\n enabled: false,\n configured: false,\n running: false,\n default_working_dir: \"~\",\n base_url: \"https://ilinkai.weixin.qq.com\",\n account_id: \"\",\n login_status: \"idle\",\n qr_code_url: \"\",\n last_error: \"\",\n user_id: \"\",\n },\n};\n\nfunction cloneState(state: ChannelsState): ChannelsState {\n return {\n telegram: { ...state.telegram },\n slack: { ...state.slack },\n weixin: { ...state.weixin },\n };\n}\n\nexport function createInitialChannelsState(initial: ChannelsStatusUpdate = {}): ChannelsState {\n const base = cloneState(DEFAULT_CHANNELS_STATE);\n return mergeChannelsStatus(base, initial);\n}\n\nexport function mergeChannelsStatus(\n current: ChannelsState,\n status: ChannelsStatusUpdate = {},\n): ChannelsState {\n return {\n telegram: { ...current.telegram, ...(status.telegram || {}) },\n slack: { ...current.slack, ...(status.slack || {}) },\n weixin: { ...current.weixin, ...(status.weixin || {}) },\n };\n}\n\nexport function buildChannelsSavePayload(channels: ChannelsState): ChannelsSavePayload {\n return {\n telegram_enabled: channels.telegram.enabled ? \"true\" : \"false\",\n telegram_bot_token: channels.telegram.bot_token,\n telegram_allowed_users: channels.telegram.allowed_users,\n telegram_default_working_dir: channels.telegram.default_working_dir,\n telegram_default_chat_id: channels.telegram.default_chat_id,\n slack_enabled: channels.slack.enabled ? \"true\" : \"false\",\n slack_bot_token: channels.slack.bot_token,\n slack_app_token: channels.slack.app_token,\n slack_default_working_dir: channels.slack.default_working_dir,\n slack_default_channel: channels.slack.default_channel,\n slack_default_user: channels.slack.default_user,\n weixin_enabled: channels.weixin.enabled ? \"true\" : \"false\",\n weixin_default_working_dir: channels.weixin.default_working_dir,\n weixin_base_url: channels.weixin.base_url,\n weixin_account_id: channels.weixin.account_id,\n };\n}\n\nexport function isWeixinQrImageSource(value: string | null | undefined): boolean {\n const normalized = (value || \"\").trim();\n if (!normalized) return false;\n if (normalized.startsWith(\"data:image/\")) return true;\n if (/\\.(png|jpg|jpeg|gif|webp|svg)(\\?|#|$)/i.test(normalized)) return true;\n return false;\n}\n", + "export const TRACE_EVENT_TYPES = new Set([\n \"tool_call\",\n \"tool_result\",\n \"command_execution\",\n \"file_change\",\n \"web_search\",\n]);\n\nconst THINKING_PREFIX = \"[thinking] \";\n\nexport interface TraceRow {\n label: string;\n value: string;\n}\n\nexport type TracePayload = Record<string, any>;\n\nexport interface TraceEventInput {\n id?: number;\n event_type?: string;\n type?: string;\n content?: string;\n timestamp?: string;\n}\n\nexport interface ExecutionStep {\n id: string;\n eventIds: number[];\n rawEventType: string;\n timestamp: string;\n rows: TraceRow[];\n detail: string;\n count: number;\n type: string;\n title: string;\n imageSrc?: string;\n number?: number;\n}\n\nfunction compact(rows: Array<TraceRow | null>): TraceRow[] {\n return rows.filter(Boolean) as TraceRow[];\n}\n\nfunction row(label: string, value: unknown): TraceRow | null {\n const formatted = formatTraceValue(value);\n return formatted === \"\" ? null : { label, value: formatted };\n}\n\nexport function parseTracePayload(content: string): TracePayload | null {\n try {\n const payload = JSON.parse(content);\n return payload && typeof payload === \"object\" && !Array.isArray(payload) ? payload : null;\n } catch {\n return null;\n }\n}\n\nexport function formatTraceValue(value: unknown): string {\n if (value === undefined || value === null) return \"\";\n if (typeof value === \"string\") return value;\n return JSON.stringify(value, null, 2);\n}\n\nexport function buildTraceRows(\n eventType: string,\n payload: TracePayload,\n rawContent = \"\",\n): TraceRow[] {\n if (eventType === \"tool_call\") {\n const name = payload.server\n ? `${payload.server}.${payload.name || payload.tool || \"unknown\"}`\n : payload.name || payload.tool || \"unknown\";\n return compact([\n row(\"Tool\", name),\n row(\"Input\", payload.input || payload.arguments),\n row(\"Result\", payload.result),\n row(\"Status\", payload.status),\n row(\"Error\", payload.error),\n ]);\n }\n\n if (eventType === \"tool_result\") {\n return compact([\n row(payload.is_error ? \"Tool Error\" : \"Tool Result\", payload.tool_use_id || \"result\"),\n row(\"Content\", payload.content),\n ]);\n }\n\n if (eventType === \"command_execution\") {\n return compact([\n row(\"Command\", payload.command),\n row(\"Output\", payload.output),\n row(\"Exit\", payload.exit_code),\n row(\"Status\", payload.status),\n ]);\n }\n\n if (eventType === \"file_change\") {\n const changes = Array.isArray(payload.changes)\n ? payload.changes\n .map((change: any) => {\n if (!change || typeof change !== \"object\") return formatTraceValue(change);\n const kind = change.kind || change.type || \"changed\";\n const path = change.path || change.file || \"\";\n return path ? `${kind}: ${path}` : kind;\n })\n .join(\"\\n\")\n : payload.changes;\n return compact([row(\"Changes\", changes), row(\"Status\", payload.status)]);\n }\n\n if (eventType === \"web_search\") {\n return compact([\n row(\"Query\", payload.query),\n row(\"Action\", payload.action),\n row(\"Status\", payload.status),\n ]);\n }\n\n return [{ label: eventType, value: rawContent }];\n}\n\nexport function buildExecutionSteps(events: TraceEventInput[] | null | undefined): ExecutionStep[] {\n const sortedEvents = [...(events || [])].sort(compareEventsChronologically);\n const steps: ExecutionStep[] = [];\n\n for (const event of sortedEvents) {\n const step = eventToStep(event);\n if (!step) continue;\n\n const previous = steps[steps.length - 1];\n if (canMergeSteps(previous, step)) {\n previous.detail = appendDetail(previous.detail, step.detail);\n previous.title = summarizeTitle(previous.detail) || previous.title;\n previous.eventIds.push(...step.eventIds);\n previous.count += step.count;\n previous.timestamp = step.timestamp;\n continue;\n }\n\n steps.push(step);\n }\n\n return steps.map((step, index) => ({\n ...step,\n number: index + 1,\n }));\n}\n\nfunction compareEventsChronologically(a: TraceEventInput, b: TraceEventInput): number {\n const timestampComparison = String(a.timestamp || \"\").localeCompare(String(b.timestamp || \"\"));\n if (timestampComparison !== 0) return timestampComparison;\n return Number(a.id || 0) - Number(b.id || 0);\n}\n\nfunction eventToStep(event: TraceEventInput): ExecutionStep | null {\n const eventType = event.event_type || event.type || \"unknown\";\n const content = event.content || \"\";\n const base = {\n id: event.id ? `event-${event.id}` : `${eventType}-${event.timestamp || \"\"}-${content.length}`,\n eventIds: event.id ? [event.id] : [],\n rawEventType: eventType,\n timestamp: event.timestamp || \"\",\n rows: [] as TraceRow[],\n detail: content,\n count: 1,\n };\n\n if (eventType === \"assistant\") {\n if (content.startsWith(THINKING_PREFIX)) {\n const detail = content.slice(THINKING_PREFIX.length);\n return {\n ...base,\n type: \"thinking\",\n title: summarizeTitle(detail) || \"Thinking\",\n detail,\n };\n }\n return {\n ...base,\n type: \"assistant\",\n title: summarizeTitle(content) || \"Assistant message\",\n };\n }\n\n if (eventType === \"user\") {\n return {\n ...base,\n type: \"user\",\n title: summarizeTitle(content) || \"User message\",\n };\n }\n\n if (eventType === \"result\") {\n return {\n ...base,\n type: \"result\",\n title: summarizeTitle(content, \"Result\") || \"Result\",\n };\n }\n\n if (eventType === \"error\") {\n return {\n ...base,\n type: \"error\",\n title: summarizeTitle(content, \"Error\") || \"Error\",\n };\n }\n\n if (eventType === \"image_content\") {\n const payload = parseTracePayload(content) || {};\n const mediaType = payload.media_type || \"image/jpeg\";\n const imageSrc = payload.data ? `data:${mediaType};base64,${payload.data}` : \"\";\n return {\n ...base,\n type: \"image_content\",\n title: \"Image output\",\n rows: compact([row(\"Media\", mediaType)]),\n detail: \"[image]\",\n imageSrc,\n };\n }\n\n if (eventType === \"generated_image\") {\n const payload = parseTracePayload(content) || { content };\n const imagePath = payload.path || payload.content || \"\";\n return {\n ...base,\n type: \"generated_image\",\n title: imagePath ? `Generated image: ${basename(imagePath)}` : \"Generated image\",\n rows: compact([row(\"Path\", imagePath), row(\"Media\", payload.media_type)]),\n detail: imagePath,\n };\n }\n\n if (!TRACE_EVENT_TYPES.has(eventType)) {\n return {\n ...base,\n type: \"event\",\n title: summarizeTitle(content, eventType) || eventType,\n };\n }\n\n const payload = parseTracePayload(content) || { content };\n const rows = buildTraceRows(eventType, payload, content);\n return {\n ...base,\n type: eventType,\n title: titleForTraceEvent(eventType, payload),\n rows,\n detail: rows.map((item) => `${item.label}: ${item.value}`).join(\"\\n\"),\n };\n}\n\nfunction titleForTraceEvent(eventType: string, payload: TracePayload): string {\n if (eventType === \"tool_call\") {\n const name = payload.server\n ? `${payload.server}.${payload.name || payload.tool || \"unknown\"}`\n : payload.name || payload.tool || \"unknown\";\n return `Call tool: ${name}`;\n }\n\n if (eventType === \"tool_result\") {\n const label = payload.is_error ? \"Tool error\" : \"Tool result\";\n return `${label}: ${payload.tool_use_id || \"result\"}`;\n }\n\n if (eventType === \"command_execution\") {\n return `Run command: ${payload.command || payload.content || \"command\"}`;\n }\n\n if (eventType === \"web_search\") {\n return `Search web: ${payload.query || payload.content || \"query\"}`;\n }\n\n if (eventType === \"file_change\") {\n const changes = Array.isArray(payload.changes) ? payload.changes : [];\n const firstPath = changes.find(\n (change: any) => change && typeof change === \"object\" && (change.path || change.file),\n );\n return firstPath ? `Change file: ${firstPath.path || firstPath.file}` : \"Change files\";\n }\n\n return eventType;\n}\n\nfunction canMergeSteps(previous: ExecutionStep | undefined, next: ExecutionStep): boolean {\n return Boolean(\n previous &&\n previous.type === next.type &&\n (next.type === \"thinking\" || next.type === \"assistant\") &&\n previous.rawEventType === next.rawEventType,\n );\n}\n\nfunction appendDetail(previous: string, next: string): string {\n if (!previous) return next || \"\";\n if (!next) return previous;\n if (\n previous.endsWith(\"\\n\") ||\n previous.endsWith(\" \") ||\n next.startsWith(\"\\n\") ||\n next.startsWith(\" \")\n ) {\n return previous + next;\n }\n return `${previous}\\n${next}`;\n}\n\nfunction summarizeTitle(text: unknown, prefix = \"\"): string {\n const normalized = String(text || \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n if (!normalized) return prefix;\n const title = normalized.length > 120 ? `${normalized.slice(0, 117).trim()}...` : normalized;\n return prefix ? `${prefix}: ${title}` : title;\n}\n\nfunction basename(value: unknown): string {\n const parts = String(value || \"\")\n .split(/[\\\\/]/)\n .filter(Boolean);\n return parts[parts.length - 1] || String(value || \"\");\n}\n" + ], + "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwBA,SAAS,aAAa,CAAC,eAAe;AAAA,EACpC,IAAa,kBAAT,QAAuC,OAAO,kBAApB;AAAA,IAAmC,OAAO;AAAA,EACxE,gBACG,yBAAyB,cAAc,0BACxC,cAAc;AAAA,EAChB,OAAsB,OAAO,kBAAtB,aAAsC,gBAAgB;AAAA;AAY/D,SAAS,SAAS,CAAC,OAAO,SAAS,SAAS;AAAA,EAC1C,KAAK,QAAQ;AAAA,EACb,KAAK,UAAU;AAAA,EACf,KAAK,OAAO;AAAA,EACZ,KAAK,UAAU,WAAW;AAAA;AAiB5B,SAAS,cAAc,GAAG;AAE1B,SAAS,aAAa,CAAC,OAAO,SAAS,SAAS;AAAA,EAC9C,KAAK,QAAQ;AAAA,EACb,KAAK,UAAU;AAAA,EACf,KAAK,OAAO;AAAA,EACZ,KAAK,UAAU,WAAW;AAAA;AAO5B,SAAS,IAAI,GAAG;AAGhB,SAAS,YAAY,CAAC,MAAM,KAAK,OAAO;AAAA,EACtC,IAAI,UAAU,MAAM;AAAA,EACpB,OAAO;AAAA,IACL,UAAU;AAAA,IACV;AAAA,IACA;AAAA,IACA,KAAgB,YAAN,YAAgB,UAAU;AAAA,IACpC;AAAA,EACF;AAAA;AAEF,SAAS,kBAAkB,CAAC,YAAY,QAAQ;AAAA,EAC9C,OAAO,aAAa,WAAW,MAAM,QAAQ,WAAW,KAAK;AAAA;AAE/D,SAAS,cAAc,CAAC,QAAQ;AAAA,EAC9B,OACe,OAAO,WAApB,YACS,WAAT,QACA,OAAO,aAAa;AAAA;AAGxB,SAAS,MAAM,CAAC,KAAK;AAAA,EACnB,IAAI,gBAAgB,EAAE,KAAK,MAAM,KAAK,KAAK;AAAA,EAC3C,OACE,MACA,IAAI,QAAQ,SAAS,QAAS,CAAC,OAAO;AAAA,IACpC,OAAO,cAAc;AAAA,GACtB;AAAA;AAIL,SAAS,aAAa,CAAC,SAAS,OAAO;AAAA,EACrC,OAAoB,OAAO,YAApB,YAAwC,YAAT,QAA4B,QAAQ,OAAhB,OACtD,OAAO,KAAK,QAAQ,GAAG,IACvB,MAAM,SAAS,EAAE;AAAA;AAEvB,SAAS,eAAe,CAAC,UAAU;AAAA,EACjC,QAAQ,SAAS;AAAA,SACV;AAAA,MACH,OAAO,SAAS;AAAA,SACb;AAAA,MACH,MAAM,SAAS;AAAA;AAAA,MAEf,QACgB,OAAO,SAAS,WAA7B,WACG,SAAS,KAAK,MAAM,IAAI,KACtB,SAAS,SAAS,WACpB,SAAS,KACP,QAAS,CAAC,gBAAgB;AAAA,QACV,SAAS,WAAvB,cACI,SAAS,SAAS,aACnB,SAAS,QAAQ;AAAA,SAEtB,QAAS,CAAC,OAAO;AAAA,QACD,SAAS,WAAvB,cACI,SAAS,SAAS,YAAc,SAAS,SAAS;AAAA,OAE1D,IACJ,SAAS;AAAA,aAEJ;AAAA,UACH,OAAO,SAAS;AAAA,aACb;AAAA,UACH,MAAM,SAAS;AAAA;AAAA;AAAA,EAGvB,MAAM;AAAA;AAER,SAAS,YAAY,CAAC,UAAU,OAAO,eAAe,WAAW,UAAU;AAAA,EACzE,IAAI,OAAO,OAAO;AAAA,EAClB,IAAoB,SAAhB,eAAsC,SAAd;AAAA,IAAoB,WAAW;AAAA,EAC3D,IAAI,iBAAiB;AAAA,EACrB,IAAa,aAAT;AAAA,IAAmB,iBAAiB;AAAA,EAEtC;AAAA,YAAQ;AAAA,WACD;AAAA,WACA;AAAA,WACA;AAAA,QACH,iBAAiB;AAAA,QACjB;AAAA,WACG;AAAA,QACH,QAAQ,SAAS;AAAA,eACV;AAAA,eACA;AAAA,YACH,iBAAiB;AAAA,YACjB;AAAA,eACG;AAAA,YACH,OACG,iBAAiB,SAAS,OAC3B,aACE,eAAe,SAAS,QAAQ,GAChC,OACA,eACA,WACA,QACF;AAAA;AAAA;AAAA,EAIZ,IAAI;AAAA,IACF,OACG,WAAW,SAAS,QAAQ,GAC5B,iBACQ,cAAP,KAAmB,MAAM,cAAc,UAAU,CAAC,IAAI,WACxD,YAAY,QAAQ,KACd,gBAAgB,IACV,kBAAR,SACG,gBACC,eAAe,QAAQ,4BAA4B,KAAK,IAAI,MAChE,aAAa,UAAU,OAAO,eAAe,IAAI,QAAS,CAAC,GAAG;AAAA,MAC5D,OAAO;AAAA,KACR,KACO,YAAR,SACC,eAAe,QAAQ,MACrB,WAAW,mBACV,UACA,iBACW,SAAS,OAAjB,QACA,YAAY,SAAS,QAAQ,SAAS,MACnC,MACC,KAAK,SAAS,KAAK,QAClB,4BACA,KACF,IAAI,OACR,cACJ,IACF,MAAM,KAAK,QAAQ,IACvB;AAAA,EAEJ,iBAAiB;AAAA,EACjB,IAAI,iBAAwB,cAAP,KAAmB,MAAM,YAAY;AAAA,EAC1D,IAAI,YAAY,QAAQ;AAAA,IACtB,SAAS,IAAI,EAAG,IAAI,SAAS,QAAQ;AAAA,MAClC,YAAY,SAAS,IACnB,OAAO,iBAAiB,cAAc,WAAW,CAAC,GAClD,kBAAkB,aACjB,WACA,OACA,eACA,MACA,QACF;AAAA,EACD,SAAM,IAAI,cAAc,QAAQ,GAAmB,OAAO,MAAtB;AAAA,IACvC,KACE,WAAW,EAAE,KAAK,QAAQ,GAAG,IAAI,EACjC,EAAE,YAAY,SAAS,KAAK,GAAG;AAAA,MAG9B,YAAY,UAAU,OACpB,OAAO,iBAAiB,cAAc,WAAW,GAAG,GACpD,kBAAkB,aACjB,WACA,OACA,eACA,MACA,QACF;AAAA,EACD,SAAiB,SAAb,UAAmB;AAAA,IAC1B,IAAmB,OAAO,SAAS,SAA/B;AAAA,MACF,OAAO,aACL,gBAAgB,QAAQ,GACxB,OACA,eACA,WACA,QACF;AAAA,IACF,QAAQ,OAAO,QAAQ;AAAA,IACvB,MAAM,MACJ,qDACyB,UAAtB,oBACG,uBAAuB,OAAO,KAAK,QAAQ,EAAE,KAAK,IAAI,IAAI,MAC1D,SACJ,2EACJ;AAAA,EACF;AAAA,EACA,OAAO;AAAA;AAET,SAAS,WAAW,CAAC,UAAU,MAAM,SAAS;AAAA,EAC5C,IAAY,YAAR;AAAA,IAAkB,OAAO;AAAA,EAC7B,IAAI,SAAS,CAAC,GACZ,QAAQ;AAAA,EACV,aAAa,UAAU,QAAQ,IAAI,IAAI,QAAS,CAAC,OAAO;AAAA,IACtD,OAAO,KAAK,KAAK,SAAS,OAAO,OAAO;AAAA,GACzC;AAAA,EACD,OAAO;AAAA;AAET,SAAS,eAAe,CAAC,SAAS;AAAA,EAChC,IAAW,QAAQ,YAAf,IAAwB;AAAA,IAC1B,IAAI,OAAO,QAAQ;AAAA,IACnB,OAAO,KAAK;AAAA,IACZ,KAAK,KACH,QAAS,CAAC,cAAc;AAAA,MACtB,IAAU,QAAQ,YAAd,KAAgC,QAAQ,YAAf;AAAA,QAC1B,QAAQ,UAAU,GAAK,QAAQ,UAAU;AAAA,OAE9C,QAAS,CAAC,OAAO;AAAA,MACf,IAAU,QAAQ,YAAd,KAAgC,QAAQ,YAAf;AAAA,QAC1B,QAAQ,UAAU,GAAK,QAAQ,UAAU;AAAA,KAEhD;AAAA,IACO,QAAQ,YAAf,OAA4B,QAAQ,UAAU,GAAK,QAAQ,UAAU;AAAA,EACvE;AAAA,EACA,IAAU,QAAQ,YAAd;AAAA,IAAuB,OAAO,QAAQ,QAAQ;AAAA,EAClD,MAAM,QAAQ;AAAA;AAAA,IA7QZ,oBACF,mBACA,qBACA,wBACA,qBACA,qBACA,oBACA,wBACA,qBACA,iBACA,iBACA,qBACA,uBAQE,sBAQF,QACA,aA8BE,wBAIA,aAEA,sBACF,gBA8BE,4BA+KA,mBA6BF,UAiCM,WACA,WACA,YACA,WACA,WACA,gBACA,aACA,WACA,kEAEA,qBAMA,SAAQ,QAAS,CAAC,IAAI;AAAA,EAC5B,OAAO,QAAS,GAAG;AAAA,IACjB,OAAO,GAAG,MAAM,MAAM,SAAS;AAAA;AAAA,GAG3B,eAAc,QAAS,GAAG;AAAA,EAChC,OAAO;AAAA,GAED,gBAAe,QAAS,CAAC,SAAS,QAAQ,UAAU;AAAA,EAC1D,IAAa,YAAT,QAA+B,YAAN;AAAA,IAC3B,MAAM,MACJ,0DAA0D,UAAU,GACtE;AAAA,EACF,IAAI,QAAQ,OAAO,CAAC,GAAG,QAAQ,KAAK,GAClC,MAAM,QAAQ;AAAA,EAChB,IAAY,UAAR;AAAA,IACF,KAAK,YAAwB,OAAO,QAAb,cAAqB,MAAM,KAAK,OAAO,MAAM;AAAA,MAClE,CAAC,eAAe,KAAK,QAAQ,QAAQ,KACzB,aAAV,SACa,aAAb,YACe,aAAf,cACW,aAAV,SAAiC,OAAO,QAAb,cAC3B,MAAM,YAAY,OAAO;AAAA,EAChC,IAAI,WAAW,UAAU,SAAS;AAAA,EAClC,IAAU,aAAN;AAAA,IAAgB,MAAM,WAAW;AAAA,EAChC,SAAI,IAAI,UAAU;AAAA,IACrB,SAAS,aAAa,MAAM,QAAQ,GAAG,IAAI,EAAG,IAAI,UAAU;AAAA,MAC1D,WAAW,KAAK,UAAU,IAAI;AAAA,IAChC,MAAM,WAAW;AAAA,EACnB;AAAA,EACA,OAAO,aAAa,QAAQ,MAAM,KAAK,KAAK;AAAA,GAEtC,iBAAgB,QAAS,CAAC,cAAc;AAAA,EAC9C,eAAe;AAAA,IACb,UAAU;AAAA,IACV,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,cAAc;AAAA,IACd,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA,EACA,aAAa,WAAW;AAAA,EACxB,aAAa,WAAW;AAAA,IACtB,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AAAA,EACA,OAAO;AAAA,GAED,iBAAgB,QAAS,CAAC,MAAM,QAAQ,UAAU;AAAA,EACxD,IAAI,UACF,QAAQ,CAAC,GACT,MAAM;AAAA,EACR,IAAY,UAAR;AAAA,IACF,KAAK,YAAwB,OAAO,QAAb,cAAqB,MAAM,KAAK,OAAO,MAAM;AAAA,MAClE,eAAe,KAAK,QAAQ,QAAQ,KACxB,aAAV,SACa,aAAb,YACe,aAAf,eACC,MAAM,YAAY,OAAO;AAAA,EAChC,IAAI,iBAAiB,UAAU,SAAS;AAAA,EACxC,IAAU,mBAAN;AAAA,IAAsB,MAAM,WAAW;AAAA,EACtC,SAAI,IAAI,gBAAgB;AAAA,IAC3B,SAAS,aAAa,MAAM,cAAc,GAAG,IAAI,EAAG,IAAI,gBAAgB;AAAA,MACtE,WAAW,KAAK,UAAU,IAAI;AAAA,IAChC,MAAM,WAAW;AAAA,EACnB;AAAA,EACA,IAAI,QAAQ,KAAK;AAAA,IACf,KAAK,YAAc,iBAAiB,KAAK,cAAe;AAAA,MAC3C,MAAM,cAAZ,cACF,MAAM,YAAY,eAAe;AAAA,EACxC,OAAO,aAAa,MAAM,KAAK,KAAK;AAAA,GAE9B,aAAY,QAAS,GAAG;AAAA,EAC9B,OAAO,EAAE,SAAS,KAAK;AAAA,GAEjB,cAAa,QAAS,CAAC,QAAQ;AAAA,EACrC,OAAO,EAAE,UAAU,wBAAwB,OAAe;AAAA,GAEpD,iBACA,QAAO,QAAS,CAAC,MAAM;AAAA,EAC7B,OAAO;AAAA,IACL,UAAU;AAAA,IACV,UAAU,EAAE,SAAS,IAAI,SAAS,KAAK;AAAA,IACvC,OAAO;AAAA,EACT;AAAA,GAEM,QAAO,QAAS,CAAC,MAAM,SAAS;AAAA,EACtC,OAAO;AAAA,IACL,UAAU;AAAA,IACV;AAAA,IACA,SAAoB,YAAN,YAAgB,OAAO;AAAA,EACvC;AAAA,GAEM,mBAAkB,QAAS,CAAC,OAAO;AAAA,EACzC,IAAI,iBAAiB,qBAAqB,GACxC,oBAAoB,CAAC;AAAA,EACvB,qBAAqB,IAAI;AAAA,EACzB,IAAI;AAAA,IACF,IAAI,cAAc,MAAM,GACtB,0BAA0B,qBAAqB;AAAA,IACxC,4BAAT,QACE,wBAAwB,mBAAmB,WAAW;AAAA,IAC3C,OAAO,gBAApB,YACW,gBAAT,QACe,OAAO,YAAY,SAAlC,cACA,YAAY,KAAK,MAAM,iBAAiB;AAAA,IAC1C,OAAO,OAAO;AAAA,IACd,kBAAkB,KAAK;AAAA,YACvB;AAAA,IACS,mBAAT,QACW,kBAAkB,UAA3B,SACC,eAAe,QAAQ,kBAAkB,QACzC,qBAAqB,IAAI;AAAA;AAAA,GAGxB,4BAA2B,QAAS,GAAG;AAAA,EAC7C,OAAO,qBAAqB,EAAE,gBAAgB;AAAA,GAExC,OAAM,QAAS,CAAC,QAAQ;AAAA,EAC9B,OAAO,qBAAqB,EAAE,IAAI,MAAM;AAAA,GAElC,kBAAiB,QAAS,CAAC,QAAQ,cAAc,WAAW;AAAA,EAClE,OAAO,qBAAqB,EAAE,eAAe,QAAQ,cAAc,SAAS;AAAA,GAEtE,eAAc,QAAS,CAAC,UAAU,MAAM;AAAA,EAC9C,OAAO,qBAAqB,EAAE,YAAY,UAAU,IAAI;AAAA,GAElD,cAAa,QAAS,CAAC,SAAS;AAAA,EACtC,OAAO,qBAAqB,EAAE,WAAW,OAAO;AAAA,GAE1C,iBAAgB,QAAS,GAAG,IAC5B,oBAAmB,QAAS,CAAC,OAAO,cAAc;AAAA,EACxD,OAAO,qBAAqB,EAAE,iBAAiB,OAAO,YAAY;AAAA,GAE5D,aAAY,QAAS,CAAC,QAAQ,MAAM;AAAA,EAC1C,OAAO,qBAAqB,EAAE,UAAU,QAAQ,IAAI;AAAA,GAE9C,kBAAiB,QAAS,CAAC,UAAU;AAAA,EAC3C,OAAO,qBAAqB,EAAE,eAAe,QAAQ;AAAA,GAE/C,SAAQ,QAAS,GAAG;AAAA,EAC1B,OAAO,qBAAqB,EAAE,MAAM;AAAA,GAE9B,uBAAsB,QAAS,CAAC,KAAK,QAAQ,MAAM;AAAA,EACzD,OAAO,qBAAqB,EAAE,oBAAoB,KAAK,QAAQ,IAAI;AAAA,GAE7D,sBAAqB,QAAS,CAAC,QAAQ,MAAM;AAAA,EACnD,OAAO,qBAAqB,EAAE,mBAAmB,QAAQ,IAAI;AAAA,GAEvD,mBAAkB,QAAS,CAAC,QAAQ,MAAM;AAAA,EAChD,OAAO,qBAAqB,EAAE,gBAAgB,QAAQ,IAAI;AAAA,GAEpD,WAAU,QAAS,CAAC,QAAQ,MAAM;AAAA,EACxC,OAAO,qBAAqB,EAAE,QAAQ,QAAQ,IAAI;AAAA,GAE5C,iBAAgB,QAAS,CAAC,aAAa,SAAS;AAAA,EACtD,OAAO,qBAAqB,EAAE,cAAc,aAAa,OAAO;AAAA,GAE1D,cAAa,QAAS,CAAC,SAAS,YAAY,MAAM;AAAA,EACxD,OAAO,qBAAqB,EAAE,WAAW,SAAS,YAAY,IAAI;AAAA,GAE5D,UAAS,QAAS,CAAC,cAAc;AAAA,EACvC,OAAO,qBAAqB,EAAE,OAAO,YAAY;AAAA,GAE3C,YAAW,QAAS,CAAC,cAAc;AAAA,EACzC,OAAO,qBAAqB,EAAE,SAAS,YAAY;AAAA,GAE7C,wBAAuB,QAAS,CACtC,WACA,aACA,mBACA;AAAA,EACA,OAAO,qBAAqB,EAAE,qBAC5B,WACA,aACA,iBACF;AAAA,GAEM,iBAAgB,QAAS,GAAG;AAAA,EAClC,OAAO,qBAAqB,EAAE,cAAc;AAAA,GAEtC,WAAU;AAAA;AAAA,EAlhBd,qBAAqB,OAAO,IAAI,4BAA4B;AAAA,EAC9D,oBAAoB,OAAO,IAAI,cAAc;AAAA,EAC7C,sBAAsB,OAAO,IAAI,gBAAgB;AAAA,EACjD,yBAAyB,OAAO,IAAI,mBAAmB;AAAA,EACvD,sBAAsB,OAAO,IAAI,gBAAgB;AAAA,EACjD,sBAAsB,OAAO,IAAI,gBAAgB;AAAA,EACjD,qBAAqB,OAAO,IAAI,eAAe;AAAA,EAC/C,yBAAyB,OAAO,IAAI,mBAAmB;AAAA,EACvD,sBAAsB,OAAO,IAAI,gBAAgB;AAAA,EACjD,kBAAkB,OAAO,IAAI,YAAY;AAAA,EACzC,kBAAkB,OAAO,IAAI,YAAY;AAAA,EACzC,sBAAsB,OAAO,IAAI,gBAAgB;AAAA,EACjD,wBAAwB,OAAO;AAAA,EAQ7B,uBAAuB;AAAA,IACvB,WAAW,QAAS,GAAG;AAAA,MACrB,OAAO;AAAA;AAAA,IAET,oBAAoB,QAAS,GAAG;AAAA,IAChC,qBAAqB,QAAS,GAAG;AAAA,IACjC,iBAAiB,QAAS,GAAG;AAAA,EAC/B;AAAA,EACA,SAAS,OAAO;AAAA,EAChB,cAAc,CAAC;AAAA,EAOjB,UAAU,UAAU,mBAAmB,CAAC;AAAA,EACxC,UAAU,UAAU,WAAW,QAAS,CAAC,cAAc,UAAU;AAAA,IAC/D,IACe,OAAO,iBAApB,YACe,OAAO,iBAAtB,cACQ,gBAAR;AAAA,MAEA,MAAM,MACJ,wGACF;AAAA,IACF,KAAK,QAAQ,gBAAgB,MAAM,cAAc,UAAU,UAAU;AAAA;AAAA,EAEvE,UAAU,UAAU,cAAc,QAAS,CAAC,UAAU;AAAA,IACpD,KAAK,QAAQ,mBAAmB,MAAM,UAAU,aAAa;AAAA;AAAA,EAG/D,eAAe,YAAY,UAAU;AAAA,EAOjC,yBAA0B,cAAc,YAAY,IAAI;AAAA,EAC5D,uBAAuB,cAAc;AAAA,EACrC,OAAO,wBAAwB,UAAU,SAAS;AAAA,EAClD,uBAAuB,uBAAuB;AAAA,EAC1C,cAAc,MAAM;AAAA,EAEpB,uBAAuB,EAAE,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK;AAAA,EAC9D,iBAAiB,OAAO,UAAU;AAAA,EA8BhC,6BAA6B;AAAA,EA+K7B,oBACe,OAAO,gBAAtB,aACI,cACA,QAAS,CAAC,OAAO;AAAA,IACf,IACe,OAAO,WAApB,YACe,OAAO,OAAO,eAA7B,YACA;AAAA,MACA,IAAI,QAAQ,IAAI,OAAO,WAAW,SAAS;AAAA,QACzC,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,SACe,OAAO,UAApB,YACS,UAAT,QACa,OAAO,MAAM,YAA1B,WACI,OAAO,MAAM,OAAO,IACpB,OAAO,KAAK;AAAA,QAClB;AAAA,MACF,CAAC;AAAA,MACD,IAAI,CAAC,OAAO,cAAc,KAAK;AAAA,QAAG;AAAA,IACpC,EAAO,SACQ,OAAO,YAApB,YACe,OAAO,QAAQ,SAA9B,YACA;AAAA,MACA,QAAQ,KAAK,qBAAqB,KAAK;AAAA,MACvC;AAAA,IACF;AAAA,IACA,QAAQ,MAAM,KAAK;AAAA;AAAA,EAE3B,WAAW;AAAA,IACT,KAAK;AAAA,IACL,SAAS,QAAS,CAAC,UAAU,aAAa,gBAAgB;AAAA,MACxD,YACE,UACA,QAAS,GAAG;AAAA,QACV,YAAY,MAAM,MAAM,SAAS;AAAA,SAEnC,cACF;AAAA;AAAA,IAEF,OAAO,QAAS,CAAC,UAAU;AAAA,MACzB,IAAI,IAAI;AAAA,MACR,YAAY,UAAU,QAAS,GAAG;AAAA,QAChC;AAAA,OACD;AAAA,MACD,OAAO;AAAA;AAAA,IAET,SAAS,QAAS,CAAC,UAAU;AAAA,MAC3B,OACE,YAAY,UAAU,QAAS,CAAC,OAAO;AAAA,QACrC,OAAO;AAAA,OACR,KAAK,CAAC;AAAA;AAAA,IAGX,MAAM,QAAS,CAAC,UAAU;AAAA,MACxB,IAAI,CAAC,eAAe,QAAQ;AAAA,QAC1B,MAAM,MACJ,uEACF;AAAA,MACF,OAAO;AAAA;AAAA,EAEX;AAAA,EACM,YAAW;AAAA,EACX,YAAW;AAAA,EACX,aAAY;AAAA,EACZ,YAAW;AAAA,EACX,YAAW;AAAA,EACX,iBAAgB;AAAA,EAChB,cAAa;AAAA,EACb,YAAW;AAAA,EACX,mEACN;AAAA,EACM,sBAAqB;AAAA,IAC3B,WAAW;AAAA,IACX,GAAG,QAAS,CAAC,MAAM;AAAA,MACjB,OAAO,qBAAqB,EAAE,aAAa,IAAI;AAAA;AAAA,EAEnD;AAAA,EA+EQ,kBAAiB;AAAA;;;;ECnbE;AAAA,EAD3B,IAAI,MAAuC;AAAA,IACzC,OAAO,UAAkB;AAAA,EAC3B;AAAA;;;;;;;;;;;;;;;;;;;;;;ACOA,SAAS,IAAI,CAAC,MAAM,MAAM;AAAA,EACxB,IAAI,QAAQ,KAAK;AAAA,EACjB,KAAK,KAAK,IAAI;AAAA,EACd;AAAA,IAAG,MAAO,IAAI,SAAS;AAAA,MACrB,IAAI,cAAe,QAAQ,MAAO,GAChC,SAAS,KAAK;AAAA,MAChB,IAAI,IAAI,QAAQ,QAAQ,IAAI;AAAA,QACzB,KAAK,eAAe,MAAQ,KAAK,SAAS,QAAU,QAAQ;AAAA,MAC1D;AAAA;AAAA,IACP;AAAA;AAEF,SAAS,IAAI,CAAC,MAAM;AAAA,EAClB,OAAa,KAAK,WAAX,IAAoB,OAAO,KAAK;AAAA;AAEzC,SAAS,GAAG,CAAC,MAAM;AAAA,EACjB,IAAU,KAAK,WAAX;AAAA,IAAmB,OAAO;AAAA,EAC9B,IAAI,QAAQ,KAAK,IACf,OAAO,KAAK,IAAI;AAAA,EAClB,IAAI,SAAS,OAAO;AAAA,IAClB,KAAK,KAAK;AAAA,IACV;AAAA,MAAG,SACG,QAAQ,GAAG,SAAS,KAAK,QAAQ,aAAa,WAAW,EAC7D,QAAQ,cAER;AAAA,QACA,IAAI,YAAY,KAAK,QAAQ,KAAK,GAChC,OAAO,KAAK,YACZ,aAAa,YAAY,GACzB,QAAQ,KAAK;AAAA,QACf,IAAI,IAAI,QAAQ,MAAM,IAAI;AAAA,UACxB,aAAa,UAAU,IAAI,QAAQ,OAAO,IAAI,KACxC,KAAK,SAAS,OACf,KAAK,cAAc,MACnB,QAAQ,eACP,KAAK,SAAS,MACf,KAAK,aAAa,MAClB,QAAQ;AAAA,QACV,SAAI,aAAa,UAAU,IAAI,QAAQ,OAAO,IAAI;AAAA,UACpD,KAAK,SAAS,OAAS,KAAK,cAAc,MAAQ,QAAQ;AAAA,QACxD;AAAA;AAAA,MACP;AAAA,EACF;AAAA,EACA,OAAO;AAAA;AAET,SAAS,OAAO,CAAC,GAAG,GAAG;AAAA,EACrB,IAAI,OAAO,EAAE,YAAY,EAAE;AAAA,EAC3B,OAAa,SAAN,IAAa,OAAO,EAAE,KAAK,EAAE;AAAA;AA2BtC,SAAS,aAAa,CAAC,aAAa;AAAA,EAClC,SAAS,QAAQ,KAAK,UAAU,EAAY,UAAT,QAAkB;AAAA,IACnD,IAAa,MAAM,aAAf;AAAA,MAAyB,IAAI,UAAU;AAAA,IACtC,SAAI,MAAM,aAAa;AAAA,MAC1B,IAAI,UAAU,GACX,MAAM,YAAY,MAAM,gBACzB,KAAK,WAAW,KAAK;AAAA,IACpB;AAAA;AAAA,IACL,QAAQ,KAAK,UAAU;AAAA,EACzB;AAAA;AAEF,SAAS,aAAa,CAAC,aAAa;AAAA,EAClC,yBAAyB;AAAA,EACzB,cAAc,WAAW;AAAA,EACzB,IAAI,CAAC;AAAA,IACH,IAAa,KAAK,SAAS,MAAvB;AAAA,MACD,0BAA0B,MACzB,yBACI,uBAAuB,MAAK,iCAAiC;AAAA,IAChE;AAAA,MACH,IAAI,aAAa,KAAK,UAAU;AAAA,MACvB,eAAT,QACE,mBAAmB,eAAe,WAAW,YAAY,WAAW;AAAA;AAAA;AAO5E,SAAS,iBAAiB,GAAG;AAAA,EAC3B,OAAO,aACH,OACQ,cAAa,IAAI,YAAY,gBACnC,QACA;AAAA;AAER,SAAS,wBAAwB,GAAG;AAAA,EAClC,aAAa;AAAA,EACb,IAAI,sBAAsB;AAAA,IACxB,IAAI,cAAsB,cAAa;AAAA,IACvC,YAAY;AAAA,IACZ,IAAI,cAAc;AAAA,IAClB,IAAI;AAAA,MACF,GAAG;AAAA,QACD,0BAA0B;AAAA,QAC1B,2BACI,yBAAyB,OAC3B,kBAAkB,aAAa,GAC9B,gBAAgB;AAAA,QACnB,mBAAmB;AAAA,QACnB,IAAI,wBAAwB;AAAA,QAC5B,IAAI;AAAA,UACF,GAAG;AAAA,YACD,cAAc,WAAW;AAAA,YACzB,KACE,cAAc,KAAK,SAAS,EACnB,gBAAT,QACA,EACE,YAAY,iBAAiB,eAAe,kBAAkB,MAGhE;AAAA,cACA,IAAI,WAAW,YAAY;AAAA,cAC3B,IAAmB,OAAO,aAAtB,YAAgC;AAAA,gBAClC,YAAY,WAAW;AAAA,gBACvB,uBAAuB,YAAY;AAAA,gBACnC,IAAI,uBAAuB,SACzB,YAAY,kBAAkB,WAChC;AAAA,gBACA,cAAsB,cAAa;AAAA,gBACnC,IAAmB,OAAO,yBAAtB,YAA4C;AAAA,kBAC9C,YAAY,WAAW;AAAA,kBACvB,cAAc,WAAW;AAAA,kBACzB,cAAc;AAAA,kBACd;AAAA,gBACF;AAAA,gBACA,gBAAgB,KAAK,SAAS,KAAK,IAAI,SAAS;AAAA,gBAChD,cAAc,WAAW;AAAA,cAC3B,EAAO;AAAA,oBAAI,SAAS;AAAA,cACpB,cAAc,KAAK,SAAS;AAAA,YAC9B;AAAA,YACA,IAAa,gBAAT;AAAA,cAAsB,cAAc;AAAA,YACnC;AAAA,cACH,IAAI,aAAa,KAAK,UAAU;AAAA,cACvB,eAAT,QACE,mBACE,eACA,WAAW,YAAY,WACzB;AAAA,cACF,cAAc;AAAA;AAAA,UAElB;AAAA,UACA;AAAA,kBACA;AAAA,UACC,cAAc,MACZ,uBAAuB,uBACvB,mBAAmB;AAAA;AAAA,QAExB,cAAmB;AAAA,MACrB;AAAA,cACA;AAAA,MACA,cACI,iCAAiC,IAChC,uBAAuB;AAAA;AAAA,EAEhC;AAAA;AAkBF,SAAS,kBAAkB,CAAC,UAAU,IAAI;AAAA,EACxC,gBAAgB,gBAAgB,QAAS,GAAG;AAAA,IAC1C,SAAiB,cAAa,CAAC;AAAA,KAC9B,EAAE;AAAA;AAAA,IAvJC,gBAAoB,WAEtB,kBAKA,WACF,aAKA,WACF,YACA,gBAAgB,GAChB,cAAc,MACd,uBAAuB,GACvB,mBAAmB,OACnB,0BAA0B,OAC1B,yBAAyB,OACzB,aAAa,OACb,iBACA,mBACA,mBA0BE,uBAAuB,OACzB,gBAAgB,IAChB,gBAAgB,GAChB,YAAY,IA+EV,kCAME,SACF,MAcI,yBAAwB,GACxB,8BAA6B,GAC7B,wBAAuB,GACvB,2BAA0B,GAC1B,sBAAqB,MACrB,iCAAgC,GAChC,2BAA0B,QAAS,CAAC,MAAM;AAAA,EAChD,KAAK,WAAW;AAAA,GAEV,2BAA0B,QAAS,CAAC,KAAK;AAAA,EAC/C,IAAI,OAAO,MAAM,MACb,QAAQ,MACN,iHACF,IACC,gBAAgB,IAAI,MAAM,KAAK,MAAM,OAAM,GAAG,IAAI;AAAA,GAEjD,oCAAmC,QAAS,GAAG;AAAA,EACrD,OAAO;AAAA,GAED,iBAAgB,QAAS,CAAC,cAAc;AAAA,EAC9C,QAAQ;AAAA,SACD;AAAA,SACA;AAAA,SACA;AAAA,MACH,IAAI,gBAAgB;AAAA,MACpB;AAAA;AAAA,MAEA,gBAAgB;AAAA;AAAA,EAEpB,IAAI,wBAAwB;AAAA,EAC5B,uBAAuB;AAAA,EACvB,IAAI;AAAA,IACF,OAAO,aAAa;AAAA,YACpB;AAAA,IACA,uBAAuB;AAAA;AAAA,GAGnB,yBAAwB,QAAS,GAAG;AAAA,EAC1C,aAAa;AAAA,GAEP,4BAA2B,QAAS,CAAC,eAAe,cAAc;AAAA,EACxE,QAAQ;AAAA,SACD;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH;AAAA;AAAA,MAEA,gBAAgB;AAAA;AAAA,EAEpB,IAAI,wBAAwB;AAAA,EAC5B,uBAAuB;AAAA,EACvB,IAAI;AAAA,IACF,OAAO,aAAa;AAAA,YACpB;AAAA,IACA,uBAAuB;AAAA;AAAA,GAGnB,6BAA4B,QAAS,CAC3C,eACA,UACA,SACA;AAAA,EACA,IAAI,cAAsB,cAAa;AAAA,EAC1B,OAAO,YAApB,YAAwC,YAAT,QACzB,UAAU,QAAQ,OACnB,UACc,OAAO,YAApB,YAA+B,IAAI,UAC/B,cAAc,UACd,eACL,UAAU;AAAA,EACf,QAAQ;AAAA,SACD;AAAA,MACH,IAAI,UAAU;AAAA,MACd;AAAA,SACG;AAAA,MACH,UAAU;AAAA,MACV;AAAA,SACG;AAAA,MACH,UAAU;AAAA,MACV;AAAA,SACG;AAAA,MACH,UAAU;AAAA,MACV;AAAA;AAAA,MAEA,UAAU;AAAA;AAAA,EAEd,UAAU,UAAU;AAAA,EACpB,gBAAgB;AAAA,IACd,IAAI;AAAA,IACJ;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,gBAAgB;AAAA,IAChB,WAAW;AAAA,EACb;AAAA,EACA,UAAU,eACJ,cAAc,YAAY,SAC5B,KAAK,YAAY,aAAa,GACrB,KAAK,SAAS,MAAvB,QACE,kBAAkB,KAAK,UAAU,MAChC,0BACI,kBAAkB,aAAa,GAAI,gBAAgB,MACnD,yBAAyB,MAC9B,mBAAmB,eAAe,UAAU,WAAW,OACvD,cAAc,YAAY,SAC5B,KAAK,WAAW,aAAa,GAC7B,2BACE,qBACE,0BAA0B,MAC5B,yBACI,uBAAuB,MAAK,iCAAiC;AAAA,EACvE,OAAO;AAAA,GAED,uBACA,yBAAwB,QAAS,CAAC,UAAU;AAAA,EAClD,IAAI,sBAAsB;AAAA,EAC1B,OAAO,QAAS,GAAG;AAAA,IACjB,IAAI,wBAAwB;AAAA,IAC5B,uBAAuB;AAAA,IACvB,IAAI;AAAA,MACF,OAAO,SAAS,MAAM,MAAM,SAAS;AAAA,cACrC;AAAA,MACA,uBAAuB;AAAA;AAAA;AAAA;AAAA;AAAA,EApR7B,IAAiB,OAAO,gBAApB,YAAkD,OAAO,YAAY,QAAlC,YAAuC;AAAA,IACxE,mBAAmB;AAAA,IACf,gBAAe,QAAS,GAAG;AAAA,MACjC,OAAO,iBAAiB,IAAI;AAAA;AAAA,EAEhC,EAAO;AAAA,IACD,YAAY,MACd,cAAc,UAAU,IAAI;AAAA,IACtB,gBAAe,QAAS,GAAG;AAAA,MACjC,OAAO,UAAU,IAAI,IAAI;AAAA;AAAA;AAAA,EAGzB,YAAY,CAAC;AAAA,EACf,aAAa,CAAC;AAAA,EAQd,kBAAiC,OAAO,eAAtB,aAAmC,aAAa;AAAA,EAClE,oBAAmC,OAAO,iBAAtB,aAAqC,eAAe;AAAA,EACxE,oBAAoC,OAAO,iBAAvB,cAAsC,eAAe;AAAA,EA6G3E,IAAmB,OAAO,sBAAtB;AAAA,IACF,mCAAmC,QAAS,GAAG;AAAA,MAC7C,kBAAkB,wBAAwB;AAAA;AAAA,EAEzC,SAAoB,OAAO,mBAAvB,aAAuC;AAAA,IAC1C,UAAU,IAAI,gBAChB,OAAO,QAAQ;AAAA,IACjB,QAAQ,MAAM,YAAY;AAAA,IAC1B,mCAAmC,QAAS,GAAG;AAAA,MAC7C,KAAK,YAAY,IAAI;AAAA;AAAA,EAEzB,EACE;AAAA,uCAAmC,QAAS,GAAG;AAAA,MAC7C,gBAAgB,0BAA0B,CAAC;AAAA;AAAA,EA0HvC,wBAAuB;AAAA;;;;ECpUJ;AAAA,EAD3B,IAAI,MAAuC;AAAA,IACzC,OAAO,UAAkB;AAAA,EAC3B;AAAA;;;;;;;;;;;;;;;;;;;;ACQA,SAAS,sBAAsB,CAAC,MAAM;AAAA,EACpC,IAAI,MAAM,8BAA8B;AAAA,EACxC,IAAI,IAAI,UAAU,QAAQ;AAAA,IACxB,OAAO,aAAa,mBAAmB,UAAU,EAAE;AAAA,IACnD,SAAS,IAAI,EAAG,IAAI,UAAU,QAAQ;AAAA,MACpC,OAAO,aAAa,mBAAmB,UAAU,EAAE;AAAA,EACvD;AAAA,EACA,OACE,2BACA,OACA,aACA,MACA;AAAA;AAGJ,SAAS,KAAI,GAAG;AAmBhB,SAAS,cAAc,CAAC,UAAU,eAAe,gBAAgB;AAAA,EAC/D,IAAI,MACF,IAAI,UAAU,UAAqB,UAAU,OAAhB,YAAqB,UAAU,KAAK;AAAA,EACnE,OAAO;AAAA,IACL,UAAU;AAAA,IACV,KAAa,OAAR,OAAc,OAAO,KAAK;AAAA,IAC/B;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA;AAIF,SAAS,sBAAsB,CAAC,IAAI,OAAO;AAAA,EACzC,IAAe,OAAX;AAAA,IAAe,OAAO;AAAA,EAC1B,IAAiB,OAAO,UAApB;AAAA,IACF,OAA6B,UAAtB,oBAA8B,QAAQ;AAAA;AAAA,IAnD7B,OAiBhB,WAiBF,oBAYE,uBAOI,+DAEA,gBAAe,QAAS,CAAC,UAAU,WAAW;AAAA,EACpD,IAAI,MACF,IAAI,UAAU,UAAqB,UAAU,OAAhB,YAAqB,UAAU,KAAK;AAAA,EACnE,IACE,CAAC,aACM,UAAU,aAAhB,KACO,UAAU,aAAhB,KACO,UAAU,aAAjB;AAAA,IAEF,MAAM,MAAM,uBAAuB,GAAG,CAAC;AAAA,EACzC,OAAO,eAAe,UAAU,WAAW,MAAM,GAAG;AAAA,GAE9C,aAAY,QAAS,CAAC,IAAI;AAAA,EAChC,IAAI,qBAAqB,sBAAqB,GAC5C,yBAAyB,UAAU;AAAA,EACrC,IAAI;AAAA,IACF,IAAM,sBAAqB,IAAI,MAAQ,UAAU,IAAI,GAAI;AAAA,MAAK,OAAO,GAAG;AAAA,YACxE;AAAA,IACC,sBAAqB,IAAI,oBACvB,UAAU,IAAI,wBACf,UAAU,EAAE,EAAE;AAAA;AAAA,GAGZ,cAAa,QAAS,CAAC,MAAM,SAAS;AAAA,EAC/B,OAAO,SAApB,aACG,WACK,UAAU,QAAQ,aACnB,UACc,OAAO,YAApB,WAC0B,YAAtB,oBACE,UACA,KACG,aACV,UAAU,MACf,UAAU,EAAE,EAAE,MAAM,OAAO;AAAA,GAEvB,eAAc,QAAS,CAAC,MAAM;AAAA,EACvB,OAAO,SAApB,YAA4B,UAAU,EAAE,EAAE,IAAI;AAAA,GAExC,WAAU,QAAS,CAAC,MAAM,SAAS;AAAA,EACzC,IAAiB,OAAO,SAApB,YAA4B,WAAwB,OAAO,QAAQ,OAA5B,UAAgC;AAAA,IACzE,IAAI,KAAK,QAAQ,IACf,cAAc,uBAAuB,IAAI,QAAQ,WAAW,GAC5D,YACe,OAAO,QAAQ,cAA5B,WAAwC,QAAQ,YAAiB,WACnE,gBACe,OAAO,QAAQ,kBAA5B,WACI,QAAQ,gBACH;AAAA,IACD,OAAZ,UACI,UAAU,EAAE,EACV,MACa,OAAO,QAAQ,eAA5B,WAAyC,QAAQ,aAAkB,WACnE;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,IACF,CACF,IACa,OAAb,YACA,UAAU,EAAE,EAAE,MAAM;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAoB,OAAO,QAAQ,UAA5B,WAAoC,QAAQ,QAAa;AAAA,IAClE,CAAC;AAAA,EACP;AAAA,GAEM,iBAAgB,QAAS,CAAC,MAAM,SAAS;AAAA,EAC/C,IAAiB,OAAO,SAApB;AAAA,IACF,IAAiB,OAAO,YAApB,YAAwC,YAAT,MAAkB;AAAA,MACnD,IAAY,QAAQ,MAAhB,QAAmC,QAAQ,OAArB,UAAyB;AAAA,QACjD,IAAI,cAAc,uBAChB,QAAQ,IACR,QAAQ,WACV;AAAA,QACA,UAAU,EAAE,EAAE,MAAM;AAAA,UAClB;AAAA,UACA,WACe,OAAO,QAAQ,cAA5B,WAAwC,QAAQ,YAAiB;AAAA,UACnE,OAAoB,OAAO,QAAQ,UAA5B,WAAoC,QAAQ,QAAa;AAAA,QAClE,CAAC;AAAA,MACH;AAAA,IACF,EAAO;AAAA,MAAQ,WAAR,QAAmB,UAAU,EAAE,EAAE,IAAI;AAAA,GAExC,WAAU,QAAS,CAAC,MAAM,SAAS;AAAA,EACzC,IACe,OAAO,SAApB,YACa,OAAO,YAApB,YACS,YAAT,QACa,OAAO,QAAQ,OAA5B,UACA;AAAA,IACA,IAAI,KAAK,QAAQ,IACf,cAAc,uBAAuB,IAAI,QAAQ,WAAW;AAAA,IAC9D,UAAU,EAAE,EAAE,MAAM,IAAI;AAAA,MACtB;AAAA,MACA,WACe,OAAO,QAAQ,cAA5B,WAAwC,QAAQ,YAAiB;AAAA,MACnE,OAAoB,OAAO,QAAQ,UAA5B,WAAoC,QAAQ,QAAa;AAAA,MAChE,MAAmB,OAAO,QAAQ,SAA5B,WAAmC,QAAQ,OAAY;AAAA,MAC7D,eACe,OAAO,QAAQ,kBAA5B,WACI,QAAQ,gBACH;AAAA,MACX,gBACe,OAAO,QAAQ,mBAA5B,WACI,QAAQ,iBACH;AAAA,MACX,aACe,OAAO,QAAQ,gBAA5B,WAA0C,QAAQ,cAAmB;AAAA,MACvE,YACe,OAAO,QAAQ,eAA5B,WAAyC,QAAQ,aAAkB;AAAA,MACrE,OAAoB,OAAO,QAAQ,UAA5B,WAAoC,QAAQ,QAAa;AAAA,IAClE,CAAC;AAAA,EACH;AAAA,GAEM,iBAAgB,QAAS,CAAC,MAAM,SAAS;AAAA,EAC/C,IAAiB,OAAO,SAApB;AAAA,IACF,IAAI,SAAS;AAAA,MACX,IAAI,cAAc,uBAAuB,QAAQ,IAAI,QAAQ,WAAW;AAAA,MACxE,UAAU,EAAE,EAAE,MAAM;AAAA,QAClB,IACe,OAAO,QAAQ,OAA5B,YAA+C,QAAQ,OAArB,WAC9B,QAAQ,KACH;AAAA,QACX;AAAA,QACA,WACe,OAAO,QAAQ,cAA5B,WAAwC,QAAQ,YAAiB;AAAA,MACrE,CAAC;AAAA,IACH,EAAO;AAAA,gBAAU,EAAE,EAAE,IAAI;AAAA,GAErB,oBAAmB,QAAS,CAAC,MAAM;AAAA,EACzC,UAAU,EAAE,EAAE,IAAI;AAAA,GAEZ,2BAA0B,QAAS,CAAC,IAAI,GAAG;AAAA,EACjD,OAAO,GAAG,CAAC;AAAA,GAEL,gBAAe,QAAS,CAAC,QAAQ,cAAc,WAAW;AAAA,EAChE,OAAO,sBAAqB,EAAE,aAAa,QAAQ,cAAc,SAAS;AAAA,GAEpE,iBAAgB,QAAS,GAAG;AAAA,EAClC,OAAO,sBAAqB,EAAE,wBAAwB;AAAA,GAEhD,YAAU;AAAA;AAAA,EAtME;AAAA,EAiBhB,YAAY;AAAA,IACZ,GAAG;AAAA,MACD,GAAG;AAAA,MACH,GAAG,QAAS,GAAG;AAAA,QACb,MAAM,MAAM,uBAAuB,GAAG,CAAC;AAAA;AAAA,MAEzC,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,MACH,GAAG;AAAA,IACL;AAAA,IACA,GAAG;AAAA,IACH,aAAa;AAAA,EACf;AAAA,EACA,qBAAoB,OAAO,IAAI,cAAc;AAAA,EAY3C,wBACI;AAAA,EAMA,gEACN;AAAA;;;;EC/ByB;AAAA,EAhC3B,SAAS,QAAQ,GAAG;AAAA,IAElB,IACE,OAAO,mCAAmC,eAC1C,OAAO,+BAA+B,aAAa,YACnD;AAAA,MACA;AAAA,IACF;AAAA,IACA,IAAI,OAAuC,CAS3C;AAAA,IACA,IAAI;AAAA,MAEF,+BAA+B,SAAS,QAAQ;AAAA,MAChD,OAAO,KAAK;AAAA,MAGZ,QAAQ,MAAM,GAAG;AAAA;AAAA;AAAA,EAIrB,IAAI,MAAuC;AAAA,IAGzC,SAAS;AAAA,IACT,OAAO,UAAkB;AAAA,EAC3B;AAAA;;;;;;;;;AClBA,SAAS,uBAAsB,CAAC,MAAM;AAAA,EACpC,IAAI,MAAM,8BAA8B;AAAA,EACxC,IAAI,IAAI,UAAU,QAAQ;AAAA,IACxB,OAAO,aAAa,mBAAmB,UAAU,EAAE;AAAA,IACnD,SAAS,IAAI,EAAG,IAAI,UAAU,QAAQ;AAAA,MACpC,OAAO,aAAa,mBAAmB,UAAU,EAAE;AAAA,EACvD;AAAA,EACA,OACE,2BACA,OACA,aACA,MACA;AAAA;AAGJ,SAAS,gBAAgB,CAAC,MAAM;AAAA,EAC9B,OAAO,EACL,CAAC,QACM,KAAK,aAAX,KAA6B,KAAK,aAAX,KAA8B,KAAK,aAAZ;AAAA;AAGnD,SAAS,sBAAsB,CAAC,OAAO;AAAA,EACrC,IAAI,OAAO,OACT,iBAAiB;AAAA,EACnB,IAAI,MAAM;AAAA,IAAW,MAAO,KAAK;AAAA,MAAU,OAAO,KAAK;AAAA,EAClD;AAAA,IACH,QAAQ;AAAA,IACR;AAAA,MACG,OAAO,QACC,KAAK,QAAQ,UAApB,MAA8B,iBAAiB,KAAK,SACnD,QAAQ,KAAK;AAAA,WACX;AAAA;AAAA,EAET,OAAa,KAAK,QAAX,IAAiB,iBAAiB;AAAA;AAE3C,SAAS,4BAA4B,CAAC,OAAO;AAAA,EAC3C,IAAW,MAAM,QAAb,IAAkB;AAAA,IACpB,IAAI,gBAAgB,MAAM;AAAA,IACjB,kBAAT,SACI,QAAQ,MAAM,WACP,UAAT,SAAmB,gBAAgB,MAAM;AAAA,IAC3C,IAAa,kBAAT;AAAA,MAAwB,OAAO,cAAc;AAAA,EACnD;AAAA,EACA,OAAO;AAAA;AAET,SAAS,4BAA4B,CAAC,OAAO;AAAA,EAC3C,IAAW,MAAM,QAAb,IAAkB;AAAA,IACpB,IAAI,gBAAgB,MAAM;AAAA,IACjB,kBAAT,SACI,QAAQ,MAAM,WACP,UAAT,SAAmB,gBAAgB,MAAM;AAAA,IAC3C,IAAa,kBAAT;AAAA,MAAwB,OAAO,cAAc;AAAA,EACnD;AAAA,EACA,OAAO;AAAA;AAET,SAAS,eAAe,CAAC,OAAO;AAAA,EAC9B,IAAI,uBAAuB,KAAK,MAAM;AAAA,IACpC,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA;AAE3C,SAAS,6BAA6B,CAAC,OAAO;AAAA,EAC5C,IAAI,YAAY,MAAM;AAAA,EACtB,IAAI,CAAC,WAAW;AAAA,IACd,YAAY,uBAAuB,KAAK;AAAA,IACxC,IAAa,cAAT;AAAA,MAAoB,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,IAC/D,OAAO,cAAc,QAAQ,OAAO;AAAA,EACtC;AAAA,EACA,SAAS,IAAI,OAAO,IAAI,cAAe;AAAA,IACrC,IAAI,UAAU,EAAE;AAAA,IAChB,IAAa,YAAT;AAAA,MAAkB;AAAA,IACtB,IAAI,UAAU,QAAQ;AAAA,IACtB,IAAa,YAAT,MAAkB;AAAA,MACpB,IAAI,QAAQ;AAAA,MACZ,IAAa,MAAT,MAAY;AAAA,QACd,IAAI;AAAA,QACJ;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,IACA,IAAI,QAAQ,UAAU,QAAQ,OAAO;AAAA,MACnC,KAAK,UAAU,QAAQ,MAAO,WAAW;AAAA,QACvC,IAAI,YAAY;AAAA,UAAG,OAAO,gBAAgB,OAAO,GAAG;AAAA,QACpD,IAAI,YAAY;AAAA,UAAG,OAAO,gBAAgB,OAAO,GAAG;AAAA,QACpD,UAAU,QAAQ;AAAA,MACpB;AAAA,MACA,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,IACzC;AAAA,IACA,IAAI,EAAE,WAAW,EAAE;AAAA,MAAS,IAAI,SAAW,IAAI;AAAA,IAC1C;AAAA,MACH,SAAS,eAAe,OAAI,UAAU,QAAQ,MAAO,WAAW;AAAA,QAC9D,IAAI,YAAY,GAAG;AAAA,UACjB,eAAe;AAAA,UACf,IAAI;AAAA,UACJ,IAAI;AAAA,UACJ;AAAA,QACF;AAAA,QACA,IAAI,YAAY,GAAG;AAAA,UACjB,eAAe;AAAA,UACf,IAAI;AAAA,UACJ,IAAI;AAAA,UACJ;AAAA,QACF;AAAA,QACA,UAAU,QAAQ;AAAA,MACpB;AAAA,MACA,IAAI,CAAC,cAAc;AAAA,QACjB,KAAK,UAAU,QAAQ,MAAO,WAAW;AAAA,UACvC,IAAI,YAAY,GAAG;AAAA,YACjB,eAAe;AAAA,YACf,IAAI;AAAA,YACJ,IAAI;AAAA,YACJ;AAAA,UACF;AAAA,UACA,IAAI,YAAY,GAAG;AAAA,YACjB,eAAe;AAAA,YACf,IAAI;AAAA,YACJ,IAAI;AAAA,YACJ;AAAA,UACF;AAAA,UACA,UAAU,QAAQ;AAAA,QACpB;AAAA,QACA,IAAI,CAAC;AAAA,UAAc,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,MAC5D;AAAA;AAAA,IAEF,IAAI,EAAE,cAAc;AAAA,MAAG,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,EAChE;AAAA,EACA,IAAU,EAAE,QAAR;AAAA,IAAa,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,EACxD,OAAO,EAAE,UAAU,YAAY,IAAI,QAAQ;AAAA;AAE7C,SAAS,wBAAwB,CAAC,MAAM;AAAA,EACtC,IAAI,MAAM,KAAK;AAAA,EACf,IAAU,QAAN,KAAoB,QAAP,MAAqB,QAAP,MAAoB,QAAN;AAAA,IAAW,OAAO;AAAA,EAC/D,KAAK,OAAO,KAAK,MAAgB,SAAT,QAAiB;AAAA,IACvC,MAAM,yBAAyB,IAAI;AAAA,IACnC,IAAa,QAAT;AAAA,MAAc,OAAO;AAAA,IACzB,OAAO,KAAK;AAAA,EACd;AAAA,EACA,OAAO;AAAA;AAuBT,SAAS,cAAa,CAAC,eAAe;AAAA,EACpC,IAAa,kBAAT,QAAuC,OAAO,kBAApB;AAAA,IAAmC,OAAO;AAAA,EACxE,gBACG,0BAAyB,cAAc,2BACxC,cAAc;AAAA,EAChB,OAAsB,OAAO,kBAAtB,aAAsC,gBAAgB;AAAA;AAG/D,SAAS,wBAAwB,CAAC,MAAM;AAAA,EACtC,IAAY,QAAR;AAAA,IAAc,OAAO;AAAA,EACzB,IAAmB,OAAO,SAAtB;AAAA,IACF,OAAO,KAAK,aAAa,yBACrB,OACA,KAAK,eAAe,KAAK,QAAQ;AAAA,EACvC,IAAiB,OAAO,SAApB;AAAA,IAA0B,OAAO;AAAA,EACrC,QAAQ;AAAA,SACD;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA;AAAA,EAEX,IAAiB,OAAO,SAApB;AAAA,IACF,QAAQ,KAAK;AAAA,WACN;AAAA,QACH,OAAO;AAAA,WACJ;AAAA,QACH,OAAO,KAAK,eAAe;AAAA,WACxB;AAAA,QACH,QAAQ,KAAK,SAAS,eAAe,aAAa;AAAA,WAC/C;AAAA,QACH,IAAI,YAAY,KAAK;AAAA,QACrB,OAAO,KAAK;AAAA,QACZ,SACI,OAAO,UAAU,eAAe,UAAU,QAAQ,IACnD,OAAc,SAAP,KAAc,gBAAgB,OAAO,MAAM;AAAA,QACrD,OAAO;AAAA,WACJ;AAAA,QACH,OACG,YAAY,KAAK,eAAe,MACxB,cAAT,OACI,YACA,yBAAyB,KAAK,IAAI,KAAK;AAAA,WAE1C;AAAA,QACH,YAAY,KAAK;AAAA,QACjB,OAAO,KAAK;AAAA,QACZ,IAAI;AAAA,UACF,OAAO,yBAAyB,KAAK,SAAS,CAAC;AAAA,UAC/C,OAAO,GAAG;AAAA;AAAA,EAElB,OAAO;AAAA;AAeT,SAAS,YAAY,CAAC,cAAc;AAAA,EAClC,OAAO,EAAE,SAAS,aAAa;AAAA;AAEjC,SAAS,IAAG,CAAC,QAAQ;AAAA,EACnB,IAAI,UACA,OAAO,UAAU,WAAW,QAAU,WAAW,SAAS,MAAO;AAAA;AAEvE,SAAS,KAAI,CAAC,QAAQ,OAAO;AAAA,EAC3B;AAAA,EACA,WAAW,SAAS,OAAO;AAAA,EAC3B,OAAO,UAAU;AAAA;AAMnB,SAAS,iBAAiB,CAAC,OAAO,kBAAkB;AAAA,EAClD,MAAK,yBAAyB,gBAAgB;AAAA,EAC9C,MAAK,yBAAyB,KAAK;AAAA,EACnC,MAAK,oBAAoB,IAAI;AAAA,EAC7B,QAAQ,iBAAiB;AAAA,SAClB;AAAA,SACA;AAAA,MACH,SAAS,QAAQ,iBAAiB,oBAC7B,QAAQ,MAAM,gBACb,kBAAkB,KAAK,IACvB,IACF;AAAA,MACJ;AAAA;AAAA,MAEA,IACI,QAAQ,iBAAiB,SAC1B,mBAAmB,iBAAiB;AAAA,QAEpC,mBAAmB,kBAAkB,gBAAgB,GACnD,QAAQ,wBAAwB,kBAAkB,KAAK;AAAA,MAE1D;AAAA,gBAAQ;AAAA,eACD;AAAA,YACH,QAAQ;AAAA,YACR;AAAA,eACG;AAAA,YACH,QAAQ;AAAA,YACR;AAAA;AAAA,YAEA,QAAQ;AAAA;AAAA;AAAA,EAGlB,KAAI,kBAAkB;AAAA,EACtB,MAAK,oBAAoB,KAAK;AAAA;AAEhC,SAAS,gBAAgB,GAAG;AAAA,EAC1B,KAAI,kBAAkB;AAAA,EACtB,KAAI,uBAAuB;AAAA,EAC3B,KAAI,uBAAuB;AAAA;AAE7B,SAAS,eAAe,CAAC,OAAO;AAAA,EACrB,MAAM,kBAAf,QAAgC,MAAK,8BAA8B,KAAK;AAAA,EACxE,IAAI,UAAU,mBAAmB;AAAA,EACjC,IAAI,2BAA2B,wBAAwB,SAAS,MAAM,IAAI;AAAA,EAC1E,YAAY,6BACT,MAAK,yBAAyB,KAAK,GACpC,MAAK,oBAAoB,wBAAwB;AAAA;AAErD,SAAS,cAAc,CAAC,OAAO;AAAA,EAC7B,wBAAwB,YAAY,UACjC,KAAI,kBAAkB,GAAG,KAAI,uBAAuB;AAAA,EACvD,6BAA6B,YAAY,UACtC,KAAI,4BAA4B,GAChC,sBAAsB,gBAAgB;AAAA;AAG3C,SAAS,6BAA6B,CAAC,MAAM;AAAA,EAC3C,IAAe,WAAN;AAAA,IACP,IAAI;AAAA,MACF,MAAM,MAAM;AAAA,MACZ,OAAO,GAAG;AAAA,MACV,IAAI,QAAQ,EAAE,MAAM,KAAK,EAAE,MAAM,cAAc;AAAA,MAC/C,SAAU,SAAS,MAAM,MAAO;AAAA,MAChC,SACE,KAAK,EAAE,MAAM,QAAQ;AAAA,OAAU,IAC3B,mBACA,KAAK,EAAE,MAAM,QAAQ,GAAG,IACtB,iBACA;AAAA;AAAA,EAEZ,OAAO;AAAA,IAAO,SAAS,OAAO;AAAA;AAGhC,SAAS,4BAA4B,CAAC,IAAI,WAAW;AAAA,EACnD,IAAI,CAAC,MAAM;AAAA,IAAS,OAAO;AAAA,EAC3B,UAAU;AAAA,EACV,IAAI,4BAA4B,MAAM;AAAA,EACtC,MAAM,oBAAyB;AAAA,EAC/B,IAAI;AAAA,IACF,IAAI,iBAAiB;AAAA,MACnB,6BAA6B,QAAS,GAAG;AAAA,QACvC,IAAI;AAAA,UACF,IAAI,WAAW;AAAA,YACb,IAAI,OAAO,QAAS,GAAG;AAAA,cACrB,MAAM,MAAM;AAAA;AAAA,YAEd,OAAO,eAAe,KAAK,WAAW,SAAS;AAAA,cAC7C,KAAK,QAAS,GAAG;AAAA,gBACf,MAAM,MAAM;AAAA;AAAA,YAEhB,CAAC;AAAA,YACD,IAAiB,OAAO,YAApB,YAA+B,QAAQ,WAAW;AAAA,cACpD,IAAI;AAAA,gBACF,QAAQ,UAAU,MAAM,CAAC,CAAC;AAAA,gBAC1B,OAAO,GAAG;AAAA,gBACV,IAAI,UAAU;AAAA;AAAA,cAEhB,QAAQ,UAAU,IAAI,CAAC,GAAG,IAAI;AAAA,YAChC,EAAO;AAAA,cACL,IAAI;AAAA,gBACF,KAAK,KAAK;AAAA,gBACV,OAAO,KAAK;AAAA,gBACZ,UAAU;AAAA;AAAA,cAEZ,GAAG,KAAK,KAAK,SAAS;AAAA;AAAA,UAE1B,EAAO;AAAA,YACL,IAAI;AAAA,cACF,MAAM,MAAM;AAAA,cACZ,OAAO,KAAK;AAAA,cACZ,UAAU;AAAA;AAAA,aAEX,OAAO,GAAG,MACM,OAAO,KAAK,UAA3B,cACA,KAAK,MAAM,QAAS,GAAG,EAAE;AAAA;AAAA,UAE7B,OAAO,QAAQ;AAAA,UACf,IAAI,UAAU,WAAwB,OAAO,OAAO,UAA3B;AAAA,YACvB,OAAO,CAAC,OAAO,OAAO,QAAQ,KAAK;AAAA;AAAA,QAEvC,OAAO,CAAC,MAAM,IAAI;AAAA;AAAA,IAEtB;AAAA,IACA,eAAe,4BAA4B,cACzC;AAAA,IACF,IAAI,qBAAqB,OAAO,yBAC9B,eAAe,6BACf,MACF;AAAA,IACA,sBACE,mBAAmB,gBACnB,OAAO,eACL,eAAe,6BACf,QACA,EAAE,OAAO,8BAA8B,CACzC;AAAA,IACF,IAAI,wBAAwB,eAAe,4BAA4B,GACrE,cAAc,sBAAsB,IACpC,eAAe,sBAAsB;AAAA,IACvC,IAAI,eAAe,cAAc;AAAA,MAC/B,IAAI,cAAc,YAAY,MAAM;AAAA,CAAI,GACtC,eAAe,aAAa,MAAM;AAAA,CAAI;AAAA,MACxC,KACE,qBAAqB,iBAAiB,EACtC,iBAAiB,YAAY,UAC7B,CAAC,YAAY,gBAAgB,SAAS,6BAA6B;AAAA,QAGnE;AAAA,MACF,MAEE,qBAAqB,aAAa,UAClC,CAAC,aAAa,oBAAoB,SAChC,6BACF;AAAA,QAGA;AAAA,MACF,IACE,mBAAmB,YAAY,UAC/B,uBAAuB,aAAa;AAAA,QAEpC,KACE,iBAAiB,YAAY,SAAS,GACpC,qBAAqB,aAAa,SAAS,EAC7C,KAAK,kBACL,KAAK,sBACL,YAAY,oBAAoB,aAAa;AAAA,UAG7C;AAAA,MACJ,MAEE,KAAK,kBAAkB,KAAK,oBAC5B,kBAAkB;AAAA,QAElB,IAAI,YAAY,oBAAoB,aAAa,qBAAqB;AAAA,UACpE,IAAU,mBAAN,KAA8B,uBAAN,GAA0B;AAAA,YACpD;AAAA,cACE,IACG,kBACD,sBACA,IAAI,sBACF,YAAY,oBACV,aAAa,qBACjB;AAAA,gBACA,IAAI,QACF;AAAA,IACA,YAAY,gBAAgB,QAAQ,YAAY,MAAM;AAAA,gBACxD,GAAG,eACD,MAAM,SAAS,aAAa,MAC3B,QAAQ,MAAM,QAAQ,eAAe,GAAG,WAAW;AAAA,gBACtD,OAAO;AAAA,cACT;AAAA,mBACK,KAAK,kBAAkB,KAAK;AAAA,UACrC;AAAA,UACA;AAAA,QACF;AAAA,IACJ;AAAA,YACA;AAAA,IACC,UAAU,OAAM,MAAM,oBAAoB;AAAA;AAAA,EAE7C,QAAQ,4BAA4B,KAAK,GAAG,eAAe,GAAG,OAAO,MACjE,8BAA8B,yBAAyB,IACvD;AAAA;AAEN,SAAS,aAAa,CAAC,OAAO,YAAY;AAAA,EACxC,QAAQ,MAAM;AAAA,SACP;AAAA,SACA;AAAA,SACA;AAAA,MACH,OAAO,8BAA8B,MAAM,IAAI;AAAA,SAC5C;AAAA,MACH,OAAO,8BAA8B,MAAM;AAAA,SACxC;AAAA,MACH,OAAO,MAAM,UAAU,cAAuB,eAAT,OACjC,8BAA8B,mBAAmB,IACjD,8BAA8B,UAAU;AAAA,SACzC;AAAA,MACH,OAAO,8BAA8B,cAAc;AAAA,SAChD;AAAA,SACA;AAAA,MACH,OAAO,6BAA6B,MAAM,MAAM,KAAE;AAAA,SAC/C;AAAA,MACH,OAAO,6BAA6B,MAAM,KAAK,QAAQ,KAAE;AAAA,SACtD;AAAA,MACH,OAAO,6BAA6B,MAAM,MAAM,IAAE;AAAA,SAC/C;AAAA,MACH,OAAO,8BAA8B,UAAU;AAAA;AAAA,MAE/C,OAAO;AAAA;AAAA;AAGb,SAAS,2BAA2B,CAAC,gBAAgB;AAAA,EACnD,IAAI;AAAA,IACF,IAAI,OAAO,IACT,WAAW;AAAA,IACb;AAAA,MACG,QAAQ,cAAc,gBAAgB,QAAQ,GAC5C,WAAW,gBACX,iBAAiB,eAAe;AAAA,WAC9B;AAAA,IACP,OAAO;AAAA,IACP,OAAO,GAAG;AAAA,IACV,OAAO;AAAA,4BAA+B,EAAE,UAAU;AAAA,IAAO,EAAE;AAAA;AAAA;AAmB/D,SAAS,0BAA0B,CAAC,iBAAiB;AAAA,EACpC,OAAO,UAAtB,cAA+B,+BAA8B,eAAe;AAAA,EAC5E,IAAI,gBAA+B,OAAO,aAAa,kBAAnC;AAAA,IAClB,IAAI;AAAA,MACF,aAAa,cAAc,YAAY,eAAe;AAAA,MACtD,OAAO,KAAK;AAAA;AAKlB,SAAS,aAAa,CAAC,GAAG;AAAA,EACxB,OAAO;AAAA,EACP,OAAa,MAAN,IAAU,KAAM,MAAO,KAAI,CAAC,IAAI,MAAO,KAAM;AAAA;AAKtD,SAAS,uBAAuB,CAAC,OAAO;AAAA,EACtC,IAAI,mBAAmB,QAAQ;AAAA,EAC/B,IAAU,qBAAN;AAAA,IAAwB,OAAO;AAAA,EACnC,QAAQ,QAAQ,CAAC;AAAA,SACV;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH,OAAO,QAAQ;AAAA,SACZ;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH,OAAO,QAAQ;AAAA,SACZ;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH,OAAO,QAAQ;AAAA,SACZ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA;AAAA,MAEP,OAAO;AAAA;AAAA;AAGb,SAAS,YAAY,CAAC,MAAM,UAAU,sBAAsB;AAAA,EAC1D,IAAI,eAAe,KAAK;AAAA,EACxB,IAAU,iBAAN;AAAA,IAAoB,OAAO;AAAA,EAC/B,IAAI,YAAY,GACd,iBAAiB,KAAK,gBACtB,cAAc,KAAK;AAAA,EACrB,OAAO,KAAK;AAAA,EACZ,IAAI,sBAAsB,eAAe;AAAA,EACnC,wBAAN,KACM,eAAe,sBAAsB,CAAC,gBAClC,iBAAN,IACK,YAAY,wBAAwB,YAAY,KAC/C,eAAe,qBACX,gBAAN,IACK,YAAY,wBAAwB,WAAW,IAChD,yBACE,uBAAuB,sBAAsB,CAAC,MAC1C,yBAAN,MACG,YAAY,wBAAwB,oBAAoB,SACjE,sBAAsB,eAAe,CAAC,gBAClC,wBAAN,IACK,YAAY,wBAAwB,mBAAmB,IAClD,gBAAN,IACG,YAAY,wBAAwB,WAAW,IAChD,yBACE,uBAAuB,eAAe,CAAC,MACnC,yBAAN,MACG,YAAY,wBAAwB,oBAAoB;AAAA,EACrE,OAAa,cAAN,IACH,IACM,aAAN,KACE,aAAa,cACN,WAAW,oBAAlB,MACE,iBAAiB,YAAY,CAAC,WAC/B,uBAAuB,WAAW,CAAC,UACpC,kBAAkB,wBACR,mBAAP,OAAgC,uBAAuB,aAA9B,KAC5B,WACA;AAAA;AAER,SAAS,yBAAyB,CAAC,MAAM,aAAa;AAAA,EACpD,QAEG,KAAK,eACJ,EAAE,KAAK,iBAAiB,CAAC,KAAK,eAC9B,iBAHF;AAAA;AAMJ,SAAS,qBAAqB,CAAC,MAAM,aAAa;AAAA,EAChD,QAAQ;AAAA,SACD;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH,OAAO,cAAc;AAAA,SAClB;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH,OAAO,cAAc;AAAA,SAClB;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH,OAAO;AAAA;AAAA,MAEP,OAAO;AAAA;AAAA;AAGb,SAAS,kBAAkB,GAAG;AAAA,EAC5B,IAAI,OAAO;AAAA,EACX,kBAAkB;AAAA,GACX,gBAAgB,cAAvB,MAAqC,gBAAgB;AAAA,EACrD,OAAO;AAAA;AAET,SAAS,aAAa,CAAC,SAAS;AAAA,EAC9B,SAAS,UAAU,CAAC,GAAG,IAAI,EAAG,KAAK,GAAG;AAAA,IAAK,QAAQ,KAAK,OAAO;AAAA,EAC/D,OAAO;AAAA;AAET,SAAS,iBAAiB,CAAC,MAAM,YAAY;AAAA,EAC3C,KAAK,gBAAgB;AAAA,EACP,eAAd,cACI,KAAK,iBAAiB,GAAK,KAAK,cAAc,GAAK,KAAK,YAAY;AAAA;AAE1E,SAAS,gBAAgB,CACvB,MACA,eACA,gBACA,aACA,cACA,qBACA;AAAA,EACA,IAAI,yBAAyB,KAAK;AAAA,EAClC,KAAK,eAAe;AAAA,EACpB,KAAK,iBAAiB;AAAA,EACtB,KAAK,cAAc;AAAA,EACnB,KAAK,YAAY;AAAA,EACjB,KAAK,gBAAgB;AAAA,EACrB,KAAK,kBAAkB;AAAA,EACvB,KAAK,8BAA8B;AAAA,EACnC,KAAK,sBAAsB;AAAA,EAC3B,MAAyB,eACA,iBACF,kBADH;AAAA,EAEpB,KACE,iBAAiB,yBAAyB,CAAC,eAC3C,IAAI,kBAEJ;AAAA,IACA,IAAI,UAAU,KAAK,MAAM,cAAc,GACrC,OAAO,KAAK;AAAA,IACd,cAAc,WAAW;AAAA,IACzB,gBAAgB,WAAW;AAAA,IAC3B,IAAI,uBAAuB,cAAc;AAAA,IACzC,IAAa,yBAAT;AAAA,MACF,KACE,cAAc,WAAW,MAAM,UAAU,EACzC,UAAU,qBAAqB,QAC/B,WACA;AAAA,QACA,IAAI,SAAS,qBAAqB;AAAA,QACzB,WAAT,SAAoB,OAAO,QAAQ;AAAA,MACrC;AAAA,IACF,kBAAkB,CAAC;AAAA,EACrB;AAAA,EACM,gBAAN,KAAqB,wBAAwB,MAAM,aAAa,CAAC;AAAA,EAC3D,wBAAN,KACQ,iBAAN,KACM,KAAK,QAAX,MACC,KAAK,kBACJ,sBAAsB,EAAE,yBAAyB,CAAC;AAAA;AAExD,SAAS,uBAAuB,CAAC,MAAM,aAAa,gBAAgB;AAAA,EAClE,KAAK,gBAAgB;AAAA,EACrB,KAAK,kBAAkB,CAAC;AAAA,EACxB,IAAI,mBAAmB,KAAK,MAAM,WAAW;AAAA,EAC7C,KAAK,kBAAkB;AAAA,EACvB,KAAK,cAAc,oBACjB,KAAK,cAAc,oBACnB,aACC,iBAAiB;AAAA;AAEtB,SAAS,iBAAiB,CAAC,MAAM,gBAAgB;AAAA,EAC/C,IAAI,qBAAsB,KAAK,kBAAkB;AAAA,EACjD,KAAK,OAAO,KAAK,cAAe,sBAAsB;AAAA,IACpD,IAAI,UAAU,KAAK,MAAM,kBAAkB,GACzC,OAAO,KAAK;AAAA,IACb,OAAO,iBAAmB,KAAK,WAAW,mBACxC,KAAK,YAAY;AAAA,IACpB,sBAAsB,CAAC;AAAA,EACzB;AAAA;AAEF,SAAS,yBAAyB,CAAC,MAAM,aAAa;AAAA,EACpD,IAAI,aAAa,cAAc,CAAC;AAAA,EAChC,cACS,aAAa,QAApB,IAA0B,IAAI,gCAAgC,UAAU;AAAA,EAC1E,QAAc,cAAc,KAAK,iBAAiB,kBAA3C,IACH,IACA;AAAA;AAEN,SAAS,+BAA+B,CAAC,MAAM;AAAA,EAC7C,QAAQ;AAAA,SACD;AAAA,MACH,OAAO;AAAA,MACP;AAAA,SACG;AAAA,MACH,OAAO;AAAA,MACP;AAAA,SACG;AAAA,MACH,OAAO;AAAA,MACP;AAAA,SACG;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH,OAAO;AAAA,MACP;AAAA,SACG;AAAA,MACH,OAAO;AAAA,MACP;AAAA;AAAA,MAEA,OAAO;AAAA;AAAA,EAEX,OAAO;AAAA;AAET,SAAS,oBAAoB,CAAC,OAAO;AAAA,EACnC,SAAS,CAAC;AAAA,EACV,OAAO,IAAI,QACP,IAAI,SACK,QAAQ,eAAf,IACE,KACA,YACF,IACF;AAAA;AAEN,SAAS,qBAAqB,GAAG;AAAA,EAC/B,IAAI,iBAAiB,wBAAwB;AAAA,EAC7C,IAAU,mBAAN;AAAA,IAAsB,OAAO;AAAA,EACjC,iBAAiB,OAAO;AAAA,EACxB,OAAkB,mBAAN,YAAuB,KAAK,iBAAiB,eAAe,IAAI;AAAA;AAE9E,SAAS,eAAe,CAAC,UAAU,IAAI;AAAA,EACrC,IAAI,mBAAmB,wBAAwB;AAAA,EAC/C,IAAI;AAAA,IACF,OAAQ,wBAAwB,IAAI,UAAW,GAAG;AAAA,YAClD;AAAA,IACA,wBAAwB,IAAI;AAAA;AAAA;AAYhC,SAAS,qBAAqB,CAAC,MAAM;AAAA,EACnC,OAAO,KAAK;AAAA,EACZ,OAAO,KAAK;AAAA,EACZ,OAAO,KAAK;AAAA,EACZ,OAAO,KAAK;AAAA,EACZ,OAAO,KAAK;AAAA;AAEd,SAAS,0BAA0B,CAAC,YAAY;AAAA,EAC9C,IAAI,aAAa,WAAW;AAAA,EAC5B,IAAI;AAAA,IAAY,OAAO;AAAA,EACvB,SAAS,aAAa,WAAW,WAAY,cAAc;AAAA,IACzD,IACG,aACC,WAAW,iCACX,WAAW,sBACb;AAAA,MACA,aAAa,WAAW;AAAA,MACxB,IACW,WAAW,UAApB,QACU,eAAT,QAAgC,WAAW,UAApB;AAAA,QAExB,KACE,aAAa,2BAA2B,UAAU,EACzC,eAAT,QAEA;AAAA,UACA,IAAK,aAAa,WAAW;AAAA,YAAuB,OAAO;AAAA,UAC3D,aAAa,2BAA2B,UAAU;AAAA,QACpD;AAAA,MACF,OAAO;AAAA,IACT;AAAA,IACA,aAAa;AAAA,IACb,aAAa,WAAW;AAAA,EAC1B;AAAA,EACA,OAAO;AAAA;AAET,SAAS,mBAAmB,CAAC,MAAM;AAAA,EACjC,IACG,OAAO,KAAK,wBAAwB,KAAK,+BAC1C;AAAA,IACA,IAAI,MAAM,KAAK;AAAA,IACf,IACQ,QAAN,KACM,QAAN,KACO,QAAP,MACO,QAAP,MACO,QAAP,MACO,QAAP,MACM,QAAN;AAAA,MAEA,OAAO;AAAA,EACX;AAAA,EACA,OAAO;AAAA;AAET,SAAS,mBAAmB,CAAC,MAAM;AAAA,EACjC,IAAI,MAAM,KAAK;AAAA,EACf,IAAU,QAAN,KAAoB,QAAP,MAAqB,QAAP,MAAoB,QAAN;AAAA,IAAW,OAAO,KAAK;AAAA,EACpE,MAAM,MAAM,wBAAuB,EAAE,CAAC;AAAA;AAExC,SAAS,oBAAoB,CAAC,MAAM;AAAA,EAClC,IAAI,YAAY,KAAK;AAAA,EACrB,cACG,YAAY,KAAK,gCAChB,EAAE,iBAAiB,IAAI,KAAO,kBAAkB,IAAI,IAAM;AAAA,EAC9D,OAAO;AAAA;AAET,SAAS,mBAAmB,CAAC,MAAM;AAAA,EACjC,KAAK,2BAA2B;AAAA;AAIlC,SAAS,qBAAqB,CAAC,kBAAkB,cAAc;AAAA,EAC7D,oBAAoB,kBAAkB,YAAY;AAAA,EAClD,oBAAoB,mBAAmB,WAAW,YAAY;AAAA;AAEhE,SAAS,mBAAmB,CAAC,kBAAkB,cAAc;AAAA,EAC3D,6BAA6B,oBAAoB;AAAA,EACjD,KACE,mBAAmB,EACnB,mBAAmB,aAAa,QAChC;AAAA,IAEA,gBAAgB,IAAI,aAAa,iBAAiB;AAAA;AAOtD,SAAS,mBAAmB,CAAC,eAAe;AAAA,EAC1C,IAAI,gBAAe,KAAK,6BAA6B,aAAa;AAAA,IAChE,OAAO;AAAA,EACT,IAAI,gBAAe,KAAK,2BAA2B,aAAa;AAAA,IAAG,OAAO;AAAA,EAC1E,IAAI,2BAA2B,KAAK,aAAa;AAAA,IAC/C,OAAQ,4BAA4B,iBAAiB;AAAA,EACvD,0BAA0B,iBAAiB;AAAA,EAC3C,OAAO;AAAA;AAET,SAAS,oBAAoB,CAAC,MAAM,MAAM,OAAO;AAAA,EAC/C,IAAI,oBAAoB,IAAI;AAAA,IAC1B,IAAa,UAAT;AAAA,MAAgB,KAAK,gBAAgB,IAAI;AAAA,IACxC;AAAA,MACH,QAAQ,OAAO;AAAA,aACR;AAAA,aACA;AAAA,aACA;AAAA,UACH,KAAK,gBAAgB,IAAI;AAAA,UACzB;AAAA,aACG;AAAA,UACH,IAAI,YAAY,KAAK,YAAY,EAAE,MAAM,GAAG,CAAC;AAAA,UAC7C,IAAgB,cAAZ,WAAqC,cAAZ,SAAuB;AAAA,YAClD,KAAK,gBAAgB,IAAI;AAAA,YACzB;AAAA,UACF;AAAA;AAAA,MAEJ,KAAK,aAAa,MAAM,KAAK,KAAK;AAAA;AAAA;AAGxC,SAAS,yBAAyB,CAAC,MAAM,MAAM,OAAO;AAAA,EACpD,IAAa,UAAT;AAAA,IAAgB,KAAK,gBAAgB,IAAI;AAAA,EACxC;AAAA,IACH,QAAQ,OAAO;AAAA,WACR;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,QACH,KAAK,gBAAgB,IAAI;AAAA,QACzB;AAAA;AAAA,IAEJ,KAAK,aAAa,MAAM,KAAK,KAAK;AAAA;AAAA;AAGtC,SAAS,8BAA8B,CAAC,MAAM,WAAW,MAAM,OAAO;AAAA,EACpE,IAAa,UAAT;AAAA,IAAgB,KAAK,gBAAgB,IAAI;AAAA,EACxC;AAAA,IACH,QAAQ,OAAO;AAAA,WACR;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,QACH,KAAK,gBAAgB,IAAI;AAAA,QACzB;AAAA;AAAA,IAEJ,KAAK,eAAe,WAAW,MAAM,KAAK,KAAK;AAAA;AAAA;AAGnD,SAAS,gBAAgB,CAAC,OAAO;AAAA,EAC/B,QAAQ,OAAO;AAAA,SACR;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA;AAAA,MAEP,OAAO;AAAA;AAAA;AAGb,SAAS,WAAW,CAAC,MAAM;AAAA,EACzB,IAAI,OAAO,KAAK;AAAA,EAChB,QACG,OAAO,KAAK,aACD,KAAK,YAAY,MAA7B,YACgB,SAAf,cAAmC,SAAZ;AAAA;AAG5B,SAAS,gBAAgB,CAAC,MAAM,YAAY,cAAc;AAAA,EACxD,IAAI,aAAa,OAAO,yBACtB,KAAK,YAAY,WACjB,UACF;AAAA,EACA,IACE,CAAC,KAAK,eAAe,UAAU,KACf,OAAO,eAAvB,eACe,OAAO,WAAW,QAAjC,cACe,OAAO,WAAW,QAAjC,YACA;AAAA,IACA,MAAqB,KACF,QAAX;AAAA,IACR,OAAO,eAAe,MAAM,YAAY;AAAA,MACtC,cAAc;AAAA,MACd,KAAK,QAAS,GAAG;AAAA,QACf,OAAO,IAAI,KAAK,IAAI;AAAA;AAAA,MAEtB,KAAK,QAAS,CAAC,OAAO;AAAA,QACpB,eAAe,KAAK;AAAA,QACpB,IAAI,KAAK,MAAM,KAAK;AAAA;AAAA,IAExB,CAAC;AAAA,IACD,OAAO,eAAe,MAAM,YAAY;AAAA,MACtC,YAAY,WAAW;AAAA,IACzB,CAAC;AAAA,IACD,OAAO;AAAA,MACL,UAAU,QAAS,GAAG;AAAA,QACpB,OAAO;AAAA;AAAA,MAET,UAAU,QAAS,CAAC,OAAO;AAAA,QACzB,eAAe,KAAK;AAAA;AAAA,MAEtB,cAAc,QAAS,GAAG;AAAA,QACxB,KAAK,gBAAgB;AAAA,QACrB,OAAO,KAAK;AAAA;AAAA,IAEhB;AAAA,EACF;AAAA;AAEF,SAAS,KAAK,CAAC,MAAM;AAAA,EACnB,IAAI,CAAC,KAAK,eAAe;AAAA,IACvB,IAAI,aAAa,YAAY,IAAI,IAAI,YAAY;AAAA,IACjD,KAAK,gBAAgB,iBACnB,MACA,YACA,KAAK,KAAK,WACZ;AAAA,EACF;AAAA;AAEF,SAAS,oBAAoB,CAAC,MAAM;AAAA,EAClC,IAAI,CAAC;AAAA,IAAM,OAAO;AAAA,EAClB,IAAI,UAAU,KAAK;AAAA,EACnB,IAAI,CAAC;AAAA,IAAS,OAAO;AAAA,EACrB,IAAI,YAAY,QAAQ,SAAS;AAAA,EACjC,IAAI,QAAQ;AAAA,EACZ,SACG,QAAQ,YAAY,IAAI,IACrB,KAAK,UACH,SACA,UACF,KAAK;AAAA,EACX,OAAO;AAAA,EACP,OAAO,SAAS,aAAa,QAAQ,SAAS,IAAI,GAAG,QAAM;AAAA;AAE7D,SAAS,gBAAgB,CAAC,KAAK;AAAA,EAC7B,MAAM,QAAwB,OAAO,aAAvB,cAAkC,WAAgB;AAAA,EAChE,IAAoB,OAAO,QAAvB;AAAA,IAA4B,OAAO;AAAA,EACvC,IAAI;AAAA,IACF,OAAO,IAAI,iBAAiB,IAAI;AAAA,IAChC,OAAO,GAAG;AAAA,IACV,OAAO,IAAI;AAAA;AAAA;AAIf,SAAS,8CAA8C,CAAC,OAAO;AAAA,EAC7D,OAAO,MAAM,QACX,qDACA,QAAS,CAAC,IAAI;AAAA,IACZ,OAAO,OAAO,GAAG,WAAW,CAAC,EAAE,SAAS,EAAE,IAAI;AAAA,GAElD;AAAA;AAEF,SAAS,WAAW,CAClB,SACA,OACA,cACA,kBACA,SACA,gBACA,MACA,MACA;AAAA,EACA,QAAQ,OAAO;AAAA,EACP,QAAR,QACe,OAAO,SAAtB,cACa,OAAO,SAApB,YACc,OAAO,SAArB,YACK,QAAQ,OAAO,OAChB,QAAQ,gBAAgB,MAAM;AAAA,EAClC,IAAY,SAAR;AAAA,IACF,IAAiB,SAAb,UAAmB;AAAA,MACrB,IAAW,UAAN,KAAsB,QAAQ,UAAf,MAAyB,QAAQ,SAAS;AAAA,QAC5D,QAAQ,QAAQ,KAAK,iBAAiB,KAAK;AAAA,IAC/C,EACE;AAAA,cAAQ,UAAU,KAAK,iBAAiB,KAAK,MAC1C,QAAQ,QAAQ,KAAK,iBAAiB,KAAK;AAAA,EAEhD;AAAA,IAAc,SAAb,YAAiC,SAAZ,WAAqB,QAAQ,gBAAgB,OAAO;AAAA,EACpE,SAAR,OACI,gBAAgB,SAAS,MAAM,iBAAiB,KAAK,CAAC,IAC9C,gBAAR,OACE,gBAAgB,SAAS,MAAM,iBAAiB,YAAY,CAAC,IACrD,oBAAR,QAA4B,QAAQ,gBAAgB,OAAO;AAAA,EACzD,WAAR,QACU,kBAAR,SACC,QAAQ,iBAAiB,CAAC,CAAC;AAAA,EACtB,WAAR,SACG,QAAQ,UACP,WAA0B,OAAO,YAAtB,cAA8C,OAAO,YAApB;AAAA,EACxC,QAAR,QACe,OAAO,SAAtB,cACa,OAAO,SAApB,YACc,OAAO,SAArB,YACK,QAAQ,OAAO,KAAK,iBAAiB,IAAI,IAC1C,QAAQ,gBAAgB,MAAM;AAAA;AAEpC,SAAS,SAAS,CAChB,SACA,OACA,cACA,SACA,gBACA,MACA,MACA,aACA;AAAA,EACQ,QAAR,QACiB,OAAO,SAAtB,cACa,OAAO,SAApB,YACc,OAAO,SAArB,cACC,QAAQ,OAAO;AAAA,EAClB,IAAY,SAAR,QAAyB,gBAAR,MAAsB;AAAA,IACzC,IACE,EACgB,SAAb,YAAiC,SAAZ,WACV,UAAN,aAAwB,UAAT,OAEvB;AAAA,MACA,MAAM,OAAO;AAAA,MACb;AAAA,IACF;AAAA,IACA,eACU,gBAAR,OAAuB,KAAK,iBAAiB,YAAY,IAAI;AAAA,IAC/D,QAAgB,SAAR,OAAgB,KAAK,iBAAiB,KAAK,IAAI;AAAA,IACvD,eAAe,UAAU,QAAQ,UAAU,QAAQ,QAAQ;AAAA,IAC3D,QAAQ,eAAe;AAAA,EACzB;AAAA,EACA,UAAkB,WAAR,OAAkB,UAAU;AAAA,EACtC,UACiB,OAAO,YAAtB,cAA8C,OAAO,YAApB,YAA+B,CAAC,CAAC;AAAA,EACpE,QAAQ,UAAU,cAAc,QAAQ,UAAU,CAAC,CAAC;AAAA,EACpD,QAAQ,iBAAiB,CAAC,CAAC;AAAA,EACnB,QAAR,QACiB,OAAO,SAAtB,cACa,OAAO,SAApB,YACc,OAAO,SAArB,cACC,QAAQ,OAAO;AAAA,EAClB,MAAM,OAAO;AAAA;AAEf,SAAS,eAAe,CAAC,MAAM,MAAM,OAAO;AAAA,EAC5B,SAAb,YAAqB,iBAAiB,KAAK,aAAa,MAAM,QAC7D,KAAK,iBAAiB,KAAK,UAC1B,KAAK,eAAe,KAAK;AAAA;AAE9B,SAAS,aAAa,CAAC,MAAM,UAAU,WAAW,oBAAoB;AAAA,EACpE,OAAO,KAAK;AAAA,EACZ,IAAI,UAAU;AAAA,IACZ,WAAW,CAAC;AAAA,IACZ,SAAS,IAAI,EAAG,IAAI,UAAU,QAAQ;AAAA,MACpC,SAAS,MAAM,UAAU,MAAM;AAAA,IACjC,KAAK,YAAY,EAAG,YAAY,KAAK,QAAQ;AAAA,MAC1C,IAAI,SAAS,eAAe,MAAM,KAAK,WAAW,KAAK,GACtD,KAAK,WAAW,aAAa,MAAM,KAAK,WAAW,WAAW,IAC9D,KAAK,uBAAuB,KAAK,WAAW,kBAAkB;AAAA,EACpE,EAAO;AAAA,IACL,YAAY,KAAK,iBAAiB,SAAS;AAAA,IAC3C,WAAW;AAAA,IACX,KAAK,IAAI,EAAG,IAAI,KAAK,QAAQ,KAAK;AAAA,MAChC,IAAI,KAAK,GAAG,UAAU,WAAW;AAAA,QAC/B,KAAK,GAAG,WAAW;AAAA,QACnB,uBAAuB,KAAK,GAAG,kBAAkB;AAAA,QACjD;AAAA,MACF;AAAA,MACS,aAAT,QAAqB,KAAK,GAAG,aAAa,WAAW,KAAK;AAAA,IAC5D;AAAA,IACS,aAAT,SAAsB,SAAS,WAAW;AAAA;AAAA;AAG9C,SAAS,cAAc,CAAC,SAAS,OAAO,cAAc;AAAA,EACpD,IACU,SAAR,SACE,QAAQ,KAAK,iBAAiB,KAAK,GACrC,UAAU,QAAQ,UAAU,QAAQ,QAAQ,QACpC,gBAAR,OACA;AAAA,IACA,QAAQ,iBAAiB,UAAU,QAAQ,eAAe;AAAA,IAC1D;AAAA,EACF;AAAA,EACA,QAAQ,eACE,gBAAR,OAAuB,KAAK,iBAAiB,YAAY,IAAI;AAAA;AAEjE,SAAS,YAAY,CAAC,SAAS,OAAO,cAAc,UAAU;AAAA,EAC5D,IAAY,SAAR,MAAe;AAAA,IACjB,IAAY,YAAR,MAAkB;AAAA,MACpB,IAAY,gBAAR;AAAA,QAAsB,MAAM,MAAM,wBAAuB,EAAE,CAAC;AAAA,MAChE,IAAI,aAAY,QAAQ,GAAG;AAAA,QACzB,IAAI,IAAI,SAAS;AAAA,UAAQ,MAAM,MAAM,wBAAuB,EAAE,CAAC;AAAA,QAC/D,WAAW,SAAS;AAAA,MACtB;AAAA,MACA,eAAe;AAAA,IACjB;AAAA,IACQ,gBAAR,SAAyB,eAAe;AAAA,IACxC,QAAQ;AAAA,EACV;AAAA,EACA,eAAe,iBAAiB,KAAK;AAAA,EACrC,QAAQ,eAAe;AAAA,EACvB,WAAW,QAAQ;AAAA,EACnB,aAAa,gBACJ,aAAP,MACS,aAAT,SACC,QAAQ,QAAQ;AAAA,EACnB,MAAM,OAAO;AAAA;AAEf,SAAS,cAAc,CAAC,MAAM,MAAM;AAAA,EAClC,IAAI,MAAM;AAAA,IACR,IAAI,aAAa,KAAK;AAAA,IACtB,IACE,cACA,eAAe,KAAK,aACd,WAAW,aAAjB,GACA;AAAA,MACA,WAAW,YAAY;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AAAA,EACA,KAAK,cAAc;AAAA;AAOrB,SAAS,gBAAgB,CAAC,OAAO,WAAW,OAAO;AAAA,EACjD,IAAI,mBAAyB,UAAU,QAAQ,IAAI,MAA5B;AAAA,EACf,SAAR,QAA+B,OAAO,UAArB,aAAqC,UAAP,KAC3C,mBACE,MAAM,YAAY,WAAW,EAAE,IACnB,cAAZ,UACG,MAAM,WAAW,KACjB,MAAM,aAAa,KACxB,mBACE,MAAM,YAAY,WAAW,KAAK,IACrB,OAAO,UAApB,YACQ,UAAN,KACA,gBAAgB,IAAI,SAAS,IACjB,cAAZ,UACG,MAAM,WAAW,QACjB,MAAM,cAAc,KAAK,OAAO,KAAK,IACvC,MAAM,aAAa,QAAQ;AAAA;AAEtC,SAAS,iBAAiB,CAAC,MAAM,QAAQ,YAAY;AAAA,EACnD,IAAY,UAAR,QAA+B,OAAO,WAApB;AAAA,IACpB,MAAM,MAAM,wBAAuB,EAAE,CAAC;AAAA,EACxC,OAAO,KAAK;AAAA,EACZ,IAAY,cAAR,MAAoB;AAAA,IACtB,SAAS,aAAa;AAAA,MACpB,CAAC,WAAW,eAAe,SAAS,KACzB,UAAR,QAAkB,OAAO,eAAe,SAAS,MAC3C,UAAU,QAAQ,IAAI,MAA5B,IACG,KAAK,YAAY,WAAW,EAAE,IAClB,cAAZ,UACG,KAAK,WAAW,KAChB,KAAK,aAAa;AAAA,IAC7B,SAAS,gBAAgB;AAAA,MACtB,YAAY,OAAO,eAClB,OAAO,eAAe,YAAY,KAChC,WAAW,kBAAkB,aAC7B,iBAAiB,MAAM,cAAc,SAAS;AAAA,EACtD,EACE;AAAA,aAAS,gBAAgB;AAAA,MACvB,OAAO,eAAe,YAAY,KAChC,iBAAiB,MAAM,cAAc,OAAO,aAAa;AAAA;AAEjE,SAAS,eAAe,CAAC,SAAS;AAAA,EAChC,IAAW,QAAQ,QAAQ,GAAG,MAA1B;AAAA,IAA6B,OAAO;AAAA,EACxC,QAAQ;AAAA,SACD;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH,OAAO;AAAA;AAAA,MAEP,OAAO;AAAA;AAAA;AAqFb,SAAS,WAAW,CAAC,KAAK;AAAA,EACxB,OAAO,qBAAqB,KAAK,KAAK,GAAG,IACrC,gGACA;AAAA;AAEN,SAAS,MAAM,GAAG;AAElB,SAAS,cAAc,CAAC,aAAa;AAAA,EACnC,cAAc,YAAY,UAAU,YAAY,cAAc;AAAA,EAC9D,YAAY,4BACT,cAAc,YAAY;AAAA,EAC7B,OAAa,YAAY,aAAlB,IAA6B,YAAY,aAAa;AAAA;AAI/D,SAAS,oBAAoB,CAAC,QAAQ;AAAA,EACpC,IAAI,mBAAmB,oBAAoB,MAAM;AAAA,EACjD,IAAI,qBAAqB,SAAS,iBAAiB,YAAY;AAAA,IAC7D,IAAI,QAAQ,OAAO,qBAAqB;AAAA,IACxC;AAAA,MAAG,QAAU,SAAS,iBAAiB,WAAY,iBAAiB;AAAA,aAC7D;AAAA,UACH,YACE,QACA,MAAM,OACN,MAAM,cACN,MAAM,cACN,MAAM,SACN,MAAM,gBACN,MAAM,MACN,MAAM,IACR;AAAA,UACA,mBAAmB,MAAM;AAAA,UACzB,IAAgB,MAAM,SAAlB,WAAkC,oBAAR,MAA0B;AAAA,YACtD,KAAK,QAAQ,OAAQ,MAAM;AAAA,cAAc,QAAQ,MAAM;AAAA,YACvD,QAAQ,MAAM,iBACZ,iBACE,+CACE,KAAK,gBACP,IACA,kBACJ;AAAA,YACA,KACE,mBAAmB,EACnB,mBAAmB,MAAM,QACzB,oBACA;AAAA,cACA,IAAI,YAAY,MAAM;AAAA,cACtB,IAAI,cAAc,UAAU,UAAU,SAAS,OAAO,MAAM;AAAA,gBAC1D,IAAI,aAAa,UAAU,qBAAqB;AAAA,gBAChD,IAAI,CAAC;AAAA,kBAAY,MAAM,MAAM,wBAAuB,EAAE,CAAC;AAAA,gBACvD,YACE,WACA,WAAW,OACX,WAAW,cACX,WAAW,cACX,WAAW,SACX,WAAW,gBACX,WAAW,MACX,WAAW,IACb;AAAA,cACF;AAAA,YACF;AAAA,YACA,KACE,mBAAmB,EACnB,mBAAmB,MAAM,QACzB;AAAA,cAEC,YAAY,MAAM,mBACjB,UAAU,SAAS,OAAO,QAAQ,qBAAqB,SAAS;AAAA,UACtE;AAAA,UACA;AAAA,aACG;AAAA,UACH,eAAe,QAAQ,MAAM,OAAO,MAAM,YAAY;AAAA,UACtD;AAAA,aACG;AAAA,UACF,mBAAmB,MAAM,OAChB,oBAAR,QACE,cAAc,QAAQ,CAAC,CAAC,MAAM,UAAU,kBAAkB,KAAE;AAAA;AAAA,EAEtE;AAAA;AAGF,SAAS,gBAAgB,CAAC,IAAI,GAAG,GAAG;AAAA,EAClC,IAAI;AAAA,IAAsB,OAAO,GAAG,GAAG,CAAC;AAAA,EACxC,uBAAuB;AAAA,EACvB,IAAI;AAAA,IACF,IAAI,2BAA2B,GAAG,CAAC;AAAA,IACnC,OAAO;AAAA,YACP;AAAA,IACA,IACI,uBAAuB,OAChB,kBAAT,QAAmC,iBAAT;AAAA,MAE1B,IACG,gBAAgB,GACjB,kBACI,IAAI,eACL,KAAK,cACL,eAAe,gBAAgB,MAChC,qBAAqB,CAAC,GACtB;AAAA,QAEF,KAAK,IAAI,EAAG,IAAI,GAAG,QAAQ;AAAA,UAAK,qBAAqB,GAAG,EAAE;AAAA;AAAA;AAAA;AAGlE,SAAS,WAAW,CAAC,MAAM,kBAAkB;AAAA,EAC3C,IAAI,YAAY,KAAK;AAAA,EACrB,IAAa,cAAT;AAAA,IAAoB,OAAO;AAAA,EAC/B,IAAI,QAAQ,UAAU,qBAAqB;AAAA,EAC3C,IAAa,UAAT;AAAA,IAAgB,OAAO;AAAA,EAC3B,YAAY,MAAM;AAAA,EAClB;AAAA,IAAG,QAAQ;AAAA,WACJ;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,SACF,QAAQ,CAAC,MAAM,cACZ,OAAO,KAAK,MACb,QAAQ,EACM,SAAb,YACY,SAAZ,WACa,SAAb,YACe,SAAf;AAAA,QAEJ,OAAO,CAAC;AAAA,QACR;AAAA;AAAA,QAEA,OAAO;AAAA;AAAA,EAEX,IAAI;AAAA,IAAM,OAAO;AAAA,EACjB,IAAI,aAA4B,OAAO,cAAtB;AAAA,IACf,MAAM,MACJ,wBAAuB,KAAK,kBAAkB,OAAO,SAAS,CAChE;AAAA,EACF,OAAO;AAAA;AAwBT,SAAS,OAAO,GAAG;AAAA,EACjB,IAAI;AAAA,IAAc,OAAO;AAAA,EACzB,IAAI,OACF,aAAa,WACb,cAAc,WAAW,QACzB,KACA,WAAW,WAAW,OAAO,KAAK,QAAQ,KAAK,aAC/C,YAAY,SAAS;AAAA,EACvB,KACE,QAAQ,EACR,QAAQ,eAAe,WAAW,WAAW,SAAS,QACtD;AAAA;AAAA,EAEF,IAAI,SAAS,cAAc;AAAA,EAC3B,KACE,MAAM,EACN,OAAO,UACP,WAAW,cAAc,SAAS,SAAS,YAAY,MACvD;AAAA;AAAA,EAEF,OAAQ,eAAe,SAAS,MAAM,OAAO,IAAI,MAAM,IAAI,MAAW,SAAC;AAAA;AAEzE,SAAS,gBAAgB,CAAC,aAAa;AAAA,EACrC,IAAI,UAAU,YAAY;AAAA,EAC1B,cAAc,eACR,cAAc,YAAY,UACtB,gBAAN,KAA4B,YAAP,OAAmB,cAAc,OACrD,cAAc;AAAA,EACZ,gBAAP,OAAuB,cAAc;AAAA,EACrC,OAAO,MAAM,eAAsB,gBAAP,KAAqB,cAAc;AAAA;AAEjE,SAAS,uBAAuB,GAAG;AAAA,EACjC,OAAO;AAAA;AAET,SAAS,wBAAwB,GAAG;AAAA,EAClC,OAAO;AAAA;AAET,SAAS,oBAAoB,CAAC,WAAW;AAAA,EACvC,SAAS,kBAAkB,CACzB,WACA,gBACA,YACA,aACA,mBACA;AAAA,IACA,KAAK,aAAa;AAAA,IAClB,KAAK,cAAc;AAAA,IACnB,KAAK,OAAO;AAAA,IACZ,KAAK,cAAc;AAAA,IACnB,KAAK,SAAS;AAAA,IACd,KAAK,gBAAgB;AAAA,IACrB,SAAS,YAAY;AAAA,MACnB,UAAU,eAAe,QAAQ,MAC7B,YAAY,UAAU,WACvB,KAAK,YAAY,YACd,UAAU,WAAW,IACrB,YAAY;AAAA,IACpB,KAAK,sBACK,YAAY,oBAApB,OACI,YAAY,mBACL,YAAY,gBAAnB,SAEF,0BACA;AAAA,IACJ,KAAK,uBAAuB;AAAA,IAC5B,OAAO;AAAA;AAAA,EAET,QAAO,mBAAmB,WAAW;AAAA,IACnC,gBAAgB,QAAS,GAAG;AAAA,MAC1B,KAAK,mBAAmB;AAAA,MACxB,IAAI,QAAQ,KAAK;AAAA,MACjB,UACG,MAAM,iBACH,MAAM,eAAe,IACP,OAAO,MAAM,gBAA3B,cAA2C,MAAM,cAAc,QAClE,KAAK,qBAAqB;AAAA;AAAA,IAE/B,iBAAiB,QAAS,GAAG;AAAA,MAC3B,IAAI,QAAQ,KAAK;AAAA,MACjB,UACG,MAAM,kBACH,MAAM,gBAAgB,IACR,OAAO,MAAM,iBAA3B,cACC,MAAM,eAAe,OACzB,KAAK,uBAAuB;AAAA;AAAA,IAEjC,SAAS,QAAS,GAAG;AAAA,IACrB,cAAc;AAAA,EAChB,CAAC;AAAA,EACD,OAAO;AAAA;AAoIT,SAAS,mBAAmB,CAAC,QAAQ;AAAA,EACnC,IAAI,cAAc,KAAK;AAAA,EACvB,OAAO,YAAY,mBACf,YAAY,iBAAiB,MAAM,KAClC,SAAS,kBAAkB,WAC1B,CAAC,CAAC,YAAY,UACd;AAAA;AAER,SAAS,qBAAqB,GAAG;AAAA,EAC/B,OAAO;AAAA;AA8GT,SAAS,wBAAwB,CAAC,cAAc,aAAa;AAAA,EAC3D,QAAQ;AAAA,SACD;AAAA,MACH,OAAc,aAAa,QAAQ,YAAY,OAAO,MAA/C;AAAA,SACJ;AAAA,MACH,OAAe,YAAY,YAApB;AAAA,SACJ;AAAA,SACA;AAAA,SACA;AAAA,MACH,OAAO;AAAA;AAAA,MAEP,OAAO;AAAA;AAAA;AAGb,SAAS,sBAAsB,CAAC,aAAa;AAAA,EAC3C,cAAc,YAAY;AAAA,EAC1B,OAAoB,OAAO,gBAApB,YAAmC,UAAU,cAChD,YAAY,OACZ;AAAA;AAGN,SAAS,yBAAyB,CAAC,cAAc,aAAa;AAAA,EAC5D,QAAQ;AAAA,SACD;AAAA,MACH,OAAO,uBAAuB,WAAW;AAAA,SACtC;AAAA,MACH,IAAW,YAAY,UAAnB;AAAA,QAA0B,OAAO;AAAA,MACrC,mBAAmB;AAAA,MACnB,OAAO;AAAA,SACJ;AAAA,MACH,OACG,eAAe,YAAY,MAC5B,iBAAiB,iBAAiB,mBAAmB,OAAO;AAAA;AAAA,MAG9D,OAAO;AAAA;AAAA;AAGb,SAAS,2BAA2B,CAAC,cAAc,aAAa;AAAA,EAC9D,IAAI;AAAA,IACF,OAA4B,iBAArB,oBACJ,CAAC,0BACA,yBAAyB,cAAc,WAAW,KAChD,eAAe,QAAQ,GACxB,eAAe,YAAY,OAAO,MAClC,cAAc,OACf,gBACA;AAAA,EACN,QAAQ;AAAA,SACD;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,IACE,EAAE,YAAY,WAAW,YAAY,UAAU,YAAY,YAC1D,YAAY,WAAW,YAAY,QACpC;AAAA,QACA,IAAI,YAAY,QAAQ,IAAI,YAAY,KAAK;AAAA,UAC3C,OAAO,YAAY;AAAA,QACrB,IAAI,YAAY;AAAA,UAAO,OAAO,OAAO,aAAa,YAAY,KAAK;AAAA,MACrE;AAAA,MACA,OAAO;AAAA,SACJ;AAAA,MACH,OAAO,8BAAuC,YAAY,WAArB,OACjC,OACA,YAAY;AAAA;AAAA,MAEhB,OAAO;AAAA;AAAA;AAoBb,SAAS,kBAAkB,CAAC,MAAM;AAAA,EAChC,IAAI,WAAW,QAAQ,KAAK,YAAY,KAAK,SAAS,YAAY;AAAA,EAClE,OAAmB,aAAZ,UACH,CAAC,CAAC,oBAAoB,KAAK,QACZ,aAAf,aACE,OACA;AAAA;AAER,SAAS,8BAA8B,CACrC,eACA,MACA,aACA,QACA;AAAA,EACA,gBACI,eACE,aAAa,KAAK,MAAM,IACvB,eAAe,CAAC,MAAM,IACxB,gBAAgB;AAAA,EACrB,OAAO,4BAA4B,MAAM,UAAU;AAAA,EACnD,IAAI,KAAK,WACL,cAAc,IAAI,eAClB,YACA,UACA,MACA,aACA,MACF,GACA,cAAc,KAAK,EAAE,OAAO,aAAa,WAAW,KAAK,CAAC;AAAA;AAI9D,SAAS,eAAe,CAAC,eAAe;AAAA,EACtC,qBAAqB,eAAe,CAAC;AAAA;AAEvC,SAAS,qBAAqB,CAAC,YAAY;AAAA,EACzC,IAAI,aAAa,oBAAoB,UAAU;AAAA,EAC/C,IAAI,qBAAqB,UAAU;AAAA,IAAG,OAAO;AAAA;AAE/C,SAAS,2BAA2B,CAAC,cAAc,YAAY;AAAA,EAC7D,IAAiB,iBAAb;AAAA,IAA2B,OAAO;AAAA;AAmBxC,SAAS,0BAA0B,GAAG;AAAA,EACpC,oBACG,gBAAgB,YAAY,oBAAoB,oBAAoB,GACpE,sBAAsB,kBAAkB;AAAA;AAE7C,SAAS,oBAAoB,CAAC,aAAa;AAAA,EACzC,IACc,YAAY,iBAAxB,WACA,sBAAsB,mBAAmB,GACzC;AAAA,IACA,IAAI,gBAAgB,CAAC;AAAA,IACrB,+BACE,eACA,qBACA,aACA,eAAe,WAAW,CAC5B;AAAA,IACA,iBAAiB,iBAAiB,aAAa;AAAA,EACjD;AAAA;AAEF,SAAS,iCAAiC,CAAC,cAAc,QAAQ,YAAY;AAAA,EAC7D,iBAAd,aACK,2BAA2B,GAC3B,kBAAkB,QAClB,sBAAsB,YACvB,gBAAgB,YAAY,oBAAoB,oBAAoB,KACrD,iBAAf,cAA+B,2BAA2B;AAAA;AAEhE,SAAS,kCAAkC,CAAC,cAAc;AAAA,EACxD,IACwB,iBAAtB,qBACY,iBAAZ,WACc,iBAAd;AAAA,IAEA,OAAO,sBAAsB,mBAAmB;AAAA;AAEpD,SAAS,0BAA0B,CAAC,cAAc,YAAY;AAAA,EAC5D,IAAgB,iBAAZ;AAAA,IAA0B,OAAO,sBAAsB,UAAU;AAAA;AAEvE,SAAS,kCAAkC,CAAC,cAAc,YAAY;AAAA,EACpE,IAAgB,iBAAZ,WAAyC,iBAAb;AAAA,IAC9B,OAAO,sBAAsB,UAAU;AAAA;AAE3C,SAAS,EAAE,CAAC,GAAG,GAAG;AAAA,EAChB,OAAQ,MAAM,MAAY,MAAN,KAAW,IAAI,MAAM,IAAI,MAAQ,MAAM,KAAK,MAAM;AAAA;AAGxE,SAAS,YAAY,CAAC,MAAM,MAAM;AAAA,EAChC,IAAI,SAAS,MAAM,IAAI;AAAA,IAAG,OAAO;AAAA,EACjC,IACe,OAAO,SAApB,YACS,SAAT,QACa,OAAO,SAApB,YACS,SAAT;AAAA,IAEA,OAAO;AAAA,EACT,IAAI,QAAQ,OAAO,KAAK,IAAI,GAC1B,QAAQ,OAAO,KAAK,IAAI;AAAA,EAC1B,IAAI,MAAM,WAAW,MAAM;AAAA,IAAQ,OAAO;AAAA,EAC1C,KAAK,QAAQ,EAAG,QAAQ,MAAM,QAAQ,SAAS;AAAA,IAC7C,IAAI,aAAa,MAAM;AAAA,IACvB,IACE,CAAC,gBAAe,KAAK,MAAM,UAAU,KACrC,CAAC,SAAS,KAAK,aAAa,KAAK,WAAW;AAAA,MAE5C,OAAO;AAAA,EACX;AAAA,EACA,OAAO;AAAA;AAET,SAAS,WAAW,CAAC,MAAM;AAAA,EACzB,MAAO,QAAQ,KAAK;AAAA,IAAc,OAAO,KAAK;AAAA,EAC9C,OAAO;AAAA;AAET,SAAS,yBAAyB,CAAC,OAAM,QAAQ;AAAA,EAC/C,IAAI,OAAO,YAAY,KAAI;AAAA,EAC3B,QAAO;AAAA,EACP,SAAS,QAAS,QAAQ;AAAA,IACxB,IAAU,KAAK,aAAX,GAAqB;AAAA,MACvB,UAAU,QAAO,KAAK,YAAY;AAAA,MAClC,IAAI,SAAQ,UAAU,WAAW;AAAA,QAC/B,OAAO,EAAE,MAAY,QAAQ,SAAS,MAAK;AAAA,MAC7C,QAAO;AAAA,IACT;AAAA,IACA,GAAG;AAAA,MACD,MAAO,QAAQ;AAAA,QACb,IAAI,KAAK,aAAa;AAAA,UACpB,OAAO,KAAK;AAAA,UACZ;AAAA,QACF;AAAA,QACA,OAAO,KAAK;AAAA,MACd;AAAA,MACA,OAAY;AAAA,IACd;AAAA,IACA,OAAO,YAAY,IAAI;AAAA,EACzB;AAAA;AAEF,SAAS,YAAY,CAAC,WAAW,WAAW;AAAA,EAC1C,OAAO,aAAa,YAChB,cAAc,YACZ,OACA,aAAmB,UAAU,aAAhB,IACX,QACA,aAAmB,UAAU,aAAhB,IACX,aAAa,WAAW,UAAU,UAAU,KAC5C,cAAc,aACZ,UAAU,SAAS,SAAS,IAC5B,UAAU,0BACR,CAAC,EAAE,UAAU,wBAAwB,SAAS,IAAI,MAClD,QACV;AAAA;AAEN,SAAS,oBAAoB,CAAC,eAAe;AAAA,EAC3C,gBACU,iBAAR,QACQ,cAAc,iBAAtB,QACQ,cAAc,cAAc,eAApC,OACI,cAAc,cAAc,cAC5B;AAAA,EACN,SACM,UAAU,iBAAiB,cAAc,QAAQ,EACrD,mBAAmB,cAAc,qBAEjC;AAAA,IACA,IAAI;AAAA,MACF,IAAI,2BACW,OAAO,QAAQ,cAAc,SAAS,SAAnD;AAAA,MACF,OAAO,KAAK;AAAA,MACZ,2BAA2B;AAAA;AAAA,IAE7B,IAAI;AAAA,MAA0B,gBAAgB,QAAQ;AAAA,IACjD;AAAA;AAAA,IACL,UAAU,iBAAiB,cAAc,QAAQ;AAAA,EACnD;AAAA,EACA,OAAO;AAAA;AAET,SAAS,wBAAwB,CAAC,MAAM;AAAA,EACtC,IAAI,WAAW,QAAQ,KAAK,YAAY,KAAK,SAAS,YAAY;AAAA,EAClE,OACE,aACc,aAAZ,YACY,KAAK,SAAhB,UACc,KAAK,SAAlB,YACU,KAAK,SAAf,SACU,KAAK,SAAf,SACe,KAAK,SAApB,eACa,aAAf,cACW,KAAK,oBAAhB;AAAA;AASN,SAAS,oBAAoB,CAAC,eAAe,aAAa,mBAAmB;AAAA,EAC3E,IAAI,MACF,kBAAkB,WAAW,oBACzB,kBAAkB,WACZ,kBAAkB,aAAxB,IACE,oBACA,kBAAkB;AAAA,EAC1B,aACU,iBAAR,QACA,kBAAkB,iBAAiB,GAAG,MACpC,MAAM,gBACR,oBAAoB,QAAO,yBAAyB,GAAG,IAClD,MAAM,EAAE,OAAO,IAAI,gBAAgB,KAAK,IAAI,aAAa,KACxD,OACC,IAAI,iBAAiB,IAAI,cAAc,eACxC,QACA,aAAa,GACd,MAAM;AAAA,IACL,YAAY,IAAI;AAAA,IAChB,cAAc,IAAI;AAAA,IAClB,WAAW,IAAI;AAAA,IACf,aAAa,IAAI;AAAA,EACnB,IACH,iBAAiB,aAAa,eAAe,GAAG,MAC7C,gBAAgB,KACjB,MAAM,4BAA4B,mBAAmB,UAAU,GAChE,IAAI,IAAI,WACJ,cAAc,IAAI,eAClB,YACA,UACA,MACA,aACA,iBACF,GACA,cAAc,KAAK,EAAE,OAAO,aAAa,WAAW,IAAI,CAAC,GACxD,YAAY,SAAS;AAAA;AAE9B,SAAS,aAAa,CAAC,WAAW,WAAW;AAAA,EAC3C,IAAI,WAAW,CAAC;AAAA,EAChB,SAAS,UAAU,YAAY,KAAK,UAAU,YAAY;AAAA,EAC1D,SAAS,WAAW,aAAa,WAAW;AAAA,EAC5C,SAAS,QAAQ,aAAa,QAAQ;AAAA,EACtC,OAAO;AAAA;AAqBT,SAAS,0BAA0B,CAAC,WAAW;AAAA,EAC7C,IAAI,mBAAmB;AAAA,IAAY,OAAO,mBAAmB;AAAA,EAC7D,IAAI,CAAC,eAAe;AAAA,IAAY,OAAO;AAAA,EACvC,IAAI,YAAY,eAAe,YAC7B;AAAA,EACF,KAAK,aAAa;AAAA,IAChB,IAAI,UAAU,eAAe,SAAS,KAAK,aAAa;AAAA,MACtD,OAAQ,mBAAmB,aAAa,UAAU;AAAA,EACtD,OAAO;AAAA;AAeT,SAAS,mBAAmB,CAAC,cAAc,WAAW;AAAA,EACpD,2BAA2B,IAAI,cAAc,SAAS;AAAA,EACtD,sBAAsB,WAAW,CAAC,YAAY,CAAC;AAAA;AAkCjD,SAAS,+BAA+B,GAAG;AAAA,EACzC,SACM,WAAW,uBACb,IAAK,2BAA2B,wBAAwB,EAC1D,IAAI,YAEJ;AAAA,IACA,IAAI,QAAQ,iBAAiB;AAAA,IAC7B,iBAAiB,OAAO;AAAA,IACxB,IAAI,QAAQ,iBAAiB;AAAA,IAC7B,iBAAiB,OAAO;AAAA,IACxB,IAAI,SAAS,iBAAiB;AAAA,IAC9B,iBAAiB,OAAO;AAAA,IACxB,IAAI,OAAO,iBAAiB;AAAA,IAC5B,iBAAiB,OAAO;AAAA,IACxB,IAAa,UAAT,QAA2B,WAAT,MAAiB;AAAA,MACrC,IAAI,UAAU,MAAM;AAAA,MACX,YAAT,OACK,OAAO,OAAO,UACb,OAAO,OAAO,QAAQ,MAAQ,QAAQ,OAAO;AAAA,MACnD,MAAM,UAAU;AAAA,IAClB;AAAA,IACM,SAAN,KAAc,8BAA8B,OAAO,QAAQ,IAAI;AAAA,EACjE;AAAA;AAEF,SAAS,eAAe,CAAC,OAAO,OAAO,QAAQ,MAAM;AAAA,EACnD,iBAAiB,2BAA2B;AAAA,EAC5C,iBAAiB,2BAA2B;AAAA,EAC5C,iBAAiB,2BAA2B;AAAA,EAC5C,iBAAiB,2BAA2B;AAAA,EAC5C,4BAA4B;AAAA,EAC5B,MAAM,SAAS;AAAA,EACf,QAAQ,MAAM;AAAA,EACL,UAAT,SAAmB,MAAM,SAAS;AAAA;AAEpC,SAAS,2BAA2B,CAAC,OAAO,OAAO,QAAQ,MAAM;AAAA,EAC/D,gBAAgB,OAAO,OAAO,QAAQ,IAAI;AAAA,EAC1C,OAAO,uBAAuB,KAAK;AAAA;AAErC,SAAS,8BAA8B,CAAC,OAAO,MAAM;AAAA,EACnD,gBAAgB,OAAO,MAAM,MAAM,IAAI;AAAA,EACvC,OAAO,uBAAuB,KAAK;AAAA;AAErC,SAAS,6BAA6B,CAAC,aAAa,QAAQ,MAAM;AAAA,EAChE,YAAY,SAAS;AAAA,EACrB,IAAI,YAAY,YAAY;AAAA,EACnB,cAAT,SAAuB,UAAU,SAAS;AAAA,EAC1C,SAAS,WAAW,OAAI,SAAS,YAAY,OAAiB,WAAT;AAAA,IAClD,OAAO,cAAc,MACnB,YAAY,OAAO,WACX,cAAT,SAAuB,UAAU,cAAc,OACxC,OAAO,QAAd,OACI,cAAc,OAAO,WACd,gBAAT,QAAwB,YAAY,cAAc,MAAM,WAAW,QACpE,cAAc,QACd,SAAS,OAAO;AAAA,EACrB,OAAa,YAAY,QAAlB,KACD,SAAS,YAAY,WACvB,YACW,WAAT,SACE,WAAW,KAAK,MAAM,IAAI,GAC3B,cAAc,OAAO,eACrB,YAAY,YAAY,WAChB,cAAT,OACK,YAAY,YAAY,CAAC,MAAM,IAChC,UAAU,KAAK,MAAM,GACxB,OAAO,OAAO,OAAO,YACxB,UACA;AAAA;AAEN,SAAS,sBAAsB,CAAC,aAAa;AAAA,EAC3C,IAAI,KAAK;AAAA,IACP,MACI,oBAAoB,GACrB,wBAAwB,MACzB,MAAM,wBAAuB,GAAG,CAAC;AAAA,EAErC,SAAS,SAAS,YAAY,OAAiB,WAAT;AAAA,IACnC,cAAc,QAAU,SAAS,YAAY;AAAA,EAChD,OAAa,YAAY,QAAlB,IAAwB,YAAY,YAAY;AAAA;AAGzD,SAAS,SAAS,CAAC,KAAK,cAAc,KAAK,MAAM;AAAA,EAC/C,KAAK,MAAM;AAAA,EACX,KAAK,MAAM;AAAA,EACX,KAAK,UACH,KAAK,QACL,KAAK,SACL,KAAK,YACL,KAAK,OACL,KAAK,cACH;AAAA,EACJ,KAAK,QAAQ;AAAA,EACb,KAAK,aAAa,KAAK,MAAM;AAAA,EAC7B,KAAK,eAAe;AAAA,EACpB,KAAK,eACH,KAAK,gBACL,KAAK,cACL,KAAK,gBACH;AAAA,EACJ,KAAK,OAAO;AAAA,EACZ,KAAK,eAAe,KAAK,QAAQ;AAAA,EACjC,KAAK,YAAY;AAAA,EACjB,KAAK,aAAa,KAAK,QAAQ;AAAA,EAC/B,KAAK,YAAY;AAAA;AAEnB,SAAS,oBAAoB,CAAC,KAAK,cAAc,KAAK,MAAM;AAAA,EAC1D,OAAO,IAAI,UAAU,KAAK,cAAc,KAAK,IAAI;AAAA;AAEnD,SAAS,eAAe,CAAC,YAAW;AAAA,EAClC,aAAY,WAAU;AAAA,EACtB,OAAO,EAAE,CAAC,cAAa,CAAC,WAAU;AAAA;AAEpC,SAAS,oBAAoB,CAAC,SAAS,cAAc;AAAA,EACnD,IAAI,iBAAiB,QAAQ;AAAA,EACpB,mBAAT,QACM,iBAAiB,qBACjB,QAAQ,KACR,cACA,QAAQ,KACR,QAAQ,IACV,GACC,eAAe,cAAc,QAAQ,aACrC,eAAe,OAAO,QAAQ,MAC9B,eAAe,YAAY,QAAQ,WACnC,eAAe,YAAY,SAC3B,QAAQ,YAAY,mBACnB,eAAe,eAAe,cAC/B,eAAe,OAAO,QAAQ,MAC9B,eAAe,QAAQ,GACvB,eAAe,eAAe,GAC9B,eAAe,YAAY;AAAA,EAChC,eAAe,QAAQ,QAAQ,QAAQ;AAAA,EACvC,eAAe,aAAa,QAAQ;AAAA,EACpC,eAAe,QAAQ,QAAQ;AAAA,EAC/B,eAAe,QAAQ,QAAQ;AAAA,EAC/B,eAAe,gBAAgB,QAAQ;AAAA,EACvC,eAAe,gBAAgB,QAAQ;AAAA,EACvC,eAAe,cAAc,QAAQ;AAAA,EACrC,eAAe,QAAQ;AAAA,EACvB,eAAe,eACJ,iBAAT,OACI,OACA,EAAE,OAAO,aAAa,OAAO,cAAc,aAAa,aAAa;AAAA,EAC3E,eAAe,UAAU,QAAQ;AAAA,EACjC,eAAe,QAAQ,QAAQ;AAAA,EAC/B,eAAe,MAAM,QAAQ;AAAA,EAC7B,eAAe,aAAa,QAAQ;AAAA,EACpC,OAAO;AAAA;AAET,SAAS,mBAAmB,CAAC,gBAAgB,aAAa;AAAA,EACxD,eAAe,SAAS;AAAA,EACxB,IAAI,UAAU,eAAe;AAAA,EACpB,YAAT,QACM,eAAe,aAAa,GAC7B,eAAe,QAAQ,aACvB,eAAe,QAAQ,MACvB,eAAe,eAAe,GAC9B,eAAe,gBAAgB,MAC/B,eAAe,gBAAgB,MAC/B,eAAe,cAAc,MAC7B,eAAe,eAAe,MAC9B,eAAe,YAAY,SAC1B,eAAe,aAAa,QAAQ,YACrC,eAAe,QAAQ,QAAQ,OAC/B,eAAe,QAAQ,QAAQ,OAC/B,eAAe,eAAe,GAC9B,eAAe,YAAY,MAC3B,eAAe,gBAAgB,QAAQ,eACvC,eAAe,gBAAgB,QAAQ,eACvC,eAAe,cAAc,QAAQ,aACrC,eAAe,OAAO,QAAQ,MAC9B,cAAc,QAAQ,cACtB,eAAe,eACL,gBAAT,OACI,OACA;AAAA,IACE,OAAO,YAAY;AAAA,IACnB,cAAc,YAAY;AAAA,EAC5B;AAAA,EACV,OAAO;AAAA;AAET,SAAS,2BAA2B,CAClC,MACA,KACA,cACA,OACA,MACA,OACA;AAAA,EACA,IAAI,WAAW;AAAA,EACf,QAAQ;AAAA,EACR,IAAmB,OAAO,SAAtB;AAAA,IAA4B,gBAAgB,IAAI,MAAM,WAAW;AAAA,EAChE,SAAiB,OAAO,SAApB;AAAA,IACP,WAAW,oBACT,MACA,cACA,mBAAmB,OACrB,IACI,KACW,SAAX,UAA8B,SAAX,UAA8B,SAAX,SACpC,KACA;AAAA,EAEN;AAAA;AAAA,MAAG,QAAQ;AAAA,aACJ;AAAA,UACH,OACG,OAAO,qBAAqB,IAAI,cAAc,KAAK,IAAI,GACvD,KAAK,cAAc,sBACnB,KAAK,QAAQ,OACd;AAAA,aAEC;AAAA,UACH,OAAO,wBAAwB,aAAa,UAAU,MAAM,OAAO,GAAG;AAAA,aACnE;AAAA,UACH,WAAW;AAAA,UACX,QAAQ;AAAA,UACR;AAAA,aACG;AAAA,UACH,OACG,OAAO,qBAAqB,IAAI,cAAc,KAAK,OAAO,CAAC,GAC3D,KAAK,cAAc,sBACnB,KAAK,QAAQ,OACd;AAAA,aAEC;AAAA,UACH,OACG,OAAO,qBAAqB,IAAI,cAAc,KAAK,IAAI,GACvD,KAAK,cAAc,sBACnB,KAAK,QAAQ,OACd;AAAA,aAEC;AAAA,UACH,OACG,OAAO,qBAAqB,IAAI,cAAc,KAAK,IAAI,GACvD,KAAK,cAAc,0BACnB,KAAK,QAAQ,OACd;AAAA;AAAA,UAGF,IAAiB,OAAO,SAApB,YAAqC,SAAT;AAAA,YAC9B,QAAQ,KAAK;AAAA,mBACN;AAAA,gBACH,WAAW;AAAA,gBACX;AAAA,mBACG;AAAA,gBACH,WAAW;AAAA,gBACX;AAAA,mBACG;AAAA,gBACH,WAAW;AAAA,gBACX;AAAA,mBACG;AAAA,gBACH,WAAW;AAAA,gBACX;AAAA,mBACG;AAAA,gBACH,WAAW;AAAA,gBACX,QAAQ;AAAA,gBACR;AAAA;AAAA,UAEN,WAAW;AAAA,UACX,eAAe,MACb,wBAAuB,KAAc,SAAT,OAAgB,SAAS,OAAO,MAAM,EAAE,CACtE;AAAA,UACA,QAAQ;AAAA;AAAA,EAEd,MAAM,qBAAqB,UAAU,cAAc,KAAK,IAAI;AAAA,EAC5D,IAAI,cAAc;AAAA,EAClB,IAAI,OAAO;AAAA,EACX,IAAI,QAAQ;AAAA,EACZ,OAAO;AAAA;AAET,SAAS,uBAAuB,CAAC,UAAU,MAAM,OAAO,KAAK;AAAA,EAC3D,WAAW,qBAAqB,GAAG,UAAU,KAAK,IAAI;AAAA,EACtD,SAAS,QAAQ;AAAA,EACjB,OAAO;AAAA;AAET,SAAS,mBAAmB,CAAC,SAAS,MAAM,OAAO;AAAA,EACjD,UAAU,qBAAqB,GAAG,SAAS,MAAM,IAAI;AAAA,EACrD,QAAQ,QAAQ;AAAA,EAChB,OAAO;AAAA;AAET,SAAS,iCAAiC,CAAC,gBAAgB;AAAA,EACzD,IAAI,QAAQ,qBAAqB,IAAI,MAAM,MAAM,CAAC;AAAA,EAClD,MAAM,YAAY;AAAA,EAClB,OAAO;AAAA;AAET,SAAS,qBAAqB,CAAC,QAAQ,MAAM,OAAO;AAAA,EAClD,OAAO,qBACL,GACS,OAAO,aAAhB,OAA2B,OAAO,WAAW,CAAC,GAC9C,OAAO,KACP,IACF;AAAA,EACA,KAAK,QAAQ;AAAA,EACb,KAAK,YAAY;AAAA,IACf,eAAe,OAAO;AAAA,IACtB,iBAAiB;AAAA,IACjB,gBAAgB,OAAO;AAAA,EACzB;AAAA,EACA,OAAO;AAAA;AAGT,SAAS,0BAA0B,CAAC,OAAO,QAAQ;AAAA,EACjD,IAAiB,OAAO,UAApB,YAAsC,UAAT,MAAgB;AAAA,IAC/C,IAAI,WAAW,eAAe,IAAI,KAAK;AAAA,IACvC,IAAe,aAAN;AAAA,MAAgB,OAAO;AAAA,IAChC,SAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA,OAAO,4BAA4B,MAAM;AAAA,IAC3C;AAAA,IACA,eAAe,IAAI,OAAO,MAAM;AAAA,IAChC,OAAO;AAAA,EACT;AAAA,EACA,OAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,OAAO,4BAA4B,MAAM;AAAA,EAC3C;AAAA;AAWF,SAAS,YAAY,CAAC,gBAAgB,eAAe;AAAA,EACnD,UAAU,oBAAoB;AAAA,EAC9B,UAAU,oBAAoB;AAAA,EAC9B,mBAAmB;AAAA,EACnB,gBAAgB;AAAA;AAElB,SAAS,UAAU,CAAC,gBAAgB,eAAe,QAAO;AAAA,EACxD,QAAQ,kBAAkB;AAAA,EAC1B,QAAQ,kBAAkB;AAAA,EAC1B,QAAQ,kBAAkB;AAAA,EAC1B,sBAAsB;AAAA,EACtB,IAAI,uBAAuB;AAAA,EAC3B,iBAAiB;AAAA,EACjB,IAAI,aAAa,KAAK,MAAM,oBAAoB,IAAI;AAAA,EACpD,wBAAwB,EAAE,KAAK;AAAA,EAC/B,UAAS;AAAA,EACT,IAAI,SAAS,KAAK,MAAM,aAAa,IAAI;AAAA,EACzC,IAAI,KAAK,QAAQ;AAAA,IACf,IAAI,uBAAuB,aAAc,aAAa;AAAA,IACtD,UACE,wBACE,KAAK,wBAAwB,GAC/B,SAAS,EAAE;AAAA,IACb,yBAAyB;AAAA,IACzB,cAAc;AAAA,IACd,gBACG,KAAM,KAAK,MAAM,aAAa,IAAI,aAClC,UAAS,aACV;AAAA,IACF,sBAAsB,SAAS;AAAA,EACjC,EACE;AAAA,IAAC,gBACE,KAAK,SAAW,UAAS,aAAc,sBACvC,sBAAsB;AAAA;AAE7B,SAAS,sBAAsB,CAAC,gBAAgB;AAAA,EACrC,eAAe,WAAxB,SACG,aAAa,gBAAgB,CAAC,GAAG,WAAW,gBAAgB,GAAG,CAAC;AAAA;AAErE,SAAS,cAAc,CAAC,gBAAgB;AAAA,EACtC,MAAO,mBAAmB;AAAA,IACvB,mBAAmB,UAAU,EAAE,iBAC7B,UAAU,kBAAkB,MAC5B,gBAAgB,UAAU,EAAE,iBAC5B,UAAU,kBAAkB;AAAA,EACjC,MAAO,mBAAmB;AAAA,IACvB,sBAAsB,QAAQ,EAAE,eAC9B,QAAQ,gBAAgB,MACxB,sBAAsB,QAAQ,EAAE,eAChC,QAAQ,gBAAgB,MACxB,gBAAgB,QAAQ,EAAE,eAC1B,QAAQ,gBAAgB;AAAA;AAE/B,SAAS,2BAA2B,CAAC,gBAAgB,kBAAkB;AAAA,EACrE,QAAQ,kBAAkB;AAAA,EAC1B,QAAQ,kBAAkB;AAAA,EAC1B,QAAQ,kBAAkB;AAAA,EAC1B,gBAAgB,iBAAiB;AAAA,EACjC,sBAAsB,iBAAiB;AAAA,EACvC,sBAAsB;AAAA;AAQxB,SAAS,wBAAwB,CAAC,OAAO;AAAA,EACvC,IAAI,QAAQ,MACV,wBACE,KACA,IAAI,UAAU,UAAqB,UAAU,OAAhB,aAAsB,UAAU,KACzD,SACA,QACJ,EACF,CACF;AAAA,EACA,oBAAoB,2BAA2B,OAAO,KAAK,CAAC;AAAA,EAC5D,MAAM;AAAA;AAER,SAAS,4BAA4B,CAAC,OAAO;AAAA,EAC3C,MAAqB,WAAjB,UACW,MACC,eAAd,UADO;AAAA,EAET,SAAS,uBAAuB;AAAA,EAChC,SAAS,oBAAoB;AAAA,EAC7B,QAAQ;AAAA,SACD;AAAA,MACH,0BAA0B,UAAU,QAAQ;AAAA,MAC5C,0BAA0B,SAAS,QAAQ;AAAA,MAC3C;AAAA,SACG;AAAA,SACA;AAAA,SACA;AAAA,MACH,0BAA0B,QAAQ,QAAQ;AAAA,MAC1C;AAAA,SACG;AAAA,SACA;AAAA,MACH,KAAK,OAAO,EAAG,OAAO,gBAAgB,QAAQ;AAAA,QAC5C,0BAA0B,gBAAgB,OAAO,QAAQ;AAAA,MAC3D;AAAA,SACG;AAAA,MACH,0BAA0B,SAAS,QAAQ;AAAA,MAC3C;AAAA,SACG;AAAA,SACA;AAAA,SACA;AAAA,MACH,0BAA0B,SAAS,QAAQ;AAAA,MAC3C,0BAA0B,QAAQ,QAAQ;AAAA,MAC1C;AAAA,SACG;AAAA,MACH,0BAA0B,UAAU,QAAQ;AAAA,MAC5C;AAAA,SACG;AAAA,MACH,0BAA0B,WAAW,QAAQ;AAAA,MAC7C,UACE,UACA,MAAM,OACN,MAAM,cACN,MAAM,SACN,MAAM,gBACN,MAAM,MACN,MAAM,MACN,IACF;AAAA,MACA;AAAA,SACG;AAAA,MACH,0BAA0B,WAAW,QAAQ;AAAA,MAC7C;AAAA,SACG;AAAA,MACH,0BAA0B,WAAW,QAAQ,GAC3C,aAAa,UAAU,MAAM,OAAO,MAAM,cAAc,MAAM,QAAQ;AAAA;AAAA,EAE5E,OAAO,MAAM;AAAA,EACC,OAAO,SAApB,YACc,OAAO,SAApB,YACa,OAAO,SAApB,YACF,SAAS,gBAAgB,KAAK,QACvB,MAAM,6BAAb,QACA,sBAAsB,SAAS,aAAa,IAAI,KACnC,MAAM,WAAd,SACE,0BAA0B,gBAAgB,QAAQ,GACnD,0BAA0B,UAAU,QAAQ,IACtC,MAAM,YAAd,QAA0B,0BAA0B,UAAU,QAAQ,GAC9D,MAAM,eAAd,QACE,0BAA0B,aAAa,QAAQ,GACzC,MAAM,WAAd,SAA0B,SAAS,UAAU,SAC5C,WAAW,QACX,WAAW;AAAA,EAChB,YAAY,yBAAyB,OAAO,IAAE;AAAA;AAEhD,SAAS,mBAAmB,CAAC,OAAO;AAAA,EAClC,KAAK,uBAAuB,MAAM,OAAQ;AAAA,IACxC,QAAQ,qBAAqB;AAAA,WACtB;AAAA,WACA;AAAA,WACA;AAAA,QACH,yBAAyB;AAAA,QACzB;AAAA,WACG;AAAA,WACA;AAAA,QACH,yBAAyB;AAAA,QACzB;AAAA;AAAA,QAEA,uBAAuB,qBAAqB;AAAA;AAAA;AAGpD,SAAS,iBAAiB,CAAC,OAAO;AAAA,EAChC,IAAI,UAAU;AAAA,IAAsB,OAAO;AAAA,EAC3C,IAAI,CAAC;AAAA,IAAa,OAAO,oBAAoB,KAAK,GAAI,cAAc,MAAK;AAAA,EACzE,IAAI,MAAM,MAAM,KACd;AAAA,EACF,IAAK,kBAAwB,QAAN,KAAoB,QAAP,IAAa;AAAA,IAC/C,IAAK,kBAAwB,QAAN;AAAA,MACpB,kBAAkB,MAAM,MACtB,kBACC,EAAa,oBAAX,UAA2C,oBAAb,aAChC,qBAAqB,MAAM,MAAM,MAAM,aAAa;AAAA,IAC1D,kBAAkB,CAAC;AAAA,EACrB;AAAA,EACA,mBAAmB,0BAA0B,yBAAyB,KAAK;AAAA,EAC3E,oBAAoB,KAAK;AAAA,EACzB,IAAW,QAAP,IAAY;AAAA,IACd,QAAQ,MAAM;AAAA,IACd,QAAiB,UAAT,OAAiB,MAAM,aAAa;AAAA,IAC5C,IAAI,CAAC;AAAA,MAAO,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,IACnD,yBACE,gDAAgD,KAAK;AAAA,EACzD,EAAO,SAAW,QAAP,IAAY;AAAA,IACrB,QAAQ,MAAM;AAAA,IACd,QAAiB,UAAT,OAAiB,MAAM,aAAa;AAAA,IAC5C,IAAI,CAAC;AAAA,MAAO,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,IACnD,yBACE,gDAAgD,KAAK;AAAA,EACzD,EACE;AAAA,IAAO,QAAP,MACM,MAAM,wBACR,iBAAiB,MAAM,IAAI,KACrB,QAAQ,6CACT,8CAA8C,MAC9C,yBAAyB,SACzB,yBAAyB,OAC7B,yBAAyB,uBACtB,kBAAkB,MAAM,UAAU,WAAW,IAC7C;AAAA,EACV,OAAO;AAAA;AAET,SAAS,mBAAmB,GAAG;AAAA,EAC7B,yBAAyB,uBAAuB;AAAA,EAChD,cAAc;AAAA;AAEhB,SAAS,mCAAmC,GAAG;AAAA,EAC7C,IAAI,eAAe;AAAA,EACV,iBAAT,SACY,wCAAT,OACI,sCAAsC,eACvC,oCAAoC,KAAK,MACvC,qCACA,YACF,GACH,kBAAkB;AAAA,EACrB,OAAO;AAAA;AAET,SAAS,mBAAmB,CAAC,OAAO;AAAA,EACzB,oBAAT,OACK,kBAAkB,CAAC,KAAK,IACzB,gBAAgB,KAAK,KAAK;AAAA;AAKhC,SAAS,YAAY,CAAC,eAAe,SAAS,WAAW;AAAA,EACvD,MAAK,aAAa,QAAQ,aAAa;AAAA,EACvC,QAAQ,gBAAgB;AAAA;AAE1B,SAAS,WAAW,CAAC,SAAS;AAAA,EAC5B,QAAQ,gBAAgB,YAAY;AAAA,EACpC,KAAI,WAAW;AAAA;AAEjB,SAAS,+BAA+B,CAAC,QAAQ,aAAa,iBAAiB;AAAA,EAC7E,MAAgB,WAAT,QAAmB;AAAA,IACxB,IAAI,YAAY,OAAO;AAAA,KACtB,OAAO,aAAa,iBAAiB,eAChC,OAAO,cAAc,aACd,cAAT,SAAuB,UAAU,cAAc,gBACtC,cAAT,SACC,UAAU,aAAa,iBAAiB,gBACxC,UAAU,cAAc;AAAA,IAC7B,IAAI,WAAW;AAAA,MAAiB;AAAA,IAChC,SAAS,OAAO;AAAA,EAClB;AAAA;AAEF,SAAS,uBAAuB,CAC9B,gBACA,UACA,aACA,0BACA;AAAA,EACA,IAAI,QAAQ,eAAe;AAAA,EAClB,UAAT,SAAmB,MAAM,SAAS;AAAA,EAClC,MAAgB,UAAT,QAAkB;AAAA,IACvB,IAAI,OAAO,MAAM;AAAA,IACjB,IAAa,SAAT,MAAe;AAAA,MACjB,IAAI,YAAY,MAAM;AAAA,MACtB,OAAO,KAAK;AAAA,MACZ;AAAA,QAAG,MAAgB,SAAT,QAAiB;AAAA,UACzB,IAAI,aAAa;AAAA,UACjB,OAAO;AAAA,UACP,SAAS,IAAI,EAAG,IAAI,SAAS,QAAQ;AAAA,YACnC,IAAI,WAAW,YAAY,SAAS,IAAI;AAAA,cACtC,KAAK,SAAS;AAAA,cACd,aAAa,KAAK;AAAA,cACT,eAAT,SAAwB,WAAW,SAAS;AAAA,cAC5C,gCACE,KAAK,QACL,aACA,cACF;AAAA,cACA,6BAA6B,YAAY;AAAA,cACzC;AAAA,YACF;AAAA,UACF,OAAO,WAAW;AAAA,QACpB;AAAA,IACF,EAAO,SAAW,MAAM,QAAb,IAAkB;AAAA,MAC3B,YAAY,MAAM;AAAA,MAClB,IAAa,cAAT;AAAA,QAAoB,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,MAC/D,UAAU,SAAS;AAAA,MACnB,OAAO,UAAU;AAAA,MACR,SAAT,SAAkB,KAAK,SAAS;AAAA,MAChC,gCAAgC,WAAW,aAAa,cAAc;AAAA,MACtE,YAAY;AAAA,IACd,EAAO;AAAA,kBAAY,MAAM;AAAA,IACzB,IAAa,cAAT;AAAA,MAAoB,UAAU,SAAS;AAAA,IAEzC;AAAA,WAAK,YAAY,MAAgB,cAAT,QAAsB;AAAA,QAC5C,IAAI,cAAc,gBAAgB;AAAA,UAChC,YAAY;AAAA,UACZ;AAAA,QACF;AAAA,QACA,QAAQ,UAAU;AAAA,QAClB,IAAa,UAAT,MAAgB;AAAA,UAClB,MAAM,SAAS,UAAU;AAAA,UACzB,YAAY;AAAA,UACZ;AAAA,QACF;AAAA,QACA,YAAY,UAAU;AAAA,MACxB;AAAA,IACF,QAAQ;AAAA,EACV;AAAA;AAEF,SAAS,6BAA6B,CACpC,SACA,gBACA,aACA,0BACA;AAAA,EACA,UAAU;AAAA,EACV,SACM,SAAS,gBAAgB,6BAA6B,MACjD,WAAT,QAEA;AAAA,IACA,IAAI,CAAC;AAAA,MACH,KAAW,OAAO,QAAQ,YAAtB;AAAA,QAA+B,6BAA6B;AAAA,MAC3D,UAAW,OAAO,QAAQ,YAAtB;AAAA,QAA+B;AAAA;AAAA,IAC1C,IAAW,OAAO,QAAd,IAAmB;AAAA,MACrB,IAAI,gBAAgB,OAAO;AAAA,MAC3B,IAAa,kBAAT;AAAA,QAAwB,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,MACnE,gBAAgB,cAAc;AAAA,MAC9B,IAAa,kBAAT,MAAwB;AAAA,QAC1B,IAAI,UAAU,OAAO;AAAA,QACrB,SAAS,OAAO,aAAa,OAAO,cAAc,KAAK,MAC3C,YAAT,OAAmB,QAAQ,KAAK,OAAO,IAAK,UAAU,CAAC,OAAO;AAAA,MACnE;AAAA,IACF,EAAO,SAAI,WAAW,6BAA6B,SAAS;AAAA,MAC1D,gBAAgB,OAAO;AAAA,MACvB,IAAa,kBAAT;AAAA,QAAwB,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,MACnE,cAAc,cAAc,kBAC1B,OAAO,cAAc,kBACX,YAAT,OACG,QAAQ,KAAK,qBAAqB,IACjC,UAAU,CAAC,qBAAqB;AAAA,IACzC;AAAA,IACA,SAAS,OAAO;AAAA,EAClB;AAAA,EACS,YAAT,QACE,wBACE,gBACA,SACA,aACA,wBACF;AAAA,EACF,eAAe,SAAS;AAAA;AAE1B,SAAS,qBAAqB,CAAC,qBAAqB;AAAA,EAClD,KACE,sBAAsB,oBAAoB,aACjC,wBAAT,QAEA;AAAA,IACA,IACE,CAAC,SACC,oBAAoB,QAAQ,eAC5B,oBAAoB,aACtB;AAAA,MAEA,OAAO;AAAA,IACT,sBAAsB,oBAAoB;AAAA,EAC5C;AAAA,EACA,OAAO;AAAA;AAET,SAAS,oBAAoB,CAAC,gBAAgB;AAAA,EAC5C,4BAA4B;AAAA,EAC5B,wBAAwB;AAAA,EACxB,iBAAiB,eAAe;AAAA,EACvB,mBAAT,SAA4B,eAAe,eAAe;AAAA;AAE5D,SAAS,WAAW,CAAC,SAAS;AAAA,EAC5B,OAAO,uBAAuB,2BAA2B,OAAO;AAAA;AAElE,SAAS,+BAA+B,CAAC,UAAU,SAAS;AAAA,EACjD,8BAAT,QAAsC,qBAAqB,QAAQ;AAAA,EACnE,OAAO,uBAAuB,UAAU,OAAO;AAAA;AAEjD,SAAS,sBAAsB,CAAC,UAAU,SAAS;AAAA,EACjD,IAAI,QAAQ,QAAQ;AAAA,EACpB,UAAU,EAAE,SAAkB,eAAe,OAAO,MAAM,KAAK;AAAA,EAC/D,IAAa,0BAAT,MAAgC;AAAA,IAClC,IAAa,aAAT;AAAA,MAAmB,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,IAC9D,wBAAwB;AAAA,IACxB,SAAS,eAAe,EAAE,OAAO,GAAG,cAAc,QAAQ;AAAA,IAC1D,SAAS,SAAS;AAAA,EACpB,EAAO;AAAA,4BAAwB,sBAAsB,OAAO;AAAA,EAC5D,OAAO;AAAA;AA8BT,SAAS,WAAW,GAAG;AAAA,EACrB,OAAO;AAAA,IACL,YAAY,IAAI;AAAA,IAChB,MAAM,IAAI;AAAA,IACV,UAAU;AAAA,EACZ;AAAA;AAEF,SAAS,YAAY,CAAC,OAAO;AAAA,EAC3B,MAAM;AAAA,EACA,MAAM,aAAZ,KACE,mBAAmB,gBAAgB,QAAS,GAAG;AAAA,IAC7C,MAAM,WAAW,MAAM;AAAA,GACxB;AAAA;AAML,SAAS,mBAAmB,CAAC,YAAY,UAAU;AAAA,EACjD,IAAa,8BAAT,MAAoC;AAAA,IACtC,IAAI,qBAAsB,4BAA4B,CAAC;AAAA,IACvD,+BAA+B;AAAA,IAC/B,uBAAuB,sBAAsB;AAAA,IAC7C,iCAAiC;AAAA,MAC/B,QAAQ;AAAA,MACR,OAAY;AAAA,MACZ,MAAM,QAAS,CAAC,SAAS;AAAA,QACvB,mBAAmB,KAAK,OAAO;AAAA;AAAA,IAEnC;AAAA,EACF;AAAA,EACA;AAAA,EACA,SAAS,KAAK,2BAA2B,yBAAyB;AAAA,EAClE,OAAO;AAAA;AAET,SAAS,yBAAyB,GAAG;AAAA,EACnC,IACQ,EAAE,iCAAR,KACS,8BAAT,MACA;AAAA,IACS,mCAAT,SACG,+BAA+B,SAAS;AAAA,IAC3C,IAAI,YAAY;AAAA,IAChB,4BAA4B;AAAA,IAC5B,uBAAuB;AAAA,IACvB,iCAAiC;AAAA,IACjC,SAAS,IAAI,EAAG,IAAI,UAAU,QAAQ;AAAA,OAAM,GAAG,UAAU,IAAI;AAAA,EAC/D;AAAA;AAEF,SAAS,kBAAkB,CAAC,UAAU,QAAQ;AAAA,EAC5C,IAAI,YAAY,CAAC,GACf,uBAAuB;AAAA,IACrB,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,MAAM,QAAS,CAAC,SAAS;AAAA,MACvB,UAAU,KAAK,OAAO;AAAA;AAAA,EAE1B;AAAA,EACF,SAAS,KACP,QAAS,GAAG;AAAA,IACV,qBAAqB,SAAS;AAAA,IAC9B,qBAAqB,QAAQ;AAAA,IAC7B,SAAS,IAAI,EAAG,IAAI,UAAU,QAAQ;AAAA,OAAM,GAAG,UAAU,IAAI,MAAM;AAAA,KAErE,QAAS,CAAC,OAAO;AAAA,IACf,qBAAqB,SAAS;AAAA,IAC9B,qBAAqB,SAAS;AAAA,IAC9B,KAAK,QAAQ,EAAG,QAAQ,UAAU,QAAQ;AAAA,OACvC,GAAG,UAAU,QAAa,SAAC;AAAA,GAElC;AAAA,EACA,OAAO;AAAA;AAaT,SAAS,iBAAiB,GAAG;AAAA,EAC3B,IAAI,iCAAiC,aAAa;AAAA,EAClD,OAAgB,mCAAT,OACH,iCACA,mBAAmB;AAAA;AAEzB,SAAS,cAAc,CAAC,yBAAyB,eAAe;AAAA,EACrD,kBAAT,OACI,MAAK,cAAc,aAAa,OAAO,IACvC,MAAK,cAAc,cAAc,IAAI;AAAA;AAE3C,SAAS,iBAAiB,GAAG;AAAA,EAC3B,IAAI,gBAAgB,kBAAkB;AAAA,EACtC,OAAgB,kBAAT,OACH,OACA,EAAE,QAAQ,aAAa,eAAe,MAAM,cAAc;AAAA;AAMhE,SAAS,kBAAkB,CAAC,UAAU;AAAA,EACpC,WAAW,SAAS;AAAA,EACpB,OAAuB,aAAhB,eAA2C,aAAf;AAAA;AAErC,SAAS,iBAAiB,CAAC,eAAe,UAAU,QAAO;AAAA,EACzD,SAAQ,cAAc;AAAA,EACX,WAAN,YACD,cAAc,KAAK,QAAQ,IAC3B,WAAU,aAAa,SAAS,KAAK,QAAQ,MAAM,GAAI,WAAW;AAAA,EACtE,QAAQ,SAAS;AAAA,SACV;AAAA,MACH,OAAO,SAAS;AAAA,SACb;AAAA,MACH,MACI,gBAAgB,SAAS,QAC3B,8BAA8B,aAAa,GAC3C;AAAA;AAAA,MAGF,IAAiB,OAAO,SAAS,WAA7B;AAAA,QAAqC,SAAS,KAAK,QAAQ,MAAM;AAAA,MAChE;AAAA,QACH,gBAAgB;AAAA,QAChB,IAAa,kBAAT,QAA0B,MAAM,cAAc;AAAA,UAChD,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,QACzC,gBAAgB;AAAA,QAChB,cAAc,SAAS;AAAA,QACvB,cAAc,KACZ,QAAS,CAAC,gBAAgB;AAAA,UACxB,IAAkB,SAAS,WAAvB,WAA+B;AAAA,YACjC,IAAI,oBAAoB;AAAA,YACxB,kBAAkB,SAAS;AAAA,YAC3B,kBAAkB,QAAQ;AAAA,UAC5B;AAAA,WAEF,QAAS,CAAC,OAAO;AAAA,UACf,IAAkB,SAAS,WAAvB,WAA+B;AAAA,YACjC,IAAI,mBAAmB;AAAA,YACvB,iBAAiB,SAAS;AAAA,YAC1B,iBAAiB,SAAS;AAAA,UAC5B;AAAA,SAEJ;AAAA;AAAA,MAEF,QAAQ,SAAS;AAAA,aACV;AAAA,UACH,OAAO,SAAS;AAAA,aACb;AAAA,UACH,MACI,gBAAgB,SAAS,QAC3B,8BAA8B,aAAa,GAC3C;AAAA;AAAA,MAGN,oBAAoB;AAAA,MACpB,MAAM;AAAA;AAAA;AAGZ,SAAS,WAAW,CAAC,UAAU;AAAA,EAC7B,IAAI;AAAA,IACF,IAAI,OAAO,SAAS;AAAA,IACpB,OAAO,KAAK,SAAS,QAAQ;AAAA,IAC7B,OAAO,GAAG;AAAA,IACV,IAAa,MAAT,QAA2B,OAAO,MAApB,YAAwC,OAAO,EAAE,SAAxB;AAAA,MACzC,MAAQ,oBAAoB,GAAI;AAAA,IAClC,MAAM;AAAA;AAAA;AAIV,SAAS,oBAAoB,GAAG;AAAA,EAC9B,IAAa,sBAAT;AAAA,IAA4B,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,EACvE,IAAI,WAAW;AAAA,EACf,oBAAoB;AAAA,EACpB,OAAO;AAAA;AAET,SAAS,6BAA6B,CAAC,gBAAgB;AAAA,EACrD,IACE,mBAAmB,qBACnB,mBAAmB;AAAA,IAEnB,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA;AAI3C,SAAS,cAAc,CAAC,UAAU;AAAA,EAChC,IAAI,SAAQ;AAAA,EACZ,0BAA0B;AAAA,EACjB,oBAAT,SAA6B,kBAAkB,CAAC;AAAA,EAChD,OAAO,kBAAkB,iBAAiB,UAAU,MAAK;AAAA;AAE3D,SAAS,SAAS,CAAC,gBAAgB,SAAS;AAAA,EAC1C,UAAU,QAAQ,MAAM;AAAA,EACxB,eAAe,MAAiB,YAAN,YAAgB,UAAU;AAAA;AAEtD,SAAS,4BAA4B,CAAC,aAAa,UAAU;AAAA,EAC3D,IAAI,SAAS,aAAa;AAAA,IACxB,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,EACzC,cAAc,OAAO,UAAU,SAAS,KAAK,QAAQ;AAAA,EACrD,MAAM,MACJ,wBACE,IACsB,gBAAtB,oBACI,uBAAuB,OAAO,KAAK,QAAQ,EAAE,KAAK,IAAI,IAAI,MAC1D,WACN,CACF;AAAA;AAEF,SAAS,qBAAqB,CAAC,wBAAwB;AAAA,EACrD,SAAS,WAAW,CAAC,aAAa,eAAe;AAAA,IAC/C,IAAI,wBAAwB;AAAA,MAC1B,IAAI,YAAY,YAAY;AAAA,MACnB,cAAT,QACM,YAAY,YAAY,CAAC,aAAa,GAAK,YAAY,SAAS,MAClE,UAAU,KAAK,aAAa;AAAA,IAClC;AAAA;AAAA,EAEF,SAAS,uBAAuB,CAAC,aAAa,mBAAmB;AAAA,IAC/D,IAAI,CAAC;AAAA,MAAwB,OAAO;AAAA,IACpC,MAAgB,sBAAT;AAAA,MACL,YAAY,aAAa,iBAAiB,GACvC,oBAAoB,kBAAkB;AAAA,IAC3C,OAAO;AAAA;AAAA,EAET,SAAS,oBAAoB,CAAC,mBAAmB;AAAA,IAC/C,SAAS,mBAAmB,IAAI,IAAgB,sBAAT;AAAA,MAC5B,kBAAkB,QAA3B,OACI,iBAAiB,IAAI,kBAAkB,KAAK,iBAAiB,IAC7D,iBAAiB,IAAI,kBAAkB,OAAO,iBAAiB,GAChE,oBAAoB,kBAAkB;AAAA,IAC3C,OAAO;AAAA;AAAA,EAET,SAAS,QAAQ,CAAC,OAAO,cAAc;AAAA,IACrC,QAAQ,qBAAqB,OAAO,YAAY;AAAA,IAChD,MAAM,QAAQ;AAAA,IACd,MAAM,UAAU;AAAA,IAChB,OAAO;AAAA;AAAA,EAET,SAAS,UAAU,CAAC,UAAU,iBAAiB,UAAU;AAAA,IACvD,SAAS,QAAQ;AAAA,IACjB,IAAI,CAAC;AAAA,MACH,OAAQ,SAAS,SAAS,SAAU;AAAA,IACtC,WAAW,SAAS;AAAA,IACpB,IAAa,aAAT;AAAA,MACF,OACG,WAAW,SAAS,OACrB,WAAW,mBACL,SAAS,SAAS,UAAW,mBAC/B;AAAA,IAER,SAAS,SAAS;AAAA,IAClB,OAAO;AAAA;AAAA,EAET,SAAS,gBAAgB,CAAC,UAAU;AAAA,IAClC,0BACW,SAAS,cAAlB,SACC,SAAS,SAAS;AAAA,IACrB,OAAO;AAAA;AAAA,EAET,SAAS,cAAc,CAAC,aAAa,SAAS,aAAa,OAAO;AAAA,IAChE,IAAa,YAAT,QAA0B,QAAQ,QAAd;AAAA,MACtB,OACG,UAAU,oBAAoB,aAAa,YAAY,MAAM,KAAK,GAClE,QAAQ,SAAS,aAClB;AAAA,IAEJ,UAAU,SAAS,SAAS,WAAW;AAAA,IACvC,QAAQ,SAAS;AAAA,IACjB,OAAO;AAAA;AAAA,EAET,SAAS,aAAa,CAAC,aAAa,SAAS,SAAS,OAAO;AAAA,IAC3D,IAAI,cAAc,QAAQ;AAAA,IAC1B,IAAI,gBAAgB;AAAA,MAClB,OAAO,eACL,aACA,SACA,QAAQ,MAAM,UACd,OACA,QAAQ,GACV;AAAA,IACF,IACW,YAAT,SACC,QAAQ,gBAAgB,eACT,OAAO,gBAApB,YACU,gBAAT,QACA,YAAY,aAAa,oBACzB,YAAY,WAAW,MAAM,QAAQ;AAAA,MAEzC,OACG,UAAU,SAAS,SAAS,QAAQ,KAAK,GAC1C,UAAU,SAAS,OAAO,GACzB,QAAQ,SAAS,aAClB;AAAA,IAEJ,UAAU,4BACR,QAAQ,MACR,QAAQ,KACR,QAAQ,OACR,MACA,YAAY,MACZ,KACF;AAAA,IACA,UAAU,SAAS,OAAO;AAAA,IAC1B,QAAQ,SAAS;AAAA,IACjB,OAAO;AAAA;AAAA,EAET,SAAS,YAAY,CAAC,aAAa,SAAS,QAAQ,OAAO;AAAA,IACzD,IACW,YAAT,QACM,QAAQ,QAAd,KACA,QAAQ,UAAU,kBAAkB,OAAO,iBAC3C,QAAQ,UAAU,mBAAmB,OAAO;AAAA,MAE5C,OACG,UAAU,sBAAsB,QAAQ,YAAY,MAAM,KAAK,GAC/D,QAAQ,SAAS,aAClB;AAAA,IAEJ,UAAU,SAAS,SAAS,OAAO,YAAY,CAAC,CAAC;AAAA,IACjD,QAAQ,SAAS;AAAA,IACjB,OAAO;AAAA;AAAA,EAET,SAAS,cAAc,CAAC,aAAa,SAAS,UAAU,OAAO,KAAK;AAAA,IAClE,IAAa,YAAT,QAA0B,QAAQ,QAAd;AAAA,MACtB,OACG,UAAU,wBACT,UACA,YAAY,MACZ,OACA,GACF,GACC,QAAQ,SAAS,aAClB;AAAA,IAEJ,UAAU,SAAS,SAAS,QAAQ;AAAA,IACpC,QAAQ,SAAS;AAAA,IACjB,OAAO;AAAA;AAAA,EAET,SAAS,WAAW,CAAC,aAAa,UAAU,OAAO;AAAA,IACjD,IACgB,OAAO,aAApB,YAAuC,aAAP,MACpB,OAAO,aAApB,YACa,OAAO,aAApB;AAAA,MAEA,OACG,WAAW,oBACV,KAAK,UACL,YAAY,MACZ,KACF,GACC,SAAS,SAAS,aACnB;AAAA,IAEJ,IAAiB,OAAO,aAApB,YAAyC,aAAT,MAAmB;AAAA,MACrD,QAAQ,SAAS;AAAA,aACV;AAAA,UACH,OACG,QAAQ,4BACP,SAAS,MACT,SAAS,KACT,SAAS,OACT,MACA,YAAY,MACZ,KACF,GACA,UAAU,OAAO,QAAQ,GACxB,MAAM,SAAS,aAChB;AAAA,aAEC;AAAA,UACH,OACG,WAAW,sBACV,UACA,YAAY,MACZ,KACF,GACC,SAAS,SAAS,aACnB;AAAA,aAEC;AAAA,UACH,OACG,WAAW,YAAY,QAAQ,GAChC,YAAY,aAAa,UAAU,KAAK;AAAA;AAAA,MAG9C,IAAI,aAAY,QAAQ,KAAK,eAAc,QAAQ;AAAA,QACjD,OACG,WAAW,wBACV,UACA,YAAY,MACZ,OACA,IACF,GACC,SAAS,SAAS,aACnB;AAAA,MAEJ,IAAmB,OAAO,SAAS,SAA/B;AAAA,QACF,OAAO,YAAY,aAAa,eAAe,QAAQ,GAAG,KAAK;AAAA,MACjE,IAAI,SAAS,aAAa;AAAA,QACxB,OAAO,YACL,aACA,gCAAgC,aAAa,QAAQ,GACrD,KACF;AAAA,MACF,6BAA6B,aAAa,QAAQ;AAAA,IACpD;AAAA,IACA,OAAO;AAAA;AAAA,EAET,SAAS,UAAU,CAAC,aAAa,UAAU,UAAU,OAAO;AAAA,IAC1D,IAAI,MAAe,aAAT,OAAoB,SAAS,MAAM;AAAA,IAC7C,IACgB,OAAO,aAApB,YAAuC,aAAP,MACpB,OAAO,aAApB,YACa,OAAO,aAApB;AAAA,MAEA,OAAgB,QAAT,OACH,OACA,eAAe,aAAa,UAAU,KAAK,UAAU,KAAK;AAAA,IAChE,IAAiB,OAAO,aAApB,YAAyC,aAAT,MAAmB;AAAA,MACrD,QAAQ,SAAS;AAAA,aACV;AAAA,UACH,OAAO,SAAS,QAAQ,MACpB,cAAc,aAAa,UAAU,UAAU,KAAK,IACpD;AAAA,aACD;AAAA,UACH,OAAO,SAAS,QAAQ,MACpB,aAAa,aAAa,UAAU,UAAU,KAAK,IACnD;AAAA,aACD;AAAA,UACH,OACG,WAAW,YAAY,QAAQ,GAChC,WAAW,aAAa,UAAU,UAAU,KAAK;AAAA;AAAA,MAGvD,IAAI,aAAY,QAAQ,KAAK,eAAc,QAAQ;AAAA,QACjD,OAAgB,QAAT,OACH,OACA,eAAe,aAAa,UAAU,UAAU,OAAO,IAAI;AAAA,MACjE,IAAmB,OAAO,SAAS,SAA/B;AAAA,QACF,OAAO,WACL,aACA,UACA,eAAe,QAAQ,GACvB,KACF;AAAA,MACF,IAAI,SAAS,aAAa;AAAA,QACxB,OAAO,WACL,aACA,UACA,gCAAgC,aAAa,QAAQ,GACrD,KACF;AAAA,MACF,6BAA6B,aAAa,QAAQ;AAAA,IACpD;AAAA,IACA,OAAO;AAAA;AAAA,EAET,SAAS,aAAa,CACpB,kBACA,aACA,QACA,UACA,OACA;AAAA,IACA,IACgB,OAAO,aAApB,YAAuC,aAAP,MACpB,OAAO,aAApB,YACa,OAAO,aAApB;AAAA,MAEA,OACG,mBAAmB,iBAAiB,IAAI,MAAM,KAAK,MACpD,eAAe,aAAa,kBAAkB,KAAK,UAAU,KAAK;AAAA,IAEtE,IAAiB,OAAO,aAApB,YAAyC,aAAT,MAAmB;AAAA,MACrD,QAAQ,SAAS;AAAA,aACV;AAAA,UACH,OACG,mBACC,iBAAiB,IACN,SAAS,QAAlB,OAAwB,SAAS,SAAS,GAC5C,KAAK,MACP,cAAc,aAAa,kBAAkB,UAAU,KAAK;AAAA,aAE3D;AAAA,UACH,OACG,mBACC,iBAAiB,IACN,SAAS,QAAlB,OAAwB,SAAS,SAAS,GAC5C,KAAK,MACP,aAAa,aAAa,kBAAkB,UAAU,KAAK;AAAA,aAE1D;AAAA,UACH,OACG,WAAW,YAAY,QAAQ,GAChC,cACE,kBACA,aACA,QACA,UACA,KACF;AAAA;AAAA,MAGN,IAAI,aAAY,QAAQ,KAAK,eAAc,QAAQ;AAAA,QACjD,OACG,mBAAmB,iBAAiB,IAAI,MAAM,KAAK,MACpD,eAAe,aAAa,kBAAkB,UAAU,OAAO,IAAI;AAAA,MAEvE,IAAmB,OAAO,SAAS,SAA/B;AAAA,QACF,OAAO,cACL,kBACA,aACA,QACA,eAAe,QAAQ,GACvB,KACF;AAAA,MACF,IAAI,SAAS,aAAa;AAAA,QACxB,OAAO,cACL,kBACA,aACA,QACA,gCAAgC,aAAa,QAAQ,GACrD,KACF;AAAA,MACF,6BAA6B,aAAa,QAAQ;AAAA,IACpD;AAAA,IACA,OAAO;AAAA;AAAA,EAET,SAAS,sBAAsB,CAC7B,aACA,mBACA,aACA,OACA;AAAA,IACA,SACM,sBAAsB,MACxB,mBAAmB,MACnB,WAAW,mBACX,SAAU,oBAAoB,GAC9B,eAAe,KACR,aAAT,QAAqB,SAAS,YAAY,QAC1C,UACA;AAAA,MACA,SAAS,QAAQ,UACX,eAAe,UAAY,WAAW,QACvC,eAAe,SAAS;AAAA,MAC7B,IAAI,WAAW,WACb,aACA,UACA,YAAY,SACZ,KACF;AAAA,MACA,IAAa,aAAT,MAAmB;AAAA,QACZ,aAAT,SAAsB,WAAW;AAAA,QACjC;AAAA,MACF;AAAA,MACA,0BACE,YACS,SAAS,cAAlB,QACA,YAAY,aAAa,QAAQ;AAAA,MACnC,oBAAoB,WAAW,UAAU,mBAAmB,MAAM;AAAA,MACzD,qBAAT,OACK,sBAAsB,WACtB,iBAAiB,UAAU;AAAA,MAChC,mBAAmB;AAAA,MACnB,WAAW;AAAA,IACb;AAAA,IACA,IAAI,WAAW,YAAY;AAAA,MACzB,OACE,wBAAwB,aAAa,QAAQ,GAC7C,eAAe,aAAa,aAAa,MAAM,GAC/C;AAAA,IAEJ,IAAa,aAAT,MAAmB;AAAA,MACrB,MAAO,SAAS,YAAY,QAAQ;AAAA,QACjC,WAAW,YAAY,aAAa,YAAY,SAAS,KAAK,GACpD,aAAT,SACI,oBAAoB,WACpB,UACA,mBACA,MACF,GACS,qBAAT,OACK,sBAAsB,WACtB,iBAAiB,UAAU,UAC/B,mBAAmB;AAAA,MAC1B,eAAe,aAAa,aAAa,MAAM;AAAA,MAC/C,OAAO;AAAA,IACT;AAAA,IACA,KACE,WAAW,qBAAqB,QAAQ,EACxC,SAAS,YAAY,QACrB;AAAA,MAEC,eAAe,cACd,UACA,aACA,QACA,YAAY,SACZ,KACF,GACW,iBAAT,SACG,0BACU,aAAa,cAAtB,QACA,SAAS,OACE,aAAa,QAAtB,OAA4B,SAAS,aAAa,GACpD,GACD,oBAAoB,WACnB,cACA,mBACA,MACF,GACS,qBAAT,OACK,sBAAsB,eACtB,iBAAiB,UAAU,cAC/B,mBAAmB;AAAA,IAC1B,0BACE,SAAS,QAAQ,QAAS,CAAC,OAAO;AAAA,MAChC,OAAO,YAAY,aAAa,KAAK;AAAA,KACtC;AAAA,IACH,eAAe,aAAa,aAAa,MAAM;AAAA,IAC/C,OAAO;AAAA;AAAA,EAET,SAAS,yBAAyB,CAChC,aACA,mBACA,aACA,OACA;AAAA,IACA,IAAY,eAAR;AAAA,MAAqB,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,IAChE,SACM,sBAAsB,MACxB,mBAAmB,MACnB,WAAW,mBACX,SAAU,oBAAoB,GAC9B,eAAe,MACf,OAAO,YAAY,KAAK,EACjB,aAAT,QAAqB,CAAC,KAAK,MAC3B,UAAU,OAAO,YAAY,KAAK,GAClC;AAAA,MACA,SAAS,QAAQ,UACX,eAAe,UAAY,WAAW,QACvC,eAAe,SAAS;AAAA,MAC7B,IAAI,WAAW,WAAW,aAAa,UAAU,KAAK,OAAO,KAAK;AAAA,MAClE,IAAa,aAAT,MAAmB;AAAA,QACZ,aAAT,SAAsB,WAAW;AAAA,QACjC;AAAA,MACF;AAAA,MACA,0BACE,YACS,SAAS,cAAlB,QACA,YAAY,aAAa,QAAQ;AAAA,MACnC,oBAAoB,WAAW,UAAU,mBAAmB,MAAM;AAAA,MACzD,qBAAT,OACK,sBAAsB,WACtB,iBAAiB,UAAU;AAAA,MAChC,mBAAmB;AAAA,MACnB,WAAW;AAAA,IACb;AAAA,IACA,IAAI,KAAK;AAAA,MACP,OACE,wBAAwB,aAAa,QAAQ,GAC7C,eAAe,aAAa,aAAa,MAAM,GAC/C;AAAA,IAEJ,IAAa,aAAT,MAAmB;AAAA,MACrB,MAAO,CAAC,KAAK,MAAM,UAAU,OAAO,YAAY,KAAK;AAAA,QAClD,OAAO,YAAY,aAAa,KAAK,OAAO,KAAK,GACvC,SAAT,SACI,oBAAoB,WAAW,MAAM,mBAAmB,MAAM,GACvD,qBAAT,OACK,sBAAsB,OACtB,iBAAiB,UAAU,MAC/B,mBAAmB;AAAA,MAC1B,eAAe,aAAa,aAAa,MAAM;AAAA,MAC/C,OAAO;AAAA,IACT;AAAA,IACA,KACE,WAAW,qBAAqB,QAAQ,EACxC,CAAC,KAAK,MACN,UAAU,OAAO,YAAY,KAAK;AAAA,MAEjC,OAAO,cAAc,UAAU,aAAa,QAAQ,KAAK,OAAO,KAAK,GAC3D,SAAT,SACG,0BACU,KAAK,cAAd,QACA,SAAS,OAAgB,KAAK,QAAd,OAAoB,SAAS,KAAK,GAAG,GACtD,oBAAoB,WAAW,MAAM,mBAAmB,MAAM,GACtD,qBAAT,OACK,sBAAsB,OACtB,iBAAiB,UAAU,MAC/B,mBAAmB;AAAA,IAC1B,0BACE,SAAS,QAAQ,QAAS,CAAC,OAAO;AAAA,MAChC,OAAO,YAAY,aAAa,KAAK;AAAA,KACtC;AAAA,IACH,eAAe,aAAa,aAAa,MAAM;AAAA,IAC/C,OAAO;AAAA;AAAA,EAET,SAAS,wBAAwB,CAC/B,aACA,mBACA,UACA,OACA;AAAA,IACa,OAAO,aAApB,YACW,aAAT,QACA,SAAS,SAAS,wBACT,SAAS,QAAlB,SACC,WAAW,SAAS,MAAM;AAAA,IAC7B,IAAiB,OAAO,aAApB,YAAyC,aAAT,MAAmB;AAAA,MACrD,QAAQ,SAAS;AAAA,aACV;AAAA,UACH,GAAG;AAAA,YACD,SAAS,MAAM,SAAS,IAAc,sBAAT,QAA8B;AAAA,cACzD,IAAI,kBAAkB,QAAQ,KAAK;AAAA,gBACjC,MAAM,SAAS;AAAA,gBACf,IAAI,QAAQ,sBAAqB;AAAA,kBAC/B,IAAU,kBAAkB,QAAxB,GAA6B;AAAA,oBAC/B,wBACE,aACA,kBAAkB,OACpB;AAAA,oBACA,QAAQ,SACN,mBACA,SAAS,MAAM,QACjB;AAAA,oBACA,MAAM,SAAS;AAAA,oBACf,cAAc;AAAA,oBACd;AAAA,kBACF;AAAA,gBACF,EAAO,SACL,kBAAkB,gBAAgB,OACpB,OAAO,QAApB,YACU,QAAT,QACA,IAAI,aAAa,oBACjB,YAAY,GAAG,MAAM,kBAAkB,MACzC;AAAA,kBACA,wBACE,aACA,kBAAkB,OACpB;AAAA,kBACA,QAAQ,SAAS,mBAAmB,SAAS,KAAK;AAAA,kBAClD,UAAU,OAAO,QAAQ;AAAA,kBACzB,MAAM,SAAS;AAAA,kBACf,cAAc;AAAA,kBACd;AAAA,gBACF;AAAA,gBACA,wBAAwB,aAAa,iBAAiB;AAAA,gBACtD;AAAA,cACF,EAAO;AAAA,4BAAY,aAAa,iBAAiB;AAAA,cACjD,oBAAoB,kBAAkB;AAAA,YACxC;AAAA,YACA,SAAS,SAAS,wBACZ,QAAQ,wBACR,SAAS,MAAM,UACf,YAAY,MACZ,OACA,SAAS,GACX,GACC,MAAM,SAAS,aACf,cAAc,UACb,QAAQ,4BACR,SAAS,MACT,SAAS,KACT,SAAS,OACT,MACA,YAAY,MACZ,KACF,GACA,UAAU,OAAO,QAAQ,GACxB,MAAM,SAAS,aACf,cAAc;AAAA,UACrB;AAAA,UACA,OAAO,iBAAiB,WAAW;AAAA,aAChC;AAAA,UACH,GAAG;AAAA,YACD,KAAK,MAAM,SAAS,IAAc,sBAAT,QAA8B;AAAA,cACrD,IAAI,kBAAkB,QAAQ;AAAA,gBAC5B,IACQ,kBAAkB,QAAxB,KACA,kBAAkB,UAAU,kBAC1B,SAAS,iBACX,kBAAkB,UAAU,mBAC1B,SAAS,gBACX;AAAA,kBACA,wBACE,aACA,kBAAkB,OACpB;AAAA,kBACA,QAAQ,SAAS,mBAAmB,SAAS,YAAY,CAAC,CAAC;AAAA,kBAC3D,MAAM,SAAS;AAAA,kBACf,cAAc;AAAA,kBACd;AAAA,gBACF,EAAO;AAAA,kBACL,wBAAwB,aAAa,iBAAiB;AAAA,kBACtD;AAAA;AAAA,cAEC;AAAA,4BAAY,aAAa,iBAAiB;AAAA,cAC/C,oBAAoB,kBAAkB;AAAA,YACxC;AAAA,YACA,QAAQ,sBAAsB,UAAU,YAAY,MAAM,KAAK;AAAA,YAC/D,MAAM,SAAS;AAAA,YACf,cAAc;AAAA,UAChB;AAAA,UACA,OAAO,iBAAiB,WAAW;AAAA,aAChC;AAAA,UACH,OACG,WAAW,YAAY,QAAQ,GAChC,yBACE,aACA,mBACA,UACA,KACF;AAAA;AAAA,MAGN,IAAI,aAAY,QAAQ;AAAA,QACtB,OAAO,uBACL,aACA,mBACA,UACA,KACF;AAAA,MACF,IAAI,eAAc,QAAQ,GAAG;AAAA,QAC3B,MAAM,eAAc,QAAQ;AAAA,QAC5B,IAAmB,OAAO,QAAtB;AAAA,UAA2B,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,QACtE,WAAW,IAAI,KAAK,QAAQ;AAAA,QAC5B,OAAO,0BACL,aACA,mBACA,UACA,KACF;AAAA,MACF;AAAA,MACA,IAAmB,OAAO,SAAS,SAA/B;AAAA,QACF,OAAO,yBACL,aACA,mBACA,eAAe,QAAQ,GACvB,KACF;AAAA,MACF,IAAI,SAAS,aAAa;AAAA,QACxB,OAAO,yBACL,aACA,mBACA,gCAAgC,aAAa,QAAQ,GACrD,KACF;AAAA,MACF,6BAA6B,aAAa,QAAQ;AAAA,IACpD;AAAA,IACA,OAAqB,OAAO,aAApB,YAAuC,aAAP,MACzB,OAAO,aAApB,YACa,OAAO,aAApB,YACI,WAAW,KAAK,UACT,sBAAT,QAAoC,kBAAkB,QAAxB,KACzB,wBAAwB,aAAa,kBAAkB,OAAO,GAC9D,QAAQ,SAAS,mBAAmB,QAAQ,GAC5C,MAAM,SAAS,aACf,cAAc,UACd,wBAAwB,aAAa,iBAAiB,GACtD,QAAQ,oBAAoB,UAAU,YAAY,MAAM,KAAK,GAC7D,MAAM,SAAS,aACf,cAAc,QACnB,iBAAiB,WAAW,KAC5B,wBAAwB,aAAa,iBAAiB;AAAA;AAAA,EAE5D,OAAO,QAAS,CAAC,aAAa,mBAAmB,UAAU,OAAO;AAAA,IAChE,IAAI;AAAA,MACF,yBAAyB;AAAA,MACzB,IAAI,kBAAkB,yBACpB,aACA,mBACA,UACA,KACF;AAAA,MACA,kBAAkB;AAAA,MAClB,OAAO;AAAA,MACP,OAAO,GAAG;AAAA,MACV,IAAI,MAAM,qBAAqB,MAAM;AAAA,QAAyB,MAAM;AAAA,MACpE,IAAI,QAAQ,qBAAqB,IAAI,GAAG,MAAM,YAAY,IAAI;AAAA,MAC9D,MAAM,QAAQ;AAAA,MACd,MAAM,SAAS;AAAA,MACf,OAAO;AAAA,cACP;AAAA;AAAA;AAON,SAAS,qBAAqB,CAAC,OAAO;AAAA,EACpC,MAAM,cAAc;AAAA,IAClB,WAAW,MAAM;AAAA,IACjB,iBAAiB;AAAA,IACjB,gBAAgB;AAAA,IAChB,QAAQ,EAAE,SAAS,MAAM,OAAO,GAAG,iBAAiB,KAAK;AAAA,IACzD,WAAW;AAAA,EACb;AAAA;AAEF,SAAS,gBAAgB,CAAC,SAAS,gBAAgB;AAAA,EACjD,UAAU,QAAQ;AAAA,EAClB,eAAe,gBAAgB,YAC5B,eAAe,cAAc;AAAA,IAC5B,WAAW,QAAQ;AAAA,IACnB,iBAAiB,QAAQ;AAAA,IACzB,gBAAgB,QAAQ;AAAA,IACxB,QAAQ,QAAQ;AAAA,IAChB,WAAW;AAAA,EACb;AAAA;AAEJ,SAAS,YAAY,CAAC,MAAM;AAAA,EAC1B,OAAO,EAAE,MAAY,KAAK,GAAG,SAAS,MAAM,UAAU,MAAM,MAAM,KAAK;AAAA;AAEzE,SAAS,aAAa,CAAC,OAAO,QAAQ,MAAM;AAAA,EAC1C,IAAI,cAAc,MAAM;AAAA,EACxB,IAAa,gBAAT;AAAA,IAAsB,OAAO;AAAA,EACjC,cAAc,YAAY;AAAA,EAC1B,KAAW,mBAAmB,OAA1B,GAA8B;AAAA,IAChC,IAAI,UAAU,YAAY;AAAA,IACjB,YAAT,OACK,OAAO,OAAO,UACb,OAAO,OAAO,QAAQ,MAAQ,QAAQ,OAAO;AAAA,IACnD,YAAY,UAAU;AAAA,IACtB,SAAS,uBAAuB,KAAK;AAAA,IACrC,8BAA8B,OAAO,MAAM,IAAI;AAAA,IAC/C,OAAO;AAAA,EACT;AAAA,EACA,gBAAgB,OAAO,aAAa,QAAQ,IAAI;AAAA,EAChD,OAAO,uBAAuB,KAAK;AAAA;AAErC,SAAS,mBAAmB,CAAC,OAAM,OAAO,MAAM;AAAA,EAC9C,QAAQ,MAAM;AAAA,EACd,IAAa,UAAT,SAAoB,QAAQ,MAAM,SAAgB,OAAO,aAAd,IAAyB;AAAA,IACtE,IAAI,aAAa,MAAM;AAAA,IACvB,cAAc,MAAK;AAAA,IACnB,QAAQ;AAAA,IACR,MAAM,QAAQ;AAAA,IACd,kBAAkB,OAAM,IAAI;AAAA,EAC9B;AAAA;AAEF,SAAS,qBAAqB,CAAC,gBAAgB,gBAAgB;AAAA,EAC7D,MAA2B,aAAvB,OACuB,WAAzB,YAAU;AAAA,EACZ,IACW,YAAT,SACE,UAAU,QAAQ,aAAc,UAAU,UAC5C;AAAA,IACA,IAAI,WAAW,MACb,UAAU;AAAA,IACZ,QAAQ,MAAM;AAAA,IACd,IAAa,UAAT,MAAgB;AAAA,MAClB,GAAG;AAAA,QACD,IAAI,QAAQ;AAAA,UACV,MAAM,MAAM;AAAA,UACZ,KAAK,MAAM;AAAA,UACX,SAAS,MAAM;AAAA,UACf,UAAU;AAAA,UACV,MAAM;AAAA,QACR;AAAA,QACS,YAAT,OACK,WAAW,UAAU,QACrB,UAAU,QAAQ,OAAO;AAAA,QAC9B,QAAQ,MAAM;AAAA,MAChB,SAAkB,UAAT;AAAA,MACA,YAAT,OACK,WAAW,UAAU,iBACrB,UAAU,QAAQ,OAAO;AAAA,IAChC,EAAO;AAAA,iBAAW,UAAU;AAAA,IAC5B,QAAQ;AAAA,MACN,WAAW,QAAQ;AAAA,MACnB,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,QAAQ,QAAQ;AAAA,MAChB,WAAW,QAAQ;AAAA,IACrB;AAAA,IACA,eAAe,cAAc;AAAA,IAC7B;AAAA,EACF;AAAA,EACA,iBAAiB,MAAM;AAAA,EACd,mBAAT,OACK,MAAM,kBAAkB,iBACxB,eAAe,OAAO;AAAA,EAC3B,MAAM,iBAAiB;AAAA;AAGzB,SAAS,2CAA2C,GAAG;AAAA,EACrD,IAAI,iCAAiC;AAAA,IACnC,IAAI,0BAA0B;AAAA,IAC9B,IAAa,4BAAT;AAAA,MAAkC,MAAM;AAAA,EAC9C;AAAA;AAEF,SAAS,kBAAkB,CACzB,yBACA,OACA,mBACA,aACA;AAAA,EACA,kCAAkC;AAAA,EAClC,IAAI,QAAQ,wBAAwB;AAAA,EACpC,iBAAiB;AAAA,EACjB,MAA4B,iBACH,mBAAN,OACjB,eAAe,MAAM,OAAO;AAAA,EAC9B,IAAa,iBAAT,MAAuB;AAAA,IACzB,MAAM,OAAO,UAAU;AAAA,IACvB,IAAI,oBAAoB,cACtB,qBAAqB,kBAAkB;AAAA,IACzC,kBAAkB,OAAO;AAAA,IAChB,mBAAT,OACK,kBAAkB,qBAClB,eAAe,OAAO;AAAA,IAC3B,iBAAiB;AAAA,IACjB,IAAI,UAAU,wBAAwB;AAAA,IAC7B,YAAT,SACI,UAAU,QAAQ,aACnB,eAAe,QAAQ,gBACxB,iBAAiB,mBACL,iBAAT,OACI,QAAQ,kBAAkB,qBAC1B,aAAa,OAAO,oBACxB,QAAQ,iBAAiB;AAAA,EAChC;AAAA,EACA,IAAa,oBAAT,MAA0B;AAAA,IAC5B,IAAI,WAAW,MAAM;AAAA,IACrB,iBAAiB;AAAA,IACjB,UAAU,qBAAqB,oBAAoB;AAAA,IACnD,eAAe;AAAA,IACf,GAAG;AAAA,MACD,IAAI,aAAa,aAAa,OAAO,YACnC,iBAAiB,eAAe,aAAa;AAAA,MAC/C,IACE,kBACK,gCAAgC,gBAAgB,cAChD,cAAc,gBAAgB,YACnC;AAAA,QACM,eAAN,KACE,eAAe,yBACd,kCAAkC;AAAA,QAC5B,YAAT,SACG,UAAU,QAAQ,OACjB;AAAA,UACE,MAAM;AAAA,UACN,KAAK,aAAa;AAAA,UAClB,SAAS,aAAa;AAAA,UACtB,UAAU;AAAA,UACV,MAAM;AAAA,QACR;AAAA,QACJ,GAAG;AAAA,UACD,IAAI,iBAAiB,yBACnB,SAAS;AAAA,UACX,aAAa;AAAA,UACb,IAAI,WAAW;AAAA,UACf,QAAQ,OAAO;AAAA,iBACR;AAAA,cACH,iBAAiB,OAAO;AAAA,cACxB,IAAmB,OAAO,mBAAtB,YAAsC;AAAA,gBACxC,WAAW,eAAe,KAAK,UAAU,UAAU,UAAU;AAAA,gBAC7D;AAAA,cACF;AAAA,cACA,WAAW;AAAA,cACX;AAAA,iBACG;AAAA,cACH,eAAe,QAAS,eAAe,QAAQ,SAAU;AAAA,iBACtD;AAAA,cACH,iBAAiB,OAAO;AAAA,cACxB,aACiB,OAAO,mBAAtB,aACI,eAAe,KAAK,UAAU,UAAU,UAAU,IAClD;AAAA,cACN,IAAa,eAAT,QAAkC,eAAN;AAAA,gBAAkB;AAAA,cAClD,WAAW,QAAO,CAAC,GAAG,UAAU,UAAU;AAAA,cAC1C;AAAA,iBACG;AAAA,cACH,iBAAiB;AAAA;AAAA,QAEvB;AAAA,QACA,aAAa,aAAa;AAAA,QACjB,eAAT,SACI,wBAAwB,SAAS,IACnC,mBAAmB,wBAAwB,SAAS,OACnD,iBAAiB,MAAM,WACf,mBAAT,OACK,MAAM,YAAY,CAAC,UAAU,IAC9B,eAAe,KAAK,UAAU;AAAA,MACtC,EACE;AAAA,QAAC,iBAAiB;AAAA,UAChB,MAAM;AAAA,UACN,KAAK,aAAa;AAAA,UAClB,SAAS,aAAa;AAAA,UACtB,UAAU,aAAa;AAAA,UACvB,MAAM;AAAA,QACR,GACW,YAAT,QACM,qBAAqB,UAAU,gBAChC,oBAAoB,YACpB,UAAU,QAAQ,OAAO,gBAC7B,kBAAkB;AAAA,MACvB,eAAe,aAAa;AAAA,MAC5B,IAAa,iBAAT;AAAA,QACF,IAAM,eAAe,MAAM,OAAO,SAAmB,iBAAT;AAAA,UAC1C;AAAA,QAEA;AAAA,UAAC,iBAAiB,cACf,eAAe,eAAe,MAC9B,eAAe,OAAO,MACtB,MAAM,iBAAiB,gBACvB,MAAM,OAAO,UAAU;AAAA,IAChC,SAAS;AAAA,IACA,YAAT,SAAqB,oBAAoB;AAAA,IACzC,MAAM,YAAY;AAAA,IAClB,MAAM,kBAAkB;AAAA,IACxB,MAAM,iBAAiB;AAAA,IACd,oBAAT,SAA6B,MAAM,OAAO,QAAQ;AAAA,IAClD,kCAAkC;AAAA,IAClC,wBAAwB,QAAQ;AAAA,IAChC,wBAAwB,gBAAgB;AAAA,EAC1C;AAAA;AAEF,SAAS,YAAY,CAAC,UAAU,SAAS;AAAA,EACvC,IAAmB,OAAO,aAAtB;AAAA,IACF,MAAM,MAAM,wBAAuB,KAAK,QAAQ,CAAC;AAAA,EACnD,SAAS,KAAK,OAAO;AAAA;AAEvB,SAAS,eAAe,CAAC,aAAa,SAAS;AAAA,EAC7C,IAAI,YAAY,YAAY;AAAA,EAC5B,IAAa,cAAT;AAAA,IACF,KACE,YAAY,YAAY,MAAM,cAAc,EAC5C,cAAc,UAAU,QACxB;AAAA,MAEA,aAAa,UAAU,cAAc,OAAO;AAAA;AAIlD,SAAS,iBAAiB,CAAC,OAAO,SAAS;AAAA,EACzC,QAAQ;AAAA,EACR,MAAK,gCAAgC,KAAK;AAAA,EAC1C,MAAK,8BAA8B,OAAO;AAAA,EAC1C,uBAAuB,QAAQ,QAAQ;AAAA;AAEzC,SAAS,yBAAyB,GAAG;AAAA,EACnC,MAAK,gCAAgC,oBAAoB;AAAA,EACzD,MAAK,8BAA8B,6BAA6B,OAAO;AAAA;AAEzE,SAAS,gBAAgB,GAAG;AAAA,EAC1B,uBAAuB,+BAA+B;AAAA,EACtD,KAAI,4BAA4B;AAAA,EAChC,KAAI,8BAA8B;AAAA;AAIpC,SAAS,8BAA8B,CAAC,SAAS;AAAA,EAC/C,IAAI,UAAU,QAAQ;AAAA,EACtB,MAAK,qBAAqB,oBAAoB,UAAU,CAAC;AAAA,EACzD,MAAK,4BAA4B,OAAO;AAAA,EAC/B,kBAAT,SACY,YAAT,QAA6B,6BAA6B,YAAtC,OAChB,gBAAgB,UACR,QAAQ,kBAAjB,SAAmC,gBAAgB;AAAA;AAE3D,SAAS,qCAAqC,CAAC,OAAO;AAAA,EACpD,MAAK,qBAAqB,oBAAoB,OAAO;AAAA,EACrD,MAAK,4BAA4B,KAAK;AAAA,EAC7B,kBAAT,SAA2B,gBAAgB;AAAA;AAE7C,SAAS,4BAA4B,CAAC,OAAO;AAAA,EACpC,MAAM,QAAb,MACK,MAAK,qBAAqB,oBAAoB,OAAO,GACtD,MAAK,4BAA4B,KAAK,GAC7B,kBAAT,SAA2B,gBAAgB,UAC3C,4BAA4B,KAAK;AAAA;AAEvC,SAAS,2BAA2B,GAAG;AAAA,EACrC,MAAK,qBAAqB,oBAAoB,OAAO;AAAA,EACrD,MAAK,4BAA4B,2BAA2B,OAAO;AAAA;AAErE,SAAS,kBAAkB,CAAC,OAAO;AAAA,EACjC,KAAI,0BAA0B;AAAA,EAC9B,kBAAkB,UAAU,gBAAgB;AAAA,EAC5C,KAAI,mBAAmB;AAAA;AAGzB,SAAS,kBAAkB,CAAC,KAAK;AAAA,EAC/B,SAAS,OAAO,IAAc,SAAT,QAAiB;AAAA,IACpC,IAAW,KAAK,QAAZ,IAAiB;AAAA,MACnB,IAAI,QAAQ,KAAK;AAAA,MACjB,IACW,UAAT,SACE,QAAQ,MAAM,YACP,UAAT,QACE,0BAA0B,KAAK,KAC/B,2BAA2B,KAAK;AAAA,QAElC,OAAO;AAAA,IACX,EAAO,SACE,KAAK,QAAZ,OACgB,KAAK,cAAc,gBAAlC,cACiB,KAAK,cAAc,gBAAnC,eACgC,KAAK,cAAc,gBAAnD,+BACe,KAAK,cAAc,gBAAlC,aACF;AAAA,MACA,KAAW,KAAK,QAAQ,SAApB;AAAA,QAA0B,OAAO;AAAA,IACvC,EAAO,SAAa,KAAK,UAAd,MAAqB;AAAA,MAC9B,KAAK,MAAM,SAAS;AAAA,MACpB,OAAO,KAAK;AAAA,MACZ;AAAA,IACF;AAAA,IACA,IAAI,SAAS;AAAA,MAAK;AAAA,IAClB,MAAgB,KAAK,YAAd,QAAyB;AAAA,MAC9B,IAAa,KAAK,WAAd,QAAwB,KAAK,WAAW;AAAA,QAAK,OAAO;AAAA,MACxD,OAAO,KAAK;AAAA,IACd;AAAA,IACA,KAAK,QAAQ,SAAS,KAAK;AAAA,IAC3B,OAAO,KAAK;AAAA,EACd;AAAA,EACA,OAAO;AAAA;AAaT,SAAS,qBAAqB,GAAG;AAAA,EAC/B,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA;AAEzC,SAAS,kBAAkB,CAAC,UAAU,UAAU;AAAA,EAC9C,IAAa,aAAT;AAAA,IAAmB,OAAO;AAAA,EAC9B,SAAS,IAAI,EAAG,IAAI,SAAS,UAAU,IAAI,SAAS,QAAQ;AAAA,IAC1D,IAAI,CAAC,SAAS,SAAS,IAAI,SAAS,EAAE;AAAA,MAAG,OAAO;AAAA,EAClD,OAAO;AAAA;AAET,SAAS,eAAe,CACtB,SACA,gBACA,YACA,OACA,WACA,iBACA;AAAA,EACA,cAAc;AAAA,EACd,0BAA0B;AAAA,EAC1B,eAAe,gBAAgB;AAAA,EAC/B,eAAe,cAAc;AAAA,EAC7B,eAAe,QAAQ;AAAA,EACvB,sBAAqB,IACV,YAAT,QAA6B,QAAQ,kBAAjB,OAChB,yBACA;AAAA,EACN,sCAAsC;AAAA,EACtC,kBAAkB,WAAU,OAAO,SAAS;AAAA,EAC5C,sCAAsC;AAAA,EACtC,+CACG,kBAAkB,qBACjB,gBACA,YACA,OACA,SACF;AAAA,EACF,qBAAqB,OAAO;AAAA,EAC5B,OAAO;AAAA;AAET,SAAS,oBAAoB,CAAC,SAAS;AAAA,EACrC,sBAAqB,IAAI;AAAA,EACzB,IAAI,uBAAgC,gBAAT,QAAiC,YAAY,SAArB;AAAA,EACnD,cAAc;AAAA,EACd,qBAAqB,cAAc,0BAA0B;AAAA,EAC7D,+BAA+B;AAAA,EAC/B,uBAAuB;AAAA,EACvB,gBAAgB;AAAA,EAChB,IAAI;AAAA,IAAsB,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,EACxD,YAAT,QACE,qBACE,UAAU,QAAQ,cACX,YAAT,QACE,sBAAsB,OAAO,MAC5B,mBAAmB;AAAA;AAE1B,SAAS,oBAAoB,CAAC,gBAAgB,YAAW,OAAO,WAAW;AAAA,EACzE,0BAA0B;AAAA,EAC1B,IAAI,oBAAoB;AAAA,EACxB,GAAG;AAAA,IACD,+CAA+C,gBAAgB;AAAA,IAC/D,uBAAuB;AAAA,IACvB,6CAA6C;AAAA,IAC7C,IAAI,MAAM;AAAA,MAAmB,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,IACpE,qBAAqB;AAAA,IACrB,qBAAqB,cAAc;AAAA,IACnC,IAAY,eAAe,eAAvB,MAAoC;AAAA,MACtC,IAAI,WAAW,eAAe;AAAA,MAC9B,SAAS,aAAa;AAAA,MACtB,SAAS,SAAS;AAAA,MAClB,SAAS,SAAS;AAAA,MACV,SAAS,aAAjB,SAA+B,SAAS,UAAU,QAAQ;AAAA,IAC5D;AAAA,IACA,sBAAqB,IAAI;AAAA,IACzB,WAAW,WAAU,OAAO,SAAS;AAAA,EACvC,SAAS;AAAA,EACT,OAAO;AAAA;AAET,SAAS,4BAA4B,GAAG;AAAA,EACtC,IAAI,aAAa,sBAAqB,GACpC,gBAAgB,WAAW,SAAS,EAAE;AAAA,EACxC,gBACiB,OAAO,cAAc,SAApC,aACI,YAAY,aAAa,IACzB;AAAA,EACN,aAAa,WAAW,SAAS,EAAE;AAAA,GACzB,gBAAT,OAAuB,YAAY,gBAAgB,UAAU,eAC3D,wBAAwB,SAAS;AAAA,EACpC,OAAO;AAAA;AAET,SAAS,oBAAoB,GAAG;AAAA,EAC9B,IAAI,kBAAwB,mBAAN;AAAA,EACtB,iBAAiB;AAAA,EACjB,OAAO;AAAA;AAET,SAAS,YAAY,CAAC,SAAS,gBAAgB,OAAO;AAAA,EACpD,eAAe,cAAc,QAAQ;AAAA,EACrC,eAAe,SAAS;AAAA,EACxB,QAAQ,SAAS,CAAC;AAAA;AAEpB,SAAS,kBAAkB,CAAC,gBAAgB;AAAA,EAC1C,IAAI,8BAA8B;AAAA,IAChC,KACE,iBAAiB,eAAe,cACvB,mBAAT,QAEA;AAAA,MACA,IAAI,QAAQ,eAAe;AAAA,MAClB,UAAT,SAAmB,MAAM,UAAU;AAAA,MACnC,iBAAiB,eAAe;AAAA,IAClC;AAAA,IACA,+BAA+B;AAAA,EACjC;AAAA,EACA,cAAc;AAAA,EACd,qBAAqB,cAAc,0BAA0B;AAAA,EAC7D,6CAA6C;AAAA,EAC7C,uBAAuB,iBAAiB;AAAA,EACxC,gBAAgB;AAAA;AAElB,SAAS,uBAAuB,GAAG;AAAA,EACjC,IAAI,OAAO;AAAA,IACT,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,IACX,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AAAA,EACS,uBAAT,OACK,wBAAwB,gBAAgB,qBAAqB,OAC7D,qBAAqB,mBAAmB,OAAO;AAAA,EACpD,OAAO;AAAA;AAET,SAAS,wBAAwB,GAAG;AAAA,EAClC,IAAa,gBAAT,MAAsB;AAAA,IACxB,IAAI,kBAAkB,wBAAwB;AAAA,IAC9C,kBACW,oBAAT,OAA2B,gBAAgB,gBAAgB;AAAA,EAC/D,EAAO;AAAA,sBAAkB,YAAY;AAAA,EACrC,IAAI,yBACO,uBAAT,OACI,wBAAwB,gBACxB,mBAAmB;AAAA,EACzB,IAAa,2BAAT;AAAA,IACD,qBAAqB,wBACnB,cAAc;AAAA,EACd;AAAA,IACH,IAAa,oBAAT,MAA0B;AAAA,MAC5B,IAAa,wBAAwB,cAAjC;AAAA,QACF,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,MACzC,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,IACzC;AAAA,IACA,cAAc;AAAA,IACd,kBAAkB;AAAA,MAChB,eAAe,YAAY;AAAA,MAC3B,WAAW,YAAY;AAAA,MACvB,WAAW,YAAY;AAAA,MACvB,OAAO,YAAY;AAAA,MACnB,MAAM;AAAA,IACR;AAAA,IACS,uBAAT,OACK,wBAAwB,gBAAgB,qBACvC,kBACD,qBAAqB,mBAAmB,OAAO;AAAA;AAAA,EAEtD,OAAO;AAAA;AAET,SAAS,kCAAkC,GAAG;AAAA,EAC5C,OAAO,EAAE,YAAY,MAAM,QAAQ,MAAM,QAAQ,MAAM,WAAW,KAAK;AAAA;AAEzE,SAAS,WAAW,CAAC,UAAU;AAAA,EAC7B,IAAI,SAAQ;AAAA,EACZ,wBAAwB;AAAA,EACf,kBAAT,SAA2B,gBAAgB,CAAC;AAAA,EAC5C,WAAW,kBAAkB,eAAe,UAAU,MAAK;AAAA,EAC3D,SAAQ;AAAA,GAEI,uBAAT,OACG,OAAM,gBACN,mBAAmB,UAHzB,SAII,SAAQ,OAAM,WACf,sBAAqB,IACX,WAAT,QAA2B,OAAM,kBAAf,OACd,yBACA;AAAA,EACR,OAAO;AAAA;AAET,SAAS,GAAG,CAAC,QAAQ;AAAA,EACnB,IAAa,WAAT,QAAgC,OAAO,WAApB,UAA4B;AAAA,IACjD,IAAmB,OAAO,OAAO,SAA7B;AAAA,MAAmC,OAAO,YAAY,MAAM;AAAA,IAChE,IAAI,OAAO,aAAa;AAAA,MAAoB,OAAO,YAAY,MAAM;AAAA,EACvE;AAAA,EACA,MAAM,MAAM,wBAAuB,KAAK,OAAO,MAAM,CAAC,CAAC;AAAA;AAEzD,SAAS,YAAY,CAAC,MAAM;AAAA,EAC1B,IAAI,YAAY,MACd,cAAc,wBAAwB;AAAA,EAC/B,gBAAT,SAAyB,YAAY,YAAY;AAAA,EACjD,IAAY,aAAR,MAAmB;AAAA,IACrB,IAAI,UAAU,wBAAwB;AAAA,IAC7B,YAAT,SACI,UAAU,QAAQ,aACX,YAAT,SACI,UAAU,QAAQ,WACZ,WAAR,SACG,YAAY;AAAA,MACX,MAAM,QAAQ,KAAK,IAAI,QAAS,CAAC,OAAO;AAAA,QACtC,OAAO,MAAM,MAAM;AAAA,OACpB;AAAA,MACD,OAAO;AAAA,IACT;AAAA,EACR;AAAA,EACQ,aAAR,SAAsB,YAAY,EAAE,MAAM,CAAC,GAAG,OAAO,EAAE;AAAA,EAC9C,gBAAT,SACI,cAAc,mCAAmC,GAClD,wBAAwB,cAAc;AAAA,EACzC,YAAY,YAAY;AAAA,EACxB,cAAc,UAAU,KAAK,UAAU;AAAA,EACvC,IAAe,gBAAN;AAAA,IACP,KACE,cAAc,UAAU,KAAK,UAAU,SAAS,MAAM,IAAI,GAAG,UAAU,EACvE,UAAU,MACV;AAAA,MAEA,YAAY,WAAW;AAAA,EAC3B,UAAU;AAAA,EACV,OAAO;AAAA;AAET,SAAS,iBAAiB,CAAC,OAAO,QAAQ;AAAA,EACxC,OAAsB,OAAO,WAAtB,aAA+B,OAAO,KAAK,IAAI;AAAA;AAExD,SAAS,aAAa,CAAC,SAAS;AAAA,EAC9B,IAAI,OAAO,yBAAyB;AAAA,EACpC,OAAO,kBAAkB,MAAM,aAAa,OAAO;AAAA;AAErD,SAAS,iBAAiB,CAAC,MAAM,SAAS,SAAS;AAAA,EACjD,IAAI,QAAQ,KAAK;AAAA,EACjB,IAAa,UAAT;AAAA,IAAgB,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,EAC3D,MAAM,sBAAsB;AAAA,EAC5B,IAAI,YAAY,KAAK,WACnB,eAAe,MAAM;AAAA,EACvB,IAAa,iBAAT,MAAuB;AAAA,IACzB,IAAa,cAAT,MAAoB;AAAA,MACtB,IAAI,YAAY,UAAU;AAAA,MAC1B,UAAU,OAAO,aAAa;AAAA,MAC9B,aAAa,OAAO;AAAA,IACtB;AAAA,IACA,QAAQ,YAAY,YAAY;AAAA,IAChC,MAAM,UAAU;AAAA,EAClB;AAAA,EACA,eAAe,KAAK;AAAA,EACpB,IAAa,cAAT;AAAA,IAAoB,KAAK,gBAAgB;AAAA,EACxC;AAAA,IACH,UAAU,UAAU;AAAA,IACpB,IAAI,oBAAqB,YAAY,MACnC,mBAAmB,MACnB,SAAS,SACT,qCAAqC;AAAA,IACvC,GAAG;AAAA,MACD,IAAI,aAAa,OAAO,OAAO;AAAA,MAC/B,IACE,eAAe,OAAO,QACjB,gCAAgC,gBAAgB,cAChD,cAAc,gBAAgB,YACnC;AAAA,QACA,IAAI,aAAa,OAAO;AAAA,QACxB,IAAU,eAAN;AAAA,UACO,qBAAT,SACG,mBAAmB,iBAAiB,OACnC;AAAA,YACE,MAAM;AAAA,YACN,YAAY;AAAA,YACZ,SAAS;AAAA,YACT,QAAQ,OAAO;AAAA,YACf,eAAe,OAAO;AAAA,YACtB,YAAY,OAAO;AAAA,YACnB,MAAM;AAAA,UACR,IACF,eAAe,yBACZ,qCAAqC;AAAA,QACvC,UAAK,cAAc,gBAAgB,YAAY;AAAA,UAClD,SAAS,OAAO;AAAA,UAChB,eAAe,yBACZ,qCAAqC;AAAA,UACxC;AAAA,QACF,EACE;AAAA,UAAC,aAAa;AAAA,YACZ,MAAM;AAAA,YACN,YAAY,OAAO;AAAA,YACnB,SAAS;AAAA,YACT,QAAQ,OAAO;AAAA,YACf,eAAe,OAAO;AAAA,YACtB,YAAY,OAAO;AAAA,YACnB,MAAM;AAAA,UACR,GACW,qBAAT,QACM,oBAAoB,mBAAmB,YACxC,YAAY,gBACZ,mBAAmB,iBAAiB,OAAO,YAC/C,wBAAwB,SAAS,YACjC,kCAAkC;AAAA,QACvC,aAAa,OAAO;AAAA,QACpB,uCACE,QAAQ,cAAc,UAAU;AAAA,QAClC,eAAe,OAAO,gBAClB,OAAO,aACP,QAAQ,cAAc,UAAU;AAAA,MACtC,EACE;AAAA,QAAC,aAAa;AAAA,UACZ,MAAM;AAAA,UACN,YAAY,OAAO;AAAA,UACnB,SAAS,OAAO;AAAA,UAChB,QAAQ,OAAO;AAAA,UACf,eAAe,OAAO;AAAA,UACtB,YAAY,OAAO;AAAA,UACnB,MAAM;AAAA,QACR,GACW,qBAAT,QACM,oBAAoB,mBAAmB,YACxC,YAAY,gBACZ,mBAAmB,iBAAiB,OAAO,YAC/C,wBAAwB,SAAS,YACjC,kCAAkC;AAAA,MACvC,SAAS,OAAO;AAAA,IAClB,SAAkB,WAAT,QAAmB,WAAW;AAAA,IAC9B,qBAAT,OACK,YAAY,eACZ,iBAAiB,OAAO;AAAA,IAC7B,IACE,CAAC,SAAS,cAAc,KAAK,aAAa,MACxC,mBAAmB,MACrB,uCACI,UAAU,gCAA0C,YAAT;AAAA,MAE/C,MAAM;AAAA,IACR,KAAK,gBAAgB;AAAA,IACrB,KAAK,YAAY;AAAA,IACjB,KAAK,YAAY;AAAA,IACjB,MAAM,oBAAoB;AAAA;AAAA,EAEnB,cAAT,SAAuB,MAAM,QAAQ;AAAA,EACrC,OAAO,CAAC,KAAK,eAAe,MAAM,QAAQ;AAAA;AAE5C,SAAS,eAAe,CAAC,SAAS;AAAA,EAChC,IAAI,OAAO,yBAAyB,GAClC,QAAQ,KAAK;AAAA,EACf,IAAa,UAAT;AAAA,IAAgB,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,EAC3D,MAAM,sBAAsB;AAAA,EAC5B,MAAqB,UACW,SAA9B,0BAAwB,OACxB,WAAW,KAAK;AAAA,EAClB,IAAa,0BAAT,MAAgC;AAAA,IAClC,MAAM,UAAU;AAAA,IAChB,IAAI,SAAU,wBAAwB,sBAAsB;AAAA,IAC5D;AAAA,MAAI,WAAW,QAAQ,UAAU,OAAO,MAAM,GAAK,SAAS,OAAO;AAAA,WAC5D,WAAW;AAAA,IAClB,SAAS,UAAU,KAAK,aAAa,MAAM,mBAAmB;AAAA,IAC9D,KAAK,gBAAgB;AAAA,IACZ,KAAK,cAAd,SAA4B,KAAK,YAAY;AAAA,IAC7C,MAAM,oBAAoB;AAAA,EAC5B;AAAA,EACA,OAAO,CAAC,UAAU,QAAQ;AAAA;AAE5B,SAAS,uBAAuB,CAAC,WAAW,aAAa,mBAAmB;AAAA,EAC1E,IAAI,QAAQ,yBACV,OAAO,yBAAyB,GAChC,uBAAuB;AAAA,EACzB,IAAI,sBAAsB;AAAA,IACxB,IAAe,sBAAN;AAAA,MAAyB,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,IACzE,oBAAoB,kBAAkB;AAAA,EACxC,EAAO;AAAA,wBAAoB,YAAY;AAAA,EACvC,IAAI,kBAAkB,CAAC,UACpB,eAAe,MAAM,eACtB,iBACF;AAAA,EACA,oBACI,KAAK,gBAAgB,mBAAqB,mBAAmB;AAAA,EACjE,OAAO,KAAK;AAAA,EACZ,aAAa,iBAAiB,KAAK,MAAM,OAAO,MAAM,SAAS,GAAG;AAAA,IAChE;AAAA,EACF,CAAC;AAAA,EACD,IACE,KAAK,gBAAgB,eACrB,mBACU,uBAAT,QAA+B,mBAAmB,cAAc,MAAM,GACvE;AAAA,IACA,MAAM,SAAS;AAAA,IACf,iBACE,GACA,EAAE,SAAc,UAAE,GAClB,oBAAoB,KAClB,MACA,OACA,MACA,mBACA,WACF,GACA,IACF;AAAA,IACA,IAAa,uBAAT;AAAA,MAA6B,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,IACxE,yBACS,cAAc,SAArB,KACA,0BAA0B,OAAO,aAAa,iBAAiB;AAAA,EACnE;AAAA,EACA,OAAO;AAAA;AAET,SAAS,yBAAyB,CAAC,OAAO,aAAa,kBAAkB;AAAA,EACvE,MAAM,SAAS;AAAA,EACf,QAAQ,EAAE,aAA0B,OAAO,iBAAiB;AAAA,EAC5D,cAAc,wBAAwB;AAAA,EAC7B,gBAAT,QACM,cAAc,mCAAmC,GAClD,wBAAwB,cAAc,aACtC,YAAY,SAAS,CAAC,KAAK,MAC1B,mBAAmB,YAAY,QACxB,qBAAT,OACK,YAAY,SAAS,CAAC,KAAK,IAC5B,iBAAiB,KAAK,KAAK;AAAA;AAErC,SAAS,mBAAmB,CAAC,OAAO,MAAM,cAAc,aAAa;AAAA,EACnE,KAAK,QAAQ;AAAA,EACb,KAAK,cAAc;AAAA,EACnB,uBAAuB,IAAI,KAAK,mBAAmB,KAAK;AAAA;AAE1D,SAAS,gBAAgB,CAAC,OAAO,MAAM,WAAW;AAAA,EAChD,OAAO,UAAU,QAAS,GAAG;AAAA,IAC3B,uBAAuB,IAAI,KAAK,mBAAmB,KAAK;AAAA,GACzD;AAAA;AAEH,SAAS,sBAAsB,CAAC,MAAM;AAAA,EACpC,IAAI,oBAAoB,KAAK;AAAA,EAC7B,OAAO,KAAK;AAAA,EACZ,IAAI;AAAA,IACF,IAAI,YAAY,kBAAkB;AAAA,IAClC,OAAO,CAAC,SAAS,MAAM,SAAS;AAAA,IAChC,OAAO,OAAO;AAAA,IACd,OAAO;AAAA;AAAA;AAGX,SAAS,kBAAkB,CAAC,OAAO;AAAA,EACjC,IAAI,QAAO,+BAA+B,OAAO,CAAC;AAAA,EACzC,UAAT,QAAiB,sBAAsB,OAAM,OAAO,CAAC;AAAA;AAEvD,SAAS,cAAc,CAAC,cAAc;AAAA,EACpC,IAAI,OAAO,wBAAwB;AAAA,EACnC,IAAmB,OAAO,iBAAtB,YAAoC;AAAA,IACtC,IAAI,0BAA0B;AAAA,IAC9B,eAAe,wBAAwB;AAAA,IACvC,IAAI,qCAAqC;AAAA,MACvC,2BAA2B,IAAE;AAAA,MAC7B,IAAI;AAAA,QACF,wBAAwB;AAAA,gBACxB;AAAA,QACA,2BAA2B,KAAE;AAAA;AAAA,IAEjC;AAAA,EACF;AAAA,EACA,KAAK,gBAAgB,KAAK,YAAY;AAAA,EACtC,KAAK,QAAQ;AAAA,IACX,SAAS;AAAA,IACT,OAAO;AAAA,IACP,UAAU;AAAA,IACV,qBAAqB;AAAA,IACrB,mBAAmB;AAAA,EACrB;AAAA,EACA,OAAO;AAAA;AAET,SAAS,oBAAoB,CAAC,MAAM,SAAS,aAAa,SAAS;AAAA,EACjE,KAAK,YAAY;AAAA,EACjB,OAAO,kBACL,MACA,aACe,OAAO,YAAtB,aAAgC,UAAU,iBAC5C;AAAA;AAEF,SAAS,mBAAmB,CAC1B,OACA,aACA,iBACA,UACA,SACA;AAAA,EACA,IAAI,oBAAoB,KAAK;AAAA,IAAG,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,EACvE,QAAQ,YAAY;AAAA,EACpB,IAAa,UAAT,MAAgB;AAAA,IAClB,IAAI,aAAa;AAAA,MACf;AAAA,MACA,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,cAAc;AAAA,MACd,QAAQ;AAAA,MACR,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,WAAW,CAAC;AAAA,MACZ,MAAM,QAAS,CAAC,UAAU;AAAA,QACxB,WAAW,UAAU,KAAK,QAAQ;AAAA;AAAA,IAEtC;AAAA,IACS,sBAAqB,MAA9B,OACI,gBAAgB,IAAE,IACjB,WAAW,eAAe;AAAA,IAC/B,SAAS,UAAU;AAAA,IACnB,kBAAkB,YAAY;AAAA,IACrB,oBAAT,QACM,WAAW,OAAO,YAAY,UAAU,YAC1C,qBAAqB,aAAa,UAAU,MAC1C,WAAW,OAAO,gBAAgB,MACnC,YAAY,UAAU,gBAAgB,OAAO;AAAA,EACpD;AAAA;AAEF,SAAS,oBAAoB,CAAC,aAAa,MAAM;AAAA,EAC/C,MAAkB,QACD,YAAL,MACV,YAAY,YAAY;AAAA,EAC1B,IAAI,KAAK,cAAc;AAAA,IACrB,IAAI,iBAAiB,sBAAqB,GACxC,oBAAoB,CAAC;AAAA,IACvB,sBAAqB,IAAI;AAAA,IACzB,IAAI;AAAA,MACF,IAAI,cAAc,OAAO,WAAW,OAAO,GACzC,0BAA0B,sBAAqB;AAAA,MACxC,4BAAT,QACE,wBAAwB,mBAAmB,WAAW;AAAA,MACxD,wBAAwB,aAAa,MAAM,WAAW;AAAA,MACtD,OAAO,OAAO;AAAA,MACd,cAAc,aAAa,MAAM,KAAK;AAAA,cACtC;AAAA,MACS,mBAAT,QACW,kBAAkB,UAA3B,SACC,eAAe,QAAQ,kBAAkB,QACzC,sBAAqB,IAAI;AAAA;AAAA,EAEhC,EACE;AAAA,QAAI;AAAA,MACD,iBAAiB,OAAO,WAAW,OAAO,GACzC,wBAAwB,aAAa,MAAM,cAAc;AAAA,MAC3D,OAAO,UAAU;AAAA,MACjB,cAAc,aAAa,MAAM,QAAQ;AAAA;AAAA;AAG/C,SAAS,uBAAuB,CAAC,aAAa,MAAM,aAAa;AAAA,EACtD,gBAAT,QACa,OAAO,gBAApB,YACe,OAAO,YAAY,SAAlC,aACI,YAAY,KACV,QAAS,CAAC,WAAW;AAAA,IACnB,gBAAgB,aAAa,MAAM,SAAS;AAAA,KAE9C,QAAS,CAAC,OAAO;AAAA,IACf,OAAO,cAAc,aAAa,MAAM,KAAK;AAAA,GAEjD,IACA,gBAAgB,aAAa,MAAM,WAAW;AAAA;AAEpD,SAAS,eAAe,CAAC,aAAa,YAAY,WAAW;AAAA,EAC3D,WAAW,SAAS;AAAA,EACpB,WAAW,QAAQ;AAAA,EACnB,sBAAsB,UAAU;AAAA,EAChC,YAAY,QAAQ;AAAA,EACpB,aAAa,YAAY;AAAA,EAChB,eAAT,SACI,YAAY,WAAW,MACzB,cAAc,aACT,YAAY,UAAU,QACrB,YAAY,UAAU,MACvB,WAAW,OAAO,WACnB,qBAAqB,aAAa,SAAS;AAAA;AAEnD,SAAS,aAAa,CAAC,aAAa,YAAY,OAAO;AAAA,EACrD,IAAI,OAAO,YAAY;AAAA,EACvB,YAAY,UAAU;AAAA,EACtB,IAAa,SAAT,MAAe;AAAA,IACjB,OAAO,KAAK;AAAA,IACZ;AAAA,MACG,WAAW,SAAS,YAClB,WAAW,SAAS,OACrB,sBAAsB,UAAU,GAC/B,aAAa,WAAW;AAAA,WACtB,eAAe;AAAA,EACxB;AAAA,EACA,YAAY,SAAS;AAAA;AAEvB,SAAS,qBAAqB,CAAC,YAAY;AAAA,EACzC,aAAa,WAAW;AAAA,EACxB,SAAS,IAAI,EAAG,IAAI,WAAW,QAAQ;AAAA,KAAM,GAAG,WAAW,IAAI;AAAA;AAEjE,SAAS,kBAAkB,CAAC,UAAU,UAAU;AAAA,EAC9C,OAAO;AAAA;AAET,SAAS,gBAAgB,CAAC,QAAQ,kBAAkB;AAAA,EAClD,IAAI,aAAa;AAAA,IACf,IAAI,eAAe,mBAAmB;AAAA,IACtC,IAAa,iBAAT,MAAuB;AAAA,MACzB,GAAG;AAAA,QACD,IAAI,2BAA2B;AAAA,QAC/B,IAAI,aAAa;AAAA,UACf,IAAI,wBAAwB;AAAA,YAC1B,GAAG;AAAA,cACD,IAAI,oCAAoC;AAAA,cACxC,SACM,oBAAoB,uBAClB,kCAAkC,aAAxC,KAEA;AAAA,gBACA,IAAI,CAAC,mBAAmB;AAAA,kBACtB,oCAAoC;AAAA,kBACpC;AAAA,gBACF;AAAA,gBACA,oCAAoC,kBAClC,kCAAkC,WACpC;AAAA,gBACA,IAAa,sCAAT,MAA4C;AAAA,kBAC9C,oCAAoC;AAAA,kBACpC;AAAA,gBACF;AAAA,cACF;AAAA,cACA,oBAAoB,kCAAkC;AAAA,cACtD,oCACW,sBAAT,QAAsC,sBAAR,MAC1B,oCACA;AAAA,YACR;AAAA,YACA,IAAI,mCAAmC;AAAA,cACrC,yBAAyB,kBACvB,kCAAkC,WACpC;AAAA,cACA,2BACW,kCAAkC,SAA3C;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,UACA,yBAAyB,wBAAwB;AAAA,QACnD;AAAA,QACA,2BAA2B;AAAA,MAC7B;AAAA,MACA,6BAA6B,mBAAmB,aAAa;AAAA,IAC/D;AAAA,EACF;AAAA,EACA,eAAe,wBAAwB;AAAA,EACvC,aAAa,gBAAgB,aAAa,YAAY;AAAA,EACtD,2BAA2B;AAAA,IACzB,SAAS;AAAA,IACT,OAAO;AAAA,IACP,UAAU;AAAA,IACV,qBAAqB;AAAA,IACrB,mBAAmB;AAAA,EACrB;AAAA,EACA,aAAa,QAAQ;AAAA,EACrB,eAAe,iBAAiB,KAC9B,MACA,yBACA,wBACF;AAAA,EACA,yBAAyB,WAAW;AAAA,EACpC,2BAA2B,eAAe,KAAE;AAAA,EAC5C,oBAAoB,2BAA2B,KAC7C,MACA,yBACA,OACA,yBAAyB,KAC3B;AAAA,EACA,2BAA2B,wBAAwB;AAAA,EACnD,oCAAoC;AAAA,IAClC,OAAO;AAAA,IACP,UAAU;AAAA,IACV;AAAA,IACA,SAAS;AAAA,EACX;AAAA,EACA,yBAAyB,QAAQ;AAAA,EACjC,eAAe,oBAAoB,KACjC,MACA,yBACA,mCACA,mBACA,YACF;AAAA,EACA,kCAAkC,WAAW;AAAA,EAC7C,yBAAyB,gBAAgB;AAAA,EACzC,OAAO,CAAC,kBAAkB,cAAc,KAAE;AAAA;AAE5C,SAAS,iBAAiB,CAAC,QAAQ;AAAA,EACjC,IAAI,YAAY,yBAAyB;AAAA,EACzC,OAAO,sBAAsB,WAAW,aAAa,MAAM;AAAA;AAE7D,SAAS,qBAAqB,CAAC,WAAW,kBAAkB,QAAQ;AAAA,EAClE,mBAAmB,kBACjB,WACA,kBACA,kBACF,EAAE;AAAA,EACF,YAAY,cAAc,iBAAiB,EAAE;AAAA,EAC7C,IACe,OAAO,qBAApB,YACS,qBAAT,QACe,OAAO,iBAAiB,SAAvC;AAAA,IAEA,IAAI;AAAA,MACF,IAAI,QAAQ,YAAY,gBAAgB;AAAA,MACxC,OAAO,GAAG;AAAA,MACV,IAAI,MAAM;AAAA,QAAmB,MAAM;AAAA,MACnC,MAAM;AAAA;AAAA,EAEL;AAAA,YAAQ;AAAA,EACb,mBAAmB,yBAAyB;AAAA,EAC5C,IAAI,cAAc,iBAAiB,OACjC,WAAW,YAAY;AAAA,EACzB,WAAW,iBAAiB,kBACxB,wBAAwB,SAAS,MACnC,iBACE,GACA,EAAE,SAAc,UAAE,GAClB,wBAAwB,KAAK,MAAM,aAAa,MAAM,GACtD,IACF;AAAA,EACF,OAAO,CAAC,OAAO,UAAU,SAAS;AAAA;AAEpC,SAAS,uBAAuB,CAAC,aAAa,QAAQ;AAAA,EACpD,YAAY,SAAS;AAAA;AAEvB,SAAS,mBAAmB,CAAC,QAAQ;AAAA,EACnC,IAAI,YAAY,yBAAyB,GACvC,mBAAmB;AAAA,EACrB,IAAa,qBAAT;AAAA,IACF,OAAO,sBAAsB,WAAW,kBAAkB,MAAM;AAAA,EAClE,yBAAyB;AAAA,EACzB,YAAY,UAAU;AAAA,EACtB,mBAAmB,yBAAyB;AAAA,EAC5C,IAAI,WAAW,iBAAiB,MAAM;AAAA,EACtC,iBAAiB,gBAAgB;AAAA,EACjC,OAAO,CAAC,WAAW,UAAU,KAAE;AAAA;AAEjC,SAAS,gBAAgB,CAAC,KAAK,MAAM,QAAQ,MAAM;AAAA,EACjD,MAAM,EAAE,KAAU,QAAgB,MAAY,MAAY,MAAM,KAAK;AAAA,EACrE,OAAO,wBAAwB;AAAA,EACtB,SAAT,SACI,OAAO,mCAAmC,GAC3C,wBAAwB,cAAc;AAAA,EACzC,SAAS,KAAK;AAAA,EACL,WAAT,OACK,KAAK,aAAa,IAAI,OAAO,OAC5B,OAAO,OAAO,MACf,OAAO,OAAO,KACd,IAAI,OAAO,MACX,KAAK,aAAa;AAAA,EACvB,OAAO;AAAA;AAET,SAAS,SAAS,GAAG;AAAA,EACnB,OAAO,yBAAyB,EAAE;AAAA;AAEpC,SAAS,eAAe,CAAC,YAAY,WAAW,QAAQ,MAAM;AAAA,EAC5D,IAAI,OAAO,wBAAwB;AAAA,EACnC,wBAAwB,SAAS;AAAA,EACjC,KAAK,gBAAgB,iBACnB,IAAI,WACJ,EAAE,SAAc,UAAE,GAClB,QACW,SAAN,YAAa,OAAO,IAC3B;AAAA;AAEF,SAAS,gBAAgB,CAAC,YAAY,WAAW,QAAQ,MAAM;AAAA,EAC7D,IAAI,OAAO,yBAAyB;AAAA,EACpC,OAAkB,SAAN,YAAa,OAAO;AAAA,EAChC,IAAI,OAAO,KAAK,cAAc;AAAA,EACrB,gBAAT,QACS,SAAT,QACA,mBAAmB,MAAM,YAAY,cAAc,IAAI,IAClD,KAAK,gBAAgB,iBAAiB,WAAW,MAAM,QAAQ,IAAI,KAClE,wBAAwB,SAAS,YAClC,KAAK,gBAAgB,iBACpB,IAAI,WACJ,MACA,QACA,IACF;AAAA;AAEN,SAAS,WAAW,CAAC,QAAQ,MAAM;AAAA,EACjC,gBAAgB,SAAS,GAAG,QAAQ,IAAI;AAAA;AAE1C,SAAS,YAAY,CAAC,QAAQ,MAAM;AAAA,EAClC,iBAAiB,MAAM,GAAG,QAAQ,IAAI;AAAA;AAExC,SAAS,kBAAkB,CAAC,SAAS;AAAA,EACnC,wBAAwB,SAAS;AAAA,EACjC,IAAI,uBAAuB,wBAAwB;AAAA,EACnD,IAAa,yBAAT;AAAA,IACD,uBAAuB,mCAAmC,GACxD,wBAAwB,cAAc,sBACtC,qBAAqB,SAAS,CAAC,OAAO;AAAA,EACtC;AAAA,IACH,IAAI,SAAS,qBAAqB;AAAA,IACzB,WAAT,OACK,qBAAqB,SAAS,CAAC,OAAO,IACvC,OAAO,KAAK,OAAO;AAAA;AAAA;AAG3B,SAAS,WAAW,CAAC,UAAU;AAAA,EAC7B,IAAI,MAAM,yBAAyB,EAAE;AAAA,EACrC,mBAAmB,EAAE,KAAU,UAAU,SAAS,CAAC;AAAA,EACnD,OAAO,QAAS,GAAG;AAAA,IACjB,KAAW,mBAAmB,OAA1B;AAAA,MAA8B,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,IACzE,OAAO,IAAI,KAAK,MAAW,WAAG,SAAS;AAAA;AAAA;AAG3C,SAAS,qBAAqB,CAAC,QAAQ,MAAM;AAAA,EAC3C,OAAO,iBAAiB,GAAG,GAAG,QAAQ,IAAI;AAAA;AAE5C,SAAS,kBAAkB,CAAC,QAAQ,MAAM;AAAA,EACxC,OAAO,iBAAiB,GAAG,GAAG,QAAQ,IAAI;AAAA;AAE5C,SAAS,sBAAsB,CAAC,QAAQ,KAAK;AAAA,EAC3C,IAAmB,OAAO,QAAtB,YAA2B;AAAA,IAC7B,SAAS,OAAO;AAAA,IAChB,IAAI,aAAa,IAAI,MAAM;AAAA,IAC3B,OAAO,QAAS,GAAG;AAAA,MACF,OAAO,eAAtB,aAAmC,WAAW,IAAI,IAAI,IAAI;AAAA;AAAA,EAE9D;AAAA,EACA,IAAa,QAAT,QAA2B,QAAN;AAAA,IACvB,OACG,SAAS,OAAO,GAChB,IAAI,UAAU,QACf,QAAS,GAAG;AAAA,MACV,IAAI,UAAU;AAAA;AAAA;AAItB,SAAS,sBAAsB,CAAC,KAAK,QAAQ,MAAM;AAAA,EACjD,OAAgB,SAAT,QAA4B,SAAN,YAAa,KAAK,OAAO,CAAC,GAAG,CAAC,IAAI;AAAA,EAC/D,iBAAiB,GAAG,GAAG,uBAAuB,KAAK,MAAM,QAAQ,GAAG,GAAG,IAAI;AAAA;AAE7E,SAAS,eAAe,GAAG;AAC3B,SAAS,cAAc,CAAC,UAAU,MAAM;AAAA,EACtC,IAAI,OAAO,yBAAyB;AAAA,EACpC,OAAkB,SAAN,YAAa,OAAO;AAAA,EAChC,IAAI,YAAY,KAAK;AAAA,EACrB,IAAa,SAAT,QAAiB,mBAAmB,MAAM,UAAU,EAAE;AAAA,IACxD,OAAO,UAAU;AAAA,EACnB,KAAK,gBAAgB,CAAC,UAAU,IAAI;AAAA,EACpC,OAAO;AAAA;AAET,SAAS,UAAU,CAAC,YAAY,MAAM;AAAA,EACpC,IAAI,OAAO,yBAAyB;AAAA,EACpC,OAAkB,SAAN,YAAa,OAAO;AAAA,EAChC,IAAI,YAAY,KAAK;AAAA,EACrB,IAAa,SAAT,QAAiB,mBAAmB,MAAM,UAAU,EAAE;AAAA,IACxD,OAAO,UAAU;AAAA,EACnB,YAAY,WAAW;AAAA,EACvB,IAAI,qCAAqC;AAAA,IACvC,2BAA2B,IAAE;AAAA,IAC7B,IAAI;AAAA,MACF,WAAW;AAAA,cACX;AAAA,MACA,2BAA2B,KAAE;AAAA;AAAA,EAEjC;AAAA,EACA,KAAK,gBAAgB,CAAC,WAAW,IAAI;AAAA,EACrC,OAAO;AAAA;AAET,SAAS,sBAAsB,CAAC,MAAM,OAAO,cAAc;AAAA,EACzD,IACa,iBAAN,cACG,cAAc,gBAArB,MACQ,gCAAgC,YAAvC;AAAA,IAEF,OAAQ,KAAK,gBAAgB;AAAA,EAC/B,KAAK,gBAAgB;AAAA,EACrB,OAAO,oBAAoB;AAAA,EAC3B,wBAAwB,SAAS;AAAA,EACjC,kCAAkC;AAAA,EAClC,OAAO;AAAA;AAET,SAAS,uBAAuB,CAAC,MAAM,WAAW,OAAO,cAAc;AAAA,EACrE,IAAI,SAAS,OAAO,SAAS;AAAA,IAAG,OAAO;AAAA,EACvC,IAAa,6BAA6B,YAAtC;AAAA,IACF,OACG,OAAO,uBAAuB,MAAM,OAAO,YAAY,GACxD,SAAS,MAAM,SAAS,MAAM,mBAAmB,OACjD;AAAA,EAEJ,KACS,cAAc,QAArB,MACQ,cAAc,gBAArB,MACQ,gCAAgC,YAAvC;AAAA,IAEF,OAAQ,mBAAmB,MAAM,KAAK,gBAAgB;AAAA,EACxD,OAAO,oBAAoB;AAAA,EAC3B,wBAAwB,SAAS;AAAA,EACjC,kCAAkC;AAAA,EAClC,OAAO;AAAA;AAET,SAAS,eAAe,CAAC,OAAO,OAAO,cAAc,eAAe,UAAU;AAAA,EAC5E,IAAI,mBAAmB,wBAAwB;AAAA,EAC/C,wBAAwB,IAChB,qBAAN,KAA0B,IAAI,mBAAmB,mBAAmB;AAAA,EACtE,IAAI,iBAAiB,sBAAqB,GACxC,oBAAoB,CAAC;AAAA,EACvB,sBAAqB,IAAI;AAAA,EACzB,2BAA2B,OAAO,OAAI,OAAO,YAAY;AAAA,EACzD,IAAI;AAAA,IACF,IAAI,cAAc,SAAS,GACzB,0BAA0B,sBAAqB;AAAA,IACxC,4BAAT,QACE,wBAAwB,mBAAmB,WAAW;AAAA,IACxD,IACW,gBAAT,QACa,OAAO,gBAApB,YACe,OAAO,YAAY,SAAlC,YACA;AAAA,MACA,IAAI,2BAA2B,mBAC7B,aACA,aACF;AAAA,MACA,yBACE,OACA,OACA,0BACA,kBAAkB,KAAK,CACzB;AAAA,IACF,EACE;AAAA,+BACE,OACA,OACA,eACA,kBAAkB,KAAK,CACzB;AAAA,IACF,OAAO,OAAO;AAAA,IACd,yBACE,OACA,OACA,EAAE,MAAM,QAAS,GAAG,IAAI,QAAQ,YAAY,QAAQ,MAAM,GAC1D,kBAAkB,CACpB;AAAA,YACA;AAAA,IACC,wBAAwB,IAAI,kBAClB,mBAAT,QACW,kBAAkB,UAA3B,SACC,eAAe,QAAQ,kBAAkB,QAC3C,sBAAqB,IAAI;AAAA;AAAA;AAGhC,SAAS,KAAI,GAAG;AAChB,SAAS,mBAAmB,CAAC,WAAW,cAAc,QAAQ,UAAU;AAAA,EACtE,IAAU,UAAU,QAAhB;AAAA,IAAqB,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,EAChE,IAAI,QAAQ,8BAA8B,SAAS,EAAE;AAAA,EACrD,gBACE,WACA,OACA,cACA,wBACS,WAAT,OACI,QACA,QAAS,GAAG;AAAA,IACV,mBAAmB,SAAS;AAAA,IAC5B,OAAO,OAAO,QAAQ;AAAA,GAE9B;AAAA;AAEF,SAAS,6BAA6B,CAAC,WAAW;AAAA,EAChD,IAAI,oBAAoB,UAAU;AAAA,EAClC,IAAa,sBAAT;AAAA,IAA4B,OAAO;AAAA,EACvC,oBAAoB;AAAA,IAClB,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,IACX,OAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO;AAAA,MACP,UAAU;AAAA,MACV,qBAAqB;AAAA,MACrB,mBAAmB;AAAA,IACrB;AAAA,IACA,MAAM;AAAA,EACR;AAAA,EACA,IAAI,oBAAoB,CAAC;AAAA,EACzB,kBAAkB,OAAO;AAAA,IACvB,eAAe;AAAA,IACf,WAAW;AAAA,IACX,WAAW;AAAA,IACX,OAAO;AAAA,MACL,SAAS;AAAA,MACT,OAAO;AAAA,MACP,UAAU;AAAA,MACV,qBAAqB;AAAA,MACrB,mBAAmB;AAAA,IACrB;AAAA,IACA,MAAM;AAAA,EACR;AAAA,EACA,UAAU,gBAAgB;AAAA,EAC1B,YAAY,UAAU;AAAA,EACb,cAAT,SAAuB,UAAU,gBAAgB;AAAA,EACjD,OAAO;AAAA;AAET,SAAS,kBAAkB,CAAC,WAAW;AAAA,EACrC,IAAI,YAAY,8BAA8B,SAAS;AAAA,EAC9C,UAAU,SAAnB,SAA4B,YAAY,UAAU,UAAU;AAAA,EAC5D,yBACE,WACA,UAAU,KAAK,OACf,CAAC,GACD,kBAAkB,CACpB;AAAA;AAEF,SAAS,uBAAuB,GAAG;AAAA,EACjC,OAAO,YAAY,qBAAqB;AAAA;AAE1C,SAAS,QAAQ,GAAG;AAAA,EAClB,OAAO,yBAAyB,EAAE;AAAA;AAEpC,SAAS,aAAa,GAAG;AAAA,EACvB,OAAO,yBAAyB,EAAE;AAAA;AAEpC,SAAS,YAAY,CAAC,OAAO;AAAA,EAC3B,SAAS,WAAW,MAAM,OAAiB,aAAT,QAAqB;AAAA,IACrD,QAAQ,SAAS;AAAA,WACV;AAAA,WACA;AAAA,QACH,IAAI,OAAO,kBAAkB;AAAA,QAC7B,QAAQ,aAAa,IAAI;AAAA,QACzB,IAAI,UAAU,cAAc,UAAU,OAAO,IAAI;AAAA,QACxC,YAAT,SACG,sBAAsB,SAAS,UAAU,IAAI,GAC9C,oBAAoB,SAAS,UAAU,IAAI;AAAA,QAC7C,WAAW,EAAE,OAAO,YAAY,EAAE;AAAA,QAClC,MAAM,UAAU;AAAA,QAChB;AAAA;AAAA,IAEJ,WAAW,SAAS;AAAA,EACtB;AAAA;AAEF,SAAS,qBAAqB,CAAC,OAAO,OAAO,QAAQ;AAAA,EACnD,IAAI,OAAO,kBAAkB;AAAA,EAC7B,SAAS;AAAA,IACP;AAAA,IACA,YAAY;AAAA,IACZ,SAAS;AAAA,IACT;AAAA,IACA,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,MAAM;AAAA,EACR;AAAA,EACA,oBAAoB,KAAK,IACrB,yBAAyB,OAAO,MAAM,KACpC,SAAS,4BAA4B,OAAO,OAAO,QAAQ,IAAI,GACxD,WAAT,SACG,sBAAsB,QAAQ,OAAO,IAAI,GAC1C,yBAAyB,QAAQ,OAAO,IAAI;AAAA;AAEpD,SAAS,gBAAgB,CAAC,OAAO,OAAO,QAAQ;AAAA,EAC9C,IAAI,OAAO,kBAAkB;AAAA,EAC7B,yBAAyB,OAAO,OAAO,QAAQ,IAAI;AAAA;AAErD,SAAS,wBAAwB,CAAC,OAAO,OAAO,QAAQ,MAAM;AAAA,EAC5D,IAAI,SAAS;AAAA,IACX;AAAA,IACA,YAAY;AAAA,IACZ,SAAS;AAAA,IACT;AAAA,IACA,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,MAAM;AAAA,EACR;AAAA,EACA,IAAI,oBAAoB,KAAK;AAAA,IAAG,yBAAyB,OAAO,MAAM;AAAA,EACjE;AAAA,IACH,IAAI,YAAY,MAAM;AAAA,IACtB,IACQ,MAAM,UAAZ,MACU,cAAT,QAA4B,UAAU,UAAhB,OACrB,YAAY,MAAM,qBAA+B,cAAT;AAAA,MAE1C,IAAI;AAAA,QACF,IAAI,eAAe,MAAM,mBACvB,aAAa,UAAU,cAAc,MAAM;AAAA,QAC7C,OAAO,gBAAgB;AAAA,QACvB,OAAO,aAAa;AAAA,QACpB,IAAI,SAAS,YAAY,YAAY;AAAA,UACnC,OACE,gBAAgB,OAAO,OAAO,QAAQ,CAAC,GAC9B,uBAAT,QAA+B,gCAAgC,GAC/D;AAAA,QAEJ,OAAO,OAAO,WACd;AAAA,IAEJ,SAAS,4BAA4B,OAAO,OAAO,QAAQ,IAAI;AAAA,IAC/D,IAAa,WAAT;AAAA,MACF,OACE,sBAAsB,QAAQ,OAAO,IAAI,GACzC,yBAAyB,QAAQ,OAAO,IAAI,GAC5C;AAAA;AAAA,EAGN,OAAO;AAAA;AAET,SAAS,0BAA0B,CAAC,OAAO,qBAAqB,OAAO,QAAQ;AAAA,EAC7E,SAAS;AAAA,IACP,MAAM;AAAA,IACN,YAAY,sBAAsB;AAAA,IAClC,SAAS;AAAA,IACT;AAAA,IACA,eAAe;AAAA,IACf,YAAY;AAAA,IACZ,MAAM;AAAA,EACR;AAAA,EACA,IAAI,oBAAoB,KAAK,GAAG;AAAA,IAC9B,IAAI;AAAA,MAAqB,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,EAClE,EACE;AAAA,IAAC,sBAAsB,4BACrB,OACA,OACA,QACA,CACF,GACW,wBAAT,QACE,sBAAsB,qBAAqB,OAAO,CAAC;AAAA;AAE3D,SAAS,mBAAmB,CAAC,OAAO;AAAA,EAClC,IAAI,YAAY,MAAM;AAAA,EACtB,OACE,UAAU,2BACA,cAAT,QAAsB,cAAc;AAAA;AAGzC,SAAS,wBAAwB,CAAC,OAAO,QAAQ;AAAA,EAC/C,6CAA6C,+BAC3C;AAAA,EACF,IAAI,UAAU,MAAM;AAAA,EACX,YAAT,OACK,OAAO,OAAO,UACb,OAAO,OAAO,QAAQ,MAAQ,QAAQ,OAAO;AAAA,EACnD,MAAM,UAAU;AAAA;AAElB,SAAS,wBAAwB,CAAC,OAAM,OAAO,MAAM;AAAA,EACnD,KAAW,OAAO,aAAd,GAAwB;AAAA,IAC1B,IAAI,aAAa,MAAM;AAAA,IACvB,cAAc,MAAK;AAAA,IACnB,QAAQ;AAAA,IACR,MAAM,QAAQ;AAAA,IACd,kBAAkB,OAAM,IAAI;AAAA,EAC9B;AAAA;AA2UF,SAAS,0BAA0B,CACjC,gBACA,MACA,0BACA,WACA;AAAA,EACA,OAAO,eAAe;AAAA,EACtB,2BAA2B,yBAAyB,WAAW,IAAI;AAAA,EACnE,2BACW,6BAAT,QAAgD,6BAAN,YACtC,OACA,QAAO,CAAC,GAAG,MAAM,wBAAwB;AAAA,EAC/C,eAAe,gBAAgB;AAAA,EACzB,eAAe,UAArB,MACG,eAAe,YAAY,YAAY;AAAA;AAsC5C,SAAS,0BAA0B,CACjC,gBACA,MACA,UACA,UACA,UACA,UACA,aACA;AAAA,EACA,iBAAiB,eAAe;AAAA,EAChC,OAAsB,OAAO,eAAe,0BAArC,aACH,eAAe,sBAAsB,UAAU,UAAU,WAAW,IACpE,KAAK,aAAa,KAAK,UAAU,uBAC/B,CAAC,aAAa,UAAU,QAAQ,KAAK,CAAC,aAAa,UAAU,QAAQ,IACrE;AAAA;AAER,SAAS,6BAA6B,CACpC,gBACA,UACA,UACA,aACA;AAAA,EACA,iBAAiB,SAAS;AAAA,EACX,OAAO,SAAS,8BAA/B,cACE,SAAS,0BAA0B,UAAU,WAAW;AAAA,EAC3C,OAAO,SAAS,qCAA/B,cACE,SAAS,iCAAiC,UAAU,WAAW;AAAA,EACjE,SAAS,UAAU,kBACjB,sBAAsB,oBAAoB,UAAU,SAAS,OAAO,IAAI;AAAA;AAE5E,SAAS,0BAA0B,CAAC,YAAW,WAAW;AAAA,EACxD,IAAI,WAAW;AAAA,EACf,IAAI,SAAS,WAAW;AAAA,IACtB,WAAW,CAAC;AAAA,IACZ,SAAS,YAAY;AAAA,MACT,aAAV,UAAuB,SAAS,YAAY,UAAU;AAAA,EAC1D;AAAA,EACA,IAAK,aAAY,WAAU,cAAe;AAAA,IACxC,aAAa,cAAc,WAAW,QAAO,CAAC,GAAG,QAAQ;AAAA,IACzD,SAAS,eAAe;AAAA,MACX,SAAS,iBAAf,cACF,SAAS,eAAe,WAAU;AAAA,EACzC;AAAA,EACA,OAAO;AAAA;AAET,SAAS,sBAAsB,CAAC,OAAO;AAAA,EACrC,mBAAkB,KAAK;AAAA;AAEzB,SAAS,oBAAoB,CAAC,OAAO;AAAA,EACnC,QAAQ,MAAM,KAAK;AAAA;AAErB,SAAS,yBAAyB,CAAC,OAAO;AAAA,EACxC,mBAAkB,KAAK;AAAA;AAEzB,SAAS,gBAAgB,CAAC,OAAM,WAAW;AAAA,EACzC,IAAI;AAAA,IACF,IAAI,kBAAkB,MAAK;AAAA,IAC3B,gBAAgB,UAAU,OAAO,EAAE,gBAAgB,UAAU,MAAM,CAAC;AAAA,IACpE,OAAO,MAAM;AAAA,IACb,WAAW,QAAS,GAAG;AAAA,MACrB,MAAM;AAAA,KACP;AAAA;AAAA;AAGL,SAAS,cAAc,CAAC,OAAM,UAAU,WAAW;AAAA,EACjD,IAAI;AAAA,IACF,IAAI,gBAAgB,MAAK;AAAA,IACzB,cAAc,UAAU,OAAO;AAAA,MAC7B,gBAAgB,UAAU;AAAA,MAC1B,eAAqB,SAAS,QAAf,IAAqB,SAAS,YAAY;AAAA,IAC3D,CAAC;AAAA,IACD,OAAO,MAAM;AAAA,IACb,WAAW,QAAS,GAAG;AAAA,MACrB,MAAM;AAAA,KACP;AAAA;AAAA;AAGL,SAAS,qBAAqB,CAAC,OAAM,WAAW,MAAM;AAAA,EACpD,OAAO,aAAa,IAAI;AAAA,EACxB,KAAK,MAAM;AAAA,EACX,KAAK,UAAU,EAAE,SAAS,KAAK;AAAA,EAC/B,KAAK,WAAW,QAAS,GAAG;AAAA,IAC1B,iBAAiB,OAAM,SAAS;AAAA;AAAA,EAElC,OAAO;AAAA;AAET,SAAS,sBAAsB,CAAC,MAAM;AAAA,EACpC,OAAO,aAAa,IAAI;AAAA,EACxB,KAAK,MAAM;AAAA,EACX,OAAO;AAAA;AAET,SAAS,0BAA0B,CAAC,QAAQ,OAAM,OAAO,WAAW;AAAA,EAClE,IAAI,2BAA2B,MAAM,KAAK;AAAA,EAC1C,IAAmB,OAAO,6BAAtB,YAAgD;AAAA,IAClD,IAAI,QAAQ,UAAU;AAAA,IACtB,OAAO,UAAU,QAAS,GAAG;AAAA,MAC3B,OAAO,yBAAyB,KAAK;AAAA;AAAA,IAEvC,OAAO,WAAW,QAAS,GAAG;AAAA,MAC5B,eAAe,OAAM,OAAO,SAAS;AAAA;AAAA,EAEzC;AAAA,EACA,IAAI,OAAO,MAAM;AAAA,EACR,SAAT,QACiB,OAAO,KAAK,sBAA3B,eACC,OAAO,WAAW,QAAS,GAAG;AAAA,IAC7B,eAAe,OAAM,OAAO,SAAS;AAAA,IACtB,OAAO,6BAAtB,eACY,2CAAT,OACI,yCAAyC,IAAI,IAAI,CAAC,IAAI,CAAC,IACxD,uCAAuC,IAAI,IAAI;AAAA,IACrD,IAAI,QAAQ,UAAU;AAAA,IACtB,KAAK,kBAAkB,UAAU,OAAO;AAAA,MACtC,gBAAyB,UAAT,OAAiB,QAAQ;AAAA,IAC3C,CAAC;AAAA;AAAA;AAGP,SAAS,cAAc,CACrB,OACA,aACA,aACA,OACA,iBACA;AAAA,EACA,YAAY,SAAS;AAAA,EACrB,IACW,UAAT,QACa,OAAO,UAApB,YACe,OAAO,MAAM,SAA5B,YACA;AAAA,IACA,cAAc,YAAY;AAAA,IACjB,gBAAT,QACE,8BACE,aACA,aACA,iBACA,IACF;AAAA,IACF,cAAc,2BAA2B;AAAA,IACzC,IAAa,gBAAT,MAAsB;AAAA,MACxB,QAAQ,YAAY;AAAA,aACb;AAAA,aACA;AAAA,UACH,OACW,kBAAT,OACI,gCAAgC,IACvB,YAAY,cAArB,QACM,iCAAN,MACC,+BAA+B,IACnC,YAAY,SAAS,MACrB,YAAY,SAAS,OACrB,YAAY,QAAQ,iBACrB,UAAU,8BACL,YAAY,SAAS,SACpB,cAAc,YAAY,aACnB,gBAAT,OACK,YAAY,cAAc,IAAI,IAAI,CAAC,KAAK,CAAC,IAC1C,YAAY,IAAI,KAAK,GACzB,mBAAmB,OAAM,OAAO,eAAe,IACnD;AAAA,aAEC;AAAA,UACH,OACG,YAAY,SAAS,OACtB,UAAU,8BACL,YAAY,SAAS,SACpB,cAAc,YAAY,aACnB,gBAAT,QACM,cAAc;AAAA,YACd,aAAa;AAAA,YACb,iBAAiB;AAAA,YACjB,YAAY,IAAI,IAAI,CAAC,KAAK,CAAC;AAAA,UAC7B,GACC,YAAY,cAAc,gBACzB,cAAc,YAAY,YACnB,gBAAT,OACK,YAAY,aAAa,IAAI,IAAI,CAAC,KAAK,CAAC,IACzC,YAAY,IAAI,KAAK,IAC7B,mBAAmB,OAAM,OAAO,eAAe,IACnD;AAAA;AAAA,MAGN,MAAM,MAAM,wBAAuB,KAAK,YAAY,GAAG,CAAC;AAAA,IAC1D;AAAA,IACA,mBAAmB,OAAM,OAAO,eAAe;AAAA,IAC/C,gCAAgC;AAAA,IAChC,OAAO;AAAA,EACT;AAAA,EACA,IAAI;AAAA,IACF,OACG,cAAc,2BAA2B,SACjC,gBAAT,SACY,YAAY,QAAQ,WAA3B,MAAsC,YAAY,SAAS,MAC3D,YAAY,SAAS,OACrB,YAAY,QAAQ,iBACrB,UAAU,+BACN,QAAO,MAAM,wBAAuB,GAAG,GAAG,EAAE,OAAO,MAAM,CAAC,GAC5D,oBAAoB,2BAA2B,OAAM,WAAW,CAAC,OAClE,UAAU,+BACP,cAAc,MAAM,wBAAuB,GAAG,GAAG;AAAA,MACjD,OAAO;AAAA,IACT,CAAC,GACD,oBACE,2BAA2B,aAAa,WAAW,CACrD,IACD,QAAO,MAAK,QAAQ,WACpB,MAAK,SAAS,OACd,mBAAmB,CAAC,iBACpB,MAAK,SAAS,iBACd,QAAQ,2BAA2B,OAAO,WAAW,GACrD,kBAAkB,sBACjB,MAAK,WACL,OACA,eACF,GACA,sBAAsB,OAAM,eAAe,GACrC,iCAAN,MACG,+BAA+B,KACtC;AAAA,EAEJ,IAAI,eAAe,MAAM,wBAAuB,GAAG,GAAG,EAAE,OAAO,MAAM,CAAC;AAAA,EACtE,eAAe,2BAA2B,cAAc,WAAW;AAAA,EAC1D,uCAAT,OACK,qCAAqC,CAAC,YAAY,IACnD,mCAAmC,KAAK,YAAY;AAAA,EAClD,iCAAN,MAAuC,+BAA+B;AAAA,EACtE,IAAa,gBAAT;AAAA,IAAsB,OAAO;AAAA,EACjC,QAAQ,2BAA2B,OAAO,WAAW;AAAA,EACrD,cAAc;AAAA,EACd,GAAG;AAAA,IACD,QAAQ,YAAY;AAAA,WACb;AAAA,QACH,OACG,YAAY,SAAS,OACrB,QAAO,kBAAkB,CAAC,iBAC1B,YAAY,SAAS,OACrB,QAAO,sBAAsB,YAAY,WAAW,OAAO,KAAI,GAChE,sBAAsB,aAAa,KAAI,GACvC;AAAA,WAEC;AAAA,QACH,IACI,cAAc,YAAY,MAC3B,eAAe,YAAY,YACrB,YAAY,QAAQ,SAA3B,MACkB,OAAO,YAAY,6BAAlC,cACW,iBAAT,QACgB,OAAO,aAAa,sBAAnC,eACU,2CAAT,QACC,CAAC,uCAAuC,IAAI,YAAY;AAAA,UAEhE,OACG,YAAY,SAAS,OACrB,mBAAmB,CAAC,iBACpB,YAAY,SAAS,iBACrB,kBAAkB,uBAAuB,eAAe,GACzD,2BACE,iBACA,OACA,aACA,KACF,GACA,sBAAsB,aAAa,eAAe,GAClD;AAAA;AAAA,IAGR,cAAc,YAAY;AAAA,EAC5B,SAAkB,gBAAT;AAAA,EACT,OAAO;AAAA;AAIT,SAAS,iBAAiB,CAAC,SAAS,gBAAgB,cAAc,cAAa;AAAA,EAC7E,eAAe,QACJ,YAAT,OACI,iBAAiB,gBAAgB,MAAM,cAAc,YAAW,IAChE,qBACE,gBACA,QAAQ,OACR,cACA,YACF;AAAA;AAER,SAAS,gBAAgB,CACvB,SACA,gBACA,YACA,WACA,cACA;AAAA,EACA,aAAY,WAAU;AAAA,EACtB,IAAI,MAAM,eAAe;AAAA,EACzB,IAAI,SAAS,WAAW;AAAA,IACtB,IAAI,kBAAkB,CAAC;AAAA,IACvB,SAAS,OAAO;AAAA,MACJ,QAAV,UAAkB,gBAAgB,OAAO,UAAU;AAAA,EACvD,EAAO;AAAA,sBAAkB;AAAA,EACzB,qBAAqB,cAAc;AAAA,EACnC,YAAY,gBACV,SACA,gBACA,YACA,iBACA,KACA,YACF;AAAA,EACA,MAAM,qBAAqB;AAAA,EAC3B,IAAa,YAAT,QAAoB,CAAC;AAAA,IACvB,OACE,aAAa,SAAS,gBAAgB,YAAW,GACjD,6BAA6B,SAAS,gBAAgB,YAAW;AAAA,EAErE,eAAe,OAAO,uBAAuB,cAAc;AAAA,EAC3D,eAAe,SAAS;AAAA,EACxB,kBAAkB,SAAS,gBAAgB,WAAW,YAAW;AAAA,EACjE,OAAO,eAAe;AAAA;AAExB,SAAS,mBAAmB,CAC1B,SACA,gBACA,YACA,WACA,cACA;AAAA,EACA,IAAa,YAAT,MAAkB;AAAA,IACpB,IAAI,OAAO,WAAU;AAAA,IACrB,IACiB,OAAO,SAAtB,cACA,CAAC,gBAAgB,IAAI,KACV,KAAK,iBAAX,aACI,WAAU,YAAnB;AAAA,MAEA,OACG,eAAe,MAAM,IACrB,eAAe,OAAO,MACvB,0BACE,SACA,gBACA,MACA,WACA,YACF;AAAA,IAEJ,UAAU,4BACR,WAAU,MACV,MACA,WACA,gBACA,eAAe,MACf,YACF;AAAA,IACA,QAAQ,MAAM,eAAe;AAAA,IAC7B,QAAQ,SAAS;AAAA,IACjB,OAAQ,eAAe,QAAQ;AAAA,EACjC;AAAA,EACA,OAAO,QAAQ;AAAA,EACf,IAAI,CAAC,8BAA8B,SAAS,YAAW,GAAG;AAAA,IACxD,IAAI,YAAY,KAAK;AAAA,IACrB,aAAY,WAAU;AAAA,IACtB,aAAqB,eAAT,OAAqB,aAAY;AAAA,IAC7C,IAAI,WAAU,WAAW,SAAS,KAAK,QAAQ,QAAQ,eAAe;AAAA,MACpE,OAAO,6BAA6B,SAAS,gBAAgB,YAAW;AAAA,EAC5E;AAAA,EACA,eAAe,SAAS;AAAA,EACxB,UAAU,qBAAqB,MAAM,SAAS;AAAA,EAC9C,QAAQ,MAAM,eAAe;AAAA,EAC7B,QAAQ,SAAS;AAAA,EACjB,OAAQ,eAAe,QAAQ;AAAA;AAEjC,SAAS,yBAAyB,CAChC,SACA,gBACA,YACA,WACA,cACA;AAAA,EACA,IAAa,YAAT,MAAkB;AAAA,IACpB,IAAI,YAAY,QAAQ;AAAA,IACxB,IACE,aAAa,WAAW,SAAS,KACjC,QAAQ,QAAQ,eAAe;AAAA,MAE/B,IACI,mBAAmB,OACpB,eAAe,eAAe,YAAY,WAC3C,8BAA8B,SAAS,YAAW;AAAA,SAE3C,QAAQ,QAAQ,YAAvB,MAAmC,mBAAmB;AAAA,MAEtD;AAAA,eACG,eAAe,QAAQ,QAAQ,OAChC,6BAA6B,SAAS,gBAAgB,YAAW;AAAA,EAEzE;AAAA,EACA,OAAO,wBACL,SACA,gBACA,YACA,WACA,YACF;AAAA;AAEF,SAAS,wBAAwB,CAC/B,SACA,gBACA,cACA,WACA;AAAA,EACA,IAAI,eAAe,UAAU,UAC3B,YAAqB,YAAT,OAAmB,QAAQ,gBAAgB;AAAA,EAChD,YAAT,QACW,eAAe,cAAxB,SACC,eAAe,YAAY;AAAA,IAC1B,aAAa;AAAA,IACb,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,cAAc;AAAA,EAChB;AAAA,EACF,IAAiB,UAAU,SAAvB,UAA6B;AAAA,IAC/B,KAAW,eAAe,QAAQ,SAA9B,GAAoC;AAAA,MACtC,YACW,cAAT,OAAqB,UAAU,YAAY,eAAc;AAAA,MAC3D,IAAa,YAAT,MAAkB;AAAA,QACpB,YAAY,eAAe,QAAQ,QAAQ;AAAA,QAC3C,KAAK,eAAe,EAAY,cAAT;AAAA,UACpB,eACC,eAAe,UAAU,QAAQ,UAAU,YAC1C,YAAY,UAAU;AAAA,QAC3B,YAAY,eAAe,CAAC;AAAA,MAC9B,EAAO;AAAA,QAAC,YAAY,GAAK,eAAe,QAAQ;AAAA,MAChD,OAAO,8BACL,SACA,gBACA,WACA,cACA,SACF;AAAA,IACF;AAAA,IACA,KAAW,eAAc,eAArB;AAAA,MACD,eAAe,gBAAgB,EAAE,WAAW,GAAG,WAAW,KAAK,GACrD,YAAT,QACE,eACE,gBACS,cAAT,OAAqB,UAAU,YAAY,IAC7C,GACO,cAAT,OACI,kBAAkB,gBAAgB,SAAS,IAC3C,0BAA0B,GAC9B,6BAA6B,cAAc;AAAA,IAE7C;AAAA,aACG,YAAY,eAAe,QAAQ,WACpC,8BACE,SACA,gBACS,cAAT,OAAqB,UAAU,YAAY,eAAc,cACzD,cACA,SACF;AAAA,EAEN,EACE;AAAA,IAAS,cAAT,QACK,eAAe,gBAAgB,UAAU,SAAS,GACnD,kBAAkB,gBAAgB,SAAS,GAC3C,4BAA4B,cAAc,GACzC,eAAe,gBAAgB,SACtB,YAAT,QAAoB,eAAe,gBAAgB,IAAI,GACxD,0BAA0B,GAC1B,4BAA4B,cAAc;AAAA,EAChD,kBAAkB,SAAS,gBAAgB,cAAc,YAAW;AAAA,EACpE,OAAO,eAAe;AAAA;AAExB,SAAS,yBAAyB,CAAC,SAAS,gBAAgB;AAAA,EAChD,YAAT,QAA2B,QAAQ,QAAf,MACV,eAAe,cAAxB,SACC,eAAe,YAAY;AAAA,IAC1B,aAAa;AAAA,IACb,iBAAiB;AAAA,IACjB,aAAa;AAAA,IACb,cAAc;AAAA,EAChB;AAAA,EACF,OAAO,eAAe;AAAA;AAExB,SAAS,6BAA6B,CACpC,SACA,gBACA,eACA,cACA,qBACA;AAAA,EACA,IAAI,2BAA2B,kBAAkB;AAAA,EACjD,2BACW,6BAAT,OACI,OACA,EAAE,QAAQ,aAAa,eAAe,MAAM,yBAAyB;AAAA,EAC3E,eAAe,gBAAgB;AAAA,IAC7B,WAAW;AAAA,IACX,WAAW;AAAA,EACb;AAAA,EACS,YAAT,QAAoB,eAAe,gBAAgB,IAAI;AAAA,EACvD,0BAA0B;AAAA,EAC1B,6BAA6B,cAAc;AAAA,EAClC,YAAT,QACE,8BAA8B,SAAS,gBAAgB,cAAa,IAAE;AAAA,EACxE,eAAe,aAAa;AAAA,EAC5B,OAAO;AAAA;AAET,SAAS,qBAAqB,CAAC,gBAAgB,WAAW;AAAA,EACxD,YAAY,kCACV,EAAE,MAAM,UAAU,MAAM,UAAU,UAAU,SAAS,GACrD,eAAe,IACjB;AAAA,EACA,UAAU,MAAM,eAAe;AAAA,EAC/B,eAAe,QAAQ;AAAA,EACvB,UAAU,SAAS;AAAA,EACnB,OAAO;AAAA;AAET,SAAS,sCAAsC,CAC7C,SACA,gBACA,cACA;AAAA,EACA,qBAAqB,gBAAgB,QAAQ,OAAO,MAAM,YAAW;AAAA,EACrE,UAAU,sBAAsB,gBAAgB,eAAe,YAAY;AAAA,EAC3E,QAAQ,SAAS;AAAA,EACjB,mBAAmB,cAAc;AAAA,EACjC,eAAe,gBAAgB;AAAA,EAC/B,OAAO;AAAA;AAET,SAAS,uBAAuB,CAAC,SAAS,gBAAgB,cAAa;AAAA,EACrE,IAAI,YAAY,eAAe,cAC7B,cAAoB,eAAe,QAAQ,SAA9B;AAAA,EACf,eAAe,SAAS;AAAA,EACxB,IAAa,YAAT,MAAkB;AAAA,IACpB,IAAI,aAAa;AAAA,MACf,IAAiB,UAAU,SAAvB;AAAA,QACF,OACG,UAAU,sBAAsB,gBAAgB,SAAS,GACzD,eAAe,QAAQ,WACxB,0BAA0B,MAAM,OAAO;AAAA,MAE3C,sCAAsC,cAAc;AAAA,OACnD,UAAU,2BACL,UAAU,4BACV,SACA,sBACF,GACC,UAAmB,YAAT,QAA4B,QAAQ,SAAhB,MAAuB,UAAU,MACvD,YAAT,SACI,eAAe,gBAAgB;AAAA,QAC/B,YAAY;AAAA,QACZ,aACW,wBAAT,OACI,EAAE,IAAI,eAAe,UAAU,oBAAoB,IACnD;AAAA,QACN,WAAW;AAAA,QACX,iBAAiB;AAAA,MACnB,GACC,eAAc,kCAAkC,OAAO,GACvD,aAAY,SAAS,gBACrB,eAAe,QAAQ,cACvB,uBAAuB,gBACvB,yBAAyB,SAC3B,UAAU;AAAA,MACf,IAAa,YAAT;AAAA,QAAkB,MAAM,yBAAyB,cAAc;AAAA,MACnE,eAAe,QAAQ;AAAA,MACvB,OAAO;AAAA,IACT;AAAA,IACA,OAAO,sBAAsB,gBAAgB,SAAS;AAAA,EACxD;AAAA,EACA,IAAI,YAAY,QAAQ;AAAA,EACxB,IAAa,cAAT,MAAoB;AAAA,IACtB,IAAI,aAAa,UAAU;AAAA,IAC3B,sCAAsC,cAAc;AAAA,IACpD,IAAI;AAAA,MACF,IAAI,eAAe,QAAQ;AAAA,QACxB,eAAe,SAAS,MACtB,iBAAiB,uCAChB,SACA,gBACA,YACF;AAAA,MACC,SAAa,eAAe,kBAAxB;AAAA,QACN,eAAe,QAAQ,QAAQ,OAC7B,eAAe,SAAS,KACxB,iBAAiB;AAAA,MACjB;AAAA,cAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,IACzC,SACF,oBACC,8BAA8B,SAAS,gBAAgB,cAAa,KAAE,GACvE,cAAoB,eAAc,QAAQ,gBAA7B,GACd,oBAAoB,YACpB;AAAA,MACA,YAAY;AAAA,MACZ,IACW,cAAT,SACE,aAAa,0BAA0B,WAAW,YAAW,GACzD,eAAN,KAAoB,eAAe,UAAU;AAAA,QAE7C,MACI,UAAU,YAAY,YACxB,+BAA+B,SAAS,UAAU,GAClD,sBAAsB,WAAW,SAAS,UAAU,GACpD;AAAA,MAEJ,gCAAgC;AAAA,MAChC,iBAAiB,uCACf,SACA,gBACA,YACF;AAAA,IACF,EACE;AAAA,MAAC,UAAU,UAAU,aAClB,yBAAyB,kBAAkB,WAAW,WAAW,GACjE,uBAAuB,gBACvB,cAAc,MACd,kBAAkB,MAClB,yBAAyB,OACjB,YAAT,QACE,4BAA4B,gBAAgB,OAAO,GACpD,iBAAiB,sBAAsB,gBAAgB,SAAS,GAChE,eAAe,SAAS;AAAA,IAC7B,OAAO;AAAA,EACT;AAAA,EACA,UAAU,qBAAqB,QAAQ,OAAO;AAAA,IAC5C,MAAM,UAAU;AAAA,IAChB,UAAU,UAAU;AAAA,EACtB,CAAC;AAAA,EACD,QAAQ,MAAM,eAAe;AAAA,EAC7B,eAAe,QAAQ;AAAA,EACvB,QAAQ,SAAS;AAAA,EACjB,OAAO;AAAA;AAET,SAAS,OAAO,CAAC,SAAS,gBAAgB;AAAA,EACxC,IAAI,MAAM,eAAe;AAAA,EACzB,IAAa,QAAT;AAAA,IACO,YAAT,QACW,QAAQ,QAAjB,SACC,eAAe,SAAS;AAAA,EACxB;AAAA,IACH,IAAmB,OAAO,QAAtB,cAA0C,OAAO,QAApB;AAAA,MAC/B,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,IACzC,IAAa,YAAT,QAAoB,QAAQ,QAAQ;AAAA,MACtC,eAAe,SAAS;AAAA;AAAA;AAG9B,SAAS,uBAAuB,CAC9B,SACA,gBACA,YACA,WACA,cACA;AAAA,EACA,qBAAqB,cAAc;AAAA,EACnC,aAAY,gBACV,SACA,gBACA,YACA,WACK,WACL,YACF;AAAA,EACA,YAAY,qBAAqB;AAAA,EACjC,IAAa,YAAT,QAAoB,CAAC;AAAA,IACvB,OACE,aAAa,SAAS,gBAAgB,YAAW,GACjD,6BAA6B,SAAS,gBAAgB,YAAW;AAAA,EAErE,eAAe,aAAa,uBAAuB,cAAc;AAAA,EACjE,eAAe,SAAS;AAAA,EACxB,kBAAkB,SAAS,gBAAgB,YAAW,YAAW;AAAA,EACjE,OAAO,eAAe;AAAA;AAExB,SAAS,uBAAuB,CAC9B,SACA,gBACA,WACA,YACA,WACA,cACA;AAAA,EACA,qBAAqB,cAAc;AAAA,EACnC,eAAe,cAAc;AAAA,EAC7B,YAAY,qBACV,gBACA,YACA,WACA,SACF;AAAA,EACA,qBAAqB,OAAO;AAAA,EAC5B,aAAY,qBAAqB;AAAA,EACjC,IAAa,YAAT,QAAoB,CAAC;AAAA,IACvB,OACE,aAAa,SAAS,gBAAgB,YAAW,GACjD,6BAA6B,SAAS,gBAAgB,YAAW;AAAA,EAErE,eAAe,cAAa,uBAAuB,cAAc;AAAA,EACjE,eAAe,SAAS;AAAA,EACxB,kBAAkB,SAAS,gBAAgB,WAAW,YAAW;AAAA,EACjE,OAAO,eAAe;AAAA;AAExB,SAAS,oBAAoB,CAC3B,SACA,gBACA,YACA,WACA,cACA;AAAA,EACA,qBAAqB,cAAc;AAAA,EACnC,IAAa,eAAe,cAAxB,MAAmC;AAAA,IACrC,IAAI,UAAU,oBACZ,cAAc,WAAU;AAAA,IACb,OAAO,gBAApB,YACW,gBAAT,SACC,UAAU,YAAY,WAAW;AAAA,IACpC,UAAU,IAAI,WAAU,WAAW,OAAO;AAAA,IAC1C,eAAe,gBACJ,QAAQ,UAAjB,QAAqC,QAAQ,UAAd,YAAsB,QAAQ,QAAQ;AAAA,IACvE,QAAQ,UAAU;AAAA,IAClB,eAAe,YAAY;AAAA,IAC3B,QAAQ,kBAAkB;AAAA,IAC1B,UAAU,eAAe;AAAA,IACzB,QAAQ,QAAQ;AAAA,IAChB,QAAQ,QAAQ,eAAe;AAAA,IAC/B,QAAQ,OAAO,CAAC;AAAA,IAChB,sBAAsB,cAAc;AAAA,IACpC,cAAc,WAAU;AAAA,IACxB,QAAQ,UACO,OAAO,gBAApB,YAA4C,gBAAT,OAC/B,YAAY,WAAW,IACvB;AAAA,IACN,QAAQ,QAAQ,eAAe;AAAA,IAC/B,cAAc,WAAU;AAAA,IACT,OAAO,gBAAtB,eACG,2BACC,gBACA,YACA,aACA,SACF,GACC,QAAQ,QAAQ,eAAe;AAAA,IACnB,OAAO,WAAU,6BAAhC,cACiB,OAAO,QAAQ,4BAA9B,cACgB,OAAO,QAAQ,8BAA9B,cACgB,OAAO,QAAQ,uBAA9B,eACA,cAAc,QAAQ,OACT,OAAO,QAAQ,uBAA9B,cACE,QAAQ,mBAAmB,GACd,OAAO,QAAQ,8BAA9B,cACE,QAAQ,0BAA0B,GACpC,gBAAgB,QAAQ,SACtB,sBAAsB,oBAAoB,SAAS,QAAQ,OAAO,IAAI,GACxE,mBAAmB,gBAAgB,WAAW,SAAS,YAAW,GAClE,4CAA4C,GAC3C,QAAQ,QAAQ,eAAe;AAAA,IACnB,OAAO,QAAQ,sBAA9B,eACG,eAAe,SAAS;AAAA,IAC3B,YAAY;AAAA,EACd,EAAO,SAAa,YAAT,MAAkB;AAAA,IAC3B,UAAU,eAAe;AAAA,IACzB,IAAI,qBAAqB,eAAe,eACtC,WAAW,2BAA2B,YAAW,kBAAkB;AAAA,IACrE,QAAQ,QAAQ;AAAA,IAChB,IAAI,aAAa,QAAQ,SACvB,uBAAuB,WAAU;AAAA,IACnC,cAAc;AAAA,IACD,OAAO,yBAApB,YACW,yBAAT,SACC,cAAc,YAAY,oBAAoB;AAAA,IACjD,IAAI,2BAA2B,WAAU;AAAA,IACzC,uBACiB,OAAO,6BAAtB,cACe,OAAO,QAAQ,4BAA9B;AAAA,IACF,qBAAqB,eAAe,iBAAiB;AAAA,IACrD,wBACkB,OAAO,QAAQ,qCAA9B,cACgB,OAAO,QAAQ,8BAA9B,eACA,sBAAsB,eAAe,gBACrC,8BACE,gBACA,SACA,WACA,WACF;AAAA,IACJ,iBAAiB;AAAA,IACjB,IAAI,WAAW,eAAe;AAAA,IAC9B,QAAQ,QAAQ;AAAA,IAChB,mBAAmB,gBAAgB,WAAW,SAAS,YAAW;AAAA,IAClE,4CAA4C;AAAA,IAC5C,aAAa,eAAe;AAAA,IAC5B,sBAAsB,aAAa,cAAc,kBAC7B,OAAO,6BAAtB,eACE,2BACC,gBACA,YACA,0BACA,SACF,GACC,aAAa,eAAe,iBAC9B,WACC,kBACA,2BACE,gBACA,YACA,UACA,WACA,UACA,YACA,WACF,MACG,wBACiB,OAAO,QAAQ,8BAA9B,cACgB,OAAO,QAAQ,uBAA9B,eACc,OAAO,QAAQ,uBAA9B,cACC,QAAQ,mBAAmB,GACd,OAAO,QAAQ,8BAA9B,cACE,QAAQ,0BAA0B,IACvB,OAAO,QAAQ,sBAA9B,eACG,eAAe,SAAS,aACX,OAAO,QAAQ,sBAA9B,eACE,eAAe,SAAS,UAC1B,eAAe,gBAAgB,WAC/B,eAAe,gBAAgB,aACnC,QAAQ,QAAQ,WAChB,QAAQ,QAAQ,YAChB,QAAQ,UAAU,aAClB,YAAY,aACG,OAAO,QAAQ,sBAA9B,eACE,eAAe,SAAS,UAC1B,YAAY;AAAA,EACnB,EAAO;AAAA,IACL,UAAU,eAAe;AAAA,IACzB,iBAAiB,SAAS,cAAc;AAAA,IACxC,cAAc,eAAe;AAAA,IAC7B,uBAAuB,2BAA2B,YAAW,WAAW;AAAA,IACxE,QAAQ,QAAQ;AAAA,IAChB,2BAA2B,eAAe;AAAA,IAC1C,WAAW,QAAQ;AAAA,IACnB,aAAa,WAAU;AAAA,IACvB,WAAW;AAAA,IACE,OAAO,eAApB,YACW,eAAT,SACC,WAAW,YAAY,UAAU;AAAA,IACpC,qBAAqB,WAAU;AAAA,KAC9B,aACgB,OAAO,uBAAtB,cACe,OAAO,QAAQ,4BAA9B,eACgB,OAAO,QAAQ,qCAA9B,cACgB,OAAO,QAAQ,8BAA9B,eACA,gBAAgB,4BAA4B,aAAa,aACzD,8BACE,gBACA,SACA,WACA,QACF;AAAA,IACJ,iBAAiB;AAAA,IACjB,WAAW,eAAe;AAAA,IAC1B,QAAQ,QAAQ;AAAA,IAChB,mBAAmB,gBAAgB,WAAW,SAAS,YAAW;AAAA,IAClE,4CAA4C;AAAA,IAC5C,IAAI,WAAW,eAAe;AAAA,IAC9B,gBAAgB,4BAChB,aAAa,YACb,kBACU,YAAT,QACU,QAAQ,iBAAjB,QACA,sBAAsB,QAAQ,YAAY,KACxB,OAAO,uBAAtB,eACE,2BACC,gBACA,YACA,oBACA,SACF,GACC,WAAW,eAAe,iBAC5B,uBACC,kBACA,2BACE,gBACA,YACA,sBACA,WACA,UACA,UACA,QACF,KACU,YAAT,QACU,QAAQ,iBAAjB,QACA,sBAAsB,QAAQ,YAAY,MACzC,cACiB,OAAO,QAAQ,+BAA9B,cACgB,OAAO,QAAQ,wBAA9B,eACc,OAAO,QAAQ,wBAA9B,cACC,QAAQ,oBAAoB,WAAW,UAAU,QAAQ,GAC5C,OAAO,QAAQ,+BAA9B,cACE,QAAQ,2BACN,WACA,UACA,QACF,IACW,OAAO,QAAQ,uBAA9B,eACG,eAAe,SAAS,IACZ,OAAO,QAAQ,4BAA9B,eACG,eAAe,SAAS,UACX,OAAO,QAAQ,uBAA9B,cACE,gBAAgB,QAAQ,iBACvB,aAAa,QAAQ,kBACtB,eAAe,SAAS,IACZ,OAAO,QAAQ,4BAA9B,cACG,gBAAgB,QAAQ,iBACvB,aAAa,QAAQ,kBACtB,eAAe,SAAS,OAC1B,eAAe,gBAAgB,WAC/B,eAAe,gBAAgB,WACnC,QAAQ,QAAQ,WAChB,QAAQ,QAAQ,UAChB,QAAQ,UAAU,UAClB,YAAY,yBACG,OAAO,QAAQ,uBAA9B,cACE,gBAAgB,QAAQ,iBACvB,aAAa,QAAQ,kBACtB,eAAe,SAAS,IACZ,OAAO,QAAQ,4BAA9B,cACG,gBAAgB,QAAQ,iBACvB,aAAa,QAAQ,kBACtB,eAAe,SAAS,OAC1B,YAAY;AAAA;AAAA,EAEnB,UAAU;AAAA,EACV,QAAQ,SAAS,cAAc;AAAA,EAC/B,aAAmB,eAAe,QAAQ,SAA9B;AAAA,EACZ,WAAW,aACL,UAAU,eAAe,WAC1B,aACC,aAA4B,OAAO,WAAU,6BAAhC,aACT,OACA,QAAQ,OAAO,GACpB,eAAe,SAAS,GAChB,YAAT,QAAoB,aACd,eAAe,QAAQ,qBACvB,gBACA,QAAQ,OACR,MACA,YACF,GACC,eAAe,QAAQ,qBACtB,gBACA,MACA,YACA,YACF,KACA,kBAAkB,SAAS,gBAAgB,YAAW,YAAW,GACpE,eAAe,gBAAgB,QAAQ,OACvC,UAAU,eAAe,SACzB,UAAU,6BACT,SACA,gBACA,YACF;AAAA,EACJ,OAAO;AAAA;AAET,SAAS,6BAA6B,CACpC,SACA,gBACA,cACA,cACA;AAAA,EACA,oBAAoB;AAAA,EACpB,eAAe,SAAS;AAAA,EACxB,kBAAkB,SAAS,gBAAgB,cAAc,YAAW;AAAA,EACpE,OAAO,eAAe;AAAA;AAQxB,SAAS,2BAA2B,CAAC,cAAa;AAAA,EAChD,OAAO,EAAE,WAAW,cAAa,WAAW,kBAAkB,EAAE;AAAA;AAElE,SAAS,6BAA6B,CACpC,SACA,qBACA,cACA;AAAA,EACA,UAAmB,YAAT,OAAmB,QAAQ,aAAa,CAAC,eAAc;AAAA,EACjE,wBAAwB,WAAW;AAAA,EACnC,OAAO;AAAA;AAET,SAAS,uBAAuB,CAAC,SAAS,gBAAgB,cAAa;AAAA,EACrE,IAAI,YAAY,eAAe,cAC7B,eAAe,OACf,cAAoB,eAAe,QAAQ,SAA9B,GACb;AAAA,GACD,kBAAkB,gBAChB,kBACU,YAAT,QAA6B,QAAQ,kBAAjB,OAChB,SACO,oBAAoB,UAAU,OAArC;AAAA,EACR,oBAAqB,eAAe,MAAM,eAAe,SAAS;AAAA,EAClE,mBAAyB,eAAe,QAAQ,QAA9B;AAAA,EAClB,eAAe,SAAS;AAAA,EACxB,IAAa,YAAT,MAAkB;AAAA,IACpB,IAAI,aAAa;AAAA,MACf,eACI,+BAA+B,cAAc,IAC7C,4BAA4B,cAAc;AAAA,OAC7C,UAAU,2BACL,UAAU,4BACV,SACA,sBACF,GACC,UAAmB,YAAT,QAA4B,QAAQ,SAAhB,MAAuB,UAAU,MACvD,YAAT,SACI,eAAe,gBAAgB;AAAA,QAC/B,YAAY;AAAA,QACZ,aACW,wBAAT,OACI,EAAE,IAAI,eAAe,UAAU,oBAAoB,IACnD;AAAA,QACN,WAAW;AAAA,QACX,iBAAiB;AAAA,MACnB,GACC,eAAc,kCAAkC,OAAO,GACvD,aAAY,SAAS,gBACrB,eAAe,QAAQ,cACvB,uBAAuB,gBACvB,yBAAyB,SAC3B,UAAU;AAAA,MACf,IAAa,YAAT;AAAA,QAAkB,MAAM,yBAAyB,cAAc;AAAA,MACnE,2BAA2B,OAAO,IAC7B,eAAe,QAAQ,KACvB,eAAe,QAAQ;AAAA,MAC5B,OAAO;AAAA,IACT;AAAA,IACA,IAAI,sBAAsB,UAAU;AAAA,IACpC,YAAY,UAAU;AAAA,IACtB,IAAI;AAAA,MACF,OACE,4BAA4B,cAAc,GACzC,eAAe,eAAe,MAC9B,sBAAsB,kCACrB,EAAE,MAAM,UAAU,UAAU,oBAAoB,GAChD,YACF,GACC,YAAY,wBACX,WACA,cACA,cACA,IACF,GACC,oBAAoB,SAAS,gBAC7B,UAAU,SAAS,gBACnB,oBAAoB,UAAU,WAC9B,eAAe,QAAQ,qBACvB,YAAY,eAAe,OAC3B,UAAU,gBAAgB,4BAA4B,YAAW,GACjE,UAAU,aAAa,8BACtB,SACA,iBACA,YACF,GACC,eAAe,gBAAgB,kBAChC,0BAA0B,MAAM,SAAS;AAAA,IAE7C,+BAA+B,cAAc;AAAA,IAC7C,OAAO,6BAA6B,gBAAgB,mBAAmB;AAAA,EACzE;AAAA,EACA,IAAI,YAAY,QAAQ;AAAA,EACxB,IACW,cAAT,SACE,sBAAsB,UAAU,YAAsB,wBAAT,OAC/C;AAAA,IACA,IAAI;AAAA,MACF,eAAe,QAAQ,OAClB,+BAA+B,cAAc,GAC7C,eAAe,SAAS,MACxB,iBAAiB,uCAChB,SACA,gBACA,YACF,KACS,eAAe,kBAAxB,QACG,4BAA4B,cAAc,GAC1C,eAAe,QAAQ,QAAQ,OAC/B,eAAe,SAAS,KACxB,iBAAiB,SACjB,4BAA4B,cAAc,GAC1C,sBAAsB,UAAU,UAChC,eAAe,eAAe,MAC9B,YAAY,kCACX,EAAE,MAAM,WAAW,UAAU,UAAU,SAAS,GAChD,YACF,GACC,sBAAsB,wBACrB,qBACA,cACA,cACA,IACF,GACC,oBAAoB,SAAS,GAC7B,UAAU,SAAS,gBACnB,oBAAoB,SAAS,gBAC7B,UAAU,UAAU,qBACpB,eAAe,QAAQ,WACxB,qBACE,gBACA,QAAQ,OACR,MACA,YACF,GACC,YAAY,eAAe,OAC3B,UAAU,gBACT,4BAA4B,YAAW,GACxC,UAAU,aAAa,8BACtB,SACA,iBACA,YACF,GACC,eAAe,gBAAgB,kBAC/B,iBAAiB,0BAA0B,MAAM,SAAS;AAAA,IAC9D,SACF,+BAA+B,cAAc,GAC9C,2BAA2B,mBAAmB,GAC9C;AAAA,MACA,kBACE,oBAAoB,eACpB,oBAAoB,YAAY;AAAA,MAClC,IAAI;AAAA,QAAiB,IAAI,SAAS,gBAAgB;AAAA,MAClD,kBAAkB;AAAA,MAClB,YAAY,MAAM,wBAAuB,GAAG,CAAC;AAAA,MAC7C,UAAU,QAAQ;AAAA,MAClB,UAAU,SAAS;AAAA,MACnB,oBAAoB,EAAE,OAAO,WAAW,QAAQ,MAAM,OAAO,KAAK,CAAC;AAAA,MACnE,iBAAiB,uCACf,SACA,gBACA,YACF;AAAA,IACF,EAAO,SACJ,oBACC,8BAA8B,SAAS,gBAAgB,cAAa,KAAE,GACvE,mBAAyB,eAAc,QAAQ,gBAA7B,GACnB,oBAAoB,iBACpB;AAAA,MACA,kBAAkB;AAAA,MAClB,IACW,oBAAT,SACE,YAAY,0BAA0B,iBAAiB,YAAW,GAC9D,cAAN,KAAmB,cAAc,UAAU;AAAA,QAE3C,MACI,UAAU,YAAY,WACxB,+BAA+B,SAAS,SAAS,GACjD,sBAAsB,iBAAiB,SAAS,SAAS,GACzD;AAAA,MAEJ,0BAA0B,mBAAmB,KAC3C,gCAAgC;AAAA,MAClC,iBAAiB,uCACf,SACA,gBACA,YACF;AAAA,IACF,EACE;AAAA,gCAA0B,mBAAmB,KACvC,eAAe,SAAS,KACzB,eAAe,QAAQ,QAAQ,OAC/B,iBAAiB,SAChB,UAAU,UAAU,aACrB,yBAAyB,kBACxB,oBAAoB,WACtB,GACC,uBAAuB,gBACvB,cAAc,MACd,kBAAkB,MAClB,yBAAyB,OACjB,YAAT,QACE,4BAA4B,gBAAgB,OAAO,GACpD,iBAAiB,6BAChB,gBACA,UAAU,QACZ,GACC,eAAe,SAAS;AAAA,IAC/B,OAAO;AAAA,EACT;AAAA,EACA,IAAI;AAAA,IACF,OACE,4BAA4B,cAAc,GACzC,sBAAsB,UAAU,UAChC,eAAe,eAAe,MAC9B,YAAY,QAAQ,OACpB,SAAS,UAAU,SACnB,YAAY,qBAAqB,WAAW;AAAA,MAC3C,MAAM;AAAA,MACN,UAAU,UAAU;AAAA,IACtB,CAAC,GACA,UAAU,eAAe,UAAU,eAAe,UAC1C,WAAT,OACK,sBAAsB,qBACrB,QACA,mBACF,KACE,sBAAsB,wBACtB,qBACA,cACA,cACA,IACF,GACC,oBAAoB,SAAS,IACjC,oBAAoB,SAAS,gBAC7B,UAAU,SAAS,gBACnB,UAAU,UAAU,qBACpB,eAAe,QAAQ,WACxB,0BAA0B,MAAM,SAAS,GACxC,YAAY,eAAe,OAC3B,sBAAsB,QAAQ,MAAM,eAC5B,wBAAT,OACK,sBAAsB,4BAA4B,YAAW,KAC5D,eAAe,oBAAoB,WAC5B,iBAAT,QACM,YAAY,aAAa,eAC1B,eACC,aAAa,WAAW,YACpB,EAAE,QAAQ,WAAW,MAAM,UAAU,IACrC,gBACL,eAAe,kBAAkB,GACrC,sBAAsB;AAAA,MACrB,WAAW,oBAAoB,YAAY;AAAA,MAC3C,WAAW;AAAA,IACb,IACH,UAAU,gBAAgB,qBAC1B,UAAU,aAAa,8BACtB,SACA,iBACA,YACF,GACC,eAAe,gBAAgB,kBAChC,0BAA0B,QAAQ,OAAO,SAAS;AAAA,EAEtD,+BAA+B,cAAc;AAAA,EAC7C,eAAc,QAAQ;AAAA,EACtB,UAAU,aAAY;AAAA,EACtB,eAAc,qBAAqB,cAAa;AAAA,IAC9C,MAAM;AAAA,IACN,UAAU,UAAU;AAAA,EACtB,CAAC;AAAA,EACD,aAAY,SAAS;AAAA,EACrB,aAAY,UAAU;AAAA,EACb,YAAT,SACI,kBAAkB,eAAe,WAC1B,oBAAT,QACM,eAAe,YAAY,CAAC,OAAO,GAAK,eAAe,SAAS,MAClE,gBAAgB,KAAK,OAAO;AAAA,EAClC,eAAe,QAAQ;AAAA,EACvB,eAAe,gBAAgB;AAAA,EAC/B,OAAO;AAAA;AAET,SAAS,4BAA4B,CAAC,gBAAgB,iBAAiB;AAAA,EACrE,kBAAkB,kCAChB,EAAE,MAAM,WAAW,UAAU,gBAAgB,GAC7C,eAAe,IACjB;AAAA,EACA,gBAAgB,SAAS;AAAA,EACzB,OAAQ,eAAe,QAAQ;AAAA;AAEjC,SAAS,iCAAiC,CAAC,gBAAgB,MAAM;AAAA,EAC/D,iBAAiB,qBAAqB,IAAI,gBAAgB,MAAM,IAAI;AAAA,EACpE,eAAe,QAAQ;AAAA,EACvB,OAAO;AAAA;AAET,SAAS,sCAAsC,CAC7C,SACA,gBACA,cACA;AAAA,EACA,qBAAqB,gBAAgB,QAAQ,OAAO,MAAM,YAAW;AAAA,EACrE,UAAU,6BACR,gBACA,eAAe,aAAa,QAC9B;AAAA,EACA,QAAQ,SAAS;AAAA,EACjB,eAAe,gBAAgB;AAAA,EAC/B,OAAO;AAAA;AAET,SAAS,2BAA2B,CAAC,OAAO,cAAa,iBAAiB;AAAA,EACxE,MAAM,SAAS;AAAA,EACf,IAAI,YAAY,MAAM;AAAA,EACb,cAAT,SAAuB,UAAU,SAAS;AAAA,EAC1C,gCAAgC,MAAM,QAAQ,cAAa,eAAe;AAAA;AAE5E,SAAS,2BAA2B,CAClC,gBACA,aACA,MACA,gBACA,UACA,gBACA;AAAA,EACA,IAAI,cAAc,eAAe;AAAA,EACxB,gBAAT,OACK,eAAe,gBAAgB;AAAA,IAC9B;AAAA,IACA,WAAW;AAAA,IACX,oBAAoB;AAAA,IACpB,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA,eAAe;AAAA,EACjB,KACE,YAAY,cAAc,aAC3B,YAAY,YAAY,MACxB,YAAY,qBAAqB,GACjC,YAAY,OAAO,gBACnB,YAAY,OAAO,MACnB,YAAY,WAAW,UACvB,YAAY,gBAAgB;AAAA;AAEnC,SAAS,2BAA2B,CAAC,SAAS,gBAAgB,cAAa;AAAA,EACzE,IAAI,YAAY,eAAe,cAC7B,cAAc,UAAU,aACxB,WAAW,UAAU;AAAA,EACvB,YAAY,UAAU;AAAA,EACtB,IAAI,kBAAkB,oBAAoB,SACxC,uBAA6B,kBAAkB,OAAzB;AAAA,EACxB,uBACM,kBAAmB,kBAAkB,IAAK,GAC3C,eAAe,SAAS,OACxB,mBAAmB;AAAA,EACxB,MAAK,qBAAqB,eAAe;AAAA,EACzC,kBAAkB,SAAS,gBAAgB,WAAW,YAAW;AAAA,EACjE,YAAY,cAAc,gBAAgB;AAAA,EAC1C,IAAI,CAAC,uBAAgC,YAAT,SAA2B,QAAQ,QAAQ,SAAvB;AAAA,IAC9C;AAAA,MAAG,KAAK,UAAU,eAAe,MAAgB,YAAT,QAAoB;AAAA,QAC1D,IAAW,QAAQ,QAAf;AAAA,UACO,QAAQ,kBAAjB,QACE,4BAA4B,SAAS,cAAa,cAAc;AAAA,QAC/D,SAAW,QAAQ,QAAf;AAAA,UACP,4BAA4B,SAAS,cAAa,cAAc;AAAA,QAC7D,SAAa,QAAQ,UAAjB,MAAwB;AAAA,UAC/B,QAAQ,MAAM,SAAS;AAAA,UACvB,UAAU,QAAQ;AAAA,UAClB;AAAA,QACF;AAAA,QACA,IAAI,YAAY;AAAA,UAAgB;AAAA,QAChC,MAAgB,QAAQ,YAAjB,QAA4B;AAAA,UACjC,IAAa,QAAQ,WAAjB,QAA2B,QAAQ,WAAW;AAAA,YAChD;AAAA,UACF,UAAU,QAAQ;AAAA,QACpB;AAAA,QACA,QAAQ,QAAQ,SAAS,QAAQ;AAAA,QACjC,UAAU,QAAQ;AAAA,MACpB;AAAA,EACF,QAAQ;AAAA,SACD;AAAA,MACH,eAAc,eAAe;AAAA,MAC7B,KAAK,cAAc,KAAe,iBAAT;AAAA,QACtB,UAAU,aAAY,WACZ,YAAT,QACW,mBAAmB,OAAO,MAAnC,SACC,cAAc,eAChB,eAAc,aAAY;AAAA,MAC/B,eAAc;AAAA,MACL,iBAAT,QACM,cAAc,eAAe,OAAS,eAAe,QAAQ,SAC7D,cAAc,aAAY,SAAW,aAAY,UAAU;AAAA,MACjE,4BACE,gBACA,OACA,aACA,cACA,UACA,SACF;AAAA,MACA;AAAA,SACG;AAAA,SACA;AAAA,MACH,eAAc;AAAA,MACd,cAAc,eAAe;AAAA,MAC7B,KAAK,eAAe,QAAQ,KAAe,gBAAT,QAAwB;AAAA,QACxD,UAAU,YAAY;AAAA,QACtB,IAAa,YAAT,QAA6B,mBAAmB,OAAO,MAAnC,MAAsC;AAAA,UAC5D,eAAe,QAAQ;AAAA,UACvB;AAAA,QACF;AAAA,QACA,UAAU,YAAY;AAAA,QACtB,YAAY,UAAU;AAAA,QACtB,eAAc;AAAA,QACd,cAAc;AAAA,MAChB;AAAA,MACA,4BACE,gBACA,MACA,cACA,MACA,UACA,SACF;AAAA,MACA;AAAA,SACG;AAAA,MACH,4BACE,gBACA,OACA,MACA,MACK,WACL,SACF;AAAA,MACA;AAAA;AAAA,MAEA,eAAe,gBAAgB;AAAA;AAAA,EAEnC,OAAO,eAAe;AAAA;AAExB,SAAS,4BAA4B,CAAC,SAAS,gBAAgB,cAAa;AAAA,EACjE,YAAT,SAAqB,eAAe,eAAe,QAAQ;AAAA,EAC3D,kCAAkC,eAAe;AAAA,EACjD,KAAW,eAAc,eAAe,gBAApC;AAAA,IACF,IAAa,YAAT,MAAkB;AAAA,MACpB,IACG,8BACC,SACA,gBACA,cACA,KACF,IACO,eAAc,eAAe,gBAApC;AAAA,QAEA,OAAO;AAAA,IACX,EAAO;AAAA,aAAO;AAAA,EAChB,IAAa,YAAT,QAAoB,eAAe,UAAU,QAAQ;AAAA,IACvD,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,EACzC,IAAa,eAAe,UAAxB,MAA+B;AAAA,IACjC,UAAU,eAAe;AAAA,IACzB,eAAc,qBAAqB,SAAS,QAAQ,YAAY;AAAA,IAChE,eAAe,QAAQ;AAAA,IACvB,KAAK,aAAY,SAAS,eAAyB,QAAQ,YAAjB;AAAA,MACvC,UAAU,QAAQ,SAChB,eAAc,aAAY,UACzB,qBAAqB,SAAS,QAAQ,YAAY,GACnD,aAAY,SAAS;AAAA,IAC1B,aAAY,UAAU;AAAA,EACxB;AAAA,EACA,OAAO,eAAe;AAAA;AAExB,SAAS,6BAA6B,CAAC,SAAS,cAAa;AAAA,EAC3D,KAAW,QAAQ,QAAQ,kBAAvB;AAAA,IAAqC,OAAO;AAAA,EAChD,UAAU,QAAQ;AAAA,EAClB,OAAgB,YAAT,QAAoB,sBAAsB,OAAO,IAAI,OAAK;AAAA;AAEnE,SAAS,sCAAsC,CAC7C,SACA,gBACA,cACA;AAAA,EACA,QAAQ,eAAe;AAAA,SAChB;AAAA,MACH,kBAAkB,gBAAgB,eAAe,UAAU,aAAa;AAAA,MACxE,aAAa,gBAAgB,cAAc,QAAQ,cAAc,KAAK;AAAA,MACtE,oBAAoB;AAAA,MACpB;AAAA,SACG;AAAA,SACA;AAAA,MACH,gBAAgB,cAAc;AAAA,MAC9B;AAAA,SACG;AAAA,MACH,kBAAkB,gBAAgB,eAAe,UAAU,aAAa;AAAA,MACxE;AAAA,SACG;AAAA,MACH,aACE,gBACA,eAAe,MACf,eAAe,cAAc,KAC/B;AAAA,MACA;AAAA,SACG;AAAA,MACH,IAAa,eAAe,kBAAxB;AAAA,QACF,OACG,eAAe,SAAS,KACzB,sCAAsC,cAAc,GACpD;AAAA,MAEJ;AAAA,SACG;AAAA,MACH,IAAI,YAAY,eAAe;AAAA,MAC/B,IAAa,cAAT,MAAoB;AAAA,QACtB,IAAa,UAAU,eAAnB;AAAA,UACF,OACE,+BAA+B,cAAc,GAC5C,eAAe,SAAS,KACzB;AAAA,QAEJ,KAAW,eAAc,eAAe,MAAM,gBAA1C;AAAA,UACF,OAAO,wBAAwB,SAAS,gBAAgB,YAAW;AAAA,QACrE,+BAA+B,cAAc;AAAA,QAC7C,UAAU,6BACR,SACA,gBACA,YACF;AAAA,QACA,OAAgB,YAAT,OAAmB,QAAQ,UAAU;AAAA,MAC9C;AAAA,MACA,+BAA+B,cAAc;AAAA,MAC7C;AAAA,SACG;AAAA,MACH,IAAI,oBAA0B,QAAQ,QAAQ,SAAvB;AAAA,MACvB,aAAmB,eAAc,eAAe,gBAApC;AAAA,MACZ,cACG,8BACC,SACA,gBACA,cACA,KACF,GACC,aAAmB,eAAc,eAAe,gBAApC;AAAA,MACf,IAAI,kBAAkB;AAAA,QACpB,IAAI;AAAA,UACF,OAAO,4BACL,SACA,gBACA,YACF;AAAA,QACF,eAAe,SAAS;AAAA,MAC1B;AAAA,MACA,mBAAmB,eAAe;AAAA,MACzB,qBAAT,SACI,iBAAiB,YAAY,MAC9B,iBAAiB,OAAO,MACxB,iBAAiB,aAAa;AAAA,MACjC,MAAK,qBAAqB,oBAAoB,OAAO;AAAA,MACrD,IAAI;AAAA,QAAW;AAAA,MACV;AAAA,eAAO;AAAA,SACT;AAAA,MACH,OACG,eAAe,QAAQ,GACxB,yBACE,SACA,gBACA,cACA,eAAe,YACjB;AAAA,SAEC;AAAA,MACH,aAAa,gBAAgB,cAAc,QAAQ,cAAc,KAAK;AAAA;AAAA,EAE1E,OAAO,6BAA6B,SAAS,gBAAgB,YAAW;AAAA;AAE1E,SAAS,SAAS,CAAC,SAAS,gBAAgB,cAAa;AAAA,EACvD,IAAa,YAAT;AAAA,IACF,IAAI,QAAQ,kBAAkB,eAAe;AAAA,MAC3C,mBAAmB;AAAA,IAChB;AAAA,MACH,IACE,CAAC,8BAA8B,SAAS,YAAW,MAC5C,eAAe,QAAQ,SAA9B;AAAA,QAEA,OACG,mBAAmB,OACpB,uCACE,SACA,gBACA,YACF;AAAA,MAEJ,oBAA0B,QAAQ,QAAQ,YAAvB,IAAiC,OAAK;AAAA;AAAA,EAG3D;AAAA,IAAC,mBAAmB,OAClB,gBACS,eAAe,QAAQ,aAA9B,KACA,WAAW,gBAAgB,eAAe,eAAe,KAAK;AAAA,EACpE,eAAe,QAAQ;AAAA,EACvB,QAAQ,eAAe;AAAA,SAChB;AAAA,MACH,GAAG;AAAA,QACD,IAAI,QAAQ,eAAe;AAAA,QAC3B,UAAU,YAAY,eAAe,WAAW;AAAA,QAChD,eAAe,OAAO;AAAA,QACtB,IAAmB,OAAO,YAAtB;AAAA,UACF,gBAAgB,OAAO,KACjB,QAAQ,2BAA2B,SAAS,KAAK,GAClD,eAAe,MAAM,GACrB,iBAAiB,qBAChB,MACA,gBACA,SACA,OACA,YACF,MACE,eAAe,MAAM,GACtB,iBAAiB,wBAChB,MACA,gBACA,SACA,OACA,YACF;AAAA,QACD;AAAA,UACH,IAAe,YAAN,aAA0B,YAAT,MAAkB;AAAA,YAC1C,IAAI,WAAW,QAAQ;AAAA,YACvB,IAAI,aAAa,yBAAwB;AAAA,cACvC,eAAe,MAAM;AAAA,cACrB,iBAAiB,iBACf,MACA,gBACA,SACA,OACA,YACF;AAAA,cACA;AAAA,YACF,EAAO,SAAI,aAAa,kBAAiB;AAAA,cACvC,eAAe,MAAM;AAAA,cACrB,iBAAiB,oBACf,MACA,gBACA,SACA,OACA,YACF;AAAA,cACA;AAAA,YACF;AAAA,UACF;AAAA,UACA,iBAAiB,yBAAyB,OAAO,KAAK;AAAA,UACtD,MAAM,MAAM,wBAAuB,KAAK,gBAAgB,EAAE,CAAC;AAAA;AAAA,MAE/D;AAAA,MACA,OAAO;AAAA,SACJ;AAAA,MACH,OAAO,wBACL,SACA,gBACA,eAAe,MACf,eAAe,cACf,YACF;AAAA,SACG;AAAA,MACH,OACG,QAAQ,eAAe,MACvB,WAAW,2BACV,OACA,eAAe,YACjB,GACA,qBACE,SACA,gBACA,OACA,UACA,YACF;AAAA,SAEC;AAAA,MACH,GAAG;AAAA,QACD,kBACE,gBACA,eAAe,UAAU,aAC3B;AAAA,QACA,IAAa,YAAT;AAAA,UAAkB,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,QAC7D,QAAQ,eAAe;AAAA,QACvB,IAAI,YAAY,eAAe;AAAA,QAC/B,WAAW,UAAU;AAAA,QACrB,iBAAiB,SAAS,cAAc;AAAA,QACxC,mBAAmB,gBAAgB,OAAO,MAAM,YAAW;AAAA,QAC3D,IAAI,YAAY,eAAe;AAAA,QAC/B,QAAQ,UAAU;AAAA,QAClB,aAAa,gBAAgB,cAAc,KAAK;AAAA,QAChD,UAAU,UAAU,SAClB,wBACE,gBACA,CAAC,YAAY,GACb,cACA,IACF;AAAA,QACF,4CAA4C;AAAA,QAC5C,QAAQ,UAAU;AAAA,QAClB,IAAI,UAAU;AAAA,UACZ,IACI,YAAY;AAAA,YACZ,SAAS;AAAA,YACT,cAAc;AAAA,YACd,OAAO,UAAU;AAAA,UACnB,GACC,eAAe,YAAY,YAAY,WACvC,eAAe,gBAAgB,WAChC,eAAe,QAAQ,KACvB;AAAA,YACA,iBAAiB,8BACf,SACA,gBACA,OACA,YACF;AAAA,YACA;AAAA,UACF,EAAO,SAAI,UAAU,UAAU;AAAA,YAC7B,WAAW,2BACT,MAAM,wBAAuB,GAAG,CAAC,GACjC,cACF;AAAA,YACA,oBAAoB,QAAQ;AAAA,YAC5B,iBAAiB,8BACf,SACA,gBACA,OACA,YACF;AAAA,YACA;AAAA,UACF,EAAO;AAAA,YACL,UAAU,eAAe,UAAU;AAAA,YACnC,QAAQ,QAAQ;AAAA,mBACT;AAAA,gBACH,UAAU,QAAQ;AAAA,gBAClB;AAAA;AAAA,gBAEA,UACa,QAAQ,aAAnB,SACI,QAAQ,cAAc,OACtB;AAAA;AAAA,YAEV,yBAAyB,kBAAkB,QAAQ,UAAU;AAAA,YAC7D,uBAAuB;AAAA,YACvB,cAAc;AAAA,YACd,kBAAkB;AAAA,YAClB,yBAAyB;AAAA,YACzB,eAAc,iBACZ,gBACA,MACA,OACA,YACF;AAAA,YACA,KAAK,eAAe,QAAQ,aAAa;AAAA,cACtC,aAAY,QAAS,aAAY,QAAQ,KAAM,MAC7C,eAAc,aAAY;AAAA;AAAA,QAE9B;AAAA,UACH,oBAAoB;AAAA,UACpB,IAAI,UAAU,UAAU;AAAA,YACtB,iBAAiB,6BACf,SACA,gBACA,YACF;AAAA,YACA;AAAA,UACF;AAAA,UACA,kBAAkB,SAAS,gBAAgB,OAAO,YAAW;AAAA;AAAA,QAE/D,iBAAiB,eAAe;AAAA,MAClC;AAAA,MACA,OAAO;AAAA,SACJ;AAAA,MACH,OACE,QAAQ,SAAS,cAAc,GACtB,YAAT,QACK,eAAc,YACb,eAAe,MACf,MACA,eAAe,cACf,IACF,KACG,eAAe,gBAAgB,eAChC,gBACE,eAAc,eAAe,MAC9B,UAAU,eAAe,cACzB,QAAQ,kCACP,wBAAwB,OAC1B,EAAE,cAAc,YAAW,GAC1B,MAAM,uBAAuB,gBAC7B,MAAM,oBAAoB,SAC3B,qBAAqB,OAAO,cAAa,OAAO,GAChD,oBAAoB,KAAK,GACxB,eAAe,YAAY,SAC7B,eAAe,gBAAgB,YAC9B,eAAe,MACf,QAAQ,eACR,eAAe,cACf,QAAQ,aACV,GACJ;AAAA,SAEC;AAAA,MACH,OACE,gBAAgB,cAAc,GACrB,YAAT,QACE,gBACE,QAAQ,eAAe,YACvB,yBACE,eAAe,MACf,eAAe,cACf,wBAAwB,OAC1B,GACD,uBAAuB,gBACvB,yBAAyB,MACzB,WAAW,wBACZ,iBAAiB,eAAe,IAAI,KAC9B,8CAA8C,UAC/C,yBAAyB,kBAAkB,MAAM,UAAU,KAC3D,yBAAyB,WAChC,kBACE,SACA,gBACA,eAAe,aAAa,UAC5B,YACF,GACA,QAAQ,SAAS,cAAc,GACtB,YAAT,SAAqB,eAAe,SAAS,UAC7C,eAAe;AAAA,SAEd;AAAA,MACH,IAAa,YAAT,QAAoB,aAAa;AAAA,QACnC,IAAK,WAAW,QAAQ;AAAA,UACrB,QAAQ,mBACP,OACA,eAAe,MACf,eAAe,cACf,sBACF,GACW,UAAT,QACM,eAAe,YAAY,OAC5B,uBAAuB,gBACvB,yBAAyB,kBAAkB,MAAM,UAAU,GAC3D,yBAAyB,OACzB,WAAW,QACX,WAAW;AAAA,QACpB,YAAY,yBAAyB,cAAc;AAAA,MACrD;AAAA,MACA,gBAAgB,cAAc;AAAA,MAC9B,WAAW,eAAe;AAAA,MAC1B,YAAY,eAAe;AAAA,MAC3B,YAAqB,YAAT,OAAmB,QAAQ,gBAAgB;AAAA,MACvD,QAAQ,UAAU;AAAA,MAClB,qBAAqB,UAAU,SAAS,IACnC,QAAQ,OACA,cAAT,QACA,qBAAqB,UAAU,SAAS,MACvC,eAAe,SAAS;AAAA,MACpB,eAAe,kBAAxB,SACI,WAAW,gBACX,SACA,gBACA,8BACA,MACA,MACA,YACF,GACC,sBAAsB,gBAAgB;AAAA,MACzC,QAAQ,SAAS,cAAc;AAAA,MAC/B,kBAAkB,SAAS,gBAAgB,OAAO,YAAW;AAAA,MAC7D,OAAO,eAAe;AAAA,SACnB;AAAA,MACH,IAAa,YAAT,QAAoB,aAAa;AAAA,QACnC,IAAK,UAAU,eAAc;AAAA,UAC1B,eAAc,uBACb,cACA,eAAe,cACf,sBACF,GACW,iBAAT,QACM,eAAe,YAAY,cAC5B,uBAAuB,gBACvB,yBAAyB,MACzB,UAAU,QACV,UAAU;AAAA,QACnB,WAAW,yBAAyB,cAAc;AAAA,MACpD;AAAA,MACA,OAAO;AAAA,SACJ;AAAA,MACH,OAAO,wBAAwB,SAAS,gBAAgB,YAAW;AAAA,SAChE;AAAA,MACH,OACE,kBACE,gBACA,eAAe,UAAU,aAC3B,GACC,QAAQ,eAAe,cACf,YAAT,OACK,eAAe,QAAQ,qBACtB,gBACA,MACA,OACA,YACF,IACA,kBAAkB,SAAS,gBAAgB,OAAO,YAAW,GACjE,eAAe;AAAA,SAEd;AAAA,MACH,OAAO,iBACL,SACA,gBACA,eAAe,MACf,eAAe,cACf,YACF;AAAA,SACG;AAAA,MACH,OACE,kBACE,SACA,gBACA,eAAe,cACf,YACF,GACA,eAAe;AAAA,SAEd;AAAA,MACH,OACE,kBACE,SACA,gBACA,eAAe,aAAa,UAC5B,YACF,GACA,eAAe;AAAA,SAEd;AAAA,MACH,OACE,kBACE,SACA,gBACA,eAAe,aAAa,UAC5B,YACF,GACA,eAAe;AAAA,SAEd;AAAA,MACH,OACG,QAAQ,eAAe,cACxB,aAAa,gBAAgB,eAAe,MAAM,MAAM,KAAK,GAC7D,kBAAkB,SAAS,gBAAgB,MAAM,UAAU,YAAW,GACtE,eAAe;AAAA,SAEd;AAAA,MACH,OACG,WAAW,eAAe,KAAK,UAC/B,QAAQ,eAAe,aAAa,UACrC,qBAAqB,cAAc,GAClC,WAAW,YAAY,QAAQ,GAC/B,QAAQ,MAAM,QAAQ,GACtB,eAAe,SAAS,GACzB,kBAAkB,SAAS,gBAAgB,OAAO,YAAW,GAC7D,eAAe;AAAA,SAEd;AAAA,MACH,OAAO,oBACL,SACA,gBACA,eAAe,MACf,eAAe,cACf,YACF;AAAA,SACG;AAAA,MACH,OAAO,0BACL,SACA,gBACA,eAAe,MACf,eAAe,cACf,YACF;AAAA,SACG;AAAA,MACH,OAAO,4BAA4B,SAAS,gBAAgB,YAAW;AAAA,SACpE;AAAA,MACH,OAAO,wBAAwB,SAAS,gBAAgB,YAAW;AAAA,SAChE;AAAA,MACH,OAAO,yBACL,SACA,gBACA,cACA,eAAe,YACjB;AAAA,SACG;AAAA,MACH,OACE,qBAAqB,cAAc,GAClC,QAAQ,YAAY,YAAY,GACxB,YAAT,QACM,WAAW,kBAAkB,GACtB,aAAT,SACI,WAAW,oBACZ,YAAY,YAAY,GACxB,SAAS,cAAc,WACxB,UAAU,YACD,cAAT,SAAuB,SAAS,oBAAoB,eACnD,WAAW,YACb,eAAe,gBAAgB,EAAE,QAAQ,OAAO,OAAO,SAAS,GACjE,sBAAsB,cAAc,GACpC,aAAa,gBAAgB,cAAc,QAAQ,OAC3C,QAAQ,QAAQ,kBAAvB,MACE,iBAAiB,SAAS,cAAc,GACzC,mBAAmB,gBAAgB,MAAM,MAAM,YAAW,GAC1D,4CAA4C,IAC7C,WAAW,QAAQ,eACnB,YAAY,eAAe,eAC5B,SAAS,WAAW,SACd,WAAW,EAAE,QAAQ,OAAO,OAAO,MAAM,GAC1C,eAAe,gBAAgB,UAC1B,eAAe,UAArB,MACG,eAAe,gBACd,eAAe,YAAY,YACzB,WACN,aAAa,gBAAgB,cAAc,KAAK,MAC9C,QAAQ,UAAU,OACpB,aAAa,gBAAgB,cAAc,KAAK,GAChD,UAAU,SAAS,SACjB,wBACE,gBACA,CAAC,YAAY,GACb,cACA,IACF,KACV,kBACE,SACA,gBACA,eAAe,aAAa,UAC5B,YACF,GACA,eAAe;AAAA,SAEd;AAAA,MACH,MAAM,eAAe;AAAA;AAAA,EAEzB,MAAM,MAAM,wBAAuB,KAAK,eAAe,GAAG,CAAC;AAAA;AAE7D,SAAS,UAAU,CAAC,gBAAgB;AAAA,EAClC,eAAe,SAAS;AAAA;AAE1B,SAAS,iCAAiC,CACxC,gBACA,MACA,UACA,UACA,cACA;AAAA,EACA,IAAK,QAAc,eAAe,OAAO,QAA7B;AAAA,IAAmC,OAAO;AAAA,EACtD,IAAI,MAAM;AAAA,IACR,IACI,eAAe,SAAS,WACzB,eAAc,eAAe;AAAA,MAE9B,IAAI,eAAe,UAAU;AAAA,QAAU,eAAe,SAAS;AAAA,MAC1D,SAAI,6BAA6B;AAAA,QAAG,eAAe,SAAS;AAAA,MAE/D;AAAA,cACI,oBAAoB,6BACtB;AAAA,EAER,EAAO;AAAA,mBAAe,SAAS;AAAA;AAEjC,SAAS,iCAAiC,CAAC,gBAAgB,UAAU;AAAA,EACnE,IAAqB,SAAS,SAA1B,iBAAyC,SAAS,MAAM,UAAU,OAAhC;AAAA,IACpC,eAAe,SAAS;AAAA,EACrB,SAAM,eAAe,SAAS,UAAW,CAAC,gBAAgB,QAAQ;AAAA,IACrE,IAAI,6BAA6B;AAAA,MAAG,eAAe,SAAS;AAAA,IAE1D;AAAA,YACI,oBAAoB,6BACtB;AAAA;AAGR,SAAS,mBAAmB,CAAC,gBAAgB,YAAY;AAAA,EAC9C,eAAT,SAAwB,eAAe,SAAS;AAAA,EAChD,eAAe,QAAQ,UACnB,aACO,eAAe,QAAtB,KAA4B,mBAAmB,IAAI,WACpD,eAAe,SAAS,YACxB,qCAAqC;AAAA;AAE1C,SAAS,kBAAkB,CAAC,aAAa,0BAA0B;AAAA,EACjE,IAAI,CAAC;AAAA,IACH,QAAQ,YAAY;AAAA,WACb;AAAA,QACH,2BAA2B,YAAY;AAAA,QACvC,SAAS,eAAe,KAAe,6BAAT;AAAA,UACnB,yBAAyB,cAAlC,SACG,eAAe,2BACf,2BAA2B,yBAAyB;AAAA,QAChD,iBAAT,OACK,YAAY,OAAO,OACnB,aAAa,UAAU;AAAA,QAC5B;AAAA,WACG;AAAA,QACH,eAAe,YAAY;AAAA,QAC3B,SAAS,mBAAmB,KAAe,iBAAT;AAAA,UACvB,aAAa,cAAtB,SAAoC,mBAAmB,eACpD,eAAe,aAAa;AAAA,QACxB,qBAAT,OACI,4BAAqC,YAAY,SAArB,OACzB,YAAY,OAAO,OACnB,YAAY,KAAK,UAAU,OAC7B,iBAAiB,UAAU;AAAA;AAAA;AAGxC,SAAS,gBAAgB,CAAC,eAAe;AAAA,EACvC,IAAI,aACS,cAAc,cAAvB,QACA,cAAc,UAAU,UAAU,cAAc,OAClD,gBAAgB,GAChB,eAAe;AAAA,EACjB,IAAI;AAAA,IACF,SAAS,YAAY,cAAc,MAAgB,cAAT;AAAA,MACvC,iBAAiB,UAAU,QAAQ,UAAU,YAC3C,gBAAgB,UAAU,eAAe,UACzC,gBAAgB,UAAU,QAAQ,UAClC,UAAU,SAAS,eACnB,YAAY,UAAU;AAAA,EAE3B;AAAA,SAAK,YAAY,cAAc,MAAgB,cAAT;AAAA,MACnC,iBAAiB,UAAU,QAAQ,UAAU,YAC3C,gBAAgB,UAAU,cAC1B,gBAAgB,UAAU,OAC1B,UAAU,SAAS,eACnB,YAAY,UAAU;AAAA,EAC7B,cAAc,gBAAgB;AAAA,EAC9B,cAAc,aAAa;AAAA,EAC3B,OAAO;AAAA;AAET,SAAS,YAAY,CAAC,SAAS,gBAAgB,cAAa;AAAA,EAC1D,IAAI,WAAW,eAAe;AAAA,EAC9B,eAAe,cAAc;AAAA,EAC7B,QAAQ,eAAe;AAAA,SAChB;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH,OAAO,iBAAiB,cAAc,GAAG;AAAA,SACtC;AAAA,MACH,OAAO,iBAAiB,cAAc,GAAG;AAAA,SACtC;AAAA,MACH,eAAc,eAAe;AAAA,MAC7B,WAAW;AAAA,MACF,YAAT,SAAqB,WAAW,QAAQ,cAAc;AAAA,MACtD,eAAe,cAAc,UAAU,aACpC,eAAe,SAAS;AAAA,MAC3B,YAAY,YAAY;AAAA,MACxB,iBAAiB;AAAA,MACjB,aAAY,mBACR,aAAY,UAAU,aAAY,gBACnC,aAAY,iBAAiB;AAAA,MAChC,IAAa,YAAT,QAA6B,QAAQ,UAAjB;AAAA,QACtB,kBAAkB,cAAc,IAC5B,WAAW,cAAc,IAChB,YAAT,QACC,QAAQ,cAAc,iBACd,eAAe,QAAQ,SAA9B,MACA,eAAe,SAAS,MAC1B,oCAAoC;AAAA,MAC1C,iBAAiB,cAAc;AAAA,MAC/B,OAAO;AAAA,SACJ;AAAA,MACH,MAA0B,MACM,eAA9B,iBAAe;AAAA,MACR,YAAT,QACK,WAAW,cAAc,GACjB,iBAAT,QACK,iBAAiB,cAAc,GAChC,kCAAkC,gBAAgB,YAAY,MAC7D,iBAAiB,cAAc,GAChC,kCACE,gBACA,MACA,MACA,UACA,YACF,MACJ,eACE,iBAAiB,QAAQ,iBACtB,WAAW,cAAc,GAC1B,iBAAiB,cAAc,GAC/B,kCAAkC,gBAAgB,YAAY,MAC7D,iBAAiB,cAAc,GAC/B,eAAe,SAAS,cACzB,UAAU,QAAQ,eACpB,YAAY,YAAY,WAAW,cAAc,GACjD,iBAAiB,cAAc,GAC/B,kCACE,gBACA,MACA,SACA,UACA,YACF;AAAA,MACN,OAAO;AAAA,SACJ;AAAA,MACH,eAAe,cAAc;AAAA,MAC7B,eAAc,wBAAwB;AAAA,MACtC,OAAO,eAAe;AAAA,MACtB,IAAa,YAAT,QAA4B,eAAe,aAAvB;AAAA,QACtB,QAAQ,kBAAkB,YAAY,WAAW,cAAc;AAAA,MAC5D;AAAA,QACH,IAAI,CAAC,UAAU;AAAA,UACb,IAAa,eAAe,cAAxB;AAAA,YACF,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,UACzC,iBAAiB,cAAc;AAAA,UAC/B,OAAO;AAAA,QACT;AAAA,QACA,UAAU,mBAAmB;AAAA,QAC7B,kBAAkB,cAAc,IAC5B,6BAA6B,gBAAgB,OAAO,KAClD,UAAU,yBAAyB,MAAM,UAAU,YAAW,GAC/D,eAAe,YAAY,SAC5B,WAAW,cAAc;AAAA;AAAA,MAE/B,iBAAiB,cAAc;AAAA,MAC/B,OAAO;AAAA,SACJ;AAAA,MACH,eAAe,cAAc;AAAA,MAC7B,OAAO,eAAe;AAAA,MACtB,IAAa,YAAT,QAA4B,eAAe,aAAvB;AAAA,QACtB,QAAQ,kBAAkB,YAAY,WAAW,cAAc;AAAA,MAC5D;AAAA,QACH,IAAI,CAAC,UAAU;AAAA,UACb,IAAa,eAAe,cAAxB;AAAA,YACF,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,UACzC,iBAAiB,cAAc;AAAA,UAC/B,OAAO;AAAA,QACT;AAAA,QACA,eAAe,mBAAmB;AAAA,QAClC,IAAI,kBAAkB,cAAc;AAAA,UAClC,6BAA6B,gBAAgB,YAAY;AAAA,QACtD;AAAA,UACH,IAAI,gBAAgB,kCAClB,wBAAwB,OAC1B;AAAA,UACA,QAAQ;AAAA,iBACD;AAAA,cACH,eAAe,cAAc,gBAC3B,8BACA,IACF;AAAA,cACA;AAAA,iBACG;AAAA,cACH,eAAe,cAAc,gBAC3B,sCACA,IACF;AAAA,cACA;AAAA;AAAA,cAEA,QAAQ;AAAA,qBACD;AAAA,kBACH,eAAe,cAAc,gBAC3B,8BACA,IACF;AAAA,kBACA;AAAA,qBACG;AAAA,kBACH,eAAe,cAAc,gBAC3B,sCACA,IACF;AAAA,kBACA;AAAA,qBACG;AAAA,kBACH,eAAe,cAAc,cAAc,KAAK;AAAA,kBAChD,aAAa,YAAY;AAAA,kBACzB,eAAe,aAAa,YAC1B,aAAa,UACf;AAAA,kBACA;AAAA,qBACG;AAAA,kBACH,eACe,OAAO,SAAS,OAA7B,WACI,cAAc,cAAc,UAAU;AAAA,oBACpC,IAAI,SAAS;AAAA,kBACf,CAAC,IACD,cAAc,cAAc,QAAQ;AAAA,kBAC1C,SAAS,WACJ,aAAa,WAAW,OACzB,SAAS,SAAS,aAAa,OAAO,SAAS;AAAA,kBACnD;AAAA;AAAA,kBAEA,eACe,OAAO,SAAS,OAA7B,WACI,cAAc,cAAc,MAAM,EAAE,IAAI,SAAS,GAAG,CAAC,IACrD,cAAc,cAAc,IAAI;AAAA;AAAA;AAAA,UAG9C,aAAa,uBAAuB;AAAA,UACpC,aAAa,oBAAoB;AAAA,UACjC;AAAA,YAAG,KACD,gBAAgB,eAAe,MACtB,kBAAT,QAEA;AAAA,cACA,IAAU,cAAc,QAApB,KAAiC,cAAc,QAApB;AAAA,gBAC7B,aAAa,YAAY,cAAc,SAAS;AAAA,cAC7C,SACG,cAAc,QAApB,KACO,cAAc,QAArB,MACS,cAAc,UAAvB,MACA;AAAA,gBACA,cAAc,MAAM,SAAS;AAAA,gBAC7B,gBAAgB,cAAc;AAAA,gBAC9B;AAAA,cACF;AAAA,cACA,IAAI,kBAAkB;AAAA,gBAAgB;AAAA,cACtC,MAAgB,cAAc,YAAvB,QAAkC;AAAA,gBACvC,IACW,cAAc,WAAvB,QACA,cAAc,WAAW;AAAA,kBAEzB;AAAA,gBACF,gBAAgB,cAAc;AAAA,cAChC;AAAA,cACA,cAAc,QAAQ,SAAS,cAAc;AAAA,cAC7C,gBAAgB,cAAc;AAAA,YAChC;AAAA,UACA,eAAe,YAAY;AAAA,UAC3B;AAAA,YAAG,QACA,qBAAqB,cAAc,MAAM,QAAQ,GAAG;AAAA,mBAEhD;AAAA,mBACA;AAAA,mBACA;AAAA,mBACA;AAAA,gBACH,WAAW,CAAC,CAAC,SAAS;AAAA,gBACtB;AAAA,mBACG;AAAA,gBACH,WAAW;AAAA,gBACX;AAAA;AAAA,gBAEA,WAAW;AAAA;AAAA,UAEf,YAAY,WAAW,cAAc;AAAA;AAAA;AAAA,MAGzC,iBAAiB,cAAc;AAAA,MAC/B,kCACE,gBACA,eAAe,MACN,YAAT,OAAmB,OAAO,QAAQ,eAClC,eAAe,cACf,YACF;AAAA,MACA,OAAO;AAAA,SACJ;AAAA,MACH,IAAI,WAAmB,eAAe,aAAvB;AAAA,QACb,QAAQ,kBAAkB,YAAY,WAAW,cAAc;AAAA,MAC5D;AAAA,QACH,IAAiB,OAAO,aAApB,YAAyC,eAAe,cAAxB;AAAA,UAClC,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,QACzC,UAAU,wBAAwB;AAAA,QAClC,IAAI,kBAAkB,cAAc,GAAG;AAAA,UACrC,UAAU,eAAe;AAAA,UACzB,eAAc,eAAe;AAAA,UAC7B,WAAW;AAAA,UACX,OAAO;AAAA,UACP,IAAa,SAAT;AAAA,YACF,QAAQ,KAAK;AAAA,mBACN;AAAA,mBACA;AAAA,gBACH,WAAW,KAAK;AAAA;AAAA,UAEtB,QAAQ,uBAAuB;AAAA,UAC/B,UACE,QAAQ,cAAc,gBACZ,aAAT,QAA4B,SAAS,6BAAhB,QACtB,sBAAsB,QAAQ,WAAW,YAAW,IAChD,OACA;AAAA,UACN,WAAW,yBAAyB,gBAAgB,IAAE;AAAA,QACxD,EACE;AAAA,UAAC,UACC,kCAAkC,OAAO,EAAE,eACzC,QACF,GACC,QAAQ,uBAAuB,gBAC/B,eAAe,YAAY;AAAA;AAAA,MAElC,iBAAiB,cAAc;AAAA,MAC/B,OAAO;AAAA,SACJ;AAAA,MACH,eAAc,eAAe;AAAA,MAC7B,IAAa,YAAT,QAA6B,QAAQ,kBAAjB,MAAgC;AAAA,QACtD,WAAW,kBAAkB,cAAc;AAAA,QAC3C,IAAa,iBAAT,MAAsB;AAAA,UACxB,IAAa,YAAT,MAAkB;AAAA,YACpB,IAAI,CAAC;AAAA,cAAU,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,YACtD,UAAU,eAAe;AAAA,YACzB,UAAmB,YAAT,OAAmB,QAAQ,aAAa;AAAA,YAClD,IAAI,CAAC;AAAA,cAAS,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,YACrD,QAAQ,uBAAuB;AAAA,UACjC,EACE;AAAA,gCAAoB,IACX,eAAe,QAAQ,SAA9B,MACG,eAAe,gBAAgB,OACjC,eAAe,SAAS;AAAA,UAC7B,iBAAiB,cAAc;AAAA,UAC/B,UAAU;AAAA,QACZ,EACE;AAAA,UAAC,eAAc,oCAAoC,GACxC,YAAT,QACW,QAAQ,kBAAjB,SACC,QAAQ,cAAc,kBAAkB,eAC1C,UAAU;AAAA,QACf,IAAI,CAAC,SAAS;AAAA,UACZ,IAAI,eAAe,QAAQ;AAAA,YACzB,OAAO,mBAAmB,cAAc,GAAG;AAAA,UAC7C,mBAAmB,cAAc;AAAA,UACjC,OAAO;AAAA,QACT;AAAA,QACA,KAAW,eAAe,QAAQ,SAA9B;AAAA,UACF,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,MAC3C;AAAA,MACA,iBAAiB,cAAc;AAAA,MAC/B,OAAO;AAAA,SACJ;AAAA,MACH,WAAW,eAAe;AAAA,MAC1B,IACW,YAAT,QACU,QAAQ,kBAAjB,QACU,QAAQ,cAAc,eAA/B,MACF;AAAA,QACA,OAAO,kBAAkB,cAAc;AAAA,QACvC,IAAa,aAAT,QAA8B,SAAS,eAAlB,MAA8B;AAAA,UACrD,IAAa,YAAT,MAAkB;AAAA,YACpB,IAAI,CAAC;AAAA,cAAM,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,YAClD,OAAO,eAAe;AAAA,YACtB,OAAgB,SAAT,OAAgB,KAAK,aAAa;AAAA,YACzC,IAAI,CAAC;AAAA,cAAM,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,YAClD,KAAK,uBAAuB;AAAA,UAC9B,EACE;AAAA,gCAAoB,IACX,eAAe,QAAQ,SAA9B,MACG,eAAe,gBAAgB,OACjC,eAAe,SAAS;AAAA,UAC7B,iBAAiB,cAAc;AAAA,UAC/B,OAAO;AAAA,QACT,EACE;AAAA,UAAC,OAAO,oCAAoC,GACjC,YAAT,QACW,QAAQ,kBAAjB,SACC,QAAQ,cAAc,kBAAkB,OAC1C,OAAO;AAAA,QACZ,IAAI,CAAC,MAAM;AAAA,UACT,IAAI,eAAe,QAAQ;AAAA,YACzB,OAAO,mBAAmB,cAAc,GAAG;AAAA,UAC7C,mBAAmB,cAAc;AAAA,UACjC,OAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA,mBAAmB,cAAc;AAAA,MACjC,KAAW,eAAe,QAAQ,SAA9B;AAAA,QACF,OAAQ,eAAe,QAAQ,cAAc;AAAA,MAC/C,eAAuB,aAAT;AAAA,MACd,UAAmB,YAAT,QAA6B,QAAQ,kBAAjB;AAAA,MAC9B,iBACI,WAAW,eAAe,OAC3B,OAAO,MACC,SAAS,cAAlB,QACW,SAAS,UAAU,kBAA5B,QACS,SAAS,UAAU,cAAc,cAA1C,SACC,OAAO,SAAS,UAAU,cAAc,UAAU,OACpD,eAAe,MACP,SAAS,kBAAlB,QACW,SAAS,cAAc,cAAhC,SACC,eAAe,SAAS,cAAc,UAAU,OACnD,iBAAiB,SAAS,SAAS,SAAS;AAAA,MAC9C,iBAAgB,WACd,iBACC,eAAe,MAAM,SAAS;AAAA,MACjC,oBAAoB,gBAAgB,eAAe,WAAW;AAAA,MAC9D,iBAAiB,cAAc;AAAA,MAC/B,OAAO;AAAA,SACJ;AAAA,MACH,OACE,iBAAiB,GACR,YAAT,QACE,2BAA2B,eAAe,UAAU,aAAa,GACnE,iBAAiB,cAAc,GAC/B;AAAA,SAEC;AAAA,MACH,OACE,YAAY,eAAe,IAAI,GAAG,iBAAiB,cAAc,GAAG;AAAA,SAEnE;AAAA,MACH,KAAI,mBAAmB;AAAA,MACvB,WAAW,eAAe;AAAA,MAC1B,IAAa,aAAT;AAAA,QAAmB,OAAO,iBAAiB,cAAc,GAAG;AAAA,MAChE,QAAc,eAAe,QAAQ,SAA9B;AAAA,MACP,eAAe,SAAS;AAAA,MACxB,IAAa,iBAAT;AAAA,QACF,IAAI;AAAA,UAAM,mBAAmB,UAAU,KAAE;AAAA,QACpC;AAAA,UACH,IACQ,iCAAN,KACU,YAAT,SAA2B,QAAQ,QAAQ,SAAvB;AAAA,YAErB,KAAK,UAAU,eAAe,MAAgB,YAAT,QAAoB;AAAA,cACvD,eAAe,mBAAmB,OAAO;AAAA,cACzC,IAAa,iBAAT,MAAuB;AAAA,gBACzB,eAAe,SAAS;AAAA,gBACxB,mBAAmB,UAAU,KAAE;AAAA,gBAC/B,UAAU,aAAa;AAAA,gBACvB,eAAe,cAAc;AAAA,gBAC7B,oBAAoB,gBAAgB,OAAO;AAAA,gBAC3C,eAAe,eAAe;AAAA,gBAC9B,UAAU;AAAA,gBACV,KAAK,eAAc,eAAe,MAAgB,iBAAT;AAAA,kBACvC,oBAAoB,cAAa,OAAO,GACrC,eAAc,aAAY;AAAA,gBAC/B,MACE,qBACC,oBAAoB,UAAU,IAAK,CACtC;AAAA,gBACA,eACE,aAAa,gBAAgB,SAAS,aAAa;AAAA,gBACrD,OAAO,eAAe;AAAA,cACxB;AAAA,cACA,UAAU,QAAQ;AAAA,YACpB;AAAA,UACO,SAAS,SAAlB,QACE,IAAI,IAAI,uCACN,eAAe,SAAS,KACzB,OAAO,MACR,mBAAmB,UAAU,KAAE,GAC9B,eAAe,QAAQ;AAAA;AAAA,MAEzB;AAAA,QACH,IAAI,CAAC;AAAA,UACH,IACI,UAAU,mBAAmB,YAAY,GAAa,YAAT,MAC/C;AAAA,YACA,IACI,eAAe,SAAS,KACzB,OAAO,MACP,UAAU,QAAQ,aAClB,eAAe,cAAc,SAC9B,oBAAoB,gBAAgB,OAAO,GAC3C,mBAAmB,UAAU,IAAE,GACtB,SAAS,SAAlB,QACe,SAAS,aAAtB,YACA,CAAC,aAAa,aACd,CAAC;AAAA,cAEH,OAAO,iBAAiB,cAAc,GAAG;AAAA,UAC7C,EACE;AAAA,gBAAI,IAAI,IAAI,SAAS,qBACnB,sCACc,iBAAd,cACE,eAAe,SAAS,KACzB,OAAO,MACR,mBAAmB,UAAU,KAAE,GAC9B,eAAe,QAAQ;AAAA,QAC9B,SAAS,eACH,aAAa,UAAU,eAAe,OACvC,eAAe,QAAQ,iBACtB,UAAU,SAAS,MACZ,YAAT,OACK,QAAQ,UAAU,eAClB,eAAe,QAAQ,cAC3B,SAAS,OAAO;AAAA;AAAA,MAEvB,IAAa,SAAS,SAAlB;AAAA,QACF,OACG,UAAU,SAAS,MACnB,SAAS,YAAY,SACrB,SAAS,OAAO,QAAQ,SACxB,SAAS,qBAAqB,IAAI,GAClC,QAAQ,UAAU,MAClB,eAAc,oBAAoB,SACnC,MACE,qBACA,OAAQ,eAAc,IAAK,IAAI,eAAc,CAC/C,GACA,eAAe,aAAa,gBAAgB,SAAS,aAAa,GAClE;AAAA,MAEJ,iBAAiB,cAAc;AAAA,MAC/B,OAAO;AAAA,SACJ;AAAA,SACA;AAAA,MACH,OACE,mBAAmB,cAAc,GACjC,iBAAiB,GAChB,WAAoB,eAAe,kBAAxB,MACH,YAAT,OACc,QAAQ,kBAAjB,SAAoC,aACpC,eAAe,SAAS,QACzB,aAAa,eAAe,SAAS,OACzC,YACW,eAAc,eAArB,MACO,eAAe,QAAQ,SAA9B,MACC,iBAAiB,cAAc,GAChC,eAAe,eAAe,MAAM,eAAe,SAAS,SAC5D,iBAAiB,cAAc,GAClC,eAAc,eAAe,aACrB,iBAAT,QACE,oBAAoB,gBAAgB,aAAY,UAAU,GAC3D,eAAc,MACN,YAAT,QACW,QAAQ,kBAAjB,QACS,QAAQ,cAAc,cAA/B,SACC,eAAc,QAAQ,cAAc,UAAU,OAChD,WAAW,MACH,eAAe,kBAAxB,QACW,eAAe,cAAc,cAAtC,SACC,WAAW,eAAe,cAAc,UAAU,OACrD,aAAa,iBAAgB,eAAe,SAAS,OAC5C,YAAT,QAAoB,KAAI,YAAY,GACpC;AAAA,SAEC;AAAA,MACH,OACG,eAAc,MACN,YAAT,SAAqB,eAAc,QAAQ,cAAc,QACzD,eAAe,cAAc,UAAU,iBACpC,eAAe,SAAS,OAC3B,YAAY,YAAY,GACxB,iBAAiB,cAAc,GAC/B;AAAA,SAEC;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA;AAAA,EAEX,MAAM,MAAM,wBAAuB,KAAK,eAAe,GAAG,CAAC;AAAA;AAE7D,SAAS,UAAU,CAAC,SAAS,gBAAgB;AAAA,EAC3C,eAAe,cAAc;AAAA,EAC7B,QAAQ,eAAe;AAAA,SAChB;AAAA,MACH,OACG,UAAU,eAAe,OAC1B,UAAU,SACJ,eAAe,QAAS,UAAU,SAAU,KAAM,kBACpD;AAAA,SAEH;AAAA,MACH,OACE,YAAY,YAAY,GACxB,iBAAiB,GAChB,UAAU,eAAe,QACnB,UAAU,WAAjB,MAAkC,UAAU,SAAjB,KACrB,eAAe,QAAS,UAAU,SAAU,KAAM,kBACpD;AAAA,SAEH;AAAA,SACA;AAAA,SACA;AAAA,MACH,OAAO,eAAe,cAAc,GAAG;AAAA,SACpC;AAAA,MACH,IAAa,eAAe,kBAAxB,MAAuC;AAAA,QACzC,mBAAmB,cAAc;AAAA,QACjC,IAAa,eAAe,cAAxB;AAAA,UACF,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,QACzC,oBAAoB;AAAA,MACtB;AAAA,MACA,UAAU,eAAe;AAAA,MACzB,OAAO,UAAU,SACX,eAAe,QAAS,UAAU,SAAU,KAAM,kBACpD;AAAA,SACD;AAAA,MACH,mBAAmB,cAAc;AAAA,MACjC,UAAU,eAAe;AAAA,MACzB,IAAa,YAAT,QAA6B,QAAQ,eAAjB,MAA6B;AAAA,QACnD,IAAa,eAAe,cAAxB;AAAA,UACF,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,QACzC,oBAAoB;AAAA,MACtB;AAAA,MACA,UAAU,eAAe;AAAA,MACzB,OAAO,UAAU,SACX,eAAe,QAAS,UAAU,SAAU,KAAM,kBACpD;AAAA,SACD;AAAA,MACH,OAAO,KAAI,mBAAmB,GAAG;AAAA,SAC9B;AAAA,MACH,OAAO,iBAAiB,GAAG;AAAA,SACxB;AAAA,MACH,OAAO,YAAY,eAAe,IAAI,GAAG;AAAA,SACtC;AAAA,SACA;AAAA,MACH,OACE,mBAAmB,cAAc,GACjC,iBAAiB,GACR,YAAT,QAAoB,KAAI,YAAY,GACnC,UAAU,eAAe,OAC1B,UAAU,SACJ,eAAe,QAAS,UAAU,SAAU,KAAM,kBACpD;AAAA,SAEH;AAAA,MACH,OAAO,YAAY,YAAY,GAAG;AAAA,SAC/B;AAAA,MACH,OAAO;AAAA;AAAA,MAEP,OAAO;AAAA;AAAA;AAGb,SAAS,qBAAqB,CAAC,SAAS,iBAAiB;AAAA,EACvD,eAAe,eAAe;AAAA,EAC9B,QAAQ,gBAAgB;AAAA,SACjB;AAAA,MACH,YAAY,YAAY;AAAA,MACxB,iBAAiB;AAAA,MACjB;AAAA,SACG;AAAA,SACA;AAAA,SACA;AAAA,MACH,eAAe,eAAe;AAAA,MAC9B;AAAA,SACG;AAAA,MACH,iBAAiB;AAAA,MACjB;AAAA,SACG;AAAA,MACM,gBAAgB,kBAAzB,QACE,mBAAmB,eAAe;AAAA,MACpC;AAAA,SACG;AAAA,MACH,mBAAmB,eAAe;AAAA,MAClC;AAAA,SACG;AAAA,MACH,KAAI,mBAAmB;AAAA,MACvB;AAAA,SACG;AAAA,MACH,YAAY,gBAAgB,IAAI;AAAA,MAChC;AAAA,SACG;AAAA,SACA;AAAA,MACH,mBAAmB,eAAe;AAAA,MAClC,iBAAiB;AAAA,MACR,YAAT,QAAoB,KAAI,YAAY;AAAA,MACpC;AAAA,SACG;AAAA,MACH,YAAY,YAAY;AAAA;AAAA;AAG9B,SAAS,yBAAyB,CAAC,OAAO,cAAc;AAAA,EACtD,IAAI;AAAA,IACF,IAAI,cAAc,aAAa,aAC7B,aAAsB,gBAAT,OAAuB,YAAY,aAAa;AAAA,IAC/D,IAAa,eAAT,MAAqB;AAAA,MACvB,IAAI,cAAc,WAAW;AAAA,MAC7B,cAAc;AAAA,MACd,GAAG;AAAA,QACD,KAAK,YAAY,MAAM,WAAW,OAAO;AAAA,UACvC,aAAkB;AAAA,UAClB,MAAyB,QACJ,SAAZ;AAAA,UACT,aAAa,OAAO;AAAA,UACpB,KAAK,UAAU;AAAA,QACjB;AAAA,QACA,cAAc,YAAY;AAAA,MAC5B,SAAS,gBAAgB;AAAA,IAC3B;AAAA,IACA,OAAO,OAAO;AAAA,IACd,wBAAwB,cAAc,aAAa,QAAQ,KAAK;AAAA;AAAA;AAGpE,SAAS,2BAA2B,CAClC,OACA,cACA,iCACA;AAAA,EACA,IAAI;AAAA,IACF,IAAI,cAAc,aAAa,aAC7B,aAAsB,gBAAT,OAAuB,YAAY,aAAa;AAAA,IAC/D,IAAa,eAAT,MAAqB;AAAA,MACvB,IAAI,cAAc,WAAW;AAAA,MAC7B,cAAc;AAAA,MACd,GAAG;AAAA,QACD,KAAK,YAAY,MAAM,WAAW,OAAO;AAAA,UACvC,IAAI,OAAO,YAAY,MACrB,UAAU,KAAK;AAAA,UACjB,IAAe,YAAN,WAAe;AAAA,YACtB,KAAK,UAAe;AAAA,YACpB,aAAa;AAAA,YACb,IAAI,yBAAyB,iCAC3B,WAAW;AAAA,YACb,IAAI;AAAA,cACF,SAAS;AAAA,cACT,OAAO,OAAO;AAAA,cACd,wBACE,YACA,wBACA,KACF;AAAA;AAAA,UAEJ;AAAA,QACF;AAAA,QACA,cAAc,YAAY;AAAA,MAC5B,SAAS,gBAAgB;AAAA,IAC3B;AAAA,IACA,OAAO,OAAO;AAAA,IACd,wBAAwB,cAAc,aAAa,QAAQ,KAAK;AAAA;AAAA;AAGpE,SAAS,oBAAoB,CAAC,cAAc;AAAA,EAC1C,IAAI,cAAc,aAAa;AAAA,EAC/B,IAAa,gBAAT,MAAsB;AAAA,IACxB,IAAI,WAAW,aAAa;AAAA,IAC5B,IAAI;AAAA,MACF,gBAAgB,aAAa,QAAQ;AAAA,MACrC,OAAO,OAAO;AAAA,MACd,wBAAwB,cAAc,aAAa,QAAQ,KAAK;AAAA;AAAA,EAEpE;AAAA;AAEF,SAAS,8BAA8B,CACrC,SACA,wBACA,UACA;AAAA,EACA,SAAS,QAAQ,2BACf,QAAQ,MACR,QAAQ,aACV;AAAA,EACA,SAAS,QAAQ,QAAQ;AAAA,EACzB,IAAI;AAAA,IACF,SAAS,qBAAqB;AAAA,IAC9B,OAAO,OAAO;AAAA,IACd,wBAAwB,SAAS,wBAAwB,KAAK;AAAA;AAAA;AAGlE,SAAS,eAAe,CAAC,SAAS,wBAAwB;AAAA,EACxD,IAAI;AAAA,IACF,IAAI,MAAM,QAAQ;AAAA,IAClB,IAAa,QAAT,MAAc;AAAA,MAChB,QAAQ,QAAQ;AAAA,aACT;AAAA,aACA;AAAA,aACA;AAAA,UACH,IAAI,gBAAgB,QAAQ;AAAA,UAC5B;AAAA,aACG;AAAA,UACH,gBAAgB,QAAQ;AAAA,UACxB;AAAA;AAAA,UAEA,gBAAgB,QAAQ;AAAA;AAAA,MAEb,OAAO,QAAtB,aACK,QAAQ,aAAa,IAAI,aAAa,IACtC,IAAI,UAAU;AAAA,IACrB;AAAA,IACA,OAAO,OAAO;AAAA,IACd,wBAAwB,SAAS,wBAAwB,KAAK;AAAA;AAAA;AAGlE,SAAS,eAAe,CAAC,SAAS,wBAAwB;AAAA,EACxD,MAAkB,KACK,eAAR;AAAA,EACf,IAAa,QAAT;AAAA,IACF,IAAmB,OAAO,eAAtB;AAAA,MACF,IAAI;AAAA,QACF,WAAW;AAAA,QACX,OAAO,OAAO;AAAA,QACd,wBAAwB,SAAS,wBAAwB,KAAK;AAAA,gBAC9D;AAAA,QACC,QAAQ,aAAa,MACnB,UAAU,QAAQ,WACX,WAAR,SAAoB,QAAQ,aAAa;AAAA;AAAA,IAE1C,SAAmB,OAAO,QAAtB;AAAA,MACP,IAAI;AAAA,QACF,IAAI,IAAI;AAAA,QACR,OAAO,WAAW;AAAA,QAClB,wBAAwB,SAAS,wBAAwB,SAAS;AAAA;AAAA,IAEjE;AAAA,UAAI,UAAU;AAAA;AAEvB,SAAS,eAAe,CAAC,cAAc;AAAA,EACrC,MAAwB,MACD,eAArB,OACwB,WAAxB,aADQ;AAAA,EAEV,IAAI;AAAA,IACF;AAAA,MAAG,QAAQ;AAAA,aACJ;AAAA,aACA;AAAA,aACA;AAAA,aACA;AAAA,UACH,MAAM,aAAa,SAAS,MAAM;AAAA,UAClC;AAAA,aACG;AAAA,UACH,MAAM,MACD,SAAS,MAAM,MAAM,MACtB,MAAM,WAAW,SAAS,SAAS,MAAM;AAAA;AAAA,IAEjD,OAAO,OAAO;AAAA,IACd,wBAAwB,cAAc,aAAa,QAAQ,KAAK;AAAA;AAAA;AAGpE,SAAS,gBAAgB,CAAC,cAAc,UAAU,UAAU;AAAA,EAC1D,IAAI;AAAA,IACF,IAAI,aAAa,aAAa;AAAA,IAC9B,iBAAiB,YAAY,aAAa,MAAM,UAAU,QAAQ;AAAA,IAClE,WAAW,oBAAoB;AAAA,IAC/B,OAAO,OAAO;AAAA,IACd,wBAAwB,cAAc,aAAa,QAAQ,KAAK;AAAA;AAAA;AAGpE,SAAS,YAAY,CAAC,OAAO;AAAA,EAC3B,OACQ,MAAM,QAAZ,KACM,MAAM,QAAZ,KACO,MAAM,QAAb,MACQ,MAAM,QAAb,MAAoB,iBAAiB,MAAM,IAAI,KAC1C,MAAM,QAAZ;AAAA;AAGJ,SAAS,cAAc,CAAC,OAAO;AAAA,EAC7B;AAAA,IAAG,UAAS;AAAA,MACV,MAAgB,MAAM,YAAf,QAA0B;AAAA,QAC/B,IAAa,MAAM,WAAf,QAAyB,aAAa,MAAM,MAAM;AAAA,UAAG,OAAO;AAAA,QAChE,QAAQ,MAAM;AAAA,MAChB;AAAA,MACA,MAAM,QAAQ,SAAS,MAAM;AAAA,MAC7B,KACE,QAAQ,MAAM,QACR,MAAM,QAAZ,KAAyB,MAAM,QAAZ,KAA0B,MAAM,QAAb,MAEtC;AAAA,QACA,IAAW,MAAM,QAAb,MAAoB,iBAAiB,MAAM,IAAI;AAAA,UAAG;AAAA,QACtD,IAAI,MAAM,QAAQ;AAAA,UAAG;AAAA,QACrB,IAAa,MAAM,UAAf,QAA8B,MAAM,QAAZ;AAAA,UAAiB;AAAA,QACxC;AAAA,UAAC,MAAM,MAAM,SAAS,OAAS,QAAQ,MAAM;AAAA,MACpD;AAAA,MACA,IAAI,EAAE,MAAM,QAAQ;AAAA,QAAI,OAAO,MAAM;AAAA,IACvC;AAAA;AAEF,SAAS,wCAAwC,CAAC,MAAM,QAAQ,QAAQ;AAAA,EACtE,IAAI,MAAM,KAAK;AAAA,EACf,IAAU,QAAN,KAAmB,QAAN;AAAA,IACd,OAAO,KAAK,WACX,UACW,OAAO,aAAb,IACG,OAAO,OACI,OAAO,aAAlB,SACE,OAAO,cAAc,OACrB,QACJ,aAAa,MAAM,MAAM,KACzB,SACM,OAAO,aAAb,IACI,OAAO,OACI,OAAO,aAAlB,SACE,OAAO,cAAc,OACrB,QACR,OAAO,YAAY,IAAI,GACtB,SAAS,OAAO,qBACP,WAAT,QAA8B,WAAN,aACd,OAAO,YAAhB,SACC,OAAO,UAAU;AAAA,EACvB,SACG,QAAN,MACQ,QAAP,MACC,iBAAiB,KAAK,IAAI,MACxB,SAAS,KAAK,WAAa,SAAS,OACvC,OAAO,KAAK,OACJ,SAAT;AAAA,IAEA,KACE,yCAAyC,MAAM,QAAQ,MAAM,GAC3D,OAAO,KAAK,QACL,SAAT;AAAA,MAGA,yCAAyC,MAAM,QAAQ,MAAM,GAC1D,OAAO,KAAK;AAAA;AAErB,SAAS,2BAA2B,CAAC,MAAM,QAAQ,QAAQ;AAAA,EACzD,IAAI,MAAM,KAAK;AAAA,EACf,IAAU,QAAN,KAAmB,QAAN;AAAA,IACd,OAAO,KAAK,WACX,SAAS,OAAO,aAAa,MAAM,MAAM,IAAI,OAAO,YAAY,IAAI;AAAA,EACnE,SACG,QAAN,MACQ,QAAP,MAAc,iBAAiB,KAAK,IAAI,MAAM,SAAS,KAAK,YAC5D,OAAO,KAAK,OACJ,SAAT;AAAA,IAEA,KACE,4BAA4B,MAAM,QAAQ,MAAM,GAAG,OAAO,KAAK,QACtD,SAAT;AAAA,MAGA,4BAA4B,MAAM,QAAQ,MAAM,GAAI,OAAO,KAAK;AAAA;AAEtE,SAAS,8BAA8B,CAAC,cAAc;AAAA,EACpD,MAA6B,WAAzB,WACmB,eAArB,UAAQ;AAAA,EACV,IAAI;AAAA,IACF,SACM,OAAO,aAAa,MAAM,aAAa,UAAU,WACrD,WAAW;AAAA,MAGX,UAAU,oBAAoB,WAAW,EAAE;AAAA,IAC7C,qBAAqB,WAAW,MAAM,KAAK;AAAA,IAC3C,UAAU,uBAAuB;AAAA,IACjC,UAAU,oBAAoB;AAAA,IAC9B,OAAO,OAAO;AAAA,IACd,wBAAwB,cAAc,aAAa,QAAQ,KAAK;AAAA;AAAA;AAQpE,SAAS,2BAA2B,CAAC,OAAM,YAAY;AAAA,EACrD,QAAO,MAAK;AAAA,EACZ,gBAAgB;AAAA,EAChB,QAAO,qBAAqB,KAAI;AAAA,EAChC,IAAI,yBAAyB,KAAI,GAAG;AAAA,IAClC,IAAI,oBAAoB;AAAA,MACtB,IAAI,kBAAkB;AAAA,QACpB,OAAO,MAAK;AAAA,QACZ,KAAK,MAAK;AAAA,MACZ;AAAA,IAEA;AAAA,SAAG;AAAA,QACD,mBACI,kBAAkB,MAAK,kBACvB,gBAAgB,eAClB;AAAA,QACF,IAAI,YACF,gBAAgB,gBAAgB,gBAAgB,aAAa;AAAA,QAC/D,IAAI,aAAmB,UAAU,eAAhB,GAA4B;AAAA,UAC3C,kBAAkB,UAAU;AAAA,UAC5B,MAA6B,cACL,cAAV;AAAA,UACd,YAAY,UAAU;AAAA,UACtB,IAAI;AAAA,YACF,gBAAgB,UAAU,UAAU;AAAA,YACpC,OAAO,MAAM;AAAA,YACb,kBAAkB;AAAA,YAClB;AAAA;AAAA,UAEF,IAAI,SAAS,GACX,QAAQ,IACR,MAAM,IACN,oBAAoB,GACpB,mBAAmB,GACnB,OAAO,OACP,aAAa;AAAA,UACf;AAAA,YAAG,UAAS;AAAA,cACV,SAAS,SAAU;AAAA,gBACjB,SAAS,mBACA,iBAAN,KAA4B,KAAK,aAAX,MACtB,QAAQ,SAAS;AAAA,gBACpB,SAAS,aACA,cAAN,KAAyB,KAAK,aAAX,MACnB,MAAM,SAAS;AAAA,gBACZ,KAAK,aAAX,MAAwB,UAAU,KAAK,UAAU;AAAA,gBACjD,KAAc,OAAO,KAAK,gBAAtB;AAAA,kBAAmC;AAAA,gBACvC,aAAa;AAAA,gBACb,OAAO;AAAA,cACT;AAAA,cACA,UAAS;AAAA,gBACP,IAAI,SAAS;AAAA,kBAAM;AAAA,gBACnB,eAAe,mBACb,EAAE,sBAAsB,iBACvB,QAAQ;AAAA,gBACX,eAAe,aACb,EAAE,qBAAqB,cACtB,MAAM;AAAA,gBACT,KAAc,OAAO,KAAK,iBAAtB;AAAA,kBAAoC;AAAA,gBACxC,OAAO;AAAA,gBACP,aAAa,KAAK;AAAA,cACpB;AAAA,cACA,OAAO;AAAA,YACT;AAAA,UACA,kBACS,UAAP,MAAuB,QAAP,KAAa,OAAO,EAAE,OAAc,IAAS;AAAA,QACjE,EAAO;AAAA,4BAAkB;AAAA,MAC3B;AAAA,IACF,kBAAkB,mBAAmB,EAAE,OAAO,GAAG,KAAK,EAAE;AAAA,EAC1D,EAAO;AAAA,sBAAkB;AAAA,EACzB,uBAAuB,EAAE,aAAa,OAAM,gBAAgB,gBAAgB;AAAA,EAC5E,WAAW;AAAA,EACX,KAAK,aAAa,WAAqB,eAAT;AAAA,IAC5B,IACI,aAAa,YACd,QAAO,WAAW,QACZ,WAAW,eAAe,UAAjC,KAAmD,UAAT;AAAA,MAEzC,MAAK,SAAS,YAAc,aAAa;AAAA,IAE1C;AAAA,YAAgB,eAAT,QAAuB;AAAA,QAC5B,aAAa;AAAA,QACb,YAAY,WAAW;AAAA,QACvB,QAAO,WAAW;AAAA,QAClB,QAAQ,WAAW;AAAA,eACZ;AAAA,YACH,KACS,QAAO,OAAd,MACE,QAAO,WAAW,aACnB,QAAgB,UAAT,OAAgB,MAAK,SAAS,MAC7B,UAAT;AAAA,cAEA,KACE,kBAAkB,EAClB,kBAAkB,MAAK,QACvB;AAAA,gBAEC,eAAe,MAAK,kBAClB,aAAa,IAAI,OAAO,aAAa;AAAA,YAC5C;AAAA,eACG;AAAA,eACA;AAAA,YACH;AAAA,eACG;AAAA,YACH,KAAW,QAAO,UAAd,KAAgC,cAAT,MAAoB;AAAA,cAC7C,QAAY;AAAA,cACZ,kBAAkB;AAAA,cAClB,eAAe,UAAU;AAAA,cACzB,YAAY,UAAU;AAAA,cACtB,YAAY,gBAAgB;AAAA,cAC5B,IAAI;AAAA,gBACF,IAAI,oBAAoB,2BACtB,gBAAgB,MAChB,YACF;AAAA,gBACA,QAAO,UAAU,wBACf,mBACA,SACF;AAAA,gBACA,UAAU,sCAAsC;AAAA,gBAChD,OAAO,OAAO;AAAA,gBACd,wBACE,iBACA,gBAAgB,QAChB,KACF;AAAA;AAAA,YAEJ;AAAA,YACA;AAAA,eACG;AAAA,YACH,KAAW,QAAO,UAAd;AAAA,cACF,IACI,QAAO,WAAW,UAAU,eAC7B,kBAAkB,MAAK,UAClB,oBAAN;AAAA,gBAEA,wBAAwB,KAAI;AAAA,cACzB,SAAU,oBAAN;AAAA,gBACP,QAAQ,MAAK;AAAA,uBACN;AAAA,uBACA;AAAA,uBACA;AAAA,oBACH,wBAAwB,KAAI;AAAA,oBAC5B;AAAA;AAAA,oBAEA,MAAK,cAAc;AAAA;AAAA;AAAA,YAE3B;AAAA,eACG;AAAA,eACA;AAAA,eACA;AAAA,eACA;AAAA,eACA;AAAA,eACA;AAAA,YACH;AAAA;AAAA,YAEA,KAAW,QAAO,UAAd;AAAA,cAAqB,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA;AAAA,QAEpE,QAAO,WAAW;AAAA,QAClB,IAAa,UAAT,MAAe;AAAA,UACjB,MAAK,SAAS,WAAW;AAAA,UACzB,aAAa;AAAA,UACb;AAAA,QACF;AAAA,QACA,aAAa,WAAW;AAAA,MAC1B;AAAA;AAEN,SAAS,yBAAyB,CAAC,cAAc,SAAS,cAAc;AAAA,EACtE,IAAI,QAAQ,aAAa;AAAA,EACzB,QAAQ,aAAa;AAAA,SACd;AAAA,SACA;AAAA,SACA;AAAA,MACH,iCAAiC,cAAc,YAAY;AAAA,MAC3D,QAAQ,KAAK,0BAA0B,GAAG,YAAY;AAAA,MACtD;AAAA,SACG;AAAA,MACH,iCAAiC,cAAc,YAAY;AAAA,MAC3D,IAAI,QAAQ;AAAA,QACV,IAAM,eAAe,aAAa,WAAqB,YAAT;AAAA,UAC5C,IAAI;AAAA,YACF,aAAa,kBAAkB;AAAA,YAC/B,OAAO,OAAO;AAAA,YACd,wBAAwB,cAAc,aAAa,QAAQ,KAAK;AAAA;AAAA,QAE/D;AAAA,UACH,IAAI,YAAY,2BACd,aAAa,MACb,QAAQ,aACV;AAAA,UACA,UAAU,QAAQ;AAAA,UAClB,IAAI;AAAA,YACF,aAAa,mBACX,WACA,SACA,aAAa,mCACf;AAAA,YACA,OAAO,WAAW;AAAA,YAClB,wBACE,cACA,aAAa,QACb,SACF;AAAA;AAAA;AAAA,MAGN,QAAQ,MAAM,qBAAqB,YAAY;AAAA,MAC/C,QAAQ,OAAO,gBAAgB,cAAc,aAAa,MAAM;AAAA,MAChE;AAAA,SACG;AAAA,MACH,iCAAiC,cAAc,YAAY;AAAA,MAC3D,IACE,QAAQ,OACN,eAAe,aAAa,aAAuB,iBAAT,OAC5C;AAAA,QACA,UAAU;AAAA,QACV,IAAa,aAAa,UAAtB;AAAA,UACF,QAAQ,aAAa,MAAM;AAAA,iBACpB;AAAA,iBACA;AAAA,cACH,UAAU,aAAa,MAAM;AAAA,cAC7B;AAAA,iBACG;AAAA,cACH,UAAU,aAAa,MAAM;AAAA;AAAA,QAEnC,IAAI;AAAA,UACF,gBAAgB,cAAc,OAAO;AAAA,UACrC,OAAO,OAAO;AAAA,UACd,wBAAwB,cAAc,aAAa,QAAQ,KAAK;AAAA;AAAA,MAEpE;AAAA,MACA;AAAA,SACG;AAAA,MACM,YAAT,QACE,QAAQ,KACR,+BAA+B,YAAY;AAAA,SAC1C;AAAA,SACA;AAAA,MACH,iCAAiC,cAAc,YAAY;AAAA,MAClD,YAAT,QAAoB,QAAQ,KAAK,gBAAgB,YAAY;AAAA,MAC7D,QAAQ,OAAO,gBAAgB,cAAc,aAAa,MAAM;AAAA,MAChE;AAAA,SACG;AAAA,MACH,iCAAiC,cAAc,YAAY;AAAA,MAC3D;AAAA,SACG;AAAA,MACH,iCAAiC,cAAc,YAAY;AAAA,MAC3D,QAAQ,KAAK,iCAAiC,cAAc,YAAY;AAAA,MACxE;AAAA,SACG;AAAA,MACH,iCAAiC,cAAc,YAAY;AAAA,MAC3D,QAAQ,KAAK,iCAAiC,cAAc,YAAY;AAAA,MACxE,QAAQ,OACJ,eAAe,aAAa,eACrB,iBAAT,SACI,eAAe,aAAa,YACrB,iBAAT,SACI,eAAe,gCAAgC,KAC/C,MACA,YACF,GACA,8BAA8B,cAAc,YAAY;AAAA,MAC9D;AAAA,SACG;AAAA,MACH,QAAiB,aAAa,kBAAtB,QAAuC;AAAA,MAC/C,IAAI,CAAC,OAAO;AAAA,QACV,UACY,YAAT,QAA6B,QAAQ,kBAAjB,QACrB;AAAA,QACF,YAAY;AAAA,QACZ,IAAI,gCAAgC;AAAA,QACpC,2BAA2B;AAAA,SAC1B,4BAA4B,YAAY,CAAC,gCACtC,yCACE,cACA,eACO,aAAa,eAAe,UAAnC,CACF,IACA,iCAAiC,cAAc,YAAY;AAAA,QAC/D,2BAA2B;AAAA,QAC3B,4BAA4B;AAAA,MAC9B;AAAA,MACA;AAAA,SACG;AAAA,MACH;AAAA;AAAA,MAEA,iCAAiC,cAAc,YAAY;AAAA;AAAA;AAGjE,SAAS,uBAAuB,CAAC,OAAO;AAAA,EACtC,IAAI,YAAY,MAAM;AAAA,EACb,cAAT,SACI,MAAM,YAAY,MAAO,wBAAwB,SAAS;AAAA,EAC9D,MAAM,QAAQ;AAAA,EACd,MAAM,YAAY;AAAA,EAClB,MAAM,UAAU;AAAA,EACV,MAAM,QAAZ,MACI,YAAY,MAAM,WACX,cAAT,QAAsB,sBAAsB,SAAS;AAAA,EACvD,MAAM,YAAY;AAAA,EAClB,MAAM,SAAS;AAAA,EACf,MAAM,eAAe;AAAA,EACrB,MAAM,gBAAgB;AAAA,EACtB,MAAM,gBAAgB;AAAA,EACtB,MAAM,eAAe;AAAA,EACrB,MAAM,YAAY;AAAA,EAClB,MAAM,cAAc;AAAA;AAItB,SAAS,kCAAkC,CACzC,cACA,wBACA,QACA;AAAA,EACA,KAAK,SAAS,OAAO,MAAgB,WAAT;AAAA,IAC1B,6BAA6B,cAAc,wBAAwB,MAAM,GACtE,SAAS,OAAO;AAAA;AAEvB,SAAS,4BAA4B,CACnC,cACA,wBACA,cACA;AAAA,EACA,IAAI,gBAA+B,OAAO,aAAa,yBAAnC;AAAA,IAClB,IAAI;AAAA,MACF,aAAa,qBAAqB,YAAY,YAAY;AAAA,MAC1D,OAAO,KAAK;AAAA,EAChB,QAAQ,aAAa;AAAA,SACd;AAAA,MACH,6BACE,gBAAgB,cAAc,sBAAsB;AAAA,MACtD,mCACE,cACA,wBACA,YACF;AAAA,MACA,aAAa,gBACT,aAAa,cAAc,UAC3B,aAAa,cACX,eAAe,aAAa,WAC9B,aAAa,WAAW,YAAY,YAAY;AAAA,MACpD;AAAA,SACG;AAAA,MACH,6BACE,gBAAgB,cAAc,sBAAsB;AAAA,MACtD,IAAI,iBAAiB,YACnB,4BAA4B;AAAA,MAC9B,iBAAiB,aAAa,IAAI,MAC9B,aAAa,aAAa,WAAa,wBAAwB;AAAA,MACnE,mCACE,cACA,wBACA,YACF;AAAA,MACA,yBAAyB,aAAa,SAAS;AAAA,MAC/C,aAAa;AAAA,MACb,wBAAwB;AAAA,MACxB;AAAA,SACG;AAAA,MACH,6BACE,gBAAgB,cAAc,sBAAsB;AAAA,SACnD;AAAA,MACH,iBAAiB;AAAA,MACjB,4BAA4B;AAAA,MAC5B,aAAa;AAAA,MACb,mCACE,cACA,wBACA,YACF;AAAA,MACA,aAAa;AAAA,MACb,wBAAwB;AAAA,MACxB,IAAa,eAAT;AAAA,QACF,IAAI;AAAA,UACF,IAAI;AAAA,aACK,WAAW,aAAjB,IACG,WAAW,OACA,WAAW,aAAtB,SACE,WAAW,cAAc,OACzB,YACJ,YAAY,aAAa,SAAS;AAAA,YACpC,OAAO,OAAO;AAAA,YACd,wBACE,cACA,wBACA,KACF;AAAA;AAAA,QAGF;AAAA,cAAI;AAAA,YACF,WAAW,YAAY,aAAa,SAAS;AAAA,YAC7C,OAAO,OAAO;AAAA,YACd,wBACE,cACA,wBACA,KACF;AAAA;AAAA,MAEN;AAAA,SACG;AAAA,MACM,eAAT,SACG,yBACK,eAAe,YACjB,uBACQ,aAAa,aAAnB,IACI,aAAa,OACF,aAAa,aAAxB,SACE,aAAa,cAAc,OAC3B,cACN,aAAa,SACf,GACA,iBAAiB,YAAY,KAC7B,uBAAuB,YAAY,aAAa,SAAS;AAAA,MAC/D;AAAA,SACG;AAAA,MACH,iBAAiB;AAAA,MACjB,4BAA4B;AAAA,MAC5B,aAAa,aAAa,UAAU;AAAA,MACpC,wBAAwB;AAAA,MACxB,mCACE,cACA,wBACA,YACF;AAAA,MACA,aAAa;AAAA,MACb,wBAAwB;AAAA,MACxB;AAAA,SACG;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH,4BAA4B,GAAG,cAAc,sBAAsB;AAAA,MACnE,6BACE,4BAA4B,GAAG,cAAc,sBAAsB;AAAA,MACrE,mCACE,cACA,wBACA,YACF;AAAA,MACA;AAAA,SACG;AAAA,MACH,8BACG,gBAAgB,cAAc,sBAAsB,GACpD,iBAAiB,aAAa,WAChB,OAAO,eAAe,yBAArC,cACE,+BACE,cACA,wBACA,cACF;AAAA,MACJ,mCACE,cACA,wBACA,YACF;AAAA,MACA;AAAA,SACG;AAAA,MACH,mCACE,cACA,wBACA,YACF;AAAA,MACA;AAAA,SACG;AAAA,MACH,6BACG,iBAAiB,8BACT,aAAa,kBAAtB;AAAA,MACF,mCACE,cACA,wBACA,YACF;AAAA,MACA,4BAA4B;AAAA,MAC5B;AAAA;AAAA,MAEA,mCACE,cACA,wBACA,YACF;AAAA;AAAA;AAGN,SAAS,gCAAgC,CAAC,cAAc,cAAc;AAAA,EACpE,IACW,aAAa,kBAAtB,SACE,eAAe,aAAa,WACrB,iBAAT,SACI,eAAe,aAAa,eAAyB,iBAAT,QAChD;AAAA,IACA,eAAe,aAAa;AAAA,IAC5B,IAAI;AAAA,MACF,iBAAiB,YAAY;AAAA,MAC7B,OAAO,OAAO;AAAA,MACd,wBAAwB,cAAc,aAAa,QAAQ,KAAK;AAAA;AAAA,EAEpE;AAAA;AAEF,SAAS,gCAAgC,CAAC,cAAc,cAAc;AAAA,EACpE,IACW,aAAa,kBAAtB,SACE,eAAe,aAAa,WACrB,iBAAT,SACI,eAAe,aAAa,eACrB,iBAAT,SACI,eAAe,aAAa,YAAsB,iBAAT;AAAA,IAE/C,IAAI;AAAA,MACF,iBAAiB,YAAY;AAAA,MAC7B,OAAO,OAAO;AAAA,MACd,wBAAwB,cAAc,aAAa,QAAQ,KAAK;AAAA;AAAA;AAGtE,SAAS,aAAa,CAAC,cAAc;AAAA,EACnC,QAAQ,aAAa;AAAA,SACd;AAAA,SACA;AAAA,SACA;AAAA,MACH,IAAI,aAAa,aAAa;AAAA,MACrB,eAAT,SACG,aAAa,aAAa,YAAY,IAAI;AAAA,MAC7C,OAAO;AAAA,SACJ;AAAA,MACH,OACG,eAAe,aAAa,WAC5B,aAAa,aAAa,aAClB,eAAT,SACG,aAAa,aAAa,cAAc,IAAI,kBAC/C;AAAA;AAAA,MAGF,MAAM,MAAM,wBAAuB,KAAK,aAAa,GAAG,CAAC;AAAA;AAAA;AAG/D,SAAS,4BAA4B,CAAC,cAAc,WAAW;AAAA,EAC7D,IAAI,aAAa,cAAc,YAAY;AAAA,EAC3C,UAAU,QAAQ,QAAS,CAAC,UAAU;AAAA,IACpC,IAAI,CAAC,WAAW,IAAI,QAAQ,GAAG;AAAA,MAC7B,WAAW,IAAI,QAAQ;AAAA,MACvB,IAAI,QAAQ,qBAAqB,KAAK,MAAM,cAAc,QAAQ;AAAA,MAClE,SAAS,KAAK,OAAO,KAAK;AAAA,IAC5B;AAAA,GACD;AAAA;AAEH,SAAS,kCAAkC,CAAC,eAAe,aAAa;AAAA,EACtE,IAAI,YAAY,YAAY;AAAA,EAC5B,IAAa,cAAT;AAAA,IACF,SAAS,IAAI,EAAG,IAAI,UAAU,QAAQ,KAAK;AAAA,MACzC,IAAI,gBAAgB,UAAU,IAC5B,QAAO,eACP,cAAc,aACd,SAAS;AAAA,MACX;AAAA,QAAG,MAAgB,WAAT,QAAmB;AAAA,UAC3B,QAAQ,OAAO;AAAA,iBACR;AAAA,cACH,IAAI,iBAAiB,OAAO,IAAI,GAAG;AAAA,gBACjC,aAAa,OAAO;AAAA,gBACpB,wBAAwB;AAAA,gBACxB;AAAA,cACF;AAAA,cACA;AAAA,iBACG;AAAA,cACH,aAAa,OAAO;AAAA,cACpB,wBAAwB;AAAA,cACxB;AAAA,iBACG;AAAA,iBACA;AAAA,cACH,aAAa,OAAO,UAAU;AAAA,cAC9B,wBAAwB;AAAA,cACxB;AAAA;AAAA,UAEJ,SAAS,OAAO;AAAA,QAClB;AAAA,MACA,IAAa,eAAT;AAAA,QAAqB,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,MAChE,6BAA6B,OAAM,aAAa,aAAa;AAAA,MAC7D,aAAa;AAAA,MACb,wBAAwB;AAAA,MACxB,QAAO,cAAc;AAAA,MACZ,UAAT,SAAkB,MAAK,SAAS;AAAA,MAChC,cAAc,SAAS;AAAA,IACzB;AAAA,EACF,IAAI,YAAY,eAAe;AAAA,IAC7B,KAAK,cAAc,YAAY,MAAgB,gBAAT;AAAA,MACpC,6BAA6B,aAAa,aAAa,GACpD,cAAc,YAAY;AAAA;AAGnC,SAAS,4BAA4B,CAAC,cAAc,OAAM;AAAA,EACxD,MAA2B,WAAvB,SACmB,UAAb;AAAA,EACV,QAAQ,aAAa;AAAA,SACd;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH,mCAAmC,OAAM,YAAY;AAAA,MACrD,4BAA4B,YAAY;AAAA,MACxC,QAAQ,MACL,4BAA4B,GAAG,cAAc,aAAa,MAAM,GACjE,0BAA0B,GAAG,YAAY,GACzC,4BAA4B,GAAG,cAAc,aAAa,MAAM;AAAA,MAClE;AAAA,SACG;AAAA,MACH,mCAAmC,OAAM,YAAY;AAAA,MACrD,4BAA4B,YAAY;AAAA,MACxC,QAAQ,QACL,6BACU,YAAT,QACA,gBAAgB,SAAS,QAAQ,MAAM;AAAA,MAC3C,QAAQ,MACN,6BACE,eAAe,aAAa,aACrB,iBAAT,SACI,QAAQ,aAAa,WACd,UAAT,SACI,UAAU,aAAa,OAAO,iBAC/B,aAAa,OAAO,kBACV,YAAT,OAAmB,QAAQ,QAAQ,OAAO,KAAK;AAAA,MACvD;AAAA,SACG;AAAA,MACH,IAAI,gBAAgB;AAAA,MACpB,mCAAmC,OAAM,YAAY;AAAA,MACrD,4BAA4B,YAAY;AAAA,MACxC,QAAQ,QACL,6BACU,YAAT,QACA,gBAAgB,SAAS,QAAQ,MAAM;AAAA,MAC3C,IAAI,QAAQ,GAAG;AAAA,QACb,IAAI,kBAA2B,YAAT,OAAmB,QAAQ,gBAAgB;AAAA,QACjE,QAAQ,aAAa;AAAA,QACrB,IAAa,YAAT;AAAA,UACF,IAAa,UAAT;AAAA,YACF,IAAa,aAAa,cAAtB,MAAiC;AAAA,cACnC,GAAG;AAAA,gBACD,QAAQ,aAAa;AAAA,gBACrB,UAAU,aAAa;AAAA,gBACvB,gBAAgB,cAAc,iBAAiB;AAAA,gBAC/C;AAAA,kBAAG,QAAQ;AAAA,yBACJ;AAAA,sBACH,kBACE,cAAc,qBAAqB,OAAO,EAAE;AAAA,sBAC9C,IACE,CAAC,mBACD,gBAAgB,4BAChB,gBAAgB,wBAEd,gBAAgB,iBADlB,gCAEA,gBAAgB,aAAa,UAAU;AAAA,wBAEtC,kBAAkB,cAAc,cAAc,KAAK,GAClD,cAAc,KAAK,aACjB,iBACA,cAAc,cAAc,cAAc,CAC5C;AAAA,sBACJ,qBAAqB,iBAAiB,OAAO,OAAO;AAAA,sBACpD,gBAAgB,uBAAuB;AAAA,sBACvC,oBAAoB,eAAe;AAAA,sBACnC,QAAQ;AAAA,sBACR;AAAA,yBACG;AAAA,sBACH,IAAI,aAAa,4BACf,QACA,QACA,aACF,EAAE,IAAI,SAAS,QAAQ,QAAQ,GAAG;AAAA,sBAClC,IAAI;AAAA,wBACF,SAAS,IAAI,EAAG,IAAI,WAAW,QAAQ;AAAA,0BACrC,IACI,kBAAkB,WAAW,IAC/B,gBAAgB,aAAa,MAAM,OACxB,QAAQ,QAAhB,QAA+B,QAAQ,SAAf,KACrB,OACA,QAAQ,SACZ,gBAAgB,aAAa,KAAK,OACvB,QAAQ,OAAhB,OAAsB,OAAO,QAAQ,QACxC,gBAAgB,aAAa,OAAO,OACzB,QAAQ,SAAhB,OAAwB,OAAO,QAAQ,UAC1C,gBAAgB,aAAa,aAAa,OAC/B,QAAQ,eAAhB,OACG,OACA,QAAQ,cAChB;AAAA,4BACA,WAAW,OAAO,GAAG,CAAC;AAAA,4BACtB;AAAA,0BACF;AAAA;AAAA,sBACJ,kBAAkB,cAAc,cAAc,KAAK;AAAA,sBACnD,qBAAqB,iBAAiB,OAAO,OAAO;AAAA,sBACpD,cAAc,KAAK,YAAY,eAAe;AAAA,sBAC9C;AAAA,yBACG;AAAA,sBACH,IACG,aAAa,4BACZ,QACA,WACA,aACF,EAAE,IAAI,SAAS,QAAQ,WAAW,GAAG;AAAA,wBAErC,KAAK,IAAI,EAAG,IAAI,WAAW,QAAQ;AAAA,0BACjC,IACI,kBAAkB,WAAW,IAC/B,gBAAgB,aAAa,SAAS,OAC3B,QAAQ,WAAhB,OACG,OACA,KAAK,QAAQ,YACjB,gBAAgB,aAAa,MAAM,OACxB,QAAQ,QAAhB,OAAuB,OAAO,QAAQ,SACzC,gBAAgB,aAAa,UAAU,OAC5B,QAAQ,YAAhB,OACG,OACA,QAAQ,aACd,gBAAgB,aAAa,YAAY,OAC9B,QAAQ,aAAhB,OACG,OACA,QAAQ,cACd,gBAAgB,aAAa,SAAS,OAC3B,QAAQ,WAAhB,OACG,OACA,QAAQ,UAChB;AAAA,4BACA,WAAW,OAAO,GAAG,CAAC;AAAA,4BACtB;AAAA,0BACF;AAAA;AAAA,sBACJ,kBAAkB,cAAc,cAAc,KAAK;AAAA,sBACnD,qBAAqB,iBAAiB,OAAO,OAAO;AAAA,sBACpD,cAAc,KAAK,YAAY,eAAe;AAAA,sBAC9C;AAAA;AAAA,sBAEA,MAAM,MAAM,wBAAuB,KAAK,KAAK,CAAC;AAAA;AAAA,gBAElD,gBAAgB,uBAAuB;AAAA,gBACvC,oBAAoB,eAAe;AAAA,gBACnC,QAAQ;AAAA,cACV;AAAA,cACA,aAAa,YAAY;AAAA,YAC3B,EACE;AAAA,6BACE,eACA,aAAa,MACb,aAAa,SACf;AAAA,UAEF;AAAA,yBAAa,YAAY,gBACvB,eACA,OACA,aAAa,aACf;AAAA,QAEF;AAAA,8BAAoB,SACN,oBAAT,OACY,QAAQ,cAAjB,SACE,UAAU,QAAQ,WACpB,QAAQ,WAAW,YAAY,OAAO,KACtC,gBAAgB,SACX,UAAT,OACI,eACE,eACA,aAAa,MACb,aAAa,SACf,IACA,gBACE,eACA,OACA,aAAa,aACf,KACK,UAAT,QACS,aAAa,cAAtB,QACA,iBACE,cACA,aAAa,eACb,QAAQ,aACV;AAAA,MACR;AAAA,MACA;AAAA,SACG;AAAA,MACH,mCAAmC,OAAM,YAAY;AAAA,MACrD,4BAA4B,YAAY;AAAA,MACxC,QAAQ,QACL,6BACU,YAAT,QACA,gBAAgB,SAAS,QAAQ,MAAM;AAAA,MAClC,YAAT,QACE,QAAQ,KACR,iBACE,cACA,aAAa,eACb,QAAQ,aACV;AAAA,MACF;AAAA,SACG;AAAA,MACH,mCAAmC,OAAM,YAAY;AAAA,MACrD,4BAA4B,YAAY;AAAA,MACxC,QAAQ,QACL,6BACU,YAAT,QACA,gBAAgB,SAAS,QAAQ,MAAM;AAAA,MAC3C,IAAI,aAAa,QAAQ,IAAI;AAAA,QAC3B,gBAAgB,aAAa;AAAA,QAC7B,IAAI;AAAA,UACF,eAAe,eAAe,EAAE;AAAA,UAChC,OAAO,OAAO;AAAA,UACd,wBAAwB,cAAc,aAAa,QAAQ,KAAK;AAAA;AAAA,MAEpE;AAAA,MACA,QAAQ,KACE,aAAa,aAArB,SACE,gBAAgB,aAAa,eAC/B,iBACE,cACA,eACS,YAAT,OAAmB,QAAQ,gBAAgB,aAC7C;AAAA,MACF,QAAQ,SAAS,iBAAiB;AAAA,MAClC;AAAA,SACG;AAAA,MACH,mCAAmC,OAAM,YAAY;AAAA,MACrD,4BAA4B,YAAY;AAAA,MACxC,IAAI,QAAQ,GAAG;AAAA,QACb,IAAa,aAAa,cAAtB;AAAA,UACF,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,QACzC,QAAQ,aAAa;AAAA,QACrB,UAAU,aAAa;AAAA,QACvB,IAAI;AAAA,UACF,QAAQ,YAAY;AAAA,UACpB,OAAO,OAAO;AAAA,UACd,wBAAwB,cAAc,aAAa,QAAQ,KAAK;AAAA;AAAA,MAEpE;AAAA,MACA;AAAA,SACG;AAAA,MACH,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,uBAAuB,iBAAiB,MAAK,aAAa;AAAA,MAC1D,mCAAmC,OAAM,YAAY;AAAA,MACrD,uBAAuB;AAAA,MACvB,4BAA4B,YAAY;AAAA,MACxC,IAAI,QAAQ,KAAc,YAAT,QAAoB,QAAQ,cAAc;AAAA,QACzD,IAAI;AAAA,UACF,iBAAiB,MAAK,aAAa;AAAA,UACnC,OAAO,OAAO;AAAA,UACd,wBAAwB,cAAc,aAAa,QAAQ,KAAK;AAAA;AAAA,MAEpE,mBACI,iBAAiB,OAAK,sBAAsB,YAAY;AAAA,MAC5D;AAAA,SACG;AAAA,MACH,QAAQ;AAAA,MACR,uBAAuB,iBACrB,aAAa,UAAU,aACzB;AAAA,MACA,mCAAmC,OAAM,YAAY;AAAA,MACrD,4BAA4B,YAAY;AAAA,MACxC,uBAAuB;AAAA,MACvB;AAAA,SACG;AAAA,MACH,mCAAmC,OAAM,YAAY;AAAA,MACrD,4BAA4B,YAAY;AAAA,MACxC;AAAA,SACG;AAAA,MACH,mCAAmC,OAAM,YAAY;AAAA,MACrD,4BAA4B,YAAY;AAAA,MACxC,QAAQ,MACJ,QAAQ,aAAa,aACd,UAAT,SACI,aAAa,cAAc,MAC7B,6BAA6B,cAAc,KAAK;AAAA,MACpD;AAAA,SACG;AAAA,MACH,mCAAmC,OAAM,YAAY;AAAA,MACrD,4BAA4B,YAAY;AAAA,MACxC,aAAa,MAAM,QAAQ,QACf,aAAa,kBAAtB,UACW,YAAT,QAA6B,QAAQ,kBAAjB,UACtB,+BAA+B,IAAI;AAAA,MACtC,QAAQ,MACJ,QAAQ,aAAa,aACd,UAAT,SACI,aAAa,cAAc,MAC7B,6BAA6B,cAAc,KAAK;AAAA,MACpD;AAAA,SACG;AAAA,MACH,gBAAyB,aAAa,kBAAtB;AAAA,MAChB,IAAI,YAAqB,YAAT,QAA6B,QAAQ,kBAAjB,MAClC,+BAA+B,0BAC/B,gCAAgC;AAAA,MAClC,2BAA2B,gCAAgC;AAAA,MAC3D,4BAA4B,iCAAiC;AAAA,MAC7D,mCAAmC,OAAM,YAAY;AAAA,MACrD,4BAA4B;AAAA,MAC5B,2BAA2B;AAAA,MAC3B,4BAA4B,YAAY;AAAA,MACxC,IAAI,QAAQ;AAAA,QACV;AAAA,UAAG,KACD,QAAO,aAAa,WAClB,MAAK,cAAc,gBACf,MAAK,cAAc,KACnB,MAAK,cAAc,GACvB,kBACY,YAAT,QACC,aACA,4BACA,6BACA,0CAA0C,YAAY,IAC1D,UAAU,MACV,QAAO,iBAGT;AAAA,YACA,IAAU,MAAK,QAAX,KAAyB,MAAK,QAAZ,IAAiB;AAAA,cACrC,IAAa,YAAT,MAAkB;AAAA,gBACpB,YAAY,UAAU;AAAA,gBACtB,IAAI;AAAA,kBACF,IAAM,kBAAkB,UAAU,WAAY;AAAA,oBAC3C,aAAa,gBAAgB,OACb,OAAO,WAAW,gBAAjC,aACI,WAAW,YAAY,WAAW,QAAQ,WAAW,IACpD,WAAW,UAAU;AAAA,kBACzB;AAAA,oBACH,IAAI,UAAU;AAAA,oBACd,IAAI,YAAY,UAAU,cAAc,OACtC,UACa,cAAN,aACI,cAAT,QACA,UAAU,eAAe,SAAS,IAC9B,UAAU,UACV;AAAA,oBACR,EAAE,MAAM,UACE,WAAR,QAAiC,OAAO,YAArB,YACf,MACC,KAAK,SAAS,KAAK;AAAA;AAAA,kBAE5B,OAAO,OAAO;AAAA,kBACd,wBAAwB,WAAW,UAAU,QAAQ,KAAK;AAAA;AAAA,cAE9D;AAAA,YACF,EAAO,SAAU,MAAK,QAAX,GAAgB;AAAA,cACzB,IAAa,YAAT,MAAkB;AAAA,gBACpB,YAAY;AAAA,gBACZ,IAAI;AAAA,kBACF,UAAU,UAAU,YAAY,gBAC5B,KACA,UAAU;AAAA,kBACd,OAAO,OAAO;AAAA,kBACd,wBAAwB,WAAW,UAAU,QAAQ,KAAK;AAAA;AAAA,cAE9D;AAAA,YACF,EAAO,SAAW,MAAK,QAAZ,IAAiB;AAAA,cAC1B,IAAa,YAAT,MAAkB;AAAA,gBACpB,YAAY;AAAA,gBACZ,IAAI;AAAA,kBACF,IAAI,WAAW,UAAU;AAAA,kBACzB,gBACI,+BAA+B,UAAU,IAAE,IAC3C,+BAA+B,UAAU,WAAW,KAAE;AAAA,kBAC1D,OAAO,OAAO;AAAA,kBACd,wBAAwB,WAAW,UAAU,QAAQ,KAAK;AAAA;AAAA,cAE9D;AAAA,YACF,EAAO,UACI,MAAK,QAAZ,MAA0B,MAAK,QAAZ,MACV,MAAK,kBAAd,QACA,UAAS,iBACF,MAAK,UAAd,MACA;AAAA,cACA,MAAK,MAAM,SAAS;AAAA,cACpB,QAAO,MAAK;AAAA,cACZ;AAAA,YACF;AAAA,YACA,IAAI,UAAS;AAAA,cAAc;AAAA,YAC3B,MAAgB,MAAK,YAAd,QAAyB;AAAA,cAC9B,IAAa,MAAK,WAAd,QAAwB,MAAK,WAAW;AAAA,gBAAc;AAAA,cAC1D,YAAY,UAAS,UAAU;AAAA,cAC/B,QAAO,MAAK;AAAA,YACd;AAAA,YACA,YAAY,UAAS,UAAU;AAAA,YAC/B,MAAK,QAAQ,SAAS,MAAK;AAAA,YAC3B,QAAO,MAAK;AAAA,UACd;AAAA,MACF,QAAQ,MACJ,QAAQ,aAAa,aACd,UAAT,SACI,UAAU,MAAM,YACT,YAAT,SACI,MAAM,aAAa,MACrB,6BAA6B,cAAc,OAAO;AAAA,MACxD;AAAA,SACG;AAAA,MACH,mCAAmC,OAAM,YAAY;AAAA,MACrD,4BAA4B,YAAY;AAAA,MACxC,QAAQ,MACJ,QAAQ,aAAa,aACd,UAAT,SACI,aAAa,cAAc,MAC7B,6BAA6B,cAAc,KAAK;AAAA,MACpD;AAAA,SACG;AAAA,MACH;AAAA,SACG;AAAA,MACH;AAAA;AAAA,MAEA,mCAAmC,OAAM,YAAY,GACnD,4BAA4B,YAAY;AAAA;AAAA;AAGhD,SAAS,2BAA2B,CAAC,cAAc;AAAA,EACjD,IAAI,QAAQ,aAAa;AAAA,EACzB,IAAI,QAAQ,GAAG;AAAA,IACb,IAAI;AAAA,MACF,SACM,iBAAiB,cAAc,aAAa,OACvC,gBAAT,QAEA;AAAA,QACA,IAAI,aAAa,WAAW,GAAG;AAAA,UAC7B,kBAAkB;AAAA,UAClB;AAAA,QACF;AAAA,QACA,cAAc,YAAY;AAAA,MAC5B;AAAA,MACA,IAAY,mBAAR;AAAA,QAAyB,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,MACpE,QAAQ,gBAAgB;AAAA,aACjB;AAAA,UACH,IAAI,SAAS,gBAAgB,WAC3B,SAAS,eAAe,YAAY;AAAA,UACtC,4BAA4B,cAAc,QAAQ,MAAM;AAAA,UACxD;AAAA,aACG;AAAA,UACH,IAAI,aAAa,gBAAgB;AAAA,UACjC,gBAAgB,QAAQ,OACrB,eAAe,YAAY,EAAE,GAAI,gBAAgB,SAAS;AAAA,UAC7D,IAAI,aAAa,eAAe,YAAY;AAAA,UAC5C,4BAA4B,cAAc,YAAY,UAAU;AAAA,UAChE;AAAA,aACG;AAAA,aACA;AAAA,UACH,IAAI,aAAa,gBAAgB,UAAU,eACzC,aAAa,eAAe,YAAY;AAAA,UAC1C,yCACE,cACA,YACA,UACF;AAAA,UACA;AAAA;AAAA,UAEA,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA;AAAA,MAE3C,OAAO,OAAO;AAAA,MACd,wBAAwB,cAAc,aAAa,QAAQ,KAAK;AAAA;AAAA,IAElE,aAAa,SAAS;AAAA,EACxB;AAAA,EACA,QAAQ,SAAS,aAAa,SAAS;AAAA;AAEzC,SAAS,qBAAqB,CAAC,aAAa;AAAA,EAC1C,IAAI,YAAY,eAAe;AAAA,IAC7B,KAAK,cAAc,YAAY,MAAgB,gBAAT,QAAwB;AAAA,MAC5D,IAAI,QAAQ;AAAA,MACZ,sBAAsB,KAAK;AAAA,MACrB,MAAM,QAAZ,KAAmB,MAAM,QAAQ,QAAQ,MAAM,UAAU,MAAM;AAAA,MAC/D,cAAc,YAAY;AAAA,IAC5B;AAAA;AAEJ,SAAS,gCAAgC,CAAC,OAAM,aAAa;AAAA,EAC3D,IAAI,YAAY,eAAe;AAAA,IAC7B,KAAK,cAAc,YAAY,MAAgB,gBAAT;AAAA,MACpC,0BAA0B,OAAM,YAAY,WAAW,WAAW,GAC/D,cAAc,YAAY;AAAA;AAEnC,SAAS,yCAAyC,CAAC,aAAa;AAAA,EAC9D,KAAK,cAAc,YAAY,MAAgB,gBAAT,QAAwB;AAAA,IAC5D,IAAI,eAAe;AAAA,IACnB,QAAQ,aAAa;AAAA,WACd;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,QACH,4BAA4B,GAAG,cAAc,aAAa,MAAM;AAAA,QAChE,0CAA0C,YAAY;AAAA,QACtD;AAAA,WACG;AAAA,QACH,gBAAgB,cAAc,aAAa,MAAM;AAAA,QACjD,IAAI,WAAW,aAAa;AAAA,QACb,OAAO,SAAS,yBAA/B,cACE,+BACE,cACA,aAAa,QACb,QACF;AAAA,QACF,0CAA0C,YAAY;AAAA,QACtD;AAAA,WACG;AAAA,QACH,yBAAyB,aAAa,SAAS;AAAA,WAC5C;AAAA,WACA;AAAA,QACH,gBAAgB,cAAc,aAAa,MAAM;AAAA,QACjD,0CAA0C,YAAY;AAAA,QACtD;AAAA,WACG;AAAA,QACM,aAAa,kBAAtB,QACE,0CAA0C,YAAY;AAAA,QACxD;AAAA,WACG;AAAA,QACH,0CAA0C,YAAY;AAAA,QACtD;AAAA;AAAA,QAEA,0CAA0C,YAAY;AAAA;AAAA,IAE1D,cAAc,YAAY;AAAA,EAC5B;AAAA;AAEF,SAAS,wCAAwC,CAC/C,uBACA,aACA,8BACA;AAAA,EACA,+BACE,iCAAuC,YAAY,eAAe,UAAlC;AAAA,EAClC,KAAK,cAAc,YAAY,MAAgB,gBAAT,QAAwB;AAAA,IAC5D,IAAI,UAAU,YAAY,WACxB,eAAe,uBACf,eAAe,aACf,QAAQ,aAAa;AAAA,IACvB,QAAQ,aAAa;AAAA,WACd;AAAA,WACA;AAAA,WACA;AAAA,QACH,yCACE,cACA,cACA,4BACF;AAAA,QACA,0BAA0B,GAAG,YAAY;AAAA,QACzC;AAAA,WACG;AAAA,QACH,yCACE,cACA,cACA,4BACF;AAAA,QACA,UAAU;AAAA,QACV,eAAe,QAAQ;AAAA,QACvB,IAAmB,OAAO,aAAa,sBAAnC;AAAA,UACF,IAAI;AAAA,YACF,aAAa,kBAAkB;AAAA,YAC/B,OAAO,OAAO;AAAA,YACd,wBAAwB,SAAS,QAAQ,QAAQ,KAAK;AAAA;AAAA,QAE1D,UAAU;AAAA,QACV,eAAe,QAAQ;AAAA,QACvB,IAAa,iBAAT,MAAuB;AAAA,UACzB,IAAI,WAAW,QAAQ;AAAA,UACvB,IAAI;AAAA,YACF,IAAI,kBAAkB,aAAa,OAAO;AAAA,YAC1C,IAAa,oBAAT;AAAA,cACF,KACE,aAAa,OAAO,kBAAkB,MAAM,eAAe,EAC3D,eAAe,gBAAgB,QAC/B;AAAA,gBAEA,aAAa,gBAAgB,eAAe,QAAQ;AAAA,YACxD,OAAO,OAAO;AAAA,YACd,wBAAwB,SAAS,QAAQ,QAAQ,KAAK;AAAA;AAAA,QAE1D;AAAA,QACA,gCACE,QAAQ,MACR,qBAAqB,YAAY;AAAA,QACnC,gBAAgB,cAAc,aAAa,MAAM;AAAA,QACjD;AAAA,WACG;AAAA,QACH,+BAA+B,YAAY;AAAA,WACxC;AAAA,WACA;AAAA,QACH,yCACE,cACA,cACA,4BACF;AAAA,QACA,gCACW,YAAT,QACA,QAAQ,KACR,gBAAgB,YAAY;AAAA,QAC9B,gBAAgB,cAAc,aAAa,MAAM;AAAA,QACjD;AAAA,WACG;AAAA,QACH,yCACE,cACA,cACA,4BACF;AAAA,QACA;AAAA,WACG;AAAA,QACH,yCACE,cACA,cACA,4BACF;AAAA,QACA,gCACE,QAAQ,KACR,iCAAiC,cAAc,YAAY;AAAA,QAC7D;AAAA,WACG;AAAA,QACH,yCACE,cACA,cACA,4BACF;AAAA,QACA,gCACE,QAAQ,KACR,iCAAiC,cAAc,YAAY;AAAA,QAC7D;AAAA,WACG;AAAA,QACM,aAAa,kBAAtB,QACE,yCACE,cACA,cACA,4BACF;AAAA,QACF,gBAAgB,cAAc,aAAa,MAAM;AAAA,QACjD;AAAA,WACG;AAAA,QACH;AAAA;AAAA,QAEA,yCACE,cACA,cACA,4BACF;AAAA;AAAA,IAEJ,cAAc,YAAY;AAAA,EAC5B;AAAA;AAEF,SAAS,kCAAkC,CAAC,SAAS,cAAc;AAAA,EACjE,IAAI,gBAAgB;AAAA,EACX,YAAT,QACW,QAAQ,kBAAjB,QACS,QAAQ,cAAc,cAA/B,SACC,gBAAgB,QAAQ,cAAc,UAAU;AAAA,EACnD,UAAU;AAAA,EACD,aAAa,kBAAtB,QACW,aAAa,cAAc,cAApC,SACC,UAAU,aAAa,cAAc,UAAU;AAAA,EAClD,YAAY,kBACD,WAAR,QAAmB,QAAQ,YACpB,iBAAR,QAAyB,aAAa,aAAa;AAAA;AAEvD,SAAS,6BAA6B,CAAC,SAAS,cAAc;AAAA,EAC5D,UAAU;AAAA,EACD,aAAa,cAAtB,SACG,UAAU,aAAa,UAAU,cAAc;AAAA,EAClD,eAAe,aAAa,cAAc;AAAA,EAC1C,iBAAiB,YACd,aAAa,YAAoB,WAAR,QAAmB,aAAa,OAAO;AAAA;AAErE,SAAS,sCAAsC,CAC7C,OACA,aACA,gBACA,sBACA;AAAA,EACA,IAAI,YAAY,eAAe;AAAA,IAC7B,KAAK,cAAc,YAAY,MAAgB,gBAAT;AAAA,MACpC,0BACE,OACA,aACA,gBACA,oBACF,GACG,cAAc,YAAY;AAAA;AAEnC,SAAS,yBAAyB,CAChC,cACA,cACA,gBACA,sBACA;AAAA,EACA,IAAI,QAAQ,aAAa;AAAA,EACzB,QAAQ,aAAa;AAAA,SACd;AAAA,SACA;AAAA,SACA;AAAA,MACH,uCACE,cACA,cACA,gBACA,oBACF;AAAA,MACA,QAAQ,QAAQ,0BAA0B,GAAG,YAAY;AAAA,MACzD;AAAA,SACG;AAAA,MACH,uCACE,cACA,cACA,gBACA,oBACF;AAAA,MACA;AAAA,SACG;AAAA,MACH,uCACE,cACA,cACA,gBACA,oBACF;AAAA,MACA,QAAQ,SACJ,eAAe,MACR,aAAa,cAAtB,SACG,eAAe,aAAa,UAAU,cAAc,QACtD,eAAe,aAAa,cAAc,OAC3C,iBAAiB,iBACd,aAAa,YACN,gBAAR,QAAwB,aAAa,YAAY;AAAA,MACrD;AAAA,SACG;AAAA,MACH,IAAI,QAAQ,MAAM;AAAA,QAChB,uCACE,cACA,cACA,gBACA,oBACF;AAAA,QACA,eAAe,aAAa;AAAA,QAC5B,IAAI;AAAA,UACF,IAAI,yBAAyB,aAAa,eACxC,KAAK,uBAAuB,IAC5B,eAAe,uBAAuB;AAAA,UACzB,OAAO,iBAAtB,cACE,aACE,IACS,aAAa,cAAtB,OAAkC,UAAU,UAC5C,aAAa,uBACb,EACF;AAAA,UACF,OAAO,OAAO;AAAA,UACd,wBAAwB,cAAc,aAAa,QAAQ,KAAK;AAAA;AAAA,MAEpE,EACE;AAAA,+CACE,cACA,cACA,gBACA,oBACF;AAAA,MACF;AAAA,SACG;AAAA,MACH,uCACE,cACA,cACA,gBACA,oBACF;AAAA,MACA;AAAA,SACG;AAAA,MACH,uCACE,cACA,cACA,gBACA,oBACF;AAAA,MACA;AAAA,SACG;AAAA,MACH;AAAA,SACG;AAAA,MACH,yBAAyB,aAAa;AAAA,MACtC,KAAK,aAAa;AAAA,MACT,aAAa,kBAAtB,OACI,uBAAuB,cAAc,IACnC,uCACE,cACA,cACA,gBACA,oBACF,IACA,wCAAwC,cAAc,YAAY,IACpE,uBAAuB,cAAc,IACnC,uCACE,cACA,cACA,gBACA,oBACF,KACE,uBAAuB,eAAe,GACxC,2CACE,cACA,cACA,gBACA,uBACO,aAAa,eAAe,WAAnC,KAA6C,KAC/C;AAAA,MACN,QAAQ,QAAQ,mCAAmC,IAAI,YAAY;AAAA,MACnE;AAAA,SACG;AAAA,MACH,uCACE,cACA,cACA,gBACA,oBACF;AAAA,MACA,QAAQ,QACN,8BAA8B,aAAa,WAAW,YAAY;AAAA,MACpE;AAAA;AAAA,MAEA,uCACE,cACA,cACA,gBACA,oBACF;AAAA;AAAA;AAGN,SAAS,0CAA0C,CACjD,uBACA,aACA,yBACA,+BACA,8BACA;AAAA,EACA,+BACE,kCACQ,YAAY,eAAe,WAAlC,KAA4C;AAAA,EAC/C,KAAK,cAAc,YAAY,MAAgB,gBAAT,QAAwB;AAAA,IAC5D,IAAI,eAAe,uBACjB,eAAe,aACf,iBAAiB,yBACjB,uBAAuB,+BACvB,QAAQ,aAAa;AAAA,IACvB,QAAQ,aAAa;AAAA,WACd;AAAA,WACA;AAAA,WACA;AAAA,QACH,2CACE,cACA,cACA,gBACA,sBACA,4BACF;AAAA,QACA,0BAA0B,GAAG,YAAY;AAAA,QACzC;AAAA,WACG;AAAA,QACH;AAAA,WACG;AAAA,QACH,IAAI,WAAW,aAAa;AAAA,QACnB,aAAa,kBAAtB,OACI,SAAS,cAAc,IACrB,2CACE,cACA,cACA,gBACA,sBACA,4BACF,IACA,wCACE,cACA,YACF,KACA,SAAS,eAAe,GAC1B,2CACE,cACA,cACA,gBACA,sBACA,4BACF;AAAA,QACJ,gCACE,QAAQ,QACR,mCACE,aAAa,WACb,YACF;AAAA,QACF;AAAA,WACG;AAAA,QACH,2CACE,cACA,cACA,gBACA,sBACA,4BACF;AAAA,QACA,gCACE,QAAQ,QACR,8BAA8B,aAAa,WAAW,YAAY;AAAA,QACpE;AAAA;AAAA,QAEA,2CACE,cACA,cACA,gBACA,sBACA,4BACF;AAAA;AAAA,IAEJ,cAAc,YAAY;AAAA,EAC5B;AAAA;AAEF,SAAS,uCAAuC,CAC9C,uBACA,aACA;AAAA,EACA,IAAI,YAAY,eAAe;AAAA,IAC7B,KAAK,cAAc,YAAY,MAAgB,gBAAT,QAAwB;AAAA,MAC5D,IAAI,eAAe,uBACjB,eAAe,aACf,QAAQ,aAAa;AAAA,MACvB,QAAQ,aAAa;AAAA,aACd;AAAA,UACH,wCAAwC,cAAc,YAAY;AAAA,UAClE,QAAQ,QACN,mCACE,aAAa,WACb,YACF;AAAA,UACF;AAAA,aACG;AAAA,UACH,wCAAwC,cAAc,YAAY;AAAA,UAClE,QAAQ,QACN,8BAA8B,aAAa,WAAW,YAAY;AAAA,UACpE;AAAA;AAAA,UAEA,wCAAwC,cAAc,YAAY;AAAA;AAAA,MAEtE,cAAc,YAAY;AAAA,IAC5B;AAAA;AAGJ,SAAS,oCAAoC,CAC3C,aACA,gBACA,gBACA;AAAA,EACA,IAAI,YAAY,eAAe;AAAA,IAC7B,KAAK,cAAc,YAAY,MAAgB,gBAAT;AAAA,MACpC,iCACE,aACA,gBACA,cACF,GACG,cAAc,YAAY;AAAA;AAEnC,SAAS,gCAAgC,CACvC,OACA,gBACA,gBACA;AAAA,EACA,QAAQ,MAAM;AAAA,SACP;AAAA,MACH,qCACE,OACA,gBACA,cACF;AAAA,MACA,MAAM,QAAQ,uBACH,MAAM,kBAAf,QACA,gBACE,gBACA,sBACA,MAAM,eACN,MAAM,aACR;AAAA,MACF;AAAA,SACG;AAAA,MACH,qCACE,OACA,gBACA,cACF;AAAA,MACA;AAAA,SACG;AAAA,SACA;AAAA,MACH,IAAI,wBAAwB;AAAA,MAC5B,uBAAuB,iBAAiB,MAAM,UAAU,aAAa;AAAA,MACrE,qCACE,OACA,gBACA,cACF;AAAA,MACA,uBAAuB;AAAA,MACvB;AAAA,SACG;AAAA,MACM,MAAM,kBAAf,SACI,wBAAwB,MAAM,WACvB,0BAAT,QACS,sBAAsB,kBAA/B,QACM,wBAAwB,qBACzB,sBAAsB,UACvB,qCACE,OACA,gBACA,cACF,GACC,sBAAsB,yBACvB,qCACE,OACA,gBACA,cACF;AAAA,MACN;AAAA;AAAA,MAEA,qCACE,OACA,gBACA,cACF;AAAA;AAAA;AAGN,SAAS,uBAAuB,CAAC,aAAa;AAAA,EAC5C,IAAI,gBAAgB,YAAY;AAAA,EAChC,IACW,kBAAT,SACE,cAAc,cAAc,OAAiB,gBAAT,OACtC;AAAA,IACA,cAAc,QAAQ;AAAA,IACtB;AAAA,MACG,gBAAgB,YAAY,SAC1B,YAAY,UAAU,MACtB,cAAc;AAAA,WACH,gBAAT;AAAA,EACT;AAAA;AAEF,SAAS,wCAAwC,CAAC,aAAa;AAAA,EAC7D,IAAI,YAAY,YAAY;AAAA,EAC5B,KAAW,YAAY,QAAQ,QAA3B,GAAgC;AAAA,IAClC,IAAa,cAAT;AAAA,MACF,SAAS,IAAI,EAAG,IAAI,UAAU,QAAQ,KAAK;AAAA,QACzC,IAAI,gBAAgB,UAAU;AAAA,QAC9B,aAAa;AAAA,QACb,qDACE,eACA,WACF;AAAA,MACF;AAAA,IACF,wBAAwB,WAAW;AAAA,EACrC;AAAA,EACA,IAAI,YAAY,eAAe;AAAA,IAC7B,KAAK,cAAc,YAAY,MAAgB,gBAAT;AAAA,MACpC,4BAA4B,WAAW,GACpC,cAAc,YAAY;AAAA;AAEnC,SAAS,2BAA2B,CAAC,cAAc;AAAA,EACjD,QAAQ,aAAa;AAAA,SACd;AAAA,SACA;AAAA,SACA;AAAA,MACH,yCAAyC,YAAY;AAAA,MACrD,aAAa,QAAQ,QACnB,4BAA4B,GAAG,cAAc,aAAa,MAAM;AAAA,MAClE;AAAA,SACG;AAAA,MACH,yCAAyC,YAAY;AAAA,MACrD;AAAA,SACG;AAAA,MACH,yCAAyC,YAAY;AAAA,MACrD;AAAA,SACG;AAAA,MACH,IAAI,WAAW,aAAa;AAAA,MACnB,aAAa,kBAAtB,QACA,SAAS,cAAc,MACb,aAAa,WAAtB,QAAuC,aAAa,OAAO,QAA3B,OAC3B,SAAS,eAAe,IAC1B,4CAA4C,YAAY,KACxD,yCAAyC,YAAY;AAAA,MACzD;AAAA;AAAA,MAEA,yCAAyC,YAAY;AAAA;AAAA;AAG3D,SAAS,2CAA2C,CAAC,aAAa;AAAA,EAChE,IAAI,YAAY,YAAY;AAAA,EAC5B,KAAW,YAAY,QAAQ,QAA3B,GAAgC;AAAA,IAClC,IAAa,cAAT;AAAA,MACF,SAAS,IAAI,EAAG,IAAI,UAAU,QAAQ,KAAK;AAAA,QACzC,IAAI,gBAAgB,UAAU;AAAA,QAC9B,aAAa;AAAA,QACb,qDACE,eACA,WACF;AAAA,MACF;AAAA,IACF,wBAAwB,WAAW;AAAA,EACrC;AAAA,EACA,KAAK,cAAc,YAAY,MAAgB,gBAAT,QAAwB;AAAA,IAC5D,YAAY;AAAA,IACZ,QAAQ,UAAU;AAAA,WACX;AAAA,WACA;AAAA,WACA;AAAA,QACH,4BAA4B,GAAG,WAAW,UAAU,MAAM;AAAA,QAC1D,4CAA4C,SAAS;AAAA,QACrD;AAAA,WACG;AAAA,QACH,IAAI,UAAU;AAAA,QACd,EAAE,cAAc,MACZ,EAAE,eAAe,IACnB,4CAA4C,SAAS;AAAA,QACvD;AAAA;AAAA,QAEA,4CAA4C,SAAS;AAAA;AAAA,IAEzD,cAAc,YAAY;AAAA,EAC5B;AAAA;AAEF,SAAS,oDAAoD,CAC3D,oBACA,wBACA;AAAA,EACA,MAAgB,eAAT,QAAuB;AAAA,IAC5B,IAAI,QAAQ;AAAA,IACZ,QAAQ,MAAM;AAAA,WACP;AAAA,WACA;AAAA,WACA;AAAA,QACH,4BAA4B,GAAG,OAAO,sBAAsB;AAAA,QAC5D;AAAA,WACG;AAAA,WACA;AAAA,QACH,IACW,MAAM,kBAAf,QACS,MAAM,cAAc,cAA7B,MACA;AAAA,UACA,IAAI,QAAQ,MAAM,cAAc,UAAU;AAAA,UAClC,SAAR,QAAiB,MAAM;AAAA,QACzB;AAAA,QACA;AAAA,WACG;AAAA,QACH,aAAa,MAAM,cAAc,KAAK;AAAA;AAAA,IAE1C,QAAQ,MAAM;AAAA,IACd,IAAa,UAAT;AAAA,MAAiB,MAAM,SAAS,OAAS,aAAa;AAAA,IAExD;AAAA;AAAA,QAAG,KAAK,QAAQ,mBAA6B,eAAT,QAAuB;AAAA,UACzD,QAAQ;AAAA,UACR,MAAoB,SACE,QAApB,gBAAc;AAAA,UAChB,wBAAwB,KAAK;AAAA,UAC7B,IAAI,UAAU,OAAO;AAAA,YACnB,aAAa;AAAA,YACb;AAAA,UACF;AAAA,UACA,IAAa,YAAT,MAAkB;AAAA,YACpB,QAAQ,SAAS;AAAA,YACjB,aAAa;AAAA,YACb;AAAA,UACF;AAAA,UACA,aAAa;AAAA,QACf;AAAA,EACJ;AAAA;AAiDF,SAAS,iBAAiB,GAAG;AAAA,EAC3B,QAAc,mBAAmB,OAA1B,KAAsC,kCAAN,IACnC,gCAAgC,CAAC,gCACxB,sBAAqB,MAA9B,OACE,sBAAsB,IACtB,sBAAsB;AAAA;AAE9B,SAAS,mBAAmB,GAAG;AAAA,EAC7B,IAAU,+BAAN;AAAA,IACF,KAAW,gCAAgC,eAAvC,KAAqD,aAAa;AAAA,MACpE,IAAI,OAAO;AAAA,MACX,+BAA+B;AAAA,OACxB,6BAA6B,aAApC,MACG,6BAA6B;AAAA,MAChC,6BAA6B;AAAA,IAC/B,EAAO;AAAA,mCAA6B;AAAA,EACtC,OAAO,2BAA2B;AAAA,EACzB,SAAT,SAAkB,KAAK,SAAS;AAAA,EAChC,OAAO;AAAA;AAET,SAAS,qBAAqB,CAAC,OAAM,OAAO,MAAM;AAAA,EAChD,IACG,UAAS,uBACD,kCAAN,KACO,kCAAN,MACK,MAAK,wBAAd;AAAA,IAEA,kBAAkB,OAAM,CAAC,GACvB,kBACE,OACA,+BACA,4BACA,KACF;AAAA,EACJ,kBAAkB,OAAM,IAAI;AAAA,EAC5B,KAAW,mBAAmB,OAA1B,KAAgC,UAAS;AAAA,IAC3C,UAAS,wBACC,mBAAmB,OAA1B,MACE,6CAA6C,OAC1C,iCAAN,KACE,kBACE,OACA,+BACA,4BACA,KACF,IACF,sBAAsB,KAAI;AAAA;AAEhC,SAAS,iBAAiB,CAAC,eAAe,OAAO,WAAW;AAAA,EAC1D,KAAW,mBAAmB,OAA1B;AAAA,IAA8B,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,EACzE,IAAI,kBACC,CAAC,cACO,QAAQ,SAAf,MACO,QAAQ,cAAc,kBAA7B,KACF,0BAA0B,eAAe,KAAK,GAChD,aAAa,kBACT,qBAAqB,eAAe,KAAK,IACzC,eAAe,eAAe,OAAO,IAAE,GAC3C,sBAAsB;AAAA,EACxB,GAAG;AAAA,IACD,IAAU,eAAN,GAAkB;AAAA,MACpB,oCACE,CAAC,mBACD,kBAAkB,eAAe,OAAO,GAAG,KAAE;AAAA,MAC/C;AAAA,IACF,EAAO;AAAA,MACL,YAAY,cAAc,QAAQ;AAAA,MAClC,IACE,uBACA,CAAC,qCAAqC,SAAS,GAC/C;AAAA,QACA,aAAa,eAAe,eAAe,OAAO,KAAE;AAAA,QACpD,sBAAsB;AAAA,QACtB;AAAA,MACF;AAAA,MACA,IAAU,eAAN,GAAkB;AAAA,QACpB,sBAAsB;AAAA,QACtB,IAAI,cAAc,6BAA6B;AAAA,UAC7C,IAAI,2BAA2B;AAAA,QAE/B;AAAA,UAAC,2BAA2B,cAAc,eAAe,YACtD,2BACO,6BAAN,IACI,2BACA,2BAA2B,YACzB,YACA;AAAA,QACZ,IAAU,6BAAN,GAAgC;AAAA,UAClC,QAAQ;AAAA,UACR,GAAG;AAAA,YACD,IAAI,QAAO;AAAA,YACX,aAAa;AAAA,YACb,IAAI,oBAAoB,MAAK,QAAQ,cAAc;AAAA,YACnD,sBACG,kBAAkB,OAAM,wBAAwB,EAAE,SAAS;AAAA,YAC9D,2BAA2B,eACzB,OACA,0BACA,KACF;AAAA,YACA,IAAU,6BAAN,GAAgC;AAAA,cAClC,IACE,2CACA,CAAC,mBACD;AAAA,gBACA,MAAK,8BAA8B;AAAA,gBACnC,6CACE;AAAA,gBACF,aAAa;AAAA,gBACb;AAAA,cACF;AAAA,cACA,sBAAsB;AAAA,cACtB,sCAAsC;AAAA,cAC7B,wBAAT,SACY,wCAAT,OACI,sCAAsC,sBACvC,oCAAoC,KAAK,MACvC,qCACA,mBACF;AAAA,YACR;AAAA,YACA,aAAa;AAAA,UACf;AAAA,UACA,sBAAsB;AAAA,UACtB,IAAU,eAAN;AAAA,YAAkB;AAAA,QACxB;AAAA,MACF;AAAA,MACA,IAAU,eAAN,GAAkB;AAAA,QACpB,kBAAkB,eAAe,CAAC;AAAA,QAClC,kBAAkB,eAAe,OAAO,GAAG,IAAE;AAAA,QAC7C;AAAA,MACF;AAAA,MACA,GAAG;AAAA,QACD,kBAAkB;AAAA,QAClB,sBAAsB;AAAA,QACtB,QAAQ;AAAA,eACD;AAAA,eACA;AAAA,YACH,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,eACpC;AAAA,YACH,KAAK,QAAQ,aAAa;AAAA,cAAO;AAAA,eAC9B;AAAA,YACH,kBACE,iBACA,OACA,4BACA,CAAC,0CACH;AAAA,YACA;AAAA,eACG;AAAA,YACH,sCAAsC;AAAA,YACtC;AAAA,eACG;AAAA,eACA;AAAA,YACH;AAAA;AAAA,YAEA,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA;AAAA,QAE3C,KACG,QAAQ,cAAc,UACrB,aAAa,+BAA+B,MAAM,IAAI,GACxD,KAAK,aACL;AAAA,UACA,kBACE,iBACA,OACA,4BACA,CAAC,0CACH;AAAA,UACA,IAAU,aAAa,iBAAiB,GAAG,IAAE,MAAzC;AAAA,YAA4C;AAAA,UAChD,sBAAsB;AAAA,UACtB,gBAAgB,gBAAgB,gBAC9B,oBAAoB,KAClB,MACA,iBACA,WACA,qCACA,2BACA,mDACA,OACA,4BACA,2CACA,mCACA,4CACA,qBACA,aACA,IACA,CACF,GACA,UACF;AAAA,UACA;AAAA,QACF;AAAA,QACA,oBACE,iBACA,WACA,qCACA,2BACA,mDACA,OACA,4BACA,2CACA,mCACA,4CACA,qBACA,MACA,IACA,CACF;AAAA,MACF;AAAA;AAAA,IAEF;AAAA,EACF,SAAS;AAAA,EACT,sBAAsB,aAAa;AAAA;AAErC,SAAS,mBAAmB,CAC1B,OACA,cACA,mBACA,aACA,6BACA,OACA,aACA,cACA,qBACA,0BACA,YACA,uBACA,0BACA,wBACA;AAAA,EACA,MAAK,gBAAgB;AAAA,EACrB,wBAAwB,aAAa;AAAA,EACrC,IACE,wBAAwB,SACV,wBAAwB,cAAtC,UACA;AAAA,IACA,wBAAwB;AAAA,MACtB,aAAa;AAAA,MACb,OAAO;AAAA,MACP,UAAU;AAAA,MACV,UAAU;AAAA,MACV,iBAAiB,CAAC;AAAA,MAClB,kBAAkB;AAAA,MAClB,0BAA0B;AAAA,MAC1B,WAAW;AAAA,IACb;AAAA,IACA,iCACE,cACA,OACA,qBACF;AAAA,IACA,IAAI,iBACD,QAAQ,cAAc,QACnB,+BAA+B,IAAI,KAClC,QAAQ,aAAa,QACpB,iCAAiC,IAAI,IACrC;AAAA,IACR,gBAAgB,uBACd,uBACA,aACF;AAAA,IACA,IAAa,kBAAT,MAAwB;AAAA,MAC1B,sBAAsB;AAAA,MACtB,MAAK,sBAAsB,cACzB,WAAW,KACT,MACA,OACA,cACA,OACA,mBACA,aACA,6BACA,aACA,cACA,qBACA,YACA,uBACA,MACA,0BACA,sBACF,CACF;AAAA,MACA,kBAAkB,OAAM,OAAO,aAAa,CAAC,wBAAwB;AAAA,MACrE;AAAA,IACF;AAAA,EACF;AAAA,EACA,WACE,OACA,cACA,OACA,mBACA,aACA,6BACA,aACA,cACA,mBACF;AAAA;AAEF,SAAS,oCAAoC,CAAC,cAAc;AAAA,EAC1D,SAAS,OAAO,iBAAkB;AAAA,IAChC,IAAI,MAAM,KAAK;AAAA,IACf,KACS,QAAN,KAAoB,QAAP,MAAqB,QAAP,OAC5B,KAAK,QAAQ,UACX,MAAM,KAAK,aACJ,QAAT,SAAkB,MAAM,IAAI,QAAkB,QAAT;AAAA,MAErC,SAAS,IAAI,EAAG,IAAI,IAAI,QAAQ,KAAK;AAAA,QACnC,IAAI,QAAQ,IAAI,IACd,cAAc,MAAM;AAAA,QACtB,QAAQ,MAAM;AAAA,QACd,IAAI;AAAA,UACF,IAAI,CAAC,SAAS,YAAY,GAAG,KAAK;AAAA,YAAG,OAAO;AAAA,UAC5C,OAAO,OAAO;AAAA,UACd,OAAO;AAAA;AAAA,MAEX;AAAA,IACF,MAAM,KAAK;AAAA,IACX,IAAI,KAAK,eAAe,SAAkB,QAAT;AAAA,MAC9B,IAAI,SAAS,MAAQ,OAAO;AAAA,IAC1B;AAAA,MACH,IAAI,SAAS;AAAA,QAAc;AAAA,MAC3B,MAAgB,KAAK,YAAd,QAAyB;AAAA,QAC9B,IAAa,KAAK,WAAd,QAAwB,KAAK,WAAW;AAAA,UAAc,OAAO;AAAA,QACjE,OAAO,KAAK;AAAA,MACd;AAAA,MACA,KAAK,QAAQ,SAAS,KAAK;AAAA,MAC3B,OAAO,KAAK;AAAA;AAAA,EAEhB;AAAA,EACA,OAAO;AAAA;AAET,SAAS,iBAAiB,CACxB,OACA,gBACA,aACA,sBACA;AAAA,EACA,kBAAkB,CAAC;AAAA,EACnB,kBAAkB,CAAC;AAAA,EACnB,MAAK,kBAAkB;AAAA,EACvB,MAAK,eAAe,CAAC;AAAA,EACrB,yBAAyB,MAAK,aAAa;AAAA,EAC3C,uBAAuB,MAAK;AAAA,EAC5B,SAAS,QAAQ,eAAgB,IAAI,SAAS;AAAA,IAC5C,IAAI,UAAU,KAAK,MAAM,KAAK,GAC5B,OAAO,KAAK;AAAA,IACd,qBAAqB,WAAW;AAAA,IAChC,SAAS,CAAC;AAAA,EACZ;AAAA,EACM,gBAAN,KACE,wBAAwB,OAAM,aAAa,cAAc;AAAA;AAE7D,SAAS,eAAe,GAAG;AAAA,EACzB,QAAc,mBAAmB,OAA1B,KACF,8BAA8B,GAAG,KAAE,GAAG,SACvC;AAAA;AAEN,SAAS,wBAAwB,GAAG;AAAA,EAClC,IAAa,mBAAT,MAAyB;AAAA,IAC3B,IAAU,kCAAN;AAAA,MACF,IAAI,kBAAkB,eAAe;AAAA,IAErC;AAAA,MAAC,kBAAkB,gBAChB,wBAAwB,4BAA4B,MACrD,mBAAmB,eAAe,GACjC,kBAAkB,MAClB,yBAAyB,GACzB,kBAAkB;AAAA,IACvB,MAAgB,oBAAT;AAAA,MACL,sBAAsB,gBAAgB,WAAW,eAAe,GAC7D,kBAAkB,gBAAgB;AAAA,IACvC,iBAAiB;AAAA,EACnB;AAAA;AAEF,SAAS,iBAAiB,CAAC,OAAM,OAAO;AAAA,EACtC,IAAI,gBAAgB,MAAK;AAAA,EAClB,kBAAP,OACI,MAAK,gBAAgB,IAAK,cAAc,aAAa;AAAA,EACzD,gBAAgB,MAAK;AAAA,EACZ,kBAAT,SACI,MAAK,sBAAsB,MAAO,cAAc;AAAA,EACpD,sBAAsB;AAAA,EACtB,yBAAyB;AAAA,EACzB,qBAAqB;AAAA,EACrB,iBAAiB,gBAAgB,qBAAqB,MAAK,SAAS,IAAI;AAAA,EACxE,gCAAgC;AAAA,EAChC,gCAAgC;AAAA,EAChC,4BAA4B;AAAA,EAC5B,6CAA6C;AAAA,EAC7C,mCAAmC,0BAA0B,OAAM,KAAK;AAAA,EACxE,0CAA0C;AAAA,EAC1C,oCACE,6BACA,gCACA,4CACA,iCACA,+BACE;AAAA,EACJ,sCAAsC,qCACpC;AAAA,EACF,oDAAoD;AAAA,GAC7C,QAAQ,OAAf,MAAsB,SAAS,QAAQ;AAAA,EACvC,IAAI,oBAAoB,MAAK;AAAA,EAC7B,IAAU,sBAAN;AAAA,IACF,KACE,QAAO,MAAK,eAAe,qBAAqB,MAChD,IAAI,qBAEJ;AAAA,MACA,IAAI,UAAU,KAAK,MAAM,iBAAiB,GACxC,OAAO,KAAK;AAAA,MACd,SAAS,MAAK;AAAA,MACd,qBAAqB,CAAC;AAAA,IACxB;AAAA,EACF,uBAAuB;AAAA,EACvB,gCAAgC;AAAA,EAChC,OAAO;AAAA;AAET,SAAS,WAAW,CAAC,OAAM,aAAa;AAAA,EACtC,0BAA0B;AAAA,EAC1B,sBAAqB,IAAI;AAAA,EACzB,gBAAgB,qBAAqB,gBAAgB,2BAC/C,cAAc,qBAAqB,GACpC,gCAAgC,KACjC,gBAAgB,4BACZ,cAAc,qBAAqB,GACpC,gCAAgC,KAChC,gCACC,gBAAgB,8BACZ,IACS,gBAAT,QACe,OAAO,gBAApB,YACe,OAAO,YAAY,SAAlC,aACA,IACA;AAAA,EACd,4BAA4B;AAAA,EACnB,mBAAT,SACI,+BAA+B,GACjC,iBACE,OACA,2BAA2B,aAAa,MAAK,OAAO,CACtD;AAAA;AAEJ,SAAS,4BAA4B,GAAG;AAAA,EACtC,IAAI,UAAU,2BAA2B;AAAA,EACzC,OAAgB,YAAT,OACH,QACC,gCAAgC,aAC/B,gCACS,kBAAT,OACE,OACA,SACD,gCAAgC,cAC7B,kCACK,gCAAgC,eAAvC,IACA,YAAY,gBACZ;AAAA;AAEV,SAAS,cAAc,GAAG;AAAA,EACxB,IAAI,iBAAiB,sBAAqB;AAAA,EAC1C,sBAAqB,IAAI;AAAA,EACzB,OAAgB,mBAAT,OAA0B,wBAAwB;AAAA;AAE3D,SAAS,mBAAmB,GAAG;AAAA,EAC7B,IAAI,sBAAsB,sBAAqB;AAAA,EAC/C,sBAAqB,IAAI;AAAA,EACzB,OAAO;AAAA;AAET,SAAS,+BAA+B,GAAG;AAAA,EACzC,+BAA+B;AAAA,EAC/B,+CACI,gCAAgC,aAChC,iCACS,2BAA2B,YAApC,SACD,mCAAmC;AAAA,GAC9B,iCAAiC,eAAxC,MACQ,4CAA4C,eAAnD,KACS,uBAAT,QACA,kBACE,oBACA,+BACA,4BACA,KACF;AAAA;AAEJ,SAAS,cAAc,CAAC,OAAM,OAAO,4BAA4B;AAAA,EAC/D,IAAI,uBAAuB;AAAA,EAC3B,oBAAoB;AAAA,EACpB,IAAI,iBAAiB,eAAe,GAClC,sBAAsB,oBAAoB;AAAA,EAC5C,IAAI,uBAAuB,SAAQ,kCAAkC;AAAA,IAClE,4BAA4B,MAAO,kBAAkB,OAAM,KAAK;AAAA,EACnE,QAAQ;AAAA,EACR,IAAI,aAAa;AAAA,EACjB;AAAA,IAAG;AAAA,MACD,IAAI;AAAA,QACF,IAAU,kCAAN,KAAgD,mBAAT,MAAyB;AAAA,UAClE,IAAI,aAAa,gBACf,cAAc;AAAA,UAChB,QAAQ;AAAA,iBACD;AAAA,cACH,yBAAyB;AAAA,cACzB,aAAa;AAAA,cACb;AAAA,iBACG;AAAA,iBACA;AAAA,iBACA;AAAA,iBACA;AAAA,cACM,2BAA2B,YAApC,SAAgD,QAAQ;AAAA,cACxD,IAAI,SAAS;AAAA,cACb,gCAAgC;AAAA,cAChC,4BAA4B;AAAA,cAC5B,uBAAuB,OAAM,YAAY,aAAa,MAAM;AAAA,cAC5D,IACE,8BACA,kCACA;AAAA,gBACA,aAAa;AAAA,gBACb;AAAA,cACF;AAAA,cACA;AAAA;AAAA,cAEC,SAAS,+BACP,gCAAgC,GAChC,4BAA4B,MAC7B,uBAAuB,OAAM,YAAY,aAAa,MAAM;AAAA;AAAA,QAEpE;AAAA,QACA,aAAa;AAAA,QACb,aAAa;AAAA,QACb;AAAA,QACA,OAAO,iBAAiB;AAAA,QACxB,YAAY,OAAM,eAAe;AAAA;AAAA,WAE9B;AAAA,EACP,SAAS,MAAK;AAAA,EACd,wBAAwB,4BAA4B;AAAA,EACpD,mBAAmB;AAAA,EACnB,sBAAqB,IAAI;AAAA,EACzB,sBAAqB,IAAI;AAAA,EAChB,mBAAT,SACI,qBAAqB,MACtB,gCAAgC,GACjC,gCAAgC;AAAA,EAClC,OAAO;AAAA;AAET,SAAS,YAAY,GAAG;AAAA,EACtB,MAAgB,mBAAT;AAAA,IAA2B,kBAAkB,cAAc;AAAA;AAEpE,SAAS,oBAAoB,CAAC,OAAM,OAAO;AAAA,EACzC,IAAI,uBAAuB;AAAA,EAC3B,oBAAoB;AAAA,EACpB,IAAI,iBAAiB,eAAe,GAClC,sBAAsB,oBAAoB;AAAA,EAC5C,uBAAuB,SAAQ,kCAAkC,SAC3D,4BAA4B,MAC7B,qCAAqC,IAAI,IAAI,KAC9C,kBAAkB,OAAM,KAAK,KAC5B,mCAAmC,0BAClC,OACA,KACF;AAAA,EACJ;AAAA,IAAG;AAAA,MACD,IAAI;AAAA,QACF,IAAU,kCAAN,KAAgD,mBAAT,MAAyB;AAAA,UAClE,QAAQ;AAAA,UACR,IAAI,cAAc;AAAA,UAClB;AAAA,YAAG,QAAQ;AAAA,mBACJ;AAAA,gBACH,gCAAgC;AAAA,gBAChC,4BAA4B;AAAA,gBAC5B,uBAAuB,OAAM,OAAO,aAAa,CAAC;AAAA,gBAClD;AAAA,mBACG;AAAA,mBACA;AAAA,gBACH,IAAI,mBAAmB,WAAW,GAAG;AAAA,kBACnC,gCAAgC;AAAA,kBAChC,4BAA4B;AAAA,kBAC5B,0BAA0B,KAAK;AAAA,kBAC/B;AAAA,gBACF;AAAA,gBACA,QAAQ,QAAS,GAAG;AAAA,kBACX,kCAAN,KACO,kCAAN,KACA,uBAAuB,UACtB,gCAAgC;AAAA,kBACnC,sBAAsB,KAAI;AAAA;AAAA,gBAE5B,YAAY,KAAK,OAAO,KAAK;AAAA,gBAC7B;AAAA,mBACG;AAAA,gBACH,gCAAgC;AAAA,gBAChC;AAAA,mBACG;AAAA,gBACH,gCAAgC;AAAA,gBAChC;AAAA,mBACG;AAAA,gBACH,mBAAmB,WAAW,KACxB,gCAAgC,GACjC,4BAA4B,MAC7B,0BAA0B,KAAK,MAC7B,gCAAgC,GACjC,4BAA4B,MAC7B,uBAAuB,OAAM,OAAO,aAAa,CAAC;AAAA,gBACtD;AAAA,mBACG;AAAA,gBACH,IAAI,WAAW;AAAA,gBACf,QAAQ,eAAe;AAAA,uBAChB;AAAA,oBACH,WAAW,eAAe;AAAA,uBACvB;AAAA,uBACA;AAAA,oBACH,IAAI,YAAY;AAAA,oBAChB,IACE,WACI,gBAAgB,QAAQ,IACxB,UAAU,UAAU,UACxB;AAAA,sBACA,gCAAgC;AAAA,sBAChC,4BAA4B;AAAA,sBAC5B,IAAI,UAAU,UAAU;AAAA,sBACxB,IAAa,YAAT;AAAA,wBAAkB,iBAAiB;AAAA,sBAClC;AAAA,wBACH,IAAI,cAAc,UAAU;AAAA,wBACnB,gBAAT,QACM,iBAAiB,aACnB,mBAAmB,WAAW,KAC7B,iBAAiB;AAAA;AAAA,sBAExB;AAAA,oBACF;AAAA;AAAA,gBAEJ,gCAAgC;AAAA,gBAChC,4BAA4B;AAAA,gBAC5B,uBAAuB,OAAM,OAAO,aAAa,CAAC;AAAA,gBAClD;AAAA,mBACG;AAAA,gBACH,gCAAgC;AAAA,gBAChC,4BAA4B;AAAA,gBAC5B,uBAAuB,OAAM,OAAO,aAAa,CAAC;AAAA,gBAClD;AAAA,mBACG;AAAA,gBACH,yBAAyB;AAAA,gBACzB,+BAA+B;AAAA,gBAC/B;AAAA;AAAA,gBAEA,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA;AAAA,QAE7C;AAAA,QACA,8BAA8B;AAAA,QAC9B;AAAA,QACA,OAAO,iBAAiB;AAAA,QACxB,YAAY,OAAM,eAAe;AAAA;AAAA,WAE9B;AAAA,EACP,wBAAwB,4BAA4B;AAAA,EACpD,sBAAqB,IAAI;AAAA,EACzB,sBAAqB,IAAI;AAAA,EACzB,mBAAmB;AAAA,EACnB,IAAa,mBAAT;AAAA,IAAyB,OAAO;AAAA,EACpC,qBAAqB;AAAA,EACrB,gCAAgC;AAAA,EAChC,gCAAgC;AAAA,EAChC,OAAO;AAAA;AAET,SAAS,6BAA6B,GAAG;AAAA,EACvC,MAAgB,mBAAT,QAA2B,CAAC,YAAY;AAAA,IAC7C,kBAAkB,cAAc;AAAA;AAEpC,SAAS,iBAAiB,CAAC,YAAY;AAAA,EACrC,IAAI,OAAO,UAAU,WAAW,WAAW,YAAY,oBAAoB;AAAA,EAC3E,WAAW,gBAAgB,WAAW;AAAA,EAC7B,SAAT,OAAgB,mBAAmB,UAAU,IAAK,iBAAiB;AAAA;AAErE,SAAS,yBAAyB,CAAC,YAAY;AAAA,EAC7C,IAAI,OAAO;AAAA,EACX,IAAI,UAAU,KAAK;AAAA,EACnB,QAAQ,KAAK;AAAA,SACN;AAAA,SACA;AAAA,MACH,OAAO,wBACL,SACA,MACA,KAAK,cACL,KAAK,MACA,WACL,6BACF;AAAA,MACA;AAAA,SACG;AAAA,MACH,OAAO,wBACL,SACA,MACA,KAAK,cACL,KAAK,KAAK,QACV,KAAK,KACL,6BACF;AAAA,MACA;AAAA,SACG;AAAA,MACH,mBAAmB,IAAI;AAAA;AAAA,MAEvB,sBAAsB,SAAS,IAAI,GAChC,OAAO,iBACN,oBAAoB,MAAM,oBAAoB,GAC/C,OAAO,UAAU,SAAS,MAAM,oBAAoB;AAAA;AAAA,EAE3D,WAAW,gBAAgB,WAAW;AAAA,EAC7B,SAAT,OAAgB,mBAAmB,UAAU,IAAK,iBAAiB;AAAA;AAErE,SAAS,sBAAsB,CAC7B,OACA,YACA,aACA,iBACA;AAAA,EACA,wBAAwB,4BAA4B;AAAA,EACpD,mBAAmB,UAAU;AAAA,EAC7B,kBAAkB;AAAA,EAClB,yBAAyB;AAAA,EACzB,IAAI,cAAc,WAAW;AAAA,EAC7B,IAAI;AAAA,IACF,IACE,eACE,OACA,aACA,YACA,aACA,6BACF,GACA;AAAA,MACA,+BAA+B;AAAA,MAC/B,iBACE,OACA,2BAA2B,aAAa,MAAK,OAAO,CACtD;AAAA,MACA,iBAAiB;AAAA,MACjB;AAAA,IACF;AAAA,IACA,OAAO,OAAO;AAAA,IACd,IAAa,gBAAT;AAAA,MAAsB,MAAQ,iBAAiB,aAAc;AAAA,IACjE,+BAA+B;AAAA,IAC/B,iBACE,OACA,2BAA2B,aAAa,MAAK,OAAO,CACtD;AAAA,IACA,iBAAiB;AAAA,IACjB;AAAA;AAAA,EAEF,IAAI,WAAW,QAAQ,OAAO;AAAA,IAC5B,IAAI,eAAqB,oBAAN;AAAA,MAAuB,QAAO;AAAA,IAC5C,SACH,qCACO,gCAAgC,eAAvC;AAAA,MAEA,QAAO;AAAA,IACJ,SACD,6CAA6C,QAAO,MAChD,oBAAN,KACQ,oBAAN,KACM,oBAAN,KACM,oBAAN;AAAA,MAED,kBAAkB,2BAA2B,SACnC,oBAAT,QACS,gBAAgB,QAAvB,OACC,gBAAgB,SAAS;AAAA,IAChC,iBAAiB,YAAY,KAAI;AAAA,EACnC,EAAO;AAAA,uBAAmB,UAAU;AAAA;AAEtC,SAAS,kBAAkB,CAAC,YAAY;AAAA,EACtC,IAAI,gBAAgB;AAAA,EACpB,GAAG;AAAA,IACD,KAAW,cAAc,QAAQ,WAA7B,GAAqC;AAAA,MACvC,iBACE,eACA,0CACF;AAAA,MACA;AAAA,IACF;AAAA,IACA,aAAa,cAAc;AAAA,IAC3B,IAAI,OAAO,aACT,cAAc,WACd,eACA,oBACF;AAAA,IACA,IAAa,SAAT,MAAe;AAAA,MACjB,iBAAiB;AAAA,MACjB;AAAA,IACF;AAAA,IACA,gBAAgB,cAAc;AAAA,IAC9B,IAAa,kBAAT,MAAwB;AAAA,MAC1B,iBAAiB;AAAA,MACjB;AAAA,IACF;AAAA,IACA,iBAAiB,gBAAgB;AAAA,EACnC,SAAkB,kBAAT;AAAA,EACH,iCAAN,MAAuC,+BAA+B;AAAA;AAExE,SAAS,gBAAgB,CAAC,YAAY,cAAc;AAAA,EAClD,GAAG;AAAA,IACD,IAAI,OAAO,WAAW,WAAW,WAAW,UAAU;AAAA,IACtD,IAAa,SAAT,MAAe;AAAA,MACjB,KAAK,SAAS;AAAA,MACd,iBAAiB;AAAA,MACjB;AAAA,IACF;AAAA,IACA,OAAO,WAAW;AAAA,IACT,SAAT,SACI,KAAK,SAAS,OAAS,KAAK,eAAe,GAAK,KAAK,YAAY;AAAA,IACrE,IACE,CAAC,iBACC,aAAa,WAAW,SAAmB,eAAT,OACpC;AAAA,MACA,iBAAiB;AAAA,MACjB;AAAA,IACF;AAAA,IACA,iBAAiB,aAAa;AAAA,EAChC,SAAkB,eAAT;AAAA,EACT,+BAA+B;AAAA,EAC/B,iBAAiB;AAAA;AAEnB,SAAS,UAAU,CACjB,OACA,cACA,OACA,mBACA,aACA,6BACA,aACA,cACA,qBACA;AAAA,EACA,MAAK,sBAAsB;AAAA,EAC3B;AAAA,IAAG,oBAAoB;AAAA,SACV,yBAAN;AAAA,EACP,KAAW,mBAAmB,OAA1B;AAAA,IAA8B,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,EACzE,IAAa,iBAAT,MAAuB;AAAA,IACzB,IAAI,iBAAiB,MAAK;AAAA,MAAS,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,IAC1E,8BAA8B,aAAa,QAAQ,aAAa;AAAA,IAChE,+BAA+B;AAAA,IAC/B,iBACE,OACA,OACA,6BACA,aACA,cACA,mBACF;AAAA,IACA,UAAS,uBACL,iBAAiB,qBAAqB,MACvC,gCAAgC;AAAA,IACnC,sBAAsB;AAAA,IACtB,qBAAqB;AAAA,IACrB,sBAAsB;AAAA,IACtB,+BAA+B;AAAA,IAC/B,4BAA4B;AAAA,IAC5B,2BAA2B;AAAA,KACpB,aAAa,eAAe,WAAnC,MACO,aAAa,QAAQ,WAA5B,KACM,MAAK,eAAe,MACrB,MAAK,mBAAmB,GACzB,mBAAmB,kBAAkB,QAAS,GAAG;AAAA,MAC/C,oBAAoB;AAAA,MACpB,OAAO;AAAA,KACR,MACC,MAAK,eAAe,MAAQ,MAAK,mBAAmB;AAAA,IAC1D,qBAA2B,aAAa,QAAQ,WAA5B;AAAA,IACpB,KAAW,aAAa,eAAe,WAAnC,KAA6C,mBAAmB;AAAA,MAClE,oBAAoB,sBAAqB;AAAA,MACzC,sBAAqB,IAAI;AAAA,MACzB,cAAc,wBAAwB;AAAA,MACtC,wBAAwB,IAAI;AAAA,MAC5B,cAAc;AAAA,MACd,oBAAoB;AAAA,MACpB,IAAI;AAAA,QACF,4BAA4B,OAAM,cAAc,KAAK;AAAA,gBACrD;AAAA,QACC,mBAAmB,aACjB,wBAAwB,IAAI,aAC5B,sBAAqB,IAAI;AAAA;AAAA,IAEhC;AAAA,IACA,uBAAuB;AAAA,IACvB,qBAAqB;AAAA,IACrB,mBAAmB;AAAA,IACnB,iBAAiB;AAAA,EACnB;AAAA;AAEF,SAAS,oBAAoB,GAAG;AAAA,EAC9B,IAAU,yBAAN,GAA4B;AAAA,IAC9B,uBAAuB;AAAA,IACvB,IAAI,QAAO,oBACT,eAAe,qBACf,yBAA+B,aAAa,QAAQ,WAA5B;AAAA,IAC1B,KAAW,aAAa,eAAe,WAAnC,KAA6C,uBAAuB;AAAA,MACtE,wBAAwB,sBAAqB;AAAA,MAC7C,sBAAqB,IAAI;AAAA,MACzB,IAAI,mBAAmB,wBAAwB;AAAA,MAC/C,wBAAwB,IAAI;AAAA,MAC5B,IAAI,uBAAuB;AAAA,MAC3B,oBAAoB;AAAA,MACpB,IAAI;AAAA,QACF,6BAA6B,cAAc,KAAI;AAAA,QAC/C,IAAI,4BAA4B,sBAC9B,iBAAiB,qBAAqB,MAAK,aAAa,GACxD,mBAAmB,0BAA0B,aAC7C,sBAAsB,0BAA0B;AAAA,QAClD,IACE,mBAAmB,oBACnB,oBACA,iBAAiB,iBACjB,aACE,iBAAiB,cAAc,iBAC/B,gBACF,GACA;AAAA,UACA,IACW,wBAAT,QACA,yBAAyB,gBAAgB,GACzC;AAAA,YACA,MAAgC,OACJ,QAApB;AAAA,YACG,QAAN,cAAc,MAAM;AAAA,YACzB,IAAI,oBAAoB;AAAA,cACrB,iBAAiB,iBAAiB,OAChC,iBAAiB,eAAe,KAAK,IACpC,KACA,iBAAiB,MAAM,MACzB;AAAA,YACC;AAAA,cACH,IAAI,MAAM,iBAAiB,iBAAiB,UAC1C,MAAO,OAAO,IAAI,eAAgB;AAAA,cACpC,IAAI,IAAI,cAAc;AAAA,gBACpB,IAAI,YAAY,IAAI,aAAa,GAC/B,SAAS,iBAAiB,YAAY,QACtC,iBAAiB,KAAK,IAAI,oBAAoB,OAAO,MAAM,GAC3D,eACa,oBAAoB,QAA1B,YACD,iBACA,KAAK,IAAI,oBAAoB,KAAK,MAAM;AAAA,gBAChD,CAAC,UAAU,UACT,iBAAiB,iBACf,iBAAiB,cAClB,eAAe,gBACf,iBAAiB;AAAA,gBACpB,IAAI,cAAc,0BACd,kBACA,cACF,GACA,YAAY,0BACV,kBACA,YACF;AAAA,gBACF,IACE,eACA,cACO,UAAU,eAAhB,KACC,UAAU,eAAe,YAAY,QACrC,UAAU,iBAAiB,YAAY,UACvC,UAAU,cAAc,UAAU,QAClC,UAAU,gBAAgB,UAAU,SACtC;AAAA,kBACA,IAAI,QAAQ,IAAI,YAAY;AAAA,kBAC5B,MAAM,SAAS,YAAY,MAAM,YAAY,MAAM;AAAA,kBACnD,UAAU,gBAAgB;AAAA,kBAC1B,iBAAiB,gBACZ,UAAU,SAAS,KAAK,GACzB,UAAU,OAAO,UAAU,MAAM,UAAU,MAAM,MAChD,MAAM,OAAO,UAAU,MAAM,UAAU,MAAM,GAC9C,UAAU,SAAS,KAAK;AAAA,gBAC9B;AAAA,cACF;AAAA;AAAA,UAEJ;AAAA,UACA,MAAM,CAAC;AAAA,UACP,KACE,YAAY,iBACX,YAAY,UAAU;AAAA,YAGjB,UAAU,aAAhB,KACE,IAAI,KAAK;AAAA,cACP,SAAS;AAAA,cACT,MAAM,UAAU;AAAA,cAChB,KAAK,UAAU;AAAA,YACjB,CAAC;AAAA,UACU,OAAO,iBAAiB,UAAvC,cACE,iBAAiB,MAAM;AAAA,UACzB,KACE,mBAAmB,EACnB,mBAAmB,IAAI,QACvB,oBACA;AAAA,YACA,IAAI,OAAO,IAAI;AAAA,YACf,KAAK,QAAQ,aAAa,KAAK;AAAA,YAC/B,KAAK,QAAQ,YAAY,KAAK;AAAA,UAChC;AAAA,QACF;AAAA,QACA,WAAW,CAAC,CAAC;AAAA,QACb,uBAAuB,gBAAgB;AAAA,gBACvC;AAAA,QACC,mBAAmB,sBACjB,wBAAwB,IAAI,kBAC5B,sBAAqB,IAAI;AAAA;AAAA,IAEhC;AAAA,IACA,MAAK,UAAU;AAAA,IACf,uBAAuB;AAAA,EACzB;AAAA;AAEF,SAAS,kBAAkB,GAAG;AAAA,EAC5B,IAAU,yBAAN,GAA4B;AAAA,IAC9B,uBAAuB;AAAA,IACvB,IAAI,QAAO,oBACT,eAAe,qBACf,uBAA6B,aAAa,QAAQ,UAA5B;AAAA,IACxB,KAAW,aAAa,eAAe,UAAnC,KAA4C,qBAAqB;AAAA,MACnE,sBAAsB,sBAAqB;AAAA,MAC3C,sBAAqB,IAAI;AAAA,MACzB,IAAI,mBAAmB,wBAAwB;AAAA,MAC/C,wBAAwB,IAAI;AAAA,MAC5B,IAAI,uBAAuB;AAAA,MAC3B,oBAAoB;AAAA,MACpB,IAAI;AAAA,QACF,0BAA0B,OAAM,aAAa,WAAW,YAAY;AAAA,gBACpE;AAAA,QACC,mBAAmB,sBACjB,wBAAwB,IAAI,kBAC5B,sBAAqB,IAAI;AAAA;AAAA,IAEhC;AAAA,IACA,uBAAuB;AAAA,EACzB;AAAA;AAEF,SAAS,gBAAgB,GAAG;AAAA,EAC1B,IAAU,yBAAN,KAAoC,yBAAN,GAA4B;AAAA,IAC5D,uBAAuB;AAAA,IACvB,aAAa;AAAA,IACb,IAAI,QAAO,oBACT,eAAe,qBACf,QAAQ,qBACR,oBAAoB;AAAA,KACf,aAAa,eAAe,WAAnC,MACO,aAAa,QAAQ,WAA5B,IACK,uBAAuB,KACtB,uBAAuB,GACxB,sBAAsB,qBAAqB,MAC5C,uBAAuB,OAAM,MAAK,YAAY;AAAA,IAClD,IAAI,iBAAiB,MAAK;AAAA,IACpB,mBAAN,MAAyB,yCAAyC;AAAA,IAClE,qBAAqB,KAAK;AAAA,IAC1B,eAAe,aAAa;AAAA,IAC5B,IAAI,gBAA+B,OAAO,aAAa,sBAAnC;AAAA,MAClB,IAAI;AAAA,QACF,aAAa,kBACX,YACA,cACK,YACI,aAAa,QAAQ,QAAQ,SAAtC,GACF;AAAA,QACA,OAAO,KAAK;AAAA,IAChB,IAAa,sBAAT,MAA4B;AAAA,MAC9B,eAAe,sBAAqB;AAAA,MACpC,iBAAiB,wBAAwB;AAAA,MACzC,wBAAwB,IAAI;AAAA,MAC5B,sBAAqB,IAAI;AAAA,MACzB,IAAI;AAAA,QACF,SACM,qBAAqB,MAAK,oBAAoB,IAAI,EACtD,IAAI,kBAAkB,QACtB,KACA;AAAA,UACA,IAAI,mBAAmB,kBAAkB;AAAA,UACzC,mBAAmB,iBAAiB,OAAO;AAAA,YACzC,gBAAgB,iBAAiB;AAAA,UACnC,CAAC;AAAA,QACH;AAAA,gBACA;AAAA,QACC,sBAAqB,IAAI,cACvB,wBAAwB,IAAI;AAAA;AAAA,IAEnC;AAAA,KACO,sBAAsB,OAA7B,KAAmC,oBAAoB;AAAA,IACvD,sBAAsB,KAAI;AAAA,IAC1B,iBAAiB,MAAK;AAAA,KACf,QAAQ,YAAf,MAAiC,iBAAiB,QAAxB,IACtB,UAAS,wBACP,uBACE,oBAAoB,GAAK,wBAAwB,SACpD,oBAAoB;AAAA,IACzB,8BAA8B,GAAG,KAAE;AAAA,EACrC;AAAA;AAEF,SAAS,sBAAsB,CAAC,OAAM,gBAAgB;AAAA,GAC7C,MAAK,oBAAoB,oBAAhC,MACI,iBAAiB,MAAK,aAChB,kBAAR,SACI,MAAK,cAAc,MAAO,aAAa,cAAc;AAAA;AAE7D,SAAS,mBAAmB,GAAG;AAAA,EAC7B,qBAAqB;AAAA,EACrB,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB,OAAO,oBAAoB;AAAA;AAE7B,SAAS,mBAAmB,GAAG;AAAA,EAC7B,IAAU,yBAAN;AAAA,IAA4B,OAAO;AAAA,EACvC,IAAI,QAAO,oBACT,iBAAiB;AAAA,EACnB,+BAA+B;AAAA,EAC/B,IAAI,iBAAiB,qBAAqB,mBAAmB,GAC3D,iBAAiB,sBAAqB,GACtC,mBAAmB,wBAAwB;AAAA,EAC7C,IAAI;AAAA,IACF,wBAAwB,IAAI,KAAK,iBAAiB,KAAK;AAAA,IACvD,sBAAqB,IAAI;AAAA,IACzB,iBAAiB;AAAA,IACjB,4BAA4B;AAAA,IAC5B,IAAI,gBAAgB,oBAClB,QAAQ;AAAA,IACV,uBAAuB;AAAA,IACvB,sBAAsB,qBAAqB;AAAA,IAC3C,sBAAsB;AAAA,IACtB,KAAW,mBAAmB,OAA1B;AAAA,MAA8B,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,IACzE,IAAI,uBAAuB;AAAA,IAC3B,oBAAoB;AAAA,IACpB,4BAA4B,cAAc,OAAO;AAAA,IACjD,0BACE,eACA,cAAc,SACd,OACA,cACF;AAAA,IACA,mBAAmB;AAAA,IACnB,8BAA8B,GAAG,KAAE;AAAA,IACnC,IACE,gBACe,OAAO,aAAa,0BAAnC;AAAA,MAEA,IAAI;AAAA,QACF,aAAa,sBAAsB,YAAY,aAAa;AAAA,QAC5D,OAAO,KAAK;AAAA,IAChB,OAAO;AAAA,YACP;AAAA,IACC,wBAAwB,IAAI,kBAC1B,sBAAqB,IAAI,gBAC1B,uBAAuB,OAAM,cAAc;AAAA;AAAA;AAGjD,SAAS,6BAA6B,CAAC,WAAW,aAAa,OAAO;AAAA,EACpE,cAAc,2BAA2B,OAAO,WAAW;AAAA,EAC3D,cAAc,sBAAsB,UAAU,WAAW,aAAa,CAAC;AAAA,EACvE,YAAY,cAAc,WAAW,aAAa,CAAC;AAAA,EAC1C,cAAT,SACG,kBAAkB,WAAW,CAAC,GAAG,sBAAsB,SAAS;AAAA;AAErE,SAAS,uBAAuB,CAAC,aAAa,wBAAwB,OAAO;AAAA,EAC3E,IAAU,YAAY,QAAlB;AAAA,IACF,8BAA8B,aAAa,aAAa,KAAK;AAAA,EAE7D;AAAA,UAAgB,2BAAT,QAAmC;AAAA,MACxC,IAAU,uBAAuB,QAA7B,GAAkC;AAAA,QACpC,8BACE,wBACA,aACA,KACF;AAAA,QACA;AAAA,MACF,EAAO,SAAU,uBAAuB,QAA7B,GAAkC;AAAA,QAC3C,IAAI,WAAW,uBAAuB;AAAA,QACtC,IAEI,OAAO,uBAAuB,KAAK,6BADrC,cAEgB,OAAO,SAAS,sBAA/B,eACW,2CAAT,QACC,CAAC,uCAAuC,IAAI,QAAQ,IACxD;AAAA,UACA,cAAc,2BAA2B,OAAO,WAAW;AAAA,UAC3D,QAAQ,uBAAuB,CAAC;AAAA,UAChC,WAAW,cAAc,wBAAwB,OAAO,CAAC;AAAA,UAChD,aAAT,SACG,2BACC,OACA,UACA,wBACA,WACF,GACA,kBAAkB,UAAU,CAAC,GAC7B,sBAAsB,QAAQ;AAAA,UAChC;AAAA,QACF;AAAA,MACF;AAAA,MACA,yBAAyB,uBAAuB;AAAA,IAClD;AAAA;AAEJ,SAAS,kBAAkB,CAAC,OAAM,UAAU,OAAO;AAAA,EACjD,IAAI,YAAY,MAAK;AAAA,EACrB,IAAa,cAAT,MAAoB;AAAA,IACtB,YAAY,MAAK,YAAY,IAAI;AAAA,IACjC,IAAI,YAAY,IAAI;AAAA,IACpB,UAAU,IAAI,UAAU,SAAS;AAAA,EACnC,EACE;AAAA,IAAC,YAAY,UAAU,IAAI,QAAQ,GACtB,cAAN,cACD,YAAY,IAAI,KAAQ,UAAU,IAAI,UAAU,SAAS;AAAA,EACjE,UAAU,IAAI,KAAK,MACf,0CAA0C,MAC5C,UAAU,IAAI,KAAK,GAClB,QAAO,kBAAkB,KAAK,MAAM,OAAM,UAAU,KAAK,GAC1D,SAAS,KAAK,OAAM,KAAI;AAAA;AAE5B,SAAS,iBAAiB,CAAC,OAAM,UAAU,aAAa;AAAA,EACtD,IAAI,YAAY,MAAK;AAAA,EACZ,cAAT,QAAsB,UAAU,OAAO,QAAQ;AAAA,EAC/C,MAAK,eAAe,MAAK,iBAAiB;AAAA,EAC1C,MAAK,aAAa,CAAC;AAAA,EACnB,uBAAuB,UACpB,gCAAgC,iBAAiB,gBAC3C,iCAAN,KACM,iCAAN,MACE,gCAAgC,cAC/B,iCACF,MAAM,IAAI,IAAI,gCACL,mBAAmB,OAA1B,KAAgC,kBAAkB,OAAM,CAAC,IACxD,iCAAiC,aACtC,sCAAsC,kCACnC,oCAAoC;AAAA,EACzC,sBAAsB,KAAI;AAAA;AAE5B,SAAS,qBAAqB,CAAC,eAAe,WAAW;AAAA,EACjD,cAAN,MAAoB,YAAY,mBAAmB;AAAA,EACnD,gBAAgB,+BAA+B,eAAe,SAAS;AAAA,EAC9D,kBAAT,SACG,kBAAkB,eAAe,SAAS,GAC3C,sBAAsB,aAAa;AAAA;AAEvC,SAAS,+BAA+B,CAAC,eAAe;AAAA,EACtD,IAAI,gBAAgB,cAAc,eAChC,YAAY;AAAA,EACL,kBAAT,SAA2B,YAAY,cAAc;AAAA,EACrD,sBAAsB,eAAe,SAAS;AAAA;AAEhD,SAAS,oBAAoB,CAAC,eAAe,UAAU;AAAA,EACrD,IAAI,YAAY;AAAA,EAChB,QAAQ,cAAc;AAAA,SACf;AAAA,SACA;AAAA,MACH,IAAI,aAAa,cAAc;AAAA,MAC/B,IAAI,gBAAgB,cAAc;AAAA,MACzB,kBAAT,SAA2B,YAAY,cAAc;AAAA,MACrD;AAAA,SACG;AAAA,MACH,aAAa,cAAc;AAAA,MAC3B;AAAA,SACG;AAAA,MACH,aAAa,cAAc,UAAU;AAAA,MACrC;AAAA;AAAA,MAEA,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA;AAAA,EAElC,eAAT,QAAuB,WAAW,OAAO,QAAQ;AAAA,EACjD,sBAAsB,eAAe,SAAS;AAAA;AAEhD,SAAS,kBAAkB,CAAC,eAAe,UAAU;AAAA,EACnD,OAAO,mBAAmB,eAAe,QAAQ;AAAA;AAQnD,SAAS,qBAAqB,CAAC,OAAM;AAAA,EACnC,UAAS,qBACE,MAAK,SAAd,SACU,sBAAT,OACI,qBAAqB,oBAAoB,QACzC,oBAAoB,kBAAkB,OAAO;AAAA,EACpD,2BAA2B;AAAA,EAC3B,yBACI,uBAAuB,MAAK,kCAAkC;AAAA;AAEpE,SAAS,6BAA6B,CAAC,qBAAqB,YAAY;AAAA,EACtE,IAAI,CAAC,kBAAkB,0BAA0B;AAAA,IAC/C,iBAAiB;AAAA,IACjB,GAAG;AAAA,MACD,IAAI,qBAAqB;AAAA,MACzB,SAAS,WAAW,mBAA6B,aAAT,QAAqB;AAAA,QAC3D,IAAI,CAAC;AAAA,UACH,IAAU,wBAAN,GAA2B;AAAA,YAC7B,IAAI,eAAe,SAAS;AAAA,YAC5B,IAAU,iBAAN;AAAA,cAAoB,IAAI,2BAA2B;AAAA,YAClD;AAAA,cACH,MAA8B,gBACL,gBAAT;AAAA,cAChB,4BACG,KAAM,KAAK,MAAM,KAAK,mBAAmB,IAAI,KAAM;AAAA,cACtD,4BACE,eAAe,EAAE,iBAAiB,CAAC;AAAA,cACrC,2BACE,2BAA2B,YACtB,2BAA2B,YAAa,IACzC,2BACE,2BAA2B,IAC3B;AAAA;AAAA,YAEJ,6BAAN,MACI,qBAAqB,MACvB,sBAAsB,UAAU,wBAAwB;AAAA,UAC5D,EACE;AAAA,YAAC,2BAA2B,+BACzB,2BAA2B,aAC1B,UACA,aAAa,qBAAqB,2BAA2B,GACpD,SAAS,wBAAlB,QACS,SAAS,kBAAhB,EACJ,IACO,2BAA2B,OAAlC,KACE,0BAA0B,UAAU,wBAAwB,MAC1D,qBAAqB,MACvB,sBAAsB,UAAU,wBAAwB;AAAA,QAChE,WAAW,SAAS;AAAA,MACtB;AAAA,IACF,SAAS;AAAA,IACT,iBAAiB;AAAA,EACnB;AAAA;AAEF,SAAS,kCAAkC,GAAG;AAAA,EAC5C,+BAA+B;AAAA;AAEjC,SAAS,8BAA8B,GAAG;AAAA,EACxC,2BAA2B,uBAAuB;AAAA,EAClD,IAAI,sBAAsB;AAAA,EACpB,+BAAN,KACE,6BAA6B,MAC5B,sBAAsB;AAAA,EACzB,SACM,cAAc,IAAI,GAAG,OAAO,MAAM,QAAO,mBACpC,UAAT,QAEA;AAAA,IACA,IAAI,OAAO,MAAK,MACd,YAAY,mCAAmC,OAAM,WAAW;AAAA,IAClE,IAAU,cAAN;AAAA,MACD,MAAK,OAAO,MACF,SAAT,OAAiB,qBAAqB,OAAS,KAAK,OAAO,MAClD,SAAT,SAAkB,oBAAoB;AAAA,IACrC,SACD,OAAO,OAAa,wBAAN,MAAoC,YAAY,OAAnB;AAAA,MAE7C,2BAA2B;AAAA,IAC7B,QAAO;AAAA,EACT;AAAA,EACO,yBAAN,KAAoC,yBAAN,KAC7B,8BAA8B,qBAAqB,KAAE;AAAA,EACjD,+BAAN,MAAqC,6BAA6B;AAAA;AAEpE,SAAS,kCAAkC,CAAC,OAAM,aAAa;AAAA,EAC7D,WAC4B,gBACL,aACI,oBADT,OAEd,QAAQ,MAAK,eAAe,UAC9B,IAAI,SAEJ;AAAA,IACA,IAAI,UAAU,KAAK,MAAM,KAAK,GAC5B,OAAO,KAAK,SACZ,iBAAiB,gBAAgB;AAAA,IACnC,IAAW,mBAAP,IAAuB;AAAA,MACzB,KAAW,OAAO,oBAAd,MAAwC,OAAO,iBAAd;AAAA,QACnC,gBAAgB,WAAW,sBAAsB,MAAM,WAAW;AAAA,IACtE,EAAO;AAAA,wBAAkB,gBAAgB,MAAK,gBAAgB;AAAA,IAC9D,SAAS,CAAC;AAAA,EACZ;AAAA,EACA,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB,iBAAiB,aACf,OACA,UAAS,cAAc,iBAAiB,GAC/B,MAAK,wBAAd,QAA4C,MAAK,kBAAZ,EACvC;AAAA,EACA,cAAc,MAAK;AAAA,EACnB,IACQ,mBAAN,KACC,UAAS,gBACD,kCAAN,KACO,kCAAN,MACK,MAAK,wBAAd;AAAA,IAEA,OACW,gBAAT,QACW,gBAAT,QACA,iBAAiB,WAAW,GAC7B,MAAK,eAAe,MACpB,MAAK,mBAAmB;AAAA,EAE7B,KACS,iBAAiB,OAAxB,KACA,0BAA0B,OAAM,cAAc,GAC9C;AAAA,IACA,cAAc,iBAAiB,CAAC;AAAA,IAChC,IAAI,gBAAgB,MAAK;AAAA,MAAkB,OAAO;AAAA,IACzC,gBAAT,QAAwB,iBAAiB,WAAW;AAAA,IACpD,QAAQ,qBAAqB,cAAc;AAAA,WACpC;AAAA,WACA;AAAA,QACH,iBAAiB;AAAA,QACjB;AAAA,WACG;AAAA,QACH,iBAAiB;AAAA,QACjB;AAAA,WACG;AAAA,QACH,iBAAiB;AAAA,QACjB;AAAA;AAAA,QAEA,iBAAiB;AAAA;AAAA,IAErB,cAAc,kCAAkC,KAAK,MAAM,KAAI;AAAA,IAC/D,iBAAiB,mBAAmB,gBAAgB,WAAW;AAAA,IAC/D,MAAK,mBAAmB;AAAA,IACxB,MAAK,eAAe;AAAA,IACpB,OAAO;AAAA,EACT;AAAA,EACS,gBAAT,QAAiC,gBAAT,QAAwB,iBAAiB,WAAW;AAAA,EAC5E,MAAK,mBAAmB;AAAA,EACxB,MAAK,eAAe;AAAA,EACpB,OAAO;AAAA;AAET,SAAS,iCAAiC,CAAC,OAAM,YAAY;AAAA,EAC3D,IAAU,yBAAN,KAAoC,yBAAN;AAAA,IAChC,OAAQ,MAAK,eAAe,MAAQ,MAAK,mBAAmB,GAAI;AAAA,EAClE,IAAI,uBAAuB,MAAK;AAAA,EAChC,IAAI,oBAAoB,KAAK,MAAK,iBAAiB;AAAA,IACjD,OAAO;AAAA,EACT,IAAI,yCAAyC;AAAA,EAC7C,yCAAyC,aACvC,OACA,UAAS,qBAAqB,yCAAyC,GAC9D,MAAK,wBAAd,QAA4C,MAAK,kBAAZ,EACvC;AAAA,EACA,IAAU,2CAAN;AAAA,IAA8C,OAAO;AAAA,EACzD,kBAAkB,OAAM,wCAAwC,UAAU;AAAA,EAC1E,mCAAmC,OAAM,IAAI,CAAC;AAAA,EAC9C,OAAe,MAAK,gBAAb,QAA6B,MAAK,iBAAiB,uBACtD,kCAAkC,KAAK,MAAM,KAAI,IACjD;AAAA;AAEN,SAAS,qBAAqB,CAAC,OAAM,OAAO;AAAA,EAC1C,IAAI,oBAAoB;AAAA,IAAG,OAAO;AAAA,EAClC,kBAAkB,OAAM,OAAO,IAAE;AAAA;AAEnC,SAAS,iCAAiC,GAAG;AAAA,EAC3C,kBAAkB,QAAS,GAAG;AAAA,KACrB,mBAAmB,OAA1B,IACI,mBACE,mBACA,kCACF,IACA,+BAA+B;AAAA,GACpC;AAAA;AAEH,SAAS,qBAAqB,GAAG;AAAA,EAC/B,IAAU,+BAAN,GAAkC;AAAA,IACpC,IAAI,kBAAkB;AAAA,IAChB,oBAAN,MACI,kBAAkB,0BACnB,6BAA6B,IACvB,2BAA2B,YAAlC,MACG,2BAA2B;AAAA,IAChC,6BAA6B;AAAA,EAC/B;AAAA,EACA,OAAO;AAAA;AAET,SAAS,oBAAoB,CAAC,YAAY;AAAA,EACxC,OAAe,cAAR,QACQ,OAAO,eAApB,YACc,OAAO,eAArB,YACE,OACe,OAAO,eAAtB,aACE,aACA,YAAY,KAAK,UAAU;AAAA;AAEnC,SAAS,2BAA2B,CAAC,MAAM,WAAW;AAAA,EACpD,IAAI,OAAO,UAAU,cAAc,cAAc,OAAO;AAAA,EACxD,KAAK,OAAO,UAAU;AAAA,EACtB,KAAK,QAAQ,UAAU;AAAA,EACvB,KAAK,MAAM,KAAK,aAAa,QAAQ,KAAK,EAAE;AAAA,EAC5C,UAAU,WAAW,aAAa,MAAM,SAAS;AAAA,EACjD,OAAO,IAAI,SAAS,IAAI;AAAA,EACxB,KAAK,WAAW,YAAY,IAAI;AAAA,EAChC,OAAO;AAAA;AAET,SAAS,eAAe,CACtB,eACA,cACA,iBACA,aACA,mBACA;AAAA,EACA,IACe,iBAAb,YACA,mBACA,gBAAgB,cAAc,mBAC9B;AAAA,IACA,IAAI,SAAS,sBACR,kBAAkB,qBAAqB,MAAM,MAChD,GACA,YAAY,YAAY;AAAA,IAC1B,cACI,gBAAgB,eAAe,UAAU,qBAAqB,QAC5D,qBAAqB,aAAa,UAAU,IAC5C,UAAU,aAAa,YAAY,GAC9B,iBAAT,SAA2B,SAAS,cAAgB,YAAY;AAAA,IAClE,IAAI,QAAQ,IAAI,eACd,UACA,UACA,MACA,aACA,iBACF;AAAA,IACA,cAAc,KAAK;AAAA,MACjB;AAAA,MACA,WAAW;AAAA,QACT;AAAA,UACE,UAAU;AAAA,UACV,UAAU,QAAS,GAAG;AAAA,YACpB,IAAI,YAAY,kBAAkB;AAAA,cAChC,IAAU,+BAAN,GAAkC;AAAA,gBACpC,IAAI,WAAW,YACX,4BAA4B,mBAAmB,SAAS,IACxD,IAAI,SAAS,iBAAiB;AAAA,gBAClC,oBACE,iBACA;AAAA,kBACE,SAAS;AAAA,kBACT,MAAM;AAAA,kBACN,QAAQ,kBAAkB;AAAA,kBAC1B;AAAA,gBACF,GACA,MACA,QACF;AAAA,cACF;AAAA,YACF,EACE;AAAA,cAAe,OAAO,WAAtB,eACG,MAAM,eAAe,GACrB,WAAW,YACR,4BAA4B,mBAAmB,SAAS,IACxD,IAAI,SAAS,iBAAiB,GAClC,oBACE,iBACA;AAAA,gBACE,SAAS;AAAA,gBACT,MAAM;AAAA,gBACN,QAAQ,kBAAkB;AAAA,gBAC1B;AAAA,cACF,GACA,QACA,QACF;AAAA;AAAA,UAEN,eAAe;AAAA,QACjB;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAsEF,SAAS,oBAAoB,CAAC,eAAe,kBAAkB;AAAA,EAC7D,oBAA0B,mBAAmB,OAA1B;AAAA,EACnB,SAAS,IAAI,EAAG,IAAI,cAAc,QAAQ,KAAK;AAAA,IAC7C,IAAI,mBAAmB,cAAc,IACnC,QAAQ,iBAAiB;AAAA,IAC3B,mBAAmB,iBAAiB;AAAA,IACpC,GAAG;AAAA,MACD,IAAI,mBAAwB;AAAA,MAC5B,IAAI;AAAA,QACF,SACM,aAAa,iBAAiB,SAAS,EAC3C,KAAK,YACL,cACA;AAAA,UACA,IAAI,uBAAuB,iBAAiB,aAC1C,WAAW,qBAAqB,UAChC,gBAAgB,qBAAqB;AAAA,UACvC,uBAAuB,qBAAqB;AAAA,UAC5C,IAAI,aAAa,oBAAoB,MAAM,qBAAqB;AAAA,YAC9D;AAAA,UACF,mBAAmB;AAAA,UACnB,MAAM,gBAAgB;AAAA,UACtB,IAAI;AAAA,YACF,iBAAiB,KAAK;AAAA,YACtB,OAAO,OAAO;AAAA,YACd,mBAAkB,KAAK;AAAA;AAAA,UAEzB,MAAM,gBAAgB;AAAA,UACtB,mBAAmB;AAAA,QACrB;AAAA,MAEA;AAAA,aACE,aAAa,EACb,aAAa,iBAAiB,QAC9B,cACA;AAAA,UACA,uBAAuB,iBAAiB;AAAA,UACxC,WAAW,qBAAqB;AAAA,UAChC,gBAAgB,qBAAqB;AAAA,UACrC,uBAAuB,qBAAqB;AAAA,UAC5C,IAAI,aAAa,oBAAoB,MAAM,qBAAqB;AAAA,YAC9D;AAAA,UACF,mBAAmB;AAAA,UACnB,MAAM,gBAAgB;AAAA,UACtB,IAAI;AAAA,YACF,iBAAiB,KAAK;AAAA,YACtB,OAAO,OAAO;AAAA,YACd,mBAAkB,KAAK;AAAA;AAAA,UAEzB,MAAM,gBAAgB;AAAA,UACtB,mBAAmB;AAAA,QACrB;AAAA,IACJ;AAAA,EACF;AAAA;AAEF,SAAS,yBAAyB,CAAC,cAAc,eAAe;AAAA,EAC9D,IAAI,2BAA2B,cAAc;AAAA,EAClC,6BAAN,cACF,2BAA2B,cAAc,4BACxC,IAAI;AAAA,EACR,IAAI,iBAAiB,eAAe;AAAA,EACpC,yBAAyB,IAAI,cAAc,MACxC,wBAAwB,eAAe,cAAc,GAAG,KAAE,GAC3D,yBAAyB,IAAI,cAAc;AAAA;AAE/C,SAAS,mBAAmB,CAAC,cAAc,wBAAwB,QAAQ;AAAA,EACzE,IAAI,mBAAmB;AAAA,EACvB,2BAA2B,oBAAoB;AAAA,EAC/C,wBACE,QACA,cACA,kBACA,sBACF;AAAA;AAGF,SAAS,0BAA0B,CAAC,sBAAsB;AAAA,EACxD,IAAI,CAAC,qBAAqB,kBAAkB;AAAA,IAC1C,qBAAqB,mBAAmB;AAAA,IACxC,gBAAgB,QAAQ,QAAS,CAAC,cAAc;AAAA,MACxB,iBAAtB,sBACG,mBAAmB,IAAI,YAAY,KAClC,oBAAoB,cAAc,OAAI,oBAAoB,GAC5D,oBAAoB,cAAc,MAAI,oBAAoB;AAAA,KAC7D;AAAA,IACD,IAAI,gBACI,qBAAqB,aAA3B,IACI,uBACA,qBAAqB;AAAA,IAClB,kBAAT,QACE,cAAc,qBACZ,cAAc,mBAAmB,MACnC,oBAAoB,mBAAmB,OAAI,aAAa;AAAA,EAC5D;AAAA;AAEF,SAAS,uBAAuB,CAC9B,iBACA,cACA,kBACA,wBACA;AAAA,EACA,QAAQ,iBAAiB,YAAY;AAAA,SAC9B;AAAA,MACH,IAAI,kBAAkB;AAAA,MACtB;AAAA,SACG;AAAA,MACH,kBAAkB;AAAA,MAClB;AAAA;AAAA,MAEA,kBAAkB;AAAA;AAAA,EAEtB,mBAAmB,gBAAgB,KACjC,MACA,cACA,kBACA,eACF;AAAA,EACA,kBAAuB;AAAA,EACvB,CAAC,iCACmB,iBAAjB,gBACiB,iBAAhB,eACY,iBAAZ,YACD,kBAAkB;AAAA,EACrB,yBACe,oBAAN,YACH,gBAAgB,iBAAiB,cAAc,kBAAkB;AAAA,IAC/D,SAAS;AAAA,IACT,SAAS;AAAA,EACX,CAAC,IACD,gBAAgB,iBAAiB,cAAc,kBAAkB,IAAE,IAC1D,oBAAN,YACH,gBAAgB,iBAAiB,cAAc,kBAAkB;AAAA,IAC/D,SAAS;AAAA,EACX,CAAC,IACD,gBAAgB,iBAAiB,cAAc,kBAAkB,KAAE;AAAA;AAE3E,SAAS,iCAAiC,CACxC,cACA,kBACA,aACA,qBACA,iBACA;AAAA,EACA,IAAI,eAAe;AAAA,EACnB,KACS,mBAAmB,OAA1B,MACO,mBAAmB,OAA1B,KACS,wBAAT;AAAA,IAEA;AAAA,MAAG,UAAS;AAAA,QACV,IAAa,wBAAT;AAAA,UAA8B;AAAA,QAClC,IAAI,UAAU,oBAAoB;AAAA,QAClC,IAAU,YAAN,KAAuB,YAAN,GAAe;AAAA,UAClC,IAAI,YAAY,oBAAoB,UAAU;AAAA,UAC9C,IAAI,cAAc;AAAA,YAAiB;AAAA,UACnC,IAAU,YAAN;AAAA,YACF,KAAK,UAAU,oBAAoB,OAAiB,YAAT,QAAoB;AAAA,cAC7D,IAAI,WAAW,QAAQ;AAAA,cACvB,KACS,aAAN,KAAwB,aAAN,MACnB,QAAQ,UAAU,kBAAkB;AAAA,gBAEpC;AAAA,cACF,UAAU,QAAQ;AAAA,YACpB;AAAA,UACF,MAAgB,cAAT,QAAsB;AAAA,YAC3B,UAAU,2BAA2B,SAAS;AAAA,YAC9C,IAAa,YAAT;AAAA,cAAkB;AAAA,YACtB,WAAW,QAAQ;AAAA,YACnB,IACQ,aAAN,KACM,aAAN,KACO,aAAP,MACO,aAAP,IACA;AAAA,cACA,sBAAsB,eAAe;AAAA,cACrC;AAAA,YACF;AAAA,YACA,YAAY,UAAU;AAAA,UACxB;AAAA,QACF;AAAA,QACA,sBAAsB,oBAAoB;AAAA,MAC5C;AAAA,EACF,iBAAiB,QAAS,GAAG;AAAA,IAC3B,IAAI,aAAa,cACf,oBAAoB,eAAe,WAAW,GAC9C,gBAAgB,CAAC;AAAA,IACnB,GAAG;AAAA,MACD,IAAI,YAAY,2BAA2B,IAAI,YAAY;AAAA,MAC3D,IAAe,cAAN,WAAiB;AAAA,QACxB,IAAI,qBAAqB,gBACvB,iBAAiB;AAAA,QACnB,QAAQ;AAAA,eACD;AAAA,YACH,IAAU,iBAAiB,WAAW,MAAlC;AAAA,cAAqC;AAAA,eACtC;AAAA,eACA;AAAA,YACH,qBAAqB;AAAA,YACrB;AAAA,eACG;AAAA,YACH,iBAAiB;AAAA,YACjB,qBAAqB;AAAA,YACrB;AAAA,eACG;AAAA,YACH,iBAAiB;AAAA,YACjB,qBAAqB;AAAA,YACrB;AAAA,eACG;AAAA,eACA;AAAA,YACH,qBAAqB;AAAA,YACrB;AAAA,eACG;AAAA,YACH,IAAU,YAAY,WAAlB;AAAA,cAA0B;AAAA,eAC3B;AAAA,eACA;AAAA,eACA;AAAA,eACA;AAAA,eACA;AAAA,eACA;AAAA,eACA;AAAA,eACA;AAAA,YACH,qBAAqB;AAAA,YACrB;AAAA,eACG;AAAA,eACA;AAAA,eACA;AAAA,eACA;AAAA,eACA;AAAA,eACA;AAAA,eACA;AAAA,eACA;AAAA,YACH,qBAAqB;AAAA,YACrB;AAAA,eACG;AAAA,eACA;AAAA,eACA;AAAA,eACA;AAAA,YACH,qBAAqB;AAAA,YACrB;AAAA,eACG;AAAA,eACA;AAAA,eACA;AAAA,YACH,qBAAqB;AAAA,YACrB;AAAA,eACG;AAAA,YACH,qBAAqB;AAAA,YACrB;AAAA,eACG;AAAA,eACA;AAAA,YACH,qBAAqB;AAAA,YACrB;AAAA,eACG;AAAA,YACH,qBAAqB;AAAA,YACrB;AAAA,eACG;AAAA,eACA;AAAA,eACA;AAAA,YACH,qBAAqB;AAAA,YACrB;AAAA,eACG;AAAA,eACA;AAAA,eACA;AAAA,eACA;AAAA,eACA;AAAA,eACA;AAAA,eACA;AAAA,eACA;AAAA,YACH,qBAAqB;AAAA,YACrB;AAAA,eACG;AAAA,eACA;AAAA,YACH,qBAAqB;AAAA;AAAA,QAEzB,IAAI,kBAAwB,mBAAmB,OAA1B,GACnB,uBACE,CAAC,mBACa,iBAAb,YAA6C,iBAAhB,cAChC,iBAAiB,iBACJ,cAAT,OACE,YAAY,YACZ,OACF;AAAA,QACN,iBAAiB,CAAC;AAAA,QAClB,SACM,WAAW,YAAY,kBAClB,aAAT,QAEA;AAAA,UACA,IAAI,YAAY;AAAA,UAChB,oBAAoB,UAAU;AAAA,UAC9B,YAAY,UAAU;AAAA,UACf,cAAN,KAA0B,cAAP,MAA2B,cAAP,MAC7B,sBAAT,QACS,mBAAT,SACE,YAAY,YAAY,UAAU,cAAc,GAC1C,aAAR,QACE,eAAe,KACb,uBAAuB,UAAU,WAAW,iBAAiB,CAC/D;AAAA,UACJ,IAAI;AAAA,YAAsB;AAAA,UAC1B,WAAW,SAAS;AAAA,QACtB;AAAA,QACA,IAAI,eAAe,WACf,YAAY,IAAI,mBAChB,WACA,gBACA,MACA,aACA,iBACF,GACA,cAAc,KAAK,EAAE,OAAO,WAAW,WAAW,eAAe,CAAC;AAAA,MACtE;AAAA,IACF;AAAA,IACA,KAAW,mBAAmB,OAA1B,GAA8B;AAAA,MAChC,GAAG;AAAA,QACD,YACkB,iBAAhB,eAAkD,iBAAlB;AAAA,QAClC,qBACiB,iBAAf,cAAgD,iBAAjB;AAAA,QACjC,IACE,aACA,gBAAgB,0BACf,iBACC,YAAY,iBAAiB,YAAY,iBAC1C,2BAA2B,cAAc,KACxC,eAAe;AAAA,UAEjB;AAAA,QACF,IAAI,sBAAsB,WAAW;AAAA,UACnC,YACE,kBAAkB,WAAW,oBACzB,qBACC,YAAY,kBAAkB,iBAC7B,UAAU,eAAe,UAAU,eACnC;AAAA,UACR,IAAI,oBAAoB;AAAA,YACtB,IACI,iBACA,YAAY,iBAAiB,YAAY,WAC1C,qBAAqB,YACrB,iBAAiB,iBACd,2BAA2B,cAAc,IACzC,MACK,mBAAT,SACI,uBACA,uBAAuB,cAAc,GACtC,iBAAiB,eAAe,KACjC,mBAAmB,wBACV,mBAAN,KACQ,mBAAP,MACM,mBAAN;AAAA,cAEN,iBAAiB;AAAA,UACrB,EAAO;AAAA,YAAC,qBAAqB,MAAQ,iBAAiB;AAAA,UACtD,IAAI,uBAAuB,gBAAgB;AAAA,YACzC,iBAAiB;AAAA,YACjB,YAAY;AAAA,YACZ,iBAAiB;AAAA,YACjB,WAAW;AAAA,YACX,IAAqB,iBAAjB,gBAAmD,iBAAlB;AAAA,cAClC,iBAAiB,uBACf,YAAY,kBACZ,iBAAiB,kBACjB,WAAW;AAAA,YAChB,uBACU,sBAAR,OACI,YACA,oBAAoB,kBAAkB;AAAA,YAC5C,oBACU,kBAAR,OACI,YACA,oBAAoB,cAAc;AAAA,YACxC,YAAY,IAAI,eACd,WACA,WAAW,SACX,oBACA,aACA,iBACF;AAAA,YACA,UAAU,SAAS;AAAA,YACnB,UAAU,gBAAgB;AAAA,YAC1B,YAAY;AAAA,YACZ,2BAA2B,iBAAiB,MAAM,eAC9C,iBAAiB,IAAI,eACrB,gBACA,WAAW,SACX,gBACA,aACA,iBACF,GACC,eAAe,SAAS,mBACxB,eAAe,gBAAgB,sBAC/B,YAAY;AAAA,YACf,uBAAuB;AAAA,YACvB,IAAI,sBAAsB;AAAA,cACxB,GAAG;AAAA,gBACD,iBAAiB;AAAA,gBACjB,iBAAiB;AAAA,gBACjB,WAAW;AAAA,gBACX,oBAAoB;AAAA,gBACpB,KACE,YAAY,eACZ,WACA,YAAY,eAAe,SAAS;AAAA,kBAEpC;AAAA,gBACF,YAAY;AAAA,gBACZ,SAAS,QAAQ,SAAU,OAAO,QAAQ,eAAe,KAAK;AAAA,kBAC5D;AAAA,gBACF,MAAO,IAAI,oBAAoB;AAAA,kBAC5B,iBAAiB,eAAe,cAAc,GAC7C;AAAA,gBACJ,MAAO,IAAI,YAAY;AAAA,kBACpB,WAAW,eAAe,QAAQ,GAAI;AAAA,gBACzC,MAAO,uBAAuB;AAAA,kBAC5B,IACE,mBAAmB,YACT,aAAT,QAAqB,mBAAmB,SAAS,WAClD;AAAA,oBACA,iBAAiB;AAAA,oBACjB;AAAA,kBACF;AAAA,kBACA,iBAAiB,eAAe,cAAc;AAAA,kBAC9C,WAAW,eAAe,QAAQ;AAAA,gBACpC;AAAA,gBACA,iBAAiB;AAAA,cACnB;AAAA,YACG;AAAA,+BAAiB;AAAA,YACb,uBAAT,QACE,sCACE,eACA,WACA,oBACA,gBACA,KACF;AAAA,YACO,mBAAT,QACW,yBAAT,QACA,sCACE,eACA,sBACA,gBACA,gBACA,IACF;AAAA,UACJ;AAAA,QACF;AAAA,MACF;AAAA,MACA,GAAG;AAAA,QACD,YAAY,aAAa,oBAAoB,UAAU,IAAI;AAAA,QAC3D,qBACE,UAAU,YAAY,UAAU,SAAS,YAAY;AAAA,QACvD,IACe,uBAAb,YACa,uBAAZ,WAA6C,UAAU,SAArB;AAAA,UAEnC,IAAI,oBAAoB;AAAA,QACrB,SAAI,mBAAmB,SAAS;AAAA,UACnC,IAAI;AAAA,YACF,oBAAoB;AAAA,UACjB;AAAA,YACH,oBAAoB;AAAA,YACpB,IAAI,kBAAkB;AAAA;AAAA,QAGxB;AAAA,UAAC,qBAAqB,UAAU,UAC9B,CAAC,sBACW,mBAAmB,YAAY,MAA3C,WACgB,UAAU,SAAzB,cAA6C,UAAU,SAAtB,UAC9B,cACA,gBAAgB,WAAW,WAAW,MACrC,oBAAoB,+BACpB,oBAAoB;AAAA,QAC7B,IACE,sBACC,oBAAoB,kBAAkB,cAAc,UAAU,IAC/D;AAAA,UACA,+BACE,eACA,mBACA,aACA,iBACF;AAAA,UACA;AAAA,QACF;AAAA,QACA,mBAAmB,gBAAgB,cAAc,WAAW,UAAU;AAAA,QACvD,iBAAf,cACE,cACa,UAAU,SAAvB,YACQ,WAAW,cAAc,SAAjC,QACA,gBAAgB,WAAW,UAAU,UAAU,KAAK;AAAA,MACxD;AAAA,MACA,kBAAkB,aAAa,oBAAoB,UAAU,IAAI;AAAA,MACjE,QAAQ;AAAA,aACD;AAAA,UACH,IACE,mBAAmB,eAAe,KACvB,gBAAgB,oBAA3B;AAAA,YAEC,gBAAgB,iBACd,oBAAoB,YACpB,gBAAgB;AAAA,UACrB;AAAA,aACG;AAAA,UACH,gBAAgB,oBAAoB,gBAAgB;AAAA,UACpD;AAAA,aACG;AAAA,UACH,YAAY;AAAA,UACZ;AAAA,aACG;AAAA,aACA;AAAA,aACA;AAAA,UACH,YAAY;AAAA,UACZ,qBAAqB,eAAe,aAAa,iBAAiB;AAAA,UAClE;AAAA,aACG;AAAA,UACH,IAAI;AAAA,YAA0B;AAAA,aAC3B;AAAA,aACA;AAAA,UACH,qBAAqB,eAAe,aAAa,iBAAiB;AAAA;AAAA,MAEtE,IAAI;AAAA,MACJ,IAAI;AAAA,QACF,GAAG;AAAA,UACD,QAAQ;AAAA,iBACD;AAAA,cACH,IAAI,YAAY;AAAA,cAChB;AAAA,iBACG;AAAA,cACH,YAAY;AAAA,cACZ;AAAA,iBACG;AAAA,cACH,YAAY;AAAA,cACZ;AAAA;AAAA,UAEJ,YAAiB;AAAA,QACnB;AAAA,MAEA;AAAA,sBACI,yBAAyB,cAAc,WAAW,MACjD,YAAY,sBACC,iBAAd,aACQ,YAAY,YAApB,QACC,YAAY;AAAA,MACnB,cACG,8BACU,YAAY,WAArB,SACC,eAAwC,cAAzB,uBACW,cAAvB,sBACA,gBACC,eAAe,QAAQ,MACtB,OAAO,mBACR,aAAY,WAAW,QAAO,KAAK,QAAQ,KAAK,aAChD,cAAc,QACpB,kBAAkB,4BAA4B,YAAY,SAAS,GACpE,IAAI,gBAAgB,WAChB,YAAY,IAAI,0BAChB,WACA,cACA,MACA,aACA,iBACF,GACA,cAAc,KAAK,EAAE,OAAO,WAAW,WAAW,gBAAgB,CAAC,GACnE,eACK,UAAU,OAAO,gBAChB,eAAe,uBAAuB,WAAW,GAC1C,iBAAT,SAA0B,UAAU,OAAO;AAAA,MACnD,IACG,eAAe,uBACZ,0BAA0B,cAAc,WAAW,IACnD,4BAA4B,cAAc,WAAW;AAAA,QAExD,YAAY,4BAA4B,YAAY,eAAe,GAClE,IAAI,UAAU,WACV,kBAAkB,IAAI,0BACtB,iBACA,eACA,MACA,aACA,iBACF,GACA,cAAc,KAAK;AAAA,UACjB,OAAO;AAAA,UACP,WAAW;AAAA,QACb,CAAC,GACA,gBAAgB,OAAO;AAAA,MAC9B,gBACE,eACA,cACA,YACA,aACA,iBACF;AAAA,IACF;AAAA,IACA,qBAAqB,eAAe,gBAAgB;AAAA,GACrD;AAAA;AAEH,SAAS,sBAAsB,CAAC,UAAU,UAAU,eAAe;AAAA,EACjE,OAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA;AAEF,SAAS,2BAA2B,CAAC,aAAa,WAAW;AAAA,EAC3D,SACM,cAAc,YAAY,WAAW,YAAY,CAAC,EAC7C,gBAAT,QAEA;AAAA,IACA,IAAI,aAAa,aACf,YAAY,WAAW;AAAA,IACzB,aAAa,WAAW;AAAA,IACjB,eAAN,KAA2B,eAAP,MAA4B,eAAP,MAC/B,cAAT,SACE,aAAa,YAAY,aAAa,WAAW,GAC3C,cAAR,QACE,UAAU,QACR,uBAAuB,aAAa,YAAY,SAAS,CAC3D,GACD,aAAa,YAAY,aAAa,SAAS,GACxC,cAAR,QACE,UAAU,KACR,uBAAuB,aAAa,YAAY,SAAS,CAC3D;AAAA,IACJ,IAAU,YAAY,QAAlB;AAAA,MAAuB,OAAO;AAAA,IAClC,cAAc,YAAY;AAAA,EAC5B;AAAA,EACA,OAAO,CAAC;AAAA;AAEV,SAAS,SAAS,CAAC,MAAM;AAAA,EACvB,IAAa,SAAT;AAAA,IAAe,OAAO;AAAA,EAC1B;AAAA,IAAG,OAAO,KAAK;AAAA,SACR,QAAc,KAAK,QAAX,KAAyB,KAAK,QAAZ;AAAA,EACjC,OAAO,OAAO,OAAO;AAAA;AAEvB,SAAS,qCAAqC,CAC5C,eACA,OACA,QACA,QACA,gBACA;AAAA,EACA,SACM,mBAAmB,MAAM,YAAY,YAAY,CAAC,EAC7C,WAAT,QAAmB,WAAW,UAE9B;AAAA,IACA,IAAI,aAAa,QACf,YAAY,WAAW,WACvB,YAAY,WAAW;AAAA,IACzB,aAAa,WAAW;AAAA,IACxB,IAAa,cAAT,QAAsB,cAAc;AAAA,MAAQ;AAAA,IACzC,eAAN,KAA2B,eAAP,MAA4B,eAAP,MAC/B,cAAT,SACE,YAAY,WACd,kBACM,YAAY,YAAY,QAAQ,gBAAgB,GAC1C,aAAR,QACE,UAAU,QACR,uBAAuB,QAAQ,WAAW,SAAS,CACrD,KACF,mBACE,YAAY,YAAY,QAAQ,gBAAgB,GAC1C,aAAR,QACE,UAAU,KACR,uBAAuB,QAAQ,WAAW,SAAS,CACrD;AAAA,IACR,SAAS,OAAO;AAAA,EAClB;AAAA,EACM,UAAU,WAAhB,KACE,cAAc,KAAK,EAAE,OAAc,UAAqB,CAAC;AAAA;AAI7D,SAAS,iCAAiC,CAAC,QAAQ;AAAA,EACjD,QAAqB,OAAO,WAApB,WAA6B,SAAS,KAAK,QAChD,QAAQ,0BAA0B;AAAA,CAAI,EACtC,QAAQ,sCAAsC,EAAE;AAAA;AAErD,SAAS,qBAAqB,CAAC,YAAY,YAAY;AAAA,EACrD,aAAa,kCAAkC,UAAU;AAAA,EACzD,OAAO,kCAAkC,UAAU,MAAM,aAAa,OAAK;AAAA;AAE7E,SAAS,OAAO,CAAC,YAAY,KAAK,KAAK,OAAO,OAAO,WAAW;AAAA,EAC9D,QAAQ;AAAA,SACD;AAAA,MACU,OAAO,UAApB,WACe,QAAX,UACgB,QAAf,cAA6B,UAAP,MACvB,eAAe,YAAY,KAAK,KAClB,OAAO,UAApB,YAA0C,OAAO,UAApB,aACnB,QAAX,UACA,eAAe,YAAY,KAAK,KAAK;AAAA,MACzC;AAAA,SACG;AAAA,MACH,0BAA0B,YAAY,SAAS,KAAK;AAAA,MACpD;AAAA,SACG;AAAA,MACH,0BAA0B,YAAY,YAAY,KAAK;AAAA,MACvD;AAAA,SACG;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH,0BAA0B,YAAY,KAAK,KAAK;AAAA,MAChD;AAAA,SACG;AAAA,MACH,kBAAkB,YAAY,OAAO,SAAS;AAAA,MAC9C;AAAA,SACG;AAAA,MACH,IAAiB,QAAb,UAAkB;AAAA,QACpB,0BAA0B,YAAY,QAAQ,KAAK;AAAA,QACnD;AAAA,MACF;AAAA,SACG;AAAA,SACA;AAAA,MACH,IAAW,UAAP,OAAyB,QAAR,OAA0B,QAAX,SAAiB;AAAA,QACnD,WAAW,gBAAgB,GAAG;AAAA,QAC9B;AAAA,MACF;AAAA,MACA,IACU,SAAR,QACe,OAAO,UAAtB,cACa,OAAO,UAApB,YACc,OAAO,UAArB,WACA;AAAA,QACA,WAAW,gBAAgB,GAAG;AAAA,QAC9B;AAAA,MACF;AAAA,MACA,QAAQ,YAAY,KAAK,KAAK;AAAA,MAC9B,WAAW,aAAa,KAAK,KAAK;AAAA,MAClC;AAAA,SACG;AAAA,SACA;AAAA,MACH,IAAmB,OAAO,UAAtB,YAA6B;AAAA,QAC/B,WAAW,aACT,KACA,sRACF;AAAA,QACA;AAAA,MACF,EACE;AAAA,QAAe,OAAO,cAAtB,eACoB,QAAjB,gBACgB,QAAZ,WACC,QAAQ,YAAY,KAAK,QAAQ,MAAM,MAAM,OAAO,IAAI,GAC1D,QACE,YACA,KACA,eACA,MAAM,aACN,OACA,IACF,GACA,QACE,YACA,KACA,cACA,MAAM,YACN,OACA,IACF,GACA,QACE,YACA,KACA,cACA,MAAM,YACN,OACA,IACF,MACC,QAAQ,YAAY,KAAK,WAAW,MAAM,SAAS,OAAO,IAAI,GAC/D,QAAQ,YAAY,KAAK,UAAU,MAAM,QAAQ,OAAO,IAAI,GAC5D,QAAQ,YAAY,KAAK,UAAU,MAAM,QAAQ,OAAO,IAAI;AAAA,MACpE,IACU,SAAR,QACa,OAAO,UAApB,YACc,OAAO,UAArB,WACA;AAAA,QACA,WAAW,gBAAgB,GAAG;AAAA,QAC9B;AAAA,MACF;AAAA,MACA,QAAQ,YAAY,KAAK,KAAK;AAAA,MAC9B,WAAW,aAAa,KAAK,KAAK;AAAA,MAClC;AAAA,SACG;AAAA,MACK,SAAR,SAAkB,WAAW,UAAU;AAAA,MACvC;AAAA,SACG;AAAA,MACK,SAAR,QAAiB,0BAA0B,UAAU,UAAU;AAAA,MAC/D;AAAA,SACG;AAAA,MACK,SAAR,QAAiB,0BAA0B,aAAa,UAAU;AAAA,MAClE;AAAA,SACG;AAAA,MACH,IAAY,SAAR,MAAe;AAAA,QACjB,IAAiB,OAAO,UAApB,YAA6B,EAAE,YAAY;AAAA,UAC7C,MAAM,MAAM,wBAAuB,EAAE,CAAC;AAAA,QACxC,MAAM,MAAM;AAAA,QACZ,IAAY,OAAR,MAAa;AAAA,UACf,IAAY,MAAM,YAAd;AAAA,YAAwB,MAAM,MAAM,wBAAuB,EAAE,CAAC;AAAA,UAClE,WAAW,YAAY;AAAA,QACzB;AAAA,MACF;AAAA,MACA;AAAA,SACG;AAAA,MACH,WAAW,WACT,SAAwB,OAAO,UAAtB,cAA4C,OAAO,UAApB;AAAA,MAC1C;AAAA,SACG;AAAA,MACH,WAAW,QACT,SAAwB,OAAO,UAAtB,cAA4C,OAAO,UAApB;AAAA,MAC1C;AAAA,SACG;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH;AAAA,SACG;AAAA,MACH;AAAA,SACG;AAAA,MACH,IACU,SAAR,QACe,OAAO,UAAtB,cACc,OAAO,UAArB,aACa,OAAO,UAApB,UACA;AAAA,QACA,WAAW,gBAAgB,YAAY;AAAA,QACvC;AAAA,MACF;AAAA,MACA,MAAM,YAAY,KAAK,KAAK;AAAA,MAC5B,WAAW,eACT,gCACA,cACA,GACF;AAAA,MACA;AAAA,SACG;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACK,SAAR,QAAgC,OAAO,UAAtB,cAA4C,OAAO,UAApB,WAC5C,WAAW,aAAa,KAAK,KAAK,KAAK,IACvC,WAAW,gBAAgB,GAAG;AAAA,MAClC;AAAA,SACG;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH,SAAwB,OAAO,UAAtB,cAA4C,OAAO,UAApB,WACpC,WAAW,aAAa,KAAK,EAAE,IAC/B,WAAW,gBAAgB,GAAG;AAAA,MAClC;AAAA,SACG;AAAA,SACA;AAAA,MACI,UAAP,OACI,WAAW,aAAa,KAAK,EAAE,IACxB,UAAP,SACU,SAAR,QACe,OAAO,UAAtB,cACa,OAAO,UAApB,WACA,WAAW,aAAa,KAAK,KAAK,IAClC,WAAW,gBAAgB,GAAG;AAAA,MACpC;AAAA,SACG;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACK,SAAR,QACe,OAAO,UAAtB,cACa,OAAO,UAApB,YACA,CAAC,MAAM,KAAK,KACZ,KAAK,QACD,WAAW,aAAa,KAAK,KAAK,IAClC,WAAW,gBAAgB,GAAG;AAAA,MAClC;AAAA,SACG;AAAA,SACA;AAAA,MACK,SAAR,QACe,OAAO,UAAtB,cACa,OAAO,UAApB,YACA,MAAM,KAAK,IACP,WAAW,gBAAgB,GAAG,IAC9B,WAAW,aAAa,KAAK,KAAK;AAAA,MACtC;AAAA,SACG;AAAA,MACH,0BAA0B,gBAAgB,UAAU;AAAA,MACpD,0BAA0B,UAAU,UAAU;AAAA,MAC9C,qBAAqB,YAAY,WAAW,KAAK;AAAA,MACjD;AAAA,SACG;AAAA,MACH,+BACE,YACA,gCACA,iBACA,KACF;AAAA,MACA;AAAA,SACG;AAAA,MACH,+BACE,YACA,gCACA,iBACA,KACF;AAAA,MACA;AAAA,SACG;AAAA,MACH,+BACE,YACA,gCACA,cACA,KACF;AAAA,MACA;AAAA,SACG;AAAA,MACH,+BACE,YACA,gCACA,cACA,KACF;AAAA,MACA;AAAA,SACG;AAAA,MACH,+BACE,YACA,gCACA,eACA,KACF;AAAA,MACA;AAAA,SACG;AAAA,MACH,+BACE,YACA,gCACA,cACA,KACF;AAAA,MACA;AAAA,SACG;AAAA,MACH,+BACE,YACA,wCACA,YACA,KACF;AAAA,MACA;AAAA,SACG;AAAA,MACH,+BACE,YACA,wCACA,YACA,KACF;AAAA,MACA;AAAA,SACG;AAAA,MACH,+BACE,YACA,wCACA,aACA,KACF;AAAA,MACA;AAAA,SACG;AAAA,MACH,qBAAqB,YAAY,MAAM,KAAK;AAAA,MAC5C;AAAA,SACG;AAAA,SACA;AAAA,MACH;AAAA;AAAA,MAEA,IACE,EAAE,IAAI,IAAI,WACD,IAAI,OAAZ,OAA0B,IAAI,OAAZ,OACV,IAAI,OAAZ,OAA0B,IAAI,OAAZ;AAAA,QAElB,MAAM,QAAQ,IAAI,GAAG,KAAK,KACzB,qBAAqB,YAAY,KAAK,KAAK;AAAA;AAAA;AAGrD,SAAS,sBAAsB,CAAC,YAAY,KAAK,KAAK,OAAO,OAAO,WAAW;AAAA,EAC7E,QAAQ;AAAA,SACD;AAAA,MACH,kBAAkB,YAAY,OAAO,SAAS;AAAA,MAC9C;AAAA,SACG;AAAA,MACH,IAAY,SAAR,MAAe;AAAA,QACjB,IAAiB,OAAO,UAApB,YAA6B,EAAE,YAAY;AAAA,UAC7C,MAAM,MAAM,wBAAuB,EAAE,CAAC;AAAA,QACxC,MAAM,MAAM;AAAA,QACZ,IAAY,OAAR,MAAa;AAAA,UACf,IAAY,MAAM,YAAd;AAAA,YAAwB,MAAM,MAAM,wBAAuB,EAAE,CAAC;AAAA,UAClE,WAAW,YAAY;AAAA,QACzB;AAAA,MACF;AAAA,MACA;AAAA,SACG;AAAA,MACU,OAAO,UAApB,WACI,eAAe,YAAY,KAAK,KAClB,OAAO,UAApB,YAA0C,OAAO,UAApB,aAC9B,eAAe,YAAY,KAAK,KAAK;AAAA,MACzC;AAAA,SACG;AAAA,MACK,SAAR,QAAiB,0BAA0B,UAAU,UAAU;AAAA,MAC/D;AAAA,SACG;AAAA,MACK,SAAR,QAAiB,0BAA0B,aAAa,UAAU;AAAA,MAClE;AAAA,SACG;AAAA,MACK,SAAR,SAAkB,WAAW,UAAU;AAAA,MACvC;AAAA,SACG;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH;AAAA,SACG;AAAA,SACA;AAAA,MACH;AAAA;AAAA,MAEA,IAAI,CAAC,6BAA6B,eAAe,GAAG;AAAA,QAClD,GAAG;AAAA,UACD,IACU,IAAI,OAAZ,OACQ,IAAI,OAAZ,QACE,QAAQ,IAAI,SAAS,SAAS,GAC/B,MAAM,IAAI,MAAM,GAAG,QAAQ,IAAI,SAAS,IAAS,SAAC,GAClD,YAAY,WAAW,qBAAqB,MAC5C,YAAoB,aAAR,OAAoB,UAAU,OAAO,MACnC,OAAO,cAAtB,cACE,WAAW,oBAAoB,KAAK,WAAW,KAAK,GACvC,OAAO,UAAtB,aACA;AAAA,YACe,OAAO,cAAtB,cACW,cAAT,SACC,OAAO,aACH,WAAW,OAAO,OACnB,WAAW,aAAa,GAAG,KAC3B,WAAW,gBAAgB,GAAG;AAAA,YACpC,WAAW,iBAAiB,KAAK,OAAO,KAAK;AAAA,YAC7C;AAAA,UACF;AAAA,UACA,OAAO,aACF,WAAW,OAAO,QACZ,UAAP,OACE,WAAW,aAAa,KAAK,EAAE,IAC/B,qBAAqB,YAAY,KAAK,KAAK;AAAA,QACnD;AAAA;AAAA;AAGR,SAAS,oBAAoB,CAAC,YAAY,KAAK,OAAO;AAAA,EACpD,QAAQ;AAAA,SACD;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH;AAAA,SACG;AAAA,MACH,0BAA0B,SAAS,UAAU;AAAA,MAC7C,0BAA0B,QAAQ,UAAU;AAAA,MAC5C,IAAI,SAAS,OACX,YAAY,OACZ;AAAA,MACF,KAAK,WAAW;AAAA,QACd,IAAI,MAAM,eAAe,OAAO,GAAG;AAAA,UACjC,IAAI,YAAY,MAAM;AAAA,UACtB,IAAY,aAAR;AAAA,YACF,QAAQ;AAAA,mBACD;AAAA,gBACH,SAAS;AAAA,gBACT;AAAA,mBACG;AAAA,gBACH,YAAY;AAAA,gBACZ;AAAA,mBACG;AAAA,mBACA;AAAA,gBACH,MAAM,MAAM,wBAAuB,KAAK,GAAG,CAAC;AAAA;AAAA,gBAE5C,QAAQ,YAAY,KAAK,SAAS,WAAW,OAAO,IAAI;AAAA;AAAA,QAEhE;AAAA,MACF,aACE,QAAQ,YAAY,KAAK,UAAU,MAAM,QAAQ,OAAO,IAAI;AAAA,MAC9D,UAAU,QAAQ,YAAY,KAAK,OAAO,MAAM,KAAK,OAAO,IAAI;AAAA,MAChE;AAAA,SACG;AAAA,MACH,0BAA0B,WAAW,UAAU;AAAA,MAC/C,IAAI,eAAgB,UAAU,YAAY,YAAY,MACpD,UAAU,MACV,iBAAiB;AAAA,MACnB,KAAK,UAAU;AAAA,QACb,IAAI,MAAM,eAAe,MAAM,GAAG;AAAA,UAChC,IAAI,gBAAgB,MAAM;AAAA,UAC1B,IAAY,iBAAR;AAAA,YACF,QAAQ;AAAA,mBACD;AAAA,gBACH,YAAY;AAAA,gBACZ;AAAA,mBACG;AAAA,gBACH,YAAY;AAAA,gBACZ;AAAA,mBACG;AAAA,gBACH,UAAU;AAAA,gBACV;AAAA,mBACG;AAAA,gBACH,iBAAiB;AAAA,gBACjB;AAAA,mBACG;AAAA,gBACH,UAAU;AAAA,gBACV;AAAA,mBACG;AAAA,gBACH,eAAe;AAAA,gBACf;AAAA,mBACG;AAAA,mBACA;AAAA,gBACH,IAAY,iBAAR;AAAA,kBACF,MAAM,MAAM,wBAAuB,KAAK,GAAG,CAAC;AAAA,gBAC9C;AAAA;AAAA,gBAEA,QAAQ,YAAY,KAAK,QAAQ,eAAe,OAAO,IAAI;AAAA;AAAA,QAEnE;AAAA,MACF,UACE,YACA,SACA,cACA,SACA,gBACA,WACA,WACA,KACF;AAAA,MACA;AAAA,SACG;AAAA,MACH,0BAA0B,WAAW,UAAU;AAAA,MAC/C,SAAS,YAAY,UAAU;AAAA,MAC/B,KAAK,aAAa;AAAA,QAChB,IACE,MAAM,eAAe,SAAS,MAC5B,eAAe,MAAM,YAAqB,gBAAR;AAAA,UAEpC,QAAQ;AAAA,iBACD;AAAA,cACH,UAAU;AAAA,cACV;AAAA,iBACG;AAAA,cACH,YAAY;AAAA,cACZ;AAAA,iBACG;AAAA,cACH,SAAS;AAAA;AAAA,cAET,QAAQ,YAAY,KAAK,WAAW,cAAc,OAAO,IAAI;AAAA;AAAA,MAErE,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,WAAW,WAAW,CAAC,CAAC;AAAA,MAChB,OAAR,OACI,cAAc,YAAY,CAAC,CAAC,QAAQ,KAAK,KAAE,IACnC,SAAR,QAAiB,cAAc,YAAY,CAAC,CAAC,QAAQ,OAAO,IAAE;AAAA,MAClE;AAAA,SACG;AAAA,MACH,0BAA0B,WAAW,UAAU;AAAA,MAC/C,UAAU,YAAY,SAAS;AAAA,MAC/B,KAAK,aAAa;AAAA,QAChB,IACE,MAAM,eAAe,SAAS,MAC5B,eAAe,MAAM,YAAqB,gBAAR;AAAA,UAEpC,QAAQ;AAAA,iBACD;AAAA,cACH,SAAS;AAAA,cACT;AAAA,iBACG;AAAA,cACH,YAAY;AAAA,cACZ;AAAA,iBACG;AAAA,cACH,UAAU;AAAA,cACV;AAAA,iBACG;AAAA,cACH,IAAY,gBAAR;AAAA,gBAAsB,MAAM,MAAM,wBAAuB,EAAE,CAAC;AAAA,cAChE;AAAA;AAAA,cAEA,QAAQ,YAAY,KAAK,WAAW,cAAc,OAAO,IAAI;AAAA;AAAA,MAErE,aAAa,YAAY,QAAQ,WAAW,OAAO;AAAA,MACnD;AAAA,SACG;AAAA,MACH,KAAK,WAAW;AAAA,QACd,IACE,MAAM,eAAe,OAAO,MAC1B,SAAS,MAAM,UAAmB,UAAR;AAAA,UAE5B,QAAQ;AAAA,iBACD;AAAA,cACH,WAAW,WACT,UACe,OAAO,WAAtB,cACa,OAAO,WAApB;AAAA,cACF;AAAA;AAAA,cAEA,QAAQ,YAAY,KAAK,SAAS,QAAQ,OAAO,IAAI;AAAA;AAAA,MAE7D;AAAA,SACG;AAAA,MACH,0BAA0B,gBAAgB,UAAU;AAAA,MACpD,0BAA0B,UAAU,UAAU;AAAA,MAC9C,0BAA0B,UAAU,UAAU;AAAA,MAC9C,0BAA0B,SAAS,UAAU;AAAA,MAC7C;AAAA,SACG;AAAA,SACA;AAAA,MACH,0BAA0B,QAAQ,UAAU;AAAA,MAC5C;AAAA,SACG;AAAA,SACA;AAAA,MACH,KAAK,SAAS,EAAG,SAAS,gBAAgB,QAAQ;AAAA,QAChD,0BAA0B,gBAAgB,SAAS,UAAU;AAAA,MAC/D;AAAA,SACG;AAAA,MACH,0BAA0B,SAAS,UAAU;AAAA,MAC7C,0BAA0B,QAAQ,UAAU;AAAA,MAC5C;AAAA,SACG;AAAA,MACH,0BAA0B,UAAU,UAAU;AAAA,MAC9C;AAAA,SACG;AAAA,SACA;AAAA,SACA;AAAA,MACH,0BAA0B,SAAS,UAAU,GAC3C,0BAA0B,QAAQ,UAAU;AAAA,SAC3C;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH,KAAK,kBAAkB;AAAA,QACrB,IACE,MAAM,eAAe,cAAc,MACjC,SAAS,MAAM,iBAA0B,UAAR;AAAA,UAEnC,QAAQ;AAAA,iBACD;AAAA,iBACA;AAAA,cACH,MAAM,MAAM,wBAAuB,KAAK,GAAG,CAAC;AAAA;AAAA,cAE5C,QAAQ,YAAY,KAAK,gBAAgB,QAAQ,OAAO,IAAI;AAAA;AAAA,MAEpE;AAAA;AAAA,MAEA,IAAI,gBAAgB,GAAG,GAAG;AAAA,QACxB,KAAK,iBAAiB;AAAA,UACpB,MAAM,eAAe,aAAa,MAC9B,SAAS,MAAM,gBACN,WAAN,aACH,uBACE,YACA,KACA,eACA,QACA,OACK,SACP;AAAA,QACN;AAAA,MACF;AAAA;AAAA,EAEJ,KAAK,gBAAgB;AAAA,IACnB,MAAM,eAAe,YAAY,MAC7B,SAAS,MAAM,eACT,UAAR,QACE,QAAQ,YAAY,KAAK,cAAc,QAAQ,OAAO,IAAI;AAAA;AAElE,SAAS,gBAAgB,CAAC,YAAY,KAAK,WAAW,WAAW;AAAA,EAC/D,QAAQ;AAAA,SACD;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH;AAAA,SACG;AAAA,MACH,IAAI,OAAO,MACT,OAAO,MACP,QAAQ,MACR,eAAe,MACf,mBAAmB,MACnB,UAAU,MACV,iBAAiB;AAAA,MACnB,KAAK,WAAW,WAAW;AAAA,QACzB,IAAI,WAAW,UAAU;AAAA,QACzB,IAAI,UAAU,eAAe,OAAO,KAAa,YAAR;AAAA,UACvC,QAAQ;AAAA,iBACD;AAAA,cACH;AAAA,iBACG;AAAA,cACH;AAAA,iBACG;AAAA,cACH,mBAAmB;AAAA;AAAA,cAEnB,UAAU,eAAe,OAAO,KAC9B,QAAQ,YAAY,KAAK,SAAS,MAAM,WAAW,QAAQ;AAAA;AAAA,MAErE;AAAA,MACA,SAAS,eAAe,WAAW;AAAA,QACjC,IAAI,UAAU,UAAU;AAAA,QACxB,WAAW,UAAU;AAAA,QACrB,IACE,UAAU,eAAe,WAAW,MAC3B,WAAR,QAA2B,YAAR;AAAA,UAEpB,QAAQ;AAAA,iBACD;AAAA,cACH,OAAO;AAAA,cACP;AAAA,iBACG;AAAA,cACH,OAAO;AAAA,cACP;AAAA,iBACG;AAAA,cACH,UAAU;AAAA,cACV;AAAA,iBACG;AAAA,cACH,iBAAiB;AAAA,cACjB;AAAA,iBACG;AAAA,cACH,QAAQ;AAAA,cACR;AAAA,iBACG;AAAA,cACH,eAAe;AAAA,cACf;AAAA,iBACG;AAAA,iBACA;AAAA,cACH,IAAY,WAAR;AAAA,gBACF,MAAM,MAAM,wBAAuB,KAAK,GAAG,CAAC;AAAA,cAC9C;AAAA;AAAA,cAEA,YAAY,YACV,QACE,YACA,KACA,aACA,SACA,WACA,QACF;AAAA;AAAA,MAEV;AAAA,MACA,YACE,YACA,OACA,cACA,kBACA,SACA,gBACA,MACA,IACF;AAAA,MACA;AAAA,SACG;AAAA,MACH,UAAU,QAAQ,eAAe,cAAc;AAAA,MAC/C,KAAK,QAAQ;AAAA,QACX,IACI,mBAAmB,UAAU,OAC/B,UAAU,eAAe,IAAI,KAAa,oBAAR;AAAA,UAElC,QAAQ;AAAA,iBACD;AAAA,cACH;AAAA,iBACG;AAAA,cACH,UAAU;AAAA;AAAA,cAEV,UAAU,eAAe,IAAI,KAC3B,QACE,YACA,KACA,MACA,MACA,WACA,gBACF;AAAA;AAAA,MAEV,KAAK,QAAQ;AAAA,QACX,IACI,OAAO,UAAU,OAClB,mBAAmB,UAAU,OAC9B,UAAU,eAAe,IAAI,MAClB,QAAR,QAAwB,oBAAR;AAAA,UAEnB,QAAQ;AAAA,iBACD;AAAA,cACH,cAAc;AAAA,cACd;AAAA,iBACG;AAAA,cACH,eAAe;AAAA,cACf;AAAA,iBACG;AAAA,cACH,QAAQ;AAAA;AAAA,cAER,SAAS,oBACP,QACE,YACA,KACA,MACA,MACA,WACA,gBACF;AAAA;AAAA,MAEV,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,YAAY;AAAA,MACJ,eAAR,OACI,cAAc,YAAY,CAAC,CAAC,WAAW,aAAa,KAAE,IACtD,CAAC,CAAC,cAAc,CAAC,CAAC,cACT,OAAR,OACG,cAAc,YAAY,CAAC,CAAC,WAAW,KAAK,IAAE,IAC9C,cAAc,YAAY,CAAC,CAAC,WAAW,YAAY,CAAC,IAAI,IAAI,KAAE;AAAA,MACtE;AAAA,SACG;AAAA,MACH,UAAU,cAAc;AAAA,MACxB,KAAK,gBAAgB;AAAA,QACnB,IACI,OAAO,UAAU,eACnB,UAAU,eAAe,YAAY,KAC3B,QAAR,QACA,CAAC,UAAU,eAAe,YAAY;AAAA,UAExC,QAAQ;AAAA,iBACD;AAAA,cACH;AAAA,iBACG;AAAA,cACH;AAAA;AAAA,cAEA,QAAQ,YAAY,KAAK,cAAc,MAAM,WAAW,IAAI;AAAA;AAAA,MAEpE,KAAK,SAAS;AAAA,QACZ,IACI,OAAO,UAAU,QAClB,OAAO,UAAU,QAClB,UAAU,eAAe,KAAK,MAAc,QAAR,QAAwB,QAAR;AAAA,UAEpD,QAAQ;AAAA,iBACD;AAAA,cACH,cAAc;AAAA,cACd;AAAA,iBACG;AAAA,cACH,UAAU;AAAA,cACV;AAAA,iBACG;AAAA,cACH;AAAA,iBACG;AAAA,cACH,IAAY,QAAR;AAAA,gBAAc,MAAM,MAAM,wBAAuB,EAAE,CAAC;AAAA,cACxD;AAAA;AAAA,cAEA,SAAS,QACP,QAAQ,YAAY,KAAK,OAAO,MAAM,WAAW,IAAI;AAAA;AAAA,MAE/D,eAAe,YAAY,aAAa,OAAO;AAAA,MAC/C;AAAA,SACG;AAAA,MACH,SAAS,eAAe;AAAA,QACtB,IACI,cAAc,UAAU,cAC1B,UAAU,eAAe,WAAW,KAC1B,eAAR,QACA,CAAC,UAAU,eAAe,WAAW;AAAA,UAEvC,QAAQ;AAAA,iBACD;AAAA,cACH,WAAW,WAAW;AAAA,cACtB;AAAA;AAAA,cAEA,QACE,YACA,KACA,aACA,MACA,WACA,WACF;AAAA;AAAA,MAER,KAAK,oBAAoB;AAAA,QACvB,IACI,cAAc,UAAU,mBACzB,UAAU,UAAU,mBACrB,UAAU,eAAe,gBAAgB,KACvC,gBAAgB,YACP,eAAR,QAA+B,WAAR;AAAA,UAE1B,QAAQ;AAAA,iBACD;AAAA,cACH,WAAW,WACT,eACe,OAAO,gBAAtB,cACa,OAAO,gBAApB;AAAA,cACF;AAAA;AAAA,cAEA,QACE,YACA,KACA,kBACA,aACA,WACA,OACF;AAAA;AAAA,MAER;AAAA,SACG;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH,SAAS,eAAe;AAAA,QACrB,cAAc,UAAU,cACvB,UAAU,eAAe,WAAW,KAC1B,eAAR,QACA,CAAC,UAAU,eAAe,WAAW,KACrC,QAAQ,YAAY,KAAK,aAAa,MAAM,WAAW,WAAW;AAAA,MACxE,KAAK,WAAW;AAAA,QACd,IACI,cAAc,UAAU,UACzB,UAAU,UAAU,UACrB,UAAU,eAAe,OAAO,KAC9B,gBAAgB,YACP,eAAR,QAA+B,WAAR;AAAA,UAE1B,QAAQ;AAAA,iBACD;AAAA,iBACA;AAAA,cACH,IAAY,eAAR;AAAA,gBACF,MAAM,MAAM,wBAAuB,KAAK,GAAG,CAAC;AAAA,cAC9C;AAAA;AAAA,cAEA,QACE,YACA,KACA,SACA,aACA,WACA,OACF;AAAA;AAAA,MAER;AAAA;AAAA,MAEA,IAAI,gBAAgB,GAAG,GAAG;AAAA,QACxB,SAAS,eAAe;AAAA,UACrB,cAAc,UAAU,cACvB,UAAU,eAAe,WAAW,KACvB,gBAAN,aACL,CAAC,UAAU,eAAe,WAAW,KACrC,uBACE,YACA,KACA,aACK,WACL,WACA,WACF;AAAA,QACN,KAAK,kBAAkB;AAAA,UACpB,cAAc,UAAU,iBACtB,UAAU,UAAU,iBACrB,CAAC,UAAU,eAAe,cAAc,KACtC,gBAAgB,WACJ,gBAAN,aAAgC,YAAN,aAChC,uBACE,YACA,KACA,gBACA,aACA,WACA,OACF;AAAA,QACN;AAAA,MACF;AAAA;AAAA,EAEJ,SAAS,eAAe;AAAA,IACrB,cAAc,UAAU,cACvB,UAAU,eAAe,WAAW,KAC1B,eAAR,QACA,CAAC,UAAU,eAAe,WAAW,KACrC,QAAQ,YAAY,KAAK,aAAa,MAAM,WAAW,WAAW;AAAA,EACxE,KAAK,YAAY;AAAA,IACd,cAAc,UAAU,WACtB,UAAU,UAAU,WACrB,CAAC,UAAU,eAAe,QAAQ,KAChC,gBAAgB,WACP,eAAR,QAA+B,WAAR,QACxB,QAAQ,YAAY,KAAK,UAAU,aAAa,WAAW,OAAO;AAAA;AAE1E,SAAS,sBAAsB,CAAC,eAAe;AAAA,EAC7C,QAAQ;AAAA,SACD;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH,OAAO;AAAA;AAAA,MAEP,OAAO;AAAA;AAAA;AAGb,SAAS,iBAAiB,GAAG;AAAA,EAC3B,IAAmB,OAAO,YAAY,qBAAlC,YAAoD;AAAA,IACtD,SACM,QAAQ,GACV,OAAO,GACP,kBAAkB,YAAY,iBAAiB,UAAU,GACzD,IAAI,EACN,IAAI,gBAAgB,QACpB,KACA;AAAA,MACA,IAAI,QAAQ,gBAAgB,IAC1B,eAAe,MAAM,cACrB,gBAAgB,MAAM,eACtB,WAAW,MAAM;AAAA,MACnB,IAAI,gBAAgB,YAAY,uBAAuB,aAAa,GAAG;AAAA,QACrE,gBAAgB;AAAA,QAChB,WAAW,MAAM;AAAA,QACjB,KAAK,KAAK,EAAG,IAAI,gBAAgB,QAAQ,KAAK;AAAA,UAC5C,IAAI,eAAe,gBAAgB,IACjC,mBAAmB,aAAa;AAAA,UAClC,IAAI,mBAAmB;AAAA,YAAU;AAAA,UACjC,MAAuC,cAAnC,qBACkC,eAApC,yBAAuB;AAAA,UACzB,uBACE,uBAAuB,oBAAoB,MACzC,eAAe,aAAa,aAC7B,iBACC,uBACC,eAAe,WACZ,KACC,WAAW,qBACX,eAAe;AAAA,QAC1B;AAAA,QACA,EAAE;AAAA,QACF,QAAS,KAAK,eAAe,kBAAmB,MAAM,WAAW;AAAA,QACjE;AAAA,QACA,IAAI,KAAK;AAAA,UAAO;AAAA,MAClB;AAAA,IACF;AAAA,IACA,IAAI,IAAI;AAAA,MAAO,OAAO,OAAO,QAAQ;AAAA,EACvC;AAAA,EACA,OAAO,UAAU,eACb,QAAQ,UAAU,WAAW,UAAwB,OAAO,UAApB,YACxC,QACA;AAAA;AAIN,SAAS,iCAAiC,CAAC,sBAAsB;AAAA,EAC/D,OAAa,qBAAqB,aAA3B,IACH,uBACA,qBAAqB;AAAA;AAE3B,SAAS,iBAAiB,CAAC,cAAc;AAAA,EACvC,QAAQ;AAAA,SACD;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAO;AAAA;AAAA,MAEP,OAAO;AAAA;AAAA;AAGb,SAAS,uBAAuB,CAAC,iBAAiB,MAAM;AAAA,EACtD,IAAU,oBAAN;AAAA,IACF,QAAQ;AAAA,WACD;AAAA,QACH,OAAO;AAAA,WACJ;AAAA,QACH,OAAO;AAAA;AAAA,QAEP,OAAO;AAAA;AAAA,EAEb,OAAa,oBAAN,KAA6C,SAApB,kBAC5B,IACA;AAAA;AAEN,SAAS,oBAAoB,CAAC,MAAM,OAAO;AAAA,EACzC,OACiB,SAAf,cACe,SAAf,cACa,OAAO,MAAM,aAA1B,YACa,OAAO,MAAM,aAA1B,YACa,OAAO,MAAM,aAA1B,YACc,OAAO,MAAM,4BAA1B,YACU,MAAM,4BAAf,QACQ,MAAM,wBAAwB,UAAtC;AAAA;AAIN,SAAS,4BAA4B,GAAG;AAAA,EACtC,IAAI,QAAQ,OAAO;AAAA,EACnB,IAAI,SAAwB,MAAM,SAArB,YAA2B;AAAA,IACtC,IAAI,UAAU;AAAA,MAAgC,OAAO;AAAA,IACrD,iCAAiC;AAAA,IACjC,OAAO;AAAA,EACT;AAAA,EACA,iCAAiC;AAAA,EACjC,OAAO;AAAA;AAgBT,SAAS,qBAAqB,CAAC,OAAO;AAAA,EACpC,WAAW,QAAS,GAAG;AAAA,IACrB,MAAM;AAAA,GACP;AAAA;AAEH,SAAS,gBAAgB,CAAC,MAAM;AAAA,EAC9B,OAAkB,SAAX;AAAA;AAET,SAAS,sBAAsB,CAAC,gBAAgB,mBAAmB;AAAA,EACjE,IAAI,OAAO,mBACT,QAAQ;AAAA,EACV,GAAG;AAAA,IACD,IAAI,WAAW,KAAK;AAAA,IACpB,eAAe,YAAY,IAAI;AAAA,IAC/B,IAAI,YAAkB,SAAS,aAAf;AAAA,MACd,IAAM,OAAO,SAAS,MAAgB,SAAT,QAA0B,SAAT,MAAgB;AAAA,QAC5D,IAAU,UAAN,GAAa;AAAA,UACf,eAAe,YAAY,QAAQ;AAAA,UACnC,iBAAiB,iBAAiB;AAAA,UAClC;AAAA,QACF;AAAA,QACA;AAAA,MACF,EAAO,SACG,SAAR,OACS,SAAT,QACS,SAAT,QACS,SAAT,QACQ,SAAR;AAAA,QAEA;AAAA,MACG,SAAe,SAAX;AAAA,QACP,yBAAyB,eAAe,cAAc,eAAe;AAAA,MAClE,SAAe,SAAX,QAAiB;AAAA,QACxB,OAAO,eAAe,cAAc;AAAA,QACpC,yBAAyB,IAAI;AAAA,QAC7B,SAAS,gBAAgB,KAAK,WAAY,iBAAiB;AAAA,UACzD,MAAsC,aAAlC,mBACuB,aAAd;AAAA,UACb,cAAc,4BACC,aAAb,YACY,aAAZ,WACY,aAAX,UACkB,cAAc,IAAI,YAAY,MAA/C,gBACF,KAAK,YAAY,aAAa;AAAA,UAChC,gBAAgB;AAAA,QAClB;AAAA,MACF,EACE;AAAA,QAAW,SAAX,UACE,yBAAyB,eAAe,cAAc,IAAI;AAAA,IAChE,OAAO;AAAA,EACT,SAAS;AAAA,EACT,iBAAiB,iBAAiB;AAAA;AAEpC,SAAS,8BAA8B,CAAC,kBAAkB,UAAU;AAAA,EAClE,IAAI,OAAO;AAAA,EACX,mBAAmB;AAAA,EACnB,GAAG;AAAA,IACD,IAAI,WAAW,KAAK;AAAA,IACd,KAAK,aAAX,IACI,YACI,KAAK,kBAAkB,KAAK,MAAM,SACnC,KAAK,MAAM,UAAU,WACpB,KAAK,MAAM,UAAU,KAAK,mBAAmB,IACxC,KAAK,aAAa,OAAO,MAAhC,MAAqC,KAAK,gBAAgB,OAAO,KAC7D,KAAK,aAAX,MACC,YACK,KAAK,eAAe,KAAK,WAAa,KAAK,YAAY,MACxD,KAAK,YAAY,KAAK,gBAAgB;AAAA,IAC/C,IAAI,YAAkB,SAAS,aAAf;AAAA,MACd,IAAM,OAAO,SAAS,MAAgB,SAAT;AAAA,QAC3B,IAAU,qBAAN;AAAA,UAAwB;AAAA,QACvB;AAAA;AAAA,MAEL;AAAA,QAAS,SAAR,OAAyB,SAAT,QAA0B,SAAT,QAA0B,SAAT,QACjD;AAAA,IACN,OAAO;AAAA,EACT,SAAS;AAAA;AAEX,SAAS,uBAAuB,CAAC,WAAW;AAAA,EAC1C,IAAI,WAAW,UAAU;AAAA,EACzB,YAAmB,SAAS,aAAhB,OAA6B,WAAW,SAAS;AAAA,EAC7D,MAAO,YAAY;AAAA,IACjB,IAAI,OAAO;AAAA,IACX,WAAW,SAAS;AAAA,IACpB,QAAQ,KAAK;AAAA,WACN;AAAA,WACA;AAAA,WACA;AAAA,QACH,wBAAwB,IAAI;AAAA,QAC5B,sBAAsB,IAAI;AAAA,QAC1B;AAAA,WACG;AAAA,WACA;AAAA,QACH;AAAA,WACG;AAAA,QACH,IAAqB,KAAK,IAAI,YAAY,MAAtC;AAAA,UAAyC;AAAA;AAAA,IAEjD,UAAU,YAAY,IAAI;AAAA,EAC5B;AAAA;AAEF,SAAS,kBAAkB,CAAC,UAAU,MAAM,OAAO,mBAAmB;AAAA,EACpE,MAAa,SAAS,aAAf,KAA2B;AAAA,IAChC,IAAI,WAAW;AAAA,IACf,IAAI,SAAS,SAAS,YAAY,MAAM,KAAK,YAAY,GAAG;AAAA,MAC1D,IACE,CAAC,sBACY,SAAS,aAArB,WAA8C,SAAS,SAAtB;AAAA,QAElC;AAAA,IACJ,EAAO,SAAI,CAAC;AAAA,MACV,IAAgB,SAAZ,WAAiC,SAAS,SAAtB,UAA4B;AAAA,QAClD,IAAI,OAAe,SAAS,QAAjB,OAAwB,OAAO,KAAK,SAAS;AAAA,QACxD,IACe,SAAS,SAAtB,YACA,SAAS,aAAa,MAAM,MAAM;AAAA,UAElC,OAAO;AAAA,MACX,EAAO;AAAA,eAAO;AAAA,IACX,SAAI,CAAC,SAAS;AAAA,MACjB,QAAQ;AAAA,aACD;AAAA,UACH,IAAI,CAAC,SAAS,aAAa,UAAU;AAAA,YAAG;AAAA,UACxC,OAAO;AAAA,aACJ;AAAA,UACH,OAAO,SAAS,aAAa,KAAK;AAAA,UAClC,IAAqB,SAAjB,gBAAyB,SAAS,aAAa,iBAAiB;AAAA,YAClE;AAAA,UACG,SACH,SAAS,SAAS,OAClB,SAAS,aAAa,MAAM,OACjB,SAAS,QAAjB,QAAgC,SAAS,SAAhB,KACtB,OACA,SAAS,SACf,SAAS,aAAa,aAAa,OACxB,SAAS,eAAjB,OAA+B,OAAO,SAAS,gBAClD,SAAS,aAAa,OAAO,OAClB,SAAS,SAAjB,OAAyB,OAAO,SAAS;AAAA,YAE5C;AAAA,UACF,OAAO;AAAA,aACJ;AAAA,UACH,IAAI,SAAS,aAAa,iBAAiB;AAAA,YAAG;AAAA,UAC9C,OAAO;AAAA,aACJ;AAAA,UACH,OAAO,SAAS,aAAa,KAAK;AAAA,UAClC,KACG,UAAkB,SAAS,OAAjB,OAAuB,OAAO,SAAS,QAChD,SAAS,aAAa,MAAM,OACjB,SAAS,QAAjB,OAAwB,OAAO,SAAS,SAC3C,SAAS,aAAa,aAAa,OACxB,SAAS,eAAjB,OAA+B,OAAO,SAAS,iBACpD,QACA,SAAS,aAAa,OAAO,KAC7B,CAAC,SAAS,aAAa,UAAU;AAAA,YAEjC;AAAA,UACF,OAAO;AAAA;AAAA,UAEP,OAAO;AAAA;AAAA,IAEb,WAAW,kBAAkB,SAAS,WAAW;AAAA,IACjD,IAAa,aAAT;AAAA,MAAmB;AAAA,EACzB;AAAA,EACA,OAAO;AAAA;AAET,SAAS,sBAAsB,CAAC,UAAU,MAAM,mBAAmB;AAAA,EACjE,IAAW,SAAP;AAAA,IAAa,OAAO;AAAA,EACxB,MAAa,SAAS,aAAf,KAA2B;AAAA,IAChC,KACS,SAAS,aAAf,KACa,SAAS,aAArB,WACa,SAAS,SAAtB,aACF,CAAC;AAAA,MAED,OAAO;AAAA,IACT,WAAW,kBAAkB,SAAS,WAAW;AAAA,IACjD,IAAa,aAAT;AAAA,MAAmB,OAAO;AAAA,EAChC;AAAA,EACA,OAAO;AAAA;AAET,SAAS,2BAA2B,CAAC,UAAU,mBAAmB;AAAA,EAChE,MAAa,SAAS,aAAf,KAA2B;AAAA,IAChC,KACS,SAAS,aAAf,KACa,SAAS,aAArB,WACa,SAAS,SAAtB,aACF,CAAC;AAAA,MAED,OAAO;AAAA,IACT,WAAW,kBAAkB,SAAS,WAAW;AAAA,IACjD,IAAa,aAAT;AAAA,MAAmB,OAAO;AAAA,EAChC;AAAA,EACA,OAAO;AAAA;AAET,SAAS,yBAAyB,CAAC,UAAU;AAAA,EAC3C,OAAgB,SAAS,SAAlB,QAAmC,SAAS,SAAlB;AAAA;AAEnC,SAAS,0BAA0B,CAAC,UAAU;AAAA,EAC5C,OACW,SAAS,SAAlB,QACU,SAAS,SAAlB,QAAwC,SAAS,cAAc,eAArC;AAAA;AAG/B,SAAS,6BAA6B,CAAC,UAAU,UAAU;AAAA,EACzD,IAAI,gBAAgB,SAAS;AAAA,EAC7B,IAAa,SAAS,SAAlB;AAAA,IAAwB,SAAS,cAAc;AAAA,EAC9C,SAAa,SAAS,SAAlB,QAAwC,cAAc,eAA5B;AAAA,IACjC,SAAS;AAAA,EACN;AAAA,IACH,IAAI,WAAW,QAAS,GAAG;AAAA,MACzB,SAAS;AAAA,MACT,cAAc,oBAAoB,oBAAoB,QAAQ;AAAA;AAAA,IAEhE,cAAc,iBAAiB,oBAAoB,QAAQ;AAAA,IAC3D,SAAS,cAAc;AAAA;AAAA;AAG3B,SAAS,iBAAiB,CAAC,MAAM;AAAA,EAC/B,MAAe,QAAR,MAAc,OAAO,KAAK,aAAa;AAAA,IAC5C,IAAI,WAAW,KAAK;AAAA,IACpB,IAAU,aAAN,KAAwB,aAAN;AAAA,MAAgB;AAAA,IACtC,IAAU,aAAN,GAAgB;AAAA,MAClB,WAAW,KAAK;AAAA,MAChB,IACU,aAAR,OACS,aAAT,QACS,aAAT,QACS,aAAT,QACQ,aAAR,OACS,aAAT,QACQ,aAAR;AAAA,QAEA;AAAA,MACF,IAAa,aAAT,QAA8B,aAAT;AAAA,QAAmB,OAAO;AAAA,IACrD;AAAA,EACF;AAAA,EACA,OAAO;AAAA;AAGT,SAAS,+CAA+C,CAAC,mBAAmB;AAAA,EAC1E,oBAAoB,kBAAkB;AAAA,EACtC,SAAS,QAAQ,EAAG,qBAAqB;AAAA,IACvC,IAAU,kBAAkB,aAAxB,GAAkC;AAAA,MACpC,IAAI,OAAO,kBAAkB;AAAA,MAC7B,IAAa,SAAT,QAA0B,SAAT,MAAe;AAAA,QAClC,IAAU,UAAN;AAAA,UACF,OAAO,kBAAkB,kBAAkB,WAAW;AAAA,QACxD;AAAA,MACF,EACE;AAAA,QAAS,SAAR,OACU,SAAT,QACS,SAAT,QACS,SAAT,QACQ,SAAR,OACA;AAAA,IACN;AAAA,IACA,oBAAoB,kBAAkB;AAAA,EACxC;AAAA,EACA,OAAO;AAAA;AAET,SAAS,0BAA0B,CAAC,gBAAgB;AAAA,EAClD,iBAAiB,eAAe;AAAA,EAChC,SAAS,QAAQ,EAAG,kBAAkB;AAAA,IACpC,IAAU,eAAe,aAArB,GAA+B;AAAA,MACjC,IAAI,OAAO,eAAe;AAAA,MAC1B,IACU,SAAR,OACS,SAAT,QACS,SAAT,QACS,SAAT,QACQ,SAAR,KACA;AAAA,QACA,IAAU,UAAN;AAAA,UAAa,OAAO;AAAA,QACxB;AAAA,MACF,EAAO;AAAA,QAAU,SAAT,QAA0B,SAAT,QAAkB;AAAA,IAC7C;AAAA,IACA,iBAAiB,eAAe;AAAA,EAClC;AAAA,EACA,OAAO;AAAA;AAET,SAAS,wBAAwB,CAAC,MAAM,OAAO,uBAAuB;AAAA,EACpE,QAAQ,kCAAkC,qBAAqB;AAAA,EAC/D,QAAQ;AAAA,SACD;AAAA,MACH,OAAO,MAAM;AAAA,MACb,IAAI,CAAC;AAAA,QAAM,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,MAClD,OAAO;AAAA,SACJ;AAAA,MACH,OAAO,MAAM;AAAA,MACb,IAAI,CAAC;AAAA,QAAM,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,MAClD,OAAO;AAAA,SACJ;AAAA,MACH,OAAO,MAAM;AAAA,MACb,IAAI,CAAC;AAAA,QAAM,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,MAClD,OAAO;AAAA;AAAA,MAEP,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA;AAAA;AAG7C,SAAS,wBAAwB,CAAC,UAAU;AAAA,EAC1C,SAAS,aAAa,SAAS,WAAY,WAAW;AAAA,IACpD,SAAS,oBAAoB,WAAW,EAAE;AAAA,EAC5C,sBAAsB,QAAQ;AAAA;AAIhC,SAAS,gBAAgB,CAAC,WAAW;AAAA,EACnC,OAAsB,OAAO,UAAU,gBAAhC,aACH,UAAU,YAAY,IAChB,UAAU,aAAhB,IACE,YACA,UAAU;AAAA;AAclB,SAAS,aAAa,GAAG;AAAA,EACvB,IAAI,uBAAuB,mBAAmB,EAAE,GAC9C,eAAe,gBAAgB;AAAA,EACjC,OAAO,wBAAwB;AAAA;AAEjC,SAAS,gBAAgB,CAAC,MAAM;AAAA,EAC9B,IAAI,WAAW,oBAAoB,IAAI;AAAA,EAC9B,aAAT,QAA2B,SAAS,QAAf,KAAiC,SAAS,SAApB,SACvC,mBAAmB,QAAQ,IAC3B,mBAAmB,EAAE,IAAI;AAAA;AAG/B,SAAS,YAAY,CAAC,KAAK,MAAM,aAAa;AAAA,EAC5C,IAAI,gBAAgB;AAAA,EACpB,IAAI,iBAA8B,OAAO,SAApB,YAA4B,MAAM;AAAA,IACrD,IAAI,qBACF,+CAA+C,IAAI;AAAA,IACrD,qBACE,eAAe,MAAM,cAAc,qBAAqB;AAAA,IAC7C,OAAO,gBAApB,aACG,sBAAsB,mBAAmB,cAAc;AAAA,IAC1D,eAAe,IAAI,kBAAkB,MAClC,eAAe,IAAI,kBAAkB,GACrC,MAAM,EAAE,KAAU,aAA0B,KAAW,GAC/C,cAAc,cAAc,kBAAkB,MAAvD,SACI,OAAO,cAAc,cAAc,MAAM,GAC3C,qBAAqB,MAAM,QAAQ,GAAG,GACtC,oBAAoB,IAAI,GACxB,cAAc,KAAK,YAAY,IAAI;AAAA,EACzC;AAAA;AAEF,SAAS,WAAW,CAAC,MAAM;AAAA,EACzB,mBAAmB,EAAE,IAAI;AAAA,EACzB,aAAa,gBAAgB,MAAM,IAAI;AAAA;AAEzC,SAAS,UAAU,CAAC,MAAM,aAAa;AAAA,EACrC,mBAAmB,EAAE,MAAM,WAAW;AAAA,EACtC,aAAa,cAAc,MAAM,WAAW;AAAA;AAE9C,SAAS,OAAO,CAAC,MAAM,IAAI,UAAS;AAAA,EAClC,mBAAmB,EAAE,MAAM,IAAI,QAAO;AAAA,EACtC,IAAI,gBAAgB;AAAA,EACpB,IAAI,iBAAiB,QAAQ,IAAI;AAAA,IAC/B,IAAI,kBACF,6BACA,+CAA+C,EAAE,IACjD;AAAA,IACU,OAAZ,UACI,YAAW,SAAQ,eACf,mBACA,mBACA,+CACE,SAAQ,WACV,IACA,MACW,OAAO,SAAQ,eAA5B,aACG,mBACC,kBACA,+CACE,SAAQ,UACV,IACA,SACH,mBACC,YACA,+CAA+C,IAAI,IACnD,OACH,mBACC,YACA,+CAA+C,IAAI,IACnD;AAAA,IACN,IAAI,MAAM;AAAA,IACV,QAAQ;AAAA,WACD;AAAA,QACH,MAAM,YAAY,IAAI;AAAA,QACtB;AAAA,WACG;AAAA,QACH,MAAM,aAAa,IAAI;AAAA;AAAA,IAE3B,gBAAgB,IAAI,GAAG,MACnB,OAAO,QACP;AAAA,MACE,KAAK;AAAA,MACL,MACc,OAAZ,WAAkB,YAAW,SAAQ,cAAmB,YAAI;AAAA,MAC9D;AAAA,IACF,GACA,QACF,GACA,gBAAgB,IAAI,KAAK,IAAI,GACpB,cAAc,cAAc,eAAe,MAApD,QACe,OAAZ,WACC,cAAc,cAAc,6BAA6B,GAAG,CAAC,KACjD,OAAb,YACC,cAAc,cAAc,yBAAyB,GAAG,CAAC,MACzD,KAAK,cAAc,cAAc,MAAM,GACzC,qBAAqB,IAAI,QAAQ,IAAI,GACrC,oBAAoB,EAAE,GACtB,cAAc,KAAK,YAAY,EAAE;AAAA,EACvC;AAAA;AAEF,SAAS,aAAa,CAAC,MAAM,UAAS;AAAA,EACpC,mBAAmB,EAAE,MAAM,QAAO;AAAA,EAClC,IAAI,gBAAgB;AAAA,EACpB,IAAI,iBAAiB,MAAM;AAAA,IACzB,IAAI,KAAK,YAAwB,OAAO,SAAQ,OAA5B,WAAiC,SAAQ,KAAK,UAChE,kBACE,mCACA,+CAA+C,EAAE,IACjD,cACA,+CAA+C,IAAI,IACnD,MACF,MAAM;AAAA,IACR,QAAQ;AAAA,WACD;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,WACA;AAAA,QACH,MAAM,aAAa,IAAI;AAAA;AAAA,IAE3B,IACE,CAAC,gBAAgB,IAAI,GAAG,MACtB,OAAO,QAAO,EAAE,KAAK,iBAAiB,KAAW,GAAG,QAAO,GAC7D,gBAAgB,IAAI,KAAK,IAAI,GACpB,cAAc,cAAc,eAAe,MAApD,OACA;AAAA,MACA,QAAQ;AAAA,aACD;AAAA,aACA;AAAA,aACA;AAAA,aACA;AAAA,aACA;AAAA,aACA;AAAA,UACH,IAAI,cAAc,cAAc,yBAAyB,GAAG,CAAC;AAAA,YAC3D;AAAA;AAAA,MAEN,KAAK,cAAc,cAAc,MAAM;AAAA,MACvC,qBAAqB,IAAI,QAAQ,IAAI;AAAA,MACrC,oBAAoB,EAAE;AAAA,MACtB,cAAc,KAAK,YAAY,EAAE;AAAA,IACnC;AAAA,EACF;AAAA;AAEF,SAAS,YAAY,CAAC,MAAM,YAAY,UAAS;AAAA,EAC/C,mBAAmB,EAAE,MAAM,YAAY,QAAO;AAAA,EAC9C,IAAI,gBAAgB;AAAA,EACpB,IAAI,iBAAiB,MAAM;AAAA,IACzB,IAAI,SAAS,qBAAqB,aAAa,EAAE,iBAC/C,MAAM,YAAY,IAAI;AAAA,IACxB,aAAa,cAAc;AAAA,IAC3B,IAAI,WAAW,OAAO,IAAI,GAAG;AAAA,IAC7B,IAAI,CAAC,UAAU;AAAA,MACb,IAAI,QAAQ,EAAE,SAAS,GAAG,SAAS,KAAK;AAAA,MACxC,IACG,WAAW,cAAc,cACxB,6BAA6B,GAAG,CAClC;AAAA,QAEA,MAAM,UAAU;AAAA,MACb;AAAA,QACH,OAAO,QACL,EAAE,KAAK,cAAc,MAAY,mBAAmB,WAAW,GAC/D,QACF;AAAA,SACC,WAAU,gBAAgB,IAAI,GAAG,MAChC,+BAA+B,MAAM,QAAO;AAAA,QAC9C,IAAI,OAAQ,WAAW,cAAc,cAAc,MAAM;AAAA,QACzD,oBAAoB,IAAI;AAAA,QACxB,qBAAqB,MAAM,QAAQ,IAAI;AAAA,QACvC,KAAK,KAAK,IAAI,QAAQ,QAAS,CAAC,SAAS,QAAQ;AAAA,UAC/C,KAAK,SAAS;AAAA,UACd,KAAK,UAAU;AAAA,SAChB;AAAA,QACD,KAAK,iBAAiB,QAAQ,QAAS,GAAG;AAAA,UACxC,MAAM,WAAW;AAAA,SAClB;AAAA,QACD,KAAK,iBAAiB,SAAS,QAAS,GAAG;AAAA,UACzC,MAAM,WAAW;AAAA,SAClB;AAAA,QACD,MAAM,WAAW;AAAA,QACjB,iBAAiB,UAAU,YAAY,aAAa;AAAA;AAAA,MAEtD,WAAW;AAAA,QACT,MAAM;AAAA,QACN,UAAU;AAAA,QACV,OAAO;AAAA,QACP;AAAA,MACF;AAAA,MACA,OAAO,IAAI,KAAK,QAAQ;AAAA,IAC1B;AAAA,EACF;AAAA;AAEF,SAAS,aAAa,CAAC,KAAK,UAAS;AAAA,EACnC,mBAAmB,EAAE,KAAK,QAAO;AAAA,EACjC,IAAI,gBAAgB;AAAA,EACpB,IAAI,iBAAiB,KAAK;AAAA,IACxB,IAAI,UAAU,qBAAqB,aAAa,EAAE,kBAChD,MAAM,aAAa,GAAG,GACtB,WAAW,QAAQ,IAAI,GAAG;AAAA,IAC5B,aACI,WAAW,cAAc,cAAc,yBAAyB,GAAG,CAAC,GACtE,aACI,MAAM,QAAO,EAAE,KAAU,OAAO,KAAG,GAAG,QAAO,IAC9C,WAAU,gBAAgB,IAAI,GAAG,MAChC,2BAA2B,KAAK,QAAO,GACxC,WAAW,cAAc,cAAc,QAAQ,GAChD,oBAAoB,QAAQ,GAC5B,qBAAqB,UAAU,QAAQ,GAAG,GAC1C,cAAc,KAAK,YAAY,QAAQ,IACxC,WAAW;AAAA,MACV,MAAM;AAAA,MACN,UAAU;AAAA,MACV,OAAO;AAAA,MACP,OAAO;AAAA,IACT,GACA,QAAQ,IAAI,KAAK,QAAQ;AAAA,EAC7B;AAAA;AAEF,SAAS,mBAAmB,CAAC,KAAK,UAAS;AAAA,EACzC,mBAAmB,EAAE,KAAK,QAAO;AAAA,EACjC,IAAI,gBAAgB;AAAA,EACpB,IAAI,iBAAiB,KAAK;AAAA,IACxB,IAAI,UAAU,qBAAqB,aAAa,EAAE,kBAChD,MAAM,aAAa,GAAG,GACtB,WAAW,QAAQ,IAAI,GAAG;AAAA,IAC5B,aACI,WAAW,cAAc,cAAc,yBAAyB,GAAG,CAAC,GACtE,aACI,MAAM,QAAO,EAAE,KAAU,OAAO,MAAI,MAAM,SAAS,GAAG,QAAO,IAC9D,WAAU,gBAAgB,IAAI,GAAG,MAChC,2BAA2B,KAAK,QAAO,GACxC,WAAW,cAAc,cAAc,QAAQ,GAChD,oBAAoB,QAAQ,GAC5B,qBAAqB,UAAU,QAAQ,GAAG,GAC1C,cAAc,KAAK,YAAY,QAAQ,IACxC,WAAW;AAAA,MACV,MAAM;AAAA,MACN,UAAU;AAAA,MACV,OAAO;AAAA,MACP,OAAO;AAAA,IACT,GACA,QAAQ,IAAI,KAAK,QAAQ;AAAA,EAC7B;AAAA;AAEF,SAAS,WAAW,CAAC,MAAM,cAAc,cAAc,iBAAiB;AAAA,EACtE,IAAI,4BAA4B,2BAC9B,wBAAwB,WACtB,iBAAiB,wBAAwB,IACzC;AAAA,EACJ,IAAI,CAAC;AAAA,IAA0B,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,EACtE,QAAQ;AAAA,SACD;AAAA,SACA;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,OAAoB,OAAO,aAAa,eAAjC,YACQ,OAAO,aAAa,SAAjC,YACI,eAAe,YAAY,aAAa,IAAI,GAC7C,eAAe,qBACd,wBACF,EAAE,iBACD,kBAAkB,aAAa,IAAI,YAAY,GAChD,oBACI,kBAAkB;AAAA,QAClB,MAAM;AAAA,QACN,UAAU;AAAA,QACV,OAAO;AAAA,QACP,OAAO;AAAA,MACT,GACA,aAAa,IAAI,cAAc,eAAe,IAChD,mBACA,EAAE,MAAM,QAAQ,UAAU,MAAM,OAAO,GAAG,OAAO,KAAK;AAAA,SACvD;AAAA,MACH,IACmB,aAAa,QAA9B,gBACa,OAAO,aAAa,SAAjC,YACa,OAAO,aAAa,eAAjC,UACA;AAAA,QACA,OAAO,YAAY,aAAa,IAAI;AAAA,QACpC,IAAI,aAAa,qBACb,wBACF,EAAE,iBACF,eAAe,WAAW,IAAI,IAAI;AAAA,QACpC,iBACI,2BACA,yBAAyB,iBAAiB,0BAC3C,eAAe;AAAA,UACd,MAAM;AAAA,UACN,UAAU;AAAA,UACV,OAAO;AAAA,UACP,OAAO,EAAE,SAAS,GAAG,SAAS,KAAK;AAAA,QACrC,GACA,WAAW,IAAI,MAAM,YAAY,IAChC,aAAa,yBAAyB,cACrC,6BAA6B,IAAI,CACnC,MACE,CAAC,WAAW,OACV,aAAa,WAAW,YACzB,aAAa,MAAM,UAAU,IAChC,gBAAgB,IAAI,IAAI,MACpB,eAAe;AAAA,UACf,KAAK;AAAA,UACL,IAAI;AAAA,UACJ,MAAM,aAAa;AAAA,UACnB,aAAa,aAAa;AAAA,UAC1B,WAAW,aAAa;AAAA,UACxB,OAAO,aAAa;AAAA,UACpB,UAAU,aAAa;AAAA,UACvB,gBAAgB,aAAa;AAAA,QAC/B,GACA,gBAAgB,IAAI,MAAM,YAAY,GACtC,cACE,kBACE,0BACA,MACA,cACA,aAAa,KACf;AAAA,QACN,IAAI,gBAAyB,oBAAT;AAAA,UAClB,MAAM,MAAM,wBAAuB,KAAK,EAAE,CAAC;AAAA,QAC7C,OAAO;AAAA,MACT;AAAA,MACA,IAAI,gBAAyB,oBAAT;AAAA,QAClB,MAAM,MAAM,wBAAuB,KAAK,EAAE,CAAC;AAAA,MAC7C,OAAO;AAAA,SACJ;AAAA,MACH,OACG,eAAe,aAAa,OAC5B,eAAe,aAAa,KAChB,OAAO,iBAApB,YACA,gBACe,OAAO,iBAAtB,cACa,OAAO,iBAApB,YACM,eAAe,aAAa,YAAY,GACzC,eAAe,qBACd,wBACF,EAAE,kBACD,kBAAkB,aAAa,IAAI,YAAY,GAChD,oBACI,kBAAkB;AAAA,QAClB,MAAM;AAAA,QACN,UAAU;AAAA,QACV,OAAO;AAAA,QACP,OAAO;AAAA,MACT,GACA,aAAa,IAAI,cAAc,eAAe,IAChD,mBACA,EAAE,MAAM,QAAQ,UAAU,MAAM,OAAO,GAAG,OAAO,KAAK;AAAA;AAAA,MAG5D,MAAM,MAAM,wBAAuB,KAAK,IAAI,CAAC;AAAA;AAAA;AAGnD,SAAS,WAAW,CAAC,MAAM;AAAA,EACzB,OAAO,WAAW,+CAA+C,IAAI,IAAI;AAAA;AAE3E,SAAS,4BAA4B,CAAC,KAAK;AAAA,EACzC,OAAO,4BAA4B,MAAM;AAAA;AAE3C,SAAS,2BAA2B,CAAC,UAAU;AAAA,EAC7C,OAAO,QAAO,CAAC,GAAG,UAAU;AAAA,IAC1B,mBAAmB,SAAS;AAAA,IAC5B,YAAY;AAAA,EACd,CAAC;AAAA;AAEH,SAAS,iBAAiB,CAAC,eAAe,KAAK,cAAc,OAAO;AAAA,EAClE,cAAc,cAAc,qCAAqC,MAAM,GAAG,IACrE,MAAM,UAAU,KACf,MAAM,cAAc,cAAc,MAAM,GACzC,MAAM,UAAU,KACjB,IAAI,iBAAiB,QAAQ,QAAS,GAAG;AAAA,IACvC,OAAQ,MAAM,WAAW;AAAA,GAC1B,GACD,IAAI,iBAAiB,SAAS,QAAS,GAAG;AAAA,IACxC,OAAQ,MAAM,WAAW;AAAA,GAC1B,GACD,qBAAqB,KAAK,QAAQ,YAAY,GAC9C,oBAAoB,GAAG,GACvB,cAAc,KAAK,YAAY,GAAG;AAAA;AAExC,SAAS,YAAY,CAAC,KAAK;AAAA,EACzB,OAAO,WAAW,+CAA+C,GAAG,IAAI;AAAA;AAE1E,SAAS,wBAAwB,CAAC,KAAK;AAAA,EACrC,OAAO,kBAAkB;AAAA;AAE3B,SAAS,eAAe,CAAC,eAAe,UAAU,OAAO;AAAA,EACvD,SAAS;AAAA,EACT,IAAa,SAAS,aAAlB;AAAA,IACF,QAAQ,SAAS;AAAA,WACV;AAAA,QACH,IAAI,WAAW,cAAc,cAC3B,uBACE,+CAA+C,MAAM,IAAI,IACzD,IACJ;AAAA,QACA,IAAI;AAAA,UACF,OACG,SAAS,WAAW,UACrB,oBAAoB,QAAQ,GAC5B;AAAA,QAEJ,IAAI,aAAa,QAAO,CAAC,GAAG,OAAO;AAAA,UACjC,aAAa,MAAM;AAAA,UACnB,mBAAmB,MAAM;AAAA,UACzB,MAAM;AAAA,UACN,YAAY;AAAA,QACd,CAAC;AAAA,QACD,YAAY,cAAc,iBAAiB,eAAe,cACxD,OACF;AAAA,QACA,oBAAoB,QAAQ;AAAA,QAC5B,qBAAqB,UAAU,SAAS,UAAU;AAAA,QAClD,iBAAiB,UAAU,MAAM,YAAY,aAAa;AAAA,QAC1D,OAAQ,SAAS,WAAW;AAAA,WACzB;AAAA,QACH,aAAa,YAAY,MAAM,IAAI;AAAA,QACnC,IAAI,eAAe,cAAc,cAC/B,6BAA6B,UAAU,CACzC;AAAA,QACA,IAAI;AAAA,UACF,OACG,SAAS,MAAM,WAAW,GAC1B,SAAS,WAAW,cACrB,oBAAoB,YAAY,GAChC;AAAA,QAEJ,WAAW,4BAA4B,KAAK;AAAA,SAC3C,aAAa,gBAAgB,IAAI,UAAU,MAC1C,+BAA+B,UAAU,UAAU;AAAA,QACrD,gBACE,cAAc,iBAAiB,eAC/B,cAAc,MAAM;AAAA,QACtB,oBAAoB,YAAY;AAAA,QAChC,IAAI,eAAe;AAAA,QACnB,aAAa,KAAK,IAAI,QAAQ,QAAS,CAAC,SAAS,QAAQ;AAAA,UACvD,aAAa,SAAS;AAAA,UACtB,aAAa,UAAU;AAAA,SACxB;AAAA,QACD,qBAAqB,cAAc,QAAQ,QAAQ;AAAA,QACnD,SAAS,MAAM,WAAW;AAAA,QAC1B,iBAAiB,cAAc,MAAM,YAAY,aAAa;AAAA,QAC9D,OAAQ,SAAS,WAAW;AAAA,WACzB;AAAA,QACH,eAAe,aAAa,MAAM,GAAG;AAAA,QACrC,IACG,aAAa,cAAc,cAC1B,yBAAyB,YAAY,CACvC;AAAA,UAEA,OACG,SAAS,WAAW,YACrB,oBAAoB,UAAU,GAC9B;AAAA,QAEJ,WAAW;AAAA,QACX,IAAK,aAAa,gBAAgB,IAAI,YAAY;AAAA,UAC/C,WAAW,QAAO,CAAC,GAAG,KAAK,GAC1B,2BAA2B,UAAU,UAAU;AAAA,QACnD,gBAAgB,cAAc,iBAAiB;AAAA,QAC/C,aAAa,cAAc,cAAc,QAAQ;AAAA,QACjD,oBAAoB,UAAU;AAAA,QAC9B,qBAAqB,YAAY,QAAQ,QAAQ;AAAA,QACjD,cAAc,KAAK,YAAY,UAAU;AAAA,QACzC,OAAQ,SAAS,WAAW;AAAA,WACzB;AAAA,QACH,OAAO;AAAA;AAAA,QAEP,MAAM,MAAM,wBAAuB,KAAK,SAAS,IAAI,CAAC;AAAA;AAAA,EAG1D;AAAA,IAAiB,SAAS,SAA1B,iBACS,SAAS,MAAM,UAAU,OAAhC,MACE,WAAW,SAAS,UACrB,SAAS,MAAM,WAAW,GAC3B,iBAAiB,UAAU,MAAM,YAAY,aAAa;AAAA,EAC9D,OAAO,SAAS;AAAA;AAElB,SAAS,gBAAgB,CAAC,UAAU,YAAY,OAAM;AAAA,EACpD,SACM,QAAQ,MAAK,iBACb,gEACF,GACA,OAAO,MAAM,SAAS,MAAM,MAAM,SAAS,KAAK,MAChD,QAAQ,MACR,IAAI,EACN,IAAI,MAAM,QACV,KACA;AAAA,IACA,IAAI,OAAO,MAAM;AAAA,IACjB,IAAI,KAAK,QAAQ,eAAe;AAAA,MAAY,QAAQ;AAAA,IAC/C,SAAI,UAAU;AAAA,MAAM;AAAA,EAC3B;AAAA,EACA,QACI,MAAM,WAAW,aAAa,UAAU,MAAM,WAAW,KACvD,aAAmB,MAAK,aAAX,IAAsB,MAAK,OAAO,OACjD,WAAW,aAAa,UAAU,WAAW,UAAU;AAAA;AAE7D,SAAS,8BAA8B,CAAC,iBAAiB,cAAc;AAAA,EAC7D,gBAAgB,eAAxB,SACG,gBAAgB,cAAc,aAAa;AAAA,EACtC,gBAAgB,kBAAxB,SACG,gBAAgB,iBAAiB,aAAa;AAAA,EACzC,gBAAgB,SAAxB,SAAkC,gBAAgB,QAAQ,aAAa;AAAA;AAEzE,SAAS,0BAA0B,CAAC,aAAa,cAAc;AAAA,EACrD,YAAY,eAApB,SACG,YAAY,cAAc,aAAa;AAAA,EAClC,YAAY,kBAApB,SACG,YAAY,iBAAiB,aAAa;AAAA,EACrC,YAAY,aAApB,SACG,YAAY,YAAY,aAAa;AAAA;AAG1C,SAAS,2BAA2B,CAAC,MAAM,cAAc,eAAe;AAAA,EACtE,IAAa,cAAT,MAAoB;AAAA,IACtB,IAAI,QAAQ,IAAI;AAAA,IAChB,IAAI,SAAU,YAAY,IAAI;AAAA,IAC9B,OAAO,IAAI,eAAe,KAAK;AAAA,EACjC,EACE;AAAA,IAAC,SAAS,WACP,QAAQ,OAAO,IAAI,aAAa,GACjC,UAAW,QAAQ,IAAI,KAAQ,OAAO,IAAI,eAAe,KAAK;AAAA,EAClE,IAAI,MAAM,IAAI,IAAI;AAAA,IAAG,OAAO;AAAA,EAC5B,MAAM,IAAI,MAAM,IAAI;AAAA,EACpB,gBAAgB,cAAc,qBAAqB,IAAI;AAAA,EACvD,KAAK,SAAS,EAAG,SAAS,cAAc,QAAQ,UAAU;AAAA,IACxD,IAAI,OAAO,cAAc;AAAA,IACzB,IACE,EACE,KAAK,4BACL,KAAK,wBACO,SAAX,UAAoC,KAAK,aAAa,KAAK,MAAxC,iBAEW,KAAK,iBAAtC,8BACA;AAAA,MACA,IAAI,UAAU,KAAK,aAAa,YAAY,KAAK;AAAA,MACjD,UAAU,OAAO;AAAA,MACjB,IAAI,WAAW,MAAM,IAAI,OAAO;AAAA,MAChC,WAAW,SAAS,KAAK,IAAI,IAAI,MAAM,IAAI,SAAS,CAAC,IAAI,CAAC;AAAA,IAC5D;AAAA,EACF;AAAA,EACA,OAAO;AAAA;AAET,SAAS,cAAc,CAAC,eAAe,MAAM,UAAU;AAAA,EACrD,gBAAgB,cAAc,iBAAiB;AAAA,EAC/C,cAAc,KAAK,aACjB,UACY,SAAZ,UAAmB,cAAc,cAAc,cAAc,IAAI,IACnE;AAAA;AAEF,SAAS,mBAAmB,CAAC,MAAM,OAAO,aAAa;AAAA,EACrD,IAAU,gBAAN,KAA6B,MAAM,YAAd;AAAA,IAAwB,OAAO;AAAA,EACxD,QAAQ;AAAA,SACD;AAAA,SACA;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,IACe,OAAO,MAAM,eAA1B,YACa,OAAO,MAAM,SAA1B,YACO,MAAM,SAAb;AAAA,QAEA;AAAA,MACF,OAAO;AAAA,SACJ;AAAA,MACH,IACe,OAAO,MAAM,QAA1B,YACa,OAAO,MAAM,SAA1B,YACO,MAAM,SAAb,MACA,MAAM,UACN,MAAM;AAAA,QAEN;AAAA,MACF,QAAQ,MAAM;AAAA,aACP;AAAA,UACH,OACG,OAAO,MAAM,UACD,OAAO,MAAM,eAA1B,YAAgD,QAAR;AAAA;AAAA,UAG1C,OAAO;AAAA;AAAA,SAER;AAAA,MACH,IACE,MAAM,SACS,OAAO,MAAM,UAA5B,cACa,OAAO,MAAM,UAA1B,YACA,CAAC,MAAM,UACP,CAAC,MAAM,WACP,MAAM,OACO,OAAO,MAAM,QAA1B;AAAA,QAEA,OAAO;AAAA;AAAA,EAEb,OAAO;AAAA;AAET,SAAS,eAAe,CAAC,UAAU;AAAA,EACjC,OAAwB,SAAS,SAA1B,iBAAyC,SAAS,MAAM,UAAU,OAAhC,IACrC,QACA;AAAA;AAEN,SAAS,eAAe,CAAC,OAAO,eAAe,UAAU,OAAO;AAAA,EAC9D,IACmB,SAAS,SAA1B,iBACc,OAAO,MAAM,UAA1B,YACQ,WAAW,MAAM,KAAK,EAAE,YAA/B,WACK,SAAS,MAAM,UAAU,OAAhC,GACA;AAAA,IACA,IAAa,SAAS,aAAlB,MAA4B;AAAA,MAC9B,IAAI,MAAM,YAAY,MAAM,IAAI,GAC9B,WAAW,cAAc,cACvB,6BAA6B,GAAG,CAClC;AAAA,MACF,IAAI,UAAU;AAAA,QACZ,gBAAgB,SAAS;AAAA,QAChB,kBAAT,QACe,OAAO,kBAApB,YACe,OAAO,cAAc,SAApC,eACC,MAAM,SACN,QAAQ,YAAY,KAAK,KAAK,GAC/B,cAAc,KAAK,OAAO,KAAK;AAAA,QACjC,SAAS,MAAM,WAAW;AAAA,QAC1B,SAAS,WAAW;AAAA,QACpB,oBAAoB,QAAQ;AAAA,QAC5B;AAAA,MACF;AAAA,MACA,WAAW,cAAc,iBAAiB;AAAA,MAC1C,QAAQ,4BAA4B,KAAK;AAAA,OACxC,MAAM,gBAAgB,IAAI,GAAG,MAC5B,+BAA+B,OAAO,GAAG;AAAA,MAC3C,WAAW,SAAS,cAAc,MAAM;AAAA,MACxC,oBAAoB,QAAQ;AAAA,MAC5B,IAAI,eAAe;AAAA,MACnB,aAAa,KAAK,IAAI,QAAQ,QAAS,CAAC,SAAS,QAAQ;AAAA,QACvD,aAAa,SAAS;AAAA,QACtB,aAAa,UAAU;AAAA,OACxB;AAAA,MACD,qBAAqB,UAAU,QAAQ,KAAK;AAAA,MAC5C,SAAS,WAAW;AAAA,IACtB;AAAA,IACS,MAAM,gBAAf,SAA+B,MAAM,cAAc,IAAI;AAAA,IACvD,MAAM,YAAY,IAAI,UAAU,aAAa;AAAA,KAC5C,gBAAgB,SAAS,MAAM,aACvB,SAAS,MAAM,UAAU,OAAhC,MACC,MAAM,SACN,WAAW,YAAY,KAAK,KAAK,GAClC,cAAc,iBAAiB,QAAQ,QAAQ,GAC/C,cAAc,iBAAiB,SAAS,QAAQ;AAAA,EACpD;AAAA;AAGF,SAAS,sBAAsB,CAAC,OAAO,eAAe;AAAA,EACpD,MAAM,eACE,MAAM,UAAZ,KACA,2BAA2B,OAAO,MAAM,WAAW;AAAA,EACrD,OAAO,IAAI,MAAM,SAAS,IAAI,MAAM,WAChC,QAAS,CAAC,QAAQ;AAAA,IAChB,IAAI,kBAAkB,WAAW,QAAS,GAAG;AAAA,MAC3C,MAAM,eACJ,2BAA2B,OAAO,MAAM,WAAW;AAAA,MACrD,IAAI,MAAM,WAAW;AAAA,QACnB,IAAI,YAAY,MAAM;AAAA,QACtB,MAAM,YAAY;AAAA,QAClB,UAAU;AAAA,MACZ;AAAA,OACC,QAAM,aAAa;AAAA,IACtB,IAAI,MAAM,YACF,8BAAN,MACC,4BAA4B,QAAQ,kBAAkB;AAAA,IACzD,IAAI,WAAW,WACb,QAAS,GAAG;AAAA,MACV,MAAM,mBAAmB;AAAA,MACzB,IACQ,MAAM,UAAZ,MACC,MAAM,eACL,2BAA2B,OAAO,MAAM,WAAW,GACrD,MAAM,YACN;AAAA,QACA,IAAI,YAAY,MAAM;AAAA,QACtB,MAAM,YAAY;AAAA,QAClB,UAAU;AAAA,MACZ;AAAA,QAED,MAAM,WAAW,4BAA4B,KAAK,OACjD,aACJ;AAAA,IACA,MAAM,YAAY;AAAA,IAClB,OAAO,QAAS,GAAG;AAAA,MACjB,MAAM,YAAY;AAAA,MAClB,aAAa,eAAe;AAAA,MAC5B,aAAa,QAAQ;AAAA;AAAA,MAGzB;AAAA;AAEN,SAAS,WAAW,GAAG;AAAA,EACrB,KAAK;AAAA,EACL,IAAU,KAAK,UAAX,MAA2B,KAAK,aAAX,KAAuB,CAAC,KAAK;AAAA,IACpD,IAAI,KAAK;AAAA,MAAa,2BAA2B,MAAM,KAAK,WAAW;AAAA,IAClE,SAAI,KAAK,WAAW;AAAA,MACvB,IAAI,YAAY,KAAK;AAAA,MACrB,KAAK,YAAY;AAAA,MACjB,UAAU;AAAA,IACZ;AAAA;AAAA;AAGJ,SAAS,0BAA0B,CAAC,OAAO,WAAW;AAAA,EACpD,MAAM,cAAc;AAAA,EACX,MAAM,cAAf,SACG,MAAM,SACN,oBAAoB,IAAI,KACzB,UAAU,QAAQ,0BAA0B,KAAK,GAChD,oBAAoB,MACrB,YAAY,KAAK,KAAK;AAAA;AAE1B,SAAS,wBAAwB,CAAC,OAAM,UAAU;AAAA,EAChD,IAAI,EAAE,SAAS,MAAM,UAAU,IAAI;AAAA,IACjC,IAAI,cAAc,kBAAkB,IAAI,KAAI;AAAA,IAC5C,IAAI;AAAA,MAAa,IAAI,OAAO,YAAY,IAAI,IAAI;AAAA,IAC3C;AAAA,MACH,cAAc,IAAI;AAAA,MAClB,kBAAkB,IAAI,OAAM,WAAW;AAAA,MACvC,SACM,QAAQ,MAAK,iBACb,8CACF,GACA,IAAI,EACN,IAAI,MAAM,QACV,KACA;AAAA,QACA,IAAI,OAAO,MAAM;AAAA,QACjB,IACa,KAAK,aAAhB,UACc,KAAK,aAAa,OAAO,MAAvC;AAAA,UAEA,YAAY,IAAI,KAAK,QAAQ,YAAY,IAAI,GAAI,OAAO;AAAA,MAC5D;AAAA,MACA,QAAQ,YAAY,IAAI,MAAM,IAAI;AAAA;AAAA,IAEpC,QAAQ,SAAS;AAAA,IACjB,OAAO,MAAM,aAAa,iBAAiB;AAAA,IAC3C,IAAI,YAAY,IAAI,IAAI,KAAK;AAAA,IAC7B,MAAM,QAAQ,YAAY,IAAI,MAAM,KAAK;AAAA,IACzC,YAAY,IAAI,MAAM,KAAK;AAAA,IAC3B,KAAK;AAAA,IACL,OAAO,YAAY,KAAK,IAAI;AAAA,IAC5B,MAAM,iBAAiB,QAAQ,IAAI;AAAA,IACnC,MAAM,iBAAiB,SAAS,IAAI;AAAA,IACpC,IACI,EAAE,WAAW,aAAa,OAAO,EAAE,WAAW,KAC5C,QAAa,MAAK,aAAX,IAAsB,MAAK,OAAO,OAC3C,MAAK,aAAa,OAAO,MAAK,UAAU;AAAA,IAC5C,SAAS,MAAM,WAAW;AAAA,EAC5B;AAAA;AAUF,SAAS,aAAa,CACpB,eACA,KACA,SACA,kBACA,iBACA,eACA,oBACA,8BACA,WACA;AAAA,EACA,KAAK,MAAM;AAAA,EACX,KAAK,gBAAgB;AAAA,EACrB,KAAK,YAAY,KAAK,UAAU,KAAK,kBAAkB;AAAA,EACvD,KAAK,gBAAgB;AAAA,EACrB,KAAK,eACH,KAAK,OACL,KAAK,iBACL,KAAK,UACL,KAAK,sBACH;AAAA,EACJ,KAAK,mBAAmB;AAAA,EACxB,KAAK,kBAAkB,cAAc,EAAE;AAAA,EACvC,KAAK,iBACH,KAAK,sBACL,KAAK,6BACL,KAAK,eACL,KAAK,YACL,KAAK,cACL,KAAK,iBACL,KAAK,eACH;AAAA,EACJ,KAAK,gBAAgB,cAAc,CAAC;AAAA,EACpC,KAAK,gBAAgB,cAAc,IAAI;AAAA,EACvC,KAAK,mBAAmB;AAAA,EACxB,KAAK,kBAAkB;AAAA,EACvB,KAAK,gBAAgB;AAAA,EACrB,KAAK,qBAAqB;AAAA,EAC1B,KAAK,cAAc;AAAA,EACnB,KAAK,mBAAmB;AAAA,EACxB,KAAK,YAAY;AAAA,EACjB,KAAK,wBAAwB,IAAI;AAAA;AAEnC,SAAS,eAAe,CACtB,eACA,KACA,SACA,iBACA,oBACA,cACA,kBACA,WACA,iBACA,eACA,oBACA,8BACA;AAAA,EACA,gBAAgB,IAAI,cAClB,eACA,KACA,SACA,kBACA,iBACA,eACA,oBACA,8BACA,SACF;AAAA,EACA,MAAM;AAAA,EACC,iBAAP,SAAwB,OAAO;AAAA,EAC/B,eAAe,qBAAqB,GAAG,MAAM,MAAM,GAAG;AAAA,EACtD,cAAc,UAAU;AAAA,EACxB,aAAa,YAAY;AAAA,EACzB,MAAM,YAAY;AAAA,EAClB,IAAI;AAAA,EACJ,cAAc,cAAc;AAAA,EAC5B,IAAI;AAAA,EACJ,aAAa,gBAAgB;AAAA,IAC3B,SAAS;AAAA,IACT,cAAc;AAAA,IACd,OAAO;AAAA,EACT;AAAA,EACA,sBAAsB,YAAY;AAAA,EAClC,OAAO;AAAA;AAET,SAAS,oBAAoB,CAAC,iBAAiB;AAAA,EAC7C,IAAI,CAAC;AAAA,IAAiB,OAAO;AAAA,EAC7B,kBAAkB;AAAA,EAClB,OAAO;AAAA;AAET,SAAS,mBAAmB,CAC1B,WACA,MACA,SACA,WACA,iBACA,UACA;AAAA,EACA,kBAAkB,qBAAqB,eAAe;AAAA,EAC7C,UAAU,YAAnB,OACK,UAAU,UAAU,kBACpB,UAAU,iBAAiB;AAAA,EAChC,YAAY,aAAa,IAAI;AAAA,EAC7B,UAAU,UAAU,EAAE,QAAiB;AAAA,EACvC,WAAsB,aAAN,YAAiB,OAAO;AAAA,EAC/B,aAAT,SAAsB,UAAU,WAAW;AAAA,EAC3C,UAAU,cAAc,WAAW,WAAW,IAAI;AAAA,EACzC,YAAT,SACG,sBAAsB,SAAS,WAAW,IAAI,GAC/C,oBAAoB,SAAS,WAAW,IAAI;AAAA;AAEhD,SAAS,iBAAiB,CAAC,OAAO,WAAW;AAAA,EAC3C,QAAQ,MAAM;AAAA,EACd,IAAa,UAAT,QAA2B,MAAM,eAAf,MAA2B;AAAA,IAC/C,IAAI,IAAI,MAAM;AAAA,IACd,MAAM,YAAkB,MAAN,KAAW,IAAI,YAAY,IAAI;AAAA,EACnD;AAAA;AAEF,SAAS,0BAA0B,CAAC,OAAO,WAAW;AAAA,EACpD,kBAAkB,OAAO,SAAS;AAAA,GACjC,QAAQ,MAAM,cAAc,kBAAkB,OAAO,SAAS;AAAA;AAEjE,SAAS,0BAA0B,CAAC,OAAO;AAAA,EACzC,IAAW,MAAM,QAAb,MAA2B,MAAM,QAAb,IAAkB;AAAA,IACxC,IAAI,QAAO,+BAA+B,OAAO,QAAQ;AAAA,IAChD,UAAT,QAAiB,sBAAsB,OAAM,OAAO,QAAQ;AAAA,IAC5D,2BAA2B,OAAO,QAAQ;AAAA,EAC5C;AAAA;AAEF,SAAS,iCAAiC,CAAC,OAAO;AAAA,EAChD,IAAW,MAAM,QAAb,MAA2B,MAAM,QAAb,IAAkB;AAAA,IACxC,IAAI,OAAO,kBAAkB;AAAA,IAC7B,OAAO,gCAAgC,IAAI;AAAA,IAC3C,IAAI,QAAO,+BAA+B,OAAO,IAAI;AAAA,IAC5C,UAAT,QAAiB,sBAAsB,OAAM,OAAO,IAAI;AAAA,IACxD,2BAA2B,OAAO,IAAI;AAAA,EACxC;AAAA;AAGF,SAAS,qBAAqB,CAC5B,cACA,kBACA,WACA,aACA;AAAA,EACA,IAAI,iBAAiB,sBAAqB;AAAA,EAC1C,sBAAqB,IAAI;AAAA,EACzB,IAAI,mBAAmB,wBAAwB;AAAA,EAC/C,IAAI;AAAA,IACD,wBAAwB,IAAI,GAC3B,cAAc,cAAc,kBAAkB,WAAW,WAAW;AAAA,YACtE;AAAA,IACC,wBAAwB,IAAI,kBAC1B,sBAAqB,IAAI;AAAA;AAAA;AAGhC,SAAS,uBAAuB,CAC9B,cACA,kBACA,WACA,aACA;AAAA,EACA,IAAI,iBAAiB,sBAAqB;AAAA,EAC1C,sBAAqB,IAAI;AAAA,EACzB,IAAI,mBAAmB,wBAAwB;AAAA,EAC/C,IAAI;AAAA,IACD,wBAAwB,IAAI,GAC3B,cAAc,cAAc,kBAAkB,WAAW,WAAW;AAAA,YACtE;AAAA,IACC,wBAAwB,IAAI,kBAC1B,sBAAqB,IAAI;AAAA;AAAA;AAGhC,SAAS,aAAa,CACpB,cACA,kBACA,iBACA,aACA;AAAA,EACA,IAAI,UAAU;AAAA,IACZ,IAAI,YAAY,0BAA0B,WAAW;AAAA,IACrD,IAAa,cAAT;AAAA,MACF,kCACE,cACA,kBACA,aACA,mBACA,eACF,GACE,uBAAuB,cAAc,WAAW;AAAA,IAC/C,SACH,uBACE,WACA,cACA,kBACA,iBACA,WACF;AAAA,MAEA,YAAY,gBAAgB;AAAA,IACzB,SACF,uBAAuB,cAAc,WAAW,GACjD,mBAAmB,KACjB,KAAK,yBAAyB,QAAQ,YAAY,GACpD;AAAA,MACA,MAAgB,cAAT,QAAsB;AAAA,QAC3B,IAAI,QAAQ,oBAAoB,SAAS;AAAA,QACzC,IAAa,UAAT;AAAA,UACF,QAAQ,MAAM;AAAA,iBACP;AAAA,cACH,QAAQ,MAAM;AAAA,cACd,IAAI,MAAM,QAAQ,cAAc,cAAc;AAAA,gBAC5C,IAAI,QAAQ,wBAAwB,MAAM,YAAY;AAAA,gBACtD,IAAU,UAAN,GAAa;AAAA,kBACf,IAAI,QAAO;AAAA,kBACX,MAAK,gBAAgB;AAAA,kBACrB,KAAK,MAAK,kBAAkB,EAAG,SAAS;AAAA,oBACtC,IAAI,OAAO,KAAM,KAAK,MAAM,KAAK;AAAA,oBACjC,MAAK,cAAc,MAAM;AAAA,oBACzB,SAAS,CAAC;AAAA,kBACZ;AAAA,kBACA,sBAAsB,KAAK;AAAA,mBACpB,mBAAmB,OAA1B,MACI,qCAAqC,IAAI,IAAI,KAC/C,8BAA8B,GAAG,KAAE;AAAA,gBACvC;AAAA,cACF;AAAA,cACA;AAAA,iBACG;AAAA,iBACA;AAAA,cACF,QAAO,+BAA+B,OAAO,CAAC,GACpC,UAAT,QAAiB,sBAAsB,OAAM,OAAO,CAAC,GACrD,gBAAgB,GAChB,2BAA2B,OAAO,CAAC;AAAA;AAAA,QAE3C,QAAQ,0BAA0B,WAAW;AAAA,QACpC,UAAT,QACE,kCACE,cACA,kBACA,aACA,mBACA,eACF;AAAA,QACF,IAAI,UAAU;AAAA,UAAW;AAAA,QACzB,YAAY;AAAA,MACd;AAAA,MACS,cAAT,QAAsB,YAAY,gBAAgB;AAAA,IACpD,EACE;AAAA,wCACE,cACA,kBACA,aACA,MACA,eACF;AAAA,EACJ;AAAA;AAEF,SAAS,yBAAyB,CAAC,aAAa;AAAA,EAC9C,cAAc,eAAe,WAAW;AAAA,EACxC,OAAO,2BAA2B,WAAW;AAAA;AAG/C,SAAS,0BAA0B,CAAC,YAAY;AAAA,EAC9C,oBAAoB;AAAA,EACpB,aAAa,2BAA2B,UAAU;AAAA,EAClD,IAAa,eAAT,MAAqB;AAAA,IACvB,IAAI,iBAAiB,uBAAuB,UAAU;AAAA,IACtD,IAAa,mBAAT;AAAA,MAAyB,aAAa;AAAA,IACrC;AAAA,MACH,IAAI,MAAM,eAAe;AAAA,MACzB,IAAW,QAAP,IAAY;AAAA,QACd,aAAa,6BAA6B,cAAc;AAAA,QACxD,IAAa,eAAT;AAAA,UAAqB,OAAO;AAAA,QAChC,aAAa;AAAA,MACf,EAAO,SAAW,QAAP,IAAY;AAAA,QACrB,aAAa,6BAA6B,cAAc;AAAA,QACxD,IAAa,eAAT;AAAA,UAAqB,OAAO;AAAA,QAChC,aAAa;AAAA,MACf,EAAO,SAAU,QAAN,GAAW;AAAA,QACpB,IAAI,eAAe,UAAU,QAAQ,cAAc;AAAA,UACjD,OAAa,eAAe,QAArB,IACH,eAAe,UAAU,gBACzB;AAAA,QACN,aAAa;AAAA,MACf,EAAO;AAAA,2BAAmB,eAAe,aAAa;AAAA;AAAA,EAE1D;AAAA,EACA,oBAAoB;AAAA,EACpB,OAAO;AAAA;AAET,SAAS,gBAAgB,CAAC,cAAc;AAAA,EACtC,QAAQ;AAAA,SACD;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,SACA;AAAA,MACH,OAAO;AAAA,SACJ;AAAA,MACH,QAAQ,wBAAwB;AAAA,aACzB;AAAA,UACH,OAAO;AAAA,aACJ;AAAA,UACH,OAAO;AAAA,aACJ;AAAA,aACA;AAAA,UACH,OAAO;AAAA,aACJ;AAAA,UACH,OAAO;AAAA;AAAA,UAEP,OAAO;AAAA;AAAA;AAAA,MAGX,OAAO;AAAA;AAAA;AAcb,SAAS,sBAAsB,CAAC,cAAc,aAAa;AAAA,EACzD,QAAQ;AAAA,SACD;AAAA,SACA;AAAA,MACH,cAAc;AAAA,MACd;AAAA,SACG;AAAA,SACA;AAAA,MACH,aAAa;AAAA,MACb;AAAA,SACG;AAAA,SACA;AAAA,MACH,cAAc;AAAA,MACd;AAAA,SACG;AAAA,SACA;AAAA,MACH,eAAe,OAAO,YAAY,SAAS;AAAA,MAC3C;AAAA,SACG;AAAA,SACA;AAAA,MACH,sBAAsB,OAAO,YAAY,SAAS;AAAA;AAAA;AAGxD,SAAS,iDAAiD,CACxD,qBACA,WACA,cACA,kBACA,iBACA,aACA;AAAA,EACA,IACW,wBAAT,QACA,oBAAoB,gBAAgB;AAAA,IAEpC,OACG,sBAAsB;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,kBAAkB,CAAC,eAAe;AAAA,IACpC,GACS,cAAT,SACI,YAAY,oBAAoB,SAAS,GAClC,cAAT,QAAsB,2BAA2B,SAAS,IAC5D;AAAA,EAEJ,oBAAoB,oBAAoB;AAAA,EACxC,YAAY,oBAAoB;AAAA,EACvB,oBAAT,QACS,UAAU,QAAQ,eAAe,MAAxC,MACA,UAAU,KAAK,eAAe;AAAA,EAChC,OAAO;AAAA;AAET,SAAS,sBAAsB,CAC7B,WACA,cACA,kBACA,iBACA,aACA;AAAA,EACA,QAAQ;AAAA,SACD;AAAA,MACH,OACG,cAAc,kDACb,aACA,WACA,cACA,kBACA,iBACA,WACF,GACA;AAAA,SAEC;AAAA,MACH,OACG,aAAa,kDACZ,YACA,WACA,cACA,kBACA,iBACA,WACF,GACA;AAAA,SAEC;AAAA,MACH,OACG,cAAc,kDACb,aACA,WACA,cACA,kBACA,iBACA,WACF,GACA;AAAA,SAEC;AAAA,MACH,IAAI,YAAY,YAAY;AAAA,MAC5B,eAAe,IACb,WACA,kDACE,eAAe,IAAI,SAAS,KAAK,MACjC,WACA,cACA,kBACA,iBACA,WACF,CACF;AAAA,MACA,OAAO;AAAA,SACJ;AAAA,MACH,OACG,YAAY,YAAY,WACzB,sBAAsB,IACpB,WACA,kDACE,sBAAsB,IAAI,SAAS,KAAK,MACxC,WACA,cACA,kBACA,iBACA,WACF,CACF,GACA;AAAA;AAAA,EAGN,OAAO;AAAA;AAET,SAAS,8BAA8B,CAAC,cAAc;AAAA,EACpD,IAAI,aAAa,2BAA2B,aAAa,MAAM;AAAA,EAC/D,IAAa,eAAT,MAAqB;AAAA,IACvB,IAAI,iBAAiB,uBAAuB,UAAU;AAAA,IACtD,IAAa,mBAAT;AAAA,MACF,IAAM,aAAa,eAAe,KAAa,eAAP,IAAoB;AAAA,QAC1D,IACI,aAAa,6BAA6B,cAAc,GACjD,eAAT,MACA;AAAA,UACA,aAAa,YAAY;AAAA,UACzB,gBAAgB,aAAa,UAAU,QAAS,GAAG;AAAA,YACjD,kCAAkC,cAAc;AAAA,WACjD;AAAA,UACD;AAAA,QACF;AAAA,MACF,EAAO,SAAW,eAAP,IAAmB;AAAA,QAC5B,IACI,aAAa,6BAA6B,cAAc,GACjD,eAAT,MACA;AAAA,UACA,aAAa,YAAY;AAAA,UACzB,gBAAgB,aAAa,UAAU,QAAS,GAAG;AAAA,YACjD,kCAAkC,cAAc;AAAA,WACjD;AAAA,UACD;AAAA,QACF;AAAA,MACF,EAAO,SACC,eAAN,KACA,eAAe,UAAU,QAAQ,cAAc,cAC/C;AAAA,QACA,aAAa,YACL,eAAe,QAArB,IACI,eAAe,UAAU,gBACzB;AAAA,QACN;AAAA,MACF;AAAA;AAAA,EACJ;AAAA,EACA,aAAa,YAAY;AAAA;AAE3B,SAAS,kCAAkC,CAAC,aAAa;AAAA,EACvD,IAAa,YAAY,cAArB;AAAA,IAAgC,OAAO;AAAA,EAC3C,SACM,mBAAmB,YAAY,iBACnC,IAAI,iBAAiB,UAErB;AAAA,IACA,IAAI,gBAAgB,0BAA0B,YAAY,WAAW;AAAA,IACrE,IAAa,kBAAT,MAAwB;AAAA,MAC1B,gBAAgB,YAAY;AAAA,MAC5B,IAAI,mBAAmB,IAAI,cAAc,YACvC,cAAc,MACd,aACF;AAAA,MACA,wBAAwB;AAAA,MACxB,cAAc,OAAO,cAAc,gBAAgB;AAAA,MACnD,wBAAwB;AAAA,IAC1B,EACE;AAAA,aACG,mBAAmB,oBAAoB,aAAa,GAC5C,qBAAT,QACE,2BAA2B,gBAAgB,GAC5C,YAAY,YAAY,eACzB;AAAA,IAEJ,iBAAiB,MAAM;AAAA,EACzB;AAAA,EACA,OAAO;AAAA;AAET,SAAS,uCAAuC,CAAC,aAAa,KAAK,KAAK;AAAA,EACtE,mCAAmC,WAAW,KAAK,IAAI,OAAO,GAAG;AAAA;AAEnE,SAAS,qBAAqB,GAAG;AAAA,EAC/B,4BAA4B;AAAA,EACnB,gBAAT,QACE,mCAAmC,WAAW,MAC7C,cAAc;AAAA,EACR,eAAT,QACE,mCAAmC,UAAU,MAC5C,aAAa;AAAA,EACP,gBAAT,QACE,mCAAmC,WAAW,MAC7C,cAAc;AAAA,EACjB,eAAe,QAAQ,uCAAuC;AAAA,EAC9D,sBAAsB,QAAQ,uCAAuC;AAAA;AAEvE,SAAS,2BAA2B,CAAC,aAAa,WAAW;AAAA,EAC3D,YAAY,cAAc,cACtB,YAAY,YAAY,MAC1B,8BACI,4BAA4B,MACpB,oCACE,mCACV,qBACF;AAAA;AAGN,SAAS,2BAA2B,CAAC,oBAAoB;AAAA,EACvD,6BAA6B,uBACzB,2BAA2B,oBACnB,oCACE,mCACV,QAAS,GAAG;AAAA,IACV,6BAA6B,uBAC1B,2BAA2B;AAAA,IAC9B,SAAS,IAAI,EAAG,IAAI,mBAAmB,QAAQ,KAAK,GAAG;AAAA,MACrD,IAAI,OAAO,mBAAmB,IAC5B,oBAAoB,mBAAmB,IAAI,IAC3C,WAAW,mBAAmB,IAAI;AAAA,MACpC,IAAmB,OAAO,sBAAtB;AAAA,QACF,IAAa,2BAA2B,qBAAqB,IAAI,MAA7D;AAAA,UACF;AAAA,QACG;AAAA;AAAA,MACP,IAAI,WAAW,oBAAoB,IAAI;AAAA,MAC9B,aAAT,SACG,mBAAmB,OAAO,GAAG,CAAC,GAC9B,KAAK,GACN,oBACE,UACA;AAAA,QACE,SAAS;AAAA,QACT,MAAM;AAAA,QACN,QAAQ,KAAK;AAAA,QACb,QAAQ;AAAA,MACV,GACA,mBACA,QACF;AAAA,IACJ;AAAA,GAEJ;AAAA;AAEJ,SAAS,gBAAgB,CAAC,WAAW;AAAA,EACnC,SAAS,OAAO,CAAC,aAAa;AAAA,IAC5B,OAAO,4BAA4B,aAAa,SAAS;AAAA;AAAA,EAElD,gBAAT,QAAwB,4BAA4B,aAAa,SAAS;AAAA,EACjE,eAAT,QAAuB,4BAA4B,YAAY,SAAS;AAAA,EAC/D,gBAAT,QAAwB,4BAA4B,aAAa,SAAS;AAAA,EAC1E,eAAe,QAAQ,OAAO;AAAA,EAC9B,sBAAsB,QAAQ,OAAO;AAAA,EACrC,SAAS,IAAI,EAAG,IAAI,+BAA+B,QAAQ,KAAK;AAAA,IAC9D,IAAI,eAAe,+BAA+B;AAAA,IAClD,aAAa,cAAc,cAAc,aAAa,YAAY;AAAA,EACpE;AAAA,EACA,MAEE,IAAI,+BAA+B,WACjC,IAAI,+BAA+B,IAAc,EAAE,cAAX;AAAA,IAG1C,+BAA+B,CAAC,GACrB,EAAE,cAAX,QAAwB,+BAA+B,MAAM;AAAA,EACjE,KAAK,UAAU,iBAAiB,WAAW;AAAA,EAC3C,IAAY,KAAR;AAAA,IACF,KAAK,eAAe,EAAG,eAAe,EAAE,QAAQ,gBAAgB,GAAG;AAAA,MACjE,IAAI,OAAO,EAAE,eACX,oBAAoB,EAAE,eAAe,IACrC,YAAY,KAAK,qBAAqB;AAAA,MACxC,IAAmB,OAAO,sBAAtB;AAAA,QACF,aAAa,4BAA4B,CAAC;AAAA,MACvC,SAAI,WAAW;AAAA,QAClB,IAAI,SAAS;AAAA,QACb,IAAI,qBAAqB,kBAAkB,aAAa,YAAY;AAAA,UAClE,IACI,OAAO,mBACR,YAAY,kBAAkB,qBAAqB;AAAA,YAEpD,SAAS,UAAU;AAAA,UAChB;AAAA,YACH,IAAa,2BAA2B,IAAI,MAAxC;AAAA,cAA2C;AAAA;AAAA,QAE9C;AAAA,mBAAS,UAAU;AAAA,QACT,OAAO,WAAtB,aACK,EAAE,eAAe,KAAK,UACtB,EAAE,OAAO,cAAc,CAAC,GAAI,gBAAgB;AAAA,QACjD,4BAA4B,CAAC;AAAA,MAC/B;AAAA,IACF;AAAA;AAEJ,SAAS,mCAAmC,GAAG;AAAA,EAC7C,SAAS,cAAc,CAAC,OAAO;AAAA,IAC7B,MAAM,gBACmB,MAAM,SAA7B,sBACA,MAAM,UAAU;AAAA,MACd,SAAS,QAAS,GAAG;AAAA,QACnB,OAAO,IAAI,QAAQ,QAAS,CAAC,SAAS;AAAA,UACpC,OAAQ,iBAAiB;AAAA,SAC1B;AAAA;AAAA,MAEH,YAAY;AAAA,MACZ,QAAQ;AAAA,IACV,CAAC;AAAA;AAAA,EAEL,SAAS,sBAAsB,GAAG;AAAA,IACvB,mBAAT,SAA4B,eAAe,GAAI,iBAAiB;AAAA,IAChE,eAAe,WAAW,qBAAqB,EAAE;AAAA;AAAA,EAEnD,SAAS,mBAAmB,GAAG;AAAA,IAC7B,IAAI,CAAC,eAAe,CAAC,WAAW,YAAY;AAAA,MAC1C,IAAI,eAAe,WAAW;AAAA,MAC9B,gBACU,aAAa,OAArB,QACA,WAAW,SAAS,aAAa,KAAK;AAAA,QACpC,OAAO,aAAa,SAAS;AAAA,QAC7B,MAAM;AAAA,QACN,SAAS;AAAA,MACX,CAAC;AAAA,IACL;AAAA;AAAA,EAEF,IAAiB,OAAO,eAApB,UAAgC;AAAA,IAClC,IAAI,cAAc,OAChB,iBAAiB;AAAA,IACnB,WAAW,iBAAiB,YAAY,cAAc;AAAA,IACtD,WAAW,iBAAiB,mBAAmB,sBAAsB;AAAA,IACrE,WAAW,iBAAiB,iBAAiB,sBAAsB;AAAA,IACnE,WAAW,qBAAqB,GAAG;AAAA,IACnC,OAAO,QAAS,GAAG;AAAA,MACjB,cAAc;AAAA,MACd,WAAW,oBAAoB,YAAY,cAAc;AAAA,MACzD,WAAW,oBAAoB,mBAAmB,sBAAsB;AAAA,MACxE,WAAW,oBAAoB,iBAAiB,sBAAsB;AAAA,MAC7D,mBAAT,SAA4B,eAAe,GAAI,iBAAiB;AAAA;AAAA,EAEpE;AAAA;AAEF,SAAS,YAAY,CAAC,cAAc;AAAA,EAClC,KAAK,gBAAgB;AAAA;AAqBvB,SAAS,qBAAqB,CAAC,cAAc;AAAA,EAC3C,KAAK,gBAAgB;AAAA;AAAA,IA7gfC,WACN,QACG,UA0IjB,SACF,2BACA,qBACA,oBACA,sBACA,yBACA,sBACA,sBACA,qBACA,yBACA,sBACA,0BACA,kBACA,kBAEE,sBAGA,2BAEA,wBAQA,wBAqDA,cACF,uBAEA,yBAEA,wBAMA,YACA,QAAQ,IAaN,oBACF,yBACA,yBACA,8BAwDE,QAAQ,QAiBR,UAAU,OA+KV,iBACF,oBACA,kBACA,aACA,cACA,KACA,yBACA,mBACA,sBACA,kBACA,aACA,cACA,OACA,gCACA,aAAa,MACb,eAAe,MAQb,OACF,MACA,KAKE,2BAA2B,KAC7B,6BAA6B,QAC7B,gBAAgB,SA2Sd,WACF,qBACA,kBACA,8BACA,0BACA,kCACA,4BACA,8BACA,yBAsEE,iBACF,8BAcE,4BAGF,2BACA,6BA0JE,qDA8KA,iBA8DA,SAgFF,sBAQE,wBAAwB,MAOxB,gBAAgB,MAClB,eAAe,MAmEb,uBAAuB,OA8DvB,WAKF,gCAAgC,OAG1B,SAWJ,OAAO,MACT,YAAY,MACZ,eAAe,MA4Fb,gBAUF,gBACA,kBACA,kBACA,eACA,eACA,gBACA,qBAmCA,qBACA,oBACA,oBACA,qBACA,qBACA,yBAKA,yBACA,yBAOA,yBACA,2BACA,2BACA,cAcA,gBAsCA,mBAiBE,wBAsCF,wBACA,uBAYA,uBACA,qBAUA,qBACA,0BAKA,0BACA,qBAoBA,qBACA,sBAIA,sBACA,cACA,wBACA,eAAe,MAIb,sBACF,4BAIA,eACA,mBAAmB,OAqBjB,cAAc,OAiDd,qBA+CA,kBAAkB,MACpB,sBAAsB,MAWpB,wBAAwB,OAEtB,qCAEE,+BAEE,2BAyDN,UAuGA,0BAEF,gBAAgB,MAChB,oBAAoB,MACpB,gBAAgB,MAChB,YAAY,OA6CV,gBASF,oBACA,OAmBE,eACF,qBACA,iBACA,gBACA,kBACA,mBACA,gBACA,4BACA,yBASE,oBA6BF,kBACA,wBAAwB,GACxB,2BAA2B,GAkFzB,oBA4NA,gBAmBA,WACF,iBAAiB,GACjB,mBAAmB,MACnB,gBAAgB,GAChB,SACA,eAAe,GACf,sBAAsB,MACtB,gBAAgB,GAChB,sBAAsB,IA8DpB,uBAAuB,MACzB,yBAAyB,MACzB,cAAc,OACd,kBAAkB,MAClB,yBAAyB,OACzB,4BAkKE,aACF,4BAA4B,MAC5B,wBAAwB,MAqKtB,sBAkBF,oBACA,gBACA,cAsBE,4BAA4B,MAC9B,+BAA+B,GAC/B,uBAAuB,GACvB,iCAAiC,MAyD/B,6BAUA,cAkBA,mBACF,0BACA,yBACA,6BAoEE,oBAAoB,MAcpB,kBAAkB,MACpB,yBAAyB,GA+rBvB,sBACF,kBACA,iBAAiB,OA+Ff,kCAAkC,OAqJlC,8BACF,gCAgBE,4BACF,gBAAgB,MA+Bd,qBAoCA,cAAc,GAChB,0BAA0B,MAC1B,cAAc,MACd,qBAAqB,MACrB,+BAA+B,OAC/B,6CAA6C,OAC7C,sCAAsC,OACtC,iBAAiB,GACjB,uBAAuB,GACvB,gBAAgB,MAChB,wBAAwB,GAmnCtB,uBA0BA,wBA0MF,yBAgDE,2BAqEA,uBAkTA,6BACF,mBAAmB,OA8rBjB,kBAq+DA,2BAA2B,OAC7B,4BAA4B,OAC5B,iBAAiB,OACjB,iBACA,aAAa,MAmTX,aAAa,MACf,wBAAwB,OAqRtB,uBAAuB,MAy6BvB,sBAAsB,MA+NtB,wBAaF,iBACA,mBAAmB,GACnB,qBAAqB,MACrB,iBAAiB,MACjB,gCAAgC,GAChC,gCAAgC,GAChC,4BAA4B,MAC5B,6CAA6C,OAC7C,mCAAmC,OACnC,0CAA0C,OAC1C,uBAAuB,GACvB,+BAA+B,GAC/B,iCAAiC,GACjC,4CAA4C,GAC5C,gCAAgC,GAChC,6BAA6B,GAC7B,oCAAoC,GACpC,qCAAqC,MACrC,sCAAsC,MACtC,oDAAoD,OACpD,+BAA+B,GAC/B,iCAAiC,GACjC,qCAAqC,UACrC,4BAA4B,MAC5B,yCAAyC,MACzC,uBAAuB,GACvB,qBAAqB,MACrB,sBAAsB,MACtB,sBAAsB,GACtB,+BAA+B,GAC/B,4BAA4B,MAC5B,2BAA2B,MAC3B,oBAAoB,GACpB,wBAAwB,MAsvCtB,qBAAqB,MACvB,oBAAoB,MACpB,uBAAuB,OACvB,2BAA2B,OAC3B,iBAAiB,OACjB,6BAA6B,GA8SzB,8BAEF,iCAEA,qCARE,sBA0DF,iBAIF,oBAgFE,iBAulBA,0BACF,sCA2/BE,gBAAgB,MAClB,uBAAuB,MA0CrB,iCAAiC,MAWjC,iBACF,eACA,cACA,mBAyPE,8CAA8C,MAkE9C,iBACF,gBAQE,oBAuBA,gBAufA,YAAY,MA0IZ,4BAA4B,GAuD5B,oBAAoB,MAkDpB,uBAkJA,WAAW,MA4HX,oBAAoB,MA0HpB,4BAA4B,OAC9B,cAAc,MACd,aAAa,MACb,cAAc,MACd,gBACA,uBACA,gCACA,0BAwOE,2BAA2B,MA0K3B,kDA6BA,8BAQE,yBAYE,cAAa,QAAS,CAAC,WAAW,UAAS;AAAA,EACjD,IAAI,CAAC,iBAAiB,SAAS;AAAA,IAAG,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,EACzE,IAAI,eAAe,OACjB,mBAAmB,IACnB,kBAAkB,wBAClB,gBAAgB,sBAChB,qBAAqB;AAAA,EACd,aAAT,QACa,aAAN,cACG,SAAQ,wBAAf,SAAuC,eAAe,OAC5C,SAAQ,qBAAd,cACF,mBAAmB,SAAQ,mBACnB,SAAQ,oBAAd,cACF,kBAAkB,SAAQ,kBAClB,SAAQ,kBAAd,cAAgC,gBAAgB,SAAQ,gBAClD,SAAQ,uBAAd,cACF,qBAAqB,SAAQ;AAAA,EAClC,WAAU,gBACR,WACA,GACA,OACA,MACA,MACA,cACA,kBACA,MACA,iBACA,eACA,oBACA,mCACF;AAAA,EACA,UAAU,gCAAgC,SAAQ;AAAA,EAClD,2BAA2B,SAAS;AAAA,EACpC,OAAO,IAAI,aAAa,QAAO;AAAA,GAEzB,eAAc,QAAS,CAAC,WAAW,iBAAiB,UAAS;AAAA,EACnE,IAAI,CAAC,iBAAiB,SAAS;AAAA,IAAG,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,EACzE,IAAI,eAAe,OACjB,mBAAmB,IACnB,kBAAkB,wBAClB,gBAAgB,sBAChB,qBAAqB,2BACrB,YAAY;AAAA,EACL,aAAT,QACa,aAAN,cACG,SAAQ,wBAAf,SAAuC,eAAe,OAC5C,SAAQ,qBAAd,cACF,mBAAmB,SAAQ,mBACnB,SAAQ,oBAAd,cACF,kBAAkB,SAAQ,kBAClB,SAAQ,kBAAd,cAAgC,gBAAgB,SAAQ,gBAClD,SAAQ,uBAAd,cACF,qBAAqB,SAAQ,qBACrB,SAAQ,cAAd,cAA4B,YAAY,SAAQ;AAAA,EACvD,kBAAkB,gBAChB,WACA,GACA,MACA,iBACQ,YAAR,OAAkB,WAAU,MAC5B,cACA,kBACA,WACA,iBACA,eACA,oBACA,mCACF;AAAA,EACA,gBAAgB,UAAU,qBAAqB,IAAI;AAAA,EACnD,WAAU,gBAAgB;AAAA,EAC1B,eAAe,kBAAkB;AAAA,EACjC,eAAe,gCAAgC,YAAY;AAAA,EAC3D,mBAAmB,aAAa,YAAY;AAAA,EAC5C,iBAAiB,WAAW;AAAA,EAC5B,cAAc,UAAS,kBAAkB,YAAY;AAAA,EACrD,WAAU;AAAA,EACV,gBAAgB,QAAQ,QAAQ;AAAA,EAChC,kBAAkB,iBAAiB,QAAO;AAAA,EAC1C,sBAAsB,eAAe;AAAA,EACrC,UAAU,gCAAgC,gBAAgB;AAAA,EAC1D,2BAA2B,SAAS;AAAA,EACpC,OAAO,IAAI,sBAAsB,eAAe;AAAA,GAE1C,YAAU;AAAA;AAAA,EAlqfM;AAAA,EACN;AAAA,EACG;AAAA,EA0IjB,UAAS,OAAO;AAAA,EAClB,4BAA4B,OAAO,IAAI,eAAe;AAAA,EACtD,sBAAqB,OAAO,IAAI,4BAA4B;AAAA,EAC5D,qBAAoB,OAAO,IAAI,cAAc;AAAA,EAC7C,uBAAsB,OAAO,IAAI,gBAAgB;AAAA,EACjD,0BAAyB,OAAO,IAAI,mBAAmB;AAAA,EACvD,uBAAsB,OAAO,IAAI,gBAAgB;AAAA,EACjD,uBAAsB,OAAO,IAAI,gBAAgB;AAAA,EACjD,sBAAqB,OAAO,IAAI,eAAe;AAAA,EAC/C,0BAAyB,OAAO,IAAI,mBAAmB;AAAA,EACvD,uBAAsB,OAAO,IAAI,gBAAgB;AAAA,EACjD,2BAA2B,OAAO,IAAI,qBAAqB;AAAA,EAC3D,mBAAkB,OAAO,IAAI,YAAY;AAAA,EACzC,mBAAkB,OAAO,IAAI,YAAY;AAAA,EAC3C,OAAO,IAAI,aAAa;AAAA,EACpB,uBAAsB,OAAO,IAAI,gBAAgB;AAAA,EACrD,OAAO,IAAI,qBAAqB;AAAA,EAChC,OAAO,IAAI,sBAAsB;AAAA,EAC7B,4BAA4B,OAAO,IAAI,2BAA2B;AAAA,EACtE,OAAO,IAAI,uBAAuB;AAAA,EAC9B,yBAAwB,OAAO;AAAA,EAQ/B,yBAAyB,OAAO,IAAI,wBAAwB;AAAA,EAqD5D,eAAc,MAAM;AAAA,EACtB,wBACQ;AAAA,EACR,0BACW;AAAA,EACX,yBAAyB;AAAA,IACvB,SAAS;AAAA,IACT,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AAAA,EACA,aAAa,CAAC;AAAA,EAcZ,qBAAqB,aAAa,IAAI;AAAA,EACxC,0BAA0B,aAAa,IAAI;AAAA,EAC3C,0BAA0B,aAAa,IAAI;AAAA,EAC3C,+BAA+B,aAAa,IAAI;AAAA,EAwP9C,kBAAiB,OAAO,UAAU;AAAA,EACpC,qBAA+B;AAAA,EAC/B,mBAA6B;AAAA,EAC7B,cAAwB;AAAA,EACxB,eAAyB;AAAA,EACzB,MAAgB;AAAA,EAChB,0BAAoC;AAAA,EACpC,oBAA8B;AAAA,EAC9B,uBAAiC;AAAA,EACjC,mBAA6B;AAAA,EAC7B,cAAwB;AAAA,EACxB,eAAyB;AAAA,EACzB,QAAkB;AAAA,EAClB,iCAA0C;AAAA,EAUxC,QAAQ,KAAK,QAAQ,KAAK,QAAQ;AAAA,EACpC,OAAM,KAAK;AAAA,EACX,MAAM,KAAK;AAAA,EAkTT,YAAY,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC;AAAA,EAChD,sBAAsB,kBAAkB;AAAA,EACxC,mBAAmB,kBAAkB;AAAA,EACrC,+BAA+B,sBAAsB;AAAA,EACrD,2BAA2B,mBAAmB;AAAA,EAC9C,mCAAmC,sBAAsB;AAAA,EACzD,6BAA6B,oBAAoB;AAAA,EACjD,+BAA+B,sBAAsB;AAAA,EACrD,0BAA0B,mBAAmB;AAAA,EAsE3C,kBAAkB,IAAI;AAAA,EACxB,+BAA+B,CAAC;AAAA,EAc9B,6BAA6B,OAC7B,+YACF;AAAA,EACA,4BAA4B,CAAC;AAAA,EAC7B,8BAA8B,CAAC;AAAA,EA0J7B,sDAAsD;AAAA,EA8KtD,kBAAkB,IAAI,IACxB,26BAA26B,MACz6B,GACF,CACF;AAAA,EA0DI,UAAU,IAAI,IAAI;AAAA,IAClB,CAAC,iBAAiB,gBAAgB;AAAA,IAClC,CAAC,WAAW,KAAK;AAAA,IACjB,CAAC,aAAa,YAAY;AAAA,IAC1B,CAAC,eAAe,aAAa;AAAA,IAC7B,CAAC,gBAAgB,eAAe;AAAA,IAChC,CAAC,qBAAqB,oBAAoB;AAAA,IAC1C,CAAC,cAAc,aAAa;AAAA,IAC5B,CAAC,iBAAiB,gBAAgB;AAAA,IAClC,CAAC,aAAa,YAAY;AAAA,IAC1B,CAAC,YAAY,WAAW;AAAA,IACxB,CAAC,YAAY,WAAW;AAAA,IACxB,CAAC,sBAAsB,qBAAqB;AAAA,IAC5C,CAAC,6BAA6B,6BAA6B;AAAA,IAC3D,CAAC,gBAAgB,eAAe;AAAA,IAChC,CAAC,kBAAkB,iBAAiB;AAAA,IACpC,CAAC,oBAAoB,mBAAmB;AAAA,IACxC,CAAC,oBAAoB,mBAAmB;AAAA,IACxC,CAAC,eAAe,cAAc;AAAA,IAC9B,CAAC,YAAY,WAAW;AAAA,IACxB,CAAC,cAAc,aAAa;AAAA,IAC5B,CAAC,gBAAgB,eAAe;AAAA,IAChC,CAAC,cAAc,aAAa;AAAA,IAC5B,CAAC,YAAY,WAAW;AAAA,IACxB,CAAC,kBAAkB,kBAAkB;AAAA,IACrC,CAAC,eAAe,cAAc;AAAA,IAC9B,CAAC,aAAa,YAAY;AAAA,IAC1B,CAAC,eAAe,cAAc;AAAA,IAC9B,CAAC,cAAc,aAAa;AAAA,IAC5B,CAAC,aAAa,YAAY;AAAA,IAC1B,CAAC,8BAA8B,8BAA8B;AAAA,IAC7D,CAAC,4BAA4B,4BAA4B;AAAA,IACzD,CAAC,aAAa,aAAa;AAAA,IAC3B,CAAC,gBAAgB,gBAAgB;AAAA,IACjC,CAAC,kBAAkB,iBAAiB;AAAA,IACpC,CAAC,iBAAiB,gBAAgB;AAAA,IAClC,CAAC,iBAAiB,gBAAgB;AAAA,IAClC,CAAC,aAAa,YAAY;AAAA,IAC1B,CAAC,aAAa,YAAY;AAAA,IAC1B,CAAC,eAAe,cAAc;AAAA,IAC9B,CAAC,oBAAoB,mBAAmB;AAAA,IACxC,CAAC,qBAAqB,oBAAoB;AAAA,IAC1C,CAAC,cAAc,aAAa;AAAA,IAC5B,CAAC,YAAY,UAAU;AAAA,IACvB,CAAC,iBAAiB,gBAAgB;AAAA,IAClC,CAAC,mBAAmB,kBAAkB;AAAA,IACtC,CAAC,kBAAkB,iBAAiB;AAAA,IACpC,CAAC,aAAa,YAAY;AAAA,IAC1B,CAAC,eAAe,cAAc;AAAA,IAC9B,CAAC,yBAAyB,wBAAwB;AAAA,IAClD,CAAC,0BAA0B,yBAAyB;AAAA,IACpD,CAAC,mBAAmB,kBAAkB;AAAA,IACtC,CAAC,oBAAoB,mBAAmB;AAAA,IACxC,CAAC,iBAAiB,gBAAgB;AAAA,IAClC,CAAC,kBAAkB,iBAAiB;AAAA,IACpC,CAAC,oBAAoB,mBAAmB;AAAA,IACxC,CAAC,iBAAiB,gBAAgB;AAAA,IAClC,CAAC,eAAe,cAAc;AAAA,IAC9B,CAAC,cAAc,aAAa;AAAA,IAC5B,CAAC,kBAAkB,iBAAiB;AAAA,IACpC,CAAC,iBAAiB,gBAAgB;AAAA,IAClC,CAAC,mBAAmB,kBAAkB;AAAA,IACtC,CAAC,qBAAqB,oBAAoB;AAAA,IAC1C,CAAC,sBAAsB,qBAAqB;AAAA,IAC5C,CAAC,eAAe,cAAc;AAAA,IAC9B,CAAC,gBAAgB,eAAe;AAAA,IAChC,CAAC,cAAc,cAAc;AAAA,IAC7B,CAAC,eAAe,cAAc;AAAA,IAC9B,CAAC,YAAY,WAAW;AAAA,IACxB,CAAC,gBAAgB,eAAe;AAAA,IAChC,CAAC,iBAAiB,gBAAgB;AAAA,IAClC,CAAC,gBAAgB,eAAe;AAAA,IAChC,CAAC,YAAY,YAAY;AAAA,IACzB,CAAC,eAAe,eAAe;AAAA,IAC/B,CAAC,eAAe,eAAe;AAAA,IAC/B,CAAC,eAAe,cAAc;AAAA,IAC9B,CAAC,eAAe,cAAc;AAAA,IAC9B,CAAC,cAAc,aAAa;AAAA,IAC5B,CAAC,WAAW,UAAU;AAAA,EACxB,CAAC;AAAA,EACD,uBACE;AAAA,EAgJA,YAAY,EACI,OAAO,WAAvB,eACgB,OAAO,OAAO,aAA9B,eACgB,OAAO,OAAO,SAAS,kBAAvC;AAAA,EAGJ,IAAI;AAAA,IACF,IAAI;AAAA,MACE,UAAU,CAAC;AAAA,MACf,OAAO,eAAe,SAAS,WAAW;AAAA,QACxC,KAAK,QAAS,GAAG;AAAA,UACf,gCAAgC;AAAA;AAAA,MAEpC,CAAC;AAAA,MACD,OAAO,iBAAiB,QAAQ,SAAS,OAAO;AAAA,MAChD,OAAO,oBAAoB,QAAQ,SAAS,OAAO;AAAA,MACnD,OAAO,GAAG;AAAA,MACV,gCAAgC;AAAA;AAAA,EAgGhC,iBAAiB;AAAA,IACjB,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,WAAW,QAAS,CAAC,OAAO;AAAA,MAC1B,OAAO,MAAM,aAAa,KAAK,IAAI;AAAA;AAAA,IAErC,kBAAkB;AAAA,IAClB,WAAW;AAAA,EACb;AAAA,EACA,iBAAiB,qBAAqB,cAAc;AAAA,EACpD,mBAAmB,QAAO,CAAC,GAAG,gBAAgB,EAAE,MAAM,GAAG,QAAQ,EAAE,CAAC;AAAA,EACpE,mBAAmB,qBAAqB,gBAAgB;AAAA,EAIxD,sBAAsB,QAAO,CAAC,GAAG,kBAAkB;AAAA,IACjD,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,OAAO;AAAA,IACP,OAAO;AAAA,IACP,SAAS;AAAA,IACT,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,kBAAkB;AAAA,IAClB,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,eAAe,QAAS,CAAC,OAAO;AAAA,MAC9B,OAAkB,MAAM,kBAAZ,YACR,MAAM,gBAAgB,MAAM,aAC1B,MAAM,YACN,MAAM,cACR,MAAM;AAAA;AAAA,IAEZ,WAAW,QAAS,CAAC,OAAO;AAAA,MAC1B,IAAI,eAAe;AAAA,QAAO,OAAO,MAAM;AAAA,MACvC,UAAU,mBACP,kBAAkC,MAAM,SAAtB,eACb,gBAAgB,MAAM,UAAU,eAAe,SAChD,gBAAgB,MAAM,UAAU,eAAe,WAC/C,gBAAgB,gBAAgB,GACpC,iBAAiB;AAAA,MACpB,OAAO;AAAA;AAAA,IAET,WAAW,QAAS,CAAC,OAAO;AAAA,MAC1B,OAAO,eAAe,QAAQ,MAAM,YAAY;AAAA;AAAA,EAEpD,CAAC;AAAA,EACD,sBAAsB,qBAAqB,mBAAmB;AAAA,EAC9D,qBAAqB,QAAO,CAAC,GAAG,qBAAqB,EAAE,cAAc,EAAE,CAAC;AAAA,EACxE,qBAAqB,qBAAqB,kBAAkB;AAAA,EAC5D,sBAAsB,QAAO,CAAC,GAAG,kBAAkB,EAAE,eAAe,EAAE,CAAC;AAAA,EACvE,sBAAsB,qBAAqB,mBAAmB;AAAA,EAC9D,0BAA0B,QAAO,CAAC,GAAG,gBAAgB;AAAA,IACnD,eAAe;AAAA,IACf,aAAa;AAAA,IACb,eAAe;AAAA,EACjB,CAAC;AAAA,EACD,0BAA0B,qBAAqB,uBAAuB;AAAA,EACtE,0BAA0B,QAAO,CAAC,GAAG,gBAAgB;AAAA,IACnD,eAAe,QAAS,CAAC,OAAO;AAAA,MAC9B,OAAO,mBAAmB,QACtB,MAAM,gBACN,OAAO;AAAA;AAAA,EAEf,CAAC;AAAA,EACD,0BAA0B,qBAAqB,uBAAuB;AAAA,EACtE,4BAA4B,QAAO,CAAC,GAAG,gBAAgB,EAAE,MAAM,EAAE,CAAC;AAAA,EAClE,4BAA4B,qBAAqB,yBAAyB;AAAA,EAC1E,eAAe;AAAA,IACb,KAAK;AAAA,IACL,UAAU;AAAA,IACV,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,MAAM;AAAA,IACN,KAAK;AAAA,IACL,KAAK;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,iBAAiB;AAAA,EACnB;AAAA,EACA,iBAAiB;AAAA,IACf,GAAG;AAAA,IACH,GAAG;AAAA,IACH,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,EACP;AAAA,EACA,oBAAoB;AAAA,IAClB,KAAK;AAAA,IACL,SAAS;AAAA,IACT,MAAM;AAAA,IACN,OAAO;AAAA,EACT;AAAA,EAYE,yBAAyB,QAAO,CAAC,GAAG,kBAAkB;AAAA,IACtD,KAAK,QAAS,CAAC,aAAa;AAAA,MAC1B,IAAI,YAAY,KAAK;AAAA,QACnB,IAAI,MAAM,aAAa,YAAY,QAAQ,YAAY;AAAA,QACvD,IAAuB,QAAnB;AAAA,UAAwB,OAAO;AAAA,MACrC;AAAA,MACA,OAAsB,YAAY,SAA3B,cACD,cAAc,iBAAiB,WAAW,GACrC,gBAAP,KAAqB,UAAU,OAAO,aAAa,WAAW,KAChD,YAAY,SAA1B,aAA8C,YAAY,SAAxB,UAChC,eAAe,YAAY,YAAY,iBACvC;AAAA;AAAA,IAER,MAAM;AAAA,IACN,UAAU;AAAA,IACV,SAAS;AAAA,IACT,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,kBAAkB;AAAA,IAClB,UAAU,QAAS,CAAC,OAAO;AAAA,MACzB,OAAsB,MAAM,SAArB,aAA4B,iBAAiB,KAAK,IAAI;AAAA;AAAA,IAE/D,SAAS,QAAS,CAAC,OAAO;AAAA,MACxB,OAAqB,MAAM,SAApB,aAAwC,MAAM,SAAlB,UAC/B,MAAM,UACN;AAAA;AAAA,IAEN,OAAO,QAAS,CAAC,OAAO;AAAA,MACtB,OAAsB,MAAM,SAArB,aACH,iBAAiB,KAAK,IACR,MAAM,SAApB,aAAwC,MAAM,SAAlB,UAC1B,MAAM,UACN;AAAA;AAAA,EAEV,CAAC;AAAA,EACD,yBAAyB,qBAAqB,sBAAsB;AAAA,EACpE,wBAAwB,QAAO,CAAC,GAAG,qBAAqB;AAAA,IACtD,WAAW;AAAA,IACX,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,oBAAoB;AAAA,IACpB,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,aAAa;AAAA,IACb,WAAW;AAAA,EACb,CAAC;AAAA,EACD,wBAAwB,qBAAqB,qBAAqB;AAAA,EAClE,sBAAsB,QAAO,CAAC,GAAG,kBAAkB;AAAA,IACjD,SAAS;AAAA,IACT,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,QAAQ;AAAA,IACR,SAAS;AAAA,IACT,SAAS;AAAA,IACT,UAAU;AAAA,IACV,kBAAkB;AAAA,EACpB,CAAC;AAAA,EACD,sBAAsB,qBAAqB,mBAAmB;AAAA,EAC9D,2BAA2B,QAAO,CAAC,GAAG,gBAAgB;AAAA,IACpD,cAAc;AAAA,IACd,aAAa;AAAA,IACb,eAAe;AAAA,EACjB,CAAC;AAAA,EACD,2BAA2B,qBAAqB,wBAAwB;AAAA,EACxE,sBAAsB,QAAO,CAAC,GAAG,qBAAqB;AAAA,IACpD,QAAQ,QAAS,CAAC,OAAO;AAAA,MACvB,OAAO,YAAY,QACf,MAAM,UACN,iBAAiB,SACf,CAAC,MAAM,cACP;AAAA;AAAA,IAER,QAAQ,QAAS,CAAC,OAAO;AAAA,MACvB,OAAO,YAAY,QACf,MAAM,UACN,iBAAiB,SACf,CAAC,MAAM,eACP,gBAAgB,SACd,CAAC,MAAM,aACP;AAAA;AAAA,IAEV,QAAQ;AAAA,IACR,WAAW;AAAA,EACb,CAAC;AAAA,EACD,sBAAsB,qBAAqB,mBAAmB;AAAA,EAC9D,uBAAuB,QAAO,CAAC,GAAG,gBAAgB;AAAA,IAChD,UAAU;AAAA,IACV,UAAU;AAAA,EACZ,CAAC;AAAA,EACD,uBAAuB,qBAAqB,oBAAoB;AAAA,EAChE,eAAe,CAAC,GAAG,IAAI,IAAI,EAAE;AAAA,EAC7B,yBAAyB,aAAa,sBAAsB;AAAA,EAE9D,aACE,kBAAkB,aACjB,eAAe,SAAS;AAAA,EACvB,uBAAuB,aAAa,eAAe,UAAU,CAAC;AAAA,EAChE,6BACE,cACC,CAAC,0BACC,gBAAgB,IAAI,gBAAgB,MAAM;AAAA,EAC/C,gBAAgB,OAAO,aAAa,EAAE;AAAA,EAuEpC,sBAAsB;AAAA,IACxB,OAAO;AAAA,IACP,MAAM;AAAA,IACN,UAAU;AAAA,IACV,kBAAkB;AAAA,IAClB,OAAO;AAAA,IACP,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,KAAK;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,IACN,KAAK;AAAA,IACL,MAAM;AAAA,EACR;AAAA,EA4CA,IAAI,WAAW;AAAA,IAEb,IAAI,WAAW;AAAA,MACT,gCAAgC,aAAa;AAAA,MACjD,IAAI,CAAC,+BAA+B;AAAA,QAC9B,4BAA4B,SAAS,cAAc,KAAK;AAAA,QAC5D,0BAA0B,aAAa,WAAW,SAAS;AAAA,QAC3D,gCACiB,OAAO,0BAA0B,YAAhD;AAAA,MACJ;AAAA,MACA,sCAAsC;AAAA,IACxC,EAAO;AAAA,4CAAsC;AAAA,IAC7C,wBACE,wCACC,CAAC,SAAS,gBAAgB,IAAI,SAAS;AAAA,EAC5C;AAAA,EA+CI,WAA0B,OAAO,OAAO,OAA7B,aAAkC,OAAO,KAAK;AAAA,EAuGzD,2BACA,aAAa,kBAAkB,YAAY,MAAM,SAAS;AAAA,EAiD1D,iBAAiB;AAAA,IACjB,cAAc,cAAc,aAAa,cAAc;AAAA,IACvD,oBAAoB,cAAc,aAAa,oBAAoB;AAAA,IACnE,gBAAgB,cAAc,aAAa,gBAAgB;AAAA,IAC3D,eAAe,cAAc,cAAc,eAAe;AAAA,IAC1D,iBAAiB,cAAc,cAAc,iBAAiB;AAAA,IAC9D,kBAAkB,cAAc,cAAc,kBAAkB;AAAA,IAChE,eAAe,cAAc,cAAc,eAAe;AAAA,EAC5D;AAAA,EACA,qBAAqB,CAAC;AAAA,EACtB,QAAQ,CAAC;AAAA,EACX,cACI,QAAQ,SAAS,cAAc,KAAK,EAAE,QACxC,oBAAoB,YACjB,OAAO,eAAe,aAAa,WACpC,OAAO,eAAe,mBAAmB,WACzC,OAAO,eAAe,eAAe,aACvC,qBAAqB,WACnB,OAAO,eAAe,cAAc;AAAA,EAWpC,gBAAgB,2BAA2B,cAAc;AAAA,EAC3D,sBAAsB,2BAA2B,oBAAoB;AAAA,EACrE,kBAAkB,2BAA2B,gBAAgB;AAAA,EAC7D,iBAAiB,2BAA2B,eAAe;AAAA,EAC3D,mBAAmB,2BAA2B,iBAAiB;AAAA,EAC/D,oBAAoB,2BAA2B,kBAAkB;AAAA,EACjE,iBAAiB,2BAA2B,eAAe;AAAA,EAC3D,6BAA6B,IAAI;AAAA,EACjC,0BACE,mnBAAmnB,MACjnB,GACF;AAAA,EACJ,wBAAwB,KAAK,WAAW;AAAA,EAKpC,qBACe,OAAO,gBAAtB,aACI,cACA,QAAS,CAAC,OAAO;AAAA,IACf,IACe,OAAO,WAApB,YACe,OAAO,OAAO,eAA7B,YACA;AAAA,MACA,IAAI,QAAQ,IAAI,OAAO,WAAW,SAAS;AAAA,QACzC,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,SACe,OAAO,UAApB,YACS,UAAT,QACa,OAAO,MAAM,YAA1B,WACI,OAAO,MAAM,OAAO,IACpB,OAAO,KAAK;AAAA,QAClB;AAAA,MACF,CAAC;AAAA,MACD,IAAI,CAAC,OAAO,cAAc,KAAK;AAAA,QAAG;AAAA,IACpC,EAAO,SACQ,OAAO,YAApB,YACe,OAAO,QAAQ,SAA9B,YACA;AAAA,MACA,QAAQ,KAAK,qBAAqB,KAAK;AAAA,MACvC;AAAA,IACF;AAAA,IACA,QAAQ,MAAM,KAAK;AAAA;AAAA,EAE3B,mBAAmB,CAAC;AAAA,EAoFlB,qBAAqB,CAAC;AAAA,EA4NtB,iBAAiB,IAAI;AAAA,EAmBrB,YAAY,CAAC;AAAA,EAIf,UAAU,CAAC;AAAA,EAuEX,6BAA6B,MAAM,wBAAuB,GAAG,CAAC;AAAA,EAkK5D,cAAc,aAAa,IAAI;AAAA,EAuK/B,uBACgB,OAAO,oBAAvB,cACI,kBACA,QAAS,GAAG;AAAA,IACV,IAAI,YAAY,CAAC,GACf,SAAU,KAAK,SAAS;AAAA,MACtB,SAAS;AAAA,MACT,kBAAkB,QAAS,CAAC,MAAM,UAAU;AAAA,QAC1C,UAAU,KAAK,QAAQ;AAAA;AAAA,IAE3B;AAAA,IACF,KAAK,QAAQ,QAAS,GAAG;AAAA,MACvB,OAAO,UAAU;AAAA,MACjB,UAAU,QAAQ,QAAS,CAAC,UAAU;AAAA,QACpC,OAAO,SAAS;AAAA,OACjB;AAAA;AAAA;AAAA,EAGX,qBAA+B;AAAA,EAC/B,iBAA2B;AAAA,EAC3B,eAAe;AAAA,IACb,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,cAAc;AAAA,EAChB;AAAA,EA2EE,8BAA8B,sBAAqB;AAAA,EACvD,sBAAqB,IAAI,QAAS,CAAC,YAAY,aAAa;AAAA,IAC1D,iCAAiC,IAAI;AAAA,IACxB,OAAO,gBAApB,YACW,gBAAT,QACe,OAAO,YAAY,SAAlC,cACA,oBAAoB,YAAY,WAAW;AAAA,IACpC,gCAAT,QACE,4BAA4B,YAAY,WAAW;AAAA;AAAA,EAEnD,eAAe,aAAa,IAAI;AAAA,EAkBhC,oBAAoB,MAAM,wBAAuB,GAAG,CAAC;AAAA,EACvD,2BAA2B,MAAM,wBAAuB,GAAG,CAAC;AAAA,EAC5D,0BAA0B,MAAM,wBAAuB,GAAG,CAAC;AAAA,EAC3D,8BAA8B,EAAE,MAAM,QAAS,GAAG,GAAG;AAAA,EAkxBnD,uBAAuB,sBAAsB,IAAE;AAAA,EACjD,mBAAmB,sBAAsB,KAAE;AAAA,EAqPzC,+BAA+B,aAAa,IAAI;AAAA,EAClD,iCAAiC,aAAa,CAAC;AAAA,EAgB7C,6BAA6B,aAAa,IAAI;AAAA,EAgC9C,sBAAsB,aAAa,CAAC;AAAA,EAiqCpC,wBAAwB;AAAA,IAC1B;AAAA,IACA;AAAA,IACA,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,qBAAqB;AAAA,IACrB,iBAAiB;AAAA,IACjB,oBAAoB;AAAA,IACpB,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,eAAe;AAAA,IACf,kBAAkB;AAAA,IAClB,eAAe;AAAA,IACf,sBAAsB;AAAA,IACtB,OAAO;AAAA,IACP,yBAAyB;AAAA,IACzB,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,eAAe;AAAA,IACf,cAAc;AAAA,IACd,iBAAiB;AAAA,EACnB;AAAA,EACA,sBAAsB,iBAAiB;AAAA,EACnC,yBAAyB;AAAA,IACzB;AAAA,IACA;AAAA,IACA,aAAa,QAAS,CAAC,UAAU,MAAM;AAAA,MACrC,wBAAwB,EAAE,gBAAgB;AAAA,QACxC;AAAA,QACW,SAAN,YAAa,OAAO;AAAA,MAC3B;AAAA,MACA,OAAO;AAAA;AAAA,IAET,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,qBAAqB,QAAS,CAAC,KAAK,QAAQ,MAAM;AAAA,MAChD,OAAgB,SAAT,QAA4B,SAAN,YAAa,KAAK,OAAO,CAAC,GAAG,CAAC,IAAI;AAAA,MAC/D,gBACE,SACA,GACA,uBAAuB,KAAK,MAAM,QAAQ,GAAG,GAC7C,IACF;AAAA;AAAA,IAEF,iBAAiB,QAAS,CAAC,QAAQ,MAAM;AAAA,MACvC,OAAO,gBAAgB,SAAS,GAAG,QAAQ,IAAI;AAAA;AAAA,IAEjD,oBAAoB,QAAS,CAAC,QAAQ,MAAM;AAAA,MAC1C,gBAAgB,GAAG,GAAG,QAAQ,IAAI;AAAA;AAAA,IAEpC,SAAS,QAAS,CAAC,YAAY,MAAM;AAAA,MACnC,IAAI,OAAO,wBAAwB;AAAA,MACnC,OAAkB,SAAN,YAAa,OAAO;AAAA,MAChC,IAAI,YAAY,WAAW;AAAA,MAC3B,IAAI,qCAAqC;AAAA,QACvC,2BAA2B,IAAE;AAAA,QAC7B,IAAI;AAAA,UACF,WAAW;AAAA,kBACX;AAAA,UACA,2BAA2B,KAAE;AAAA;AAAA,MAEjC;AAAA,MACA,KAAK,gBAAgB,CAAC,WAAW,IAAI;AAAA,MACrC,OAAO;AAAA;AAAA,IAET,YAAY,QAAS,CAAC,SAAS,YAAY,MAAM;AAAA,MAC/C,IAAI,OAAO,wBAAwB;AAAA,MACnC,IAAe,SAAN,WAAY;AAAA,QACnB,IAAI,eAAe,KAAK,UAAU;AAAA,QAClC,IAAI,qCAAqC;AAAA,UACvC,2BAA2B,IAAE;AAAA,UAC7B,IAAI;AAAA,YACF,KAAK,UAAU;AAAA,oBACf;AAAA,YACA,2BAA2B,KAAE;AAAA;AAAA,QAEjC;AAAA,MACF,EAAO;AAAA,uBAAe;AAAA,MACtB,KAAK,gBAAgB,KAAK,YAAY;AAAA,MACtC,UAAU;AAAA,QACR,SAAS;AAAA,QACT,OAAO;AAAA,QACP,UAAU;AAAA,QACV,qBAAqB;AAAA,QACrB,mBAAmB;AAAA,MACrB;AAAA,MACA,KAAK,QAAQ;AAAA,MACb,UAAU,QAAQ,WAAW,sBAAsB,KACjD,MACA,yBACA,OACF;AAAA,MACA,OAAO,CAAC,KAAK,eAAe,OAAO;AAAA;AAAA,IAErC,QAAQ,QAAS,CAAC,cAAc;AAAA,MAC9B,IAAI,OAAO,wBAAwB;AAAA,MACnC,eAAe,EAAE,SAAS,aAAa;AAAA,MACvC,OAAQ,KAAK,gBAAgB;AAAA;AAAA,IAE/B,UAAU,QAAS,CAAC,cAAc;AAAA,MAChC,eAAe,eAAe,YAAY;AAAA,MAC1C,IAAI,QAAQ,aAAa,OACvB,WAAW,iBAAiB,KAAK,MAAM,yBAAyB,KAAK;AAAA,MACvE,MAAM,WAAW;AAAA,MACjB,OAAO,CAAC,aAAa,eAAe,QAAQ;AAAA;AAAA,IAE9C,eAAe;AAAA,IACf,kBAAkB,QAAS,CAAC,OAAO,cAAc;AAAA,MAC/C,IAAI,OAAO,wBAAwB;AAAA,MACnC,OAAO,uBAAuB,MAAM,OAAO,YAAY;AAAA;AAAA,IAEzD,eAAe,QAAS,GAAG;AAAA,MACzB,IAAI,YAAY,eAAe,KAAE;AAAA,MACjC,YAAY,gBAAgB,KAC1B,MACA,yBACA,UAAU,OACV,MACA,KACF;AAAA,MACA,wBAAwB,EAAE,gBAAgB;AAAA,MAC1C,OAAO,CAAC,OAAI,SAAS;AAAA;AAAA,IAEvB,sBAAsB,QAAS,CAAC,WAAW,aAAa,mBAAmB;AAAA,MACzE,IAAI,QAAQ,yBACV,OAAO,wBAAwB;AAAA,MACjC,IAAI,aAAa;AAAA,QACf,IAAe,sBAAN;AAAA,UACP,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,QACzC,oBAAoB,kBAAkB;AAAA,MACxC,EAAO;AAAA,QACL,oBAAoB,YAAY;AAAA,QAChC,IAAa,uBAAT;AAAA,UACF,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,SAClC,gCAAgC,SAAvC,KACE,0BAA0B,OAAO,aAAa,iBAAiB;AAAA;AAAA,MAEnE,KAAK,gBAAgB;AAAA,MACrB,IAAI,OAAO,EAAE,OAAO,mBAAmB,YAAyB;AAAA,MAChE,KAAK,QAAQ;AAAA,MACb,YAAY,iBAAiB,KAAK,MAAM,OAAO,MAAM,SAAS,GAAG;AAAA,QAC/D;AAAA,MACF,CAAC;AAAA,MACD,MAAM,SAAS;AAAA,MACf,iBACE,GACA,EAAE,SAAc,UAAE,GAClB,oBAAoB,KAClB,MACA,OACA,MACA,mBACA,WACF,GACA,IACF;AAAA,MACA,OAAO;AAAA;AAAA,IAET,OAAO,QAAS,GAAG;AAAA,MACjB,IAAI,OAAO,wBAAwB,GACjC,mBAAmB,mBAAmB;AAAA,MACxC,IAAI,aAAa;AAAA,QACf,IAAI,2BAA2B;AAAA,QAC/B,IAAI,mBAAmB;AAAA,QACvB,4BAEI,mBAAmB,EAAE,KAAM,KAAK,MAAM,gBAAgB,IAAI,IAC1D,SAAS,EAAE,IAAI;AAAA,QACnB,mBACE,MAAM,mBAAmB,OAAO;AAAA,QAClC,2BAA2B;AAAA,QAC3B,IAAI,6BACD,oBAAoB,MAAM,yBAAyB,SAAS,EAAE;AAAA,QACjE,oBAAoB;AAAA,MACtB,EACE;AAAA,QAAC,2BAA2B,yBACzB,mBACC,MACA,mBACA,OACA,yBAAyB,SAAS,EAAE,IACpC;AAAA,MACN,OAAQ,KAAK,gBAAgB;AAAA;AAAA,IAE/B;AAAA,IACA,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,eAAe,QAAS,CAAC,aAAa;AAAA,MACpC,IAAI,OAAO,wBAAwB;AAAA,MACnC,KAAK,gBAAgB,KAAK,YAAY;AAAA,MACtC,IAAI,QAAQ;AAAA,QACV,SAAS;AAAA,QACT,OAAO;AAAA,QACP,UAAU;AAAA,QACV,qBAAqB;AAAA,QACrB,mBAAmB;AAAA,MACrB;AAAA,MACA,KAAK,QAAQ;AAAA,MACb,OAAO,2BAA2B,KAChC,MACA,yBACA,MACA,KACF;AAAA,MACA,MAAM,WAAW;AAAA,MACjB,OAAO,CAAC,aAAa,IAAI;AAAA;AAAA,IAE3B;AAAA,IACA,iBAAiB,QAAS,GAAG;AAAA,MAC3B,OAAQ,wBAAwB,EAAE,gBAAgB,aAAa,KAC7D,MACA,uBACF;AAAA;AAAA,IAEF,gBAAgB,QAAS,CAAC,UAAU;AAAA,MAClC,IAAI,OAAO,wBAAwB,GACjC,MAAM,EAAE,MAAM,SAAS;AAAA,MACzB,KAAK,gBAAgB;AAAA,MACrB,OAAO,QAAS,GAAG;AAAA,QACjB,KAAW,mBAAmB,OAA1B;AAAA,UACF,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,QACzC,OAAO,IAAI,KAAK,MAAW,WAAG,SAAS;AAAA;AAAA;AAAA,EAG7C;AAAA,EACA,0BAA0B;AAAA,IACxB;AAAA,IACA;AAAA,IACA,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,qBAAqB;AAAA,IACrB,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,UAAU,QAAS,GAAG;AAAA,MACpB,OAAO,cAAc,iBAAiB;AAAA;AAAA,IAExC,eAAe;AAAA,IACf,kBAAkB,QAAS,CAAC,OAAO,cAAc;AAAA,MAC/C,IAAI,OAAO,yBAAyB;AAAA,MACpC,OAAO,wBACL,MACA,YAAY,eACZ,OACA,YACF;AAAA;AAAA,IAEF,eAAe,QAAS,GAAG;AAAA,MACzB,IAAI,oBAAoB,cAAc,iBAAiB,EAAE,IACvD,QAAQ,yBAAyB,EAAE;AAAA,MACrC,OAAO;AAAA,QACS,OAAO,sBAArB,YACI,oBACA,YAAY,iBAAiB;AAAA,QACjC;AAAA,MACF;AAAA;AAAA,IAEF,sBAAsB;AAAA,IACtB,OAAO;AAAA,IACP;AAAA,IACA,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,eAAe,QAAS,CAAC,aAAa,SAAS;AAAA,MAC7C,IAAI,OAAO,yBAAyB;AAAA,MACpC,OAAO,qBAAqB,MAAM,aAAa,aAAa,OAAO;AAAA;AAAA,IAErE;AAAA,IACA,iBAAiB;AAAA,EACnB;AAAA,EACF,wBAAwB,iBAAiB;AAAA,EACrC,4BAA4B;AAAA,IAC9B;AAAA,IACA;AAAA,IACA,aAAa;AAAA,IACb,YAAY;AAAA,IACZ,WAAW;AAAA,IACX,qBAAqB;AAAA,IACrB,oBAAoB;AAAA,IACpB,iBAAiB;AAAA,IACjB,SAAS;AAAA,IACT,YAAY;AAAA,IACZ,QAAQ;AAAA,IACR,UAAU,QAAS,GAAG;AAAA,MACpB,OAAO,gBAAgB,iBAAiB;AAAA;AAAA,IAE1C,eAAe;AAAA,IACf,kBAAkB,QAAS,CAAC,OAAO,cAAc;AAAA,MAC/C,IAAI,OAAO,yBAAyB;AAAA,MACpC,OAAgB,gBAAT,OACH,uBAAuB,MAAM,OAAO,YAAY,IAChD,wBACE,MACA,YAAY,eACZ,OACA,YACF;AAAA;AAAA,IAEN,eAAe,QAAS,GAAG;AAAA,MACzB,IAAI,oBAAoB,gBAAgB,iBAAiB,EAAE,IACzD,QAAQ,yBAAyB,EAAE;AAAA,MACrC,OAAO;AAAA,QACS,OAAO,sBAArB,YACI,oBACA,YAAY,iBAAiB;AAAA,QACjC;AAAA,MACF;AAAA;AAAA,IAEF,sBAAsB;AAAA,IACtB,OAAO;AAAA,IACP;AAAA,IACA,cAAc;AAAA,IACd,gBAAgB;AAAA,IAChB,eAAe,QAAS,CAAC,aAAa,SAAS;AAAA,MAC7C,IAAI,OAAO,yBAAyB;AAAA,MACpC,IAAa,gBAAT;AAAA,QACF,OAAO,qBAAqB,MAAM,aAAa,aAAa,OAAO;AAAA,MACrE,KAAK,YAAY;AAAA,MACjB,OAAO,CAAC,aAAa,KAAK,MAAM,QAAQ;AAAA;AAAA,IAE1C;AAAA,IACA,iBAAiB;AAAA,EACnB;AAAA,EACA,0BAA0B,iBAAiB;AAAA,EAiBvC,wBAAwB;AAAA,IAC1B,iBAAiB,QAAS,CAAC,MAAM,SAAS,UAAU;AAAA,MAClD,OAAO,KAAK;AAAA,MACZ,IAAI,OAAO,kBAAkB,GAC3B,SAAS,aAAa,IAAI;AAAA,MAC5B,OAAO,UAAU;AAAA,MACN,aAAN,aAA2B,aAAT,SAAsB,OAAO,WAAW;AAAA,MAC/D,UAAU,cAAc,MAAM,QAAQ,IAAI;AAAA,MACjC,YAAT,SACG,sBAAsB,SAAS,MAAM,IAAI,GAC1C,oBAAoB,SAAS,MAAM,IAAI;AAAA;AAAA,IAE3C,qBAAqB,QAAS,CAAC,MAAM,SAAS,UAAU;AAAA,MACtD,OAAO,KAAK;AAAA,MACZ,IAAI,OAAO,kBAAkB,GAC3B,SAAS,aAAa,IAAI;AAAA,MAC5B,OAAO,MAAM;AAAA,MACb,OAAO,UAAU;AAAA,MACN,aAAN,aAA2B,aAAT,SAAsB,OAAO,WAAW;AAAA,MAC/D,UAAU,cAAc,MAAM,QAAQ,IAAI;AAAA,MACjC,YAAT,SACG,sBAAsB,SAAS,MAAM,IAAI,GAC1C,oBAAoB,SAAS,MAAM,IAAI;AAAA;AAAA,IAE3C,oBAAoB,QAAS,CAAC,MAAM,UAAU;AAAA,MAC5C,OAAO,KAAK;AAAA,MACZ,IAAI,OAAO,kBAAkB,GAC3B,SAAS,aAAa,IAAI;AAAA,MAC5B,OAAO,MAAM;AAAA,MACF,aAAN,aAA2B,aAAT,SAAsB,OAAO,WAAW;AAAA,MAC/D,WAAW,cAAc,MAAM,QAAQ,IAAI;AAAA,MAClC,aAAT,SACG,sBAAsB,UAAU,MAAM,IAAI,GAC3C,oBAAoB,UAAU,MAAM,IAAI;AAAA;AAAA,EAE9C;AAAA,EA+QI,8BAA8B,MAAM,wBAAuB,GAAG,CAAC;AAAA,EA+rB/D,mBAAmB;AAAA,IACrB,YAAY;AAAA,IACZ,aAAa;AAAA,IACb,WAAW;AAAA,IACX,iBAAiB;AAAA,EACnB;AAAA,EAm+DE,kBAAiC,OAAO,YAAtB,aAAgC,UAAU;AAAA,EAktD1D,yBAAyB;AAAA,IACzB,iBAAiB,QAAS,CAAC,cAAc;AAAA,MACvC,IAAI,QAAQ,YAAY,YAAY,GAClC,eAAe,MAAM,KAAK,IAAI,YAAY;AAAA,MACjC,iBAAN,cACD,eAAe,aAAa,GAC9B,MAAM,KAAK,IAAI,cAAc,YAAY;AAAA,MAC3C,OAAO;AAAA;AAAA,IAET,aAAa,QAAS,GAAG;AAAA,MACvB,OAAO,YAAY,YAAY,EAAE,WAAW;AAAA;AAAA,EAEhD;AAAA,EACA,kBAAiC,OAAO,YAAtB,aAAgC,UAAU;AAAA,EAqkD9D,KACM,uBAAuB,EAC3B,uBAAuB,wBAAwB,QAC/C,wBACA;AAAA,IACI,+BACA,wBAAwB,uBAC1B,kCACE,6BAA6B,YAAY,GAC3C,sCACE,6BAA6B,GAAG,YAAY,IAC5C,6BAA6B,MAAM,CAAC;AAAA,IACxC,oBACE,iCACA,OAAO,mCACT;AAAA,EACF;AAAA,EACA,oBAAoB,eAAe,gBAAgB;AAAA,EACnD,oBAAoB,qBAAqB,sBAAsB;AAAA,EAC/D,oBAAoB,iBAAiB,kBAAkB;AAAA,EACvD,oBAAoB,YAAY,eAAe;AAAA,EAC/C,oBAAoB,WAAW,SAAS;AAAA,EACxC,oBAAoB,YAAY,QAAQ;AAAA,EACxC,oBAAoB,gBAAgB,iBAAiB;AAAA,EACrD,oBAAoB,kBAAkB,mBAAmB;AAAA,EACzD,oBAAoB,mBAAmB,oBAAoB;AAAA,EAC3D,oBAAoB,gBAAgB,iBAAiB;AAAA,EACrD,oBAAoB,gBAAgB,CAAC,YAAY,WAAW,CAAC;AAAA,EAC7D,oBAAoB,gBAAgB,CAAC,YAAY,WAAW,CAAC;AAAA,EAC7D,oBAAoB,kBAAkB,CAAC,cAAc,aAAa,CAAC;AAAA,EACnE,oBAAoB,kBAAkB,CAAC,cAAc,aAAa,CAAC;AAAA,EACnE,sBACE,YACA,oEAAoE,MAAM,GAAG,CAC/E;AAAA,EACA,sBACE,YACA,uFAAuF,MACrF,GACF,CACF;AAAA,EACA,sBAAsB,iBAAiB;AAAA,IACrC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAAA,EACD,sBACE,oBACA,2DAA2D,MAAM,GAAG,CACtE;AAAA,EACA,sBACE,sBACA,6DAA6D,MAAM,GAAG,CACxE;AAAA,EACA,sBACE,uBACA,8DAA8D,MAAM,GAAG,CACzE;AAAA,EACI,kBACA,6NAA6N,MAC3N,GACF;AAAA,EACF,qBAAqB,IAAI,IACvB,iEACG,MAAM,GAAG,EACT,OAAO,eAAe,CAC3B;AAAA,EA4EE,kBAAkB,oBAAoB,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,CAAC;AAAA,EAulBxE,2BAA2B;AAAA,EAC7B,uCAAuC;AAAA,EAijCrC,kBAAiC,OAAO,eAAtB,aAAmC,aAAkB;AAAA,EACzE,gBAA+B,OAAO,iBAAtB,aAAqC,eAAoB;AAAA,EACzE,eAA8B,OAAO,YAAtB,aAAgC,UAAe;AAAA,EAC9D,oBACiB,OAAO,mBAAtB,aACI,iBACgB,OAAO,iBAAvB,cACE,QAAS,CAAC,UAAU;AAAA,IAClB,OAAO,aACJ,QAAQ,IAAI,EACZ,KAAK,QAAQ,EACb,MAAM,qBAAqB;AAAA,MAEhC;AAAA,EAiTN,kBAAkB,IAAI;AAAA,EACxB,iBAAiB,IAAI;AAAA,EAQnB,qBAAqB,wBAAwB;AAAA,EACjD,wBAAwB,IAAI;AAAA,IAC1B,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AAAA,EAYI,iBAAiC,OAAO,aAAvB,cAAkC,OAAO;AAAA,EA0uB1D,wBAAwB;AAAA,IAC1B,UAAU;AAAA,IACV,UAAU;AAAA,IACV,UAAU;AAAA,IACV,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB,cAAc;AAAA,EAChB;AAAA,EAqYE,iBAAiB,IAAI;AAAA,EACrB,wBAAwB,IAAI;AAAA,EAC5B,iCAAiC,CAAC;AAAA,EAClC,2BACE,sPAAsP,MACpP,GACF;AAAA,EA0WJ,sBAAsB,UAAU,SAAS,aAAa,UAAU,SAC9D,QAAS,CAAC,UAAU;AAAA,IAClB,IAAI,QAAO,KAAK;AAAA,IAChB,IAAa,UAAT;AAAA,MAAe,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,IAC1D,IAAI,UAAU,MAAK,SACjB,OAAO,kBAAkB;AAAA,IAC3B,oBAAoB,SAAS,MAAM,UAAU,OAAM,MAAM,IAAI;AAAA;AAAA,EAEjE,sBAAsB,UAAU,UAAU,aAAa,UAAU,UAC/D,QAAS,GAAG;AAAA,IACV,IAAI,QAAO,KAAK;AAAA,IAChB,IAAa,UAAT,MAAe;AAAA,MACjB,KAAK,gBAAgB;AAAA,MACrB,IAAI,YAAY,MAAK;AAAA,MACrB,oBAAoB,MAAK,SAAS,GAAG,MAAM,OAAM,MAAM,IAAI;AAAA,MAC3D,gBAAgB;AAAA,MAChB,UAAU,gCAAgC;AAAA,IAC5C;AAAA;AAAA,EAKJ,sBAAsB,UAAU,6BAA6B,QAAS,CAAC,QAAQ;AAAA,IAC7E,IAAI,QAAQ;AAAA,MACV,IAAI,iBAAiB,sBAAsB;AAAA,MAC3C,SAAS,EAAE,WAAW,MAAM,QAAgB,UAAU,eAAe;AAAA,MACrE,SACM,IAAI,EACR,IAAI,+BAA+B,UAC7B,mBAAN,KACA,iBAAiB,+BAA+B,GAAG,UACnD;AAAA;AAAA,MAEF,+BAA+B,OAAO,GAAG,GAAG,MAAM;AAAA,MAC5C,MAAN,KAAW,+BAA+B,MAAM;AAAA,IAClD;AAAA;AAAA,EAEE,mDAAyD;AAAA,EAC7D,IAEE,qDADA;AAAA,IAGA,MAAM,MACJ,wBACE,KACA,kDACA,QACF,CACF;AAAA,EACF,wBAAwB,cAAc,QAAS,CAAC,oBAAoB;AAAA,IAClE,IAAI,QAAQ,mBAAmB;AAAA,IAC/B,IAAe,UAAN,WAAa;AAAA,MACpB,IAAmB,OAAO,mBAAmB,WAAzC;AAAA,QACF,MAAM,MAAM,wBAAuB,GAAG,CAAC;AAAA,MACzC,qBAAqB,OAAO,KAAK,kBAAkB,EAAE,KAAK,GAAG;AAAA,MAC7D,MAAM,MAAM,wBAAuB,KAAK,kBAAkB,CAAC;AAAA,IAC7D;AAAA,IACA,qBAAqB,8BAA8B,KAAK;AAAA,IACxD,qBACW,uBAAT,OACI,yBAAyB,kBAAkB,IAC3C;AAAA,IACN,qBACW,uBAAT,OAA8B,OAAO,mBAAmB;AAAA,IAC1D,OAAO;AAAA;AAAA,EAEL,+BAA+B;AAAA,IACjC,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,qBAAqB;AAAA,IACrB,sBAAsB;AAAA,IACtB,mBAAmB;AAAA,EACrB;AAAA,EACA,IAAoB,OAAO,mCAAvB,aAAuD;AAAA,IACrD,0BAA0B;AAAA,IAC9B,IACE,CAAC,wBAAwB,cACzB,wBAAwB;AAAA,MAExB,IAAI;AAAA,QACD,aAAa,wBAAwB,OACpC,4BACF,GACG,eAAe;AAAA,QAClB,OAAO,KAAK;AAAA,EAClB;AAAA;;;;EC1jf2B;AAAA,EAhC3B,SAAS,QAAQ,GAAG;AAAA,IAElB,IACE,OAAO,mCAAmC,eAC1C,OAAO,+BAA+B,aAAa,YACnD;AAAA,MACA;AAAA,IACF;AAAA,IACA,IAAI,OAAuC,CAS3C;AAAA,IACA,IAAI;AAAA,MAEF,+BAA+B,SAAS,QAAQ;AAAA,MAChD,OAAO,KAAK;AAAA,MAGZ,QAAQ,MAAM,GAAG;AAAA;AAAA;AAAA,EAIrB,IAAI,MAAuC;AAAA,IAGzC,SAAS;AAAA,IACT,OAAO,UAAkB;AAAA,EAC3B;AAAA;;;;EC/BA,OAAO,UAAU,QAAS,GAAG;AAAA,IAC3B,OAAO,OAAO,YAAY,cAAc,QAAQ,aAAa,QAAQ,UAAU;AAAA;AAAA;;;;ECLjF,IAAI;AAAA,EACJ,IAAM,kBAAkB;AAAA,IACtB;AAAA,IACA;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAC1C;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IAC7C;AAAA,IAAM;AAAA,IAAM;AAAA,IAAM;AAAA,IAAM;AAAA,IAAM;AAAA,IAAM;AAAA,IAAM;AAAA,IAAM;AAAA,IAAM;AAAA,IACtD;AAAA,IAAM;AAAA,IAAM;AAAA,IAAM;AAAA,IAAM;AAAA,IAAM;AAAA,IAAM;AAAA,IAAM;AAAA,IAAM;AAAA,IAAM;AAAA,EACxD;AAAA,EAQQ,wBAAgB,SAAS,aAAc,CAAC,UAAS;AAAA,IACvD,IAAI,CAAC;AAAA,MAAS,MAAM,IAAI,MAAM,uCAAuC;AAAA,IACrE,IAAI,WAAU,KAAK,WAAU;AAAA,MAAI,MAAM,IAAI,MAAM,2CAA2C;AAAA,IAC5F,OAAO,WAAU,IAAI;AAAA;AAAA,EASf,kCAA0B,SAAS,uBAAwB,CAAC,UAAS;AAAA,IAC3E,OAAO,gBAAgB;AAAA;AAAA,EASjB,sBAAc,QAAS,CAAC,MAAM;AAAA,IACpC,IAAI,QAAQ;AAAA,IAEZ,OAAO,SAAS,GAAG;AAAA,MACjB;AAAA,MACA,UAAU;AAAA,IACZ;AAAA,IAEA,OAAO;AAAA;AAAA,EAGD,4BAAoB,SAAS,iBAAkB,CAAC,GAAG;AAAA,IACzD,IAAI,OAAO,MAAM,YAAY;AAAA,MAC3B,MAAM,IAAI,MAAM,uCAAuC;AAAA,IACzD;AAAA,IAEA,iBAAiB;AAAA;AAAA,EAGX,6BAAqB,QAAS,GAAG;AAAA,IACvC,OAAO,OAAO,mBAAmB;AAAA;AAAA,EAG3B,iBAAS,SAAS,MAAO,CAAC,OAAO;AAAA,IACvC,OAAO,eAAe,KAAK;AAAA;AAAA;;;;EC7DrB,YAAI,EAAE,KAAK,EAAE;AAAA,EACb,YAAI,EAAE,KAAK,EAAE;AAAA,EACb,YAAI,EAAE,KAAK,EAAE;AAAA,EACb,YAAI,EAAE,KAAK,EAAE;AAAA,EAErB,SAAS,UAAW,CAAC,QAAQ;AAAA,IAC3B,IAAI,OAAO,WAAW,UAAU;AAAA,MAC9B,MAAM,IAAI,MAAM,uBAAuB;AAAA,IACzC;AAAA,IAEA,MAAM,QAAQ,OAAO,YAAY;AAAA,IAEjC,QAAQ;AAAA,WACD;AAAA,WACA;AAAA,QACH,OAAe;AAAA,WAEZ;AAAA,WACA;AAAA,QACH,OAAe;AAAA,WAEZ;AAAA,WACA;AAAA,QACH,OAAe;AAAA,WAEZ;AAAA,WACA;AAAA,QACH,OAAe;AAAA;AAAA,QAGf,MAAM,IAAI,MAAM,uBAAuB,MAAM;AAAA;AAAA;AAAA,EAI3C,kBAAU,SAAS,OAAQ,CAAC,OAAO;AAAA,IACzC,OAAO,SAAS,OAAO,MAAM,QAAQ,eACnC,MAAM,OAAO,KAAK,MAAM,MAAM;AAAA;AAAA,EAG1B,eAAO,SAAS,IAAK,CAAC,OAAO,cAAc;AAAA,IACjD,IAAY,gBAAQ,KAAK,GAAG;AAAA,MAC1B,OAAO;AAAA,IACT;AAAA,IAEA,IAAI;AAAA,MACF,OAAO,WAAW,KAAK;AAAA,MACvB,OAAO,GAAG;AAAA,MACV,OAAO;AAAA;AAAA;AAAA;;;;EC/CX,SAAS,SAAU,GAAG;AAAA,IACpB,KAAK,SAAS,CAAC;AAAA,IACf,KAAK,SAAS;AAAA;AAAA,EAGhB,UAAU,YAAY;AAAA,IAEpB,KAAK,QAAS,CAAC,QAAO;AAAA,MACpB,MAAM,WAAW,KAAK,MAAM,SAAQ,CAAC;AAAA,MACrC,QAAS,KAAK,OAAO,cAAe,IAAI,SAAQ,IAAM,OAAO;AAAA;AAAA,IAG/D,KAAK,QAAS,CAAC,KAAK,QAAQ;AAAA,MAC1B,SAAS,IAAI,EAAG,IAAI,QAAQ,KAAK;AAAA,QAC/B,KAAK,QAAS,QAAS,SAAS,IAAI,IAAM,OAAO,CAAC;AAAA,MACpD;AAAA;AAAA,IAGF,iBAAiB,QAAS,GAAG;AAAA,MAC3B,OAAO,KAAK;AAAA;AAAA,IAGd,QAAQ,QAAS,CAAC,KAAK;AAAA,MACrB,MAAM,WAAW,KAAK,MAAM,KAAK,SAAS,CAAC;AAAA,MAC3C,IAAI,KAAK,OAAO,UAAU,UAAU;AAAA,QAClC,KAAK,OAAO,KAAK,CAAC;AAAA,MACpB;AAAA,MAEA,IAAI,KAAK;AAAA,QACP,KAAK,OAAO,aAAc,QAAU,KAAK,SAAS;AAAA,MACpD;AAAA,MAEA,KAAK;AAAA;AAAA,EAET;AAAA,EAEA,OAAO,UAAU;AAAA;;;;EC/BjB,SAAS,SAAU,CAAC,MAAM;AAAA,IACxB,IAAI,CAAC,QAAQ,OAAO,GAAG;AAAA,MACrB,MAAM,IAAI,MAAM,mDAAmD;AAAA,IACrE;AAAA,IAEA,KAAK,OAAO;AAAA,IACZ,KAAK,OAAO,IAAI,WAAW,OAAO,IAAI;AAAA,IACtC,KAAK,cAAc,IAAI,WAAW,OAAO,IAAI;AAAA;AAAA,EAY/C,UAAU,UAAU,MAAM,QAAS,CAAC,KAAK,KAAK,OAAO,UAAU;AAAA,IAC7D,MAAM,SAAQ,MAAM,KAAK,OAAO;AAAA,IAChC,KAAK,KAAK,UAAS;AAAA,IACnB,IAAI;AAAA,MAAU,KAAK,YAAY,UAAS;AAAA;AAAA,EAU1C,UAAU,UAAU,MAAM,QAAS,CAAC,KAAK,KAAK;AAAA,IAC5C,OAAO,KAAK,KAAK,MAAM,KAAK,OAAO;AAAA;AAAA,EAWrC,UAAU,UAAU,MAAM,QAAS,CAAC,KAAK,KAAK,OAAO;AAAA,IACnD,KAAK,KAAK,MAAM,KAAK,OAAO,QAAQ;AAAA;AAAA,EAUtC,UAAU,UAAU,aAAa,QAAS,CAAC,KAAK,KAAK;AAAA,IACnD,OAAO,KAAK,YAAY,MAAM,KAAK,OAAO;AAAA;AAAA,EAG5C,OAAO,UAAU;AAAA;;;;ECtDjB,IAAM,gCAAmC;AAAA,EAgBjC,0BAAkB,SAAS,eAAgB,CAAC,UAAS;AAAA,IAC3D,IAAI,aAAY;AAAA,MAAG,OAAO,CAAC;AAAA,IAE3B,MAAM,WAAW,KAAK,MAAM,WAAU,CAAC,IAAI;AAAA,IAC3C,MAAM,OAAO,cAAc,QAAO;AAAA,IAClC,MAAM,YAAY,SAAS,MAAM,KAAK,KAAK,MAAM,OAAO,OAAO,IAAI,WAAW,EAAE,IAAI;AAAA,IACpF,MAAM,YAAY,CAAC,OAAO,CAAC;AAAA,IAE3B,SAAS,IAAI,EAAG,IAAI,WAAW,GAAG,KAAK;AAAA,MACrC,UAAU,KAAK,UAAU,IAAI,KAAK;AAAA,IACpC;AAAA,IAEA,UAAU,KAAK,CAAC;AAAA,IAEhB,OAAO,UAAU,QAAQ;AAAA;AAAA,EAuBnB,uBAAe,SAAS,YAAa,CAAC,UAAS;AAAA,IACrD,MAAM,SAAS,CAAC;AAAA,IAChB,MAAM,MAAc,wBAAgB,QAAO;AAAA,IAC3C,MAAM,YAAY,IAAI;AAAA,IAEtB,SAAS,IAAI,EAAG,IAAI,WAAW,KAAK;AAAA,MAClC,SAAS,IAAI,EAAG,IAAI,WAAW,KAAK;AAAA,QAElC,IAAK,MAAM,KAAK,MAAM,KACjB,MAAM,KAAK,MAAM,YAAY,KAC7B,MAAM,YAAY,KAAK,MAAM,GAAI;AAAA,UACpC;AAAA,QACF;AAAA,QAEA,OAAO,KAAK,CAAC,IAAI,IAAI,IAAI,EAAE,CAAC;AAAA,MAC9B;AAAA,IACF;AAAA,IAEA,OAAO;AAAA;AAAA;;;;ECjFT,IAAM,gCAAmC;AAAA,EACzC,IAAM,sBAAsB;AAAA,EASpB,uBAAe,SAAS,YAAa,CAAC,UAAS;AAAA,IACrD,MAAM,OAAO,cAAc,QAAO;AAAA,IAElC,OAAO;AAAA,MAEL,CAAC,GAAG,CAAC;AAAA,MAEL,CAAC,OAAO,qBAAqB,CAAC;AAAA,MAE9B,CAAC,GAAG,OAAO,mBAAmB;AAAA,IAChC;AAAA;AAAA;;;;EChBM,mBAAW;AAAA,IACjB,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,YAAY;AAAA,IACZ,YAAY;AAAA,EACd;AAAA,EAMA,IAAM,gBAAgB;AAAA,IACpB,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,EACN;AAAA,EAQQ,kBAAU,SAAS,OAAQ,CAAC,MAAM;AAAA,IACxC,OAAO,QAAQ,QAAQ,SAAS,MAAM,CAAC,MAAM,IAAI,KAAK,QAAQ,KAAK,QAAQ;AAAA;AAAA,EAUrE,eAAO,SAAS,IAAK,CAAC,OAAO;AAAA,IACnC,OAAe,gBAAQ,KAAK,IAAI,SAAS,OAAO,EAAE,IAAI;AAAA;AAAA,EAUhD,uBAAe,SAAS,YAAa,CAAC,MAAM;AAAA,IAClD,MAAM,OAAO,KAAK;AAAA,IAClB,IAAI,SAAS;AAAA,IACb,IAAI,eAAe;AAAA,IACnB,IAAI,eAAe;AAAA,IACnB,IAAI,UAAU;AAAA,IACd,IAAI,UAAU;AAAA,IAEd,SAAS,MAAM,EAAG,MAAM,MAAM,OAAO;AAAA,MACnC,eAAe,eAAe;AAAA,MAC9B,UAAU,UAAU;AAAA,MAEpB,SAAS,MAAM,EAAG,MAAM,MAAM,OAAO;AAAA,QACnC,IAAI,UAAS,KAAK,IAAI,KAAK,GAAG;AAAA,QAC9B,IAAI,YAAW,SAAS;AAAA,UACtB;AAAA,QACF,EAAO;AAAA,UACL,IAAI,gBAAgB;AAAA,YAAG,UAAU,cAAc,MAAM,eAAe;AAAA,UACpE,UAAU;AAAA,UACV,eAAe;AAAA;AAAA,QAGjB,UAAS,KAAK,IAAI,KAAK,GAAG;AAAA,QAC1B,IAAI,YAAW,SAAS;AAAA,UACtB;AAAA,QACF,EAAO;AAAA,UACL,IAAI,gBAAgB;AAAA,YAAG,UAAU,cAAc,MAAM,eAAe;AAAA,UACpE,UAAU;AAAA,UACV,eAAe;AAAA;AAAA,MAEnB;AAAA,MAEA,IAAI,gBAAgB;AAAA,QAAG,UAAU,cAAc,MAAM,eAAe;AAAA,MACpE,IAAI,gBAAgB;AAAA,QAAG,UAAU,cAAc,MAAM,eAAe;AAAA,IACtE;AAAA,IAEA,OAAO;AAAA;AAAA,EAQD,uBAAe,SAAS,YAAa,CAAC,MAAM;AAAA,IAClD,MAAM,OAAO,KAAK;AAAA,IAClB,IAAI,SAAS;AAAA,IAEb,SAAS,MAAM,EAAG,MAAM,OAAO,GAAG,OAAO;AAAA,MACvC,SAAS,MAAM,EAAG,MAAM,OAAO,GAAG,OAAO;AAAA,QACvC,MAAM,OAAO,KAAK,IAAI,KAAK,GAAG,IAC5B,KAAK,IAAI,KAAK,MAAM,CAAC,IACrB,KAAK,IAAI,MAAM,GAAG,GAAG,IACrB,KAAK,IAAI,MAAM,GAAG,MAAM,CAAC;AAAA,QAE3B,IAAI,SAAS,KAAK,SAAS;AAAA,UAAG;AAAA,MAChC;AAAA,IACF;AAAA,IAEA,OAAO,SAAS,cAAc;AAAA;AAAA,EASxB,uBAAe,SAAS,YAAa,CAAC,MAAM;AAAA,IAClD,MAAM,OAAO,KAAK;AAAA,IAClB,IAAI,SAAS;AAAA,IACb,IAAI,UAAU;AAAA,IACd,IAAI,UAAU;AAAA,IAEd,SAAS,MAAM,EAAG,MAAM,MAAM,OAAO;AAAA,MACnC,UAAU,UAAU;AAAA,MACpB,SAAS,MAAM,EAAG,MAAM,MAAM,OAAO;AAAA,QACnC,UAAY,WAAW,IAAK,OAAS,KAAK,IAAI,KAAK,GAAG;AAAA,QACtD,IAAI,OAAO,OAAO,YAAY,QAAS,YAAY;AAAA,UAAQ;AAAA,QAE3D,UAAY,WAAW,IAAK,OAAS,KAAK,IAAI,KAAK,GAAG;AAAA,QACtD,IAAI,OAAO,OAAO,YAAY,QAAS,YAAY;AAAA,UAAQ;AAAA,MAC7D;AAAA,IACF;AAAA,IAEA,OAAO,SAAS,cAAc;AAAA;AAAA,EAWxB,uBAAe,SAAS,YAAa,CAAC,MAAM;AAAA,IAClD,IAAI,YAAY;AAAA,IAChB,MAAM,eAAe,KAAK,KAAK;AAAA,IAE/B,SAAS,IAAI,EAAG,IAAI,cAAc;AAAA,MAAK,aAAa,KAAK,KAAK;AAAA,IAE9D,MAAM,IAAI,KAAK,IAAI,KAAK,KAAM,YAAY,MAAM,eAAgB,CAAC,IAAI,EAAE;AAAA,IAEvE,OAAO,IAAI,cAAc;AAAA;AAAA,EAW3B,SAAS,SAAU,CAAC,aAAa,GAAG,GAAG;AAAA,IACrC,QAAQ;AAAA,WACO,iBAAS;AAAA,QAAY,QAAQ,IAAI,KAAK,MAAM;AAAA,WAC5C,iBAAS;AAAA,QAAY,OAAO,IAAI,MAAM;AAAA,WACtC,iBAAS;AAAA,QAAY,OAAO,IAAI,MAAM;AAAA,WACtC,iBAAS;AAAA,QAAY,QAAQ,IAAI,KAAK,MAAM;AAAA,WAC5C,iBAAS;AAAA,QAAY,QAAQ,KAAK,MAAM,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,KAAK,MAAM;AAAA,WAC5E,iBAAS;AAAA,QAAY,OAAQ,IAAI,IAAK,IAAK,IAAI,IAAK,MAAM;AAAA,WAC1D,iBAAS;AAAA,QAAY,QAAS,IAAI,IAAK,IAAK,IAAI,IAAK,KAAK,MAAM;AAAA,WAChE,iBAAS;AAAA,QAAY,QAAS,IAAI,IAAK,KAAK,IAAI,KAAK,KAAK,MAAM;AAAA;AAAA,QAEpE,MAAM,IAAI,MAAM,qBAAqB,WAAW;AAAA;AAAA;AAAA,EAUrD,oBAAY,SAAS,SAAU,CAAC,SAAS,MAAM;AAAA,IACrD,MAAM,OAAO,KAAK;AAAA,IAElB,SAAS,MAAM,EAAG,MAAM,MAAM,OAAO;AAAA,MACnC,SAAS,MAAM,EAAG,MAAM,MAAM,OAAO;AAAA,QACnC,IAAI,KAAK,WAAW,KAAK,GAAG;AAAA,UAAG;AAAA,QAC/B,KAAK,IAAI,KAAK,KAAK,UAAU,SAAS,KAAK,GAAG,CAAC;AAAA,MACjD;AAAA,IACF;AAAA;AAAA,EASM,sBAAc,SAAS,WAAY,CAAC,MAAM,iBAAiB;AAAA,IACjE,MAAM,cAAc,OAAO,KAAa,gBAAQ,EAAE;AAAA,IAClD,IAAI,cAAc;AAAA,IAClB,IAAI,eAAe;AAAA,IAEnB,SAAS,IAAI,EAAG,IAAI,aAAa,KAAK;AAAA,MACpC,gBAAgB,CAAC;AAAA,MACT,kBAAU,GAAG,IAAI;AAAA,MAGzB,MAAM,UACI,qBAAa,IAAI,IACjB,qBAAa,IAAI,IACjB,qBAAa,IAAI,IACjB,qBAAa,IAAI;AAAA,MAGnB,kBAAU,GAAG,IAAI;AAAA,MAEzB,IAAI,UAAU,cAAc;AAAA,QAC1B,eAAe;AAAA,QACf,cAAc;AAAA,MAChB;AAAA,IACF;AAAA,IAEA,OAAO;AAAA;AAAA;;;;ECxOT,IAAM;AAAA,EAEN,IAAM,kBAAkB;AAAA,IAEtB;AAAA,IAAG;AAAA,IAAG;AAAA,IAAG;AAAA,IACT;AAAA,IAAG;AAAA,IAAG;AAAA,IAAG;AAAA,IACT;AAAA,IAAG;AAAA,IAAG;AAAA,IAAG;AAAA,IACT;AAAA,IAAG;AAAA,IAAG;AAAA,IAAG;AAAA,IACT;AAAA,IAAG;AAAA,IAAG;AAAA,IAAG;AAAA,IACT;AAAA,IAAG;AAAA,IAAG;AAAA,IAAG;AAAA,IACT;AAAA,IAAG;AAAA,IAAG;AAAA,IAAG;AAAA,IACT;AAAA,IAAG;AAAA,IAAG;AAAA,IAAG;AAAA,IACT;AAAA,IAAG;AAAA,IAAG;AAAA,IAAG;AAAA,IACT;AAAA,IAAG;AAAA,IAAG;AAAA,IAAG;AAAA,IACT;AAAA,IAAG;AAAA,IAAG;AAAA,IAAG;AAAA,IACT;AAAA,IAAG;AAAA,IAAG;AAAA,IAAI;AAAA,IACV;AAAA,IAAG;AAAA,IAAG;AAAA,IAAI;AAAA,IACV;AAAA,IAAG;AAAA,IAAG;AAAA,IAAI;AAAA,IACV;AAAA,IAAG;AAAA,IAAI;AAAA,IAAI;AAAA,IACX;AAAA,IAAG;AAAA,IAAI;AAAA,IAAI;AAAA,IACX;AAAA,IAAG;AAAA,IAAI;AAAA,IAAI;AAAA,IACX;AAAA,IAAG;AAAA,IAAI;AAAA,IAAI;AAAA,IACX;AAAA,IAAG;AAAA,IAAI;AAAA,IAAI;AAAA,IACX;AAAA,IAAG;AAAA,IAAI;AAAA,IAAI;AAAA,IACX;AAAA,IAAG;AAAA,IAAI;AAAA,IAAI;AAAA,IACX;AAAA,IAAG;AAAA,IAAI;AAAA,IAAI;AAAA,IACX;AAAA,IAAG;AAAA,IAAI;AAAA,IAAI;AAAA,IACX;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IACZ;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IACZ;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IACZ;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IACZ;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IACZ;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IACZ;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IACZ;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IACZ;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IACZ;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IACZ;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IACZ;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IACZ;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IACZ;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IACZ;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IACZ;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IACZ;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,EACd;AAAA,EAEA,IAAM,qBAAqB;AAAA,IAEzB;AAAA,IAAG;AAAA,IAAI;AAAA,IAAI;AAAA,IACX;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IACZ;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IACZ;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IACZ;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IACZ;AAAA,IAAI;AAAA,IAAI;AAAA,IAAI;AAAA,IACZ;AAAA,IAAI;AAAA,IAAI;AAAA,IAAK;AAAA,IACb;AAAA,IAAI;AAAA,IAAI;AAAA,IAAK;AAAA,IACb;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IACd;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IACd;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IACd;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IACd;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAM;AAAA,IAChB;AAAA,IAAK;AAAA,IAAK;AAAA,IAAM;AAAA,IAChB;AAAA,IAAK;AAAA,IAAK;AAAA,IAAM;AAAA,IAChB;AAAA,IAAK;AAAA,IAAK;AAAA,IAAM;AAAA,IAChB;AAAA,IAAK;AAAA,IAAK;AAAA,IAAM;AAAA,IAChB;AAAA,IAAK;AAAA,IAAK;AAAA,IAAM;AAAA,IAChB;AAAA,IAAK;AAAA,IAAK;AAAA,IAAM;AAAA,IAChB;AAAA,IAAK;AAAA,IAAM;AAAA,IAAM;AAAA,IACjB;AAAA,IAAK;AAAA,IAAM;AAAA,IAAM;AAAA,IACjB;AAAA,IAAK;AAAA,IAAM;AAAA,IAAM;AAAA,IACjB;AAAA,IAAK;AAAA,IAAM;AAAA,IAAM;AAAA,IACjB;AAAA,IAAK;AAAA,IAAM;AAAA,IAAM;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", + "debugId": "018A608DD777E92F64756E2164756E21", + "names": [] +} \ No newline at end of file diff --git a/taskboard-electron/.bun/renderer/index.html b/taskboard-electron/.bun/renderer/index.html new file mode 100644 index 0000000..a40d4f2 --- /dev/null +++ b/taskboard-electron/.bun/renderer/index.html @@ -0,0 +1,11 @@ +<!doctype html> +<html> + <head> + <meta charset="UTF-8" /> + <title>AgentForge + + +
+ + + diff --git a/taskboard-electron/bun.lock b/taskboard-electron/bun.lock index 45df1fb..4cf40a9 100644 --- a/taskboard-electron/bun.lock +++ b/taskboard-electron/bun.lock @@ -20,14 +20,12 @@ "@electron-forge/maker-zip": "^7.11.1", "@electron-forge/plugin-auto-unpack-natives": "^7.11.1", "@electron-forge/plugin-fuses": "^7.11.1", - "@electron-forge/plugin-vite": "^7.11.1", "@electron/fuses": "^1.8.0", "@eslint/js": "^9.39.4", "@types/bun": "^1.3.14", "@types/node": "^25.9.3", "@types/react": "^19.2.17", "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^5.1.4", "electron": "40.2.1", "eslint": "^9.39.4", "eslint-config-prettier": "^10.1.8", @@ -37,7 +35,6 @@ "prettier": "^3.8.3", "typescript": "^6.0.3", "typescript-eslint": "^8.61.0", - "vite": "^7.3.1", }, }, }, @@ -58,8 +55,6 @@ "@babel/helper-module-transforms": ["@babel/helper-module-transforms@7.28.6", "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", { "dependencies": { "@babel/helper-module-imports": "^7.28.6", "@babel/helper-validator-identifier": "^7.28.5", "@babel/traverse": "^7.28.6" }, "peerDependencies": { "@babel/core": "^7.0.0" } }, "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA=="], - "@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.28.6", "https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", {}, "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug=="], - "@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], "@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.28.5", "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", {}, "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q=="], @@ -70,10 +65,6 @@ "@babel/parser": ["@babel/parser@7.29.0", "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.0.tgz", { "dependencies": { "@babel/types": "^7.29.0" }, "bin": { "parser": "bin/babel-parser.js" } }, "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww=="], - "@babel/plugin-transform-react-jsx-self": ["@babel/plugin-transform-react-jsx-self@7.27.1", "https://registry.npmmirror.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw=="], - - "@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.27.1", "https://registry.npmmirror.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw=="], - "@babel/template": ["@babel/template@7.28.6", "https://registry.npmmirror.com/@babel/template/-/template-7.28.6.tgz", { "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/parser": "^7.28.6", "@babel/types": "^7.28.6" } }, "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ=="], "@babel/traverse": ["@babel/traverse@7.29.0", "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.29.0.tgz", { "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", "@babel/helper-globals": "^7.28.0", "@babel/parser": "^7.29.0", "@babel/template": "^7.28.6", "@babel/types": "^7.29.0", "debug": "^4.3.1" } }, "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA=="], @@ -104,8 +95,6 @@ "@electron-forge/plugin-fuses": ["@electron-forge/plugin-fuses@7.11.1", "https://registry.npmmirror.com/@electron-forge/plugin-fuses/-/plugin-fuses-7.11.1.tgz", { "dependencies": { "@electron-forge/plugin-base": "7.11.1", "@electron-forge/shared-types": "7.11.1" }, "peerDependencies": { "@electron/fuses": "^1.0.0" } }, "sha512-Td517mHf+RjQAayFDM2kKb7NaGdRXrZfPbc7KOHlGbXthp5YTkFu2cCZGWokiqt1y1wsFaAodULhqBIg7vbbbw=="], - "@electron-forge/plugin-vite": ["@electron-forge/plugin-vite@7.11.1", "https://registry.npmmirror.com/@electron-forge/plugin-vite/-/plugin-vite-7.11.1.tgz", { "dependencies": { "@electron-forge/plugin-base": "7.11.1", "@electron-forge/shared-types": "7.11.1", "chalk": "^4.0.0", "debug": "^4.3.1", "fs-extra": "^10.0.0", "listr2": "^7.0.2" } }, "sha512-kc/WQs/0+9VC9Q4oSSocMa02YxKDvAYxhWtNcL+qlswZMJlxe8gX7vl/yXq9AjPQxw7f3jzf7nruUPKQ+vyLLg=="], - "@electron-forge/publisher-base": ["@electron-forge/publisher-base@7.11.1", "https://registry.npmmirror.com/@electron-forge/publisher-base/-/publisher-base-7.11.1.tgz", { "dependencies": { "@electron-forge/shared-types": "7.11.1" } }, "sha512-rXE9oMFGMtdQrixnumWYH5TTGsp99iPHZb3jI74YWq518ctCh6DlIgWlhf6ok2X0+lhWovcIb45KJucUFAQ13w=="], "@electron-forge/shared-types": ["@electron-forge/shared-types@7.11.1", "https://registry.npmmirror.com/@electron-forge/shared-types/-/shared-types-7.11.1.tgz", { "dependencies": { "@electron-forge/tracer": "7.11.1", "@electron/packager": "^18.3.5", "@electron/rebuild": "^3.7.0", "listr2": "^7.0.2" } }, "sha512-vvBWdAEh53UJlDGUevpaJk1+sqDMQibfrbHR+0IPA4MPyQex7/Uhv3vYH9oGHujBVAChQahjAuJt0fG6IJBLZg=="], @@ -142,58 +131,6 @@ "@electron/windows-sign": ["@electron/windows-sign@1.2.2", "https://registry.npmmirror.com/@electron/windows-sign/-/windows-sign-1.2.2.tgz", { "dependencies": { "cross-dirname": "^0.1.0", "debug": "^4.3.4", "fs-extra": "^11.1.1", "minimist": "^1.2.8", "postject": "^1.0.0-alpha.6" }, "bin": { "electron-windows-sign": "bin/electron-windows-sign.js" } }, "sha512-dfZeox66AvdPtb2lD8OsIIQh12Tp0GNCRUDfBHIKGpbmopZto2/A8nSpYYLoedPIHpqkeblZ/k8OV0Gy7PYuyQ=="], - "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.3", "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", { "os": "aix", "cpu": "ppc64" }, "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg=="], - - "@esbuild/android-arm": ["@esbuild/android-arm@0.27.3", "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.27.3.tgz", { "os": "android", "cpu": "arm" }, "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA=="], - - "@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.3", "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", { "os": "android", "cpu": "arm64" }, "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg=="], - - "@esbuild/android-x64": ["@esbuild/android-x64@0.27.3", "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.27.3.tgz", { "os": "android", "cpu": "x64" }, "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ=="], - - "@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.3", "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", { "os": "darwin", "cpu": "arm64" }, "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg=="], - - "@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.3", "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", { "os": "darwin", "cpu": "x64" }, "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg=="], - - "@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.3", "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", { "os": "freebsd", "cpu": "arm64" }, "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w=="], - - "@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.3", "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", { "os": "freebsd", "cpu": "x64" }, "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA=="], - - "@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.3", "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", { "os": "linux", "cpu": "arm" }, "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw=="], - - "@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.3", "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", { "os": "linux", "cpu": "arm64" }, "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg=="], - - "@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.3", "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", { "os": "linux", "cpu": "ia32" }, "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg=="], - - "@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.3", "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", { "os": "linux", "cpu": "none" }, "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA=="], - - "@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.3", "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", { "os": "linux", "cpu": "none" }, "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw=="], - - "@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.3", "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", { "os": "linux", "cpu": "ppc64" }, "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA=="], - - "@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.3", "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", { "os": "linux", "cpu": "none" }, "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ=="], - - "@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.3", "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", { "os": "linux", "cpu": "s390x" }, "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw=="], - - "@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.3", "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", { "os": "linux", "cpu": "x64" }, "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA=="], - - "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.3", "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", { "os": "none", "cpu": "arm64" }, "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA=="], - - "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.3", "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", { "os": "none", "cpu": "x64" }, "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA=="], - - "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.3", "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", { "os": "openbsd", "cpu": "arm64" }, "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw=="], - - "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.3", "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", { "os": "openbsd", "cpu": "x64" }, "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ=="], - - "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.3", "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", { "os": "none", "cpu": "arm64" }, "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g=="], - - "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.3", "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", { "os": "sunos", "cpu": "x64" }, "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA=="], - - "@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.3", "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", { "os": "win32", "cpu": "arm64" }, "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA=="], - - "@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.3", "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", { "os": "win32", "cpu": "ia32" }, "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q=="], - - "@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.3", "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", { "os": "win32", "cpu": "x64" }, "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA=="], - "@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.9.1", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ=="], "@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.2", "", {}, "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew=="], @@ -278,58 +215,6 @@ "@npmcli/move-file": ["@npmcli/move-file@2.0.1", "https://registry.npmmirror.com/@npmcli/move-file/-/move-file-2.0.1.tgz", { "dependencies": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" } }, "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ=="], - "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-rc.3", "https://registry.npmmirror.com/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", {}, "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q=="], - - "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", { "os": "android", "cpu": "arm" }, "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg=="], - - "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", { "os": "android", "cpu": "arm64" }, "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q=="], - - "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", { "os": "darwin", "cpu": "arm64" }, "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg=="], - - "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", { "os": "darwin", "cpu": "x64" }, "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w=="], - - "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", { "os": "freebsd", "cpu": "arm64" }, "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA=="], - - "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", { "os": "freebsd", "cpu": "x64" }, "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg=="], - - "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", { "os": "linux", "cpu": "arm" }, "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw=="], - - "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", { "os": "linux", "cpu": "arm" }, "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA=="], - - "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", { "os": "linux", "cpu": "arm64" }, "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA=="], - - "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", { "os": "linux", "cpu": "arm64" }, "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA=="], - - "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", { "os": "linux", "cpu": "none" }, "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg=="], - - "@rollup/rollup-linux-loong64-musl": ["@rollup/rollup-linux-loong64-musl@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", { "os": "linux", "cpu": "none" }, "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q=="], - - "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", { "os": "linux", "cpu": "ppc64" }, "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA=="], - - "@rollup/rollup-linux-ppc64-musl": ["@rollup/rollup-linux-ppc64-musl@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", { "os": "linux", "cpu": "ppc64" }, "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA=="], - - "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", { "os": "linux", "cpu": "none" }, "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg=="], - - "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", { "os": "linux", "cpu": "none" }, "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg=="], - - "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", { "os": "linux", "cpu": "s390x" }, "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w=="], - - "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", { "os": "linux", "cpu": "x64" }, "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg=="], - - "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", { "os": "linux", "cpu": "x64" }, "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg=="], - - "@rollup/rollup-openbsd-x64": ["@rollup/rollup-openbsd-x64@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", { "os": "openbsd", "cpu": "x64" }, "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ=="], - - "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", { "os": "none", "cpu": "arm64" }, "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA=="], - - "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", { "os": "win32", "cpu": "arm64" }, "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A=="], - - "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", { "os": "win32", "cpu": "ia32" }, "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA=="], - - "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", { "os": "win32", "cpu": "x64" }, "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA=="], - - "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.59.0", "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", { "os": "win32", "cpu": "x64" }, "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA=="], - "@sindresorhus/is": ["@sindresorhus/is@4.6.0", "https://registry.npmmirror.com/@sindresorhus/is/-/is-4.6.0.tgz", {}, "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw=="], "@szmarczak/http-timer": ["@szmarczak/http-timer@4.0.6", "https://registry.npmmirror.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", { "dependencies": { "defer-to-connect": "^2.0.0" } }, "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w=="], @@ -338,14 +223,6 @@ "@types/appdmg": ["@types/appdmg@0.5.5", "https://registry.npmmirror.com/@types/appdmg/-/appdmg-0.5.5.tgz", { "dependencies": { "@types/node": "*" } }, "sha512-G+n6DgZTZFOteITE30LnWj+HRVIGr7wMlAiLWOO02uJFWVEitaPU9JVXm9wJokkgshBawb2O1OykdcsmkkZfgg=="], - "@types/babel__core": ["@types/babel__core@7.20.5", "https://registry.npmmirror.com/@types/babel__core/-/babel__core-7.20.5.tgz", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="], - - "@types/babel__generator": ["@types/babel__generator@7.27.0", "https://registry.npmmirror.com/@types/babel__generator/-/babel__generator-7.27.0.tgz", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="], - - "@types/babel__template": ["@types/babel__template@7.4.4", "https://registry.npmmirror.com/@types/babel__template/-/babel__template-7.4.4.tgz", { "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A=="], - - "@types/babel__traverse": ["@types/babel__traverse@7.28.0", "https://registry.npmmirror.com/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="], - "@types/bun": ["@types/bun@1.3.14", "", { "dependencies": { "bun-types": "1.3.14" } }, "sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw=="], "@types/cacheable-request": ["@types/cacheable-request@6.0.3", "https://registry.npmmirror.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", { "dependencies": { "@types/http-cache-semantics": "*", "@types/keyv": "^3.1.4", "@types/node": "*", "@types/responselike": "^1.0.0" } }, "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw=="], @@ -398,8 +275,6 @@ "@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.61.0", "", { "dependencies": { "@typescript-eslint/types": "8.61.0", "eslint-visitor-keys": "^5.0.0" } }, "sha512-QVLZu3ZPQEE+HICQyAMZ2yLQhxf0meY/wx6Hx14YcTNj13JB3qHlX3lJ02L3fLGHgERRH71kvYDwiXIguT3AjQ=="], - "@vitejs/plugin-react": ["@vitejs/plugin-react@5.1.4", "https://registry.npmmirror.com/@vitejs/plugin-react/-/plugin-react-5.1.4.tgz", { "dependencies": { "@babel/core": "^7.29.0", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-rc.3", "@types/babel__core": "^7.20.5", "react-refresh": "^0.18.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-VIcFLdRi/VYRU8OL/puL7QXMYafHmqOnwTZY50U1JPlCNj30PxCMx65c494b1K9be9hX83KVt0+gTEwTWLqToA=="], - "@vscode/sudo-prompt": ["@vscode/sudo-prompt@9.3.2", "https://registry.npmmirror.com/@vscode/sudo-prompt/-/sudo-prompt-9.3.2.tgz", {}, "sha512-gcXoCN00METUNFeQOFJ+C9xUI0DKB+0EGMVg7wbVYRHBw2Eq3fKisDZOkRdOz3kqXRKOENMfShPOmypw1/8nOw=="], "@webassemblyjs/ast": ["@webassemblyjs/ast@1.14.1", "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.14.1.tgz", { "dependencies": { "@webassemblyjs/helper-numbers": "1.13.2", "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ=="], @@ -678,8 +553,6 @@ "es6-error": ["es6-error@4.1.1", "https://registry.npmmirror.com/es6-error/-/es6-error-4.1.1.tgz", {}, "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg=="], - "esbuild": ["esbuild@0.27.3", "https://registry.npmmirror.com/esbuild/-/esbuild-0.27.3.tgz", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.3", "@esbuild/android-arm": "0.27.3", "@esbuild/android-arm64": "0.27.3", "@esbuild/android-x64": "0.27.3", "@esbuild/darwin-arm64": "0.27.3", "@esbuild/darwin-x64": "0.27.3", "@esbuild/freebsd-arm64": "0.27.3", "@esbuild/freebsd-x64": "0.27.3", "@esbuild/linux-arm": "0.27.3", "@esbuild/linux-arm64": "0.27.3", "@esbuild/linux-ia32": "0.27.3", "@esbuild/linux-loong64": "0.27.3", "@esbuild/linux-mips64el": "0.27.3", "@esbuild/linux-ppc64": "0.27.3", "@esbuild/linux-riscv64": "0.27.3", "@esbuild/linux-s390x": "0.27.3", "@esbuild/linux-x64": "0.27.3", "@esbuild/netbsd-arm64": "0.27.3", "@esbuild/netbsd-x64": "0.27.3", "@esbuild/openbsd-arm64": "0.27.3", "@esbuild/openbsd-x64": "0.27.3", "@esbuild/openharmony-arm64": "0.27.3", "@esbuild/sunos-x64": "0.27.3", "@esbuild/win32-arm64": "0.27.3", "@esbuild/win32-ia32": "0.27.3", "@esbuild/win32-x64": "0.27.3" }, "bin": "bin/esbuild" }, "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg=="], - "escalade": ["escalade@3.2.0", "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz", {}, "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA=="], "escape-string-regexp": ["escape-string-regexp@4.0.0", "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], @@ -764,8 +637,6 @@ "fs.realpath": ["fs.realpath@1.0.0", "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz", {}, "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="], - "fsevents": ["fsevents@2.3.3", "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], - "function-bind": ["function-bind@1.1.2", "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], "function.prototype.name": ["function.prototype.name@1.1.8", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "functions-have-names": "^1.2.3", "hasown": "^2.0.2", "is-callable": "^1.2.7" } }, "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q=="], @@ -1066,8 +937,6 @@ "nan": ["nan@2.25.0", "https://registry.npmmirror.com/nan/-/nan-2.25.0.tgz", {}, "sha512-0M90Ag7Xn5KMLLZ7zliPWP3rT90P6PN+IzVFS0VqmnPktBk3700xUVv8Ikm9EUaUE5SDWdp/BIxdENzVznpm1g=="], - "nanoid": ["nanoid@3.3.11", "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz", { "bin": "bin/nanoid.cjs" }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], - "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], "negotiator": ["negotiator@0.6.4", "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.4.tgz", {}, "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w=="], @@ -1170,8 +1039,6 @@ "possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="], - "postcss": ["postcss@8.5.8", "https://registry.npmmirror.com/postcss/-/postcss-8.5.8.tgz", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg=="], - "postject": ["postject@1.0.0-alpha.6", "https://registry.npmmirror.com/postject/-/postject-1.0.0-alpha.6.tgz", { "dependencies": { "commander": "^9.4.0" }, "bin": "dist/cli.js" }, "sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A=="], "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], @@ -1206,8 +1073,6 @@ "react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], - "react-refresh": ["react-refresh@0.18.0", "https://registry.npmmirror.com/react-refresh/-/react-refresh-0.18.0.tgz", {}, "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw=="], - "read-binary-file-arch": ["read-binary-file-arch@1.0.6", "https://registry.npmmirror.com/read-binary-file-arch/-/read-binary-file-arch-1.0.6.tgz", { "dependencies": { "debug": "^4.3.4" }, "bin": "cli.js" }, "sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg=="], "read-pkg": ["read-pkg@2.0.0", "https://registry.npmmirror.com/read-pkg/-/read-pkg-2.0.0.tgz", { "dependencies": { "load-json-file": "^2.0.0", "normalize-package-data": "^2.3.2", "path-type": "^2.0.0" } }, "sha512-eFIBOPW7FGjzBuk3hdXEuNSiTZS/xEMlH49HxMyzb0hyPfu4EhVjT2DH32K1hSSmVq4sebAWnZuuY5auISUTGA=="], @@ -1254,8 +1119,6 @@ "roarr": ["roarr@2.15.4", "https://registry.npmmirror.com/roarr/-/roarr-2.15.4.tgz", { "dependencies": { "boolean": "^3.0.1", "detect-node": "^2.0.4", "globalthis": "^1.0.1", "json-stringify-safe": "^5.0.1", "semver-compare": "^1.0.0", "sprintf-js": "^1.1.2" } }, "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A=="], - "rollup": ["rollup@4.59.0", "https://registry.npmmirror.com/rollup/-/rollup-4.59.0.tgz", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.59.0", "@rollup/rollup-android-arm64": "4.59.0", "@rollup/rollup-darwin-arm64": "4.59.0", "@rollup/rollup-darwin-x64": "4.59.0", "@rollup/rollup-freebsd-arm64": "4.59.0", "@rollup/rollup-freebsd-x64": "4.59.0", "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", "@rollup/rollup-linux-arm-musleabihf": "4.59.0", "@rollup/rollup-linux-arm64-gnu": "4.59.0", "@rollup/rollup-linux-arm64-musl": "4.59.0", "@rollup/rollup-linux-loong64-gnu": "4.59.0", "@rollup/rollup-linux-loong64-musl": "4.59.0", "@rollup/rollup-linux-ppc64-gnu": "4.59.0", "@rollup/rollup-linux-ppc64-musl": "4.59.0", "@rollup/rollup-linux-riscv64-gnu": "4.59.0", "@rollup/rollup-linux-riscv64-musl": "4.59.0", "@rollup/rollup-linux-s390x-gnu": "4.59.0", "@rollup/rollup-linux-x64-gnu": "4.59.0", "@rollup/rollup-linux-x64-musl": "4.59.0", "@rollup/rollup-openbsd-x64": "4.59.0", "@rollup/rollup-openharmony-arm64": "4.59.0", "@rollup/rollup-win32-arm64-msvc": "4.59.0", "@rollup/rollup-win32-ia32-msvc": "4.59.0", "@rollup/rollup-win32-x64-gnu": "4.59.0", "@rollup/rollup-win32-x64-msvc": "4.59.0", "fsevents": "~2.3.2" }, "bin": "dist/bin/rollup" }, "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg=="], - "run-parallel": ["run-parallel@1.2.0", "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], "safe-array-concat": ["safe-array-concat@1.1.4", "", { "dependencies": { "call-bind": "^1.0.9", "call-bound": "^1.0.4", "get-intrinsic": "^1.3.0", "has-symbols": "^1.1.0", "isarray": "^2.0.5" } }, "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg=="], @@ -1310,8 +1173,6 @@ "source-map": ["source-map@0.6.1", "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], - "source-map-js": ["source-map-js@1.2.1", "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="], - "source-map-support": ["source-map-support@0.5.21", "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz", { "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w=="], "spdx-correct": ["spdx-correct@3.2.0", "https://registry.npmmirror.com/spdx-correct/-/spdx-correct-3.2.0.tgz", { "dependencies": { "spdx-expression-parse": "^3.0.0", "spdx-license-ids": "^3.0.0" } }, "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA=="], @@ -1428,8 +1289,6 @@ "validate-npm-package-license": ["validate-npm-package-license@3.0.4", "https://registry.npmmirror.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", { "dependencies": { "spdx-correct": "^3.0.0", "spdx-expression-parse": "^3.0.0" } }, "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew=="], - "vite": ["vite@7.3.1", "https://registry.npmmirror.com/vite/-/vite-7.3.1.tgz", { "dependencies": { "esbuild": "^0.27.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "tsx", "yaml"], "bin": "bin/vite.js" }, "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA=="], - "watchpack": ["watchpack@2.5.1", "https://registry.npmmirror.com/watchpack/-/watchpack-2.5.1.tgz", { "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" } }, "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg=="], "wcwidth": ["wcwidth@1.0.1", "https://registry.npmmirror.com/wcwidth/-/wcwidth-1.0.1.tgz", { "dependencies": { "defaults": "^1.0.3" } }, "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg=="], @@ -1516,8 +1375,6 @@ "@eslint-community/eslint-utils/eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="], - "@eslint/eslintrc/ajv": ["ajv@6.15.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw=="], - "@eslint/eslintrc/globals": ["globals@14.0.0", "", {}, "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ=="], "@inquirer/checkbox/@inquirer/type": ["@inquirer/type@2.0.0", "https://registry.npmmirror.com/@inquirer/type/-/type-2.0.0.tgz", { "dependencies": { "mute-stream": "^1.0.0" } }, "sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag=="], @@ -1590,8 +1447,6 @@ "cacache/rimraf": ["rimraf@3.0.2", "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", { "dependencies": { "glob": "^7.1.3" }, "bin": "bin.js" }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="], - "cacheable-request/get-stream": ["get-stream@5.2.0", "https://registry.npmmirror.com/get-stream/-/get-stream-5.2.0.tgz", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="], - "cli-truncate/string-width": ["string-width@5.1.2", "https://registry.npmmirror.com/string-width/-/string-width-5.1.2.tgz", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], "cliui/strip-ansi": ["strip-ansi@6.0.1", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], @@ -1624,13 +1479,7 @@ "electron-winstaller/fs-extra": ["fs-extra@7.0.1", "https://registry.npmmirror.com/fs-extra/-/fs-extra-7.0.1.tgz", { "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", "universalify": "^0.1.0" } }, "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw=="], - "eslint-plugin-react/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], - - "eslint-scope/estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], - - "esquery/estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], - - "esrecurse/estraverse": ["estraverse@5.3.0", "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="], + "eslint-plugin-react/semver": ["semver@6.3.1", "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], "execa/cross-spawn": ["cross-spawn@6.0.6", "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-6.0.6.tgz", { "dependencies": { "nice-try": "^1.0.4", "path-key": "^2.0.1", "semver": "^5.5.0", "shebang-command": "^1.2.0", "which": "^1.2.9" } }, "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw=="], @@ -1650,8 +1499,6 @@ "log-update/ansi-escapes": ["ansi-escapes@5.0.0", "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-5.0.0.tgz", { "dependencies": { "type-fest": "^1.0.2" } }, "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA=="], - "log-update/wrap-ansi": ["wrap-ansi@8.1.0", "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz", { "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", "strip-ansi": "^7.0.1" } }, "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ=="], - "lru-cache/yallist": ["yallist@3.1.1", "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], "make-fetch-happen/lru-cache": ["lru-cache@7.18.3", "https://registry.npmmirror.com/lru-cache/-/lru-cache-7.18.3.tgz", {}, "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA=="], @@ -1672,9 +1519,7 @@ "minizlib/minipass": ["minipass@3.3.6", "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw=="], - "minizlib/yallist": ["yallist@4.0.0", "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], - - "node-exports-info/semver": ["semver@6.3.1", "", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], + "node-exports-info/semver": ["semver@6.3.1", "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", { "bin": "bin/semver.js" }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], "normalize-package-data/resolve": ["resolve@1.22.11", "https://registry.npmmirror.com/resolve/-/resolve-1.22.11.tgz", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": "bin/resolve" }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="], @@ -1694,8 +1539,6 @@ "rechoir/resolve": ["resolve@1.22.11", "https://registry.npmmirror.com/resolve/-/resolve-1.22.11.tgz", { "dependencies": { "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": "bin/resolve" }, "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ=="], - "restore-cursor/signal-exit": ["signal-exit@3.0.7", "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], - "schema-utils/ajv": ["ajv@8.18.0", "https://registry.npmmirror.com/ajv/-/ajv-8.18.0.tgz", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A=="], "slice-ansi/ansi-styles": ["ansi-styles@6.2.3", "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.3.tgz", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], @@ -1712,10 +1555,6 @@ "terser/commander": ["commander@2.20.3", "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], - "tinyglobby/fdir": ["fdir@6.5.0", "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", { "peerDependencies": { "picomatch": "^3 || ^4" } }, "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg=="], - - "tinyglobby/picomatch": ["picomatch@4.0.3", "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], - "tmp-promise/tmp": ["tmp@0.2.5", "https://registry.npmmirror.com/tmp/-/tmp-0.2.5.tgz", {}, "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow=="], "trim-repeated/escape-string-regexp": ["escape-string-regexp@1.0.5", "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", {}, "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg=="], @@ -1726,8 +1565,6 @@ "wrap-ansi/string-width": ["string-width@5.1.2", "https://registry.npmmirror.com/string-width/-/string-width-5.1.2.tgz", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], - "wrap-ansi/strip-ansi": ["strip-ansi@7.2.0", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.2.0.tgz", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], - "yargs/find-up": ["find-up@4.1.0", "", { "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" } }, "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw=="], "@electron/get/fs-extra/jsonfile": ["jsonfile@4.0.0", "https://registry.npmmirror.com/jsonfile/-/jsonfile-4.0.0.tgz", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], @@ -1738,22 +1575,16 @@ "@electron/rebuild/yargs/cliui": ["cliui@8.0.1", "https://registry.npmmirror.com/cliui/-/cliui-8.0.1.tgz", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ=="], - "@electron/rebuild/yargs/string-width": ["string-width@4.2.3", "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - "@electron/rebuild/yargs/y18n": ["y18n@5.0.8", "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], "@electron/rebuild/yargs/yargs-parser": ["yargs-parser@21.1.1", "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-21.1.1.tgz", {}, "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw=="], "@electron/universal/minimatch/brace-expansion": ["brace-expansion@2.0.2", "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.2.tgz", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], - "@eslint/eslintrc/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], - "@inquirer/core/@types/node/undici-types": ["undici-types@6.21.0", "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], "@inquirer/core/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "@inquirer/core/wrap-ansi/string-width": ["string-width@4.2.3", "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - "@types/appdmg/@types/node/undici-types": ["undici-types@6.21.0", "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], "@types/cacheable-request/@types/node/undici-types": ["undici-types@6.21.0", "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], @@ -1776,30 +1607,20 @@ "cacache/glob/minimatch": ["minimatch@5.1.9", "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.9.tgz", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw=="], - "cacache/minipass/yallist": ["yallist@4.0.0", "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], - "cacache/rimraf/glob": ["glob@7.2.3", "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", { "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], "cli-truncate/string-width/emoji-regex": ["emoji-regex@9.2.2", "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], - "cli-truncate/string-width/strip-ansi": ["strip-ansi@7.2.0", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.2.0.tgz", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], - "cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "cliui/wrap-ansi/string-width": ["string-width@4.2.3", "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - "electron-installer-debian/yargs/cliui": ["cliui@7.0.4", "https://registry.npmmirror.com/cliui/-/cliui-7.0.4.tgz", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ=="], - "electron-installer-debian/yargs/string-width": ["string-width@4.2.3", "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - "electron-installer-debian/yargs/y18n": ["y18n@5.0.8", "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], "electron-installer-debian/yargs/yargs-parser": ["yargs-parser@20.2.9", "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-20.2.9.tgz", {}, "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="], "electron-installer-redhat/yargs/cliui": ["cliui@7.0.4", "https://registry.npmmirror.com/cliui/-/cliui-7.0.4.tgz", { "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ=="], - "electron-installer-redhat/yargs/string-width": ["string-width@4.2.3", "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - "electron-installer-redhat/yargs/y18n": ["y18n@5.0.8", "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz", {}, "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="], "electron-installer-redhat/yargs/yargs-parser": ["yargs-parser@20.2.9", "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-20.2.9.tgz", {}, "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w=="], @@ -1824,32 +1645,12 @@ "execa/cross-spawn/which": ["which@1.3.1", "https://registry.npmmirror.com/which/-/which-1.3.1.tgz", { "dependencies": { "isexe": "^2.0.0" }, "bin": "bin/which" }, "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ=="], - "fs-minipass/minipass/yallist": ["yallist@4.0.0", "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], - "get-package-info/debug/ms": ["ms@2.0.0", "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", {}, "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="], "jest-worker/@types/node/undici-types": ["undici-types@6.21.0", "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], "log-update/ansi-escapes/type-fest": ["type-fest@1.4.0", "https://registry.npmmirror.com/type-fest/-/type-fest-1.4.0.tgz", {}, "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA=="], - "log-update/wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.3.tgz", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], - - "log-update/wrap-ansi/string-width": ["string-width@5.1.2", "https://registry.npmmirror.com/string-width/-/string-width-5.1.2.tgz", { "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", "strip-ansi": "^7.0.1" } }, "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA=="], - - "make-fetch-happen/minipass/yallist": ["yallist@4.0.0", "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], - - "minipass-collect/minipass/yallist": ["yallist@4.0.0", "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], - - "minipass-fetch/minipass/yallist": ["yallist@4.0.0", "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], - - "minipass-flush/minipass/yallist": ["yallist@4.0.0", "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], - - "minipass-pipeline/minipass/yallist": ["yallist@4.0.0", "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], - - "minipass-sized/minipass/yallist": ["yallist@4.0.0", "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], - - "minizlib/minipass/yallist": ["yallist@4.0.0", "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], - "ora/cli-cursor/restore-cursor": ["restore-cursor@3.1.0", "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-3.1.0.tgz", { "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" } }, "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA=="], "ora/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], @@ -1858,106 +1659,50 @@ "schema-utils/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], - "ssri/minipass/yallist": ["yallist@4.0.0", "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", {}, "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="], - "string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "webpack/eslint-scope/estraverse": ["estraverse@4.3.0", "https://registry.npmmirror.com/estraverse/-/estraverse-4.3.0.tgz", {}, "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw=="], "wrap-ansi/string-width/emoji-regex": ["emoji-regex@9.2.2", "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], - "wrap-ansi/string-width/strip-ansi": ["strip-ansi@7.2.0", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.2.0.tgz", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], - - "wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.2.2.tgz", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], - "yargs/find-up/locate-path": ["locate-path@5.0.0", "", { "dependencies": { "p-locate": "^4.1.0" } }, "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g=="], "@electron/node-gyp/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.2.tgz", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], - "@electron/rebuild/yargs/cliui/string-width": ["string-width@4.2.3", "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], - "@electron/rebuild/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "@electron/rebuild/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], - "@electron/rebuild/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "@electron/rebuild/yargs/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], - - "@electron/rebuild/yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - - "@inquirer/core/wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "@inquirer/core/wrap-ansi/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], - "@typescript-eslint/typescript-estree/minimatch/brace-expansion/balanced-match": ["balanced-match@4.0.4", "", {}, "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA=="], "cacache/glob/minimatch/brace-expansion": ["brace-expansion@2.0.2", "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.2.tgz", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], - "cli-truncate/string-width/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.2.2.tgz", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], - - "cliui/wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "cliui/wrap-ansi/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], - "electron-installer-debian/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "electron-installer-debian/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], - "electron-installer-debian/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "electron-installer-debian/yargs/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], - - "electron-installer-debian/yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "electron-installer-redhat/yargs/cliui/strip-ansi": ["strip-ansi@6.0.1", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "electron-installer-redhat/yargs/cliui/wrap-ansi": ["wrap-ansi@7.0.0", "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q=="], - "electron-installer-redhat/yargs/string-width/emoji-regex": ["emoji-regex@8.0.0", "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "electron-installer-redhat/yargs/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], - - "electron-installer-redhat/yargs/string-width/strip-ansi": ["strip-ansi@6.0.1", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], - "electron/@electron/get/fs-extra/jsonfile": ["jsonfile@4.0.0", "https://registry.npmmirror.com/jsonfile/-/jsonfile-4.0.0.tgz", { "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg=="], "electron/@electron/get/fs-extra/universalify": ["universalify@0.1.2", "https://registry.npmmirror.com/universalify/-/universalify-0.1.2.tgz", {}, "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg=="], "execa/cross-spawn/shebang-command/shebang-regex": ["shebang-regex@1.0.0", "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-1.0.0.tgz", {}, "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ=="], - "log-update/wrap-ansi/string-width/emoji-regex": ["emoji-regex@9.2.2", "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], - - "log-update/wrap-ansi/string-width/strip-ansi": ["strip-ansi@7.2.0", "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.2.0.tgz", { "dependencies": { "ansi-regex": "^6.2.2" } }, "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w=="], - - "ora/cli-cursor/restore-cursor/signal-exit": ["signal-exit@3.0.7", "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", {}, "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="], - "read-pkg-up/find-up/locate-path/p-locate": ["p-locate@2.0.0", "https://registry.npmmirror.com/p-locate/-/p-locate-2.0.0.tgz", { "dependencies": { "p-limit": "^1.1.0" } }, "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg=="], "read-pkg-up/find-up/locate-path/path-exists": ["path-exists@3.0.0", "https://registry.npmmirror.com/path-exists/-/path-exists-3.0.0.tgz", {}, "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ=="], - "wrap-ansi/string-width/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.2.2.tgz", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], - "yargs/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], - "@electron/rebuild/yargs/cliui/string-width/emoji-regex": ["emoji-regex@8.0.0", "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], - - "@electron/rebuild/yargs/cliui/string-width/is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], - "@electron/rebuild/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "@electron/rebuild/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "electron-installer-debian/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "electron-installer-debian/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "electron-installer-redhat/yargs/cliui/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - "electron-installer-redhat/yargs/string-width/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], - - "log-update/wrap-ansi/string-width/strip-ansi/ansi-regex": ["ansi-regex@6.2.2", "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.2.2.tgz", {}, "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg=="], - "read-pkg-up/find-up/locate-path/p-locate/p-limit": ["p-limit@1.3.0", "https://registry.npmmirror.com/p-limit/-/p-limit-1.3.0.tgz", { "dependencies": { "p-try": "^1.0.0" } }, "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q=="], "yargs/find-up/locate-path/p-locate/p-limit": ["p-limit@2.3.0", "", { "dependencies": { "p-try": "^2.0.0" } }, "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w=="], diff --git a/taskboard-electron/eslint.config.mjs b/taskboard-electron/eslint.config.mjs index 1991f59..9ee2248 100644 --- a/taskboard-electron/eslint.config.mjs +++ b/taskboard-electron/eslint.config.mjs @@ -8,22 +8,21 @@ import prettier from "eslint-config-prettier"; export default tseslint.config( { ignores: [ - ".vite/**", + ".bun/**", "out/**", "node_modules/**", "resources/**", "dist/**", // Throwaway manual hot-reload probe, not part of the app or test suite. - "test_hot_reload.mjs", ], }, js.configs.recommended, - // TypeScript sources (main, preload, renderer, tests). + // TypeScript sources (main, preload, renderer, tests, build scripts). ...tseslint.configs.recommended.map((config) => ({ ...config, - files: ["src/**/*.{ts,tsx}"], + files: ["src/**/*.{ts,tsx}", "scripts/**/*.ts"], })), // Project-wide tweaks: allow `_`-prefixed throwaways and intentional empty @@ -64,23 +63,15 @@ export default tseslint.config( }, }, - // Node-side code: Electron main/preload, build scripts, Forge/Vite configs. + // Node-side code: Electron main/preload, build scripts, Forge config. { - files: [ - "src/main.ts", - "src/preload.ts", - "scripts/**/*.mjs", - "forge.config.js", - "*.config.js", - "vite.*.config.mjs", - ], + files: ["src/main.ts", "src/preload.ts", "scripts/**/*.ts", "forge.config.js", "*.config.js"], languageOptions: { ecmaVersion: 2024, globals: { ...globals.node, - // Injected by the electron-forge Vite plugin at build time. - MAIN_WINDOW_VITE_DEV_SERVER_URL: "readonly", - MAIN_WINDOW_VITE_NAME: "readonly", + // Bun runtime globals used by the build scripts (run with `bun`). + Bun: "readonly", }, }, }, @@ -96,7 +87,7 @@ export default tseslint.config( // Renderer code: browser context + React/JSX. { - files: ["src/renderer.ts", "src/renderer/**/*.{ts,tsx}"], + files: ["src/renderer/**/*.{ts,tsx}"], plugins: { react, "react-hooks": reactHooks }, languageOptions: { ecmaVersion: 2024, diff --git a/taskboard-electron/forge.config.js b/taskboard-electron/forge.config.js index 7584340..3e64c16 100644 --- a/taskboard-electron/forge.config.js +++ b/taskboard-electron/forge.config.js @@ -7,6 +7,20 @@ module.exports = { name: "AgentForge", appBundleId: "com.agentforge.app", extraResource: ["./resources/taskboard"], + // Bun builds the app into .bun/ (see scripts/build.ts); ship only the + // built output, package.json, and pruned node_modules. + ignore: [ + /^\/src/, + /^\/scripts/, + /^\/resources/, + /^\/index\.html$/, + /^\/tsconfig.*\.json$/, + /^\/eslint\.config\.mjs$/, + /^\/bun\.lock$/, + /^\/package-lock\.json$/, + /^\/\.vite/, + /^\/out/, + ], osxSign: { // "-" is codesign's ad-hoc identity, not a keychain certificate name. identity: "-", @@ -31,29 +45,6 @@ module.exports = { }, ], plugins: [ - { - name: "@electron-forge/plugin-vite", - config: { - build: [ - { - entry: "src/main.ts", - config: "vite.main.config.mjs", - target: "main", - }, - { - entry: "src/preload.ts", - config: "vite.preload.config.mjs", - target: "preload", - }, - ], - renderer: [ - { - name: "main_window", - config: "vite.renderer.config.mjs", - }, - ], - }, - }, new FusesPlugin({ version: FuseVersion.V1, [FuseV1Options.RunAsNode]: false, diff --git a/taskboard-electron/index.html b/taskboard-electron/index.html index 4997c85..8221757 100644 --- a/taskboard-electron/index.html +++ b/taskboard-electron/index.html @@ -6,6 +6,6 @@
- + diff --git a/taskboard-electron/package-lock.json b/taskboard-electron/package-lock.json deleted file mode 100644 index 4379adb..0000000 --- a/taskboard-electron/package-lock.json +++ /dev/null @@ -1,11832 +0,0 @@ -{ - "name": "agentforge", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "agentforge", - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "chokidar": "^5.0.0", - "electron-squirrel-startup": "^1.0.1", - "qrcode": "^1.5.4", - "react": "^19.2.4", - "react-dom": "^19.2.4" - }, - "devDependencies": { - "@electron-forge/cli": "^7.11.1", - "@electron-forge/maker-deb": "^7.11.1", - "@electron-forge/maker-dmg": "^7.11.1", - "@electron-forge/maker-rpm": "^7.11.1", - "@electron-forge/maker-squirrel": "^7.11.1", - "@electron-forge/maker-zip": "^7.11.1", - "@electron-forge/plugin-auto-unpack-natives": "^7.11.1", - "@electron-forge/plugin-fuses": "^7.11.1", - "@electron-forge/plugin-vite": "^7.11.1", - "@electron/fuses": "^1.8.0", - "@eslint/js": "^9.39.4", - "@vitejs/plugin-react": "^5.1.4", - "electron": "40.2.1", - "eslint": "^9.39.4", - "eslint-config-prettier": "^10.1.8", - "eslint-plugin-react": "^7.37.5", - "eslint-plugin-react-hooks": "^7.1.1", - "globals": "^17.6.0", - "prettier": "^3.8.3", - "vite": "^7.3.1" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.29.0", - "resolved": "https://registry.npmmirror.com/@babel/code-frame/-/code-frame-7.29.0.tgz", - "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.28.5", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.29.0", - "resolved": "https://registry.npmmirror.com/@babel/compat-data/-/compat-data-7.29.0.tgz", - "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.29.0", - "resolved": "https://registry.npmmirror.com/@babel/core/-/core-7.29.0.tgz", - "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-compilation-targets": "^7.28.6", - "@babel/helper-module-transforms": "^7.28.6", - "@babel/helpers": "^7.28.6", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/traverse": "^7.29.0", - "@babel/types": "^7.29.0", - "@jridgewell/remapping": "^2.3.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/generator": { - "version": "7.29.1", - "resolved": "https://registry.npmmirror.com/@babel/generator/-/generator-7.29.1.tgz", - "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.29.0", - "@babel/types": "^7.29.0", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.28.6", - "resolved": "https://registry.npmmirror.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", - "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.28.6", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmmirror.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.28.6", - "resolved": "https://registry.npmmirror.com/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", - "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.28.6", - "resolved": "https://registry.npmmirror.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", - "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.28.6", - "@babel/helper-validator-identifier": "^7.28.5", - "@babel/traverse": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.28.6", - "resolved": "https://registry.npmmirror.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", - "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmmirror.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.28.6", - "resolved": "https://registry.npmmirror.com/@babel/helpers/-/helpers-7.28.6.tgz", - "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.29.0", - "resolved": "https://registry.npmmirror.com/@babel/parser/-/parser-7.29.0.tgz", - "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.29.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", - "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.27.1", - "resolved": "https://registry.npmmirror.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", - "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/template": { - "version": "7.28.6", - "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.28.6.tgz", - "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.28.6", - "@babel/parser": "^7.28.6", - "@babel/types": "^7.28.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.29.0", - "resolved": "https://registry.npmmirror.com/@babel/traverse/-/traverse-7.29.0.tgz", - "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.29.0", - "@babel/generator": "^7.29.0", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.29.0", - "@babel/template": "^7.28.6", - "@babel/types": "^7.29.0", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.29.0", - "resolved": "https://registry.npmmirror.com/@babel/types/-/types-7.29.0.tgz", - "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@electron-forge/cli": { - "version": "7.11.1", - "resolved": "https://registry.npmmirror.com/@electron-forge/cli/-/cli-7.11.1.tgz", - "integrity": "sha512-pk8AoLsr7t7LBAt0cFD06XFA6uxtPdvtLx06xeal7O9o7GHGCbj29WGwFoJ8Br/ENM0Ho868S3PrAn1PtBXt5g==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/malept" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/subscription/pkg/npm-.electron-forge-cli?utm_medium=referral&utm_source=npm_fund" - } - ], - "license": "MIT", - "dependencies": { - "@electron-forge/core": "7.11.1", - "@electron-forge/core-utils": "7.11.1", - "@electron-forge/shared-types": "7.11.1", - "@electron/get": "^3.0.0", - "@inquirer/prompts": "^6.0.1", - "@listr2/prompt-adapter-inquirer": "^2.0.22", - "chalk": "^4.0.0", - "commander": "^11.1.0", - "debug": "^4.3.1", - "fs-extra": "^10.0.0", - "listr2": "^7.0.2", - "log-symbols": "^4.0.0", - "semver": "^7.2.1" - }, - "bin": { - "electron-forge": "dist/electron-forge.js", - "electron-forge-vscode-nix": "script/vscode.sh", - "electron-forge-vscode-win": "script/vscode.cmd" - }, - "engines": { - "node": ">= 16.4.0" - } - }, - "node_modules/@electron-forge/core": { - "version": "7.11.1", - "resolved": "https://registry.npmmirror.com/@electron-forge/core/-/core-7.11.1.tgz", - "integrity": "sha512-YtuPLzggPKPabFAD2rOZFE0s7f4KaUTpGRduhSMbZUqpqD1TIPyfoDBpYiZvao3Ht8pyZeOJjbzcC0LpFs9gIQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/malept" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/subscription/pkg/npm-.electron-forge-core?utm_medium=referral&utm_source=npm_fund" - } - ], - "license": "MIT", - "dependencies": { - "@electron-forge/core-utils": "7.11.1", - "@electron-forge/maker-base": "7.11.1", - "@electron-forge/plugin-base": "7.11.1", - "@electron-forge/publisher-base": "7.11.1", - "@electron-forge/shared-types": "7.11.1", - "@electron-forge/template-base": "7.11.1", - "@electron-forge/template-vite": "7.11.1", - "@electron-forge/template-vite-typescript": "7.11.1", - "@electron-forge/template-webpack": "7.11.1", - "@electron-forge/template-webpack-typescript": "7.11.1", - "@electron-forge/tracer": "7.11.1", - "@electron/get": "^3.0.0", - "@electron/packager": "^18.3.5", - "@electron/rebuild": "^3.7.0", - "@malept/cross-spawn-promise": "^2.0.0", - "@vscode/sudo-prompt": "^9.3.1", - "chalk": "^4.0.0", - "debug": "^4.3.1", - "fast-glob": "^3.2.7", - "filenamify": "^4.1.0", - "find-up": "^5.0.0", - "fs-extra": "^10.0.0", - "global-dirs": "^3.0.0", - "got": "^11.8.5", - "interpret": "^3.1.1", - "jiti": "^2.4.2", - "listr2": "^7.0.2", - "lodash": "^4.17.20", - "log-symbols": "^4.0.0", - "node-fetch": "^2.6.7", - "rechoir": "^0.8.0", - "semver": "^7.2.1", - "source-map-support": "^0.5.13", - "username": "^5.1.0" - }, - "engines": { - "node": ">= 16.4.0" - } - }, - "node_modules/@electron-forge/core-utils": { - "version": "7.11.1", - "resolved": "https://registry.npmmirror.com/@electron-forge/core-utils/-/core-utils-7.11.1.tgz", - "integrity": "sha512-9UxRWVsfcziBsbAA2MS0Oz4yYovQCO2BhnGIfsbKNTBtMc/RcVSxAS0NMyymce44i43p1ZC/FqWhnt1XqYw3bQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/shared-types": "7.11.1", - "@electron/rebuild": "^3.7.0", - "@malept/cross-spawn-promise": "^2.0.0", - "chalk": "^4.0.0", - "debug": "^4.3.1", - "find-up": "^5.0.0", - "fs-extra": "^10.0.0", - "log-symbols": "^4.0.0", - "parse-author": "^2.0.0", - "semver": "^7.2.1" - }, - "engines": { - "node": ">= 16.4.0" - } - }, - "node_modules/@electron-forge/maker-base": { - "version": "7.11.1", - "resolved": "https://registry.npmmirror.com/@electron-forge/maker-base/-/maker-base-7.11.1.tgz", - "integrity": "sha512-yhZrCGoN6bDeiB5DHFaueZ1h84AReElEj+f0hl2Ph4UbZnO0cnLpbx+Bs+XfMLAiA+beC8muB5UDK5ysfuT9BQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/shared-types": "7.11.1", - "fs-extra": "^10.0.0", - "which": "^2.0.2" - }, - "engines": { - "node": ">= 16.4.0" - } - }, - "node_modules/@electron-forge/maker-deb": { - "version": "7.11.1", - "resolved": "https://registry.npmmirror.com/@electron-forge/maker-deb/-/maker-deb-7.11.1.tgz", - "integrity": "sha512-QTYiryQLYPDkq6pIfBmx0GQ6D8QatUkowH7rTlW5MnCUa0uumX0Xu7yGIjesuwW37fxT3Lv4xi+FSXMCm2eC1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/maker-base": "7.11.1", - "@electron-forge/shared-types": "7.11.1" - }, - "engines": { - "node": ">= 16.4.0" - }, - "optionalDependencies": { - "electron-installer-debian": "^3.2.0" - } - }, - "node_modules/@electron-forge/maker-dmg": { - "version": "7.11.1", - "resolved": "https://registry.npmmirror.com/@electron-forge/maker-dmg/-/maker-dmg-7.11.1.tgz", - "integrity": "sha512-7zs5/Ewz1PcOl4N1102stFgBiFGWxU18+UPFUSd/fgf9MErBl4HBWuVNMIHyeJ/56rdfkcmTxTqE+9TBEYrZcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/maker-base": "7.11.1", - "@electron-forge/shared-types": "7.11.1", - "fs-extra": "^10.0.0" - }, - "engines": { - "node": ">= 16.4.0" - }, - "optionalDependencies": { - "electron-installer-dmg": "^5.0.1" - } - }, - "node_modules/@electron-forge/maker-rpm": { - "version": "7.11.1", - "resolved": "https://registry.npmmirror.com/@electron-forge/maker-rpm/-/maker-rpm-7.11.1.tgz", - "integrity": "sha512-iEfJPRQQyaTqk2EbUfZgulChNWvxGXeYUH0xBX/r5cj1pL4vcJXt3jLMQBVn3mk/0Ytv9UWRs8R/XuNWX6sf2w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/maker-base": "7.11.1", - "@electron-forge/shared-types": "7.11.1" - }, - "engines": { - "node": ">= 16.4.0" - }, - "optionalDependencies": { - "electron-installer-redhat": "^3.2.0" - } - }, - "node_modules/@electron-forge/maker-squirrel": { - "version": "7.11.1", - "resolved": "https://registry.npmmirror.com/@electron-forge/maker-squirrel/-/maker-squirrel-7.11.1.tgz", - "integrity": "sha512-oSg7fgad6l+X0DjtRkSpMzB0AjzyDO4mb2gzM4kTodkP1ADeiMi08bxy0ZeCESqLm5+fG72cAPmEr3BAPvI1yw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/maker-base": "7.11.1", - "@electron-forge/shared-types": "7.11.1", - "fs-extra": "^10.0.0" - }, - "engines": { - "node": ">= 16.4.0" - }, - "optionalDependencies": { - "electron-winstaller": "^5.3.0" - } - }, - "node_modules/@electron-forge/maker-zip": { - "version": "7.11.1", - "resolved": "https://registry.npmmirror.com/@electron-forge/maker-zip/-/maker-zip-7.11.1.tgz", - "integrity": "sha512-30rcp0AbJLfkFBX2hmO14LKXx7z9V61LffTVbTCFMh5vUB2kZvcA5xAhsBk2oUJWfGVxe1DuSEU0rDR9bUMHUg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/maker-base": "7.11.1", - "@electron-forge/shared-types": "7.11.1", - "cross-zip": "^4.0.0", - "fs-extra": "^10.0.0", - "got": "^11.8.5" - }, - "engines": { - "node": ">= 16.4.0" - } - }, - "node_modules/@electron-forge/plugin-auto-unpack-natives": { - "version": "7.11.1", - "resolved": "https://registry.npmmirror.com/@electron-forge/plugin-auto-unpack-natives/-/plugin-auto-unpack-natives-7.11.1.tgz", - "integrity": "sha512-5uRM3WNv7jIeDt8pLP3V4U2puWHPGJ/3qRuSE47RKgTp5qxpZidWHSYcEJJxjoqOL/7KFwSqKSQ/a36GoZV4Fg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/plugin-base": "7.11.1", - "@electron-forge/shared-types": "7.11.1" - }, - "engines": { - "node": ">= 16.4.0" - } - }, - "node_modules/@electron-forge/plugin-base": { - "version": "7.11.1", - "resolved": "https://registry.npmmirror.com/@electron-forge/plugin-base/-/plugin-base-7.11.1.tgz", - "integrity": "sha512-lKpSOV1GA3FoYiD9k05i6v4KaQVmojnRgCr7d6VL1bFp13QOtXSaAWhFI9mtSY7rGElOacX6Zt7P7rPoB8T9eQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/shared-types": "7.11.1" - }, - "engines": { - "node": ">= 16.4.0" - } - }, - "node_modules/@electron-forge/plugin-fuses": { - "version": "7.11.1", - "resolved": "https://registry.npmmirror.com/@electron-forge/plugin-fuses/-/plugin-fuses-7.11.1.tgz", - "integrity": "sha512-Td517mHf+RjQAayFDM2kKb7NaGdRXrZfPbc7KOHlGbXthp5YTkFu2cCZGWokiqt1y1wsFaAodULhqBIg7vbbbw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/plugin-base": "7.11.1", - "@electron-forge/shared-types": "7.11.1" - }, - "engines": { - "node": ">= 16.4.0" - }, - "peerDependencies": { - "@electron/fuses": "^1.0.0" - } - }, - "node_modules/@electron-forge/plugin-vite": { - "version": "7.11.1", - "resolved": "https://registry.npmmirror.com/@electron-forge/plugin-vite/-/plugin-vite-7.11.1.tgz", - "integrity": "sha512-kc/WQs/0+9VC9Q4oSSocMa02YxKDvAYxhWtNcL+qlswZMJlxe8gX7vl/yXq9AjPQxw7f3jzf7nruUPKQ+vyLLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/plugin-base": "7.11.1", - "@electron-forge/shared-types": "7.11.1", - "chalk": "^4.0.0", - "debug": "^4.3.1", - "fs-extra": "^10.0.0", - "listr2": "^7.0.2" - }, - "engines": { - "node": ">= 16.4.0" - } - }, - "node_modules/@electron-forge/publisher-base": { - "version": "7.11.1", - "resolved": "https://registry.npmmirror.com/@electron-forge/publisher-base/-/publisher-base-7.11.1.tgz", - "integrity": "sha512-rXE9oMFGMtdQrixnumWYH5TTGsp99iPHZb3jI74YWq518ctCh6DlIgWlhf6ok2X0+lhWovcIb45KJucUFAQ13w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/shared-types": "7.11.1" - }, - "engines": { - "node": ">= 16.4.0" - } - }, - "node_modules/@electron-forge/shared-types": { - "version": "7.11.1", - "resolved": "https://registry.npmmirror.com/@electron-forge/shared-types/-/shared-types-7.11.1.tgz", - "integrity": "sha512-vvBWdAEh53UJlDGUevpaJk1+sqDMQibfrbHR+0IPA4MPyQex7/Uhv3vYH9oGHujBVAChQahjAuJt0fG6IJBLZg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/tracer": "7.11.1", - "@electron/packager": "^18.3.5", - "@electron/rebuild": "^3.7.0", - "listr2": "^7.0.2" - }, - "engines": { - "node": ">= 16.4.0" - } - }, - "node_modules/@electron-forge/template-base": { - "version": "7.11.1", - "resolved": "https://registry.npmmirror.com/@electron-forge/template-base/-/template-base-7.11.1.tgz", - "integrity": "sha512-XpTaEf+EfQw+0BlSAtSpZKYIKYvKu4raNzSGHZZoSYHp+HDC7R+MlpFQmSJiGdYQzQ14C+uxO42tVjgM0DMbpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/core-utils": "7.11.1", - "@electron-forge/shared-types": "7.11.1", - "@malept/cross-spawn-promise": "^2.0.0", - "debug": "^4.3.1", - "fs-extra": "^10.0.0", - "semver": "^7.2.1", - "username": "^5.1.0" - }, - "engines": { - "node": ">= 16.4.0" - } - }, - "node_modules/@electron-forge/template-vite": { - "version": "7.11.1", - "resolved": "https://registry.npmmirror.com/@electron-forge/template-vite/-/template-vite-7.11.1.tgz", - "integrity": "sha512-Or8Lxf4awoeUZoMTKJEw5KQDIhqOFs24WhVka3yZXxc6VgVWN79KmYKYM6uM/YMQttmafhsBhY2t1Lxo1WR/ug==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/shared-types": "7.11.1", - "@electron-forge/template-base": "7.11.1", - "fs-extra": "^10.0.0" - }, - "engines": { - "node": ">= 16.4.0" - } - }, - "node_modules/@electron-forge/template-vite-typescript": { - "version": "7.11.1", - "resolved": "https://registry.npmmirror.com/@electron-forge/template-vite-typescript/-/template-vite-typescript-7.11.1.tgz", - "integrity": "sha512-Us4AHXFb+4z+gXgZImSqMBS63oKnsQWLOhqRg321xiDzu2UcQPlwgWNb4rAEKNVC1e7LXrUNDHuBiTrQkvWXbg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/shared-types": "7.11.1", - "@electron-forge/template-base": "7.11.1", - "fs-extra": "^10.0.0" - }, - "engines": { - "node": ">= 16.4.0" - } - }, - "node_modules/@electron-forge/template-webpack": { - "version": "7.11.1", - "resolved": "https://registry.npmmirror.com/@electron-forge/template-webpack/-/template-webpack-7.11.1.tgz", - "integrity": "sha512-15lbXxi+er461MPk6sbwAOyjofAHwmQjTvxNCiNpaU2naEwbj3t0SlLq/BMr5HxnVOaMmA7+lKV9afkIom+d4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/shared-types": "7.11.1", - "@electron-forge/template-base": "7.11.1", - "fs-extra": "^10.0.0" - }, - "engines": { - "node": ">= 16.4.0" - } - }, - "node_modules/@electron-forge/template-webpack-typescript": { - "version": "7.11.1", - "resolved": "https://registry.npmmirror.com/@electron-forge/template-webpack-typescript/-/template-webpack-typescript-7.11.1.tgz", - "integrity": "sha512-6ExfFnFkHBz8rvRFTFg5HVGTC12uJpbVk4q8DVg0R8rhhxhqiVNh8lF2UPtZ2yT2UtGWjXNVlyP3Y3T6q6E3GQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron-forge/shared-types": "7.11.1", - "@electron-forge/template-base": "7.11.1", - "fs-extra": "^10.0.0", - "typescript": "~5.4.5", - "webpack": "^5.69.1" - }, - "engines": { - "node": ">= 16.4.0" - } - }, - "node_modules/@electron-forge/tracer": { - "version": "7.11.1", - "resolved": "https://registry.npmmirror.com/@electron-forge/tracer/-/tracer-7.11.1.tgz", - "integrity": "sha512-tiB6cglVQFcSw9N8GRwVwZUeB9u0DOx2Mj7aFXBUsFLUYQapvVGv51tUSy/UAW5lvmubGscYIILuVko+II3+NA==", - "dev": true, - "license": "MIT", - "dependencies": { - "chrome-trace-event": "^1.0.3" - }, - "engines": { - "node": ">= 14.17.5" - } - }, - "node_modules/@electron/asar": { - "version": "3.4.1", - "resolved": "https://registry.npmmirror.com/@electron/asar/-/asar-3.4.1.tgz", - "integrity": "sha512-i4/rNPRS84t0vSRa2HorerGRXWyF4vThfHesw0dmcWHp+cspK743UanA0suA5Q5y8kzY2y6YKrvbIUn69BCAiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "commander": "^5.0.0", - "glob": "^7.1.6", - "minimatch": "^3.0.4" - }, - "bin": { - "asar": "bin/asar.js" - }, - "engines": { - "node": ">=10.12.0" - } - }, - "node_modules/@electron/asar/node_modules/commander": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/@electron/fuses": { - "version": "1.8.0", - "resolved": "https://registry.npmmirror.com/@electron/fuses/-/fuses-1.8.0.tgz", - "integrity": "sha512-zx0EIq78WlY/lBb1uXlziZmDZI4ubcCXIMJ4uGjXzZW0nS19TjSPeXPAjzzTmKQlJUZm0SbmZhPKP7tuQ1SsEw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.1", - "fs-extra": "^9.0.1", - "minimist": "^1.2.5" - }, - "bin": { - "electron-fuses": "dist/bin.js" - } - }, - "node_modules/@electron/fuses/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@electron/get": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/@electron/get/-/get-3.1.0.tgz", - "integrity": "sha512-F+nKc0xW+kVbBRhFzaMgPy3KwmuNTYX1fx6+FxxoSnNgwYX6LD7AKBTWkU0MQ6IBoe7dz069CNkR673sPAgkCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.1.1", - "env-paths": "^2.2.0", - "fs-extra": "^8.1.0", - "got": "^11.8.5", - "progress": "^2.0.3", - "semver": "^6.2.0", - "sumchecker": "^3.0.1" - }, - "engines": { - "node": ">=14" - }, - "optionalDependencies": { - "global-agent": "^3.0.0" - } - }, - "node_modules/@electron/get/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/@electron/get/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@electron/get/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@electron/get/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmmirror.com/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/@electron/node-gyp": { - "version": "10.2.0-electron.1", - "resolved": "git+ssh://git@github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2", - "integrity": "sha512-lBSgDMQqt7QWMuIjS8zNAq5FI5o5RVBAcJUGWGI6GgoQITJt3msAkUrHp8YHj3RTVE+h70ndqMGqURjp3IfRyQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "env-paths": "^2.2.0", - "exponential-backoff": "^3.1.1", - "glob": "^8.1.0", - "graceful-fs": "^4.2.6", - "make-fetch-happen": "^10.2.1", - "nopt": "^6.0.0", - "proc-log": "^2.0.1", - "semver": "^7.3.5", - "tar": "^6.2.1", - "which": "^2.0.2" - }, - "bin": { - "node-gyp": "bin/node-gyp.js" - }, - "engines": { - "node": ">=12.13.0" - } - }, - "node_modules/@electron/node-gyp/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@electron/node-gyp/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmmirror.com/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@electron/node-gyp/node_modules/minimatch": { - "version": "5.1.9", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.9.tgz", - "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@electron/notarize": { - "version": "2.5.0", - "resolved": "https://registry.npmmirror.com/@electron/notarize/-/notarize-2.5.0.tgz", - "integrity": "sha512-jNT8nwH1f9X5GEITXaQ8IF/KdskvIkOFfB2CvwumsveVidzpSc+mvhhTMdAGSYF3O+Nq49lJ7y+ssODRXu06+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.1.1", - "fs-extra": "^9.0.1", - "promise-retry": "^2.0.1" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@electron/notarize/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@electron/osx-sign": { - "version": "1.3.3", - "resolved": "https://registry.npmmirror.com/@electron/osx-sign/-/osx-sign-1.3.3.tgz", - "integrity": "sha512-KZ8mhXvWv2rIEgMbWZ4y33bDHyUKMXnx4M0sTyPNK/vcB81ImdeY9Ggdqy0SWbMDgmbqyQ+phgejh6V3R2QuSg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "compare-version": "^0.1.2", - "debug": "^4.3.4", - "fs-extra": "^10.0.0", - "isbinaryfile": "^4.0.8", - "minimist": "^1.2.6", - "plist": "^3.0.5" - }, - "bin": { - "electron-osx-flat": "bin/electron-osx-flat.js", - "electron-osx-sign": "bin/electron-osx-sign.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@electron/packager": { - "version": "18.4.4", - "resolved": "https://registry.npmmirror.com/@electron/packager/-/packager-18.4.4.tgz", - "integrity": "sha512-fTUCmgL25WXTcFpM1M72VmFP8w3E4d+KNzWxmTDRpvwkfn/S206MAtM2cy0GF78KS9AwASMOUmlOIzCHeNxcGQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@electron/asar": "^3.2.13", - "@electron/get": "^3.0.0", - "@electron/notarize": "^2.1.0", - "@electron/osx-sign": "^1.0.5", - "@electron/universal": "^2.0.1", - "@electron/windows-sign": "^1.0.0", - "@malept/cross-spawn-promise": "^2.0.0", - "debug": "^4.0.1", - "extract-zip": "^2.0.0", - "filenamify": "^4.1.0", - "fs-extra": "^11.1.0", - "galactus": "^1.0.0", - "get-package-info": "^1.0.0", - "junk": "^3.1.0", - "parse-author": "^2.0.0", - "plist": "^3.0.0", - "prettier": "^3.4.2", - "resedit": "^2.0.0", - "resolve": "^1.1.6", - "semver": "^7.1.3", - "yargs-parser": "^21.1.1" - }, - "bin": { - "electron-packager": "bin/electron-packager.js" - }, - "engines": { - "node": ">= 16.13.0" - }, - "funding": { - "url": "https://github.com/electron/packager?sponsor=1" - } - }, - "node_modules/@electron/packager/node_modules/fs-extra": { - "version": "11.3.4", - "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-11.3.4.tgz", - "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@electron/rebuild": { - "version": "3.7.2", - "resolved": "https://registry.npmmirror.com/@electron/rebuild/-/rebuild-3.7.2.tgz", - "integrity": "sha512-19/KbIR/DAxbsCkiaGMXIdPnMCJLkcf8AvGnduJtWBs/CBwiAjY1apCqOLVxrXg+rtXFCngbXhBanWjxLUt1Mg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron/node-gyp": "git+https://github.com/electron/node-gyp.git#06b29aafb7708acef8b3669835c8a7857ebc92d2", - "@malept/cross-spawn-promise": "^2.0.0", - "chalk": "^4.0.0", - "debug": "^4.1.1", - "detect-libc": "^2.0.1", - "fs-extra": "^10.0.0", - "got": "^11.7.0", - "node-abi": "^3.45.0", - "node-api-version": "^0.2.0", - "ora": "^5.1.0", - "read-binary-file-arch": "^1.0.6", - "semver": "^7.3.5", - "tar": "^6.0.5", - "yargs": "^17.0.1" - }, - "bin": { - "electron-rebuild": "lib/cli.js" - }, - "engines": { - "node": ">=12.13.0" - } - }, - "node_modules/@electron/universal": { - "version": "2.0.3", - "resolved": "https://registry.npmmirror.com/@electron/universal/-/universal-2.0.3.tgz", - "integrity": "sha512-Wn9sPYIVFRFl5HmwMJkARCCf7rqK/EurkfQ/rJZ14mHP3iYTjZSIOSVonEAnhWeAXwtw7zOekGRlc6yTtZ0t+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@electron/asar": "^3.3.1", - "@malept/cross-spawn-promise": "^2.0.0", - "debug": "^4.3.1", - "dir-compare": "^4.2.0", - "fs-extra": "^11.1.1", - "minimatch": "^9.0.3", - "plist": "^3.1.0" - }, - "engines": { - "node": ">=16.4" - } - }, - "node_modules/@electron/universal/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@electron/universal/node_modules/fs-extra": { - "version": "11.3.4", - "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-11.3.4.tgz", - "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@electron/universal/node_modules/minimatch": { - "version": "9.0.9", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.9.tgz", - "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.2" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@electron/windows-sign": { - "version": "1.2.2", - "resolved": "https://registry.npmmirror.com/@electron/windows-sign/-/windows-sign-1.2.2.tgz", - "integrity": "sha512-dfZeox66AvdPtb2lD8OsIIQh12Tp0GNCRUDfBHIKGpbmopZto2/A8nSpYYLoedPIHpqkeblZ/k8OV0Gy7PYuyQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "cross-dirname": "^0.1.0", - "debug": "^4.3.4", - "fs-extra": "^11.1.1", - "minimist": "^1.2.8", - "postject": "^1.0.0-alpha.6" - }, - "bin": { - "electron-windows-sign": "bin/electron-windows-sign.js" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@electron/windows-sign/node_modules/fs-extra": { - "version": "11.3.4", - "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-11.3.4.tgz", - "integrity": "sha512-CTXd6rk/M3/ULNQj8FBqBWHYBVYybQ3VPBw0xGKFe3tuH7ytT6ACnvzpIQ3UZtB8yvUKC2cXn1a+x+5EVQLovA==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", - "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/android-arm/-/android-arm-0.27.3.tgz", - "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", - "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/android-x64/-/android-x64-0.27.3.tgz", - "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", - "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", - "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", - "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", - "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", - "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", - "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", - "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", - "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", - "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", - "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", - "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", - "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", - "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", - "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", - "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", - "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", - "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", - "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", - "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", - "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", - "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", - "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", - "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", - "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/config-array": { - "version": "0.21.2", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", - "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/object-schema": "^2.1.7", - "debug": "^4.3.1", - "minimatch": "^3.1.5" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-helpers": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", - "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.17.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/core": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", - "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", - "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.14.0", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.1", - "minimatch": "^3.1.5", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/ajv": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", - "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@eslint/js": { - "version": "9.39.4", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", - "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - } - }, - "node_modules/@eslint/object-schema": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", - "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/plugin-kit": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", - "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.17.0", - "levn": "^0.4.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmmirror.com/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@humanfs/core": { - "version": "0.19.2", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", - "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanfs/types": "^0.15.0" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node": { - "version": "0.16.8", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", - "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanfs/core": "^0.19.2", - "@humanfs/types": "^0.15.0", - "@humanwhocodes/retry": "^0.4.0" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/types": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", - "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/retry": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", - "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@inquirer/checkbox": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/@inquirer/checkbox/-/checkbox-3.0.1.tgz", - "integrity": "sha512-0hm2nrToWUdD6/UHnel/UKGdk1//ke5zGUpHIvk5ZWmaKezlGxZkOJXNSWsdxO/rEqTkbB3lNC2J6nBElV2aAQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^9.2.1", - "@inquirer/figures": "^1.0.6", - "@inquirer/type": "^2.0.0", - "ansi-escapes": "^4.3.2", - "yoctocolors-cjs": "^2.1.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/confirm": { - "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/@inquirer/confirm/-/confirm-4.0.1.tgz", - "integrity": "sha512-46yL28o2NJ9doViqOy0VDcoTzng7rAb6yPQKU7VDLqkmbCaH4JqK4yk4XqlzNWy9PVC5pG1ZUXPBQv+VqnYs2w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^9.2.1", - "@inquirer/type": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/core": { - "version": "9.2.1", - "resolved": "https://registry.npmmirror.com/@inquirer/core/-/core-9.2.1.tgz", - "integrity": "sha512-F2VBt7W/mwqEU4bL0RnHNZmC/OxzNx9cOYxHqnXX3MP6ruYvZUZAW9imgN9+h/uBT/oP8Gh888J2OZSbjSeWcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/figures": "^1.0.6", - "@inquirer/type": "^2.0.0", - "@types/mute-stream": "^0.0.4", - "@types/node": "^22.5.5", - "@types/wrap-ansi": "^3.0.0", - "ansi-escapes": "^4.3.2", - "cli-width": "^4.1.0", - "mute-stream": "^1.0.0", - "signal-exit": "^4.1.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^6.2.0", - "yoctocolors-cjs": "^2.1.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/editor": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/@inquirer/editor/-/editor-3.0.1.tgz", - "integrity": "sha512-VA96GPFaSOVudjKFraokEEmUQg/Lub6OXvbIEZU1SDCmBzRkHGhxoFAVaF30nyiB4m5cEbDgiI2QRacXZ2hw9Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^9.2.1", - "@inquirer/type": "^2.0.0", - "external-editor": "^3.1.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/expand": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/@inquirer/expand/-/expand-3.0.1.tgz", - "integrity": "sha512-ToG8d6RIbnVpbdPdiN7BCxZGiHOTomOX94C2FaT5KOHupV40tKEDozp12res6cMIfRKrXLJyexAZhWVHgbALSQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^9.2.1", - "@inquirer/type": "^2.0.0", - "yoctocolors-cjs": "^2.1.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/figures": { - "version": "1.0.15", - "resolved": "https://registry.npmmirror.com/@inquirer/figures/-/figures-1.0.15.tgz", - "integrity": "sha512-t2IEY+unGHOzAaVM5Xx6DEWKeXlDDcNPeDyUpsRc6CUhBfU3VQOEl+Vssh7VNp1dR8MdUJBWhuObjXCsVpjN5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/input": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/@inquirer/input/-/input-3.0.1.tgz", - "integrity": "sha512-BDuPBmpvi8eMCxqC5iacloWqv+5tQSJlUafYWUe31ow1BVXjW2a5qe3dh4X/Z25Wp22RwvcaLCc2siHobEOfzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^9.2.1", - "@inquirer/type": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/number": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/@inquirer/number/-/number-2.0.1.tgz", - "integrity": "sha512-QpR8jPhRjSmlr/mD2cw3IR8HRO7lSVOnqUvQa8scv1Lsr3xoAMMworcYW3J13z3ppjBFBD2ef1Ci6AE5Qn8goQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^9.2.1", - "@inquirer/type": "^2.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/password": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/@inquirer/password/-/password-3.0.1.tgz", - "integrity": "sha512-haoeEPUisD1NeE2IanLOiFr4wcTXGWrBOyAyPZi1FfLJuXOzNmxCJPgUrGYKVh+Y8hfGJenIfz5Wb/DkE9KkMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^9.2.1", - "@inquirer/type": "^2.0.0", - "ansi-escapes": "^4.3.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/prompts": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/@inquirer/prompts/-/prompts-6.0.1.tgz", - "integrity": "sha512-yl43JD/86CIj3Mz5mvvLJqAOfIup7ncxfJ0Btnl0/v5TouVUyeEdcpknfgc+yMevS/48oH9WAkkw93m7otLb/A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/checkbox": "^3.0.1", - "@inquirer/confirm": "^4.0.1", - "@inquirer/editor": "^3.0.1", - "@inquirer/expand": "^3.0.1", - "@inquirer/input": "^3.0.1", - "@inquirer/number": "^2.0.1", - "@inquirer/password": "^3.0.1", - "@inquirer/rawlist": "^3.0.1", - "@inquirer/search": "^2.0.1", - "@inquirer/select": "^3.0.1" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/rawlist": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/@inquirer/rawlist/-/rawlist-3.0.1.tgz", - "integrity": "sha512-VgRtFIwZInUzTiPLSfDXK5jLrnpkuSOh1ctfaoygKAdPqjcjKYmGh6sCY1pb0aGnCGsmhUxoqLDUAU0ud+lGXQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^9.2.1", - "@inquirer/type": "^2.0.0", - "yoctocolors-cjs": "^2.1.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/search": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/@inquirer/search/-/search-2.0.1.tgz", - "integrity": "sha512-r5hBKZk3g5MkIzLVoSgE4evypGqtOannnB3PKTG9NRZxyFRKcfzrdxXXPcoJQsxJPzvdSU2Rn7pB7lw0GCmGAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^9.2.1", - "@inquirer/figures": "^1.0.6", - "@inquirer/type": "^2.0.0", - "yoctocolors-cjs": "^2.1.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/select": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/@inquirer/select/-/select-3.0.1.tgz", - "integrity": "sha512-lUDGUxPhdWMkN/fHy1Lk7pF3nK1fh/gqeyWXmctefhxLYxlDsc7vsPBEpxrfVGDsVdyYJsiJoD4bJ1b623cV1Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/core": "^9.2.1", - "@inquirer/figures": "^1.0.6", - "@inquirer/type": "^2.0.0", - "ansi-escapes": "^4.3.2", - "yoctocolors-cjs": "^2.1.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@inquirer/type": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/@inquirer/type/-/type-2.0.0.tgz", - "integrity": "sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag==", - "dev": true, - "license": "MIT", - "dependencies": { - "mute-stream": "^1.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmmirror.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmmirror.com/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmmirror.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.11", - "resolved": "https://registry.npmmirror.com/@jridgewell/source-map/-/source-map-0.3.11.tgz", - "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmmirror.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmmirror.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@listr2/prompt-adapter-inquirer": { - "version": "2.0.22", - "resolved": "https://registry.npmmirror.com/@listr2/prompt-adapter-inquirer/-/prompt-adapter-inquirer-2.0.22.tgz", - "integrity": "sha512-hV36ZoY+xKL6pYOt1nPNnkciFkn89KZwqLhAFzJvYysAvL5uBQdiADZx/8bIDXIukzzwG0QlPYolgMzQUtKgpQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@inquirer/type": "^1.5.5" - }, - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "@inquirer/prompts": ">= 3 < 8" - } - }, - "node_modules/@listr2/prompt-adapter-inquirer/node_modules/@inquirer/type": { - "version": "1.5.5", - "resolved": "https://registry.npmmirror.com/@inquirer/type/-/type-1.5.5.tgz", - "integrity": "sha512-MzICLu4yS7V8AA61sANROZ9vT1H3ooca5dSmI1FjZkzq7o/koMsRfQSzRtFo+F3Ao4Sf1C0bpLKejpKB/+j6MA==", - "dev": true, - "license": "MIT", - "dependencies": { - "mute-stream": "^1.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@malept/cross-spawn-promise": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/@malept/cross-spawn-promise/-/cross-spawn-promise-2.0.0.tgz", - "integrity": "sha512-1DpKU0Z5ThltBwjNySMC14g0CkbyhCaz9FkhxqNsZI6uAPJXFS8cMXlBKo26FJ8ZuW6S9GCMcR9IO5k2X5/9Fg==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/malept" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" - } - ], - "license": "Apache-2.0", - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "engines": { - "node": ">= 12.13.0" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmmirror.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmmirror.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@npmcli/fs": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/@npmcli/fs/-/fs-2.1.2.tgz", - "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "@gar/promisify": "^1.1.3", - "semver": "^7.3.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/@npmcli/move-file": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/@npmcli/move-file/-/move-file-2.0.1.tgz", - "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "dev": true, - "license": "MIT", - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-rc.3", - "resolved": "https://registry.npmmirror.com/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", - "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", - "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", - "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", - "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", - "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", - "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", - "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", - "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", - "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", - "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", - "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", - "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", - "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", - "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", - "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", - "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", - "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", - "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", - "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", - "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", - "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", - "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", - "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", - "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", - "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", - "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmmirror.com/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, - "node_modules/@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmmirror.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", - "dev": true, - "license": "MIT", - "dependencies": { - "defer-to-connect": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/@types/appdmg": { - "version": "0.5.5", - "resolved": "https://registry.npmmirror.com/@types/appdmg/-/appdmg-0.5.5.tgz", - "integrity": "sha512-G+n6DgZTZFOteITE30LnWj+HRVIGr7wMlAiLWOO02uJFWVEitaPU9JVXm9wJokkgshBawb2O1OykdcsmkkZfgg==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmmirror.com/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", - "resolved": "https://registry.npmmirror.com/@types/babel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmmirror.com/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmmirror.com/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", - "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.2" - } - }, - "node_modules/@types/cacheable-request": { - "version": "6.0.3", - "resolved": "https://registry.npmmirror.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/http-cache-semantics": "*", - "@types/keyv": "^3.1.4", - "@types/node": "*", - "@types/responselike": "^1.0.0" - } - }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmmirror.com/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmmirror.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmmirror.com/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/fs-extra": { - "version": "9.0.13", - "resolved": "https://registry.npmmirror.com/@types/fs-extra/-/fs-extra-9.0.13.tgz", - "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/http-cache-semantics": { - "version": "4.2.0", - "resolved": "https://registry.npmmirror.com/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmmirror.com/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/keyv": { - "version": "3.1.4", - "resolved": "https://registry.npmmirror.com/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/mute-stream": { - "version": "0.0.4", - "resolved": "https://registry.npmmirror.com/@types/mute-stream/-/mute-stream-0.0.4.tgz", - "integrity": "sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/node": { - "version": "22.19.13", - "resolved": "https://registry.npmmirror.com/@types/node/-/node-22.19.13.tgz", - "integrity": "sha512-akNQMv0wW5uyRpD2v2IEyRSZiR+BeGuoB6L310EgGObO44HSMNT8z1xzio28V8qOrgYaopIDNA18YgdXd+qTiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, - "node_modules/@types/responselike": { - "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/@types/responselike/-/responselike-1.0.3.tgz", - "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/wrap-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/@types/wrap-ansi/-/wrap-ansi-3.0.0.tgz", - "integrity": "sha512-ltIpx+kM7g/MLRZfkbL7EsCEjfzCcScLpkg37eXEtx5kmrAKBkTJwd1GIAjDSL8wTpM6Hzn5YO4pSb91BEwu1g==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/yauzl": { - "version": "2.10.3", - "resolved": "https://registry.npmmirror.com/@types/yauzl/-/yauzl-2.10.3.tgz", - "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@vitejs/plugin-react": { - "version": "5.1.4", - "resolved": "https://registry.npmmirror.com/@vitejs/plugin-react/-/plugin-react-5.1.4.tgz", - "integrity": "sha512-VIcFLdRi/VYRU8OL/puL7QXMYafHmqOnwTZY50U1JPlCNj30PxCMx65c494b1K9be9hX83KVt0+gTEwTWLqToA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.29.0", - "@babel/plugin-transform-react-jsx-self": "^7.27.1", - "@babel/plugin-transform-react-jsx-source": "^7.27.1", - "@rolldown/pluginutils": "1.0.0-rc.3", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.18.0" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" - } - }, - "node_modules/@vscode/sudo-prompt": { - "version": "9.3.2", - "resolved": "https://registry.npmmirror.com/@vscode/sudo-prompt/-/sudo-prompt-9.3.2.tgz", - "integrity": "sha512-gcXoCN00METUNFeQOFJ+C9xUI0DKB+0EGMVg7wbVYRHBw2Eq3fKisDZOkRdOz3kqXRKOENMfShPOmypw1/8nOw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.14.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/ast/-/ast-1.14.1.tgz", - "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/helper-numbers": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.13.2", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", - "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.13.2", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", - "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.14.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", - "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.13.2", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", - "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.13.2", - "@webassemblyjs/helper-api-error": "1.13.2", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.13.2", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", - "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.14.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", - "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/wasm-gen": "1.14.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.13.2", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", - "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.13.2", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", - "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.13.2", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", - "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.14.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", - "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/helper-wasm-section": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-opt": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1", - "@webassemblyjs/wast-printer": "1.14.1" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.14.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", - "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.14.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", - "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.14.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", - "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-api-error": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.14.1", - "resolved": "https://registry.npmmirror.com/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", - "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@xmldom/xmldom": { - "version": "0.8.11", - "resolved": "https://registry.npmmirror.com/@xmldom/xmldom/-/xmldom-0.8.11.tgz", - "integrity": "sha512-cQzWCtO6C8TQiYl1ruKNn2U6Ao4o4WBBcbL61yJl84x+j5sOWWFU9X7DpND8XZG3daDppSsigMdfAIl2upQBRw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmmirror.com/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true, - "license": "ISC" - }, - "node_modules/acorn": { - "version": "8.16.0", - "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.16.0.tgz", - "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-phases": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", - "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.13.0" - }, - "peerDependencies": { - "acorn": "^8.14.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmmirror.com/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/agentkeepalive": { - "version": "4.6.0", - "resolved": "https://registry.npmmirror.com/agentkeepalive/-/agentkeepalive-4.6.0.tgz", - "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "humanize-ms": "^1.2.1" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmmirror.com/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/appdmg": { - "version": "0.6.6", - "resolved": "https://registry.npmmirror.com/appdmg/-/appdmg-0.6.6.tgz", - "integrity": "sha512-GRmFKlCG+PWbcYF4LUNonTYmy0GjguDy6Jh9WP8mpd0T6j80XIJyXBiWlD0U+MLNhqV9Nhx49Gl9GpVToulpLg==", - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "dependencies": { - "async": "^1.4.2", - "ds-store": "^0.1.5", - "execa": "^1.0.0", - "fs-temp": "^1.0.0", - "fs-xattr": "^0.3.0", - "image-size": "^0.7.4", - "is-my-json-valid": "^2.20.0", - "minimist": "^1.1.3", - "parse-color": "^1.0.0", - "path-exists": "^4.0.0", - "repeat-string": "^1.5.4" - }, - "bin": { - "appdmg": "bin/appdmg.js" - }, - "engines": { - "node": ">=8.5" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", - "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "is-array-buffer": "^3.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array-includes": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", - "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.24.0", - "es-object-atoms": "^1.1.1", - "get-intrinsic": "^1.3.0", - "is-string": "^1.1.1", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.findlast": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", - "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flat": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", - "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.flatmap": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", - "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/array.prototype.tosorted": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", - "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.3", - "es-errors": "^1.3.0", - "es-shim-unscopables": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", - "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/async": { - "version": "1.5.2", - "resolved": "https://registry.npmmirror.com/async/-/async-1.5.2.tgz", - "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/async-function": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", - "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/author-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/author-regex/-/author-regex-1.0.0.tgz", - "integrity": "sha512-KbWgR8wOYRAPekEmMXrYYdc7BRyhn2Ftk7KWfMUnQ43hFdojWEFRxhhRUm3/OFEdPa1r0KAvTTg9YQK57xTe0g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/base32-encode": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/base32-encode/-/base32-encode-1.2.0.tgz", - "integrity": "sha512-cHFU8XeRyx0GgmoWi5qHMCVRiqU6J3MHWxVgun7jggCBUpVzm1Ir7M9dYr2whjSNc3tFeXfQ/oZjQu/4u55h9A==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "to-data-view": "^1.1.0" - } - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmmirror.com/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/baseline-browser-mapping": { - "version": "2.10.0", - "resolved": "https://registry.npmmirror.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", - "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.cjs" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmmirror.com/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true, - "license": "MIT" - }, - "node_modules/boolean": { - "version": "3.2.0", - "resolved": "https://registry.npmmirror.com/boolean/-/boolean-3.2.0.tgz", - "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/bplist-creator": { - "version": "0.0.8", - "resolved": "https://registry.npmmirror.com/bplist-creator/-/bplist-creator-0.0.8.tgz", - "integrity": "sha512-Za9JKzD6fjLC16oX2wsXfc+qBEhJBJB1YPInoAQpMLhDuj5aVOv1baGeIQSq1Fr3OCqzvsoQcSBSwGId/Ja2PA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "stream-buffers": "~2.2.0" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmmirror.com/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.28.1", - "resolved": "https://registry.npmmirror.com/browserslist/-/browserslist-4.28.1.tgz", - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "baseline-browser-mapping": "^2.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmmirror.com/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmmirror.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/cacache": { - "version": "16.1.3", - "resolved": "https://registry.npmmirror.com/cacache/-/cacache-16.1.3.tgz", - "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "@npmcli/fs": "^2.1.0", - "@npmcli/move-file": "^2.0.0", - "chownr": "^2.0.0", - "fs-minipass": "^2.1.0", - "glob": "^8.0.1", - "infer-owner": "^1.0.4", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "mkdirp": "^1.0.4", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^9.0.0", - "tar": "^6.1.11", - "unique-filename": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/cacache/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/cacache/node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmmirror.com/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/cacache/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/cacache/node_modules/minimatch": { - "version": "5.1.9", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-5.1.9.tgz", - "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmmirror.com/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.6.0" - } - }, - "node_modules/cacheable-request": { - "version": "7.0.4", - "resolved": "https://registry.npmmirror.com/cacheable-request/-/cacheable-request-7.0.4.tgz", - "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", - "dev": true, - "license": "MIT", - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cacheable-request/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/call-bind": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", - "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "get-intrinsic": "^1.3.0", - "set-function-length": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/call-bound": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", - "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "get-intrinsic": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001776", - "resolved": "https://registry.npmmirror.com/caniuse-lite/-/caniuse-lite-1.0.30001776.tgz", - "integrity": "sha512-sg01JDPzZ9jGshqKSckOQthXnYwOEP50jeVFhaSFbZcOy05TiuuaffDOfcwtCisJ9kNQuLBFibYywv2Bgm9osw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmmirror.com/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chardet": { - "version": "0.7.0", - "resolved": "https://registry.npmmirror.com/chardet/-/chardet-0.7.0.tgz", - "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true, - "license": "MIT" - }, - "node_modules/chokidar": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/chokidar/-/chokidar-5.0.0.tgz", - "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", - "license": "MIT", - "dependencies": { - "readdirp": "^5.0.0" - }, - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/chrome-trace-event": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", - "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/cli-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-4.0.0.tgz", - "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", - "dev": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^4.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmmirror.com/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/cli-truncate/-/cli-truncate-3.1.0.tgz", - "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-width": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/cli-width/-/cli-width-4.1.0.tgz", - "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 12" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmmirror.com/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/cliui/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-response": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmmirror.com/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true, - "license": "MIT" - }, - "node_modules/commander": { - "version": "11.1.0", - "resolved": "https://registry.npmmirror.com/commander/-/commander-11.1.0.tgz", - "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - } - }, - "node_modules/compare-version": { - "version": "0.1.2", - "resolved": "https://registry.npmmirror.com/compare-version/-/compare-version-0.1.2.tgz", - "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmmirror.com/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/cross-dirname": { - "version": "0.1.0", - "resolved": "https://registry.npmmirror.com/cross-dirname/-/cross-dirname-0.1.0.tgz", - "integrity": "sha512-+R08/oI0nl3vfPcqftZRpytksBXDzOUveBq/NBVx0sUp1axwzPQrKinNx5yd5sxPu8j1wIy8AfnVQ+5eFdha6Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cross-zip": { - "version": "4.0.1", - "resolved": "https://registry.npmmirror.com/cross-zip/-/cross-zip-4.0.1.tgz", - "integrity": "sha512-n63i0lZ0rvQ6FXiGQ+/JFCKAUyPFhLQYJIqKaa+tSJtfKeULF/IDNDAbdnSIxgS4NTuw2b0+lj8LzfITuq+ZxQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "engines": { - "node": ">=12.10" - } - }, - "node_modules/data-view-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", - "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/data-view-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", - "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/inspect-js" - } - }, - "node_modules/data-view-byte-offset": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", - "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmmirror.com/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-response": "^3.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmmirror.com/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/dijkstrajs": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", - "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", - "license": "MIT" - }, - "node_modules/dir-compare": { - "version": "4.2.0", - "resolved": "https://registry.npmmirror.com/dir-compare/-/dir-compare-4.2.0.tgz", - "integrity": "sha512-2xMCmOoMrdQIPHdsTawECdNPwlVFB9zGcz3kuhmBO6U3oU+UQjsue0i8ayLKpgBcm+hcXPMVSGUN9d+pvJ6+VQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimatch": "^3.0.5", - "p-limit": "^3.1.0 " - } - }, - "node_modules/doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ds-store": { - "version": "0.1.6", - "resolved": "https://registry.npmmirror.com/ds-store/-/ds-store-0.1.6.tgz", - "integrity": "sha512-kY21M6Lz+76OS3bnCzjdsJSF7LBpLYGCVfavW8TgQD2XkcqIZ86W0y9qUDZu6fp7SIZzqosMDW2zi7zVFfv4hw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "bplist-creator": "~0.0.3", - "macos-alias": "~0.2.5", - "tn1150": "^0.1.0" - } - }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmmirror.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, - "license": "MIT" - }, - "node_modules/electron": { - "version": "40.2.1", - "resolved": "https://registry.npmmirror.com/electron/-/electron-40.2.1.tgz", - "integrity": "sha512-0zOeyN8LB1KHIjVV5jyMmQmkqx3J8OkkVlab3p7vOM28jI46blxW7M52Tcdi6X2m5o2jj8ejOlAh5+boL3w8aQ==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "@electron/get": "^2.0.0", - "@types/node": "^24.9.0", - "extract-zip": "^2.0.1" - }, - "bin": { - "electron": "cli.js" - }, - "engines": { - "node": ">= 12.20.55" - } - }, - "node_modules/electron-installer-common": { - "version": "0.10.4", - "resolved": "https://registry.npmmirror.com/electron-installer-common/-/electron-installer-common-0.10.4.tgz", - "integrity": "sha512-8gMNPXfAqUE5CfXg8RL0vXpLE9HAaPkgLXVoHE3BMUzogMWenf4LmwQ27BdCUrEhkjrKl+igs2IHJibclR3z3Q==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@electron/asar": "^3.2.5", - "@malept/cross-spawn-promise": "^1.0.0", - "debug": "^4.1.1", - "fs-extra": "^9.0.0", - "glob": "^7.1.4", - "lodash": "^4.17.15", - "parse-author": "^2.0.0", - "semver": "^7.1.1", - "tmp-promise": "^3.0.2" - }, - "engines": { - "node": ">= 10.0.0" - }, - "funding": { - "url": "https://github.com/electron-userland/electron-installer-common?sponsor=1" - }, - "optionalDependencies": { - "@types/fs-extra": "^9.0.1" - } - }, - "node_modules/electron-installer-common/node_modules/@malept/cross-spawn-promise": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", - "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/malept" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" - } - ], - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/electron-installer-common/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/electron-installer-debian": { - "version": "3.2.0", - "resolved": "https://registry.npmmirror.com/electron-installer-debian/-/electron-installer-debian-3.2.0.tgz", - "integrity": "sha512-58ZrlJ1HQY80VucsEIG9tQ//HrTlG6sfofA3nRGr6TmkX661uJyu4cMPPh6kXW+aHdq/7+q25KyQhDrXvRL7jw==", - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin", - "linux" - ], - "dependencies": { - "@malept/cross-spawn-promise": "^1.0.0", - "debug": "^4.1.1", - "electron-installer-common": "^0.10.2", - "fs-extra": "^9.0.0", - "get-folder-size": "^2.0.1", - "lodash": "^4.17.4", - "word-wrap": "^1.2.3", - "yargs": "^16.0.2" - }, - "bin": { - "electron-installer-debian": "src/cli.js" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/electron-installer-debian/node_modules/@malept/cross-spawn-promise": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", - "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/malept" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" - } - ], - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/electron-installer-debian/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmmirror.com/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "license": "ISC", - "optional": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/electron-installer-debian/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/electron-installer-debian/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/electron-installer-debian/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/electron-installer-debian/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/electron-installer-debian/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/electron-installer-debian/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmmirror.com/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/electron-installer-debian/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "license": "ISC", - "optional": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/electron-installer-dmg": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/electron-installer-dmg/-/electron-installer-dmg-5.0.1.tgz", - "integrity": "sha512-qOa1aAQdX57C+vzhDk3549dd/PRlNL4F8y736MTD1a43qptD+PvHY97Bo9gSf+OZ8iUWE7BrYSpk/FgLUe40EA==", - "dev": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@types/appdmg": "^0.5.5", - "debug": "^4.3.2", - "minimist": "^1.2.7" - }, - "bin": { - "electron-installer-dmg": "dist/electron-installer-dmg-bin.js" - }, - "engines": { - "node": ">= 16" - }, - "optionalDependencies": { - "appdmg": "^0.6.4" - } - }, - "node_modules/electron-installer-redhat": { - "version": "3.4.0", - "resolved": "https://registry.npmmirror.com/electron-installer-redhat/-/electron-installer-redhat-3.4.0.tgz", - "integrity": "sha512-gEISr3U32Sgtj+fjxUAlSDo3wyGGq6OBx7rF5UdpIgbnpUvMN4W5uYb0ThpnAZ42VEJh/3aODQXHbFS4f5J3Iw==", - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin", - "linux" - ], - "dependencies": { - "@malept/cross-spawn-promise": "^1.0.0", - "debug": "^4.1.1", - "electron-installer-common": "^0.10.2", - "fs-extra": "^9.0.0", - "lodash": "^4.17.15", - "word-wrap": "^1.2.3", - "yargs": "^16.0.2" - }, - "bin": { - "electron-installer-redhat": "src/cli.js" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/electron-installer-redhat/node_modules/@malept/cross-spawn-promise": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", - "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/malept" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" - } - ], - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "cross-spawn": "^7.0.1" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/electron-installer-redhat/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmmirror.com/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "license": "ISC", - "optional": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/electron-installer-redhat/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/electron-installer-redhat/node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/electron-installer-redhat/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/electron-installer-redhat/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/electron-installer-redhat/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/electron-installer-redhat/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmmirror.com/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/electron-installer-redhat/node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "dev": true, - "license": "ISC", - "optional": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/electron-squirrel-startup": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/electron-squirrel-startup/-/electron-squirrel-startup-1.0.1.tgz", - "integrity": "sha512-sTfFIHGku+7PsHLJ7v0dRcZNkALrV+YEozINTW8X1nM//e5O3L+rfYuvSW00lmGHnYmUjARZulD8F2V8ISI9RA==", - "license": "Apache-2.0", - "dependencies": { - "debug": "^2.2.0" - } - }, - "node_modules/electron-squirrel-startup/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/electron-squirrel-startup/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/electron-to-chromium": { - "version": "1.5.307", - "resolved": "https://registry.npmmirror.com/electron-to-chromium/-/electron-to-chromium-1.5.307.tgz", - "integrity": "sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==", - "dev": true, - "license": "ISC" - }, - "node_modules/electron-winstaller": { - "version": "5.4.0", - "resolved": "https://registry.npmmirror.com/electron-winstaller/-/electron-winstaller-5.4.0.tgz", - "integrity": "sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@electron/asar": "^3.2.1", - "debug": "^4.1.1", - "fs-extra": "^7.0.1", - "lodash": "^4.17.21", - "temp": "^0.9.0" - }, - "engines": { - "node": ">=8.0.0" - }, - "optionalDependencies": { - "@electron/windows-sign": "^1.1.2" - } - }, - "node_modules/electron-winstaller/node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/electron-winstaller/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "license": "MIT", - "optional": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/electron-winstaller/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmmirror.com/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/electron/node_modules/@electron/get": { - "version": "2.0.3", - "resolved": "https://registry.npmmirror.com/@electron/get/-/get-2.0.3.tgz", - "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.1.1", - "env-paths": "^2.2.0", - "fs-extra": "^8.1.0", - "got": "^11.8.5", - "progress": "^2.0.3", - "semver": "^6.2.0", - "sumchecker": "^3.0.1" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "global-agent": "^3.0.0" - } - }, - "node_modules/electron/node_modules/@types/node": { - "version": "24.11.0", - "resolved": "https://registry.npmmirror.com/@types/node/-/node-24.11.0.tgz", - "integrity": "sha512-fPxQqz4VTgPI/IQ+lj9r0h+fDR66bzoeMGHp8ASee+32OSGIkeASsoZuJixsQoVef1QJbeubcPBxKk22QVoWdw==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~7.16.0" - } - }, - "node_modules/electron/node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/electron/node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "dev": true, - "license": "MIT", - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/electron/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmmirror.com/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/electron/node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "dev": true, - "license": "MIT" - }, - "node_modules/electron/node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmmirror.com/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT" - }, - "node_modules/encode-utf8": { - "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/encode-utf8/-/encode-utf8-1.0.3.tgz", - "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" - } - }, - "node_modules/encoding/node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.5", - "resolved": "https://registry.npmmirror.com/end-of-stream/-/end-of-stream-1.4.5.tgz", - "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.20.0", - "resolved": "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-5.20.0.tgz", - "integrity": "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.3.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmmirror.com/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmmirror.com/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "dev": true, - "license": "MIT" - }, - "node_modules/error-ex": { - "version": "1.3.4", - "resolved": "https://registry.npmmirror.com/error-ex/-/error-ex-1.3.4.tgz", - "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, - "node_modules/es-abstract": { - "version": "1.24.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", - "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-buffer-byte-length": "^1.0.2", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "data-view-buffer": "^1.0.2", - "data-view-byte-length": "^1.0.2", - "data-view-byte-offset": "^1.0.1", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "es-set-tostringtag": "^2.1.0", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.8", - "get-intrinsic": "^1.3.0", - "get-proto": "^1.0.1", - "get-symbol-description": "^1.1.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.5", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-set": "^2.0.3", - "is-shared-array-buffer": "^1.0.4", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.15", - "is-weakref": "^1.1.1", - "math-intrinsics": "^1.1.0", - "object-inspect": "^1.13.4", - "object-keys": "^1.1.1", - "object.assign": "^4.1.7", - "own-keys": "^1.0.1", - "regexp.prototype.flags": "^1.5.4", - "safe-array-concat": "^1.1.3", - "safe-push-apply": "^1.0.0", - "safe-regex-test": "^1.1.0", - "set-proto": "^1.0.0", - "stop-iteration-iterator": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.3", - "typed-array-byte-length": "^1.0.3", - "typed-array-byte-offset": "^1.0.4", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.1.0", - "which-typed-array": "^1.1.19" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-iterator-helpers": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.3.2.tgz", - "integrity": "sha512-HVLACW1TppGYjJ8H6/jqH/pqOtKRw6wMlrB23xfExmFWxFquAIWCmwoLsOyN96K4a5KbmOf5At9ZUO3GZbetAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.9", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.24.2", - "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.1.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.3.0", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "internal-slot": "^1.1.0", - "iterator.prototype": "^1.1.5", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-module-lexer": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/es-module-lexer/-/es-module-lexer-2.0.0.tgz", - "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", - "dev": true, - "license": "MIT" - }, - "node_modules/es-object-atoms": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", - "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-shim-unscopables": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", - "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-to-primitive": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", - "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.2.7", - "is-date-object": "^1.0.5", - "is-symbol": "^1.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmmirror.com/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/esbuild": { - "version": "0.27.3", - "resolved": "https://registry.npmmirror.com/esbuild/-/esbuild-0.27.3.tgz", - "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.3", - "@esbuild/android-arm": "0.27.3", - "@esbuild/android-arm64": "0.27.3", - "@esbuild/android-x64": "0.27.3", - "@esbuild/darwin-arm64": "0.27.3", - "@esbuild/darwin-x64": "0.27.3", - "@esbuild/freebsd-arm64": "0.27.3", - "@esbuild/freebsd-x64": "0.27.3", - "@esbuild/linux-arm": "0.27.3", - "@esbuild/linux-arm64": "0.27.3", - "@esbuild/linux-ia32": "0.27.3", - "@esbuild/linux-loong64": "0.27.3", - "@esbuild/linux-mips64el": "0.27.3", - "@esbuild/linux-ppc64": "0.27.3", - "@esbuild/linux-riscv64": "0.27.3", - "@esbuild/linux-s390x": "0.27.3", - "@esbuild/linux-x64": "0.27.3", - "@esbuild/netbsd-arm64": "0.27.3", - "@esbuild/netbsd-x64": "0.27.3", - "@esbuild/openbsd-arm64": "0.27.3", - "@esbuild/openbsd-x64": "0.27.3", - "@esbuild/openharmony-arm64": "0.27.3", - "@esbuild/sunos-x64": "0.27.3", - "@esbuild/win32-arm64": "0.27.3", - "@esbuild/win32-ia32": "0.27.3", - "@esbuild/win32-x64": "0.27.3" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmmirror.com/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "9.39.4", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", - "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.8.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.2", - "@eslint/config-helpers": "^0.4.2", - "@eslint/core": "^0.17.0", - "@eslint/eslintrc": "^3.3.5", - "@eslint/js": "9.39.4", - "@eslint/plugin-kit": "^0.4.1", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.2", - "@types/estree": "^1.0.6", - "ajv": "^6.14.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.6", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.4.0", - "eslint-visitor-keys": "^4.2.1", - "espree": "^10.4.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.5", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } - } - }, - "node_modules/eslint-config-prettier": { - "version": "10.1.8", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", - "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", - "dev": true, - "license": "MIT", - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "funding": { - "url": "https://opencollective.com/eslint-config-prettier" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-react": { - "version": "7.37.5", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", - "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-includes": "^3.1.8", - "array.prototype.findlast": "^1.2.5", - "array.prototype.flatmap": "^1.3.3", - "array.prototype.tosorted": "^1.1.4", - "doctrine": "^2.1.0", - "es-iterator-helpers": "^1.2.1", - "estraverse": "^5.3.0", - "hasown": "^2.0.2", - "jsx-ast-utils": "^2.4.1 || ^3.0.0", - "minimatch": "^3.1.2", - "object.entries": "^1.1.9", - "object.fromentries": "^2.0.8", - "object.values": "^1.2.1", - "prop-types": "^15.8.1", - "resolve": "^2.0.0-next.5", - "semver": "^6.3.1", - "string.prototype.matchall": "^4.0.12", - "string.prototype.repeat": "^1.0.0" - }, - "engines": { - "node": ">=4" - }, - "peerDependencies": { - "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", - "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.24.4", - "@babel/parser": "^7.24.4", - "hermes-parser": "^0.25.1", - "zod": "^3.25.0 || ^4.0.0", - "zod-validation-error": "^3.5.0 || ^4.0.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint-plugin-react/node_modules/resolve": { - "version": "2.0.0-next.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", - "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "is-core-module": "^2.16.2", - "node-exports-info": "^1.6.0", - "object-keys": "^1.1.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/ajv": { - "version": "6.15.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", - "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/eslint/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/espree": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.15.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", - "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eventemitter3": { - "version": "5.0.4", - "resolved": "https://registry.npmmirror.com/eventemitter3/-/eventemitter3-5.0.4.tgz", - "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", - "dev": true, - "license": "MIT" - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmmirror.com/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/execa": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/execa/-/execa-1.0.0.tgz", - "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^6.0.0", - "get-stream": "^4.0.0", - "is-stream": "^1.1.0", - "npm-run-path": "^2.0.0", - "p-finally": "^1.0.0", - "signal-exit": "^3.0.0", - "strip-eof": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/execa/node_modules/cross-spawn": { - "version": "6.0.6", - "resolved": "https://registry.npmmirror.com/cross-spawn/-/cross-spawn-6.0.6.tgz", - "integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==", - "dev": true, - "license": "MIT", - "dependencies": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" - }, - "engines": { - "node": ">=4.8" - } - }, - "node_modules/execa/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/execa/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/execa/node_modules/shebang-command": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-1.2.0.tgz", - "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/execa/node_modules/shebang-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-1.0.0.tgz", - "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/execa/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/execa/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmmirror.com/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/exponential-backoff": { - "version": "3.1.3", - "resolved": "https://registry.npmmirror.com/exponential-backoff/-/exponential-backoff-3.1.3.tgz", - "integrity": "sha512-ZgEeZXj30q+I0EN+CbSSpIyPaJ5HVQD18Z1m+u1FXbAeT94mr1zw50q4q6jiiC447Nl/YTcIYSAftiGqetwXCA==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/external-editor": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/external-editor/-/external-editor-3.1.0.tgz", - "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", - "dev": true, - "license": "MIT", - "dependencies": { - "chardet": "^0.7.0", - "iconv-lite": "^0.4.24", - "tmp": "^0.0.33" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" - } - }, - "node_modules/extract-zip/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmmirror.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmmirror.com/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/fastq": { - "version": "1.20.1", - "resolved": "https://registry.npmmirror.com/fastq/-/fastq-1.20.1.tgz", - "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/filename-reserved-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz", - "integrity": "sha512-lc1bnsSr4L4Bdif8Xb/qrtokGbq5zlsms/CYH8PP+WtCkGNF65DPiQY8vG3SakEdRn8Dlnm+gW/qWKKjS5sZzQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/filenamify": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/filenamify/-/filenamify-4.3.0.tgz", - "integrity": "sha512-hcFKyUG57yWGAzu1CMt/dPzYZuv+jAJUT85bL8mrXvNe6hWj6yEHEc4EdcgiA6Z3oi1/9wXJdZPXF2dZNgwgOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "filename-reserved-regex": "^2.0.0", - "strip-outer": "^1.0.1", - "trim-repeated": "^1.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmmirror.com/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/flatted": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", - "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", - "dev": true, - "license": "ISC" - }, - "node_modules/flora-colossus": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/flora-colossus/-/flora-colossus-2.0.0.tgz", - "integrity": "sha512-dz4HxH6pOvbUzZpZ/yXhafjbR2I8cenK5xL0KtBFb7U2ADsR+OwXifnxZjij/pZWF775uSCMzWVd+jDik2H2IA==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4", - "fs-extra": "^10.1.0" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/fmix": { - "version": "0.1.0", - "resolved": "https://registry.npmmirror.com/fmix/-/fmix-0.1.0.tgz", - "integrity": "sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "imul": "^1.0.0" - } - }, - "node_modules/for-each": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", - "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmmirror.com/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-temp": { - "version": "1.2.1", - "resolved": "https://registry.npmmirror.com/fs-temp/-/fs-temp-1.2.1.tgz", - "integrity": "sha512-okTwLB7/Qsq82G6iN5zZJFsOfZtx2/pqrA7Hk/9fvy+c+eJS9CvgGXT2uNxwnI14BDY9L/jQPkaBgSvlKfSW9w==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "random-path": "^0.1.0" - } - }, - "node_modules/fs-xattr": { - "version": "0.3.1", - "resolved": "https://registry.npmmirror.com/fs-xattr/-/fs-xattr-0.3.1.tgz", - "integrity": "sha512-UVqkrEW0GfDabw4C3HOrFlxKfx0eeigfRne69FxSBdHIP8Qt5Sq6Pu3RM9KmMlkygtC4pPKkj5CiPO5USnj2GA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "!win32" - ], - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "license": "ISC" - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmmirror.com/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmmirror.com/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/function.prototype.name": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", - "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "functions-have-names": "^1.2.3", - "hasown": "^2.0.2", - "is-callable": "^1.2.7" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/galactus": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/galactus/-/galactus-1.0.0.tgz", - "integrity": "sha512-R1fam6D4CyKQGNlvJne4dkNF+PvUUl7TAJInvTGa9fti9qAv95quQz29GXapA4d8Ec266mJJxFVh82M4GIIGDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4", - "flora-colossus": "^2.0.0", - "fs-extra": "^10.1.0" - }, - "engines": { - "node": ">= 12" - } - }, - "node_modules/gar": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/gar/-/gar-1.0.4.tgz", - "integrity": "sha512-w4n9cPWyP7aHxKxYHFQMegj7WIAsL/YX/C4Bs5Rr8s1H9M1rNtRWRsw+ovYMkXDQ5S4ZbYHsHAPmevPjPgw44w==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/generate-function": { - "version": "2.3.1", - "resolved": "https://registry.npmmirror.com/generate-function/-/generate-function-2.3.1.tgz", - "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "is-property": "^1.0.2" - } - }, - "node_modules/generate-object-property": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/generate-object-property/-/generate-object-property-1.2.0.tgz", - "integrity": "sha512-TuOwZWgJ2VAMEGJvAyPWvpqxSANF0LDpmyHauMjFYzaACvn+QTT/AZomvPCzVBV7yDN3OmwHQ5OvHaeLKre3JQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "is-property": "^1.0.0" - } - }, - "node_modules/generator-function": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", - "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-folder-size": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/get-folder-size/-/get-folder-size-2.0.1.tgz", - "integrity": "sha512-+CEb+GDCM7tkOS2wdMKTn9vU7DgnKUTuDlehkNJKNSovdCOVxs14OfKCk4cvSaR3za4gj+OBdl9opPN9xrJ0zA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "gar": "^1.0.4", - "tiny-each-async": "2.0.3" - }, - "bin": { - "get-folder-size": "bin/get-folder-size" - } - }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-package-info": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/get-package-info/-/get-package-info-1.0.0.tgz", - "integrity": "sha512-SCbprXGAPdIhKAXiG+Mk6yeoFH61JlYunqdFQFHDtLjJlDjFf6x07dsS8acO+xWt52jpdVo49AlVDnUVK1sDNw==", - "dev": true, - "license": "MIT", - "dependencies": { - "bluebird": "^3.1.1", - "debug": "^2.2.0", - "lodash.get": "^4.0.0", - "read-pkg-up": "^2.0.0" - }, - "engines": { - "node": ">= 4.0" - } - }, - "node_modules/get-package-info/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmmirror.com/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/get-package-info/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "dev": true, - "license": "MIT" - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "license": "MIT", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/get-symbol-description": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", - "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmmirror.com/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmmirror.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/global-agent": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/global-agent/-/global-agent-3.0.0.tgz", - "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", - "dev": true, - "license": "BSD-3-Clause", - "optional": true, - "dependencies": { - "boolean": "^3.0.1", - "es6-error": "^4.1.1", - "matcher": "^3.0.0", - "roarr": "^2.15.3", - "semver": "^7.3.2", - "serialize-error": "^7.0.1" - }, - "engines": { - "node": ">=10.0" - } - }, - "node_modules/global-dirs": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/global-dirs/-/global-dirs-3.0.1.tgz", - "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ini": "2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globals": { - "version": "17.6.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-17.6.0.tgz", - "integrity": "sha512-sepffkT8stwnIYbsMBpoCHJuJM5l98FUF2AnE07hfvE0m/qp3R586hw4jF4uadbhvg1ooIdzuu7CsfD2jzCaNA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/got": { - "version": "11.8.6", - "resolved": "https://registry.npmmirror.com/got/-/got-11.8.6.tgz", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=10.19.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmmirror.com/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/has-bigints": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", - "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", - "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", - "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hermes-estree": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", - "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", - "dev": true, - "license": "MIT" - }, - "node_modules/hermes-parser": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", - "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "hermes-estree": "0.25.1" - } - }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmmirror.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true, - "license": "ISC" - }, - "node_modules/http-cache-semantics": { - "version": "4.2.0", - "resolved": "https://registry.npmmirror.com/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dev": true, - "license": "MIT", - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" - }, - "engines": { - "node": ">=10.19.0" - } - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmmirror.com/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.0.0" - } - }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmmirror.com/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmmirror.com/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/image-size": { - "version": "0.7.5", - "resolved": "https://registry.npmmirror.com/image-size/-/image-size-0.7.5.tgz", - "integrity": "sha512-Hiyv+mXHfFEP7LzUL/llg9RwFxxY+o9N3JVLIeG5E7iFIFAalxvRU9UZthBdYDEVnzHMgjnKJPPpay5BWf1g9g==", - "dev": true, - "license": "MIT", - "optional": true, - "bin": { - "image-size": "bin/image-size.js" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imul": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/imul/-/imul-1.0.1.tgz", - "integrity": "sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmmirror.com/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "dev": true, - "license": "ISC" - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmmirror.com/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmmirror.com/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/ini": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/internal-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", - "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.2", - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/interpret": { - "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/interpret/-/interpret-3.1.1.tgz", - "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/ip-address": { - "version": "10.1.0", - "resolved": "https://registry.npmmirror.com/ip-address/-/ip-address-10.1.0.tgz", - "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/is-array-buffer": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", - "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmmirror.com/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-async-function": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", - "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "async-function": "^1.0.0", - "call-bound": "^1.0.3", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-bigint": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", - "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-bigints": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-boolean-object": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", - "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-core-module": { - "version": "2.16.2", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", - "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-data-view": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", - "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-date-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", - "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finalizationregistry": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", - "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-generator-function": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", - "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.4", - "generator-function": "^2.0.0", - "get-proto": "^1.0.1", - "has-tostringtag": "^1.0.2", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-my-ip-valid": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/is-my-ip-valid/-/is-my-ip-valid-1.0.1.tgz", - "integrity": "sha512-jxc8cBcOWbNK2i2aTkCZP6i7wkHF1bqKFrwEHuN5Jtg5BSaZHUZQ/JTOJwoV41YvHnOaRyWWh72T/KvfNz9DJg==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/is-my-json-valid": { - "version": "2.20.6", - "resolved": "https://registry.npmmirror.com/is-my-json-valid/-/is-my-json-valid-2.20.6.tgz", - "integrity": "sha512-1JQwulVNjx8UqkPE/bqDaxtH4PXCe/2VRh/y3p99heOV87HG4Id5/VfDswd+YiAfHcRTfDlWgISycnHuhZq1aw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "generate-function": "^2.0.0", - "generate-object-property": "^1.1.0", - "is-my-ip-valid": "^1.0.0", - "jsonpointer": "^5.0.0", - "xtend": "^4.0.0" - } - }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmmirror.com/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-object": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", - "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-property": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/is-property/-/is-property-1.0.2.tgz", - "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/is-regex": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", - "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-set": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", - "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-string": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", - "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-symbol": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", - "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-symbols": "^1.1.0", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", - "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmmirror.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakref": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", - "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-weakset": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", - "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true, - "license": "MIT" - }, - "node_modules/isbinaryfile": { - "version": "4.0.10", - "resolved": "https://registry.npmmirror.com/isbinaryfile/-/isbinaryfile-4.0.10.tgz", - "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/gjtorikian/" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/iterator.prototype": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", - "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.6", - "get-proto": "^1.0.0", - "has-symbols": "^1.1.0", - "set-function-name": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmmirror.com/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/jest-worker/node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/jiti": { - "version": "2.6.1", - "resolved": "https://registry.npmmirror.com/jiti/-/jiti-2.6.1.tgz", - "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", - "dev": true, - "license": "MIT", - "bin": { - "jiti": "lib/jiti-cli.mjs" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", - "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/puzrin" - }, - { - "type": "github", - "url": "https://github.com/sponsors/nodeca" - } - ], - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmmirror.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true, - "license": "ISC", - "optional": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonfile": { - "version": "6.2.0", - "resolved": "https://registry.npmmirror.com/jsonfile/-/jsonfile-6.2.0.tgz", - "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsonpointer": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/jsonpointer/-/jsonpointer-5.0.1.tgz", - "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jsx-ast-utils": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", - "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.flat": "^1.3.1", - "object.assign": "^4.1.4", - "object.values": "^1.1.6" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/junk": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/junk/-/junk-3.1.0.tgz", - "integrity": "sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmmirror.com/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/listr2": { - "version": "7.0.2", - "resolved": "https://registry.npmmirror.com/listr2/-/listr2-7.0.2.tgz", - "integrity": "sha512-rJysbR9GKIalhTbVL2tYbF2hVyDnrf7pFUZBwjPaMIdadYHmeT+EVi/Bu3qd7ETQPahTotg2WRCatXwRBW554g==", - "dev": true, - "license": "MIT", - "dependencies": { - "cli-truncate": "^3.1.0", - "colorette": "^2.0.20", - "eventemitter3": "^5.0.1", - "log-update": "^5.0.1", - "rfdc": "^1.3.0", - "wrap-ansi": "^8.1.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/listr2/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/listr2/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/listr2/node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/listr2/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha512-3p6ZOGNbiX4CdvEd1VcE6yi78UrGNpjHO33noGwHCnT/o2fyllJDepsm8+mFFv/DvtwFHht5HIHSyOy5a+ChVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/loader-runner": { - "version": "4.3.1", - "resolved": "https://registry.npmmirror.com/loader-runner/-/loader-runner-4.3.1.tgz", - "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.11.5" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.23", - "resolved": "https://registry.npmmirror.com/lodash/-/lodash-4.17.23.tgz", - "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmmirror.com/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.", - "dev": true, - "license": "MIT" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/log-update/-/log-update-5.0.1.tgz", - "integrity": "sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-escapes": "^5.0.0", - "cli-cursor": "^4.0.0", - "slice-ansi": "^5.0.0", - "strip-ansi": "^7.0.1", - "wrap-ansi": "^8.0.1" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/ansi-escapes": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/ansi-escapes/-/ansi-escapes-5.0.0.tgz", - "integrity": "sha512-5GFMVX8HqE/TB+FuBJGuO5XG0WrsA6ptUqoODaT/n9mmUaZFkqnBueB4leqGBCmrUHnCnC4PCZTCd0E7QQ83bA==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^1.0.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/log-update/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-update/node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/log-update/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/macos-alias": { - "version": "0.2.12", - "resolved": "https://registry.npmmirror.com/macos-alias/-/macos-alias-0.2.12.tgz", - "integrity": "sha512-yiLHa7cfJcGRFq4FrR4tMlpNHb4Vy4mWnpajlSSIFM5k4Lv8/7BbbDLzCAVogWNl0LlLhizRp1drXv0hK9h0Yw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "dependencies": { - "nan": "^2.4.0" - } - }, - "node_modules/make-fetch-happen": { - "version": "10.2.1", - "resolved": "https://registry.npmmirror.com/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", - "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", - "dev": true, - "license": "ISC", - "dependencies": { - "agentkeepalive": "^4.2.1", - "cacache": "^16.1.0", - "http-cache-semantics": "^4.1.0", - "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", - "is-lambda": "^1.0.1", - "lru-cache": "^7.7.1", - "minipass": "^3.1.6", - "minipass-collect": "^1.0.2", - "minipass-fetch": "^2.0.3", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.4", - "negotiator": "^0.6.3", - "promise-retry": "^2.0.1", - "socks-proxy-agent": "^7.0.0", - "ssri": "^9.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/make-fetch-happen/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmmirror.com/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/map-age-cleaner": { - "version": "0.1.3", - "resolved": "https://registry.npmmirror.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", - "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-defer": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/matcher": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/matcher/-/matcher-3.0.0.tgz", - "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "escape-string-regexp": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/mem": { - "version": "4.3.0", - "resolved": "https://registry.npmmirror.com/mem/-/mem-4.3.0.tgz", - "integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "map-age-cleaner": "^0.1.1", - "mimic-fn": "^2.0.0", - "p-is-promise": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, - "license": "MIT" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmmirror.com/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmmirror.com/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmmirror.com/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmmirror.com/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmmirror.com/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-collect": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/minipass-collect/-/minipass-collect-1.0.2.tgz", - "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-fetch": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/minipass-fetch/-/minipass-fetch-2.1.2.tgz", - "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^3.1.6", - "minipass-sized": "^1.0.3", - "minizlib": "^2.1.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - }, - "optionalDependencies": { - "encoding": "^0.1.13" - } - }, - "node_modules/minipass-flush": { - "version": "1.0.5", - "resolved": "https://registry.npmmirror.com/minipass-flush/-/minipass-flush-1.0.5.tgz", - "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minipass-pipeline": { - "version": "1.2.4", - "resolved": "https://registry.npmmirror.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", - "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass-sized": { - "version": "1.0.3", - "resolved": "https://registry.npmmirror.com/minipass-sized/-/minipass-sized-1.0.3.tgz", - "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/minipass/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "license": "MIT", - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/murmur-32": { - "version": "0.2.0", - "resolved": "https://registry.npmmirror.com/murmur-32/-/murmur-32-0.2.0.tgz", - "integrity": "sha512-ZkcWZudylwF+ir3Ld1n7gL6bI2mQAzXvSobPwVtu8aYi2sbXeipeSkdcanRLzIofLcM5F53lGaKm2dk7orBi7Q==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "encode-utf8": "^1.0.3", - "fmix": "^0.1.0", - "imul": "^1.0.0" - } - }, - "node_modules/mute-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/mute-stream/-/mute-stream-1.0.0.tgz", - "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/nan": { - "version": "2.25.0", - "resolved": "https://registry.npmmirror.com/nan/-/nan-2.25.0.tgz", - "integrity": "sha512-0M90Ag7Xn5KMLLZ7zliPWP3rT90P6PN+IzVFS0VqmnPktBk3700xUVv8Ikm9EUaUE5SDWdp/BIxdENzVznpm1g==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" - }, - "node_modules/negotiator": { - "version": "0.6.4", - "resolved": "https://registry.npmmirror.com/negotiator/-/negotiator-0.6.4.tgz", - "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmmirror.com/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true, - "license": "MIT" - }, - "node_modules/nice-try": { - "version": "1.0.5", - "resolved": "https://registry.npmmirror.com/nice-try/-/nice-try-1.0.5.tgz", - "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/node-abi": { - "version": "3.87.0", - "resolved": "https://registry.npmmirror.com/node-abi/-/node-abi-3.87.0.tgz", - "integrity": "sha512-+CGM1L1CgmtheLcBuleyYOn7NWPVu0s0EJH2C4puxgEZb9h8QpR9G2dBfZJOAUhi7VQxuBPMd0hiISWcTyiYyQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.3.5" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/node-api-version": { - "version": "0.2.1", - "resolved": "https://registry.npmmirror.com/node-api-version/-/node-api-version-0.2.1.tgz", - "integrity": "sha512-2xP/IGGMmmSQpI1+O/k72jF/ykvZ89JeuKX3TLJAYPDVLUalrshrLHkeVcCCZqG/eEa635cr8IBYzgnDvM2O8Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "semver": "^7.3.5" - } - }, - "node_modules/node-exports-info": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.0.tgz", - "integrity": "sha512-pyFS63ptit/P5WqUkt+UUfe+4oevH+bFeIiPPdfb0pFeYEu/1ELnJu5l+5EcTKYL5M7zaAa7S8ddywgXypqKCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "array.prototype.flatmap": "^1.3.3", - "es-errors": "^1.3.0", - "object.entries": "^1.1.9", - "semver": "^6.3.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/node-exports-info/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmmirror.com/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-releases": { - "version": "2.0.36", - "resolved": "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.36.tgz", - "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", - "dev": true, - "license": "MIT" - }, - "node_modules/nopt": { - "version": "6.0.0", - "resolved": "https://registry.npmmirror.com/nopt/-/nopt-6.0.0.tgz", - "integrity": "sha512-ZwLpbTgdhuZUnZzjd7nb1ZV+4DoiC6/sfiVKok72ym/4Tlf+DFdlHYmT2JPmcNNWV6Pi3SDf1kT+A4r9RTuT9g==", - "dev": true, - "license": "ISC", - "dependencies": { - "abbrev": "^1.0.0" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmmirror.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmmirror.com/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmmirror.com/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/npm-run-path": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/npm-run-path/-/npm-run-path-2.0.2.tgz", - "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/npm-run-path/node_modules/path-key": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/path-key/-/path-key-2.0.1.tgz", - "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-inspect": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", - "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", - "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0", - "has-symbols": "^1.1.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.entries": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", - "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.fromentries": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/object.values": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", - "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmmirror.com/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmmirror.com/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora/node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ora/node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ora/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/own-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", - "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.6", - "object-keys": "^1.1.1", - "safe-push-apply": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/p-defer": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/p-defer/-/p-defer-1.0.0.tgz", - "integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/p-finally": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/p-finally/-/p-finally-1.0.0.tgz", - "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/p-is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/p-is-promise/-/p-is-promise-2.1.0.tgz", - "integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/parse-author": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/parse-author/-/parse-author-2.0.0.tgz", - "integrity": "sha512-yx5DfvkN8JsHL2xk2Os9oTia467qnvRgey4ahSm2X8epehBLx/gWLcy5KI+Y36ful5DzGbCS6RazqZGgy1gHNw==", - "dev": true, - "license": "MIT", - "dependencies": { - "author-regex": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/parse-color": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/parse-color/-/parse-color-1.0.0.tgz", - "integrity": "sha512-fuDHYgFHJGbpGMgw9skY/bj3HL/Jrn4l/5rSspy00DoT4RyLnDcRvPxdZ+r6OFwIsgAuhDh4I09tAId4mI12bw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "color-convert": "~0.5.0" - } - }, - "node_modules/parse-color/node_modules/color-convert": { - "version": "0.5.3", - "resolved": "https://registry.npmmirror.com/color-convert/-/color-convert-0.5.3.tgz", - "integrity": "sha512-RwBeO/B/vZR3dfKL1ye/vx8MHZ40ugzpyfeVG5GsiuGnrlMWe2o8wxBbLCpw9CsxV+wHuzYlCiWnybrIA0ling==", - "dev": true, - "optional": true - }, - "node_modules/parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "error-ex": "^1.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmmirror.com/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha512-dUnb5dXUf+kzhC/W/F4e5/SkluXIFf5VUHolW1Eg1irn1hGWjPGdsRcvYJ1nD6lhk8Ir7VM0bHJKsYTx8Jx9OQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "pify": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/pe-library": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/pe-library/-/pe-library-1.0.1.tgz", - "integrity": "sha512-nh39Mo1eGWmZS7y+mK/dQIqg7S1lp38DpRxkyoHf0ZcUs/HDc+yyTjuOtTvSMZHmfSLuSQaX945u05Y2Q6UWZg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14", - "npm": ">=7" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/jet2jet" - } - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true, - "license": "MIT" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmmirror.com/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/plist": { - "version": "3.1.0", - "resolved": "https://registry.npmmirror.com/plist/-/plist-3.1.0.tgz", - "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@xmldom/xmldom": "^0.8.8", - "base64-js": "^1.5.1", - "xmlbuilder": "^15.1.1" - }, - "engines": { - "node": ">=10.4.0" - } - }, - "node_modules/pngjs": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", - "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", - "license": "MIT", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/possible-typed-array-names": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", - "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/postcss": { - "version": "8.5.8", - "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.8.tgz", - "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postject": { - "version": "1.0.0-alpha.6", - "resolved": "https://registry.npmmirror.com/postject/-/postject-1.0.0-alpha.6.tgz", - "integrity": "sha512-b9Eb8h2eVqNE8edvKdwqkrY6O7kAwmI8kcnBv1NScolYJbo59XUF0noFq+lxbC1yN20bmC0WBEbDC5H/7ASb0A==", - "dev": true, - "license": "MIT", - "dependencies": { - "commander": "^9.4.0" - }, - "bin": { - "postject": "dist/cli.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/postject/node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmmirror.com/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.20.0 || >=14" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz", - "integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==", - "dev": true, - "license": "MIT", - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/proc-log": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/proc-log/-/proc-log-2.0.1.tgz", - "integrity": "sha512-Kcmo2FhfDTXdcbfDH76N7uBYHINxc/8GW7UAVuVP9I+Va3uHSerrnKV6dLooga/gh7GlgzuCCr/eoldnL1muGw==", - "dev": true, - "license": "ISC", - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmmirror.com/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/promise-inflight": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/promise-inflight/-/promise-inflight-1.0.1.tgz", - "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", - "dev": true, - "license": "ISC" - }, - "node_modules/promise-retry": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/promise-retry/-/promise-retry-2.0.1.tgz", - "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "err-code": "^2.0.2", - "retry": "^0.12.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, - "license": "MIT", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "node_modules/pump": { - "version": "3.0.4", - "resolved": "https://registry.npmmirror.com/pump/-/pump-3.0.4.tgz", - "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", - "dev": true, - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/qrcode": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", - "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", - "license": "MIT", - "dependencies": { - "dijkstrajs": "^1.0.1", - "pngjs": "^5.0.0", - "yargs": "^15.3.1" - }, - "bin": { - "qrcode": "bin/qrcode" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/qrcode/node_modules/cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "node_modules/qrcode/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/qrcode/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/qrcode/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/qrcode/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "license": "MIT", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/qrcode/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "license": "MIT", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/qrcode/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/qrcode/node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/qrcode/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/qrcode/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "license": "ISC" - }, - "node_modules/qrcode/node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "license": "MIT", - "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/qrcode/node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "license": "ISC", - "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmmirror.com/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/random-path": { - "version": "0.1.2", - "resolved": "https://registry.npmmirror.com/random-path/-/random-path-0.1.2.tgz", - "integrity": "sha512-4jY0yoEaQ5v9StCl5kZbNIQlg1QheIDBrdkDn53EynpPb9FgO6//p3X/tgMnrC45XN6QZCzU1Xz/+pSSsJBpRw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "base32-encode": "^0.1.0 || ^1.0.0", - "murmur-32": "^0.1.0 || ^0.2.0" - } - }, - "node_modules/react": { - "version": "19.2.4", - "resolved": "https://registry.npmmirror.com/react/-/react-19.2.4.tgz", - "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "19.2.4", - "resolved": "https://registry.npmmirror.com/react-dom/-/react-dom-19.2.4.tgz", - "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", - "license": "MIT", - "dependencies": { - "scheduler": "^0.27.0" - }, - "peerDependencies": { - "react": "^19.2.4" - } - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/react-refresh": { - "version": "0.18.0", - "resolved": "https://registry.npmmirror.com/react-refresh/-/react-refresh-0.18.0.tgz", - "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-binary-file-arch": { - "version": "1.0.6", - "resolved": "https://registry.npmmirror.com/read-binary-file-arch/-/read-binary-file-arch-1.0.6.tgz", - "integrity": "sha512-BNg9EN3DD3GsDXX7Aa8O4p92sryjkmzYYgmgTAc6CA4uGLEDzFfxOxugu21akOxpcXHiEgsYkC6nPsQvLLLmEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4" - }, - "bin": { - "read-binary-file-arch": "cli.js" - } - }, - "node_modules/read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha512-eFIBOPW7FGjzBuk3hdXEuNSiTZS/xEMlH49HxMyzb0hyPfu4EhVjT2DH32K1hSSmVq4sebAWnZuuY5auISUTGA==", - "dev": true, - "license": "MIT", - "dependencies": { - "load-json-file": "^2.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha512-1orxQfbWGUiTn9XsPlChs6rLie/AV9jwZTGmu2NZw/CUDJQchXJFYE0Fq5j7+n558T1JhDWLdhyd1Zj+wLY//w==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^2.0.0", - "read-pkg": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmmirror.com/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up/node_modules/locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up/node_modules/p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-try": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up/node_modules/p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^1.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/read-pkg-up/node_modules/path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmmirror.com/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdirp": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/readdirp/-/readdirp-5.0.0.tgz", - "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", - "license": "MIT", - "engines": { - "node": ">= 20.19.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/rechoir": { - "version": "0.8.0", - "resolved": "https://registry.npmmirror.com/rechoir/-/rechoir-0.8.0.tgz", - "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve": "^1.20.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", - "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.9", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.7", - "get-proto": "^1.0.1", - "which-builtin-type": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.4", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", - "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "set-function-name": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmmirror.com/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmmirror.com/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "license": "ISC" - }, - "node_modules/resedit": { - "version": "2.0.3", - "resolved": "https://registry.npmmirror.com/resedit/-/resedit-2.0.3.tgz", - "integrity": "sha512-oTeemxwoMuxxTYxXUwjkrOPfngTQehlv0/HoYFNkB4uzsP1Un1A9nI8JQKGOFkxpqkC7qkMs0lUsGrvUlbLNUA==", - "dev": true, - "license": "MIT", - "dependencies": { - "pe-library": "^1.0.1" - }, - "engines": { - "node": ">=14", - "npm": ">=7" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/jet2jet" - } - }, - "node_modules/resolve": { - "version": "1.22.11", - "resolved": "https://registry.npmmirror.com/resolve/-/resolve-1.22.11.tgz", - "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.16.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmmirror.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true, - "license": "MIT" - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/responselike": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "dev": true, - "license": "MIT", - "dependencies": { - "lowercase-keys": "^2.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/restore-cursor": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/restore-cursor/-/restore-cursor-4.0.0.tgz", - "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", - "dev": true, - "license": "MIT", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/restore-cursor/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/retry": { - "version": "0.12.0", - "resolved": "https://registry.npmmirror.com/retry/-/retry-0.12.0.tgz", - "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rfdc": { - "version": "1.4.1", - "resolved": "https://registry.npmmirror.com/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "dev": true, - "license": "MIT" - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/roarr": { - "version": "2.15.4", - "resolved": "https://registry.npmmirror.com/roarr/-/roarr-2.15.4.tgz", - "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", - "dev": true, - "license": "BSD-3-Clause", - "optional": true, - "dependencies": { - "boolean": "^3.0.1", - "detect-node": "^2.0.4", - "globalthis": "^1.0.1", - "json-stringify-safe": "^5.0.1", - "semver-compare": "^1.0.0", - "sprintf-js": "^1.1.2" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/rollup": { - "version": "4.59.0", - "resolved": "https://registry.npmmirror.com/rollup/-/rollup-4.59.0.tgz", - "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.59.0", - "@rollup/rollup-android-arm64": "4.59.0", - "@rollup/rollup-darwin-arm64": "4.59.0", - "@rollup/rollup-darwin-x64": "4.59.0", - "@rollup/rollup-freebsd-arm64": "4.59.0", - "@rollup/rollup-freebsd-x64": "4.59.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", - "@rollup/rollup-linux-arm-musleabihf": "4.59.0", - "@rollup/rollup-linux-arm64-gnu": "4.59.0", - "@rollup/rollup-linux-arm64-musl": "4.59.0", - "@rollup/rollup-linux-loong64-gnu": "4.59.0", - "@rollup/rollup-linux-loong64-musl": "4.59.0", - "@rollup/rollup-linux-ppc64-gnu": "4.59.0", - "@rollup/rollup-linux-ppc64-musl": "4.59.0", - "@rollup/rollup-linux-riscv64-gnu": "4.59.0", - "@rollup/rollup-linux-riscv64-musl": "4.59.0", - "@rollup/rollup-linux-s390x-gnu": "4.59.0", - "@rollup/rollup-linux-x64-gnu": "4.59.0", - "@rollup/rollup-linux-x64-musl": "4.59.0", - "@rollup/rollup-openbsd-x64": "4.59.0", - "@rollup/rollup-openharmony-arm64": "4.59.0", - "@rollup/rollup-win32-arm64-msvc": "4.59.0", - "@rollup/rollup-win32-ia32-msvc": "4.59.0", - "@rollup/rollup-win32-x64-gnu": "4.59.0", - "@rollup/rollup-win32-x64-msvc": "4.59.0", - "fsevents": "~2.3.2" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmmirror.com/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-array-concat": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz", - "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.9", - "call-bound": "^1.0.4", - "get-intrinsic": "^1.3.0", - "has-symbols": "^1.1.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmmirror.com/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/safe-push-apply": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", - "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-regex-test": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", - "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-regex": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmmirror.com/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "license": "MIT" - }, - "node_modules/scheduler": { - "version": "0.27.0", - "resolved": "https://registry.npmmirror.com/scheduler/-/scheduler-0.27.0.tgz", - "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", - "license": "MIT" - }, - "node_modules/schema-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmmirror.com/schema-utils/-/schema-utils-4.3.3.tgz", - "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/semver": { - "version": "7.7.4", - "resolved": "https://registry.npmmirror.com/semver/-/semver-7.7.4.tgz", - "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/serialize-error": { - "version": "7.0.1", - "resolved": "https://registry.npmmirror.com/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "type-fest": "^0.13.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/serialize-error/node_modules/type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "optional": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "license": "ISC" - }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/set-proto": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", - "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmmirror.com/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", - "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmmirror.com/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmmirror.com/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/smart-buffer": { - "version": "4.2.0", - "resolved": "https://registry.npmmirror.com/smart-buffer/-/smart-buffer-4.2.0.tgz", - "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks": { - "version": "2.8.7", - "resolved": "https://registry.npmmirror.com/socks/-/socks-2.8.7.tgz", - "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ip-address": "^10.0.1", - "smart-buffer": "^4.2.0" - }, - "engines": { - "node": ">= 10.0.0", - "npm": ">= 3.0.0" - } - }, - "node_modules/socks-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmmirror.com/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", - "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", - "dev": true, - "license": "MIT", - "dependencies": { - "agent-base": "^6.0.2", - "debug": "^4.3.3", - "socks": "^2.6.2" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmmirror.com/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmmirror.com/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/spdx-correct": { - "version": "3.2.0", - "resolved": "https://registry.npmmirror.com/spdx-correct/-/spdx-correct-3.2.0.tgz", - "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-exceptions": { - "version": "2.5.0", - "resolved": "https://registry.npmmirror.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", - "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", - "dev": true, - "license": "CC-BY-3.0" - }, - "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "node_modules/spdx-license-ids": { - "version": "3.0.23", - "resolved": "https://registry.npmmirror.com/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", - "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", - "dev": true, - "license": "CC0-1.0" - }, - "node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmmirror.com/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true, - "license": "BSD-3-Clause", - "optional": true - }, - "node_modules/ssri": { - "version": "9.0.1", - "resolved": "https://registry.npmmirror.com/ssri/-/ssri-9.0.1.tgz", - "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", - "dev": true, - "license": "ISC", - "dependencies": { - "minipass": "^3.1.1" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/stop-iteration-iterator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", - "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "internal-slot": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/stream-buffers": { - "version": "2.2.0", - "resolved": "https://registry.npmmirror.com/stream-buffers/-/stream-buffers-2.2.0.tgz", - "integrity": "sha512-uyQK/mx5QjHun80FLJTfaWE7JtwfRMKBLkMne6udYOmvH0CawotVa7TfgYHzAnpphn4+TweIx1QKMnRIbipmUg==", - "dev": true, - "license": "Unlicense", - "optional": true, - "engines": { - "node": ">= 0.10.0" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmmirror.com/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmmirror.com/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/string-width/node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.2.2" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/string.prototype.matchall": { - "version": "4.0.12", - "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", - "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.6", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.6", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "internal-slot": "^1.1.0", - "regexp.prototype.flags": "^1.5.3", - "set-function-name": "^2.0.2", - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.repeat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", - "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", - "dev": true, - "license": "MIT", - "dependencies": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - } - }, - "node_modules/string.prototype.trim": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", - "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-data-property": "^1.1.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-object-atoms": "^1.0.0", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimend": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", - "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/string.prototype.trimstart": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-eof": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/strip-eof/-/strip-eof-1.0.0.tgz", - "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/strip-outer": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/strip-outer/-/strip-outer-1.0.1.tgz", - "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/strip-outer/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/sumchecker": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/sumchecker/-/sumchecker-3.0.1.tgz", - "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "debug": "^4.1.0" - }, - "engines": { - "node": ">= 8.0" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmmirror.com/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tapable": { - "version": "2.3.0", - "resolved": "https://registry.npmmirror.com/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmmirror.com/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "dev": true, - "license": "ISC", - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/tar/node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=8" - } - }, - "node_modules/tar/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/temp": { - "version": "0.9.4", - "resolved": "https://registry.npmmirror.com/temp/-/temp-0.9.4.tgz", - "integrity": "sha512-yYrrsWnrXMcdsnu/7YMYAofM1ktpL5By7vZhf15CrXijWWrEYZks5AXBudalfSWJLlnen/QUJUB5aoB0kqZUGA==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "mkdirp": "^0.5.1", - "rimraf": "~2.6.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/temp/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmmirror.com/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/temp/node_modules/rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmmirror.com/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "optional": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - } - }, - "node_modules/terser": { - "version": "5.46.0", - "resolved": "https://registry.npmmirror.com/terser/-/terser-5.46.0.tgz", - "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.15.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.17", - "resolved": "https://registry.npmmirror.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.17.tgz", - "integrity": "sha512-YR7PtUp6GMU91BgSJmlaX/rS2lGDbAF7D+Wtq7hRO+MiljNmodYvqslzCFiYVAgW+Qoaaia/QUIP4lGXufjdZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.25", - "jest-worker": "^27.4.5", - "schema-utils": "^4.3.0", - "terser": "^5.31.1" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmmirror.com/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/tiny-each-async": { - "version": "2.0.3", - "resolved": "https://registry.npmmirror.com/tiny-each-async/-/tiny-each-async-2.0.3.tgz", - "integrity": "sha512-5ROII7nElnAirvFn8g7H7MtpfV1daMcyfTGQwsn/x2VtyV+VPiO5CjReCJtWLvoKTDEDmZocf3cNPraiMnBXLA==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmmirror.com/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmmirror.com/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "os-tmpdir": "~1.0.2" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/tmp-promise": { - "version": "3.0.3", - "resolved": "https://registry.npmmirror.com/tmp-promise/-/tmp-promise-3.0.3.tgz", - "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "tmp": "^0.2.0" - } - }, - "node_modules/tmp-promise/node_modules/tmp": { - "version": "0.2.5", - "resolved": "https://registry.npmmirror.com/tmp/-/tmp-0.2.5.tgz", - "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/tn1150": { - "version": "0.1.0", - "resolved": "https://registry.npmmirror.com/tn1150/-/tn1150-0.1.0.tgz", - "integrity": "sha512-DbplOfQFkqG5IHcDyyrs/lkvSr3mPUVsFf/RbDppOshs22yTPnSJWEe6FkYd1txAwU/zcnR905ar2fi4kwF29w==", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "unorm": "^1.4.1" - }, - "engines": { - "node": ">=0.12" - } - }, - "node_modules/to-data-view": { - "version": "1.1.0", - "resolved": "https://registry.npmmirror.com/to-data-view/-/to-data-view-1.1.0.tgz", - "integrity": "sha512-1eAdufMg6mwgmlojAx3QeMnzB/BTVp7Tbndi3U7ftcT2zCZadjxkkmLmd97zmaxWi+sgGcgWrokmpEoy0Dn0vQ==", - "dev": true, - "license": "MIT", - "optional": true - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmmirror.com/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmmirror.com/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true, - "license": "MIT" - }, - "node_modules/trim-repeated": { - "version": "1.0.0", - "resolved": "https://registry.npmmirror.com/trim-repeated/-/trim-repeated-1.0.0.tgz", - "integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^1.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/trim-repeated/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmmirror.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmmirror.com/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typed-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", - "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/typed-array-byte-length": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", - "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.14" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-byte-offset": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", - "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.15", - "reflect.getprototypeof": "^1.0.9" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typed-array-length": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.8.tgz", - "integrity": "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.9", - "for-each": "^0.3.5", - "gopd": "^1.2.0", - "is-typed-array": "^1.1.15", - "possible-typed-array-names": "^1.1.0", - "reflect.getprototypeof": "^1.0.10" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/typescript": { - "version": "5.4.5", - "resolved": "https://registry.npmmirror.com/typescript/-/typescript-5.4.5.tgz", - "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/unbox-primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", - "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "has-bigints": "^1.0.2", - "has-symbols": "^1.1.0", - "which-boxed-primitive": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/undici-types": { - "version": "6.21.0", - "resolved": "https://registry.npmmirror.com/undici-types/-/undici-types-6.21.0.tgz", - "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/unique-filename": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/unique-filename/-/unique-filename-2.0.1.tgz", - "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", - "dev": true, - "license": "ISC", - "dependencies": { - "unique-slug": "^3.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/unique-slug": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/unique-slug/-/unique-slug-3.0.0.tgz", - "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "imurmurhash": "^0.1.4" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmmirror.com/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/unorm": { - "version": "1.6.0", - "resolved": "https://registry.npmmirror.com/unorm/-/unorm-1.6.0.tgz", - "integrity": "sha512-b2/KCUlYZUeA7JFUuRJZPUtr4gZvBh7tavtv4fvk4+KV9pfGiR6CQAQAWl49ZpR3ts2dk4FYkP7EIgDJoiOLDA==", - "dev": true, - "license": "MIT or GPL-2.0", - "optional": true, - "engines": { - "node": ">= 0.4.0" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmmirror.com/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/username": { - "version": "5.1.0", - "resolved": "https://registry.npmmirror.com/username/-/username-5.1.0.tgz", - "integrity": "sha512-PCKbdWw85JsYMvmCv5GH3kXmM66rCd9m1hBEDutPNv94b/pqCMT4NtcKyeWYvLFiE8b+ha1Jdl8XAaUdPn5QTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "execa": "^1.0.0", - "mem": "^4.3.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmmirror.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "node_modules/vite": { - "version": "7.3.1", - "resolved": "https://registry.npmmirror.com/vite/-/vite-7.3.1.tgz", - "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.27.0", - "fdir": "^6.5.0", - "picomatch": "^4.0.3", - "postcss": "^8.5.6", - "rollup": "^4.43.0", - "tinyglobby": "^0.2.15" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^20.19.0 || >=22.12.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^20.19.0 || >=22.12.0", - "jiti": ">=1.21.0", - "less": "^4.0.0", - "lightningcss": "^1.21.0", - "sass": "^1.70.0", - "sass-embedded": "^1.70.0", - "stylus": ">=0.54.8", - "sugarss": "^5.0.0", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vite/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmmirror.com/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/vite/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/watchpack": { - "version": "2.5.1", - "resolved": "https://registry.npmmirror.com/watchpack/-/watchpack-2.5.1.tgz", - "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", - "dev": true, - "license": "MIT", - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmmirror.com/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, - "license": "MIT", - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmmirror.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/webpack": { - "version": "5.105.4", - "resolved": "https://registry.npmmirror.com/webpack/-/webpack-5.105.4.tgz", - "integrity": "sha512-jTywjboN9aHxFlToqb0K0Zs9SbBoW4zRUlGzI2tYNxVYcEi/IPpn+Xi4ye5jTLvX2YeLuic/IvxNot+Q1jMoOw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.8", - "@types/json-schema": "^7.0.15", - "@webassemblyjs/ast": "^1.14.1", - "@webassemblyjs/wasm-edit": "^1.14.1", - "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.16.0", - "acorn-import-phases": "^1.0.3", - "browserslist": "^4.28.1", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.20.0", - "es-module-lexer": "^2.0.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.3.1", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^4.3.3", - "tapable": "^2.3.0", - "terser-webpack-plugin": "^5.3.17", - "watchpack": "^2.5.1", - "webpack-sources": "^3.3.4" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-sources": { - "version": "3.3.4", - "resolved": "https://registry.npmmirror.com/webpack-sources/-/webpack-sources-3.3.4.tgz", - "integrity": "sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmmirror.com/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "license": "MIT", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmmirror.com/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", - "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-bigint": "^1.1.0", - "is-boolean-object": "^1.2.1", - "is-number-object": "^1.1.1", - "is-string": "^1.1.1", - "is-symbol": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", - "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "function.prototype.name": "^1.1.6", - "has-tostringtag": "^1.0.2", - "is-async-function": "^2.0.0", - "is-date-object": "^1.1.0", - "is-finalizationregistry": "^1.1.0", - "is-generator-function": "^1.0.10", - "is-regex": "^1.2.1", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.1.0", - "which-collection": "^1.0.2", - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-collection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-module": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", - "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", - "license": "ISC" - }, - "node_modules/which-typed-array": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.21.tgz", - "integrity": "sha512-zbRA8cVm6io/d5W8uIe2hblzN76/Wm3v/yiythQvr+dpBWeqhPSWIDNj4zOyHi4zKbMK6DN34Xsr9jPHJERAEw==", - "dev": true, - "license": "MIT", - "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.9", - "call-bound": "^1.0.4", - "for-each": "^0.3.5", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmmirror.com/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/xmlbuilder": { - "version": "15.1.1", - "resolved": "https://registry.npmmirror.com/xmlbuilder/-/xmlbuilder-15.1.1.tgz", - "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.0" - } - }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmmirror.com/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.4" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmmirror.com/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmmirror.com/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmmirror.com/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/yargs/node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmmirror.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmmirror.com/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yoctocolors-cjs": { - "version": "2.1.3", - "resolved": "https://registry.npmmirror.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.3.tgz", - "integrity": "sha512-U/PBtDf35ff0D8X8D0jfdzHYEPFxAI7jJlxZXwCSez5M3190m+QobIfh+sWDWSHMCWWJN2AWamkegn6vr6YBTw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zod": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", - "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-validation-error": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", - "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "zod": "^3.25.0 || ^4.0.0" - } - } - } -} diff --git a/taskboard-electron/package.json b/taskboard-electron/package.json index ab2eb0a..c7a4cd9 100644 --- a/taskboard-electron/package.json +++ b/taskboard-electron/package.json @@ -3,22 +3,22 @@ "productName": "AgentForge", "version": "1.0.0", "description": "Kanban task board for orchestrating AI coding agents", - "main": ".vite/build/main.js", + "main": ".bun/build/main.js", "private": true, "scripts": { - "prepackage": "node scripts/build-backend.mjs", - "premake": "node scripts/build-backend.mjs", - "start": "electron-forge start", - "package": "electron-forge package", - "make": "electron-forge make", + "start": "bun scripts/dev.ts", + "build": "bun scripts/build.ts", + "build:backend": "bun scripts/build-backend.ts", + "package": "bun scripts/build.ts && bun scripts/build-backend.ts && electron-forge package", + "make": "bun scripts/build.ts && bun scripts/build-backend.ts && electron-forge make", "publish": "electron-forge publish", "test": "TZ=Asia/Shanghai bun test src/renderer/", "typecheck": "tsc --noEmit -p tsconfig.json && tsc --noEmit -p tsconfig.node.json", "lint": "eslint .", "lint:fix": "eslint . --fix", - "format": "prettier --write \"src/**/*.{ts,tsx}\" \"scripts/**/*.mjs\" \"*.config.js\" \"vite.*.config.mjs\" \"eslint.config.mjs\"", - "format:check": "prettier --check \"src/**/*.{ts,tsx}\" \"scripts/**/*.mjs\" \"*.config.js\" \"vite.*.config.mjs\" \"eslint.config.mjs\"", - "build:check": "SKIP_BACKEND_BUILD=1 vite build --config vite.renderer.config.mjs --outDir .vite/build-check --emptyOutDir" + "format": "prettier --write \"src/**/*.{ts,tsx}\" \"scripts/**/*.ts\" \"*.config.js\" \"eslint.config.mjs\"", + "format:check": "prettier --check \"src/**/*.{ts,tsx}\" \"scripts/**/*.ts\" \"*.config.js\" \"eslint.config.mjs\"", + "build:check": "bun scripts/build.ts" }, "keywords": [], "author": "danielwalnut", @@ -32,14 +32,12 @@ "@electron-forge/maker-zip": "^7.11.1", "@electron-forge/plugin-auto-unpack-natives": "^7.11.1", "@electron-forge/plugin-fuses": "^7.11.1", - "@electron-forge/plugin-vite": "^7.11.1", "@electron/fuses": "^1.8.0", "@eslint/js": "^9.39.4", "@types/bun": "^1.3.14", "@types/node": "^25.9.3", "@types/react": "^19.2.17", "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^5.1.4", "electron": "40.2.1", "eslint": "^9.39.4", "eslint-config-prettier": "^10.1.8", @@ -48,8 +46,7 @@ "globals": "^17.6.0", "prettier": "^3.8.3", "typescript": "^6.0.3", - "typescript-eslint": "^8.61.0", - "vite": "^7.3.1" + "typescript-eslint": "^8.61.0" }, "dependencies": { "chokidar": "^5.0.0", diff --git a/taskboard-electron/scripts/build-backend.mjs b/taskboard-electron/scripts/build-backend.mjs deleted file mode 100644 index bc19f8a..0000000 --- a/taskboard-electron/scripts/build-backend.mjs +++ /dev/null @@ -1,22 +0,0 @@ -import { spawnSync } from "node:child_process"; -import path from "node:path"; -import { fileURLToPath } from "node:url"; - -if (process.env.SKIP_BACKEND_BUILD === "1") { - console.log("[build-backend] SKIP_BACKEND_BUILD=1, skipping bundled backend rebuild"); - process.exit(0); -} - -const scriptDir = path.dirname(fileURLToPath(import.meta.url)); -const projectRoot = path.resolve(scriptDir, "..", ".."); - -console.log("[build-backend] Rebuilding bundled Python backend..."); - -const result = spawnSync("make", ["build-backend"], { - cwd: projectRoot, - stdio: "inherit", -}); - -if (result.status !== 0) { - process.exit(result.status ?? 1); -} diff --git a/taskboard-electron/scripts/build-backend.ts b/taskboard-electron/scripts/build-backend.ts new file mode 100644 index 0000000..21967b4 --- /dev/null +++ b/taskboard-electron/scripts/build-backend.ts @@ -0,0 +1,27 @@ +// Compile the Bun TypeScript backend into a single-file binary bundled with +// the Electron app (replaces the PyInstaller build of taskboard.py). +import { spawnSync } from "node:child_process"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +if (process.env.SKIP_BACKEND_BUILD === "1") { + console.log("[build-backend] SKIP_BACKEND_BUILD=1, skipping bundled backend rebuild"); + process.exit(0); +} + +const scriptDir = path.dirname(fileURLToPath(import.meta.url)); +const appRoot = path.resolve(scriptDir, ".."); +const backendDir = path.resolve(appRoot, "..", "backend"); +const outfile = path.join(appRoot, "resources", "taskboard"); + +console.log("[build-backend] Compiling Bun backend binary..."); + +const result = spawnSync("bun", ["build", "--compile", "taskboard.ts", "--outfile", outfile], { + cwd: backendDir, + stdio: "inherit", +}); + +if (result.status !== 0) { + process.exit(result.status ?? 1); +} +console.log(`[build-backend] Backend binary written to ${outfile}`); diff --git a/taskboard-electron/scripts/build.ts b/taskboard-electron/scripts/build.ts new file mode 100644 index 0000000..206a13d --- /dev/null +++ b/taskboard-electron/scripts/build.ts @@ -0,0 +1,66 @@ +// Bun bundler pipeline for the Electron app (replaces @electron-forge/plugin-vite). +// Outputs: +// .bun/build/main.js - Electron main process (CJS, electron external) +// .bun/build/preload.js - context-bridge preload (CJS) +// .bun/renderer/index.html (+ hashed assets) - React renderer +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +const appRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); + +function reportFailure(label: string, result: Awaited>): never { + console.error(`[build] ${label} failed`); + for (const log of result.logs) console.error(log); + process.exit(1); +} + +export async function buildMain(): Promise { + const result = await Bun.build({ + entrypoints: [path.join(appRoot, "src/main.ts")], + outdir: path.join(appRoot, ".bun/build"), + target: "node", + format: "cjs", + // Runtime deps resolved from packaged node_modules; electron is provided + // by the Electron runtime itself. + external: ["electron", "electron-squirrel-startup", "chokidar"], + sourcemap: "linked", + throw: false, + }); + if (!result.success) reportFailure("main", result); + console.log("[build] main -> .bun/build/main.js"); +} + +export async function buildPreload(): Promise { + const result = await Bun.build({ + entrypoints: [path.join(appRoot, "src/preload.ts")], + outdir: path.join(appRoot, ".bun/build"), + target: "node", + format: "cjs", + external: ["electron"], + sourcemap: "linked", + throw: false, + }); + if (!result.success) reportFailure("preload", result); + console.log("[build] preload -> .bun/build/preload.js"); +} + +export async function buildRenderer(): Promise { + const result = await Bun.build({ + entrypoints: [path.join(appRoot, "index.html")], + outdir: path.join(appRoot, ".bun/renderer"), + target: "browser", + sourcemap: "linked", + define: { "process.env.NODE_ENV": '"production"' }, + throw: false, + }); + if (!result.success) reportFailure("renderer", result); + console.log("[build] renderer -> .bun/renderer/index.html"); +} + +export async function buildAll(): Promise { + await Promise.all([buildMain(), buildPreload(), buildRenderer()]); +} + +if (import.meta.main) { + await buildAll(); +} diff --git a/taskboard-electron/scripts/dev.ts b/taskboard-electron/scripts/dev.ts new file mode 100644 index 0000000..f1a185b --- /dev/null +++ b/taskboard-electron/scripts/dev.ts @@ -0,0 +1,69 @@ +// Dev runner: bun-builds main/preload/renderer, launches Electron, and +// rebuilds on source changes. Renderer rebuilds are picked up by main.ts +// (it watches .bun/renderer in dev and reloads the window); main/preload +// changes restart Electron. +import { spawn, type ChildProcess } from "node:child_process"; +import { createRequire } from "node:module"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; +import chokidar from "chokidar"; +import { buildAll, buildMain, buildPreload, buildRenderer } from "./build.ts"; + +const appRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); +const require = createRequire(import.meta.url); +// The electron package's main export is the path to the Electron binary. +const electronBin = require("electron") as unknown as string; + +await buildAll(); + +let electron: ChildProcess | null = null; +let restarting = false; + +function launchElectron(): void { + electron = spawn(electronBin, ["."], { cwd: appRoot, stdio: "inherit" }); + electron.on("exit", (code) => { + if (!restarting) process.exit(code ?? 0); + }); +} + +async function restartElectron(): Promise { + restarting = true; + const prev = electron; + if (prev) { + await new Promise((resolve) => { + prev.once("exit", () => resolve()); + prev.kill("SIGTERM"); + setTimeout(resolve, 3000); + }); + } + restarting = false; + launchElectron(); +} + +let pending: Promise = Promise.resolve(); +function queue(job: () => Promise): void { + pending = pending.then(job).catch((err) => console.error("[dev] rebuild failed:", err)); +} + +const watcher = chokidar.watch(["src", "index.html"], { + cwd: appRoot, + ignoreInitial: true, +}); +watcher.on("all", (_event, filePath) => { + if (filePath.endsWith(".test.ts")) return; + const isMain = filePath === path.join("src", "main.ts"); + const isPreload = filePath === path.join("src", "preload.ts"); + if (isMain || isPreload) { + queue(async () => { + await (isMain ? buildMain() : buildPreload()); + console.log("[dev] main/preload changed; restarting Electron"); + await restartElectron(); + }); + } else { + queue(async () => { + await buildRenderer(); + }); + } +}); + +launchElectron(); diff --git a/taskboard-electron/src/main.ts b/taskboard-electron/src/main.ts index 54947a3..a21a2bf 100644 --- a/taskboard-electron/src/main.ts +++ b/taskboard-electron/src/main.ts @@ -1,15 +1,12 @@ import { app, BrowserWindow, dialog, ipcMain, powerSaveBlocker } from "electron"; import path from "node:path"; +import os from "node:os"; import http from "node:http"; import { spawn, type ChildProcess } from "node:child_process"; import started from "electron-squirrel-startup"; import chokidar, { type FSWatcher } from "chokidar"; -// Injected by the electron-forge Vite plugin at build time. -declare const MAIN_WINDOW_VITE_DEV_SERVER_URL: string | undefined; -declare const MAIN_WINDOW_VITE_NAME: string; - -interface PythonCommand { +interface BackendCommand { cmd: string; args: string[]; cwd: string | undefined; @@ -19,18 +16,21 @@ if (started) { app.quit(); } -let pythonProcess: ChildProcess | null = null; -let pythonWatcher: FSWatcher | undefined; +let backendProcess: ChildProcess | null = null; +let backendWatcher: FSWatcher | undefined; +let rendererWatcher: FSWatcher | undefined; -function getPythonCommand(): PythonCommand { +function getBackendCommand(): BackendCommand { if (app.isPackaged) { + // Single-file binary produced by `bun build --compile`. const binaryPath = path.join(process.resourcesPath, "taskboard"); return { cmd: binaryPath, args: [], cwd: undefined }; } else { - // In dev mode, app.getAppPath() returns taskboard-electron/ dir - // The Python project root is one level up + // In dev mode, app.getAppPath() returns taskboard-electron/ dir; + // the project root (containing backend/) is one level up. Keep cwd at + // the project root so backend relative paths match packaged behavior. const projectRoot = path.join(app.getAppPath(), ".."); - return { cmd: "uv", args: ["run", "taskboard.py"], cwd: projectRoot }; + return { cmd: "bun", args: [path.join("backend", "taskboard.ts")], cwd: projectRoot }; } } @@ -81,42 +81,48 @@ function killPortSync(port: number): void { } } -// macOS apps launched from Finder/Dock inherit a minimal PATH (no Homebrew), -// so the Python backend can't find tools like `node` (needed by the Weixin -// bridge). Prepend the common install dirs so child processes resolve them. +// macOS apps launched from Finder/Dock inherit a minimal PATH (no Homebrew, +// no ~/.bun), so child processes can't find tools like `bun`, `node`, or the +// agent CLIs. Prepend the common install dirs so they resolve. function augmentedPath(): string { - const extra = ["/opt/homebrew/bin", "/usr/local/bin", "/usr/bin", "/bin"]; + const extra = [ + path.join(os.homedir(), ".bun", "bin"), + "/opt/homebrew/bin", + "/usr/local/bin", + "/usr/bin", + "/bin", + ]; const current = process.env.PATH || ""; const merged = [...extra, ...current.split(":")].filter(Boolean); return [...new Set(merged)].join(":"); } -function startPythonBackend(): Promise { +function startBackend(): Promise { killPortSync(9712); - const { cmd, args, cwd } = getPythonCommand(); - pythonProcess = spawn(cmd, args, { + const { cmd, args, cwd } = getBackendCommand(); + backendProcess = spawn(cmd, args, { stdio: ["ignore", "pipe", "pipe"], env: { ...process.env, PATH: augmentedPath() }, ...(cwd ? { cwd } : {}), }); - pythonProcess.stdout.on("data", (data) => { - console.log("[Python]", data.toString().trim()); + backendProcess.stdout.on("data", (data) => { + console.log("[Backend]", data.toString().trim()); }); - pythonProcess.stderr.on("data", (data) => { - console.error("[Python stderr]", data.toString().trim()); + backendProcess.stderr.on("data", (data) => { + console.error("[Backend stderr]", data.toString().trim()); }); - pythonProcess.on("error", (err) => { - console.error("[Python] Failed to start:", err); + backendProcess.on("error", (err) => { + console.error("[Backend] Failed to start:", err); }); return waitForBackend(9712, 15000); } -function stopPythonBackend(): void { - if (!pythonProcess) return; - const proc = pythonProcess; - pythonProcess = null; +function stopBackend(): void { + if (!backendProcess) return; + const proc = backendProcess; + backendProcess = null; try { proc.kill("SIGTERM"); } catch (_) { @@ -124,7 +130,7 @@ function stopPythonBackend(): void { } } -function setupPythonHotReload(): FSWatcher | undefined { +function setupBackendHotReload(): FSWatcher | undefined { if (app.isPackaged) return; // 生产环境不启用热重载 const projectRoot = path.resolve(path.join(app.getAppPath(), "..")); @@ -144,18 +150,16 @@ function setupPythonHotReload(): FSWatcher | undefined { let isRestarting = false; // 重启锁 const scheduleRestart = (filePath: string, eventType: string) => { - // Restart for .py/.toml files in the project root or in the channels/ directory. - // Files in other subdirectories are ignored to avoid restarting when a running - // task modifies files (e.g. README.md, todo.md in working directories). + // Restart for backend TypeScript sources only (backend/**/*.ts). Files in + // other directories are ignored to avoid restarting when a running task + // modifies files (e.g. README.md, todo.md in working directories). const ext = path.extname(filePath).toLowerCase(); - if (![".py", ".toml"].includes(ext)) { + if (ext !== ".ts") { return; } - // Allow root-level files and files under channels/ - const isRootLevel = !filePath.includes("/") && !filePath.includes(path.sep); - const isChannelsDir = - filePath.startsWith("channels/") || filePath.startsWith(`channels${path.sep}`); - if (!isRootLevel && !isChannelsDir) { + const isBackendDir = + filePath.startsWith("backend/") || filePath.startsWith(`backend${path.sep}`); + if (!isBackendDir) { return; } @@ -174,13 +178,13 @@ function setupPythonHotReload(): FSWatcher | undefined { } isRestarting = true; - console.log("[Hot Reload] Restarting Python backend..."); + console.log("[Hot Reload] Restarting backend..."); try { - stopPythonBackend(); - await startPythonBackend(); - console.log("[Hot Reload] Python backend restarted successfully"); + stopBackend(); + await startBackend(); + console.log("[Hot Reload] Backend restarted successfully"); } catch (error) { - console.error("[Hot Reload] Failed to restart Python backend:", error); + console.error("[Hot Reload] Failed to restart backend:", error); } finally { isRestarting = false; } @@ -195,17 +199,36 @@ function setupPythonHotReload(): FSWatcher | undefined { console.error("[Hot Reload] File watcher error:", error); }); - console.log("[Hot Reload] Python backend hot reload enabled"); + console.log("[Hot Reload] Backend hot reload enabled"); + return watcher; +} + +// In dev, scripts/dev.ts rebuilds the renderer bundle on source changes; +// reload the window whenever the built output updates. +function setupRendererReload(win: BrowserWindow): FSWatcher | undefined { + if (app.isPackaged) return; + const rendererOut = path.join(app.getAppPath(), ".bun", "renderer"); + let reloadTimeout: NodeJS.Timeout | null = null; + const watcher = chokidar.watch(rendererOut, { ignoreInitial: true }); + watcher.on("all", () => { + if (reloadTimeout) clearTimeout(reloadTimeout); + reloadTimeout = setTimeout(() => { + if (!win.isDestroyed()) { + console.log("[Hot Reload] Renderer bundle changed, reloading window"); + win.webContents.reloadIgnoringCache(); + } + }, 150); + }); return watcher; } // Handle terminal Ctrl+C and kill signals so the backend is cleaned up process.on("SIGINT", () => { - stopPythonBackend(); + stopBackend(); process.exit(0); }); process.on("SIGTERM", () => { - stopPythonBackend(); + stopBackend(); process.exit(0); }); @@ -223,11 +246,8 @@ const createWindow = () => { }, }); - if (MAIN_WINDOW_VITE_DEV_SERVER_URL) { - mainWindow.loadURL(MAIN_WINDOW_VITE_DEV_SERVER_URL); - } else { - mainWindow.loadFile(path.join(__dirname, `../renderer/${MAIN_WINDOW_VITE_NAME}/index.html`)); - } + // Renderer bundle produced by scripts/build.ts (Bun.build). + mainWindow.loadFile(path.join(app.getAppPath(), ".bun", "renderer", "index.html")); return mainWindow; }; @@ -242,16 +262,17 @@ ipcMain.handle("select-directory", async () => { app.whenReady().then(() => { powerSaveBlocker.start("prevent-app-suspension"); - createWindow(); + const mainWindow = createWindow(); - // 设置Python后端热重载 + // 设置后端与渲染层热重载 if (!app.isPackaged) { - pythonWatcher = setupPythonHotReload(); + backendWatcher = setupBackendHotReload(); + rendererWatcher = setupRendererReload(mainWindow); } - startPythonBackend() - .then(() => console.log("[Python] Backend is ready on port 9712")) - .catch((err) => console.error("[Python] Backend failed:", err)); + startBackend() + .then(() => console.log("[Backend] Ready on port 9712")) + .catch((err) => console.error("[Backend] Failed:", err)); }); app.on("activate", () => { @@ -261,13 +282,16 @@ app.on("activate", () => { }); app.on("window-all-closed", () => { - stopPythonBackend(); + stopBackend(); app.quit(); }); app.on("before-quit", () => { - stopPythonBackend(); - if (pythonWatcher) { - pythonWatcher.close(); + stopBackend(); + if (backendWatcher) { + backendWatcher.close(); + } + if (rendererWatcher) { + rendererWatcher.close(); } }); diff --git a/taskboard-electron/src/renderer.ts b/taskboard-electron/src/renderer.ts deleted file mode 100644 index 6b772e6..0000000 --- a/taskboard-electron/src/renderer.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** - * This file will automatically be loaded by vite and run in the "renderer" context. - * To learn more about the differences between the "main" and the "renderer" context in - * Electron, visit: - * - * https://electronjs.org/docs/tutorial/process-model - * - * By default, Node.js integration in this file is disabled. When enabling Node.js integration - * in a renderer process, please be aware of potential security implications. You can read - * more about security risks here: - * - * https://electronjs.org/docs/tutorial/security - * - * To enable Node.js integration in this file, open up `main.js` and enable the `nodeIntegration` - * flag: - * - * ``` - * // Create the browser window. - * mainWindow = new BrowserWindow({ - * width: 800, - * height: 600, - * webPreferences: { - * nodeIntegration: true - * } - * }); - * ``` - */ - -import "./index.css"; - -console.log('👋 This message is being logged by "renderer.js", included via Vite'); diff --git a/taskboard-electron/src/vite-env.d.ts b/taskboard-electron/src/vite-env.d.ts deleted file mode 100644 index 11f02fe..0000000 --- a/taskboard-electron/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/taskboard-electron/test_hot_reload.mjs b/taskboard-electron/test_hot_reload.mjs deleted file mode 100644 index 6fdb483..0000000 --- a/taskboard-electron/test_hot_reload.mjs +++ /dev/null @@ -1,329 +0,0 @@ -/** - * 热重载逻辑单元测试 - * - * 测试目标: - * 1. isRestarting 锁能防止并发重启 - * 2. 防抖机制(debounce)能合并短时间内多次文件变化 - * 3. finally 块能确保锁被正确释放 - */ - -// 辅助函数:等待指定毫秒 -const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms)); - -// 颜色输出 -const colors = { - reset: '\x1b[0m', - green: '\x1b[32m', - red: '\x1b[31m', - yellow: '\x1b[33m', - blue: '\x1b[36m' -}; - -function logTest(name, passed, details = '') { - const icon = passed ? '✅' : '❌'; - const color = passed ? colors.green : colors.red; - console.log(`${color}${icon} ${name}${colors.reset}`); - if (details) console.log(` ${colors.yellow}${details}${colors.reset}`); -} - -async function runTests() { - console.log('\n' + colors.blue + '═'.repeat(50) + colors.reset); - console.log(colors.blue + ' 热重载逻辑单元测试' + colors.reset); - console.log(colors.blue + '═'.repeat(50) + colors.reset + '\n'); - - let passed = 0; - let failed = 0; - - // ==================== 测试 1 ==================== - // 验证防抖机制:短时间内多次变化只触发一次重启 - console.log(colors.blue + '测试 1: 防抖机制' + colors.reset); - - function setupDebounceTest() { - let restartTimeout = null; - let restartCount = 0; - const log = []; - - const triggerChange = () => { - if (restartTimeout) { - log.push('Clearing existing timeout'); - clearTimeout(restartTimeout); - } - - restartTimeout = setTimeout(() => { - restartCount++; - log.push(`[RESTART] #${restartCount}`); - }, 500); - }; - - const getRestartCount = () => restartCount; - const getLog = () => [...log]; - - return { triggerChange, getRestartCount, getLog }; - } - - const test1 = setupDebounceTest(); - test1.triggerChange(); - await sleep(100); - test1.triggerChange(); - await sleep(100); - test1.triggerChange(); - await sleep(100); - - // 等待防抖定时器触发 - await sleep(800); - - const passed1 = test1.getRestartCount() === 1 && - test1.getLog().filter(l => l.includes('[RESTART]')).length === 1 && - test1.getLog().filter(l => l.includes('Clearing existing timeout')).length >= 1; - logTest('短时间内多次变化只触发一次重启', passed1, - `实际重启次数: ${test1.getRestartCount()}${passed1 ? '' : ' (期望: 1)'}`); - if (passed1) passed++; else failed++; - - // ==================== 测试 2 ==================== - // 验证并发重启防护:多个并发变化只执行一次 - console.log('\n' + colors.blue + '测试 2: 并发重启防护' + colors.reset); - - function setupConcurrencyTest() { - let isRestarting = false; - let restartCount = 0; - let skipCount = 0; - - const attemptRestart = () => { - return new Promise((resolve) => { - // 不设置 setTimeout 直接执行,模拟多个并发请求同时到达 - if (isRestarting) { - skipCount++; - resolve('skipped'); - return; - } - - isRestarting = true; - restartCount++; - resolve('started'); - - // 模拟异步重启 - setTimeout(() => { - isRestarting = false; - }, 100); - }); - }; - - const getStats = () => ({ restartCount, skipCount }); - - return { attemptRestart, getStats }; - } - - const test2 = setupConcurrencyTest(); - - // 并发触发多次重启请求 - const promises = [ - test2.attemptRestart(), - test2.attemptRestart(), - test2.attemptRestart(), - test2.attemptRestart(), - test2.attemptRestart(), - ]; - - const results = await Promise.all(promises); - - // 确保锁已释放 - await sleep(150); - const stats = test2.getStats(); - - const passed2 = stats.restartCount === 1 && stats.skipCount === 4; - logTest('并发请求只执行一次重启,其余被跳过', passed2, - `重启: ${stats.restartCount}, 跳过: ${stats.skipCount}${passed2 ? '' : ' (期望: restart=1, skip=4)'}`); - if (passed2) passed++; else failed++; - - // ==================== 测试 3 ==================== - // 验证 finally 块:锁在异常情况下也能释放 - console.log('\n' + colors.blue + '测试 3: 异常情况下锁的正确释放' + colors.reset); - - function setupFinallyTest() { - let isRestarting = false; - - const restartWithError = () => { - return Promise((resolve, reject) => { - isRestarting = true; - - try { - // 模拟操作 - process.nextTick(() => { - throw new Error('Simulated error'); - }); - } catch (error) { - throw error; - } finally { - isRestarting = false; - } - resolve('completed'); - }); - }; - - const isLocked = () => isRestarting; - return { restartWithError, isLocked }; - } - - const test3 = setupFinallyTest(); - try { - await test3.restartWithError(); - } catch (e) { - // 预期错误 - } - - // 实际代码是异步执行,用更接近实际的方式测试 - function setupFinallyTestAsync() { - let isRestarting = false; - - const restartWithError = () => { - return new Promise((resolve, reject) => { - isRestarting = true; - process.nextTick(() => { - try { - throw new Error('Simulated error'); - } catch (error) { - reject(error); - } finally { - isRestarting = false; - } - }); - }); - }; - - const isLocked = () => isRestarting; - return { restartWithError, isLocked }; - } - - const test3Async = setupFinallyTestAsync(); - try { - await test3Async.restartWithError(); - } catch (e) { - // 预期错误 - } - - await sleep(50); // 确保 finally 执行 - - const passed3 = !test3Async.isLocked(); - logTest('异常后锁被正确释放', passed3, - passed3 ? '' : `锁状态: ${test3Async.isLocked()} (期望: false)`); - if (passed3) passed++; else failed++; - - // ==================== 测试 4 ==================== - // 验证完整的重载循环:防抖 -> 重启锁 -> finally - console.log('\n' + colors.blue + '测试 4: 完整重载流程' + colors.reset); - - function setupFullFlowTest() { - let restartTimeout = null; - let isRestarting = false; - let restartCount = 0; - const log = []; - - const triggerChange = () => { - return new Promise((resolve) => { - if (restartTimeout) { - clearTimeout(restartTimeout); - log.push('[DEBOUNCE] Cleared'); - } - - restartTimeout = setTimeout(async () => { - if (isRestarting) { - log.push('[LOCK] Busy, skipping'); - resolve('skipped'); - return; - } - - isRestarting = true; - restartCount++; - log.push(`[RESTART] #${restartCount} started`); - - try { - // 模拟重启耗时要大于防抖延迟,才能测试并发场景 - await new Promise(r => setTimeout(r, 500)); - log.push(`[RESTART] #${restartCount} completed`); - resolve('completed'); - } catch (error) { - log.push(`[ERROR] ${error.message}`); - throw error; - } finally { - isRestarting = false; - log.push('[LOCK] Released'); - } - }, 200); // 200ms 防抖 - }); - }; - - const getLog = () => [...log]; - const getRestartCount = () => restartCount; - - return { triggerChange, getLog, getRestartCount }; - } - - const test4 = setupFullFlowTest(); - - // 触发多次变化(应该被防抖合并) - test4.triggerChange(); - await sleep(100); - test4.triggerChange(); - await sleep(100); - test4.triggerChange(); - await sleep(250); // 等待防抖过去,第一次重启刚开始(耗时500ms) - - // 在重启期间再次触发(应该被跳过) - // 此时防抖200ms,重启已经进行了250ms,还有250ms才结束 - // 新触发会在 200ms 后检查锁,此时重启还在进行中 - test4.triggerChange(); - await sleep(600); // 等待所有完成 - - const log4 = test4.getLog(); - const passed4 = test4.getRestartCount() === 1 && - log4.includes('[DEBOUNCE] Cleared') && - log4.filter(l => l.includes('Busy, skipping')).length >= 1 && - log4.includes('[LOCK] Released'); - - logTest('完整流程正确执行', passed4, - `重启次数: ${test4.getRestartCount()}${passed4 ? '' : ' (期望: 1)'}\n` + - ` 日志: ${log4.join(', ')}`); - if (passed4) passed++; else failed++; - - // ==================== 测试 5 ==================== - // 验证序列重启:完成后可以继续重启 - console.log('\n' + colors.blue + '测试 5: 序列重启' + colors.reset); - - const test5 = setupFullFlowTest(); - - // 第一次 - await test5.triggerChange(); - // 防抖200ms + 重启500ms = 至少需要700ms - await sleep(800); - - // 等待后第二次 - await sleep(100); - await test5.triggerChange(); - await sleep(800); - - const passed5 = test5.getRestartCount() === 2; - logTest('序列变化能触发多次重启', passed5, - `重启次数: ${test5.getRestartCount()}${passed5 ? '' : ' (期望: 2)'}`); - if (passed5) passed++; else failed++; - - // ==================== 测试总结 ==================== - console.log('\n' + colors.blue + '═'.repeat(50) + colors.reset); - console.log(colors.blue + ` 测试结果: ${passed}/${passed + failed} 通过` + colors.reset); - console.log(colors.blue + '═'.repeat(50) + colors.reset); - - if (failed === 0) { - console.log(colors.green + '\n✨ 所有测试通过!热重载逻辑正确。' + colors.reset + '\n'); - return 0; - } else { - console.log(colors.red + `\n⚠️ ${failed} 个测试失败,需要修复。` + colors.reset + '\n'); - return 1; - } -} - -// 运行测试 -runTests().then(exitCode => { - process.exit(exitCode); -}).catch(error => { - console.error(colors.red + '测试运行出错:' + colors.reset, error); - process.exit(1); -}); diff --git a/taskboard-electron/tsconfig.json b/taskboard-electron/tsconfig.json index 29bf262..4415828 100644 --- a/taskboard-electron/tsconfig.json +++ b/taskboard-electron/tsconfig.json @@ -14,5 +14,5 @@ "isolatedModules": true, "types": ["bun"] }, - "include": ["src/renderer.ts", "src/renderer/**/*", "src/vite-env.d.ts"] + "include": ["src/renderer/**/*"] } diff --git a/taskboard-electron/vite.main.config.mjs b/taskboard-electron/vite.main.config.mjs deleted file mode 100644 index a008242..0000000 --- a/taskboard-electron/vite.main.config.mjs +++ /dev/null @@ -1,8 +0,0 @@ -import { defineConfig } from "vite"; - -// https://vitejs.dev/config -export default defineConfig({ - build: { - watch: process.env.NODE_ENV === "development" ? {} : null, - }, -}); diff --git a/taskboard-electron/vite.preload.config.mjs b/taskboard-electron/vite.preload.config.mjs deleted file mode 100644 index fbf7eda..0000000 --- a/taskboard-electron/vite.preload.config.mjs +++ /dev/null @@ -1,4 +0,0 @@ -import { defineConfig } from "vite"; - -// https://vitejs.dev/config -export default defineConfig({}); diff --git a/taskboard-electron/vite.renderer.config.mjs b/taskboard-electron/vite.renderer.config.mjs deleted file mode 100644 index 45be425..0000000 --- a/taskboard-electron/vite.renderer.config.mjs +++ /dev/null @@ -1,14 +0,0 @@ -import { defineConfig } from "vite"; -import react from "@vitejs/plugin-react"; - -// https://vitejs.dev/config -export default defineConfig({ - plugins: [react()], - server: { - hmr: true, - watch: { - usePolling: false, - interval: 100, - }, - }, -}); From 3d67c0d72870f1ee2605c72cacd4e1841eaf7aab Mon Sep 17 00:00:00 2001 From: taohe Date: Sat, 13 Jun 2026 01:10:20 +0800 Subject: [PATCH 07/18] build: switch Makefile and CI to Bun toolchain Co-Authored-By: Claude Fable 5 --- .github/workflows/ci.yml | 41 ++++++++++++++-------------- Makefile | 59 ++++++++++++++++++---------------------- backend/bun.lock | 3 ++ backend/package.json | 5 +++- 4 files changed, 54 insertions(+), 54 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 64e28e9..28934de 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,26 +15,24 @@ jobs: backend-quality: name: Backend Quality runs-on: ubuntu-latest + defaults: + run: + working-directory: backend steps: - name: Check out repository uses: actions/checkout@v5 - - name: Set up Python - uses: actions/setup-python@v5 + - name: Set up Bun + uses: oven-sh/setup-bun@v2 with: - python-version: "3.12" - - - name: Set up uv - uses: astral-sh/setup-uv@v6 - with: - enable-cache: true + bun-version: latest - name: Install dependencies - run: uv sync --dev + run: bun install --frozen-lockfile - name: Run backend quality gate - run: make check + run: bun run check frontend-quality: name: Frontend Quality @@ -47,24 +45,25 @@ jobs: - name: Check out repository uses: actions/checkout@v5 - - name: Set up Node.js - uses: actions/setup-node@v5 + - name: Set up Bun + uses: oven-sh/setup-bun@v2 with: - node-version: "22" - cache: npm - cache-dependency-path: taskboard-electron/package-lock.json + bun-version: latest - name: Install dependencies - run: npm ci + run: bun install --frozen-lockfile + + - name: Typecheck (tsc) + run: bun run typecheck - name: Lint (ESLint) - run: npm run lint + run: bun run lint - name: Format check (Prettier) - run: npm run format:check + run: bun run format:check - name: Unit tests - run: npm test + run: bun run test - - name: Renderer build check - run: npm run build:check + - name: Renderer/main build check (Bun.build) + run: bun run build:check diff --git a/Makefile b/Makefile index de82100..07734f8 100644 --- a/Makefile +++ b/Makefile @@ -1,19 +1,19 @@ -.PHONY: help build-backend build-electron package-dmg clean install-deps lint format format-check test test-cov check +.PHONY: help build-backend build-electron package-dmg clean install-deps lint format format-check test test-cov check dev-backend dev-electron check-backend check-dmg # 项目配置 PROJECT_NAME = AgentForge -BACKEND_SRC = taskboard.py +BACKEND_DIR = backend BACKEND_BINARY = taskboard-electron/resources/taskboard ELECTRON_DIR = taskboard-electron DMG_OUTPUT = $(ELECTRON_DIR)/out/make/$(PROJECT_NAME)-1.0.0-arm64.dmg help: - @echo "AgentForge 打包工具" + @echo "AgentForge 打包工具 (Bun + TypeScript)" @echo "" @echo "可用命令:" @echo " make help - 显示此帮助信息" - @echo " make install-deps - 安装项目依赖" - @echo " make build-backend - 构建Python后端二进制文件" + @echo " make install-deps - 安装项目依赖 (bun install)" + @echo " make build-backend - 编译后端单文件二进制 (bun build --compile)" @echo " make build-electron - 构建Electron应用" @echo " make package-dmg - 打包为DMG文件(包含所有步骤)" @echo " make clean - 清理构建文件" @@ -21,30 +21,25 @@ help: @echo "快速打包: make package-dmg" install-deps: - @echo "安装Python依赖..." - uv add pyinstaller croniter python-dateutil pytz + @echo "安装后端依赖..." + cd $(BACKEND_DIR) && bun install @echo "安装Electron依赖..." - cd $(ELECTRON_DIR) && npm install + cd $(ELECTRON_DIR) && bun install build-backend: - @echo "构建Python后端二进制文件..." - uv run pyinstaller --onefile --name taskboard \ - --distpath $(ELECTRON_DIR)/resources \ - --hidden-import croniter --hidden-import dateutil --hidden-import pytz \ - --add-data vendor/skill-creator:vendor/skill-creator \ - --add-data channels/weixin_bridge:channels/weixin_bridge \ - $(BACKEND_SRC) + @echo "编译后端单文件二进制 (bun build --compile)..." + cd $(ELECTRON_DIR) && bun scripts/build-backend.ts @echo "后端二进制文件位置: $(BACKEND_BINARY)" @ls -lh $(BACKEND_BINARY) build-electron: @echo "构建Electron应用..." - cd $(ELECTRON_DIR) && SKIP_BACKEND_BUILD=1 npm run package + cd $(ELECTRON_DIR) && bun scripts/build.ts && SKIP_BACKEND_BUILD=1 bunx electron-forge package @echo "Electron应用构建完成" -package-dmg: build-backend build-electron +package-dmg: build-backend @echo "打包DMG文件..." - cd $(ELECTRON_DIR) && SKIP_BACKEND_BUILD=1 npm run make + cd $(ELECTRON_DIR) && bun scripts/build.ts && SKIP_BACKEND_BUILD=1 bunx electron-forge make @if [ -f "$(DMG_OUTPUT)" ]; then \ echo "DMG文件生成成功: $(DMG_OUTPUT)"; \ ls -lh "$(DMG_OUTPUT)"; \ @@ -55,20 +50,19 @@ package-dmg: build-backend build-electron clean: @echo "清理构建文件..." - rm -rf build/ rm -rf $(ELECTRON_DIR)/out/ - rm -rf $(ELECTRON_DIR)/.vite/ + rm -rf $(ELECTRON_DIR)/.bun/ rm -f $(BACKEND_BINARY) @echo "清理完成" # 开发相关命令 dev-backend: @echo "启动后端开发服务器..." - uv run python $(BACKEND_SRC) + cd $(BACKEND_DIR) && bun taskboard.ts dev-electron: @echo "启动Electron开发模式..." - cd $(ELECTRON_DIR) && npm start + cd $(ELECTRON_DIR) && bun run start # 检查命令 check-backend: @@ -84,23 +78,24 @@ check-dmg: fi lint: - @echo "运行 Ruff lint..." - uv run ruff check . + @echo "运行 TypeScript 类型检查..." + cd $(BACKEND_DIR) && bun run typecheck format: - @echo "运行 Ruff format..." - uv run ruff format . + @echo "运行 Prettier format..." + cd $(BACKEND_DIR) && bun run format format-check: @echo "检查代码格式..." - uv run ruff format --check . + cd $(BACKEND_DIR) && bun run format:check test: - @echo "运行 Python 测试..." - uv run pytest + @echo "运行后端测试..." + cd $(BACKEND_DIR) && bun test test-cov: - @echo "运行 Python 测试并检查覆盖率..." - uv run pytest --cov --cov-report=term-missing + @echo "运行后端测试并检查覆盖率..." + cd $(BACKEND_DIR) && bun test --coverage -check: lint format-check test-cov +check: + cd $(BACKEND_DIR) && bun run check diff --git a/backend/bun.lock b/backend/bun.lock index 983586f..e8a9a07 100644 --- a/backend/bun.lock +++ b/backend/bun.lock @@ -12,6 +12,7 @@ }, "devDependencies": { "@types/bun": "^1.3.5", + "prettier": "^3.8.4", "typescript": "^5.9.3", }, }, @@ -137,6 +138,8 @@ "p-timeout": ["p-timeout@3.2.0", "", { "dependencies": { "p-finally": "^1.0.0" } }, "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg=="], + "prettier": ["prettier@3.8.4", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-N2MylSdi48+5N/6S5j+maeHbUSIzzZ5uOcX5Hm4QpV8Dkb1HFjfAKTKX6yNPJQD9AhcT3ifHNB66tWTTJDi11Q=="], + "protobufjs": ["protobufjs@7.6.4", "", { "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", "@protobufjs/codegen": "^2.0.5", "@protobufjs/eventemitter": "^1.1.1", "@protobufjs/fetch": "^1.1.1", "@protobufjs/float": "^1.0.2", "@protobufjs/path": "^1.1.2", "@protobufjs/pool": "^1.1.0", "@protobufjs/utf8": "^1.1.1", "@types/node": ">=13.7.0", "long": "^5.3.2" } }, "sha512-RJJPTTpvFfHcWLkIa2JFWK4XvtSzS0yEWDmunqHXli1h3JlkbcQZXDZdcWxv+JK3Xsl5/UFDPZ0iGm7DAengYw=="], "proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="], diff --git a/backend/package.json b/backend/package.json index 245e1c5..f259a49 100644 --- a/backend/package.json +++ b/backend/package.json @@ -6,9 +6,11 @@ "type": "module", "scripts": { "start": "bun taskboard.ts", - "check": "bunx tsc --noEmit && bun test", + "check": "bun run typecheck && bun run format:check && bun test --coverage", "test": "bun test", "typecheck": "bunx tsc --noEmit", + "format": "prettier --write \"taskboard.ts\" \"src/**/*.ts\" \"tests/**/*.ts\"", + "format:check": "prettier --check \"taskboard.ts\" \"src/**/*.ts\" \"tests/**/*.ts\"", "compile": "bun build --compile taskboard.ts --outfile ../taskboard-electron/resources/taskboard" }, "dependencies": { @@ -19,6 +21,7 @@ }, "devDependencies": { "@types/bun": "^1.3.5", + "prettier": "^3.8.4", "typescript": "^5.9.3" } } From b3af3d7e447f8676d5563868fa0d15190088f605 Mon Sep 17 00:00:00 2001 From: taohe Date: Sat, 13 Jun 2026 01:10:32 +0800 Subject: [PATCH 08/18] style(backend): apply prettier formatting Co-Authored-By: Claude Fable 5 --- backend/src/bus.ts | 21 +++- backend/src/db.ts | 191 +++++++++++++++++++++++++++-------- backend/src/util.ts | 15 ++- backend/tests/bus.test.ts | 5 +- backend/tests/taskdb.test.ts | 100 +++++++++++++----- 5 files changed, 258 insertions(+), 74 deletions(-) diff --git a/backend/src/bus.ts b/backend/src/bus.ts index 22224b9..b0036d7 100644 --- a/backend/src/bus.ts +++ b/backend/src/bus.ts @@ -32,7 +32,8 @@ export const InboundMessageType = { CANCEL_TASK: "cancel_task", // cancel a task STATUS_QUERY: "status_query", // query task status } as const; -export type InboundMessageType = (typeof InboundMessageType)[keyof typeof InboundMessageType]; +export type InboundMessageType = + (typeof InboundMessageType)[keyof typeof InboundMessageType]; /** Outbound message event types (enum values identical to Python). */ export const OutboundMessageType = { @@ -42,7 +43,8 @@ export const OutboundMessageType = { TASK_UPDATED: "task_updated", STATUS_RESPONSE: "status_response", } as const; -export type OutboundMessageType = (typeof OutboundMessageType)[keyof typeof OutboundMessageType]; +export type OutboundMessageType = + (typeof OutboundMessageType)[keyof typeof OutboundMessageType]; /** * UTC-naive ISO timestamp, matching Python's `datetime.utcnow().isoformat()` @@ -214,7 +216,10 @@ export class MessageBus { } /** The scheduler calls this to take the next inbound message (optional). */ - get_inbound(block: boolean = true, timeout: number | null = null): Promise { + get_inbound( + block: boolean = true, + timeout: number | null = null, + ): Promise { return this.inbound_queue.get(block, timeout); } @@ -247,7 +252,10 @@ export class MessageBus { } /** Polling channels call this to take the next outbound message. */ - get_outbound(block: boolean = true, timeout: number | null = null): Promise { + get_outbound( + block: boolean = true, + timeout: number | null = null, + ): Promise { return this.outbound_queue.get(block, timeout); } } @@ -487,7 +495,10 @@ export abstract class BusAwareSchedulerMixin { bus: MessageBus | null = null; abstract db: TaskDBLike; - _bus_notify(task_id: number, override_type: OutboundMessageType | null = null): void { + _bus_notify( + task_id: number, + override_type: OutboundMessageType | null = null, + ): void { bus_notify(this.bus, this.db, task_id, override_type); } } diff --git a/backend/src/db.ts b/backend/src/db.ts index 1f3324e..282eab5 100644 --- a/backend/src/db.ts +++ b/backend/src/db.ts @@ -78,7 +78,9 @@ export class TaskDB { // Columns already exist } this._migrate("ALTER TABLE tasks ADD COLUMN session_id TEXT"); - this._migrate("ALTER TABLE tasks ADD COLUMN prompt_images TEXT DEFAULT '[]'"); + this._migrate( + "ALTER TABLE tasks ADD COLUMN prompt_images TEXT DEFAULT '[]'", + ); this._migrate("ALTER TABLE tasks ADD COLUMN image_paths TEXT DEFAULT '[]'"); this._migrate("ALTER TABLE tasks ADD COLUMN notify_slack_channel TEXT"); this._migrate("ALTER TABLE tasks ADD COLUMN notify_telegram_chat_id TEXT"); @@ -273,7 +275,9 @@ export class TaskDB { const run_ids = runRows.map((r) => r["id"]); if (run_ids.length) { this.conn - .query("UPDATE skill_patterns SET contributing_run_ids = ? WHERE id = ?") + .query( + "UPDATE skill_patterns SET contributing_run_ids = ? WHERE id = ?", + ) .run(JSON.stringify(run_ids), row["id"]); } } @@ -377,7 +381,9 @@ export class TaskDB { add_task(task: Task): number { const now = nowIso(); - logger.debug(`add_task called with image_paths: ${JSON.stringify(task.image_paths)}`); + logger.debug( + `add_task called with image_paths: ${JSON.stringify(task.image_paths)}`, + ); const image_paths_json = JSON.stringify(task.image_paths); logger.debug(`image_paths JSON: ${image_paths_json}`); const cur = this.conn @@ -415,18 +421,24 @@ export class TaskDB { /** Look up the most recent task created from a given Feishu root message ID. */ get_task_by_feishu_root_msg(root_msg_id: string): Row | null { const row = this.conn - .query("SELECT * FROM tasks WHERE feishu_root_msg_id = ? ORDER BY id DESC LIMIT 1") + .query( + "SELECT * FROM tasks WHERE feishu_root_msg_id = ? ORDER BY id DESC LIMIT 1", + ) .get(root_msg_id) as Row | null; return row ? { ...row } : null; } get_setting(key: string, defaultValue: string | null = null): string | null { - const row = this.conn.query("SELECT value FROM settings WHERE key = ?").get(key) as Row | null; + const row = this.conn + .query("SELECT value FROM settings WHERE key = ?") + .get(key) as Row | null; return row ? row["value"] : defaultValue; } set_setting(key: string, value: string): void { - this.conn.query("INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)").run(key, value); + this.conn + .query("INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)") + .run(key, value); } private _deserialize_heartbeat(row: Row): Row { @@ -435,14 +447,19 @@ export class TaskDB { return d; } - _compute_heartbeat_next_run_at(heartbeat: Heartbeat, now: Date | null = null): string { + _compute_heartbeat_next_run_at( + heartbeat: Heartbeat, + now: Date | null = null, + ): string { const base = now ?? new Date(); if (heartbeat.schedule_type === HeartbeatScheduleType.CRON) { if (!heartbeat.cron_expr) { throw new Error("cron heartbeat requires cron_expr"); } return dateToLocalIso( - CronExpressionParser.parse(heartbeat.cron_expr, { currentDate: base }).next().toDate(), + CronExpressionParser.parse(heartbeat.cron_expr, { currentDate: base }) + .next() + .toDate(), ); } if (heartbeat.schedule_type === HeartbeatScheduleType.INTERVAL) { @@ -450,16 +467,23 @@ export class TaskDB { throw new Error("interval heartbeat requires interval_seconds > 0"); } return dateToLocalIso( - new Date(base.getTime() + Math.trunc(heartbeat.interval_seconds) * 1000), + new Date( + base.getTime() + Math.trunc(heartbeat.interval_seconds) * 1000, + ), ); } - throw new Error(`Unsupported heartbeat schedule_type: ${heartbeat.schedule_type}`); + throw new Error( + `Unsupported heartbeat schedule_type: ${heartbeat.schedule_type}`, + ); } add_heartbeat(heartbeat: Heartbeat): number { const now = nowIso(); if (heartbeat.next_run_at === null) { - heartbeat.next_run_at = this._compute_heartbeat_next_run_at(heartbeat, new Date()); + heartbeat.next_run_at = this._compute_heartbeat_next_run_at( + heartbeat, + new Date(), + ); } const cur = this.conn .query( @@ -516,12 +540,17 @@ export class TaskDB { "updated_at", ]); - update_heartbeat(heartbeat_id: number, kwargs: Record): void { + update_heartbeat( + heartbeat_id: number, + kwargs: Record, + ): void { const invalid = Object.keys(kwargs).filter( (k) => !TaskDB.ALLOWED_HEARTBEAT_COLUMNS.has(k), ); if (invalid.length) { - throw new Error(`Invalid heartbeat column(s): ${JSON.stringify(invalid)}`); + throw new Error( + `Invalid heartbeat column(s): ${JSON.stringify(invalid)}`, + ); } const updates: Record = { ...kwargs }; updates["updated_at"] = nowIso(); @@ -529,7 +558,9 @@ export class TaskDB { .map((k) => `${k} = ?`) .join(", "); const vals = [...Object.values(updates), heartbeat_id]; - this.conn.query(`UPDATE heartbeats SET ${sets} WHERE id = ?`).run(...(vals as any[])); + this.conn + .query(`UPDATE heartbeats SET ${sets} WHERE id = ?`) + .run(...(vals as any[])); } get_heartbeat(heartbeat_id: number): Row | null { @@ -575,8 +606,12 @@ export class TaskDB { delete_heartbeat(heartbeat_id: number): void { this.transaction(() => { - this.conn.query("DELETE FROM heartbeat_ticks WHERE heartbeat_id = ?").run(heartbeat_id); - this.conn.query("DELETE FROM heartbeat_dedup WHERE heartbeat_id = ?").run(heartbeat_id); + this.conn + .query("DELETE FROM heartbeat_ticks WHERE heartbeat_id = ?") + .run(heartbeat_id); + this.conn + .query("DELETE FROM heartbeat_dedup WHERE heartbeat_id = ?") + .run(heartbeat_id); this.conn.query("DELETE FROM heartbeats WHERE id = ?").run(heartbeat_id); }); } @@ -602,7 +637,8 @@ export class TaskDB { raw_output: string | null = null, error: string | null = null, ): void { - const payload_json = decision_payload !== null ? JSON.stringify(decision_payload) : null; + const payload_json = + decision_payload !== null ? JSON.stringify(decision_payload) : null; this.conn .query( ` @@ -611,7 +647,16 @@ export class TaskDB { WHERE id = ? `, ) - .run(nowIso(), status, decision_type, payload_json, task_id, raw_output, error, tick_id); + .run( + nowIso(), + status, + decision_type, + payload_json, + task_id, + raw_output, + error, + tick_id, + ); } get_heartbeat_ticks(heartbeat_id: number, limit: number = 50): Row[] { @@ -666,7 +711,11 @@ export class TaskDB { return row ? { ...row } : null; } - upsert_heartbeat_dedup(heartbeat_id: number, dedupe_key: string, task_id: number | null): void { + upsert_heartbeat_dedup( + heartbeat_id: number, + dedupe_key: string, + task_id: number | null, + ): void { const now = nowIso(); this.conn .query( @@ -706,7 +755,9 @@ export class TaskDB { ]); update_task(task_id: number, kwargs: Record): void { - const invalid = Object.keys(kwargs).filter((k) => !TaskDB.ALLOWED_TASK_COLUMNS.has(k)); + const invalid = Object.keys(kwargs).filter( + (k) => !TaskDB.ALLOWED_TASK_COLUMNS.has(k), + ); if (invalid.length) { throw new Error(`Invalid task column(s): ${JSON.stringify(invalid)}`); } @@ -721,7 +772,9 @@ export class TaskDB { .map((k) => `${k} = ?`) .join(", "); const vals = [...Object.values(updates), task_id]; - this.conn.query(`UPDATE tasks SET ${sets} WHERE id = ?`).run(...(vals as any[])); + this.conn + .query(`UPDATE tasks SET ${sets} WHERE id = ?`) + .run(...(vals as any[])); } private _deserialize_task(row: Row): Row { @@ -734,7 +787,10 @@ export class TaskDB { } catch { d["prompt_images"] = []; } - } else if (d["prompt_images"] === null || d["prompt_images"] === undefined) { + } else if ( + d["prompt_images"] === null || + d["prompt_images"] === undefined + ) { d["prompt_images"] = []; } // Deserialize image_paths @@ -752,12 +808,16 @@ export class TaskDB { } get_task(task_id: number): Row | null { - const row = this.conn.query("SELECT * FROM tasks WHERE id = ?").get(task_id) as Row | null; + const row = this.conn + .query("SELECT * FROM tasks WHERE id = ?") + .get(task_id) as Row | null; return row ? this._deserialize_task(row) : null; } get_all_tasks(): Row[] { - const rows = this.conn.query("SELECT * FROM tasks ORDER BY created_at DESC").all() as Row[]; + const rows = this.conn + .query("SELECT * FROM tasks ORDER BY created_at DESC") + .all() as Row[]; return rows.map((r) => this._deserialize_task(r)); } @@ -838,7 +898,9 @@ export class TaskDB { `, ) .run(run_status, run_result, run_error, raw_output, run_id); - this.conn.query(`UPDATE tasks SET ${sets} WHERE id = ?`).run(...(vals as any[])); + this.conn + .query(`UPDATE tasks SET ${sets} WHERE id = ?`) + .run(...(vals as any[])); }); } @@ -855,7 +917,12 @@ export class TaskDB { } /** Add a new output event to the database. */ - add_output_event(task_id: number, run_id: number, event_type: string, content: string): void { + add_output_event( + task_id: number, + run_id: number, + event_type: string, + content: string, + ): void { this.conn .query( ` @@ -867,7 +934,11 @@ export class TaskDB { } /** Get output events for a task, ordered by timestamp. */ - get_output_events(task_id: number, limit: number = 1000, offset: number = 0): Row[] { + get_output_events( + task_id: number, + limit: number = 1000, + offset: number = 0, + ): Row[] { const rows = this.conn .query( ` @@ -1031,7 +1102,15 @@ export class TaskDB { VALUES (?, ?, ?, 1, ?, ?, ?, ?, 'tracking') `, ) - .run(pattern_key, kind, summary || "", now, now, JSON.stringify(tids), JSON.stringify(rids)); + .run( + pattern_key, + kind, + summary || "", + now, + now, + JSON.stringify(tids), + JSON.stringify(rids), + ); return Number(cur.lastInsertRowid); } @@ -1067,7 +1146,9 @@ export class TaskDB { return 0; } const row = this.conn - .query("SELECT recurrence_count FROM skill_patterns WHERE pattern_key = ?") + .query( + "SELECT recurrence_count FROM skill_patterns WHERE pattern_key = ?", + ) .get(pattern_key) as Row | null; return row ? row["recurrence_count"] : 0; } @@ -1077,7 +1158,11 @@ export class TaskDB { * * Tolerant: if timestamps can't be parsed, don't block promotion. */ - static _within_window(first_seen: string, last_seen: string, window_days: number): boolean { + static _within_window( + first_seen: string, + last_seen: string, + window_days: number, + ): boolean { let f: Date | null; let ls: Date | null; try { @@ -1129,11 +1214,15 @@ export class TaskDB { if (new Set(tids).size < min_tasks) { continue; } - if (!TaskDB._within_window(r["first_seen"], r["last_seen"], window_days)) { + if ( + !TaskDB._within_window(r["first_seen"], r["last_seen"], window_days) + ) { continue; } this.conn - .query("UPDATE skill_patterns SET status = 'candidate', updated_at = ? WHERE id = ?") + .query( + "UPDATE skill_patterns SET status = 'candidate', updated_at = ? WHERE id = ?", + ) .run(now, r["id"]); marked += 1; } @@ -1209,7 +1298,9 @@ export class TaskDB { } delete_skill_draft(pattern_id: number): void { - this.conn.query("DELETE FROM skill_drafts WHERE pattern_id = ?").run(pattern_id); + this.conn + .query("DELETE FROM skill_drafts WHERE pattern_id = ?") + .run(pattern_id); } // ── Skill registry ───────────────────────────────────────────────────── @@ -1240,29 +1331,41 @@ export class TaskDB { if (cur.lastInsertRowid) { return Number(cur.lastInsertRowid); } - const row = this.conn.query("SELECT id FROM skills WHERE name = ?").get(name) as Row | null; + const row = this.conn + .query("SELECT id FROM skills WHERE name = ?") + .get(name) as Row | null; return row ? Number(row["id"]) : null; } get_skills(): Row[] { - const rows = this.conn.query("SELECT * FROM skills ORDER BY created_at DESC").all() as Row[]; + const rows = this.conn + .query("SELECT * FROM skills ORDER BY created_at DESC") + .all() as Row[]; return rows.map((r) => ({ ...r })); } get_skill(skill_id: number): Row | null { - const row = this.conn.query("SELECT * FROM skills WHERE id = ?").get(skill_id) as Row | null; + const row = this.conn + .query("SELECT * FROM skills WHERE id = ?") + .get(skill_id) as Row | null; return row ? { ...row } : null; } set_skill_enabled(skill_id: number, enabled: boolean): void { - this.conn.query("UPDATE skills SET enabled = ? WHERE id = ?").run(enabled ? 1 : 0, skill_id); + this.conn + .query("UPDATE skills SET enabled = ? WHERE id = ?") + .run(enabled ? 1 : 0, skill_id); } delete_skill(skill_id: number): void { this.conn.query("DELETE FROM skills WHERE id = ?").run(skill_id); } - add_dependency(task_id: number, depends_on_task_id: number, inject_result: boolean = false): void { + add_dependency( + task_id: number, + depends_on_task_id: number, + inject_result: boolean = false, + ): void { this.conn .query( ` @@ -1309,7 +1412,9 @@ export class TaskDB { /** Remove all upstream dependencies for a task. */ clear_dependencies(task_id: number): void { - this.conn.query("DELETE FROM task_dependencies WHERE task_id = ?").run(task_id); + this.conn + .query("DELETE FROM task_dependencies WHERE task_id = ?") + .run(task_id); } /** Return upstream tasks that task_id depends on. */ @@ -1351,10 +1456,14 @@ export class TaskDB { delete_task(task_id: number): void { this.transaction(() => { - this.conn.query("DELETE FROM task_output_events WHERE task_id = ?").run(task_id); + this.conn + .query("DELETE FROM task_output_events WHERE task_id = ?") + .run(task_id); this.conn.query("DELETE FROM task_runs WHERE task_id = ?").run(task_id); this.conn - .query("DELETE FROM task_dependencies WHERE task_id = ? OR depends_on_task_id = ?") + .query( + "DELETE FROM task_dependencies WHERE task_id = ? OR depends_on_task_id = ?", + ) .run(task_id, task_id); this.conn.query("DELETE FROM tasks WHERE id = ?").run(task_id); }); diff --git a/backend/src/util.ts b/backend/src/util.ts index b4a43a7..77d2254 100644 --- a/backend/src/util.ts +++ b/backend/src/util.ts @@ -26,7 +26,8 @@ export function getEnv(): Record { ]; const current = env.PATH ?? ""; env.PATH = - extra.filter((p) => !current.includes(p)).join(":") + (current ? `:${current}` : ""); + extra.filter((p) => !current.includes(p)).join(":") + + (current ? `:${current}` : ""); return env; } @@ -60,9 +61,13 @@ export function nowIso(): string { * * Throws on unparseable input (≙ Python ValueError). */ -export function parseComparableDatetime(value: string | null | undefined): Date | null { +export function parseComparableDatetime( + value: string | null | undefined, +): Date | null { if (!value) return null; - const normalized = /^\d{4}-\d{2}-\d{2}$/.test(value) ? `${value}T00:00:00` : value; + const normalized = /^\d{4}-\d{2}-\d{2}$/.test(value) + ? `${value}T00:00:00` + : value; const dt = new Date(normalized); if (Number.isNaN(dt.getTime())) { throw new Error(`Invalid isoformat string: ${JSON.stringify(value)}`); @@ -70,7 +75,9 @@ export function parseComparableDatetime(value: string | null | undefined): Date return dt; } -export function normalizeDatetimeForStorage(value: string | null | undefined): string | null { +export function normalizeDatetimeForStorage( + value: string | null | undefined, +): string | null { if (value === null || value === undefined) return null; let dt: Date | null; try { diff --git a/backend/tests/bus.test.ts b/backend/tests/bus.test.ts index fadf3ba..bd666aa 100644 --- a/backend/tests/bus.test.ts +++ b/backend/tests/bus.test.ts @@ -238,7 +238,10 @@ test("test_bus_aware_scheduler_mixin_publishes_task_updates", async () => { }); test("test_bus_aware_scheduler_mixin_noops_without_bus", () => { - const scheduler = new FakeScheduler(new StubDB({ 1: { status: "completed" } }), null); + const scheduler = new FakeScheduler( + new StubDB({ 1: { status: "completed" } }), + null, + ); scheduler._bus_notify(1); }); diff --git a/backend/tests/taskdb.test.ts b/backend/tests/taskdb.test.ts index 2e8ac75..1b5c662 100644 --- a/backend/tests/taskdb.test.ts +++ b/backend/tests/taskdb.test.ts @@ -33,7 +33,9 @@ describe("TaskDB", () => { // ── completed-run queries (skill sweep inputs) helper ───────────────────── function finishWithTimestamp(run_id: number, finished_at: string): void { db.conn - .query("UPDATE task_runs SET status='completed', finished_at=? WHERE id=?") + .query( + "UPDATE task_runs SET status='completed', finished_at=? WHERE id=?", + ) .run(finished_at, run_id); } @@ -49,14 +51,18 @@ describe("TaskDB", () => { // ── run history ──────────────────────────────────────────────────────────── test("test_run_lifecycle_and_ordering", () => { - const tid = db.add_task(makeTask({ title: "t", prompt: "p", working_dir: "." })); + const tid = db.add_task( + makeTask({ title: "t", prompt: "p", working_dir: "." }), + ); const run1 = db.add_run(tid); db.finish_run(run1, "completed", "ok", null, "raw1"); const run2 = db.add_run(tid); db.finish_run(run2, "failed", null, "boom"); const runs = db.get_task_runs(tid); - expect(new Set(runs.map((r) => r["status"]))).toEqual(new Set(["completed", "failed"])); + expect(new Set(runs.map((r) => r["status"]))).toEqual( + new Set(["completed", "failed"]), + ); expect(new Set(runs.map((r) => r["id"]))).toEqual(new Set([run1, run2])); const completed = runs.find((r) => r["id"] === run1)!; expect(completed["result"]).toBe("ok"); @@ -65,7 +71,9 @@ describe("TaskDB", () => { }); test("test_finish_run_and_update_task_is_atomic", () => { - const tid = db.add_task(makeTask({ title: "t", prompt: "p", working_dir: "." })); + const tid = db.add_task( + makeTask({ title: "t", prompt: "p", working_dir: "." }), + ); const rid = db.add_run(tid); db.finish_run_and_update_task( @@ -87,7 +95,9 @@ describe("TaskDB", () => { // ── output events ────────────────────────────────────────────────────────── test("test_output_events_per_task_and_per_run", () => { - const tid = db.add_task(makeTask({ title: "t", prompt: "p", working_dir: "." })); + const tid = db.add_task( + makeTask({ title: "t", prompt: "p", working_dir: "." }), + ); const run1 = db.add_run(tid); const run2 = db.add_run(tid); db.add_output_event(tid, run1, "assistant", "hello"); @@ -109,7 +119,9 @@ describe("TaskDB", () => { // ── completed-run queries (skill sweep inputs) ───────────────────────────── test("test_get_completed_runs_since_watermark", () => { - const tid = db.add_task(makeTask({ title: "t", prompt: "p", working_dir: "." })); + const tid = db.add_task( + makeTask({ title: "t", prompt: "p", working_dir: "." }), + ); const old = db.add_run(tid); const newer = db.add_run(tid); finishWithTimestamp(old, "2020-01-01T00:00:00"); @@ -126,7 +138,9 @@ describe("TaskDB", () => { }); test("test_get_recent_completed_runs_oldest_first_with_limit", () => { - const tid = db.add_task(makeTask({ title: "t", prompt: "p", working_dir: "." })); + const tid = db.add_task( + makeTask({ title: "t", prompt: "p", working_dir: "." }), + ); const r1 = db.add_run(tid); const r2 = db.add_run(tid); const r3 = db.add_run(tid); @@ -158,8 +172,12 @@ describe("TaskDB", () => { db.upsert_skill_pattern("k", "recipe", "", 2, 11); expect(db.get_skill_pattern_recurrence("k")).toBe(2); const pattern = db.get_skill_pattern(pid)!; - expect([...JSON.parse(pattern["contributing_task_ids"])].sort()).toEqual([1, 2]); - expect([...JSON.parse(pattern["contributing_run_ids"])].sort()).toEqual([10, 11]); + expect([...JSON.parse(pattern["contributing_task_ids"])].sort()).toEqual([ + 1, 2, + ]); + expect([...JSON.parse(pattern["contributing_run_ids"])].sort()).toEqual([ + 10, 11, + ]); // empty summary must NOT clobber the prior one expect(pattern["summary"]).toBe("updated"); }); @@ -205,7 +223,17 @@ describe("TaskDB", () => { expect(db.get_skill_draft(pid)!["status"]).toBe("drafting"); // ON CONFLICT(pattern_id) updates in place - db.upsert_skill_draft(pid, "ready", "my-skill", "", "recipe", "b", null, true, "reusable"); + db.upsert_skill_draft( + pid, + "ready", + "my-skill", + "", + "recipe", + "b", + null, + true, + "reusable", + ); const draft = db.get_skill_draft(pid)!; expect(draft["status"]).toBe("ready"); expect(draft["name"]).toBe("my-skill"); @@ -223,8 +251,12 @@ describe("TaskDB", () => { // ── dependencies / DAG ───────────────────────────────────────────────────── test("test_dependency_crud_and_views", () => { - const up = db.add_task(makeTask({ title: "up", prompt: "p", working_dir: "." })); - const down = db.add_task(makeTask({ title: "down", prompt: "p", working_dir: "." })); + const up = db.add_task( + makeTask({ title: "up", prompt: "p", working_dir: "." }), + ); + const down = db.add_task( + makeTask({ title: "down", prompt: "p", working_dir: "." }), + ); db.add_dependency(down, up, true); // duplicate insert is ignored @@ -246,25 +278,39 @@ describe("TaskDB", () => { }); test("test_add_dependencies_batch_and_clear", () => { - const a = db.add_task(makeTask({ title: "a", prompt: "p", working_dir: "." })); - const b = db.add_task(makeTask({ title: "b", prompt: "p", working_dir: "." })); - const down = db.add_task(makeTask({ title: "d", prompt: "p", working_dir: "." })); + const a = db.add_task( + makeTask({ title: "a", prompt: "p", working_dir: "." }), + ); + const b = db.add_task( + makeTask({ title: "b", prompt: "p", working_dir: "." }), + ); + const down = db.add_task( + makeTask({ title: "d", prompt: "p", working_dir: "." }), + ); db.add_dependencies_batch(down, [ { task_id: a, inject_result: true }, { task_id: b, inject_result: false }, ]); const deps = db.get_dependencies(down); - expect(new Set(deps.map((d) => d["depends_on_task_id"]))).toEqual(new Set([a, b])); + expect(new Set(deps.map((d) => d["depends_on_task_id"]))).toEqual( + new Set([a, b]), + ); db.clear_dependencies(down); expect(db.get_dependencies(down)).toEqual([]); }); test("test_get_dag_tasks_filters_by_dag_id", () => { - db.add_task(makeTask({ title: "x", prompt: "p", working_dir: ".", dag_id: "flow-1" })); - db.add_task(makeTask({ title: "y", prompt: "p", working_dir: ".", dag_id: "flow-1" })); - db.add_task(makeTask({ title: "z", prompt: "p", working_dir: ".", dag_id: "other" })); + db.add_task( + makeTask({ title: "x", prompt: "p", working_dir: ".", dag_id: "flow-1" }), + ); + db.add_task( + makeTask({ title: "y", prompt: "p", working_dir: ".", dag_id: "flow-1" }), + ); + db.add_task( + makeTask({ title: "z", prompt: "p", working_dir: ".", dag_id: "other" }), + ); const flow = db.get_dag_tasks("flow-1"); expect(new Set(flow.map((t) => t["title"]))).toEqual(new Set(["x", "y"])); @@ -272,8 +318,12 @@ describe("TaskDB", () => { // ── cascading delete ─────────────────────────────────────────────────────── test("test_delete_task_removes_runs_events_and_deps", () => { - const up = db.add_task(makeTask({ title: "up", prompt: "p", working_dir: "." })); - const tid = db.add_task(makeTask({ title: "t", prompt: "p", working_dir: "." })); + const up = db.add_task( + makeTask({ title: "up", prompt: "p", working_dir: "." }), + ); + const tid = db.add_task( + makeTask({ title: "t", prompt: "p", working_dir: "." }), + ); db.add_dependency(tid, up); const rid = db.add_run(tid); db.add_output_event(tid, rid, "assistant", "hi"); @@ -293,7 +343,9 @@ describe("TaskDB", () => { const past = dateToLocalIso(new Date(now.getTime() - 5 * 60 * 1000)); const future = dateToLocalIso(new Date(now.getTime() + 60 * 60 * 1000)); - const immediate = db.add_task(makeTask({ title: "now", prompt: "p", working_dir: "." })); + const immediate = db.add_task( + makeTask({ title: "now", prompt: "p", working_dir: "." }), + ); const due_scheduled = db.add_task( makeTask({ title: "due", @@ -314,7 +366,9 @@ describe("TaskDB", () => { }), ); db.update_task(not_yet, { status: "scheduled" }); - const running = db.add_task(makeTask({ title: "running", prompt: "p", working_dir: "." })); + const running = db.add_task( + makeTask({ title: "running", prompt: "p", working_dir: "." }), + ); db.update_task(running, { status: "running" }); const due_ids = new Set(db.get_due_tasks().map((t) => t["id"])); From 80562a1fdd8668c5b4e4797b16c90fe554721291 Mon Sep 17 00:00:00 2001 From: taohe Date: Sat, 13 Jun 2026 01:11:28 +0800 Subject: [PATCH 09/18] docs: update AGENTS.md for TypeScript+Bun architecture Co-Authored-By: Claude Fable 5 --- AGENTS.md | 104 +++++++++++++++++++++++++++++------------------------- 1 file changed, 55 insertions(+), 49 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 814e648..ccaea42 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,89 +1,95 @@ ## Project Overview -AgentForge is a macOS desktop app (Electron + Python) that provides a kanban-style task board for orchestrating AI coding agents (**Claude Code or OpenAI Codex CLI**). The Python backend manages task scheduling, execution, and persistence; the React frontend renders the board and streams live output. Tasks can also be created/monitored from chat channels (Telegram / Slack / Feishu / WeChat), and a **Skill Library** distills recurring task patterns into reusable Claude Code skills. +AgentForge is a macOS desktop app (Electron + Bun/TypeScript) that provides a kanban-style task board for orchestrating AI coding agents (**Claude Code or OpenAI Codex CLI**). The TypeScript backend (running on Bun) manages task scheduling, execution, and persistence; the React frontend renders the board and streams live output. Tasks can also be created/monitored from chat channels (Telegram / Slack / Feishu / WeChat), and a **Skill Library** distills recurring task patterns into reusable Claude Code skills. + +The entire project is TypeScript-only and uses **Bun** to build, run, test, and compile (no Python, no Node toolchain — Electron's bundled Node runs the packaged app, but all tooling is Bun). ## Commands -### Python Backend +### Backend (`backend/`) ```bash -# Run backend directly (dev) -uv run taskboard.py - -# Run with explicit port (default 9712) -uv run taskboard.py # listens on 127.0.0.1:9712 (loopback only — not network-exposed) +# Run backend directly (dev) — listens on 127.0.0.1:9712 (loopback only) +cd backend && bun taskboard.ts # Verify health curl http://127.0.0.1:9712/api/health -# Build PyInstaller binary (must run from project root) -uv run pyinstaller --onefile --name taskboard \ - --distpath taskboard-electron/resources \ - --hidden-import croniter --hidden-import dateutil --hidden-import pytz \ - taskboard.py +# Compile single-file binary for packaging (replaces PyInstaller) +cd taskboard-electron && bun scripts/build-backend.ts +# (equivalent: cd backend && bun run compile) ``` ### Electron App ```bash -# Dev: starts Electron + Vite dev server (spawns uv run taskboard.py automatically) -cd taskboard-electron && npm start +# Dev: Bun-builds main/preload/renderer, launches Electron with watch + reload +# (spawns `bun backend/taskboard.ts` automatically) +cd taskboard-electron && bun run start # Build distributable DMG (arm64) -cd taskboard-electron && npm run make +cd taskboard-electron && bun run make # Output: taskboard-electron/out/make/AgentForge-1.0.0-arm64.dmg ``` ### Tests & Quality ```bash # Backend (⭐ backend-quality CI job runs `make check`) -make check # ruff lint + ruff format --check + pytest (coverage, fail_under=90) -make test # pytest only -make lint # ruff check ONLY (no format-check, no tests — NOT the CI gate) -make format # apply ruff formatting -uv run pytest -q # run the Python suite directly +make check # = cd backend && bun run check (tsc --noEmit + prettier --check + bun test --coverage) +make test # bun test only +make lint # tsc typecheck ONLY (no format-check, no tests — NOT the CI gate) +make format # apply prettier formatting +cd backend && bun test # run the suite directly -# Frontend (⭐ frontend-quality CI job runs all four, from taskboard-electron/) +# Frontend (⭐ frontend-quality CI job runs all five, from taskboard-electron/) cd taskboard-electron -npm run lint # ESLint (flat config, eslint.config.mjs) -npm run format:check # Prettier --check (npm run format to apply) -npm test # node --test (pins TZ=Asia/Shanghai — date tests assert local wall time) -npm run build:check # vite renderer build — catches compile/import errors +bun run typecheck # tsc over renderer + main/preload tsconfigs +bun run lint # ESLint (flat config, typescript-eslint, eslint.config.mjs) +bun run format:check # Prettier --check (bun run format to apply) +bun run test # bun test (pins TZ=Asia/Shanghai — date tests assert local wall time) +bun run build:check # Bun.build of main/preload/renderer — catches compile/import errors ``` -CI (`.github/workflows/ci.yml`) runs two jobs: **backend-quality** (`make check`) -and **frontend-quality** (lint + format check + tests + build). The workflow uses -`concurrency` to cancel superseded runs on the same ref. There are 34 pytest files -under `tests/` (backend coverage gate is 90%) plus `.test.mjs` files beside the renderer. +CI (`.github/workflows/ci.yml`) runs two jobs: **backend-quality** (`bun run check` in `backend/`) +and **frontend-quality** (typecheck + lint + format check + tests + build). The workflow uses +`concurrency` to cancel superseded runs on the same ref. Backend tests live in `backend/tests/*.test.ts` +(bun:test), frontend tests beside the renderer sources as `*.test.ts`. ## Architecture ### Two-process model -The Electron main process (`taskboard-electron/src/main.js`) spawns the Python backend on startup and kills it on quit. The React renderer communicates with the backend exclusively via HTTP on `127.0.0.1:9712` (loopback only). There is no WebSocket or IPC for data — the renderer polls the REST API with `fetch()`. +The Electron main process (`taskboard-electron/src/main.ts`) spawns the Bun backend on startup and kills it on quit. The React renderer communicates with the backend exclusively via HTTP on `127.0.0.1:9712` (loopback only). There is no WebSocket or IPC for data — the renderer polls the REST API with `fetch()`. -### Python backend (`taskboard.py`) -Single-file HTTP server (`BaseHTTPRequestHandler`) with: -- **`TaskDB`** — SQLite layer at `~/.agentforge/tasks.db`. Thread-safe with a lock. Stores tasks, run history, and streaming output events. -- **`AgentExecutor`** — Runs the agent CLI: `claude -p … --output-format stream-json --verbose --permission-mode bypassPermissions`, or `codex exec --json …`. Parses the NDJSON stream and persists each event to `task_output_events`. -- **`TaskScheduler`** — Background thread that polls every 2 seconds for due tasks. Supports four schedule types: +### Bun backend (`backend/`) +TypeScript modules served by `Bun.serve` (entry `backend/taskboard.ts`): +- **`src/db.ts` — `TaskDB`** — SQLite layer (bun:sqlite) at `~/.agentforge/tasks.db`. Stores tasks, run history, and streaming output events. Method names keep the original Python snake_case spelling (they double as API JSON keys). +- **`src/executor.ts` — `AgentExecutor`** — Runs the agent CLI: `claude -p … --output-format stream-json --verbose --permission-mode bypassPermissions`, or `codex exec --json …`. Parses the NDJSON stream and persists each event to `task_output_events`. +- **`src/scheduler.ts` — `TaskScheduler`** — Polls every 2 seconds for due tasks. Supports four schedule types: - `immediate`: runs as soon as scheduled - `delayed`: runs after N seconds (relative time) - `scheduled_at`: runs once at a specific datetime (absolute time) - - `cron`: recurring schedule using croniter for cron expression evaluation -- **`Heartbeat`** — Background watcher: on a cron/interval it runs a `check_prompt` via an agent that returns a JSON decision (idle/trigger/resume/notify) and may auto-create tasks. -- **Skill Library** — `TaskScheduler.run_skill_sweep` periodically (or via the manual "Scan" button) asks an agent to detect recurring patterns across completed runs (`skill_patterns` table), distills candidates into standard Claude Code `SKILL.md` files using the vendored `vendor/skill-creator`, and on approval writes them to `~/.agentforge/skills` symlinked into both `~/.claude/skills` and `~/.agents/skills`. Off by default (`skill_library_enabled` setting). -- **Channels** (`channels/`) — Optional Telegram / Slack / Feishu / WeChat bridges (a `MessageBus` in `taskboard_bus.py` decouples them from the scheduler). Feishu uses a lark WebSocket long-connection. -- **REST API** — Endpoints under `/api/tasks*`, `/api/heartbeats*`, `/api/skill-patterns`, `/api/skills*`, `/api/settings`, `/api/channels/*`, `/api/health`. - -### Electron main process (`taskboard-electron/src/main.js`) -- In **dev mode**: `app.getAppPath()` returns `taskboard-electron/`, so `path.join(app.getAppPath(), '..')` resolves to project root for `uv run taskboard.py`. The `cwd` option must point to project root when spawning. -- In **packaged mode**: uses the binary at `resources/taskboard` bundled inside the `.app`. + - `cron`: recurring schedule using cron-parser for cron expression evaluation +- **Heartbeats** — Background watcher: on a cron/interval it runs a `check_prompt` via an agent that returns a JSON decision (idle/trigger/resume/notify) and may auto-create tasks. +- **Skill Library** (`src/skills.ts` + scheduler) — `TaskScheduler.run_skill_sweep` periodically (or via the manual "Scan" button) asks an agent to detect recurring patterns across completed runs (`skill_patterns` table), distills candidates into standard Claude Code `SKILL.md` files using the vendored `vendor/skill-creator`, and on approval writes them to `~/.agentforge/skills` symlinked into both `~/.claude/skills` and `~/.agents/skills`. Off by default (`skill_library_enabled` setting). +- **Channels** (`src/channels/`) — Optional Telegram / Slack / Feishu / WeChat bridges (a `MessageBus` in `src/bus.ts` decouples them from the scheduler). Feishu uses a lark WebSocket long-connection (`@larksuiteoapi/node-sdk`). +- **REST API** (`src/api.ts`, `src/server.ts`) — Endpoints under `/api/tasks*`, `/api/heartbeats*`, `/api/skill-patterns`, `/api/skills*`, `/api/settings`, `/api/channels/*`, `/api/health`. + +### Electron main process (`taskboard-electron/src/main.ts`) +- In **dev mode**: `app.getAppPath()` returns `taskboard-electron/`, so `path.join(app.getAppPath(), '..')` resolves to project root for `bun backend/taskboard.ts`. The `cwd` option must point to project root when spawning. +- In **packaged mode**: uses the `bun build --compile` binary at `resources/taskboard` bundled inside the `.app`. - Polls `/api/health` (15s timeout) before loading the UI. - Exposes `window.electronAPI.selectDirectory()` to renderer via context bridge for native directory picker. -### React frontend (`taskboard-electron/src/renderer/App.jsx`) -Single large component (~4200 lines). Key design points: +### Build pipeline (`taskboard-electron/scripts/`) +- `build.ts` — `Bun.build` bundles main (CJS, electron external), preload (CJS), and renderer (HTML entrypoint → `.bun/renderer/`). Replaces the old Vite plugin. +- `dev.ts` — watch-rebuild + Electron launcher; renderer rebuilds trigger window reload (main.ts watches `.bun/renderer`), backend `.ts` changes restart the backend. +- `build-backend.ts` — `bun build --compile` of `backend/taskboard.ts` into `resources/taskboard`. +- electron-forge is retained only for packaging/DMG (`bunx electron-forge package|make`); `forge.config.js` ships `.bun/` output via packager ignore rules. + +### React frontend (`taskboard-electron/src/renderer/App.tsx`) +Single large component (~6200 lines). Key design points: - `API` constant hardcoded to `http://127.0.0.1:9712/api`. - Three top-level views (tab switch): **Tasks** (kanban), **Heartbeats**, **Skills**. - Kanban columns: **Queue** (pending/scheduled/blocked) → **Running** → **Done** (completed/failed/cancelled). -- `FormattedOutput` component parses stream-json events (type: `user`/`assistant`/`result`/`error`) and renders colorized output; trace/event aggregation helpers live in `traceSteps.mjs` (tested by `traceSteps.test.mjs`). +- `FormattedOutput` component parses stream-json events (type: `user`/`assistant`/`result`/`error`) and renders colorized output; trace/event aggregation helpers live in `traceSteps.ts` (tested by `traceSteps.test.ts`). +- Backend payload interfaces (snake_case) live in `src/renderer/types.ts`. - Task creation supports four schedule types: - `immediate`: run immediately - `delayed`: run after N seconds @@ -100,6 +106,6 @@ Single large component (~4200 lines). Key design points: ## Workflow Rules ### Always run `make check` after changing code -- After any change to Python code (or before pushing / reporting done), run **`make check`** — not `make lint`. `make lint` only runs `ruff check`; it skips `ruff format --check` and the tests, so it will pass while CI still fails on formatting or a broken test. +- After any change to backend code (or before pushing / reporting done), run **`make check`** — not `make lint`. `make lint` only runs the tsc typecheck; it skips `prettier --check` and the tests, so it will pass while CI still fails on formatting or a broken test. - If `make check` reports formatting diffs, run `make format` to fix them, then re-run `make check`. -- For frontend-only changes, run the frontend gate from `taskboard-electron/`: `npm run lint && npm run format:check && npm test && npm run build:check` (this is exactly what the frontend-quality CI job runs). If `format:check` fails, run `npm run format` to fix. +- For frontend-only changes, run the frontend gate from `taskboard-electron/`: `bun run typecheck && bun run lint && bun run format:check && bun run test && bun run build:check` (this is exactly what the frontend-quality CI job runs). If `format:check` fails, run `bun run format` to fix. From 68bea63b92f40b46efa7a0770f254191657511c3 Mon Sep 17 00:00:00 2001 From: taohe Date: Sat, 13 Jun 2026 01:12:41 +0800 Subject: [PATCH 10/18] feat(skills): port agentforge skill CLI to TypeScript/Bun Co-Authored-By: Claude Fable 5 --- skills/agentforge/SKILL.md | 58 ++-- skills/agentforge/scripts/agentforge_api.py | 285 -------------------- skills/agentforge/scripts/agentforge_api.ts | 264 ++++++++++++++++++ 3 files changed, 293 insertions(+), 314 deletions(-) delete mode 100644 skills/agentforge/scripts/agentforge_api.py create mode 100644 skills/agentforge/scripts/agentforge_api.ts diff --git a/skills/agentforge/SKILL.md b/skills/agentforge/SKILL.md index 038df05..5f70b39 100644 --- a/skills/agentforge/SKILL.md +++ b/skills/agentforge/SKILL.md @@ -16,17 +16,17 @@ Interact with AgentForge, a task orchestration system for AI coding agents. ## Script Path -The CLI script is located at `$SKILL_DIR/scripts/agentforge_api.py` relative to this skill's installation directory. +The CLI script is located at `$SKILL_DIR/scripts/agentforge_api.ts` relative to this skill's installation directory. Resolve the absolute path before invoking: ```bash SKILL_DIR="$(cd "$(dirname "$0")" && pwd)" -python "$SKILL_DIR/scripts/agentforge_api.py" --method health +bun "$SKILL_DIR/scripts/agentforge_api.ts" --method health ``` In practice, use the full absolute path when calling the script, e.g.: ```bash -python /path/to/skills/agentforge/scripts/agentforge_api.py --method list +bun /path/to/skills/agentforge/scripts/agentforge_api.ts --method list ``` **No external dependencies required** — the script uses only Python standard library (`urllib`, `json`, `argparse`). @@ -37,26 +37,26 @@ Use the CLI script with explicit `--method` parameter: ```bash # Create an immediate task -python scripts/agentforge_api.py --method create \ +bun scripts/agentforge_api.ts --method create \ --prompt "Run the test suite" --title "Run tests" --dir /path/to/project # List all tasks -python scripts/agentforge_api.py --method list +bun scripts/agentforge_api.ts --method list # Get task details -python scripts/agentforge_api.py --method get --task-id 5 +bun scripts/agentforge_api.ts --method get --task-id 5 # View live output -python scripts/agentforge_api.py --method output --task-id 5 +bun scripts/agentforge_api.ts --method output --task-id 5 # Retry a failed task -python scripts/agentforge_api.py --method retry --task-id 5 +bun scripts/agentforge_api.ts --method retry --task-id 5 # Delete a task -python scripts/agentforge_api.py --method delete --task-id 5 +bun scripts/agentforge_api.ts --method delete --task-id 5 # Cancel a task -python scripts/agentforge_api.py --method cancel --task-id 5 +bun scripts/agentforge_api.ts --method cancel --task-id 5 ``` ## Core Operations @@ -67,35 +67,35 @@ Create tasks using `--method create` with explicit parameters: **Immediate execution:** ```bash -python scripts/agentforge_api.py --method create \ +bun scripts/agentforge_api.ts --method create \ --prompt "Fix the bug in login.py" \ --title "Fix login bug" --dir ~/my-project ``` **Delayed execution:** ```bash -python scripts/agentforge_api.py --method create \ +bun scripts/agentforge_api.ts --method create \ --prompt "Send status report" --title "Status report" \ --schedule delayed --delay 300 ``` **At specific time (one-time execution):** ```bash -python scripts/agentforge_api.py --method create \ +bun scripts/agentforge_api.ts --method create \ --prompt "Deploy to production" --title "Production deploy" \ --schedule scheduled_at --at "2026-02-15 14:30:00" ``` **Recurring cron schedule:** ```bash -python scripts/agentforge_api.py --method create \ +bun scripts/agentforge_api.ts --method create \ --prompt "Run daily backup" --title "Daily backup" \ --schedule cron --cron "0 2 * * *" --max-runs 30 ``` **With image attachments:** ```bash -python scripts/agentforge_api.py --method create \ +bun scripts/agentforge_api.ts --method create \ --prompt "Analyze this screenshot" --title "Screenshot analysis" \ --image-paths "/path/to/image1.png,/path/to/image2.jpg" ``` @@ -110,7 +110,7 @@ python scripts/agentforge_api.py --method create \ **List all tasks:** ```bash -python scripts/agentforge_api.py --method list +bun scripts/agentforge_api.ts --method list # Output: 🕐 #1: My task (pending) # ⏳ #2: Running task (running) # ✅ #3: Done task (completed) @@ -118,13 +118,13 @@ python scripts/agentforge_api.py --method list **List with status filter:** ```bash -python scripts/agentforge_api.py --method list --status running -python scripts/agentforge_api.py --method list --status completed --json +bun scripts/agentforge_api.ts --method list --status running +bun scripts/agentforge_api.ts --method list --status completed --json ``` **Get specific task:** ```bash -python scripts/agentforge_api.py --method get --task-id 5 +bun scripts/agentforge_api.ts --method get --task-id 5 # Returns full JSON with status, result, error, etc. ``` @@ -141,7 +141,7 @@ python scripts/agentforge_api.py --method get --task-id 5 **Retry a failed task (re-enqueue for execution):** ```bash -python scripts/agentforge_api.py --method retry --task-id 5 +bun scripts/agentforge_api.ts --method retry --task-id 5 # Returns: {"status": "pending"} ``` @@ -152,7 +152,7 @@ python scripts/agentforge_api.py --method retry --task-id 5 **Permanently delete a task:** ```bash -python scripts/agentforge_api.py --method delete --task-id 5 +bun scripts/agentforge_api.ts --method delete --task-id 5 # Returns: {"status": "deleted"} ``` @@ -163,7 +163,7 @@ python scripts/agentforge_api.py --method delete --task-id 5 **Cancel a running or pending task:** ```bash -python scripts/agentforge_api.py --method cancel --task-id 5 +bun scripts/agentforge_api.ts --method cancel --task-id 5 # Returns: {"status": "cancelled"} ``` @@ -175,19 +175,19 @@ python scripts/agentforge_api.py --method cancel --task-id 5 **Get run history:** ```bash -python scripts/agentforge_api.py --method runs --task-id 5 +bun scripts/agentforge_api.ts --method runs --task-id 5 ``` **Get live output for running task:** ```bash -python scripts/agentforge_api.py --method output --task-id 5 +bun scripts/agentforge_api.ts --method output --task-id 5 # Shows: Status: Running # Output: [live accumulated output] ``` **Get structured events:** ```bash -python scripts/agentforge_api.py --method events --task-id 5 --limit 100 +bun scripts/agentforge_api.ts --method events --task-id 5 --limit 100 ``` ## Response Formatting @@ -209,19 +209,19 @@ Create workflows where tasks automatically trigger downstream tasks upon complet **Create a task with upstream dependencies:** ```bash # Task #12 will be BLOCKED until tasks #10 and #11 complete -python scripts/agentforge_api.py --method create \ +bun scripts/agentforge_api.ts --method create \ --prompt "Analyze results" --title "Analysis" --dir ~/project \ --depends-on 10,11 --dag-id my-pipeline # Inject upstream results into the prompt automatically -python scripts/agentforge_api.py --method create \ +bun scripts/agentforge_api.ts --method create \ --prompt "Summarize the findings" --title "Summary" --dir ~/project \ --depends-on 12 --inject-result --dag-id my-pipeline ``` **View a full DAG pipeline:** ```bash -python scripts/agentforge_api.py --method dag --dag-id my-pipeline +bun scripts/agentforge_api.ts --method dag --dag-id my-pipeline # Output: # DAG: my-pipeline (3 tasks) # ✅ #10: Build (completed) @@ -245,7 +245,7 @@ The CLI provides specific error messages: ## Implementation Notes -- The CLI script (`scripts/agentforge_api.py`) handles all HTTP communication +- The CLI script (`scripts/agentforge_api.ts`) handles all HTTP communication - Uses only Python standard library (no `pip install` needed) - Default API endpoint: `http://127.0.0.1:9712/api` - AgentForge must be running locally for this skill to work diff --git a/skills/agentforge/scripts/agentforge_api.py b/skills/agentforge/scripts/agentforge_api.py deleted file mode 100644 index 1b660f5..0000000 --- a/skills/agentforge/scripts/agentforge_api.py +++ /dev/null @@ -1,285 +0,0 @@ -#!/usr/bin/env python3 -""" -AgentForge CLI - Command-line interface for AgentForge API - -Usage: - agentforge_api.py --method create --prompt "..." [options] - agentforge_api.py --method list [--status STATUS] - agentforge_api.py --method get --task-id ID - agentforge_api.py --method runs --task-id ID - agentforge_api.py --method output --task-id ID - agentforge_api.py --method events --task-id ID [--limit N] - agentforge_api.py --method cancel --task-id ID - agentforge_api.py --method retry --task-id ID - agentforge_api.py --method delete --task-id ID - agentforge_api.py --method dag --dag-id ID - agentforge_api.py --method health - -Examples: - agentforge_api.py --method create --prompt "Run tests" --title "Test run" --dir /path/to/project - agentforge_api.py --method create --prompt "Backup" --schedule delayed --delay 300 - agentforge_api.py --method create --prompt "Deploy" --schedule scheduled_at --at "2026-02-15 14:30:00" - agentforge_api.py --method create --prompt "Daily report" --schedule cron --cron "0 2 * * *" - agentforge_api.py --method create --prompt "Step 2" --depends-on 10,11 --inject-result --dag-id my-pipeline - agentforge_api.py --method list --status running - agentforge_api.py --method get --task-id 5 - agentforge_api.py --method output --task-id 5 - agentforge_api.py --method retry --task-id 5 - agentforge_api.py --method delete --task-id 5 - agentforge_api.py --method dag --dag-id my-pipeline -""" - -import argparse -import json -import os -import sys -import urllib.error -import urllib.parse -import urllib.request -from datetime import datetime - -API_BASE = "http://127.0.0.1:9712/api" - -SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) - - -def api_request(method, path, json_data=None, params=None): - """Make HTTP request to AgentForge API using stdlib only.""" - url = f"{API_BASE}{path}" - if params: - url += "?" + urllib.parse.urlencode(params) - - body = None - headers = {} - if json_data is not None: - body = json.dumps(json_data).encode("utf-8") - headers["Content-Type"] = "application/json" - - req = urllib.request.Request(url, data=body, headers=headers, method=method) - - try: - with urllib.request.urlopen(req) as resp: - return json.loads(resp.read().decode("utf-8")) - except urllib.error.URLError as e: - if isinstance(e, urllib.error.HTTPError): - try: - err_body = json.loads(e.read().decode("utf-8")) - detail = err_body.get("error", e.reason) - except Exception: - detail = e.reason - print(f"API error (HTTP {e.code}): {detail}", file=sys.stderr) - elif "Connection refused" in str(e.reason) or "No connection" in str(e.reason): - print( - "Connection failed: AgentForge is not running.\n" - "Start it with: cd && uv run taskboard.py", - file=sys.stderr, - ) - else: - print(f"Network error: {e.reason}", file=sys.stderr) - sys.exit(1) - - -STATUS_ICONS = { - "pending": "🕐", - "scheduled": "⏰", - "running": "⏳", - "completed": "✅", - "failed": "❌", - "cancelled": "🚫", - "blocked": "⊘", -} - - -def main(): - parser = argparse.ArgumentParser( - description="AgentForge CLI - Manage AI agent tasks", - formatter_class=argparse.RawDescriptionHelpFormatter, - epilog=__doc__, - ) - - parser.add_argument( - "--method", - required=True, - choices=[ - "create", "list", "get", "runs", "output", "events", - "cancel", "retry", "delete", "dag", "health", - ], - help="API method to call", - ) - - # Task creation parameters - parser.add_argument("--prompt", help="Task prompt/instruction (for create)") - parser.add_argument("--title", help="Task title (for create)") - parser.add_argument("--dir", default=".", help="Working directory (for create, default: .)") - parser.add_argument( - "--schedule", - choices=["immediate", "delayed", "scheduled_at", "cron"], - default="immediate", - help="Schedule type (for create)", - ) - parser.add_argument("--cron", help="Cron expression (for create with schedule=cron)") - parser.add_argument("--delay", type=int, help="Delay in seconds (for create with schedule=delayed)") - parser.add_argument("--at", help="Specific datetime (for create with schedule=scheduled_at, format: 'YYYY-MM-DD HH:MM:SS')") - parser.add_argument("--max-runs", type=int, help="Max runs for cron tasks (for create)") - parser.add_argument("--tags", default="", help="Comma-separated tags (for create)") - parser.add_argument("--image-paths", help="Comma-separated list of image file paths (for create)") - # DAG parameters - parser.add_argument("--depends-on", help="Comma-separated upstream task IDs (for create), e.g. '10,11'") - parser.add_argument("--inject-result", action="store_true", help="Inject upstream results into prompt (for create with --depends-on)") - parser.add_argument("--dag-id", help="DAG workflow group label (for create or dag method)") - - # Query parameters - parser.add_argument("--task-id", type=int, help="Task ID (for get/runs/output/events/cancel/retry/delete)") - parser.add_argument("--status", help="Filter by status (for list)") - parser.add_argument("--limit", type=int, default=1000, help="Max events to return (for events)") - parser.add_argument("--offset", type=int, default=0, help="Events to skip (for events)") - - # Output formatting - parser.add_argument("--json", action="store_true", help="Output as JSON (for list/output)") - - args = parser.parse_args() - - # Route to appropriate handler - if args.method == "create": - if not args.prompt: - parser.error("--prompt is required for create method") - - data = { - "prompt": args.prompt, - "title": args.title or args.prompt[:60], - "working_dir": args.dir, - "schedule_type": args.schedule, - "tags": args.tags, - } - - if args.cron: - data["cron_expr"] = args.cron - if args.delay: - data["delay_seconds"] = args.delay - if args.at: - try: - dt = datetime.strptime(args.at, "%Y-%m-%d %H:%M:%S") - data["next_run_at"] = dt.isoformat() - except ValueError: - print("Error: --at must be in format 'YYYY-MM-DD HH:MM:SS'", file=sys.stderr) - sys.exit(1) - if args.max_runs: - data["max_runs"] = args.max_runs - if args.dag_id: - data["dag_id"] = args.dag_id - if args.image_paths: - paths = [p.strip() for p in args.image_paths.split(",") if p.strip()] - data["image_paths"] = paths - if args.depends_on: - ids = [int(x.strip()) for x in args.depends_on.split(",") if x.strip().isdigit()] - data["depends_on"] = [ - {"task_id": tid, "inject_result": args.inject_result} - for tid in ids - ] - - result = api_request("POST", "/tasks", json_data=data) - print(json.dumps(result, indent=2)) - - elif args.method == "list": - tasks = api_request("GET", "/tasks") - - if args.status: - tasks = [t for t in tasks if t["status"] == args.status] - - if args.json: - print(json.dumps(tasks, indent=2)) - else: - if not tasks: - print("No tasks found.") - for task in tasks: - icon = STATUS_ICONS.get(task["status"], "❓") - dag_label = f" [dag:{task['dag_id']}]" if task.get("dag_id") else "" - print(f"{icon} #{task['id']}: {task['title']} ({task['status']}){dag_label}") - - elif args.method == "get": - if not args.task_id: - parser.error("--task-id is required for get method") - task = api_request("GET", f"/tasks/{args.task_id}") - print(json.dumps(task, indent=2)) - - elif args.method == "runs": - if not args.task_id: - parser.error("--task-id is required for runs method") - runs = api_request("GET", f"/tasks/{args.task_id}/runs") - print(json.dumps(runs, indent=2)) - - elif args.method == "output": - if not args.task_id: - parser.error("--task-id is required for output method") - result = api_request("GET", f"/tasks/{args.task_id}/output") - - if args.json: - print(json.dumps(result, indent=2)) - else: - if result["is_running"]: - print("Status: Running") - print("\nOutput:") - else: - print("Status: Not running") - print(result["output"]) - - elif args.method == "events": - if not args.task_id: - parser.error("--task-id is required for events method") - params = {"limit": args.limit, "offset": args.offset} - result = api_request("GET", f"/tasks/{args.task_id}/events", params=params) - print(json.dumps(result, indent=2)) - - elif args.method == "cancel": - if not args.task_id: - parser.error("--task-id is required for cancel method") - result = api_request("POST", f"/tasks/{args.task_id}/cancel") - print(json.dumps(result, indent=2)) - - elif args.method == "retry": - if not args.task_id: - parser.error("--task-id is required for retry method") - result = api_request("POST", f"/tasks/{args.task_id}/retry") - print(json.dumps(result, indent=2)) - - elif args.method == "delete": - if not args.task_id: - parser.error("--task-id is required for delete method") - req = urllib.request.Request( - f"{API_BASE}/tasks/{args.task_id}", method="DELETE" - ) - try: - with urllib.request.urlopen(req) as resp: - result = json.loads(resp.read().decode("utf-8")) - print(json.dumps(result, indent=2)) - except urllib.error.HTTPError as e: - try: - err_body = json.loads(e.read().decode("utf-8")) - detail = err_body.get("error", e.reason) - except Exception: - detail = e.reason - print(f"API error (HTTP {e.code}): {detail}", file=sys.stderr) - sys.exit(1) - - elif args.method == "dag": - if not args.dag_id: - parser.error("--dag-id is required for dag method") - tasks = api_request("GET", f"/dag/{args.dag_id}") - if args.json: - print(json.dumps(tasks, indent=2)) - else: - print(f"DAG: {args.dag_id} ({len(tasks)} tasks)") - for task in tasks: - icon = STATUS_ICONS.get(task["status"], "❓") - deps = task.get("dependencies", []) - dep_ids = ", ".join(f"#{d['depends_on_task_id']}" for d in deps) - dep_label = f" <- {dep_ids}" if deps else "" - print(f" {icon} #{task['id']}: {task['title']} ({task['status']}){dep_label}") - - elif args.method == "health": - result = api_request("GET", "/health") - print(json.dumps(result, indent=2)) - - -if __name__ == "__main__": - main() diff --git a/skills/agentforge/scripts/agentforge_api.ts b/skills/agentforge/scripts/agentforge_api.ts new file mode 100644 index 0000000..80f4251 --- /dev/null +++ b/skills/agentforge/scripts/agentforge_api.ts @@ -0,0 +1,264 @@ +#!/usr/bin/env bun +/** + * AgentForge CLI - Command-line interface for AgentForge API + * + * Usage: + * agentforge_api.ts --method create --prompt "..." [options] + * agentforge_api.ts --method list [--status STATUS] + * agentforge_api.ts --method get --task-id ID + * agentforge_api.ts --method runs --task-id ID + * agentforge_api.ts --method output --task-id ID + * agentforge_api.ts --method events --task-id ID [--limit N] + * agentforge_api.ts --method cancel --task-id ID + * agentforge_api.ts --method retry --task-id ID + * agentforge_api.ts --method delete --task-id ID + * agentforge_api.ts --method dag --dag-id ID + * agentforge_api.ts --method health + * + * Examples: + * agentforge_api.ts --method create --prompt "Run tests" --title "Test run" --dir /path/to/project + * agentforge_api.ts --method create --prompt "Backup" --schedule delayed --delay 300 + * agentforge_api.ts --method create --prompt "Deploy" --schedule scheduled_at --at "2026-02-15 14:30:00" + * agentforge_api.ts --method create --prompt "Daily report" --schedule cron --cron "0 2 * * *" + * agentforge_api.ts --method create --prompt "Step 2" --depends-on 10,11 --inject-result --dag-id my-pipeline + * agentforge_api.ts --method list --status running + * agentforge_api.ts --method dag --dag-id my-pipeline + */ + +import { parseArgs } from "node:util"; + +const API_BASE = "http://127.0.0.1:9712/api"; + +function fail(message: string): never { + console.error(message); + process.exit(1); +} + +async function apiRequest( + method: string, + path: string, + jsonData?: unknown, + params?: Record, +): Promise { + let url = `${API_BASE}${path}`; + if (params) { + const qs = new URLSearchParams(); + for (const [k, v] of Object.entries(params)) qs.set(k, String(v)); + url += `?${qs.toString()}`; + } + + let resp: Response; + try { + resp = await fetch(url, { + method, + ...(jsonData !== undefined + ? { body: JSON.stringify(jsonData), headers: { "Content-Type": "application/json" } } + : {}), + }); + } catch (err: any) { + const reason = String(err?.cause ?? err?.message ?? err); + if (reason.includes("ECONNREFUSED") || reason.includes("Unable to connect")) { + fail( + "Connection failed: AgentForge is not running.\n" + + "Start it with: cd /backend && bun taskboard.ts", + ); + } + fail(`Network error: ${reason}`); + } + + if (!resp.ok) { + let detail: string = resp.statusText; + try { + const errBody: any = await resp.json(); + detail = errBody.error ?? resp.statusText; + } catch { + /* non-JSON error body */ + } + fail(`API error (HTTP ${resp.status}): ${detail}`); + } + return resp.json(); +} + +const STATUS_ICONS: Record = { + pending: "🕐", + scheduled: "⏰", + running: "⏳", + completed: "✅", + failed: "❌", + cancelled: "🚫", + blocked: "⊘", +}; + +const METHODS = [ + "create", + "list", + "get", + "runs", + "output", + "events", + "cancel", + "retry", + "delete", + "dag", + "health", +] as const; + +async function main(): Promise { + const { values: args } = parseArgs({ + args: process.argv.slice(2), + options: { + method: { type: "string" }, + prompt: { type: "string" }, + title: { type: "string" }, + dir: { type: "string", default: "." }, + schedule: { type: "string", default: "immediate" }, + cron: { type: "string" }, + delay: { type: "string" }, + at: { type: "string" }, + "max-runs": { type: "string" }, + tags: { type: "string", default: "" }, + "image-paths": { type: "string" }, + "depends-on": { type: "string" }, + "inject-result": { type: "boolean", default: false }, + "dag-id": { type: "string" }, + "task-id": { type: "string" }, + status: { type: "string" }, + limit: { type: "string", default: "1000" }, + offset: { type: "string", default: "0" }, + json: { type: "boolean", default: false }, + }, + }); + + const method = args.method; + if (!method || !(METHODS as readonly string[]).includes(method)) { + fail(`--method is required and must be one of: ${METHODS.join(", ")}`); + } + if (!["immediate", "delayed", "scheduled_at", "cron"].includes(args.schedule!)) { + fail("--schedule must be one of: immediate, delayed, scheduled_at, cron"); + } + + const taskId = args["task-id"] ? Number(args["task-id"]) : undefined; + const requireTaskId = (m: string): number => { + if (!taskId) fail(`--task-id is required for ${m} method`); + return taskId; + }; + + if (method === "create") { + if (!args.prompt) fail("--prompt is required for create method"); + + const data: Record = { + prompt: args.prompt, + title: args.title || args.prompt.slice(0, 60), + working_dir: args.dir, + schedule_type: args.schedule, + tags: args.tags, + }; + + if (args.cron) data.cron_expr = args.cron; + if (args.delay) data.delay_seconds = Number(args.delay); + if (args.at) { + const m = /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/.exec(args.at); + if (!m) fail("Error: --at must be in format 'YYYY-MM-DD HH:MM:SS'"); + data.next_run_at = `${m[1]}-${m[2]}-${m[3]}T${m[4]}:${m[5]}:${m[6]}`; + } + if (args["max-runs"]) data.max_runs = Number(args["max-runs"]); + if (args["dag-id"]) data.dag_id = args["dag-id"]; + if (args["image-paths"]) { + data.image_paths = args["image-paths"] + .split(",") + .map((p) => p.trim()) + .filter(Boolean); + } + if (args["depends-on"]) { + const ids = args["depends-on"] + .split(",") + .map((x) => x.trim()) + .filter((x) => /^\d+$/.test(x)) + .map(Number); + data.depends_on = ids.map((tid) => ({ + task_id: tid, + inject_result: args["inject-result"], + })); + } + + const result = await apiRequest("POST", "/tasks", data); + console.log(JSON.stringify(result, null, 2)); + } else if (method === "list") { + let tasks: any[] = await apiRequest("GET", "/tasks"); + + if (args.status) tasks = tasks.filter((t) => t.status === args.status); + + if (args.json) { + console.log(JSON.stringify(tasks, null, 2)); + } else { + if (!tasks.length) console.log("No tasks found."); + for (const task of tasks) { + const icon = STATUS_ICONS[task.status] ?? "❓"; + const dagLabel = task.dag_id ? ` [dag:${task.dag_id}]` : ""; + console.log(`${icon} #${task.id}: ${task.title} (${task.status})${dagLabel}`); + } + } + } else if (method === "get") { + const id = requireTaskId("get"); + const task = await apiRequest("GET", `/tasks/${id}`); + console.log(JSON.stringify(task, null, 2)); + } else if (method === "runs") { + const id = requireTaskId("runs"); + const runs = await apiRequest("GET", `/tasks/${id}/runs`); + console.log(JSON.stringify(runs, null, 2)); + } else if (method === "output") { + const id = requireTaskId("output"); + const result = await apiRequest("GET", `/tasks/${id}/output`); + + if (args.json) { + console.log(JSON.stringify(result, null, 2)); + } else { + if (result.is_running) { + console.log("Status: Running"); + console.log("\nOutput:"); + } else { + console.log("Status: Not running"); + } + console.log(result.output); + } + } else if (method === "events") { + const id = requireTaskId("events"); + const result = await apiRequest("GET", `/tasks/${id}/events`, undefined, { + limit: Number(args.limit), + offset: Number(args.offset), + }); + console.log(JSON.stringify(result, null, 2)); + } else if (method === "cancel") { + const id = requireTaskId("cancel"); + const result = await apiRequest("POST", `/tasks/${id}/cancel`); + console.log(JSON.stringify(result, null, 2)); + } else if (method === "retry") { + const id = requireTaskId("retry"); + const result = await apiRequest("POST", `/tasks/${id}/retry`); + console.log(JSON.stringify(result, null, 2)); + } else if (method === "delete") { + const id = requireTaskId("delete"); + const result = await apiRequest("DELETE", `/tasks/${id}`); + console.log(JSON.stringify(result, null, 2)); + } else if (method === "dag") { + if (!args["dag-id"]) fail("--dag-id is required for dag method"); + const tasks: any[] = await apiRequest("GET", `/dag/${args["dag-id"]}`); + if (args.json) { + console.log(JSON.stringify(tasks, null, 2)); + } else { + console.log(`DAG: ${args["dag-id"]} (${tasks.length} tasks)`); + for (const task of tasks) { + const icon = STATUS_ICONS[task.status] ?? "❓"; + const deps: any[] = task.dependencies ?? []; + const depIds = deps.map((d) => `#${d.depends_on_task_id}`).join(", "); + const depLabel = deps.length ? ` <- ${depIds}` : ""; + console.log(` ${icon} #${task.id}: ${task.title} (${task.status})${depLabel}`); + } + } + } else if (method === "health") { + const result = await apiRequest("GET", "/health"); + console.log(JSON.stringify(result, null, 2)); + } +} + +await main(); From 5cf99b54722a09ca97994f06cf7c4cc1af716d1a Mon Sep 17 00:00:00 2001 From: taohe Date: Sat, 13 Jun 2026 01:13:55 +0800 Subject: [PATCH 11/18] docs: update READMEs for TypeScript+Bun toolchain Co-Authored-By: Claude Fable 5 --- README.md | 39 ++++++++++++++++----------------------- README.zh.md | 39 ++++++++++++++++----------------------- 2 files changed, 32 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index a0eb28a..f07304a 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) [![Platform: macOS](https://img.shields.io/badge/Platform-macOS%2012%2B-lightgrey?logo=apple)](https://github.com/releases) -[![Python 3.12+](https://img.shields.io/badge/Python-3.12%2B-blue?logo=python)](https://python.org) +[![Bun 1.3+](https://img.shields.io/badge/Bun-1.3%2B-black?logo=bun)](https://bun.sh) [![TypeScript](https://img.shields.io/badge/TypeScript-5-blue?logo=typescript)](https://www.typescriptlang.org) [![Claude Code](https://img.shields.io/badge/Powered%20by-Claude%20Code-orange)](https://docs.anthropic.com/en/docs/claude-code) **Website**: https://agentforge-landing-weld.vercel.app/ @@ -64,8 +64,7 @@ Distilled skills are standard Claude Code `SKILL.md` files (canonical copy in `~ ## Requirements - macOS 12.0+ (Apple Silicon or Intel) -- Python 3.12+ -- Node.js 18+ +- [Bun](https://bun.sh) 1.3+ - [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code) installed and on `PATH` (default agent) - [OpenAI Codex CLI](https://github.com/openai/codex) on `PATH` — optional, required only if using Codex as agent backend (`npm install -g @openai/codex`) @@ -99,30 +98,25 @@ make package-dmg git clone https://github.com/your-org/agentforge.git cd agentforge -uv sync -cd taskboard-electron && npm install && cd .. +make install-deps # bun install in backend/ and taskboard-electron/ -# Terminal 1: start Python backend -uv run taskboard.py - -# Terminal 2: start Electron + Vite dev server -cd taskboard-electron && npm start +# Start Electron + backend (Bun builds, watches, and spawns the backend) +cd taskboard-electron && bun run start ``` --- ## Troubleshooting -### `npm install` hangs or freezes +### `bun install` hangs or freezes This is the most common setup issue. The Electron binary (~100 MB) is downloaded from GitHub and may stall on slow connections or in China. **Quick fix — use mirrors:** ```bash -npm config set registry https://registry.npmmirror.com export ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/ -cd taskboard-electron && npm install +cd taskboard-electron && bun install --registry https://registry.npmmirror.com ``` **Full guide:** [docs/installation-troubleshooting.md](docs/installation-troubleshooting.md) covers: @@ -419,9 +413,8 @@ To keep the backend running persistently without the desktop app: com.agentforge.taskboard ProgramArguments - /usr/local/bin/uv - run - /path/to/agentforge/taskboard.py + /usr/local/bin/bun + /path/to/agentforge/backend/taskboard.ts WorkingDirectory /path/to/agentforge @@ -447,7 +440,7 @@ launchctl load ~/Library/LaunchAgents/com.agentforge.taskboard.plist ``` ┌──────────────────┐ HTTP/JSON ┌──────────────────┐ -│ React Frontend │ <────────────────> │ Python Backend │ +│ React Frontend │ <────────────────> │ Bun/TS Backend │ │ (Kanban UI) │ localhost:9712 │ (Scheduler+API) │ └──────────────────┘ └───────┬──────────┘ | @@ -456,9 +449,9 @@ launchctl load ~/Library/LaunchAgents/com.agentforge.taskboard.plist [ SQLite DB ] [ Scheduler ] [ Claude CLI ] ``` -- **Python backend** (`taskboard.py`) — single-file `BaseHTTPRequestHandler` server. Manages tasks in SQLite (`~/.agentforge/tasks.db`), runs `claude` or `codex` CLI via `AgentExecutor`, and schedules work with `TaskScheduler` (polls every 2 s, supports cron via `croniter`). -- **Electron shell** (`taskboard-electron/`) — spawns the Python backend on start, kills it on quit. Loads React renderer from Vite dev server (dev) or bundled assets (prod). -- **React frontend** (`App.jsx`) — single-component kanban board that polls the REST API and renders colorized streaming output. +- **Bun/TypeScript backend** (`backend/`) — `Bun.serve` HTTP server. Manages tasks in SQLite via `bun:sqlite` (`~/.agentforge/tasks.db`), runs `claude` or `codex` CLI via `AgentExecutor`, and schedules work with `TaskScheduler` (polls every 2 s, supports cron via `cron-parser`). +- **Electron shell** (`taskboard-electron/`) — spawns the backend on start, kills it on quit. Renderer/main/preload are bundled with `Bun.build` (`scripts/build.ts`); in dev `bun run start` watches and reloads. +- **React frontend** (`App.tsx`) — single-component kanban board that polls the REST API and renders colorized streaming output. --- @@ -472,9 +465,9 @@ Contributions are welcome! Here's how to get started: 4. Open a pull request with a clear description of the change. **Key files:** -- `taskboard.py` — entire Python backend (DB, scheduler, executor, HTTP handlers) -- `taskboard-electron/src/main.js` — Electron main process -- `taskboard-electron/src/renderer/App.jsx` — React frontend (~1500 lines) +- `backend/` — entire TypeScript backend (DB, scheduler, executor, HTTP API, channels) +- `taskboard-electron/src/main.ts` — Electron main process +- `taskboard-electron/src/renderer/App.tsx` — React frontend - `channels/` — pluggable chat channel adapters (Telegram, Slack, Feishu, WeChat) - `skills/agentforge/` — Claude Code skill for agent-to-agent delegation diff --git a/README.zh.md b/README.zh.md index 195e17d..59b03d0 100644 --- a/README.zh.md +++ b/README.zh.md @@ -4,7 +4,7 @@ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) [![Platform: macOS](https://img.shields.io/badge/Platform-macOS%2012%2B-lightgrey?logo=apple)](https://github.com/releases) -[![Python 3.12+](https://img.shields.io/badge/Python-3.12%2B-blue?logo=python)](https://python.org) +[![Bun 1.3+](https://img.shields.io/badge/Bun-1.3%2B-black?logo=bun)](https://bun.sh) [![TypeScript](https://img.shields.io/badge/TypeScript-5-blue?logo=typescript)](https://www.typescriptlang.org) [![Claude Code](https://img.shields.io/badge/Powered%20by-Claude%20Code-orange)](https://docs.anthropic.com/en/docs/claude-code) **官网**: https://agentforge-landing-weld.vercel.app/ @@ -63,8 +63,7 @@ ## 环境要求 - macOS 12.0+(Apple Silicon 或 Intel) -- Python 3.12+ -- Node.js 18+ +- [Bun](https://bun.sh) 1.3+ - [Claude Code CLI](https://docs.anthropic.com/en/docs/claude-code)(已安装并在 `PATH` 中) --- @@ -97,30 +96,25 @@ make package-dmg git clone https://github.com/your-org/agentforge.git cd agentforge -uv sync -cd taskboard-electron && npm install && cd .. +make install-deps # bun install in backend/ and taskboard-electron/ -# 终端 1:启动 Python 后端 -uv run taskboard.py - -# 终端 2:启动 Electron + Vite 开发服务 -cd taskboard-electron && npm start +# 启动 Electron + 后端(Bun 负责构建、监听并自动拉起后端) +cd taskboard-electron && bun run start ``` --- ## 常见问题 -### `npm install` 卡住不动 +### `bun install` 卡住不动 这是最常见的安装问题。Electron 二进制包约 100MB,从 GitHub 下载,在国内网络环境下极易卡住。 **快速解决——使用国内镜像:** ```bash -npm config set registry https://registry.npmmirror.com export ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/ -cd taskboard-electron && npm install +cd taskboard-electron && bun install --registry https://registry.npmmirror.com ``` **完整排查指南:** [docs/installation-troubleshooting.md](docs/installation-troubleshooting.md),涵盖: @@ -367,9 +361,8 @@ AgentForge 自动处理调度、依赖追踪和结果传递。 com.agentforge.taskboard ProgramArguments - /usr/local/bin/uv - run - /path/to/agentforge/taskboard.py + /usr/local/bin/bun + /path/to/agentforge/backend/taskboard.ts WorkingDirectory /path/to/agentforge @@ -395,7 +388,7 @@ launchctl load ~/Library/LaunchAgents/com.agentforge.taskboard.plist ``` ┌──────────────────┐ HTTP/JSON ┌──────────────────┐ -│ React 前端 │ <────────────────> │ Python 后端 │ +│ React 前端 │ <────────────────> │ Bun/TS 后端 │ │ (看板 UI) │ localhost:9712 │ (调度器+API) │ └──────────────────┘ └───────┬──────────┘ | @@ -404,9 +397,9 @@ launchctl load ~/Library/LaunchAgents/com.agentforge.taskboard.plist [ SQLite DB ] [ 调度器 ] [ Claude CLI ] ``` -- **Python 后端**(`taskboard.py`)—— 单文件 `BaseHTTPRequestHandler` 服务。在 SQLite(`~/.agentforge/tasks.db`)中管理任务,通过 `AgentExecutor` 运行 `claude` CLI,通过 `TaskScheduler` 调度任务(每 2 秒轮询,支持通过 `croniter` 解析 cron 表达式)。 -- **Electron 外壳**(`taskboard-electron/`)—— 启动时创建 Python 后端进程,退出时终止它。开发模式下从 Vite 开发服务器加载 React 渲染器,生产模式下使用打包后的静态资源。 -- **React 前端**(`App.jsx`)—— 单组件看板,轮询 REST API 并渲染带颜色的流式输出。 +- **Bun/TypeScript 后端**(`backend/`)—— `Bun.serve` HTTP 服务。通过 `bun:sqlite` 在 SQLite(`~/.agentforge/tasks.db`)中管理任务,通过 `AgentExecutor` 运行 `claude` / `codex` CLI,通过 `TaskScheduler` 调度任务(每 2 秒轮询,支持通过 `cron-parser` 解析 cron 表达式)。 +- **Electron 外壳**(`taskboard-electron/`)—— 启动时创建后端进程,退出时终止它。主进程/preload/渲染器均由 `Bun.build` 打包(`scripts/build.ts`);开发模式 `bun run start` 自动监听并热重载。 +- **React 前端**(`App.tsx`)—— 单组件看板,轮询 REST API 并渲染带颜色的流式输出。 --- @@ -420,9 +413,9 @@ launchctl load ~/Library/LaunchAgents/com.agentforge.taskboard.plist 4. 提交 PR,并清晰描述改动内容。 **关键文件:** -- `taskboard.py` —— 整个 Python 后端(数据库、调度器、执行器、HTTP 处理器) -- `taskboard-electron/src/main.js` —— Electron 主进程 -- `taskboard-electron/src/renderer/App.jsx` —— React 前端(约 1500 行) +- `backend/` —— 整个 TypeScript 后端(数据库、调度器、执行器、HTTP API、频道) +- `taskboard-electron/src/main.ts` —— Electron 主进程 +- `taskboard-electron/src/renderer/App.tsx` —— React 前端 - `channels/` —— 可插拔消息频道适配器 - `skills/agentforge/` —— 用于智能体间委托的 Claude Code Skill From e76c098cb409d89fbf46da5357d9b6e1651855e3 Mon Sep 17 00:00:00 2001 From: taohe Date: Sat, 13 Jun 2026 01:14:50 +0800 Subject: [PATCH 12/18] feat(backend): port channel agent/dir utils to TypeScript Co-Authored-By: Claude Fable 5 --- backend/src/channels/agent_utils.ts | 64 +++++++++++++++ backend/src/channels/dir_utils.ts | 116 ++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 backend/src/channels/agent_utils.ts create mode 100644 backend/src/channels/dir_utils.ts diff --git a/backend/src/channels/agent_utils.ts b/backend/src/channels/agent_utils.ts new file mode 100644 index 0000000..0db9033 --- /dev/null +++ b/backend/src/channels/agent_utils.ts @@ -0,0 +1,64 @@ +/** + * Shared utilities for switching the default coding agent across all channels. + * + * Usage from any channel: + * /agent claude — switch to Claude Code + * /agent codex — switch to Codex CLI + */ + +// Structural view of TaskDB — only what these helpers touch. +export interface SettingsDB { + get_setting(key: string, defaultValue?: string | null): string | null; + set_setting(key: string, value: string): void; +} + +// Supported agent names +export const SUPPORTED_AGENTS: Record = { + claude: "Claude Code (claude CLI)", + codex: "Codex CLI (openai/codex)", +}; +export const DEFAULT_AGENT = "codex"; + +// Regex: /agent +const AGENT_CMD_RE = /^\/agent\s+(\S+)\s*$/i; + +/** Return the agent name argument if `text` is a /agent command, else null. */ +export function parse_agent_command(text: string): string | null { + const m = AGENT_CMD_RE.exec(text.trim()); + return m ? m[1]!.toLowerCase() : null; +} + +/** + * If `text` is a /agent command, persist the choice to DB and return a + * confirmation string. Returns null if `text` is not an agent command. + * + * The setting is stored as global `default_agent` (shared across all channels + * and the Forge desktop app). + */ +export function handle_agent_command( + text: string, + channel_key: string, + db: SettingsDB, +): string | null { + const agent = parse_agent_command(text); + if (agent === null) return null; + + if (!(agent in SUPPORTED_AGENTS)) { + const names = Object.keys(SUPPORTED_AGENTS) + .map((k) => `\`${k}\``) + .join(", "); + return `❌ Unknown agent \`${agent}\`. Supported: ${names}`; + } + + db.set_setting("default_agent", agent); + const label = SUPPORTED_AGENTS[agent]; + return `🤖 Default agent switched to: **${label}**`; +} + +/** + * Return the current default agent from settings. + * Falls back to the app default if not set. + */ +export function resolve_agent(channel_key: string, db: SettingsDB): string { + return db.get_setting("default_agent", DEFAULT_AGENT) ?? DEFAULT_AGENT; +} diff --git a/backend/src/channels/dir_utils.ts b/backend/src/channels/dir_utils.ts new file mode 100644 index 0000000..b5879e7 --- /dev/null +++ b/backend/src/channels/dir_utils.ts @@ -0,0 +1,116 @@ +/** + * Shared utilities for working-directory management across all channels. + * + * Two features: + * 1. /dir (or cd) command — explicit path switch, persists to DB. + * 2. Claude-based extraction — ask claude-haiku to pull a path from a + * free-text prompt so the user can say "在 ~/myproject 里帮我…" + * without typing a /dir command first. + */ + +import type { SettingsDB } from "./agent_utils.ts"; + +// ── 1. Explicit /dir / cd command ───────────────────────────────────────── + +// Patterns we recognise as "switch directory" commands: +// /dir ~/foo cd ~/foo /cd ~/foo +const DIR_CMD_RE = /^(?:\/dir|\/cd|cd)\s+(\S+)\s*$/i; + +/** Return the path argument if `text` is a /dir or cd command, else null. */ +export function parse_dir_command(text: string): string | null { + const m = DIR_CMD_RE.exec(text.trim()); + return m ? m[1]! : null; +} + +/** + * If `text` is a /dir command, persist the new path to DB and return a + * confirmation string. Returns null if `text` is not a dir command. + * + * `channel_key` is the settings key prefix, e.g. "telegram", "slack", "feishu". + */ +export function handle_dir_command( + text: string, + channel_key: string, + db: SettingsDB, +): string | null { + const path = parse_dir_command(text); + if (path === null) return null; + + const setting_key = `${channel_key}_default_working_dir`; + db.set_setting(setting_key, path); + return `📁 Working directory set to: ${path}`; +} + +// ── 2. Claude-based path extraction ─────────────────────────────────────── + +const EXTRACT_SYSTEM = + "You are a path-extraction assistant. " + + "Given a user message, decide if it explicitly mentions a filesystem path " + + "where some work should be done (e.g. ~/projects/foo, /home/user/bar, " + + "./myapp, C:\\\\Users\\\\foo). " + + "Reply with a JSON object and nothing else:\n" + + ' {"path": ""} — if a path is found\n' + + ' {"path": null} — if no path is mentioned\n' + + "Do NOT invent a path. Only return one that is clearly stated in the message."; + +/** + * Call the Anthropic Messages API (claude-haiku) to extract an explicit + * working directory from `prompt`. + * Returns the path string, or null if none found / on any error. + */ +export async function extract_working_dir_with_claude( + prompt: string, +): Promise { + const api_key = process.env.ANTHROPIC_API_KEY ?? ""; + if (!api_key) return null; + + try { + const resp = await fetch("https://api.anthropic.com/v1/messages", { + method: "POST", + headers: { + "x-api-key": api_key, + "anthropic-version": "2023-06-01", + "content-type": "application/json", + }, + body: JSON.stringify({ + model: "claude-haiku-4-5", + max_tokens: 64, + system: EXTRACT_SYSTEM, + messages: [{ role: "user", content: prompt }], + }), + signal: AbortSignal.timeout(15000), + }); + if (resp.status !== 200) return null; + + const data: any = await resp.json(); + const text = (data?.content?.[0]?.text ?? "").trim(); + const parsed = JSON.parse(text); + const path = parsed?.path; + if (path && typeof path === "string") return path.trim(); + } catch { + /* network/parse errors → no extraction */ + } + return null; +} + +// Seam for tests (≙ pytest monkeypatching dir_utils.extract_working_dir_with_claude): +// resolve_working_dir reads the extractor through this mutable hook object. +export const _hooks = { extract_working_dir_with_claude }; + +/** + * Determine the working directory for a new task: + * 1. Try to extract an explicit path from `prompt` via Claude. + * 2. Fall back to the channel's default_working_dir in DB. + * 3. Fall back to "~". + */ +export async function resolve_working_dir( + prompt: string, + channel_key: string, + db: SettingsDB, +): Promise { + const extracted = await _hooks.extract_working_dir_with_claude(prompt); + if (extracted) return extracted; + + const setting_key = `${channel_key}_default_working_dir`; + return db.get_setting(setting_key) || "~"; +} From 535f64e264ed23cb524acb599203d0533a9fb874 Mon Sep 17 00:00:00 2001 From: taohe Date: Sat, 13 Jun 2026 01:17:35 +0800 Subject: [PATCH 13/18] docs: update install troubleshooting and keep_running.sh for Bun Co-Authored-By: Claude Fable 5 --- docs/installation-troubleshooting.md | 58 +++++++++++++--------------- keep_running.sh | 2 +- 2 files changed, 28 insertions(+), 32 deletions(-) diff --git a/docs/installation-troubleshooting.md b/docs/installation-troubleshooting.md index e97d2e5..e3e3614 100644 --- a/docs/installation-troubleshooting.md +++ b/docs/installation-troubleshooting.md @@ -4,13 +4,13 @@ This guide covers the most common issues when installing AgentForge's Electron f --- -## `npm install` hangs or freezes +## `bun install` hangs or freezes This is the most common issue. The terminal appears stuck after a few lines of output, with no error message. ### Why this happens -`npm install` in `taskboard-electron/` triggers two heavy operations: +`bun install` in `taskboard-electron/` triggers two heavy operations: 1. **Electron binary download** — Electron 40 is ~100MB, downloaded from GitHub releases. This is the most common culprit, especially in China or on slow connections. 2. **Native module compilation** — Some packages use `node-gyp` to compile C++ code. This requires build tools and can silently stall if they are missing. @@ -25,11 +25,11 @@ If this is your first install, give it **3–5 minutes**. The download may still ## Step 2: Diagnose the hang -Open a second terminal while `npm install` is running: +Open a second terminal while `bun install` is running: ```bash -# Check if node is actively doing network I/O -lsof -p $(pgrep -f "node.*npm") 2>/dev/null | grep -i net +# Check if bun is actively doing network I/O +lsof -p $(pgrep -f "bun") 2>/dev/null | grep -i net ``` - If you see active connections → it's downloading, just slow. Use the mirror fix below. @@ -45,13 +45,13 @@ Set mirrors before installing: ```bash # npm registry mirror -npm config set registry https://registry.npmmirror.com +bun install --registry https://registry.npmmirror.com # Electron binary mirror (critical — this is what usually hangs) export ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/ cd taskboard-electron -npm install +bun install ``` To make the Electron mirror permanent: @@ -68,7 +68,7 @@ Use a VPN, or set a custom Electron mirror: ```bash export ELECTRON_MIRROR=https://github.com/electron/electron/releases/download/ cd taskboard-electron -npm install +bun install ``` --- @@ -81,15 +81,15 @@ If a previous interrupted install left corrupted cache: cd taskboard-electron rm -rf node_modules rm -f package-lock.json -npm cache clean --force -npm install +bun pm cache rm +bun install ``` --- ## Fix C: Missing build tools (native module compilation fails) -Some packages require platform-specific compilers. Install them before running `npm install`. +Some packages require platform-specific compilers. Install them before running `bun install`. ### macOS @@ -114,7 +114,7 @@ sudo apt-get install build-essential python3 Run in an **Administrator** PowerShell: ```powershell -npm install --global windows-build-tools +bun install --global windows-build-tools ``` Or install manually: @@ -123,21 +123,19 @@ Or install manually: --- -## Fix D: Node.js version mismatch +## Fix D: Bun version mismatch -AgentForge requires **Node.js 18 or later**. Check your version: +AgentForge requires **Bun 1.3 or later**. Check your version: ```bash -node -v # Should be v18.x or higher -npm -v # Should be 9.x or higher +bun -v # Should be 1.3.x or higher ``` -If outdated, install the latest LTS from [nodejs.org](https://nodejs.org/) or use a version manager: +If outdated or missing, install/upgrade from [bun.sh](https://bun.sh/): ```bash -# Using nvm -nvm install --lts -nvm use --lts +curl -fsSL https://bun.sh/install | bash # install +bun upgrade # or upgrade in place ``` --- @@ -148,23 +146,23 @@ nvm use --lts cd taskboard-electron # Clean everything -rm -rf node_modules .vite -rm -f package-lock.json +rm -rf node_modules .bun +rm -f bun.lock # Set mirrors -npm config set registry https://registry.npmmirror.com +bun install --registry https://registry.npmmirror.com echo 'electron_mirror=https://npmmirror.com/mirrors/electron/' >> ~/.npmrc # Reinstall -npm cache clean --force -npm install +bun pm cache rm +bun install ``` --- ## Verify installation succeeded -After `npm install` completes, confirm Electron was downloaded: +After `bun install` completes, confirm Electron was downloaded: ```bash ls taskboard-electron/node_modules/electron/dist/ @@ -175,7 +173,7 @@ Then start the app: ```bash cd taskboard-electron -npm start +bun run start ``` --- @@ -185,11 +183,9 @@ npm start Collect this information when reporting an issue: ```bash -node -v -npm -v +bun -v uname -a # macOS/Linux -npm config get registry -cat ~/.npmrc +cat ~/.npmrc # electron mirror config, if any ``` Open an issue at: https://github.com/anthropics/agentforge/issues diff --git a/keep_running.sh b/keep_running.sh index a9305c9..e825390 100755 --- a/keep_running.sh +++ b/keep_running.sh @@ -13,4 +13,4 @@ sudo pmset -c displaysleep 10 # 显示器可睡眠10分钟 # 2. 启动关键进程并保持唤醒 echo "[INFO] 启动进程并保持唤醒..." -caffeinate -dimsu bash -c "cd taskboard-electron && npm start" \ No newline at end of file +caffeinate -dimsu bash -c "cd taskboard-electron && bun run start" \ No newline at end of file From 651aafcb095cc2c241069d227e11082c0d2c020d Mon Sep 17 00:00:00 2001 From: taohe Date: Sat, 13 Jun 2026 06:24:43 +0800 Subject: [PATCH 14/18] wip(backend): executor/skills/scheduler port and weixin bridge conversion (tests pending) Co-Authored-By: Claude Fable 5 --- backend/src/channels/weixin_bridge/index.ts | 1012 +++++++ .../src/channels/weixin_bridge/package.json | 7 + backend/src/executor.ts | 274 ++ backend/src/scheduler.ts | 2609 +++++++++++++++++ backend/src/skills.ts | 179 ++ 5 files changed, 4081 insertions(+) create mode 100644 backend/src/channels/weixin_bridge/index.ts create mode 100644 backend/src/channels/weixin_bridge/package.json create mode 100644 backend/src/executor.ts create mode 100644 backend/src/scheduler.ts create mode 100644 backend/src/skills.ts diff --git a/backend/src/channels/weixin_bridge/index.ts b/backend/src/channels/weixin_bridge/index.ts new file mode 100644 index 0000000..b76a815 --- /dev/null +++ b/backend/src/channels/weixin_bridge/index.ts @@ -0,0 +1,1012 @@ +// AgentForge Weixin bridge — TypeScript port of channels/weixin_bridge/index.mjs. +// +// Plain sidecar process (run with `bun index.ts`) that speaks the WeChat ilink +// protocol and communicates with the backend channel over stdio NDJSON. +// Runtime behavior, protocol strings, and NDJSON message shapes are kept +// byte-identical to the original Node ESM source; only types were added. +// Stdlib-only (node:crypto/fs/path/readline + global fetch) — no npm deps. + +import crypto from "node:crypto"; +import fs from "node:fs"; +import path from "node:path"; +import readline from "node:readline"; + +const DEFAULT_BASE_URL = "https://ilinkai.weixin.qq.com"; +const INITIAL_BASE_URL = + process.env.AGENTFORGE_WEIXIN_BASE_URL || DEFAULT_BASE_URL; +const BOT_TYPE = process.env.AGENTFORGE_WEIXIN_BOT_TYPE || "3"; +const DATA_DIR = + process.env.AGENTFORGE_WEIXIN_DATA_DIR || + path.join(process.env.HOME || ".", ".agentforge", "weixin"); +const ACCOUNT_FILE = path.join(DATA_DIR, "account.json"); +const AUTO_LOGIN = + (process.env.AGENTFORGE_WEIXIN_AUTO_LOGIN || "true") !== "false"; +const ACCOUNT_ID_OVERRIDE = process.env.AGENTFORGE_WEIXIN_ACCOUNT_ID || ""; +const CHANNEL_VERSION = "agentforge-weixin-bridge/0.2.0"; +const DEFAULT_CDN_BASE_URL = process.env.AGENTFORGE_WEIXIN_CDN_BASE_URL || ""; +const MESSAGE_TYPE = { + USER: 1, + BOT: 2, +}; +const MESSAGE_STATE = { + FINISH: 2, +}; +const MESSAGE_ITEM_TYPE = { + TEXT: 1, + IMAGE: 2, +}; +const UPLOAD_MEDIA_TYPE = { + IMAGE: 1, +}; +const IMAGE_MIME_BY_EXT: Record = { + ".png": "image/png", + ".jpg": "image/jpeg", + ".jpeg": "image/jpeg", + ".gif": "image/gif", + ".webp": "image/webp", +}; + +interface BridgeState { + accountId: string; + baseUrl: string; + token: string; + userId: string; + syncCursor: string; +} + +/** Inbound NDJSON command from the channel process. */ +interface BridgeCommand { + type?: string; + request_id?: string; + account_id?: string; + peer_id?: string; + context_token?: string; + reply_to_message_id?: string; + text?: string; + image_paths?: unknown; +} + +interface UploadedImage { + filekey: string; + downloadEncryptedQueryParam: string; + aeskey: string; // hex string + fileSize: number; + fileSizeCiphertext: number; +} + +let shuttingDown = false; +let loginInFlight: Promise | null = null; +let pollerStarted = false; +let pollTimer: ReturnType | null = null; +let state: BridgeState = loadState(); +const pendingSentMessages = new Map< + string, + { requestId: string; peerId: string } +>(); + +function emit(event: Record): void { + process.stdout.write(`${JSON.stringify(event)}\n`); +} + +function log(message: string): void { + process.stderr.write(`[WeixinBridge] ${message}\n`); +} + +function ensureDataDir(): void { + fs.mkdirSync(DATA_DIR, { recursive: true }); +} + +function ensureMediaDir(kind: string): string { + const dir = path.join(DATA_DIR, "media", kind); + fs.mkdirSync(dir, { recursive: true }); + return dir; +} + +function mediaFileName(prefix: string, ext: string): string { + const stamp = new Date().toISOString().replace(/[:.]/g, "-"); + return `${prefix}-${stamp}-${crypto.randomBytes(6).toString("hex")}${ext}`; +} + +function imageExtFromBuffer(buf: Buffer, fallback = ".jpg"): string { + if ( + buf + .subarray(0, 8) + .equals(Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])) + ) { + return ".png"; + } + if (buf.subarray(0, 3).equals(Buffer.from([0xff, 0xd8, 0xff]))) { + return ".jpg"; + } + if ( + buf.subarray(0, 6).toString("ascii") === "GIF87a" || + buf.subarray(0, 6).toString("ascii") === "GIF89a" + ) { + return ".gif"; + } + if ( + buf.subarray(0, 4).toString("ascii") === "RIFF" && + buf.subarray(8, 12).toString("ascii") === "WEBP" + ) { + return ".webp"; + } + return fallback; +} + +function getImageMimeFromFilename(filePath: string): string { + return IMAGE_MIME_BY_EXT[path.extname(filePath).toLowerCase()] || "image/jpeg"; +} + +function encryptAesEcb(plaintext: Buffer, key: Buffer): Buffer { + const cipher = crypto.createCipheriv("aes-128-ecb", key, null); + return Buffer.concat([cipher.update(plaintext), cipher.final()]); +} + +function decryptAesEcb(ciphertext: Buffer, key: Buffer): Buffer { + const decipher = crypto.createDecipheriv("aes-128-ecb", key, null); + return Buffer.concat([decipher.update(ciphertext), decipher.final()]); +} + +function aesEcbPaddedSize(plaintextSize: number): number { + return Math.ceil((plaintextSize + 1) / 16) * 16; +} + +function parseAesKey(aesKeyBase64: string, label: string): Buffer { + const decoded = Buffer.from(aesKeyBase64, "base64"); + if (decoded.length === 16) { + return decoded; + } + if ( + decoded.length === 32 && + /^[0-9a-fA-F]{32}$/.test(decoded.toString("ascii")) + ) { + return Buffer.from(decoded.toString("ascii"), "hex"); + } + throw new Error( + `${label}: aes_key must decode to 16 raw bytes or a 32-char hex string`, + ); +} + +function resolveCdnBaseUrl(): string { + return ( + DEFAULT_CDN_BASE_URL || + state?.baseUrl || + process.env.AGENTFORGE_WEIXIN_BASE_URL || + DEFAULT_BASE_URL + ); +} + +function buildCdnDownloadUrl( + encryptedQueryParam: string, + cdnBaseUrl: string = resolveCdnBaseUrl(), +): string { + return `${cdnBaseUrl.replace(/\/$/, "")}/download?encrypted_query_param=${encodeURIComponent(encryptedQueryParam)}`; +} + +function buildCdnUploadUrl( + uploadParam: string, + filekey: string, + cdnBaseUrl: string = resolveCdnBaseUrl(), +): string { + return `${cdnBaseUrl.replace(/\/$/, "")}/upload?encrypted_query_param=${encodeURIComponent(uploadParam)}&filekey=${encodeURIComponent(filekey)}`; +} + +async function fetchCdnBytes(url: string, label: string): Promise { + const response = await fetch(url); + if (!response.ok) { + const body = await response.text().catch(() => ""); + throw new Error( + `${label}: CDN download ${response.status} ${response.statusText}: ${body}`, + ); + } + return Buffer.from(await response.arrayBuffer()); +} + +async function downloadAndDecryptBuffer( + encryptedQueryParam: string, + aesKeyBase64: string, + label: string, + fullUrl?: string, +): Promise { + const key = parseAesKey(aesKeyBase64, label); + const url = fullUrl || buildCdnDownloadUrl(encryptedQueryParam); + const encrypted = await fetchCdnBytes(url, label); + return decryptAesEcb(encrypted, key); +} + +async function downloadPlainCdnBuffer( + encryptedQueryParam: string, + label: string, + fullUrl?: string, +): Promise { + const url = fullUrl || buildCdnDownloadUrl(encryptedQueryParam); + return fetchCdnBytes(url, label); +} + +function loadState(): BridgeState { + try { + if (!fs.existsSync(ACCOUNT_FILE)) { + return { + accountId: ACCOUNT_ID_OVERRIDE, + baseUrl: process.env.AGENTFORGE_WEIXIN_BASE_URL || DEFAULT_BASE_URL, + token: "", + userId: "", + syncCursor: "", + }; + } + const parsed = JSON.parse(fs.readFileSync(ACCOUNT_FILE, "utf8")) as Record< + string, + string | undefined + >; + return { + accountId: ACCOUNT_ID_OVERRIDE || parsed.accountId || "", + baseUrl: + parsed.baseUrl || + process.env.AGENTFORGE_WEIXIN_BASE_URL || + DEFAULT_BASE_URL, + token: parsed.token || "", + userId: parsed.userId || "", + syncCursor: parsed.syncCursor || "", + }; + } catch (error) { + log(`failed to load state: ${String(error)}`); + return { + accountId: ACCOUNT_ID_OVERRIDE, + baseUrl: process.env.AGENTFORGE_WEIXIN_BASE_URL || DEFAULT_BASE_URL, + token: "", + userId: "", + syncCursor: "", + }; + } +} + +function saveState(): void { + ensureDataDir(); + fs.writeFileSync( + ACCOUNT_FILE, + JSON.stringify( + { + accountId: state.accountId, + baseUrl: state.baseUrl, + token: state.token, + userId: state.userId, + syncCursor: state.syncCursor, + }, + null, + 2, + ), + "utf8", + ); +} + +function clearSession(): void { + state = { + ...state, + token: "", + syncCursor: "", + baseUrl: INITIAL_BASE_URL, + }; + saveState(); +} + +function ensureTrailingSlash(url: string): string { + return url.endsWith("/") ? url : `${url}/`; +} + +function randomWechatUin(): string { + const uint32 = crypto.randomBytes(4).readUInt32BE(0); + return Buffer.from(String(uint32), "utf8").toString("base64"); +} + +function buildHeaders(body: string, token: string): Record { + const headers: Record = { + "Content-Type": "application/json", + AuthorizationType: "ilink_bot_token", + "Content-Length": String(Buffer.byteLength(body, "utf8")), + "X-WECHAT-UIN": randomWechatUin(), + }; + if (token) { + headers.Authorization = `Bearer ${token}`; + } + return headers; +} + +async function postJson( + endpoint: string, + payload: Record, + token: string, + timeoutMs = 15000, +): Promise { + const body = JSON.stringify({ + ...payload, + base_info: { channel_version: CHANNEL_VERSION }, + }); + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), timeoutMs); + try { + const response = await fetch( + new URL(endpoint, ensureTrailingSlash(state.baseUrl)), + { + method: "POST", + headers: buildHeaders(body, token), + body, + signal: controller.signal, + }, + ); + const raw = await response.text(); + if (!response.ok) { + throw new Error(`${response.status} ${response.statusText}: ${raw}`); + } + return raw ? JSON.parse(raw) : {}; + } finally { + clearTimeout(timeout); + } +} + +async function getUploadUrl(params: { + filekey: string; + media_type: number; + to_user_id: string; + rawsize: number; + rawfilemd5: string; + filesize: number; + aeskey: string; +}): Promise { + return postJson( + "ilink/bot/getuploadurl", + { + filekey: params.filekey, + media_type: params.media_type, + to_user_id: params.to_user_id, + rawsize: params.rawsize, + rawfilemd5: params.rawfilemd5, + filesize: params.filesize, + no_need_thumb: true, + aeskey: params.aeskey, + }, + state.token, + 15000, + ); +} + +async function uploadBufferToCdn(params: { + buf: Buffer; + uploadFullUrl?: string; + uploadParam?: string; + filekey: string; + aeskey: Buffer; + label: string; +}): Promise<{ downloadParam: string }> { + const ciphertext = encryptAesEcb(params.buf, params.aeskey); + const uploadUrl = + params.uploadFullUrl?.trim() || + (params.uploadParam + ? buildCdnUploadUrl(params.uploadParam, params.filekey) + : ""); + if (!uploadUrl) { + throw new Error(`${params.label}: CDN upload URL missing`); + } + + let lastError: unknown = null; + for (let attempt = 1; attempt <= 3; attempt += 1) { + try { + const response = await fetch(uploadUrl, { + method: "POST", + headers: { "Content-Type": "application/octet-stream" }, + body: new Uint8Array(ciphertext), + }); + if (response.status >= 400 && response.status < 500) { + const body = + response.headers.get("x-error-message") || (await response.text()); + throw new Error( + `${params.label}: CDN upload client error ${response.status}: ${body}`, + ); + } + if (response.status !== 200) { + const body = + response.headers.get("x-error-message") || + `status ${response.status}`; + throw new Error(`${params.label}: CDN upload server error: ${body}`); + } + const downloadParam = response.headers.get("x-encrypted-param") || ""; + if (!downloadParam) { + throw new Error( + `${params.label}: CDN response missing x-encrypted-param`, + ); + } + return { downloadParam }; + } catch (error) { + lastError = error; + if (error instanceof Error && error.message.includes("client error")) { + throw error; + } + if (attempt < 3) { + log( + `${params.label}: CDN upload attempt ${attempt} failed: ${String(error)}`, + ); + } + } + } + throw lastError || new Error(`${params.label}: CDN upload failed`); +} + +async function uploadImageToWeixin( + filePath: string, + toUserId: string, +): Promise { + const plaintext = fs.readFileSync(filePath); + const rawsize = plaintext.length; + const rawfilemd5 = crypto.createHash("md5").update(plaintext).digest("hex"); + const filesize = aesEcbPaddedSize(rawsize); + const filekey = crypto.randomBytes(16).toString("hex"); + const aeskey = crypto.randomBytes(16); + const uploadUrlResp = await getUploadUrl({ + filekey, + media_type: UPLOAD_MEDIA_TYPE.IMAGE, + to_user_id: toUserId, + rawsize, + rawfilemd5, + filesize, + aeskey: aeskey.toString("hex"), + }); + const uploaded = await uploadBufferToCdn({ + buf: plaintext, + uploadFullUrl: uploadUrlResp.upload_full_url, + uploadParam: uploadUrlResp.upload_param, + filekey, + aeskey, + label: `uploadImageToWeixin:${path.basename(filePath)}`, + }); + return { + filekey, + downloadEncryptedQueryParam: uploaded.downloadParam, + aeskey: aeskey.toString("hex"), + fileSize: rawsize, + fileSizeCiphertext: filesize, + }; +} + +function buildImageItem(uploaded: UploadedImage): Record { + return { + type: MESSAGE_ITEM_TYPE.IMAGE, + image_item: { + media: { + encrypt_query_param: uploaded.downloadEncryptedQueryParam, + aes_key: Buffer.from(uploaded.aeskey).toString("base64"), + encrypt_type: 1, + }, + mid_size: uploaded.fileSizeCiphertext, + }, + }; +} + +async function fetchQrCode(): Promise { + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), 15000); + try { + const url = new URL( + `ilink/bot/get_bot_qrcode?bot_type=${encodeURIComponent(BOT_TYPE)}`, + ensureTrailingSlash(INITIAL_BASE_URL), + ); + log(`fetchQrCode: GET ${url}`); + const response = await fetch(url, { signal: controller.signal }); + log(`fetchQrCode: status=${response.status} ok=${response.ok}`); + const raw = await response.text(); + if (!response.ok) { + log(`fetchQrCode: error body=${raw.slice(0, 200)}`); + throw new Error(`${response.status} ${response.statusText}: ${raw}`); + } + const data = JSON.parse(raw); + log( + `fetchQrCode: qrcode=${data?.qrcode || "MISSING"} img_len=${String(data?.qrcode_img_content || "").length}`, + ); + return data; + } finally { + clearTimeout(timeout); + } +} + +async function pollQrStatus( + qrcode: string, + baseUrl: string = INITIAL_BASE_URL, +): Promise { + const controller = new AbortController(); + const timeout = setTimeout(() => controller.abort(), 35000); + try { + const url = new URL( + `ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(qrcode)}`, + ensureTrailingSlash(baseUrl), + ); + const response = await fetch(url, { + headers: { "iLink-App-ClientVersion": "1" }, + signal: controller.signal, + }); + const raw = await response.text(); + if (!response.ok) { + throw new Error(`${response.status} ${response.statusText}: ${raw}`); + } + return JSON.parse(raw); + } catch (error) { + if (error instanceof Error && error.name === "AbortError") { + return { status: "wait" }; + } + throw error; + } finally { + clearTimeout(timeout); + } +} + +function extractText(itemList: any[] = []): string { + const parts: string[] = []; + for (const item of itemList) { + if (item?.type === MESSAGE_ITEM_TYPE.TEXT && item.text_item?.text) { + parts.push(String(item.text_item.text)); + } else if (item?.type === 3 && item.voice_item?.text) { + parts.push(String(item.voice_item.text)); + } + } + return parts.join("\n").trim(); +} + +function extractReplyToMessageId(itemList: any[] = []): string { + for (const item of itemList) { + const refMessageId = item?.ref_msg?.message_item?.msg_id; + if (refMessageId) { + return String(refMessageId); + } + } + return ""; +} + +function extractReplyReference(itemList: any[] = []): { + messageId: string; + title: string; + text: string; +} { + for (const item of itemList) { + const ref = item?.ref_msg; + if (!ref) { + continue; + } + return { + messageId: ref?.message_item?.msg_id ? String(ref.message_item.msg_id) : "", + title: ref?.title ? String(ref.title) : "", + text: ref?.message_item ? extractText([ref.message_item]) : "", + }; + } + return { messageId: "", title: "", text: "" }; +} + +async function downloadInboundImage( + item: any, +): Promise<{ path: string; media_type: string; size: number } | null> { + const imageItem = item?.image_item; + const media = imageItem?.media; + if (!media?.encrypt_query_param && !media?.full_url) { + return null; + } + const aesKeyBase64 = imageItem.aeskey + ? Buffer.from(imageItem.aeskey, "hex").toString("base64") + : media.aes_key; + const label = "inbound image"; + const buf = aesKeyBase64 + ? await downloadAndDecryptBuffer( + media.encrypt_query_param || "", + aesKeyBase64, + label, + media.full_url, + ) + : await downloadPlainCdnBuffer( + media.encrypt_query_param || "", + label, + media.full_url, + ); + const ext = imageExtFromBuffer(buf); + const filePath = path.join( + ensureMediaDir("inbound"), + mediaFileName("weixin-inbound", ext), + ); + fs.writeFileSync(filePath, buf); + return { + path: filePath, + media_type: IMAGE_MIME_BY_EXT[ext] || getImageMimeFromFilename(filePath), + size: buf.length, + }; +} + +async function extractInboundImages(itemList: any[] = []): Promise<{ + images: Array<{ path: string; media_type: string; size: number }>; + errors: string[]; +}> { + const images: Array<{ path: string; media_type: string; size: number }> = []; + const errors: string[] = []; + for (const item of itemList) { + if (item?.type !== MESSAGE_ITEM_TYPE.IMAGE) { + continue; + } + try { + const image = await downloadInboundImage(item); + if (image) { + images.push(image); + } + } catch (error) { + const message = String(error); + errors.push(message); + log(`inbound image download failed: ${message}`); + } + } + return { images, errors }; +} + +function extractQuotedMessageId(msg: any): string { + for (const item of msg?.item_list || []) { + if (item?.msg_id) { + return String(item.msg_id); + } + } + if (msg?.message_id != null) { + return String(msg.message_id); + } + return ""; +} + +function maybeEmitSentConfirmation(msg: any): void { + const clientId = String(msg?.client_id || ""); + if (!clientId) { + return; + } + const pending = pendingSentMessages.get(clientId); + if (!pending) { + return; + } + const quotedMessageId = extractQuotedMessageId(msg); + if (!quotedMessageId) { + return; + } + pendingSentMessages.delete(clientId); + emit({ + type: "sent", + request_id: pending.requestId, + message_id: clientId, + quoted_message_id: quotedMessageId, + peer_id: pending.peerId, + }); +} + +async function normalizeInboundMessage( + msg: any, +): Promise | null> { + if (msg?.message_type !== MESSAGE_TYPE.USER) { + return null; + } + const peerId = msg.from_user_id || ""; + const text = extractText(msg.item_list || []); + const { images, errors } = await extractInboundImages(msg.item_list || []); + if (!peerId || (!text && !images.length)) { + return null; + } + const replyRef = extractReplyReference(msg.item_list || []); + return { + type: "message", + account_id: state.accountId || ACCOUNT_ID_OVERRIDE || "", + peer_id: peerId, + context_token: msg.context_token || "", + message_id: String(msg.message_id || msg.client_id || crypto.randomUUID()), + reply_to_message_id: replyRef.messageId, + reply_to_message_title: replyRef.title, + reply_to_message_text: replyRef.text, + text, + image_paths: images.map((image) => image.path), + images, + image_errors: errors, + raw_message_type: msg.message_type || 0, + }; +} + +async function sendMessageItem( + command: BridgeCommand, + item: Record, +): Promise { + if (!state.token) { + throw new Error("weixin account is not logged in"); + } + const messageId = crypto.randomUUID(); + await postJson( + "ilink/bot/sendmessage", + { + msg: { + from_user_id: "", + to_user_id: command.peer_id, + client_id: messageId, + message_type: MESSAGE_TYPE.BOT, + message_state: MESSAGE_STATE.FINISH, + item_list: [item], + context_token: command.context_token || undefined, + }, + }, + state.token, + 15000, + ); + pendingSentMessages.set(messageId, { + requestId: command.request_id || "", + peerId: command.peer_id || "", + }); + emit({ + type: "accepted", + request_id: command.request_id || "", + client_id: messageId, + peer_id: command.peer_id, + }); + return messageId; +} + +async function sendTextMessage(command: BridgeCommand): Promise { + return sendMessageItem(command, { + type: MESSAGE_ITEM_TYPE.TEXT, + text_item: { text: command.text || "" }, + }); +} + +async function sendMessageWithImages(command: BridgeCommand): Promise { + const imagePaths = Array.isArray(command.image_paths) + ? command.image_paths.filter( + (imagePath): imagePath is string => + typeof imagePath === "string" && Boolean(imagePath), + ) + : []; + if (!imagePaths.length) { + await sendTextMessage(command); + return; + } + + if ((command.text || "").trim()) { + await sendTextMessage(command); + } + for (const imagePath of imagePaths) { + const uploaded = await uploadImageToWeixin(imagePath, command.peer_id || ""); + await sendMessageItem(command, buildImageItem(uploaded)); + } +} + +async function pollUpdatesOnce(): Promise { + if (!state.token || shuttingDown) { + return; + } + + const response = await postJson( + "ilink/bot/getupdates", + { + get_updates_buf: state.syncCursor || "", + }, + state.token, + 40000, + ); + + if (response?.errcode === -14) { + emit({ type: "error", message: "session_expired" }); + clearSession(); + pollerStarted = false; + if (AUTO_LOGIN) { + await ensureLogin(); + } + return; + } + + if (typeof response?.get_updates_buf === "string") { + state.syncCursor = response.get_updates_buf; + saveState(); + } + + for (const msg of response?.msgs || []) { + maybeEmitSentConfirmation(msg); + const normalized = await normalizeInboundMessage(msg); + if (normalized) { + emit(normalized); + } + } +} + +async function pollLoop(): Promise { + if (pollerStarted) { + return; + } + pollerStarted = true; + emit({ type: "ready", account_id: state.accountId || "" }); + while (!shuttingDown && state.token) { + try { + await pollUpdatesOnce(); + } catch (error) { + emit({ type: "error", message: String(error) }); + await new Promise((resolve) => { + pollTimer = setTimeout(resolve, 2000); + }); + } + } + pollerStarted = false; +} + +async function startPollingIfReady(): Promise { + if (state.token && !pollerStarted) { + void pollLoop(); + } +} + +async function loginFlow(): Promise { + const MAX_QR_RETRIES = 3; + log( + `loginFlow: start INITIAL_BASE_URL=${INITIAL_BASE_URL} state.baseUrl=${state.baseUrl}`, + ); + try { + for (let attempt = 0; attempt < MAX_QR_RETRIES; attempt++) { + log(`loginFlow: fetchQrCode attempt ${attempt + 1}/${MAX_QR_RETRIES}`); + const qr = await fetchQrCode(); + if (!qr?.qrcode || !qr?.qrcode_img_content) { + throw new Error("QR code response missing qrcode image content"); + } + log( + `qr payload received: len=${String(qr.qrcode_img_content).length} prefix=${String(qr.qrcode_img_content).slice(0, 80)}`, + ); + + emit({ + type: "qr", + qrcode_url: qr.qrcode_img_content, + account_id: state.accountId || ACCOUNT_ID_OVERRIDE || "", + }); + + let currentPollBaseUrl = INITIAL_BASE_URL; + let expired = false; + + while (!shuttingDown) { + const status = await pollQrStatus(qr.qrcode, currentPollBaseUrl); + if (status?.status === "confirmed" && status?.bot_token) { + state = { + ...state, + accountId: + ACCOUNT_ID_OVERRIDE || status.ilink_bot_id || state.accountId, + baseUrl: status.baseurl || state.baseUrl, + token: status.bot_token, + userId: status.ilink_user_id || state.userId, + syncCursor: "", + }; + saveState(); + emit({ + type: "login_success", + account_id: state.accountId, + user_id: state.userId, + }); + await startPollingIfReady(); + return; + } + if (status?.status === "scaned_but_redirect") { + const redirect = String(status.redirect_host || "").trim(); + if (redirect) { + currentPollBaseUrl = redirect.startsWith("http") + ? redirect + : `https://${redirect}`; + } + continue; + } + if (status?.status === "expired") { + expired = true; + break; + } + if (status?.status === "scaned") { + emit({ type: "scaned" }); + } + } + + if (!expired) return; + if (attempt + 1 < MAX_QR_RETRIES) { + log( + `QR code expired, retrying (attempt ${attempt + 2}/${MAX_QR_RETRIES})`, + ); + } + } + throw new Error("QR code expired"); + } catch (error) { + emit({ type: "error", message: `login_failed: ${String(error)}` }); + throw error; + } finally { + loginInFlight = null; + } +} + +async function ensureLogin(): Promise { + if (loginInFlight) { + log("ensureLogin: login already in flight, reusing"); + return loginInFlight; + } + log("ensureLogin: starting new loginFlow"); + loginInFlight = loginFlow().catch(() => undefined); + return loginInFlight; +} + +async function handleCommand(command: BridgeCommand): Promise { + if (!command?.type) { + return; + } + + if (command.type === "send_message") { + await sendMessageWithImages(command); + return; + } + + if (command.type === "login") { + log( + `handleCommand: login — token=${state.token ? "present" : "absent"} baseUrl=${state.baseUrl} loginInFlight=${loginInFlight != null}`, + ); + clearSession(); + log( + `handleCommand: login — session cleared, INITIAL_BASE_URL=${INITIAL_BASE_URL}`, + ); + await ensureLogin(); + return; + } + + if (command.type === "logout") { + log( + `handleCommand: logout — token=${state.token ? "present" : "absent"} baseUrl=${state.baseUrl} loginInFlight=${loginInFlight != null}`, + ); + loginInFlight = null; + clearSession(); + log( + `handleCommand: logout — session cleared, INITIAL_BASE_URL=${INITIAL_BASE_URL}`, + ); + emit({ type: "logged_out" }); + await ensureLogin(); + } +} + +ensureDataDir(); + +const rl = readline.createInterface({ + input: process.stdin, + crlfDelay: Infinity, +}); + +rl.on("line", (line: string) => { + if (!line.trim()) { + return; + } + let command: BridgeCommand; + try { + command = JSON.parse(line); + } catch { + emit({ type: "error", message: "invalid_json" }); + return; + } + void handleCommand(command).catch((error) => { + emit({ + type: "error", + request_id: command?.request_id || "", + message: String(error), + }); + }); +}); + +process.on("SIGINT", () => { + shuttingDown = true; + if (pollTimer) { + clearTimeout(pollTimer); + } + process.exit(0); +}); + +process.on("SIGTERM", () => { + shuttingDown = true; + if (pollTimer) { + clearTimeout(pollTimer); + } + process.exit(0); +}); + +if (state.token) { + void startPollingIfReady(); +} else if (AUTO_LOGIN) { + void ensureLogin(); +} + +// `extractReplyToMessageId` was unused in the original index.mjs as well; +// kept (and referenced here) so the port stays 1:1 without tripping +// noUnusedLocals-style lint rules. +void extractReplyToMessageId; diff --git a/backend/src/channels/weixin_bridge/package.json b/backend/src/channels/weixin_bridge/package.json new file mode 100644 index 0000000..367e9f3 --- /dev/null +++ b/backend/src/channels/weixin_bridge/package.json @@ -0,0 +1,7 @@ +{ + "name": "agentforge-weixin-bridge", + "private": true, + "type": "module", + "version": "0.1.0", + "description": "Node sidecar bridge for AgentForge Weixin channel" +} diff --git a/backend/src/executor.ts b/backend/src/executor.ts new file mode 100644 index 0000000..97aa97d --- /dev/null +++ b/backend/src/executor.ts @@ -0,0 +1,274 @@ +// AgentExecutor + subprocess seams, ported from taskboard.py (class +// AgentExecutor, lines 1597-1656). +// +// Python runs agent CLIs through the `subprocess` module and the pytest +// suites monkeypatch `taskboard.subprocess.run` / `taskboard.subprocess.Popen` +// (plus `taskboard.os.getpgid` / `taskboard.os.killpg`). The TS port keeps +// the same seams injectable so the ported tests can swap in fakes: +// +// - `AgentExecutor.subprocess_run` (≙ subprocess.run) — swappable static +// - `TaskScheduler._popen` (≙ subprocess.Popen) — swappable property +// - `TaskScheduler._os` (≙ os.getpgid/killpg/kill) +// +// This module also defines the exception types (FileNotFoundError / +// TimeoutExpired / OSError / ProcessLookupError) and the PIPE sentinel that +// Python code references through the subprocess/os builtins. + +import { spawn, spawnSync } from "node:child_process"; +import type { Readable } from "node:stream"; +import { CLAUDE_STREAM_JSON_ARGS, DEFAULT_TIMEOUT_SECONDS } from "./types.ts"; +import { getEnv } from "./util.ts"; +import { expanduser } from "./skills.ts"; + +// ── exception types (≙ Python builtins / subprocess) ──────────────────────── + +/** ≙ builtins.OSError */ +export class OSError extends Error {} + +/** ≙ builtins.FileNotFoundError (subclass of OSError, like Python) */ +export class FileNotFoundError extends OSError {} + +/** ≙ builtins.ProcessLookupError (subclass of OSError, like Python) */ +export class ProcessLookupError extends OSError {} + +/** ≙ subprocess.TimeoutExpired */ +export class TimeoutExpired extends Error { + cmd: unknown; + timeout: number | null; + + constructor(cmd: unknown = null, timeout: number | null = null) { + super(`Command timed out after ${timeout} seconds`); + this.cmd = cmd; + this.timeout = timeout; + } +} + +/** ≙ subprocess.PIPE sentinel (tests assert `captured.stdin === PIPE`). */ +export const PIPE: unique symbol = Symbol.for("subprocess.PIPE"); + +// ── subprocess.run seam (used by AgentExecutor.run) ───────────────────────── + +export interface SubprocessRunResult { + returncode: number; + stdout: string; + stderr: string; +} + +export interface SubprocessRunOptions { + cwd: string; + timeout: number; // seconds (≙ subprocess.run(timeout=...)) + env: Record; +} + +export type SubprocessRunFn = (cmd: string[], opts: SubprocessRunOptions) => SubprocessRunResult; + +/** Real implementation backed by child_process.spawnSync. */ +export function default_subprocess_run( + cmd: string[], + opts: SubprocessRunOptions, +): SubprocessRunResult { + const res = spawnSync(cmd[0]!, cmd.slice(1), { + cwd: opts.cwd, + env: opts.env, + timeout: opts.timeout * 1000, + encoding: "utf-8", + maxBuffer: 64 * 1024 * 1024, + }); + if (res.error) { + const code = (res.error as NodeJS.ErrnoException).code; + if (code === "ENOENT") throw new FileNotFoundError(res.error.message); + if (code === "ETIMEDOUT") throw new TimeoutExpired(cmd, opts.timeout); + throw new OSError(res.error.message); + } + // Killed by the timeout without spawnSync reporting ETIMEDOUT (signal exit). + if (res.signal === "SIGTERM" && res.status === null) { + throw new TimeoutExpired(cmd, opts.timeout); + } + return { + returncode: res.status ?? -1, + stdout: res.stdout ?? "", + stderr: res.stderr ?? "", + }; +} + +// ── subprocess.Popen seam (used by TaskScheduler) ─────────────────────────── + +export interface PopenStdin { + write(data: string): void; + close(): void; +} + +/** + * Minimal structural view of a Popen object as taskboard.py uses it: + * iterate stdout/stderr line-by-line, wait(), kill(), read returncode. + * Test fakes implement exactly this shape. + */ +export interface PopenLike { + pid: number; + stdout: Iterable | AsyncIterable; + stderr: Iterable | AsyncIterable; + stdin?: PopenStdin | null; + returncode: number | null; + /** ≙ proc.wait(timeout=...); throws/rejects TimeoutExpired on timeout. */ + wait(timeout?: number | null): number | Promise; + kill(): void; +} + +export interface PopenOptions { + stdin?: typeof PIPE | null; + stdout?: typeof PIPE; + stderr?: typeof PIPE; + cwd?: string; + env?: Record; + start_new_session?: boolean; +} + +/** + * ≙ subprocess.Popen — may throw (or reject with) FileNotFoundError / OSError. + * Test fakes are usually synchronous; callers `await` the result either way. + */ +export type PopenFn = (cmd: string[], opts: PopenOptions) => PopenLike | Promise; + +/** Split a Readable into lines, keeping the trailing "\n" like Python file iteration. */ +async function* lineIterable(stream: Readable): AsyncGenerator { + stream.setEncoding("utf-8"); + let buf = ""; + for await (const chunk of stream) { + buf += chunk; + let idx: number; + while ((idx = buf.indexOf("\n")) !== -1) { + yield buf.slice(0, idx + 1); + buf = buf.slice(idx + 1); + } + } + if (buf) yield buf; +} + +/** Real Popen implementation backed by child_process.spawn. */ +export const default_popen: PopenFn = (cmd, opts) => { + return new Promise((resolve, reject) => { + const child = spawn(cmd[0]!, cmd.slice(1), { + cwd: opts.cwd, + env: opts.env, + detached: opts.start_new_session === true, + stdio: [opts.stdin === PIPE ? "pipe" : "ignore", "pipe", "pipe"], + }); + child.once("error", (err) => { + const code = (err as NodeJS.ErrnoException).code; + reject( + code === "ENOENT" + ? new FileNotFoundError(`No such file or directory: '${cmd[0]}'`) + : new OSError(err.message), + ); + }); + child.once("spawn", () => { + const wrapper: PopenLike = { + pid: child.pid!, + stdout: lineIterable(child.stdout!), + stderr: lineIterable(child.stderr!), + stdin: child.stdin + ? { + write: (data: string) => child.stdin!.write(data), + close: () => child.stdin!.end(), + } + : null, + returncode: null, + wait: () => 0, // replaced below + kill: () => { + child.kill("SIGKILL"); + }, + }; + const exited = new Promise((res) => { + child.once("close", (code) => { + wrapper.returncode = code ?? -1; + res(wrapper.returncode); + }); + }); + wrapper.wait = (timeout: number | null = null): Promise => { + if (timeout === null || timeout === undefined) return exited; + return new Promise((res, rej) => { + const timer = setTimeout(() => rej(new TimeoutExpired(cmd, timeout)), timeout * 1000); + exited.then((code) => { + clearTimeout(timer); + res(code); + }); + }); + }; + resolve(wrapper); + }); + }); +}; + +// ── AgentExecutor ──────────────────────────────────────────────────────────── + +/** Executes prompts via configurable AI agent CLIs. */ +export class AgentExecutor { + /** Injectable seam ≙ pytest monkeypatching `taskboard.subprocess.run`. */ + static subprocess_run: SubprocessRunFn = default_subprocess_run; + + /** + * Run a prompt through Claude Code CLI. + * Returns (success: bool, output: str) + * + * Args: + * prompt: The text prompt to send + * working_dir: Working directory for the command + * timeout: Command timeout in seconds + * image_paths: Optional list of image file paths to include + */ + static run( + prompt: string, + working_dir: string = ".", + timeout: number = DEFAULT_TIMEOUT_SECONDS, + image_paths: string[] | null = null, + ): [boolean, string] { + try { + const cmd = ["claude", "-p", prompt]; + + // Add image paths if provided + if (image_paths) { + for (const img_path of image_paths) { + cmd.push("-i", img_path); + } + } + + cmd.push(...CLAUDE_STREAM_JSON_ARGS); + + const result = AgentExecutor.subprocess_run(cmd, { + cwd: expanduser(working_dir), + timeout, + env: getEnv(), + }); + if (result.returncode === 0) { + let output = result.stdout; + for (let line of result.stdout.split("\n").reverse()) { + line = line.trim(); + if (!line) continue; + try { + const event = JSON.parse(line); + if (event && typeof event === "object" && event.type === "result") { + output = event.result ?? result.stdout; + break; + } + } catch { + // not JSON — keep scanning + } + } + return [true, output]; + } else { + return [false, result.stderr || result.stdout]; + } + } catch (e) { + if (e instanceof FileNotFoundError) { + return [false, "claude CLI not found. Is it installed?"]; + } + if (e instanceof TimeoutExpired) { + return [false, `claude CLI timed out after ${timeout}s`]; + } + if (e instanceof OSError) { + return [false, e.message]; + } + throw e; + } + } +} diff --git a/backend/src/scheduler.ts b/backend/src/scheduler.ts new file mode 100644 index 0000000..e2183bc --- /dev/null +++ b/backend/src/scheduler.ts @@ -0,0 +1,2609 @@ +// TaskScheduler, ported from taskboard.py (class TaskScheduler, lines 1787-3798). +// +// Method names, prompts, error messages and JSON keys are kept byte-identical +// to the Python source — tests assert on them. Python's per-task/heartbeat +// threads become async functions; the injectable seams (`_popen`, `_os`, +// `_sleep`, `AgentExecutor.subprocess_run`) replace the pytest monkeypatching +// of `taskboard.subprocess.*` / `taskboard.os.*` / `taskboard.time.sleep`. + +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import { CronExpressionParser } from "cron-parser"; +import { BusAwareSchedulerMixin, OutboundMessageType, type MessageBus } from "./bus.ts"; +import type { TaskDB } from "./db.ts"; +import { + AgentExecutor, + FileNotFoundError, + OSError, + PIPE, + ProcessLookupError, + TimeoutExpired, + default_popen, + type PopenFn, + type PopenLike, +} from "./executor.ts"; +import { logger } from "./log.ts"; +import { _skill_creator_dir, _sanitize_skill_name, _compose_skill_md } from "./skills.ts"; +import { + _parse_skill_frontmatter, + expanduser, + link_skill, + remove_skill_from_disk, + unlink_skill, + write_skill_to_disk, +} from "./skills.ts"; +import { + CLAUDE_STREAM_JSON_ARGS, + DEFAULT_AGENT, + DEFAULT_TIMEOUT_SECONDS, + GENERATED_IMAGE_MEDIA_TYPES, + HeartbeatDecisionType, + LIVE_OUTPUT_EVENT_TYPES, + ScheduleType, + SECRET_KEY_FRAGMENTS, + TaskStatus, + makeHeartbeat, + type Task, +} from "./types.ts"; +import { + getEnv, + dateToLocalIso, + normalizeDatetimeForStorage, + nowIso, + parseComparableDatetime, + parseJsonObject, +} from "./util.ts"; + +type Row = Record; + +// ── small helpers ──────────────────────────────────────────────────────────── + +function errStr(e: unknown): string { + return e instanceof Error ? e.message : String(e); +} + +function sleepSeconds(seconds: number): Promise { + return new Promise((resolve) => setTimeout(resolve, seconds * 1000)); +} + +/** Await a promise but give up after `seconds` (≙ Thread.join(timeout=...)). */ +async function joinWithTimeout(p: Promise, seconds: number): Promise { + let timer: ReturnType | undefined; + const timeout = new Promise((resolve) => { + timer = setTimeout(resolve, seconds * 1000); + }); + try { + await Promise.race([p.catch(() => {}), timeout]); + } finally { + if (timer !== undefined) clearTimeout(timer); + } +} + +/** ≙ croniter.is_valid(expr) */ +function croniter_is_valid(expr: string): boolean { + try { + CronExpressionParser.parse(expr); + return true; + } catch { + return false; + } +} + +/** ≙ croniter(expr, base).get_next(datetime).isoformat() (local-naive storage) */ +function cron_next_iso(expr: string, base: Date): string { + return dateToLocalIso(CronExpressionParser.parse(expr, { currentDate: base }).next().toDate()); +} + +/** ≙ the Python dict key tuple (run_id, item_id) for codex/claude delta state. */ +function tupleKey(run_id: number | null, item_id: string): string { + return JSON.stringify([run_id, item_id]); +} + +/** ≙ os.path.realpath (non-strict: resolves as far as possible, never throws). */ +function realpathNonStrict(p: string): string { + try { + return fs.realpathSync(p); + } catch { + return path.resolve(p); + } +} + +const _int = (v: unknown): number | null => { + if (v === null || v === undefined) return null; + const n = typeof v === "number" ? Math.trunc(v) : parseInt(String(v), 10); + return Number.isNaN(n) ? null : n; +}; + +// ── injectable os seam (≙ monkeypatching taskboard.os.getpgid/killpg) ─────── + +export interface OsOps { + getpgid(pid: number): number; + killpg(pgid: number, sig: number | NodeJS.Signals): void; + kill(pid: number, sig: number | NodeJS.Signals): void; +} + +function mapKillError(e: unknown): Error { + const code = (e as NodeJS.ErrnoException | null)?.code; + if (code === "ESRCH") return new ProcessLookupError(errStr(e)); + if (code === "EPERM") return new OSError(errStr(e)); + return e instanceof Error ? e : new OSError(String(e)); +} + +export const default_os: OsOps = { + // start_new_session=True makes the child its own process-group leader, + // so the group id equals the child pid (≙ os.getpgid for our children). + getpgid(pid: number): number { + return pid; + }, + killpg(pgid: number, sig: number | NodeJS.Signals): void { + try { + process.kill(-pgid, sig); + } catch (e) { + throw mapKillError(e); + } + }, + kill(pid: number, sig: number | NodeJS.Signals): void { + try { + process.kill(pid, sig); + } catch (e) { + throw mapKillError(e); + } + }, +}; + +// ── scheduler types ────────────────────────────────────────────────────────── + +/** ≙ the threading.Thread handles stored in _active_tasks/_active_heartbeats. */ +export interface ActiveHandle { + is_alive(): boolean; + promise?: Promise | null; +} + +export type OutputListener = ( + task_id: number, + run_id: number, + event_type: string, + content: string, +) => void; + +export interface ChannelLike { + notify_task(task_id: number): void; +} + +export type DependsOn = number | { task_id: number; inject_result?: unknown }; + +/** Background scheduler that checks and runs due tasks. */ +export class TaskScheduler extends BusAwareSchedulerMixin { + db: TaskDB; + executor: AgentExecutor; + on_task_update: ((task_id: number) => void) | null; + _channels: ChannelLike[] = []; // generic Channel instances (e.g. TelegramChannel) + _output_event_listeners: OutputListener[] = []; // callables(task_id, run_id, event_type, content) + _running = false; + _shutting_down = false; + _loop_promise: Promise | null = null; // ≙ self._thread + _active_tasks: Map = new Map(); + _active_heartbeats: Map = new Map(); + _live_output: Map = new Map(); // task_id -> accumulated stdout + _live_heartbeat_output: Map = new Map(); // tick_id -> accumulated stdout/stderr + _active_pgids: Map = new Map(); // task_id -> process group id + _codex_item_text: Map = new Map(); // key = JSON.stringify([run_id, item_id]) + _claude_message_text: Map = new Map(); // key = JSON.stringify([run_id, message_id]) + // Skill Library sweep state (manual + scheduled share this guard) + _skill_sweep_running = false; + _last_skill_sweep: Row | null = null; + + // ── injectable seams (≙ pytest monkeypatching) ──────────────────────── + /** ≙ subprocess.Popen */ + _popen: PopenFn = default_popen; + /** ≙ os.getpgid / os.killpg / os.kill */ + _os: OsOps = default_os; + /** ≙ time.sleep */ + _sleep: (seconds: number) => Promise = sleepSeconds; + + readonly SKILL_SWEEP_RUN_LIMIT = 50; + + constructor( + db: TaskDB, + on_task_update: ((task_id: number) => void) | null = null, + bus: MessageBus | null = null, + ) { + super(); + this.db = db; + this.executor = new AgentExecutor(); + this.on_task_update = on_task_update; + this.bus = bus; // MessageBus integration (optional) + } + + start(): void { + this._running = true; + this._loop_promise = this._loop(); + logger.info("Scheduler started"); + } + + async stop(): Promise { + this._shutting_down = true; + this._running = false; + if (this._loop_promise) { + await joinWithTimeout(this._loop_promise, 5); + } + // Wait up to 5 seconds for running tasks to finish + let deadline = Date.now() / 1000 + 5; + const running = [...this._active_tasks.entries()].filter(([, t]) => t.is_alive()); + if (running.length) { + logger.info(`Waiting for ${running.length} running task(s) to finish...`); + for (const [, t] of running) { + const remaining = Math.max(0, deadline - Date.now() / 1000); + if (t.promise) await joinWithTimeout(t.promise, remaining); + } + } + const heartbeat_running = [...this._active_heartbeats.entries()].filter(([, t]) => + t.is_alive(), + ); + if (heartbeat_running.length) { + logger.info(`Waiting for ${heartbeat_running.length} heartbeat(s) to finish...`); + for (const [, t] of heartbeat_running) { + const remaining = Math.max(0, deadline - Date.now() / 1000); + if (t.promise) await joinWithTimeout(t.promise, remaining); + } + } + // Gracefully terminate any processes still alive, then force-kill if needed + for (const [tid, pgid] of [...this._active_pgids.entries()]) { + try { + this._os.killpg(pgid, "SIGTERM"); + logger.info(`Sent SIGTERM to task ${tid} (pgid ${pgid})`); + } catch (e) { + if (e instanceof OSError) continue; + throw e; + } + // Wait up to 5 seconds for the process group to exit + deadline = Date.now() / 1000 + 5; + let gone = false; + while (Date.now() / 1000 < deadline) { + try { + this._os.killpg(pgid, 0); // check if still alive + } catch (e) { + if (e instanceof OSError) { + gone = true; // process group is gone + break; + } + throw e; + } + await this._sleep(0.1); + } + if (!gone) { + // Still alive — escalate to SIGKILL + logger.warning(`Force-killing task ${tid} (pgid ${pgid}) after SIGTERM timeout`); + try { + this._os.killpg(pgid, "SIGKILL"); + } catch (e) { + logger.error(`killpg(${pgid}) SIGKILL failed: ${errStr(e)}`); + } + } + } + logger.info("Scheduler stopped"); + } + + async _loop(): Promise { + while (this._running) { + try { + this._tick(); + } catch (e) { + logger.error(`Scheduler error: ${errStr(e)}`); + } + await this._sleep(2); // check every 2 seconds + } + } + + _tick(): void { + if (this._shutting_down) { + return; + } + const due_tasks = this.db.get_due_tasks(); + for (const task of due_tasks) { + const tid = task["id"]; + const handle = this._active_tasks.get(tid); + if (handle && handle.is_alive()) { + continue; // already running + } + // Check if it's time + if (task["schedule_type"] === "immediate" && task["status"] === "pending") { + this._spawn_task(task); + } else if (task["schedule_type"] === "delayed" && task["status"] === "pending") { + this._schedule_delayed(task); + } else if (task["schedule_type"] === "delayed" && task["status"] === "scheduled") { + const nra = task["next_run_at"]; + const run_at = nra ? parseComparableDatetime(nra) : null; + if (run_at && run_at.getTime() <= Date.now()) { + this._spawn_task(task); + } + } else if (task["schedule_type"] === "scheduled_at" && task["status"] === "scheduled") { + const nra = task["next_run_at"]; + const run_at = nra ? parseComparableDatetime(nra) : null; + if (run_at && run_at.getTime() <= Date.now()) { + this._spawn_task(task); + } + } else if (task["schedule_type"] === "cron" && task["status"] === "scheduled") { + const nra = task["next_run_at"]; + const run_at = nra ? parseComparableDatetime(nra) : null; + if (run_at && run_at.getTime() <= Date.now()) { + this._spawn_task(task); + } + } + } + const due_heartbeats = this.db.get_due_heartbeats(); + for (const heartbeat of due_heartbeats) { + const hid = heartbeat["id"]; + const handle = this._active_heartbeats.get(hid); + if (handle && handle.is_alive()) { + continue; + } + this._spawn_heartbeat(heartbeat); + } + this._maybe_run_scheduled_sweep(); + } + + /** + * Built-in "skill-distiller": cron-driven auto sweep, gated by the toggle. + * + * Gated by skill_library_enabled (default OFF). Agent + cadence come from + * skill_sweep_agent / skill_sweep_cron. The manual button bypasses this + * entirely. When disabled, returns immediately — never calls an agent. + */ + _maybe_run_scheduled_sweep(): void { + if (!["1", "true", "True"].includes(this.db.get_setting("skill_library_enabled", "0") ?? "")) { + return; + } + const cron = this.db.get_setting("skill_sweep_cron", "0 3 * * *"); + if (!cron || !croniter_is_valid(cron)) { + return; + } + const now = new Date(); + const next_run_raw = this.db.get_setting("skill_sweep_next_run", ""); + if (!next_run_raw) { + // First tick after enabling: schedule forward, don't run immediately. + this.db.set_setting("skill_sweep_next_run", cron_next_iso(cron, now)); + return; + } + let next_run: Date | null; + try { + next_run = parseComparableDatetime(next_run_raw); + } catch { + next_run = null; + } + if (next_run === null || next_run.getTime() <= now.getTime()) { + this.trigger_skill_sweep(this.db.get_setting("skill_sweep_agent", null)); + this.db.set_setting("skill_sweep_next_run", cron_next_iso(cron, now)); + } + } + + _schedule_delayed(task: Row): void { + const delay = task["delay_seconds"] || 0; + const run_at = new Date(Date.now() + delay * 1000); + this.db.update_task(task["id"], { status: "scheduled", next_run_at: dateToLocalIso(run_at) }); + this._notify(task["id"]); + } + + _spawn_heartbeat(heartbeat: Row): void { + let alive = true; + const handle: ActiveHandle = { is_alive: () => alive, promise: null }; + this._active_heartbeats.set(heartbeat["id"], handle); + handle.promise = (async () => { + try { + await this._execute_heartbeat(heartbeat); + } catch (e) { + logger.error(`Heartbeat ${heartbeat["id"]} thread error: ${errStr(e)}`); + } finally { + alive = false; + } + })(); + } + + _spawn_task(task: Row): void { + // Register the handle in _active_tasks *before* updating the DB so + // that if the run crashes immediately after the DB write, the task + // is still visible in _active_tasks and won't be re-picked by _tick(). + let alive = true; + const handle: ActiveHandle = { is_alive: () => alive, promise: null }; + this._active_tasks.set(task["id"], handle); + this.db.update_task(task["id"], { status: "running" }); + handle.promise = (async () => { + try { + await this._execute_task(task); + } catch (e) { + logger.error(`Task ${task["id"]} thread error: ${errStr(e)}`); + } finally { + alive = false; + } + })(); + } + + _render_heartbeat_check_prompt(heartbeat: Row): string { + const lines = [ + "You are AgentForge heartbeat decision engine.", + "Return JSON only. No markdown, no explanation, no code fences.", + "JSON schema:", + '{"decision":"idle|trigger_task|error","reason":"string","dedupe_key":"string","title":"string","prompt":"string","metadata":{}}', + "", + `Heartbeat name: ${heartbeat["name"]}`, + `Working directory: ${heartbeat["working_dir"]}`, + `Current time: ${nowIso()}`, + `Last tick at: ${heartbeat["last_tick_at"] || ""}`, + `Last decision: ${heartbeat["last_decision"] || ""}`, + `Last triggered at: ${heartbeat["last_triggered_at"] || ""}`, + `Last dedupe key: ${heartbeat["last_dedupe_key"] || ""}`, + "", + "User-defined check instructions:", + heartbeat["check_prompt"], + ]; + if (heartbeat["action_prompt_template"]) { + lines.push( + "", + "When decision is trigger_task, use this action prompt template as the base prompt to expand or adapt:", + heartbeat["action_prompt_template"], + ); + } + return lines.join("\n"); + } + + _parse_heartbeat_decision(raw_text: string): Row { + let text = raw_text.trim(); + if (text.startsWith("```")) { + text = text + .split(/\r?\n/) + .filter((line) => !line.trim().startsWith("```")) + .join("\n") + .trim(); + } + if (!text.startsWith("{")) { + const start = text.indexOf("{"); + const end = text.lastIndexOf("}"); + if (start !== -1 && end !== -1 && end > start) { + text = text.slice(start, end + 1); + } + } + const payload = JSON.parse(text) as Row; + const decision = payload["decision"]; + if (!(Object.values(HeartbeatDecisionType) as string[]).includes(decision)) { + throw new Error(`Invalid heartbeat decision: ${decision}`); + } + const normalized: Row = { + decision, + reason: String(payload["reason"] ?? ""), + dedupe_key: String(payload["dedupe_key"] ?? ""), + title: String(payload["title"] ?? ""), + prompt: String(payload["prompt"] ?? ""), + metadata: payload["metadata"] || {}, + }; + if ( + typeof normalized["metadata"] !== "object" || + normalized["metadata"] === null || + Array.isArray(normalized["metadata"]) + ) { + throw new Error("Heartbeat decision metadata must be an object"); + } + return normalized; + } + + // ── Skill Library: cross-run sweep ───────────────────────────────────── + + /** + * Synchronous sweep core (tested directly). + * + * full=false (scheduled): only runs since the watermark — incremental, cheap. + * full=true (manual button): re-scans the most recent completed runs ignoring + * the watermark, so the button always analyzes something. Counting is + * idempotent per run_id, so re-scanning never inflates recurrence counts. + */ + async run_skill_sweep(agent: string | null = null, full: boolean = false): Promise { + agent = + agent || + this.db.get_setting("skill_sweep_agent", null) || + this.db.get_setting("default_agent", DEFAULT_AGENT); + const watermark = this.db.get_setting("skill_sweep_watermark", "") || ""; + let runs: Row[]; + if (full) { + runs = this.db.get_recent_completed_runs(this.SKILL_SWEEP_RUN_LIMIT); + } else { + runs = this.db.get_completed_runs_since(watermark, this.SKILL_SWEEP_RUN_LIMIT); + } + if (!runs.length) { + const result: Row = { + scanned: 0, + detected: 0, + new: 0, + candidates: 0, + watermark, + agent, + full, + }; + this._last_skill_sweep = result; + return result; + } + + const existing = this.db.get_skill_patterns(); + const prompt = this._build_sweep_prompt(runs, existing); + const [ok, raw] = await this._run_agent_prompt_once(agent!, prompt, "."); + if (!ok) { + throw new Error(raw || "skill sweep agent failed"); + } + + let detected = 0; + let new_occurrences = 0; + for (const item of TaskScheduler._parse_sweep_output(raw)) { + if (typeof item !== "object" || item === null || Array.isArray(item)) { + continue; + } + const it = item as Row; + const tid = _int(it["task_id"]); + const rid = _int(it["run_id"]); + const before = this.db.get_skill_pattern_recurrence(it["pattern_key"] ?? ""); + const pid = this.db.upsert_skill_pattern( + it["pattern_key"] ?? "", + it["kind"] ?? "recipe", + String(it["summary"] ?? ""), + tid, + rid, + ); + if (pid !== null) { + detected += 1; + const after = this.db.get_skill_pattern_recurrence(it["pattern_key"] ?? ""); + if (after > before) { + new_occurrences += 1; + } + } + } + + const finished = runs.map((r) => r["finished_at"]).filter(Boolean) as string[]; + const new_watermark = finished.length ? finished.reduce((a, b) => (a > b ? a : b)) : watermark; + if (new_watermark && new_watermark > watermark) { + this.db.set_setting("skill_sweep_watermark", new_watermark); + } + const candidates = this.db.refresh_skill_candidates(); + const result: Row = { + scanned: runs.length, + detected, + new: new_occurrences, + candidates, + watermark: new_watermark, + agent, + full, + }; + this._last_skill_sweep = result; + return result; + } + + /** + * Start a sweep in the background. Returns false if one is already running. + * + * The HTTP server is single-threaded, so a sweep (which can take minutes) + * must not block the request thread. + */ + trigger_skill_sweep(agent: string | null = null, full: boolean = false): boolean { + if (this._skill_sweep_running) { + return false; + } + this._skill_sweep_running = true; + + void (async () => { + try { + await this.run_skill_sweep(agent, full); + } catch (e) { + // surface to status, never crash the worker + logger.error(`Skill sweep failed: ${errStr(e)}`); + this._last_skill_sweep = { error: errStr(e) }; + } finally { + this._skill_sweep_running = false; + } + })(); + return true; + } + + skill_sweep_status(): { running: boolean; last: Row | null } { + return { running: this._skill_sweep_running, last: this._last_skill_sweep }; + } + + // ── Skill Library: distillation / approval ───────────────────────────── + _build_distill_context(tids: number[]): string { + const blocks: string[] = []; + for (const tid of tids.slice(0, 5)) { + const task = this.db.get_task(tid); + if (!task) { + continue; + } + const runs = this.db.get_task_runs(tid, 1); + const result: string = (runs.length ? runs[0]!["result"] : "") || ""; + blocks.push( + `[task #${tid}] ${task["title"] || "Untitled"}\n` + + ` prompt: ${String(task["prompt"] || "") + .trim() + .slice(0, 600)}\n` + + ` result: ${result.trim().slice(0, 600)}`, + ); + } + return blocks.join("\n\n"); + } + + _build_distill_prompt( + pattern: Row, + context: string, + skill_creator_rel: string | null = null, + ): string { + const kind = pattern["kind"] ?? "recipe"; + let header: string; + if (skill_creator_rel) { + header = + "You are creating a reusable Claude Code skill from a recurring task pattern. " + + "You MUST author it USING the skill-creator skill, whose full authoring guidance " + + "is on disk in this working directory at:\n" + + ` ${skill_creator_rel}\n` + + "Read that file first and follow its conventions for skill structure, the " + + "description (triggering accuracy), progressive disclosure, and body style. " + + "Do NOT run any of skill-creator's scripts, do NOT scaffold a directory on disk, " + + "do NOT run evals or package anything — your ONLY output is the JSON described " + + "below.\n\n"; + } else { + header = + "You are creating a reusable Claude Code skill from a recurring task pattern, " + + "following Anthropic's skill-creator conventions (concise description that states " + + "what AND when with concrete triggers; imperative body that explains why; " + + "progressive disclosure; well under 500 lines).\n\n"; + } + return ( + header + + `Pattern key: ${pattern["pattern_key"]}\n` + + `Kind: ${kind}\n` + + `Summary: ${pattern["summary"] ?? ""}\n` + + `Observed ${pattern["recurrence_count"] ?? 0} times across these task runs:\n\n` + + `${context}\n\n` + + "STEP 1 — Decide if a skill is genuinely warranted. A skill IS warranted when the " + + "pattern is one of:\n" + + " - a repeatable, multi-step workflow run many times across different inputs;\n" + + " - produces an objectively verifiable output (file transform, data extraction, " + + "code generation, fixed procedure);\n" + + " - encodes specialized/domain knowledge or best practices worth codifying.\n" + + "A skill is NOT warranted for one-off, trivial, or purely subjective work (taste, " + + "writing style) with no reusable procedure. Be honest — most patterns are not " + + "skill-worthy.\n\n" + + "STEP 2 — If worthy, author the SKILL.md using the skill-creator guidance above. " + + "The description is the PRIMARY trigger: state BOTH what it does AND when to use it, " + + "third person, concrete trigger phrasing. The body_markdown must NOT include YAML " + + "frontmatter (it is added separately).\n\n" + + "Respond with ONLY a JSON object, no prose, no code fence:\n" + + '{"worthy": true, "worthiness_reason": "one sentence on why it is / is not ' + + 'skill-worthy", "name": "short-kebab-name", "description": "what AND when, with ' + + 'concrete triggers", "body_markdown": "the skill body, no frontmatter"}\n' + + "If NOT worthy, set worthy=false and give the reason, but still fill name/" + + "description/body_markdown with your best attempt — the human makes the final call." + ); + } + + /** Synchronous distill core (tested directly). Saves a 'ready' draft. */ + async distill_skill_draft(pattern_id: number, agent: string | null = null): Promise { + const pattern = this.db.get_skill_pattern(pattern_id); + if (!pattern) { + throw new Error("pattern not found"); + } + agent = + agent || + this.db.get_setting("skill_sweep_agent", null) || + this.db.get_setting("default_agent", DEFAULT_AGENT); + let tids: number[]; + try { + tids = JSON.parse(pattern["contributing_task_ids"]) || []; + if (!Array.isArray(tids)) tids = []; + } catch { + tids = []; + } + const context = this._build_distill_context(tids); + + // Run the distill in a throwaway working dir that has the vendored + // skill-creator skill loaded, so the agent actually authors the SKILL.md + // *using* skill-creator (not just "in its style"). + const creator_src = _skill_creator_dir(); + let creator_rel: string | null = null; + const workdir = fs.mkdtempSync(path.join(os.tmpdir(), "agentforge-distill-")); + let ok: boolean; + let raw: string; + try { + let hasCreatorMd = false; + try { + hasCreatorMd = fs.statSync(path.join(creator_src, "SKILL.md")).isFile(); + } catch { + hasCreatorMd = false; + } + if (hasCreatorMd) { + const dest = path.join(workdir, ".claude", "skills", "skill-creator"); + fs.mkdirSync(dest, { recursive: true }); + fs.copyFileSync(path.join(creator_src, "SKILL.md"), path.join(dest, "SKILL.md")); + creator_rel = ".claude/skills/skill-creator/SKILL.md"; + } + const prompt = this._build_distill_prompt(pattern, context, creator_rel); + [ok, raw] = await this._run_agent_prompt_once(agent!, prompt, workdir); + } finally { + fs.rmSync(workdir, { recursive: true, force: true }); + } + if (!ok) { + throw new Error(raw || "distill agent failed"); + } + const obj = parseJsonObject(raw); + const name = _sanitize_skill_name((obj["name"] as string) || pattern["pattern_key"]); + const description = String(obj["description"] ?? "").trim(); + const body_md = String(obj["body_markdown"] || obj["body"] || "").trim(); + const worthy_raw = obj["worthy"]; + const worthy = typeof worthy_raw === "boolean" ? worthy_raw : null; + const worthiness_reason = String(obj["worthiness_reason"] ?? "").trim(); + const skill_md = _compose_skill_md(name, description, body_md); + this.db.upsert_skill_draft( + pattern_id, + "ready", + name, + description, + pattern["kind"], + skill_md, + null, + worthy, + worthiness_reason, + ); + return { + pattern_id, + name, + description, + kind: pattern["kind"], + body: skill_md, + worthy, + worthiness_reason, + }; + } + + /** Start distillation in the background (single-threaded server). */ + trigger_skill_draft(pattern_id: number, agent: string | null = null): boolean { + const pattern = this.db.get_skill_pattern(pattern_id); + if (!pattern) { + return false; + } + this.db.upsert_skill_draft(pattern_id, "drafting", "", "", pattern["kind"]); + + void (async () => { + try { + await this.distill_skill_draft(pattern_id, agent); + } catch (e) { + // surface to draft row, never crash + logger.error(`Skill distill failed: ${errStr(e)}`); + this.db.upsert_skill_draft(pattern_id, "error", "", "", pattern["kind"], "", errStr(e)); + } + })(); + return true; + } + + /** Write the approved SKILL.md, symlink it for both agents, register it. */ + approve_skill(pattern_id: number, name: string, description: string, body: string): Row | null { + const pattern = this.db.get_skill_pattern(pattern_id); + if (!pattern) { + throw new Error("pattern not found"); + } + if (!(body || "").trim()) { + throw new Error("skill body is empty"); + } + // The edited SKILL.md is the single source of truth: derive the skill name + // and registry description from its frontmatter, falling back to the args. + const [fm_name, fm_desc] = _parse_skill_frontmatter(body); + name = _sanitize_skill_name(fm_name || name || pattern["pattern_key"]); + if (!name) { + throw new Error("invalid skill name"); + } + description = fm_desc || description || ""; + const [skill_md_path] = write_skill_to_disk(name, body); + const skill_id = this.db.add_skill( + name, + description || "", + skill_md_path, + pattern["pattern_key"], + pattern["contributing_task_ids"], + pattern["kind"], + ); + this.db.set_skill_pattern_status(pattern_id, "promoted", skill_id); + this.db.delete_skill_draft(pattern_id); + return skill_id !== null ? this.db.get_skill(skill_id) : null; + } + + dismiss_skill_pattern(pattern_id: number): void { + if (!this.db.get_skill_pattern(pattern_id)) { + throw new Error("pattern not found"); + } + this.db.set_skill_pattern_status(pattern_id, "dismissed"); + this.db.delete_skill_draft(pattern_id); + } + + // ── Skill Library: registry management (#19) ─────────────────────────── + + /** + * Enable/disable a registered skill by adding/removing both symlinks. + * + * Canonical SKILL.md is preserved either way — disabling just stops the + * agents from loading it. + */ + toggle_skill(skill_id: number, enabled: boolean): Row | null { + const skill = this.db.get_skill(skill_id); + if (!skill) { + throw new Error("skill not found"); + } + if (enabled) { + link_skill(skill["name"]); + } else { + unlink_skill(skill["name"]); + } + this.db.set_skill_enabled(skill_id, enabled); + return this.db.get_skill(skill_id); + } + + /** Delete a skill: remove symlinks, canonical dir, and registry row. */ + remove_skill(skill_id: number): void { + const skill = this.db.get_skill(skill_id); + if (!skill) { + throw new Error("skill not found"); + } + remove_skill_from_disk(skill["name"]); + this.db.delete_skill(skill_id); + } + + _build_sweep_prompt(runs: Row[], existing: Row[]): string { + let existing_block: string; + if (existing.length) { + existing_block = existing + .map( + (p) => + `- ${p["pattern_key"]} (${p["kind"]}, seen ${p["recurrence_count"]}x): ${p["summary"]}`, + ) + .join("\n"); + } else { + existing_block = "(none yet)"; + } + const run_lines: string[] = []; + for (const r of runs) { + const p = String(r["prompt"] || "") + .trim() + .replaceAll("\n", " ") + .slice(0, 400); + const res = String(r["result"] || "") + .trim() + .replaceAll("\n", " ") + .slice(0, 300); + run_lines.push( + `[run #${r["run_id"]} · task #${r["task_id"]}] ${r["title"] || "Untitled"}\n` + + ` prompt: ${p}\n` + + ` result: ${res}`, + ); + } + const runs_block = run_lines.join("\n"); + return ( + "You analyze a developer's recently completed AI-agent task runs to detect " + + "RECURRING patterns of work worth distilling into a reusable skill.\n\n" + + "Existing tracked patterns — REUSE an existing pattern_key verbatim when a run " + + "matches one semantically; otherwise mint a new short kebab-case key:\n" + + `${existing_block}\n\n` + + "Recently completed task runs to analyze (each line is ONE run):\n" + + `${runs_block}\n\n` + + "Emit ONE entry PER RUN that represents a meaningful, repeatable capability. Kinds:\n" + + '- "recipe": a successful repeatable approach/workflow worth reusing.\n' + + '- "pitfall": a failure that was diagnosed and fixed, worth avoiding next time.\n' + + "CRITICAL: when several runs share the same capability, they MUST reuse the SAME " + + "pattern_key (so occurrences aggregate), but each run still gets its OWN entry with " + + "its own run_id and task_id. Do NOT collapse multiple matching runs into a single " + + "entry — one entry per run is how recurrence is counted. Reuse an existing tracked " + + "pattern_key verbatim when it matches. Skip trivial or truly one-off runs.\n\n" + + "Respond with ONLY a JSON array, no prose, no code fence (example shows two runs of " + + "the same pattern):\n" + + '[{"pattern_key":"run-pytest-suite","kind":"recipe","summary":"one concise line","run_id":12,"task_id":3},' + + '{"pattern_key":"run-pytest-suite","kind":"recipe","summary":"one concise line","run_id":15,"task_id":4}]\n' + + "If nothing is worth tracking, respond with []." + ); + } + + static _parse_sweep_output(raw_text: string): unknown[] { + let text = (raw_text || "").trim(); + if (text.startsWith("```")) { + text = text + .split(/\r?\n/) + .filter((ln) => !ln.trim().startsWith("```")) + .join("\n") + .trim(); + } + if (!text.startsWith("[")) { + const start = text.indexOf("["); + const end = text.lastIndexOf("]"); + if (start !== -1 && end !== -1 && end > start) { + text = text.slice(start, end + 1); + } + } + let data: unknown; + try { + data = JSON.parse(text); + } catch { + return []; + } + return Array.isArray(data) ? data : []; + } + + /** Instance alias so tests can call `sched._parse_sweep_output(...)` like Python. */ + _parse_sweep_output(raw_text: string): unknown[] { + return TaskScheduler._parse_sweep_output(raw_text); + } + + async _run_agent_prompt_once( + agent: string, + prompt: string, + working_dir: string, + ): Promise<[boolean, string]> { + const working_dir_expanded = expanduser(working_dir); + let cmd: string[]; + if (agent === "codex") { + cmd = [ + "codex", + "exec", + "--json", + "--dangerously-bypass-approvals-and-sandbox", + "--skip-git-repo-check", + "--cd", + working_dir_expanded, + prompt, + ]; + } else { + cmd = ["claude", "-p", prompt, ...CLAUDE_STREAM_JSON_ARGS]; + } + return this._run_agent_command(agent, cmd, working_dir_expanded); + } + + async _run_agent_command( + agent: string, + cmd: string[], + working_dir_expanded: string, + on_stdout_line: ((line: string) => void) | null = null, + on_stderr_line: ((line: string) => void) | null = null, + ): Promise<[boolean, string]> { + let proc: PopenLike; + try { + proc = await this._popen(cmd, { + stdout: PIPE, + stderr: PIPE, + cwd: working_dir_expanded, + env: getEnv(), + }); + } catch (e) { + if (e instanceof FileNotFoundError) { + return [false, `${agent} CLI not found`]; + } + if (e instanceof OSError) { + return [false, e.message]; + } + throw e; + } + const timeout_secs = parseInt( + this.db.get_setting("timeout", String(DEFAULT_TIMEOUT_SECONDS)) ?? + String(DEFAULT_TIMEOUT_SECONDS), + 10, + ); + const stdout_chunks: string[] = []; + const stderr_chunks: string[] = []; + + const _read_stream = async ( + stream: Iterable | AsyncIterable, + chunks: string[], + callback: ((line: string) => void) | null, + ): Promise => { + for await (const line of stream) { + chunks.push(line); + if (callback) { + callback(line); + } + } + }; + + const stdout_promise = _read_stream(proc.stdout, stdout_chunks, on_stdout_line).catch(() => {}); + const stderr_promise = _read_stream(proc.stderr, stderr_chunks, on_stderr_line).catch(() => {}); + try { + await proc.wait(timeout_secs); + } catch (e) { + if (e instanceof TimeoutExpired) { + try { + proc.kill(); + } catch { + // ≙ except OSError: pass + } + await joinWithTimeout(stdout_promise, 1); + await joinWithTimeout(stderr_promise, 1); + return [false, `${agent} heartbeat decision timed out`]; + } + throw e; + } + + await joinWithTimeout(stdout_promise, 1); + await joinWithTimeout(stderr_promise, 1); + const raw_stdout = stdout_chunks.join(""); + const raw_stderr = stderr_chunks.join(""); + if (proc.returncode !== 0) { + return [false, raw_stderr || raw_stdout || `${agent} heartbeat decision failed`]; + } + + if (agent === "codex") { + let out = ""; + for (let line of raw_stdout.split("\n")) { + line = line.trim(); + if (!line) continue; + let event: any; + try { + event = JSON.parse(line); + } catch { + continue; + } + if (event?.type === "item.completed" && event?.item?.type === "agent_message") { + out = event.item.text ?? ""; + } + } + return [true, out || raw_stdout]; + } + + let out = ""; + let last_assistant_text = ""; + for (let line of raw_stdout.split("\n")) { + line = line.trim(); + if (!line) continue; + let event: any; + try { + event = JSON.parse(line); + } catch { + continue; + } + if (event?.type === "assistant") { + const msg = event.message ?? {}; + const content = msg.content ?? []; + const text_parts: string[] = []; + for (const c of content) { + if (typeof c === "string") { + text_parts.push(c); + } else if (c && typeof c === "object" && c.type === "text") { + text_parts.push(c.text ?? ""); + } + } + if (text_parts.length) { + last_assistant_text = text_parts.join(""); + } + } else if (event?.type === "result") { + const result_text = event.result; + if (result_text) { + out = result_text; + } + } + } + return [true, out || last_assistant_text || raw_stdout]; + } + + _heartbeat_trigger_suppressed(heartbeat: Row, dedupe_key: string): boolean { + if (!dedupe_key) { + return false; + } + const existing = this.db.get_heartbeat_dedup(heartbeat["id"], dedupe_key); + if (!existing) { + return false; + } + const cooldown = Math.trunc(Number(heartbeat["cooldown_seconds"] || 0)); + const triggered_at = existing["triggered_at"]; + if (triggered_at) { + try { + const triggered_dt = parseComparableDatetime(triggered_at); + if (triggered_dt && cooldown > 0 && Date.now() < triggered_dt.getTime() + cooldown * 1000) { + return true; + } + } catch { + // ≙ except ValueError: pass + } + } + const existing_task_id = existing["task_id"]; + if (existing_task_id) { + const task = this.db.get_task(existing_task_id); + if (task && ["pending", "scheduled", "blocked", "running"].includes(task["status"])) { + return true; + } + } + return false; + } + + async _execute_heartbeat(heartbeat: Row): Promise { + const hid = heartbeat["id"]; + const tick_id = this.db.add_heartbeat_tick(hid); + const now = new Date(); + const output_chunks: string[] = []; + this._live_heartbeat_output.set(tick_id, ""); + const next_run_at = this.db._compute_heartbeat_next_run_at( + makeHeartbeat({ + id: hid, + name: heartbeat["name"], + enabled: heartbeat["enabled"], + working_dir: heartbeat["working_dir"], + schedule_type: heartbeat["schedule_type"], + cron_expr: heartbeat["cron_expr"] ?? null, + interval_seconds: heartbeat["interval_seconds"] ?? null, + check_prompt: heartbeat["check_prompt"], + action_prompt_template: heartbeat["action_prompt_template"] || "", + default_agent: heartbeat["default_agent"] || DEFAULT_AGENT, + cooldown_seconds: Math.trunc(Number(heartbeat["cooldown_seconds"] || 0)), + }), + now, + ); + try { + const _append_tick_output = (line: string): void => { + output_chunks.push(line); + this._live_heartbeat_output.set(tick_id, output_chunks.join("")); + }; + + const agent = heartbeat["default_agent"] || DEFAULT_AGENT; + const prompt = this._render_heartbeat_check_prompt(heartbeat); + const working_dir_expanded = expanduser(heartbeat["working_dir"]); + let cmd: string[]; + if (agent === "codex") { + cmd = [ + "codex", + "exec", + "--json", + "--dangerously-bypass-approvals-and-sandbox", + "--skip-git-repo-check", + "--cd", + working_dir_expanded, + prompt, + ]; + } else { + cmd = [ + "claude", + "-p", + prompt, + "--output-format", + "stream-json", + "--verbose", + "--permission-mode", + "bypassPermissions", + ]; + } + const [success, raw_output] = await this._run_agent_command( + agent, + cmd, + working_dir_expanded, + _append_tick_output, + _append_tick_output, + ); + if (!success) { + throw new Error(raw_output); + } + const decision = this._parse_heartbeat_decision(raw_output); + let decision_type: string = decision["decision"]; + if (decision_type === HeartbeatDecisionType.TRIGGER_TASK) { + const dedupe_key: string = decision["dedupe_key"] ?? ""; + if (this._heartbeat_trigger_suppressed(heartbeat, dedupe_key)) { + decision_type = HeartbeatDecisionType.IDLE; + decision["decision"] = decision_type; + decision["reason"] = + "Suppressed duplicate signal during cooldown or while prior task is still active"; + } else { + const task_prompt = + decision["prompt"] || heartbeat["action_prompt_template"] || heartbeat["check_prompt"]; + const task_title = decision["title"] || `Heartbeat: ${heartbeat["name"]}`; + const task = { + title: task_title, + prompt: task_prompt, + working_dir: heartbeat["working_dir"], + schedule_type: ScheduleType.IMMEDIATE, + agent: heartbeat["default_agent"] || DEFAULT_AGENT, + tags: "heartbeat", + }; + const task_id = this.submit_task(makeTaskFromPartial(task)); + if (dedupe_key) { + this.db.upsert_heartbeat_dedup(hid, dedupe_key, task_id); + } + this.db.update_heartbeat(hid, { + next_run_at, + last_tick_at: dateToLocalIso(now), + last_decision: decision_type, + last_error: null, + last_triggered_at: dateToLocalIso(now), + last_dedupe_key: dedupe_key, + }); + this.db.finish_heartbeat_tick( + tick_id, + "triggered", + decision_type, + decision, + task_id, + output_chunks.length ? output_chunks.join("").slice(0, 500000) : null, + ); + return; + } + } + this.db.update_heartbeat(hid, { + next_run_at, + last_tick_at: dateToLocalIso(now), + last_decision: decision_type, + last_error: null, + last_dedupe_key: (decision["dedupe_key"] || heartbeat["last_dedupe_key"]) ?? null, + }); + this.db.finish_heartbeat_tick( + tick_id, + decision_type === HeartbeatDecisionType.IDLE ? "idle" : decision_type, + decision_type, + decision, + null, + output_chunks.length ? output_chunks.join("").slice(0, 500000) : null, + ); + } catch (e) { + logger.error(`Heartbeat ${hid} failed: ${errStr(e)}`); + this.db.update_heartbeat(hid, { + next_run_at, + last_tick_at: dateToLocalIso(now), + last_decision: HeartbeatDecisionType.ERROR, + last_error: errStr(e), + }); + this.db.finish_heartbeat_tick( + tick_id, + "error", + HeartbeatDecisionType.ERROR, + null, + null, + output_chunks.length ? output_chunks.join("").slice(0, 500000) : null, + errStr(e), + ); + } finally { + this._live_heartbeat_output.delete(tick_id); + this._active_heartbeats.delete(hid); + } + } + + /** Return only the newly emitted text for a cumulative Codex message item. */ + _codex_text_delta(run_id: number | null, item_id: string, current_text: string): string | null { + const key = tupleKey(run_id, item_id); + const previous = this._codex_item_text.get(key) ?? ""; + this._codex_item_text.set(key, current_text); + if (!current_text) { + return null; + } + if (previous && current_text.startsWith(previous)) { + const delta = current_text.slice(previous.length); + return delta || null; + } + if (current_text === previous) { + return null; + } + return current_text; + } + + _codex_append_text_delta(run_id: number | null, item_id: string, delta: string): string | null { + if (delta === "") { + return null; + } + const key = tupleKey(run_id, item_id); + this._codex_item_text.set(key, (this._codex_item_text.get(key) ?? "") + delta); + return delta; + } + + _codex_event_delta_text(event: Row, item: Row): string | null { + const delta = item["delta"] !== undefined ? item["delta"] : event["delta"]; + if (typeof delta === "string") { + return delta; + } + if (delta && typeof delta === "object" && !Array.isArray(delta)) { + const text = delta["text"]; + return typeof text === "string" ? text : null; + } + return null; + } + + _clear_codex_run_state(run_id: number): void { + for (const key of [...this._codex_item_text.keys()]) { + if ((JSON.parse(key) as [number | null, string])[0] === run_id) { + this._codex_item_text.delete(key); + } + } + } + + _extract_codex_thread_id(raw_stdout: string): string | null { + for (let line of raw_stdout.split("\n")) { + line = line.trim(); + if (!line) continue; + let event: any; + try { + event = JSON.parse(line); + } catch { + continue; + } + if (event?.type === "thread.started" && event?.thread_id) { + return String(event.thread_id); + } + } + return null; + } + + _codex_generated_images_root(): string { + const codex_home = + process.env.CODEX_HOME || path.join(process.env.HOME || os.homedir(), ".codex"); + return path.join(expanduser(codex_home), "generated_images"); + } + + _find_codex_generated_images( + thread_id: string | null, + since_timestamp: number | null = null, + ): string[] { + if (!thread_id) { + return []; + } + const image_dir = path.join(this._codex_generated_images_root(), thread_id); + let isDir = false; + try { + isDir = fs.statSync(image_dir).isDirectory(); + } catch { + isDir = false; + } + if (!isDir) { + return []; + } + const paths: string[] = []; + let entries: string[]; + try { + entries = (fs.readdirSync(image_dir, { recursive: true }) as Array).map( + (e) => String(e), + ); + } catch { + return []; + } + for (const rel of entries) { + const p = path.join(image_dir, rel); + let st: fs.Stats; + try { + st = fs.statSync(p); + } catch { + continue; + } + if ( + !st.isFile() || + GENERATED_IMAGE_MEDIA_TYPES[path.extname(p).toLowerCase()] === undefined + ) { + continue; + } + if (since_timestamp !== null) { + if (st.mtimeMs / 1000 < since_timestamp) { + continue; + } + } + paths.push(p); + } + return paths.sort(); + } + + _image_media_type(image_path: string): string { + return GENERATED_IMAGE_MEDIA_TYPES[path.extname(image_path).toLowerCase()] ?? "image/png"; + } + + _extract_codex_success_output( + raw_stdout: string, + generated_images: string[] | null = null, + ): string { + let out = ""; + for (let line of raw_stdout.split("\n")) { + line = line.trim(); + if (!line) continue; + let event: any; + try { + event = JSON.parse(line); + } catch { + continue; + } + if (event?.type === "item.completed" && event?.item?.type === "agent_message") { + out = event.item.text ?? ""; + } + } + + const parts: string[] = []; + if (out.trim()) { + parts.push(out.trim()); + } + if (generated_images && generated_images.length) { + const image_lines = generated_images.map((p) => `- ${p}`).join("\n"); + parts.push(`已生成 ${generated_images.length} 张图片:\n${image_lines}`); + } + return parts.join("\n\n"); + } + + _store_generated_image_events(task_id: number, run_id: number, generated_images: string[]): void { + for (const image_path of generated_images) { + const media_type = this._image_media_type(image_path); + const metadata = { path: image_path, media_type }; + this._store_output_event(task_id, run_id, "generated_image", this._trace_json(metadata)); + let image_data: string; + try { + image_data = fs.readFileSync(image_path).toString("base64"); + } catch (e) { + logger.warning(`Task ${task_id}: failed to read generated image ${image_path}: ${errStr(e)}`); + continue; + } + this.db.add_output_event( + task_id, + run_id, + "image_content", + JSON.stringify({ ...metadata, data: image_data }), + ); + } + } + + /** Return newly emitted text for Claude partial/cumulative assistant messages. */ + _claude_text_delta( + run_id: number | null, + message_id: string, + current_text: string, + ): string | null { + const key = tupleKey(run_id, message_id); + const previous = this._claude_message_text.get(key) ?? ""; + if (!current_text) { + return null; + } + + if (!previous) { + this._claude_message_text.set(key, current_text); + return current_text; + } + + if (current_text === previous) { + return null; + } + + if (current_text.startsWith(previous)) { + this._claude_message_text.set(key, current_text); + const delta = current_text.slice(previous.length); + return delta || null; + } + + // Claude can emit either cumulative partial messages or text chunks. For + // same-message non-cumulative chunks, keep our own accumulated state. + this._claude_message_text.set(key, previous + current_text); + return current_text; + } + + _claude_message_id(event: Row, run_id: number | null): string { + const message = event["message"] ?? {}; + if (message && typeof message === "object" && !Array.isArray(message)) { + const message_id = message["id"] || message["message_id"]; + if (message_id) { + return String(message_id); + } + } + return `assistant:${run_id}`; + } + + _clear_claude_run_state(run_id: number): void { + for (const key of [...this._claude_message_text.keys()]) { + if ((JSON.parse(key) as [number | null, string])[0] === run_id) { + this._claude_message_text.delete(key); + } + } + } + + _redact_display_payload(value: any): any { + if (Array.isArray(value)) { + return value.map((item) => this._redact_display_payload(item)); + } + if (value && typeof value === "object") { + const redacted: Row = {}; + for (const [key, child] of Object.entries(value)) { + const key_str = String(key).toLowerCase(); + if (SECRET_KEY_FRAGMENTS.some((fragment) => key_str.includes(fragment))) { + redacted[key] = "[redacted]"; + } else { + redacted[key] = this._redact_display_payload(child); + } + } + return redacted; + } + return value; + } + + _compact_payload(payload: Row): Row { + const out: Row = {}; + for (const [key, value] of Object.entries(payload)) { + if (value !== null && value !== undefined) { + out[key] = value; + } + } + return out; + } + + _trace_json(payload: Row): string { + return JSON.stringify(this._redact_display_payload(payload)); + } + + _content_to_display_text(content: any): string { + if (content === null || content === undefined) { + return ""; + } + if (typeof content === "string") { + return content; + } + if (Array.isArray(content)) { + const parts: string[] = []; + for (const item of content) { + if (typeof item === "string") { + parts.push(item); + } else if (item && typeof item === "object" && item.type === "text") { + parts.push(item.text ?? ""); + } else if (item && typeof item === "object" && item.type === "image") { + parts.push("[image]"); + } else { + parts.push(JSON.stringify(this._redact_display_payload(item))); + } + } + return parts.join(""); + } + if (typeof content === "object") { + if (content.type === "text") { + return content.text ?? ""; + } + return JSON.stringify(this._redact_display_payload(content)); + } + return String(content); + } + + _should_stream_event(event_type: string): boolean { + return LIVE_OUTPUT_EVENT_TYPES.has(event_type); + } + + _store_output_event(task_id: number, run_id: number, event_type: string, content: string): void { + if (!content) { + return; + } + this.db.add_output_event(task_id, run_id, event_type, content); + if (this._should_stream_event(event_type)) { + this._fire_output_listeners(task_id, run_id, event_type, content); + } + } + + /** + * Normalize a Codex JSONL event into (event_type, content) for storage. + * + * Returns (null, null) to skip events that carry no displayable content. + */ + _parse_codex_event(event: Row, run_id: number | null = null): [string | null, string | null] { + const etype: string = event["type"] ?? ""; + if (etype === "item.updated" || etype === "item.completed") { + const item: Row = event["item"] ?? {}; + const itype: string = item["type"] ?? ""; + if (itype === "agent_message") { + const item_id = String(item["id"] || item["item_id"] || "agent_message"); + const event_delta = this._codex_event_delta_text(event, item); + let delta: string | null; + if (etype === "item.updated" && event_delta !== null) { + delta = this._codex_append_text_delta(run_id, item_id, event_delta); + } else { + delta = this._codex_text_delta(run_id, item_id, item["text"] ?? ""); + } + return delta !== null ? ["assistant", delta] : [null, null]; + } else if (itype === "reasoning") { + const item_id = String(item["id"] || item["item_id"] || "reasoning"); + const event_delta = this._codex_event_delta_text(event, item); + let text: string; + if (etype === "item.updated" && event_delta !== null) { + text = this._codex_append_text_delta(run_id, item_id, event_delta) || ""; + } else { + text = this._codex_text_delta(run_id, item_id, item["text"] ?? "") || ""; + } + return text ? ["assistant", `[thinking] ${text}`] : [null, null]; + } else if (itype === "command_execution") { + return [ + "command_execution", + this._trace_json( + this._compact_payload({ + id: item["id"] ?? item["item_id"], + command: item["command"] ?? "", + output: item["aggregated_output"] ?? "", + exit_code: item["exit_code"], + status: item["status"], + }), + ), + ]; + } else if (itype === "mcp_tool_call" || itype === "collab_tool_call") { + return [ + "tool_call", + this._trace_json( + this._compact_payload({ + id: item["id"] ?? item["item_id"], + server: item["server"], + name: item["tool"] ?? item["name"], + input: item["arguments"] ?? item["input"], + result: item["result"], + status: item["status"], + error: item["error"], + }), + ), + ]; + } else if (itype === "web_search") { + return [ + "web_search", + this._trace_json( + this._compact_payload({ + id: item["id"] ?? item["item_id"], + query: item["query"], + action: item["action"], + status: item["status"], + }), + ), + ]; + } else if (itype === "file_change") { + return [ + "file_change", + this._trace_json( + this._compact_payload({ + id: item["id"] ?? item["item_id"], + changes: item["changes"], + status: item["status"], + }), + ), + ]; + } else { + return [etype, JSON.stringify(event)]; + } + } else if (etype === "turn.failed") { + const err = event["error"] ?? {}; + const msg = + err && typeof err === "object" && !Array.isArray(err) + ? (err["message"] ?? "") + : String(err); + return ["error", msg]; + } else if (etype === "error") { + return ["error", event["message"] ?? ""]; + } else if (etype === "turn.completed") { + // turn.completed only carries usage stats; final text comes from agent_message items + return [null, null]; + } else if (etype === "thread.started" || etype === "turn.started" || etype === "item.started") { + return [null, null]; + } else { + return [etype, JSON.stringify(event)]; + } + } + + /** Parse a line from the output stream and store it as an event. */ + _parse_and_store_event(task_id: number, run_id: number, line: string, agent: string = "claude") { + if (!line.trim()) { + return; + } + + let event: any; + try { + event = JSON.parse(line); + } catch { + // If it's not valid JSON, store as raw text + if (line.trim() && line.trim().length > 10) { + // Only store meaningful non-JSON lines + this.db.add_output_event(task_id, run_id, "text", line.trim()); + } + return; + } + + if (agent === "codex") { + const [event_type, content] = this._parse_codex_event(event, run_id); + if (event_type && content) { + this._store_output_event(task_id, run_id, event_type, content); + } + return; + } + + // Claude stream-json + const event_type: string = event?.type ?? "unknown"; + if (event_type === "assistant") { + const [text0, image_events, trace_events] = this._extract_message_content(event); + let text_content: string | null = text0; + if (text_content) { + const message_id = this._claude_message_id(event, run_id); + text_content = this._claude_text_delta(run_id, message_id, text_content); + } + if (text_content) { + this._store_output_event(task_id, run_id, event_type, text_content); + } + for (const img_json of image_events) { + this.db.add_output_event(task_id, run_id, "image_content", img_json); + } + for (const [trace_type, trace_content] of trace_events) { + this._store_output_event(task_id, run_id, trace_type, trace_content); + } + } else if (event_type === "user") { + const [text_content, image_events, trace_events] = this._extract_message_content(event); + if (text_content) { + this.db.add_output_event(task_id, run_id, event_type, text_content); + } + for (const img_json of image_events) { + this.db.add_output_event(task_id, run_id, "image_content", img_json); + } + for (const [trace_type, trace_content] of trace_events) { + this._store_output_event(task_id, run_id, trace_type, trace_content); + } + } else { + let content = ""; + if (event_type === "result") { + content = event?.result ?? ""; + } else if (event_type === "error") { + content = event?.error ?? ""; + } else { + // For other event types, store the full JSON + content = JSON.stringify(event); + } + + if (content) { + this._store_output_event(task_id, run_id, event_type, content); + } + } + } + + /** + * Extract text and image content from user/assistant messages. + * + * Returns (text, image_events, trace_events), where image_events and + * trace_events contain already serialized display payloads. + */ + _extract_message_content(event: Row): [string, string[], Array<[string, string]>] { + const message = event["message"] ?? {}; + const content = message["content"] ?? []; + const text_parts: string[] = []; + const image_events: string[] = []; + const trace_events: Array<[string, string]> = []; + + for (const item of content) { + if (typeof item === "string") { + text_parts.push(item); + } else if (item && typeof item === "object" && !Array.isArray(item)) { + if (item.type === "text") { + text_parts.push(item.text ?? ""); + } else if (item.type === "image") { + const source = item.source ?? {}; + if (source.type === "base64") { + const img_json = JSON.stringify({ + media_type: source.media_type ?? "image/jpeg", + data: source.data ?? "", + }); + image_events.push(img_json); + } + // Non-base64 image sources (url, etc.) are ignored silently + } else if (item.type === "tool_use") { + trace_events.push([ + "tool_call", + this._trace_json( + this._compact_payload({ + id: item.id, + name: item.name, + input: item.input, + }), + ), + ]); + } else if (item.type === "tool_result") { + trace_events.push([ + "tool_result", + this._trace_json( + this._compact_payload({ + tool_use_id: item.tool_use_id, + content: this._content_to_display_text(item.content), + is_error: item.is_error ?? false, + }), + ), + ]); + } + } + } + + return [text_parts.join(""), image_events, trace_events]; + } + + /** + * Extract a clean, human-readable error summary from raw CLI output. + * + * The full raw output is already stored in run.raw_output; this produces + * a concise message for task.error and notification channels. + */ + _extract_error_summary(raw_stderr: string, raw_stdout: string): string { + // If stderr is short and not JSON, it's likely a plain error message + if (raw_stderr && raw_stderr.length < 2000) { + const first_line = (raw_stderr.trim().split("\n")[0] ?? "").trim(); + if (first_line && !first_line.startsWith("{")) { + return raw_stderr.trim().slice(0, 1000); + } + } + + // Try to parse stdout as stream-json to find error events + const error_messages: string[] = []; + let last_assistant_text = ""; + const source = raw_stdout ? raw_stdout : raw_stderr; + for (let line of source.split("\n")) { + line = line.trim(); + if (!line) continue; + try { + const event = JSON.parse(line); + const event_type = event?.type ?? ""; + if (event_type === "error") { + const err = event.error ?? ""; + if (err) { + error_messages.push(err); + } + } else if (event_type === "result") { + if (event.subtype === "error_during_execution") { + const err = event.error ?? event.result ?? ""; + if (err) { + error_messages.push(String(err)); + } + } + } else if (event_type === "assistant") { + const msg = event.message ?? {}; + const content = msg.content ?? []; + const text_parts: string[] = []; + for (const c of content) { + if (typeof c === "string") { + text_parts.push(c); + } else if (c && typeof c === "object" && c.type === "text") { + text_parts.push(c.text ?? ""); + } + } + if (text_parts.length) { + last_assistant_text = text_parts.join(""); + } + } + } catch { + // not JSON — keep scanning + } + } + + if (error_messages.length) { + return error_messages.join("\n").slice(0, 1000); + } + + if (last_assistant_text) { + return last_assistant_text.slice(0, 1000); + } + + // Fall back to raw stderr or first 500 chars of stdout + return (raw_stderr || raw_stdout || "Unknown error").trim().slice(0, 500); + } + + async _execute_task(task: Row): Promise { + const tid: number = task["id"]; + this._live_output.set(tid, ""); + // Status already set to "running" by _spawn_task() before thread start. + this._notify(tid); + + const run_id = this.db.add_run(tid); + + // Build command — inject upstream results if configured + const prompt = this._build_injected_prompt(task); + const prompt_images: Row[] = task["prompt_images"] || []; + const image_paths: string[] = task["image_paths"] || []; // List of local image file paths + + // Convert image_paths to prompt_images format (base64 encoded) + if (image_paths.length && !prompt_images.length) { + // Only if not already using prompt_images + const _ALLOWED_IMAGE_ROOTS = [expanduser("~"), "/tmp"]; + + /** Return true only if path resolves inside an allowed directory. */ + const _is_safe_image_path = (p: string): boolean => { + let resolved: string; + try { + resolved = realpathNonStrict(path.resolve(p)); + } catch { + return false; + } + for (const root of _ALLOWED_IMAGE_ROOTS) { + try { + const resolved_root = realpathNonStrict(root); + if (resolved.startsWith(resolved_root + path.sep) || resolved === resolved_root) { + return true; + } + } catch { + continue; + } + } + return false; + }; + + for (const img_path of image_paths) { + if (!_is_safe_image_path(img_path)) { + logger.warning( + `Task ${tid}: Rejected image path outside allowed directories: ${img_path}`, + ); + continue; + } + try { + const buf = fs.readFileSync(img_path); + const img_data = buf.toString("base64"); + + // Detect media type from file extension + const img_path_lower = img_path.toLowerCase(); + let media_type: string; + if (img_path_lower.endsWith(".png")) { + media_type = "image/png"; + } else if (img_path_lower.endsWith(".jpg") || img_path_lower.endsWith(".jpeg")) { + media_type = "image/jpeg"; + } else if (img_path_lower.endsWith(".gif")) { + media_type = "image/gif"; + } else if (img_path_lower.endsWith(".webp")) { + media_type = "image/webp"; + } else { + // Try to detect from magic bytes + const header = buf.subarray(0, 12); + if (header.length >= 3 && header[0] === 0xff && header[1] === 0xd8 && header[2] === 0xff) { + media_type = "image/jpeg"; + } else if ( + header.length >= 8 && + header.subarray(0, 8).equals(Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])) + ) { + media_type = "image/png"; + } else if ( + header.subarray(0, 6).toString("latin1") === "GIF87a" || + header.subarray(0, 6).toString("latin1") === "GIF89a" + ) { + media_type = "image/gif"; + } else if ( + header.subarray(0, 4).toString("latin1") === "RIFF" && + header.toString("latin1").includes("WEBP") + ) { + media_type = "image/webp"; + } else { + media_type = "image/jpeg"; // default fallback + } + } + + prompt_images.push({ + media_type, + data: img_data, + name: path.basename(img_path), + }); + logger.debug( + `Task ${tid}: Loaded image ${img_path} as ${media_type} (${img_data.length} bytes base64)`, + ); + } catch (e) { + logger.error(`Task ${tid}: Failed to load image ${img_path}: ${errStr(e)}`); + } + } + } + + const agent: string = task["agent"] || DEFAULT_AGENT; + const use_stdin = prompt_images.length > 0 && agent === "claude"; + + let cmd: string[]; + if (agent === "codex") { + const working_dir_expanded = expanduser(task["working_dir"]); + if (task["session_id"]) { + cmd = [ + "codex", + "exec", + "resume", + "--json", + "--dangerously-bypass-approvals-and-sandbox", + "--skip-git-repo-check", + task["session_id"], + prompt, + ]; + } else { + cmd = [ + "codex", + "exec", + "--json", + "--dangerously-bypass-approvals-and-sandbox", + "--skip-git-repo-check", + "--cd", + working_dir_expanded, + prompt, + ]; + } + for (const img_path of image_paths) { + cmd.push("--image", img_path); + } + } else if (use_stdin) { + // Claude multimodal input: pass via stdin with --input-format stream-json + cmd = ["claude", "-p", "--input-format", "stream-json", ...CLAUDE_STREAM_JSON_ARGS]; + } else { + cmd = ["claude", "-p", prompt, ...CLAUDE_STREAM_JSON_ARGS]; + } + if (agent === "claude" && task["session_id"]) { + cmd.push("--resume", task["session_id"]); + } + let raw_stdout = ""; + let raw_stderr = ""; + // Initialized before the try so the failure branch can read it even when + // Popen itself raises (e.g. CLI not found) before the timer is armed. + const timed_out = { value: false }; + let success = false; + let output = ""; + try { + const timeout_secs = parseInt( + this.db.get_setting("timeout", String(DEFAULT_TIMEOUT_SECONDS)) ?? + String(DEFAULT_TIMEOUT_SECONDS), + 10, + ); + const start_time = Date.now() / 1000; + const proc = await this._popen(cmd, { + stdin: use_stdin ? PIPE : null, + stdout: PIPE, + stderr: PIPE, + cwd: expanduser(task["working_dir"]), + env: getEnv(), + start_new_session: true, // Create a new process group so all sub-agents are tracked + }); + if (use_stdin) { + // Build multimodal message content + const content: Row[] = [{ type: "text", text: prompt }]; + for (const img of prompt_images) { + content.push({ + type: "image", + source: { + type: "base64", + media_type: img["media_type"] ?? "image/jpeg", + data: img["data"] ?? "", + }, + }); + } + const stdin_msg = JSON.stringify({ + type: "user", + message: { role: "user", content }, + }); + proc.stdin!.write(stdin_msg + "\n"); + proc.stdin!.close(); + } + const pgid = this._os.getpgid(proc.pid); + this._active_pgids.set(tid, pgid); + + // Read stderr concurrently so it never blocks stdout reading + const stderr_chunks: string[] = []; + const stderr_promise = (async () => { + for await (const line of proc.stderr) { + stderr_chunks.push(line); + } + })().catch(() => {}); + + // Timer that kills the entire process group if it exceeds the configured timeout + const _kill = (): void => { + timed_out.value = true; + try { + this._os.killpg(pgid, "SIGKILL"); + } catch (e) { + logger.error( + `Task ${tid}: killpg(${pgid}) failed: ${errStr(e)}, falling back to kill(${proc.pid})`, + ); + try { + this._os.kill(proc.pid, "SIGKILL"); + } catch (e2) { + logger.error(`Task ${tid}: kill(${proc.pid}) also failed: ${errStr(e2)}`); + } + } + }; + + const timer = setTimeout(_kill, timeout_secs * 1000); + + const chunks: string[] = []; + try { + for await (const line of proc.stdout) { + chunks.push(line); + this._live_output.set(tid, chunks.join("")); + // Parse and store each line as an event + this._parse_and_store_event(tid, run_id, line, agent); + } + await proc.wait(); + } finally { + clearTimeout(timer); + } + await joinWithTimeout(stderr_promise, 2); + + // Wait for any sub-agents still running in the process group. + // Claude Code may spawn background Task agents that outlive the main process. + if (!timed_out.value && proc.returncode === 0) { + const elapsed = Date.now() / 1000 - start_time; + const remaining = Math.max(0, timeout_secs - elapsed); + const subagent_deadline = Date.now() / 1000 + remaining; + let waiting_logged = false; + let broke = false; + while (Date.now() / 1000 < subagent_deadline) { + try { + this._os.killpg(pgid, 0); // raises ProcessLookupError when group is gone + } catch (e) { + if (e instanceof ProcessLookupError) { + broke = true; + break; + } + throw e; + } + if (!waiting_logged) { + waiting_logged = true; + logger.info(`Task ${tid}: main process exited, waiting for sub-agents...`); + } + this._live_output.set( + tid, + chunks.join("") + "\n[⏳ Waiting for sub-agents to complete...]", + ); + await this._sleep(1); + } + if (!broke) { + // Sub-agents exceeded remaining timeout — kill the group + timed_out.value = true; + try { + this._os.killpg(pgid, "SIGKILL"); + } catch (e) { + logger.error(`Task ${tid}: killpg(${pgid}) on sub-agent timeout failed: ${errStr(e)}`); + } + } + } + + this._active_pgids.delete(tid); + + raw_stdout = chunks.join(""); + raw_stderr = stderr_chunks.join(""); + + if (timed_out.value) { + success = false; + output = `Task timed out after ${timeout_secs}s`; + } else if (proc.returncode === 0) { + if (agent === "codex") { + const thread_id = this._extract_codex_thread_id(raw_stdout); + const generated_images = this._find_codex_generated_images(thread_id, start_time); + if (generated_images.length) { + this._store_generated_image_events(tid, run_id, generated_images); + } + success = true; + output = this._extract_codex_success_output(raw_stdout, generated_images); + } else { + // Claude stream-json: find the last result event and last assistant text + let out = ""; + let last_assistant_text = ""; + for (let line of raw_stdout.split("\n")) { + line = line.trim(); + if (!line) continue; + try { + const event = JSON.parse(line); + if (event?.type === "assistant") { + const msg = event.message ?? {}; + const content = msg.content ?? []; + const text_parts: string[] = []; + for (const c of content) { + if (typeof c === "string") { + text_parts.push(c); + } else if (c && typeof c === "object" && c.type === "text") { + text_parts.push(c.text ?? ""); + } + } + if (text_parts.length) { + last_assistant_text = text_parts.join(""); + } + } else if (event?.type === "result") { + const result_text = event.result; + if (result_text) { + out = result_text; + } + } + } catch { + // not JSON — keep scanning + } + } + // If result event had no result field (e.g. error_during_execution + // with 0 output tokens), fall back to last assistant message text + if (!out) { + out = last_assistant_text; + } + success = true; + output = out; + } + } else { + success = false; + output = raw_stderr || raw_stdout; + } + } catch (e) { + if (e instanceof FileNotFoundError) { + const cli_name = task["agent"] === "codex" ? "codex" : "claude"; + const install_hint = + cli_name === "codex" ? "Install with: npm install -g @openai/codex" : "Is it installed?"; + success = false; + output = `${cli_name} CLI not found. ${install_hint}`; + this._active_pgids.delete(tid); + } else { + logger.error(`Task ${tid} subprocess error: ${errStr(e)}`); + success = false; + output = errStr(e); + this._active_pgids.delete(tid); + } + } + + this._live_output.delete(tid); + if (agent === "codex") { + this._clear_codex_run_state(run_id); + } else if (agent === "claude") { + this._clear_claude_run_state(run_id); + } + + // Extract session_id from output (format differs by agent) + let extracted_session_id: string | null = null; + if (agent === "codex") { + // Codex emits session_id in the thread.started event at the beginning + extracted_session_id = this._extract_codex_thread_id(raw_stdout); + } else { + // Claude emits session_id in the result event at the end + for (let line of raw_stdout.split("\n").reverse()) { + line = line.trim(); + if (!line) continue; + try { + const event = JSON.parse(line); + if (event?.type === "result" && event?.session_id) { + extracted_session_id = event.session_id; + break; + } + } catch { + // not JSON — keep scanning + } + } + } + + // Truncate raw_output for storage (max 500KB) + const raw_output_stored = raw_stdout ? raw_stdout.slice(0, 500000) : null; + + const new_count = (task["run_count"] || 0) + 1; + if (success) { + const updates: Row = { + result: output.slice(0, 50000), // truncate for storage + last_run_at: nowIso(), + run_count: new_count, + }; + if (extracted_session_id) { + updates["session_id"] = extracted_session_id; + } + // Handle cron rescheduling + let cron_will_reschedule = false; + if (task["schedule_type"] === "cron" && task["cron_expr"]) { + const max_runs = task["max_runs"]; + if (max_runs && new_count >= max_runs) { + updates["status"] = "completed"; + } else { + updates["status"] = "scheduled"; + updates["next_run_at"] = cron_next_iso(task["cron_expr"], new Date()); + cron_will_reschedule = true; + } + } else { + updates["status"] = "completed"; + } + this.db.finish_run_and_update_task( + run_id, + "completed", + tid, + updates, + output, + null, + raw_output_stored, + ); + // For cron tasks that get rescheduled, notify channels with TASK_COMPLETED + // before the status flips to "scheduled", so channels actually fire. + if (cron_will_reschedule) { + this._bus_notify(tid, OutboundMessageType.TASK_COMPLETED); + } + } else { + // Extract a clean, human-readable error summary for task.error and + // notification channels. The full raw output is preserved in run_error. + let error_summary: string; + if (timed_out.value) { + // The timeout IS the reason — don't let an unrelated stderr line + // (e.g. codex's "Reading additional input from stdin…") mask it. + error_summary = output; + } else { + error_summary = + raw_stderr || raw_stdout + ? this._extract_error_summary(raw_stderr, raw_stdout) + : output || "Unknown error"; + } + const updates: Row = { + status: "failed", + error: error_summary, + last_run_at: nowIso(), + run_count: new_count, + }; + // Persist the conversation id even on failure so the task stays + // resumable (e.g. replying in a Feishu/Slack/Telegram thread to + // retry). Codex emits thread_id in the opening thread.started event, + // so even a started-then-failed run has one to recover. + if (extracted_session_id) { + updates["session_id"] = extracted_session_id; + } + this.db.finish_run_and_update_task( + run_id, + "failed", + tid, + updates, + null, + output, + raw_output_stored, + ); + } + + this._notify(tid); + this._active_tasks.delete(tid); + + // DAG: trigger downstream cascade after task finishes + if (success) { + this._on_task_completed(tid); + } else { + this._on_task_failed(tid); + } + } + + /** Fire all registered output listeners (non-blocking; errors are swallowed). */ + _fire_output_listeners( + task_id: number, + run_id: number, + event_type: string, + content: string, + ): void { + const listeners = [...this._output_event_listeners]; + for (const cb of listeners) { + try { + cb(task_id, run_id, event_type, content); + } catch (e) { + logger.error(`Output listener error: ${errStr(e)}`); + } + } + } + + /** + * Register a callback invoked for each assistant output event. + * + * Signature: cb(task_id: int, run_id: int, event_type: str, content: str) + * Called from the task execution path — must be non-blocking. + */ + add_output_listener(cb: OutputListener): void { + this._output_event_listeners.push(cb); + } + + remove_output_listener(cb: OutputListener): void { + const idx = this._output_event_listeners.indexOf(cb); + if (idx !== -1) { + this._output_event_listeners.splice(idx, 1); + } + } + + _notify(task_id: number): void { + if (this.on_task_update) { + this.on_task_update(task_id); + } + for (const ch of this._channels) { + // ≙ a daemon thread per channel notify + setTimeout(() => { + try { + ch.notify_task(task_id); + } catch (e) { + logger.error(`Channel notify error: ${errStr(e)}`); + } + }, 0); + } + // Publish to MessageBus (non-blocking; subscribers notified synchronously) + this._bus_notify(task_id); + } + + /** + * Add and schedule a new task. + * + * depends_on: list of dicts [{task_id, inject_result}] or list of ints. + * If any upstream task is not yet completed, the task starts as BLOCKED. + */ + submit_task(task: Task, depends_on: DependsOn[] | null = null): number { + const now = new Date(); + + // Resolve depends_on to normalized list + const dep_list: Array<{ task_id: number; inject_result: boolean }> = []; + if (depends_on) { + for (const dep of depends_on) { + if (typeof dep === "number") { + dep_list.push({ task_id: dep, inject_result: false }); + } else if (dep && typeof dep === "object") { + dep_list.push({ + task_id: dep.task_id, + inject_result: Boolean(dep.inject_result ?? false), + }); + } + } + } + + // Determine initial status: BLOCKED if any upstream not completed + let has_unmet = false; + if (dep_list.length) { + for (const dep of dep_list) { + const upstream = this.db.get_task(dep.task_id); + if (!upstream || upstream["status"] !== "completed") { + has_unmet = true; + break; + } + } + } + + if (has_unmet) { + task.status = TaskStatus.BLOCKED; + } else if (task.schedule_type === ScheduleType.IMMEDIATE) { + task.status = TaskStatus.PENDING; + } else if (task.schedule_type === ScheduleType.DELAYED) { + task.status = TaskStatus.PENDING; + } else if (task.schedule_type === ScheduleType.SCHEDULED_AT) { + task.status = TaskStatus.SCHEDULED; + if (!task.next_run_at) { + throw new Error("scheduled_at requires next_run_at to be set"); + } + task.next_run_at = normalizeDatetimeForStorage(task.next_run_at); + } else if (task.schedule_type === ScheduleType.CRON) { + task.status = TaskStatus.SCHEDULED; + if (task.cron_expr) { + task.next_run_at = cron_next_iso(task.cron_expr, now); + } + } + + const task_id = this.db.add_task(task); + + // Store dependency rows atomically — if any insert fails the whole + // batch is rolled back so we never leave a task with partial deps. + if (dep_list.length) { + this.db.add_dependencies_batch(task_id, dep_list); + } + + return task_id; + } + + // ──────────────────────── DAG helpers ──────────────────────── + + /** Prepend upstream results to the prompt for deps with inject_result=True. */ + _build_injected_prompt(task: Row): string { + const deps = this.db.get_dependencies(task["id"]); + const injections: string[] = []; + for (const dep of deps) { + if (dep["inject_result"]) { + const upstream = this.db.get_task(dep["depends_on_task_id"]); + if (upstream && upstream["result"]) { + injections.push( + `=== Result from upstream task #${upstream["id"]} (${upstream["title"]}) ===\n` + + `${upstream["result"]}\n` + + `=== End of upstream result ===`, + ); + } + } + } + if (injections.length) { + return injections.join("\n\n") + "\n\n---\n\n" + task["prompt"]; + } + return task["prompt"]; + } + + /** Check whether any blocked downstream tasks can now be unblocked. */ + _on_task_completed(task_id: number): void { + const dependents = this.db.get_dependents(task_id); + for (const dep of dependents) { + const downstream_id = dep["task_id"]; + if (dep["task_status"] !== "blocked") { + continue; + } + // Check all upstream deps of this downstream task + const all_deps = this.db.get_dependencies(downstream_id); + if (all_deps.every((d) => d["depends_on_status"] === "completed")) { + // All upstream done — unblock + const downstream = this.db.get_task(downstream_id); + if (!downstream) { + continue; + } + // Determine next status based on schedule_type + const stype = downstream["schedule_type"] ?? "immediate"; + let new_status: string; + if (stype === "immediate") { + new_status = "pending"; + } else if (stype === "delayed") { + new_status = "pending"; + } else if (stype === "scheduled_at") { + new_status = "scheduled"; + } else if (stype === "cron") { + new_status = "scheduled"; + } else { + new_status = "pending"; + } + this.db.update_task(downstream_id, { status: new_status }); + logger.info(`DAG: Task ${downstream_id} unblocked (all upstream done)`); + this._notify(downstream_id); + } + } + } + + /** Cascade-cancel all blocked downstream tasks recursively. */ + _on_task_failed(task_id: number): void { + const to_cancel: Array<[number, number]> = []; + const visited = new Set(); + const queue: number[] = [task_id]; + while (queue.length) { + const current = queue.pop()!; + for (const dep of this.db.get_dependents(current)) { + const downstream_id = dep["task_id"]; + if (visited.has(downstream_id)) { + continue; + } + visited.add(downstream_id); + const task_status = dep["task_status"]; + if (["blocked", "pending", "scheduled"].includes(task_status)) { + to_cancel.push([downstream_id, task_id]); + queue.push(downstream_id); + } + } + } + for (const [downstream_id, origin_id] of to_cancel) { + this.db.update_task(downstream_id, { + status: "cancelled", + error: `Cancelled: upstream task #${origin_id} failed`, + }); + logger.info(`DAG: Task ${downstream_id} cascade-cancelled (upstream #${origin_id} failed)`); + this._notify(downstream_id); + } + } + + // ───────────────────────────────────────────────────────────── + + cancel_task(task_id: number): void { + const pgid = this._active_pgids.get(task_id); + if (pgid) { + try { + this._os.killpg(pgid, "SIGKILL"); + } catch (e) { + if (!(e instanceof OSError)) throw e; + // ≙ except OSError: pass + } + } + this.db.update_task(task_id, { status: "cancelled" }); + this._notify(task_id); + } + + retry_task(task_id: number): void { + this.db.update_task(task_id, { status: "pending", error: null }); + this._notify(task_id); + } + + trigger_heartbeat_now(heartbeat_id: number): void { + const heartbeat = this.db.get_heartbeat(heartbeat_id); + if (!heartbeat) { + throw new Error("heartbeat not found"); + } + const handle = this._active_heartbeats.get(heartbeat_id); + if (handle && handle.is_alive()) { + throw new Error("heartbeat already running"); + } + this._spawn_heartbeat(heartbeat); + } + + pause_heartbeat(heartbeat_id: number): void { + const heartbeat = this.db.get_heartbeat(heartbeat_id); + if (!heartbeat) { + throw new Error("heartbeat not found"); + } + this.db.update_heartbeat(heartbeat_id, { enabled: 0 }); + } + + resume_heartbeat(heartbeat_id: number): void { + const heartbeat = this.db.get_heartbeat(heartbeat_id); + if (!heartbeat) { + throw new Error("heartbeat not found"); + } + const next_run_at = this.db._compute_heartbeat_next_run_at( + makeHeartbeat({ + id: heartbeat_id, + name: heartbeat["name"], + enabled: true, + working_dir: heartbeat["working_dir"], + schedule_type: heartbeat["schedule_type"], + cron_expr: heartbeat["cron_expr"] ?? null, + interval_seconds: heartbeat["interval_seconds"] ?? null, + check_prompt: heartbeat["check_prompt"], + action_prompt_template: heartbeat["action_prompt_template"] || "", + default_agent: heartbeat["default_agent"] || DEFAULT_AGENT, + cooldown_seconds: Math.trunc(Number(heartbeat["cooldown_seconds"] || 0)), + }), + new Date(), + ); + this.db.update_heartbeat(heartbeat_id, { enabled: 1, next_run_at }); + } +} + +// Heartbeat-triggered tasks are built from a plain object (≙ Task(**kwargs)). +import { makeTask } from "./types.ts"; + +function makeTaskFromPartial(partial: Partial): Task { + return makeTask(partial); +} diff --git a/backend/src/skills.ts b/backend/src/skills.ts new file mode 100644 index 0000000..eb15f5f --- /dev/null +++ b/backend/src/skills.ts @@ -0,0 +1,179 @@ +// Skill Library: on-disk skill files, ported from taskboard.py (lines 1662-1768). +// +// Canonical SKILL.md lives in an AgentForge-owned dir and is symlinked into +// each agent's native skill dir. Both agents load via their own progressive +// disclosure; enable/disable just adds/removes the two symlinks (canonical kept). + +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import { logger } from "./log.ts"; + +/** + * ≙ Python os.path.expanduser: "~" resolves through $HOME (tests override + * process.env.HOME), falling back to os.homedir(). + */ +export function expanduser(p: string): string { + const home = process.env.HOME || os.homedir(); + if (p === "~") return home; + if (p.startsWith("~/")) return path.join(home, p.slice(2)); + return p; +} + +function islink(p: string): boolean { + try { + return fs.lstatSync(p).isSymbolicLink(); + } catch { + return false; + } +} + +export function _skill_library_dirs(): [string, string, string] { + return [ + expanduser("~/.agentforge/skills"), // canonical (AgentForge-owned) + expanduser("~/.claude/skills"), // claude consumer + expanduser("~/.agents/skills"), // codex consumer + ]; +} + +/** + * Path to the vendored Anthropic skill-creator skill (dev tree or packaged binary). + * + * Python resolves `getattr(sys, "_MEIPASS", dirname(abspath(__file__)))` + + * "vendor/skill-creator": taskboard.py sits at the repo root, so the dev path + * is /vendor/skill-creator, and a PyInstaller binary uses the bundled + * data dir (sys._MEIPASS). + * + * Bun-compile has no _MEIPASS equivalent (no bundled-data dir): inside a + * compiled binary import.meta.dir is a virtual bunfs path, so we fall back to + * a vendor/ dir next to the executable (dirname(process.execPath)) — the + * packager must ship vendor/skill-creator alongside the binary. In the dev + * tree this file lives at backend/src/, so the repo root is two levels up. + */ +export function _skill_creator_dir(): string { + const here = import.meta.dir; + const isCompiled = here.includes("$bunfs") || here.includes("~BUN"); + const base = isCompiled ? path.dirname(process.execPath) : path.resolve(here, "..", ".."); + return path.join(base, "vendor", "skill-creator"); +} + +/** Lowercase kebab slug safe as a directory name (no path traversal). */ +export function _sanitize_skill_name(name: string | null | undefined): string { + name = (name || "").trim().toLowerCase(); + let slug = ""; + for (const ch of name) { + slug += /[\p{L}\p{N}]/u.test(ch) ? ch : "-"; + } + while (slug.includes("--")) { + slug = slug.replace("--", "-"); + } + return slug.replace(/^-+|-+$/g, ""); +} + +/** Create/refresh the claude + codex symlinks pointing at the canonical dir. */ +export function link_skill(name: string): string[] { + const [canonical_root, claude_root, agents_root] = _skill_library_dirs(); + const skill_dir = path.join(canonical_root, name); + const links: string[] = []; + for (const root of [claude_root, agents_root]) { + fs.mkdirSync(root, { recursive: true }); + const link = path.join(root, name); + if (islink(link)) { + fs.unlinkSync(link); + } + if (!fs.existsSync(link)) { + try { + fs.symlinkSync(skill_dir, link, "dir"); + } catch (e) { + logger.warning(`symlink ${link} failed: ${e instanceof Error ? e.message : e}`); + } + } + links.push(link); + } + return links; +} + +/** Remove both consumer symlinks; leave the canonical dir intact. */ +export function unlink_skill(name: string): void { + const [_canonical_root, claude_root, agents_root] = _skill_library_dirs(); + void _canonical_root; + for (const root of [claude_root, agents_root]) { + const link = path.join(root, name); + if (islink(link)) { + try { + fs.unlinkSync(link); + } catch { + // ≙ except OSError: pass + } + } + } +} + +/** Write canonical SKILL.md and create both symlinks. Returns (md_path, dir). */ +export function write_skill_to_disk(name: string, body: string): [string, string] { + const [canonical_root, _claude_root, _agents_root] = _skill_library_dirs(); + void _claude_root; + void _agents_root; + const skill_dir = path.join(canonical_root, name); + fs.mkdirSync(skill_dir, { recursive: true }); + const skill_md = path.join(skill_dir, "SKILL.md"); + fs.writeFileSync(skill_md, body, { encoding: "utf-8" }); + link_skill(name); + return [skill_md, skill_dir]; +} + +/** Remove symlinks and the canonical dir entirely (used on delete). */ +export function remove_skill_from_disk(name: string): void { + unlink_skill(name); + const [canonical_root, _claude_root, _agents_root] = _skill_library_dirs(); + void _claude_root; + void _agents_root; + const skill_dir = path.join(canonical_root, name); + let isDir = false; + try { + isDir = fs.statSync(skill_dir).isDirectory(); + } catch { + isDir = false; + } + if (isDir) { + fs.rmSync(skill_dir, { recursive: true, force: true }); + } +} + +export function _compose_skill_md( + name: string, + description: string | null | undefined, + body_markdown: string | null | undefined, +): string { + const desc = (description || "").replaceAll("\n", " ").trim(); + const body = (body_markdown || "").trim(); + return `---\nname: ${name}\ndescription: ${desc}\n---\n\n${body}\n`; +} + +/** Pull name + description out of a SKILL.md's YAML frontmatter (best-effort). */ +export function _parse_skill_frontmatter(body: string | null | undefined): [string, string] { + let name = ""; + let description = ""; + const text = (body || "").replace(/^\s+/, ""); + if (!text.startsWith("---")) { + return [name, description]; + } + const end = text.indexOf("\n---", 3); + if (end === -1) { + return [name, description]; + } + for (const line of text.slice(3, end).split("\n")) { + const sep = line.indexOf(":"); + if (sep === -1) { + continue; + } + const key = line.slice(0, sep).trim().toLowerCase(); + const val = line.slice(sep + 1).trim(); + if (key === "name" && !name) { + name = val; + } else if (key === "description" && !description) { + description = val; + } + } + return [name, description]; +} From 95cfd0d8a5491ccec742d955edca69bfd5de7c50 Mon Sep 17 00:00:00 2001 From: taohe Date: Sat, 13 Jun 2026 06:38:27 +0800 Subject: [PATCH 15/18] feat(backend): port Slack channel to TypeScript with tests Co-Authored-By: Claude Fable 5 --- backend/src/channels/slack.ts | 1017 +++++++++++++++++++++++++++ backend/tests/slack-channel.test.ts | 620 ++++++++++++++++ backend/tests/slack-more.test.ts | 538 ++++++++++++++ 3 files changed, 2175 insertions(+) create mode 100644 backend/src/channels/slack.ts create mode 100644 backend/tests/slack-channel.test.ts create mode 100644 backend/tests/slack-more.test.ts diff --git a/backend/src/channels/slack.ts b/backend/src/channels/slack.ts new file mode 100644 index 0000000..63be71b --- /dev/null +++ b/backend/src/channels/slack.ts @@ -0,0 +1,1017 @@ +/** + * AgentForge Slack Channel — ported from channels/slack_channel.py. + * + * Listens for @bot mentions and DMs via Slack Socket Mode (no public IP + * required). Send any message to create a task; reply to a completion + * notification to resume. Slash commands (/status, /cancel, /resume) are also + * supported. + * + * Required environment variables: + * SLACK_BOT_TOKEN — xoxb-... bot token + * SLACK_APP_TOKEN — xapp-... app-level token (for Socket Mode) + * + * Porting notes: + * - Python used slack-sdk's WebClient + SocketModeClient. The TS port uses + * @slack/web-api + @slack/socket-mode, wrapped in thin adapters so the + * channel keeps the exact Python calling surface (chat_postMessage, + * reactions_add, conversations_open, auth_test, + * socket_mode_request_listeners, connect/disconnect). Tests inject fake + * client objects with the same surface. + * - Python's lazy `_require_slack()` import guard is mirrored: the dynamic + * import goes through the `_hooks.import_slack` test seam and import + * failures raise the same error message. + * - Python's daemon threads (reaction adds, notification sends) become + * fire-and-forget async functions; threading.Lock dropped (single-threaded + * event loop). + */ + +import { Channel, OutboundMessageType } from "../bus.ts"; +import type { MessageBus, OutboundMessage, TaskDBLike } from "../bus.ts"; +import { makeTask, ScheduleType } from "../types.ts"; +import { handle_agent_command, resolve_agent } from "./agent_utils.ts"; +import type { SettingsDB } from "./agent_utils.ts"; +import { handle_dir_command, resolve_working_dir } from "./dir_utils.ts"; +import type { Task } from "../types.ts"; + +// ── injected client surfaces (≙ slack_sdk WebClient / SocketModeClient) ── + +/** Structural view of the web client the channel talks to (Python names). */ +export interface WebClientLike { + auth_test(): Promise; + chat_postMessage(args: { + channel: string; + thread_ts?: string | null; + text: string; + mrkdwn?: boolean; + }): Promise; + reactions_add(args: { + channel: string; + timestamp: string; + name: string; + }): Promise; + conversations_open(args: { users: string }): Promise; +} + +/** ≙ slack_sdk SocketModeRequest (type / envelope_id / payload). */ +export interface SocketModeRequestLike { + type: string; + envelope_id: string; + payload: Record; +} + +/** The "client" passed to socket-mode listeners; used only to ack. */ +export interface SocketAckClientLike { + send_socket_mode_response(resp: { envelope_id: string }): void; +} + +export type SocketModeRequestListener = ( + client: SocketAckClientLike, + req: SocketModeRequestLike, +) => void | Promise; + +/** Structural view of the socket-mode client (Python calling surface). */ +export interface SocketModeClientLike { + socket_mode_request_listeners: SocketModeRequestListener[]; + connect(): void | Promise; + disconnect(): void | Promise; +} + +/** What `_require_slack()` returns: the two client constructors. */ +export interface SlackSDK { + WebClient: new (token?: string) => WebClientLike; + SocketModeClient: new (opts: { + app_token?: string; + web_client?: WebClientLike | null; + }) => SocketModeClientLike; +} + +// ── lazy import guard (≙ Python _require_slack) ─────────────────────────── + +async function _import_slack(): Promise { + const webApi: any = await import("@slack/web-api"); + const socketMode: any = await import("@slack/socket-mode"); + + /** Adapter exposing the Python slack_sdk WebClient surface. */ + class WebClientAdapter implements WebClientLike { + private _client: any; + + constructor(token?: string) { + this._client = new webApi.WebClient(token); + } + + auth_test(): Promise { + return this._client.auth.test(); + } + + chat_postMessage(args: { + channel: string; + thread_ts?: string | null; + text: string; + mrkdwn?: boolean; + }): Promise { + return this._client.chat.postMessage({ + channel: args.channel, + thread_ts: args.thread_ts ?? undefined, + text: args.text, + mrkdwn: args.mrkdwn, + }); + } + + reactions_add(args: { + channel: string; + timestamp: string; + name: string; + }): Promise { + return this._client.reactions.add({ + channel: args.channel, + timestamp: args.timestamp, + name: args.name, + }); + } + + conversations_open(args: { users: string }): Promise { + return this._client.conversations.open({ users: args.users }); + } + } + + /** + * Adapter exposing the Python slack_sdk SocketModeClient surface + * (socket_mode_request_listeners + connect/disconnect) on top of + * @slack/socket-mode's EventEmitter API. + */ + class SocketModeClientAdapter implements SocketModeClientLike { + socket_mode_request_listeners: SocketModeRequestListener[] = []; + private _client: any; + + constructor(opts: { + app_token?: string; + web_client?: WebClientLike | null; + }) { + this._client = new socketMode.SocketModeClient({ + appToken: opts.app_token, + }); + this._client.on("slack_event", (args: any) => { + const ack_client: SocketAckClientLike = { + send_socket_mode_response: (_resp: { envelope_id: string }) => { + void Promise.resolve(args.ack()).catch((e: unknown) => { + console.log(`[Slack] ack failed: ${e}`); + }); + }, + }; + const req: SocketModeRequestLike = { + type: args.type, + envelope_id: args.envelope_id, + payload: args.body ?? {}, + }; + for (const listener of this.socket_mode_request_listeners) { + void Promise.resolve(listener(ack_client, req)).catch( + (e: unknown) => { + console.log(`[Slack] socket request listener error: ${e}`); + }, + ); + } + }); + } + + async connect(): Promise { + await this._client.start(); + } + + async disconnect(): Promise { + await this._client.disconnect(); + } + } + + return { + WebClient: WebClientAdapter, + SocketModeClient: SocketModeClientAdapter, + }; +} + +// Test seam (≙ pytest monkeypatching the slack_sdk import / _require_slack). +export const _hooks = { import_slack: _import_slack }; + +export async function _require_slack(): Promise { + try { + return await _hooks.import_slack(); + } catch (e) { + throw new Error( + "slack-sdk is required for SlackChannel. Install it with: uv add slack-sdk", + { cause: e }, + ); + } +} + +// ── help text (byte-identical to Python) ────────────────────────────────── + +export const HELP_TEXT = `*AgentForge Bot* 👋 +Send me any message and I'll create a task from it. +Reply to a completion/failure notification to resume that task. + +*Commands:* +• \`/status \` — show task details +• \`/cancel \` — cancel a task +• \`/resume \` — resume a task with a message +• \`/dir \` — set default working directory +  e.g. \`/dir ~/workspace/myproject\` +• \`/agent \` — switch coding agent (\`claude\` / \`codex\`) +• \`/help\` — show this message + +*Tips:* +• You can also mention a path in your message and it will be used automatically. + e.g. _在 ~/myapp 里帮我修复登录 bug_ +• Reply to any result notification to continue the conversation. +`; + +// ── structural dependencies ─────────────────────────────────────────────── + +/** Minimal structural view of TaskDB used by this channel. */ +export interface SlackTaskDB extends TaskDBLike, SettingsDB { + update_task(task_id: number, updates: Record): void; +} + +/** + * Minimal structural view of TaskScheduler used by this channel + * (≙ Python `TaskScheduler.submit_task(task) -> int`). + */ +export interface SchedulerLike { + submit_task(task: Task): number; +} + +// ── channel ─────────────────────────────────────────────────────────────── + +/** Slack channel integration using Socket Mode. */ +export class SlackChannel extends Channel { + declare db: SlackTaskDB; + scheduler: SchedulerLike; + + bot_token: string; + app_token: string; + + _web_client: WebClientLike | null = null; + _socket_client: SocketModeClientLike | null = null; + _bot_user_id: string | null = null; + + // Maps task_id → [channel_id, thread_ts, reaction_ts] for reply-back on completion + // thread_ts: used for posting reply messages in the correct thread + // reaction_ts: used for adding emoji reactions (may differ from thread_ts on resume) + _task_origin: Map = new Map(); + + // DM channel cache for P2P fallback (user_id → DM channel_id) + _dm_channel_cache: Map = new Map(); + + // Maps notification thread_ts → task_id for resume-by-reply + _notification_map: Map = new Map(); + + // Maps thread root ts → task_id for thread-based session resume + _thread_ts_map: Map = new Map(); + + constructor( + bus: MessageBus, + db: SlackTaskDB, + scheduler: SchedulerLike, + bot_token: string = "", + app_token: string = "", + ) { + super("slack", bus, db); + this.scheduler = scheduler; + + this.bot_token = bot_token || process.env.SLACK_BOT_TOKEN || ""; + this.app_token = app_token || process.env.SLACK_APP_TOKEN || ""; + + // Subscribe to outbound bus messages for task notifications + bus.subscribe_outbound(this._on_outbound); + + console.log( + `[Slack] Initialized. bot_token=${this.bot_token ? "set" : "MISSING"}, ` + + `app_token=${this.app_token ? "set" : "MISSING"}`, + ); + } + + // ── lifecycle ──────────────────────────────────────────────── + + async start(): Promise { + if (!this.bot_token || !this.app_token) { + console.log( + "[Slack] Missing SLACK_BOT_TOKEN or SLACK_APP_TOKEN — channel disabled", + ); + return; + } + + console.log("[Slack] Starting... importing slack_sdk"); + const { WebClient, SocketModeClient } = await _require_slack(); + console.log("[Slack] slack_sdk imported successfully"); + + this._web_client = new WebClient(this.bot_token); + console.log("[Slack] WebClient created, calling auth_test()..."); + + // Resolve bot's own user ID so we can ignore self-messages + try { + const resp = await this._web_client.auth_test(); + this._bot_user_id = resp["user_id"]; + console.log( + `[Slack] auth_test OK — bot_user_id=${this._bot_user_id}, ` + + `team=${resp["team"] ?? "?"}, user=${resp["user"] ?? "?"}`, + ); + } catch (e) { + console.log(`[Slack] auth_test FAILED: ${e}`); + console.error((e as Error)?.stack ?? e); + return; + } + + console.log("[Slack] Creating SocketModeClient..."); + this._socket_client = new SocketModeClient({ + app_token: this.app_token, + web_client: this._web_client, + }); + + // Register event handler + this._socket_client.socket_mode_request_listeners.push( + this._handle_socket_request, + ); + console.log("[Slack] Registered socket_mode_request_listeners"); + + this._running = true; + console.log("[Slack] Calling socket_client.connect()..."); + await this._socket_client.connect(); + console.log("[Slack] Socket Mode connected — listening for events"); + } + + stop(): void { + console.log("[Slack] Stopping..."); + this._running = false; + this.bus.unsubscribe_outbound(this._on_outbound); + if (this._socket_client) { + try { + void Promise.resolve(this._socket_client.disconnect()).catch(() => {}); + } catch { + /* ignore */ + } + } + console.log("[Slack] Stopped"); + } + + // ── socket mode handler ────────────────────────────────────── + + // Arrow property: a stable bound reference is pushed into + // socket_mode_request_listeners (≙ Python bound method). + _handle_socket_request = async ( + client: SocketAckClientLike, + req: SocketModeRequestLike, + ): Promise => { + console.log( + `[Slack] <<< Socket request received: type=${req.type}, ` + + `envelope_id=${req.envelope_id.slice(0, 12)}...`, + ); + + // Acknowledge immediately (Slack requires < 3s ack) + client.send_socket_mode_response({ envelope_id: req.envelope_id }); + console.log( + `[Slack] ACK sent for envelope ${req.envelope_id.slice(0, 12)}`, + ); + + if (req.type !== "events_api") { + console.log( + `[Slack] Ignoring non-events_api request type: ${req.type}`, + ); + return; + } + + const payload = req.payload ?? {}; + const event: Record = payload["event"] ?? {}; + const event_type: string = event["type"] ?? ""; + + console.log( + `[Slack] Event type=${event_type}, ` + + `user=${event["user"] ?? "?"}, ` + + `channel=${event["channel"] ?? "?"}, ` + + `channel_type=${event["channel_type"] ?? "?"}, ` + + `bot_id=${event["bot_id"] ?? "none"}, ` + + `subtype=${event["subtype"] ?? "none"}, ` + + `text=${JSON.stringify((event["text"] ?? "").slice(0, 80))}`, + ); + + // Handle message events + try { + if (event_type === "message") { + await this._handle_message_event(event); + } else if (event_type === "app_mention") { + await this._handle_mention_event(event); + } else if (event_type === "app_home_opened") { + await this._handle_app_home_opened(event); + } else { + console.log(`[Slack] Unhandled event type: ${event_type}`); + } + } catch (e) { + console.log(`[Slack] ERROR handling ${event_type} event: ${e}`); + console.error((e as Error)?.stack ?? e); + } + }; + + /** Handle DM messages (channel_type == 'im'). */ + async _handle_message_event(event: Record): Promise { + // Only process DMs, not channel messages (those come via app_mention) + if (event["channel_type"] !== "im") { + console.log( + `[Slack] message event skipped: channel_type=${JSON.stringify( + event["channel_type"], + )} (not 'im')`, + ); + return; + } + // Ignore bot messages and message edits + if (event["bot_id"] || event["subtype"]) { + console.log( + `[Slack] message event skipped: bot_id=${event["bot_id"]}, ` + + `subtype=${event["subtype"]}`, + ); + return; + } + + const user_id: string = event["user"] ?? ""; + if (user_id === this._bot_user_id) { + console.log("[Slack] message event skipped: message from self (bot)"); + return; + } + + const text: string = (event["text"] ?? "").trim(); + const channel_id: string = event["channel"] ?? ""; + const thread_ts: string | null = event["thread_ts"] ?? null; + const msg_ts: string = event["ts"]; + + console.log( + `[Slack] DM from user=${user_id}, channel=${channel_id}, ` + + `text=${JSON.stringify(text.slice(0, 80))}`, + ); + await this._handle_user_message(text, channel_id, thread_ts, msg_ts); + } + + /** Handle @bot mentions in channels. */ + async _handle_mention_event(event: Record): Promise { + if (event["bot_id"] || event["subtype"]) { + console.log( + `[Slack] mention event skipped: bot_id=${event["bot_id"]}, ` + + `subtype=${event["subtype"]}`, + ); + return; + } + + const user_id: string = event["user"] ?? ""; + if (user_id === this._bot_user_id) { + console.log("[Slack] mention event skipped: mention from self (bot)"); + return; + } + + // Strip the mention prefix (<@BOTID> ...) from the text + let text: string = (event["text"] ?? "").trim(); + if (this._bot_user_id) { + const mention_prefix = `<@${this._bot_user_id}>`; + if (text.startsWith(mention_prefix)) { + text = text.slice(mention_prefix.length).trim(); + } + } + + const channel_id: string = event["channel"] ?? ""; + const thread_ts: string | null = event["thread_ts"] ?? null; + const msg_ts: string = event["ts"]; + + console.log( + `[Slack] Mention from user=${user_id}, channel=${channel_id}, ` + + `text=${JSON.stringify(text.slice(0, 80))}`, + ); + await this._handle_user_message(text, channel_id, thread_ts, msg_ts); + } + + /** Handle app_home_opened event — send HELP_TEXT DM on first open. */ + async _handle_app_home_opened(event: Record): Promise { + const user_id: string = event["user"] ?? ""; + if (!user_id || user_id === this._bot_user_id) { + return; + } + // Only send on the first open (tab == "home", not "messages") + const tab: string = event["tab"] ?? ""; + if (tab !== "home") { + return; + } + console.log( + `[Slack] app_home_opened by user=${user_id}, sending HELP_TEXT via DM`, + ); + const dm_ch = await this._open_dm_channel(user_id); + if (dm_ch) { + await this._reply(dm_ch, null, HELP_TEXT); + } else { + console.log(`[Slack] Failed to open DM channel with user ${user_id}`); + } + } + + // ── unified message handler ─────────────────────────────────── + + /** Handle any user message: commands, resume-by-reply, or create task. */ + async _handle_user_message( + text: string, + channel_id: string, + thread_ts: string | null, + msg_ts: string, + ): Promise { + if (!text) { + await this._reply(channel_id, msg_ts, HELP_TEXT); + return; + } + + // ── slash commands ──────────────────────────────────────── + if (text.startsWith("/")) { + const ws = text.search(/\s/); + const cmd = (ws === -1 ? text : text.slice(0, ws)).toLowerCase(); + const args = ws === -1 ? "" : text.slice(ws + 1).trim(); + + if (cmd === "/status") { + await this._cmd_status(args, channel_id, msg_ts); + } else if (cmd === "/cancel") { + await this._cmd_cancel(args, channel_id, msg_ts); + } else if (cmd === "/resume") { + await this._cmd_resume(args, channel_id, msg_ts); + } else if (cmd === "/dir" || cmd === "/cd") { + const reply = handle_dir_command(text, "slack", this.db); + await this._reply(channel_id, msg_ts, reply ? reply : HELP_TEXT); + } else if (cmd === "/agent") { + const reply = handle_agent_command(text, "slack", this.db); + await this._reply(channel_id, msg_ts, reply ? reply : HELP_TEXT); + } else if (cmd === "/help") { + await this._reply(channel_id, msg_ts, HELP_TEXT); + } else { + await this._reply(channel_id, msg_ts, HELP_TEXT); + } + return; + } + + if (text.toLowerCase() === "help") { + await this._reply(channel_id, msg_ts, HELP_TEXT); + return; + } + + // ── reply to a notification thread → resume task ────────── + if (thread_ts) { + // Look up task_id: first from notification_map, then from thread_ts_map + let task_id = this._notification_map.get(thread_ts); + if (!task_id) { + task_id = this._thread_ts_map.get(thread_ts); + } + if (task_id) { + const task = this.db.get_task(task_id); + if (task && task["session_id"]) { + this.db.update_task(task_id, { + status: "pending", + prompt: text, + result: null, + error: null, + question: null, + }); + this._task_origin.set(task_id, [channel_id, thread_ts, msg_ts]); + this._add_reaction(channel_id, msg_ts, "eyes"); + await this._reply(channel_id, thread_ts, ":arrow_forward:"); + console.log( + `[Slack] Auto-resuming task ${task_id} from thread reply`, + ); + return; + } else { + await this._reply( + channel_id, + thread_ts, + `:x: Task *#${task_id}* has no saved session to resume.`, + ); + return; + } + } + } + + // ── default: create a new task from message text ────────── + await this._create_task(text, channel_id, msg_ts); + } + + // ── task creation ───────────────────────────────────────────── + + /** Create a new task from any message. */ + async _create_task( + text: string, + channel_id: string, + thread_ts: string, + ): Promise { + const title = text.slice(0, 60) + (text.length > 60 ? "…" : ""); + + const task = makeTask({ + title: `[Slack] ${title}`, + prompt: text, + working_dir: await resolve_working_dir(text, "slack", this.db), + schedule_type: ScheduleType.IMMEDIATE, + tags: "slack", + agent: resolve_agent("slack", this.db), + }); + const task_id = this.scheduler.submit_task(task); + console.log(`[Slack] Task #${task_id} created from message`); + + this._task_origin.set(task_id, [channel_id, thread_ts, thread_ts]); + console.log( + `[Slack] Origin set for task #${task_id}: channel=${channel_id}, ` + + `thread_ts=${thread_ts}`, + ); + + // Track thread root ts → task_id so replies in the thread can resume + this._thread_ts_map.set(thread_ts, task_id); + + // Acknowledge with an eyes reaction and a brief running hint + this._add_reaction(channel_id, thread_ts, "eyes"); + await this._reply(channel_id, thread_ts, `Task #${task_id} is running…`); + } + + // ── commands ────────────────────────────────────────────────── + + async _cmd_status( + args: string, + channel_id: string, + thread_ts: string, + ): Promise { + const task_id = SlackChannel._parse_task_id(args); + if (task_id === null) { + await this._reply( + channel_id, + thread_ts, + ":warning: Usage: `/status `", + ); + return; + } + + const task = this.db.get_task(task_id); + if (!task) { + await this._reply( + channel_id, + thread_ts, + `:x: Task #${task_id} not found.`, + ); + return; + } + + const status_emoji: Record = { + pending: ":hourglass:", + scheduled: ":calendar:", + running: ":runner:", + completed: ":white_check_mark:", + failed: ":x:", + cancelled: ":no_entry_sign:", + }; + const emoji = status_emoji[task["status"] as string] ?? ":grey_question:"; + const lines = [ + `${emoji} *Task #${task["id"]}* — *${task["title"]}*`, + `Status: \`${task["status"]}\``, + `Created: ${task["created_at"] ?? "—"}`, + `Last run: ${task["last_run_at"] || "—"}`, + ]; + if (task["error"]) { + lines.push(`Error: \`${(task["error"] as string).slice(0, 300)}\``); + } + if (task["result"]) { + lines.push(`Result: ${(task["result"] as string).slice(0, 500)}`); + } + + await this._reply(channel_id, thread_ts, lines.join("\n")); + } + + async _cmd_cancel( + args: string, + channel_id: string, + thread_ts: string, + ): Promise { + const task_id = SlackChannel._parse_task_id(args); + if (task_id === null) { + await this._reply( + channel_id, + thread_ts, + ":warning: Usage: `/cancel `", + ); + return; + } + + const task = this.db.get_task(task_id); + if (!task) { + await this._reply( + channel_id, + thread_ts, + `:x: Task #${task_id} not found.`, + ); + return; + } + + const status = task["status"] as string; + if ( + status === "completed" || + status === "failed" || + status === "cancelled" + ) { + await this._reply( + channel_id, + thread_ts, + `:information_source: Task #${task_id} is already \`${status}\`.`, + ); + return; + } + + this.db.update_task(task_id, { status: "cancelled" }); + await this._reply( + channel_id, + thread_ts, + `:no_entry_sign: Task #${task_id} cancelled.`, + ); + } + + async _cmd_resume( + args: string, + channel_id: string, + thread_ts: string, + ): Promise { + // ≙ Python args.strip().split(" ", 1) + const stripped = args.trim(); + const sp = stripped.indexOf(" "); + const head = sp === -1 ? stripped : stripped.slice(0, sp); + const tail = sp === -1 ? null : stripped.slice(sp + 1); + + if (!/^[+-]?\d+$/.test(head.replace(/^#+/, ""))) { + await this._reply( + channel_id, + thread_ts, + ":warning: Usage: `/resume `", + ); + return; + } + + const tid = parseInt(head.replace(/^#+/, ""), 10); + const resume_msg = tail !== null ? tail.trim() : ""; + if (!resume_msg) { + await this._reply( + channel_id, + thread_ts, + ":warning: Please provide a message to resume with.", + ); + return; + } + + const task = this.db.get_task(tid); + if (!task || !task["session_id"]) { + await this._reply( + channel_id, + thread_ts, + `:x: Task #${tid} not found or has no saved session.`, + ); + return; + } + + this.db.update_task(tid, { + status: "pending", + prompt: resume_msg, + result: null, + error: null, + question: null, + }); + this._task_origin.set(tid, [channel_id, thread_ts, thread_ts]); + this._add_reaction(channel_id, thread_ts, "eyes"); + await this._reply(channel_id, thread_ts, ":arrow_forward:"); + } + + // ── Channel ABC: send outbound message ─────────────────────── + + /** Forward task completion/failure to the originating Slack thread. */ + send(msg: OutboundMessage): void { + // Python's send() is synchronous (its network calls run on threads); the + // TS port keeps a synchronous signature and runs the async body + // fire-and-forget. + void this._send(msg).catch((e) => { + console.log(`[Slack] send() error: ${e}`); + }); + } + + private async _send(msg: OutboundMessage): Promise { + if ( + msg.type !== OutboundMessageType.TASK_COMPLETED && + msg.type !== OutboundMessageType.TASK_FAILED + ) { + return; + } + + const task_id = msg.task_id; + const origin = this._task_origin.get(task_id); + console.log( + `[Slack] send() task_id=${task_id} (type=${typeof task_id}), ` + + `origin=${JSON.stringify(origin ?? null)}, ` + + `keys=${JSON.stringify([...this._task_origin.keys()])}`, + ); + + // Build notification text + let title: string; + let text: string; + if (msg.type === OutboundMessageType.TASK_COMPLETED) { + const result_text = ((msg.payload["result"] as string | null) || "") + .trim() + .slice(0, 10000); + title = (msg.payload["title"] as string | null) || `Task #${task_id}`; + text = result_text || "Done."; + } else { + const error_text = ( + (msg.payload["error"] as string | null) || "Unknown error" + ) + .trim() + .slice(0, 800); + title = (msg.payload["title"] as string | null) || `Task #${task_id}`; + text = error_text; + } + + let channel_id: string; + let thread_ts: string | null; + if (origin) { + const [origin_channel, origin_thread, reaction_ts] = origin; + channel_id = origin_channel; + thread_ts = origin_thread; + // Add emoji reaction to the message that triggered the task (or resume) + const react_target = (reaction_ts || thread_ts) as string; + if (msg.type === OutboundMessageType.TASK_COMPLETED) { + this._add_reaction(channel_id, react_target, "white_check_mark"); + } else { + this._add_reaction(channel_id, react_target, "x"); + } + } else { + // Fallback: P2P DM to configured user, or default channel + const dm_user = this.db.get_setting("slack_default_user"); + const default_channel = this.db.get_setting("slack_default_channel"); + if (dm_user) { + const dm_ch = await this._open_dm_channel(dm_user); + if (dm_ch) { + channel_id = dm_ch; + thread_ts = null; + const status_emoji = + msg.type === OutboundMessageType.TASK_COMPLETED + ? ":white_check_mark:" + : ":x:"; + text = `${status_emoji} *${title}*\n${text}`; + console.log(`[Slack] Falling back to P2P DM with user ${dm_user}`); + } else { + console.log( + `[Slack] Failed to open DM with user ${dm_user}, skipping`, + ); + return; + } + } else if (default_channel) { + channel_id = default_channel; + thread_ts = null; + const status_emoji = + msg.type === OutboundMessageType.TASK_COMPLETED + ? ":white_check_mark:" + : ":x:"; + text = `${status_emoji} *${title}*\n${text}`; + } else { + console.log( + `[Slack] No origin, no known user, no slack_default_channel for ` + + `task #${task_id}, skipping`, + ); + return; + } + } + + console.log( + `[Slack] Sending outbound notification for task #${task_id}: ${msg.type}`, + ); + + // ≙ Python's _send_and_track daemon thread + const send_channel = channel_id; + const send_thread = thread_ts; + const send_text = text; + void (async () => { + const sent_ts = await this._reply_return_ts( + send_channel, + send_thread, + send_text, + ); + if (sent_ts) { + this._notification_map.set(sent_ts, task_id); + console.log( + `[Slack] Notification ts=${sent_ts} mapped to task #${task_id}`, + ); + } + })(); + + // Free origin memory after terminal state + this._task_origin.delete(task_id); + } + + /** MessageBus outbound subscriber callback (stable bound reference). */ + _on_outbound = (msg: OutboundMessage): void => { + this.send(msg); + }; + + // ── helpers ────────────────────────────────────────────────── + + /** Open (or retrieve cached) DM channel with a user. */ + async _open_dm_channel(user_id: string): Promise { + const cached = this._dm_channel_cache.get(user_id); + if (cached !== undefined) { + return cached; + } + if (!this._web_client) { + return null; + } + try { + const resp = await this._web_client.conversations_open({ + users: user_id, + }); + const ch_id: string = resp["channel"]["id"]; + this._dm_channel_cache.set(user_id, ch_id); + console.log(`[Slack] Opened DM channel ${ch_id} with user ${user_id}`); + return ch_id; + } catch (e) { + console.log( + `[Slack] conversations.open failed for user ${user_id}: ${e}`, + ); + return null; + } + } + + /** Add an emoji reaction to a message (non-blocking). */ + _add_reaction(channel_id: string, timestamp: string, emoji: string): void { + const web_client = this._web_client; + if (!web_client) { + return; + } + + // ≙ Python daemon thread running _do() + void (async () => { + try { + await web_client.reactions_add({ + channel: channel_id, + timestamp, + name: emoji, + }); + } catch (e) { + if (String(e).includes("already_reacted")) { + // Reaction already exists, ignore + } else { + console.log(`[Slack] Failed to add reaction ${emoji}: ${e}`); + } + } + })(); + } + + async _reply( + channel_id: string, + thread_ts: string | null, + text: string, + ): Promise { + if (!this._web_client) { + console.log("[Slack] _reply skipped: no web_client"); + return; + } + try { + console.log( + `[Slack] >>> Sending message to channel=${channel_id}, ` + + `thread=${thread_ts}, len=${text.length}`, + ); + await this._web_client.chat_postMessage({ + channel: channel_id, + thread_ts, + text, + mrkdwn: true, + }); + console.log("[Slack] >>> Message sent OK"); + } catch (e) { + console.log(`[Slack] >>> chat_postMessage FAILED: ${e}`); + console.error((e as Error)?.stack ?? e); + } + } + + /** Send a message and return its ts (for tracking notification threads). */ + async _reply_return_ts( + channel_id: string, + thread_ts: string | null, + text: string, + ): Promise { + if (!this._web_client) { + return null; + } + try { + const resp = await this._web_client.chat_postMessage({ + channel: channel_id, + thread_ts, + text, + mrkdwn: true, + }); + return resp?.["ts"] ?? null; + } catch (e) { + console.log(`[Slack] >>> chat_postMessage FAILED: ${e}`); + console.error((e as Error)?.stack ?? e); + return null; + } + } + + static _parse_task_id(s: string): number | null { + const stripped = s.trim().replace(/^#+/, ""); + if (!/^[+-]?\d+$/.test(stripped)) { + return null; + } + return parseInt(stripped, 10); + } +} diff --git a/backend/tests/slack-channel.test.ts b/backend/tests/slack-channel.test.ts new file mode 100644 index 0000000..a983a38 --- /dev/null +++ b/backend/tests/slack-channel.test.ts @@ -0,0 +1,620 @@ +// Ported from tests/test_slack_channel.py (bun:test). +// +// Python's MagicMock web client becomes a small object of bun `mock()` +// functions with the same call surface; `_wait_threads()` (joining Python's +// daemon threads) becomes draining the event loop with setTimeout(0). + +import { expect, mock, test } from "bun:test"; + +import { + MessageBus, + makeOutboundMessage, + OutboundMessageType, +} from "../src/bus.ts"; +import { _hooks as dir_hooks } from "../src/channels/dir_utils.ts"; +import { SlackChannel } from "../src/channels/slack.ts"; +import type { SlackTaskDB } from "../src/channels/slack.ts"; +import type { Task } from "../src/types.ts"; + +class StubDB implements SlackTaskDB { + settings: Record = {}; + tasks: Record> = {}; + updated: Array<[number, Record]> = []; + + get_setting(key: string, defaultValue: string | null = null): string | null { + return this.settings[key] ?? defaultValue; + } + + set_setting(key: string, value: string): void { + this.settings[key] = value; + } + + get_task(task_id: number): Record | null { + return this.tasks[task_id] ?? null; + } + + update_task(task_id: number, updates: Record): void { + this.updated.push([task_id, updates]); + this.tasks[task_id] = { + ...(this.tasks[task_id] ?? { id: task_id }), + ...updates, + }; + } +} + +class StubScheduler { + submitted: Task[] = []; + + submit_task(task: Task): number { + this.submitted.push(task); + return this.submitted.length; + } +} + +/** ≙ the MagicMock web client injected by the pytest helper. */ +function make_web_client() { + return { + auth_test: mock(async () => ({}) as Record), + chat_postMessage: mock(async (_args: any) => ({ ts: "1700.0001" }) as any), + reactions_add: mock(async (_args: any) => ({}) as any), + conversations_open: mock(async (_args: any) => ({}) as any), + }; +} + +type WebClientMock = ReturnType; + +function _make_channel(db?: StubDB, scheduler?: StubScheduler) { + const bus = new MessageBus(); + const the_db = db ?? new StubDB(); + const the_scheduler = scheduler ?? new StubScheduler(); + const channel = new SlackChannel( + bus, + the_db, + the_scheduler, + "xoxb-test", + "xapp-test", + ); + // Inject a mock web client and bot id so helpers don't hit the network. + const web = make_web_client(); + channel._web_client = web; + channel._bot_user_id = "UBOT"; + return { channel, bus, db: the_db, scheduler: the_scheduler, web }; +} + +function last_text(web: WebClientMock): string { + return (web.chat_postMessage.mock.calls.at(-1)![0] as any).text; +} + +function all_texts(web: WebClientMock): string[] { + return web.chat_postMessage.mock.calls.map((c) => (c[0] as any).text); +} + +/** ≙ pytest `patch("channels.dir_utils.resolve_working_dir", ...)`. */ +async function with_resolved_dir( + value: string, + fn: () => Promise, +): Promise { + const orig = dir_hooks.extract_working_dir_with_claude; + dir_hooks.extract_working_dir_with_claude = async () => value; + try { + return await fn(); + } finally { + dir_hooks.extract_working_dir_with_claude = orig; + } +} + +/** ≙ pytest capsys: capture console.log output. */ +function capture_logs(): { logs: string[]; restore: () => void } { + const logs: string[] = []; + const orig = console.log; + console.log = (...args: unknown[]) => { + logs.push(args.map(String).join(" ")); + }; + return { + logs, + restore: () => { + console.log = orig; + }, + }; +} + +/** ≙ joining the daemon threads spawned by send()/_add_reaction. */ +async function _wait_threads(): Promise { + await new Promise((r) => setTimeout(r, 0)); + await new Promise((r) => setTimeout(r, 0)); +} + +// ── construction / config ──────────────────────────────────────── + +test("test_init_reads_tokens_and_subscribes", () => { + const { channel, bus } = _make_channel(); + expect(channel.bot_token).toBe("xoxb-test"); + expect(channel.app_token).toBe("xapp-test"); + expect(channel.name).toBe("slack"); + expect((bus as any)._outbound_listeners).toContain(channel._on_outbound); +}); + +test("test_init_falls_back_to_env", () => { + const orig_bot = process.env.SLACK_BOT_TOKEN; + const orig_app = process.env.SLACK_APP_TOKEN; + process.env.SLACK_BOT_TOKEN = "xoxb-env"; + process.env.SLACK_APP_TOKEN = "xapp-env"; + try { + const channel = new SlackChannel( + new MessageBus(), + new StubDB(), + new StubScheduler(), + ); + expect(channel.bot_token).toBe("xoxb-env"); + expect(channel.app_token).toBe("xapp-env"); + } finally { + if (orig_bot === undefined) delete process.env.SLACK_BOT_TOKEN; + else process.env.SLACK_BOT_TOKEN = orig_bot; + if (orig_app === undefined) delete process.env.SLACK_APP_TOKEN; + else process.env.SLACK_APP_TOKEN = orig_app; + } +}); + +test("test_start_disabled_without_tokens", async () => { + const channel = new SlackChannel( + new MessageBus(), + new StubDB(), + new StubScheduler(), + ); + channel.bot_token = ""; + channel.app_token = ""; + const { logs, restore } = capture_logs(); + try { + await channel.start(); + } finally { + restore(); + } + expect(logs.join("\n")).toContain("disabled"); + expect(channel._running).toBe(false); +}); + +test("test_parse_task_id", () => { + expect(SlackChannel._parse_task_id("#42")).toBe(42); + expect(SlackChannel._parse_task_id(" 7 ")).toBe(7); + expect(SlackChannel._parse_task_id("nope")).toBeNull(); + expect(SlackChannel._parse_task_id("")).toBeNull(); +}); + +// ── task creation ──────────────────────────────────────────────── + +test("test_create_task_submits_and_tracks_origin", async () => { + const scheduler = new StubScheduler(); + const { channel } = _make_channel(undefined, scheduler); + + await with_resolved_dir("~/myapp", () => + channel._handle_user_message("fix login bug", "C1", null, "100.1"), + ); + + expect(scheduler.submitted.length).toBe(1); + const task = scheduler.submitted[0]!; + expect(task.prompt).toBe("fix login bug"); + expect(task.title).toBe("[Slack] fix login bug"); + expect(task.tags).toBe("slack"); + expect(task.working_dir).toBe("~/myapp"); + // origin tracked: [channel_id, thread_ts, reaction_ts] + expect(channel._task_origin.get(1)).toEqual(["C1", "100.1", "100.1"]); + expect(channel._thread_ts_map.get("100.1")).toBe(1); +}); + +test("test_empty_message_replies_help", async () => { + const { channel, web } = _make_channel(); + await channel._handle_user_message("", "C1", null, "100.1"); + expect(last_text(web)).toContain("AgentForge Bot"); +}); + +test("test_help_command_and_word", async () => { + const { channel, web } = _make_channel(); + await channel._handle_user_message("/help", "C1", null, "1.0"); + await channel._handle_user_message("help", "C1", null, "2.0"); + const texts = all_texts(web); + expect(texts.length).toBe(2); + for (const t of texts) { + expect(t).toContain("AgentForge Bot"); + } +}); + +test("test_unknown_command_replies_help", async () => { + const { channel, web } = _make_channel(); + await channel._handle_user_message("/bogus", "C1", null, "1.0"); + expect(last_text(web)).toContain("AgentForge Bot"); +}); + +// ── commands ───────────────────────────────────────────────────── + +test("test_cmd_status_usage_and_not_found", async () => { + const { channel, web } = _make_channel(); + await channel._cmd_status("", "C1", "1.0"); + expect(last_text(web)).toContain("Usage"); + + await channel._cmd_status("99", "C1", "1.0"); + expect(last_text(web)).toContain("not found"); +}); + +test("test_cmd_status_renders_task", async () => { + const db = new StubDB(); + db.tasks[5] = { + id: 5, + title: "Build feature", + status: "completed", + created_at: "2026-01-01", + last_run_at: "2026-01-02", + result: "all green", + error: null, + }; + const { channel, web } = _make_channel(db); + await channel._cmd_status("#5", "C1", "1.0"); + const text = last_text(web); + expect(text).toContain(":white_check_mark:"); + expect(text).toContain("Task #5"); + expect(text).toContain("Build feature"); + expect(text).toContain("all green"); +}); + +test("test_cmd_cancel_paths", async () => { + const db = new StubDB(); + db.tasks[1] = { id: 1, title: "t", status: "running" }; + db.tasks[2] = { id: 2, title: "t", status: "completed" }; + const { channel, web } = _make_channel(db); + + await channel._cmd_cancel("", "C1", "1.0"); + expect(last_text(web)).toContain("Usage"); + + await channel._cmd_cancel("99", "C1", "1.0"); + expect(last_text(web)).toContain("not found"); + + await channel._cmd_cancel("2", "C1", "1.0"); + expect(last_text(web)).toContain("already"); + + await channel._cmd_cancel("1", "C1", "1.0"); + expect(db.updated.at(-1)).toEqual([1, { status: "cancelled" }]); + expect(last_text(web)).toContain("cancelled"); +}); + +test("test_cmd_resume_paths", async () => { + const db = new StubDB(); + db.tasks[1] = { id: 1, title: "t", status: "completed", session_id: "s1" }; + db.tasks[2] = { id: 2, title: "t", status: "completed" }; // no session + const { channel, web } = _make_channel(db); + + await channel._cmd_resume("", "C1", "1.0"); + expect(last_text(web)).toContain("Usage"); + + await channel._cmd_resume("1", "C1", "1.0"); + expect(last_text(web)).toContain("provide a message"); + + await channel._cmd_resume("2 keep going", "C1", "1.0"); + expect(last_text(web)).toContain("no saved session"); + + await channel._cmd_resume("#1 keep going", "C1", "1.0"); + expect(db.updated.at(-1)![0]).toBe(1); + expect(db.updated.at(-1)![1]["prompt"]).toBe("keep going"); + expect(db.updated.at(-1)![1]["status"]).toBe("pending"); + expect(channel._task_origin.get(1)).toEqual(["C1", "1.0", "1.0"]); +}); + +test("test_slash_command_dispatch_dir_and_agent", async () => { + const db = new StubDB(); + const { channel } = _make_channel(db); + + await channel._handle_user_message("/dir ~/proj", "C1", null, "1.0"); + expect(db.get_setting("slack_default_working_dir")).toBe("~/proj"); + + await channel._handle_user_message("/agent codex", "C1", null, "2.0"); + expect(db.get_setting("default_agent")).toBe("codex"); +}); + +// ── resume by thread reply ─────────────────────────────────────── + +test("test_thread_reply_resumes_task", async () => { + const db = new StubDB(); + db.tasks[8] = { id: 8, title: "t", status: "completed", session_id: "s8" }; + const { channel } = _make_channel(db); + channel._notification_map.set("root.1", 8); + + await channel._handle_user_message( + "continue please", + "C1", + "root.1", + "200.1", + ); + + expect(db.updated.at(-1)![0]).toBe(8); + expect(db.updated.at(-1)![1]["prompt"]).toBe("continue please"); + expect(channel._task_origin.get(8)).toEqual(["C1", "root.1", "200.1"]); +}); + +test("test_thread_reply_via_thread_ts_map", async () => { + const db = new StubDB(); + db.tasks[9] = { id: 9, title: "t", status: "completed", session_id: "s9" }; + const { channel } = _make_channel(db); + channel._thread_ts_map.set("root.9", 9); + + await channel._handle_user_message("more work", "C1", "root.9", "300.1"); + expect(db.updated.at(-1)![0]).toBe(9); +}); + +test("test_thread_reply_no_session_warns", async () => { + const db = new StubDB(); + db.tasks[10] = { id: 10, title: "t", status: "completed" }; // no session + const { channel, web } = _make_channel(db); + channel._notification_map.set("root.10", 10); + + await channel._handle_user_message("go", "C1", "root.10", "400.1"); + expect(db.updated).toEqual([]); + expect(last_text(web)).toContain("no saved session"); +}); + +// ── event dispatch ─────────────────────────────────────────────── + +test("test_handle_message_event_dm", async () => { + const db = new StubDB(); + const { channel, scheduler } = _make_channel(db); + await with_resolved_dir("~", () => + channel._handle_message_event({ + channel_type: "im", + user: "U1", + text: "do something", + channel: "D1", + ts: "10.1", + }), + ); + expect(scheduler.submitted.length).toBe(1); +}); + +test("test_handle_message_event_skips_non_dm_and_bot", async () => { + const { channel, scheduler } = _make_channel(); + await channel._handle_message_event({ channel_type: "channel", text: "x" }); + await channel._handle_message_event({ + channel_type: "im", + bot_id: "B1", + text: "x", + }); + await channel._handle_message_event({ + channel_type: "im", + user: "UBOT", + text: "x", + channel: "D1", + ts: "1", + }); + expect(scheduler.submitted.length).toBe(0); +}); + +test("test_handle_mention_event_strips_prefix", async () => { + const { channel, scheduler } = _make_channel(); + await with_resolved_dir("~", () => + channel._handle_mention_event({ + user: "U1", + text: "<@UBOT> build the thing", + channel: "C9", + ts: "50.1", + }), + ); + const task = scheduler.submitted[0]!; + expect(task.prompt).toBe("build the thing"); +}); + +test("test_handle_mention_event_skips_bot", async () => { + const { channel, scheduler } = _make_channel(); + await channel._handle_mention_event({ bot_id: "B1", text: "x" }); + await channel._handle_mention_event({ user: "UBOT", text: "x" }); + expect(scheduler.submitted.length).toBe(0); +}); + +test("test_app_home_opened_sends_help", async () => { + const { channel, web } = _make_channel(); + web.conversations_open.mockImplementation(async () => ({ + channel: { id: "D5" }, + })); + await channel._handle_app_home_opened({ user: "U7", tab: "home" }); + expect(last_text(web)).toContain("AgentForge Bot"); +}); + +test("test_app_home_opened_ignores_non_home_tab", async () => { + const { channel, web } = _make_channel(); + await channel._handle_app_home_opened({ user: "U7", tab: "messages" }); + expect(web.chat_postMessage).not.toHaveBeenCalled(); +}); + +test("test_handle_socket_request_dispatches_message", async () => { + const { channel, scheduler } = _make_channel(); + const client = { send_socket_mode_response: mock((_resp: any) => {}) }; + + const req = { + type: "events_api", + envelope_id: "envelope-1234567890", + payload: { + event: { + type: "message", + channel_type: "im", + user: "U1", + text: "hello there", + channel: "D1", + ts: "9.9", + }, + }, + }; + + await with_resolved_dir("~", () => + channel._handle_socket_request(client, req), + ); + expect(client.send_socket_mode_response).toHaveBeenCalledTimes(1); + expect(scheduler.submitted.length).toBe(1); +}); + +test("test_handle_socket_request_ignores_non_events_api", async () => { + const { channel, scheduler } = _make_channel(); + const client = { send_socket_mode_response: mock((_resp: any) => {}) }; + + const req = { + type: "hello", + envelope_id: "envelope-abcdefghijkl", + payload: {}, + }; + + await channel._handle_socket_request(client, req); + expect(client.send_socket_mode_response).toHaveBeenCalledTimes(1); + expect(scheduler.submitted.length).toBe(0); +}); + +// ── outbound send ──────────────────────────────────────────────── + +test("test_send_completion_to_origin", async () => { + const db = new StubDB(); + const { channel, web } = _make_channel(db); + channel._task_origin.set(3, ["C1", "100.1", "100.1"]); + + channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_COMPLETED, + task_id: 3, + payload: { title: "Fix login", result: "all done" }, + }), + ); + await _wait_threads(); + // Reaction added + reply posted with the result text. + const react_names = web.reactions_add.mock.calls.map( + (c) => (c[0] as any).name, + ); + expect(react_names).toContain("white_check_mark"); + const posted = all_texts(web); + expect(posted.some((t) => t.includes("all done"))).toBe(true); + // Notification ts mapped to task and origin freed. + expect(channel._notification_map.get("1700.0001")).toBe(3); + expect(channel._task_origin.has(3)).toBe(false); +}); + +test("test_send_failure_to_origin_adds_x_reaction", async () => { + const db = new StubDB(); + const { channel, web } = _make_channel(db); + channel._task_origin.set(4, ["C1", "100.1", "100.1"]); + + channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_FAILED, + task_id: 4, + payload: { title: "Broke", error: "boom" }, + }), + ); + await _wait_threads(); + const react_names = web.reactions_add.mock.calls.map( + (c) => (c[0] as any).name, + ); + expect(react_names).toContain("x"); + const posted = all_texts(web); + expect(posted.some((t) => t.includes("boom"))).toBe(true); +}); + +test("test_send_ignores_non_terminal_types", async () => { + const { channel, web } = _make_channel(); + channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_STARTED, + task_id: 1, + payload: {}, + }), + ); + expect(web.chat_postMessage).not.toHaveBeenCalled(); +}); + +test("test_send_fallback_to_default_channel", async () => { + const db = new StubDB(); + db.settings["slack_default_channel"] = "C-DEFAULT"; + const { channel, web } = _make_channel(db); + + channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_COMPLETED, + task_id: 11, + payload: { title: "Job", result: "ok" }, + }), + ); + await _wait_threads(); + const call = web.chat_postMessage.mock.calls.at(-1)![0] as any; + expect(call.channel).toBe("C-DEFAULT"); + expect(call.text).toContain("Job"); +}); + +test("test_send_fallback_to_dm_user", async () => { + const db = new StubDB(); + db.settings["slack_default_user"] = "U-DM"; + const { channel, web } = _make_channel(db); + web.conversations_open.mockImplementation(async () => ({ + channel: { id: "D-DM" }, + })); + + channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_COMPLETED, + task_id: 12, + payload: { title: "Job", result: "ok" }, + }), + ); + await _wait_threads(); + const call = web.chat_postMessage.mock.calls.at(-1)![0] as any; + expect(call.channel).toBe("D-DM"); +}); + +test("test_send_no_origin_no_default_skips", async () => { + const { channel, web } = _make_channel(); + channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_COMPLETED, + task_id: 13, + payload: { title: "Job", result: "ok" }, + }), + ); + await _wait_threads(); + expect(web.chat_postMessage).not.toHaveBeenCalled(); +}); + +// ── low-level helpers ──────────────────────────────────────────── + +test("test_open_dm_channel_caches", async () => { + const { channel, web } = _make_channel(); + web.conversations_open.mockImplementation(async () => ({ + channel: { id: "D1" }, + })); + expect(await channel._open_dm_channel("U1")).toBe("D1"); + // Second call should hit the cache, not the API. + web.conversations_open.mockClear(); + expect(await channel._open_dm_channel("U1")).toBe("D1"); + expect(web.conversations_open).not.toHaveBeenCalled(); +}); + +test("test_open_dm_channel_handles_error", async () => { + const { channel, web } = _make_channel(); + web.conversations_open.mockImplementation(async () => { + throw new Error("nope"); + }); + expect(await channel._open_dm_channel("U2")).toBeNull(); +}); + +test("test_reply_return_ts", async () => { + const { channel, web } = _make_channel(); + web.chat_postMessage.mockImplementation(async () => ({ ts: "999.1" })); + expect(await channel._reply_return_ts("C1", null, "hi")).toBe("999.1"); + + web.chat_postMessage.mockImplementation(async () => { + throw new Error("fail"); + }); + expect(await channel._reply_return_ts("C1", null, "hi")).toBeNull(); +}); + +test("test_stop_unsubscribes", () => { + const { channel, bus } = _make_channel(); + const disconnect = mock(() => {}); + channel._socket_client = { + socket_mode_request_listeners: [], + connect: () => {}, + disconnect, + }; + channel.stop(); + expect(channel._running).toBe(false); + expect(disconnect).toHaveBeenCalledTimes(1); + expect((bus as any)._outbound_listeners).not.toContain(channel._on_outbound); +}); diff --git a/backend/tests/slack-more.test.ts b/backend/tests/slack-more.test.ts new file mode 100644 index 0000000..4a9744f --- /dev/null +++ b/backend/tests/slack-more.test.ts @@ -0,0 +1,538 @@ +// Ported from tests/test_slack_more.py (bun:test). +// +// Additional Slack channel coverage. Focuses on branches not exercised by +// tests/slack-channel.test.ts: +// - the _require_slack import guard (success + import failure) +// - the start() / Socket Mode bootstrap (SDK fully faked, no network) +// - _handle_socket_request error dispatch + unhandled event types +// - mention/app_home edge branches +// - send() default-channel fallback + reaction/reply error paths +// - low-level helper guards (no web client, postMessage failures) + +import { expect, mock, test } from "bun:test"; + +import { + MessageBus, + makeOutboundMessage, + OutboundMessageType, +} from "../src/bus.ts"; +import { _hooks as dir_hooks } from "../src/channels/dir_utils.ts"; +import { + _hooks as slack_hooks, + _require_slack, + SlackChannel, +} from "../src/channels/slack.ts"; +import type { SlackSDK, SlackTaskDB } from "../src/channels/slack.ts"; +import type { Task } from "../src/types.ts"; + +class StubDB implements SlackTaskDB { + settings: Record = {}; + tasks: Record> = {}; + updated: Array<[number, Record]> = []; + + get_setting(key: string, defaultValue: string | null = null): string | null { + return this.settings[key] ?? defaultValue; + } + + set_setting(key: string, value: string): void { + this.settings[key] = value; + } + + get_task(task_id: number): Record | null { + return this.tasks[task_id] ?? null; + } + + update_task(task_id: number, updates: Record): void { + this.updated.push([task_id, updates]); + this.tasks[task_id] = { + ...(this.tasks[task_id] ?? { id: task_id }), + ...updates, + }; + } +} + +class StubScheduler { + submitted: Task[] = []; + + submit_task(task: Task): number { + this.submitted.push(task); + return this.submitted.length; + } +} + +function make_web_client() { + return { + auth_test: mock(async () => ({}) as Record), + chat_postMessage: mock(async (_args: any) => ({ ts: "1700.0001" }) as any), + reactions_add: mock(async (_args: any) => ({}) as any), + conversations_open: mock(async (_args: any) => ({}) as any), + }; +} + +type WebClientMock = ReturnType; + +function _make_channel(db?: StubDB, scheduler?: StubScheduler) { + const bus = new MessageBus(); + const the_db = db ?? new StubDB(); + const the_scheduler = scheduler ?? new StubScheduler(); + const channel = new SlackChannel( + bus, + the_db, + the_scheduler, + "xoxb-test", + "xapp-test", + ); + const web = make_web_client(); + channel._web_client = web; + channel._bot_user_id = "UBOT"; + return { channel, bus, db: the_db, scheduler: the_scheduler, web }; +} + +function last_text(web: WebClientMock): string { + return (web.chat_postMessage.mock.calls.at(-1)![0] as any).text; +} + +async function with_resolved_dir( + value: string, + fn: () => Promise, +): Promise { + const orig = dir_hooks.extract_working_dir_with_claude; + dir_hooks.extract_working_dir_with_claude = async () => value; + try { + return await fn(); + } finally { + dir_hooks.extract_working_dir_with_claude = orig; + } +} + +function capture_logs(): { logs: string[]; restore: () => void } { + const logs: string[] = []; + const orig = console.log; + console.log = (...args: unknown[]) => { + logs.push(args.map(String).join(" ")); + }; + return { + logs, + restore: () => { + console.log = orig; + }, + }; +} + +async function _wait_threads(): Promise { + await new Promise((r) => setTimeout(r, 0)); + await new Promise((r) => setTimeout(r, 0)); +} + +// ── _require_slack import guard ────────────────────────────────── + +test("test_require_slack_returns_sdk_symbols", async () => { + const { WebClient, SocketModeClient } = await _require_slack(); + // The real @slack packages are installed in this environment; just confirm + // the constructors are returned. (The TS SDK has no SocketModeResponse / + // SocketModeRequest classes; acks go through the adapter instead.) + expect(WebClient).toBeDefined(); + expect(SocketModeClient).toBeDefined(); +}); + +test("test_require_slack_raises_on_missing_dependency", async () => { + // Hide the slack SDK so the import inside _require_slack fails. + const orig = slack_hooks.import_slack; + slack_hooks.import_slack = async () => { + throw new Error("Cannot find package '@slack/web-api'"); + }; + try { + let error: Error | null = null; + try { + await _require_slack(); + throw new Error("expected import error"); + } catch (e) { + error = e as Error; + } + expect(String(error)).toContain("slack-sdk is required"); + } finally { + slack_hooks.import_slack = orig; + } +}); + +// ── start() Socket Mode bootstrap ──────────────────────────────── + +/** Build a stand-in slack SDK so start() runs without a real connection. */ +function _install_fake_slack_sdk(opts: { auth_raises?: boolean } = {}) { + class FakeWebClient { + token: string | undefined; + + constructor(token?: string) { + this.token = token; + } + + async auth_test(): Promise> { + if (opts.auth_raises) { + throw new Error("bad token"); + } + return { user_id: "UBOT99", team: "T1", user: "agentbot" }; + } + } + + class FakeSocketModeClient { + app_token: string | undefined; + web_client: unknown; + socket_mode_request_listeners: unknown[] = []; + connected = false; + + constructor(o: { app_token?: string; web_client?: unknown }) { + this.app_token = o.app_token; + this.web_client = o.web_client; + } + + connect(): void { + // No-op: never opens a real socket, returns immediately. + this.connected = true; + } + + disconnect(): void { + this.connected = false; + } + } + + const orig = slack_hooks.import_slack; + slack_hooks.import_slack = async () => + ({ + WebClient: FakeWebClient, + SocketModeClient: FakeSocketModeClient, + }) as unknown as SlackSDK; + return { + restore: () => { + slack_hooks.import_slack = orig; + }, + }; +} + +test("test_start_bootstraps_socket_mode", async () => { + const { restore } = _install_fake_slack_sdk(); + try { + const channel = new SlackChannel( + new MessageBus(), + new StubDB(), + new StubScheduler(), + "xoxb-real", + "xapp-real", + ); + await channel.start(); + + expect(channel._running).toBe(true); + expect(channel._bot_user_id).toBe("UBOT99"); + // Connected (no real network) and our listener registered. + expect((channel._socket_client as any).connected).toBe(true); + expect(channel._socket_client!.socket_mode_request_listeners).toContain( + channel._handle_socket_request, + ); + } finally { + restore(); + } +}); + +test("test_start_aborts_when_auth_test_fails", async () => { + const { restore } = _install_fake_slack_sdk({ auth_raises: true }); + try { + const channel = new SlackChannel( + new MessageBus(), + new StubDB(), + new StubScheduler(), + "xoxb-real", + "xapp-real", + ); + await channel.start(); + + // auth_test failed → bootstrap returns before creating the socket client. + expect(channel._bot_user_id).toBeNull(); + expect(channel._socket_client).toBeNull(); + } finally { + restore(); + } +}); + +// ── _handle_socket_request dispatch branches ───────────────────── + +test("test_socket_request_dispatches_mention", async () => { + const { channel, scheduler } = _make_channel(); + const client = { send_socket_mode_response: mock((_resp: any) => {}) }; + + const req = { + type: "events_api", + envelope_id: "envelope-mention-1", + payload: { + event: { + type: "app_mention", + user: "U1", + text: "<@UBOT> do the thing", + channel: "C1", + ts: "1.0", + }, + }, + }; + + await with_resolved_dir("~", () => + channel._handle_socket_request(client, req), + ); + expect(scheduler.submitted.length).toBe(1); + expect(scheduler.submitted[0]!.prompt).toBe("do the thing"); +}); + +test("test_socket_request_dispatches_app_home_opened", async () => { + const { channel, web } = _make_channel(); + web.conversations_open.mockImplementation(async () => ({ + channel: { id: "D9" }, + })); + const client = { send_socket_mode_response: mock((_resp: any) => {}) }; + + const req = { + type: "events_api", + envelope_id: "envelope-home-12345", + payload: { event: { type: "app_home_opened", user: "U2", tab: "home" } }, + }; + + await channel._handle_socket_request(client, req); + expect(last_text(web)).toContain("AgentForge Bot"); +}); + +test("test_socket_request_unhandled_event_type", async () => { + const { channel, scheduler } = _make_channel(); + const client = { send_socket_mode_response: mock((_resp: any) => {}) }; + + const req = { + type: "events_api", + envelope_id: "envelope-unknown-99", + payload: { event: { type: "reaction_added" } }, + }; + + await channel._handle_socket_request(client, req); + expect(client.send_socket_mode_response).toHaveBeenCalledTimes(1); + expect(scheduler.submitted.length).toBe(0); +}); + +test("test_socket_request_swallows_handler_exception", async () => { + const { channel } = _make_channel(); + const client = { send_socket_mode_response: mock((_resp: any) => {}) }; + + const req = { + type: "events_api", + envelope_id: "envelope-boom-123", + payload: { event: { type: "message", channel_type: "im" } }, + }; + + // Force the message handler to blow up so the except branch runs. + (channel as any)._handle_message_event = () => { + throw new Error("kaboom"); + }; + await channel._handle_socket_request(client, req); + // Ack still sent; exception is caught, not propagated. + expect(client.send_socket_mode_response).toHaveBeenCalledTimes(1); +}); + +// ── message/mention strip-prefix branches ──────────────────────── + +test("test_mention_without_prefix_keeps_text", async () => { + const { channel, scheduler } = _make_channel(); + // No leading "<@UBOT>" so the strip branch is skipped. + await with_resolved_dir("~", () => + channel._handle_mention_event({ + user: "U1", + text: "just build it", + channel: "C1", + ts: "2.0", + }), + ); + expect(scheduler.submitted[0]!.prompt).toBe("just build it"); +}); + +test("test_mention_when_bot_user_id_unset", async () => { + const { channel, scheduler } = _make_channel(); + channel._bot_user_id = null; // skip the "if self._bot_user_id" strip block + await with_resolved_dir("~", () => + channel._handle_mention_event({ + user: "U1", + text: "<@UX> hi", + channel: "C1", + ts: "3.0", + }), + ); + expect(scheduler.submitted[0]!.prompt).toBe("<@UX> hi"); +}); + +test("test_app_home_opened_ignores_self_and_empty_user", async () => { + const { channel, web } = _make_channel(); + await channel._handle_app_home_opened({ user: "UBOT", tab: "home" }); // self + await channel._handle_app_home_opened({ user: "", tab: "home" }); // empty + expect(web.chat_postMessage).not.toHaveBeenCalled(); +}); + +test("test_app_home_opened_dm_open_fails", async () => { + const { channel, web } = _make_channel(); + web.conversations_open.mockImplementation(async () => { + throw new Error("nope"); + }); + const { logs, restore } = capture_logs(); + try { + await channel._handle_app_home_opened({ user: "U7", tab: "home" }); + } finally { + restore(); + } + // _open_dm_channel returned null → the else branch logs a failure. + expect(logs.join("\n")).toContain("Failed to open DM channel"); + expect(web.chat_postMessage).not.toHaveBeenCalled(); +}); + +// ── _cmd_status error/result rendering ─────────────────────────── + +test("test_cmd_status_renders_error_only", async () => { + const db = new StubDB(); + db.tasks[3] = { + id: 3, + title: "Broke", + status: "failed", + created_at: "2026-01-01", + last_run_at: null, + error: "stack trace here", + result: null, + }; + const { channel, web } = _make_channel(db); + await channel._cmd_status("#3", "C1", "1.0"); + const text = last_text(web); + expect(text).toContain("Error:"); + expect(text).toContain("stack trace here"); + expect(text).not.toContain("Result:"); +}); + +// ── send() default-channel fallback message format ─────────────── + +test("test_send_default_channel_failure_prefixes_x_emoji", async () => { + const db = new StubDB(); + db.settings["slack_default_channel"] = "C-DEF"; + const { channel, web } = _make_channel(db); + + channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_FAILED, + task_id: 21, + payload: { title: "Job", error: "broke" }, + }), + ); + // _send_and_track runs detached; drain it. + await _wait_threads(); + + const call = web.chat_postMessage.mock.calls.at(-1)![0] as any; + expect(call.channel).toBe("C-DEF"); + expect(call.text).toContain(":x:"); + expect(call.text).toContain("broke"); + // The sent ts was tracked back to the task. + expect(channel._notification_map.get("1700.0001")).toBe(21); +}); + +test("test_send_dm_fallback_fails_to_open_skips", async () => { + const db = new StubDB(); + db.settings["slack_default_user"] = "U-DM"; + const { channel, web } = _make_channel(db); + web.conversations_open.mockImplementation(async () => { + throw new Error("denied"); + }); + + const { logs, restore } = capture_logs(); + try { + channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_COMPLETED, + task_id: 22, + payload: { title: "Job", result: "ok" }, + }), + ); + await _wait_threads(); + } finally { + restore(); + } + + expect(logs.join("\n")).toContain("Failed to open DM"); + expect(web.chat_postMessage).not.toHaveBeenCalled(); +}); + +// ── _on_outbound passthrough ───────────────────────────────────── + +test("test_on_outbound_delegates_to_send", () => { + const { channel } = _make_channel(); + const send = mock((_msg: any) => {}); + (channel as any).send = send; + const msg = makeOutboundMessage({ + type: OutboundMessageType.TASK_STARTED, + task_id: 1, + payload: {}, + }); + channel._on_outbound(msg); + expect(send).toHaveBeenCalledTimes(1); + expect(send.mock.calls[0]![0]).toBe(msg); +}); + +// ── helper no-web-client / failure guards ──────────────────────── + +test("test_open_dm_channel_returns_none_without_web_client", async () => { + const { channel } = _make_channel(); + channel._web_client = null; + expect(await channel._open_dm_channel("U1")).toBeNull(); +}); + +test("test_add_reaction_noop_without_web_client", () => { + const { channel } = _make_channel(); + channel._web_client = null; + // Should simply return without spawning anything or throwing. + channel._add_reaction("C1", "1.0", "eyes"); +}); + +test("test_add_reaction_handles_already_reacted_and_errors", async () => { + const { channel, web } = _make_channel(); + + // already_reacted is swallowed silently. + web.reactions_add.mockImplementation(async () => { + throw new Error("already_reacted"); + }); + channel._add_reaction("C1", "1.0", "eyes"); + + // other errors are logged. + web.reactions_add.mockImplementation(async () => { + throw new Error("rate_limited"); + }); + channel._add_reaction("C1", "1.0", "eyes"); + + await _wait_threads(); + expect(web.reactions_add).toHaveBeenCalledTimes(2); +}); + +test("test_reply_skips_without_web_client", async () => { + const { channel } = _make_channel(); + channel._web_client = null; + const { logs, restore } = capture_logs(); + try { + await channel._reply("C1", null, "hi"); + } finally { + restore(); + } + expect(logs.join("\n")).toContain("no web_client"); +}); + +test("test_reply_logs_postmessage_failure", async () => { + const { channel, web } = _make_channel(); + web.chat_postMessage.mockImplementation(async () => { + throw new Error("api down"); + }); + const { logs, restore } = capture_logs(); + try { + await channel._reply("C1", null, "hi"); + } finally { + restore(); + } + expect(logs.join("\n")).toContain("chat_postMessage FAILED"); +}); + +test("test_reply_return_ts_none_without_web_client", async () => { + const { channel } = _make_channel(); + channel._web_client = null; + expect(await channel._reply_return_ts("C1", null, "hi")).toBeNull(); +}); From 14a6380c2c3991244a14e423ce046f0942e11dd2 Mon Sep 17 00:00:00 2001 From: taohe Date: Sat, 13 Jun 2026 06:38:55 +0800 Subject: [PATCH 16/18] feat(backend): port Telegram channel to TypeScript with tests Co-Authored-By: Claude Fable 5 --- backend/src/channels/telegram.ts | 884 ++++++++++++++++++ backend/tests/telegram-channel.test.ts | 700 ++++++++++++++ .../tests/telegram-forwarded-messages.test.ts | 594 ++++++++++++ backend/tests/telegram-more.test.ts | 586 ++++++++++++ 4 files changed, 2764 insertions(+) create mode 100644 backend/src/channels/telegram.ts create mode 100644 backend/tests/telegram-channel.test.ts create mode 100644 backend/tests/telegram-forwarded-messages.test.ts create mode 100644 backend/tests/telegram-more.test.ts diff --git a/backend/src/channels/telegram.ts b/backend/src/channels/telegram.ts new file mode 100644 index 0000000..29051fb --- /dev/null +++ b/backend/src/channels/telegram.ts @@ -0,0 +1,884 @@ +/** + * Telegram channel for AgentForge — ported from channels/telegram_channel.py. + * + * Send any message to create a task. Reply to a completion/failure notification + * to resume that task. Slash commands also supported: + * + * /help — show help + * /status — task details + * /cancel — cancel a task + * /resume — resume a task with a message + * /dir — set default working directory + * + * When a task completes or fails the bot sends a notification to the chat where + * the task was created. + * + * Configuration via environment variables: + * TELEGRAM_BOT_TOKEN — required, bot token from @BotFather + * TELEGRAM_ALLOWED_USERS — optional, comma-separated Telegram user IDs + * (numeric). When set, any other user is rejected. + * + * Porting notes + * ───────────── + * The Python original uses the python-telegram-bot SDK (Application + Update + + * polling on a dedicated thread/event loop). This port talks to the raw + * Telegram Bot API over fetch instead: + * - a long-polling loop calls getUpdates with offset/timeout and routes + * message updates to the same handler logic as the Python handlers; + * - sending uses sendMessage / setMessageReaction directly. + * The HTTP transport is an injectable seam (`_api`, default = fetch against + * https://api.telegram.org/bot/) so tests can intercept calls + * exactly where the pytest suite mocked `Application.bot`. Method names and + * user-facing strings are kept byte-identical to the Python source. + * + * Threading-model mapping: + * _loop / _thread → _poll_promise (the async polling loop) + * _loop_ready (Event) → _ready (boolean, set when the loop starts) + * _app (Application) → _api (TelegramApi seam; null ≙ missing app) + * asyncio.run_coroutine_threadsafe(coro) → plain `await` (single runtime) + */ + +import { + Channel, + MessageBus, + OutboundMessageType, + type OutboundMessage, + type TaskDBLike, +} from "../bus.ts"; +import { makeTask, ScheduleType, type Task } from "../types.ts"; +import { + handle_agent_command, + resolve_agent, + type SettingsDB, +} from "./agent_utils.ts"; +import { handle_dir_command, resolve_working_dir } from "./dir_utils.ts"; + +// ≙ Python's try/except ImportError guard around the telegram SDK import. +// fetch is always available on Bun, so this is true by default; the setter is +// the test seam matching `monkeypatch.setattr(telegram_channel, +// "TELEGRAM_AVAILABLE", False)`. +export let TELEGRAM_AVAILABLE = true; + +export function _set_telegram_available(value: boolean): void { + TELEGRAM_AVAILABLE = value; +} + +export const HELP_TEXT = + "👋 *AgentForge Bot*\n\n" + + "Send me any message and I'll create a task from it\\.\n" + + "Reply to a completion/failure notification to resume that task\\.\n\n" + + "*Commands:*\n" + + "/status `` — task details\n" + + "/cancel `` — cancel a task\n" + + "/resume ` ` — resume a task\n" + + "/dir `` — set default working directory\n" + + "    e\\.g\\. `/dir ~/workspace/myproject`\n" + + "/agent `` — switch coding agent \\(`claude` / `codex`\\)\n" + + "/help — show this message\n\n" + + "*Tips:*\n" + + "• You can also mention a path in your message and it will be used automatically\\.\n" + + " e\\.g\\. _在 ~/myapp 里帮我修复登录 bug_\n" + + "• Reply to any result notification to continue the conversation\\."; + +// ── Bot-API-shaped update types ─────────────────────────────────── + +export interface TgUser { + id: number; + username?: string | null; + first_name?: string | null; + last_name?: string | null; +} + +export interface TgChat { + id: number | string; + type?: string | null; + title?: string | null; + username?: string | null; +} + +export interface TgMessage { + message_id: number; + text?: string | null; + chat: TgChat; + from?: TgUser | null; // sender (≙ update.effective_user) + reply_to_message?: { message_id: number } | null; + forward_from?: TgUser | null; + forward_from_chat?: TgChat | null; + forward_date?: number | null; +} + +export interface TgUpdate { + update_id?: number; + message?: TgMessage | null; +} + +/** ≙ python-telegram-bot's `context` — only `args` is ever used. */ +export interface TgContext { + args: string[]; +} + +// ── structural dependency interfaces ────────────────────────────── + +/** Minimal structural view of TaskDB used by this channel. */ +export interface TelegramDB extends TaskDBLike, SettingsDB { + update_task(task_id: number, updates: Record): void; +} + +/** + * Minimal structural view of TaskScheduler (do NOT import scheduler.ts — + * the channel only ever calls submit_task). + */ +export interface TelegramScheduler { + submit_task(task: Task): number; +} + +// ── injectable HTTP seam ────────────────────────────────────────── + +/** + * Calls a Telegram Bot API method and resolves with its `result` payload. + * Rejects on transport errors or when the API answers `ok: false`. + */ +export type TelegramApi = ( + method: string, + params?: Record, +) => Promise; + +/** Default TelegramApi implementation: fetch against api.telegram.org. */ +export function make_fetch_api(token: string): TelegramApi { + return async (method: string, params: Record = {}) => { + const resp = await fetch(`https://api.telegram.org/bot${token}/${method}`, { + method: "POST", + headers: { "content-type": "application/json" }, + body: JSON.stringify(params), + }); + const data = (await resp.json()) as { + ok?: boolean; + result?: unknown; + description?: string; + }; + if (!data.ok) { + throw new Error( + `Telegram API ${method} failed: ${data.description ?? `HTTP ${resp.status}`}`, + ); + } + return data.result; + }; +} + +function sleep(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +// ── TelegramChannel ─────────────────────────────────────────────── + +export class TelegramChannel extends Channel { + declare db: TelegramDB; + scheduler: TelegramScheduler; + _token: string; + _allowed_users: Set; + + /** HTTP seam (≙ self._app / self._app.bot); null ≙ app not built. */ + _api: TelegramApi | null; + /** ≙ self._loop_ready (threading.Event). */ + _ready = false; + /** ≙ self._thread — the long-polling loop's promise. */ + _poll_promise: Promise | null = null; + /** getUpdates offset (next update_id to fetch). */ + _offset = 0; + + // Maps task_id → (chat_id, reply_message_id, reaction_message_id) for reply-back and reactions + // reply_message_id: used for reply_to_message_id when posting completion + // reaction_message_id: used for adding emoji reactions (may differ on resume) + _task_origin: Map = new Map(); + + // Maps notification message_id → task_id for resume-by-reply + _notification_map: Map = new Map(); + + /** Slash-command routing table (≙ the CommandHandler registrations). */ + readonly _command_handlers: Record< + string, + (update: TgUpdate, context: TgContext) => Promise + >; + + constructor( + bus: MessageBus, + db: TelegramDB, + scheduler: TelegramScheduler, + token: string, + allowed_users: number[] | null = null, + ) { + super("telegram", bus, db); + this.scheduler = scheduler; + this._token = token; + this._allowed_users = new Set(allowed_users ?? []); + this._api = make_fetch_api(token); + + this._command_handlers = { + start: (u, c) => this._cmd_help(u, c), + help: (u, c) => this._cmd_help(u, c), + status: (u, c) => this._cmd_status(u, c), + cancel: (u, c) => this._cmd_cancel(u, c), + resume: (u, c) => this._cmd_resume(u, c), + }; + + // Subscribe to bus so send() is called on task updates + bus.subscribe_outbound(this._on_outbound); + } + + // ── lifecycle ──────────────────────────────────────────────── + + start(): void { + if (!TELEGRAM_AVAILABLE) { + console.log( + "[Telegram] python-telegram-bot not installed. Run: uv add python-telegram-bot", + ); + return; + } + this._running = true; + this._poll_promise = this._run_bot(); + console.log("[Telegram] Bot thread started"); + } + + stop(): void { + console.log("[Telegram] Stopping bot…"); + this._running = false; + this.bus.unsubscribe_outbound(this._on_outbound); + console.log("[Telegram] Bot stopped"); + } + + // ── Channel ABC: send outbound message ─────────────────────── + + /** + * MessageBus outbound subscriber callback. Arrow-function property so the + * reference passed to subscribe/unsubscribe is stable (≙ bound method). + */ + _on_outbound = (msg: OutboundMessage): void => { + void this.send(msg); + }; + + /** Forward a task completion/failure notification to the originating chat. */ + async send(msg: OutboundMessage): Promise { + if (!this._running) return; + if ( + msg.type !== OutboundMessageType.TASK_COMPLETED && + msg.type !== OutboundMessageType.TASK_FAILED + ) { + return; + } + if (!this._ready) { + console.log( + "[Telegram] send() called before event loop ready, dropping message", + ); + return; + } + if (!this._api) return; + const api = this._api; + + const task_id = msg.task_id; + const origin = this._task_origin.get(task_id); + + const title = + (msg.payload["title"] as string | null | undefined) || `Task #${task_id}`; + + const is_completed = msg.type === OutboundMessageType.TASK_COMPLETED; + let body: string; + if (is_completed) { + let result_text = ( + (msg.payload["result"] as string | null | undefined) || "" + ).trim(); + if (result_text.length > 10000) { + result_text = result_text.slice(0, 10000) + "\n…(truncated)"; + } + body = result_text || "Done."; + } else { + let error_text = ( + (msg.payload["error"] as string | null | undefined) || "Unknown error" + ).trim(); + // Smart truncation: keep beginning (most informative) and signal cut + if (error_text.length > 800) { + error_text = + error_text.slice(0, 800) + + "\n…(truncated — use /status for full details)"; + } + body = error_text; + } + + let chat_id: number | string; + let orig_message_id: number | null = null; + let reaction_message_id: number | null = null; + let text: string; + if (origin) { + [chat_id, orig_message_id, reaction_message_id] = origin; + // Always include task title and status emoji for clarity + const status_emoji = is_completed ? "✅" : "❌"; + text = `${status_emoji} Task #${task_id}: ${title}\n${body}`; + if (!is_completed) { + text += `\n\n/status ${task_id}`; + } + } else { + const default_chat_id = + this.db.get_setting("telegram_default_chat_id", "") ?? ""; + if (!default_chat_id) { + console.log( + `[Telegram] No origin and no telegram_default_chat_id configured for task #${task_id}, skipping`, + ); + return; + } + // ≙ str(default_chat_id).lstrip("-").isdigit() + chat_id = /^\d+$/.test(String(default_chat_id).replace(/^-+/, "")) + ? parseInt(String(default_chat_id), 10) + : default_chat_id; + const status_emoji = is_completed ? "✅" : "❌"; + text = `${status_emoji} Task #${task_id}: ${title}\n${body}`; + if (!is_completed) { + text += `\n\n/status ${task_id}`; + } + console.log( + `[Telegram] Using default chat_id=${chat_id} for task #${task_id}`, + ); + } + + // Free origin memory after terminal state (Python pops right after + // scheduling the coroutine; here we pop before awaiting the sends). + this._task_origin.delete(task_id); + + // ≙ the _send_and_track() coroutine + try { + const react_target = reaction_message_id ?? orig_message_id; + if (react_target) { + // Add emoji reaction to the message that triggered the task (or resume) + const emoji = + msg.type === OutboundMessageType.TASK_COMPLETED ? "👍" : "👎"; + try { + await api("setMessageReaction", { + chat_id, + message_id: react_target, + reaction: [{ type: "emoji", emoji }], + }); + } catch (e) { + console.log( + `[Telegram] Failed to set reaction on message ${react_target}: ${e}`, + ); + } + } + + const params: Record = { chat_id, text }; + if (orig_message_id !== null) + params["reply_to_message_id"] = orig_message_id; + const sent = (await api("sendMessage", params)) as + | { message_id: number } + | null + | undefined; + if (sent) { + this._notification_map.set(sent.message_id, task_id); + console.log( + `[Telegram] Notification msg_id=${sent.message_id} mapped to task #${task_id}`, + ); + } + } catch (e) { + console.log(`[Telegram] Failed to send notification to ${chat_id}: ${e}`); + } + } + + // ── private helpers ────────────────────────────────────────── + + /** Entry point for the polling loop (≙ the bot thread's _run_bot). */ + async _run_bot(): Promise { + this._ready = true; // ≙ self._loop_ready.set() + try { + await this._start_app(); + } catch (e) { + console.log(`[Telegram] Bot error: ${e}`); + } + } + + /** ≙ Application bootstrap + updater.start_polling(drop_pending_updates=True). */ + async _start_app(): Promise { + await this._drop_pending_updates(); + console.log("[Telegram] Bot polling started"); + + while (this._running) { + await this._poll_once(); + } + } + + /** Skip the pending-update backlog (≙ drop_pending_updates=True). */ + async _drop_pending_updates(): Promise { + if (!this._api) return; + try { + const updates = (await this._api("getUpdates", { + offset: -1, + timeout: 0, + })) as TgUpdate[] | null | undefined; + if (updates && updates.length > 0) { + const last = updates[updates.length - 1]!; + this._offset = (last.update_id ?? 0) + 1; + } + } catch (e) { + console.log(`[Telegram] Failed to drop pending updates: ${e}`); + } + } + + /** One getUpdates long-poll iteration; routes each update to the handlers. */ + async _poll_once(): Promise { + if (!this._api) return; + try { + const updates = (await this._api("getUpdates", { + offset: this._offset, + timeout: 30, + allowed_updates: ["message"], + })) as TgUpdate[] | null | undefined; + for (const update of updates ?? []) { + if (typeof update.update_id === "number") { + this._offset = update.update_id + 1; + } + try { + await this._handle_update(update); + } catch (e) { + console.log(`[Telegram] Error handling update: ${e}`); + } + } + } catch (e) { + console.log(`[Telegram] Polling error: ${e}`); + await sleep(1000); + } + } + + /** + * Route a Bot API update: registered slash commands go to their _cmd_* + * handler, all other text goes to _handle_text_message (which itself deals + * with /dir and /agent — same effective routing as the Python handlers). + */ + async _handle_update(update: TgUpdate): Promise { + const msg = update.message; + if (!msg || typeof msg.text !== "string" || !msg.text) return; + const text = msg.text.trim(); + if (text.startsWith("/")) { + const parts = text.split(/\s+/); + const cmd = parts[0]!.slice(1).split("@")[0]!.toLowerCase(); + const handler = this._command_handlers[cmd]; + if (handler) { + await handler(update, { args: parts.slice(1) }); + return; + } + } + await this._handle_text_message(update, { args: [] }); + } + + /** ≙ update.message.reply_text(...) */ + async _reply_text( + update: TgUpdate, + text: string, + extra: Record = {}, + ): Promise { + await this._api!("sendMessage", { + chat_id: update.message!.chat.id, + text, + ...extra, + }); + } + + async _send_text(chat_id: number | string, text: string): Promise { + try { + await this._api!("sendMessage", { chat_id, text }); + } catch (e) { + console.log(`[Telegram] Failed to send message to ${chat_id}: ${e}`); + } + } + + _is_allowed(user_id: number): boolean { + if (this._allowed_users.size === 0) return true; + return this._allowed_users.has(user_id); + } + + // ── unified text message handler ────────────────────────────── + + /** + * 格式化转发的消息文本,添加发送者和时间信息 + * + * @param text 消息文本 + * @param update Telegram Update 对象 + * @returns 格式化后的文本 + */ + _format_forwarded_text(text: string, update: TgUpdate): string { + const msg = update.message!; + const is_forwarded = msg.forward_from || msg.forward_date; + + if (!is_forwarded) return text; + + const parts: string[] = ["📨 [转发消息]"]; + + // 获取发送者信息 + let sender_name = "未知用户"; + if (msg.forward_from) { + const sender = msg.forward_from; + if (sender.username) { + sender_name = `@${sender.username}`; + } else { + const name_parts: string[] = [sender.first_name || ""]; + if (sender.last_name) { + name_parts.push(sender.last_name); + } + sender_name = name_parts.filter(Boolean).join(" "); + } + parts.push(`转发自: ${sender_name}`); + } else if (msg.forward_from_chat) { + const chat = msg.forward_from_chat; + sender_name = chat.title || chat.username || "未知频道"; + if (chat.type === "channel") { + parts.push(`转发自频道: ${sender_name}`); + } else if (chat.type === "group" || chat.type === "supergroup") { + parts.push(`转发自群组: ${sender_name}`); + } else { + parts.push(`转发自: ${sender_name}`); + } + } else { + parts.push(`转发自: ${sender_name}`); + } + + // 添加时间戳 (UTC+8, ≙ datetime.fromtimestamp(..., tz=timezone(timedelta(hours=8)))) + if (msg.forward_date) { + const d = new Date((msg.forward_date + 8 * 3600) * 1000); + const pad = (n: number) => String(n).padStart(2, "0"); + const ts = + `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())} ` + + `${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}`; + parts.push(`时间: ${ts}`); + } + + parts.push("\n--- 转发内容 ---"); + parts.push(text); + + return parts.join("\n"); + } + + /** Handle any non-command text: resume-by-reply or create task. */ + async _handle_text_message( + update: TgUpdate, + _context: TgContext, + ): Promise { + if (!this._is_allowed(update.message!.from!.id)) { + await this._reply_text( + update, + "⛔ You are not authorised to use this bot.", + ); + return; + } + + let text = (update.message!.text || "").trim(); + if (!text) return; + + // ── /dir command: switch working directory ───────────────── + const dir_reply = handle_dir_command(text, "telegram", this.db); + if (dir_reply !== null) { + await this._reply_text(update, dir_reply); + return; + } + + // ── /agent command: switch coding agent ────────────────── + const agent_reply = handle_agent_command(text, "telegram", this.db); + if (agent_reply !== null) { + await this._reply_text(update, agent_reply); + return; + } + + // ── 检测转发消息 ─────────────────────────────────────── + text = this._format_forwarded_text(text, update); + + const chat_id = update.message!.chat.id; + + // ── reply to a notification → resume task ───────────────── + const reply = update.message!.reply_to_message; + if (reply) { + const task_id = this._notification_map.get(reply.message_id); + if (task_id) { + const task = this.db.get_task(task_id); + if (task && task["session_id"]) { + this.db.update_task(task_id, { + status: "pending", + prompt: text, + result: null, + error: null, + question: null, + }); + this._task_origin.set(task_id, [ + chat_id, + update.message!.message_id, + update.message!.message_id, + ]); + + // Add "eyes" reaction and send resuming message + try { + await this._api!("setMessageReaction", { + chat_id, + message_id: update.message!.message_id, + reaction: [{ type: "emoji", emoji: "👀" }], + }); + } catch (e) { + console.log(`[Telegram] Failed to set resume reaction: ${e}`); + } + await this._reply_text(update, "▶️"); + console.log(`[Telegram] Auto-resuming task ${task_id} from reply`); + return; + } else { + await this._reply_text( + update, + `❌ Task #${task_id} has no saved session to resume.`, + ); + return; + } + } + } + + // ── default: create a new task ──────────────────────────── + await this._create_task(text, chat_id, update); + } + + /** Create a new task from any message text. */ + async _create_task( + text: string, + chat_id: number | string, + update: TgUpdate, + ): Promise { + const msg = update.message!; + + // 检查是否为转发消息,用于添加标题标记 + const is_forwarded = Boolean(msg.forward_from || msg.forward_date); + const title_prefix = is_forwarded ? "📨 " : ""; + const title = text.slice(0, 60) + (text.length > 60 ? "…" : ""); + + const working_dir = await resolve_working_dir(text, "telegram", this.db); + + const task = makeTask({ + title: `[Telegram] ${title_prefix}${title}`, + prompt: text, + working_dir, + schedule_type: ScheduleType.IMMEDIATE, + tags: "telegram" + (is_forwarded ? ", forwarded" : ""), + agent: resolve_agent("telegram", this.db), + }); + const task_id = this.scheduler.submit_task(task); + console.log( + `[Telegram] Task #${task_id} created from message${is_forwarded ? " (forwarded)" : ""}`, + ); + + const message_id = msg.message_id; + this._task_origin.set(task_id, [chat_id, message_id, message_id]); + + // Acknowledge with an "eyes" reaction and a brief running hint + // (≙ the _react() coroutine scheduled via run_coroutine_threadsafe) + try { + await this._api!("setMessageReaction", { + chat_id, + message_id, + reaction: [{ type: "emoji", emoji: "👀" }], + }); + await this._api!("sendMessage", { + chat_id, + text: `Task #${task_id} is running…`, + reply_to_message_id: message_id, + }); + } catch (e) { + console.log(`[Telegram] Failed to set reaction: ${e}`); + } + } + + // ── command handlers ────────────────────────────────────────── + + async _cmd_help(update: TgUpdate, _context: TgContext): Promise { + if (!this._is_allowed(update.message!.from!.id)) { + await this._reply_text( + update, + "⛔ You are not authorised to use this bot.", + ); + return; + } + await this._reply_text(update, HELP_TEXT, { parse_mode: "MarkdownV2" }); + } + + async _cmd_status(update: TgUpdate, context: TgContext): Promise { + if (!this._is_allowed(update.message!.from!.id)) { + await this._reply_text(update, "⛔ Not authorised."); + return; + } + + const arg0 = + context.args.length > 0 ? context.args[0]!.replace(/^#+/, "") : ""; + if (!/^\d+$/.test(arg0)) { + await this._reply_text(update, "Usage: /status "); + return; + } + + const task_id = parseInt(arg0, 10); + const task = this.db.get_task(task_id); + if (!task) { + await this._reply_text(update, `❌ Task #${task_id} not found.`); + return; + } + + const status_icon: Record = { + pending: "🕐", + scheduled: "📅", + running: "⏳", + completed: "✅", + failed: "❌", + cancelled: "🚫", + }; + const icon = status_icon[task["status"] as string] ?? "•"; + const lines = [ + `${icon} Task #${task_id} — ${task["status"]}`, + `${task["title"]}`, + `Created: ${String(task["created_at"] ?? "—").slice(0, 16)}`, + `Last run: ${String(task["last_run_at"] || "—").slice(0, 16)}`, + ]; + if (task["error"]) { + lines.push(`\nError: ${String(task["error"]).slice(0, 300)}`); + } + if (task["result"]) { + lines.push(`\nResult: ${String(task["result"]).slice(0, 500)}`); + } + + await this._reply_text(update, lines.join("\n")); + } + + async _cmd_cancel(update: TgUpdate, context: TgContext): Promise { + if (!this._is_allowed(update.message!.from!.id)) { + await this._reply_text(update, "⛔ Not authorised."); + return; + } + + const arg0 = + context.args.length > 0 ? context.args[0]!.replace(/^#+/, "") : ""; + if (!/^\d+$/.test(arg0)) { + await this._reply_text(update, "Usage: /cancel "); + return; + } + + const task_id = parseInt(arg0, 10); + const task = this.db.get_task(task_id); + if (!task) { + await this._reply_text(update, `❌ Task #${task_id} not found.`); + return; + } + const status = task["status"] as string; + if ( + status === "completed" || + status === "failed" || + status === "cancelled" + ) { + await this._reply_text( + update, + `ℹ️ Task #${task_id} is already ${status}.`, + ); + return; + } + + this.db.update_task(task_id, { status: "cancelled" }); + await this._reply_text(update, `🚫 Task #${task_id} cancelled.`); + } + + async _cmd_resume(update: TgUpdate, context: TgContext): Promise { + if (!this._is_allowed(update.message!.from!.id)) { + await this._reply_text(update, "⛔ Not authorised."); + return; + } + + const arg0 = + context.args.length > 0 ? context.args[0]!.replace(/^#+/, "") : ""; + if (!/^\d+$/.test(arg0)) { + await this._reply_text(update, "Usage: /resume "); + return; + } + + const tid = parseInt(arg0, 10); + const resume_msg = context.args.slice(1).join(" ").trim(); + if (!resume_msg) { + await this._reply_text( + update, + "Please provide a message to resume with.", + ); + return; + } + + const task = this.db.get_task(tid); + if (!task || !task["session_id"]) { + await this._reply_text( + update, + `❌ Task #${tid} not found or has no saved session.`, + ); + return; + } + + this.db.update_task(tid, { + status: "pending", + prompt: resume_msg, + result: null, + error: null, + question: null, + }); + const chat_id = update.message!.chat.id; + this._task_origin.set(tid, [ + chat_id, + update.message!.message_id, + update.message!.message_id, + ]); + + // Add "eyes" reaction to the user's command message + try { + await this._api!("setMessageReaction", { + chat_id, + message_id: update.message!.message_id, + reaction: [{ type: "emoji", emoji: "👀" }], + }); + } catch (e) { + console.log(`[Telegram] Failed to set resume reaction: ${e}`); + } + + await this._reply_text(update, "▶️"); + } +} + +// ── helpers ────────────────────────────────────────────────────────────────── + +/** Escape special MarkdownV2 characters. */ +export function _escape_md(text: string): string { + const special = "\\_*[]()~`>#+-=|{}.!"; + return [...text].map((c) => (special.includes(c) ? `\\${c}` : c)).join(""); +} + +// ── factory helper ─────────────────────────────────────────────────────────── + +/** Create a TelegramChannel from explicit params or environment variables. */ +export function create_telegram_channel( + db: TelegramDB, + scheduler: TelegramScheduler, + bus: MessageBus | null = null, + token: string = "", + allowed_users_str: string = "", +): TelegramChannel | null { + token = (token || process.env.TELEGRAM_BOT_TOKEN || "").trim(); + if (!token) return null; + + const allowed_raw = ( + allowed_users_str || + process.env.TELEGRAM_ALLOWED_USERS || + "" + ).trim(); + const allowed_users: number[] = []; + if (allowed_raw) { + for (const raw of allowed_raw.split(",")) { + const uid = raw.trim(); + if (/^\d+$/.test(uid)) { + allowed_users.push(parseInt(uid, 10)); + } + } + } + + return new TelegramChannel( + bus ?? new MessageBus(), + db, + scheduler, + token, + allowed_users, + ); +} diff --git a/backend/tests/telegram-channel.test.ts b/backend/tests/telegram-channel.test.ts new file mode 100644 index 0000000..c08ae35 --- /dev/null +++ b/backend/tests/telegram-channel.test.ts @@ -0,0 +1,700 @@ +// Ported from tests/test_telegram_channel.py (bun:test). +// +// The pytest suite mocked python-telegram-bot objects (Application/Update, +// AsyncMock bot). Here the channel talks to the raw Bot API through the +// injectable `_api` seam, so tests install a recording FakeApi and build plain +// Bot-API-shaped JSON update objects. `update.message.reply_text` assertions +// become assertions on recorded `sendMessage` calls; the patched +// `asyncio.run_coroutine_threadsafe` plumbing disappears because the TS port +// simply awaits its API calls. + +import { afterEach, beforeEach, expect, spyOn, test } from "bun:test"; + +import { + MessageBus, + makeOutboundMessage, + OutboundMessageType, +} from "../src/bus.ts"; +import { _hooks } from "../src/channels/dir_utils.ts"; +import { + _escape_md, + _set_telegram_available, + create_telegram_channel, + TelegramChannel, + type TelegramApi, + type TgContext, + type TgMessage, + type TgUpdate, +} from "../src/channels/telegram.ts"; +import type { Task } from "../src/types.ts"; + +// ── stubs (≙ the pytest StubDB / StubScheduler) ────────────────── + +class StubDB { + settings = new Map(); + tasks = new Map>(); + updated: Array<[number, Record]> = []; + + get_setting(key: string, defaultValue: string | null = null): string | null { + return this.settings.get(key) ?? defaultValue; + } + + set_setting(key: string, value: string): void { + this.settings.set(key, value); + } + + get_task(task_id: number): Record | null { + return this.tasks.get(task_id) ?? null; + } + + update_task(task_id: number, updates: Record): void { + this.updated.push([task_id, updates]); + const task = this.tasks.get(task_id) ?? { id: task_id }; + Object.assign(task, updates); + this.tasks.set(task_id, task); + } +} + +class StubScheduler { + submitted: Task[] = []; + + submit_task(task: Task): number { + this.submitted.push(task); + return this.submitted.length; + } +} + +// ── FakeApi: recording stand-in for the fetch seam (≙ AsyncMock bot) ── + +interface ApiCall { + method: string; + params: Record; +} + +class FakeApi { + calls: ApiCall[] = []; + results = new Map(); + errors = new Map(); + + fn: TelegramApi = async (method, params = {}) => { + this.calls.push({ method, params }); + const err = this.errors.get(method); + if (err) throw err; + if (this.results.has(method)) return this.results.get(method); + if (method === "getUpdates") return []; + return null; + }; + + callsFor(method: string): ApiCall[] { + return this.calls.filter((c) => c.method === method); + } + + lastText(method: string = "sendMessage"): string { + const calls = this.callsFor(method); + expect(calls.length).toBeGreaterThan(0); + return String(calls[calls.length - 1]!.params["text"]); + } +} + +// ── helpers ────────────────────────────────────────────────────── + +function _make_channel( + opts: { + db?: StubDB; + scheduler?: StubScheduler; + allowed_users?: number[] | null; + } = {}, +) { + const db = opts.db ?? new StubDB(); + const scheduler = opts.scheduler ?? new StubScheduler(); + const channel = new TelegramChannel( + new MessageBus(), + db, + scheduler, + "123:ABC", + opts.allowed_users ?? null, + ); + // Give it a fake API so async helpers can run without a real bot. + const api = new FakeApi(); + channel._api = api.fn; + return { channel, api, db, scheduler }; +} + +type FakeUpdate = TgUpdate & { message: TgMessage }; + +function _fake_update( + opts: { + text?: string; + user_id?: number; + chat_id?: number; + message_id?: number; + reply?: { message_id: number } | null; + } = {}, +): FakeUpdate { + const { + text = "hello", + user_id = 1, + chat_id = 10, + message_id = 100, + reply = null, + } = opts; + return { + message: { + message_id, + text, + chat: { id: chat_id }, + from: { id: user_id }, + reply_to_message: reply, + forward_from: null, + forward_from_chat: null, + forward_date: null, + }, + }; +} + +function _ctx(args: string[] = []): TgContext { + return { args }; +} + +function captureLog() { + const lines: string[] = []; + const spy = spyOn(console, "log").mockImplementation((...args: unknown[]) => { + lines.push(args.map(String).join(" ")); + }); + return { + text: () => lines.join("\n"), + restore: () => spy.mockRestore(), + }; +} + +function withEnvUnset(keys: string[], fn: () => T): T { + const saved: Record = {}; + for (const k of keys) { + saved[k] = process.env[k]; + delete process.env[k]; + } + try { + return fn(); + } finally { + for (const k of keys) { + if (saved[k] !== undefined) process.env[k] = saved[k]; + else delete process.env[k]; + } + } +} + +// Never let resolve_working_dir hit the real Anthropic extractor +// (≙ pytest patching channels.dir_utils.resolve_working_dir). +const _original_extract = _hooks.extract_working_dir_with_claude; +beforeEach(() => { + _hooks.extract_working_dir_with_claude = async () => null; +}); +afterEach(() => { + _hooks.extract_working_dir_with_claude = _original_extract; + _set_telegram_available(true); +}); + +// ── construction / factory ─────────────────────────────────────── + +test("test_init_sets_allowed_users", () => { + const { channel } = _make_channel({ allowed_users: [1, 2] }); + expect(channel._allowed_users).toEqual(new Set([1, 2])); + expect(channel.name).toBe("telegram"); + const listeners = ( + channel.bus as unknown as { _outbound_listeners: unknown[] } + )._outbound_listeners; + expect(listeners.includes(channel._on_outbound)).toBe(true); +}); + +test("test_create_telegram_channel_no_token_returns_none", () => { + withEnvUnset(["TELEGRAM_BOT_TOKEN"], () => { + expect( + create_telegram_channel(new StubDB(), new StubScheduler(), null, ""), + ).toBeNull(); + }); +}); + +test("test_create_telegram_channel_parses_allowed_users", () => { + const channel = create_telegram_channel( + new StubDB(), + new StubScheduler(), + null, + "123:ABC", + "10, 20 , bad, 30", + ); + expect(channel).not.toBeNull(); + expect(channel!._allowed_users).toEqual(new Set([10, 20, 30])); +}); + +test("test_create_telegram_channel_empty_allowed_users", () => { + withEnvUnset(["TELEGRAM_ALLOWED_USERS"], () => { + const channel = create_telegram_channel( + new StubDB(), + new StubScheduler(), + null, + "123:ABC", + "", + ); + expect(channel!._allowed_users).toEqual(new Set()); + }); +}); + +test("test_create_telegram_channel_from_env", () => { + const saved_token = process.env.TELEGRAM_BOT_TOKEN; + const saved_users = process.env.TELEGRAM_ALLOWED_USERS; + process.env.TELEGRAM_BOT_TOKEN = "999:ZZZ"; + process.env.TELEGRAM_ALLOWED_USERS = "5,6"; + try { + const channel = create_telegram_channel(new StubDB(), new StubScheduler()); + expect(channel).not.toBeNull(); + expect(channel!._token).toBe("999:ZZZ"); + expect(channel!._allowed_users).toEqual(new Set([5, 6])); + } finally { + if (saved_token !== undefined) process.env.TELEGRAM_BOT_TOKEN = saved_token; + else delete process.env.TELEGRAM_BOT_TOKEN; + if (saved_users !== undefined) + process.env.TELEGRAM_ALLOWED_USERS = saved_users; + else delete process.env.TELEGRAM_ALLOWED_USERS; + } +}); + +test("test_create_telegram_channel_makes_bus_when_none", () => { + const channel = create_telegram_channel( + new StubDB(), + new StubScheduler(), + null, + "123:ABC", + ); + expect(channel!.bus).not.toBeNull(); + expect(channel!.bus).toBeInstanceOf(MessageBus); +}); + +// ── allowed-user check ─────────────────────────────────────────── + +test("test_is_allowed", () => { + const { channel: open_channel } = _make_channel(); + expect(open_channel._is_allowed(999)).toBe(true); // no allowlist → all allowed + + const { channel: restricted } = _make_channel({ allowed_users: [42] }); + expect(restricted._is_allowed(42)).toBe(true); + expect(restricted._is_allowed(7)).toBe(false); +}); + +// ── escape helper ──────────────────────────────────────────────── + +test("test_escape_md", () => { + expect(_escape_md("a.b-c!")).toBe("a\\.b\\-c\\!"); + expect(_escape_md("plain")).toBe("plain"); +}); + +// ── forwarded-message formatting ───────────────────────────────── + +test("test_format_forwarded_not_forwarded_returns_text", () => { + const { channel } = _make_channel(); + const update = _fake_update({ text: "just text" }); + expect(channel._format_forwarded_text("just text", update)).toBe("just text"); +}); + +test("test_format_forwarded_from_user_with_username", () => { + const { channel } = _make_channel(); + const update = _fake_update(); + update.message.forward_from = { + id: 1, + username: "alice", + first_name: "Alice", + last_name: null, + }; + update.message.forward_date = 1700000000; + const out = channel._format_forwarded_text("body", update); + expect(out).toContain("📨 [转发消息]"); + expect(out).toContain("转发自: @alice"); + expect(out).toContain("--- 转发内容 ---"); + expect(out.endsWith("body")).toBe(true); + expect(out).toContain("时间:"); +}); + +test("test_format_forwarded_from_user_without_username", () => { + const { channel } = _make_channel(); + const update = _fake_update(); + update.message.forward_from = { + id: 1, + username: null, + first_name: "Bob", + last_name: "Lee", + }; + update.message.forward_date = null; + const out = channel._format_forwarded_text("body", update); + expect(out).toContain("转发自: Bob Lee"); +}); + +test("test_format_forwarded_from_channel_chat", () => { + const { channel } = _make_channel(); + const update = _fake_update(); + update.message.forward_from = null; + update.message.forward_date = 1700000000; + update.message.forward_from_chat = { + id: -1, + title: "News", + username: "news", + type: "channel", + }; + const out = channel._format_forwarded_text("body", update); + expect(out).toContain("转发自频道: News"); +}); + +test("test_format_forwarded_from_group_chat", () => { + const { channel } = _make_channel(); + const update = _fake_update(); + update.message.forward_from = null; + update.message.forward_date = 1700000000; + update.message.forward_from_chat = { + id: -1, + title: "Devs", + username: null, + type: "supergroup", + }; + const out = channel._format_forwarded_text("body", update); + expect(out).toContain("转发自群组: Devs"); +}); + +// ── text message handler ───────────────────────────────────────── + +test("test_handle_text_message_unauthorised", async () => { + const { channel, api } = _make_channel({ allowed_users: [42] }); + const update = _fake_update({ user_id: 7 }); + await channel._handle_text_message(update, _ctx()); + expect(api.callsFor("sendMessage").length).toBe(1); + expect(api.lastText()).toContain("not authorised"); +}); + +test("test_handle_text_message_empty_ignored", async () => { + const { channel, api, scheduler } = _make_channel(); + const update = _fake_update({ text: " " }); + await channel._handle_text_message(update, _ctx()); + expect(scheduler.submitted.length).toBe(0); + expect(api.callsFor("sendMessage").length).toBe(0); +}); + +test("test_handle_text_message_dir_command", async () => { + const { channel, api, db } = _make_channel(); + const update = _fake_update({ text: "/dir ~/proj" }); + await channel._handle_text_message(update, _ctx()); + expect(db.get_setting("telegram_default_working_dir")).toBe("~/proj"); + expect(api.callsFor("sendMessage").length).toBe(1); +}); + +test("test_handle_text_message_agent_command", async () => { + const { channel, db } = _make_channel(); + const update = _fake_update({ text: "/agent codex" }); + await channel._handle_text_message(update, _ctx()); + expect(db.get_setting("default_agent")).toBe("codex"); +}); + +test("test_handle_text_message_creates_task", async () => { + const { channel, scheduler } = _make_channel(); + _hooks.extract_working_dir_with_claude = async () => "~/app"; + const update = _fake_update({ text: "fix the bug" }); + await channel._handle_text_message(update, _ctx()); + expect(scheduler.submitted.length).toBe(1); + const task = scheduler.submitted[0]!; + expect(task.prompt).toBe("fix the bug"); + expect(task.title).toBe("[Telegram] fix the bug"); + expect(task.tags).toBe("telegram"); + expect(task.working_dir).toBe("~/app"); + expect(channel._task_origin.get(1)).toEqual([10, 100, 100]); +}); + +test("test_handle_text_message_resume_by_reply", async () => { + const { channel, api, db } = _make_channel(); + db.tasks.set(5, { id: 5, status: "completed", session_id: "s5" }); + channel._notification_map.set(200, 5); + const update = _fake_update({ + text: "continue", + message_id: 300, + reply: { message_id: 200 }, + }); + await channel._handle_text_message(update, _ctx()); + expect(db.updated[db.updated.length - 1]![0]).toBe(5); + expect(db.updated[db.updated.length - 1]![1]["prompt"]).toBe("continue"); + expect(channel._task_origin.get(5)).toEqual([10, 300, 300]); + expect(api.callsFor("setMessageReaction").length).toBeGreaterThan(0); + expect(api.lastText()).toBe("▶️"); +}); + +test("test_handle_text_message_resume_no_session", async () => { + const { channel, api, db } = _make_channel(); + db.tasks.set(6, { id: 6, status: "completed" }); // no session_id + channel._notification_map.set(201, 6); + const update = _fake_update({ text: "continue", reply: { message_id: 201 } }); + await channel._handle_text_message(update, _ctx()); + expect(db.updated).toEqual([]); + expect(api.lastText()).toContain("no saved session"); +}); + +test("test_handle_text_message_reply_unknown_notification_creates_task", async () => { + const { channel, scheduler } = _make_channel(); + const update = _fake_update({ + text: "new task", + reply: { message_id: 12345 }, + }); // not in notification_map + await channel._handle_text_message(update, _ctx()); + expect(scheduler.submitted.length).toBe(1); +}); + +test("test_create_task_forwarded_tags", async () => { + const { channel, scheduler } = _make_channel(); + const update = _fake_update({ text: "forwarded body" }); + update.message.forward_date = 1700000000; + await channel._create_task("forwarded body", 10, update); + const task = scheduler.submitted[0]!; + expect(task.tags).toContain("forwarded"); + expect(task.title.startsWith("[Telegram] 📨")).toBe(true); +}); + +// ── command handlers ───────────────────────────────────────────── + +test("test_cmd_help_authorised_and_not", async () => { + const { channel, api } = _make_channel({ allowed_users: [1] }); + const ok = _fake_update({ user_id: 1 }); + await channel._cmd_help(ok, _ctx()); + expect(api.callsFor("sendMessage").length).toBe(1); + + const denied = _fake_update({ user_id: 99 }); + await channel._cmd_help(denied, _ctx()); + expect(api.lastText()).toContain("not authorised"); +}); + +test("test_cmd_status_usage_and_not_found", async () => { + const { channel, api } = _make_channel(); + const u = _fake_update(); + await channel._cmd_status(u, _ctx([])); + expect(api.lastText()).toContain("Usage"); + + const u2 = _fake_update(); + await channel._cmd_status(u2, _ctx(["99"])); + expect(api.lastText()).toContain("not found"); +}); + +test("test_cmd_status_renders", async () => { + const { channel, api, db } = _make_channel(); + db.tasks.set(7, { + id: 7, + title: "Build it", + status: "completed", + created_at: "2026-01-01T10:00:00", + last_run_at: "2026-01-02T11:00:00", + result: "green", + error: null, + }); + const u = _fake_update(); + await channel._cmd_status(u, _ctx(["#7"])); + const text = api.lastText(); + expect(text).toContain("✅"); + expect(text).toContain("Task #7"); + expect(text).toContain("green"); +}); + +test("test_cmd_status_unauthorised", async () => { + const { channel, api } = _make_channel({ allowed_users: [1] }); + const u = _fake_update({ user_id: 2 }); + await channel._cmd_status(u, _ctx(["1"])); + expect(api.lastText()).toContain("Not authorised"); +}); + +test("test_cmd_cancel_paths", async () => { + const { channel, api, db } = _make_channel(); + db.tasks.set(1, { id: 1, title: "t", status: "running" }); + db.tasks.set(2, { id: 2, title: "t", status: "completed" }); + + await channel._cmd_cancel(_fake_update(), _ctx([])); + expect(api.lastText()).toContain("Usage"); + + await channel._cmd_cancel(_fake_update(), _ctx(["99"])); + expect(api.lastText()).toContain("not found"); + + await channel._cmd_cancel(_fake_update(), _ctx(["2"])); + expect(api.lastText()).toContain("already"); + + await channel._cmd_cancel(_fake_update(), _ctx(["1"])); + expect(db.updated[db.updated.length - 1]).toEqual([ + 1, + { status: "cancelled" }, + ]); + expect(api.lastText()).toContain("cancelled"); +}); + +test("test_cmd_resume_paths", async () => { + const { channel, api, db } = _make_channel(); + db.tasks.set(1, { id: 1, title: "t", status: "completed", session_id: "s1" }); + db.tasks.set(2, { id: 2, title: "t", status: "completed" }); + + await channel._cmd_resume(_fake_update(), _ctx([])); + expect(api.lastText()).toContain("Usage"); + + await channel._cmd_resume(_fake_update(), _ctx(["1"])); + expect(api.lastText()).toContain("provide a message"); + + await channel._cmd_resume(_fake_update(), _ctx(["2", "go"])); + expect(api.lastText()).toContain("no saved session"); + + await channel._cmd_resume( + _fake_update({ message_id: 555 }), + _ctx(["#1", "keep", "going"]), + ); + expect(db.updated[db.updated.length - 1]![0]).toBe(1); + expect(db.updated[db.updated.length - 1]![1]["prompt"]).toBe("keep going"); + expect(channel._task_origin.get(1)).toEqual([10, 555, 555]); + expect(api.lastText()).toBe("▶️"); +}); + +test("test_cmd_resume_unauthorised", async () => { + const { channel, api } = _make_channel({ allowed_users: [1] }); + const u = _fake_update({ user_id: 2 }); + await channel._cmd_resume(u, _ctx(["1", "x"])); + expect(api.lastText()).toContain("Not authorised"); +}); + +// ── outbound send ──────────────────────────────────────────────── + +function _patch_loop(channel: TelegramChannel): void { + channel._ready = true; // ≙ channel._loop_ready.set() + channel._running = true; +} + +test("test_send_completion_to_origin", async () => { + const { channel, api } = _make_channel(); + _patch_loop(channel); + channel._task_origin.set(3, [10, 100, 100]); + api.results.set("sendMessage", { message_id: 777 }); + + await channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_COMPLETED, + task_id: 3, + payload: { title: "Fix login", result: "done" }, + }), + ); + + expect(api.callsFor("sendMessage").length).toBe(1); + const text = api.lastText(); + expect(text).toContain("✅ Task #3: Fix login"); + expect(text).toContain("done"); + expect(channel._notification_map.get(777)).toBe(3); + expect(channel._task_origin.has(3)).toBe(false); +}); + +test("test_send_failure_to_origin", async () => { + const { channel, api } = _make_channel(); + _patch_loop(channel); + channel._task_origin.set(4, [10, 100, 100]); + api.results.set("sendMessage", { message_id: 1 }); + + await channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_FAILED, + task_id: 4, + payload: { title: "Broke", error: "boom" }, + }), + ); + + const text = api.lastText(); + expect(text).toContain("❌ Task #4: Broke"); + expect(text).toContain("boom"); + expect(text).toContain("/status 4"); +}); + +test("test_send_not_running_drops", async () => { + const { channel, api } = _make_channel(); + channel._running = false; + await channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_COMPLETED, + task_id: 1, + payload: {}, + }), + ); + expect(api.calls.length).toBe(0); +}); + +test("test_send_ignores_non_terminal", async () => { + const { channel, api } = _make_channel(); + _patch_loop(channel); + await channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_STARTED, + task_id: 1, + payload: {}, + }), + ); + expect(api.calls.length).toBe(0); +}); + +test("test_send_uses_default_chat_id", async () => { + const { channel, api, db } = _make_channel(); + db.settings.set("telegram_default_chat_id", "-100123"); + _patch_loop(channel); + api.results.set("sendMessage", { message_id: 2 }); + + await channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_COMPLETED, + task_id: 8, + payload: { title: "Job", result: "ok" }, + }), + ); + + const sends = api.callsFor("sendMessage"); + expect(sends.length).toBe(1); + expect(sends[0]!.params["chat_id"]).toBe(-100123); +}); + +test("test_send_no_origin_no_default_skips", async () => { + const { channel, api } = _make_channel(); + _patch_loop(channel); + const log = captureLog(); + try { + await channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_COMPLETED, + task_id: 9, + payload: { title: "Job", result: "ok" }, + }), + ); + } finally { + log.restore(); + } + expect(api.calls.length).toBe(0); +}); + +test("test_send_truncates_long_result", async () => { + const { channel, api } = _make_channel(); + _patch_loop(channel); + channel._task_origin.set(10, [10, 100, 100]); + api.results.set("sendMessage", { message_id: 3 }); + const long = "x".repeat(20000); + + await channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_COMPLETED, + task_id: 10, + payload: { title: "Big", result: long }, + }), + ); + + expect(api.lastText()).toContain("(truncated)"); +}); + +// ── lifecycle ──────────────────────────────────────────────────── + +test("test_start_without_telegram", () => { + _set_telegram_available(false); + const { channel } = _make_channel(); + const log = captureLog(); + try { + channel.start(); + } finally { + log.restore(); + _set_telegram_available(true); + } + expect(log.text()).toContain("not installed"); +}); diff --git a/backend/tests/telegram-forwarded-messages.test.ts b/backend/tests/telegram-forwarded-messages.test.ts new file mode 100644 index 0000000..8c32b84 --- /dev/null +++ b/backend/tests/telegram-forwarded-messages.test.ts @@ -0,0 +1,594 @@ +// Ported from tests/test_telegram_forwarded_messages.py (bun:test). +// +// Tests for Telegram forwarded message handling functionality. +// +// The pytest file built MockUser/MockChat/MockMessage dataclasses mimicking +// python-telegram-bot objects; here the equivalents are plain Bot-API-shaped +// JSON objects. Where Python patched the Task class to inspect constructor +// kwargs, the TS port asserts on the Task object handed to the scheduler stub. + +import { afterEach, beforeEach, describe, expect, test } from "bun:test"; + +import { MessageBus } from "../src/bus.ts"; +import { _hooks } from "../src/channels/dir_utils.ts"; +import { + TelegramChannel, + type TelegramApi, + type TgChat, + type TgMessage, + type TgUpdate, + type TgUser, +} from "../src/channels/telegram.ts"; +import type { Task } from "../src/types.ts"; + +// ── stubs ──────────────────────────────────────────────────────── + +class StubDB { + settings = new Map(); + tasks = new Map>(); + updated: Array<[number, Record]> = []; + + get_setting(key: string, defaultValue: string | null = null): string | null { + return this.settings.get(key) ?? defaultValue; + } + + set_setting(key: string, value: string): void { + this.settings.set(key, value); + } + + get_task(task_id: number): Record | null { + return this.tasks.get(task_id) ?? null; + } + + update_task(task_id: number, updates: Record): void { + this.updated.push([task_id, updates]); + } +} + +class StubScheduler { + submitted: Task[] = []; + + submit_task(task: Task): number { + this.submitted.push(task); + return this.submitted.length; + } +} + +const silentApi: TelegramApi = async () => null; + +/** ≙ the mock_telegram_channel pytest fixture. */ +function mock_telegram_channel() { + const db = new StubDB(); + const scheduler = new StubScheduler(); + const channel = new TelegramChannel( + new MessageBus(), + db, + scheduler, + "fake_token", + null, + ); + // Mock the app and loop (≙ channel._app / channel._loop / _loop_ready mocks). + channel._api = silentApi; + channel._ready = true; + return { channel, db, scheduler }; +} + +// ── Mock Telegram objects (≙ MockUser / MockChat / MockMessage) ── + +function MockUser(o: { + id: number; + first_name: string; + last_name?: string; + username?: string; +}): TgUser { + return { + id: o.id, + first_name: o.first_name, + last_name: o.last_name ?? "", + username: o.username ?? "", + }; +} + +function MockChat(o: { + id: number; + type?: string; + title?: string; + username?: string; +}): TgChat { + return { + id: o.id, + type: o.type ?? "private", + title: o.title ?? "", + username: o.username ?? "", + }; +} + +function MockMessage(o: { + message_id: number; + text: string; + from_user: TgUser; + chat: TgChat; + forward_from?: TgUser | null; + forward_from_chat?: TgChat | null; + forward_date?: number | null; +}): TgMessage { + return { + message_id: o.message_id, + text: o.text, + from: o.from_user, + chat: o.chat, + forward_from: o.forward_from ?? null, + forward_from_chat: o.forward_from_chat ?? null, + forward_date: o.forward_date ?? null, + reply_to_message: null, + }; +} + +function makeUpdate(message: TgMessage): TgUpdate & { message: TgMessage } { + return { message }; +} + +// Keep resolve_working_dir off the network (≙ db.get_setting.return_value = "~"). +const _original_extract = _hooks.extract_working_dir_with_claude; +beforeEach(() => { + _hooks.extract_working_dir_with_claude = async () => null; +}); +afterEach(() => { + _hooks.extract_working_dir_with_claude = _original_extract; +}); + +// ── Test detection of forwarded messages in Telegram updates ──── + +describe("TestTelegramForwardMessageDetection", () => { + test("test_format_forwarded_text_from_user", () => { + // Test formatting a message forwarded from a user. + const { channel } = mock_telegram_channel(); + const forward_user = MockUser({ + id: 12345, + first_name: "Alice", + last_name: "Smith", + username: "alice_smith", + }); + + const message = MockMessage({ + message_id: 100, + text: "Original message content", + from_user: MockUser({ id: 999, first_name: "Bob" }), + chat: MockChat({ id: 888, type: "private" }), + forward_from: forward_user, + forward_date: 1738080000, + }); + + const result = channel._format_forwarded_text( + "Original message content", + makeUpdate(message), + ); + + expect(result).toContain("📨 [转发消息]"); + expect(result).toContain("转发自: @alice_smith"); + expect(result).toContain("时间: 2025-01-29 00:00"); + expect(result).toContain("--- 转发内容 ---"); + expect(result).toContain("Original message content"); + }); + + test("test_format_forwarded_text_from_user_no_username", () => { + // Test formatting when forwarded user has no username. + const { channel } = mock_telegram_channel(); + const forward_user = MockUser({ + id: 12345, + first_name: "张三", + last_name: "李四", + username: "", + }); + + const message = MockMessage({ + message_id: 100, + text: "测试消息", + from_user: MockUser({ id: 999, first_name: "王五" }), + chat: MockChat({ id: 888, type: "private" }), + forward_from: forward_user, + forward_date: 1738080000, + }); + + const result = channel._format_forwarded_text( + "测试消息", + makeUpdate(message), + ); + + expect(result).toContain("转发自: 张三 李四"); + }); + + test("test_format_forwarded_text_from_user_only_firstname", () => { + // Test formatting when forwarded user has only first name. + const { channel } = mock_telegram_channel(); + const forward_user = MockUser({ + id: 12345, + first_name: "Charlie", + last_name: "", + username: "", + }); + + const message = MockMessage({ + message_id: 100, + text: "Message", + from_user: MockUser({ id: 999, first_name: "Dave" }), + chat: MockChat({ id: 888, type: "private" }), + forward_from: forward_user, + forward_date: 1738080000, + }); + + const result = channel._format_forwarded_text( + "Message", + makeUpdate(message), + ); + + expect(result).toContain("转发自: Charlie"); + }); + + test("test_format_forwarded_text_from_channel", () => { + // Test formatting a message forwarded from a channel. + const { channel } = mock_telegram_channel(); + const forward_chat = MockChat({ + id: -100123456789, + type: "channel", + title: "Tech News", + username: "technews", + }); + + const message = MockMessage({ + message_id: 100, + text: "Breaking news: API update", + from_user: MockUser({ id: 999, first_name: "Reader" }), + chat: MockChat({ id: 888, type: "private" }), + forward_from_chat: forward_chat, + forward_date: 1738083600, + }); + + const result = channel._format_forwarded_text( + "Breaking news: API update", + makeUpdate(message), + ); + + expect(result).toContain("📨 [转发消息]"); + expect(result).toContain("转发自频道: Tech News"); + }); + + test("test_format_forwarded_text_from_group", () => { + // Test formatting a message forwarded from a group. + const { channel } = mock_telegram_channel(); + const forward_chat = MockChat({ + id: -100987654321, + type: "supergroup", + title: "Python Developers", + username: "", + }); + + const message = MockMessage({ + message_id: 100, + text: "Check this code snippet", + from_user: MockUser({ id: 999, first_name: "Dev" }), + chat: MockChat({ id: 888, type: "private" }), + forward_from_chat: forward_chat, + forward_date: 1738087200, + }); + + const result = channel._format_forwarded_text( + "Check this code snippet", + makeUpdate(message), + ); + + expect(result).toContain("转发自群组: Python Developers"); + }); + + test("test_format_forwarded_text_from_chat_no_title", () => { + // Test formatting when forwarded chat has no title. + const { channel } = mock_telegram_channel(); + const forward_chat = MockChat({ + id: -100111222333, + type: "group", + title: "", + username: "unknown_group", + }); + + const message = MockMessage({ + message_id: 100, + text: "Message", + from_user: MockUser({ id: 999, first_name: "User" }), + chat: MockChat({ id: 888, type: "private" }), + forward_from_chat: forward_chat, + forward_date: 1738080000, + }); + + const result = channel._format_forwarded_text( + "Message", + makeUpdate(message), + ); + + expect(result).toContain("转发自群组: unknown_group"); + }); + + test("test_format_forwarded_text_no_timestamp", () => { + // Test formatting when forward_date is missing. + const { channel } = mock_telegram_channel(); + const forward_user = MockUser({ id: 12345, first_name: "Sender" }); + + const message = MockMessage({ + message_id: 100, + text: "Message", + from_user: MockUser({ id: 999, first_name: "User" }), + chat: MockChat({ id: 888, type: "private" }), + forward_from: forward_user, + forward_date: null, + }); + + const result = channel._format_forwarded_text( + "Message", + makeUpdate(message), + ); + + expect(result).toContain("📨 [转发消息]"); + expect(result).toContain("转发自:"); + // Should not have time component + expect(result).not.toContain("时间:"); + }); + + test("test_format_forwarded_text_not_forwarded", () => { + // Test that regular messages are unchanged. + const { channel } = mock_telegram_channel(); + const message = MockMessage({ + message_id: 100, + text: "Regular message", + from_user: MockUser({ id: 999, first_name: "User" }), + chat: MockChat({ id: 888, type: "private" }), + }); + + const result = channel._format_forwarded_text( + "Regular message", + makeUpdate(message), + ); + + expect(result).toBe("Regular message"); + expect(result).not.toContain("转发"); + }); + + test("test_format_forwarded_text_fallback_to_generic_sender", () => { + // Test formatting when forwarded info is incomplete. + const { channel } = mock_telegram_channel(); + const message = MockMessage({ + message_id: 100, + text: "Message", + from_user: MockUser({ id: 999, first_name: "User" }), + chat: MockChat({ id: 888, type: "private" }), + forward_from: null, + forward_from_chat: null, + forward_date: 1738080000, + }); + + // The message has forward_date but no forward_from or forward_from_chat. + // This is technically possible in Telegram API. + const result = channel._format_forwarded_text( + "Message", + makeUpdate(message), + ); + + // Should still show it's forwarded with timestamp + expect(result).toContain("📨 [转发消息]"); + expect(result).toContain("时间: 2025-01-29 00:00"); + }); +}); + +// ── Test task creation from forwarded messages ─────────────────── + +describe("TestTelegramForwardedTaskCreation", () => { + test("test_create_task_from_forwarded_message", async () => { + // Test that forwarded messages create tasks with appropriate tags. + const { channel, scheduler } = mock_telegram_channel(); + const forward_user = MockUser({ + id: 12345, + first_name: "Alice", + username: "alice", + }); + + const message = MockMessage({ + message_id: 100, + text: "Analyze this forwarded post", + from_user: MockUser({ id: 999, first_name: "Bob" }), + chat: MockChat({ id: 888, type: "private" }), + forward_from: forward_user, + forward_date: 1738080000, + }); + const update = makeUpdate(message); + + // Format the text first (as done in _handle_text_message) + const formatted_text = channel._format_forwarded_text( + message.text!, + update, + ); + + // Call _create_task + await channel._create_task(formatted_text, 888, update); + + // Verify Task was created with forwarded tag + expect(scheduler.submitted.length).toBe(1); + const task = scheduler.submitted[0]!; + expect(task.tags).toContain(", forwarded"); + expect(task.title).toContain("📨 "); + }); + + test("test_create_task_from_normal_message", async () => { + // Test that normal messages create tasks without forwarded tag. + const { channel, scheduler } = mock_telegram_channel(); + const message = MockMessage({ + message_id: 100, + text: "Regular task", + from_user: MockUser({ id: 999, first_name: "Bob" }), + chat: MockChat({ id: 888, type: "private" }), + }); + const update = makeUpdate(message); + + // Call _create_task + await channel._create_task("Regular task", 888, update); + + // Verify Task was created without forwarded tag + expect(scheduler.submitted.length).toBe(1); + const task = scheduler.submitted[0]!; + expect(task.tags).toBe("telegram"); + expect(task.title).not.toContain("📨 "); + }); +}); + +// ── Test real-world scenarios of forwarded messages ────────────── + +describe("TestTelegramForwardedMessageScenarios", () => { + test("test_user_forwards_news_article", () => { + // Simulate a user forwarding a news article from a channel. + const { channel } = mock_telegram_channel(); + const forward_chat = MockChat({ + id: -100123456789, + type: "channel", + title: "Breaking News", + }); + + const message = MockMessage({ + message_id: 100, + text: "Stock market hits all-time high amid tech rally...", + from_user: MockUser({ id: 999, first_name: "Investor" }), + chat: MockChat({ id: 888, type: "private" }), + forward_from_chat: forward_chat, + forward_date: 1738080000, + }); + + const result = channel._format_forwarded_text( + message.text!, + makeUpdate(message), + ); + + expect(result).toContain("转发自频道: Breaking News"); + expect(result).toContain("Stock market hits all-time high"); + }); + + test("test_user_forwards_another_users_code", () => { + // Simulate forwarding code snippet from another user. + const { channel } = mock_telegram_channel(); + const forward_user = MockUser({ + id: 12345, + first_name: "Dev", + username: "cool_dev", + }); + + const message = MockMessage({ + message_id: 100, + text: "```python\ndef hello():\n print('world')\n```", + from_user: MockUser({ id: 999, first_name: "Learner" }), + chat: MockChat({ id: 888, type: "private" }), + forward_from: forward_user, + forward_date: 1738083600, + }); + + const result = channel._format_forwarded_text( + message.text!, + makeUpdate(message), + ); + + expect(result).toContain("转发自: @cool_dev"); + expect(result).toContain("def hello():"); + }); + + test("test_forwarded_multiline_message", () => { + // Test handling of forwarded messages with multiple lines. + const { channel } = mock_telegram_channel(); + const forward_user = MockUser({ id: 12345, first_name: "Announcer" }); + + const text = + "This is a forwarded message\n" + + "with multiple lines\n" + + "and some bullet points:\n" + + "- Point 1\n" + + "- Point 2\n" + + "- Point 3"; + + const message = MockMessage({ + message_id: 100, + text, + from_user: MockUser({ id: 999, first_name: "Receiver" }), + chat: MockChat({ id: 888, type: "private" }), + forward_from: forward_user, + forward_date: 1738087200, + }); + + const result = channel._format_forwarded_text(text, makeUpdate(message)); + + expect(result).toContain("转发自: Announcer"); + expect(result).toContain("--- 转发内容 ---"); + expect(result).toContain("Point 1"); + expect(result).toContain("Point 3"); + }); + + test("test_empty_text_with_forward", () => { + // Test when forwarded message has no text (e.g., media-only). + const { channel } = mock_telegram_channel(); + const forward_user = MockUser({ id: 12345, first_name: "Sender" }); + + const message = MockMessage({ + message_id: 100, + text: "", // Empty text, maybe just a photo + from_user: MockUser({ id: 999, first_name: "User" }), + chat: MockChat({ id: 888, type: "private" }), + forward_from: forward_user, + forward_date: 1738080000, + }); + + const result = channel._format_forwarded_text("", makeUpdate(message)); + + expect(result).toContain("📨 [转发消息]"); + expect(result).toContain("转发自: Sender"); + expect(result).toContain("--- 转发内容 ---"); + }); +}); + +// ── Integration tests for the complete forwarded message flow ──── + +describe("TestTelegramForwardedMessageIntegration", () => { + test("test_complete_forwarded_message_flow", async () => { + // Test the complete flow from forwarded message to task creation. + const { channel, scheduler } = mock_telegram_channel(); + + // Setup + const forward_user = MockUser({ + id: 12345, + first_name: "Alice", + username: "alice", + }); + const current_user = MockUser({ id: 999, first_name: "Bob" }); + const chat = MockChat({ id: 888, type: "private" }); + + const message = MockMessage({ + message_id: 100, + text: "Review this code", + from_user: current_user, + chat, + forward_from: forward_user, + forward_date: 1738080000, + }); + const update = makeUpdate(message); + + // Execute text formatting + // Note: We're simulating just the text processing part + const formatted_text = channel._format_forwarded_text( + message.text!, + update, + ); + + // Verify formatting + expect(formatted_text).toContain("📨 [转发消息]"); + expect(formatted_text).toContain("转发自: @alice"); + expect(formatted_text).toContain("Review this code"); + + // Task creation would normally happen next + await channel._create_task(formatted_text, 888, update); + + // Verify task was created with forwarded content + expect(scheduler.submitted.length).toBe(1); + expect(scheduler.submitted[0]!.prompt).toBe(formatted_text); + }); +}); diff --git a/backend/tests/telegram-more.test.ts b/backend/tests/telegram-more.test.ts new file mode 100644 index 0000000..ae142d7 --- /dev/null +++ b/backend/tests/telegram-more.test.ts @@ -0,0 +1,586 @@ +// Ported from tests/test_telegram_more.py (bun:test). +// +// Additional Telegram channel coverage: +// - the import-availability guard +// - start()/_run_bot/_start_app bootstrap (SDK bootstrap → polling bootstrap) +// - _send_text helper (success + failure) +// - send() early-exit + reaction/send error branches and default-chat-id path +// - _format_forwarded_text "unknown chat type" fallback +// - reaction-failure print branches in resume/create +// - command edge cases (status error-only render, cancel unauthorised, +// resume reaction failure) +// +// Python's threading/event-loop assertions (run_coroutine_threadsafe call +// counts, loop.is_closed) map onto the TS port's _poll_promise/_ready seam. + +import { afterEach, beforeEach, expect, spyOn, test } from "bun:test"; + +import { + MessageBus, + makeOutboundMessage, + OutboundMessageType, +} from "../src/bus.ts"; +import { _hooks } from "../src/channels/dir_utils.ts"; +import { + TELEGRAM_AVAILABLE, + TelegramChannel, + type TelegramApi, + type TgContext, + type TgMessage, + type TgUpdate, +} from "../src/channels/telegram.ts"; +import type { Task } from "../src/types.ts"; + +// ── stubs (≙ the pytest StubDB / StubScheduler) ────────────────── + +class StubDB { + settings = new Map(); + tasks = new Map>(); + updated: Array<[number, Record]> = []; + + get_setting(key: string, defaultValue: string | null = null): string | null { + return this.settings.get(key) ?? defaultValue; + } + + set_setting(key: string, value: string): void { + this.settings.set(key, value); + } + + get_task(task_id: number): Record | null { + return this.tasks.get(task_id) ?? null; + } + + update_task(task_id: number, updates: Record): void { + this.updated.push([task_id, updates]); + const task = this.tasks.get(task_id) ?? { id: task_id }; + Object.assign(task, updates); + this.tasks.set(task_id, task); + } +} + +class StubScheduler { + submitted: Task[] = []; + + submit_task(task: Task): number { + this.submitted.push(task); + return this.submitted.length; + } +} + +interface ApiCall { + method: string; + params: Record; +} + +class FakeApi { + calls: ApiCall[] = []; + results = new Map(); + errors = new Map(); + + fn: TelegramApi = async (method, params = {}) => { + this.calls.push({ method, params }); + const err = this.errors.get(method); + if (err) throw err; + if (this.results.has(method)) return this.results.get(method); + if (method === "getUpdates") return []; + return null; + }; + + callsFor(method: string): ApiCall[] { + return this.calls.filter((c) => c.method === method); + } + + lastText(method: string = "sendMessage"): string { + const calls = this.callsFor(method); + expect(calls.length).toBeGreaterThan(0); + return String(calls[calls.length - 1]!.params["text"]); + } +} + +function _make_channel( + opts: { + db?: StubDB; + scheduler?: StubScheduler; + allowed_users?: number[] | null; + } = {}, +) { + const db = opts.db ?? new StubDB(); + const scheduler = opts.scheduler ?? new StubScheduler(); + const channel = new TelegramChannel( + new MessageBus(), + db, + scheduler, + "123:ABC", + opts.allowed_users ?? null, + ); + const api = new FakeApi(); + channel._api = api.fn; + return { channel, api, db, scheduler }; +} + +type FakeUpdate = TgUpdate & { message: TgMessage }; + +function _fake_update( + opts: { + text?: string; + user_id?: number; + chat_id?: number; + message_id?: number; + reply?: { message_id: number } | null; + } = {}, +): FakeUpdate { + const { + text = "hello", + user_id = 1, + chat_id = 10, + message_id = 100, + reply = null, + } = opts; + return { + message: { + message_id, + text, + chat: { id: chat_id }, + from: { id: user_id }, + reply_to_message: reply, + forward_from: null, + forward_from_chat: null, + forward_date: null, + }, + }; +} + +function _ctx(args: string[] = []): TgContext { + return { args }; +} + +function captureLog() { + const lines: string[] = []; + const spy = spyOn(console, "log").mockImplementation((...args: unknown[]) => { + lines.push(args.map(String).join(" ")); + }); + return { + text: () => lines.join("\n"), + restore: () => spy.mockRestore(), + }; +} + +const _original_extract = _hooks.extract_working_dir_with_claude; +beforeEach(() => { + _hooks.extract_working_dir_with_claude = async () => null; +}); +afterEach(() => { + _hooks.extract_working_dir_with_claude = _original_extract; +}); + +// ── import-availability guard ──────────────────────────────────── + +test("test_telegram_available_flag_is_boolean", () => { + // The module imported fine; the flag reflects whether the transport is usable. + expect(typeof TELEGRAM_AVAILABLE).toBe("boolean"); +}); + +// ── stop() lifecycle ───────────────────────────────────────────── + +test("test_stop_shuts_down_app_and_joins_thread", async () => { + const { channel } = _make_channel(); + channel._running = true; + // Real polling loop present → stop() must let it terminate (≙ thread join). + let finished = false; + channel._poll_promise = (async () => { + while (channel._running) { + await new Promise((resolve) => setTimeout(resolve, 1)); + } + finished = true; + })(); + + const log = captureLog(); + try { + channel.stop(); + } finally { + log.restore(); + } + await channel._poll_promise; // ≙ channel._thread.join() + + expect(channel._running).toBe(false); + expect(finished).toBe(true); + // Outbound subscription removed. + const listeners = ( + channel.bus as unknown as { _outbound_listeners: unknown[] } + )._outbound_listeners; + expect(listeners.includes(channel._on_outbound)).toBe(false); +}); + +test("test_stop_without_loop_is_safe", () => { + const { channel } = _make_channel(); + channel._poll_promise = null; + channel._api = null; + const log = captureLog(); + try { + channel.stop(); // no polling loop running, nothing to join + } finally { + log.restore(); + } + expect(channel._running).toBe(false); +}); + +// ── start() / _run_bot / _start_app bootstrap ──────────────────── + +test("test_start_spawns_thread_and_runs_loop", async () => { + // Drive start() with _start_app stubbed so nothing connects. The real bot + // loop would block; the stub returns at once and we await the poll promise + // (≙ joining the thread) to confirm it finishes cleanly. + const { channel } = _make_channel(); + + const started: Record = {}; + channel._start_app = async () => { + // Mimic real _start_app: mark ready, then return at once (no polling). + started["ran"] = true; + }; + + const log = captureLog(); + try { + channel.start(); + } finally { + log.restore(); + } + expect(channel._running).toBe(true); + expect(channel._poll_promise).not.toBeNull(); + await channel._poll_promise; // ≙ thread.join(timeout=5) + expect(started["ran"]).toBe(true); + // _run_bot marked the loop ready and completed without error. + expect(channel._ready).toBe(true); +}); + +test("test_run_bot_handles_start_app_exception", async () => { + const { channel } = _make_channel(); + + channel._start_app = async () => { + throw new Error("startup failed"); + }; + + const log = captureLog(); + try { + await channel._run_bot(); + } finally { + log.restore(); + } + expect(log.text()).toContain("Bot error"); + // The loop completed (≙ channel._loop.is_closed() is True). + expect(channel._ready).toBe(true); +}); + +test("test_start_app_builds_application_and_registers_handlers", async () => { + // Exercise _start_app: drop pending updates, start polling, exit loop. + const { channel, api } = _make_channel(); + // _running starts False so the `while self._running` loop is skipped and + // _start_app proceeds straight past the polling bootstrap — no hang. + channel._running = false; + + const log = captureLog(); + try { + await channel._start_app(); + } finally { + log.restore(); + } + + // drop_pending_updates=True ≙ one initial getUpdates backlog fetch. + expect(api.callsFor("getUpdates").length).toBe(1); + expect(log.text()).toContain("Bot polling started"); + // Handlers were registered (5 commands; the message handler is the + // _handle_update text fallthrough). + expect(Object.keys(channel._command_handlers).length).toBe(5); +}); + +// ── _send_text helper ──────────────────────────────────────────── + +test("test_send_text_success", async () => { + const { channel, api } = _make_channel(); + await channel._send_text(42, "hi there"); + const sends = api.callsFor("sendMessage"); + expect(sends.length).toBe(1); + expect(sends[0]!.params).toEqual({ chat_id: 42, text: "hi there" }); +}); + +test("test_send_text_logs_failure", async () => { + const { channel, api } = _make_channel(); + api.errors.set("sendMessage", new Error("network")); + const log = captureLog(); + try { + await channel._send_text(42, "hi"); + } finally { + log.restore(); + } + expect(log.text()).toContain("Failed to send message to 42"); +}); + +// ── send() early-exit branches ─────────────────────────────────── + +test("test_send_drops_when_loop_not_ready", async () => { + const { channel, api } = _make_channel(); + channel._running = true; + // _ready never set → send() drops the message immediately. + const log = captureLog(); + try { + await channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_COMPLETED, + task_id: 1, + payload: {}, + }), + ); + } finally { + log.restore(); + } + expect(api.calls.length).toBe(0); + expect(log.text()).toContain("before event loop ready"); +}); + +test("test_send_drops_when_app_or_loop_missing", async () => { + const { channel, api } = _make_channel(); + channel._running = true; + channel._ready = true; + channel._api = null; // ≙ channel._app = None + await channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_COMPLETED, + task_id: 1, + payload: {}, + }), + ); + expect(api.calls.length).toBe(0); +}); + +// ── send() coroutine body: reaction + truncation + reaction failure ── + +function _patch_loop(channel: TelegramChannel): void { + channel._ready = true; + channel._running = true; +} + +test("test_send_completion_reaction_failure_still_sends", async () => { + // When setMessageReaction rejects, the except branch logs and sending the + // message proceeds. + const { channel, api } = _make_channel(); + _patch_loop(channel); + channel._task_origin.set(5, [10, 100, 100]); + + api.errors.set("setMessageReaction", new Error("no react")); + api.results.set("sendMessage", { message_id: 900 }); + + const log = captureLog(); + try { + await channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_COMPLETED, + task_id: 5, + payload: { title: "Job", result: "done" }, + }), + ); + } finally { + log.restore(); + } + + expect(log.text()).toContain("Failed to set reaction on message 100"); + expect(api.callsFor("sendMessage").length).toBe(1); + expect(channel._notification_map.get(900)).toBe(5); +}); + +test("test_send_failure_default_chat_includes_status_link", async () => { + // Default-chat-id failure path covers the no-origin branch and error body. + const { channel, api, db } = _make_channel(); + db.settings.set("telegram_default_chat_id", "-100777"); + _patch_loop(channel); + api.results.set("sendMessage", { message_id: 2 }); + + const log = captureLog(); + try { + await channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_FAILED, + task_id: 8, + payload: { title: "Broke", error: "x".repeat(1500) }, + }), + ); + } finally { + log.restore(); + } + + const text = api.lastText(); + expect(text).toContain("❌ Task #8: Broke"); + expect(text).toContain("truncated"); // error > 800 → smart truncation + expect(text).toContain("/status 8"); +}); + +test("test_send_coroutine_swallows_send_failure", async () => { + const { channel, api } = _make_channel(); + _patch_loop(channel); + channel._task_origin.set(9, [10, 100, 100]); + + api.errors.set("sendMessage", new Error("send down")); + + const log = captureLog(); + try { + await channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_COMPLETED, + task_id: 9, + payload: { title: "Job", result: "ok" }, + }), + ); + } finally { + log.restore(); + } + expect(log.text()).toContain("Failed to send notification"); +}); + +test("test_send_default_chat_id_non_numeric_string", async () => { + const { channel, api, db } = _make_channel(); + db.settings.set("telegram_default_chat_id", "@mychannel"); + _patch_loop(channel); + api.results.set("sendMessage", { message_id: 3 }); + + const log = captureLog(); + try { + await channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_COMPLETED, + task_id: 11, + payload: { title: "Job", result: "ok" }, + }), + ); + } finally { + log.restore(); + } + // Non-numeric chat id stays a string (not int-cast). + const sends = api.callsFor("sendMessage"); + expect(sends[sends.length - 1]!.params["chat_id"]).toBe("@mychannel"); +}); + +// ── _format_forwarded_text unknown chat type ───────────────────── + +test("test_format_forwarded_from_unknown_chat_type", () => { + const { channel } = _make_channel(); + const update = _fake_update(); + update.message.forward_date = 1700000000; + update.message.forward_from_chat = { + id: -1, + title: "Mystery", + username: null, + type: "private", + }; + const out = channel._format_forwarded_text("body", update); + // type not channel/group/supergroup → generic "转发自:" line. + expect(out).toContain("转发自: Mystery"); +}); + +// ── resume-by-reply reaction failure branch ────────────────────── + +test("test_resume_by_reply_reaction_failure_logged", async () => { + const { channel, api, db } = _make_channel(); + db.tasks.set(5, { id: 5, status: "completed", session_id: "s5" }); + channel._notification_map.set(200, 5); + api.errors.set("setMessageReaction", new Error("no react")); + const update = _fake_update({ + text: "continue", + message_id: 300, + reply: { message_id: 200 }, + }); + + const log = captureLog(); + try { + await channel._handle_text_message(update, _ctx()); + } finally { + log.restore(); + } + + expect(db.updated[db.updated.length - 1]![0]).toBe(5); + expect(log.text()).toContain("Failed to set resume reaction"); + expect(api.lastText()).toBe("▶️"); +}); + +// ── _create_task react coroutine ───────────────────────────────── + +test("test_create_task_react_coroutine_runs", async () => { + const { channel, api } = _make_channel(); + const update = _fake_update({ + text: "build it", + chat_id: 10, + message_id: 100, + }); + + const log = captureLog(); + try { + await channel._create_task("build it", 10, update); + } finally { + log.restore(); + } + + expect(api.callsFor("setMessageReaction").length).toBe(1); + expect(api.callsFor("sendMessage").length).toBe(1); + expect(api.lastText()).toContain("running"); +}); + +test("test_create_task_react_coroutine_logs_failure", async () => { + const { channel, api } = _make_channel(); + const update = _fake_update({ text: "build it" }); + api.errors.set("setMessageReaction", new Error("nope")); + + const log = captureLog(); + try { + await channel._create_task("build it", 10, update); + } finally { + log.restore(); + } + expect(log.text()).toContain("Failed to set reaction"); +}); + +// ── _cmd_status error-only render ──────────────────────────────── + +test("test_cmd_status_renders_error_only", async () => { + const { channel, api, db } = _make_channel(); + db.tasks.set(7, { + id: 7, + title: "Broke", + status: "failed", + created_at: "2026-01-01T10:00:00", + last_run_at: null, + error: "stack trace", + result: null, + }); + const u = _fake_update(); + await channel._cmd_status(u, _ctx(["7"])); + const text = api.lastText(); + expect(text).toContain("Error: stack trace"); + expect(text).not.toContain("Result:"); +}); + +// ── _cmd_cancel unauthorised ───────────────────────────────────── + +test("test_cmd_cancel_unauthorised", async () => { + const { channel, api } = _make_channel({ allowed_users: [1] }); + const u = _fake_update({ user_id: 2 }); + await channel._cmd_cancel(u, _ctx(["1"])); + expect(api.lastText()).toContain("Not authorised"); +}); + +// ── _cmd_resume reaction failure branch ────────────────────────── + +test("test_cmd_resume_reaction_failure_logged", async () => { + const { channel, api, db } = _make_channel(); + db.tasks.set(1, { id: 1, title: "t", status: "completed", session_id: "s1" }); + api.errors.set("setMessageReaction", new Error("no react")); + const u = _fake_update({ message_id: 555 }); + + const log = captureLog(); + try { + await channel._cmd_resume(u, _ctx(["#1", "keep", "going"])); + } finally { + log.restore(); + } + + expect(db.updated[db.updated.length - 1]![0]).toBe(1); + expect(db.updated[db.updated.length - 1]![1]["prompt"]).toBe("keep going"); + expect(log.text()).toContain("Failed to set resume reaction"); + expect(api.lastText()).toBe("▶️"); +}); From 1b99b1267c15d63b1054348772ef7273b16d4229 Mon Sep 17 00:00:00 2001 From: taohe Date: Sat, 13 Jun 2026 06:42:27 +0800 Subject: [PATCH 17/18] test(backend): port executor/scheduler/skills test suites (164 tests) Co-Authored-By: Claude Fable 5 --- backend/tests/codex-streaming-events.test.ts | 343 ++++++++ backend/tests/execute-task.test.ts | 786 +++++++++++++++++++ backend/tests/gaps.test.ts | 331 ++++++++ backend/tests/gaps2.test.ts | 590 ++++++++++++++ backend/tests/scheduler-logic.test.ts | 745 ++++++++++++++++++ backend/tests/scheduler-more.test.ts | 786 +++++++++++++++++++ backend/tests/skill-patterns.test.ts | 261 ++++++ 7 files changed, 3842 insertions(+) create mode 100644 backend/tests/codex-streaming-events.test.ts create mode 100644 backend/tests/execute-task.test.ts create mode 100644 backend/tests/gaps.test.ts create mode 100644 backend/tests/gaps2.test.ts create mode 100644 backend/tests/scheduler-logic.test.ts create mode 100644 backend/tests/scheduler-more.test.ts create mode 100644 backend/tests/skill-patterns.test.ts diff --git a/backend/tests/codex-streaming-events.test.ts b/backend/tests/codex-streaming-events.test.ts new file mode 100644 index 0000000..676c9fd --- /dev/null +++ b/backend/tests/codex-streaming-events.test.ts @@ -0,0 +1,343 @@ +// Codex NDJSON streaming-event parsing and generated-image handling. +// +// Ported from tests/test_codex_streaming_events.py; test() descriptions keep +// the Python test function names. +// +// The Python suite builds `TaskScheduler(Mock())` and replaces +// `db.add_output_event` with a Mock; here the db seam is a stub object that +// records every add_output_event call. + +import { afterEach, beforeEach, describe, expect, test } from "bun:test"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import type { TaskDB } from "../src/db.ts"; +import { TaskScheduler } from "../src/scheduler.ts"; + +type Row = Record; + +interface StubbedScheduler { + scheduler: TaskScheduler; + /** Every db.add_output_event(...) call's positional args. */ + stored: any[][]; +} + +function _scheduler(): StubbedScheduler { + const stored: any[][] = []; + const db = { + add_output_event: (...args: any[]) => { + stored.push(args); + }, + } as unknown as TaskDB; + const scheduler = new TaskScheduler(db); + return { scheduler, stored }; +} + +function addListener(scheduler: TaskScheduler): any[][] { + const calls: any[][] = []; + scheduler.add_output_listener((...args) => { + calls.push(args); + }); + return calls; +} + +describe("codex streaming events", () => { + let tmpDir: string; + let savedCodexHome: string | undefined; + + beforeEach(() => { + tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "agentforge-test-")); + savedCodexHome = process.env.CODEX_HOME; + }); + + afterEach(() => { + if (savedCodexHome === undefined) delete process.env.CODEX_HOME; + else process.env.CODEX_HOME = savedCodexHome; + fs.rmSync(tmpDir, { recursive: true, force: true }); + }); + + test("test_codex_item_updated_cumulative_text_emits_only_deltas", () => { + const { scheduler, stored } = _scheduler(); + const listener = addListener(scheduler); + + const events = [ + { + type: "item.updated", + item: { id: "msg_1", type: "agent_message", text: "Hel" }, + }, + { + type: "item.updated", + item: { id: "msg_1", type: "agent_message", text: "Hello " }, + }, + { + type: "item.updated", + item: { id: "msg_1", type: "agent_message", text: "Hello world" }, + }, + { + type: "item.completed", + item: { id: "msg_1", type: "agent_message", text: "Hello world" }, + }, + ]; + + for (const event of events) { + scheduler._parse_and_store_event(1, 2, JSON.stringify(event), "codex"); + } + + expect(stored.map((c) => c[3])).toEqual(["Hel", "lo ", "world"]); + expect(listener.map((c) => c[3])).toEqual(["Hel", "lo ", "world"]); + }); + + test("test_codex_item_updated_delta_text_does_not_duplicate_completed_text", () => { + const { scheduler, stored } = _scheduler(); + const listener = addListener(scheduler); + + const events = [ + { + type: "item.updated", + delta: { text: "Hello" }, + item: { id: "msg_1", type: "agent_message" }, + }, + { + type: "item.updated", + delta: { text: " world" }, + item: { id: "msg_1", type: "agent_message" }, + }, + { + type: "item.completed", + item: { id: "msg_1", type: "agent_message", text: "Hello world" }, + }, + ]; + + for (const event of events) { + scheduler._parse_and_store_event(1, 2, JSON.stringify(event), "codex"); + } + + expect(stored.map((c) => c[3])).toEqual(["Hello", " world"]); + expect(listener.map((c) => c[3])).toEqual(["Hello", " world"]); + }); + + test("test_codex_reasoning_updated_text_does_not_duplicate_completed_text", () => { + const { scheduler, stored } = _scheduler(); + const listener = addListener(scheduler); + + const events = [ + { + type: "item.updated", + delta: { text: "Think" }, + item: { id: "reasoning_1", type: "reasoning" }, + }, + { + type: "item.updated", + delta: { text: " carefully" }, + item: { id: "reasoning_1", type: "reasoning" }, + }, + { + type: "item.completed", + item: { id: "reasoning_1", type: "reasoning", text: "Think carefully" }, + }, + ]; + + for (const event of events) { + scheduler._parse_and_store_event(1, 2, JSON.stringify(event), "codex"); + } + + expect(stored.map((c) => c[3])).toEqual([ + "[thinking] Think", + "[thinking] carefully", + ]); + expect(listener.map((c) => c[3])).toEqual([ + "[thinking] Think", + "[thinking] carefully", + ]); + }); + + test("test_codex_command_execution_is_stored_and_streamed", () => { + const { scheduler, stored } = _scheduler(); + const listener = addListener(scheduler); + + const event = { + type: "item.completed", + item: { + id: "cmd_1", + type: "command_execution", + command: "pytest -q", + aggregated_output: "42 passed", + exit_code: 0, + status: "completed", + }, + }; + + scheduler._parse_and_store_event(1, 2, JSON.stringify(event), "codex"); + + expect(stored.length).toBe(1); + const [task_id, run_id, event_type, content] = stored[0]!; + expect([task_id, run_id, event_type]).toEqual([1, 2, "command_execution"]); + expect(JSON.parse(content)).toEqual({ + id: "cmd_1", + command: "pytest -q", + output: "42 passed", + exit_code: 0, + status: "completed", + }); + expect(listener.length).toBe(1); + expect(listener[0]).toEqual([1, 2, "command_execution", content]); + }); + + test("test_codex_mcp_tool_call_is_stored_and_streamed_with_redacted_arguments", () => { + const { scheduler, stored } = _scheduler(); + const listener = addListener(scheduler); + + const event = { + type: "item.completed", + item: { + id: "mcp_1", + type: "mcp_tool_call", + server: "github", + tool: "search_issues", + arguments: { + query: "is:open", + token: "ghp_secret", + }, + result: { total_count: 1 }, + status: "completed", + }, + }; + + scheduler._parse_and_store_event(1, 2, JSON.stringify(event), "codex"); + + const [task_id, run_id, event_type, content] = stored[stored.length - 1]!; + expect([task_id, run_id, event_type]).toEqual([1, 2, "tool_call"]); + expect(JSON.parse(content)).toEqual({ + id: "mcp_1", + server: "github", + name: "search_issues", + input: { + query: "is:open", + token: "[redacted]", + }, + result: { total_count: 1 }, + status: "completed", + }); + expect(listener.length).toBe(1); + expect(listener[0]).toEqual([1, 2, "tool_call", content]); + }); + + test("test_codex_web_search_and_file_change_events_are_stored_and_streamed", () => { + const { scheduler, stored } = _scheduler(); + const listener = addListener(scheduler); + + const events = [ + { + type: "item.completed", + item: { + id: "search_1", + type: "web_search", + query: "AgentForge taskboard", + action: "search", + }, + }, + { + type: "item.completed", + item: { + id: "file_1", + type: "file_change", + changes: [{ path: "taskboard.py", kind: "modified" }], + status: "completed", + }, + }, + ]; + + for (const event of events) { + scheduler._parse_and_store_event(1, 2, JSON.stringify(event), "codex"); + } + + const parsed = stored.map((c) => [c[2], JSON.parse(c[3])]); + expect(parsed).toEqual([ + [ + "web_search", + { + id: "search_1", + query: "AgentForge taskboard", + action: "search", + }, + ], + [ + "file_change", + { + id: "file_1", + changes: [{ path: "taskboard.py", kind: "modified" }], + status: "completed", + }, + ], + ]); + expect(listener.map((c) => c[2])).toEqual(["web_search", "file_change"]); + }); + + test("test_codex_empty_final_message_uses_generated_images_not_raw_json", () => { + const codex_home = path.join(tmpDir, "codex"); + const thread_id = "019e6224-test"; + const image_dir = path.join(codex_home, "generated_images", thread_id); + fs.mkdirSync(image_dir, { recursive: true }); + const image_path = path.join(image_dir, "skills-overview.png"); + fs.writeFileSync( + image_path, + Buffer.concat([ + Buffer.from([0x89]), + Buffer.from("PNG\r\n"), + Buffer.from([0x1a, 0x0a]), + Buffer.from("fakepng"), + ]), + ); + process.env.CODEX_HOME = codex_home; + + const raw_stdout = [ + JSON.stringify({ type: "thread.started", thread_id }), + JSON.stringify({ + type: "item.completed", + item: { id: "msg_1", type: "agent_message", text: "" }, + }), + JSON.stringify({ type: "turn.completed", usage: { output_tokens: 10 } }), + ].join("\n"); + + const { scheduler } = _scheduler(); + const generated_images = scheduler._find_codex_generated_images(thread_id); + const output = scheduler._extract_codex_success_output( + raw_stdout, + generated_images, + ); + + expect(generated_images).toEqual([image_path]); + expect(output).toBe(`已生成 1 张图片:\n- ${image_path}`); + expect(output).not.toContain("thread.started"); + expect(output).not.toContain("item.completed"); + }); + + test("test_store_generated_image_events_adds_path_and_renderable_image", () => { + const image_path = path.join(tmpDir, "result.png"); + fs.writeFileSync( + image_path, + Buffer.concat([ + Buffer.from([0x89]), + Buffer.from("PNG\r\n"), + Buffer.from([0x1a, 0x0a]), + Buffer.from("fakepng"), + ]), + ); + + const { scheduler, stored } = _scheduler(); + scheduler._store_generated_image_events(1, 2, [image_path]); + + const parsed: Array<[string, Row]> = stored.map((c) => [ + c[2], + JSON.parse(c[3]), + ]); + expect(parsed[0]).toEqual([ + "generated_image", + { path: image_path, media_type: "image/png" }, + ]); + expect(parsed[1]![0]).toBe("image_content"); + expect(parsed[1]![1]["path"]).toBe(image_path); + expect(parsed[1]![1]["media_type"]).toBe("image/png"); + expect(parsed[1]![1]["data"]).toBeTruthy(); + }); +}); diff --git a/backend/tests/execute-task.test.ts b/backend/tests/execute-task.test.ts new file mode 100644 index 0000000..0538fb0 --- /dev/null +++ b/backend/tests/execute-task.test.ts @@ -0,0 +1,786 @@ +// Hermetic tests for the agent subprocess execution + stream-parsing paths. +// +// Ported from tests/test_execute_task.py; test() descriptions keep the Python +// test function names. +// +// Strategy: swap the injectable seams (`TaskScheduler._popen` ≙ subprocess.Popen, +// `TaskScheduler._os` ≙ os.getpgid/killpg, `AgentExecutor.subprocess_run` ≙ +// subprocess.run) with finite fakes so the read loops always terminate. A real +// TaskDB on a tmp-dir SQLite file lets us assert the persisted run status and +// the parsed output events afterwards. + +import { afterEach, beforeEach, describe, expect, test } from "bun:test"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import { TaskDB } from "../src/db.ts"; +import { + AgentExecutor, + FileNotFoundError, + PIPE, + ProcessLookupError, + default_subprocess_run, + type PopenLike, + type SubprocessRunOptions, +} from "../src/executor.ts"; +import { TaskScheduler } from "../src/scheduler.ts"; +import { ScheduleType, makeTask } from "../src/types.ts"; + +type Row = Record; + +// ── Fakes ──────────────────────────────────────────────────────────────────── +class _FakeStdin { + buffer = ""; + closed = false; + write(data: string): void { + this.buffer += data; + } + close(): void { + this.closed = true; + } +} + +/** + * Minimal stand-in for the Popen object used by the scheduler. + * `_execute_task` (and `_run_agent_command`) iterate `proc.stdout` / + * `proc.stderr` directly and call `.wait()`. The stdout/stderr iterables + * are finite so the read loop never hangs. + */ +class FakePopen implements PopenLike { + static _next_pid = 4242; + pid: number; + stdout: Iterable | AsyncIterable; + stderr: Iterable | AsyncIterable; + stdin: _FakeStdin; + returncode: number; + _killed = false; + + constructor( + stdout_lines: Iterable | AsyncIterable, + stderr_lines: string[] | null = null, + returncode = 0, + ) { + FakePopen._next_pid += 1; + this.pid = FakePopen._next_pid; + this.stdout = stdout_lines; + this.stderr = stderr_lines ?? []; + this.returncode = returncode; + this.stdin = new _FakeStdin(); + } + + wait(_timeout: number | null = null): number { + return this.returncode; + } + + kill(): void { + this._killed = true; + } +} + +/** + * Make the process-group bookkeeping in `_execute_task` inert (≙ the autouse + * `_stub_process_group` pytest fixture): `killpg(_, 0)` immediately raises + * ProcessLookupError so the sub-agent wait loop exits at once. + */ +function stubProcessGroup(sched: TaskScheduler): void { + sched._os = { + getpgid: (pid: number) => pid, + killpg: () => { + // sig == 0 is the "is the group alive?" probe → report it's gone. + throw new ProcessLookupError(); + }, + kill: () => { + throw new ProcessLookupError(); + }, + }; +} + +// ── Stream fixtures (realistic stream-json lines for both agents) ──────────── +function _claude_lines( + result_text = "All done.", + session_id = "sess-abc", +): string[] { + return [ + JSON.stringify({ type: "system", subtype: "init", session_id }) + "\n", + JSON.stringify({ + type: "assistant", + message: { + id: "msg_1", + role: "assistant", + content: [{ type: "text", text: "Working on it. " }], + }, + }) + "\n", + JSON.stringify({ + type: "assistant", + message: { + id: "msg_2", + role: "assistant", + content: [ + { + type: "tool_use", + id: "toolu_1", + name: "Bash", + input: { command: "ls" }, + }, + ], + }, + }) + "\n", + JSON.stringify({ + type: "user", + message: { + role: "user", + content: [ + { + type: "tool_result", + tool_use_id: "toolu_1", + content: [{ type: "text", text: "file.txt" }], + is_error: false, + }, + ], + }, + }) + "\n", + " \n", // blank line — tolerated + "this is not json at all and is longer than ten chars\n", // raw-text branch + JSON.stringify({ + type: "result", + subtype: "success", + result: result_text, + session_id, + }) + "\n", + ]; +} + +function _codex_lines( + thread_id = "thread-xyz", + final_text = "Codex finished.", +): string[] { + return [ + JSON.stringify({ type: "thread.started", thread_id }) + "\n", + JSON.stringify({ + type: "item.completed", + item: { + id: "cmd_1", + type: "command_execution", + command: "pytest -q", + aggregated_output: "1 passed", + exit_code: 0, + status: "completed", + }, + }) + "\n", + JSON.stringify({ + type: "item.completed", + item: { id: "msg_1", type: "agent_message", text: final_text }, + }) + "\n", + JSON.stringify({ type: "turn.completed", usage: { output_tokens: 5 } }) + + "\n", + ]; +} + +describe("execute task", () => { + let tmpDir: string; + let db: TaskDB; + let scheduler: TaskScheduler; + + beforeEach(() => { + tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "agentforge-test-")); + db = new TaskDB(path.join(tmpDir, "t.db")); + scheduler = new TaskScheduler(db); // NOTE: never .start() — keep it hermetic + stubProcessGroup(scheduler); + }); + + afterEach(() => { + AgentExecutor.subprocess_run = default_subprocess_run; + db.conn.close(); + fs.rmSync(tmpDir, { recursive: true, force: true }); + }); + + // ── AgentExecutor.run: command-line construction + flags ───────────────── + test("test_agent_executor_run_builds_claude_command_with_permission_flags", () => { + const captured: Row = {}; + AgentExecutor.subprocess_run = ( + cmd: string[], + opts: SubprocessRunOptions, + ) => { + captured["cmd"] = cmd; + captured["kwargs"] = opts; + return { + returncode: 0, + stdout: JSON.stringify({ type: "result", result: "hi" }) + "\n", + stderr: "", + }; + }; + + const [ok, output] = AgentExecutor.run("do a thing", ".", 30); + + expect(ok).toBe(true); + expect(output).toBe("hi"); // result event text extracted, not raw stdout + const cmd: string[] = captured["cmd"]; + expect(cmd.slice(0, 3)).toEqual(["claude", "-p", "do a thing"]); + // stream-json + bypassPermissions flags appended + expect(cmd).toContain("--output-format"); + expect(cmd).toContain("stream-json"); + expect(cmd).toContain("--permission-mode"); + expect(cmd[cmd.indexOf("--permission-mode") + 1]).toBe("bypassPermissions"); + expect(captured["kwargs"].timeout).toBe(30); + }); + + test("test_agent_executor_run_includes_image_flags", () => { + let cmd: string[] = []; + AgentExecutor.subprocess_run = (c: string[]) => { + cmd = c; + return { returncode: 0, stdout: "", stderr: "" }; + }; + AgentExecutor.run("p", ".", undefined as unknown as number, [ + "/tmp/a.png", + "/tmp/b.jpg", + ]); + // each image passed via -i + expect(cmd.filter((a) => a === "-i").length).toBe(2); + expect(cmd).toContain("/tmp/a.png"); + expect(cmd).toContain("/tmp/b.jpg"); + }); + + test("test_agent_executor_run_nonzero_returns_stderr", () => { + AgentExecutor.subprocess_run = () => ({ + returncode: 1, + stdout: "", + stderr: "boom from cli", + }); + const [ok, output] = AgentExecutor.run("p"); + expect(ok).toBe(false); + expect(output).toBe("boom from cli"); + }); + + test("test_agent_executor_run_handles_missing_cli", () => { + AgentExecutor.subprocess_run = () => { + throw new FileNotFoundError(); + }; + const [ok, output] = AgentExecutor.run("p"); + expect(ok).toBe(false); + expect(output).toContain("not found"); + }); + + // ── _execute_task: claude success path ─────────────────────────────────── + test("test_execute_task_claude_success_persists_completed_and_events", async () => { + const tid = db.add_task( + makeTask({ + title: "claude task", + prompt: "hello", + working_dir: ".", + agent: "claude", + }), + ); + const task = db.get_task(tid)!; + scheduler._active_tasks.set(tid, { is_alive: () => true }); // _execute_task pops this at the end + + const fake = new FakePopen(_claude_lines("All done.", "sess-abc")); + scheduler._popen = () => fake; + await scheduler._execute_task(task); + + const refreshed = db.get_task(tid)!; + expect(refreshed["status"]).toBe("completed"); + expect(refreshed["result"]).toBe("All done."); + expect(refreshed["run_count"]).toBe(1); + // session_id extracted from the trailing result event + expect(refreshed["session_id"]).toBe("sess-abc"); + + const runs = db.get_task_runs(tid); + expect(runs.length).toBe(1); + expect(runs[0]!["status"]).toBe("completed"); + expect(runs[0]!["raw_output"]).toBeTruthy(); // raw stdout stored + + const events = db.get_output_events(tid); + const types = new Set(events.map((e) => e["event_type"])); + // assistant text, a tool_call, a tool_result, the result event, and the raw + // non-JSON line all persisted. + expect(types.has("assistant")).toBe(true); + expect(types.has("tool_call")).toBe(true); + expect(types.has("tool_result")).toBe(true); + expect(types.has("result")).toBe(true); + expect(types.has("text")).toBe(true); // the malformed/non-JSON line + }); + + // ── _execute_task: codex success path ──────────────────────────────────── + test("test_execute_task_codex_success_persists_completed_and_events", async () => { + const tid = db.add_task( + makeTask({ + title: "codex task", + prompt: "hello", + working_dir: ".", + agent: "codex", + }), + ); + const task = db.get_task(tid)!; + scheduler._active_tasks.set(tid, { is_alive: () => true }); + + // No generated images for this run. + (scheduler as any)._find_codex_generated_images = () => []; + + const fake = new FakePopen(_codex_lines("thread-xyz", "Codex finished.")); + scheduler._popen = () => fake; + await scheduler._execute_task(task); + + const refreshed = db.get_task(tid)!; + expect(refreshed["status"]).toBe("completed"); + expect(refreshed["result"]).toBe("Codex finished."); + // thread.started thread_id captured as session_id + expect(refreshed["session_id"]).toBe("thread-xyz"); + + const events = db.get_output_events(tid); + const types = new Set(events.map((e) => e["event_type"])); + expect(types.has("command_execution")).toBe(true); + // codex agent_message text stored as assistant output + expect(types.has("assistant")).toBe(true); + }); + + test("test_execute_task_codex_builds_resume_command_when_session_present", async () => { + const tid = db.add_task( + makeTask({ + title: "codex resume", + prompt: "again", + working_dir: ".", + agent: "codex", + }), + ); + db.update_task(tid, { session_id: "prev-thread" }); + const task = db.get_task(tid)!; + scheduler._active_tasks.set(tid, { is_alive: () => true }); + (scheduler as any)._find_codex_generated_images = () => []; + + const captured: Row = {}; + scheduler._popen = (cmd: string[]) => { + captured["cmd"] = cmd; + return new FakePopen(_codex_lines("prev-thread", "ok")); + }; + await scheduler._execute_task(task); + + const cmd: string[] = captured["cmd"]; + expect(cmd.slice(0, 4)).toEqual(["codex", "exec", "resume", "--json"]); + expect(cmd).toContain("prev-thread"); + expect(cmd).toContain("--dangerously-bypass-approvals-and-sandbox"); + }); + + // ── _execute_task: failure path (non-zero exit) ────────────────────────── + test("test_execute_task_failure_sets_failed_with_error_summary", async () => { + const tid = db.add_task( + makeTask({ + title: "boom", + prompt: "fail please", + working_dir: ".", + agent: "claude", + }), + ); + const task = db.get_task(tid)!; + scheduler._active_tasks.set(tid, { is_alive: () => true }); + + const fake = new FakePopen([], ["fatal: something exploded\n"], 1); + scheduler._popen = () => fake; + await scheduler._execute_task(task); + + const refreshed = db.get_task(tid)!; + expect(refreshed["status"]).toBe("failed"); + expect(refreshed["error"] || "").toContain("exploded"); + + const runs = db.get_task_runs(tid); + expect(runs[0]!["status"]).toBe("failed"); + }); + + // ── _execute_task: failure still persists session_id (resumable retry) ─── + test("test_execute_task_codex_failure_still_persists_session_id", async () => { + // A codex run that emits ``thread.started`` then fails must still persist + // the ``thread_id`` as ``session_id``. Otherwise a failed task cannot be + // resumed (e.g. replying in the Feishu thread to retry) → "no saved session". + const tid = db.add_task( + makeTask({ + title: "codex boom", + prompt: "x", + working_dir: ".", + agent: "codex", + }), + ); + const task = db.get_task(tid)!; + scheduler._active_tasks.set(tid, { is_alive: () => true }); + (scheduler as any)._find_codex_generated_images = () => []; + + const stdout_lines = [ + JSON.stringify({ type: "thread.started", thread_id: "thread-fail-1" }) + + "\n", + ]; + const fake = new FakePopen( + stdout_lines, + ["codex error: model overloaded\n"], + 1, + ); + scheduler._popen = () => fake; + await scheduler._execute_task(task); + + const refreshed = db.get_task(tid)!; + expect(refreshed["status"]).toBe("failed"); + // The conversation id is preserved despite the failure → resumable. + expect(refreshed["session_id"]).toBe("thread-fail-1"); + }); + + test("test_execute_task_claude_failure_still_persists_session_id", async () => { + // A claude run whose trailing ``result`` event carries a ``session_id`` + // (e.g. ``error_during_execution``) must persist it on failure too. + const tid = db.add_task( + makeTask({ + title: "claude boom", + prompt: "x", + working_dir: ".", + agent: "claude", + }), + ); + const task = db.get_task(tid)!; + scheduler._active_tasks.set(tid, { is_alive: () => true }); + + const stdout_lines = [ + JSON.stringify({ + type: "system", + subtype: "init", + session_id: "sess-fail-9", + }) + "\n", + JSON.stringify({ + type: "result", + subtype: "error_during_execution", + session_id: "sess-fail-9", + }) + "\n", + ]; + const fake = new FakePopen(stdout_lines, ["boom\n"], 1); + scheduler._popen = () => fake; + await scheduler._execute_task(task); + + const refreshed = db.get_task(tid)!; + expect(refreshed["status"]).toBe("failed"); + expect(refreshed["session_id"]).toBe("sess-fail-9"); + }); + + // ── _execute_task: missing CLI binary ──────────────────────────────────── + test("test_execute_task_missing_binary_fails_with_install_hint", async () => { + const tid = db.add_task( + makeTask({ + title: "no cli", + prompt: "x", + working_dir: ".", + agent: "codex", + }), + ); + const task = db.get_task(tid)!; + scheduler._active_tasks.set(tid, { is_alive: () => true }); + + scheduler._popen = () => { + throw new FileNotFoundError(); + }; + await scheduler._execute_task(task); + + const refreshed = db.get_task(tid)!; + expect(refreshed["status"]).toBe("failed"); + expect(refreshed["error"] || "").toContain("codex"); + expect(refreshed["error"] || "").toContain("not found"); + }); + + // ── _execute_task: cron reschedule on success ──────────────────────────── + test("test_execute_task_cron_success_reschedules_instead_of_completing", async () => { + const tid = db.add_task( + makeTask({ + title: "cron task", + prompt: "tick", + working_dir: ".", + agent: "claude", + schedule_type: ScheduleType.CRON, + cron_expr: "*/5 * * * *", + }), + ); + const task = db.get_task(tid)!; + scheduler._active_tasks.set(tid, { is_alive: () => true }); + + const fake = new FakePopen(_claude_lines("tick done")); + scheduler._popen = () => fake; + await scheduler._execute_task(task); + + const refreshed = db.get_task(tid)!; + // cron task with remaining runs reschedules rather than completing + expect(refreshed["status"]).toBe("scheduled"); + expect(refreshed["next_run_at"]).toBeTruthy(); + expect(refreshed["run_count"]).toBe(1); + }); + + // ── _execute_task: image path handling (safe load + unsafe reject) ─────── + test("test_execute_task_claude_loads_safe_image_and_streams_via_stdin", async () => { + // A real PNG under /tmp is a safe path → base64-loaded → claude switches to + // the stdin ``--input-format stream-json`` multimodal command; an unsafe path + // outside the allowed roots is rejected and never loaded. + // + // /tmp is one of the hard-coded allowed roots (realpaths cleanly on mac/linux). + const fd_dir = fs.mkdtempSync("/tmp/agentforge-img-"); + const img = path.join(fd_dir, "pic.png"); + fs.writeFileSync( + img, + Buffer.concat([ + Buffer.from([0x89]), + Buffer.from("PNG\r\n"), + Buffer.from([0x1a, 0x0a]), + Buffer.from("fakepng"), + ]), + ); + + const tid = db.add_task( + makeTask({ + title: "img task", + prompt: "see image", + working_dir: ".", + agent: "claude", + image_paths: [img, "/etc/shadow"], // one safe, one rejected + }), + ); + const task = db.get_task(tid)!; + scheduler._active_tasks.set(tid, { is_alive: () => true }); + + const captured: Row = {}; + scheduler._popen = (cmd: string[], kwargs) => { + captured["cmd"] = cmd; + captured["stdin"] = kwargs.stdin; + return new FakePopen(_claude_lines("saw it")); + }; + await scheduler._execute_task(task); + fs.rmSync(fd_dir, { recursive: true, force: true }); + + const refreshed = db.get_task(tid)!; + expect(refreshed["status"]).toBe("completed"); + // Safe image loaded → multimodal stdin path selected. + const cmd: string[] = captured["cmd"]; + expect(cmd).toContain("--input-format"); + expect(cmd[cmd.indexOf("--input-format") + 1]).toBe("stream-json"); + expect(captured["stdin"]).toBe(PIPE); + }); + + test("test_execute_task_codex_passes_image_flag", async () => { + const fd_dir = fs.mkdtempSync("/tmp/agentforge-img-"); + const img = path.join(fd_dir, "shot.png"); + fs.writeFileSync( + img, + Buffer.concat([ + Buffer.from([0x89]), + Buffer.from("PNG\r\n"), + Buffer.from([0x1a, 0x0a]), + Buffer.from("fakepng"), + ]), + ); + + const tid = db.add_task( + makeTask({ + title: "codex img", + prompt: "render", + working_dir: ".", + agent: "codex", + image_paths: [img], + }), + ); + const task = db.get_task(tid)!; + scheduler._active_tasks.set(tid, { is_alive: () => true }); + (scheduler as any)._find_codex_generated_images = () => []; + + const captured: Row = {}; + scheduler._popen = (cmd: string[]) => { + captured["cmd"] = cmd; + return new FakePopen(_codex_lines("thread-xyz", "rendered")); + }; + await scheduler._execute_task(task); + fs.rmSync(fd_dir, { recursive: true, force: true }); + + const cmd: string[] = captured["cmd"]; + expect(cmd).toContain("--image"); + expect(cmd[cmd.indexOf("--image") + 1]).toBe(img); + }); + + test("test_execute_task_claude_resume_appends_session_flag", async () => { + const tid = db.add_task( + makeTask({ + title: "resume", + prompt: "continue", + working_dir: ".", + agent: "claude", + }), + ); + db.update_task(tid, { session_id: "claude-sess-1" }); + const task = db.get_task(tid)!; + scheduler._active_tasks.set(tid, { is_alive: () => true }); + + const captured: Row = {}; + scheduler._popen = (cmd: string[]) => { + captured["cmd"] = cmd; + return new FakePopen(_claude_lines("resumed", "claude-sess-1")); + }; + await scheduler._execute_task(task); + + const cmd: string[] = captured["cmd"]; + expect(cmd).toContain("--resume"); + expect(cmd[cmd.indexOf("--resume") + 1]).toBe("claude-sess-1"); + }); + + // ── _execute_task: timeout / kill path ─────────────────────────────────── + test("test_execute_task_timeout_kills_group_and_marks_failed", async () => { + // A short configured timeout fires the kill timer while stdout is still + // streaming, exercising ``_kill`` (killpg → kill fallback) and the + // ``timed_out`` failure branch. + db.set_setting("timeout", "0"); // setTimeout(_kill, 0) fires immediately + const tid = db.add_task( + makeTask({ + title: "slow", + prompt: "hang", + working_dir: ".", + agent: "claude", + }), + ); + const task = db.get_task(tid)!; + scheduler._active_tasks.set(tid, { is_alive: () => true }); + + async function* slow_lines(): AsyncGenerator { + // Give the timer (delay 0) a moment to fire mid-stream. + await new Promise((r) => setTimeout(r, 200)); + yield JSON.stringify({ type: "system", subtype: "init" }) + "\n"; + } + + const fake = new FakePopen(slow_lines()); + scheduler._popen = () => fake; + await scheduler._execute_task(task); + + const refreshed = db.get_task(tid)!; + expect(refreshed["status"]).toBe("failed"); + // The run record preserves the raw "Task timed out after Ns" message. + const runs = db.get_task_runs(tid); + expect(runs[0]!["status"]).toBe("failed"); + expect(runs[0]!["error"] || "").toContain("timed out"); + }); + + test("test_execute_task_timeout_error_summary_states_timeout_not_stderr", async () => { + // On timeout the human-readable ``task.error`` must say it timed out, not + // surface an unrelated stderr line. Regression: codex prints "Reading + // additional input from stdin…" to stderr, which ``_extract_error_summary`` + // picked over the real "Task timed out after Ns" reason. + db.set_setting("timeout", "0"); // kill timer (delay 0) fires immediately + const tid = db.add_task( + makeTask({ + title: "slow review", + prompt: "hang", + working_dir: ".", + agent: "codex", + }), + ); + const task = db.get_task(tid)!; + scheduler._active_tasks.set(tid, { is_alive: () => true }); + (scheduler as any)._find_codex_generated_images = () => []; + + async function* slow_lines(): AsyncGenerator { + await new Promise((r) => setTimeout(r, 200)); // let the delay-0 timer fire mid-stream + yield JSON.stringify({ type: "thread.started", thread_id: "t-1" }) + "\n"; + } + + const fake = new FakePopen( + slow_lines(), + ["Reading additional input from stdin...\n"], + 0, + ); + scheduler._popen = () => fake; + await scheduler._execute_task(task); + + const refreshed = db.get_task(tid)!; + expect(refreshed["status"]).toBe("failed"); + // error summary states the timeout, not the stderr noise + expect(refreshed["error"] || "").toContain("timed out"); + expect(refreshed["error"] || "").not.toContain("stdin"); + }); + + // ── _run_agent_command: heartbeat/skill-sweep invocation ───────────────── + test("test_run_agent_command_claude_returns_result_text", async () => { + const lines = [ + JSON.stringify({ + type: "assistant", + message: { + id: "m1", + content: [{ type: "text", text: "intermediate" }], + }, + }) + "\n", + JSON.stringify({ type: "result", result: "FINAL DECISION" }) + "\n", + ]; + const fake = new FakePopen(lines, null, 0); + const seen: string[] = []; + scheduler._popen = () => fake; + const [ok, out] = await scheduler._run_agent_command( + "claude", + ["claude", "-p", "decide"], + ".", + (line) => seen.push(line), + ); + expect(ok).toBe(true); + expect(out).toBe("FINAL DECISION"); + expect(seen.some((s) => s.includes("FINAL DECISION"))).toBe(true); + // db unused here but keep reference to satisfy fixture wiring + expect(db).not.toBeNull(); + }); + + test("test_run_agent_command_codex_returns_last_agent_message", async () => { + const fake = new FakePopen( + _codex_lines("thread-xyz", "codex decision"), + null, + 0, + ); + scheduler._popen = () => fake; + const [ok, out] = await scheduler._run_agent_command( + "codex", + ["codex", "exec"], + ".", + ); + expect(ok).toBe(true); + expect(out).toBe("codex decision"); + }); + + test("test_run_agent_command_nonzero_returns_stderr", async () => { + const fake = new FakePopen([], ["heartbeat blew up\n"], 2); + scheduler._popen = () => fake; + const [ok, out] = await scheduler._run_agent_command( + "claude", + ["claude", "-p", "x"], + ".", + ); + expect(ok).toBe(false); + expect(out).toContain("blew up"); + }); + + test("test_run_agent_command_missing_binary", async () => { + scheduler._popen = () => { + throw new FileNotFoundError(); + }; + const [ok, out] = await scheduler._run_agent_command( + "claude", + ["claude"], + ".", + ); + expect(ok).toBe(false); + expect(out).toContain("not found"); + }); + + // ── _extract_error_summary: branches ───────────────────────────────────── + test("test_extract_error_summary_prefers_short_plain_stderr", () => { + const summary = scheduler._extract_error_summary("permission denied", ""); + expect(summary).toBe("permission denied"); + }); + + test("test_extract_error_summary_parses_stream_json_error_event", () => { + const stdout = [ + JSON.stringify({ type: "system", subtype: "init" }), + JSON.stringify({ type: "error", error: "rate limited" }), + ].join("\n"); + const summary = scheduler._extract_error_summary("", stdout); + expect(summary).toBe("rate limited"); + }); + + test("test_extract_error_summary_falls_back_to_last_assistant_text", () => { + const stdout = JSON.stringify({ + type: "assistant", + message: { content: [{ type: "text", text: "I could not finish." }] }, + }); + const summary = scheduler._extract_error_summary("", stdout); + expect(summary).toBe("I could not finish."); + }); +}); diff --git a/backend/tests/gaps.test.ts b/backend/tests/gaps.test.ts new file mode 100644 index 0000000..b6d2fb5 --- /dev/null +++ b/backend/tests/gaps.test.ts @@ -0,0 +1,331 @@ +// Final mop-up coverage for still-reachable scheduler/skills branches. +// +// Ported from tests/test_taskboard_gaps.py; test() descriptions keep the +// Python test function names. +// +// SKIPPED (exercise the HTTP API / run_server lifecycle — owned by the API +// handler test suite, not ported here): +// - test_run_server_starts_all_channels_via_settings +// - test_run_server_auto_enables_telegram_and_slack_via_env +// - test_run_server_telegram_factory_returns_none_no_start + +import { afterEach, beforeEach, describe, expect, test } from "bun:test"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import { TaskDB } from "../src/db.ts"; +import { + FileNotFoundError, + OSError, + TimeoutExpired, + type PopenLike, +} from "../src/executor.ts"; +import { TaskScheduler } from "../src/scheduler.ts"; +import { ScheduleType, makeTask } from "../src/types.ts"; + +type Row = Record; + +// ── _run_agent_command: subprocess branches (Popen mocked) ─────────────────── +class _FakePopen implements PopenLike { + pid = 9999; + returncode: number; + stdout: string[]; + stderr: string[]; + _wait_raises: Error | null; + killed = false; + + constructor( + returncode = 0, + stdout_lines: string[] | null = null, + stderr_lines: string[] | null = null, + wait_raises: Error | null = null, + ) { + this.returncode = returncode; + this.stdout = stdout_lines ?? []; + this.stderr = stderr_lines ?? []; + this._wait_raises = wait_raises; + } + + wait(_timeout: number | null = null): number { + if (this._wait_raises !== null) { + throw this._wait_raises; + } + return this.returncode; + } + + kill(): void { + this.killed = true; + } +} + +describe("taskboard gaps", () => { + let tmpDir: string; + let db: TaskDB; + let sched: TaskScheduler; + let savedHome: string | undefined; + + beforeEach(() => { + tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "agentforge-test-")); + savedHome = process.env.HOME; + db = new TaskDB(path.join(tmpDir, "t.db")); + sched = new TaskScheduler(db); + }); + + afterEach(() => { + if (savedHome === undefined) delete process.env.HOME; + else process.env.HOME = savedHome; + db.conn.close(); + fs.rmSync(tmpDir, { recursive: true, force: true }); + }); + + function _make_pattern(key = "pk"): number { + db.upsert_skill_pattern(key, "recipe", "summary", 1); + const row = db.conn + .query("SELECT id FROM skill_patterns WHERE pattern_key=?") + .get(key) as Row; + return Number(row["id"]); + } + + test("test_run_agent_command_filenotfound", async () => { + sched._popen = () => { + throw new FileNotFoundError(); + }; + const [ok, out] = await sched._run_agent_command("claude", ["claude"], "."); + expect(ok).toBe(false); + expect(out).toContain("not found"); + }); + + test("test_run_agent_command_oserror", async () => { + sched._popen = () => { + throw new OSError("boom"); + }; + const [ok, out] = await sched._run_agent_command("claude", ["claude"], "."); + expect(ok).toBe(false); + expect(out).toContain("boom"); + }); + + test("test_run_agent_command_timeout_kills_proc", async () => { + const proc = new _FakePopen( + 0, + null, + null, + new TimeoutExpired(["claude"], 1), + ); + sched._popen = () => proc; + const [ok, out] = await sched._run_agent_command("claude", ["claude"], "."); + expect(ok).toBe(false); + expect(out).toContain("timed out"); + expect(proc.killed).toBe(true); + }); + + test("test_run_agent_command_nonzero_returns_stderr", async () => { + const proc = new _FakePopen(2, [], ["the error\n"]); + sched._popen = () => proc; + const [ok, out] = await sched._run_agent_command("claude", ["claude"], "."); + expect(ok).toBe(false); + expect(out).toContain("the error"); + }); + + test("test_run_agent_command_codex_parses_agent_message", async () => { + const lines = [ + "\n", // blank → skipped + "not json\n", // parse error → skipped + JSON.stringify({ type: "thread.started", thread_id: "t1" }) + "\n", + JSON.stringify({ + type: "item.completed", + item: { type: "agent_message", text: "CODEX FINAL" }, + }) + "\n", + ]; + const proc = new _FakePopen(0, lines); + sched._popen = () => proc; + const [ok, out] = await sched._run_agent_command("codex", ["codex"], "."); + expect(ok).toBe(true); + expect(out).toBe("CODEX FINAL"); + }); + + test("test_run_agent_command_claude_parses_result_and_assistant", async () => { + const lines = [ + "\n", // blank → skipped + "garbage\n", // parse error → skipped + JSON.stringify({ + type: "assistant", + message: { content: [{ type: "text", text: "thinking" }, "raw-str"] }, + }) + "\n", + JSON.stringify({ type: "result", result: "CLAUDE RESULT" }) + "\n", + ]; + const proc = new _FakePopen(0, lines); + sched._popen = () => proc; + const [ok, out] = await sched._run_agent_command("claude", ["claude"], "."); + expect(ok).toBe(true); + expect(out).toBe("CLAUDE RESULT"); + }); + + test("test_run_agent_command_claude_falls_back_to_assistant_text", async () => { + // No result event → falls back to the last assistant text. + const lines = [ + JSON.stringify({ + type: "assistant", + message: { content: [{ type: "text", text: "ONLY TEXT" }] }, + }) + "\n", + ]; + const proc = new _FakePopen(0, lines); + sched._popen = () => proc; + const [ok, out] = await sched._run_agent_command("claude", ["claude"], "."); + expect(ok).toBe(true); + expect(out).toBe("ONLY TEXT"); + }); + + // ── skill draft worker error path + approve_skill guards ───────────────── + test("test_trigger_skill_draft_worker_records_error", async () => { + const pid = _make_pattern(); + + (sched as any).distill_skill_draft = async () => { + throw new Error("distill kaboom"); + }; + expect(sched.trigger_skill_draft(pid)).toBe(true); + + // Poll until the background worker persists the error to the draft row. + for (let i = 0; i < 50; i++) { + const draft = db.get_skill_draft(pid); + if (draft && draft["status"] === "error") break; + await new Promise((r) => setTimeout(r, 20)); + } + const draft = db.get_skill_draft(pid)!; + expect(draft["status"]).toBe("error"); + expect(draft["error"] || "").toContain("distill kaboom"); + }); + + test("test_trigger_skill_draft_unknown_pattern_returns_false", () => { + expect(sched.trigger_skill_draft(99999)).toBe(false); + }); + + test("test_approve_skill_invalid_name_raises", () => { + process.env.HOME = tmpDir; + const pid = _make_pattern("!!!"); // sanitizes to empty + // Body with frontmatter whose name also sanitizes to empty. + const body = "---\nname: !!!\n---\nbody"; + expect(() => sched.approve_skill(pid, "!!!", "d", body)).toThrow( + /invalid skill name/, + ); + }); + + test("test_approve_skill_empty_body_raises", () => { + const pid = _make_pattern(); + expect(() => sched.approve_skill(pid, "ok", "d", " ")).toThrow( + /skill body is empty/, + ); + }); + + // ── output listeners: error swallow + remove edge ──────────────────────── + test("test_fire_output_listeners_swallows_callback_error", () => { + const calls: Array<[number, string]> = []; + + const bad = () => { + throw new Error("listener boom"); + }; + const good = ( + task_id: number, + _run_id: number, + _event_type: string, + content: string, + ) => { + calls.push([task_id, content]); + }; + + sched.add_output_listener(bad); + sched.add_output_listener(good); + // Must not raise even though `bad` throws; `good` still runs. + sched._fire_output_listeners(1, 2, "assistant", "hello"); + expect(calls).toEqual([[1, "hello"]]); + }); + + test("test_remove_output_listener_unregistered_is_noop", () => { + // Removing a callback that was never added hits the not-found branch. + sched.remove_output_listener(() => {}); // must not raise + }); + + // ── DAG hooks: edge branches ───────────────────────────────────────────── + test("test_on_task_completed_skips_when_downstream_deleted", () => { + const up = db.add_task( + makeTask({ title: "up", prompt: "p", working_dir: "." }), + ); + const down = sched.submit_task( + makeTask({ title: "down", prompt: "p", working_dir: "." }), + [up], + ); + expect(db.get_task(down)!["status"]).toBe("blocked"); + + db.update_task(up, { status: "completed" }); + // get_task(downstream) returns null → the `continue` branch is taken. + const real_get_task = db.get_task.bind(db); + + (db as any).get_task = (task_id: number) => + task_id === down ? null : real_get_task(task_id); + sched._on_task_completed(up); + (db as any).get_task = real_get_task; + // Downstream never updated because it "vanished" mid-hook. + expect(db.get_task(down)!["status"]).toBe("blocked"); + }); + + test("test_on_task_completed_unknown_schedule_type_defaults_pending", () => { + const up = db.add_task( + makeTask({ title: "up", prompt: "p", working_dir: "." }), + ); + const down = sched.submit_task( + makeTask({ title: "down", prompt: "p", working_dir: "." }), + [up], + ); + // Force an unrecognized schedule_type so the else-branch (pending) runs. + db.conn + .query("UPDATE tasks SET schedule_type='weird' WHERE id=?") + .run(down); + db.update_task(up, { status: "completed" }); + sched._on_task_completed(up); + expect(db.get_task(down)!["status"]).toBe("pending"); + }); + + test("test_on_task_failed_diamond_visits_shared_downstream_once", () => { + // root → a, root → b, both a & b → leaf. The `already visited` continue + // branch fires for leaf the second time it's reached. + const root = db.add_task( + makeTask({ title: "root", prompt: "p", working_dir: "." }), + ); + const a = db.add_task( + makeTask({ title: "a", prompt: "p", working_dir: "." }), + ); + const b = db.add_task( + makeTask({ title: "b", prompt: "p", working_dir: "." }), + ); + const leaf = db.add_task( + makeTask({ title: "leaf", prompt: "p", working_dir: "." }), + ); + db.add_dependency(a, root); + db.add_dependency(b, root); + db.add_dependency(leaf, a); + db.add_dependency(leaf, b); + for (const t of [a, b, leaf]) { + db.update_task(t, { status: "blocked" }); + } + sched._on_task_failed(root); + expect(db.get_task(a)!["status"]).toBe("cancelled"); + expect(db.get_task(b)!["status"]).toBe("cancelled"); + expect(db.get_task(leaf)!["status"]).toBe("cancelled"); + }); + + // ── _schedule_delayed transitions pending → scheduled with next_run_at ─── + test("test_schedule_delayed_sets_scheduled_and_next_run", () => { + const tid = db.add_task( + makeTask({ + title: "t", + prompt: "p", + working_dir: ".", + schedule_type: ScheduleType.DELAYED, + delay_seconds: 30, + }), + ); + sched._schedule_delayed(db.get_task(tid)!); + const row = db.get_task(tid)!; + expect(row["status"]).toBe("scheduled"); + expect(row["next_run_at"]).not.toBeNull(); + }); +}); diff --git a/backend/tests/gaps2.test.ts b/backend/tests/gaps2.test.ts new file mode 100644 index 0000000..0017d7e --- /dev/null +++ b/backend/tests/gaps2.test.ts @@ -0,0 +1,590 @@ +// Second mop-up coverage pass for still-reachable scheduler branches. +// +// Ported from tests/test_taskboard_gaps2.py; test() descriptions keep the +// Python test function names. +// +// Targets the Codex/Claude streaming delta + event-normalization helpers +// (_codex_text_delta, _codex_append_text_delta, _codex_event_delta_text, +// _extract_codex_thread_id, _find_codex_generated_images, _image_media_type, +// _extract_codex_success_output, _store_generated_image_events, +// _claude_text_delta, _claude_message_id, _content_to_display_text, +// _parse_codex_event variants, _store_output_event empty-skip) and the +// _execute_task EDGE branches (magic-byte media sniffing, unsafe-path +// rejection, the sub-agent wait loop, the notify fan-out). +// +// SKIPPED (exercise the HTTP API handler — owned by the API handler test +// suite, not ported here): +// - test_feishu_settings_restart_stops_old_and_starts_new +// - test_channels_settings_restart_all_three +// - test_telegram_restart_factory_returns_none +// - test_create_dag_prompt_images_json_string +// - test_create_dag_prompt_images_bad_json_falls_back +// - test_task_resume_not_found +// - test_delete_csrf_rejected +// - test_delete_csrf_accepted_with_token +// - test_post_body_too_large_returns_413 +// - test_read_body_too_large_drains_declared_body + +import { afterEach, beforeEach, describe, expect, test } from "bun:test"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import { TaskDB } from "../src/db.ts"; +import { ProcessLookupError, type PopenLike } from "../src/executor.ts"; +import { TaskScheduler } from "../src/scheduler.ts"; +import { makeTask } from "../src/types.ts"; + +type Row = Record; + +// ── shared FakePopen for _execute_task drives ─────────────────────────────── +class _FakeStdin { + buffer = ""; + write(data: string): void { + this.buffer += data; + } + close(): void {} +} + +class FakePopen implements PopenLike { + static _next_pid = 9000; + pid: number; + stdout: Iterable | AsyncIterable; + stderr: Iterable | AsyncIterable; + stdin: _FakeStdin; + returncode: number; + + constructor( + stdout_lines: Iterable | AsyncIterable, + stderr_lines: string[] | null = null, + returncode = 0, + ) { + FakePopen._next_pid += 1; + this.pid = FakePopen._next_pid; + this.stdout = stdout_lines; + this.stderr = stderr_lines ?? []; + this.returncode = returncode; + this.stdin = new _FakeStdin(); + } + + wait(_timeout: number | null = null): number { + return this.returncode; + } + + kill(): void {} +} + +/** ≙ the `_stub_process_group` pytest fixture. */ +function stubProcessGroup(sched: TaskScheduler): void { + sched._os = { + getpgid: (pid: number) => pid, + killpg: () => { + throw new ProcessLookupError(); + }, + kill: () => { + throw new ProcessLookupError(); + }, + }; +} + +function _claude_lines(result_text = "done", session_id = "s1"): string[] { + return [ + JSON.stringify({ type: "system", subtype: "init", session_id }) + "\n", + JSON.stringify({ + type: "result", + subtype: "success", + result: result_text, + session_id, + }) + "\n", + ]; +} + +/** ≙ the Python dict key tuple (run_id, item_id) used by the delta-state maps. */ +function tupleKey(run_id: number | null, item_id: string): string { + return JSON.stringify([run_id, item_id]); +} + +describe("taskboard gaps2", () => { + let tmpDir: string; + let db: TaskDB; + let sched: TaskScheduler; + let savedHome: string | undefined; + let savedCodexHome: string | undefined; + + beforeEach(() => { + tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "agentforge-test-")); + savedHome = process.env.HOME; + savedCodexHome = process.env.CODEX_HOME; + db = new TaskDB(path.join(tmpDir, "t.db")); + sched = new TaskScheduler(db); + }); + + afterEach(() => { + if (savedHome === undefined) delete process.env.HOME; + else process.env.HOME = savedHome; + if (savedCodexHome === undefined) delete process.env.CODEX_HOME; + else process.env.CODEX_HOME = savedCodexHome; + db.conn.close(); + fs.rmSync(tmpDir, { recursive: true, force: true }); + }); + + // ── Codex streaming delta helpers ─────────────────────────────────────── + test("test_codex_text_delta_cumulative_and_reset", () => { + // First emission returns the whole text (no previous). + expect(sched._codex_text_delta(1, "item", "Hello")).toBe("Hello"); + // Cumulative continuation returns only the new suffix. + expect(sched._codex_text_delta(1, "item", "Hello World")).toBe(" World"); + // Identical text → no new delta. + expect(sched._codex_text_delta(1, "item", "Hello World")).toBeNull(); + // Empty current text → null. + expect(sched._codex_text_delta(1, "item2", "")).toBeNull(); + // Non-prefix (a full rewrite) returns the new text as-is. + expect(sched._codex_text_delta(1, "item", "Totally different")).toBe( + "Totally different", + ); + }); + + test("test_codex_append_text_delta_accumulates", () => { + expect(sched._codex_append_text_delta(2, "a", "")).toBeNull(); + expect(sched._codex_append_text_delta(2, "a", "foo")).toBe("foo"); + expect(sched._codex_append_text_delta(2, "a", "bar")).toBe("bar"); + expect(sched._codex_item_text.get(tupleKey(2, "a"))).toBe("foobar"); + }); + + test("test_codex_event_delta_text_variants", () => { + // string delta on item + expect(sched._codex_event_delta_text({}, { delta: "abc" })).toBe("abc"); + // dict delta with text on event + expect(sched._codex_event_delta_text({ delta: { text: "xyz" } }, {})).toBe( + "xyz", + ); + // dict delta whose text is not a string → null + expect( + sched._codex_event_delta_text({}, { delta: { text: 5 } }), + ).toBeNull(); + // no delta anywhere → null + expect(sched._codex_event_delta_text({}, {})).toBeNull(); + }); + + test("test_extract_codex_thread_id_skips_noise", () => { + const raw = [ + " ", // blank + "not json", // parse error + JSON.stringify({ type: "turn.started" }), // no thread id + JSON.stringify({ type: "thread.started", thread_id: "TH-42" }), + ].join("\n"); + expect(sched._extract_codex_thread_id(raw)).toBe("TH-42"); + expect(sched._extract_codex_thread_id("only noise here")).toBeNull(); + }); + + test("test_image_media_type_extension_map", () => { + expect(sched._image_media_type("/x/a.png")).toBe("image/png"); + expect(sched._image_media_type("/x/a.JPG")).toBe("image/jpeg"); + expect(sched._image_media_type("/x/a.webp")).toBe("image/webp"); + // unknown extension → default png + expect(sched._image_media_type("/x/a.bmp")).toBe("image/png"); + }); + + test("test_find_codex_generated_images_filters_and_sorts", () => { + process.env.HOME = tmpDir; + delete process.env.CODEX_HOME; + + // No thread id → empty. + expect(sched._find_codex_generated_images(null)).toEqual([]); + // Thread id with no directory → empty. + expect(sched._find_codex_generated_images("ghost")).toEqual([]); + + const img_dir = path.join(tmpDir, ".codex", "generated_images", "TH"); + fs.mkdirSync(img_dir, { recursive: true }); + fs.writeFileSync(path.join(img_dir, "b.png"), "x"); + fs.writeFileSync(path.join(img_dir, "a.webp"), "y"); + fs.writeFileSync(path.join(img_dir, "note.txt"), "skip me"); // non-image suffix + + const found = sched._find_codex_generated_images("TH"); + expect(found.map((p) => path.basename(p))).toEqual(["a.webp", "b.png"]); + }); + + test("test_find_codex_generated_images_since_timestamp", () => { + process.env.HOME = tmpDir; + delete process.env.CODEX_HOME; + const img_dir = path.join(tmpDir, ".codex", "generated_images", "TH"); + fs.mkdirSync(img_dir, { recursive: true }); + const old = path.join(img_dir, "old.png"); + fs.writeFileSync(old, "x"); + fs.utimesSync(old, 1000, 1000); // ancient mtime + const fresh = path.join(img_dir, "new.png"); + fs.writeFileSync(fresh, "y"); // current mtime + + // Only the freshly written file passes the since_timestamp filter. + const found = sched._find_codex_generated_images( + "TH", + Date.now() / 1000 - 60, + ); + expect(found.map((p) => path.basename(p))).toEqual(["new.png"]); + }); + + test("test_extract_codex_success_output_with_images", () => { + const raw = [ + " ", // blank skipped + "not json", // decode error skipped + JSON.stringify({ + type: "item.completed", + item: { type: "agent_message", text: "Done" }, + }), + ].join("\n"); + const out = sched._extract_codex_success_output(raw, ["/a.png", "/b.png"]); + expect(out).toContain("Done"); + expect(out).toContain("2 张图片"); + expect(out).toContain("/a.png"); + expect(out).toContain("/b.png"); + // No images and no agent_message text → empty string. + expect(sched._extract_codex_success_output("nothing here")).toBe(""); + }); + + test("test_store_generated_image_events_persists_metadata_and_data", () => { + const tid = db.add_task( + makeTask({ title: "t", prompt: "p", working_dir: "." }), + ); + const run_id = db.add_run(tid); + + const real = fs.mkdtempSync("/tmp/agentforge-img-"); + const img = path.join(real, "pic.png"); + fs.writeFileSync( + img, + Buffer.concat([ + Buffer.from([0x89]), + Buffer.from("PNG\r\n"), + Buffer.from([0x1a, 0x0a]), + Buffer.from("bytes"), + ]), + ); + const missing = path.join(real, "gone.png"); // never created → read-error branch + + sched._store_generated_image_events(tid, run_id, [img, missing]); + fs.rmSync(real, { recursive: true, force: true }); + + const events = db.get_output_events(tid); + const types = events.map((e) => e["event_type"]); + // The real image yields both a generated_image trace and an image_content row; + // the missing one yields only the trace (read fails → continue). + expect(types.filter((t) => t === "generated_image").length).toBe(2); + expect(types.filter((t) => t === "image_content").length).toBe(1); + const content = events.find((e) => e["event_type"] === "image_content")!; + const parsed = JSON.parse(content["content"]); + expect(parsed["media_type"]).toBe("image/png"); + expect(parsed["data"]).toBeTruthy(); // base64 payload present + }); + + // ── Claude streaming delta helpers ────────────────────────────────────── + test("test_claude_text_delta_paths", () => { + // empty current → null + expect(sched._claude_text_delta(1, "m", "")).toBeNull(); + // first emission returns whole text + expect(sched._claude_text_delta(1, "m", "abc")).toBe("abc"); + // identical → null + expect(sched._claude_text_delta(1, "m", "abc")).toBeNull(); + // cumulative continuation → suffix + expect(sched._claude_text_delta(1, "m", "abcdef")).toBe("def"); + // non-cumulative chunk on same message → returns chunk, accumulates state + expect(sched._claude_text_delta(1, "m", "ZZZ")).toBe("ZZZ"); + expect(sched._claude_message_text.get(tupleKey(1, "m"))).toBe("abcdefZZZ"); + }); + + test("test_claude_message_id_fallback", () => { + expect(sched._claude_message_id({ message: { id: "msg-7" } }, 1)).toBe( + "msg-7", + ); + expect(sched._claude_message_id({ message: { message_id: "mm" } }, 1)).toBe( + "mm", + ); + // no id at all → synthesized from run id + expect(sched._claude_message_id({ message: {} }, 3)).toBe("assistant:3"); + expect(sched._claude_message_id({ message: "not-a-dict" }, 4)).toBe( + "assistant:4", + ); + }); + + test("test_content_to_display_text_variants", () => { + expect(sched._content_to_display_text(null)).toBe(""); + expect(sched._content_to_display_text("plain")).toBe("plain"); + const mixed = [ + "raw", + { type: "text", text: "T" }, + { type: "image" }, + { type: "other", k: "v" }, + ]; + const out = sched._content_to_display_text(mixed); + expect(out).toContain("raw"); + expect(out).toContain("T"); + expect(out).toContain("[image]"); + expect(out).toContain("other"); + // dict with text type + expect(sched._content_to_display_text({ type: "text", text: "hi" })).toBe( + "hi", + ); + // dict without text type → JSON dump + expect(sched._content_to_display_text({ foo: "bar" })).toContain("foo"); + // non-str/list/dict → String() + expect(sched._content_to_display_text(42)).toBe("42"); + }); + + test("test_store_output_event_skips_empty", () => { + const tid = db.add_task( + makeTask({ title: "t", prompt: "p", working_dir: "." }), + ); + const run_id = db.add_run(tid); + sched._store_output_event(tid, run_id, "assistant", ""); // empty → no row + expect(db.get_output_events(tid)).toEqual([]); + sched._store_output_event(tid, run_id, "assistant", "real"); + expect(db.get_output_events(tid).length).toBe(1); + }); + + // ── _parse_codex_event normalization branches ─────────────────────────── + test("test_parse_codex_event_reasoning_and_kinds", () => { + // reasoning delta → "[thinking] ..." assistant content + let [etype, content] = sched._parse_codex_event( + { + type: "item.updated", + item: { id: "r1", type: "reasoning", delta: "ponder" }, + }, + 1, + ); + expect(etype).toBe("assistant"); + expect(content).toBe("[thinking] ponder"); + + // command_execution + [etype, content] = sched._parse_codex_event({ + type: "item.completed", + item: { + id: "c1", + type: "command_execution", + command: "ls", + aggregated_output: "files", + exit_code: 0, + status: "completed", + }, + }); + expect(etype).toBe("command_execution"); + expect(JSON.parse(content!)["command"]).toBe("ls"); + + // mcp_tool_call → tool_call + [etype] = sched._parse_codex_event({ + type: "item.completed", + item: { type: "mcp_tool_call", tool: "x" }, + }); + expect(etype).toBe("tool_call"); + + // web_search + [etype] = sched._parse_codex_event({ + type: "item.completed", + item: { type: "web_search", query: "q" }, + }); + expect(etype).toBe("web_search"); + + // file_change + [etype] = sched._parse_codex_event({ + type: "item.completed", + item: { type: "file_change", changes: [] }, + }); + expect(etype).toBe("file_change"); + + // unknown item type → passthrough (etype, full json) + [etype, content] = sched._parse_codex_event({ + type: "item.completed", + item: { type: "mystery" }, + }); + expect(etype).toBe("item.completed"); + }); + + test("test_parse_codex_event_errors_and_skips", () => { + // turn.failed → error with message + expect( + sched._parse_codex_event({ + type: "turn.failed", + error: { message: "boom" }, + }), + ).toEqual(["error", "boom"]); + // turn.failed with non-dict error + expect( + sched._parse_codex_event({ type: "turn.failed", error: "plain" }), + ).toEqual(["error", "plain"]); + // plain error event + expect(sched._parse_codex_event({ type: "error", message: "bad" })).toEqual( + ["error", "bad"], + ); + // silent skips + expect(sched._parse_codex_event({ type: "turn.completed" })).toEqual([ + null, + null, + ]); + expect(sched._parse_codex_event({ type: "thread.started" })).toEqual([ + null, + null, + ]); + // truly unknown top-level type → passthrough + const [etype] = sched._parse_codex_event({ type: "weird.thing", a: 1 }); + expect(etype).toBe("weird.thing"); + }); + + // ── _execute_task EDGE: magic-byte media sniff + unsafe-path reject ────── + test("test_execute_task_sniffs_media_type_for_extensionless_images", async () => { + // An extension-less safe image is loaded and its media type detected from + // magic bytes; an unsafe path (outside allowed roots) is rejected. The Claude + // multimodal stdin path is then taken with the sniffed media type. + stubProcessGroup(sched); + + const real = fs.mkdtempSync("/tmp/agentforge-img-"); + const gif = path.join(real, "noext_gif"); // no extension → magic-byte branch + fs.writeFileSync( + gif, + Buffer.concat([Buffer.from("GIF89a"), Buffer.alloc(16)]), + ); + + const tid = db.add_task( + makeTask({ + title: "img", + prompt: "see", + working_dir: ".", + agent: "claude", + image_paths: [gif, "/etc/shadow"], // one safe extensionless, one rejected + }), + ); + const task = db.get_task(tid)!; + sched._active_tasks.set(tid, { is_alive: () => true }); + + const captured: Row = {}; + sched._popen = (cmd: string[], kwargs) => { + captured["cmd"] = cmd; + captured["stdin_obj"] = kwargs.stdin; + return new FakePopen(_claude_lines("ok")); + }; + await sched._execute_task(task); + fs.rmSync(real, { recursive: true, force: true }); + + expect(db.get_task(tid)!["status"]).toBe("completed"); + // multimodal stdin path selected because exactly one image loaded + const cmd: string[] = captured["cmd"]; + expect(cmd).toContain("--input-format"); + // stdin is the PIPE sentinel; the message content lives on the fake stdin + // object that _popen returned. + const { PIPE } = await import("../src/executor.ts"); + expect(captured["stdin_obj"]).toBe(PIPE); + }); + + test("test_execute_task_sniffs_jpeg_magic_bytes", async () => { + stubProcessGroup(sched); + const real = fs.mkdtempSync("/tmp/agentforge-img-"); + const jpg = path.join(real, "noext_jpeg"); + fs.writeFileSync( + jpg, + Buffer.concat([Buffer.from([0xff, 0xd8, 0xff]), Buffer.alloc(16)]), + ); + + const tid = db.add_task( + makeTask({ + title: "j", + prompt: "p", + working_dir: ".", + agent: "claude", + image_paths: [jpg], + }), + ); + const task = db.get_task(tid)!; + sched._active_tasks.set(tid, { is_alive: () => true }); + + const written: { fp?: FakePopen } = {}; + sched._popen = () => { + const fp = new FakePopen(_claude_lines()); + written.fp = fp; + return fp; + }; + await sched._execute_task(task); + fs.rmSync(real, { recursive: true, force: true }); + + expect(db.get_task(tid)!["status"]).toBe("completed"); + // The multimodal stdin message embeds the jpeg media type sniffed from bytes. + expect(written.fp!.stdin.buffer).toContain("image/jpeg"); + }); + + test("test_execute_task_notify_fans_out_to_channels_and_callback", async () => { + // _notify (called several times during execution) fires the on_task_update + // callback and schedules a notify call for each registered channel. + const updates: number[] = []; + + class _Chan { + notified: number[] = []; + notify_task(task_id: number): void { + this.notified.push(task_id); + } + } + + const chan = new _Chan(); + const sched2 = new TaskScheduler(db, (tid) => updates.push(tid)); + stubProcessGroup(sched2); + sched2._channels.push(chan); + + const tid = db.add_task( + makeTask({ title: "t", prompt: "p", working_dir: ".", agent: "claude" }), + ); + const task = db.get_task(tid)!; + sched2._active_tasks.set(tid, { is_alive: () => true }); + + const fake = new FakePopen(_claude_lines("fine")); + sched2._popen = () => fake; + await sched2._execute_task(task); + + // Give the deferred notify callbacks a moment to run. + for (let i = 0; i < 50; i++) { + if (chan.notified.includes(tid)) break; + await new Promise((r) => setTimeout(r, 20)); + } + + expect(db.get_task(tid)!["status"]).toBe("completed"); + expect(updates).toContain(tid); // on_task_update callback fired + expect(chan.notified).toContain(tid); // channel notify_task fired + }); + + test("test_execute_task_waits_for_subagents_then_group_exits", async () => { + // Drive the sub-agent wait loop: the first killpg(pgid, 0) probe reports the + // group alive (enters the wait body once), the second reports it gone (breaks). + // The 1s pause seam is stubbed so the wait is instant. + const tid = db.add_task( + makeTask({ + title: "sub", + prompt: "p", + working_dir: ".", + agent: "claude", + }), + ); + const task = db.get_task(tid)!; + sched._active_tasks.set(tid, { is_alive: () => true }); + + const probe_calls = { n: 0 }; + + sched._os = { + getpgid: (pid: number) => pid, + killpg: (_pgid: number, sig: number | NodeJS.Signals) => { + if (sig === 0) { + probe_calls.n += 1; + if (probe_calls.n === 1) { + return; // group still alive → loop body runs once + } + throw new ProcessLookupError(); // gone → loop breaks + } + throw new ProcessLookupError(); + }, + kill: () => { + throw new ProcessLookupError(); + }, + }; + // Make the 1s wait-loop sleep instant. + sched._sleep = async () => {}; + + const fake = new FakePopen(_claude_lines("ok")); + sched._popen = () => fake; + await sched._execute_task(task); + + expect(db.get_task(tid)!["status"]).toBe("completed"); + // The loop probed at least twice (alive, then gone). + expect(probe_calls.n).toBeGreaterThanOrEqual(2); + }); +}); diff --git a/backend/tests/scheduler-logic.test.ts b/backend/tests/scheduler-logic.test.ts new file mode 100644 index 0000000..7e879f3 --- /dev/null +++ b/backend/tests/scheduler-logic.test.ts @@ -0,0 +1,745 @@ +// Direct unit tests for TaskScheduler logic not exercised by HTTP tests. +// +// Ported from tests/test_scheduler_logic.py; test() descriptions keep the +// Python test function names. +// +// Covers schedule computation / due dispatch (_tick, _schedule_delayed), heartbeat +// decision flow (idle / notify / suppressed / error), heartbeat next-run + cooldown +// suppression, skill sweep core (run_skill_sweep, _parse_sweep_output, +// _build_sweep_prompt), distill prompt building, submit_task dependency gating, and +// the DAG unblock / cascade-cancel helpers. All agent execution is mocked — no real +// subprocess is ever spawned, and the background loop is never started. + +import { afterEach, beforeEach, describe, expect, test } from "bun:test"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import { TaskDB } from "../src/db.ts"; +import { TaskScheduler } from "../src/scheduler.ts"; +import { + HeartbeatDecisionType, + HeartbeatScheduleType, + ScheduleType, + makeHeartbeat, + makeTask, + type Heartbeat, +} from "../src/types.ts"; +import { dateToLocalIso } from "../src/util.ts"; + +type Row = Record; + +function make_heartbeat(overrides: Partial = {}): Heartbeat { + return makeHeartbeat({ + name: "Repo watcher", + working_dir: ".", + schedule_type: HeartbeatScheduleType.INTERVAL, + interval_seconds: 60, + check_prompt: "Inspect repo.", + action_prompt_template: "Review the latest changes.", + default_agent: "claude", + cooldown_seconds: 300, + ...overrides, + }); +} + +/** ≙ the `_mock_agent` helper: stub `_run_agent_command` with a fixed payload. */ +function _mock_agent(sched: TaskScheduler, payload: string): void { + (sched as any)._run_agent_command = async ( + _agent: string, + _cmd: string[], + _cwd: string, + on_stdout_line: ((line: string) => void) | null = null, + ): Promise<[boolean, string]> => { + if (on_stdout_line) { + on_stdout_line(payload); + } + return [true, payload]; + }; +} + +describe("scheduler logic", () => { + let tmpDir: string; + let db: TaskDB; + let sched: TaskScheduler; + + beforeEach(() => { + tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "agentforge-test-")); + db = new TaskDB(path.join(tmpDir, "sched-test.db")); + sched = new TaskScheduler(db); + }); + + afterEach(() => { + db.conn.close(); + fs.rmSync(tmpDir, { recursive: true, force: true }); + }); + + // ── heartbeat next-run computation ────────────────────────────────────── + test("test_compute_next_run_interval", () => { + const now = new Date(2024, 0, 1, 12, 0, 0); + const nxt = db._compute_heartbeat_next_run_at( + make_heartbeat({ interval_seconds: 90 }), + now, + ); + expect(nxt).toBe(dateToLocalIso(new Date(now.getTime() + 90 * 1000))); + }); + + test("test_compute_next_run_cron", () => { + const now = new Date(2024, 0, 1, 12, 30, 0); + const hb = make_heartbeat({ + schedule_type: HeartbeatScheduleType.CRON, + cron_expr: "0 * * * *", + interval_seconds: null, + }); + const nxt = db._compute_heartbeat_next_run_at(hb, now); + expect(nxt).toBe(dateToLocalIso(new Date(2024, 0, 1, 13, 0, 0))); + }); + + test("test_compute_next_run_invalid_raises", () => { + expect(() => + db._compute_heartbeat_next_run_at( + make_heartbeat({ interval_seconds: 0 }), + new Date(), + ), + ).toThrow(/interval_seconds/); + expect(() => + db._compute_heartbeat_next_run_at( + make_heartbeat({ + schedule_type: HeartbeatScheduleType.CRON, + cron_expr: null, + }), + new Date(), + ), + ).toThrow(/cron_expr/); + }); + + // ── _tick dispatch by schedule type ───────────────────────────────────── + test("test_tick_promotes_delayed_pending_to_scheduled", () => { + const tid = db.add_task( + makeTask({ + title: "delayed", + prompt: "p", + working_dir: ".", + schedule_type: ScheduleType.DELAYED, + delay_seconds: 120, + }), + ); + const spawned: number[] = []; + (sched as any)._spawn_task = (t: Row) => spawned.push(t["id"]); + + sched._tick(); // pending delayed → schedules forward, does not spawn yet + + expect(spawned).toEqual([]); + const task = db.get_task(tid)!; + expect(task["status"]).toBe("scheduled"); + const nra = new Date(task["next_run_at"]); + expect(nra.getTime()).toBeGreaterThan(Date.now()); + }); + + test("test_tick_spawns_immediate_and_due_cron", () => { + const imm = db.add_task( + makeTask({ title: "imm", prompt: "p", working_dir: "." }), + ); + const cron = db.add_task( + makeTask({ + title: "cron", + prompt: "p", + working_dir: ".", + schedule_type: ScheduleType.CRON, + cron_expr: "* * * * *", + next_run_at: dateToLocalIso(new Date(Date.now() - 60 * 1000)), + }), + ); + db.update_task(cron, { status: "scheduled" }); + + const spawned: number[] = []; + (sched as any)._spawn_task = (t: Row) => spawned.push(t["id"]); + + sched._tick(); + + expect(spawned).toContain(imm); + expect(spawned).toContain(cron); + }); + + test("test_tick_skips_active_task", () => { + const tid = db.add_task( + makeTask({ title: "imm", prompt: "p", working_dir: "." }), + ); + + sched._active_tasks.set(tid, { is_alive: () => true }); + const spawned: number[] = []; + (sched as any)._spawn_task = (t: Row) => spawned.push(t["id"]); + + sched._tick(); + expect(spawned).toEqual([]); // already running, not re-picked + }); + + test("test_tick_shutting_down_is_noop", () => { + db.add_task(makeTask({ title: "imm", prompt: "p", working_dir: "." })); + sched._shutting_down = true; + const called: Row[] = []; + (sched as any)._spawn_task = (t: Row) => called.push(t); + sched._tick(); + expect(called).toEqual([]); + }); + + test("test_schedule_delayed_uses_delay_seconds", () => { + const tid = db.add_task( + makeTask({ + title: "d", + prompt: "p", + working_dir: ".", + schedule_type: ScheduleType.DELAYED, + delay_seconds: 300, + }), + ); + const before = Date.now(); + sched._schedule_delayed(db.get_task(tid)!); + const task = db.get_task(tid)!; + expect(task["status"]).toBe("scheduled"); + const nra = new Date(task["next_run_at"]).getTime(); + expect(nra).toBeGreaterThanOrEqual(before + 299 * 1000); + expect(nra).toBeLessThanOrEqual(before + 301 * 1000); + }); + + // ── submit_task scheduling / dependency gating ────────────────────────── + test("test_submit_task_cron_sets_next_run", () => { + const tid = sched.submit_task( + makeTask({ + title: "c", + prompt: "p", + working_dir: ".", + schedule_type: ScheduleType.CRON, + cron_expr: "0 0 * * *", + }), + ); + const task = db.get_task(tid)!; + expect(task["status"]).toBe("scheduled"); + expect(task["next_run_at"]).not.toBeNull(); + expect(new Date(task["next_run_at"]).getTime()).toBeGreaterThan(Date.now()); + }); + + test("test_submit_task_scheduled_at_requires_next_run", () => { + expect(() => + sched.submit_task( + makeTask({ + title: "s", + prompt: "p", + working_dir: ".", + schedule_type: ScheduleType.SCHEDULED_AT, + }), + ), + ).toThrow(/next_run_at/); + }); + + test("test_submit_task_blocks_on_unmet_dependency", () => { + const upstream = db.add_task( + makeTask({ title: "up", prompt: "p", working_dir: "." }), + ); // pending, not completed + const down = sched.submit_task( + makeTask({ title: "down", prompt: "p", working_dir: "." }), + [{ task_id: upstream, inject_result: true }], + ); + expect(db.get_task(down)!["status"]).toBe("blocked"); + const deps = db.get_dependencies(down); + expect(deps[0]!["depends_on_task_id"]).toBe(upstream); + expect(deps[0]!["inject_result"]).toBe(1); + }); + + test("test_submit_task_ready_when_dependency_completed", () => { + const upstream = db.add_task( + makeTask({ title: "up", prompt: "p", working_dir: "." }), + ); + db.update_task(upstream, { status: "completed" }); + const down = sched.submit_task( + makeTask({ title: "down", prompt: "p", working_dir: "." }), + [upstream], // bare int form + ); + expect(db.get_task(down)!["status"]).toBe("pending"); + }); + + // ── DAG unblock / cascade-cancel ──────────────────────────────────────── + test("test_on_task_completed_unblocks_downstream", () => { + const up = db.add_task( + makeTask({ title: "up", prompt: "p", working_dir: "." }), + ); + const down = sched.submit_task( + makeTask({ title: "down", prompt: "p", working_dir: "." }), + [up], + ); + expect(db.get_task(down)!["status"]).toBe("blocked"); + + db.update_task(up, { status: "completed" }); + sched._on_task_completed(up); + + expect(db.get_task(down)!["status"]).toBe("pending"); + }); + + test("test_on_task_completed_keeps_blocked_when_other_dep_pending", () => { + const a = db.add_task( + makeTask({ title: "a", prompt: "p", working_dir: "." }), + ); + const b = db.add_task( + makeTask({ title: "b", prompt: "p", working_dir: "." }), + ); + const down = sched.submit_task( + makeTask({ title: "down", prompt: "p", working_dir: "." }), + [a, b], + ); + + db.update_task(a, { status: "completed" }); + sched._on_task_completed(a); + // b still pending → stays blocked + expect(db.get_task(down)!["status"]).toBe("blocked"); + }); + + test("test_on_task_failed_cascade_cancels", () => { + const root = db.add_task( + makeTask({ title: "root", prompt: "p", working_dir: "." }), + ); + const mid = sched.submit_task( + makeTask({ title: "mid", prompt: "p", working_dir: "." }), + [root], + ); + const leaf = sched.submit_task( + makeTask({ title: "leaf", prompt: "p", working_dir: "." }), + [mid], + ); + + sched._on_task_failed(root); + + expect(db.get_task(mid)!["status"]).toBe("cancelled"); + expect(db.get_task(leaf)!["status"]).toBe("cancelled"); // recursive cascade + expect(db.get_task(mid)!["error"]).toContain(`#${root}`); + }); + + test("test_build_injected_prompt_prepends_upstream_result", () => { + const up = db.add_task( + makeTask({ title: "upstream", prompt: "p", working_dir: "." }), + ); + db.update_task(up, { status: "completed", result: "UPSTREAM OUTPUT" }); + const down = db.add_task( + makeTask({ title: "down", prompt: "DO THE THING", working_dir: "." }), + ); + db.add_dependency(down, up, true); + + const injected = sched._build_injected_prompt(db.get_task(down)!); + expect(injected).toContain("UPSTREAM OUTPUT"); + expect(injected.trim().endsWith("DO THE THING")).toBe(true); + }); + + test("test_build_injected_prompt_without_inject_returns_original", () => { + const up = db.add_task( + makeTask({ title: "upstream", prompt: "p", working_dir: "." }), + ); + db.update_task(up, { status: "completed", result: "X" }); + const down = db.add_task( + makeTask({ title: "down", prompt: "ORIGINAL", working_dir: "." }), + ); + db.add_dependency(down, up, false); + expect(sched._build_injected_prompt(db.get_task(down)!)).toBe("ORIGINAL"); + }); + + // ── cancel / retry ────────────────────────────────────────────────────── + test("test_cancel_and_retry_task", () => { + const tid = db.add_task( + makeTask({ title: "t", prompt: "p", working_dir: "." }), + ); + db.update_task(tid, { status: "running" }); + + sched.cancel_task(tid); + expect(db.get_task(tid)!["status"]).toBe("cancelled"); + + db.update_task(tid, { status: "failed", error: "boom" }); + sched.retry_task(tid); + const retried = db.get_task(tid)!; + expect(retried["status"]).toBe("pending"); + expect(retried["error"]).toBeNull(); + }); + + // ── heartbeat decision parsing ────────────────────────────────────────── + test("test_parse_heartbeat_decision_strips_fence_and_normalizes", () => { + const raw = '```json\n{"decision":"idle","reason":"nothing"}\n```'; + const decision = sched._parse_heartbeat_decision(raw); + expect(decision["decision"]).toBe("idle"); + expect(decision["reason"]).toBe("nothing"); + // missing fields are coerced to defaults + expect(decision["title"]).toBe(""); + expect(decision["metadata"]).toEqual({}); + }); + + test("test_parse_heartbeat_decision_extracts_embedded_object", () => { + const raw = + 'noise before {"decision":"trigger_task","dedupe_key":"k"} noise after'; + const decision = sched._parse_heartbeat_decision(raw); + expect(decision["decision"]).toBe("trigger_task"); + expect(decision["dedupe_key"]).toBe("k"); + }); + + test("test_parse_heartbeat_decision_invalid_decision_raises", () => { + expect(() => + sched._parse_heartbeat_decision('{"decision":"explode"}'), + ).toThrow(/Invalid heartbeat decision/); + }); + + test("test_parse_heartbeat_decision_non_dict_metadata_raises", () => { + expect(() => + sched._parse_heartbeat_decision('{"decision":"idle","metadata":[1,2]}'), + ).toThrow(/metadata must be an object/); + }); + + test("test_render_heartbeat_check_prompt_includes_action_template", () => { + const hid = db.add_heartbeat( + make_heartbeat({ action_prompt_template: "REVIEW THE DIFF" }), + ); + const prompt = sched._render_heartbeat_check_prompt(db.get_heartbeat(hid)!); + expect(prompt).toContain("Inspect repo."); + expect(prompt).toContain("REVIEW THE DIFF"); + expect(prompt).toContain("trigger_task"); + }); + + // ── heartbeat tick execution flow ─────────────────────────────────────── + test("test_execute_heartbeat_idle_decision", async () => { + const hid = db.add_heartbeat(make_heartbeat()); + _mock_agent(sched, JSON.stringify({ decision: "idle", reason: "calm" })); + + await sched._execute_heartbeat(db.get_heartbeat(hid)!); + + expect(db.get_all_tasks()).toEqual([]); + const hb = db.get_heartbeat(hid)!; + expect(hb["last_decision"]).toBe(HeartbeatDecisionType.IDLE); + expect(hb["last_error"]).toBeNull(); + // next_run_at advanced + expect(new Date(hb["next_run_at"]).getTime()).toBeGreaterThan(Date.now()); + const tick = db.get_latest_heartbeat_tick(hid)!; + expect(tick["status"]).toBe("idle"); + }); + + test("test_execute_heartbeat_notify_only_records_decision", async () => { + const hid = db.add_heartbeat(make_heartbeat()); + _mock_agent( + sched, + JSON.stringify({ + decision: "notify_only", + reason: "FYI", + dedupe_key: "n1", + }), + ); + + await sched._execute_heartbeat(db.get_heartbeat(hid)!); + + expect(db.get_all_tasks()).toEqual([]); // notify does not create a task + const hb = db.get_heartbeat(hid)!; + expect(hb["last_decision"]).toBe(HeartbeatDecisionType.NOTIFY_ONLY); + const tick = db.get_latest_heartbeat_tick(hid)!; + expect(tick["status"]).toBe(HeartbeatDecisionType.NOTIFY_ONLY); + }); + + test("test_execute_heartbeat_trigger_falls_back_to_action_template", async () => { + const hid = db.add_heartbeat( + make_heartbeat({ action_prompt_template: "DEFAULT ACTION" }), + ); + // decision has no prompt/title → falls back to action_prompt_template + default title + _mock_agent( + sched, + JSON.stringify({ decision: "trigger_task", dedupe_key: "dk" }), + ); + + await sched._execute_heartbeat(db.get_heartbeat(hid)!); + + const tasks = db.get_all_tasks(); + expect(tasks.length).toBe(1); + expect(tasks[0]!["prompt"]).toBe("DEFAULT ACTION"); + expect(tasks[0]!["title"]).toBe("Heartbeat: Repo watcher"); + expect(tasks[0]!["tags"]).toBe("heartbeat"); + // dedup row recorded + expect(db.get_heartbeat_dedup(hid, "dk")).not.toBeNull(); + }); + + test("test_execute_heartbeat_agent_failure_records_error", async () => { + const hid = db.add_heartbeat(make_heartbeat()); + + (sched as any)._run_agent_command = async (): Promise< + [boolean, string] + > => [false, "agent crashed"]; + + await sched._execute_heartbeat(db.get_heartbeat(hid)!); + + const hb = db.get_heartbeat(hid)!; + expect(hb["last_decision"]).toBe(HeartbeatDecisionType.ERROR); + expect(hb["last_error"]).toContain("agent crashed"); + expect(db.get_latest_heartbeat_tick(hid)!["status"]).toBe("error"); + }); + + // ── heartbeat cooldown suppression ────────────────────────────────────── + test("test_trigger_suppressed_empty_key_is_false", () => { + expect( + sched._heartbeat_trigger_suppressed({ id: 1, cooldown_seconds: 300 }, ""), + ).toBe(false); + }); + + test("test_trigger_suppressed_during_cooldown", () => { + const hid = db.add_heartbeat(make_heartbeat({ cooldown_seconds: 600 })); + db.upsert_heartbeat_dedup(hid, "k", null); // triggered now + expect( + sched._heartbeat_trigger_suppressed(db.get_heartbeat(hid)!, "k"), + ).toBe(true); + }); + + test("test_trigger_not_suppressed_after_cooldown_when_no_active_task", () => { + const hid = db.add_heartbeat(make_heartbeat({ cooldown_seconds: 60 })); + db.upsert_heartbeat_dedup(hid, "k", null); + // age the dedup row past the cooldown + const old = dateToLocalIso(new Date(Date.now() - 120 * 1000)); + db.conn + .query( + "UPDATE heartbeat_dedup SET triggered_at=? WHERE heartbeat_id=? AND dedupe_key=?", + ) + .run(old, hid, "k"); + expect( + sched._heartbeat_trigger_suppressed(db.get_heartbeat(hid)!, "k"), + ).toBe(false); + }); + + test("test_trigger_suppressed_while_prior_task_active", () => { + const hid = db.add_heartbeat(make_heartbeat({ cooldown_seconds: 0 })); // no cooldown + const task_id = db.add_task( + makeTask({ title: "t", prompt: "p", working_dir: "." }), + ); // pending = active + db.upsert_heartbeat_dedup(hid, "k", task_id); + expect( + sched._heartbeat_trigger_suppressed(db.get_heartbeat(hid)!, "k"), + ).toBe(true); + + // once that task completes, the signal is no longer suppressed + db.update_task(task_id, { status: "completed" }); + expect( + sched._heartbeat_trigger_suppressed(db.get_heartbeat(hid)!, "k"), + ).toBe(false); + }); + + // ── trigger_heartbeat_now ─────────────────────────────────────────────── + test("test_trigger_heartbeat_now_unknown_raises", () => { + expect(() => sched.trigger_heartbeat_now(99999)).toThrow(/not found/); + }); + + // ── skill sweep core ──────────────────────────────────────────────────── + test("test_parse_sweep_output_variants", () => { + expect(sched._parse_sweep_output("[]")).toEqual([]); + const fenced = '```json\n[{"pattern_key":"k"}]\n```'; + expect(sched._parse_sweep_output(fenced)).toEqual([{ pattern_key: "k" }]); + const embedded = 'prose [{"pattern_key":"k2"}] tail'; + expect(sched._parse_sweep_output(embedded)).toEqual([ + { pattern_key: "k2" }, + ]); + // non-array / garbage → empty list, never raises + expect(sched._parse_sweep_output('{"a":1}')).toEqual([]); + expect(sched._parse_sweep_output("not json")).toEqual([]); + expect(sched._parse_sweep_output("")).toEqual([]); + }); + + test("test_run_skill_sweep_no_runs_short_circuits", async () => { + const called: unknown[][] = []; + (sched as any)._run_agent_prompt_once = async ( + ...a: unknown[] + ): Promise<[boolean, string]> => { + called.push(a); + return [true, "[]"]; + }; + + const result = await sched.run_skill_sweep("claude"); + + expect(result["scanned"]).toBe(0); + expect(result["detected"]).toBe(0); + expect(called).toEqual([]); // never invokes the agent when there's nothing to scan + }); + + test("test_run_skill_sweep_detects_and_advances_watermark", async () => { + const tid = db.add_task( + makeTask({ title: "t", prompt: "run pytest", working_dir: "." }), + ); + const r1 = db.add_run(tid); + const r2 = db.add_run(tid); + db.conn + .query( + "UPDATE task_runs SET status='completed', finished_at=? WHERE id=?", + ) + .run("2024-01-01T00:00:00", r1); + db.conn + .query( + "UPDATE task_runs SET status='completed', finished_at=? WHERE id=?", + ) + .run("2024-01-02T00:00:00", r2); + + // agent reuses the same pattern_key across both runs → recurrence aggregates + const sweep_output = JSON.stringify([ + { + pattern_key: "run-pytest", + kind: "recipe", + summary: "s", + run_id: r1, + task_id: tid, + }, + { + pattern_key: "run-pytest", + kind: "recipe", + summary: "s", + run_id: r2, + task_id: tid, + }, + ]); + (sched as any)._run_agent_prompt_once = async (): Promise< + [boolean, string] + > => [true, sweep_output]; + + const result = await sched.run_skill_sweep("claude", true); + + expect(result["scanned"]).toBe(2); + expect(result["detected"]).toBe(2); + expect(result["new"]).toBe(2); + expect(db.get_skill_pattern_recurrence("run-pytest")).toBe(2); + // watermark advanced to the newest finished_at + expect(db.get_setting("skill_sweep_watermark")).toBe("2024-01-02T00:00:00"); + }); + + test("test_run_skill_sweep_agent_failure_raises", async () => { + const tid = db.add_task( + makeTask({ title: "t", prompt: "p", working_dir: "." }), + ); + const rid = db.add_run(tid); + db.conn + .query( + "UPDATE task_runs SET status='completed', finished_at=? WHERE id=?", + ) + .run("2024-01-01T00:00:00", rid); + (sched as any)._run_agent_prompt_once = async (): Promise< + [boolean, string] + > => [false, "kaboom"]; + await expect(sched.run_skill_sweep("claude", true)).rejects.toThrow( + /kaboom/, + ); + }); + + test("test_run_skill_sweep_full_ignores_watermark", async () => { + const tid = db.add_task( + makeTask({ title: "t", prompt: "p", working_dir: "." }), + ); + const rid = db.add_run(tid); + db.conn + .query( + "UPDATE task_runs SET status='completed', finished_at=? WHERE id=?", + ) + .run("2024-01-01T00:00:00", rid); + // watermark is past the run; full=true must still re-scan it + db.set_setting("skill_sweep_watermark", "2030-01-01T00:00:00"); + (sched as any)._run_agent_prompt_once = async (): Promise< + [boolean, string] + > => [true, "[]"]; + + const result = await sched.run_skill_sweep("claude", true); + expect(result["scanned"]).toBe(1); + }); + + test("test_skill_sweep_status_reflects_last_result", async () => { + (sched as any)._run_agent_prompt_once = async (): Promise< + [boolean, string] + > => [true, "[]"]; + await sched.run_skill_sweep("claude"); // no runs → cached as last + const status = sched.skill_sweep_status(); + expect(status.running).toBe(false); + expect(status.last!["scanned"]).toBe(0); + }); + + // ── prompt builders ───────────────────────────────────────────────────── + test("test_build_sweep_prompt_lists_existing_and_runs", () => { + const runs = [ + { + run_id: 5, + task_id: 2, + title: "Run tests", + prompt: "uv run pytest", + result: "all green", + }, + ]; + const existing = [ + { + pattern_key: "run-pytest", + kind: "recipe", + recurrence_count: 3, + summary: "tests", + }, + ]; + const prompt = sched._build_sweep_prompt(runs, existing); + expect(prompt).toContain("run-pytest"); + expect(prompt).toContain("run #5"); + expect(prompt).toContain("uv run pytest"); + // empty existing renders the placeholder + expect(sched._build_sweep_prompt(runs, [])).toContain("(none yet)"); + }); + + test("test_build_distill_context_and_prompt", () => { + const tid = db.add_task( + makeTask({ title: "Run tests", prompt: "run pytest", working_dir: "." }), + ); + const rid = db.add_run(tid); + db.finish_run(rid, "completed", "green"); + + const context = sched._build_distill_context([tid]); + expect(context).toContain(`task #${tid}`); + expect(context).toContain("run pytest"); + expect(context).toContain("green"); + + const pattern = db.get_skill_pattern( + db.upsert_skill_pattern("k", "recipe", "summary", tid)!, + )!; + const with_creator = sched._build_distill_prompt( + pattern, + context, + "a/SKILL.md", + ); + expect(with_creator).toContain("skill-creator"); + expect(with_creator).toContain("a/SKILL.md"); + const without_creator = sched._build_distill_prompt(pattern, context, null); + expect(without_creator).not.toContain("a/SKILL.md"); + expect(without_creator).toContain("skill-creator conventions"); + }); + + // ── timezone normalization on submit (scheduled_at) ───────────────────── + test("test_submit_scheduled_at_naive_passthrough", () => { + // ≙ Python (now + 2h).replace(microsecond=0).isoformat() + const naive = dateToLocalIso(new Date(Date.now() + 2 * 3600 * 1000)).slice( + 0, + 19, + ); + const tid = sched.submit_task( + makeTask({ + title: "s", + prompt: "p", + working_dir: ".", + schedule_type: ScheduleType.SCHEDULED_AT, + next_run_at: naive, + }), + ); + // Naive input keeps the same local wall time (no tz shift). Deviation from + // Python: storage re-serializes with a 6-digit fractional suffix instead of + // passing the string through byte-identically. + const stored: string = db.get_task(tid)!["next_run_at"]; + expect(stored.startsWith(naive)).toBe(true); + expect(new Date(stored).getTime()).toBe(new Date(naive).getTime()); + }); + + test("test_submit_scheduled_at_aware_is_localized", () => { + const aware = new Date(Date.now() + 3 * 3600 * 1000); + const tid = sched.submit_task( + makeTask({ + title: "s", + prompt: "p", + working_dir: ".", + schedule_type: ScheduleType.SCHEDULED_AT, + next_run_at: aware.toISOString(), // offset-aware (UTC) input + }), + ); + // ≙ aware.astimezone().replace(tzinfo=None).isoformat(): local-naive storage + const expected = dateToLocalIso(aware); + expect(db.get_task(tid)!["next_run_at"]).toBe(expected); + }); +}); diff --git a/backend/tests/scheduler-more.test.ts b/backend/tests/scheduler-more.test.ts new file mode 100644 index 0000000..b7ac604 --- /dev/null +++ b/backend/tests/scheduler-more.test.ts @@ -0,0 +1,786 @@ +// Additional direct unit tests for TaskScheduler / heartbeat / skill-sweep +// branches that the other suites don't reach. +// +// Ported from tests/test_scheduler_more.py; test() descriptions keep the +// Python test function names. +// +// Everything constructs TaskDB + TaskScheduler directly, never starts the +// background loop, and mocks every agent invocation so no real CLI is spawned. +// Skill-library file I/O is sandboxed under a temp $HOME. + +import { afterEach, beforeEach, describe, expect, test } from "bun:test"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import { TaskDB } from "../src/db.ts"; +import { + AgentExecutor, + FileNotFoundError, + OSError, + TimeoutExpired, + default_subprocess_run, +} from "../src/executor.ts"; +import { TaskScheduler, default_os } from "../src/scheduler.ts"; +import { + _compose_skill_md, + _parse_skill_frontmatter, + _sanitize_skill_name, + expanduser, + link_skill, + remove_skill_from_disk, + unlink_skill, + write_skill_to_disk, +} from "../src/skills.ts"; +import { + HeartbeatDecisionType, + HeartbeatScheduleType, + ScheduleType, + makeHeartbeat, + makeTask, + type Heartbeat, +} from "../src/types.ts"; + +type Row = Record; + +function make_heartbeat(overrides: Partial = {}): Heartbeat { + return makeHeartbeat({ + name: "Repo watcher", + working_dir: ".", + schedule_type: HeartbeatScheduleType.INTERVAL, + interval_seconds: 60, + check_prompt: "Inspect repo.", + action_prompt_template: "Review the latest changes.", + default_agent: "claude", + cooldown_seconds: 300, + ...overrides, + }); +} + +function make_pattern( + db: TaskDB, + key = "k", + recurrence = 3, + tasks: number[] = [1, 2, 3], + kind = "recipe", +): number { + db.upsert_skill_pattern(key, kind, "summary", tasks[0]!); + db.conn + .query( + "UPDATE skill_patterns SET recurrence_count=?, contributing_task_ids=? WHERE pattern_key=?", + ) + .run(recurrence, JSON.stringify(tasks), key); + const row = db.conn + .query("SELECT id FROM skill_patterns WHERE pattern_key=?") + .get(key) as Row; + return Number(row["id"]); +} + +/** ≙ the `_mock_agent` helper. */ +function _mock_agent( + sched: TaskScheduler, + payload: string, + success = true, +): void { + (sched as any)._run_agent_command = async ( + _agent: string, + _cmd: string[], + _cwd: string, + on_stdout_line: ((line: string) => void) | null = null, + ): Promise<[boolean, string]> => { + if (on_stdout_line) { + on_stdout_line(payload); + } + return [success, payload]; + }; +} + +describe("scheduler more", () => { + let tmpDir: string; + let db: TaskDB; + let sched: TaskScheduler; + let savedHome: string | undefined; + + beforeEach(() => { + tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "agentforge-test-")); + // Sandbox $HOME so the on-disk skill helpers never touch the real home dir. + savedHome = process.env.HOME; + process.env.HOME = tmpDir; + db = new TaskDB(path.join(tmpDir, "t.db")); + sched = new TaskScheduler(db); + }); + + afterEach(() => { + AgentExecutor.subprocess_run = default_subprocess_run; + if (savedHome === undefined) delete process.env.HOME; + else process.env.HOME = savedHome; + db.conn.close(); + fs.rmSync(tmpDir, { recursive: true, force: true }); + }); + + // ── on-disk skill helpers (module-level functions) ────────────────────── + test("test_write_skill_to_disk_creates_canonical_and_symlinks", () => { + const [md_path, skill_dir] = write_skill_to_disk( + "My Skill", + "---\nname: my-skill\n---\nbody", + ); + expect(fs.statSync(md_path).isFile()).toBe(true); + expect(path.basename(md_path)).toBe("SKILL.md"); + expect(skill_dir.endsWith("My Skill")).toBe(true); + const claude = expanduser("~/.claude/skills/My Skill"); + const agents = expanduser("~/.agents/skills/My Skill"); + expect(fs.lstatSync(claude).isSymbolicLink()).toBe(true); + expect(fs.lstatSync(agents).isSymbolicLink()).toBe(true); + // symlink target resolves back to canonical SKILL.md + expect(fs.statSync(path.join(claude, "SKILL.md")).isFile()).toBe(true); + }); + + test("test_link_skill_replaces_stale_symlink", () => { + write_skill_to_disk("s1", "body-1"); + const claude = expanduser("~/.claude/skills/s1"); + // Point the consumer symlink somewhere stale, then re-link. + fs.unlinkSync(claude); + fs.symlinkSync(path.join(tmpDir, "nowhere"), claude, "dir"); + expect(fs.readlinkSync(claude).endsWith("nowhere")).toBe(true); + + const links = link_skill("s1"); + expect(links).toContain(claude); + // re-link removed the stale link and recreated it at the canonical dir + expect( + fs + .realpathSync(claude) + .endsWith(path.join(".agentforge", "skills", "s1")), + ).toBe(true); + }); + + test("test_unlink_skill_removes_only_symlinks", () => { + write_skill_to_disk("s2", "body-2"); + const canonical = expanduser("~/.agentforge/skills/s2/SKILL.md"); + unlink_skill("s2"); + expect(fs.existsSync(expanduser("~/.claude/skills/s2"))).toBe(false); + expect(fs.existsSync(expanduser("~/.agents/skills/s2"))).toBe(false); + expect(fs.statSync(canonical).isFile()).toBe(true); // canonical preserved + // unlinking again is a no-op (no symlink present) + unlink_skill("s2"); + expect(fs.statSync(canonical).isFile()).toBe(true); + }); + + test("test_remove_skill_from_disk_wipes_everything", () => { + write_skill_to_disk("s3", "body-3"); + remove_skill_from_disk("s3"); + expect(fs.existsSync(expanduser("~/.agentforge/skills/s3"))).toBe(false); + expect(fs.existsSync(expanduser("~/.claude/skills/s3"))).toBe(false); + // removing a non-existent skill is harmless + remove_skill_from_disk("never-existed"); + }); + + // ── frontmatter / compose / sanitize edges ────────────────────────────── + test("test_parse_skill_frontmatter_edges", () => { + // no frontmatter at all + expect(_parse_skill_frontmatter("just a body")).toEqual(["", ""]); + // opening fence but no closing fence + expect(_parse_skill_frontmatter("---\nname: x")).toEqual(["", ""]); + // well-formed, with a non key:value line and a duplicate that is ignored + const [name, desc] = _parse_skill_frontmatter( + "---\nname: my-skill\nbare line without colon\ndescription: does x\nname: ignored\n---\nbody", + ); + expect(name).toBe("my-skill"); + expect(desc).toBe("does x"); + // leading whitespace is tolerated + expect(_parse_skill_frontmatter(" \n---\nname: lead\n---\n")[0]).toBe( + "lead", + ); + }); + + test("test_compose_skill_md_flattens_and_strips", () => { + const md = _compose_skill_md("nm", " multi\nline desc ", " body here "); + expect(md).toContain("name: nm"); + expect(md).toContain("description: multi line desc"); + expect(md.trim().endsWith("body here")).toBe(true); + // null inputs don't blow up + expect(_compose_skill_md("nm", null, null)).toContain("name: nm"); + }); + + test("test_sanitize_skill_name_edges", () => { + expect(_sanitize_skill_name(" Hello World ")).toBe("hello-world"); + expect(_sanitize_skill_name("-leading-and-trailing-")).toBe( + "leading-and-trailing", + ); + expect(_sanitize_skill_name(null)).toBe(""); + }); + + // ── AgentExecutor.run (subprocess mocked — not the _execute_task path) ─── + test("test_agent_executor_run_extracts_result_event", () => { + const stdout = [ + JSON.stringify({ type: "assistant", message: "thinking" }), + JSON.stringify({ type: "result", result: "FINAL ANSWER" }), + "", // blank line skipped + ].join("\n"); + const captured: Row = {}; + AgentExecutor.subprocess_run = (cmd: string[]) => { + captured["cmd"] = cmd; + return { returncode: 0, stdout, stderr: "" }; + }; + const [ok, out] = AgentExecutor.run( + "do it", + ".", + undefined as unknown as number, + ["/tmp/a.png"], + ); + expect(ok).toBe(true); + expect(out).toBe("FINAL ANSWER"); + // image path threaded through as -i + expect(captured["cmd"]).toContain("-i"); + expect(captured["cmd"]).toContain("/tmp/a.png"); + }); + + test("test_agent_executor_run_no_result_event_returns_full_stdout", () => { + const stdout = JSON.stringify({ + type: "assistant", + message: "no result line", + }); + AgentExecutor.subprocess_run = () => ({ + returncode: 0, + stdout, + stderr: "", + }); + const [ok, out] = AgentExecutor.run("p"); + expect(ok).toBe(true); + expect(out).toBe(stdout); // falls back to full stdout when no result event + }); + + test("test_agent_executor_run_nonzero_returns_stderr", () => { + AgentExecutor.subprocess_run = () => ({ + returncode: 1, + stdout: "", + stderr: "the error", + }); + const [ok, out] = AgentExecutor.run("p"); + expect(ok).toBe(false); + expect(out).toBe("the error"); + }); + + test("test_agent_executor_run_tolerates_garbage_lines", () => { + // A non-JSON line precedes the result event; the parse error is swallowed. + const stdout = [ + "this is not json", + JSON.stringify({ type: "result", result: "OK" }), + ].join("\n"); + AgentExecutor.subprocess_run = () => ({ + returncode: 0, + stdout, + stderr: "", + }); + const [ok, out] = AgentExecutor.run("p"); + expect(ok).toBe(true); + expect(out).toBe("OK"); + }); + + test("test_agent_executor_run_timeout", () => { + AgentExecutor.subprocess_run = (cmd: string[]) => { + throw new TimeoutExpired(cmd, 600); + }; + const [ok, out] = AgentExecutor.run("p", ".", 600); + expect(ok).toBe(false); + expect(out).toContain("timed out"); + }); + + test("test_agent_executor_run_missing_cli", () => { + AgentExecutor.subprocess_run = () => { + throw new FileNotFoundError(); + }; + const [ok, out] = AgentExecutor.run("p"); + expect(ok).toBe(false); + expect(out).toContain("not found"); + }); + + test("test_agent_executor_run_oserror", () => { + AgentExecutor.subprocess_run = () => { + throw new OSError("disk gone"); + }; + const [ok, out] = AgentExecutor.run("p"); + expect(ok).toBe(false); + expect(out).toContain("disk gone"); + }); + + // ── _run_agent_prompt_once builds the right CLI per agent ──────────────── + test("test_run_agent_prompt_once_codex_command", async () => { + const seen: Row = {}; + (sched as any)._run_agent_command = async ( + agent: string, + cmd: string[], + cwd: string, + ): Promise<[boolean, string]> => { + seen["agent"] = agent; + seen["cmd"] = cmd; + seen["cwd"] = cwd; + return [true, "ok"]; + }; + const [ok, out] = await sched._run_agent_prompt_once( + "codex", + "the prompt", + ".", + ); + expect(ok).toBe(true); + expect(out).toBe("ok"); + expect(seen["cmd"][0]).toBe("codex"); + expect(seen["cmd"]).toContain("--json"); + expect(seen["cmd"][seen["cmd"].length - 1]).toBe("the prompt"); + }); + + test("test_run_agent_prompt_once_claude_command", async () => { + const seen: Row = {}; + (sched as any)._run_agent_command = async ( + _agent: string, + cmd: string[], + ): Promise<[boolean, string]> => { + seen["cmd"] = cmd; + return [true, "ok"]; + }; + await sched._run_agent_prompt_once("claude", "p2", "."); + expect(seen["cmd"][0]).toBe("claude"); + expect(seen["cmd"][1]).toBe("-p"); + }); + + // ── heartbeat: codex prompt path + resume decision ────────────────────── + test("test_execute_heartbeat_codex_agent_builds_codex_cmd", async () => { + const hid = db.add_heartbeat(make_heartbeat({ default_agent: "codex" })); + const seen: Row = {}; + + (sched as any)._run_agent_command = async ( + agent: string, + cmd: string[], + ): Promise<[boolean, string]> => { + seen["cmd"] = cmd; + seen["agent"] = agent; + return [true, JSON.stringify({ decision: "idle", reason: "calm" })]; + }; + await sched._execute_heartbeat(db.get_heartbeat(hid)!); + + expect(seen["agent"]).toBe("codex"); + expect(seen["cmd"][0]).toBe("codex"); + expect(seen["cmd"]).toContain("--json"); + expect(db.get_heartbeat(hid)!["last_decision"]).toBe( + HeartbeatDecisionType.IDLE, + ); + }); + + test("test_execute_heartbeat_resume_decision_records_status", async () => { + const hid = db.add_heartbeat(make_heartbeat()); + // A non-idle, non-trigger decision flows down the generic finish branch. + _mock_agent( + sched, + JSON.stringify({ decision: "error", reason: "self-reported error" }), + ); + await sched._execute_heartbeat(db.get_heartbeat(hid)!); + const hb = db.get_heartbeat(hid)!; + expect(hb["last_decision"]).toBe(HeartbeatDecisionType.ERROR); + const tick = db.get_latest_heartbeat_tick(hid)!; + expect(tick["status"]).toBe(HeartbeatDecisionType.ERROR); + }); + + test("test_execute_heartbeat_trigger_then_suppressed_records_idle", async () => { + const hid = db.add_heartbeat(make_heartbeat({ cooldown_seconds: 600 })); + const payload = JSON.stringify({ + decision: "trigger_task", + dedupe_key: "dk", + prompt: "do it", + }); + _mock_agent(sched, payload); + + await sched._execute_heartbeat(db.get_heartbeat(hid)!); // first → triggers a task + expect(db.get_all_tasks().length).toBe(1); + await sched._execute_heartbeat(db.get_heartbeat(hid)!); // second → suppressed → idle + + expect(db.get_all_tasks().length).toBe(1); + const hb = db.get_heartbeat(hid)!; + expect(hb["last_decision"]).toBe(HeartbeatDecisionType.IDLE); + const tick = db.get_latest_heartbeat_tick(hid)!; + expect(JSON.parse(tick["decision_payload"])["reason"]).toContain( + "Suppressed duplicate", + ); + }); + + test("test_execute_heartbeat_trigger_uses_decision_prompt_over_template", async () => { + const hid = db.add_heartbeat( + make_heartbeat({ action_prompt_template: "TEMPLATE" }), + ); + _mock_agent( + sched, + JSON.stringify({ + decision: "trigger_task", + prompt: "CUSTOM PROMPT", + title: "Custom", + }), + ); + await sched._execute_heartbeat(db.get_heartbeat(hid)!); + const tasks = db.get_all_tasks(); + expect(tasks[0]!["prompt"]).toBe("CUSTOM PROMPT"); + expect(tasks[0]!["title"]).toBe("Custom"); + }); + + test("test_execute_heartbeat_codex_agent_failure_raises_inline", async () => { + const hid = db.add_heartbeat(make_heartbeat({ default_agent: "codex" })); + + (sched as any)._run_agent_command = async (): Promise< + [boolean, string] + > => [false, "codex crashed"]; + await sched._execute_heartbeat(db.get_heartbeat(hid)!); + const hb = db.get_heartbeat(hid)!; + expect(hb["last_decision"]).toBe(HeartbeatDecisionType.ERROR); + expect(hb["last_error"]).toContain("codex crashed"); + }); + + // ── _heartbeat_trigger_suppressed edge: unparseable triggered_at ──────── + test("test_trigger_suppressed_bad_timestamp_falls_through", () => { + const hid = db.add_heartbeat(make_heartbeat({ cooldown_seconds: 600 })); + db.upsert_heartbeat_dedup(hid, "k", null); + db.conn + .query( + "UPDATE heartbeat_dedup SET triggered_at=? WHERE heartbeat_id=? AND dedupe_key=?", + ) + .run("not-a-date", hid, "k"); + // bad timestamp → cooldown check skipped, no active task → not suppressed + expect( + sched._heartbeat_trigger_suppressed(db.get_heartbeat(hid)!, "k"), + ).toBe(false); + }); + + // ── pause / resume heartbeat ──────────────────────────────────────────── + test("test_pause_heartbeat_disables", () => { + const hid = db.add_heartbeat(make_heartbeat()); + sched.pause_heartbeat(hid); + expect(db.get_heartbeat(hid)!["enabled"]).toBe(false); + }); + + test("test_resume_heartbeat_enables_and_schedules", () => { + const hid = db.add_heartbeat(make_heartbeat()); + sched.pause_heartbeat(hid); + sched.resume_heartbeat(hid); + const hb = db.get_heartbeat(hid)!; + expect(hb["enabled"]).toBe(true); + expect(new Date(hb["next_run_at"]).getTime()).toBeGreaterThan(Date.now()); + }); + + test("test_pause_resume_unknown_raises", () => { + expect(() => sched.pause_heartbeat(99999)).toThrow(/not found/); + expect(() => sched.resume_heartbeat(99999)).toThrow(/not found/); + }); + + // ── trigger_heartbeat_now: already running guard ──────────────────────── + test("test_trigger_heartbeat_now_already_running_raises", () => { + const hid = db.add_heartbeat(make_heartbeat()); + + sched._active_heartbeats.set(hid, { is_alive: () => true }); + expect(() => sched.trigger_heartbeat_now(hid)).toThrow(/already running/); + }); + + // ── distill: contributing_task_ids parse fallbacks ────────────────────── + test("test_distill_skill_draft_bad_task_ids_json", async () => { + const pid = make_pattern(db); + // Corrupt the JSON so the parse fails → tids defaults to [] + db.conn + .query("UPDATE skill_patterns SET contributing_task_ids=? WHERE id=?") + .run("not json", pid); + const obj = { name: "X", description: "d", body_markdown: "b" }; + (sched as any)._run_agent_command = async (): Promise< + [boolean, string] + > => [true, JSON.stringify(obj)]; + + const draft = await sched.distill_skill_draft(pid, "claude"); + expect(draft["name"]).toBe("x"); + expect(db.get_skill_draft(pid)!["status"]).toBe("ready"); + }); + + test("test_distill_skill_draft_unknown_pattern_raises", async () => { + await expect(sched.distill_skill_draft(99999)).rejects.toThrow( + /pattern not found/, + ); + }); + + test("test_distill_falls_back_to_pattern_key_when_no_name", async () => { + const pid = make_pattern(db, "my-recurring-thing"); + const obj = { description: "d", body_markdown: "b" }; // no name + (sched as any)._run_agent_command = async (): Promise< + [boolean, string] + > => [true, JSON.stringify(obj)]; + const draft = await sched.distill_skill_draft(pid, "claude"); + expect(draft["name"]).toBe("my-recurring-thing"); + }); + + // ── trigger_skill_draft: marks 'drafting' for a real pattern ──────────── + test("test_trigger_skill_draft_sets_drafting_status", async () => { + const pid = make_pattern(db); + // keep the agent from doing anything real; the worker will use it + (sched as any).distill_skill_draft = async () => { + db.upsert_skill_draft(pid, "ready", "x", "", "recipe", "b"); + }; + expect(sched.trigger_skill_draft(pid)).toBe(true); + // row exists (either still 'drafting' or already 'ready' from the worker) + const draft = db.get_skill_draft(pid); + expect(draft).not.toBeNull(); + expect(["drafting", "ready"]).toContain(draft!["status"]); + }); + + // ── distill prompt building: codex agent default resolution ───────────── + test("test_distill_agent_resolution_uses_setting", async () => { + db.set_setting("skill_sweep_agent", "codex"); + const pid = make_pattern(db); + const seen: Row = {}; + const obj = { name: "x", description: "d", body_markdown: "b" }; + + (sched as any)._run_agent_command = async ( + agent: string, + ): Promise<[boolean, string]> => { + seen["agent"] = agent; + return [true, JSON.stringify(obj)]; + }; + await sched.distill_skill_draft(pid); // no agent arg → resolves from setting + expect(seen["agent"]).toBe("codex"); + }); + + // ── skill-sweep: non-dict items skipped, recurrence drives 'new' ──────── + test("test_run_skill_sweep_skips_non_dict_items", async () => { + const tid = db.add_task( + makeTask({ title: "t", prompt: "p", working_dir: "." }), + ); + const rid = db.add_run(tid); + db.finish_run(rid, "completed", "ok"); + + const payload = JSON.stringify([ + "garbage-string", // non-dict → skipped + { pattern_key: "real", kind: "recipe", summary: "s", task_id: tid }, + { pattern_key: "", kind: "recipe", summary: "s" }, // blank key → not upserted + ]); + (sched as any)._run_agent_command = async (): Promise< + [boolean, string] + > => [true, payload]; + + const result = await sched.run_skill_sweep("claude", true); + expect(result["scanned"]).toBe(1); + expect(result["detected"]).toBe(1); // only the valid keyed entry + expect(db.get_skill_pattern_recurrence("real")).toBe(1); + }); + + test("test_run_skill_sweep_resolves_default_agent_setting", async () => { + db.set_setting("default_agent", "codex"); + const result = await sched.run_skill_sweep(); // no runs → short-circuits but resolves agent + expect(result["agent"]).toBe("codex"); + }); + + // ── trigger_skill_sweep background worker captures error ──────────────── + test("test_trigger_skill_sweep_worker_records_error", async () => { + const tid = db.add_task( + makeTask({ title: "t", prompt: "p", working_dir: "." }), + ); + const rid = db.add_run(tid); + db.finish_run(rid, "completed", "ok"); + + (sched as any).run_skill_sweep = async () => { + throw new Error("worker boom"); + }; + expect(sched.trigger_skill_sweep(null, true)).toBe(true); + // poll until the background worker records the error to sweep status + for (let i = 0; i < 50; i++) { + const status = sched.skill_sweep_status(); + if (status.last && "error" in status.last) break; + await new Promise((r) => setTimeout(r, 20)); + } + const status = sched.skill_sweep_status(); + expect(status.running).toBe(false); + expect(status.last!["error"]).toBe("worker boom"); + }); + + // ── DAG post-execution hooks: scheduled_at / cron unblock to 'scheduled' ─ + test("test_on_task_completed_unblocks_scheduled_at_to_scheduled", () => { + const up = db.add_task( + makeTask({ title: "up", prompt: "p", working_dir: "." }), + ); + const future = new Date(Date.now() + 2 * 3600 * 1000).toISOString(); + const down = sched.submit_task( + makeTask({ + title: "down", + prompt: "p", + working_dir: ".", + schedule_type: ScheduleType.SCHEDULED_AT, + next_run_at: future, + }), + [up], + ); + expect(db.get_task(down)!["status"]).toBe("blocked"); + + db.update_task(up, { status: "completed" }); + sched._on_task_completed(up); + // scheduled_at downstream unblocks into 'scheduled', not 'pending' + expect(db.get_task(down)!["status"]).toBe("scheduled"); + }); + + test("test_on_task_completed_unblocks_cron_to_scheduled", () => { + const up = db.add_task( + makeTask({ title: "up", prompt: "p", working_dir: "." }), + ); + const down = sched.submit_task( + makeTask({ + title: "down", + prompt: "p", + working_dir: ".", + schedule_type: ScheduleType.CRON, + cron_expr: "0 0 * * *", + }), + [up], + ); + db.update_task(up, { status: "completed" }); + sched._on_task_completed(up); + expect(db.get_task(down)!["status"]).toBe("scheduled"); + }); + + test("test_on_task_completed_unblocks_delayed_to_pending", () => { + const up = db.add_task( + makeTask({ title: "up", prompt: "p", working_dir: "." }), + ); + const down = sched.submit_task( + makeTask({ + title: "down", + prompt: "p", + working_dir: ".", + schedule_type: ScheduleType.DELAYED, + delay_seconds: 30, + }), + [up], + ); + db.update_task(up, { status: "completed" }); + sched._on_task_completed(up); + expect(db.get_task(down)!["status"]).toBe("pending"); + }); + + test("test_on_task_completed_unblocks_immediate_to_pending", () => { + const up = db.add_task( + makeTask({ title: "up", prompt: "p", working_dir: "." }), + ); + const down = sched.submit_task( + makeTask({ title: "down", prompt: "p", working_dir: "." }), // immediate + [up], + ); + expect(db.get_task(down)!["status"]).toBe("blocked"); + db.update_task(up, { status: "completed" }); + sched._on_task_completed(up); + expect(db.get_task(down)!["status"]).toBe("pending"); + }); + + test("test_on_task_failed_cancels_pending_and_scheduled_downstream", () => { + // The existing suite covers the blocked→cancelled chain; here we exercise the + // pending/scheduled cancellable states and a diamond (shared downstream). + const root = db.add_task( + makeTask({ title: "root", prompt: "p", working_dir: "." }), + ); + const a = db.add_task( + makeTask({ title: "a", prompt: "p", working_dir: "." }), + ); + const b = db.add_task( + makeTask({ title: "b", prompt: "p", working_dir: "." }), + ); + db.add_dependency(a, root); + db.add_dependency(b, root); + db.update_task(a, { status: "pending" }); + db.update_task(b, { status: "scheduled" }); + sched._on_task_failed(root); + expect(db.get_task(a)!["status"]).toBe("cancelled"); + expect(db.get_task(b)!["status"]).toBe("cancelled"); + }); + + test("test_on_task_completed_ignores_non_blocked_dependents", () => { + const up = db.add_task( + makeTask({ title: "up", prompt: "p", working_dir: "." }), + ); + const down = db.add_task( + makeTask({ title: "down", prompt: "p", working_dir: "." }), + ); + db.add_dependency(down, up); + // downstream is 'pending', not 'blocked' → hook leaves it alone + db.update_task(up, { status: "completed" }); + sched._on_task_completed(up); + expect(db.get_task(down)!["status"]).toBe("pending"); + }); + + test("test_on_task_failed_skips_already_running_downstream", () => { + const root = db.add_task( + makeTask({ title: "root", prompt: "p", working_dir: "." }), + ); + const down = db.add_task( + makeTask({ title: "down", prompt: "p", working_dir: "." }), + ); + db.add_dependency(down, root); + db.update_task(down, { status: "running" }); // not a cancellable state + sched._on_task_failed(root); + expect(db.get_task(down)!["status"]).toBe("running"); // untouched + }); + + // ── cancel_task with a registered pgid path ───────────────────────────── + test("test_cancel_task_with_pgid_attempts_killpg", () => { + const tid = db.add_task( + makeTask({ title: "t", prompt: "p", working_dir: "." }), + ); + db.update_task(tid, { status: "running" }); + sched._active_pgids.set(tid, 424242); + const killed: number[] = []; + sched._os = { + ...default_os, + killpg: (pgid: number) => { + killed.push(pgid); + }, + }; + sched.cancel_task(tid); + expect(killed).toEqual([424242]); + expect(db.get_task(tid)!["status"]).toBe("cancelled"); + }); + + test("test_cancel_task_pgid_killpg_oserror_swallowed", () => { + const tid = db.add_task( + makeTask({ title: "t", prompt: "p", working_dir: "." }), + ); + sched._active_pgids.set(tid, 999); + + sched._os = { + ...default_os, + killpg: () => { + throw new OSError("no such pgid"); + }, + }; + sched.cancel_task(tid); // must not raise + expect(db.get_task(tid)!["status"]).toBe("cancelled"); + }); + + // ── _build_injected_prompt: multiple upstreams concatenated ───────────── + test("test_build_injected_prompt_multiple_upstreams", () => { + const u1 = db.add_task( + makeTask({ title: "u1", prompt: "p", working_dir: "." }), + ); + const u2 = db.add_task( + makeTask({ title: "u2", prompt: "p", working_dir: "." }), + ); + db.update_task(u1, { status: "completed", result: "RESULT ONE" }); + db.update_task(u2, { status: "completed", result: "RESULT TWO" }); + const down = db.add_task( + makeTask({ title: "down", prompt: "MAIN", working_dir: "." }), + ); + db.add_dependency(down, u1, true); + db.add_dependency(down, u2, true); + + const injected = sched._build_injected_prompt(db.get_task(down)!); + expect(injected).toContain("RESULT ONE"); + expect(injected).toContain("RESULT TWO"); + expect(injected.trim().endsWith("MAIN")).toBe(true); + }); + + test("test_build_injected_prompt_skips_upstream_without_result", () => { + const up = db.add_task( + makeTask({ title: "up", prompt: "p", working_dir: "." }), + ); + db.update_task(up, { status: "completed" }); // no result set + const down = db.add_task( + makeTask({ title: "down", prompt: "ORIG", working_dir: "." }), + ); + db.add_dependency(down, up, true); + // inject requested but upstream has no result → original prompt unchanged + expect(sched._build_injected_prompt(db.get_task(down)!)).toBe("ORIG"); + }); +}); diff --git a/backend/tests/skill-patterns.test.ts b/backend/tests/skill-patterns.test.ts new file mode 100644 index 0000000..3f9e4ad --- /dev/null +++ b/backend/tests/skill-patterns.test.ts @@ -0,0 +1,261 @@ +// Skill-pattern ledger + skill-sweep tests. +// +// Ported from tests/test_skill_patterns.py; test() descriptions keep the +// Python test function names. + +import { afterEach, beforeEach, describe, expect, test } from "bun:test"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; +import { TaskDB } from "../src/db.ts"; +import { TaskScheduler } from "../src/scheduler.ts"; +import { makeTask } from "../src/types.ts"; + +describe("skill patterns", () => { + let tmpDir: string; + let db: TaskDB; + + beforeEach(() => { + tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "agentforge-test-")); + db = new TaskDB(path.join(tmpDir, "agentforge-test.db")); + }); + + afterEach(() => { + db.conn.close(); + fs.rmSync(tmpDir, { recursive: true, force: true }); + }); + + function add_completed_task( + title = "Run tests", + prompt = "run the test suite", + result = "ok", + ) { + const tid = db.add_task(makeTask({ title, prompt, working_dir: "." })); + const run_id = db.add_run(tid); + db.finish_run(run_id, "completed", result, null, ""); + return tid; + } + + // ── upsert / dedup ledger ────────────────────────────────────────────── + test("test_upsert_new_then_bump", () => { + const pid = db.upsert_skill_pattern( + "run-pytest", + "recipe", + "run pytest suite", + 1, + ); + expect(pid).not.toBeNull(); + + let patterns = db.get_skill_patterns(); + expect(patterns.length).toBe(1); + expect(patterns[0]!["recurrence_count"]).toBe(1); + expect(JSON.parse(patterns[0]!["contributing_task_ids"])).toEqual([1]); + expect(patterns[0]!["status"]).toBe("tracking"); + + db.upsert_skill_pattern("run-pytest", "recipe", "updated summary", 2); + patterns = db.get_skill_patterns(); + expect(patterns.length).toBe(1); + expect(patterns[0]!["recurrence_count"]).toBe(2); + expect(new Set(JSON.parse(patterns[0]!["contributing_task_ids"]))).toEqual( + new Set([1, 2]), + ); + expect(patterns[0]!["summary"]).toBe("updated summary"); + }); + + test("test_upsert_distinct_keys", () => { + db.upsert_skill_pattern("a", "recipe", "s", 1); + db.upsert_skill_pattern("b", "pitfall", "s", 1); + const patterns = db.get_skill_patterns(); + expect(patterns.length).toBe(2); + expect(new Set(patterns.map((p) => p["kind"]))).toEqual( + new Set(["recipe", "pitfall"]), + ); + }); + + test("test_upsert_ignores_blank_key", () => { + expect(db.upsert_skill_pattern("", "recipe", "s", 1)).toBeNull(); + expect(db.upsert_skill_pattern(" ", "recipe", "s", 1)).toBeNull(); + expect(db.get_skill_patterns()).toEqual([]); + }); + + test("test_upsert_invalid_kind_defaults_to_recipe", () => { + db.upsert_skill_pattern("k", "bogus", "s", 1); + expect(db.get_skill_patterns()[0]!["kind"]).toBe("recipe"); + }); + + test("test_same_task_counts_occurrence_but_not_distinct", () => { + db.upsert_skill_pattern("k", "recipe", "s", 5); + db.upsert_skill_pattern("k", "recipe", "s", 5); + const p = db.get_skill_patterns()[0]!; + expect(p["recurrence_count"]).toBe(2); // each observation bumps the count + expect(JSON.parse(p["contributing_task_ids"])).toEqual([5]); // but distinct tasks stay = 1 + }); + + // ── completed-runs watermark query ───────────────────────────────────── + test("test_get_completed_runs_since_watermark", () => { + add_completed_task(); + add_completed_task("Deploy"); + expect(db.get_completed_runs_since("").length).toBe(2); + expect(db.get_completed_runs_since("2999-01-01T00:00:00")).toEqual([]); + }); + + test("test_get_completed_runs_excludes_unfinished", () => { + const tid = db.add_task(makeTask({ title: "Pending", prompt: "x" })); + db.add_run(tid); // left running, no finish + expect(db.get_completed_runs_since("")).toEqual([]); + }); + + // ── sweep output parsing ─────────────────────────────────────────────── + test("test_parse_sweep_output_variants", () => { + const sched = new TaskScheduler(db); + const arr = + '[{"pattern_key":"x","kind":"recipe","summary":"s","task_id":1}]'; + expect((sched._parse_sweep_output(arr)[0] as any)["pattern_key"]).toBe("x"); + expect( + (sched._parse_sweep_output("```json\n" + arr + "\n```")[0] as any)[ + "pattern_key" + ], + ).toBe("x"); + expect( + (sched._parse_sweep_output("Here you go:\n" + arr + "\nDone.")[0] as any)[ + "pattern_key" + ], + ).toBe("x"); + expect(sched._parse_sweep_output("nonsense")).toEqual([]); + expect(sched._parse_sweep_output("[]")).toEqual([]); + expect(sched._parse_sweep_output("")).toEqual([]); + }); + + // ── full sweep (mocked agent) ────────────────────────────────────────── + test("test_run_skill_sweep_upserts_and_advances_watermark", async () => { + const sched = new TaskScheduler(db); + const t1 = add_completed_task("Run tests", "run pytest"); + const t2 = add_completed_task("Run tests again", "run the suite"); + + const payload = JSON.stringify([ + { + pattern_key: "run-test-suite", + kind: "recipe", + summary: "run pytest", + task_id: t1, + }, + { + pattern_key: "run-test-suite", + kind: "recipe", + summary: "run pytest", + task_id: t2, + }, + ]); + + (sched as any)._run_agent_command = async (): Promise< + [boolean, string] + > => [true, payload]; + + const result = await sched.run_skill_sweep("claude"); + expect(result["scanned"]).toBe(2); + expect(result["detected"]).toBe(2); + + const patterns = db.get_skill_patterns(); + expect(patterns.length).toBe(1); + expect(patterns[0]!["recurrence_count"]).toBe(2); + expect(new Set(JSON.parse(patterns[0]!["contributing_task_ids"]))).toEqual( + new Set([t1, t2]), + ); + + expect(db.get_setting("skill_sweep_watermark", "")).not.toBe(""); + + // second sweep: watermark consumed everything → nothing new + const result2 = await sched.run_skill_sweep("claude"); + expect(result2["scanned"]).toBe(0); + expect(result2["detected"]).toBe(0); + }); + + test("test_run_skill_sweep_empty_history", async () => { + const sched = new TaskScheduler(db); + const result = await sched.run_skill_sweep("claude"); + expect(result["scanned"]).toBe(0); + expect(result["detected"]).toBe(0); + expect(result["agent"]).toBe("claude"); + expect(result["watermark"]).toBe(""); + }); + + test("test_upsert_run_id_idempotent", () => { + // same run_id seen twice → counted once + db.upsert_skill_pattern("k", "recipe", "s", 1, 100); + db.upsert_skill_pattern("k", "recipe", "s", 1, 100); + let p = db.get_skill_patterns()[0]!; + expect(p["recurrence_count"]).toBe(1); + expect(JSON.parse(p["contributing_run_ids"])).toEqual([100]); + // a different run of the same task → new occurrence + db.upsert_skill_pattern("k", "recipe", "s", 1, 101); + p = db.get_skill_patterns()[0]!; + expect(p["recurrence_count"]).toBe(2); + expect(new Set(JSON.parse(p["contributing_run_ids"]))).toEqual( + new Set([100, 101]), + ); + expect(JSON.parse(p["contributing_task_ids"])).toEqual([1]); // still one distinct task + }); + + test("test_full_sweep_rescan_does_not_inflate", async () => { + const sched = new TaskScheduler(db); + const t1 = add_completed_task("ETL", "run weekly etl"); + const t2 = add_completed_task("ETL", "run weekly etl again"); + const run1 = db.get_task_runs(t1)[0]!["id"]; + const run2 = db.get_task_runs(t2)[0]!["id"]; + + const payload = JSON.stringify([ + { + pattern_key: "weekly-etl", + kind: "recipe", + summary: "etl", + run_id: run1, + task_id: t1, + }, + { + pattern_key: "weekly-etl", + kind: "recipe", + summary: "etl", + run_id: run2, + task_id: t2, + }, + ]); + (sched as any)._run_agent_command = async (): Promise< + [boolean, string] + > => [true, payload]; + + const r1 = await sched.run_skill_sweep("claude", true); + expect(r1["scanned"]).toBe(2); + expect(r1["new"]).toBe(2); + expect(db.get_skill_patterns()[0]!["recurrence_count"]).toBe(2); + + // Re-scan the SAME runs → idempotent: recurrence unchanged, no new occurrences + const r2 = await sched.run_skill_sweep("claude", true); + expect(r2["scanned"]).toBe(2); + expect(r2["new"]).toBe(0); + expect(db.get_skill_patterns()[0]!["recurrence_count"]).toBe(2); + }); + + test("test_run_skill_sweep_agent_failure_raises", async () => { + const sched = new TaskScheduler(db); + add_completed_task(); + + (sched as any)._run_agent_command = async (): Promise< + [boolean, string] + > => [false, "agent exploded"]; + + await expect(sched.run_skill_sweep("claude")).rejects.toThrow( + /agent exploded/, + ); + // failed sweep must not advance the watermark + expect(db.get_setting("skill_sweep_watermark", "")).toBe(""); + }); + + test("test_trigger_skill_sweep_guards_concurrency", () => { + const sched = new TaskScheduler(db); + // Simulate an in-flight sweep + sched._skill_sweep_running = true; + expect(sched.trigger_skill_sweep()).toBe(false); + const status = sched.skill_sweep_status(); + expect(status.running).toBe(true); + }); +}); From 518871cd1dece22c718917308d3ac3e6c8edc72f Mon Sep 17 00:00:00 2001 From: taohe Date: Sat, 13 Jun 2026 09:39:31 +0800 Subject: [PATCH 18/18] Complete Bun TypeScript migration --- .gitignore | 6 + .python-version | 1 - README.md | 8 +- README.zh.md | 6 +- backend/src/api.ts | 1388 +++++ backend/src/channels/feishu.ts | 1878 ++++++ backend/src/channels/slack.ts | 6 +- backend/src/channels/telegram.ts | 2 +- backend/src/channels/weixin.ts | 1157 ++++ backend/src/channels/weixin_bridge/index.ts | 13 +- .../src/channels/weixin_bridge/package.json | 7 - backend/src/executor.ts | 15 +- backend/src/scheduler.ts | 376 +- backend/src/server.ts | 196 + backend/src/skills.ts | 37 +- backend/taskboard.ts | 27 + backend/tests/api-handler.test.ts | 1620 +++++ backend/tests/dir-utils.test.ts | 103 + backend/tests/executor-wrappers.test.ts | 93 + backend/tests/feishu-channel.test.ts | 1393 +++++ backend/tests/gaps.test.ts | 7 +- backend/tests/gaps2.test.ts | 13 +- backend/tests/server-lifecycle.test.ts | 122 + backend/tests/slack-more.test.ts | 4 +- backend/tests/telegram-channel.test.ts | 2 +- backend/tests/weixin-channel.test.ts | 759 +++ channels/README.md | 324 - channels/__init__.py | 1 - channels/agent_utils.py | 68 - channels/dir_utils.py | 132 - channels/feishu_channel.py | 1961 ------ channels/slack_channel.py | 646 -- channels/telegram_channel.py | 621 -- channels/weixin_bridge/index.mjs | 824 --- channels/weixin_bridge/package.json | 10 - channels/weixin_channel.py | 725 --- index.html | 4 +- pyproject.toml | 59 - .../{chunk-nbmpy57s.js => chunk-qgtap3d3.js} | 68 +- ...-nbmpy57s.js.map => chunk-qgtap3d3.js.map} | 8 +- taskboard-electron/.bun/renderer/index.html | 2 +- taskboard-electron/forge.config.js | 6 +- taskboard-electron/scripts/build-backend.ts | 39 +- taskboard-electron/scripts/build.ts | 13 +- taskboard-electron/src/main.ts | 14 +- taskboard-electron/src/renderer/App.tsx | 18 +- .../src/renderer/channelsSettings.test.ts | 67 + .../src/renderer/channelsSettings.ts | 56 +- taskboard.py | 5240 ----------------- taskboard.spec | 38 - taskboard_bus.py | 410 -- tests/__init__.py | 0 tests/conftest.py | 10 - tests/test_api_handler.py | 910 --- tests/test_api_handler_more.py | 762 --- tests/test_channel_utils.py | 96 - tests/test_claude_streaming_events.py | 157 - tests/test_codex_streaming_events.py | 283 - tests/test_dir_utils.py | 137 - tests/test_execute_task.py | 695 --- tests/test_feishu_forwarded_messages.py | 316 - tests/test_feishu_inbound.py | 597 -- tests/test_feishu_lifecycle.py | 834 --- tests/test_feishu_message_rendering.py | 741 --- tests/test_feishu_outbound.py | 552 -- tests/test_heartbeat.py | 149 - tests/test_scheduler_logic.py | 689 --- tests/test_scheduler_more.py | 731 --- tests/test_scheduler_timezones.py | 96 - tests/test_server_lifecycle.py | 206 - tests/test_skill_distill.py | 225 - tests/test_skill_patterns.py | 232 - tests/test_skill_registry.py | 106 - tests/test_skill_scheduler.py | 79 - tests/test_slack_channel.py | 508 -- tests/test_slack_more.py | 433 -- tests/test_task_output_api.py | 30 - tests/test_taskboard_bus.py | 230 - tests/test_taskboard_gaps.py | 522 -- tests/test_taskboard_gaps2.py | 792 --- tests/test_taskdb.py | 333 -- tests/test_telegram_channel.py | 580 -- tests/test_telegram_forwarded_messages.py | 503 -- tests/test_telegram_more.py | 507 -- tests/test_weixin_channel.py | 538 -- tests/test_weixin_more.py | 844 --- tests/test_weixin_status.py | 38 - uv.lock | 959 --- 88 files changed, 9332 insertions(+), 26681 deletions(-) delete mode 100644 .python-version create mode 100644 backend/src/api.ts create mode 100644 backend/src/channels/feishu.ts create mode 100644 backend/src/channels/weixin.ts delete mode 100644 backend/src/channels/weixin_bridge/package.json create mode 100644 backend/src/server.ts create mode 100644 backend/taskboard.ts create mode 100644 backend/tests/api-handler.test.ts create mode 100644 backend/tests/dir-utils.test.ts create mode 100644 backend/tests/executor-wrappers.test.ts create mode 100644 backend/tests/feishu-channel.test.ts create mode 100644 backend/tests/server-lifecycle.test.ts create mode 100644 backend/tests/weixin-channel.test.ts delete mode 100644 channels/README.md delete mode 100644 channels/__init__.py delete mode 100644 channels/agent_utils.py delete mode 100644 channels/dir_utils.py delete mode 100644 channels/feishu_channel.py delete mode 100644 channels/slack_channel.py delete mode 100644 channels/telegram_channel.py delete mode 100644 channels/weixin_bridge/index.mjs delete mode 100644 channels/weixin_bridge/package.json delete mode 100644 channels/weixin_channel.py delete mode 100644 pyproject.toml rename taskboard-electron/.bun/renderer/{chunk-nbmpy57s.js => chunk-qgtap3d3.js} (99%) rename taskboard-electron/.bun/renderer/{chunk-nbmpy57s.js.map => chunk-qgtap3d3.js.map} (82%) delete mode 100644 taskboard.py delete mode 100644 taskboard.spec delete mode 100644 taskboard_bus.py delete mode 100644 tests/__init__.py delete mode 100644 tests/conftest.py delete mode 100644 tests/test_api_handler.py delete mode 100644 tests/test_api_handler_more.py delete mode 100644 tests/test_channel_utils.py delete mode 100644 tests/test_claude_streaming_events.py delete mode 100644 tests/test_codex_streaming_events.py delete mode 100644 tests/test_dir_utils.py delete mode 100644 tests/test_execute_task.py delete mode 100644 tests/test_feishu_forwarded_messages.py delete mode 100644 tests/test_feishu_inbound.py delete mode 100644 tests/test_feishu_lifecycle.py delete mode 100644 tests/test_feishu_message_rendering.py delete mode 100644 tests/test_feishu_outbound.py delete mode 100644 tests/test_heartbeat.py delete mode 100644 tests/test_scheduler_logic.py delete mode 100644 tests/test_scheduler_more.py delete mode 100644 tests/test_scheduler_timezones.py delete mode 100644 tests/test_server_lifecycle.py delete mode 100644 tests/test_skill_distill.py delete mode 100644 tests/test_skill_patterns.py delete mode 100644 tests/test_skill_registry.py delete mode 100644 tests/test_skill_scheduler.py delete mode 100644 tests/test_slack_channel.py delete mode 100644 tests/test_slack_more.py delete mode 100644 tests/test_task_output_api.py delete mode 100644 tests/test_taskboard_bus.py delete mode 100644 tests/test_taskboard_gaps.py delete mode 100644 tests/test_taskboard_gaps2.py delete mode 100644 tests/test_taskdb.py delete mode 100644 tests/test_telegram_channel.py delete mode 100644 tests/test_telegram_forwarded_messages.py delete mode 100644 tests/test_telegram_more.py delete mode 100644 tests/test_weixin_channel.py delete mode 100644 tests/test_weixin_more.py delete mode 100644 tests/test_weixin_status.py delete mode 100644 uv.lock diff --git a/.gitignore b/.gitignore index 5edfa31..5ca70c2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,17 @@ # Python-generated files __pycache__/ *.py[oc] +.pytest_cache/ +.ruff_cache/ +.python-version build/ dist/ wheels/ *.egg-info +# JS/Bun dependencies +node_modules/ + # Virtual environments .venv .coverage diff --git a/.python-version b/.python-version deleted file mode 100644 index e4fba21..0000000 --- a/.python-version +++ /dev/null @@ -1 +0,0 @@ -3.12 diff --git a/README.md b/README.md index f07304a..34dbe48 100644 --- a/README.md +++ b/README.md @@ -304,7 +304,7 @@ Or configure from the desktop app's settings page.
WeChat setup (experimental) -WeChat uses a Node.js sidecar bridge — no environment variables needed. Configure and enable it via the API or the desktop app's settings page. +WeChat uses a Bun/TypeScript sidecar bridge — no environment variables needed. Configure and enable it via the API or the desktop app's settings page. ### 1. Enable via API @@ -331,7 +331,7 @@ On first launch the bridge will request a QR code login. Scan it with your WeCha
-> See [`channels/README.md`](channels/README.md) for detailed setup, notification behavior, and adding custom channels. +Channel adapters live in [`backend/src/channels/`](backend/src/channels/). Configure them from the desktop app settings page or the REST endpoints shown above. --- @@ -461,14 +461,14 @@ Contributions are welcome! Here's how to get started: 1. Fork the repository and create a feature branch. 2. Start the app in development mode (see [Option 3](#option-3-development-mode) above). -3. Make your changes and verify them manually — there are no automated tests. +3. Make your changes and run the relevant Bun quality gate (`make check` for backend changes; the frontend gate from `taskboard-electron/` for renderer/Electron changes). 4. Open a pull request with a clear description of the change. **Key files:** - `backend/` — entire TypeScript backend (DB, scheduler, executor, HTTP API, channels) - `taskboard-electron/src/main.ts` — Electron main process - `taskboard-electron/src/renderer/App.tsx` — React frontend -- `channels/` — pluggable chat channel adapters (Telegram, Slack, Feishu, WeChat) +- `backend/src/channels/` — pluggable chat channel adapters (Telegram, Slack, Feishu, WeChat) - `skills/agentforge/` — Claude Code skill for agent-to-agent delegation --- diff --git a/README.zh.md b/README.zh.md index 59b03d0..f9e1b06 100644 --- a/README.zh.md +++ b/README.zh.md @@ -279,7 +279,7 @@ curl -X POST http://127.0.0.1:9712/api/feishu/settings \ -> 详细配置、通知行为及自定义频道开发,请参阅 [`channels/README.md`](channels/README.md)。 +频道适配器位于 [`backend/src/channels/`](backend/src/channels/),可在桌面应用设置页或上面的 REST 接口中配置。 --- @@ -409,14 +409,14 @@ launchctl load ~/Library/LaunchAgents/com.agentforge.taskboard.plist 1. Fork 本仓库并创建功能分支。 2. 以开发模式启动应用(参见[方式三](#方式三开发模式))。 -3. 修改代码并手动验证——项目目前没有自动化测试。 +3. 修改代码并运行对应的 Bun 质量门禁(后端改动运行 `make check`;前端/Electron 改动在 `taskboard-electron/` 下运行前端门禁)。 4. 提交 PR,并清晰描述改动内容。 **关键文件:** - `backend/` —— 整个 TypeScript 后端(数据库、调度器、执行器、HTTP API、频道) - `taskboard-electron/src/main.ts` —— Electron 主进程 - `taskboard-electron/src/renderer/App.tsx` —— React 前端 -- `channels/` —— 可插拔消息频道适配器 +- `backend/src/channels/` —— 可插拔消息频道适配器 - `skills/agentforge/` —— 用于智能体间委托的 Claude Code Skill --- diff --git a/backend/src/api.ts b/backend/src/api.ts new file mode 100644 index 0000000..0933b52 --- /dev/null +++ b/backend/src/api.ts @@ -0,0 +1,1388 @@ +import crypto from "node:crypto"; +import fs from "node:fs"; +import os from "node:os"; +import { CronExpressionParser } from "cron-parser"; + +import { MessageBus } from "./bus.ts"; +import type { TaskDB } from "./db.ts"; +import type { TaskScheduler } from "./scheduler.ts"; +import { + DEFAULT_AGENT, + DEFAULT_TIMEOUT_SECONDS, + HeartbeatScheduleType, + ScheduleType, + makeHeartbeat, + makeTask, + type Heartbeat, + type Task, +} from "./types.ts"; +import { dateToLocalIso } from "./util.ts"; +import { FeishuChannel } from "./channels/feishu.ts"; +import { SlackChannel } from "./channels/slack.ts"; +import { + create_telegram_channel, + type TelegramChannel, +} from "./channels/telegram.ts"; +import { WeixinChannel } from "./channels/weixin.ts"; + +type Row = Record; + +export interface ApiContext { + db: TaskDB; + scheduler: TaskScheduler; + bus: MessageBus; + telegram_channel: TelegramChannel | null; + slack_channel: SlackChannel | null; + weixin_channel: WeixinChannel | null; + feishu_channel: FeishuChannel | null; +} + +const CSRF_TOKEN = crypto.randomBytes(32).toString("hex"); +const MAX_BODY_SIZE = 10 * 1024 * 1024; + +function isAllowedOrigin(origin: string): boolean { + if (origin === "null") return true; + if (!origin) return true; + return ( + origin === "http://localhost" || origin.startsWith("http://localhost:") + ); +} + +function corsHeaders(origin: string): Headers { + const headers = new Headers({ + "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS", + "Access-Control-Allow-Headers": "Content-Type, X-CSRF-Token", + }); + if (isAllowedOrigin(origin)) { + headers.set("Access-Control-Allow-Origin", origin); + headers.set("Vary", "Origin"); + } + return headers; +} + +function jsonResponse(data: unknown, status = 200, origin = ""): Response { + const headers = corsHeaders(origin); + headers.set("Content-Type", "application/json"); + return new Response(JSON.stringify(data), { status, headers }); +} + +function timingSafeEqual(a: string, b: string): boolean { + const left = Buffer.from(a); + const right = Buffer.from(b); + return left.length === right.length && crypto.timingSafeEqual(left, right); +} + +function checkCsrf(req: Request): boolean { + const origin = req.headers.get("Origin") ?? ""; + if (!origin) return true; + return timingSafeEqual(req.headers.get("X-CSRF-Token") ?? "", CSRF_TOKEN); +} + +async function readJsonBody( + req: Request, + origin: string, +): Promise { + const rawLength = req.headers.get("Content-Length") ?? "0"; + const length = Number.parseInt(rawLength, 10) || 0; + if (length > MAX_BODY_SIZE) { + void req.body?.cancel(); + return jsonResponse({ error: "request body too large" }, 413, origin); + } + const raw = await req.text(); + if (!raw) return {}; + try { + const parsed = JSON.parse(raw); + if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) { + return parsed as Row; + } + return {}; + } catch { + return jsonResponse({ error: "invalid JSON body" }, 400, origin); + } +} + +function idAt(path: string, index = 3): number | null { + const raw = path.split("/")[index]; + if (!raw || !/^\d+$/.test(raw)) return null; + return Number.parseInt(raw, 10); +} + +function asBool(value: unknown): boolean { + if (typeof value === "boolean") return value; + if (typeof value === "string") return value.toLowerCase() === "true"; + return Boolean(value); +} + +function asString(value: unknown, fallback = ""): string { + if (value === null || value === undefined) return fallback; + return String(value); +} + +function parseJsonList(value: unknown): any[] { + if (Array.isArray(value)) return value; + if (typeof value === "string") { + try { + const parsed = JSON.parse(value); + return Array.isArray(parsed) ? parsed : []; + } catch { + return []; + } + } + return []; +} + +function cronValid(expr: string): boolean { + try { + CronExpressionParser.parse(expr); + return true; + } catch { + return false; + } +} + +function cronNextIso(expr: string): string { + return dateToLocalIso(CronExpressionParser.parse(expr).next().toDate()); +} + +function ensureWorkingDir( + workingDir: string, + missingMessage: string, +): Row | null { + if (workingDir && workingDir !== ".") { + const expanded = + workingDir === "~" + ? os.homedir() + : workingDir.replace(/^~\//, `${os.homedir()}/`); + if (!fs.existsSync(expanded) || !fs.statSync(expanded).isDirectory()) { + return { error: missingMessage, field: "working_dir" }; + } + } + return null; +} + +function dependencyList( + value: unknown, + forceInject = false, +): Array<{ task_id: number; inject_result: boolean }> { + const deps: Array<{ task_id: number; inject_result: boolean }> = []; + if (!Array.isArray(value)) return deps; + for (const item of value) { + if (Number.isInteger(item)) { + deps.push({ task_id: item, inject_result: forceInject }); + } else if (item && typeof item === "object" && "task_id" in item) { + deps.push({ + task_id: Number((item as Row)["task_id"]), + inject_result: forceInject || Boolean((item as Row)["inject_result"]), + }); + } + } + return deps.filter((d) => Number.isInteger(d.task_id)); +} + +function attachDependencyMetadata(db: TaskDB, task: Row): Row { + const tid = Number(task["id"]); + return { + ...task, + dependencies: db.get_dependencies(tid), + dependents: db.get_dependents(tid).map((d) => d["task_id"]), + }; +} + +function taskOutputPayload(ctx: ApiContext, taskId: number): Row { + const isRunning = ctx.scheduler._live_output.has(taskId); + if (isRunning) { + return { + output: ctx.scheduler._live_output.get(taskId) ?? "", + is_running: true, + }; + } + const runs = ctx.db.get_task_runs(taskId, 1); + return { output: runs[0]?.["raw_output"] ?? "", is_running: false }; +} + +function taskMessages(ctx: ApiContext, taskId: number): Row[] { + const messages: Row[] = []; + const runs = ctx.db.get_task_runs(taskId, 50); + for (const run of [...runs].reverse()) { + for (const rawLine of String(run["raw_output"] ?? "").split(/\r?\n/)) { + const line = rawLine.trim(); + if (!line) continue; + try { + const event = JSON.parse(line) as Row; + const content = event["message"]?.["content"] ?? []; + if (event["type"] === "user") { + const text = content + .map((c: unknown) => + typeof c === "string" + ? c + : c && typeof c === "object" && (c as Row)["type"] === "text" + ? (c as Row)["text"] + : "", + ) + .join(""); + if (text.trim()) + messages.push({ role: "user", text, run_id: run["id"] }); + } else if (event["type"] === "assistant") { + const text = Array.isArray(content) + ? content + .map((c) => + c && typeof c === "object" && c["type"] === "text" + ? c["text"] + : "", + ) + .join("") + : ""; + if (text.trim()) + messages.push({ role: "assistant", text, run_id: run["id"] }); + } + } catch { + // Keep the Python route's tolerant "skip malformed NDJSON" behavior. + } + } + } + return messages; +} + +function validateHeartbeatPayload( + ctx: ApiContext, + body: Row, + existing: Row | null = null, +): { heartbeat?: Heartbeat; response?: ResponseData } { + const name = body["name"] ?? existing?.["name"] ?? "Untitled heartbeat"; + const checkPrompt = body["check_prompt"] ?? existing?.["check_prompt"] ?? ""; + if (!String(checkPrompt).trim()) { + return { + response: [ + { error: "check_prompt cannot be empty", field: "check_prompt" }, + 400, + ], + }; + } + + const workingDir = asString( + body["working_dir"] ?? existing?.["working_dir"] ?? ".", + ); + const workingDirError = ensureWorkingDir( + workingDir, + `working_dir does not exist or is not a directory: ${workingDir}`, + ); + if (workingDirError) return { response: [workingDirError, 400] }; + + const scheduleType = asString( + body["schedule_type"] ?? existing?.["schedule_type"] ?? "interval", + ); + if ( + scheduleType !== HeartbeatScheduleType.CRON && + scheduleType !== HeartbeatScheduleType.INTERVAL + ) { + return { + response: [ + { + error: `invalid heartbeat schedule_type: ${scheduleType}`, + field: "schedule_type", + }, + 400, + ], + }; + } + + let cronExpr = body["cron_expr"] ?? existing?.["cron_expr"] ?? null; + let intervalSeconds = + body["interval_seconds"] ?? existing?.["interval_seconds"] ?? null; + if (scheduleType === HeartbeatScheduleType.CRON) { + if (!String(cronExpr ?? "").trim()) { + return { + response: [ + { + error: "cron_expr is required for cron heartbeat", + field: "cron_expr", + }, + 400, + ], + }; + } + if (!cronValid(String(cronExpr))) { + return { + response: [ + { error: `invalid cron expression: ${cronExpr}`, field: "cron_expr" }, + 400, + ], + }; + } + intervalSeconds = null; + } else { + const parsed = Number.parseInt(String(intervalSeconds ?? ""), 10); + if (!Number.isInteger(parsed) || parsed <= 0) { + return { + response: [ + { + error: "interval_seconds must be a positive integer", + field: "interval_seconds", + }, + 400, + ], + }; + } + intervalSeconds = parsed; + cronExpr = null; + } + + const cooldownSeconds = Number.parseInt( + String(body["cooldown_seconds"] ?? existing?.["cooldown_seconds"] ?? 0), + 10, + ); + if (!Number.isInteger(cooldownSeconds)) { + return { + response: [ + { + error: "cooldown_seconds must be an integer", + field: "cooldown_seconds", + }, + 400, + ], + }; + } + if (cooldownSeconds < 0) { + return { + response: [ + { + error: "cooldown_seconds cannot be negative", + field: "cooldown_seconds", + }, + 400, + ], + }; + } + + const heartbeat = makeHeartbeat({ + id: existing?.["id"] ?? null, + name: String(name), + enabled: asBool(body["enabled"] ?? existing?.["enabled"] ?? true), + working_dir: workingDir, + schedule_type: scheduleType, + cron_expr: cronExpr === null ? null : String(cronExpr), + interval_seconds: intervalSeconds === null ? null : Number(intervalSeconds), + check_prompt: String(checkPrompt), + action_prompt_template: String( + body["action_prompt_template"] ?? + existing?.["action_prompt_template"] ?? + "", + ), + default_agent: String( + body["default_agent"] ?? + existing?.["default_agent"] ?? + ctx.db.get_setting("default_agent", DEFAULT_AGENT), + ), + cooldown_seconds: cooldownSeconds, + next_run_at: existing?.["next_run_at"] ?? null, + last_tick_at: existing?.["last_tick_at"] ?? null, + last_decision: existing?.["last_decision"] ?? null, + last_error: existing?.["last_error"] ?? null, + last_triggered_at: existing?.["last_triggered_at"] ?? null, + last_dedupe_key: existing?.["last_dedupe_key"] ?? null, + }); + heartbeat.next_run_at = ctx.db._compute_heartbeat_next_run_at( + heartbeat, + new Date(), + ); + return { heartbeat }; +} + +type ResponseData = [unknown, number?]; + +function weixinStatus(ctx: ApiContext): Row { + const snapshot = ctx.weixin_channel?.get_status_snapshot?.() ?? {}; + const runtimeAccount = asString(snapshot["account_id"]); + const configuredAccount = ctx.db.get_setting("weixin_account_id", "") ?? ""; + return { + enabled: ctx.db.get_setting("weixin_enabled", "false") === "true", + configured: Boolean(snapshot["configured"]), + running: Boolean(ctx.weixin_channel?._running), + default_working_dir: ctx.db.get_setting("weixin_default_working_dir", "~"), + base_url: ctx.db.get_setting( + "weixin_base_url", + "https://ilinkai.weixin.qq.com", + ), + account_id: runtimeAccount || configuredAccount, + login_status: snapshot["login_status"] ?? "idle", + qr_code_url: snapshot["qr_code_url"] ?? "", + last_error: snapshot["last_error"] ?? "", + user_id: snapshot["user_id"] ?? "", + }; +} + +function channelsStatus(ctx: ApiContext): Row { + const tgToken = + ctx.db.get_setting("telegram_bot_token", "") || + process.env.TELEGRAM_BOT_TOKEN || + ""; + const slBot = + ctx.db.get_setting("slack_bot_token", "") || + process.env.SLACK_BOT_TOKEN || + ""; + const slApp = + ctx.db.get_setting("slack_app_token", "") || + process.env.SLACK_APP_TOKEN || + ""; + return { + telegram: { + enabled: ctx.db.get_setting("telegram_enabled", "false") === "true", + configured: Boolean(tgToken), + running: Boolean(ctx.telegram_channel?._running), + default_working_dir: ctx.db.get_setting( + "telegram_default_working_dir", + "~", + ), + default_chat_id: ctx.db.get_setting("telegram_default_chat_id", ""), + allowed_users: ctx.db.get_setting("telegram_allowed_users", ""), + }, + slack: { + enabled: ctx.db.get_setting("slack_enabled", "false") === "true", + configured: Boolean(slBot && slApp), + running: Boolean(ctx.slack_channel?._running), + default_working_dir: ctx.db.get_setting("slack_default_working_dir", "~"), + default_channel: ctx.db.get_setting("slack_default_channel", ""), + default_user: ctx.db.get_setting("slack_default_user", ""), + }, + weixin: weixinStatus(ctx), + feishu: { + configured: ctx.db.get_setting("feishu_enabled", "false") === "true", + running: Boolean(ctx.feishu_channel?._running), + }, + }; +} + +async function restartChannels(ctx: ApiContext, body: Row): Promise { + if (ctx.telegram_channel) { + ctx.telegram_channel.stop(); + ctx.telegram_channel = null; + } + const tgEnabled = + (body["telegram_enabled"] ?? + ctx.db.get_setting("telegram_enabled", "false")) === "true"; + if (tgEnabled) { + const token = + ctx.db.get_setting("telegram_bot_token", "") || + process.env.TELEGRAM_BOT_TOKEN || + ""; + const allowed = + ctx.db.get_setting("telegram_allowed_users", "") || + process.env.TELEGRAM_ALLOWED_USERS || + ""; + if (token) { + ctx.telegram_channel = create_telegram_channel( + ctx.db, + ctx.scheduler, + ctx.bus, + token, + allowed, + ); + ctx.telegram_channel?.start(); + } + } + + if (ctx.slack_channel) { + ctx.slack_channel.stop(); + ctx.slack_channel = null; + } + const slEnabled = + (body["slack_enabled"] ?? ctx.db.get_setting("slack_enabled", "false")) === + "true"; + if (slEnabled) { + const botToken = + ctx.db.get_setting("slack_bot_token", "") || + process.env.SLACK_BOT_TOKEN || + ""; + const appToken = + ctx.db.get_setting("slack_app_token", "") || + process.env.SLACK_APP_TOKEN || + ""; + if (botToken && appToken) { + ctx.slack_channel = new SlackChannel( + ctx.bus, + ctx.db, + ctx.scheduler, + botToken, + appToken, + ); + await ctx.slack_channel.start(); + } + } + + if (ctx.weixin_channel) { + ctx.weixin_channel.stop(); + ctx.weixin_channel = null; + } + const wxEnabled = + (body["weixin_enabled"] ?? + ctx.db.get_setting("weixin_enabled", "false")) === "true"; + if (wxEnabled) { + ctx.weixin_channel = new WeixinChannel(ctx.bus, ctx.db, ctx.scheduler); + ctx.weixin_channel.start(); + } + + if (ctx.feishu_channel) { + ctx.feishu_channel.stop(); + ctx.feishu_channel = null; + } + const fsEnabled = + (body["feishu_enabled"] ?? + ctx.db.get_setting("feishu_enabled", "false")) === "true"; + if (fsEnabled) { + ctx.feishu_channel = new FeishuChannel(ctx.bus, ctx.db, ctx.scheduler); + ctx.feishu_channel.start(); + } +} + +async function handleGet( + ctx: ApiContext, + req: Request, + url: URL, + origin: string, +): Promise { + const path = url.pathname; + + if (path === "/api/heartbeats") { + return jsonResponse(ctx.db.get_all_heartbeats(), 200, origin); + } + if ( + path.startsWith("/api/heartbeats/") && + path.includes("/ticks/") && + path.endsWith("/output") + ) { + const hid = idAt(path); + const tickId = idAt(path, 5); + if (hid === null || tickId === null) + return jsonResponse({ error: "not found" }, 404, origin); + const tick = ctx.db.get_heartbeat_tick(hid, tickId); + if (!tick) return jsonResponse({ error: "not found" }, 404, origin); + const output = + ctx.scheduler._live_heartbeat_output.get(tickId) ?? + tick["raw_output"] ?? + ""; + return jsonResponse( + { output, is_running: ctx.scheduler._live_heartbeat_output.has(tickId) }, + 200, + origin, + ); + } + if (path.startsWith("/api/heartbeats/") && path.endsWith("/ticks")) { + const hid = idAt(path); + if (hid === null) return jsonResponse({ error: "not found" }, 404, origin); + const limit = Number.parseInt(url.searchParams.get("limit") ?? "50", 10); + return jsonResponse( + { ticks: ctx.db.get_heartbeat_ticks(hid, limit) }, + 200, + origin, + ); + } + if (path.startsWith("/api/heartbeats/")) { + const hid = idAt(path); + if (hid === null) return jsonResponse({ error: "not found" }, 404, origin); + const heartbeat = ctx.db.get_heartbeat(hid); + return heartbeat + ? jsonResponse(heartbeat, 200, origin) + : jsonResponse({ error: "not found" }, 404, origin); + } + + if (path === "/api/tasks") { + return jsonResponse( + ctx.db.get_all_tasks().map((t) => attachDependencyMetadata(ctx.db, t)), + 200, + origin, + ); + } + if (path.startsWith("/api/tasks/") && path.endsWith("/runs")) { + const tid = idAt(path); + return tid === null + ? jsonResponse({ error: "not found" }, 404, origin) + : jsonResponse(ctx.db.get_task_runs(tid), 200, origin); + } + if (path.startsWith("/api/tasks/") && path.endsWith("/output")) { + const tid = idAt(path); + return tid === null + ? jsonResponse({ error: "not found" }, 404, origin) + : jsonResponse(taskOutputPayload(ctx, tid), 200, origin); + } + if (path.startsWith("/api/tasks/") && path.endsWith("/events")) { + const tid = idAt(path); + if (tid === null) return jsonResponse({ error: "not found" }, 404, origin); + const limit = Number.parseInt(url.searchParams.get("limit") ?? "1000", 10); + const offset = Number.parseInt(url.searchParams.get("offset") ?? "0", 10); + const events = ctx.db.get_output_events(tid, limit, offset); + return jsonResponse({ events, total: events.length }, 200, origin); + } + if (path.startsWith("/api/tasks/") && path.endsWith("/messages")) { + const tid = idAt(path); + return tid === null + ? jsonResponse({ error: "not found" }, 404, origin) + : jsonResponse(taskMessages(ctx, tid), 200, origin); + } + if (path.startsWith("/api/tasks/") && path.endsWith("/dependencies")) { + const tid = idAt(path); + return tid === null + ? jsonResponse({ error: "not found" }, 404, origin) + : jsonResponse(ctx.db.get_dependencies(tid), 200, origin); + } + if (path.startsWith("/api/tasks/") && path.endsWith("/dependents")) { + const tid = idAt(path); + return tid === null + ? jsonResponse({ error: "not found" }, 404, origin) + : jsonResponse(ctx.db.get_dependents(tid), 200, origin); + } + if (path.startsWith("/api/dag/")) { + const dagId = decodeURIComponent(path.slice("/api/dag/".length)); + const tasks = ctx.db + .get_dag_tasks(dagId) + .map((t) => attachDependencyMetadata(ctx.db, t)); + return jsonResponse(tasks, 200, origin); + } + if (path.startsWith("/api/tasks/")) { + const tid = idAt(path); + const task = tid === null ? null : ctx.db.get_task(tid); + return task + ? jsonResponse(attachDependencyMetadata(ctx.db, task), 200, origin) + : jsonResponse({ error: "not found" }, 404, origin); + } + + if (path === "/api/skill-patterns") { + return jsonResponse( + { + patterns: ctx.db.get_skill_patterns(), + sweep: ctx.scheduler.skill_sweep_status(), + }, + 200, + origin, + ); + } + if (path === "/api/skills") { + return jsonResponse({ skills: ctx.db.get_skills() }, 200, origin); + } + if (path.startsWith("/api/skills/") && path.endsWith("/content")) { + const sid = idAt(path); + const skill = sid === null ? null : ctx.db.get_skill(sid); + if (!skill) return jsonResponse({ error: "not found" }, 404, origin); + let content: string; + try { + content = fs.readFileSync(String(skill["path"]), "utf8"); + } catch (e) { + content = `(无法读取 SKILL.md:${e})`; + } + return jsonResponse({ content, path: skill["path"], skill }, 200, origin); + } + + if (path === "/api/csrf-token") + return jsonResponse({ csrf_token: CSRF_TOKEN }, 200, origin); + if (path === "/api/health") + return jsonResponse( + { status: "ok", tasks: ctx.db.get_all_tasks().length }, + 200, + origin, + ); + if (path === "/api/settings") { + return jsonResponse( + { + default_agent: ctx.db.get_setting("default_agent", DEFAULT_AGENT), + timeout: Number.parseInt( + ctx.db.get_setting("timeout", String(DEFAULT_TIMEOUT_SECONDS)) ?? + String(DEFAULT_TIMEOUT_SECONDS), + 10, + ), + skill_library_enabled: + ctx.db.get_setting("skill_library_enabled", "0") === "1", + skill_sweep_agent: ctx.db.get_setting( + "skill_sweep_agent", + DEFAULT_AGENT, + ), + skill_sweep_cron: ctx.db.get_setting("skill_sweep_cron", "0 3 * * *"), + }, + 200, + origin, + ); + } + if (path === "/api/feishu/settings") { + return jsonResponse( + { + feishu_app_id: ctx.db.get_setting("feishu_app_id", ""), + feishu_app_secret: ctx.db.get_setting("feishu_app_secret", ""), + feishu_default_chat_id: ctx.db.get_setting( + "feishu_default_chat_id", + "", + ), + feishu_default_working_dir: ctx.db.get_setting( + "feishu_default_working_dir", + "~", + ), + feishu_enabled: ctx.db.get_setting("feishu_enabled", "false"), + }, + 200, + origin, + ); + } + if (path === "/api/channels/status") { + return jsonResponse(channelsStatus(ctx), 200, origin); + } + + return jsonResponse({ error: "not found" }, 404, origin); +} + +async function handlePost( + ctx: ApiContext, + req: Request, + url: URL, + origin: string, +): Promise { + const bodyOrResponse = await readJsonBody(req, origin); + if (bodyOrResponse instanceof Response) return bodyOrResponse; + const body = bodyOrResponse; + const path = url.pathname; + + if (path === "/api/heartbeats") { + const validated = validateHeartbeatPayload(ctx, body); + if (validated.response) + return jsonResponse( + validated.response[0], + validated.response[1] ?? 200, + origin, + ); + const id = ctx.db.add_heartbeat(validated.heartbeat!); + return jsonResponse({ id, status: "created" }, 201, origin); + } + if (path.startsWith("/api/heartbeats/") && path.endsWith("/run-now")) { + const hid = idAt(path); + if (hid === null) return jsonResponse({ error: "not found" }, 404, origin); + try { + ctx.scheduler.trigger_heartbeat_now(hid); + } catch (e) { + const msg = e instanceof Error ? e.message : String(e); + return jsonResponse( + { error: msg }, + msg.includes("not found") ? 404 : 409, + origin, + ); + } + return jsonResponse({ status: "scheduled" }, 200, origin); + } + if (path.startsWith("/api/heartbeats/") && path.endsWith("/pause")) { + const hid = idAt(path); + if (hid === null) return jsonResponse({ error: "not found" }, 404, origin); + try { + ctx.scheduler.pause_heartbeat(hid); + } catch (e) { + return jsonResponse( + { error: e instanceof Error ? e.message : String(e) }, + 404, + origin, + ); + } + return jsonResponse({ status: "paused" }, 200, origin); + } + if (path.startsWith("/api/heartbeats/") && path.endsWith("/resume")) { + const hid = idAt(path); + if (hid === null) return jsonResponse({ error: "not found" }, 404, origin); + try { + ctx.scheduler.resume_heartbeat(hid); + } catch (e) { + return jsonResponse( + { error: e instanceof Error ? e.message : String(e) }, + 404, + origin, + ); + } + return jsonResponse({ status: "resumed" }, 200, origin); + } + + if (path === "/api/skills/sweep") { + const started = ctx.scheduler.trigger_skill_sweep( + body["agent"] ?? null, + Boolean(body["full"] ?? true), + ); + return started + ? jsonResponse({ status: "started" }, 200, origin) + : jsonResponse({ error: "sweep already running" }, 409, origin); + } + if (path.startsWith("/api/skill-patterns/") && path.endsWith("/draft")) { + const pid = idAt(path); + if ( + pid === null || + !ctx.scheduler.trigger_skill_draft(pid, body["agent"] ?? null) + ) { + return jsonResponse({ error: "pattern not found" }, 404, origin); + } + return jsonResponse({ status: "drafting" }, 200, origin); + } + if (path.startsWith("/api/skill-patterns/") && path.endsWith("/approve")) { + const pid = idAt(path); + if (pid === null) + return jsonResponse({ error: "pattern not found" }, 404, origin); + const draft = ctx.db.get_skill_draft(pid); + try { + const skill = ctx.scheduler.approve_skill( + pid, + String(body["name"] ?? draft?.["name"] ?? ""), + String(body["description"] ?? draft?.["description"] ?? ""), + String(body["body"] ?? draft?.["body"] ?? ""), + ); + return jsonResponse({ status: "approved", skill }, 200, origin); + } catch (e) { + const msg = e instanceof Error ? e.message : String(e); + return jsonResponse( + { error: msg }, + msg.includes("not found") ? 404 : 400, + origin, + ); + } + } + if (path.startsWith("/api/skill-patterns/") && path.endsWith("/dismiss")) { + const pid = idAt(path); + try { + if (pid === null) throw new Error("pattern not found"); + ctx.scheduler.dismiss_skill_pattern(pid); + } catch (e) { + return jsonResponse( + { error: e instanceof Error ? e.message : String(e) }, + 404, + origin, + ); + } + return jsonResponse({ status: "dismissed" }, 200, origin); + } + + if (path === "/api/tasks") { + const prompt = asString(body["prompt"]); + if (!prompt.trim()) + return jsonResponse( + { error: "prompt cannot be empty", field: "prompt" }, + 400, + origin, + ); + const workingDir = asString(body["working_dir"], "."); + const dirError = ensureWorkingDir( + workingDir, + `working_dir does not exist or is not a directory: ${workingDir}`, + ); + if (dirError) return jsonResponse(dirError, 400, origin); + const scheduleType = asString(body["schedule_type"], "immediate"); + const cronExpr = + body["cron_expr"] === undefined ? null : asString(body["cron_expr"]); + if (scheduleType === "cron") { + if (!cronExpr?.trim()) + return jsonResponse( + { + error: "cron_expr is required for cron schedule", + field: "cron_expr", + }, + 400, + origin, + ); + if (!cronValid(cronExpr)) + return jsonResponse( + { error: `invalid cron expression: ${cronExpr}`, field: "cron_expr" }, + 400, + origin, + ); + } + const deps = dependencyList( + body["depends_on"], + Boolean(body["inject_result"]), + ); + const task: Task = makeTask({ + title: asString(body["title"], "Untitled"), + prompt, + working_dir: workingDir, + schedule_type: scheduleType as ScheduleType, + cron_expr: cronExpr, + delay_seconds: body["delay_seconds"] ?? null, + next_run_at: body["next_run_at"] ?? null, + max_runs: body["max_runs"] ?? null, + tags: asString(body["tags"]), + agent: asString( + body["agent"] ?? ctx.db.get_setting("default_agent", DEFAULT_AGENT), + DEFAULT_AGENT, + ), + prompt_images: parseJsonList(body["prompt_images"]), + image_paths: parseJsonList(body["image_paths"]).map(String), + dag_id: body["dag_id"] ?? null, + }); + const id = ctx.scheduler.submit_task(task, deps); + return jsonResponse({ id, status: "created" }, 201, origin); + } + + if (path === "/api/settings") { + for (const [key, value] of Object.entries(body)) + ctx.db.set_setting(key, String(value)); + return jsonResponse({ status: "updated" }, 200, origin); + } + if (path === "/api/feishu/settings") { + for (const key of [ + "feishu_app_id", + "feishu_app_secret", + "feishu_default_chat_id", + "feishu_default_working_dir", + "feishu_enabled", + ]) { + if (key in body) ctx.db.set_setting(key, String(body[key])); + } + await restartChannels(ctx, body); + return jsonResponse({ status: "updated" }, 200, origin); + } + if (path === "/api/channels/settings") { + const allowed = new Set([ + "telegram_bot_token", + "telegram_allowed_users", + "telegram_default_working_dir", + "telegram_enabled", + "telegram_default_chat_id", + "slack_bot_token", + "slack_app_token", + "slack_default_working_dir", + "slack_default_channel", + "slack_default_user", + "slack_enabled", + "weixin_default_working_dir", + "weixin_base_url", + "weixin_account_id", + "weixin_enabled", + ]); + for (const [key, value] of Object.entries(body)) { + if (allowed.has(key)) ctx.db.set_setting(key, String(value)); + } + await restartChannels(ctx, body); + return jsonResponse({ status: "updated" }, 200, origin); + } + if (path === "/api/channels/weixin/action") { + const action = asString(body["action"]).trim().toLowerCase(); + if (!ctx.weixin_channel) + return jsonResponse({ error: "weixin channel not running" }, 400, origin); + if (action === "login" || action === "reconnect") { + ctx.weixin_channel.request_login(); + return jsonResponse({ status: "ok", action }, 200, origin); + } + if (action === "logout") { + ctx.weixin_channel.request_logout(); + return jsonResponse({ status: "ok", action }, 200, origin); + } + return jsonResponse({ error: "unsupported action" }, 400, origin); + } + + if (path === "/api/dag") { + const taskDefs = Array.isArray(body["tasks"]) + ? (body["tasks"] as Row[]) + : []; + if (!taskDefs.length) + return jsonResponse({ error: "tasks list is required" }, 400, origin); + const dagId = asString( + body["dag_id"], + `dag-${Math.trunc(Date.now() / 1000)}`, + ); + const refToId = new Map(); + const results: Row = {}; + for (const tdef of taskDefs) { + const ref = asString(tdef["ref"], String(refToId.size)); + const dependsOn: Array<{ task_id: number; inject_result: boolean }> = []; + for (const depRef of Array.isArray(tdef["depends_on_refs"]) + ? tdef["depends_on_refs"] + : []) { + const upstreamId = refToId.get(String(depRef)); + if (upstreamId === undefined) { + return jsonResponse( + { + error: `ref '${depRef}' not found - declare tasks in topological order`, + }, + 400, + origin, + ); + } + dependsOn.push({ + task_id: upstreamId, + inject_result: Boolean(tdef["inject_result"]), + }); + } + const task = makeTask({ + title: asString(tdef["title"], asString(tdef["prompt"]).slice(0, 60)), + prompt: asString(tdef["prompt"]), + working_dir: asString(tdef["working_dir"], "."), + schedule_type: asString( + tdef["schedule_type"], + "immediate", + ) as ScheduleType, + cron_expr: tdef["cron_expr"] ?? null, + delay_seconds: tdef["delay_seconds"] ?? null, + next_run_at: tdef["next_run_at"] ?? null, + max_runs: tdef["max_runs"] ?? null, + tags: asString(tdef["tags"]), + agent: asString( + tdef["agent"] ?? ctx.db.get_setting("default_agent", DEFAULT_AGENT), + DEFAULT_AGENT, + ), + prompt_images: parseJsonList(tdef["prompt_images"]), + dag_id: dagId, + }); + const taskId = ctx.scheduler.submit_task(task, dependsOn); + refToId.set(ref, taskId); + results[ref] = taskId; + } + return jsonResponse({ dag_id: dagId, task_ids: results }, 201, origin); + } + + if (path.startsWith("/api/tasks/") && path.endsWith("/dependencies")) { + const tid = idAt(path); + const depTaskId = Number(body["depends_on_task_id"]); + if (tid === null || !Number.isInteger(depTaskId)) + return jsonResponse( + { error: "depends_on_task_id required" }, + 400, + origin, + ); + const task = ctx.db.get_task(tid); + const upstream = ctx.db.get_task(depTaskId); + if (!task || !upstream) + return jsonResponse({ error: "task not found" }, 404, origin); + const shouldBlock = + upstream["status"] !== "completed" && + ["pending", "scheduled"].includes(task["status"]); + ctx.db.transaction(() => { + ctx.db.add_dependency(tid, depTaskId, Boolean(body["inject_result"])); + if (shouldBlock) ctx.db.update_task(tid, { status: "blocked" }); + }); + if (shouldBlock) ctx.scheduler._notify(tid); + return jsonResponse({ status: "added" }, 200, origin); + } + if (path.startsWith("/api/tasks/") && path.endsWith("/cancel")) { + const tid = idAt(path); + if (tid === null) return jsonResponse({ error: "not found" }, 404, origin); + ctx.scheduler.cancel_task(tid); + return jsonResponse({ status: "cancelled" }, 200, origin); + } + if (path.startsWith("/api/tasks/") && path.endsWith("/retry")) { + const tid = idAt(path); + if (tid === null) return jsonResponse({ error: "not found" }, 404, origin); + ctx.scheduler.retry_task(tid); + return jsonResponse({ status: "retrying" }, 200, origin); + } + if (path.startsWith("/api/tasks/") && path.endsWith("/respond")) { + const tid = idAt(path); + const task = tid === null ? null : ctx.db.get_task(tid); + if (!task || tid === null) + return jsonResponse({ error: "not found" }, 404, origin); + const answer = asString(body["answer"]); + ctx.db.update_task(tid, { + status: "pending", + prompt: answer, + answer, + question: null, + error: null, + }); + return jsonResponse({ status: "responding" }, 200, origin); + } + if (path.startsWith("/api/tasks/") && path.endsWith("/resume")) { + const tid = idAt(path); + const task = tid === null ? null : ctx.db.get_task(tid); + const message = asString(body["message"]).trim(); + if (!task || tid === null) + return jsonResponse({ error: "not found" }, 404, origin); + if (!message) + return jsonResponse({ error: "message required" }, 400, origin); + if (!task["session_id"]) + return jsonResponse( + { error: "no session_id - cannot resume" }, + 400, + origin, + ); + ctx.db.update_task(tid, { + status: "pending", + prompt: message, + result: null, + error: null, + question: null, + }); + return jsonResponse({ status: "resuming" }, 200, origin); + } + + return jsonResponse({ error: "not found" }, 404, origin); +} + +async function handlePut( + ctx: ApiContext, + req: Request, + url: URL, + origin: string, +): Promise { + const bodyOrResponse = await readJsonBody(req, origin); + if (bodyOrResponse instanceof Response) return bodyOrResponse; + const body = bodyOrResponse; + const path = url.pathname; + + if (path === "/api/settings") { + for (const [key, value] of Object.entries(body)) + ctx.db.set_setting(key, String(value)); + return jsonResponse({ status: "updated" }, 200, origin); + } + if (path.startsWith("/api/skills/")) { + const sid = idAt(path); + if (sid === null) + return jsonResponse({ error: "invalid skill id" }, 400, origin); + try { + const skill = ctx.scheduler.toggle_skill( + sid, + Boolean(body["enabled"] ?? true), + ); + return jsonResponse({ status: "updated", skill }, 200, origin); + } catch (e) { + return jsonResponse( + { error: e instanceof Error ? e.message : String(e) }, + 404, + origin, + ); + } + } + if (path.startsWith("/api/heartbeats/") && path.split("/").length === 4) { + const hid = idAt(path); + if (hid === null) + return jsonResponse({ error: "invalid heartbeat id" }, 400, origin); + const existing = ctx.db.get_heartbeat(hid); + if (!existing) return jsonResponse({ error: "not found" }, 404, origin); + const validated = validateHeartbeatPayload(ctx, body, existing); + if (validated.response) + return jsonResponse( + validated.response[0], + validated.response[1] ?? 200, + origin, + ); + const hb = validated.heartbeat!; + ctx.db.update_heartbeat(hid, { + name: hb.name, + enabled: hb.enabled ? 1 : 0, + working_dir: hb.working_dir, + schedule_type: hb.schedule_type, + cron_expr: hb.cron_expr, + interval_seconds: hb.interval_seconds, + check_prompt: hb.check_prompt, + action_prompt_template: hb.action_prompt_template, + default_agent: hb.default_agent, + cooldown_seconds: hb.cooldown_seconds, + next_run_at: hb.next_run_at, + }); + return jsonResponse(ctx.db.get_heartbeat(hid), 200, origin); + } + if (path.startsWith("/api/tasks/") && path.split("/").length === 4) { + const tid = idAt(path); + if (tid === null) + return jsonResponse({ error: "invalid task id" }, 400, origin); + const task = ctx.db.get_task(tid); + if (!task) return jsonResponse({ error: "not found" }, 404, origin); + if (!["pending", "scheduled", "blocked"].includes(task["status"])) { + return jsonResponse( + { + error: `Cannot edit task with status '${task["status"]}'. Only pending, scheduled, or blocked tasks can be edited.`, + }, + 409, + origin, + ); + } + const prompt = asString(body["prompt"] ?? task["prompt"]); + if (!prompt.trim()) + return jsonResponse( + { error: "prompt cannot be empty", field: "prompt" }, + 400, + origin, + ); + const workingDir = asString(body["working_dir"] ?? task["working_dir"]); + const dirError = ensureWorkingDir( + workingDir, + `working_dir does not exist: ${workingDir}`, + ); + if (dirError) return jsonResponse(dirError, 400, origin); + const scheduleType = asString( + body["schedule_type"] ?? task["schedule_type"], + ); + const cronExpr = asString(body["cron_expr"] ?? task["cron_expr"]); + if (scheduleType === "cron") { + if (!cronExpr.trim()) + return jsonResponse( + { error: "cron_expr required for cron schedule", field: "cron_expr" }, + 400, + origin, + ); + if (!cronValid(cronExpr)) + return jsonResponse( + { error: `invalid cron expression: ${cronExpr}`, field: "cron_expr" }, + 400, + origin, + ); + } + + const updates: Row = {}; + for (const field of [ + "title", + "prompt", + "working_dir", + "schedule_type", + "cron_expr", + "delay_seconds", + "max_runs", + "tags", + "agent", + "dag_id", + ]) { + if (field in body) updates[field] = body[field]; + } + if ("prompt_images" in body) + updates["prompt_images"] = JSON.stringify( + parseJsonList(body["prompt_images"]), + ); + if ("image_paths" in body) + updates["image_paths"] = JSON.stringify( + parseJsonList(body["image_paths"]), + ); + + const newScheduleType = asString( + updates["schedule_type"] ?? task["schedule_type"], + ); + if (newScheduleType === "immediate") { + Object.assign(updates, { + status: "pending", + next_run_at: null, + cron_expr: null, + delay_seconds: null, + }); + } else if (newScheduleType === "delayed") { + Object.assign(updates, { + status: "pending", + next_run_at: null, + cron_expr: null, + }); + } else if (newScheduleType === "scheduled_at") { + const nextRunAt = body["next_run_at"] ?? task["next_run_at"]; + if (!nextRunAt) + return jsonResponse( + { + error: "next_run_at required for scheduled_at", + field: "next_run_at", + }, + 400, + origin, + ); + Object.assign(updates, { + next_run_at: nextRunAt, + status: "scheduled", + cron_expr: null, + delay_seconds: null, + }); + } else if (newScheduleType === "cron") { + const newCron = asString(updates["cron_expr"] ?? task["cron_expr"]); + Object.assign(updates, { + next_run_at: cronNextIso(newCron), + status: "scheduled", + delay_seconds: null, + }); + } + + if ("depends_on" in body) { + ctx.db.clear_dependencies(tid); + const deps = dependencyList(body["depends_on"]); + if (deps.length) { + ctx.db.add_dependencies_batch(tid, deps); + if ( + deps.some( + (dep) => ctx.db.get_task(dep.task_id)?.["status"] !== "completed", + ) + ) { + updates["status"] = "blocked"; + } + } + } + if (Object.keys(updates).length) ctx.db.update_task(tid, updates); + const updated = ctx.db.get_task(tid); + return jsonResponse( + updated ? attachDependencyMetadata(ctx.db, updated) : null, + 200, + origin, + ); + } + return jsonResponse({ error: "not found" }, 404, origin); +} + +async function handleDelete( + ctx: ApiContext, + url: URL, + origin: string, +): Promise { + const path = url.pathname; + const parts = path.split("/"); + if ( + parts.length === 6 && + parts[2] === "tasks" && + parts[4] === "dependencies" + ) { + const tid = Number(parts[3]); + const depId = Number(parts[5]); + ctx.db.remove_dependency(tid, depId); + return jsonResponse({ status: "removed" }, 200, origin); + } + if (path.startsWith("/api/heartbeats/")) { + const hid = idAt(path); + if (hid !== null) ctx.db.delete_heartbeat(hid); + return jsonResponse({ status: "deleted" }, 200, origin); + } + if (path.startsWith("/api/skills/")) { + const sid = idAt(path); + if (sid === null) + return jsonResponse({ error: "invalid skill id" }, 400, origin); + try { + ctx.scheduler.remove_skill(sid); + return jsonResponse({ status: "deleted" }, 200, origin); + } catch (e) { + return jsonResponse( + { error: e instanceof Error ? e.message : String(e) }, + 404, + origin, + ); + } + } + if (path.startsWith("/api/tasks/")) { + const tid = idAt(path); + if (tid !== null) ctx.db.delete_task(tid); + return jsonResponse({ status: "deleted" }, 200, origin); + } + return jsonResponse({ error: "not found" }, 404, origin); +} + +export async function handleApiRequest( + ctx: ApiContext, + req: Request, +): Promise { + const origin = req.headers.get("Origin") ?? ""; + if (origin && !isAllowedOrigin(origin)) { + return new Response(null, { status: 403 }); + } + if (req.method === "OPTIONS") { + return new Response(null, { status: 200, headers: corsHeaders(origin) }); + } + const url = new URL(req.url); + if (!url.pathname.startsWith("/api/")) { + return jsonResponse({ error: "not found" }, 404, origin); + } + if (["POST", "PUT", "DELETE"].includes(req.method) && !checkCsrf(req)) { + void req.body?.cancel(); + return jsonResponse( + { error: "CSRF token missing or invalid" }, + 403, + origin, + ); + } + + try { + if (req.method === "GET") return await handleGet(ctx, req, url, origin); + if (req.method === "POST") return await handlePost(ctx, req, url, origin); + if (req.method === "PUT") return await handlePut(ctx, req, url, origin); + if (req.method === "DELETE") return await handleDelete(ctx, url, origin); + return jsonResponse({ error: "method not allowed" }, 405, origin); + } catch (e) { + return jsonResponse( + { error: e instanceof Error ? e.message : String(e) }, + 500, + origin, + ); + } +} diff --git a/backend/src/channels/feishu.ts b/backend/src/channels/feishu.ts new file mode 100644 index 0000000..09dc741 --- /dev/null +++ b/backend/src/channels/feishu.ts @@ -0,0 +1,1878 @@ +/** + * Feishu/Lark channel for AgentForge. + * + * The implementation keeps the Python channel's public method names and JSON + * shapes, but uses Bun/TypeScript primitives and the official + * @larksuiteoapi/node-sdk at runtime. SDK calls are deliberately structural so + * tests can inject small fake clients without depending on SDK internals. + */ + +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; + +import { + Channel, + MessageBus, + OutboundMessageType, + type OutboundMessage, + type TaskDBLike, +} from "../bus.ts"; +import { + makeTask, + ScheduleType, + type PromptImage, + type Task, +} from "../types.ts"; +import { + handle_agent_command, + resolve_agent, + type SettingsDB, +} from "./agent_utils.ts"; +import { handle_dir_command, resolve_working_dir } from "./dir_utils.ts"; + +type Row = Record; + +export const HELP_TEXT = `**AgentForge Bot** 👋 +发送任意消息即可创建任务。回复任务完成/失败通知即可继续对话。 + +**命令列表:** +• \`/status \` — 查看任务详情 +• \`/cancel \` — 取消任务 +• \`/resume \` — 继续执行任务 +• \`/dir \` — 设置默认工作目录 +  例如:\`/dir ~/workspace/myproject\` +• \`/agent \` — 切换 coding agent(\`claude\` / \`codex\`) +• \`/ccu\` — 查看 Claude Code 当前用量(ccu-blocks) +• \`/help\` — 显示此帮助 + +**小技巧:** +• 消息中直接提到路径,Bot 会自动识别并使用。 + 例如:_在 ~/myapp 里帮我修复登录 bug_ +• 回复任意结果通知即可继续对话。 +`; + +export const FEISHU_CARD_MARKDOWN_CHUNK = 7000; +export const FEISHU_FALLBACK_MARKDOWN_LIMIT = 8000; +export const FEISHU_CARD_MAX_ELEMENTS = 200; +export const FEISHU_PANEL_MAX_LINE_ELEMENTS = 80; +export const FEISHU_PANEL_PLAIN_TEXT_CHUNK = 1800; +export const FEISHU_THINKING_PREFIX = "[thinking] "; +export const FEISHU_UPLOADABLE_IMAGE_SUFFIXES = new Set([ + ".png", + ".jpg", + ".jpeg", + ".gif", + ".webp", +]); +export const FEISHU_STREAM_EVENT_TYPES = new Set([ + "assistant", + "tool_call", + "tool_result", + "command_execution", + "file_change", + "web_search", + "error", +]); + +const FEISHU_MARKDOWN_IMAGE_RE = /!\[[^\]]*]\(([^)\n]+)\)/g; + +export let FEISHU_AVAILABLE = true; + +export function _set_feishu_available(value: boolean): void { + FEISHU_AVAILABLE = value; +} + +export const _hooks = { + import_lark: async (): Promise => + await import("@larksuiteoapi/node-sdk"), +}; + +export interface FeishuTaskDB extends TaskDBLike, SettingsDB { + update_task(task_id: number, updates: Record): void; + get_task_runs(task_id: number, limit?: number): Row[]; + get_run_output_events(run_id: number, limit?: number): Row[]; + get_task_by_feishu_root_msg(root_msg_id: string): Row | null; +} + +export interface FeishuScheduler { + submit_task(task: Task): number; + add_output_listener(cb: OutputListener): void; + remove_output_listener(cb: OutputListener): void; +} + +export type OutputListener = ( + task_id: number, + run_id: number, + event_type: string, + content: string, +) => void; + +function isPlainObject(value: unknown): value is Row { + return typeof value === "object" && value !== null && !Array.isArray(value); +} + +function stringifyCard(card: Row): string { + return JSON.stringify(card); +} + +function responseSuccess(response: any): boolean { + if (!response) return false; + if (typeof response.success === "function") + return Boolean(response.success()); + if (typeof response.code === "number") return response.code === 0; + return Boolean(response.success); +} + +function responseMessageId(response: any): string | null { + return ( + response?.data?.message_id ?? + response?.data?.messageId ?? + response?.message_id ?? + response?.messageId ?? + null + ); +} + +function responseImageKey(response: any): string | null { + return ( + response?.data?.image_key ?? + response?.data?.imageKey ?? + response?.image_key ?? + null + ); +} + +function callMaybeAsync(value: T | Promise): Promise { + return Promise.resolve(value); +} + +function errStr(e: unknown): string { + return e instanceof Error ? e.message : String(e); +} + +function getSenderOpenId(sender: Row): string { + const senderId = sender["sender_id"]; + if (typeof senderId === "string") return senderId; + return senderId?.["open_id"] ?? senderId?.["openId"] ?? "unknown"; +} + +function localImageMediaType(imagePath: string): string { + const ext = path.extname(imagePath).toLowerCase(); + if (ext === ".png") return "image/png"; + if (ext === ".gif") return "image/gif"; + if (ext === ".webp") return "image/webp"; + return "image/jpeg"; +} + +function expandUser(p: string): string { + if (p === "~") return os.homedir(); + if (p.startsWith("~/")) return path.join(os.homedir(), p.slice(2)); + return p; +} + +function fileUrlPath(target: string): string { + try { + return new URL(target).pathname; + } catch { + const rest = target.slice("file://".length); + const slash = rest.indexOf("/"); + return slash >= 0 ? rest.slice(slash) : ""; + } +} + +function decodePath(target: string): string { + try { + return decodeURIComponent(target); + } catch { + return target; + } +} + +function extractEvent(data: any): Row { + return data?.event ?? data?.data?.event ?? data ?? {}; +} + +function extractMessage(data: any): Row { + return extractEvent(data)["message"] ?? {}; +} + +function extractSender(data: any): Row { + return extractEvent(data)["sender"] ?? {}; +} + +function asString(value: unknown, fallback = ""): string { + if (value === null || value === undefined) return fallback; + return String(value); +} + +export class _FeishuStreamWriter { + static readonly MIN_INTERVAL = 0.25; + + task_id: number; + msg_id: string; + _channel: FeishuChannel; + _task_title: string; + _run_id: number | null = null; + _parts: string[] = []; + _last_patch = 0; + _timer: ReturnType | null = null; + _stopped = false; + _patch_in_flight = false; + _dirty = false; + + constructor( + task_id: number, + msg_id: string, + channel: FeishuChannel, + task_title: string, + ) { + this.task_id = task_id; + this.msg_id = msg_id; + this._channel = channel; + this._task_title = task_title; + } + + on_event( + task_id: number, + run_id: number, + event_type: string, + content: string, + ): void { + if (this._stopped || task_id !== this.task_id) return; + if (!FEISHU_STREAM_EVENT_TYPES.has(event_type) || content === "") return; + let display_content = this._display_content(event_type, content); + if (!display_content) return; + if (this._run_id === null) { + this._run_id = run_id; + } else if (this._run_id !== run_id) { + this._run_id = run_id; + this._parts = []; + } + if ( + event_type !== "assistant" && + this._parts.length && + !this._parts.at(-1)!.endsWith("\n") + ) { + display_content = "\n" + display_content; + } + this._parts.push(display_content); + this._schedule(); + } + + _display_content(event_type: string, content: string): string { + if (event_type !== "assistant") + return this._format_trace_event(event_type, content); + return content.startsWith(FEISHU_THINKING_PREFIX) + ? content.slice(FEISHU_THINKING_PREFIX.length) + : content; + } + + _load_trace_payload(content: string): Row { + try { + const payload = JSON.parse(content); + return isPlainObject(payload) ? payload : { content: payload }; + } catch { + return { content }; + } + } + + _format_trace_value(value: unknown): string { + return this._compact_trace_summary(value); + } + + _compact_trace_summary(value: unknown, limit = 140): string { + if ( + value === null || + value === undefined || + value === "" || + (Array.isArray(value) && value.length === 0) || + (isPlainObject(value) && Object.keys(value).length === 0) + ) { + return ""; + } + if (isPlainObject(value)) { + for (const key of [ + "command", + "query", + "path", + "file", + "message", + "content", + "text", + ]) { + if (value[key]) return this._compact_trace_summary(value[key], limit); + } + const safe_parts: string[] = []; + for (const [key, item] of Object.entries(value)) { + if (item === null || item === undefined || item === "") continue; + if ( + ["token", "secret", "password", "key"].some((s) => + key.toLowerCase().includes(s), + ) + ) { + continue; + } + safe_parts.push(`${key}=${this._compact_trace_summary(item, 48)}`); + if (safe_parts.length >= 2) break; + } + return this._truncate_trace_text(safe_parts.join(", "), limit); + } + if (Array.isArray(value)) { + const first = this._compact_trace_summary( + value[0], + Math.max(24, limit - 20), + ); + const suffix = value.length > 1 ? ` 等 ${value.length} 项` : ""; + return this._truncate_trace_text(`${first}${suffix}`, limit); + } + return this._truncate_trace_text(String(value), limit); + } + + _truncate_trace_text(value: string, limit = 140): string { + const lines = String(value) + .replace(/\r\n/g, "\n") + .replace(/\r/g, "\n") + .split("\n") + .map((line) => line.trim()) + .filter(Boolean); + const normalized = (lines[0] ?? "").split(/\s+/).join(" "); + return normalized.length <= limit + ? normalized + : normalized.slice(0, limit - 1).trimEnd() + "…"; + } + + _trace_line(icon: string, label: string, ...parts: unknown[]): string { + const compact_parts = parts.map((part) => + typeof part === "string" + ? this._truncate_trace_text(part) + : this._compact_trace_summary(part), + ); + const suffix = compact_parts.filter(Boolean).join(" · "); + return `${icon} ${label}${suffix ? " " + suffix : ""}`; + } + + _format_trace_event(event_type: string, content: string): string { + const payload = this._load_trace_payload(content); + let line = ""; + if (event_type === "tool_call") { + let name = payload["name"] || payload["tool"] || "unknown"; + if (payload["server"]) name = `${payload["server"]}.${name}`; + line = this._trace_line( + "▣", + "调用工具", + name, + payload["input"] || payload["arguments"], + payload["result"], + payload["status"], + payload["error"] + ? `错误 ${this._format_trace_value(payload["error"])}` + : "", + ); + } else if (event_type === "tool_result") { + line = this._trace_line( + "↵", + payload["is_error"] ? "工具错误" : "工具返回", + payload["tool_use_id"], + payload["content"], + ); + } else if (event_type === "command_execution") { + line = this._trace_line( + "$", + "执行命令", + payload["command"] || payload["content"] || "", + payload["output"], + payload["exit_code"] !== undefined && payload["exit_code"] !== null + ? `退出码 ${payload["exit_code"]}` + : "", + payload["status"], + ); + } else if (event_type === "file_change") { + let summary = ""; + const changes = payload["changes"]; + if (Array.isArray(changes)) { + const summaries = changes + .filter(isPlainObject) + .map((change) => + `${change["kind"] || change["type"] || "changed"}: ${change["path"] || change["file"] || ""}`.trim(), + ); + summary = summaries.slice(0, 3).join(";"); + if (summaries.length > 3) summary += ` 等 ${summaries.length} 项`; + } else if (changes) { + summary = this._format_trace_value(changes); + } + line = this._trace_line("◇", "文件变更", summary, payload["status"]); + } else if (event_type === "web_search") { + line = this._trace_line( + "⌕", + "网页搜索", + payload["query"] || payload["content"] || "", + payload["status"], + ); + } else if (event_type === "error") { + line = this._trace_line( + "!", + "错误", + payload["message"] || payload["content"] || content, + ); + } else { + line = this._trace_line("•", `[${event_type}]`, content); + } + return line ? `${line}\n` : ""; + } + + _schedule(): void { + if (this._stopped) return; + this._dirty = true; + this._schedule_dirty_locked(); + } + + _schedule_dirty_locked(): void { + if (this._stopped || !this._dirty || this._patch_in_flight || this._timer) + return; + const delay = Math.max( + 0, + _FeishuStreamWriter.MIN_INTERVAL - (Date.now() / 1000 - this._last_patch), + ); + if (delay <= 0) { + this._start_patch_locked(); + return; + } + this._timer = setTimeout(() => this._timer_fired(), delay * 1000); + } + + _start_patch_locked(): void { + this._patch_in_flight = true; + this._dirty = false; + void this._do_patch(); + } + + _timer_fired(): void { + this._timer = null; + this._schedule_dirty_locked(); + } + + async _do_patch(): Promise { + const text = this._parts.join(""); + const card = this._channel._build_streaming_card( + this.task_id, + this._task_title, + text, + ); + try { + await this._channel._patch_message(this.msg_id, card); + } finally { + this._last_patch = Date.now() / 1000; + this._patch_in_flight = false; + this._schedule_dirty_locked(); + } + } + + snapshot_text(): string { + return this._parts.join(""); + } + + stop(): void { + this._stopped = true; + if (this._timer) { + clearTimeout(this._timer); + this._timer = null; + } + } +} + +export class FeishuChannel extends Channel { + declare db: FeishuTaskDB; + scheduler: FeishuScheduler; + _client: any = null; + _ws_client: any = null; + _ws_promise: Promise | null = null; + _event_dispatcher: any = null; + _lark: any = null; + + _task_origin: Map = new Map(); + _notification_map: Map = new Map(); + _root_msg_map: Map = new Map(); + _writers: Map = new Map(); + _writer_listeners: Map = new Map(); + _streaming_msg: Map = new Map(); + + constructor(bus: MessageBus, db: FeishuTaskDB, scheduler: FeishuScheduler) { + super("feishu", bus, db); + this.scheduler = scheduler; + bus.subscribe_outbound(this._on_outbound); + } + + start(): void { + void this._start().catch((e) => { + console.log(`[Feishu] ERROR during initialization: ${e}`); + }); + } + + async _start(): Promise { + if (!FEISHU_AVAILABLE) { + console.log( + "[Feishu] @larksuiteoapi/node-sdk not installed. Run: bun add @larksuiteoapi/node-sdk", + ); + return; + } + const appId = this.db.get_setting("feishu_app_id") || ""; + const appSecret = this.db.get_setting("feishu_app_secret") || ""; + if (!appId || !appSecret) { + console.log( + "[Feishu] Not configured - set feishu_app_id / feishu_app_secret in settings", + ); + return; + } + try { + const lark = await _hooks.import_lark(); + this._lark = lark; + this._client = new lark.Client({ + appId, + appSecret, + appType: lark.AppType?.SelfBuild, + domain: lark.Domain?.Feishu, + }); + const wsCtor = lark.WSClient ?? lark.ws?.Client; + if (wsCtor) { + const eventDispatcher = this._build_event_dispatcher(lark); + this._ws_client = new wsCtor({ + appId, + appSecret, + }); + this._event_dispatcher = eventDispatcher; + } + this._running = true; + if (this._ws_client) { + this._ws_promise = this._run_ws(this._event_dispatcher); + } + console.log("[Feishu] Initialization complete"); + } catch (e) { + console.log(`[Feishu] ERROR during initialization: ${e}`); + this._client = null; + this._ws_client = null; + this._event_dispatcher = null; + } + } + + _build_event_dispatcher(lark: any): any { + const handlers: Row = { + "im.message.receive_v1": (data: any) => this._on_message_sync(data), + "im.chat.member.bot.added_v1": (data: any) => this._on_bot_added(data), + "im.message.reaction.created_v1": (data: any) => this._on_reaction(data), + "im.message.reaction.deleted_v1": (data: any) => this._on_reaction(data), + "im.message.message_read_v1": () => undefined, + "im.message.recalled_v1": () => undefined, + }; + if (typeof lark.EventDispatcher === "function") { + return new lark.EventDispatcher({}).register(handlers); + } + return { register: handlers }; + } + + stop(): void { + console.log("[Feishu] Stopping WebSocket bot..."); + this._running = false; + this.bus.unsubscribe_outbound(this._on_outbound); + for (const [task_id, writer] of this._writers) { + const listener = this._writer_listeners.get(task_id); + if (listener) this.scheduler.remove_output_listener(listener); + writer.stop(); + } + this._writers.clear(); + this._writer_listeners.clear(); + this._streaming_msg.clear(); + try { + if (typeof this._ws_client?.stop === "function") this._ws_client.stop(); + else if (typeof this._ws_client?.disconnect === "function") + void this._ws_client.disconnect(); + else if (typeof this._ws_client?.close === "function") + this._ws_client.close({ force: true }); + } catch (e) { + console.log(`[Feishu] Error stopping ws_client: ${e}`); + } + this._client = null; + this._ws_client = null; + this._ws_promise = null; + this._event_dispatcher = null; + } + + async _run_ws(eventDispatcher: any = null): Promise { + try { + if (!this._running || !this._ws_client) return; + if (typeof this._ws_client.start === "function") { + await this._ws_client.start({ eventDispatcher }); + return; + } else if (typeof this._ws_client.connect === "function") { + await this._ws_client.connect(); + } + } catch (e) { + if (this._running) console.log(`[Feishu] WebSocket error: ${e}`); + this._running = false; + } + } + + send(msg: OutboundMessage): void { + void this._send(msg).catch((e) => console.log(`[Feishu] send error: ${e}`)); + } + + async _send(msg: OutboundMessage): Promise { + if ( + msg.type !== OutboundMessageType.TASK_COMPLETED && + msg.type !== OutboundMessageType.TASK_FAILED + ) + return; + const task_id = msg.task_id; + if (!this._client) { + console.log( + `[Feishu] Client not initialized, skipping notification for task ${task_id}`, + ); + return; + } + const task = this.db.get_task(task_id) as Row | null; + if (!task) { + console.log(`[Feishu] Task ${task_id} not found in database`); + return; + } + + const is_completed = msg.type === OutboundMessageType.TASK_COMPLETED; + let content: string; + if (is_completed) { + const result_text = asString( + msg.payload["result"] ?? task["result"], + ).trim(); + content = result_text || "Done."; + } else { + content = asString( + msg.payload["error"] ?? task["error"] ?? "Unknown error", + ) + .trim() + .slice(0, 800); + } + + const origin = this._task_origin.get(task_id); + const streaming_msg_id = this._streaming_msg.get(task_id) ?? null; + this._streaming_msg.delete(task_id); + const streaming_history = this._stop_streaming(task_id); + + let image_keys: string[] = []; + if (is_completed) { + const image_paths = this._collect_generated_image_paths( + task_id, + content, + task, + ); + const uploaded_images = await this._upload_image_entries(image_paths); + image_keys = uploaded_images.map(([, image_key]) => image_key); + if (image_keys.length) { + content = this._hide_generated_image_paths( + content, + image_keys.length, + uploaded_images.map(([image_path]) => image_path), + ); + } + } + + const card = this._build_notification_card({ + task_id, + task, + is_completed, + body_text: content, + streaming_history, + image_keys, + }); + + let sent_id: string | null = null; + if (origin) { + const [, root_msg_id, reaction_msg_id] = origin; + this._add_reaction(reaction_msg_id, is_completed ? "DONE" : "Cry"); + if ( + streaming_msg_id && + (await this._patch_message(streaming_msg_id, card)) + ) { + sent_id = streaming_msg_id; + } + if (!sent_id) { + sent_id = await this._reply_message(root_msg_id, content, card); + } + } + + if (!sent_id) { + const chat_id = this.db.get_setting("feishu_default_chat_id"); + if (chat_id) { + sent_id = await this._send_message( + chat_id, + content, + card, + this._truncate_text(content, FEISHU_FALLBACK_MARKDOWN_LIMIT), + ); + } + } + + if (sent_id) { + this._notification_map.set(sent_id, task_id); + console.log( + `[Feishu] Notification message_id=${sent_id} mapped to task #${task_id}`, + ); + } else { + console.log(`[Feishu] Failed to send notification for task ${task_id}`); + } + this._task_origin.delete(task_id); + } + + _on_outbound = (msg: OutboundMessage): void => { + this.send(msg); + }; + + _generated_image_paths_for_task(task_id: number): string[] { + let runs: Row[]; + try { + runs = this.db.get_task_runs(task_id, 1); + } catch (e) { + console.log(`[Feishu] Failed to load runs for generated images: ${e}`); + return []; + } + if (!Array.isArray(runs) || !runs.length) return []; + const run_id = runs[0]?.["id"]; + if (!run_id) return []; + let events: Row[]; + try { + events = this.db.get_run_output_events(run_id, 1000); + } catch (e) { + console.log( + `[Feishu] Failed to load output events for generated images: ${e}`, + ); + return []; + } + const paths: string[] = []; + const seen = new Set(); + for (const event of events) { + if (!isPlainObject(event) || event["event_type"] !== "generated_image") + continue; + try { + const payload = JSON.parse(event["content"] || "{}"); + const imagePath = payload?.path; + if ( + imagePath && + !seen.has(imagePath) && + fs.existsSync(imagePath) && + fs.statSync(imagePath).isFile() + ) { + seen.add(imagePath); + paths.push(imagePath); + } + } catch { + // Ignore malformed generated-image event payloads. + } + } + return paths; + } + + _collect_generated_image_paths( + task_id: number, + content: string, + task: Row | null = null, + ): string[] { + const paths = this._generated_image_paths_for_task(task_id); + paths.push( + ...this._generated_image_paths_from_markdown( + content, + task?.["working_dir"], + ), + ); + return this._dedupe_image_paths(paths); + } + + _generated_image_paths_from_markdown( + content: string, + working_dir: string | null = null, + ): string[] { + const paths: string[] = []; + FEISHU_MARKDOWN_IMAGE_RE.lastIndex = 0; + for (const match of content.matchAll(FEISHU_MARKDOWN_IMAGE_RE)) { + const imagePath = this._local_image_path_from_reference( + match[1] ?? "", + working_dir, + ); + if (imagePath) paths.push(imagePath); + } + return paths; + } + + _local_image_path_from_reference( + reference: string, + working_dir: string | null = null, + ): string | null { + let target = this._markdown_image_reference_target(reference); + if ( + !target || + target.startsWith("http://") || + target.startsWith("https://") || + target.startsWith("data:") + ) { + return null; + } + if (target.startsWith("file://")) target = fileUrlPath(target); + else if (target.startsWith("sandbox:")) + target = target.slice("sandbox:".length); + target = decodePath(target).trim(); + if (!target) return null; + let imagePath = expandUser(target); + if (!path.isAbsolute(imagePath) && working_dir) + imagePath = path.join(expandUser(working_dir), imagePath); + if ( + !FEISHU_UPLOADABLE_IMAGE_SUFFIXES.has( + path.extname(imagePath).toLowerCase(), + ) + ) + return null; + try { + if (!fs.statSync(imagePath).isFile()) return null; + return fs.realpathSync(imagePath); + } catch { + return null; + } + } + + _markdown_image_reference_target(reference: string): string { + const raw = (reference || "").trim(); + if (!raw) return ""; + if (raw.startsWith("<")) { + const end = raw.indexOf(">"); + if (end >= 0) return raw.slice(1, end).trim(); + } + if (raw[0] === "'" || raw[0] === '"') { + const end = raw.indexOf(raw[0], 1); + if (end > 0) return raw.slice(1, end).trim(); + } + const titled = raw.match(/(.+?)\s+['"][^'"]*['"]\s*$/); + return (titled ? titled[1]! : raw).trim(); + } + + _dedupe_image_paths(image_paths: string[]): string[] { + const deduped: string[] = []; + const seen = new Set(); + for (const imagePath of image_paths) { + const canonical = this._canonical_image_path(imagePath); + if (!canonical || seen.has(canonical)) continue; + seen.add(canonical); + deduped.push(canonical); + } + return deduped; + } + + _canonical_image_path(imagePath: string | null): string | null { + if (!imagePath) return null; + try { + const expanded = expandUser(imagePath); + if (!fs.statSync(expanded).isFile()) return null; + return fs.realpathSync(expanded); + } catch { + return null; + } + } + + async _upload_images(image_paths: string[]): Promise { + return (await this._upload_image_entries(image_paths)).map( + ([, image_key]) => image_key, + ); + } + + async _upload_image_entries( + image_paths: string[], + ): Promise> { + const entries: Array<[string, string]> = []; + for (const imagePath of image_paths) { + const imageKey = await this._upload_image(imagePath); + if (imageKey) entries.push([imagePath, imageKey]); + } + return entries; + } + + async _upload_image(imagePath: string): Promise { + if (!this._client) return null; + try { + const image = fs.readFileSync(imagePath); + let response: any; + if (this._client.im?.v1?.image?.create) { + response = await callMaybeAsync( + this._client.im.v1.image.create({ + request_body: { image_type: "message", image }, + data: { image_type: "message", image }, + }), + ); + } else { + response = await callMaybeAsync( + this._client.im.image.create({ + data: { image_type: "message", image }, + }), + ); + } + if (responseSuccess(response)) return responseImageKey(response); + console.log( + `[Feishu] Image upload failed: ${response?.code} ${response?.msg}`, + ); + return null; + } catch (e) { + console.log( + `[Feishu] Failed to upload generated image ${imagePath}: ${e}`, + ); + return null; + } + } + + _hide_generated_image_paths( + content: string, + image_count: number, + uploaded_paths: string[] = [], + ): string { + const uploaded = new Set( + uploaded_paths + .map((p) => this._canonical_image_path(p)) + .filter((p): p is string => Boolean(p)), + ); + const lines: string[] = []; + for (const line of (content || "").split(/\r?\n/)) { + const stripped = line.trim(); + if (!stripped) { + lines.push(""); + continue; + } + if (this._line_is_uploaded_image_path(stripped, uploaded)) continue; + const cleaned = this._remove_uploaded_markdown_image_refs(line, uploaded); + const visible = cleaned.trim(); + if (visible && !["-", "*", "+"].includes(visible)) + lines.push(cleaned.trimEnd()); + } + const cleaned = lines.join("\n").trim(); + if (!cleaned || cleaned.startsWith("已生成")) + return `已生成 ${image_count} 张图片。`; + return cleaned; + } + + _line_is_uploaded_image_path( + stripped_line: string, + uploaded_paths: Set, + ): boolean { + if (!stripped_line.startsWith("- ")) return false; + const canonical = this._canonical_image_path(stripped_line.slice(2).trim()); + return Boolean( + (canonical && uploaded_paths.has(canonical)) || + stripped_line.includes("/.codex/generated_images/"), + ); + } + + _remove_uploaded_markdown_image_refs( + line: string, + uploaded_paths: Set, + ): string { + if (!uploaded_paths.size) return line; + return line.replace(FEISHU_MARKDOWN_IMAGE_RE, (full, target) => { + const imagePath = this._local_image_path_from_reference(target); + const canonical = this._canonical_image_path(imagePath); + return canonical && uploaded_paths.has(canonical) ? "" : full; + }); + } + + async _send_message( + chat_id: string, + content: string, + card: Row | null = null, + fallback_content: string | null = null, + ): Promise { + if (!this._client) return null; + try { + const receive_id_type = chat_id.startsWith("oc_") ? "chat_id" : "open_id"; + const card_payload = card ?? this._build_legacy_markdown_card(content); + const message_id = await this._create_message( + receive_id_type, + chat_id, + card_payload, + ); + if (message_id) return message_id; + if (card !== null) { + return await this._create_message( + receive_id_type, + chat_id, + this._build_legacy_markdown_card(fallback_content ?? content), + ); + } + return null; + } catch (e) { + console.log(`[Feishu] Error sending message: ${e}`); + return null; + } + } + + async _reply_message( + parent_message_id: string, + content: string, + card: Row | null = null, + ): Promise { + if (!this._client) return null; + try { + const reply_card = card ?? this._build_legacy_markdown_card(content); + const message_id = await this._create_reply( + parent_message_id, + reply_card, + ); + if (message_id) return message_id; + if (card !== null) + return await this._create_reply( + parent_message_id, + this._build_legacy_markdown_card(content), + ); + return null; + } catch (e) { + console.log(`[Feishu] Error replying to message: ${e}`); + return null; + } + } + + async _create_message( + receive_id_type: string, + chat_id: string, + card: Row, + ): Promise { + if (!this._client) return null; + const request = { + receive_id_type, + params: { receive_id_type }, + request_body: { + receive_id: chat_id, + msg_type: "interactive", + content: stringifyCard(card), + }, + data: { + receive_id: chat_id, + msg_type: "interactive", + content: stringifyCard(card), + }, + }; + const response = this._client.im?.v1?.message?.create + ? await callMaybeAsync(this._client.im.v1.message.create(request)) + : await callMaybeAsync(this._client.im.message.create(request)); + if (responseSuccess(response)) return responseMessageId(response); + console.log(`[Feishu] Send failed: ${response?.code} ${response?.msg}`); + return null; + } + + async _create_reply( + parent_message_id: string, + card: Row, + ): Promise { + if (!this._client) return null; + const request = { + message_id: parent_message_id, + path: { message_id: parent_message_id }, + request_body: { + msg_type: "interactive", + content: stringifyCard(card), + reply_in_thread: true, + }, + data: { + msg_type: "interactive", + content: stringifyCard(card), + reply_in_thread: true, + }, + }; + const response = this._client.im?.v1?.message?.reply + ? await callMaybeAsync(this._client.im.v1.message.reply(request)) + : await callMaybeAsync(this._client.im.message.reply(request)); + if (responseSuccess(response)) return responseMessageId(response); + console.log(`[Feishu] Reply failed: ${response?.code} ${response?.msg}`); + return null; + } + + async _patch_message(message_id: string, card: Row): Promise { + if (!this._client) return false; + try { + const request = { + message_id, + path: { message_id }, + request_body: { content: stringifyCard(card) }, + data: { content: stringifyCard(card) }, + }; + const response = this._client.im?.v1?.message?.patch + ? await callMaybeAsync(this._client.im.v1.message.patch(request)) + : await callMaybeAsync(this._client.im.message.patch(request)); + if (responseSuccess(response)) return true; + console.log(`[Feishu] Patch failed: ${response?.code} ${response?.msg}`); + return false; + } catch (e) { + console.log(`[Feishu] Error patching message ${message_id}: ${e}`); + return false; + } + } + + _build_streaming_card( + task_id: number, + task_title: string, + output_text: string, + done = false, + ): Row { + let elements: Row[]; + if (done) { + const display_text = output_text.trim() || "完成"; + elements = [ + { + tag: "markdown", + content: this._preserve_feishu_markdown_linebreaks(display_text), + }, + ]; + } else if (!output_text.trim()) { + elements = [{ tag: "markdown", content: "Thinking ▌" }]; + } else { + elements = [this._build_streaming_history_panel(output_text, true)]; + } + return { + schema: "2.0", + config: { wide_screen_mode: true, width_mode: "fill" }, + body: { elements }, + }; + } + + _build_streaming_history_panel(output_text: string, expanded = false): Row { + return { + tag: "collapsible_panel", + expanded, + header: { + title: { tag: "plain_text", content: "执行过程" }, + vertical_align: "center", + icon: { + tag: "standard_icon", + token: "down-small-ccm_outlined", + color: "", + size: "16px 16px", + }, + icon_position: "right", + icon_expanded_angle: -180, + }, + border: { color: "grey", corner_radius: "5px" }, + vertical_spacing: "8px", + padding: "8px 8px 8px 8px", + elements: this._build_streaming_history_elements(output_text), + }; + } + + _build_streaming_history_elements(output_text: string): Row[] { + const normalized = output_text + .replace(/\r\n/g, "\n") + .replace(/\r/g, "\n") + .replace(/\n+$/g, ""); + if (!normalized) return []; + const line_elements = + this._build_streaming_history_line_elements(normalized); + return line_elements.length <= FEISHU_PANEL_MAX_LINE_ELEMENTS + ? line_elements + : this._build_streaming_history_markdown_elements(normalized); + } + + _build_streaming_history_markdown_elements(text: string): Row[] { + return this._chunk_text(text, FEISHU_CARD_MARKDOWN_CHUNK - 16).map( + (chunk) => ({ + tag: "markdown", + content: chunk, + }), + ); + } + + _build_streaming_history_line_elements(text: string): Row[] { + const elements: Row[] = []; + for (const line of text.split("\n")) { + for (const chunk of line + ? this._chunk_text(line, FEISHU_PANEL_PLAIN_TEXT_CHUNK) + : [" "]) { + elements.push(this._build_streaming_history_line(chunk)); + } + } + return elements; + } + + _build_streaming_history_line(content: string): Row { + return { + tag: "div", + text: { + tag: "plain_text", + text_color: "grey", + text_size: "notation", + content, + }, + }; + } + + _preserve_feishu_markdown_linebreaks(text: string): string { + return text.replace(/\r\n/g, "\n").replace(/\r/g, "\n"); + } + + _start_streaming( + task_id: number, + running_msg_id: string, + task_title: string, + ): void { + this._stop_streaming(task_id); + const writer = new _FeishuStreamWriter( + task_id, + running_msg_id, + this, + task_title, + ); + this._writers.set(task_id, writer); + this._streaming_msg.set(task_id, running_msg_id); + const listener = writer.on_event.bind(writer); + this._writer_listeners.set(task_id, listener); + this.scheduler.add_output_listener(listener); + } + + _stop_streaming(task_id: number): string | null { + const writer = this._writers.get(task_id); + if (!writer) return null; + this._writers.delete(task_id); + const listener = this._writer_listeners.get(task_id); + if (listener) { + this.scheduler.remove_output_listener(listener); + this._writer_listeners.delete(task_id); + } + const history = writer.snapshot_text(); + writer.stop(); + return history; + } + + _build_notification_card(args: { + task_id: number; + task: Row; + is_completed: boolean; + body_text: string; + streaming_history?: string | null; + image_keys?: string[] | null; + }): Row { + const clean_body = + (args.body_text || "").trim() || + (args.is_completed ? "Done." : "Unknown error"); + const summary = clean_body + ? this._truncate_text(clean_body.split(/\r?\n/)[0] ?? "", 120) + : ""; + let elements = this._build_result_elements( + clean_body, + args.image_keys ?? [], + ); + if (args.streaming_history?.trim()) { + let panel_text = args.streaming_history; + if (args.is_completed) { + const stripped = this._strip_final_result_from_history( + args.streaming_history, + clean_body, + ); + if (stripped.trim()) panel_text = stripped; + } + elements = [this._build_streaming_history_panel(panel_text)].concat( + elements, + ); + } + if (!args.is_completed) { + elements.push({ + tag: "markdown", + content: `\`/status ${args.task_id}\` for full details`, + }); + } + return { + schema: "2.0", + config: { + wide_screen_mode: true, + enable_forward: true, + width_mode: "fill", + summary: { content: summary }, + }, + body: { elements }, + }; + } + + _strip_final_result_from_history( + history: string, + final_text: string, + ): string { + const final_body = (final_text || "").trim(); + if (!final_body) return history; + const trimmed = history.trimEnd(); + return trimmed.endsWith(final_body) + ? trimmed.slice(0, -final_body.length).trimEnd() + : history; + } + + _build_result_elements( + body_text: string, + image_keys: string[] | null = null, + ): Row[] { + const clean_body = (body_text || "").trim() || "Done."; + const elements: Row[] = this._chunk_text( + clean_body, + FEISHU_CARD_MARKDOWN_CHUNK, + ).map((chunk) => ({ + tag: "markdown", + content: chunk, + })); + for (const [index, image_key] of (image_keys ?? []).entries()) { + elements.push({ + tag: "img", + img_key: image_key, + alt: { tag: "plain_text", content: `generated image ${index + 1}` }, + }); + } + return elements; + } + + _build_legacy_markdown_card(content: string): Row { + return { + config: { wide_screen_mode: true }, + elements: [{ tag: "markdown", content }], + }; + } + + _truncate_text(text: string, limit: number): string { + const normalized = text.replace(/\r\n/g, "\n").trim(); + return normalized.length <= limit + ? normalized + : normalized.slice(0, limit).trimEnd() + "\n…(truncated)"; + } + + _chunk_text(text: string, limit: number): string[] { + const normalized = text.replace(/\r\n/g, "\n"); + if (!normalized) return [""]; + const chunks: string[] = []; + for (let i = 0; i < normalized.length; i += limit) + chunks.push(normalized.slice(i, i + limit)); + return chunks; + } + + _escape_feishu_markdown(text: string): string { + return text.replace(/\\/g, "\\\\"); + } + + _add_reaction(message_id: string, emoji_type = "THUMBSUP"): void { + if (!this._client) return; + void (async () => { + try { + const request = { + message_id, + path: { message_id }, + request_body: { reaction_type: { emoji_type } }, + data: { reaction_type: { emoji_type } }, + }; + if (this._client.im?.v1?.message_reaction?.create) { + await this._client.im.v1.message_reaction.create(request); + } else if (this._client.im?.messageReaction?.create) { + await this._client.im.messageReaction.create(request); + } + } catch (e) { + console.log(`[Feishu] Failed to add reaction to ${message_id}: ${e}`); + } + })(); + } + + _get_usage_stats(): string { + return "📊 Claude Code 用量统计在 TypeScript 运行时暂不可用"; + } + + _extract_forwarded_content(message: Row): Row | null { + const msg_type = message["message_type"]; + if (msg_type === "forward") { + try { + const content = JSON.parse(message["content"]); + return { + type: "forward", + sender_name: content["sender_name"] ?? "Unknown", + sender_id: content["sender_id"] ?? null, + timestamp: content["create_time"] ?? null, + text: content["text"] ?? "", + images: content["images"] ?? [], + }; + } catch { + return null; + } + } + if (msg_type === "post") { + try { + const post_body = JSON.parse(message["content"]); + const lang_body = + post_body["content"] ?? + post_body["zh_cn"] ?? + post_body["en_us"] ?? + Object.values(post_body)[0] ?? + {}; + const paragraphs = Array.isArray(lang_body) + ? lang_body + : (lang_body["content"] ?? []); + for (const para of paragraphs) { + for (const elem of para) { + if (elem?.tag === "quote") { + const user = elem["user"] ?? {}; + return { + type: "quote", + sender_name: user["name"] ?? "未知用户", + sender_id: user["open_id"] ?? null, + text: elem["text"] ?? "", + timestamp: elem["create_time"] ?? null, + }; + } + if (elem?.tag === "nested_message") { + const nested = elem["nested_message"] ?? {}; + return { + type: "forward", + sender_name: nested["sender_name"] ?? "未知用户", + sender_id: nested["sender_id"] ?? null, + timestamp: nested["create_time"] ?? null, + text: nested["text"] ?? "", + images: nested["images"] ?? [], + }; + } + } + } + } catch { + return null; + } + } + return null; + } + + _format_forwarded_prompt( + original_content: string, + forwarded: Row | null, + ): string { + if (!forwarded) return original_content; + const parts = [ + "📨 [转发消息]", + `转发自: ${forwarded["sender_name"] ?? "未知用户"}`, + ]; + if (forwarded["timestamp"]) { + const dt = new Date(Number(forwarded["timestamp"]) * 1000); + const fmt = new Intl.DateTimeFormat("zh-CN", { + timeZone: "Asia/Shanghai", + year: "numeric", + month: "2-digit", + day: "2-digit", + hour: "2-digit", + minute: "2-digit", + hour12: false, + }).format(dt); + parts.push(`时间: ${fmt.replaceAll("/", "-")}`); + } + parts.push("\n--- 转发内容 ---"); + parts.push(forwarded["text"] ?? ""); + const images = Array.isArray(forwarded["images"]) + ? forwarded["images"] + : []; + if (images.length) parts.push(`\n[包含 ${images.length} 张图片]`); + if (original_content.trim()) { + parts.push("\n--- 用户附加消息 ---"); + parts.push(original_content); + } + return parts.join("\n"); + } + + async _download_image( + message_id: string, + image_key: string, + ): Promise { + if (!this._client) return null; + try { + const request = { + message_id, + file_key: image_key, + type: "image", + path: { message_id, file_key: image_key }, + params: { type: "image" }, + }; + const response = this._client.im?.v1?.message_resource?.get + ? await callMaybeAsync(this._client.im.v1.message_resource.get(request)) + : await callMaybeAsync(this._client.im.messageResource.get(request)); + if (!responseSuccess(response)) return null; + const image_data: Buffer = Buffer.from( + response?.raw?.content ?? response?.data ?? [], + ); + let extension = "jpg"; + if (image_data.subarray(0, 3).equals(Buffer.from([0xff, 0xd8, 0xff]))) + extension = "jpg"; + else if ( + image_data + .subarray(0, 8) + .equals(Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])) + ) + extension = "png"; + else if ( + image_data.subarray(0, 6).toString() === "GIF87a" || + image_data.subarray(0, 6).toString() === "GIF89a" + ) + extension = "gif"; + else if ( + image_data.subarray(0, 4).toString() === "RIFF" && + image_data.subarray(8, 12).toString() === "WEBP" + ) + extension = "webp"; + const downloads_dir = path.join( + os.homedir(), + ".agentforge", + "feishu_images", + ); + fs.mkdirSync(downloads_dir, { recursive: true }); + const filePath = path.join(downloads_dir, `${image_key}.${extension}`); + fs.writeFileSync(filePath, image_data); + return filePath; + } catch (e) { + console.log(`[Feishu] Error downloading image ${image_key}: ${e}`); + return null; + } + } + + _on_reaction(_data: unknown): void { + return; + } + + _on_bot_added(data: any): void { + const event = extractEvent(data); + const chat_id = event["chat_id"]; + if (chat_id) void this._send_message(chat_id, HELP_TEXT); + } + + _on_message_sync(data: any): void { + if (!this._running) return; + void this._handle_inbound(data).catch((e) => + console.log(`[Feishu] Inbound handler error: ${e}`), + ); + } + + async _handle_inbound(data: any): Promise { + const event = extractEvent(data); + const message = event["message"] ?? {}; + const sender = event["sender"] ?? {}; + if (sender["sender_type"] === "bot") return; + + const parsed = await this._parse_message_content(message); + if (!parsed) return; + let { content, image_paths } = parsed; + const forwarded = this._extract_forwarded_content(message); + if (forwarded) { + content = this._format_forwarded_prompt(content, forwarded); + for (const img of forwarded["images"] ?? []) { + const img_key = img?.["image_key"]; + if (img_key) { + const img_path = await this._download_image( + message["message_id"], + img_key, + ); + if (img_path) image_paths.push(img_path); + } + } + } + if (!content) return; + + this._add_reaction(message["message_id"], "OK"); + const sender_id = getSenderOpenId(sender); + const chat_type = message["chat_type"]; + const chat_id = message["chat_id"]; + const reply_to = chat_type === "group" ? chat_id : sender_id; + + if (content.trim() === "/help" || content.trim() === "/start") { + await this._send_message(reply_to, HELP_TEXT); + return; + } + if (content.startsWith("/dir ") || content.startsWith("/cd ")) { + const reply = handle_dir_command(content, "feishu", this.db); + if (reply) await this._send_message(reply_to, reply); + return; + } + if (content.startsWith("/agent ")) { + const reply = handle_agent_command(content, "feishu", this.db); + if (reply) await this._send_message(reply_to, reply); + return; + } + if (content.trim().toLowerCase().startsWith("/ccu")) { + await this._send_message(reply_to, this._get_usage_stats()); + return; + } + if (content.startsWith("/resume ")) { + await this._handle_resume_command(content, reply_to, message); + return; + } + if (content.startsWith("/status ")) { + await this._handle_status_command(content, reply_to); + return; + } + if ( + [ + "notification", + "任务完成", + "任务失败", + "任务状态", + "任务已", + "task completed", + "task failed", + "task status", + ].some((keyword) => content.toLowerCase().includes(keyword)) + ) { + return; + } + + const parent_id = message["parent_id"] || null; + const root_id = message["root_id"] || null; + if (parent_id || root_id) { + const resumed = await this._try_resume_thread_message( + content, + reply_to, + message, + parent_id, + root_id, + ); + if (resumed) return; + } + await this._create_task_from_message( + content, + image_paths, + reply_to, + message, + ); + } + + async _parse_message_content( + message: Row, + ): Promise<{ content: string; image_paths: string[] } | null> { + const msg_type = message["message_type"]; + const image_paths: string[] = []; + if (msg_type === "text") { + try { + return { + content: String(JSON.parse(message["content"])["text"] ?? "").trim(), + image_paths, + }; + } catch { + return { + content: String(message["content"] ?? "").trim(), + image_paths, + }; + } + } + if (msg_type === "post") { + try { + const post_body = JSON.parse(message["content"]); + const lang_body = post_body["content"] + ? post_body + : post_body["zh_cn"] || + post_body["en_us"] || + Object.values(post_body)[0] || + {}; + const text_parts: string[] = []; + for (const para of lang_body["content"] ?? []) { + for (const elem of para) { + if (elem?.tag === "text") text_parts.push(elem["text"] ?? ""); + if (elem?.tag === "img" && elem["image_key"]) { + const imagePath = await this._download_image( + message["message_id"], + elem["image_key"], + ); + if (imagePath) image_paths.push(imagePath); + } + } + } + const content = [ + String(lang_body["title"] ?? "").trim(), + text_parts.join("").trim(), + ] + .filter(Boolean) + .join("\n"); + return { + content: + content || (image_paths.length ? "请分析这些图片的内容" : ""), + image_paths, + }; + } catch { + return { content: "", image_paths }; + } + } + if (msg_type === "image") { + try { + const image_key = JSON.parse(message["content"])["image_key"]; + if (image_key) { + const imagePath = await this._download_image( + message["message_id"], + image_key, + ); + if (imagePath) image_paths.push(imagePath); + } + } catch { + // Keep default prompt for malformed image payloads. + } + return { content: "请分析这张图片的内容", image_paths }; + } + return null; + } + + async _handle_resume_command( + content: string, + reply_to: string, + message: Row, + ): Promise { + const parts = content.slice(8).trim().split(" "); + const tid = Number(parts.shift()); + const resume_msg = parts.join(" ").trim(); + if (!Number.isInteger(tid) || !resume_msg) { + await this._send_message( + reply_to, + "Usage: `/resume `", + ); + return; + } + const task = this.db.get_task(tid) as Row | null; + if (task?.["session_id"]) { + this.db.update_task(tid, { + status: "pending", + prompt: resume_msg, + result: null, + error: null, + question: null, + }); + this._task_origin.set(tid, [ + reply_to, + message["message_id"], + message["message_id"], + ]); + const title = + (this.db.get_task(tid) as Row | null)?.["title"] ?? `Task #${tid}`; + const running_msg_id = await this._create_reply( + message["message_id"], + this._build_streaming_card(tid, title, ""), + ); + if (running_msg_id) this._start_streaming(tid, running_msg_id, title); + } else { + await this._send_message( + reply_to, + `❌ Task #${tid} not found or has no saved session.`, + ); + } + } + + async _handle_status_command( + content: string, + reply_to: string, + ): Promise { + const tid = Number(content.slice(8).trim().split(/\s+/)[0]); + if (!Number.isInteger(tid)) return; + const task = this.db.get_task(tid) as Row | null; + if (!task) { + await this._send_message(reply_to, `❌ Task #${tid} not found.`); + return; + } + const icons: Record = { + completed: "✅", + failed: "❌", + running: "⏳", + pending: "🕐", + cancelled: "🚫", + }; + const icon = icons[String(task["status"])] ?? "❓"; + await this._send_message( + reply_to, + `${icon} **Task #${tid}** — ${task["status"]}\n\n**${task["title"]}**`, + ); + } + + async _try_resume_thread_message( + content: string, + reply_to: string, + message: Row, + parent_id: string | null, + root_id: string | null, + ): Promise { + let task_id: number | undefined; + if (parent_id) task_id = this._notification_map.get(parent_id); + if (!task_id && root_id) task_id = this._notification_map.get(root_id); + if (!task_id && root_id) task_id = this._root_msg_map.get(root_id); + if (!task_id && parent_id) task_id = this._root_msg_map.get(parent_id); + if (!task_id) { + for (const msg_id of [root_id, parent_id].filter(Boolean) as string[]) { + const db_task = this.db.get_task_by_feishu_root_msg(msg_id); + if (db_task) { + task_id = db_task["id"]; + break; + } + } + } + if (!task_id) return false; + const task = this.db.get_task(task_id) as Row | null; + const thread_root = root_id || parent_id!; + if (task?.["session_id"]) { + this.db.update_task(task_id, { + status: "pending", + prompt: content, + result: null, + error: null, + question: null, + }); + this._task_origin.set(task_id, [ + reply_to, + thread_root, + message["message_id"], + ]); + const title = + (this.db.get_task(task_id) as Row | null)?.["title"] ?? + `Task #${task_id}`; + const running_msg_id = await this._create_reply( + thread_root, + this._build_streaming_card(task_id, title, ""), + ); + if (running_msg_id) this._start_streaming(task_id, running_msg_id, title); + } else { + await this._reply_message( + thread_root, + `❌ Task #${task_id} not found or has no saved session.`, + ); + } + return true; + } + + async _create_task_from_message( + content: string, + image_paths: string[], + reply_to: string, + message: Row, + ): Promise { + const working_dir = await resolve_working_dir(content, "feishu", this.db); + const title = content.slice(0, 60) + (content.length > 60 ? "…" : ""); + const prompt_images: PromptImage[] = []; + for (const imagePath of image_paths) { + try { + prompt_images.push({ + name: path.basename(imagePath), + media_type: localImageMediaType(imagePath), + data: fs.readFileSync(imagePath).toString("base64"), + }); + } catch (e) { + console.log( + `[Feishu] Failed to convert image ${imagePath} to base64: ${e}`, + ); + } + } + const task = makeTask({ + title: `[Feishu] ${title}`, + prompt: content, + working_dir, + schedule_type: ScheduleType.IMMEDIATE, + tags: "feishu", + image_paths, + prompt_images, + feishu_root_msg_id: message["message_id"] ?? null, + agent: resolve_agent("feishu", this.db), + }); + const task_id = this.scheduler.submit_task(task); + const running_msg_id = await this._create_reply( + message["message_id"], + this._build_streaming_card(task_id, task.title, ""), + ); + this._task_origin.set(task_id, [ + reply_to, + message["message_id"], + message["message_id"], + ]); + this._root_msg_map.set(message["message_id"], task_id); + if (running_msg_id) + this._start_streaming(task_id, running_msg_id, task.title); + } +} diff --git a/backend/src/channels/slack.ts b/backend/src/channels/slack.ts index 63be71b..d82a940 100644 --- a/backend/src/channels/slack.ts +++ b/backend/src/channels/slack.ts @@ -196,8 +196,10 @@ export async function _require_slack(): Promise { return await _hooks.import_slack(); } catch (e) { throw new Error( - "slack-sdk is required for SlackChannel. Install it with: uv add slack-sdk", - { cause: e }, + "@slack/web-api and @slack/socket-mode are required for SlackChannel", + { + cause: e, + }, ); } } diff --git a/backend/src/channels/telegram.ts b/backend/src/channels/telegram.ts index 29051fb..ba5f887 100644 --- a/backend/src/channels/telegram.ts +++ b/backend/src/channels/telegram.ts @@ -230,7 +230,7 @@ export class TelegramChannel extends Channel { start(): void { if (!TELEGRAM_AVAILABLE) { console.log( - "[Telegram] python-telegram-bot not installed. Run: uv add python-telegram-bot", + "[Telegram] Telegram Bot API transport unavailable in this runtime", ); return; } diff --git a/backend/src/channels/weixin.ts b/backend/src/channels/weixin.ts new file mode 100644 index 0000000..483d8ef --- /dev/null +++ b/backend/src/channels/weixin.ts @@ -0,0 +1,1157 @@ +/** + * Weixin channel for AgentForge — ported from channels/weixin_channel.py. + * + * Text-only MVP backed by a sidecar bridge process that communicates with the + * backend via newline-delimited JSON over stdio. The Python original spawned + * the Node bridge (`node weixin_bridge/index.mjs`); this port spawns the + * TypeScript bridge under Bun (`bun weixin_bridge/index.ts`). Protocol + * strings, NDJSON command/event shapes, and user-facing strings are kept + * byte-identical to the Python source. + * + * Porting notes + * ───────────── + * - subprocess.Popen → the injectable `_hooks.spawn_bridge` seam returning a + * WeixinBridgeProcess (stdin writer + stdout line iterable + poll/terminate/ + * wait). Tests inject a fake process exactly where the pytest suite + * monkeypatched `channels.weixin_channel.subprocess.Popen`. + * - The stdout reader daemon thread → an async loop (`_read_bridge_events`) + * whose promise is kept in `_reader_promise` (≙ `_reader_thread`). + * - Python merged the bridge's stderr into stdout (stderr=subprocess.STDOUT); + * here the default spawn inherits stderr so bridge logs go straight to the + * backend's stderr instead of through the "Ignoring non-JSON" logger. + * - threading.Lock fields are dropped (single-threaded event loop). + * - resolve_working_dir is async in TS, so _handle_message_event (and thus + * _handle_bridge_event) is async. + */ + +import crypto from "node:crypto"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; + +import { + Channel, + MessageBus, + OutboundMessageType, + type OutboundMessage, + type TaskDBLike, +} from "../bus.ts"; +import { + makeTask, + ScheduleType, + type PromptImage, + type Task, +} from "../types.ts"; +import { + handle_agent_command, + resolve_agent, + type SettingsDB, +} from "./agent_utils.ts"; +import { handle_dir_command, resolve_working_dir } from "./dir_utils.ts"; + +export const WEIXIN_UPLOADABLE_IMAGE_SUFFIXES = new Set([ + ".png", + ".jpg", + ".jpeg", + ".gif", + ".webp", +]); +const WEIXIN_MARKDOWN_IMAGE_RE = /!\[[^\]]*]\(([^)]+)\)/g; +// ≙ re.compile(r"^/new(?:\s+(.*))?$", re.IGNORECASE | re.DOTALL) +const WEIXIN_NEW_SESSION_RE = /^\/new(?:\s+([\s\S]*))?$/i; + +// ── injectable process seam ─────────────────────────────────────── + +/** Writable stdin of the bridge process (≙ Popen.stdin in text mode). */ +export interface WeixinBridgeStdin { + write(data: string): unknown; + flush?(): unknown; +} + +/** + * Minimal view of the spawned bridge process (≙ subprocess.Popen). `stdout` + * yields lines (like iterating Popen.stdout in text mode); tests supply a + * plain string[]. + */ +export interface WeixinBridgeProcess { + stdin: WeixinBridgeStdin | null; + stdout: AsyncIterable | Iterable | null; + /** ≙ Popen.poll(): null while alive, exit code once exited. */ + poll(): number | null; + terminate(): void; + /** ≙ Popen.wait(timeout=...); may return a promise (not awaited). */ + wait(timeout?: number | null): unknown; +} + +export type SpawnBridge = ( + cmd: string[], + env: Record, +) => WeixinBridgeProcess; + +/** Split a byte stream into lines (trailing newline included, like Python). */ +async function* _iter_lines( + stream: ReadableStream, +): AsyncGenerator { + const decoder = new TextDecoder(); + let buffered = ""; + for await (const chunk of stream) { + buffered += decoder.decode(chunk, { stream: true }); + let idx: number; + while ((idx = buffered.indexOf("\n")) !== -1) { + yield buffered.slice(0, idx + 1); + buffered = buffered.slice(idx + 1); + } + } + buffered += decoder.decode(); + if (buffered) yield buffered; +} + +/** + * Default spawn implementation (≙ subprocess.Popen(..., text=True)). + * Bun.spawn throws synchronously with code "ENOENT" when the executable is + * missing, matching Python's FileNotFoundError handling in start(). + */ +function _default_spawn_bridge( + cmd: string[], + env: Record, +): WeixinBridgeProcess { + const proc = Bun.spawn({ + cmd: cmd as [string, ...string[]], + env, + stdin: "pipe", + stdout: "pipe", + // Python used stderr=subprocess.STDOUT; inheriting keeps bridge logs + // visible without routing them through the NDJSON event reader. + stderr: "inherit", + }); + return { + stdin: proc.stdin, + stdout: _iter_lines(proc.stdout), + poll: () => proc.exitCode, + terminate: () => { + proc.kill(); + }, + wait: (_timeout?: number | null) => proc.exited, + }; +} + +/** ≙ shutil.which — the backend itself runs under Bun, so the current + * executable is the most reliable full path to the runtime (it survives the + * minimal PATH a Finder/Dock-launched macOS app inherits). */ +function _default_which(cmd: string): string | null { + const execPath = process.execPath || ""; + if (path.basename(execPath) === cmd) { + return execPath; + } + + for (const dir of (process.env.PATH || "").split(path.delimiter)) { + if (!dir) continue; + const candidate = path.join(dir, cmd); + if (fs.existsSync(candidate)) { + return candidate; + } + } + return null; +} + +/** + * Locate the Bun binary used to run the sidecar bridge. + * + * ≙ Python's _find_node_executable (the bridge ran on Node there): macOS apps + * launched from Finder/Dock inherit a minimal PATH that excludes Homebrew + * (`/opt/homebrew/bin`), so fall back to the common install locations when + * the primary lookup misses. + */ +export function _find_bun_executable(): string | null { + const found = _hooks.which("bun"); + if (found) { + return found; + } + for (const candidate of [ + "/opt/homebrew/bin/bun", + "/usr/local/bin/bun", + path.join(os.homedir(), ".bun", "bin", "bun"), + ]) { + if (_hooks.path_exists(candidate)) { + return candidate; + } + } + return null; +} + +function _is_bridge_script(entrypoint: string): boolean { + return new Set([".ts", ".js", ".mjs", ".cjs"]).has( + path.extname(entrypoint).toLowerCase(), + ); +} + +// Test seams (≙ the pytest monkeypatch targets): +// spawn_bridge ≙ channels.weixin_channel.subprocess.Popen +// which ≙ channels.weixin_channel.shutil.which +// path_exists ≙ channels.weixin_channel.os.path.exists +// handle_dir_command ≙ channels.dir_utils.handle_dir_command (Python +// handle_agent_command imports these inside _handle_message_event, so +// module-attribute patches took effect there) +export const _hooks = { + spawn_bridge: _default_spawn_bridge as SpawnBridge, + which: _default_which, + path_exists: (p: string): boolean => fs.existsSync(p), + handle_dir_command, + handle_agent_command, +}; + +// ── structural dependency interfaces ────────────────────────────── + +/** Minimal structural view of TaskDB used by this channel. */ +export interface WeixinTaskDB extends TaskDBLike, SettingsDB { + update_task(task_id: number, updates: Record): void; + get_task_runs(task_id: number, limit?: number): unknown; + get_run_output_events(run_id: number, limit?: number): unknown; +} + +/** + * Minimal structural view of TaskScheduler (do NOT import scheduler.ts). + * Python source: TaskScheduler.submit_task(self, task, depends_on=None) -> int; + * this channel only ever calls submit_task(task). + */ +export interface WeixinScheduler { + submit_task(task: Task): number; +} + +/** Status snapshot consumed by _build_weixin_channel_status in taskboard. */ +interface WeixinStatus { + configured: boolean; + login_status: string; + qr_code_url: string; + last_error: string; + account_id: string; + user_id: string; +} + +// ── helpers (≙ urllib.parse / pathlib bits) ─────────────────────── + +/** ≙ urlparse(target).path for file:// references (scheme + netloc dropped). */ +function _file_url_path(target: string): string { + const rest = target.slice("file://".length); + const slash = rest.indexOf("/"); + return slash >= 0 ? rest.slice(slash) : ""; +} + +/** ≙ urllib.parse.unquote (left untouched when percent-decoding fails). */ +function _unquote(value: string): string { + try { + return decodeURIComponent(value); + } catch { + return value; + } +} + +/** ≙ Path.expanduser(). */ +function _expanduser(p: string): string { + if (p === "~") return os.homedir(); + if (p.startsWith("~/")) return path.join(os.homedir(), p.slice(2)); + return p; +} + +function _is_plain_object(value: unknown): value is Record { + return typeof value === "object" && value !== null && !Array.isArray(value); +} + +const PNG_HEADER = Buffer.from([ + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, +]); +const JPEG_HEADER = Buffer.from([0xff, 0xd8, 0xff]); + +// ── WeixinChannel ───────────────────────────────────────────────── + +/** Weixin integration using a sidecar bridge process. */ +export class WeixinChannel extends Channel { + declare db: WeixinTaskDB; + scheduler: WeixinScheduler; + bridge_cmd: string[]; + _bridge_proc: WeixinBridgeProcess | null = null; + /** ≙ self._reader_thread (daemon thread joining the bridge stdout). */ + _reader_promise: Promise | null = null; + + // task_id -> origin metadata used for notifications and resume + _task_origin: Map> = new Map(); + + // account_id:peer_id -> current task_id. Weixin has no thread, so this + // gives each peer a current AgentForge session until /new starts another. + _peer_current_task: Map = new Map(); + + // notification message_id -> task_id for resume-by-reply + _notification_map: Map = new Map(); + + // request_id -> task_id for sent acknowledgements from the bridge + _pending_notifications: Map = new Map(); + + _status: WeixinStatus = { + configured: false, + login_status: "idle", + qr_code_url: "", + last_error: "", + account_id: "", + user_id: "", + }; + + constructor( + bus: MessageBus, + db: WeixinTaskDB, + scheduler: WeixinScheduler, + bridge_cmd: string[] | null = null, + ) { + super("weixin", bus, db); + this.scheduler = scheduler; + this.bridge_cmd = bridge_cmd ?? this._default_bridge_cmd(); + + bus.subscribe_outbound(this._on_outbound); + } + + _bridge_script_path(): string { + // ≙ the PyInstaller sys._MEIPASS branch: the Python build shipped the + // bridge via --add-data and resolved it under sys._MEIPASS when frozen. + // The Bun single-binary build (`bun build --compile`) cannot resolve + // source-relative paths either, so the packaged app sets + // AGENTFORGE_WEIXIN_BRIDGE to the bridge entrypoint it ships alongside + // the binary; dev falls back to the source tree next to this module. + const override = process.env.AGENTFORGE_WEIXIN_BRIDGE; + if (override) { + return override; + } + const packagedBridge = path.join( + path.dirname(process.execPath), + "weixin-bridge", + ); + if (_hooks.path_exists(packagedBridge)) { + return packagedBridge; + } + return path.join(import.meta.dir, "weixin_bridge", "index.ts"); + } + + _default_bridge_cmd(): string[] { + const bridgeEntrypoint = this._bridge_script_path(); + if (!_is_bridge_script(bridgeEntrypoint)) { + return [bridgeEntrypoint]; + } + + // Resolve bun to a full path so it's found even under the minimal PATH + // a packaged macOS app inherits. Falls back to bare "bun" when missing; + // start() then surfaces the spawn ENOENT as an error status. + return [_find_bun_executable() || "bun", bridgeEntrypoint]; + } + + start(): void { + this._running = true; + try { + const env: Record = { ...process.env }; + if (env["AGENTFORGE_WEIXIN_DATA_DIR"] === undefined) { + env["AGENTFORGE_WEIXIN_DATA_DIR"] = path.join( + os.homedir(), + ".agentforge", + "weixin", + ); + } + if (env["AGENTFORGE_WEIXIN_BASE_URL"] === undefined) { + env["AGENTFORGE_WEIXIN_BASE_URL"] = + this.db.get_setting( + "weixin_base_url", + "https://ilinkai.weixin.qq.com", + ) ?? "https://ilinkai.weixin.qq.com"; + } + if (env["AGENTFORGE_WEIXIN_ACCOUNT_ID"] === undefined) { + env["AGENTFORGE_WEIXIN_ACCOUNT_ID"] = + this.db.get_setting("weixin_account_id", "") ?? ""; + } + this._bridge_proc = _hooks.spawn_bridge(this.bridge_cmd, env); + } catch (exc) { + this._running = false; + this._bridge_proc = null; + if ((exc as NodeJS.ErrnoException)?.code === "ENOENT") { + const msg = + "Bun not found. Install Bun (https://bun.sh) to use the Weixin channel."; + console.log(`[Weixin] ${msg}`); + this._update_status({ login_status: "error", last_error: msg }); + return; + } + const msg = `Failed to start Weixin bridge: ${exc}`; + console.log(`[Weixin] ${msg}`); + this._update_status({ login_status: "error", last_error: msg }); + return; + } + + this._reader_promise = this._read_bridge_events().catch((exc) => { + console.log(`[Weixin] Bridge reader error: ${exc}`); + }); + console.log("[Weixin] Bridge started"); + } + + stop(): void { + this._running = false; + this.bus.unsubscribe_outbound(this._on_outbound); + if (this._bridge_proc && this._bridge_proc.poll() === null) { + try { + this._bridge_proc.terminate(); + void this._bridge_proc.wait(5); + } catch { + /* pass */ + } + } + this._bridge_proc = null; + } + + send(msg: OutboundMessage): void { + if (!this._running) { + return; + } + if ( + msg.type !== OutboundMessageType.TASK_COMPLETED && + msg.type !== OutboundMessageType.TASK_FAILED + ) { + return; + } + + const task_id = msg.task_id; + const origin = this._task_origin.get(task_id); + if (!origin) { + console.log( + `[Weixin] No origin for task #${task_id}, skipping outbound notification`, + ); + return; + } + + const title = + (msg.payload["title"] as string | null | undefined) || `Task #${task_id}`; + const task = this.db.get_task(task_id) ?? {}; + let text: string; + let image_paths: string[]; + if (msg.type === OutboundMessageType.TASK_COMPLETED) { + let body = + ((msg.payload["result"] as string | null | undefined) || "").trim() || + "Done."; + image_paths = this._collect_generated_image_paths(task_id, body, task); + if (image_paths.length > 0) { + body = this._hide_generated_image_paths( + body, + image_paths.length, + image_paths, + ); + } + text = `✅ Task #${task_id} · ${title}\n${body}`; + } else { + const body = ( + (msg.payload["error"] as string | null | undefined) || "Unknown error" + ).trim(); + image_paths = []; + text = `❌ Task #${task_id} · ${title}\n${body}`; + } + + const request_id = crypto.randomUUID().replaceAll("-", ""); // ≙ uuid.uuid4().hex + this._pending_notifications.set(request_id, task_id); + const command: Record = { + type: "send_message", + request_id, + account_id: origin["account_id"] ?? "", + peer_id: origin["peer_id"], + context_token: origin["context_token"] ?? "", + reply_to_message_id: origin["message_id"] ?? "", + text, + }; + if (image_paths.length > 0) { + command["image_paths"] = image_paths; + } + this._send_command(command); + + this._task_origin.delete(task_id); + } + + /** Arrow-function property so subscribe/unsubscribe get a stable bound ref. */ + _on_outbound = (msg: OutboundMessage): void => { + this.send(msg); + }; + + async _read_bridge_events(): Promise { + const proc = this._bridge_proc; + if (!proc || !proc.stdout) { + return; + } + + for await (const raw_line of proc.stdout) { + if (!this._running) { + return; + } + const line = raw_line.trim(); + if (!line) { + continue; + } + let event: Record; + try { + event = JSON.parse(line); + } catch { + console.log(`[Weixin] Ignoring non-JSON bridge output: ${line}`); + continue; + } + await this._handle_bridge_event(event); + } + } + + async _handle_bridge_event(event: Record): Promise { + const event_type = event["type"]; + if (event_type === "message") { + await this._handle_message_event(event); + } else if (event_type === "sent") { + this._handle_sent_event(event); + } else if (event_type === "qr") { + const qr_value = + ((event["qrcode_url"] as string | undefined) ?? "") || ""; + console.log( + `[Weixin] QR payload len=${qr_value.length} prefix=${JSON.stringify(qr_value.slice(0, 80))}`, + ); + this._update_status({ + login_status: "waiting_for_scan", + qr_code_url: qr_value, + account_id: (event["account_id"] as string | undefined) ?? "", + last_error: "", + }); + console.log("[Weixin] Bridge event: qr"); + } else if (event_type === "scaned") { + this._update_status({ login_status: "scanned", last_error: "" }); + console.log("[Weixin] Bridge event: scaned"); + } else if (event_type === "login_success") { + this._update_status({ + configured: true, + login_status: "connected", + qr_code_url: "", + account_id: (event["account_id"] as string | undefined) ?? "", + user_id: (event["user_id"] as string | undefined) ?? "", + last_error: "", + }); + console.log("[Weixin] Bridge event: login_success"); + } else if (event_type === "ready") { + this._update_status({ + configured: true, + login_status: "connected", + qr_code_url: "", + account_id: (event["account_id"] as string | undefined) ?? "", + last_error: "", + }); + console.log("[Weixin] Bridge event: ready"); + } else if (event_type === "logged_out") { + this._update_status({ + configured: false, + login_status: "idle", + qr_code_url: "", + last_error: "", + user_id: "", + }); + console.log("[Weixin] Bridge event: logged_out"); + } else if (event_type === "error") { + this._update_status({ + login_status: "error", + last_error: (event["message"] as string | undefined) ?? "unknown_error", + }); + console.log("[Weixin] Bridge event: error"); + } + } + + _handle_sent_event(event: Record): void { + const request_id = + ((event["request_id"] as string | undefined) || "") ?? ""; + const message_id = + ((event["message_id"] as string | undefined) || "") ?? ""; + const quoted_message_id = + ((event["quoted_message_id"] as string | undefined) || "") ?? ""; + if (!request_id || (!message_id && !quoted_message_id)) { + return; + } + const task_id = this._pending_notifications.get(request_id); + if (task_id === undefined) { + return; + } + if (message_id) { + this._notification_map.set(message_id, task_id); + } + if (quoted_message_id) { + this._notification_map.set(quoted_message_id, task_id); + } + if (quoted_message_id) { + this._pending_notifications.delete(request_id); + } + } + + async _handle_message_event(event: Record): Promise { + let text = ((event["text"] as string | null | undefined) || "").trim(); + const image_paths = this._extract_image_paths(event); + if (!text && image_paths.length === 0) { + return; + } + + const reply_to_message_id = + (event["reply_to_message_id"] as string | undefined) || ""; + const reply_to_message_title = + (event["reply_to_message_title"] as string | undefined) || ""; + const reply_to_message_text = + (event["reply_to_message_text"] as string | undefined) || ""; + const peer_id = + (event["peer_id"] as string | undefined) || + (event["from_user_id"] as string | undefined) || + ""; + const account_id = (event["account_id"] as string | undefined) || ""; + const context_token = (event["context_token"] as string | undefined) || ""; + const message_id = (event["message_id"] as string | undefined) || ""; + const peer_key = this._peer_key(account_id, peer_id); + + const new_match = text ? WEIXIN_NEW_SESSION_RE.exec(text) : null; + const force_new_session = Boolean(new_match); + if (new_match) { + text = (new_match[1] || "").trim(); + this._clear_peer_current_task(peer_key); + if (!text && image_paths.length === 0) { + this._reply_to_event( + event, + "🆕 已开启新的 Weixin session,请发送新的任务内容。", + ); + return; + } + } + + const dir_reply = _hooks.handle_dir_command(text, "weixin", this.db); + if (dir_reply !== null) { + this._reply_to_event(event, dir_reply); + return; + } + + const agent_reply = _hooks.handle_agent_command(text, "weixin", this.db); + if (agent_reply !== null) { + this._reply_to_event(event, agent_reply); + return; + } + + let task_id: number | null = null; + if (reply_to_message_id) { + task_id = this._notification_map.get(reply_to_message_id) ?? null; + } + + if (task_id === null) { + task_id = this._extract_task_id_from_reply_reference( + reply_to_message_title, + reply_to_message_text, + ); + } + + if (task_id === null && !force_new_session) { + task_id = this._get_peer_current_task(peer_key); + } + + if (task_id !== null && !force_new_session) { + const task = this.db.get_task(task_id); + if (task && task["session_id"]) { + const updates = this._build_resume_updates(text, image_paths); + this.db.update_task(task_id, updates); + this._task_origin.set(task_id, { + account_id, + peer_id, + context_token, + message_id, + }); + this._set_peer_current_task(peer_key, task_id); + this._reply_to_event( + event, + `▶️ 收到!正在唤醒 Task #${task_id},请稍候~`, + ); + return; + } + if ( + reply_to_message_id || + reply_to_message_title || + reply_to_message_text + ) { + this._reply_to_event( + event, + `❌ Task #${task_id} has no saved session to resume.`, + ); + return; + } + } + + const prompt = text || this._default_image_prompt(image_paths); + const prompt_images = this._build_prompt_images(image_paths); + const task = makeTask({ + title: `[Weixin] ${prompt.slice(0, 60)}${prompt.length > 60 ? "…" : ""}`, + prompt, + working_dir: await resolve_working_dir(prompt, "weixin", this.db), + schedule_type: ScheduleType.IMMEDIATE, + tags: "weixin", + image_paths, + prompt_images, + agent: resolve_agent("weixin", this.db), + }); + const new_task_id = this.scheduler.submit_task(task); + this._task_origin.set(new_task_id, { + account_id, + peer_id, + context_token, + message_id, + }); + this._set_peer_current_task(peer_key, new_task_id); + this._reply_to_event(event, `Task #${new_task_id} is running…`); + } + + _peer_key(account_id: string, peer_id: string): string { + return `${account_id}:${peer_id}`; + } + + _get_peer_current_task(peer_key: string): number | null { + return this._peer_current_task.get(peer_key) ?? null; + } + + _set_peer_current_task(peer_key: string, task_id: number): void { + if (!peer_key) { + return; + } + this._peer_current_task.set(peer_key, task_id); + } + + _clear_peer_current_task(peer_key: string): void { + this._peer_current_task.delete(peer_key); + } + + _default_image_prompt(image_paths: string[]): string { + if (image_paths.length === 1) { + return "请分析这张图片。"; + } + return `请分析这 ${image_paths.length} 张图片。`; + } + + _extract_image_paths(event: Record): string[] { + const paths: string[] = []; + const raw_paths = event["image_paths"]; + if (Array.isArray(raw_paths)) { + for (const p of raw_paths) { + if (p) paths.push(String(p)); + } + } + const raw_images = event["images"]; + if (Array.isArray(raw_images)) { + for (const image of raw_images) { + if (!_is_plain_object(image)) { + continue; + } + const p = image["path"] || image["local_path"]; + if (p) { + paths.push(String(p)); + } + } + } + return this._dedupe_image_paths(paths); + } + + _build_resume_updates( + prompt: string, + image_paths: string[], + ): Record { + const resume_prompt = prompt || this._default_image_prompt(image_paths); + const updates: Record = { + status: "pending", + prompt: resume_prompt, + result: null, + error: null, + question: null, + }; + if (image_paths.length > 0) { + updates["image_paths"] = JSON.stringify(image_paths); + updates["prompt_images"] = JSON.stringify( + this._build_prompt_images(image_paths), + ); + } + return updates; + } + + _build_prompt_images(image_paths: string[]): PromptImage[] { + const prompt_images: PromptImage[] = []; + for (const image_path of image_paths) { + let data: string; + try { + data = fs.readFileSync(image_path).toString("base64"); + } catch (exc) { + console.log( + `[Weixin] Failed to read inbound image ${image_path}: ${exc}`, + ); + continue; + } + prompt_images.push({ + name: path.basename(image_path), + media_type: this._image_media_type(image_path), + data, + }); + } + return prompt_images; + } + + _image_media_type(image_path: string): string { + const suffix = path.extname(image_path).toLowerCase(); + if (suffix === ".png") { + return "image/png"; + } + if (suffix === ".jpg" || suffix === ".jpeg") { + return "image/jpeg"; + } + if (suffix === ".gif") { + return "image/gif"; + } + if (suffix === ".webp") { + return "image/webp"; + } + let header: Buffer; + try { + const fd = fs.openSync(image_path, "r"); + try { + const buf = Buffer.alloc(12); + const read = fs.readSync(fd, buf, 0, 12, 0); + header = buf.subarray(0, read); + } finally { + fs.closeSync(fd); + } + } catch { + return "image/jpeg"; + } + if (header.subarray(0, 8).equals(PNG_HEADER)) { + return "image/png"; + } + if (header.subarray(0, 3).equals(JPEG_HEADER)) { + return "image/jpeg"; + } + const gif_magic = header.subarray(0, 6).toString("latin1"); + if (gif_magic === "GIF87a" || gif_magic === "GIF89a") { + return "image/gif"; + } + if ( + header.subarray(0, 4).toString("latin1") === "RIFF" && + header.includes("WEBP") + ) { + return "image/webp"; + } + return "image/jpeg"; + } + + _collect_generated_image_paths( + task_id: number, + content: string, + task: Record | null = null, + ): string[] { + const paths = this._generated_image_paths_for_task(task_id); + paths.push( + ...this._generated_image_paths_from_markdown( + content, + ((task ?? {})["working_dir"] as string | null | undefined) ?? null, + ), + ); + return this._dedupe_image_paths(paths); + } + + _generated_image_paths_for_task(task_id: number): string[] { + let runs: unknown; + try { + runs = this.db.get_task_runs(task_id, 1); + } catch (exc) { + console.log(`[Weixin] Failed to load runs for generated images: ${exc}`); + return []; + } + if (!Array.isArray(runs) || runs.length === 0) { + return []; + } + + const first: unknown = runs[0]; + const run_id = _is_plain_object(first) ? first["id"] : null; + if (!run_id) { + return []; + } + let events: unknown; + try { + events = this.db.get_run_output_events(run_id as number, 1000); + } catch (exc) { + console.log( + `[Weixin] Failed to load output events for generated images: ${exc}`, + ); + return []; + } + if (!Array.isArray(events)) { + return []; + } + + const paths: string[] = []; + for (const event of events) { + if ( + !_is_plain_object(event) || + event["event_type"] !== "generated_image" + ) { + continue; + } + let payload: unknown; + try { + payload = JSON.parse((event["content"] as string | undefined) || "{}"); + } catch { + continue; + } + const p = _is_plain_object(payload) ? payload["path"] : null; + if (p) { + paths.push(p as string); + } + } + return paths; + } + + _generated_image_paths_from_markdown( + content: string, + working_dir: string | null = null, + ): string[] { + const paths: string[] = []; + for (const match of (content || "").matchAll(WEIXIN_MARKDOWN_IMAGE_RE)) { + const image_path = this._local_image_path_from_reference( + match[1]!, + working_dir, + ); + if (image_path) { + paths.push(image_path); + } + } + return paths; + } + + _local_image_path_from_reference( + reference: string, + working_dir: string | null = null, + ): string | null { + let target = this._markdown_image_reference_target(reference); + if ( + !target || + target.startsWith("http://") || + target.startsWith("https://") || + target.startsWith("data:") + ) { + return null; + } + if (target.startsWith("file://")) { + target = _file_url_path(target); + } else if (target.startsWith("sandbox:")) { + target = target.slice("sandbox:".length); + } + target = _unquote(target).trim(); + if (!target) { + return null; + } + + let p = _expanduser(target); + if (!path.isAbsolute(p) && working_dir) { + p = path.join(_expanduser(working_dir), p); + } + return this._canonical_image_path(p); + } + + _markdown_image_reference_target(reference: string): string { + const raw = (reference || "").trim(); + if (!raw) { + return ""; + } + if (raw.startsWith("<")) { + const end = raw.indexOf(">"); + if (end >= 0) { + return raw.slice(1, end).trim(); + } + } + if (raw[0] === "'" || raw[0] === '"') { + const end = raw.indexOf(raw[0]!, 1); + if (end > 0) { + return raw.slice(1, end).trim(); + } + } + const titled = /^(.+?)\s+['"][^'"]*['"]\s*$/.exec(raw); + return (titled ? titled[1]! : raw).trim(); + } + + _dedupe_image_paths(image_paths: string[]): string[] { + const deduped: string[] = []; + const seen = new Set(); + for (const image_path of image_paths) { + const canonical = this._canonical_image_path(image_path); + if (!canonical || seen.has(canonical)) { + continue; + } + seen.add(canonical); + deduped.push(canonical); + } + return deduped; + } + + _canonical_image_path(image_path: string): string | null { + try { + const p = _expanduser(image_path); + if ( + !WEIXIN_UPLOADABLE_IMAGE_SUFFIXES.has(path.extname(p).toLowerCase()) + ) { + return null; + } + const stat = fs.statSync(p, { throwIfNoEntry: false }); + if (!stat || !stat.isFile()) { + return null; + } + return fs.realpathSync(path.resolve(p)); // ≙ Path.resolve() + } catch { + return null; + } + } + + _hide_generated_image_paths( + content: string, + image_count: number, + uploaded_paths: string[] | null = null, + ): string { + const uploaded = new Set(); + for (const p of uploaded_paths ?? []) { + const canonical = this._canonical_image_path(p); + if (canonical) { + uploaded.add(canonical); + } + } + const lines: string[] = []; + for (const line of (content || "").split(/\r\n|\r|\n/)) { + const stripped = line.trim(); + if (!stripped) { + lines.push(""); + continue; + } + if (this._line_is_uploaded_image_path(stripped, uploaded)) { + continue; + } + const cleaned_line = this._remove_uploaded_markdown_image_refs( + line, + uploaded, + ); + const visible = cleaned_line.trim(); + if (visible && visible !== "-" && visible !== "*" && visible !== "+") { + lines.push(cleaned_line.replace(/\s+$/, "")); // ≙ rstrip() + } + } + const cleaned = lines.join("\n").trim(); + if (!cleaned || cleaned.startsWith("已生成")) { + return `已生成 ${image_count} 张图片。`; + } + return cleaned; + } + + _line_is_uploaded_image_path( + stripped_line: string, + uploaded_paths: Set, + ): boolean { + if (!stripped_line.startsWith("- ")) { + return false; + } + const candidate = stripped_line.slice(2).trim(); + const canonical = this._canonical_image_path(candidate); + if (canonical && uploaded_paths.has(canonical)) { + return true; + } + return stripped_line.includes("/.codex/generated_images/"); + } + + _remove_uploaded_markdown_image_refs( + line: string, + uploaded_paths: Set, + ): string { + if (uploaded_paths.size === 0) { + return line; + } + + return line.replace(WEIXIN_MARKDOWN_IMAGE_RE, (match, ref: string) => { + const image_path = this._local_image_path_from_reference(ref); + const canonical = image_path + ? this._canonical_image_path(image_path) + : null; + return canonical !== null && uploaded_paths.has(canonical) ? "" : match; + }); + } + + _reply_to_event(event: Record, text: string): void { + const peer_id = + (event["peer_id"] as string | undefined) || + (event["from_user_id"] as string | undefined); + if (!peer_id) { + return; + } + this._send_command({ + type: "send_message", + account_id: (event["account_id"] as string | undefined) ?? "", + peer_id, + context_token: (event["context_token"] as string | undefined) ?? "", + reply_to_message_id: (event["message_id"] as string | undefined) ?? "", + text, + }); + } + + _extract_task_id_from_reply_reference(...parts: string[]): number | null { + for (const part of parts) { + if (!part) { + continue; + } + const match = /\bTask\s+#(\d+)\b/.exec(part); + if (match) { + return parseInt(match[1]!, 10); + } + } + return null; + } + + _send_command(payload: Record): void { + const proc_alive = Boolean( + this._bridge_proc && this._bridge_proc.poll() === null, + ); + const stdin_ok = Boolean(this._bridge_proc && this._bridge_proc.stdin); + console.log( + `[Weixin] _send_command: type=${payload["type"]} proc_alive=${proc_alive} stdin_ok=${stdin_ok}`, + ); + if (!this._bridge_proc || !this._bridge_proc.stdin) { + console.log( + "[Weixin] _send_command: bridge not running, command dropped", + ); + return; + } + this._bridge_proc.stdin.write(JSON.stringify(payload) + "\n"); + this._bridge_proc.stdin.flush?.(); + } + + request_login(): void { + console.log("[Weixin] request_login: called"); + this._update_status({ + configured: false, + login_status: "idle", + qr_code_url: "", + last_error: "", + user_id: "", + }); + this._send_command({ type: "login" }); + } + + request_logout(): void { + console.log("[Weixin] request_logout: called"); + this._update_status({ + configured: false, + login_status: "idle", + qr_code_url: "", + last_error: "", + user_id: "", + }); + this._send_command({ type: "logout" }); + } + + _update_status(updates: Partial): void { + for (const [k, v] of Object.entries(updates)) { + if (v !== null && v !== undefined) { + (this._status as unknown as Record)[k] = v; + } + } + } + + get_status_snapshot(): Record { + return { ...this._status }; + } +} diff --git a/backend/src/channels/weixin_bridge/index.ts b/backend/src/channels/weixin_bridge/index.ts index b76a815..785305d 100644 --- a/backend/src/channels/weixin_bridge/index.ts +++ b/backend/src/channels/weixin_bridge/index.ts @@ -134,7 +134,9 @@ function imageExtFromBuffer(buf: Buffer, fallback = ".jpg"): string { } function getImageMimeFromFilename(filePath: string): string { - return IMAGE_MIME_BY_EXT[path.extname(filePath).toLowerCase()] || "image/jpeg"; + return ( + IMAGE_MIME_BY_EXT[path.extname(filePath).toLowerCase()] || "image/jpeg" + ); } function encryptAesEcb(plaintext: Buffer, key: Buffer): Buffer { @@ -569,7 +571,9 @@ function extractReplyReference(itemList: any[] = []): { continue; } return { - messageId: ref?.message_item?.msg_id ? String(ref.message_item.msg_id) : "", + messageId: ref?.message_item?.msg_id + ? String(ref.message_item.msg_id) + : "", title: ref?.title ? String(ref.title) : "", text: ref?.message_item ? extractText([ref.message_item]) : "", }; @@ -763,7 +767,10 @@ async function sendMessageWithImages(command: BridgeCommand): Promise { await sendTextMessage(command); } for (const imagePath of imagePaths) { - const uploaded = await uploadImageToWeixin(imagePath, command.peer_id || ""); + const uploaded = await uploadImageToWeixin( + imagePath, + command.peer_id || "", + ); await sendMessageItem(command, buildImageItem(uploaded)); } } diff --git a/backend/src/channels/weixin_bridge/package.json b/backend/src/channels/weixin_bridge/package.json deleted file mode 100644 index 367e9f3..0000000 --- a/backend/src/channels/weixin_bridge/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "agentforge-weixin-bridge", - "private": true, - "type": "module", - "version": "0.1.0", - "description": "Node sidecar bridge for AgentForge Weixin channel" -} diff --git a/backend/src/executor.ts b/backend/src/executor.ts index 97aa97d..db896bc 100644 --- a/backend/src/executor.ts +++ b/backend/src/executor.ts @@ -60,7 +60,10 @@ export interface SubprocessRunOptions { env: Record; } -export type SubprocessRunFn = (cmd: string[], opts: SubprocessRunOptions) => SubprocessRunResult; +export type SubprocessRunFn = ( + cmd: string[], + opts: SubprocessRunOptions, +) => SubprocessRunResult; /** Real implementation backed by child_process.spawnSync. */ export function default_subprocess_run( @@ -127,7 +130,10 @@ export interface PopenOptions { * ≙ subprocess.Popen — may throw (or reject with) FileNotFoundError / OSError. * Test fakes are usually synchronous; callers `await` the result either way. */ -export type PopenFn = (cmd: string[], opts: PopenOptions) => PopenLike | Promise; +export type PopenFn = ( + cmd: string[], + opts: PopenOptions, +) => PopenLike | Promise; /** Split a Readable into lines, keeping the trailing "\n" like Python file iteration. */ async function* lineIterable(stream: Readable): AsyncGenerator { @@ -187,7 +193,10 @@ export const default_popen: PopenFn = (cmd, opts) => { wrapper.wait = (timeout: number | null = null): Promise => { if (timeout === null || timeout === undefined) return exited; return new Promise((res, rej) => { - const timer = setTimeout(() => rej(new TimeoutExpired(cmd, timeout)), timeout * 1000); + const timer = setTimeout( + () => rej(new TimeoutExpired(cmd, timeout)), + timeout * 1000, + ); exited.then((code) => { clearTimeout(timer); res(code); diff --git a/backend/src/scheduler.ts b/backend/src/scheduler.ts index e2183bc..7e9e923 100644 --- a/backend/src/scheduler.ts +++ b/backend/src/scheduler.ts @@ -10,7 +10,11 @@ import fs from "node:fs"; import os from "node:os"; import path from "node:path"; import { CronExpressionParser } from "cron-parser"; -import { BusAwareSchedulerMixin, OutboundMessageType, type MessageBus } from "./bus.ts"; +import { + BusAwareSchedulerMixin, + OutboundMessageType, + type MessageBus, +} from "./bus.ts"; import type { TaskDB } from "./db.ts"; import { AgentExecutor, @@ -24,7 +28,11 @@ import { type PopenLike, } from "./executor.ts"; import { logger } from "./log.ts"; -import { _skill_creator_dir, _sanitize_skill_name, _compose_skill_md } from "./skills.ts"; +import { + _skill_creator_dir, + _sanitize_skill_name, + _compose_skill_md, +} from "./skills.ts"; import { _parse_skill_frontmatter, expanduser, @@ -68,7 +76,10 @@ function sleepSeconds(seconds: number): Promise { } /** Await a promise but give up after `seconds` (≙ Thread.join(timeout=...)). */ -async function joinWithTimeout(p: Promise, seconds: number): Promise { +async function joinWithTimeout( + p: Promise, + seconds: number, +): Promise { let timer: ReturnType | undefined; const timeout = new Promise((resolve) => { timer = setTimeout(resolve, seconds * 1000); @@ -92,7 +103,9 @@ function croniter_is_valid(expr: string): boolean { /** ≙ croniter(expr, base).get_next(datetime).isoformat() (local-naive storage) */ function cron_next_iso(expr: string, base: Date): string { - return dateToLocalIso(CronExpressionParser.parse(expr, { currentDate: base }).next().toDate()); + return dateToLocalIso( + CronExpressionParser.parse(expr, { currentDate: base }).next().toDate(), + ); } /** ≙ the Python dict key tuple (run_id, item_id) for codex/claude delta state. */ @@ -230,7 +243,9 @@ export class TaskScheduler extends BusAwareSchedulerMixin { } // Wait up to 5 seconds for running tasks to finish let deadline = Date.now() / 1000 + 5; - const running = [...this._active_tasks.entries()].filter(([, t]) => t.is_alive()); + const running = [...this._active_tasks.entries()].filter(([, t]) => + t.is_alive(), + ); if (running.length) { logger.info(`Waiting for ${running.length} running task(s) to finish...`); for (const [, t] of running) { @@ -238,11 +253,13 @@ export class TaskScheduler extends BusAwareSchedulerMixin { if (t.promise) await joinWithTimeout(t.promise, remaining); } } - const heartbeat_running = [...this._active_heartbeats.entries()].filter(([, t]) => - t.is_alive(), + const heartbeat_running = [...this._active_heartbeats.entries()].filter( + ([, t]) => t.is_alive(), ); if (heartbeat_running.length) { - logger.info(`Waiting for ${heartbeat_running.length} heartbeat(s) to finish...`); + logger.info( + `Waiting for ${heartbeat_running.length} heartbeat(s) to finish...`, + ); for (const [, t] of heartbeat_running) { const remaining = Math.max(0, deadline - Date.now() / 1000); if (t.promise) await joinWithTimeout(t.promise, remaining); @@ -274,7 +291,9 @@ export class TaskScheduler extends BusAwareSchedulerMixin { } if (!gone) { // Still alive — escalate to SIGKILL - logger.warning(`Force-killing task ${tid} (pgid ${pgid}) after SIGTERM timeout`); + logger.warning( + `Force-killing task ${tid} (pgid ${pgid}) after SIGTERM timeout`, + ); try { this._os.killpg(pgid, "SIGKILL"); } catch (e) { @@ -308,23 +327,38 @@ export class TaskScheduler extends BusAwareSchedulerMixin { continue; // already running } // Check if it's time - if (task["schedule_type"] === "immediate" && task["status"] === "pending") { + if ( + task["schedule_type"] === "immediate" && + task["status"] === "pending" + ) { this._spawn_task(task); - } else if (task["schedule_type"] === "delayed" && task["status"] === "pending") { + } else if ( + task["schedule_type"] === "delayed" && + task["status"] === "pending" + ) { this._schedule_delayed(task); - } else if (task["schedule_type"] === "delayed" && task["status"] === "scheduled") { + } else if ( + task["schedule_type"] === "delayed" && + task["status"] === "scheduled" + ) { const nra = task["next_run_at"]; const run_at = nra ? parseComparableDatetime(nra) : null; if (run_at && run_at.getTime() <= Date.now()) { this._spawn_task(task); } - } else if (task["schedule_type"] === "scheduled_at" && task["status"] === "scheduled") { + } else if ( + task["schedule_type"] === "scheduled_at" && + task["status"] === "scheduled" + ) { const nra = task["next_run_at"]; const run_at = nra ? parseComparableDatetime(nra) : null; if (run_at && run_at.getTime() <= Date.now()) { this._spawn_task(task); } - } else if (task["schedule_type"] === "cron" && task["status"] === "scheduled") { + } else if ( + task["schedule_type"] === "cron" && + task["status"] === "scheduled" + ) { const nra = task["next_run_at"]; const run_at = nra ? parseComparableDatetime(nra) : null; if (run_at && run_at.getTime() <= Date.now()) { @@ -352,7 +386,11 @@ export class TaskScheduler extends BusAwareSchedulerMixin { * entirely. When disabled, returns immediately — never calls an agent. */ _maybe_run_scheduled_sweep(): void { - if (!["1", "true", "True"].includes(this.db.get_setting("skill_library_enabled", "0") ?? "")) { + if ( + !["1", "true", "True"].includes( + this.db.get_setting("skill_library_enabled", "0") ?? "", + ) + ) { return; } const cron = this.db.get_setting("skill_sweep_cron", "0 3 * * *"); @@ -381,7 +419,10 @@ export class TaskScheduler extends BusAwareSchedulerMixin { _schedule_delayed(task: Row): void { const delay = task["delay_seconds"] || 0; const run_at = new Date(Date.now() + delay * 1000); - this.db.update_task(task["id"], { status: "scheduled", next_run_at: dateToLocalIso(run_at) }); + this.db.update_task(task["id"], { + status: "scheduled", + next_run_at: dateToLocalIso(run_at), + }); this._notify(task["id"]); } @@ -465,7 +506,9 @@ export class TaskScheduler extends BusAwareSchedulerMixin { } const payload = JSON.parse(text) as Row; const decision = payload["decision"]; - if (!(Object.values(HeartbeatDecisionType) as string[]).includes(decision)) { + if ( + !(Object.values(HeartbeatDecisionType) as string[]).includes(decision) + ) { throw new Error(`Invalid heartbeat decision: ${decision}`); } const normalized: Row = { @@ -496,7 +539,10 @@ export class TaskScheduler extends BusAwareSchedulerMixin { * the watermark, so the button always analyzes something. Counting is * idempotent per run_id, so re-scanning never inflates recurrence counts. */ - async run_skill_sweep(agent: string | null = null, full: boolean = false): Promise { + async run_skill_sweep( + agent: string | null = null, + full: boolean = false, + ): Promise { agent = agent || this.db.get_setting("skill_sweep_agent", null) || @@ -506,7 +552,10 @@ export class TaskScheduler extends BusAwareSchedulerMixin { if (full) { runs = this.db.get_recent_completed_runs(this.SKILL_SWEEP_RUN_LIMIT); } else { - runs = this.db.get_completed_runs_since(watermark, this.SKILL_SWEEP_RUN_LIMIT); + runs = this.db.get_completed_runs_since( + watermark, + this.SKILL_SWEEP_RUN_LIMIT, + ); } if (!runs.length) { const result: Row = { @@ -538,7 +587,9 @@ export class TaskScheduler extends BusAwareSchedulerMixin { const it = item as Row; const tid = _int(it["task_id"]); const rid = _int(it["run_id"]); - const before = this.db.get_skill_pattern_recurrence(it["pattern_key"] ?? ""); + const before = this.db.get_skill_pattern_recurrence( + it["pattern_key"] ?? "", + ); const pid = this.db.upsert_skill_pattern( it["pattern_key"] ?? "", it["kind"] ?? "recipe", @@ -548,15 +599,21 @@ export class TaskScheduler extends BusAwareSchedulerMixin { ); if (pid !== null) { detected += 1; - const after = this.db.get_skill_pattern_recurrence(it["pattern_key"] ?? ""); + const after = this.db.get_skill_pattern_recurrence( + it["pattern_key"] ?? "", + ); if (after > before) { new_occurrences += 1; } } } - const finished = runs.map((r) => r["finished_at"]).filter(Boolean) as string[]; - const new_watermark = finished.length ? finished.reduce((a, b) => (a > b ? a : b)) : watermark; + const finished = runs + .map((r) => r["finished_at"]) + .filter(Boolean) as string[]; + const new_watermark = finished.length + ? finished.reduce((a, b) => (a > b ? a : b)) + : watermark; if (new_watermark && new_watermark > watermark) { this.db.set_setting("skill_sweep_watermark", new_watermark); } @@ -580,7 +637,10 @@ export class TaskScheduler extends BusAwareSchedulerMixin { * The HTTP server is single-threaded, so a sweep (which can take minutes) * must not block the request thread. */ - trigger_skill_sweep(agent: string | null = null, full: boolean = false): boolean { + trigger_skill_sweep( + agent: string | null = null, + full: boolean = false, + ): boolean { if (this._skill_sweep_running) { return false; } @@ -680,7 +740,10 @@ export class TaskScheduler extends BusAwareSchedulerMixin { } /** Synchronous distill core (tested directly). Saves a 'ready' draft. */ - async distill_skill_draft(pattern_id: number, agent: string | null = null): Promise { + async distill_skill_draft( + pattern_id: number, + agent: string | null = null, + ): Promise { const pattern = this.db.get_skill_pattern(pattern_id); if (!pattern) { throw new Error("pattern not found"); @@ -703,7 +766,9 @@ export class TaskScheduler extends BusAwareSchedulerMixin { // *using* skill-creator (not just "in its style"). const creator_src = _skill_creator_dir(); let creator_rel: string | null = null; - const workdir = fs.mkdtempSync(path.join(os.tmpdir(), "agentforge-distill-")); + const workdir = fs.mkdtempSync( + path.join(os.tmpdir(), "agentforge-distill-"), + ); let ok: boolean; let raw: string; try { @@ -716,7 +781,10 @@ export class TaskScheduler extends BusAwareSchedulerMixin { if (hasCreatorMd) { const dest = path.join(workdir, ".claude", "skills", "skill-creator"); fs.mkdirSync(dest, { recursive: true }); - fs.copyFileSync(path.join(creator_src, "SKILL.md"), path.join(dest, "SKILL.md")); + fs.copyFileSync( + path.join(creator_src, "SKILL.md"), + path.join(dest, "SKILL.md"), + ); creator_rel = ".claude/skills/skill-creator/SKILL.md"; } const prompt = this._build_distill_prompt(pattern, context, creator_rel); @@ -728,7 +796,9 @@ export class TaskScheduler extends BusAwareSchedulerMixin { throw new Error(raw || "distill agent failed"); } const obj = parseJsonObject(raw); - const name = _sanitize_skill_name((obj["name"] as string) || pattern["pattern_key"]); + const name = _sanitize_skill_name( + (obj["name"] as string) || pattern["pattern_key"], + ); const description = String(obj["description"] ?? "").trim(); const body_md = String(obj["body_markdown"] || obj["body"] || "").trim(); const worthy_raw = obj["worthy"]; @@ -758,7 +828,10 @@ export class TaskScheduler extends BusAwareSchedulerMixin { } /** Start distillation in the background (single-threaded server). */ - trigger_skill_draft(pattern_id: number, agent: string | null = null): boolean { + trigger_skill_draft( + pattern_id: number, + agent: string | null = null, + ): boolean { const pattern = this.db.get_skill_pattern(pattern_id); if (!pattern) { return false; @@ -771,14 +844,27 @@ export class TaskScheduler extends BusAwareSchedulerMixin { } catch (e) { // surface to draft row, never crash logger.error(`Skill distill failed: ${errStr(e)}`); - this.db.upsert_skill_draft(pattern_id, "error", "", "", pattern["kind"], "", errStr(e)); + this.db.upsert_skill_draft( + pattern_id, + "error", + "", + "", + pattern["kind"], + "", + errStr(e), + ); } })(); return true; } /** Write the approved SKILL.md, symlink it for both agents, register it. */ - approve_skill(pattern_id: number, name: string, description: string, body: string): Row | null { + approve_skill( + pattern_id: number, + name: string, + description: string, + body: string, + ): Row | null { const pattern = this.db.get_skill_pattern(pattern_id); if (!pattern) { throw new Error("pattern not found"); @@ -1000,8 +1086,16 @@ export class TaskScheduler extends BusAwareSchedulerMixin { } }; - const stdout_promise = _read_stream(proc.stdout, stdout_chunks, on_stdout_line).catch(() => {}); - const stderr_promise = _read_stream(proc.stderr, stderr_chunks, on_stderr_line).catch(() => {}); + const stdout_promise = _read_stream( + proc.stdout, + stdout_chunks, + on_stdout_line, + ).catch(() => {}); + const stderr_promise = _read_stream( + proc.stderr, + stderr_chunks, + on_stderr_line, + ).catch(() => {}); try { await proc.wait(timeout_secs); } catch (e) { @@ -1023,7 +1117,10 @@ export class TaskScheduler extends BusAwareSchedulerMixin { const raw_stdout = stdout_chunks.join(""); const raw_stderr = stderr_chunks.join(""); if (proc.returncode !== 0) { - return [false, raw_stderr || raw_stdout || `${agent} heartbeat decision failed`]; + return [ + false, + raw_stderr || raw_stdout || `${agent} heartbeat decision failed`, + ]; } if (agent === "codex") { @@ -1037,7 +1134,10 @@ export class TaskScheduler extends BusAwareSchedulerMixin { } catch { continue; } - if (event?.type === "item.completed" && event?.item?.type === "agent_message") { + if ( + event?.type === "item.completed" && + event?.item?.type === "agent_message" + ) { out = event.item.text ?? ""; } } @@ -1092,7 +1192,11 @@ export class TaskScheduler extends BusAwareSchedulerMixin { if (triggered_at) { try { const triggered_dt = parseComparableDatetime(triggered_at); - if (triggered_dt && cooldown > 0 && Date.now() < triggered_dt.getTime() + cooldown * 1000) { + if ( + triggered_dt && + cooldown > 0 && + Date.now() < triggered_dt.getTime() + cooldown * 1000 + ) { return true; } } catch { @@ -1102,7 +1206,10 @@ export class TaskScheduler extends BusAwareSchedulerMixin { const existing_task_id = existing["task_id"]; if (existing_task_id) { const task = this.db.get_task(existing_task_id); - if (task && ["pending", "scheduled", "blocked", "running"].includes(task["status"])) { + if ( + task && + ["pending", "scheduled", "blocked", "running"].includes(task["status"]) + ) { return true; } } @@ -1127,7 +1234,9 @@ export class TaskScheduler extends BusAwareSchedulerMixin { check_prompt: heartbeat["check_prompt"], action_prompt_template: heartbeat["action_prompt_template"] || "", default_agent: heartbeat["default_agent"] || DEFAULT_AGENT, - cooldown_seconds: Math.trunc(Number(heartbeat["cooldown_seconds"] || 0)), + cooldown_seconds: Math.trunc( + Number(heartbeat["cooldown_seconds"] || 0), + ), }), now, ); @@ -1185,8 +1294,11 @@ export class TaskScheduler extends BusAwareSchedulerMixin { "Suppressed duplicate signal during cooldown or while prior task is still active"; } else { const task_prompt = - decision["prompt"] || heartbeat["action_prompt_template"] || heartbeat["check_prompt"]; - const task_title = decision["title"] || `Heartbeat: ${heartbeat["name"]}`; + decision["prompt"] || + heartbeat["action_prompt_template"] || + heartbeat["check_prompt"]; + const task_title = + decision["title"] || `Heartbeat: ${heartbeat["name"]}`; const task = { title: task_title, prompt: task_prompt, @@ -1213,7 +1325,9 @@ export class TaskScheduler extends BusAwareSchedulerMixin { decision_type, decision, task_id, - output_chunks.length ? output_chunks.join("").slice(0, 500000) : null, + output_chunks.length + ? output_chunks.join("").slice(0, 500000) + : null, ); return; } @@ -1223,7 +1337,8 @@ export class TaskScheduler extends BusAwareSchedulerMixin { last_tick_at: dateToLocalIso(now), last_decision: decision_type, last_error: null, - last_dedupe_key: (decision["dedupe_key"] || heartbeat["last_dedupe_key"]) ?? null, + last_dedupe_key: + (decision["dedupe_key"] || heartbeat["last_dedupe_key"]) ?? null, }); this.db.finish_heartbeat_tick( tick_id, @@ -1257,7 +1372,11 @@ export class TaskScheduler extends BusAwareSchedulerMixin { } /** Return only the newly emitted text for a cumulative Codex message item. */ - _codex_text_delta(run_id: number | null, item_id: string, current_text: string): string | null { + _codex_text_delta( + run_id: number | null, + item_id: string, + current_text: string, + ): string | null { const key = tupleKey(run_id, item_id); const previous = this._codex_item_text.get(key) ?? ""; this._codex_item_text.set(key, current_text); @@ -1274,12 +1393,19 @@ export class TaskScheduler extends BusAwareSchedulerMixin { return current_text; } - _codex_append_text_delta(run_id: number | null, item_id: string, delta: string): string | null { + _codex_append_text_delta( + run_id: number | null, + item_id: string, + delta: string, + ): string | null { if (delta === "") { return null; } const key = tupleKey(run_id, item_id); - this._codex_item_text.set(key, (this._codex_item_text.get(key) ?? "") + delta); + this._codex_item_text.set( + key, + (this._codex_item_text.get(key) ?? "") + delta, + ); return delta; } @@ -1322,7 +1448,8 @@ export class TaskScheduler extends BusAwareSchedulerMixin { _codex_generated_images_root(): string { const codex_home = - process.env.CODEX_HOME || path.join(process.env.HOME || os.homedir(), ".codex"); + process.env.CODEX_HOME || + path.join(process.env.HOME || os.homedir(), ".codex"); return path.join(expanduser(codex_home), "generated_images"); } @@ -1346,9 +1473,9 @@ export class TaskScheduler extends BusAwareSchedulerMixin { const paths: string[] = []; let entries: string[]; try { - entries = (fs.readdirSync(image_dir, { recursive: true }) as Array).map( - (e) => String(e), - ); + entries = ( + fs.readdirSync(image_dir, { recursive: true }) as Array + ).map((e) => String(e)); } catch { return []; } @@ -1377,7 +1504,10 @@ export class TaskScheduler extends BusAwareSchedulerMixin { } _image_media_type(image_path: string): string { - return GENERATED_IMAGE_MEDIA_TYPES[path.extname(image_path).toLowerCase()] ?? "image/png"; + return ( + GENERATED_IMAGE_MEDIA_TYPES[path.extname(image_path).toLowerCase()] ?? + "image/png" + ); } _extract_codex_success_output( @@ -1394,7 +1524,10 @@ export class TaskScheduler extends BusAwareSchedulerMixin { } catch { continue; } - if (event?.type === "item.completed" && event?.item?.type === "agent_message") { + if ( + event?.type === "item.completed" && + event?.item?.type === "agent_message" + ) { out = event.item.text ?? ""; } } @@ -1410,16 +1543,27 @@ export class TaskScheduler extends BusAwareSchedulerMixin { return parts.join("\n\n"); } - _store_generated_image_events(task_id: number, run_id: number, generated_images: string[]): void { + _store_generated_image_events( + task_id: number, + run_id: number, + generated_images: string[], + ): void { for (const image_path of generated_images) { const media_type = this._image_media_type(image_path); const metadata = { path: image_path, media_type }; - this._store_output_event(task_id, run_id, "generated_image", this._trace_json(metadata)); + this._store_output_event( + task_id, + run_id, + "generated_image", + this._trace_json(metadata), + ); let image_data: string; try { image_data = fs.readFileSync(image_path).toString("base64"); } catch (e) { - logger.warning(`Task ${task_id}: failed to read generated image ${image_path}: ${errStr(e)}`); + logger.warning( + `Task ${task_id}: failed to read generated image ${image_path}: ${errStr(e)}`, + ); continue; } this.db.add_output_event( @@ -1491,7 +1635,9 @@ export class TaskScheduler extends BusAwareSchedulerMixin { const redacted: Row = {}; for (const [key, child] of Object.entries(value)) { const key_str = String(key).toLowerCase(); - if (SECRET_KEY_FRAGMENTS.some((fragment) => key_str.includes(fragment))) { + if ( + SECRET_KEY_FRAGMENTS.some((fragment) => key_str.includes(fragment)) + ) { redacted[key] = "[redacted]"; } else { redacted[key] = this._redact_display_payload(child); @@ -1551,7 +1697,12 @@ export class TaskScheduler extends BusAwareSchedulerMixin { return LIVE_OUTPUT_EVENT_TYPES.has(event_type); } - _store_output_event(task_id: number, run_id: number, event_type: string, content: string): void { + _store_output_event( + task_id: number, + run_id: number, + event_type: string, + content: string, + ): void { if (!content) { return; } @@ -1566,13 +1717,18 @@ export class TaskScheduler extends BusAwareSchedulerMixin { * * Returns (null, null) to skip events that carry no displayable content. */ - _parse_codex_event(event: Row, run_id: number | null = null): [string | null, string | null] { + _parse_codex_event( + event: Row, + run_id: number | null = null, + ): [string | null, string | null] { const etype: string = event["type"] ?? ""; if (etype === "item.updated" || etype === "item.completed") { const item: Row = event["item"] ?? {}; const itype: string = item["type"] ?? ""; if (itype === "agent_message") { - const item_id = String(item["id"] || item["item_id"] || "agent_message"); + const item_id = String( + item["id"] || item["item_id"] || "agent_message", + ); const event_delta = this._codex_event_delta_text(event, item); let delta: string | null; if (etype === "item.updated" && event_delta !== null) { @@ -1586,9 +1742,11 @@ export class TaskScheduler extends BusAwareSchedulerMixin { const event_delta = this._codex_event_delta_text(event, item); let text: string; if (etype === "item.updated" && event_delta !== null) { - text = this._codex_append_text_delta(run_id, item_id, event_delta) || ""; + text = + this._codex_append_text_delta(run_id, item_id, event_delta) || ""; } else { - text = this._codex_text_delta(run_id, item_id, item["text"] ?? "") || ""; + text = + this._codex_text_delta(run_id, item_id, item["text"] ?? "") || ""; } return text ? ["assistant", `[thinking] ${text}`] : [null, null]; } else if (itype === "command_execution") { @@ -1657,7 +1815,11 @@ export class TaskScheduler extends BusAwareSchedulerMixin { } else if (etype === "turn.completed") { // turn.completed only carries usage stats; final text comes from agent_message items return [null, null]; - } else if (etype === "thread.started" || etype === "turn.started" || etype === "item.started") { + } else if ( + etype === "thread.started" || + etype === "turn.started" || + etype === "item.started" + ) { return [null, null]; } else { return [etype, JSON.stringify(event)]; @@ -1665,7 +1827,12 @@ export class TaskScheduler extends BusAwareSchedulerMixin { } /** Parse a line from the output stream and store it as an event. */ - _parse_and_store_event(task_id: number, run_id: number, line: string, agent: string = "claude") { + _parse_and_store_event( + task_id: number, + run_id: number, + line: string, + agent: string = "claude", + ) { if (!line.trim()) { return; } @@ -1693,11 +1860,16 @@ export class TaskScheduler extends BusAwareSchedulerMixin { // Claude stream-json const event_type: string = event?.type ?? "unknown"; if (event_type === "assistant") { - const [text0, image_events, trace_events] = this._extract_message_content(event); + const [text0, image_events, trace_events] = + this._extract_message_content(event); let text_content: string | null = text0; if (text_content) { const message_id = this._claude_message_id(event, run_id); - text_content = this._claude_text_delta(run_id, message_id, text_content); + text_content = this._claude_text_delta( + run_id, + message_id, + text_content, + ); } if (text_content) { this._store_output_event(task_id, run_id, event_type, text_content); @@ -1709,7 +1881,8 @@ export class TaskScheduler extends BusAwareSchedulerMixin { this._store_output_event(task_id, run_id, trace_type, trace_content); } } else if (event_type === "user") { - const [text_content, image_events, trace_events] = this._extract_message_content(event); + const [text_content, image_events, trace_events] = + this._extract_message_content(event); if (text_content) { this.db.add_output_event(task_id, run_id, event_type, text_content); } @@ -1742,7 +1915,9 @@ export class TaskScheduler extends BusAwareSchedulerMixin { * Returns (text, image_events, trace_events), where image_events and * trace_events contain already serialized display payloads. */ - _extract_message_content(event: Row): [string, string[], Array<[string, string]>] { + _extract_message_content( + event: Row, + ): [string, string[], Array<[string, string]>] { const message = event["message"] ?? {}; const content = message["content"] ?? []; const text_parts: string[] = []; @@ -1892,7 +2067,10 @@ export class TaskScheduler extends BusAwareSchedulerMixin { for (const root of _ALLOWED_IMAGE_ROOTS) { try { const resolved_root = realpathNonStrict(root); - if (resolved.startsWith(resolved_root + path.sep) || resolved === resolved_root) { + if ( + resolved.startsWith(resolved_root + path.sep) || + resolved === resolved_root + ) { return true; } } catch { @@ -1918,7 +2096,10 @@ export class TaskScheduler extends BusAwareSchedulerMixin { let media_type: string; if (img_path_lower.endsWith(".png")) { media_type = "image/png"; - } else if (img_path_lower.endsWith(".jpg") || img_path_lower.endsWith(".jpeg")) { + } else if ( + img_path_lower.endsWith(".jpg") || + img_path_lower.endsWith(".jpeg") + ) { media_type = "image/jpeg"; } else if (img_path_lower.endsWith(".gif")) { media_type = "image/gif"; @@ -1927,11 +2108,20 @@ export class TaskScheduler extends BusAwareSchedulerMixin { } else { // Try to detect from magic bytes const header = buf.subarray(0, 12); - if (header.length >= 3 && header[0] === 0xff && header[1] === 0xd8 && header[2] === 0xff) { + if ( + header.length >= 3 && + header[0] === 0xff && + header[1] === 0xd8 && + header[2] === 0xff + ) { media_type = "image/jpeg"; } else if ( header.length >= 8 && - header.subarray(0, 8).equals(Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])) + header + .subarray(0, 8) + .equals( + Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]), + ) ) { media_type = "image/png"; } else if ( @@ -1958,7 +2148,9 @@ export class TaskScheduler extends BusAwareSchedulerMixin { `Task ${tid}: Loaded image ${img_path} as ${media_type} (${img_data.length} bytes base64)`, ); } catch (e) { - logger.error(`Task ${tid}: Failed to load image ${img_path}: ${errStr(e)}`); + logger.error( + `Task ${tid}: Failed to load image ${img_path}: ${errStr(e)}`, + ); } } } @@ -1997,7 +2189,13 @@ export class TaskScheduler extends BusAwareSchedulerMixin { } } else if (use_stdin) { // Claude multimodal input: pass via stdin with --input-format stream-json - cmd = ["claude", "-p", "--input-format", "stream-json", ...CLAUDE_STREAM_JSON_ARGS]; + cmd = [ + "claude", + "-p", + "--input-format", + "stream-json", + ...CLAUDE_STREAM_JSON_ARGS, + ]; } else { cmd = ["claude", "-p", prompt, ...CLAUDE_STREAM_JSON_ARGS]; } @@ -2069,7 +2267,9 @@ export class TaskScheduler extends BusAwareSchedulerMixin { try { this._os.kill(proc.pid, "SIGKILL"); } catch (e2) { - logger.error(`Task ${tid}: kill(${proc.pid}) also failed: ${errStr(e2)}`); + logger.error( + `Task ${tid}: kill(${proc.pid}) also failed: ${errStr(e2)}`, + ); } } }; @@ -2110,7 +2310,9 @@ export class TaskScheduler extends BusAwareSchedulerMixin { } if (!waiting_logged) { waiting_logged = true; - logger.info(`Task ${tid}: main process exited, waiting for sub-agents...`); + logger.info( + `Task ${tid}: main process exited, waiting for sub-agents...`, + ); } this._live_output.set( tid, @@ -2124,7 +2326,9 @@ export class TaskScheduler extends BusAwareSchedulerMixin { try { this._os.killpg(pgid, "SIGKILL"); } catch (e) { - logger.error(`Task ${tid}: killpg(${pgid}) on sub-agent timeout failed: ${errStr(e)}`); + logger.error( + `Task ${tid}: killpg(${pgid}) on sub-agent timeout failed: ${errStr(e)}`, + ); } } } @@ -2140,12 +2344,18 @@ export class TaskScheduler extends BusAwareSchedulerMixin { } else if (proc.returncode === 0) { if (agent === "codex") { const thread_id = this._extract_codex_thread_id(raw_stdout); - const generated_images = this._find_codex_generated_images(thread_id, start_time); + const generated_images = this._find_codex_generated_images( + thread_id, + start_time, + ); if (generated_images.length) { this._store_generated_image_events(tid, run_id, generated_images); } success = true; - output = this._extract_codex_success_output(raw_stdout, generated_images); + output = this._extract_codex_success_output( + raw_stdout, + generated_images, + ); } else { // Claude stream-json: find the last result event and last assistant text let out = ""; @@ -2195,7 +2405,9 @@ export class TaskScheduler extends BusAwareSchedulerMixin { if (e instanceof FileNotFoundError) { const cli_name = task["agent"] === "codex" ? "codex" : "claude"; const install_hint = - cli_name === "codex" ? "Install with: npm install -g @openai/codex" : "Is it installed?"; + cli_name === "codex" + ? "Install with: npm install -g @openai/codex" + : "Is it installed?"; success = false; output = `${cli_name} CLI not found. ${install_hint}`; this._active_pgids.delete(tid); @@ -2530,7 +2742,9 @@ export class TaskScheduler extends BusAwareSchedulerMixin { status: "cancelled", error: `Cancelled: upstream task #${origin_id} failed`, }); - logger.info(`DAG: Task ${downstream_id} cascade-cancelled (upstream #${origin_id} failed)`); + logger.info( + `DAG: Task ${downstream_id} cascade-cancelled (upstream #${origin_id} failed)`, + ); this._notify(downstream_id); } } @@ -2593,7 +2807,9 @@ export class TaskScheduler extends BusAwareSchedulerMixin { check_prompt: heartbeat["check_prompt"], action_prompt_template: heartbeat["action_prompt_template"] || "", default_agent: heartbeat["default_agent"] || DEFAULT_AGENT, - cooldown_seconds: Math.trunc(Number(heartbeat["cooldown_seconds"] || 0)), + cooldown_seconds: Math.trunc( + Number(heartbeat["cooldown_seconds"] || 0), + ), }), new Date(), ); diff --git a/backend/src/server.ts b/backend/src/server.ts new file mode 100644 index 0000000..fc27293 --- /dev/null +++ b/backend/src/server.ts @@ -0,0 +1,196 @@ +import net from "node:net"; + +import { MessageBus, UIChannel } from "./bus.ts"; +import { TaskDB } from "./db.ts"; +import { logger } from "./log.ts"; +import { TaskScheduler } from "./scheduler.ts"; +import { handleApiRequest, type ApiContext } from "./api.ts"; +import { FeishuChannel } from "./channels/feishu.ts"; +import { SlackChannel } from "./channels/slack.ts"; +import { create_telegram_channel } from "./channels/telegram.ts"; +import { WeixinChannel } from "./channels/weixin.ts"; + +function portIsOpen(port: number): Promise { + return new Promise((resolve) => { + const socket = net.createConnection({ host: "127.0.0.1", port }); + socket.setTimeout(1000); + socket.once("connect", () => { + socket.destroy(); + resolve(true); + }); + socket.once("error", () => resolve(false)); + socket.once("timeout", () => { + socket.destroy(); + resolve(false); + }); + }); +} + +function pidAlive(pid: number): boolean { + try { + process.kill(pid, 0); + return true; + } catch { + return false; + } +} + +function sleep(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +export async function killStaleProcessOnPort(port: number): Promise { + if (!(await portIsOpen(port))) return; + try { + const result = Bun.spawnSync({ + cmd: ["lsof", "-ti", `:${port}`], + stdout: "pipe", + stderr: "pipe", + }); + const pids = new TextDecoder() + .decode(result.stdout) + .split(/\r?\n/) + .map((p) => p.trim()) + .filter((p) => /^\d+$/.test(p)) + .map((p) => Number.parseInt(p, 10)) + .filter((pid) => pid !== process.pid); + + for (const pid of pids) { + logger.info(`Killing stale process ${pid} on port ${port}`); + try { + process.kill(pid, "SIGTERM"); + } catch { + // Process may have already exited. + } + } + for (let i = 0; i < 10; i += 1) { + await sleep(300); + if (!pids.some(pidAlive)) return; + } + for (const pid of pids.filter(pidAlive)) { + logger.warning(`Force-killing stale process ${pid}`); + try { + process.kill(pid, "SIGKILL"); + } catch { + // Process may have already exited. + } + } + await sleep(300); + } catch (e) { + logger.warning(`Could not clean up port ${port}: ${e}`); + } +} + +export interface RunningServer { + server: Bun.Server; + context: ApiContext; + stop(): Promise; +} + +export async function runServer( + port = 9712, + dbPath?: string, +): Promise { + await killStaleProcessOnPort(port); + + logger.info("Initializing database..."); + const db = new TaskDB(dbPath); + + logger.info("Initializing MessageBus..."); + const bus = new MessageBus(); + const uiChannel = new UIChannel(bus, db); + uiChannel.start(); + + logger.info("Initializing scheduler..."); + const scheduler = new TaskScheduler(db, () => undefined, bus); + + const context: ApiContext = { + db, + scheduler, + bus, + telegram_channel: null, + slack_channel: null, + weixin_channel: null, + feishu_channel: null, + }; + + const tgEnabled = + db.get_setting("telegram_enabled", "false") === "true" || + Boolean(process.env.TELEGRAM_BOT_TOKEN); + const tgToken = + db.get_setting("telegram_bot_token", "") || + process.env.TELEGRAM_BOT_TOKEN || + ""; + const tgAllowed = + db.get_setting("telegram_allowed_users", "") || + process.env.TELEGRAM_ALLOWED_USERS || + ""; + if (tgEnabled && tgToken) { + logger.info("Starting Telegram channel..."); + context.telegram_channel = create_telegram_channel( + db, + scheduler, + bus, + tgToken, + tgAllowed, + ); + context.telegram_channel?.start(); + } else { + logger.info("Telegram channel disabled"); + } + + const slEnabled = + db.get_setting("slack_enabled", "false") === "true" || + Boolean(process.env.SLACK_BOT_TOKEN && process.env.SLACK_APP_TOKEN); + const slBot = + db.get_setting("slack_bot_token", "") || process.env.SLACK_BOT_TOKEN || ""; + const slApp = + db.get_setting("slack_app_token", "") || process.env.SLACK_APP_TOKEN || ""; + if (slEnabled && slBot && slApp) { + logger.info("Starting Slack channel..."); + context.slack_channel = new SlackChannel(bus, db, scheduler, slBot, slApp); + void context.slack_channel.start(); + } else { + logger.info("Slack channel disabled"); + } + + if (db.get_setting("weixin_enabled", "false") === "true") { + logger.info("Starting Weixin channel..."); + context.weixin_channel = new WeixinChannel(bus, db, scheduler); + context.weixin_channel.start(); + } else { + logger.info("Weixin channel disabled"); + } + + if (db.get_setting("feishu_enabled", "false") === "true") { + logger.info("Starting Feishu channel..."); + context.feishu_channel = new FeishuChannel(bus, db, scheduler); + context.feishu_channel.start(); + } else { + logger.info("Feishu channel disabled"); + } + + scheduler.start(); + + const server = Bun.serve({ + hostname: "127.0.0.1", + port, + fetch: (req) => handleApiRequest(context, req), + }); + + logger.info(`API server running on http://127.0.0.1:${port}`); + logger.info(`Database at ${db.db_path}`); + + const stop = async (): Promise => { + logger.info("Shutting down..."); + context.telegram_channel?.stop(); + context.slack_channel?.stop(); + context.weixin_channel?.stop(); + context.feishu_channel?.stop(); + await scheduler.stop(); + db.conn.close(); + server.stop(true); + }; + + return { server, context, stop }; +} diff --git a/backend/src/skills.ts b/backend/src/skills.ts index eb15f5f..82a69d0 100644 --- a/backend/src/skills.ts +++ b/backend/src/skills.ts @@ -39,22 +39,22 @@ export function _skill_library_dirs(): [string, string, string] { /** * Path to the vendored Anthropic skill-creator skill (dev tree or packaged binary). * - * Python resolves `getattr(sys, "_MEIPASS", dirname(abspath(__file__)))` + - * "vendor/skill-creator": taskboard.py sits at the repo root, so the dev path - * is /vendor/skill-creator, and a PyInstaller binary uses the bundled - * data dir (sys._MEIPASS). - * - * Bun-compile has no _MEIPASS equivalent (no bundled-data dir): inside a - * compiled binary import.meta.dir is a virtual bunfs path, so we fall back to - * a vendor/ dir next to the executable (dirname(process.execPath)) — the - * packager must ship vendor/skill-creator alongside the binary. In the dev - * tree this file lives at backend/src/, so the repo root is two levels up. + * In the dev tree this file lives at backend/src/, so the repo root is two + * levels up. Inside a Bun-compiled binary, import.meta.dir is a virtual bunfs + * path, so we resolve relative to dirname(process.execPath); the Electron + * packager ships skill-creator as an extra resource beside the binary. */ export function _skill_creator_dir(): string { const here = import.meta.dir; const isCompiled = here.includes("$bunfs") || here.includes("~BUN"); - const base = isCompiled ? path.dirname(process.execPath) : path.resolve(here, "..", ".."); - return path.join(base, "vendor", "skill-creator"); + if (!isCompiled) { + return path.join(path.resolve(here, "..", ".."), "vendor", "skill-creator"); + } + const resourceDir = path.dirname(process.execPath); + const nested = path.join(resourceDir, "vendor", "skill-creator"); + return fs.existsSync(nested) + ? nested + : path.join(resourceDir, "skill-creator"); } /** Lowercase kebab slug safe as a directory name (no path traversal). */ @@ -85,7 +85,9 @@ export function link_skill(name: string): string[] { try { fs.symlinkSync(skill_dir, link, "dir"); } catch (e) { - logger.warning(`symlink ${link} failed: ${e instanceof Error ? e.message : e}`); + logger.warning( + `symlink ${link} failed: ${e instanceof Error ? e.message : e}`, + ); } } links.push(link); @@ -110,7 +112,10 @@ export function unlink_skill(name: string): void { } /** Write canonical SKILL.md and create both symlinks. Returns (md_path, dir). */ -export function write_skill_to_disk(name: string, body: string): [string, string] { +export function write_skill_to_disk( + name: string, + body: string, +): [string, string] { const [canonical_root, _claude_root, _agents_root] = _skill_library_dirs(); void _claude_root; void _agents_root; @@ -151,7 +156,9 @@ export function _compose_skill_md( } /** Pull name + description out of a SKILL.md's YAML frontmatter (best-effort). */ -export function _parse_skill_frontmatter(body: string | null | undefined): [string, string] { +export function _parse_skill_frontmatter( + body: string | null | undefined, +): [string, string] { let name = ""; let description = ""; const text = (body || "").replace(/^\s+/, ""); diff --git a/backend/taskboard.ts b/backend/taskboard.ts new file mode 100644 index 0000000..5726951 --- /dev/null +++ b/backend/taskboard.ts @@ -0,0 +1,27 @@ +import { logger } from "./src/log.ts"; +import { runServer } from "./src/server.ts"; + +const rawPort = process.argv[2]; +const port = rawPort ? Number.parseInt(rawPort, 10) : 9712; +const dbPath = process.argv[3]; + +logger.info( + `=== Bun backend starting at ${new Date().toISOString()} on port ${port} ===`, +); + +const running = await runServer(port, dbPath); +let shuttingDown = false; + +async function shutdown(): Promise { + if (shuttingDown) return; + shuttingDown = true; + await running.stop(); + process.exit(0); +} + +process.on("SIGINT", () => { + void shutdown(); +}); +process.on("SIGTERM", () => { + void shutdown(); +}); diff --git a/backend/tests/api-handler.test.ts b/backend/tests/api-handler.test.ts new file mode 100644 index 0000000..057a0d3 --- /dev/null +++ b/backend/tests/api-handler.test.ts @@ -0,0 +1,1620 @@ +import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; + +import { MessageBus } from "../src/bus.ts"; +import { TaskDB } from "../src/db.ts"; +import { TaskScheduler } from "../src/scheduler.ts"; +import { handleApiRequest, type ApiContext } from "../src/api.ts"; +import { FeishuChannel } from "../src/channels/feishu.ts"; + +describe("api handler", () => { + let tmpDir: string; + let db: TaskDB; + let scheduler: TaskScheduler; + let ctx: ApiContext; + + beforeEach(() => { + tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "agentforge-api-test-")); + db = new TaskDB(path.join(tmpDir, "api-test.db")); + const bus = new MessageBus(); + scheduler = new TaskScheduler(db, null, bus); + ctx = { + db, + scheduler, + bus, + telegram_channel: null, + slack_channel: null, + weixin_channel: null, + feishu_channel: null, + }; + }); + + afterEach(() => { + db.conn.close(); + fs.rmSync(tmpDir, { recursive: true, force: true }); + }); + + async function json(req: Request): Promise { + const res = await handleApiRequest(ctx, req); + return (await res.json()) as Record; + } + + test("GET /api/health returns ok and task count", async () => { + const res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/health"), + ); + expect(res.status).toBe(200); + expect(await res.json()).toEqual({ status: "ok", tasks: 0 }); + }); + + test("POST /api/tasks enforces browser CSRF and creates tasks with token", async () => { + const body = JSON.stringify({ + title: "API task", + prompt: "ship it", + working_dir: ".", + }); + const rejected = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/tasks", { + method: "POST", + headers: { + Origin: "http://localhost:5173", + "Content-Type": "application/json", + }, + body, + }), + ); + expect(rejected.status).toBe(403); + + const csrf = await json( + new Request("http://127.0.0.1:9712/api/csrf-token", { + headers: { Origin: "http://localhost:5173" }, + }), + ); + const created = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/tasks", { + method: "POST", + headers: { + Origin: "http://localhost:5173", + "Content-Type": "application/json", + "X-CSRF-Token": csrf["csrf_token"], + }, + body, + }), + ); + expect(created.status).toBe(201); + const payload = (await created.json()) as Record; + expect(payload["status"]).toBe("created"); + + const tasks = await json(new Request("http://127.0.0.1:9712/api/tasks")); + expect(Array.isArray(tasks)).toBe(true); + expect(tasks).toHaveLength(1); + expect(tasks[0]["title"]).toBe("API task"); + expect(tasks[0]["dependencies"]).toEqual([]); + expect(tasks[0]["dependents"]).toEqual([]); + }); + + test("GET task output falls back to latest persisted raw output", async () => { + const created = await json( + new Request("http://127.0.0.1:9712/api/tasks", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + title: "Run", + prompt: "do it", + working_dir: ".", + }), + }), + ); + const taskId = Number(created["id"]); + const runId = db.add_run(taskId); + db.finish_run(runId, "completed", "ok", null, "raw output"); + + const output = await json( + new Request(`http://127.0.0.1:9712/api/tasks/${taskId}/output`), + ); + expect(output).toEqual({ output: "raw output", is_running: false }); + }); + + test("POST /api/feishu/settings restarts the Feishu channel", async () => { + const old = { + stopped: false, + stop() { + this.stopped = true; + }, + }; + ctx.feishu_channel = old as any; + + const enabled = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/feishu/settings", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ feishu_enabled: "true" }), + }), + ); + + expect(enabled.status).toBe(200); + expect(old.stopped).toBe(true); + expect(ctx.feishu_channel).toBeInstanceOf(FeishuChannel); + expect(db.get_setting("feishu_enabled")).toBe("true"); + + const started = ctx.feishu_channel; + const disabled = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/feishu/settings", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ feishu_enabled: "false" }), + }), + ); + + expect(disabled.status).toBe(200); + expect(ctx.feishu_channel).toBeNull(); + expect(started?._running).toBe(false); + expect(db.get_setting("feishu_enabled")).toBe("false"); + }); + + test("DELETE /api/tasks enforces CSRF for browser origins", async () => { + const created = await json( + new Request("http://127.0.0.1:9712/api/tasks", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + title: "Delete me", + prompt: "later", + schedule_type: "delayed", + delay_seconds: 999, + }), + }), + ); + const taskId = Number(created["id"]); + + const rejected = await handleApiRequest( + ctx, + new Request(`http://127.0.0.1:9712/api/tasks/${taskId}`, { + method: "DELETE", + headers: { + Origin: "http://localhost:5173", + "X-CSRF-Token": "wrong", + }, + }), + ); + + expect(rejected.status).toBe(403); + expect(db.get_task(taskId)).not.toBeNull(); + + const csrf = await json( + new Request("http://127.0.0.1:9712/api/csrf-token", { + headers: { Origin: "http://localhost:5173" }, + }), + ); + const accepted = await handleApiRequest( + ctx, + new Request(`http://127.0.0.1:9712/api/tasks/${taskId}`, { + method: "DELETE", + headers: { + Origin: "http://localhost:5173", + "X-CSRF-Token": csrf["csrf_token"], + }, + }), + ); + + expect(accepted.status).toBe(200); + expect(await accepted.json()).toEqual({ status: "deleted" }); + expect(db.get_task(taskId)).toBeNull(); + }); + + test("POST /api/channels/settings stops existing disabled channels", async () => { + const stopped: string[] = []; + ctx.telegram_channel = { stop: () => stopped.push("telegram") } as any; + ctx.slack_channel = { stop: () => stopped.push("slack") } as any; + ctx.weixin_channel = { stop: () => stopped.push("weixin") } as any; + ctx.feishu_channel = { stop: () => stopped.push("feishu") } as any; + + const res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/channels/settings", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + telegram_enabled: "false", + slack_enabled: "false", + weixin_enabled: "false", + }), + }), + ); + + expect(res.status).toBe(200); + expect(stopped).toEqual(["telegram", "slack", "weixin", "feishu"]); + expect(ctx.telegram_channel).toBeNull(); + expect(ctx.slack_channel).toBeNull(); + expect(ctx.weixin_channel).toBeNull(); + expect(ctx.feishu_channel).toBeNull(); + }); + + test("POST /api/dag accepts prompt_images as JSON string", async () => { + const res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/dag", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + dag_id: "imgdag", + tasks: [ + { + ref: "a", + prompt: "first", + schedule_type: "immediate", + prompt_images: JSON.stringify([ + { media_type: "image/png", data: "AAA" }, + ]), + }, + ], + }), + }), + ); + + expect(res.status).toBe(201); + const payload = (await res.json()) as Record; + const taskId = Number(payload["task_ids"]["a"]); + expect(db.get_task(taskId)!["prompt_images"]).toEqual([ + { media_type: "image/png", data: "AAA" }, + ]); + }); + + test("POST /api/dag falls back to empty prompt_images for bad JSON", async () => { + const res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/dag", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + tasks: [ + { + ref: "a", + prompt: "first", + schedule_type: "immediate", + prompt_images: "{not json", + }, + ], + }), + }), + ); + + expect(res.status).toBe(201); + const payload = (await res.json()) as Record; + const taskId = Number(payload["task_ids"]["a"]); + expect(db.get_task(taskId)!["prompt_images"]).toEqual([]); + }); + + test("POST /api/tasks/:id/resume returns 404 for missing tasks", async () => { + const res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/tasks/99999/resume", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ message: "go" }), + }), + ); + + expect(res.status).toBe(404); + expect(await res.json()).toEqual({ error: "not found" }); + }); + + test("POST rejects declared bodies larger than the API cap", async () => { + const res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/tasks", { + method: "POST", + headers: { + "Content-Type": "application/json", + "Content-Length": String(10 * 1024 * 1024 + 1), + }, + body: "{}", + }), + ); + + expect(res.status).toBe(413); + expect(await res.json()).toEqual({ error: "request body too large" }); + }); + + test("CORS, method, and JSON error paths return explicit responses", async () => { + const forbiddenOrigin = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/health", { + headers: { Origin: "https://evil.example" }, + }), + ); + expect(forbiddenOrigin.status).toBe(403); + + const options = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/tasks", { + method: "OPTIONS", + headers: { Origin: "http://localhost:5173" }, + }), + ); + expect(options.status).toBe(200); + expect(options.headers.get("Access-Control-Allow-Origin")).toBe( + "http://localhost:5173", + ); + + const invalidJson = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/tasks", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: "{", + }), + ); + expect(invalidJson.status).toBe(400); + expect(await invalidJson.json()).toEqual({ error: "invalid JSON body" }); + + const methodNotAllowed = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/tasks", { method: "PATCH" }), + ); + expect(methodNotAllowed.status).toBe(405); + expect(await methodNotAllowed.json()).toEqual({ + error: "method not allowed", + }); + + const outsideApi = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/not-api"), + ); + expect(outsideApi.status).toBe(404); + }); + + test("GET settings and channel status expose stored non-secret configuration", async () => { + db.set_setting("timeout", "123"); + db.set_setting("default_agent", "codex"); + db.set_setting("skill_library_enabled", "1"); + db.set_setting("skill_sweep_agent", "claude"); + db.set_setting("skill_sweep_cron", "5 4 * * *"); + db.set_setting("telegram_enabled", "true"); + db.set_setting("telegram_bot_token", "tg-secret"); + db.set_setting("telegram_allowed_users", "42"); + db.set_setting("telegram_default_working_dir", "~/tg"); + db.set_setting("telegram_default_chat_id", "-10042"); + db.set_setting("slack_enabled", "true"); + db.set_setting("slack_bot_token", "xoxb"); + db.set_setting("slack_app_token", "xapp"); + db.set_setting("slack_default_channel", "C42"); + db.set_setting("weixin_enabled", "true"); + db.set_setting("weixin_account_id", "configured-account"); + ctx.weixin_channel = { + _running: true, + get_status_snapshot: () => ({ + configured: true, + login_status: "logged_in", + account_id: "runtime-account", + qr_code_url: "qr", + user_id: "wx-user", + }), + } as any; + + const settings = await json( + new Request("http://127.0.0.1:9712/api/settings"), + ); + expect(settings).toEqual({ + default_agent: "codex", + timeout: 123, + skill_library_enabled: true, + skill_sweep_agent: "claude", + skill_sweep_cron: "5 4 * * *", + }); + + const status = await json( + new Request("http://127.0.0.1:9712/api/channels/status"), + ); + expect(status.telegram).toEqual({ + enabled: true, + configured: true, + running: false, + default_working_dir: "~/tg", + default_chat_id: "-10042", + allowed_users: "42", + }); + expect(status.slack.configured).toBe(true); + expect(status.slack.default_channel).toBe("C42"); + expect(status.weixin.account_id).toBe("runtime-account"); + expect(status.weixin.running).toBe(true); + expect(status.weixin.login_status).toBe("logged_in"); + }); + + test("task detail routes expose runs, events, messages, and dependency metadata", async () => { + const upstream = await json( + new Request("http://127.0.0.1:9712/api/tasks", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + title: "Upstream", + prompt: "prepare", + working_dir: ".", + dag_id: "dag-api", + }), + }), + ); + const upstreamId = Number(upstream["id"]); + + const downstream = await json( + new Request("http://127.0.0.1:9712/api/tasks", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + title: "Downstream", + prompt: "consume", + working_dir: ".", + dag_id: "dag-api", + depends_on: [{ task_id: upstreamId, inject_result: true }], + }), + }), + ); + const downstreamId = Number(downstream["id"]); + + const runId = db.add_run(downstreamId); + const raw = [ + JSON.stringify({ + type: "user", + message: { content: [{ type: "text", text: "hello" }] }, + }), + "not-json", + JSON.stringify({ + type: "assistant", + message: { content: [{ type: "text", text: "world" }] }, + }), + ].join("\n"); + db.finish_run(runId, "completed", "done", null, raw); + db.add_output_event(downstreamId, runId, "assistant", "event-content"); + + const task = await json( + new Request(`http://127.0.0.1:9712/api/tasks/${downstreamId}`), + ); + expect(task.dependencies).toEqual([ + expect.objectContaining({ + task_id: downstreamId, + depends_on_task_id: upstreamId, + inject_result: 1, + }), + ]); + + const dependents = await json( + new Request(`http://127.0.0.1:9712/api/tasks/${upstreamId}/dependents`), + ); + expect(dependents.map((d: any) => d.task_id)).toEqual([downstreamId]); + + const deps = await json( + new Request( + `http://127.0.0.1:9712/api/tasks/${downstreamId}/dependencies`, + ), + ); + expect(deps).toEqual([ + expect.objectContaining({ + task_id: downstreamId, + depends_on_task_id: upstreamId, + inject_result: 1, + }), + ]); + + const runs = await json( + new Request(`http://127.0.0.1:9712/api/tasks/${downstreamId}/runs`), + ); + expect(runs[0].id).toBe(runId); + + const events = await json( + new Request( + `http://127.0.0.1:9712/api/tasks/${downstreamId}/events?limit=5&offset=0`, + ), + ); + expect(events.total).toBe(1); + expect(events.events[0].content).toBe("event-content"); + + const messages = await json( + new Request(`http://127.0.0.1:9712/api/tasks/${downstreamId}/messages`), + ); + expect(messages.map((m: any) => [m.role, m.text])).toEqual([ + ["user", "hello"], + ["assistant", "world"], + ]); + + const dag = await json( + new Request("http://127.0.0.1:9712/api/dag/dag-api"), + ); + expect( + dag.map((t: any) => t.id).sort((a: number, b: number) => a - b), + ).toEqual([upstreamId, downstreamId]); + }); + + test("POST /api/tasks validates prompt, working dir, and cron schedules", async () => { + const emptyPrompt = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/tasks", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ prompt: " " }), + }), + ); + expect(emptyPrompt.status).toBe(400); + expect(await emptyPrompt.json()).toEqual({ + error: "prompt cannot be empty", + field: "prompt", + }); + + const badDir = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/tasks", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + prompt: "x", + working_dir: path.join(tmpDir, "missing"), + }), + }), + ); + expect(badDir.status).toBe(400); + expect(((await badDir.json()) as Record).field).toBe( + "working_dir", + ); + + const missingCron = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/tasks", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ prompt: "x", schedule_type: "cron" }), + }), + ); + expect(missingCron.status).toBe(400); + + const invalidCron = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/tasks", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + prompt: "x", + schedule_type: "cron", + cron_expr: "not cron", + }), + }), + ); + expect(invalidCron.status).toBe(400); + expect(((await invalidCron.json()) as Record).field).toBe( + "cron_expr", + ); + }); + + test("task mutation routes edit, respond, resume, cancel, retry, and remove dependencies", async () => { + const upstream = await json( + new Request("http://127.0.0.1:9712/api/tasks", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ title: "Up", prompt: "up" }), + }), + ); + const task = await json( + new Request("http://127.0.0.1:9712/api/tasks", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ title: "Editable", prompt: "first" }), + }), + ); + const upstreamId = Number(upstream.id); + const taskId = Number(task.id); + + const addDep = await handleApiRequest( + ctx, + new Request(`http://127.0.0.1:9712/api/tasks/${taskId}/dependencies`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ depends_on_task_id: upstreamId }), + }), + ); + expect(addDep.status).toBe(200); + expect(db.get_task(taskId)!["status"]).toBe("blocked"); + + const removeDep = await handleApiRequest( + ctx, + new Request( + `http://127.0.0.1:9712/api/tasks/${taskId}/dependencies/${upstreamId}`, + { method: "DELETE" }, + ), + ); + expect(removeDep.status).toBe(200); + expect(db.get_dependencies(taskId)).toEqual([]); + + const edited = await handleApiRequest( + ctx, + new Request(`http://127.0.0.1:9712/api/tasks/${taskId}`, { + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + title: "Edited", + prompt: "second", + schedule_type: "scheduled_at", + next_run_at: "2030-01-01T00:00:00", + prompt_images: JSON.stringify([ + { media_type: "image/png", data: "x" }, + ]), + }), + }), + ); + expect(edited.status).toBe(200); + const editedPayload = (await edited.json()) as any; + expect(editedPayload.title).toBe("Edited"); + expect(editedPayload.status).toBe("scheduled"); + expect(editedPayload.prompt_images).toEqual([ + { media_type: "image/png", data: "x" }, + ]); + + const respond = await handleApiRequest( + ctx, + new Request(`http://127.0.0.1:9712/api/tasks/${taskId}/respond`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ answer: "answer" }), + }), + ); + expect(respond.status).toBe(200); + expect(db.get_task(taskId)!["answer"]).toBe("answer"); + + db.update_task(taskId, { session_id: "sess-1" }); + const resume = await handleApiRequest( + ctx, + new Request(`http://127.0.0.1:9712/api/tasks/${taskId}/resume`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ message: "continue" }), + }), + ); + expect(resume.status).toBe(200); + expect(db.get_task(taskId)!["prompt"]).toBe("continue"); + + const cancel = await handleApiRequest( + ctx, + new Request(`http://127.0.0.1:9712/api/tasks/${taskId}/cancel`, { + method: "POST", + }), + ); + expect(cancel.status).toBe(200); + expect(db.get_task(taskId)!["status"]).toBe("cancelled"); + + const retry = await handleApiRequest( + ctx, + new Request(`http://127.0.0.1:9712/api/tasks/${taskId}/retry`, { + method: "POST", + }), + ); + expect(retry.status).toBe(200); + expect(db.get_task(taskId)!["status"]).toBe("pending"); + }); + + test("heartbeat API covers create, ticks, output, pause, resume, update, and delete", async () => { + const created = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/heartbeats", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + name: "Heartbeat", + check_prompt: "check", + schedule_type: "interval", + interval_seconds: 60, + cooldown_seconds: 5, + }), + }), + ); + expect(created.status).toBe(201); + const heartbeatId = Number(((await created.json()) as any).id); + + expect( + await json(new Request("http://127.0.0.1:9712/api/heartbeats")), + ).toHaveLength(1); + expect( + ( + await json( + new Request(`http://127.0.0.1:9712/api/heartbeats/${heartbeatId}`), + ) + ).name, + ).toBe("Heartbeat"); + + const tickId = db.add_heartbeat_tick(heartbeatId); + db.finish_heartbeat_tick( + tickId, + "completed", + "idle", + { decision: "idle" }, + null, + "tick raw", + ); + const ticks = await json( + new Request(`http://127.0.0.1:9712/api/heartbeats/${heartbeatId}/ticks`), + ); + expect(ticks.ticks[0].id).toBe(tickId); + + let output = await json( + new Request( + `http://127.0.0.1:9712/api/heartbeats/${heartbeatId}/ticks/${tickId}/output`, + ), + ); + expect(output).toEqual({ output: "tick raw", is_running: false }); + + scheduler._live_heartbeat_output.set(tickId, "live tick"); + output = await json( + new Request( + `http://127.0.0.1:9712/api/heartbeats/${heartbeatId}/ticks/${tickId}/output`, + ), + ); + expect(output).toEqual({ output: "live tick", is_running: true }); + + const pause = await handleApiRequest( + ctx, + new Request(`http://127.0.0.1:9712/api/heartbeats/${heartbeatId}/pause`, { + method: "POST", + }), + ); + expect(pause.status).toBe(200); + expect(db.get_heartbeat(heartbeatId)!["enabled"]).toBe(false); + + const resume = await handleApiRequest( + ctx, + new Request( + `http://127.0.0.1:9712/api/heartbeats/${heartbeatId}/resume`, + { method: "POST" }, + ), + ); + expect(resume.status).toBe(200); + expect(db.get_heartbeat(heartbeatId)!["enabled"]).toBe(true); + + const updated = await handleApiRequest( + ctx, + new Request(`http://127.0.0.1:9712/api/heartbeats/${heartbeatId}`, { + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + name: "Cron heartbeat", + check_prompt: "check", + schedule_type: "cron", + cron_expr: "0 9 * * *", + cooldown_seconds: 0, + }), + }), + ); + expect(updated.status).toBe(200); + expect(((await updated.json()) as any).schedule_type).toBe("cron"); + + const deleted = await handleApiRequest( + ctx, + new Request(`http://127.0.0.1:9712/api/heartbeats/${heartbeatId}`, { + method: "DELETE", + }), + ); + expect(deleted.status).toBe(200); + expect(db.get_heartbeat(heartbeatId)).toBeNull(); + }); + + test("heartbeat validation rejects malformed payloads", async () => { + const empty = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/heartbeats", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ check_prompt: "" }), + }), + ); + expect(empty.status).toBe(400); + expect(((await empty.json()) as Record).field).toBe( + "check_prompt", + ); + + const badSchedule = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/heartbeats", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + check_prompt: "x", + schedule_type: "nonsense", + }), + }), + ); + expect(badSchedule.status).toBe(400); + expect(((await badSchedule.json()) as Record).field).toBe( + "schedule_type", + ); + + const badCron = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/heartbeats", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + check_prompt: "x", + schedule_type: "cron", + cron_expr: "bad cron", + }), + }), + ); + expect(badCron.status).toBe(400); + expect(((await badCron.json()) as Record).field).toBe( + "cron_expr", + ); + + const badInterval = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/heartbeats", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + check_prompt: "x", + schedule_type: "interval", + interval_seconds: 0, + }), + }), + ); + expect(badInterval.status).toBe(400); + expect(((await badInterval.json()) as Record).field).toBe( + "interval_seconds", + ); + + const badCooldown = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/heartbeats", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + check_prompt: "x", + schedule_type: "interval", + interval_seconds: 10, + cooldown_seconds: -1, + }), + }), + ); + expect(badCooldown.status).toBe(400); + expect(((await badCooldown.json()) as Record).field).toBe( + "cooldown_seconds", + ); + }); + + test("Weixin action API delegates to the running channel", async () => { + const calls: string[] = []; + + const missing = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/channels/weixin/action", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ action: "login" }), + }), + ); + expect(missing.status).toBe(400); + + ctx.weixin_channel = { + request_login: () => calls.push("login"), + request_logout: () => calls.push("logout"), + } as any; + + const login = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/channels/weixin/action", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ action: "reconnect" }), + }), + ); + expect(login.status).toBe(200); + + const logout = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/channels/weixin/action", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ action: "logout" }), + }), + ); + expect(logout.status).toBe(200); + + const unsupported = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/channels/weixin/action", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ action: "dance" }), + }), + ); + expect(unsupported.status).toBe(400); + expect(calls).toEqual(["login", "logout"]); + }); + + test("skill content, toggle, and delete routes use the skill registry", async () => { + const skillDir = path.join(tmpDir, "skill"); + fs.mkdirSync(skillDir); + const skillPath = path.join(skillDir, "SKILL.md"); + fs.writeFileSync(skillPath, "# Skill\n", "utf8"); + const skillId = db.add_skill("demo", "desc", skillPath)!; + + const list = await json(new Request("http://127.0.0.1:9712/api/skills")); + expect(list.skills.map((s: any) => s.id)).toContain(skillId); + + const content = await json( + new Request(`http://127.0.0.1:9712/api/skills/${skillId}/content`), + ); + expect(content.content).toBe("# Skill\n"); + expect(content.path).toBe(skillPath); + + const toggled = await handleApiRequest( + ctx, + new Request(`http://127.0.0.1:9712/api/skills/${skillId}`, { + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ enabled: false }), + }), + ); + expect(toggled.status).toBe(200); + expect(db.get_skill(skillId)!["enabled"]).toBe(0); + + const deleted = await handleApiRequest( + ctx, + new Request(`http://127.0.0.1:9712/api/skills/${skillId}`, { + method: "DELETE", + }), + ); + expect(deleted.status).toBe(200); + expect(db.get_skill(skillId)).toBeNull(); + }); + + test("settings, skill workflow, and delete error routes cover edge cases", async () => { + const nonObjectSettings = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/settings", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(["ignored"]), + }), + ); + expect(nonObjectSettings.status).toBe(200); + + const putSettings = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/settings", { + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ timeout: 90 }), + }), + ); + expect(putSettings.status).toBe(200); + expect(db.get_setting("timeout")).toBe("90"); + + db.set_setting("feishu_app_id", "cli_x"); + const feishuSettings = await json( + new Request("http://127.0.0.1:9712/api/feishu/settings"), + ); + expect(feishuSettings.feishu_app_id).toBe("cli_x"); + + const missingContent = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/skills/999/content"), + ); + expect(missingContent.status).toBe(404); + + const brokenSkillId = db.add_skill( + "broken", + "missing file", + path.join(tmpDir, "missing", "SKILL.md"), + )!; + const brokenContent = await json( + new Request(`http://127.0.0.1:9712/api/skills/${brokenSkillId}/content`), + ); + expect(brokenContent.content).toContain("无法读取"); + + (scheduler as any).trigger_skill_sweep = mock(() => true); + let res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/skills/sweep", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ agent: "codex", full: false }), + }), + ); + expect(res.status).toBe(200); + expect((scheduler as any).trigger_skill_sweep.mock.calls[0]).toEqual([ + "codex", + false, + ]); + (scheduler as any).trigger_skill_sweep = mock(() => false); + res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/skills/sweep", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: "{}", + }), + ); + expect(res.status).toBe(409); + + (scheduler as any).trigger_skill_draft = mock(() => true); + res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/skill-patterns/1/draft", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ agent: "claude" }), + }), + ); + expect(res.status).toBe(200); + (scheduler as any).trigger_skill_draft = mock(() => false); + res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/skill-patterns/bad/draft", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: "{}", + }), + ); + expect(res.status).toBe(404); + + (scheduler as any).approve_skill = mock(() => ({ id: 1, name: "ok" })); + res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/skill-patterns/1/approve", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ name: "ok", description: "d", body: "# Skill" }), + }), + ); + expect(res.status).toBe(200); + (scheduler as any).approve_skill = mock(() => { + throw new Error("pattern not found"); + }); + res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/skill-patterns/1/approve", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: "{}", + }), + ); + expect(res.status).toBe(404); + + (scheduler as any).dismiss_skill_pattern = mock(() => undefined); + res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/skill-patterns/1/dismiss", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: "{}", + }), + ); + expect(res.status).toBe(200); + res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/skill-patterns/bad/dismiss", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: "{}", + }), + ); + expect(res.status).toBe(404); + + res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/skills/bad", { + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: "{}", + }), + ); + expect(res.status).toBe(400); + (scheduler as any).toggle_skill = mock(() => { + throw new Error("skill not found"); + }); + res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/skills/123", { + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: "{}", + }), + ); + expect(res.status).toBe(404); + + res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/skills/bad", { + method: "DELETE", + }), + ); + expect(res.status).toBe(400); + (scheduler as any).remove_skill = mock(() => { + throw new Error("skill not found"); + }); + res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/skills/123", { + method: "DELETE", + }), + ); + expect(res.status).toBe(404); + res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/unknown", { method: "DELETE" }), + ); + expect(res.status).toBe(404); + }); + + test("heartbeat routes cover validation and scheduler error branches", async () => { + let res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/heartbeats", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + check_prompt: "check", + working_dir: path.join(tmpDir, "missing"), + schedule_type: "interval", + interval_seconds: 60, + }), + }), + ); + expect(res.status).toBe(400); + + res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/heartbeats", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + check_prompt: "check", + schedule_type: "cron", + }), + }), + ); + expect(res.status).toBe(400); + + res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/heartbeats", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + check_prompt: "check", + schedule_type: "interval", + interval_seconds: 60, + cooldown_seconds: "not-int", + enabled: "false", + }), + }), + ); + expect(res.status).toBe(400); + + const created = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/heartbeats", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + check_prompt: "check", + schedule_type: "interval", + interval_seconds: 60, + cooldown_seconds: 0, + enabled: "false", + }), + }), + ); + const heartbeatId = Number(((await created.json()) as any).id); + expect(db.get_heartbeat(heartbeatId)!["enabled"]).toBe(false); + + const tickId = db.add_heartbeat_tick(heartbeatId); + expect( + ( + await handleApiRequest( + ctx, + new Request( + `http://127.0.0.1:9712/api/heartbeats/bad/ticks/${tickId}/output`, + ), + ) + ).status, + ).toBe(404); + expect( + ( + await handleApiRequest( + ctx, + new Request( + `http://127.0.0.1:9712/api/heartbeats/${heartbeatId}/ticks/999/output`, + ), + ) + ).status, + ).toBe(404); + expect( + ( + await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/heartbeats/bad/ticks"), + ) + ).status, + ).toBe(404); + expect( + ( + await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/heartbeats/bad"), + ) + ).status, + ).toBe(404); + + (scheduler as any).trigger_heartbeat_now = mock(() => undefined); + res = await handleApiRequest( + ctx, + new Request( + `http://127.0.0.1:9712/api/heartbeats/${heartbeatId}/run-now`, + { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: "{}", + }, + ), + ); + expect(res.status).toBe(200); + (scheduler as any).trigger_heartbeat_now = mock(() => { + throw new Error("heartbeat already running"); + }); + res = await handleApiRequest( + ctx, + new Request( + `http://127.0.0.1:9712/api/heartbeats/${heartbeatId}/run-now`, + { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: "{}", + }, + ), + ); + expect(res.status).toBe(409); + (scheduler as any).trigger_heartbeat_now = mock(() => { + throw new Error("heartbeat not found"); + }); + res = await handleApiRequest( + ctx, + new Request( + `http://127.0.0.1:9712/api/heartbeats/${heartbeatId}/run-now`, + { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: "{}", + }, + ), + ); + expect(res.status).toBe(404); + + expect( + ( + await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/heartbeats/bad", { + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: "{}", + }), + ) + ).status, + ).toBe(400); + expect( + ( + await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/heartbeats/999", { + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: "{}", + }), + ) + ).status, + ).toBe(404); + + (scheduler as any).pause_heartbeat = mock(() => { + throw new Error("heartbeat not found"); + }); + expect( + ( + await handleApiRequest( + ctx, + new Request( + `http://127.0.0.1:9712/api/heartbeats/${heartbeatId}/pause`, + { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: "{}", + }, + ), + ) + ).status, + ).toBe(404); + (scheduler as any).resume_heartbeat = mock(() => { + throw new Error("heartbeat not found"); + }); + expect( + ( + await handleApiRequest( + ctx, + new Request( + `http://127.0.0.1:9712/api/heartbeats/${heartbeatId}/resume`, + { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: "{}", + }, + ), + ) + ).status, + ).toBe(404); + }); + + test("task routes cover live output, message parsing, validation, and DAG errors", async () => { + const upstream = await json( + new Request("http://127.0.0.1:9712/api/tasks", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ prompt: "upstream" }), + }), + ); + db.update_task(Number(upstream.id), { status: "completed" }); + + const created = await json( + new Request("http://127.0.0.1:9712/api/tasks", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + prompt: "downstream", + schedule_type: "cron", + cron_expr: "*/5 * * * *", + depends_on: [Number(upstream.id), { task_id: Number(upstream.id) }], + inject_result: true, + prompt_images: JSON.stringify({ not: "a list" }), + image_paths: ["a.png", 1], + }), + }), + ); + const taskId = Number(created.id); + expect(db.get_dependencies(taskId)).toHaveLength(1); + + scheduler._live_output.set(taskId, "live output"); + expect( + await json( + new Request(`http://127.0.0.1:9712/api/tasks/${taskId}/output`), + ), + ).toEqual({ output: "live output", is_running: true }); + + const runId = db.add_run(taskId); + db.finish_run( + runId, + "completed", + "ok", + null, + [ + JSON.stringify({ + type: "user", + message: { + content: [ + "hello ", + { type: "text", text: "world" }, + { type: "image", source: "ignored" }, + ], + }, + }), + JSON.stringify({ + type: "assistant", + message: { + content: [{ type: "text", text: "answer" }, { type: "tool" }], + }, + }), + "{bad json", + ].join("\n"), + ); + const messages = await json( + new Request(`http://127.0.0.1:9712/api/tasks/${taskId}/messages`), + ); + expect(messages.map((m: any) => m.text)).toEqual(["hello world", "answer"]); + + for (const suffix of [ + "runs", + "output", + "events", + "messages", + "dependencies", + "dependents", + ]) { + const res = await handleApiRequest( + ctx, + new Request(`http://127.0.0.1:9712/api/tasks/bad/${suffix}`), + ); + expect(res.status).toBe(404); + } + + let res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/tasks/bad/dependencies", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: "{}", + }), + ); + expect(res.status).toBe(400); + res = await handleApiRequest( + ctx, + new Request(`http://127.0.0.1:9712/api/tasks/${taskId}/dependencies`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ depends_on_task_id: 999 }), + }), + ); + expect(res.status).toBe(404); + + res = await handleApiRequest( + ctx, + new Request(`http://127.0.0.1:9712/api/tasks/${taskId}/resume`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ message: " " }), + }), + ); + expect(res.status).toBe(400); + res = await handleApiRequest( + ctx, + new Request(`http://127.0.0.1:9712/api/tasks/${taskId}/resume`, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ message: "continue" }), + }), + ); + expect(res.status).toBe(400); + expect( + ( + await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/tasks/bad/cancel", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: "{}", + }), + ) + ).status, + ).toBe(404); + expect( + ( + await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/tasks/bad/retry", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: "{}", + }), + ) + ).status, + ).toBe(404); + expect( + ( + await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/tasks/999/respond", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: "{}", + }), + ) + ).status, + ).toBe(404); + + res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/dag", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ tasks: [] }), + }), + ); + expect(res.status).toBe(400); + res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/dag", { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ + tasks: [{ ref: "b", prompt: "b", depends_on_refs: ["missing"] }], + }), + }), + ); + expect(res.status).toBe(400); + + res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/tasks/bad", { + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: "{}", + }), + ); + expect(res.status).toBe(400); + res = await handleApiRequest( + ctx, + new Request("http://127.0.0.1:9712/api/tasks/999", { + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: "{}", + }), + ); + expect(res.status).toBe(404); + + db.update_task(taskId, { status: "completed" }); + res = await handleApiRequest( + ctx, + new Request(`http://127.0.0.1:9712/api/tasks/${taskId}`, { + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ prompt: "edit" }), + }), + ); + expect(res.status).toBe(409); + + db.update_task(taskId, { status: "pending" }); + for (const body of [ + { prompt: " " }, + { prompt: "ok", working_dir: path.join(tmpDir, "missing") }, + { prompt: "ok", schedule_type: "cron", cron_expr: "" }, + { prompt: "ok", schedule_type: "cron", cron_expr: "bad cron" }, + { prompt: "ok", schedule_type: "scheduled_at", next_run_at: "" }, + ]) { + res = await handleApiRequest( + ctx, + new Request(`http://127.0.0.1:9712/api/tasks/${taskId}`, { + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(body), + }), + ); + expect(res.status).toBe(400); + } + + for (const body of [ + { prompt: "immediate", schedule_type: "immediate" }, + { prompt: "delayed", schedule_type: "delayed", delay_seconds: 30 }, + { prompt: "cron", schedule_type: "cron", cron_expr: "*/10 * * * *" }, + { + prompt: "blocked", + depends_on: [{ task_id: Number(upstream.id), inject_result: true }], + prompt_images: [{ media_type: "image/png", data: "x" }], + image_paths: ["image.png"], + }, + ]) { + res = await handleApiRequest( + ctx, + new Request(`http://127.0.0.1:9712/api/tasks/${taskId}`, { + method: "PUT", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify(body), + }), + ); + expect(res.status).toBe(200); + } + + const explodingDb = { + ...ctx, + db: { + ...db, + get_all_tasks: () => { + throw new Error("db down"); + }, + }, + } as any; + const failure = await handleApiRequest( + explodingDb, + new Request("http://127.0.0.1:9712/api/health"), + ); + expect(failure.status).toBe(500); + }); +}); diff --git a/backend/tests/dir-utils.test.ts b/backend/tests/dir-utils.test.ts new file mode 100644 index 0000000..4d77a46 --- /dev/null +++ b/backend/tests/dir-utils.test.ts @@ -0,0 +1,103 @@ +import { afterEach, describe, expect, mock, test } from "bun:test"; + +import { + extract_working_dir_with_claude, + handle_dir_command, + parse_dir_command, + resolve_working_dir, +} from "../src/channels/dir_utils.ts"; + +class SettingsStub { + values: Record = {}; + + get_setting(key: string, fallback: string | null = null): string | null { + return this.values[key] ?? fallback; + } + + set_setting(key: string, value: string): void { + this.values[key] = value; + } +} + +const originalApiKey = process.env.ANTHROPIC_API_KEY; +const originalFetch = globalThis.fetch; + +afterEach(() => { + if (originalApiKey === undefined) delete process.env.ANTHROPIC_API_KEY; + else process.env.ANTHROPIC_API_KEY = originalApiKey; + globalThis.fetch = originalFetch; +}); + +describe("dir utils", () => { + test("explicit dir commands parse and persist", () => { + const db = new SettingsStub(); + + expect(parse_dir_command("/dir ~/app")).toBe("~/app"); + expect(parse_dir_command("/cd /tmp/app")).toBe("/tmp/app"); + expect(parse_dir_command("cd ./app")).toBe("./app"); + expect(parse_dir_command("hello")).toBeNull(); + expect(handle_dir_command("/dir /work", "telegram", db)).toContain("/work"); + expect(db.values["telegram_default_working_dir"]).toBe("/work"); + expect(handle_dir_command("not a dir command", "telegram", db)).toBeNull(); + }); + + test("Claude extraction covers success, empty, non-200, and error paths", async () => { + delete process.env.ANTHROPIC_API_KEY; + expect(await extract_working_dir_with_claude("in ~/app")).toBeNull(); + + process.env.ANTHROPIC_API_KEY = "test-key"; + globalThis.fetch = mock(async () => ({ + status: 200, + json: async () => ({ + content: [{ text: JSON.stringify({ path: " ~/project " }) }], + }), + })) as any; + expect(await extract_working_dir_with_claude("in ~/project")).toBe( + "~/project", + ); + + globalThis.fetch = mock(async () => ({ + status: 200, + json: async () => ({ + content: [{ text: JSON.stringify({ path: null }) }], + }), + })) as any; + expect(await extract_working_dir_with_claude("no path")).toBeNull(); + + globalThis.fetch = mock(async () => ({ status: 429 })) as any; + expect(await extract_working_dir_with_claude("rate limited")).toBeNull(); + + globalThis.fetch = mock(async () => ({ + status: 200, + json: async () => ({ content: [{ text: "{bad json" }] }), + })) as any; + expect(await extract_working_dir_with_claude("bad json")).toBeNull(); + + globalThis.fetch = mock(async () => { + throw new Error("network down"); + }) as any; + expect(await extract_working_dir_with_claude("network down")).toBeNull(); + }); + + test("resolve_working_dir prefers extracted path then settings then home", async () => { + const db = new SettingsStub(); + db.values["slack_default_working_dir"] = "/configured"; + + process.env.ANTHROPIC_API_KEY = "test-key"; + globalThis.fetch = mock(async () => ({ + status: 200, + json: async () => ({ + content: [{ text: JSON.stringify({ path: "/extracted" }) }], + }), + })) as any; + expect(await resolve_working_dir("use /extracted", "slack", db)).toBe( + "/extracted", + ); + + delete process.env.ANTHROPIC_API_KEY; + expect(await resolve_working_dir("no extraction", "slack", db)).toBe( + "/configured", + ); + expect(await resolve_working_dir("no setting", "telegram", db)).toBe("~"); + }); +}); diff --git a/backend/tests/executor-wrappers.test.ts b/backend/tests/executor-wrappers.test.ts new file mode 100644 index 0000000..2a3d8ce --- /dev/null +++ b/backend/tests/executor-wrappers.test.ts @@ -0,0 +1,93 @@ +import { describe, expect, test } from "bun:test"; + +import { + default_popen, + default_subprocess_run, + FileNotFoundError, + TimeoutExpired, +} from "../src/executor.ts"; +import { getEnv } from "../src/util.ts"; + +async function collect(iterable: Iterable | AsyncIterable) { + const lines: string[] = []; + for await (const line of iterable) { + lines.push(line); + } + return lines; +} + +describe("executor subprocess wrappers", () => { + test("default_subprocess_run captures stdout, stderr, and return code", () => { + const result = default_subprocess_run( + [ + process.execPath, + "-e", + "console.log('out'); console.error('err'); process.exit(7)", + ], + { cwd: ".", timeout: 5, env: getEnv() }, + ); + + expect(result.returncode).toBe(7); + expect(result.stdout).toContain("out"); + expect(result.stderr).toContain("err"); + }); + + test("default_subprocess_run maps missing binaries and timeouts", () => { + expect(() => + default_subprocess_run(["agentforge-definitely-missing"], { + cwd: ".", + timeout: 5, + env: getEnv(), + }), + ).toThrow(FileNotFoundError); + + expect(() => + default_subprocess_run( + [process.execPath, "-e", "setTimeout(() => {}, 1000)"], + { cwd: ".", timeout: 0.01, env: getEnv() }, + ), + ).toThrow(TimeoutExpired); + }); + + test("default_popen exposes line iterables and waits for exit", async () => { + const proc = await default_popen( + [ + process.execPath, + "-e", + "console.log('line1'); console.log('line2'); console.error('errline')", + ], + { cwd: ".", env: getEnv() }, + ); + + const [stdout, stderr, code] = await Promise.all([ + collect(proc.stdout), + collect(proc.stderr), + proc.wait(), + ]); + + expect(code).toBe(0); + expect(stdout).toEqual(["line1\n", "line2\n"]); + expect(stderr).toEqual(["errline\n"]); + expect(proc.returncode).toBe(0); + }); + + test("default_popen maps spawn errors and wait timeouts", async () => { + await expect( + default_popen(["agentforge-definitely-missing"], { + cwd: ".", + env: getEnv(), + }), + ).rejects.toBeInstanceOf(FileNotFoundError); + + const proc = await default_popen( + [process.execPath, "-e", "setTimeout(() => {}, 1000)"], + { cwd: ".", env: getEnv() }, + ); + try { + await expect(proc.wait(0.01)).rejects.toBeInstanceOf(TimeoutExpired); + } finally { + proc.kill(); + await Promise.resolve(proc.wait()).catch(() => null); + } + }); +}); diff --git a/backend/tests/feishu-channel.test.ts b/backend/tests/feishu-channel.test.ts new file mode 100644 index 0000000..77e2bd1 --- /dev/null +++ b/backend/tests/feishu-channel.test.ts @@ -0,0 +1,1393 @@ +// Ported from tests/test_feishu_*.py (bun:test). +// +// The Python suite mocked the lark SDK and threaded dispatch. The TypeScript +// channel uses async SDK wrappers and structural request objects, so these +// tests inject a small fake client and await the public helper seams directly. + +import { describe, expect, mock, test } from "bun:test"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; + +import { + MessageBus, + makeOutboundMessage, + OutboundMessageType, +} from "../src/bus.ts"; +import { _hooks as dirHooks } from "../src/channels/dir_utils.ts"; +import { + _hooks as feishuHooks, + _FeishuStreamWriter, + _set_feishu_available, + FEISHU_CARD_MARKDOWN_CHUNK, + FEISHU_PANEL_MAX_LINE_ELEMENTS, + FEISHU_THINKING_PREFIX, + FeishuChannel, + HELP_TEXT, + type FeishuScheduler, + type FeishuTaskDB, + type OutputListener, +} from "../src/channels/feishu.ts"; +import type { Task } from "../src/types.ts"; + +type Row = Record; + +class StubDB implements FeishuTaskDB { + settings: Record = {}; + tasks = new Map(); + updated: Array<[number, Row]> = []; + runs: Row[] = []; + events: Row[] = []; + byRoot = new Map(); + + get_setting(key: string, defaultValue: string | null = null): string | null { + return this.settings[key] ?? defaultValue; + } + + set_setting(key: string, value: string): void { + this.settings[key] = value; + } + + get_task(task_id: number): Row | null { + return this.tasks.get(task_id) ?? null; + } + + update_task(task_id: number, updates: Row): void { + this.updated.push([task_id, updates]); + this.tasks.set(task_id, { + ...(this.tasks.get(task_id) ?? { id: task_id }), + ...updates, + }); + } + + get_task_runs(_task_id: number, _limit?: number): Row[] { + return this.runs; + } + + get_run_output_events(_run_id: number, _limit?: number): Row[] { + return this.events; + } + + get_task_by_feishu_root_msg(root_msg_id: string): Row | null { + return this.byRoot.get(root_msg_id) ?? null; + } +} + +class StubScheduler implements FeishuScheduler { + submitted: Task[] = []; + listeners: OutputListener[] = []; + removed: OutputListener[] = []; + + submit_task(task: Task): number { + this.submitted.push(task); + return this.submitted.length; + } + + add_output_listener(cb: OutputListener): void { + this.listeners.push(cb); + } + + remove_output_listener(cb: OutputListener): void { + this.removed.push(cb); + this.listeners = this.listeners.filter((listener) => listener !== cb); + } +} + +function larkResponse( + opts: { + success?: boolean; + messageId?: string; + imageKey?: string; + code?: number; + msg?: string; + raw?: Buffer; + } = {}, +): Row { + const success = opts.success ?? true; + return { + success: () => success, + code: opts.code ?? (success ? 0 : 99), + msg: opts.msg ?? (success ? "ok" : "bad"), + data: { + message_id: opts.messageId, + image_key: opts.imageKey, + }, + raw: { content: opts.raw ?? Buffer.from([]) }, + }; +} + +function makeClient() { + return { + im: { + v1: { + message: { + create: mock(() => larkResponse({ messageId: "om_created" })), + reply: mock(() => larkResponse({ messageId: "om_reply" })), + patch: mock(() => larkResponse()), + }, + image: { + create: mock(() => larkResponse({ imageKey: "img_uploaded" })), + }, + message_resource: { + get: mock(() => larkResponse()), + }, + message_reaction: { + create: mock(() => larkResponse()), + }, + }, + }, + }; +} + +function makeChannel() { + const bus = new MessageBus(); + const db = new StubDB(); + const scheduler = new StubScheduler(); + const channel = new FeishuChannel(bus, db, scheduler); + channel._client = makeClient(); + return { channel, bus, db, scheduler, client: channel._client }; +} + +function textPayload(text: string): string { + return JSON.stringify({ text }); +} + +function makeEvent( + opts: { + content?: string; + messageType?: string; + senderType?: string; + openId?: string; + chatType?: string; + chatId?: string; + messageId?: string; + parentId?: string | null; + rootId?: string | null; + } = {}, +): Row { + return { + event: { + sender: { + sender_type: opts.senderType ?? "user", + sender_id: { open_id: opts.openId ?? "ou_sender" }, + }, + message: { + message_type: opts.messageType ?? "text", + content: opts.content ?? textPayload("hello"), + message_id: opts.messageId ?? "om_msg", + chat_type: opts.chatType ?? "p2p", + chat_id: opts.chatId ?? "oc_chat", + parent_id: opts.parentId ?? null, + root_id: opts.rootId ?? null, + }, + }, + }; +} + +async function withResolvedDir( + value: string, + fn: () => Promise, +): Promise { + const original = dirHooks.extract_working_dir_with_claude; + dirHooks.extract_working_dir_with_claude = async () => value; + try { + return await fn(); + } finally { + dirHooks.extract_working_dir_with_claude = original; + } +} + +function panelTexts(panel: Row): string[] { + return (panel["elements"] as Row[]) + .filter((element) => element["tag"] === "div") + .map((element) => element["text"]["content"]); +} + +describe("Feishu lifecycle", () => { + test("start noops when SDK is unavailable or import fails", async () => { + const { channel, db } = makeChannel(); + db.settings["feishu_app_id"] = "cli_id"; + db.settings["feishu_app_secret"] = "secret"; + channel._client = null; + + _set_feishu_available(false); + try { + await channel._start(); + expect(channel._running).toBe(false); + expect(channel._client).toBeNull(); + } finally { + _set_feishu_available(true); + } + + const original = feishuHooks.import_lark; + feishuHooks.import_lark = async () => { + throw new Error("sdk unavailable"); + }; + try { + await channel._start(); + } finally { + feishuHooks.import_lark = original; + } + + expect(channel._running).toBe(false); + expect(channel._client).toBeNull(); + expect(channel._ws_client).toBeNull(); + }); + + test("start passes an EventDispatcher into WSClient.start and keeps running", async () => { + const { channel, db } = makeChannel(); + db.settings["feishu_app_id"] = "cli_1234567890abcdef"; + db.settings["feishu_app_secret"] = "secret"; + + const start = mock(async (_params: Row) => undefined); + const close = mock((_opts?: Row) => undefined); + const register = mock(function (this: Row, handlers: Row) { + this.handlers = handlers; + return this; + }); + const dispatcher: Row = { register }; + const fakeLark = { + AppType: { SelfBuild: 0 }, + Domain: { Feishu: 0 }, + Client: mock(function Client(this: Row, params: Row) { + this.params = params; + }), + WSClient: mock(function WSClient(_this: Row, params: Row) { + return { params, start, close }; + }), + EventDispatcher: mock(function EventDispatcher() { + return dispatcher; + }), + }; + const original = feishuHooks.import_lark; + feishuHooks.import_lark = async () => fakeLark; + try { + await channel._start(); + await channel._ws_promise; + } finally { + feishuHooks.import_lark = original; + } + + expect(fakeLark.WSClient.mock.calls[0][0]).toEqual({ + appId: "cli_1234567890abcdef", + appSecret: "secret", + }); + expect(register.mock.calls[0][0]).toEqual( + expect.objectContaining({ + "im.message.receive_v1": expect.any(Function), + "im.chat.member.bot.added_v1": expect.any(Function), + "im.message.reaction.created_v1": expect.any(Function), + "im.message.reaction.deleted_v1": expect.any(Function), + }), + ); + expect(start.mock.calls[0][0]).toEqual({ eventDispatcher: dispatcher }); + expect(channel._running).toBe(true); + }); + + test("event dispatcher fallback and websocket connect/error branches", async () => { + const { channel } = makeChannel(); + const dispatcher = channel._build_event_dispatcher({}); + expect(Object.keys(dispatcher.register)).toContain("im.message.receive_v1"); + + const connect = mock(async () => undefined); + channel._running = true; + channel._ws_client = { connect }; + await channel._run_ws(); + expect(connect).toHaveBeenCalledTimes(1); + + channel._running = true; + channel._ws_client = { + start: mock(async () => { + throw new Error("ws down"); + }), + }; + await channel._run_ws({}); + expect(channel._running).toBe(false); + }); + + test("stop handles ws stop, disconnect, close, and thrown close errors", () => { + const { channel } = makeChannel(); + + const stop = mock(() => undefined); + channel._ws_client = { stop }; + channel.stop(); + expect(stop).toHaveBeenCalledTimes(1); + + const disconnect = mock(async () => undefined); + channel._ws_client = { disconnect }; + channel.stop(); + expect(disconnect).toHaveBeenCalledTimes(1); + + const close = mock(() => undefined); + channel._ws_client = { close }; + channel.stop(); + expect((close as any).mock.calls[0][0]).toEqual({ force: true }); + + channel._ws_client = { + close: mock(() => { + throw new Error("close down"); + }), + }; + expect(() => channel.stop()).not.toThrow(); + }); +}); + +describe("Feishu stream writer", () => { + test("formats assistant and trace events without leaking secret fields", () => { + const { channel } = makeChannel(); + const writer = new _FeishuStreamWriter(1, "om_stream", channel, "Task"); + + expect( + writer._display_content( + "assistant", + `${FEISHU_THINKING_PREFIX}thinking aloud`, + ), + ).toBe("thinking aloud"); + expect( + writer._format_trace_event( + "tool_call", + JSON.stringify({ + server: "mcp", + name: "search", + input: { query: "coverage", token: "secret" }, + status: "ok", + }), + ), + ).toContain("mcp.search"); + expect( + writer._format_trace_event( + "tool_result", + JSON.stringify({ is_error: true, tool_use_id: "toolu_1", content: [] }), + ), + ).toContain("工具错误"); + expect( + writer._format_trace_event( + "command_execution", + JSON.stringify({ + command: "bun test", + output: "ok", + exit_code: 0, + status: "done", + }), + ), + ).toContain("退出码 0"); + expect( + writer._format_trace_event( + "file_change", + JSON.stringify({ + changes: [ + { kind: "edit", path: "a.ts" }, + { kind: "add", path: "b.ts" }, + { kind: "delete", path: "c.ts" }, + { kind: "edit", path: "d.ts" }, + ], + }), + ), + ).toContain("等 4 项"); + expect( + writer._format_trace_event( + "web_search", + JSON.stringify({ query: "bun coverage", status: "ok" }), + ), + ).toContain("网页搜索"); + expect(writer._format_trace_event("error", "plain failure")).toContain( + "plain failure", + ); + expect(writer._format_trace_event("custom", "raw")).toContain("[custom]"); + + const compact = writer._compact_trace_summary({ + password: "hidden", + message: "hello\nworld", + }); + expect(compact).toBe("hello"); + expect( + writer._compact_trace_summary([{ text: "first" }, { text: "second" }]), + ).toContain("等 2 项"); + expect(writer._truncate_trace_text("x ".repeat(200), 20)).toEndWith("…"); + }); + + test("patch scheduling writes cards, resets on new run, and stops timers", async () => { + const { channel } = makeChannel(); + channel._patch_message = mock(async () => true) as any; + const writer = new _FeishuStreamWriter(2, "om_stream", channel, "Task"); + writer._last_patch = 0; + + writer.on_event(99, 1, "assistant", "ignored"); + writer.on_event(2, 1, "assistant", "hello"); + writer.on_event(2, 1, "tool_call", JSON.stringify({ name: "tool" })); + await Promise.resolve(); + + expect(writer.snapshot_text()).toContain("hello"); + expect(channel._patch_message).toHaveBeenCalled(); + + writer._last_patch = Date.now() / 1000; + writer.on_event(2, 2, "assistant", "fresh"); + expect(writer.snapshot_text()).toBe("fresh"); + expect(writer._timer).not.toBeNull(); + writer.stop(); + expect(writer._timer).toBeNull(); + writer._dirty = false; + writer._schedule(); + expect(writer._dirty).toBe(false); + }); +}); + +describe("Feishu notification cards", () => { + test("completed card shows result content without task metadata", () => { + const { channel } = makeChannel(); + + const card = channel._build_notification_card({ + task_id: 42, + task: { + id: 42, + title: "Fix Feishu rendering", + prompt: "make it scan well", + agent: "codex", + working_dir: "~/workspace/agentforge", + }, + is_completed: true, + body_text: "Done.\n\n- summary\n- details", + }); + + expect(card["schema"]).toBe("2.0"); + expect(card["config"]["summary"]["content"]).toBe("Done."); + expect(card["body"]["elements"]).toEqual([ + { tag: "markdown", content: "Done.\n\n- summary\n- details" }, + ]); + expect(JSON.stringify(card)).not.toContain("Task #42"); + expect(JSON.stringify(card)).not.toContain("Prompt"); + }); + + test("failed card appends a status hint", () => { + const { channel } = makeChannel(); + + const card = channel._build_notification_card({ + task_id: 7, + task: { id: 7, title: "Broken task", prompt: "debug", agent: "claude" }, + is_completed: false, + body_text: "Traceback: boom", + }); + + expect( + card["body"]["elements"].some( + (element: Row) => + element["tag"] === "markdown" && + String(element["content"]).includes("/status 7"), + ), + ).toBe(true); + }); + + test("streaming history is placed above final result", () => { + const { channel } = makeChannel(); + + const card = channel._build_notification_card({ + task_id: 103, + task: { id: 103, title: "Finished", prompt: "go", agent: "codex" }, + is_completed: true, + body_text: "final result", + streaming_history: "step one\nstep two", + }); + + const [panel, result] = card["body"]["elements"]; + expect(panel["tag"]).toBe("collapsible_panel"); + expect(panel["expanded"]).toBe(false); + expect(panel["header"]["title"]["content"]).toBe("执行过程"); + expect(panelTexts(panel)).toEqual(["step one", "step two"]); + expect(result).toEqual({ tag: "markdown", content: "final result" }); + }); +}); + +describe("Feishu outbound dispatch", () => { + test("non-terminal outbound messages are ignored", async () => { + const { channel, db } = makeChannel(); + db.get_task = mock(() => null) as any; + + await channel._send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_STARTED, + task_id: 1, + }), + ); + + expect((db.get_task as any).mock.calls).toHaveLength(0); + }); + + test("terminal outbound messages handle missing client, task, and destination", async () => { + const { channel, db } = makeChannel(); + + channel._client = null; + await channel._send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_COMPLETED, + task_id: 1, + }), + ); + + channel._client = makeClient(); + await channel._send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_COMPLETED, + task_id: 404, + }), + ); + + db.tasks.set(12, { id: 12, title: "No destination", result: "" }); + await channel._send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_COMPLETED, + task_id: 12, + }), + ); + + expect(channel._notification_map.size).toBe(0); + }); + + test("completed notification falls back to default chat and maps message id", async () => { + const { channel, db } = makeChannel(); + db.settings["feishu_default_chat_id"] = "oc_default"; + db.tasks.set(5, { + id: 5, + title: "Done", + prompt: "p", + agent: "codex", + result: "all good", + }); + channel._stop_streaming = mock(() => null) as any; + channel._collect_generated_image_paths = mock(() => []) as any; + channel._send_message = mock(async () => "om_sent") as any; + + await channel._send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_COMPLETED, + task_id: 5, + payload: { result: "all good" }, + }), + ); + + expect((channel._send_message as any).mock.calls[0][0]).toBe("oc_default"); + expect((channel._send_message as any).mock.calls[0][1]).toBe("all good"); + expect((channel._send_message as any).mock.calls[0][3]).toBe("all good"); + expect(channel._notification_map.get("om_sent")).toBe(5); + }); + + test("failed notification replies to origin and uses cry reaction", async () => { + const { channel, db } = makeChannel(); + db.tasks.set(8, { + id: 8, + title: "Boom", + prompt: "p", + agent: "codex", + result: null, + }); + channel._task_origin.set(8, ["oc_chat", "om_root", "om_trigger"]); + channel._stop_streaming = mock(() => null) as any; + channel._add_reaction = mock(() => undefined) as any; + channel._reply_message = mock(async () => "om_reply") as any; + + await channel._send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_FAILED, + task_id: 8, + payload: { error: "nope" }, + }), + ); + + expect((channel._add_reaction as any).mock.calls[0]).toEqual([ + "om_trigger", + "Cry", + ]); + expect((channel._reply_message as any).mock.calls[0][0]).toBe("om_root"); + expect(channel._notification_map.get("om_reply")).toBe(8); + expect(channel._task_origin.has(8)).toBe(false); + }); + + test("streaming card is patched when present", async () => { + const { channel, db } = makeChannel(); + db.tasks.set(9, { + id: 9, + title: "Done", + prompt: "p", + agent: "codex", + result: "final", + }); + channel._task_origin.set(9, ["oc_chat", "om_root", "om_trigger"]); + channel._streaming_msg.set(9, "om_stream"); + channel._stop_streaming = mock(() => "history") as any; + channel._collect_generated_image_paths = mock(() => []) as any; + channel._add_reaction = mock(() => undefined) as any; + channel._patch_message = mock(async () => true) as any; + channel._reply_message = mock(async () => "om_reply") as any; + + await channel._send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_COMPLETED, + task_id: 9, + payload: { result: "final" }, + }), + ); + + expect((channel._patch_message as any).mock.calls[0][0]).toBe("om_stream"); + expect((channel._reply_message as any).mock.calls).toHaveLength(0); + expect(channel._notification_map.get("om_stream")).toBe(9); + }); + + test("uploaded generated images are attached to the card", async () => { + const { channel, db } = makeChannel(); + db.settings["feishu_default_chat_id"] = "oc_default"; + db.tasks.set(11, { + id: 11, + title: "Image", + prompt: "p", + agent: "codex", + result: "see image", + }); + channel._stop_streaming = mock(() => null) as any; + channel._collect_generated_image_paths = mock(() => ["/tmp/a.png"]) as any; + channel._upload_image_entries = mock(async () => [ + ["/tmp/a.png", "img_key_1"], + ]) as any; + channel._hide_generated_image_paths = mock(() => "see image") as any; + channel._send_message = mock(async () => "om_sent") as any; + + await channel._send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_COMPLETED, + task_id: 11, + payload: { result: "see image" }, + }), + ); + + const card = (channel._send_message as any).mock.calls[0][2]; + expect(card["body"]["elements"].at(-1)).toEqual({ + tag: "img", + img_key: "img_key_1", + alt: { tag: "plain_text", content: "generated image 1" }, + }); + }); +}); + +describe("Feishu SDK wrappers", () => { + test("create message returns message id and sends interactive content", async () => { + const { channel, client } = makeChannel(); + + const result = await channel._create_message("chat_id", "oc_x", { + schema: "2.0", + }); + + expect(result).toBe("om_created"); + const req = client.im.v1.message.create.mock.calls[0][0]; + expect(req.receive_id_type).toBe("chat_id"); + expect(req.request_body.receive_id).toBe("oc_x"); + expect(req.request_body.msg_type).toBe("interactive"); + expect(JSON.parse(req.request_body.content)).toEqual({ schema: "2.0" }); + }); + + test("create reply sets reply-in-thread flag", async () => { + const { channel, client } = makeChannel(); + + const result = await channel._create_reply("om_parent", { schema: "2.0" }); + + expect(result).toBe("om_reply"); + const req = client.im.v1.message.reply.mock.calls[0][0]; + expect(req.message_id).toBe("om_parent"); + expect(req.request_body.reply_in_thread).toBe(true); + expect(req.request_body.msg_type).toBe("interactive"); + }); + + test("send message falls back to legacy markdown card when card send fails", async () => { + const { channel, client } = makeChannel(); + client.im.v1.message.create + .mockImplementationOnce(() => larkResponse({ success: false })) + .mockImplementationOnce(() => larkResponse({ messageId: "om_fallback" })); + + const result = await channel._send_message( + "oc_chat", + "visible content", + { schema: "2.0" }, + "fallback", + ); + + expect(result).toBe("om_fallback"); + expect(client.im.v1.message.create.mock.calls).toHaveLength(2); + const fallbackReq = client.im.v1.message.create.mock.calls[1][0]; + expect(JSON.parse(fallbackReq.request_body.content)).toEqual({ + config: { wide_screen_mode: true }, + elements: [{ tag: "markdown", content: "fallback" }], + }); + }); + + test("message, reply, patch, reaction, and upload wrappers cover fallback paths", async () => { + const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "agentforge-feishu-")); + const imagePath = path.join(tmpDir, "upload.png"); + fs.writeFileSync(imagePath, Buffer.from([0x89, 0x50, 0x4e, 0x47])); + const legacyClient: Row = { + im: { + message: { + create: mock(() => ({ code: 0, data: { messageId: "om_legacy" } })), + reply: mock(() => ({ success: true, message_id: "om_reply_legacy" })), + patch: mock(() => ({ code: 0 })), + }, + image: { + create: mock(() => ({ code: 0, data: { imageKey: "img_legacy" } })), + }, + messageReaction: { + create: mock(() => ({ code: 0 })), + }, + }, + }; + const { channel } = makeChannel(); + channel._client = legacyClient; + + try { + expect(await channel._send_message("ou_user", "hello")).toBe("om_legacy"); + expect( + legacyClient.im.message.create.mock.calls[0][0].receive_id_type, + ).toBe("open_id"); + expect(await channel._reply_message("om_parent", "reply")).toBe( + "om_reply_legacy", + ); + expect(await channel._patch_message("om_parent", { schema: "2.0" })).toBe( + true, + ); + expect(await channel._upload_image(imagePath)).toBe("img_legacy"); + expect(await channel._upload_images([imagePath])).toEqual(["img_legacy"]); + + legacyClient.im.message.create.mockImplementationOnce(() => { + throw new Error("send down"); + }); + expect(await channel._send_message("oc_chat", "hello")).toBeNull(); + + legacyClient.im.message.reply.mockImplementationOnce(() => { + throw new Error("reply down"); + }); + expect(await channel._reply_message("om_parent", "hello")).toBeNull(); + + legacyClient.im.message.patch.mockImplementationOnce(() => ({ + code: 99, + msg: "bad", + })); + expect(await channel._patch_message("om_parent", {})).toBe(false); + legacyClient.im.message.patch.mockImplementationOnce(() => { + throw new Error("patch down"); + }); + expect(await channel._patch_message("om_parent", {})).toBe(false); + + legacyClient.im.image.create.mockImplementationOnce(() => ({ + code: 99, + msg: "bad image", + })); + expect(await channel._upload_image(imagePath)).toBeNull(); + expect( + await channel._upload_image(path.join(tmpDir, "missing.png")), + ).toBeNull(); + + channel._add_reaction("om_parent", "OK"); + await Promise.resolve(); + expect(legacyClient.im.messageReaction.create).toHaveBeenCalled(); + legacyClient.im.messageReaction.create.mockImplementationOnce(() => { + throw new Error("reaction down"); + }); + channel._add_reaction("om_parent", "OK"); + await Promise.resolve(); + } finally { + fs.rmSync(tmpDir, { recursive: true, force: true }); + } + }); +}); + +describe("Feishu rendering and image helpers", () => { + test("streaming and result card helpers chunk and truncate content", () => { + const { channel } = makeChannel(); + + expect( + channel._build_streaming_card(1, "Task", "", false)["body"]["elements"], + ).toEqual([{ tag: "markdown", content: "Thinking ▌" }]); + expect( + channel._build_streaming_card(1, "Task", "done\r\nok", true)["body"][ + "elements" + ][0]["content"], + ).toBe("done\nok"); + + const manyLines = Array.from( + { length: FEISHU_PANEL_MAX_LINE_ELEMENTS + 1 }, + (_, i) => `line ${i}`, + ).join("\n"); + expect(channel._build_streaming_history_elements(manyLines)[0]["tag"]).toBe( + "markdown", + ); + expect( + channel._build_result_elements( + "x".repeat(FEISHU_CARD_MARKDOWN_CHUNK + 2), + ), + ).toHaveLength(2); + expect(channel._build_result_elements("", ["img_a"])).toEqual([ + { tag: "markdown", content: "Done." }, + { + tag: "img", + img_key: "img_a", + alt: { tag: "plain_text", content: "generated image 1" }, + }, + ]); + expect( + channel._strip_final_result_from_history("step\nfinal", "final"), + ).toBe("step"); + expect(channel._strip_final_result_from_history("step", "")).toBe("step"); + expect(channel._truncate_text("a".repeat(10), 5)).toBe( + "aaaaa\n…(truncated)", + ); + expect(channel._chunk_text("", 5)).toEqual([""]); + expect(channel._escape_feishu_markdown("\\")).toBe("\\\\"); + }); + + test("generated image helpers collect, normalize, and hide uploaded paths", () => { + const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "agentforge-feishu-")); + const eventImage = path.join(tmpDir, "event.png"); + const markdownImage = path.join(tmpDir, "markdown image.png"); + fs.writeFileSync(eventImage, Buffer.from([0x89, 0x50, 0x4e, 0x47])); + fs.writeFileSync(markdownImage, Buffer.from([0x89, 0x50, 0x4e, 0x47])); + const { channel, db } = makeChannel(); + db.runs = [{ id: 5 }]; + db.events = [ + { event_type: "generated_image", content: "bad json" }, + { + event_type: "generated_image", + content: JSON.stringify({ path: eventImage }), + }, + { + event_type: "generated_image", + content: JSON.stringify({ path: eventImage }), + }, + ]; + + try { + expect( + channel._collect_generated_image_paths( + 1, + `![m](markdown%20image.png)\n![r](https://example.test/x.png)`, + { working_dir: tmpDir }, + ), + ).toEqual([fs.realpathSync(eventImage), fs.realpathSync(markdownImage)]); + expect( + channel._local_image_path_from_reference(`file://${eventImage}`), + ).toBe(fs.realpathSync(eventImage)); + expect( + channel._local_image_path_from_reference(`sandbox:${eventImage}`), + ).toBe(fs.realpathSync(eventImage)); + expect( + channel._local_image_path_from_reference("'bad.txt'", tmpDir), + ).toBeNull(); + expect(channel._markdown_image_reference_target(`<${eventImage}>`)).toBe( + eventImage, + ); + expect( + channel._dedupe_image_paths([eventImage, eventImage, null as any]), + ).toEqual([fs.realpathSync(eventImage)]); + expect( + channel._line_is_uploaded_image_path( + `- ${eventImage}`, + new Set([fs.realpathSync(eventImage)]), + ), + ).toBe(true); + expect( + channel._line_is_uploaded_image_path( + "- /tmp/.codex/generated_images/x.png", + new Set(), + ), + ).toBe(true); + expect( + channel._remove_uploaded_markdown_image_refs( + `before ![x](${eventImage}) after`, + new Set([fs.realpathSync(eventImage)]), + ), + ).toBe("before after"); + expect( + channel._hide_generated_image_paths(`Done\n- ${eventImage}\n-`, 1, [ + eventImage, + ]), + ).toBe("Done"); + expect(channel._hide_generated_image_paths("已生成图片", 2, [])).toBe( + "已生成 2 张图片。", + ); + + db.get_task_runs = mock(() => { + throw new Error("runs down"); + }) as any; + expect(channel._generated_image_paths_for_task(1)).toEqual([]); + db.get_task_runs = mock(() => [{ id: 5 }]) as any; + db.get_run_output_events = mock(() => { + throw new Error("events down"); + }) as any; + expect(channel._generated_image_paths_for_task(1)).toEqual([]); + } finally { + fs.rmSync(tmpDir, { recursive: true, force: true }); + } + }); +}); + +describe("Feishu forwarded, media, and command handling", () => { + test("forwarded content parsing and formatting handles supported shapes", () => { + const { channel } = makeChannel(); + + const direct = channel._extract_forwarded_content({ + message_type: "forward", + content: JSON.stringify({ + sender_name: "Ada", + sender_id: "ou_ada", + create_time: 1700000000, + text: "forwarded body", + images: [{ image_key: "img_1" }], + }), + })!; + expect(direct["sender_name"]).toBe("Ada"); + expect( + channel._format_forwarded_prompt("please inspect", direct), + ).toContain("用户附加消息"); + expect(channel._format_forwarded_prompt("", direct)).toContain( + "包含 1 张图片", + ); + + expect( + channel._extract_forwarded_content({ + message_type: "forward", + content: "{bad json", + }), + ).toBeNull(); + expect( + channel._extract_forwarded_content({ + message_type: "post", + content: JSON.stringify({ + content: [ + [ + { + tag: "quote", + user: { name: "Lin", open_id: "ou_lin" }, + text: "quoted", + }, + ], + ], + }), + })!["type"], + ).toBe("quote"); + expect( + channel._extract_forwarded_content({ + message_type: "post", + content: JSON.stringify({ + zh_cn: { + content: [ + [ + { + tag: "nested_message", + nested_message: { + sender_name: "Nested", + text: "nested body", + }, + }, + ], + ], + }, + }), + })!["sender_name"], + ).toBe("Nested"); + expect( + channel._extract_forwarded_content({ + message_type: "post", + content: "{bad json", + }), + ).toBeNull(); + }); + + test("download and parse message content cover text, post, image, and unknown", async () => { + const { channel, client } = makeChannel(); + const payloads = [ + Buffer.from([0xff, 0xd8, 0xff]), + Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]), + Buffer.from("GIF89a"), + Buffer.from("RIFFxxxxWEBP"), + ]; + client.im.v1.message_resource.get = mock(() => + larkResponse({ raw: payloads.shift() ?? Buffer.from([]) }), + ); + + const downloaded = [ + await channel._download_image("om", "jpg_key"), + await channel._download_image("om", "png_key"), + await channel._download_image("om", "gif_key"), + await channel._download_image("om", "webp_key"), + ]; + expect(downloaded.map((p) => path.extname(p ?? ""))).toEqual([ + ".jpg", + ".png", + ".gif", + ".webp", + ]); + + client.im.v1.message_resource.get = mock(() => + larkResponse({ success: false }), + ); + expect(await channel._download_image("om", "missing")).toBeNull(); + client.im.v1.message_resource.get = mock(() => { + throw new Error("download down"); + }); + expect(await channel._download_image("om", "throwing")).toBeNull(); + + expect( + await channel._parse_message_content({ + message_type: "text", + content: JSON.stringify({ text: " hi " }), + }), + ).toEqual({ content: "hi", image_paths: [] }); + expect( + await channel._parse_message_content({ + message_type: "text", + content: " raw ", + }), + ).toEqual({ content: "raw", image_paths: [] }); + channel._download_image = mock(async () => "/tmp/img.png") as any; + expect( + await channel._parse_message_content({ + message_type: "post", + message_id: "om_post", + content: JSON.stringify({ + zh_cn: { + title: "Title", + content: [ + [ + { tag: "text", text: "body" }, + { tag: "img", image_key: "img" }, + ], + ], + }, + }), + }), + ).toEqual({ content: "Title\nbody", image_paths: ["/tmp/img.png"] }); + expect( + await channel._parse_message_content({ + message_type: "post", + content: "{bad json", + }), + ).toEqual({ content: "", image_paths: [] }); + expect( + await channel._parse_message_content({ + message_type: "image", + message_id: "om_img", + content: JSON.stringify({ image_key: "img" }), + }), + ).toEqual({ + content: "请分析这张图片的内容", + image_paths: ["/tmp/img.png"], + }); + expect( + await channel._parse_message_content({ + message_type: "image", + content: "{bad json", + }), + ).toEqual({ content: "请分析这张图片的内容", image_paths: [] }); + expect( + await channel._parse_message_content({ message_type: "audio" }), + ).toBeNull(); + }); + + test("inbound command branches reply without creating tasks", async () => { + const { channel, db, scheduler } = makeChannel(); + db.tasks.set(9, { id: 9, status: "running", title: "Run task" }); + channel._send_message = mock(async () => "om_reply") as any; + channel._add_reaction = mock(() => undefined) as any; + + await channel._handle_inbound(makeEvent({ senderType: "bot" })); + await channel._handle_inbound(makeEvent({ content: textPayload("/help") })); + await channel._handle_inbound( + makeEvent({ content: textPayload("/start") }), + ); + await channel._handle_inbound( + makeEvent({ content: textPayload("/dir /tmp/app") }), + ); + await channel._handle_inbound( + makeEvent({ content: textPayload("/agent codex") }), + ); + await channel._handle_inbound(makeEvent({ content: textPayload("/ccu") })); + await channel._handle_inbound( + makeEvent({ content: textPayload("/status nope") }), + ); + await channel._handle_inbound( + makeEvent({ content: textPayload("/status 404") }), + ); + await channel._handle_inbound( + makeEvent({ content: textPayload("/status 9") }), + ); + await channel._handle_inbound( + makeEvent({ content: textPayload("task completed notification") }), + ); + + expect(scheduler.submitted).toHaveLength(0); + const sent = (channel._send_message as any).mock.calls.map( + (call: Row[]) => call[1], + ); + expect(sent.some((text: string) => text.includes("AgentForge Bot"))).toBe( + true, + ); + expect( + sent.some((text: string) => text.includes("Working directory")), + ).toBe(true); + expect( + sent.some((text: string) => text.includes("Default agent switched")), + ).toBe(true); + expect(sent.some((text: string) => text.includes("Claude Code 用量"))).toBe( + true, + ); + expect(sent.some((text: string) => text.includes("not found"))).toBe(true); + expect(sent.some((text: string) => text.includes("Run task"))).toBe(true); + }); + + test("resume command and thread resume cover usage, missing, mapped, and DB root paths", async () => { + const { channel, db } = makeChannel(); + channel._send_message = mock(async () => "om_sent") as any; + channel._reply_message = mock(async () => "om_thread_reply") as any; + channel._create_reply = mock(async () => "om_running") as any; + channel._start_streaming = mock(() => undefined) as any; + + await channel._handle_resume_command("/resume nope", "ou_user", { + message_id: "om_resume", + }); + await channel._handle_resume_command("/resume 404 go", "ou_user", { + message_id: "om_resume", + }); + db.tasks.set(10, { id: 10, title: "Resume", session_id: "sess" }); + await channel._handle_resume_command("/resume 10 continue", "ou_user", { + message_id: "om_resume", + }); + + expect(db.updated.at(-1)).toEqual([ + 10, + { + status: "pending", + prompt: "continue", + result: null, + error: null, + question: null, + }, + ]); + expect(channel._task_origin.get(10)).toEqual([ + "ou_user", + "om_resume", + "om_resume", + ]); + + channel._notification_map.set("om_parent", 11); + db.tasks.set(11, { id: 11, title: "No session" }); + expect( + await channel._try_resume_thread_message( + "continue", + "ou_user", + { message_id: "om_child" }, + "om_parent", + null, + ), + ).toBe(true); + expect((channel._reply_message as any).mock.calls.at(-1)[1]).toContain( + "no saved session", + ); + + db.byRoot.set("om_root", { id: 12 }); + db.tasks.set(12, { id: 12, title: "Root task", session_id: "sess12" }); + expect( + await channel._try_resume_thread_message( + "root continue", + "ou_user", + { message_id: "om_child2" }, + null, + "om_root", + ), + ).toBe(true); + expect(db.updated.at(-1)![0]).toBe(12); + expect( + await channel._try_resume_thread_message( + "no map", + "ou_user", + { message_id: "om_child3" }, + "none", + null, + ), + ).toBe(false); + }); +}); + +describe("Feishu inbound handling", () => { + test("bot-added event sends help text", () => { + const { channel } = makeChannel(); + channel._send_message = mock(async () => "om_help") as any; + + channel._on_bot_added({ event: { chat_id: "oc_new" } }); + + expect((channel._send_message as any).mock.calls[0]).toEqual([ + "oc_new", + HELP_TEXT, + ]); + }); + + test("plain text message creates a task and starts a streaming reply", async () => { + const { channel, db, scheduler } = makeChannel(); + db.settings["default_agent"] = "claude"; + channel._add_reaction = mock(() => undefined) as any; + channel._create_reply = mock(async () => "om_running") as any; + channel._start_streaming = mock(() => undefined) as any; + + await withResolvedDir("/tmp/project", async () => { + await channel._handle_inbound( + makeEvent({ + content: textPayload("fix login"), + messageId: "om_root", + }), + ); + }); + + expect((channel._add_reaction as any).mock.calls[0]).toEqual([ + "om_root", + "OK", + ]); + expect(scheduler.submitted).toHaveLength(1); + const task = scheduler.submitted[0]!; + expect(task.title).toBe("[Feishu] fix login"); + expect(task.prompt).toBe("fix login"); + expect(task.working_dir).toBe("/tmp/project"); + expect(task.tags).toBe("feishu"); + expect(task.feishu_root_msg_id).toBe("om_root"); + expect(task.agent).toBe("claude"); + expect(channel._root_msg_map.get("om_root")).toBe(1); + expect(channel._task_origin.get(1)).toEqual([ + "ou_sender", + "om_root", + "om_root", + ]); + expect((channel._create_reply as any).mock.calls[0][0]).toBe("om_root"); + expect((channel._start_streaming as any).mock.calls[0][0]).toBe(1); + }); + + test("post message with only an image creates default image-analysis prompt", async () => { + const { channel, scheduler } = makeChannel(); + const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "agentforge-feishu-")); + const imagePath = path.join(tmpDir, "pic.png"); + fs.writeFileSync(imagePath, Buffer.from([0x89, 0x50, 0x4e, 0x47])); + channel._download_image = mock(async () => imagePath) as any; + channel._add_reaction = mock(() => undefined) as any; + channel._create_reply = mock(async () => null) as any; + + try { + await withResolvedDir("/tmp", async () => { + await channel._handle_inbound( + makeEvent({ + messageType: "post", + content: JSON.stringify({ + content: [[{ tag: "img", image_key: "img_x" }]], + }), + messageId: "om_img", + }), + ); + }); + } finally { + fs.rmSync(tmpDir, { recursive: true, force: true }); + } + + expect(scheduler.submitted).toHaveLength(1); + expect(scheduler.submitted[0]!.prompt).toBe("请分析这些图片的内容"); + expect(scheduler.submitted[0]!.image_paths).toEqual([imagePath]); + expect(scheduler.submitted[0]!.prompt_images).toHaveLength(1); + }); + + test("resume command updates task and starts streaming", async () => { + const { channel, db } = makeChannel(); + db.tasks.set(12, { + id: 12, + title: "Existing task", + session_id: "sess_1", + status: "completed", + }); + channel._add_reaction = mock(() => undefined) as any; + channel._create_reply = mock(async () => "om_running") as any; + channel._start_streaming = mock(() => undefined) as any; + + await channel._handle_inbound( + makeEvent({ + content: textPayload("/resume 12 continue please"), + messageId: "om_resume", + }), + ); + + expect(db.updated[0]).toEqual([ + 12, + { + status: "pending", + prompt: "continue please", + result: null, + error: null, + question: null, + }, + ]); + expect(channel._task_origin.get(12)).toEqual([ + "ou_sender", + "om_resume", + "om_resume", + ]); + expect((channel._start_streaming as any).mock.calls[0][0]).toBe(12); + }); + + test("reply in a mapped thread resumes the task", async () => { + const { channel, db } = makeChannel(); + db.tasks.set(33, { + id: 33, + title: "Mapped task", + session_id: "sess_33", + status: "completed", + }); + channel._notification_map.set("om_parent", 33); + channel._add_reaction = mock(() => undefined) as any; + channel._create_reply = mock(async () => "om_running") as any; + channel._start_streaming = mock(() => undefined) as any; + + await channel._handle_inbound( + makeEvent({ + content: textPayload("continue from thread"), + messageId: "om_child", + parentId: "om_parent", + }), + ); + + expect(db.updated[0]![0]).toBe(33); + expect(db.updated[0]![1]["prompt"]).toBe("continue from thread"); + expect(channel._task_origin.get(33)).toEqual([ + "ou_sender", + "om_parent", + "om_child", + ]); + }); +}); + +describe("Feishu streaming listener lifecycle", () => { + test("start and stop streaming unregister the exact listener", () => { + const { channel, scheduler } = makeChannel(); + + channel._start_streaming(44, "om_stream", "Streaming task"); + expect(scheduler.listeners).toHaveLength(1); + const listener = scheduler.listeners[0]!; + + const history = channel._stop_streaming(44); + + expect(history).toBe(""); + expect(scheduler.removed).toEqual([listener]); + expect(scheduler.listeners).toHaveLength(0); + expect(channel._writer_listeners.has(44)).toBe(false); + }); + + test("stop unregisters active writer listeners", () => { + const { channel, scheduler } = makeChannel(); + + channel._start_streaming(45, "om_stream", "Streaming task"); + const listener = scheduler.listeners[0]!; + channel.stop(); + + expect(scheduler.removed).toContain(listener); + expect(scheduler.listeners).toHaveLength(0); + expect(channel._writers.size).toBe(0); + expect(channel._writer_listeners.size).toBe(0); + expect(channel._streaming_msg.size).toBe(0); + }); +}); diff --git a/backend/tests/gaps.test.ts b/backend/tests/gaps.test.ts index b6d2fb5..2cc0cc4 100644 --- a/backend/tests/gaps.test.ts +++ b/backend/tests/gaps.test.ts @@ -3,11 +3,8 @@ // Ported from tests/test_taskboard_gaps.py; test() descriptions keep the // Python test function names. // -// SKIPPED (exercise the HTTP API / run_server lifecycle — owned by the API -// handler test suite, not ported here): -// - test_run_server_starts_all_channels_via_settings -// - test_run_server_auto_enables_telegram_and_slack_via_env -// - test_run_server_telegram_factory_returns_none_no_start +// HTTP API and Bun server lifecycle branches live in api-handler.test.ts and +// server-lifecycle.test.ts. import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import fs from "node:fs"; diff --git a/backend/tests/gaps2.test.ts b/backend/tests/gaps2.test.ts index 0017d7e..fa90c1f 100644 --- a/backend/tests/gaps2.test.ts +++ b/backend/tests/gaps2.test.ts @@ -12,18 +12,7 @@ // _execute_task EDGE branches (magic-byte media sniffing, unsafe-path // rejection, the sub-agent wait loop, the notify fan-out). // -// SKIPPED (exercise the HTTP API handler — owned by the API handler test -// suite, not ported here): -// - test_feishu_settings_restart_stops_old_and_starts_new -// - test_channels_settings_restart_all_three -// - test_telegram_restart_factory_returns_none -// - test_create_dag_prompt_images_json_string -// - test_create_dag_prompt_images_bad_json_falls_back -// - test_task_resume_not_found -// - test_delete_csrf_rejected -// - test_delete_csrf_accepted_with_token -// - test_post_body_too_large_returns_413 -// - test_read_body_too_large_drains_declared_body +// HTTP API handler branches live in api-handler.test.ts. import { afterEach, beforeEach, describe, expect, test } from "bun:test"; import fs from "node:fs"; diff --git a/backend/tests/server-lifecycle.test.ts b/backend/tests/server-lifecycle.test.ts new file mode 100644 index 0000000..7913969 --- /dev/null +++ b/backend/tests/server-lifecycle.test.ts @@ -0,0 +1,122 @@ +// Ported from tests/test_server_lifecycle.py for the Bun server shape. +// +// The Python QuietHTTPServer hook no longer exists; the stable lifecycle +// contract is that runServer owns a loopback Bun server, a TaskDB under HOME, +// default-disabled channels, and a clean stop path. + +import { afterEach, beforeEach, describe, expect, test } from "bun:test"; +import fs from "node:fs"; +import net from "node:net"; +import os from "node:os"; +import path from "node:path"; + +import { TaskDB } from "../src/db.ts"; +import { + killStaleProcessOnPort, + runServer, + type RunningServer, +} from "../src/server.ts"; + +async function freePort(): Promise { + return await new Promise((resolve, reject) => { + const srv = net.createServer(); + srv.once("error", reject); + srv.listen(0, "127.0.0.1", () => { + const address = srv.address(); + srv.close(() => { + if (address && typeof address === "object") resolve(address.port); + else reject(new Error("failed to allocate a free port")); + }); + }); + }); +} + +describe("server lifecycle", () => { + let tmpDir: string; + let savedHome: string | undefined; + let savedTelegramToken: string | undefined; + let savedSlackBotToken: string | undefined; + let savedSlackAppToken: string | undefined; + let running: RunningServer | null; + + beforeEach(() => { + tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "agentforge-server-")); + savedHome = process.env.HOME; + savedTelegramToken = process.env.TELEGRAM_BOT_TOKEN; + savedSlackBotToken = process.env.SLACK_BOT_TOKEN; + savedSlackAppToken = process.env.SLACK_APP_TOKEN; + process.env.HOME = tmpDir; + delete process.env.TELEGRAM_BOT_TOKEN; + delete process.env.SLACK_BOT_TOKEN; + delete process.env.SLACK_APP_TOKEN; + running = null; + }); + + afterEach(async () => { + if (running) { + await running.stop(); + running = null; + } + if (savedHome === undefined) delete process.env.HOME; + else process.env.HOME = savedHome; + if (savedTelegramToken === undefined) delete process.env.TELEGRAM_BOT_TOKEN; + else process.env.TELEGRAM_BOT_TOKEN = savedTelegramToken; + if (savedSlackBotToken === undefined) delete process.env.SLACK_BOT_TOKEN; + else process.env.SLACK_BOT_TOKEN = savedSlackBotToken; + if (savedSlackAppToken === undefined) delete process.env.SLACK_APP_TOKEN; + else process.env.SLACK_APP_TOKEN = savedSlackAppToken; + fs.rmSync(tmpDir, { recursive: true, force: true }); + }); + + test("runServer serves health and leaves channels disabled by default", async () => { + const port = await freePort(); + const dbPath = path.join(tmpDir, ".agentforge", "tasks.db"); + + running = await runServer(port, dbPath); + + const res = await fetch(`http://127.0.0.1:${port}/api/health`); + expect(res.status).toBe(200); + expect(await res.json()).toEqual({ status: "ok", tasks: 0 }); + expect(running.context.telegram_channel).toBeNull(); + expect(running.context.slack_channel).toBeNull(); + expect(running.context.weixin_channel).toBeNull(); + expect(running.context.feishu_channel).toBeNull(); + expect(fs.existsSync(path.join(tmpDir, ".agentforge", "tasks.db"))).toBe( + true, + ); + }); + + test("runServer creates a Feishu channel when settings enable it", async () => { + const dbPath = path.join(tmpDir, ".agentforge", "tasks.db"); + const seed = new TaskDB(dbPath); + seed.set_setting("feishu_enabled", "true"); + seed.conn.close(); + const port = await freePort(); + + running = await runServer(port, dbPath); + + expect(running.context.feishu_channel?.name).toBe("feishu"); + expect(running.context.feishu_channel?._running).toBe(false); + }); + + test("killStaleProcessOnPort handles closed ports and same-process listeners", async () => { + await killStaleProcessOnPort(await freePort()); + + const srv = net.createServer(); + const port = await new Promise((resolve, reject) => { + srv.once("error", reject); + srv.listen(0, "127.0.0.1", () => { + const address = srv.address(); + if (address && typeof address === "object") resolve(address.port); + else reject(new Error("failed to listen")); + }); + }); + + try { + await killStaleProcessOnPort(port); + expect(srv.listening).toBe(true); + } finally { + await new Promise((resolve) => srv.close(() => resolve())); + } + }); +}); diff --git a/backend/tests/slack-more.test.ts b/backend/tests/slack-more.test.ts index 4a9744f..3f17559 100644 --- a/backend/tests/slack-more.test.ts +++ b/backend/tests/slack-more.test.ts @@ -149,7 +149,9 @@ test("test_require_slack_raises_on_missing_dependency", async () => { } catch (e) { error = e as Error; } - expect(String(error)).toContain("slack-sdk is required"); + expect(String(error)).toContain( + "@slack/web-api and @slack/socket-mode are required", + ); } finally { slack_hooks.import_slack = orig; } diff --git a/backend/tests/telegram-channel.test.ts b/backend/tests/telegram-channel.test.ts index c08ae35..b5af534 100644 --- a/backend/tests/telegram-channel.test.ts +++ b/backend/tests/telegram-channel.test.ts @@ -696,5 +696,5 @@ test("test_start_without_telegram", () => { log.restore(); _set_telegram_available(true); } - expect(log.text()).toContain("not installed"); + expect(log.text()).toContain("Telegram Bot API transport unavailable"); }); diff --git a/backend/tests/weixin-channel.test.ts b/backend/tests/weixin-channel.test.ts new file mode 100644 index 0000000..1356b27 --- /dev/null +++ b/backend/tests/weixin-channel.test.ts @@ -0,0 +1,759 @@ +// Weixin channel startup tests. +// +// The Weixin channel uses a sidecar bridge process instead of a chat SDK. These +// tests lock down the packaging-sensitive command selection and spawn env. + +import { afterEach, describe, expect, mock, test } from "bun:test"; +import fs from "node:fs"; +import os from "node:os"; +import path from "node:path"; + +import { + makeOutboundMessage, + MessageBus, + OutboundMessageType, +} from "../src/bus.ts"; +import { _hooks as dirHooks } from "../src/channels/dir_utils.ts"; +import { + _find_bun_executable, + _hooks, + WeixinChannel, + type WeixinBridgeProcess, + type WeixinScheduler, + type WeixinTaskDB, +} from "../src/channels/weixin.ts"; +import type { Task } from "../src/types.ts"; + +type Row = Record; + +class StubDB implements WeixinTaskDB { + settings: Record = {}; + tasks = new Map(); + updated: Array<[number, Row]> = []; + runs: unknown = []; + events: unknown = []; + + get_task(task_id: number): Row | null { + return this.tasks.get(task_id) ?? null; + } + + get_setting(key: string, defaultValue: string | null = null): string | null { + return this.settings[key] ?? defaultValue; + } + + set_setting(key: string, value: string): void { + this.settings[key] = value; + } + + update_task(task_id: number, updates: Record): void { + this.updated.push([task_id, updates]); + this.tasks.set(task_id, { + ...(this.tasks.get(task_id) ?? { id: task_id }), + ...updates, + }); + } + + get_task_runs(_task_id: number, _limit?: number): unknown { + return this.runs; + } + + get_run_output_events(_run_id: number, _limit?: number): unknown { + return this.events; + } +} + +class StubScheduler implements WeixinScheduler { + submitted: Task[] = []; + + submit_task(task: Task): number { + this.submitted.push(task); + return this.submitted.length; + } +} + +const originalHooks = { ..._hooks }; +const originalDirHooks = { ...dirHooks }; +const originalBridgeEnv = process.env.AGENTFORGE_WEIXIN_BRIDGE; + +afterEach(() => { + _hooks.spawn_bridge = originalHooks.spawn_bridge; + _hooks.which = originalHooks.which; + _hooks.path_exists = originalHooks.path_exists; + _hooks.handle_dir_command = originalHooks.handle_dir_command; + _hooks.handle_agent_command = originalHooks.handle_agent_command; + dirHooks.extract_working_dir_with_claude = + originalDirHooks.extract_working_dir_with_claude; + if (originalBridgeEnv === undefined) { + delete process.env.AGENTFORGE_WEIXIN_BRIDGE; + } else { + process.env.AGENTFORGE_WEIXIN_BRIDGE = originalBridgeEnv; + } +}); + +function makeChannel(bridge_cmd: string[] | null = null) { + const bus = new MessageBus(); + const db = new StubDB(); + const scheduler = new StubScheduler(); + const channel = new WeixinChannel(bus, db, scheduler, bridge_cmd); + return { channel, bus, db, scheduler }; +} + +function fakeBridgeProcess(): WeixinBridgeProcess { + return { + stdin: { write: mock(() => undefined) }, + stdout: [], + poll: mock(() => null), + terminate: mock(() => undefined), + wait: mock(() => undefined), + }; +} + +function writtenCommands(proc: WeixinBridgeProcess): Row[] { + const write = proc.stdin!.write as ReturnType; + return write.mock.calls.map((call) => JSON.parse(String(call[0]).trim())); +} + +function writeImage(filePath: string, bytes: number[]): string { + fs.writeFileSync(filePath, Buffer.from(bytes)); + return fs.realpathSync(filePath); +} + +async function withResolvedDir( + value: string, + fn: () => Promise, +): Promise { + dirHooks.extract_working_dir_with_claude = async () => value; + return await fn(); +} + +describe("Weixin bridge startup", () => { + test("finds Bun from hooks before common fallback paths", () => { + _hooks.which = mock(() => "/opt/homebrew/bin/bun"); + _hooks.path_exists = mock(() => false); + + expect(_find_bun_executable()).toBe("/opt/homebrew/bin/bun"); + }); + + test("finds Bun from common fallback paths and returns null when absent", () => { + _hooks.which = mock(() => null); + _hooks.path_exists = mock((candidate: string) => + candidate.endsWith(path.join(".bun", "bin", "bun")), + ); + + expect(_find_bun_executable()).toBe( + path.join(os.homedir(), ".bun", "bin", "bun"), + ); + + _hooks.path_exists = mock(() => false); + expect(_find_bun_executable()).toBeNull(); + }); + + test("uses a packaged bridge binary override directly", () => { + process.env.AGENTFORGE_WEIXIN_BRIDGE = + "/Applications/AgentForge/Contents/Resources/weixin-bridge"; + + const { channel } = makeChannel(); + + expect(channel.bridge_cmd).toEqual([ + "/Applications/AgentForge/Contents/Resources/weixin-bridge", + ]); + }); + + test("runs a script bridge override through Bun", () => { + process.env.AGENTFORGE_WEIXIN_BRIDGE = "/tmp/weixin_bridge/index.ts"; + _hooks.which = mock(() => "/usr/local/bin/bun"); + _hooks.path_exists = mock(() => false); + + const { channel } = makeChannel(); + + expect(channel.bridge_cmd).toEqual([ + "/usr/local/bin/bun", + "/tmp/weixin_bridge/index.ts", + ]); + }); + + test("start spawns the bridge with configured environment", async () => { + const proc = fakeBridgeProcess(); + const spawn_bridge = mock((_cmd: string[], _env: Row) => proc); + _hooks.spawn_bridge = spawn_bridge; + + const { channel, db } = makeChannel(["/tmp/weixin-bridge"]); + db.settings["weixin_base_url"] = "https://weixin.example.test"; + db.settings["weixin_account_id"] = "account-1"; + + channel.start(); + await channel._reader_promise; + + expect(spawn_bridge.mock.calls[0][0]).toEqual(["/tmp/weixin-bridge"]); + expect(spawn_bridge.mock.calls[0][1]).toEqual( + expect.objectContaining({ + AGENTFORGE_WEIXIN_DATA_DIR: path.join( + os.homedir(), + ".agentforge", + "weixin", + ), + AGENTFORGE_WEIXIN_BASE_URL: "https://weixin.example.test", + AGENTFORGE_WEIXIN_ACCOUNT_ID: "account-1", + }), + ); + expect(channel._running).toBe(true); + + channel.stop(); + expect(proc.terminate).toHaveBeenCalledTimes(1); + }); + + test("start records missing Bun and generic bridge startup failures", () => { + const missing: NodeJS.ErrnoException = new Error("missing"); + missing.code = "ENOENT"; + _hooks.spawn_bridge = mock(() => { + throw missing; + }); + + const missingCase = makeChannel(["bun", "bridge.ts"]); + missingCase.channel.start(); + + expect(missingCase.channel._running).toBe(false); + expect(missingCase.channel.get_status_snapshot()).toEqual( + expect.objectContaining({ + login_status: "error", + last_error: expect.stringContaining("Bun not found"), + }), + ); + + _hooks.spawn_bridge = mock(() => { + throw new Error("boom"); + }); + + const genericCase = makeChannel(["/tmp/weixin-bridge"]); + genericCase.channel.start(); + + expect(genericCase.channel._running).toBe(false); + expect(genericCase.channel.get_status_snapshot()).toEqual( + expect.objectContaining({ + login_status: "error", + last_error: expect.stringContaining("Failed to start Weixin bridge"), + }), + ); + }); +}); + +describe("Weixin bridge events and commands", () => { + test("bridge reader ignores noise and updates status for lifecycle events", async () => { + const proc = fakeBridgeProcess(); + proc.stdout = [ + "\n", + "not-json\n", + JSON.stringify({ + type: "qr", + qrcode_url: "https://qr.example", + account_id: "acct-1", + }) + "\n", + JSON.stringify({ type: "scaned" }) + "\n", + JSON.stringify({ + type: "login_success", + account_id: "acct-2", + user_id: "user-1", + }) + "\n", + JSON.stringify({ type: "ready", account_id: "acct-3" }) + "\n", + JSON.stringify({ type: "logged_out" }) + "\n", + JSON.stringify({ type: "error", message: "bridge down" }) + "\n", + ]; + _hooks.spawn_bridge = mock(() => proc); + + const { channel } = makeChannel(["/tmp/weixin-bridge"]); + channel.start(); + await channel._reader_promise; + + expect(channel.get_status_snapshot()).toEqual( + expect.objectContaining({ + configured: false, + login_status: "error", + qr_code_url: "", + account_id: "acct-3", + user_id: "", + last_error: "bridge down", + }), + ); + }); + + test("sent events map bridge message ids back to task ids", () => { + const { channel } = makeChannel(); + channel._pending_notifications.set("req-1", 42); + + channel._handle_sent_event({ request_id: "", message_id: "om_x" }); + channel._handle_sent_event({ request_id: "unknown", message_id: "om_x" }); + expect(channel._notification_map.size).toBe(0); + + channel._handle_sent_event({ request_id: "req-1", message_id: "msg-1" }); + expect(channel._notification_map.get("msg-1")).toBe(42); + expect(channel._pending_notifications.has("req-1")).toBe(true); + + channel._handle_sent_event({ + request_id: "req-1", + quoted_message_id: "quote-1", + }); + expect(channel._notification_map.get("quote-1")).toBe(42); + expect(channel._pending_notifications.has("req-1")).toBe(false); + }); + + test("request login and logout reset status and write bridge commands", () => { + const proc = fakeBridgeProcess(); + const { channel } = makeChannel(); + channel._running = true; + channel._bridge_proc = proc; + channel._update_status({ + configured: true, + login_status: "connected", + qr_code_url: "qr", + last_error: "old", + user_id: "user-1", + }); + + channel.request_login(); + channel.request_logout(); + + expect(writtenCommands(proc).map((cmd) => cmd["type"])).toEqual([ + "login", + "logout", + ]); + expect(channel.get_status_snapshot()).toEqual( + expect.objectContaining({ + configured: false, + login_status: "idle", + qr_code_url: "", + last_error: "", + user_id: "", + }), + ); + }); + + test("send ignores inactive cases and emits completed and failed notifications", () => { + const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "agentforge-weixin-")); + const image = writeImage( + path.join(tmpDir, "generated.png"), + [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a], + ); + const proc = fakeBridgeProcess(); + const { channel, db } = makeChannel(); + channel._bridge_proc = proc; + db.tasks.set(7, { + id: 7, + title: "Render", + working_dir: tmpDir, + }); + db.tasks.set(8, { id: 8, title: "Broken" }); + db.runs = [{ id: 70 }]; + db.events = [ + { event_type: "generated_image", content: "{bad json" }, + { + event_type: "generated_image", + content: JSON.stringify({ path: image }), + }, + ]; + + try { + channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_COMPLETED, + task_id: 7, + payload: { title: "No origin", result: "ignored" }, + }), + ); + expect(writtenCommands(proc)).toHaveLength(0); + + channel._running = true; + channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_STARTED, + task_id: 7, + }), + ); + expect(writtenCommands(proc)).toHaveLength(0); + + channel._task_origin.set(7, { + account_id: "acct", + peer_id: "peer", + context_token: "ctx", + message_id: "origin-msg", + }); + channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_COMPLETED, + task_id: 7, + payload: { + title: "Render", + result: `Done\n- ${image}\n![out](${image})`, + }, + }), + ); + + channel._task_origin.set(8, { + account_id: "acct", + peer_id: "peer", + message_id: "origin-fail", + }); + channel.send( + makeOutboundMessage({ + type: OutboundMessageType.TASK_FAILED, + task_id: 8, + payload: { title: "Broken", error: "boom" }, + }), + ); + } finally { + fs.rmSync(tmpDir, { recursive: true, force: true }); + } + + const commands = writtenCommands(proc); + expect(commands).toHaveLength(2); + expect(commands[0]).toEqual( + expect.objectContaining({ + type: "send_message", + account_id: "acct", + peer_id: "peer", + context_token: "ctx", + reply_to_message_id: "origin-msg", + image_paths: [image], + }), + ); + expect(commands[0]["text"]).toContain("✅ Task #7 · Render\nDone"); + expect(commands[0]["text"]).not.toContain(image); + expect(commands[1]["text"]).toBe("❌ Task #8 · Broken\nboom"); + expect(channel._task_origin.has(7)).toBe(false); + expect(channel._task_origin.has(8)).toBe(false); + }); +}); + +describe("Weixin inbound messages", () => { + test("handles empty, new-session, dir, and agent command branches", async () => { + const proc = fakeBridgeProcess(); + const { channel } = makeChannel(); + channel._running = true; + channel._bridge_proc = proc; + channel._set_peer_current_task("acct:peer", 99); + + await channel._handle_message_event({ text: " " }); + expect(writtenCommands(proc)).toHaveLength(0); + + await channel._handle_message_event({ + text: "/new", + account_id: "acct", + peer_id: "peer", + message_id: "msg-new", + }); + await channel._handle_message_event({ + text: "/dir /tmp/project", + account_id: "acct", + peer_id: "peer", + message_id: "msg-dir", + }); + await channel._handle_message_event({ + text: "/agent llama", + account_id: "acct", + peer_id: "peer", + message_id: "msg-agent", + }); + + const replies = writtenCommands(proc).map((cmd) => cmd["text"]); + expect(replies[0]).toContain("新的 Weixin session"); + expect(replies[1]).toContain("Working directory set to: /tmp/project"); + expect(replies[2]).toContain("Unknown agent"); + expect(channel._get_peer_current_task("acct:peer")).toBeNull(); + }); + + test("creates image tasks and resumes mapped sessions", async () => { + const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "agentforge-weixin-")); + const image = writeImage( + path.join(tmpDir, "inbound.jpg"), + [0xff, 0xd8, 0xff, 0x00], + ); + const proc = fakeBridgeProcess(); + const { channel, db, scheduler } = makeChannel(); + channel._running = true; + channel._bridge_proc = proc; + db.settings["default_agent"] = "claude"; + + try { + await withResolvedDir("/tmp/workspace", async () => { + await channel._handle_message_event({ + image_paths: [image, image], + account_id: "acct", + peer_id: "peer", + context_token: "ctx", + message_id: "msg-img", + }); + }); + + expect(scheduler.submitted).toHaveLength(1); + expect(scheduler.submitted[0]!.prompt).toBe("请分析这张图片。"); + expect(scheduler.submitted[0]!.working_dir).toBe("/tmp/workspace"); + expect(scheduler.submitted[0]!.agent).toBe("claude"); + expect(scheduler.submitted[0]!.prompt_images).toEqual([ + expect.objectContaining({ + name: "inbound.jpg", + media_type: "image/jpeg", + }), + ]); + expect(channel._task_origin.get(1)).toEqual({ + account_id: "acct", + peer_id: "peer", + context_token: "ctx", + message_id: "msg-img", + }); + expect(channel._get_peer_current_task("acct:peer")).toBe(1); + + db.tasks.set(1, { + id: 1, + session_id: "sess-1", + status: "completed", + }); + channel._notification_map.set("notice-1", 1); + await channel._handle_message_event({ + text: "continue", + reply_to_message_id: "notice-1", + account_id: "acct", + peer_id: "peer", + context_token: "ctx2", + message_id: "msg-resume", + }); + + expect(db.updated[0]).toEqual([ + 1, + { + status: "pending", + prompt: "continue", + result: null, + error: null, + question: null, + }, + ]); + expect(channel._task_origin.get(1)).toEqual({ + account_id: "acct", + peer_id: "peer", + context_token: "ctx2", + message_id: "msg-resume", + }); + + db.tasks.set(12, { id: 12, status: "completed" }); + await channel._handle_message_event({ + text: "resume?", + reply_to_message_title: "Task #12 finished", + account_id: "acct", + peer_id: "other-peer", + message_id: "msg-no-session", + }); + expect( + writtenCommands(proc).some((cmd) => + String(cmd["text"]).includes("has no saved session"), + ), + ).toBe(true); + } finally { + fs.rmSync(tmpDir, { recursive: true, force: true }); + } + }); +}); + +describe("Weixin image and task-output helpers", () => { + test("extracts inbound image paths, prompt images, and media types", () => { + const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "agentforge-weixin-")); + const png = writeImage( + path.join(tmpDir, "a.png"), + [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a], + ); + const jpg = writeImage( + path.join(tmpDir, "b.unknown"), + [0xff, 0xd8, 0xff, 0x00], + ); + const gif = writeImage( + path.join(tmpDir, "c.gif"), + [0x47, 0x49, 0x46, 0x38, 0x39, 0x61], + ); + const webp = writeImage( + path.join(tmpDir, "d.webp"), + [0x52, 0x49, 0x46, 0x46, 0, 0, 0, 0, 0x57, 0x45, 0x42, 0x50], + ); + const missing = path.join(tmpDir, "missing.png"); + const { channel } = makeChannel(); + + try { + expect( + channel._extract_image_paths({ + image_paths: [png, png, "", missing], + images: [{ path: gif }, { local_path: webp }, "bad"], + }), + ).toEqual([png, gif, webp]); + expect(channel._default_image_prompt([png])).toBe("请分析这张图片。"); + expect(channel._default_image_prompt([png, gif])).toBe( + "请分析这 2 张图片。", + ); + expect(channel._build_resume_updates("", [png])).toEqual( + expect.objectContaining({ + status: "pending", + prompt: "请分析这张图片。", + image_paths: JSON.stringify([png]), + }), + ); + expect(channel._build_prompt_images([png, missing])).toEqual([ + expect.objectContaining({ + name: "a.png", + media_type: "image/png", + }), + ]); + expect(channel._image_media_type(png)).toBe("image/png"); + expect(channel._image_media_type(jpg)).toBe("image/jpeg"); + expect(channel._image_media_type(gif)).toBe("image/gif"); + expect(channel._image_media_type(webp)).toBe("image/webp"); + expect(channel._image_media_type(path.join(tmpDir, "missing"))).toBe( + "image/jpeg", + ); + } finally { + fs.rmSync(tmpDir, { recursive: true, force: true }); + } + }); + + test("collects generated images from DB events and markdown references", () => { + const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "agentforge-weixin-")); + const fromEvent = writeImage( + path.join(tmpDir, "event.png"), + [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a], + ); + const fromMarkdown = writeImage( + path.join(tmpDir, "markdown.png"), + [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a], + ); + const { channel, db } = makeChannel(); + db.runs = [{ id: 101 }]; + db.events = [ + { event_type: "assistant", content: "skip" }, + { event_type: "generated_image", content: "bad json" }, + { + event_type: "generated_image", + content: JSON.stringify({ path: fromEvent }), + }, + { + event_type: "generated_image", + content: JSON.stringify({ path: fromEvent }), + }, + ]; + + try { + expect( + channel._collect_generated_image_paths( + 5, + `![local](markdown.png)\n![remote](https://example.test/x.png)`, + { working_dir: tmpDir }, + ), + ).toEqual([fromEvent, fromMarkdown]); + expect( + channel._generated_image_paths_from_markdown("![x](data:abc)"), + ).toEqual([]); + + db.runs = []; + expect(channel._generated_image_paths_for_task(5)).toEqual([]); + + db.runs = [{ id: 101 }]; + db.get_run_output_events = mock(() => { + throw new Error("events down"); + }) as any; + expect(channel._generated_image_paths_for_task(5)).toEqual([]); + } finally { + fs.rmSync(tmpDir, { recursive: true, force: true }); + } + }); + + test("normalizes markdown references and hides uploaded image paths", () => { + const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "agentforge-weixin-")); + const image = writeImage( + path.join(tmpDir, "space image.png"), + [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a], + ); + const relative = path.basename(image).replace(" ", "%20"); + const { channel } = makeChannel(); + + try { + expect( + channel._markdown_image_reference_target(`<${image}> "title"`), + ).toBe(image); + expect(channel._markdown_image_reference_target(`'${image}'`)).toBe( + image, + ); + expect( + channel._local_image_path_from_reference("https://x/y.png"), + ).toBeNull(); + expect(channel._local_image_path_from_reference(`file://${image}`)).toBe( + image, + ); + expect(channel._local_image_path_from_reference(`sandbox:${image}`)).toBe( + image, + ); + expect(channel._local_image_path_from_reference(relative, tmpDir)).toBe( + image, + ); + expect(channel._dedupe_image_paths([image, image, "/nope.txt"])).toEqual([ + image, + ]); + expect( + channel._line_is_uploaded_image_path(`- ${image}`, new Set([image])), + ).toBe(true); + expect( + channel._line_is_uploaded_image_path( + "- /tmp/.codex/generated_images/x.png", + new Set(), + ), + ).toBe(true); + expect( + channel._remove_uploaded_markdown_image_refs( + `keep ![x](${image}) text`, + new Set([image]), + ), + ).toBe("keep text"); + expect( + channel._hide_generated_image_paths( + `Done\n- ${image}\n![x](${image})\n-`, + 1, + [image], + ), + ).toBe("Done"); + expect(channel._hide_generated_image_paths("已生成图片", 2, [])).toBe( + "已生成 2 张图片。", + ); + } finally { + fs.rmSync(tmpDir, { recursive: true, force: true }); + } + }); + + test("reply and send command handle missing peers and missing bridge", () => { + const proc = fakeBridgeProcess(); + const { channel } = makeChannel(); + + channel._reply_to_event({ message_id: "no-peer" }, "ignored"); + expect(writtenCommands(proc)).toHaveLength(0); + + channel._bridge_proc = proc; + channel._reply_to_event( + { + from_user_id: "user-1", + account_id: "acct", + context_token: "ctx", + message_id: "msg-1", + }, + "hello", + ); + channel._bridge_proc = null; + channel._send_command({ type: "dropped" }); + + expect(writtenCommands(proc)).toEqual([ + expect.objectContaining({ + type: "send_message", + account_id: "acct", + peer_id: "user-1", + context_token: "ctx", + reply_to_message_id: "msg-1", + text: "hello", + }), + ]); + expect( + channel._extract_task_id_from_reply_reference("", "Task #123 done"), + ).toBe(123); + expect(channel._extract_task_id_from_reply_reference("nothing")).toBeNull(); + }); +}); diff --git a/channels/README.md b/channels/README.md deleted file mode 100644 index 182158a..0000000 --- a/channels/README.md +++ /dev/null @@ -1,324 +0,0 @@ -# AgentForge Channels - -Channels are pluggable integrations that let you control AgentForge and receive -notifications from external messaging services. - ---- - -## Telegram Channel - -Control AgentForge through a Telegram bot: create tasks, list their status, and -receive automatic notifications when tasks complete or fail. - -### 1. Create a Bot - -1. Open Telegram and start a chat with [@BotFather](https://t.me/BotFather). -2. Send `/newbot` and follow the prompts. -3. Copy the **HTTP API token** BotFather gives you (looks like `123456789:ABCdef…`). - -### 2. Get Your User ID (optional but recommended) - -To restrict bot access to specific users, find your numeric Telegram user ID: - -1. Start a chat with [@userinfobot](https://t.me/userinfobot) or [@getidsbot](https://t.me/getidsbot). -2. It will reply with your numeric user ID (e.g. `123456789`). - -### 3. Configure Environment Variables - -| Variable | Required | Description | -|---------------------------|----------|-------------| -| `TELEGRAM_BOT_TOKEN` | ✅ Yes | Bot token from @BotFather | -| `TELEGRAM_ALLOWED_USERS` | No | Comma-separated numeric user IDs that may use the bot. If not set, **anyone** who finds the bot can use it. | - -Example: - -```bash -export TELEGRAM_BOT_TOKEN="123456789:ABCdefGHIjklMNOpqrSTUvwxYZ" -export TELEGRAM_ALLOWED_USERS="123456789,987654321" -``` - -### 4. Install the Dependency - -```bash -uv add python-telegram-bot -``` - -Or install all project dependencies (which now include it): - -```bash -uv sync -``` - -### 5. Start AgentForge - -```bash -uv run taskboard.py -``` - -If `TELEGRAM_BOT_TOKEN` is present in the environment, the Telegram channel -starts automatically. You will see: - -``` -[AgentForge] TELEGRAM_BOT_TOKEN detected — starting Telegram channel... -[Telegram] Bot thread started -[Telegram] Bot polling started -``` - -### 6. Available Bot Commands - -| Command | Description | -|---------|-------------| -| `/newtask \| <prompt>` | Create and queue a new immediate task | -| `/list` | List all tasks (up to 30) with their current status | -| `/status <task_id>` | Show detailed status of a specific task | -| `/cancel <task_id>` | Cancel a pending or running task | -| `/help` | Show command reference | - -**Examples:** - -``` -/newtask Fix login bug | Investigate and fix the authentication error in src/auth.py - -/newtask | Write a summary of all TODO comments across the codebase - -/status 42 - -/cancel 7 -``` - -> If only a prompt is provided (no `|` separator), the first 60 characters are -> used as the task title. - -### 7. Notifications - -When a task completes or fails, the bot sends a message to every Telegram chat -that has previously interacted with it during the current session. - -**Completed:** -``` -✅ Task #42 completed - -Fix login bug - -Authentication issue resolved. Updated JWT validation in auth.py… -``` - -**Failed:** -``` -❌ Task #42 failed - -Fix login bug - -claude CLI error: timeout after 600s -``` - -### 8. Default Working Directory - -By default tasks created via Telegram run in `~` (your home directory). -To change this, set a value in the AgentForge settings database: - -```bash -curl -X POST http://127.0.0.1:9712/api/settings \ - -H 'Content-Type: application/json' \ - -d '{"telegram_default_working_dir": "/path/to/your/project"}' -``` - ---- - -## Slack Channel - -Control AgentForge through a Slack bot using Socket Mode (no public IP or ngrok required). -Create tasks, check status, and receive automatic thread replies when tasks complete or fail. - -### 1. Create a Slack App - -1. Go to [api.slack.com/apps](https://api.slack.com/apps) and click **Create New App → From scratch**. -2. Give it a name (e.g. `AgentForge`) and select your workspace. - -### 2. Configure Bot Permissions - -Under **OAuth & Permissions → Scopes → Bot Token Scopes**, add: - -| Scope | Purpose | -|-------|---------| -| `app_mentions:read` | Receive @mentions in channels | -| `chat:write` | Send messages | -| `im:history` | Read DMs | -| `im:read` | List DMs | -| `im:write` | Open DM conversations | - -### 3. Enable Socket Mode - -1. Go to **Socket Mode** in the left sidebar and toggle it on. -2. Under **App-Level Tokens**, click **Generate Token and Scopes**. -3. Name it (e.g. `agentforge-socket`), add the scope `connections:write`, and click **Generate**. -4. Copy the token — it starts with `xapp-`. - -### 4. Subscribe to Events - -Under **Event Subscriptions**, toggle on **Enable Events**, then under -**Subscribe to bot events** add: - -- `app_mention` — to receive @bot mentions in channels -- `message.im` — to receive direct messages - -### 5. Install the App - -Under **OAuth & Permissions**, click **Install to Workspace** and copy the -**Bot User OAuth Token** (starts with `xoxb-`). - -Invite the bot to any channels where you want to mention it: - -``` -/invite @AgentForge -``` - -### 6. Configure Environment Variables - -| Variable | Required | Description | -|----------|----------|-------------| -| `SLACK_BOT_TOKEN` | ✅ Yes | Bot token from OAuth & Permissions (xoxb-…) | -| `SLACK_APP_TOKEN` | ✅ Yes | App-level token for Socket Mode (xapp-…) | -| `SLACK_ALLOWED_USERS` | No | Comma-separated Slack user IDs allowed to use the bot. If not set, **anyone** in your workspace can use it. | - -Example: - -```bash -export SLACK_BOT_TOKEN="xoxb-123456789-abcdefghijk" -export SLACK_APP_TOKEN="xapp-1-A1B2C3D4E5-xyz..." -export SLACK_ALLOWED_USERS="U012AB3CD,U098ZY7WX" -``` - -To find a user ID: click the user's profile → ⋮ menu → **Copy member ID**. - -### 7. Install the Dependency - -```bash -uv sync # slack-sdk is already in pyproject.toml -``` - -### 8. Start AgentForge - -```bash -uv run taskboard.py -``` - -If both `SLACK_BOT_TOKEN` and `SLACK_APP_TOKEN` are set, the Slack channel starts automatically: - -``` -[AgentForge] SLACK_BOT_TOKEN + SLACK_APP_TOKEN detected — starting Slack channel... -[Slack] Authenticated as user_id=U0123456789 -[Slack] Socket Mode connected -``` - -### 9. Available Commands - -Send these in a DM to the bot, or @mention the bot in a channel: - -| Command | Description | -|---------|-------------| -| `newtask <title> \| <prompt>` | Create and queue a new immediate task | -| `list` | List all tasks (up to 20) with status | -| `status <task_id>` | Show detailed status of a specific task | -| `cancel <task_id>` | Cancel a pending or running task | -| `help` | Show command reference | - -**Examples (DM or @mention):** - -``` -newtask Fix login bug | Investigate and fix the auth error in src/auth.py - -@AgentForge list - -@AgentForge status 42 - -cancel 7 -``` - -### 10. Notifications - -When you create a task with `newtask`, AgentForge remembers which Slack channel -and thread the request came from. When the task completes or fails it posts a -reply **in that same thread**: - -**Completed:** -``` -✅ Task #42 Fix login bug completed. -Result: Authentication issue resolved. Updated JWT validation in auth.py… -``` - -**Failed:** -``` -❌ Task #42 Fix login bug failed. -Error: `claude CLI exit code 1` -``` - ---- - -## Weixin Channel - -Experimental text-only Weixin channel backed by a Node sidecar bridge. - -### Current MVP Scope - -- Receive text messages and create tasks -- Reply to task result messages to resume a saved session -- Send task completion/failure text notifications back to the same peer -- Start QR-code login automatically when there is no saved session -- Reuse `/dir` and `/agent` command handling - -### 1. Enable the Channel - -```bash -curl -X POST http://127.0.0.1:9712/api/channels/settings \ - -H 'Content-Type: application/json' \ - -d '{ - "weixin_enabled": "true", - "weixin_default_working_dir": "/path/to/your/project", - "weixin_base_url": "https://ilinkai.weixin.qq.com", - "weixin_account_id": "" - }' -``` - -### 2. Start AgentForge - -```bash -uv run taskboard.py -``` - -If enabled, AgentForge will attempt to launch the bridge process. On a first-time login it will emit a QR event and keep polling until you confirm on your phone: - -```text -[Weixin] Bridge started -``` - -### Notes - -- This is a text-only MVP. -- The bridge implements the QR login flow and the documented `getupdates` / `sendmessage` HTTP protocol directly. -- The first version is single-account oriented from the AgentForge side, even though the upstream Weixin plugin supports multiple accounts. - ---- - -## Adding New Channels - -Create a new file under `channels/` that imports and subclasses `Channel` from -`taskboard_bus.py`: - -```python -from taskboard_bus import Channel - -class MyChannel(Channel): - def start(self) -> None: - ... - - def stop(self) -> None: - ... - - def notify_task(self, task_id: int) -> None: - # Called whenever a task status changes - ... -``` - -Then instantiate it in `run_server()` inside `taskboard.py`, append it to -`scheduler._channels`, and call `channel.start()`. diff --git a/channels/__init__.py b/channels/__init__.py deleted file mode 100644 index b05f179..0000000 --- a/channels/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# AgentForge channel integrations diff --git a/channels/agent_utils.py b/channels/agent_utils.py deleted file mode 100644 index 3f1dff4..0000000 --- a/channels/agent_utils.py +++ /dev/null @@ -1,68 +0,0 @@ -""" -Shared utilities for switching the default coding agent across all channels. - -Usage from any channel: - /agent claude — switch to Claude Code - /agent codex — switch to Codex CLI -""" - -from __future__ import annotations - -import re -from typing import TYPE_CHECKING, Optional - -if TYPE_CHECKING: - from taskboard import TaskDB - - -# Supported agent names -SUPPORTED_AGENTS = { - "claude": "Claude Code (claude CLI)", - "codex": "Codex CLI (openai/codex)", -} -DEFAULT_AGENT = "codex" - -# Regex: /agent <name> -_AGENT_CMD_RE = re.compile( - r"^/agent\s+(\S+)\s*$", - re.IGNORECASE, -) - - -def parse_agent_command(text: str) -> Optional[str]: - """Return the agent name argument if `text` is a /agent command, else None.""" - m = _AGENT_CMD_RE.match(text.strip()) - return m.group(1).lower() if m else None - - -def handle_agent_command( - text: str, - channel_key: str, - db: "TaskDB", -) -> Optional[str]: - """ - If `text` is a /agent command, persist the choice to DB and return a - confirmation string. Returns None if `text` is not an agent command. - - The setting is stored as global `default_agent` (shared across all channels - and the Forge desktop app). - """ - agent = parse_agent_command(text) - if agent is None: - return None - - if agent not in SUPPORTED_AGENTS: - names = ", ".join(f"`{k}`" for k in SUPPORTED_AGENTS) - return f"❌ Unknown agent `{agent}`. Supported: {names}" - - db.set_setting("default_agent", agent) - label = SUPPORTED_AGENTS[agent] - return f"🤖 Default agent switched to: **{label}**" - - -def resolve_agent(channel_key: str, db: "TaskDB") -> str: - """ - Return the current default agent from settings. - Falls back to the app default if not set. - """ - return db.get_setting("default_agent", DEFAULT_AGENT) diff --git a/channels/dir_utils.py b/channels/dir_utils.py deleted file mode 100644 index 7fea0cf..0000000 --- a/channels/dir_utils.py +++ /dev/null @@ -1,132 +0,0 @@ -""" -Shared utilities for working-directory management across all channels. - -Two features: -1. /dir (or cd) command — explicit path switch, persists to DB. -2. Claude-based extraction — ask claude-haiku to pull a path from a - free-text prompt so the user can say "在 ~/myproject 里帮我…" - without typing a /dir command first. -""" - -from __future__ import annotations - -import json -import os -import re -from typing import TYPE_CHECKING, Optional - -if TYPE_CHECKING: - from taskboard import TaskDB - - -# ── 1. Explicit /dir / cd command ───────────────────────────────────────── - -# Patterns we recognise as "switch directory" commands: -# /dir ~/foo cd ~/foo /cd ~/foo -_DIR_CMD_RE = re.compile( - r"^(?:/dir|/cd|cd)\s+(\S+)\s*$", - re.IGNORECASE, -) - - -def parse_dir_command(text: str) -> Optional[str]: - """Return the path argument if `text` is a /dir or cd command, else None.""" - m = _DIR_CMD_RE.match(text.strip()) - return m.group(1) if m else None - - -def handle_dir_command( - text: str, - channel_key: str, - db: "TaskDB", -) -> Optional[str]: - """ - If `text` is a /dir command, persist the new path to DB and return a - confirmation string. Returns None if `text` is not a dir command. - - `channel_key` is the settings key prefix, e.g. "telegram", "slack", "feishu". - """ - path = parse_dir_command(text) - if path is None: - return None - - setting_key = f"{channel_key}_default_working_dir" - db.set_setting(setting_key, path) - return f"📁 Working directory set to: {path}" - - -# ── 2. Claude-based path extraction ─────────────────────────────────────── - -_EXTRACT_SYSTEM = ( - "You are a path-extraction assistant. " - "Given a user message, decide if it explicitly mentions a filesystem path " - "where some work should be done (e.g. ~/projects/foo, /home/user/bar, " - "./myapp, C:\\\\Users\\\\foo). " - "Reply with a JSON object and nothing else:\n" - ' {"path": "<extracted path>"} — if a path is found\n' - ' {"path": null} — if no path is mentioned\n' - "Do NOT invent a path. Only return one that is clearly stated in the message." -) - - -def extract_working_dir_with_claude(prompt: str) -> Optional[str]: - """ - Call the Anthropic Messages API (claude-haiku) to extract an explicit - working directory from `prompt`. - Returns the path string, or None if none found / on any error. - - Uses `requests` (already a project dependency) so no extra SDK needed. - """ - api_key = os.environ.get("ANTHROPIC_API_KEY", "") - if not api_key: - return None - - try: - import requests # already in pyproject.toml - - resp = requests.post( - "https://api.anthropic.com/v1/messages", - headers={ - "x-api-key": api_key, - "anthropic-version": "2023-06-01", - "content-type": "application/json", - }, - json={ - "model": "claude-haiku-4-5", - "max_tokens": 64, - "system": _EXTRACT_SYSTEM, - "messages": [{"role": "user", "content": prompt}], - }, - timeout=15, - ) - if resp.status_code != 200: - return None - - data = resp.json() - text = data.get("content", [{}])[0].get("text", "").strip() - parsed = json.loads(text) - path = parsed.get("path") - if path and isinstance(path, str): - return path.strip() - except Exception: - pass - return None - - -def resolve_working_dir( - prompt: str, - channel_key: str, - db: "TaskDB", -) -> str: - """ - Determine the working directory for a new task: - 1. Try to extract an explicit path from `prompt` via Claude. - 2. Fall back to the channel's default_working_dir in DB. - 3. Fall back to "~". - """ - extracted = extract_working_dir_with_claude(prompt) - if extracted: - return extracted - - setting_key = f"{channel_key}_default_working_dir" - return db.get_setting(setting_key) or "~" diff --git a/channels/feishu_channel.py b/channels/feishu_channel.py deleted file mode 100644 index 89a6def..0000000 --- a/channels/feishu_channel.py +++ /dev/null @@ -1,1961 +0,0 @@ -""" -TaskForge Feishu/Lark Channel - -Bidirectional Feishu/Lark bot integration via WebSocket long-connection. -Outbound: sends card notifications when tasks complete or fail. -Inbound: receives messages and either creates new tasks or resumes sessions. - -Requires lark-oapi: uv add lark-oapi -Configure via settings API: - feishu_app_id, feishu_app_secret, - feishu_default_chat_id (oc_… group chat or ou_… open_id) - feishu_default_working_dir (working directory for tasks created from bot) -""" - -import asyncio -import base64 -import json -import logging -import re -import threading -import time -from datetime import datetime, timedelta, timezone -from pathlib import Path -from typing import TYPE_CHECKING, Any, Optional -from urllib.parse import unquote, urlparse - -from taskboard_bus import Channel, MessageBus, OutboundMessage, OutboundMessageType - -if TYPE_CHECKING: - from taskboard import TaskDB, TaskScheduler - -# Lazy-load lark SDK -try: - import lark_oapi as lark - import lark_oapi.ws.client as lark_ws_client - from lark_oapi.api.im.v1 import ( - CreateImageRequest, - CreateImageRequestBody, - CreateMessageReactionRequest, - CreateMessageReactionRequestBody, - CreateMessageRequest, - CreateMessageRequestBody, - Emoji, - GetMessageResourceRequest, - PatchMessageRequest, - PatchMessageRequestBody, - ReplyMessageRequest, - ReplyMessageRequestBody, - ) - - FEISHU_AVAILABLE = True -except ImportError: - FEISHU_AVAILABLE = False - lark = None - lark_ws_client = None - Emoji = None - - -HELP_TEXT = """\ -**AgentForge Bot** 👋 -发送任意消息即可创建任务。回复任务完成/失败通知即可继续对话。 - -**命令列表:** -• `/status <id>` — 查看任务详情 -• `/cancel <id>` — 取消任务 -• `/resume <id> <message>` — 继续执行任务 -• `/dir <path>` — 设置默认工作目录 -  例如:`/dir ~/workspace/myproject` -• `/agent <name>` — 切换 coding agent(`claude` / `codex`) -• `/ccu` — 查看 Claude Code 当前用量(ccu-blocks) -• `/help` — 显示此帮助 - -**小技巧:** -• 消息中直接提到路径,Bot 会自动识别并使用。 - 例如:_在 ~/myapp 里帮我修复登录 bug_ -• 回复任意结果通知即可继续对话。 -""" - -FEISHU_CARD_MARKDOWN_CHUNK = 7000 -FEISHU_FALLBACK_MARKDOWN_LIMIT = 8000 -FEISHU_CARD_MAX_ELEMENTS = 200 -FEISHU_PANEL_MAX_LINE_ELEMENTS = 80 -FEISHU_PANEL_PLAIN_TEXT_CHUNK = 1800 -FEISHU_THINKING_PREFIX = "[thinking] " -FEISHU_MARKDOWN_IMAGE_RE = re.compile(r"!\[[^\]]*]\(([^)\n]+)\)") -FEISHU_UPLOADABLE_IMAGE_SUFFIXES = {".png", ".jpg", ".jpeg", ".gif", ".webp"} -FEISHU_STREAM_EVENT_TYPES = { - "assistant", - "tool_call", - "tool_result", - "command_execution", - "file_change", - "web_search", - "error", -} - - -class _FeishuStreamWriter: - """Rate-limited, event-driven Feishu card updater for a single running task. - - Registered as an output listener on TaskScheduler. Each time the agent emits - displayable output or trace events, the writer appends the chunk and schedules - a card patch. - Patches are rate-limited to at most one every MIN_INTERVAL seconds so we don't - hammer the Feishu API. Patch requests are serialized so older requests cannot - race and overwrite newer content. - - run_id is latched from the first event received, so the writer can be registered - before the run row is created in the DB. - """ - - MIN_INTERVAL = 0.25 # seconds between patches - - def __init__(self, task_id: int, msg_id: str, channel: "FeishuChannel", task_title: str): - self.task_id = task_id - self.msg_id = msg_id - self._channel = channel - self._task_title = task_title - - self._run_id: Optional[int] = None # latched on first event - self._parts: list[str] = [] - self._parts_lock = threading.Lock() - self._last_patch = 0.0 - self._timer: Optional[threading.Timer] = None - self._state_lock = threading.Lock() - self._stopped = False - self._patch_in_flight = False - self._dirty = False - - # called from the executor thread — must not block - def on_event(self, task_id: int, run_id: int, event_type: str, content: str) -> None: - if self._stopped or task_id != self.task_id: - return - if event_type not in FEISHU_STREAM_EVENT_TYPES or content == "": - return - display_content = self._display_content(event_type, content) - if not display_content: - return - with self._parts_lock: - # Latch the run_id on the first event; reset parts if run_id changes (resume) - if self._run_id is None: - self._run_id = run_id - elif self._run_id != run_id: - self._run_id = run_id - self._parts.clear() - if event_type != "assistant" and self._parts and not self._parts[-1].endswith("\n"): - display_content = "\n" + display_content - self._parts.append(display_content) - self._schedule() - - def _display_content(self, event_type: str, content: str) -> str: - if event_type != "assistant": - return self._format_trace_event(event_type, content) - if content.startswith(FEISHU_THINKING_PREFIX): - return content[len(FEISHU_THINKING_PREFIX) :] - return content - - def _load_trace_payload(self, content: str) -> dict[str, Any]: - try: - payload = json.loads(content) - except json.JSONDecodeError: - return {"content": content} - return payload if isinstance(payload, dict) else {"content": payload} - - def _format_trace_value(self, value: Any) -> str: - return self._compact_trace_summary(value) - - def _compact_trace_summary(self, value: Any, limit: int = 140) -> str: - if value in (None, "", {}, []): - return "" - if isinstance(value, dict): - for key in ("command", "query", "path", "file", "message", "content", "text"): - if value.get(key): - return self._compact_trace_summary(value[key], limit) - safe_parts = [] - for key, item in value.items(): - if item in (None, "", {}, []): - continue - if any( - secret in str(key).lower() for secret in ("token", "secret", "password", "key") - ): - continue - safe_parts.append(f"{key}={self._compact_trace_summary(item, 48)}") - if len(safe_parts) >= 2: - break - return self._truncate_trace_text(", ".join(safe_parts), limit) - if isinstance(value, list): - if not value: - return "" - first = self._compact_trace_summary(value[0], max(24, limit - 20)) - suffix = f" 等 {len(value)} 项" if len(value) > 1 else "" - return self._truncate_trace_text(f"{first}{suffix}", limit) - return self._truncate_trace_text(str(value), limit) - - def _truncate_trace_text(self, value: str, limit: int = 140) -> str: - lines = [ - line.strip() - for line in str(value).replace("\r\n", "\n").replace("\r", "\n").split("\n") - if line.strip() - ] - normalized = " ".join((lines[0] if lines else "").split()) - if len(normalized) <= limit: - return normalized - return normalized[: limit - 1].rstrip() + "…" - - def _trace_line(self, icon: str, label: str, *parts: Any) -> str: - compact_parts = [ - self._compact_trace_summary(part) - if not isinstance(part, str) - else self._truncate_trace_text(part) - for part in parts - ] - suffix = " · ".join(part for part in compact_parts if part) - return f"{icon} {label}{(' ' + suffix) if suffix else ''}" - - def _format_trace_event(self, event_type: str, content: str) -> str: - payload = self._load_trace_payload(content) - line = "" - - if event_type == "tool_call": - name = payload.get("name") or payload.get("tool") or "unknown" - if payload.get("server"): - name = f"{payload['server']}.{name}" - tool_input = payload.get("input") or payload.get("arguments") - result = payload.get("result") - error = payload.get("error") - line = self._trace_line( - "▣", - "调用工具", - name, - tool_input, - result, - payload.get("status"), - f"错误 {self._format_trace_value(error)}" if error else "", - ) - elif event_type == "tool_result": - label = "工具错误" if payload.get("is_error") else "工具返回" - line = self._trace_line( - "↵", - label, - payload.get("tool_use_id"), - payload.get("content"), - ) - elif event_type == "command_execution": - command = payload.get("command") or payload.get("content") or "" - exit_code = ( - f"退出码 {payload['exit_code']}" if payload.get("exit_code") is not None else "" - ) - line = self._trace_line( - "$", - "执行命令", - command, - payload.get("output"), - exit_code, - payload.get("status"), - ) - elif event_type == "file_change": - changes = payload.get("changes") - summary = "" - if isinstance(changes, list): - summaries = [] - for change in changes: - if isinstance(change, dict): - path = change.get("path") or change.get("file") or "" - kind = change.get("kind") or change.get("type") or "changed" - summaries.append(f"{kind}: {path}".strip()) - summary = ";".join(summaries[:3]) - if len(summaries) > 3: - summary += f" 等 {len(summaries)} 项" - elif changes: - summary = self._format_trace_value(changes) - line = self._trace_line("◇", "文件变更", summary, payload.get("status")) - elif event_type == "web_search": - query = payload.get("query") or payload.get("content") or "" - line = self._trace_line("⌕", "网页搜索", query, payload.get("status")) - elif event_type == "error": - line = self._trace_line( - "!", - "错误", - payload.get("message") or payload.get("content") or content, - ) - else: - line = self._trace_line("•", f"[{event_type}]", content) - - return f"{line}\n" if line else "" - - def _schedule(self) -> None: - with self._state_lock: - if self._stopped: - return - self._dirty = True - self._schedule_dirty_locked() - - def _schedule_dirty_locked(self) -> None: - if self._stopped or not self._dirty or self._patch_in_flight or self._timer: - return - - delay = max(0.0, self.MIN_INTERVAL - (time.time() - self._last_patch)) - if delay <= 0: - self._start_patch_locked() - return - - self._timer = threading.Timer(delay, self._timer_fired) - self._timer.daemon = True - self._timer.start() - - def _start_patch_locked(self) -> None: - self._patch_in_flight = True - self._dirty = False - threading.Thread(target=self._do_patch, daemon=True).start() - - def _timer_fired(self) -> None: - with self._state_lock: - self._timer = None - self._schedule_dirty_locked() - - def _do_patch(self) -> None: - with self._parts_lock: - text = "".join(self._parts) - card = self._channel._build_streaming_card(self.task_id, self._task_title, text) - try: - self._channel._patch_message(self.msg_id, card) - finally: - with self._state_lock: - self._last_patch = time.time() - self._patch_in_flight = False - self._schedule_dirty_locked() - - def snapshot_text(self) -> str: - with self._parts_lock: - return "".join(self._parts) - - def stop(self) -> None: - with self._state_lock: - self._stopped = True - if self._timer: - self._timer.cancel() - self._timer = None - - -class FeishuChannel(Channel): - """Feishu/Lark channel integration using WebSocket long-connection.""" - - def __init__(self, bus: MessageBus, db: "TaskDB", scheduler: "TaskScheduler"): - super().__init__("feishu", bus, db) - self.scheduler = scheduler - self._client = None - self._ws_client = None - self._ws_thread: Optional[threading.Thread] = None - self._ws_loop: Optional[asyncio.AbstractEventLoop] = None - - # task_id -> (reply_to_chat_id, root_message_id, reaction_message_id) for thread-style replies - # root_message_id: used for replying in thread - # reaction_message_id: used for adding emoji reactions (may differ on resume) - self._task_origin: dict[int, tuple[str, str, str]] = {} - self._origin_lock = threading.Lock() - - # notification message_id -> task_id for resume-by-reply - self._notification_map: dict[str, int] = {} - self._notification_lock = threading.Lock() - - # root_message_id -> task_id for thread-based session resume - self._root_msg_map: dict[str, int] = {} - self._root_msg_lock = threading.Lock() - - # task_id -> _FeishuStreamWriter for live card updates - self._writers: dict[int, "_FeishuStreamWriter"] = {} - self._writers_lock = threading.Lock() - - # task_id -> running card message_id (used by send() to patch instead of reply) - self._streaming_msg: dict[int, str] = {} - self._streaming_lock = threading.Lock() - - # Subscribe to outbound bus messages for task notifications - bus.subscribe_outbound(self._on_outbound) - - # ── lifecycle ──────────────────────────────────────────────── - - def start(self) -> None: - if not FEISHU_AVAILABLE: - print("[Feishu] lark-oapi not installed. Run: uv add lark-oapi") - return - - app_id = self.db.get_setting("feishu_app_id") - app_secret = self.db.get_setting("feishu_app_secret") - print(f"[Feishu] Starting with app_id: {app_id[:8]}... (masked)") - - if not app_id or not app_secret: - print("[Feishu] Not configured — set feishu_app_id / feishu_app_secret in settings") - return - - try: - # The lark SDK's "Lark" logger ships its own stdout handler; stop it - # propagating to the root logger (configured via basicConfig in - # taskboard.py) so each line isn't emitted twice. - logging.getLogger("Lark").propagate = False - - print("[Feishu] Building Lark client...") - self._client = ( - lark.Client.builder() - .app_id(app_id) - .app_secret(app_secret) - .log_level(lark.LogLevel.INFO) - .build() - ) - print("[Feishu] Lark client built successfully") - - print("[Feishu] Registering event handler...") - event_handler = ( - lark.EventDispatcherHandler.builder("", "") - .register_p2_im_message_receive_v1(self._on_message_sync) - .register_p2_im_chat_member_bot_added_v1(self._on_bot_added) - .register_p2_im_message_reaction_created_v1(self._on_reaction) - .register_p2_im_message_reaction_deleted_v1(self._on_reaction) - # No-op processors for read-only receipts we subscribe to but - # don't act on — without these the SDK logs "processor not - # found, type: im.message.message_read_v1" on every receipt. - .register_p2_im_message_message_read_v1(lambda data: None) - .register_p2_im_message_recalled_v1(lambda data: None) - .build() - ) - print("[Feishu] Event handler registered") - - print("[Feishu] Creating WebSocket client...") - self._ws_client = lark.ws.Client( - app_id, - app_secret, - event_handler=event_handler, - log_level=lark.LogLevel.INFO, - ) - print("[Feishu] WebSocket client created") - - self._running = True - self._ws_thread = threading.Thread(target=self._run_ws, daemon=True) - self._ws_thread.start() - print("[Feishu] WebSocket bot thread started (no public IP required)") - print("[Feishu] Initialization complete") - except Exception as e: - print(f"[Feishu] ERROR during initialization: {e}") - import traceback - - traceback.print_exc() - - def stop(self) -> None: - print("[Feishu] Stopping WebSocket bot...") - self._running = False - self.bus.unsubscribe_outbound(self._on_outbound) - if ( - self._ws_thread - and self._ws_thread.is_alive() - and self._ws_loop is None - and self._ws_thread is not threading.current_thread() - ): - deadline = time.time() + 1 - while self._ws_loop is None and time.time() < deadline: - time.sleep(0.01) - - ws_client = self._ws_client - ws_loop = self._ws_loop - if ws_client: - try: - stop_fn = getattr(ws_client, "stop", None) - if callable(stop_fn): - print("[Feishu] Calling ws_client.stop()...") - stop_fn() - print("[Feishu] ws_client.stop() completed") - else: - self._stop_ws_loop(ws_client, ws_loop) - except Exception as e: - print(f"[Feishu] Error stopping ws_client: {e}") - - if ( - self._ws_thread - and self._ws_thread.is_alive() - and self._ws_thread is not threading.current_thread() - ): - self._ws_thread.join(timeout=10) - if self._ws_thread.is_alive(): - print("[Feishu] WebSocket thread did not stop within timeout") - - self._client = None - self._ws_client = None - self._ws_loop = None - self._ws_thread = None - print("[Feishu] Bot stopped") - - def _run_ws(self): - print("[Feishu] WebSocket thread starting...") - ws_loop = asyncio.new_event_loop() - self._ws_loop = ws_loop - asyncio.set_event_loop(ws_loop) - previous_sdk_loop = None - if lark_ws_client is not None: - previous_sdk_loop = getattr(lark_ws_client, "loop", None) - lark_ws_client.loop = ws_loop - try: - if not self._running: - print("[Feishu] WebSocket start skipped; channel already stopped") - return - if not self._ws_client: - print("[Feishu] WebSocket client missing; cannot start") - return - print("[Feishu] Calling ws_client.start()...") - self._ws_client.start() - print("[Feishu] ws_client.start() returned (connection ended)") - except RuntimeError as e: - if not self._running and "Event loop stopped before Future completed" in str(e): - print("[Feishu] WebSocket loop stopped") - else: - print(f"[Feishu] WebSocket error: {e}") - import traceback - - traceback.print_exc() - except Exception as e: - print(f"[Feishu] WebSocket error: {e}") - import traceback - - traceback.print_exc() - finally: - self._running = False - if lark_ws_client is not None and getattr(lark_ws_client, "loop", None) is ws_loop: - lark_ws_client.loop = previous_sdk_loop - self._close_ws_loop(ws_loop) - if self._ws_loop is ws_loop: - self._ws_loop = None - print("[Feishu] WebSocket thread exiting") - - def _stop_ws_loop(self, ws_client: Any, ws_loop: Optional[asyncio.AbstractEventLoop]) -> None: - """Stop lark-oapi versions that expose no public ws_client.stop().""" - if not ws_loop or ws_loop.is_closed(): - return - - disconnect = getattr(ws_client, "_disconnect", None) - if ws_loop.is_running(): - if callable(disconnect): - future = asyncio.run_coroutine_threadsafe(disconnect(), ws_loop) - try: - future.result(timeout=5) - except Exception as e: - print(f"[Feishu] Error disconnecting ws_client: {e}") - ws_loop.call_soon_threadsafe(ws_loop.stop) - return - - if callable(disconnect): - try: - ws_loop.run_until_complete(disconnect()) - except Exception as e: - print(f"[Feishu] Error disconnecting ws_client: {e}") - ws_loop.stop() - - def _close_ws_loop(self, ws_loop: asyncio.AbstractEventLoop) -> None: - if ws_loop.is_closed(): - return - try: - pending = [task for task in asyncio.all_tasks(ws_loop) if not task.done()] - for task in pending: - task.cancel() - if pending: - ws_loop.run_until_complete(asyncio.gather(*pending, return_exceptions=True)) - ws_loop.run_until_complete(ws_loop.shutdown_asyncgens()) - except Exception as e: - print(f"[Feishu] Error closing WebSocket event loop: {e}") - finally: - ws_loop.close() - - # ── Channel ABC: send outbound message ─────────────────────── - - def send(self, msg: OutboundMessage) -> None: - """Send task completion/failure notification to Feishu, threaded under the original message.""" - if msg.type not in (OutboundMessageType.TASK_COMPLETED, OutboundMessageType.TASK_FAILED): - return - - task_id = msg.task_id - if not self._client: - print(f"[Feishu] Client not initialized, skipping notification for task {task_id}") - return - - task = self.db.get_task(task_id) - if not task: - print(f"[Feishu] Task {task_id} not found in database") - return - - is_completed = msg.type == OutboundMessageType.TASK_COMPLETED - print( - f"[Feishu] Sending notification for task {task_id} ({'completed' if is_completed else 'failed'})" - ) - - if is_completed: - result_text = (msg.payload.get("result") or task.get("result") or "").strip() - content = result_text or "Done." - else: - error_text = (msg.payload.get("error") or task.get("error") or "Unknown error").strip()[ - :800 - ] - content = error_text - - # Try to reply in thread if we have an origin message - with self._origin_lock: - origin = self._task_origin.get(task_id) - - # Stop streaming thread and get the running card message_id/history if any - streaming_msg_id = None - with self._streaming_lock: - streaming_msg_id = self._streaming_msg.pop(task_id, None) - streaming_history = self._stop_streaming(task_id) - image_keys = [] - if is_completed: - image_paths = self._collect_generated_image_paths(task_id, content, task) - uploaded_images = self._upload_image_entries(image_paths) - image_keys = [image_key for _, image_key in uploaded_images] - if image_keys: - content = self._hide_generated_image_paths( - content, - len(image_keys), - uploaded_paths=[image_path for image_path, _ in uploaded_images], - ) - - card = self._build_notification_card( - task_id=task_id, - task=task, - is_completed=is_completed, - body_text=content, - streaming_history=streaming_history, - image_keys=image_keys, - ) - - sent_id = None - if origin: - reply_to_chat, root_msg_id, reaction_msg_id = origin - # Add emoji reaction to the message that triggered the task (or resume) - emoji = "DONE" if is_completed else "Cry" - self._add_reaction(reaction_msg_id, emoji) - - # If we have a streaming card, patch it with the final result - if streaming_msg_id: - patched = self._patch_message(streaming_msg_id, card) - if patched: - sent_id = streaming_msg_id - if not sent_id: - sent_id = self._reply_message(root_msg_id, content, card=card) - - # Fallback: send to default chat if no origin or reply failed - if not sent_id: - chat_id = self.db.get_setting("feishu_default_chat_id") - if chat_id: - sent_id = self._send_message( - chat_id, - content, - card=card, - fallback_content=self._truncate_text(content, FEISHU_FALLBACK_MARKDOWN_LIMIT), - ) - - if sent_id: - print(f"[Feishu] Notification sent successfully, message_id: {sent_id}") - with self._notification_lock: - self._notification_map[sent_id] = task_id - print(f"[Feishu] Notification message_id={sent_id} mapped to task #{task_id}") - else: - print(f"[Feishu] Failed to send notification for task {task_id}") - - # Free origin memory after terminal state - with self._origin_lock: - self._task_origin.pop(task_id, None) - - def _on_outbound(self, msg: OutboundMessage) -> None: - """MessageBus outbound subscriber callback.""" - self.send(msg) - - def _generated_image_paths_for_task(self, task_id: int) -> list[str]: - try: - runs = self.db.get_task_runs(task_id, limit=1) - except Exception as e: - print(f"[Feishu] Failed to load runs for generated images: {e}") - return [] - if not isinstance(runs, list) or not runs: - return [] - - run_id = runs[0].get("id") if isinstance(runs[0], dict) else None - if not run_id: - return [] - try: - events = self.db.get_run_output_events(run_id, limit=1000) - except Exception as e: - print(f"[Feishu] Failed to load output events for generated images: {e}") - return [] - if not isinstance(events, list): - return [] - - paths = [] - seen = set() - for event in events: - if not isinstance(event, dict) or event.get("event_type") != "generated_image": - continue - try: - payload = json.loads(event.get("content") or "{}") - except json.JSONDecodeError: - continue - path = payload.get("path") if isinstance(payload, dict) else None - if not path or path in seen or not Path(path).is_file(): - continue - seen.add(path) - paths.append(path) - return paths - - def _collect_generated_image_paths( - self, task_id: int, content: str, task: Optional[dict[str, Any]] = None - ) -> list[str]: - paths = self._generated_image_paths_for_task(task_id) - paths.extend( - self._generated_image_paths_from_markdown( - content, - working_dir=(task or {}).get("working_dir"), - ) - ) - return self._dedupe_image_paths(paths) - - def _generated_image_paths_from_markdown( - self, content: str, working_dir: Optional[str] = None - ) -> list[str]: - paths = [] - for match in FEISHU_MARKDOWN_IMAGE_RE.finditer(content or ""): - image_path = self._local_image_path_from_reference(match.group(1), working_dir) - if image_path: - paths.append(image_path) - return paths - - def _local_image_path_from_reference( - self, reference: str, working_dir: Optional[str] = None - ) -> Optional[str]: - target = self._markdown_image_reference_target(reference) - if not target or target.startswith(("http://", "https://", "data:")): - return None - if target.startswith("file://"): - parsed = urlparse(target) - target = parsed.path - elif target.startswith("sandbox:"): - target = target[len("sandbox:") :] - target = unquote(target).strip() - if not target: - return None - - path = Path(target).expanduser() - if not path.is_absolute() and working_dir: - path = Path(working_dir).expanduser() / path - if path.suffix.lower() not in FEISHU_UPLOADABLE_IMAGE_SUFFIXES: - return None - try: - if not path.is_file(): - return None - return str(path.resolve()) - except OSError: - return None - - def _markdown_image_reference_target(self, reference: str) -> str: - raw = (reference or "").strip() - if not raw: - return "" - if raw.startswith("<"): - end = raw.find(">") - if end >= 0: - return raw[1:end].strip() - if raw[0] in ("'", '"'): - end = raw.find(raw[0], 1) - if end > 0: - return raw[1:end].strip() - titled = re.match(r"(.+?)\s+['\"][^'\"]*['\"]\s*$", raw) - return (titled.group(1) if titled else raw).strip() - - def _dedupe_image_paths(self, image_paths: list[str]) -> list[str]: - deduped = [] - seen = set() - for image_path in image_paths: - canonical = self._canonical_image_path(image_path) - if not canonical or canonical in seen: - continue - seen.add(canonical) - deduped.append(canonical) - return deduped - - def _canonical_image_path(self, image_path: str) -> Optional[str]: - try: - path = Path(image_path).expanduser() - if not path.is_file(): - return None - return str(path.resolve()) - except OSError: - return None - - def _upload_images(self, image_paths: list[str]) -> list[str]: - return [image_key for _, image_key in self._upload_image_entries(image_paths)] - - def _upload_image_entries(self, image_paths: list[str]) -> list[tuple[str, str]]: - entries = [] - for image_path in image_paths: - image_key = self._upload_image(image_path) - if image_key: - entries.append((image_path, image_key)) - return entries - - def _upload_image(self, image_path: str) -> Optional[str]: - if not self._client: - return None - try: - with open(image_path, "rb") as image_file: - request = ( - CreateImageRequest.builder() - .request_body( - CreateImageRequestBody.builder() - .image_type("message") - .image(image_file) - .build() - ) - .build() - ) - response = self._client.im.v1.image.create(request) - except Exception as e: - print(f"[Feishu] Failed to upload generated image {image_path}: {e}") - return None - - if response.success(): - image_key = response.data.image_key - print(f"[Feishu] Uploaded generated image {image_path}, image_key={image_key}") - return image_key - print(f"[Feishu] Image upload failed: {response.code} {response.msg}") - return None - - def _hide_generated_image_paths( - self, content: str, image_count: int, uploaded_paths: Optional[list[str]] = None - ) -> str: - uploaded = { - canonical - for path in (uploaded_paths or []) - if (canonical := self._canonical_image_path(path)) - } - lines = [] - for line in (content or "").splitlines(): - stripped = line.strip() - if not stripped: - lines.append("") - continue - if self._line_is_uploaded_image_path(stripped, uploaded): - continue - cleaned_line = self._remove_uploaded_markdown_image_refs(line, uploaded) - visible = cleaned_line.strip() - if visible and visible not in {"-", "*", "+"}: - lines.append(cleaned_line.rstrip()) - cleaned = "\n".join(lines).strip() - if not cleaned or cleaned.startswith("已生成"): - return f"已生成 {image_count} 张图片。" - return cleaned - - def _line_is_uploaded_image_path(self, stripped_line: str, uploaded_paths: set[str]) -> bool: - if not stripped_line.startswith("- "): - return False - candidate = stripped_line[2:].strip() - canonical = self._canonical_image_path(candidate) - if canonical and canonical in uploaded_paths: - return True - return "/.codex/generated_images/" in stripped_line - - def _remove_uploaded_markdown_image_refs(self, line: str, uploaded_paths: set[str]) -> str: - if not uploaded_paths: - return line - - def replace(match: re.Match) -> str: - image_path = self._local_image_path_from_reference(match.group(1)) - canonical = self._canonical_image_path(image_path) if image_path else None - return "" if canonical in uploaded_paths else match.group(0) - - return FEISHU_MARKDOWN_IMAGE_RE.sub(replace, line) - - # ── outbound: low-level send ────────────────────────────────── - - def _send_message( - self, - chat_id: str, - content: str, - card: Optional[dict[str, Any]] = None, - fallback_content: Optional[str] = None, - ) -> Optional[str]: - """Send a card to chat_id. Falls back to the legacy markdown card on failure.""" - print(f"[Feishu] _send_message called, chat_id: {chat_id}, content length: {len(content)}") - if not self._client: - print("[Feishu] Client not initialized in _send_message") - return None - try: - receive_id_type = "chat_id" if chat_id.startswith("oc_") else "open_id" - print(f"[Feishu] receive_id_type: {receive_id_type}") - card_payload = card or self._build_legacy_markdown_card(content) - message_id = self._create_message( - receive_id_type=receive_id_type, - chat_id=chat_id, - card=card_payload, - ) - if message_id: - return message_id - - if card is not None: - legacy_content = fallback_content or content - print("[Feishu] Structured card send failed, retrying with legacy markdown card") - return self._create_message( - receive_id_type=receive_id_type, - chat_id=chat_id, - card=self._build_legacy_markdown_card(legacy_content), - ) - return None - except Exception as e: - print(f"[Feishu] Error sending message: {e}") - import traceback - - traceback.print_exc() - return None - - def _reply_message( - self, - parent_message_id: str, - content: str, - card: Optional[dict[str, Any]] = None, - ) -> Optional[str]: - """Reply to a specific message (thread-style). Falls back to the legacy markdown card.""" - print( - f"[Feishu] _reply_message called, parent_message_id: {parent_message_id}, content length: {len(content)}" - ) - if not self._client: - print("[Feishu] Client not initialized in _reply_message") - return None - try: - reply_card = card or self._build_legacy_markdown_card(content) - message_id = self._create_reply(parent_message_id=parent_message_id, card=reply_card) - if message_id: - return message_id - - if card is not None: - print("[Feishu] Structured card reply failed, retrying with legacy markdown card") - return self._create_reply( - parent_message_id=parent_message_id, - card=self._build_legacy_markdown_card(content), - ) - return None - except Exception as e: - print(f"[Feishu] Error replying to message: {e}") - import traceback - - traceback.print_exc() - return None - - def _create_message( - self, receive_id_type: str, chat_id: str, card: dict[str, Any] - ) -> Optional[str]: - print("[Feishu] Building CreateMessageRequest...") - request = ( - CreateMessageRequest.builder() - .receive_id_type(receive_id_type) - .request_body( - CreateMessageRequestBody.builder() - .receive_id(chat_id) - .msg_type("interactive") - .content(json.dumps(card, ensure_ascii=False)) - .build() - ) - .build() - ) - print("[Feishu] Calling im.v1.message.create()...") - response = self._client.im.v1.message.create(request) - print( - f"[Feishu] Response received: success={response.success()}, code={response.code}, msg={response.msg}" - ) - if response.success(): - message_id = response.data.message_id - print(f"[Feishu] Message sent successfully, message_id: {message_id}") - return message_id - - print(f"[Feishu] Send failed: {response.code} {response.msg}") - return None - - def _create_reply(self, parent_message_id: str, card: dict[str, Any]) -> Optional[str]: - if not self._client or not FEISHU_AVAILABLE: - print("[Feishu] Client not initialized in _create_reply") - return None - request = ( - ReplyMessageRequest.builder() - .message_id(parent_message_id) - .request_body( - ReplyMessageRequestBody.builder() - .msg_type("interactive") - .content(json.dumps(card, ensure_ascii=False)) - .reply_in_thread(True) - .build() - ) - .build() - ) - print("[Feishu] Calling im.v1.message.reply()...") - response = self._client.im.v1.message.reply(request) - print( - f"[Feishu] Reply response: success={response.success()}, code={response.code}, msg={response.msg}" - ) - if response.success(): - message_id = response.data.message_id - print(f"[Feishu] Reply sent successfully, message_id: {message_id}") - return message_id - - print(f"[Feishu] Reply failed: {response.code} {response.msg}") - return None - - def _patch_message(self, message_id: str, card: dict[str, Any]) -> bool: - """Patch an existing interactive card message with new content.""" - if not self._client or not FEISHU_AVAILABLE: - return False - try: - request = ( - PatchMessageRequest.builder() - .message_id(message_id) - .request_body( - PatchMessageRequestBody.builder() - .content(json.dumps(card, ensure_ascii=False)) - .build() - ) - .build() - ) - response = self._client.im.v1.message.patch(request) - if response.success(): - return True - print(f"[Feishu] Patch failed: {response.code} {response.msg}") - return False - except Exception as e: - print(f"[Feishu] Error patching message {message_id}: {e}") - return False - - def _build_streaming_card( - self, task_id: int, task_title: str, output_text: str, done: bool = False - ) -> dict[str, Any]: - """Build a card showing live streaming output.""" - elements: list[dict[str, Any]] - if done: - display_text = output_text.strip() or "完成" - elements = [ - { - "tag": "markdown", - "content": self._preserve_feishu_markdown_linebreaks(display_text), - } - ] - elif not output_text.strip(): - elements = [{"tag": "markdown", "content": "Thinking ▌"}] - else: - elements = [self._build_streaming_history_panel(output_text, expanded=True)] - return { - "schema": "2.0", - "config": {"wide_screen_mode": True, "width_mode": "fill"}, - "body": { - "elements": elements, - }, - } - - def _build_streaming_history_panel( - self, output_text: str, expanded: bool = False - ) -> dict[str, Any]: - elements = self._build_streaming_history_elements(output_text) - return { - "tag": "collapsible_panel", - "expanded": expanded, - "header": { - "title": { - "tag": "plain_text", - "content": "执行过程", - }, - "vertical_align": "center", - "icon": { - "tag": "standard_icon", - "token": "down-small-ccm_outlined", - "color": "", - "size": "16px 16px", - }, - "icon_position": "right", - "icon_expanded_angle": -180, - }, - "border": { - "color": "grey", - "corner_radius": "5px", - }, - "vertical_spacing": "8px", - "padding": "8px 8px 8px 8px", - "elements": elements, - } - - def _build_streaming_history_elements(self, output_text: str) -> list[dict[str, Any]]: - normalized = output_text.replace("\r\n", "\n").replace("\r", "\n").rstrip("\n") - if not normalized: - return [] - - line_elements = self._build_streaming_history_line_elements(normalized) - if len(line_elements) <= FEISHU_PANEL_MAX_LINE_ELEMENTS: - return line_elements - - return self._build_streaming_history_markdown_elements(normalized) - - def _build_streaming_history_markdown_elements(self, text: str) -> list[dict[str, Any]]: - chunks = self._chunk_text(text, FEISHU_CARD_MARKDOWN_CHUNK - 16) - return [{"tag": "markdown", "content": chunk} for chunk in chunks] - - def _build_streaming_history_line_elements(self, text: str) -> list[dict[str, Any]]: - elements: list[dict[str, Any]] = [] - for line in text.split("\n"): - chunks = self._chunk_text(line, FEISHU_PANEL_PLAIN_TEXT_CHUNK) if line else [" "] - for chunk in chunks: - elements.append(self._build_streaming_history_line(chunk)) - return elements - - def _build_streaming_history_line(self, content: str) -> dict[str, Any]: - return { - "tag": "div", - "text": { - "tag": "plain_text", - "text_color": "grey", - "text_size": "notation", - "content": content, - }, - } - - def _preserve_feishu_markdown_linebreaks(self, text: str) -> str: - return text.replace("\r\n", "\n").replace("\r", "\n") - - def _start_streaming(self, task_id: int, running_msg_id: str, task_title: str) -> None: - """Register an event-driven writer that patches the running card on each assistant event.""" - # Stop any previous writer for this task - self._stop_streaming(task_id) - - writer = _FeishuStreamWriter(task_id, running_msg_id, self, task_title) - with self._writers_lock: - self._writers[task_id] = writer - with self._streaming_lock: - self._streaming_msg[task_id] = running_msg_id - - self.scheduler.add_output_listener(writer.on_event) - print(f"[Feishu] Streaming writer registered for task {task_id}, msg_id={running_msg_id}") - - def _stop_streaming(self, task_id: int) -> Optional[str]: - """Unregister the streaming writer for task_id.""" - with self._writers_lock: - writer = self._writers.pop(task_id, None) - if writer: - self.scheduler.remove_output_listener(writer.on_event) - history = writer.snapshot_text() - writer.stop() - print(f"[Feishu] Streaming writer stopped for task {task_id}") - return history - return None - - def _build_notification_card( - self, - task_id: int, - task: dict[str, Any], - is_completed: bool, - body_text: str, - streaming_history: Optional[str] = None, - image_keys: Optional[list[str]] = None, - ) -> dict[str, Any]: - clean_body = (body_text or "").strip() or ("Done." if is_completed else "Unknown error") - summary = self._truncate_text(clean_body.splitlines()[0], 120) if clean_body else "" - elements = self._build_result_elements(body_text=clean_body, image_keys=image_keys) - if streaming_history and streaming_history.strip(): - panel_text = streaming_history - if is_completed: - # Drop the final answer from the folded "执行过程" panel to avoid - # showing it twice — but only when something is left. Otherwise keep - # the full history so the execution-process panel never vanishes. - stripped = self._strip_final_result_from_history(streaming_history, clean_body) - if stripped.strip(): - panel_text = stripped - elements = [self._build_streaming_history_panel(panel_text)] + elements - - if not is_completed: - elements.append( - { - "tag": "markdown", - "content": f"`/status {task_id}` for full details", - } - ) - - return { - "schema": "2.0", - "config": { - "wide_screen_mode": True, - "enable_forward": True, - "width_mode": "fill", - "summary": {"content": summary}, - }, - "body": { - "elements": elements, - }, - } - - def _strip_final_result_from_history(self, history: str, final_text: str) -> str: - final_body = (final_text or "").strip() - if not final_body: - return history - - trimmed_history = history.rstrip() - if trimmed_history.endswith(final_body): - return trimmed_history[: -len(final_body)].rstrip() - return history - - def _build_result_elements( - self, body_text: str, image_keys: Optional[list[str]] = None - ) -> list[dict[str, Any]]: - clean_body = (body_text or "").strip() or "Done." - elements = [ - {"tag": "markdown", "content": chunk} - for chunk in self._chunk_text(clean_body, FEISHU_CARD_MARKDOWN_CHUNK) - ] - for index, image_key in enumerate(image_keys or [], start=1): - elements.append( - { - "tag": "img", - "img_key": image_key, - "alt": {"tag": "plain_text", "content": f"generated image {index}"}, - } - ) - return elements - - def _build_legacy_markdown_card(self, content: str) -> dict[str, Any]: - return { - "config": {"wide_screen_mode": True}, - "elements": [{"tag": "markdown", "content": content}], - } - - def _truncate_text(self, text: str, limit: int) -> str: - normalized = text.replace("\r\n", "\n").strip() - if len(normalized) <= limit: - return normalized - return normalized[:limit].rstrip() + "\n…(truncated)" - - def _chunk_text(self, text: str, limit: int) -> list[str]: - normalized = text.replace("\r\n", "\n") - if not normalized: - return [""] - return [normalized[i : i + limit] for i in range(0, len(normalized), limit)] - - def _escape_feishu_markdown(self, text: str) -> str: - return text.replace("\\", "\\\\") - - def _add_reaction(self, message_id: str, emoji_type: str = "THUMBSUP"): - """Add an emoji reaction in a background thread (non-blocking).""" - if not self._client or not FEISHU_AVAILABLE: - return - - def _do(): - try: - req = ( - CreateMessageReactionRequest.builder() - .message_id(message_id) - .request_body( - CreateMessageReactionRequestBody.builder() - .reaction_type(Emoji.builder().emoji_type(emoji_type).build()) - .build() - ) - .build() - ) - self._client.im.v1.message_reaction.create(req) - except Exception as e: - print(f"[Feishu] Failed to add reaction to {message_id}: {e}") - - threading.Thread(target=_do, daemon=True).start() - - # ── usage stats ──────────────────────────────────────────────── - - def _get_usage_stats(self) -> str: - """Compute current 5-hour block usage via claude-monitor library.""" - try: - from datetime import datetime, timezone - - from claude_monitor.core.plans import Plans - from claude_monitor.data.analysis import analyze_usage - from claude_monitor.utils.time_utils import TimezoneHandler - - data = analyze_usage(hours_back=192, quick_start=False, use_cache=False) - if not data or not data.get("blocks"): - return "📊 未找到 Claude Code 用量记录" - - blocks = data["blocks"] - real_blocks = [b for b in blocks if not b.get("isGap")] - if not real_blocks: - return "📊 未找到 Claude Code 用量记录" - - # Prefer the active block; fall back to the most recent one - block = next( - (b for b in real_blocks if b.get("isActive")), - real_blocks[-1], - ) - - now = datetime.now(timezone.utc) - tz = TimezoneHandler() - end_time = tz.parse_timestamp(block["endTime"]) - start_time = tz.parse_timestamp(block["startTime"]) - remaining = end_time - now - - total_tokens = block["totalTokens"] # input + output, excludes cache - total_cost = block["costUSD"] - sent_msgs = block["sentMessagesCount"] - - # Use static plan limits (matches `claude-monitor --plan pro`) - plan = (self.db.get_setting("claude_plan") or "pro").lower().strip() - token_limit = Plans.get_token_limit(plan, blocks) - cost_limit = Plans.get_cost_limit(plan) - msg_limit = Plans.get_message_limit(plan) - - token_pct = min(total_tokens / token_limit * 100, 100) if token_limit > 0 else 0 - cost_pct = min(total_cost / cost_limit * 100, 100) if cost_limit > 0 else 0 - msg_pct = min(sent_msgs / msg_limit * 100, 100) if msg_limit > 0 else 0 - - def _bar(pct: float, width: int = 20) -> str: - filled = int(pct / (100 / width)) - return "█" * filled + "░" * (width - filled) - - # Burn rate from block data - duration_min = block.get("durationMinutes", 1) or 1 - tok_per_min = total_tokens / duration_min - cost_per_hr = (total_cost / duration_min) * 60 - - # Format times in local timezone - local_tz = datetime.now().astimezone().tzinfo - bs_local = start_time.astimezone(local_tz) - be_local = end_time.astimezone(local_tz) - remain_h = int(max(remaining.total_seconds(), 0) // 3600) - remain_m = int((max(remaining.total_seconds(), 0) % 3600) // 60) - - active_label = " (活跃)" if block.get("isActive") else " (已结束)" - lines = [ - "**📊 Claude Code 用量**\n", - f"Block: {bs_local:%m/%d %H:%M} → {be_local:%H:%M} (剩余 {remain_h}h{remain_m}m){active_label}\n", - f"💰 Cost: **[{_bar(cost_pct)}] {cost_pct:.1f}%**", - f" ${total_cost:.2f} / ${cost_limit:.0f}", - f"📊 Token: **[{_bar(token_pct)}] {token_pct:.1f}%**", - f" {total_tokens:,} / {token_limit:,}", - f"📨 Msgs: **[{_bar(msg_pct)}] {msg_pct:.1f}%**", - f" {sent_msgs} / {msg_limit}\n", - f"🔥 Burn: {tok_per_min:,.0f} tok/min | ${cost_per_hr:.2f}/hr", - f"\nPlan: {plan}", - ] - return "\n".join(lines) - - except Exception as e: - return f"❌ 获取用量统计失败:{e}" - - # ── forwarded message support ─────────────────────────────────── - - def _extract_forwarded_content(self, message) -> Optional[dict]: - """解析飞书转发/引用消息内容 - - Returns: - dict 包含转发信息的字典,或 None - { - "type": "forward" | "quote", - "sender_name": str, - "sender_id": str | None, - "timestamp": int | None, - "text": str, - "images": list[dict] - } - """ - msg_type = message.message_type - - # 检查 forward 类型(如果飞书 API 支持) - if msg_type == "forward": - try: - content = json.loads(message.content) - return { - "type": "forward", - "sender_name": content.get("sender_name", "Unknown"), - "sender_id": content.get("sender_id"), - "timestamp": content.get("create_time"), - "text": content.get("text", ""), - "images": content.get("images", []), - } - except json.JSONDecodeError: - pass - - # 检查 post 类型中的引用/转发标记 - elif msg_type == "post": - try: - post_body = json.loads(message.content) - - # 检查是否有 quote 标记(引用回复) - for lang_key in ["content", "zh_cn", "en_us"]: - if lang_key in post_body: - lang_body = post_body[lang_key] - break - else: - lang_body = next(iter(post_body.values()), {}) - - # 如果 lang_body 是列表(简化的 content 格式),直接遍历 - # 否则从 lang_body 中获取 content - paragraphs = ( - lang_body if isinstance(lang_body, list) else lang_body.get("content", []) - ) - - # 遍历内容查找引用 block - for para in paragraphs: - for elem in para: - # 引用消息(quote 类型) - if elem.get("tag") == "quote": - quote_text = elem.get("text", "") - quote_user = elem.get("user", {}) - sender_name = quote_user.get("name", "未知用户") - - return { - "type": "quote", - "sender_name": sender_name, - "sender_id": quote_user.get("open_id"), - "text": quote_text, - "timestamp": elem.get("create_time"), - } - - # 嵌套消息(可能是转发) - if elem.get("tag") == "nested_message": - nested = elem.get("nested_message", {}) - return { - "type": "forward", - "sender_name": nested.get("sender_name", "未知用户"), - "sender_id": nested.get("sender_id"), - "timestamp": nested.get("create_time"), - "text": nested.get("text", ""), - "images": nested.get("images", []), - } - - except (json.JSONDecodeError, AttributeError): - pass - - return None - - def _format_forwarded_prompt(self, original_content: str, forwarded: dict) -> str: - """将转发内容格式化到 prompt 中 - - Args: - original_content: 用户发送的原始消息文本 - forwarded: 从 _extract_forwarded_content 返回的转发信息 - - Returns: - 格式化后的完整 prompt - """ - if not forwarded: - return original_content - - parts = [] - - # 添加时间和发送者信息 - parts.append("📨 [转发消息]") - - sender_name = forwarded.get("sender_name", "未知用户") - parts.append(f"转发自: {sender_name}") - - if forwarded.get("timestamp"): - ts = datetime.fromtimestamp(forwarded["timestamp"], tz=timezone(timedelta(hours=8))) - parts.append(f"时间: {ts.strftime('%Y-%m-%d %H:%M')}") - - parts.append("\n--- 转发内容 ---") - parts.append(forwarded.get("text", "")) - - # 如果有图片信息,添加说明 - images = forwarded.get("images", []) - if images: - parts.append(f"\n[包含 {len(images)} 张图片]") - - # 如果有用户附加消息,添加到转发内容之后 - if original_content.strip(): - parts.append("\n--- 用户附加消息 ---") - parts.append(original_content) - - return "\n".join(parts) - - def _download_image(self, message_id: str, image_key: str) -> Optional[str]: - """Download an image from Feishu and save it to a temporary location. - Returns the local file path or None if download fails.""" - if not self._client or not FEISHU_AVAILABLE: - print("[Feishu] Client not available for image download") - return None - - try: - print(f"[Feishu] Downloading image {image_key} from message {message_id}") - # Create downloads directory - downloads_dir = Path.home() / ".agentforge" / "feishu_images" - downloads_dir.mkdir(parents=True, exist_ok=True) - - # Request the image resource - request = ( - GetMessageResourceRequest.builder() - .message_id(message_id) - .file_key(image_key) - .type("image") - .build() - ) - - response = self._client.im.v1.message_resource.get(request) - - if not response.success(): - print(f"[Feishu] Failed to download image: {response.code} {response.msg}") - return None - - # Get image content - image_data = response.raw.content - - # Detect actual image format from magic bytes - if image_data.startswith(b"\xff\xd8\xff"): - extension = "jpg" - elif image_data.startswith(b"\x89PNG\r\n\x1a\n"): - extension = "png" - elif image_data.startswith(b"GIF87a") or image_data.startswith(b"GIF89a"): - extension = "gif" - elif image_data.startswith(b"RIFF") and b"WEBP" in image_data[:12]: - extension = "webp" - else: - # Default to jpg if unknown - extension = "jpg" - - # Save with correct extension - file_path = downloads_dir / f"{image_key}.{extension}" - - with open(file_path, "wb") as f: - f.write(image_data) - - print(f"[Feishu] Image saved to {file_path} (detected format: {extension})") - return str(file_path) - - except Exception as e: - print(f"[Feishu] Error downloading image {image_key}: {e}") - import traceback - - traceback.print_exc() - return None - - # ── inbound: receive messages via WebSocket ─────────────────── - - def _on_reaction(self, data) -> None: - """No-op handler for message reaction events. - - The bot adds emoji reactions to acknowledge tasks, which echoes an - `im.message.reaction.created_v1` event back over the WebSocket. We don't - act on reactions, but registering a handler stops the lark SDK from - logging `processor not found` errors for every reaction. - """ - return - - def _on_bot_added(self, data) -> None: - """Called when the bot is added to a chat (including P2P when a user follows the bot).""" - print("[Feishu] _on_bot_added called") - try: - event = data.event - chat_id = getattr(event, "chat_id", None) - if not chat_id: - print("[Feishu] _on_bot_added: no chat_id in event") - return - print(f"[Feishu] Bot added to chat_id={chat_id}, sending HELP_TEXT") - self._send_message(chat_id, HELP_TEXT) - except Exception as e: - print(f"[Feishu] _on_bot_added error: {e}") - import traceback - - traceback.print_exc() - - def _on_message_sync(self, data) -> None: - """Called from the WebSocket thread; runs handler synchronously.""" - print(f"[Feishu] _on_message_sync called, data type: {type(data)}") - if not self._running: - print("[Feishu] Ignoring inbound message after channel stopped") - return - try: - self._handle_inbound(data) - print("[Feishu] Message handled successfully") - except Exception as e: - print(f"[Feishu] Inbound handler error: {e}") - import traceback - - traceback.print_exc() - - def _handle_inbound(self, data) -> None: - """Parse incoming Feishu message and act on it.""" - print("[Feishu] _handle_inbound processing message...") - event = data.event - message = event.message - sender = event.sender - - if sender.sender_type == "bot": - print("[Feishu] Ignoring message from bot (self)") - return # ignore self-messages - - msg_type = message.message_type - print(f"[Feishu] Message type: {msg_type}") - image_paths = [] # Initialize for all message types - if msg_type == "text": - try: - content = json.loads(message.content).get("text", "").strip() - except (json.JSONDecodeError, AttributeError): - content = (message.content or "").strip() - elif msg_type == "post": - # Rich text message (may contain text + images) - try: - post_body = json.loads(message.content) - print(f"[Feishu] Parsed post_body keys: {post_body.keys()}") - - # Check if this is direct format (has "content" key directly) - if "content" in post_body: - lang_body = post_body - else: - # Try language-specific keys - lang_body = ( - post_body.get("zh_cn") - or post_body.get("en_us") - or next(iter(post_body.values()), {}) - ) - - title_part = lang_body.get("title", "").strip() - text_parts = [] - image_paths = [] # Store actual downloaded image paths - for para in lang_body.get("content", []): - for elem in para: - if elem.get("tag") == "text": - text_parts.append(elem.get("text", "")) - elif elem.get("tag") == "img": - # Download the image - image_key = elem.get("image_key", "") - if image_key: - print(f"[Feishu] Found image: {image_key}, attempting download...") - image_path = self._download_image(message.message_id, image_key) - if image_path: - image_paths.append(image_path) - print(f"[Feishu] Successfully downloaded image to {image_path}") - else: - print(f"[Feishu] Failed to download image {image_key}") - - body_text = "".join(text_parts).strip() - print(f"[Feishu] Extracted text_parts: {text_parts}, body_text: {body_text}") - print(f"[Feishu] Downloaded image paths: {image_paths}") - - content = "\n".join(filter(None, [title_part, body_text])).strip() - - # If no text was extracted but there are images, provide a default prompt - if not content and image_paths: - content = "请分析这些图片的内容" - - print(f"[Feishu] Final content: {content[:200]}") - except (json.JSONDecodeError, AttributeError, StopIteration) as e: - print(f"[Feishu] Failed to parse post message: {e}") - import traceback - - traceback.print_exc() - # Don't use raw content as fallback - it's the JSON structure - content = "" - image_paths = [] - elif msg_type == "image": - # Single image message: {"image_key": "img_xxxx"} - try: - img_content = json.loads(message.content) - image_key = img_content.get("image_key", "") - if image_key: - print(f"[Feishu] Found single image message, image_key: {image_key}") - image_path = self._download_image(message.message_id, image_key) - if image_path: - image_paths.append(image_path) - print(f"[Feishu] Downloaded single image to {image_path}") - else: - print(f"[Feishu] Failed to download single image {image_key}") - content = "请分析这张图片的内容" - except (json.JSONDecodeError, AttributeError) as e: - print(f"[Feishu] Failed to parse image message: {e}") - content = "请分析这张图片的内容" - else: - print(f"[Feishu] Ignoring non-text/post/image message (type={msg_type})") - return - - print(f"[Feishu] Message content: {content[:100]}...") - - # ── 检测转发/引用消息 ─────────────────────────────────── - forwarded = self._extract_forwarded_content(message) - if forwarded: - print( - f"[Feishu] Detected forwarded/quoted message from {forwarded.get('sender_name', 'unknown')}" - ) - content = self._format_forwarded_prompt(content, forwarded) - # 处理转发中包含的图片(如果有) - for img_info in forwarded.get("images", []): - img_key = img_info.get("image_key") - if img_key: - img_path = self._download_image(message.message_id, img_key) - if img_path: - image_paths.append(img_path) - - if not content: - print("[Feishu] Empty content after processing, ignoring") - return - - # Acknowledge with a "get" reaction - print("[Feishu] Adding reaction to message...") - self._add_reaction(message.message_id, "OK") - - sender_id = sender.sender_id.open_id if sender.sender_id else "unknown" - chat_type = message.chat_type # "p2p" or "group" - chat_id = message.chat_id - reply_to = chat_id if chat_type == "group" else sender_id - print(f"[Feishu] sender_id: {sender_id}, chat_type: {chat_type}, reply_to: {reply_to}") - - # ── command: /help ─────────────────────────────────────── - if content.strip() in ("/help", "/start"): - self._send_message(reply_to, HELP_TEXT) - return - - # ── command: /dir <path> — switch working directory ────── - if content.startswith("/dir ") or content.startswith("/cd "): - from channels.dir_utils import handle_dir_command - - reply = handle_dir_command(content, "feishu", self.db) - if reply: - self._send_message(reply_to, reply) - return - - # ── command: /agent <name> — switch coding agent ───────── - if content.startswith("/agent "): - from channels.agent_utils import handle_agent_command - - reply = handle_agent_command(content, "feishu", self.db) - if reply: - self._send_message(reply_to, reply) - return - - # ── command: /ccu [blocks] — usage stats ──────────────── - if content.strip().lower().startswith("/ccu"): - stats = self._get_usage_stats() - self._send_message(reply_to, stats) - return - - # ── command: /resume <task_id> <message> ──────────────── - if content.startswith("/resume "): - print("[Feishu] Processing /resume command") - parts = content[8:].strip().split(" ", 1) - if len(parts) >= 2 and parts[0].isdigit(): - tid = int(parts[0]) - resume_msg = parts[1].strip() - task = self.db.get_task(tid) - if task and task.get("session_id"): - self.db.update_task( - tid, - status="pending", - prompt=resume_msg, - result=None, - error=None, - question=None, - ) - with self._origin_lock: - self._task_origin[tid] = (reply_to, message.message_id, message.message_id) - task_obj = self.db.get_task(tid) - resume_title = (task_obj or {}).get("title", f"Task #{tid}") - running_card = self._build_streaming_card(tid, resume_title, "") - running_msg_id = self._create_reply( - parent_message_id=message.message_id, card=running_card - ) - if running_msg_id: - self._start_streaming(tid, running_msg_id, resume_title) - print(f"[Feishu] Task {tid} resumed") - else: - self._send_message( - reply_to, - f"❌ Task #{tid} not found or has no saved session.", - ) - print(f"[Feishu] Task {tid} not found or no session_id") - else: - self._send_message(reply_to, "Usage: `/resume <task_id> <message>`") - print("[Feishu] Invalid /resume syntax") - return - - # ── command: /status <task_id> ─────────────────────────── - if content.startswith("/status "): - print("[Feishu] Processing /status command") - parts = content[8:].strip().split() - if parts and parts[0].isdigit(): - tid = int(parts[0]) - task = self.db.get_task(tid) - if task: - s = task["status"] - icon = { - "completed": "✅", - "failed": "❌", - "running": "⏳", - "pending": "🕐", - "cancelled": "🚫", - }.get(s, "❓") - self._send_message( - reply_to, - f"{icon} **Task #{tid}** — {s}\n\n**{task['title']}**", - ) - print(f"[Feishu] Status sent for task {tid}") - else: - self._send_message(reply_to, f"❌ Task #{tid} not found.") - print(f"[Feishu] Task {tid} not found") - return - - # ── filter system notifications ─────────────────────────── - if any( - keyword in content.lower() - for keyword in [ - "notification", - "任务完成", - "任务失败", - "任务状态", - "任务已", - "task completed", - "task failed", - "task status", - ] - ): - print("[Feishu] Ignoring system notification") - return - - # ── detect reply in thread → resume task session ───────── - # Check parent_id (direct reply) and root_id (any message in thread) - parent_id = getattr(message, "parent_id", None) or None - root_id = getattr(message, "root_id", None) or None - is_thread_msg = bool(parent_id or root_id) - - if is_thread_msg: - print(f"[Feishu] Thread message detected: parent_id={parent_id}, root_id={root_id}") - # Try to find task_id: first by notification_map (parent_id), then by root_msg_map (root_id) - task_id = None - with self._notification_lock: - if parent_id: - task_id = self._notification_map.get(parent_id) - if not task_id and root_id: - task_id = self._notification_map.get(root_id) - if not task_id: - with self._root_msg_lock: - if root_id: - task_id = self._root_msg_map.get(root_id) - if not task_id and parent_id: - task_id = self._root_msg_map.get(parent_id) - - # Fallback: query DB by feishu_root_msg_id (survives service restarts) - if not task_id: - for msg_id in filter(None, [root_id, parent_id]): - db_task = self.db.get_task_by_feishu_root_msg(msg_id) - if db_task: - task_id = db_task["id"] - print( - f"[Feishu] Recovered task {task_id} from DB via feishu_root_msg_id={msg_id}" - ) - break - - # Determine which message to reply to in the thread - thread_root = root_id or parent_id - - if task_id: - print(f"[Feishu] Found matching task {task_id} for thread message") - task = self.db.get_task(task_id) - if task and task.get("session_id"): - self.db.update_task( - task_id, - status="pending", - prompt=content, - result=None, - error=None, - question=None, - ) - with self._origin_lock: - self._task_origin[task_id] = (reply_to, thread_root, message.message_id) - task_obj = self.db.get_task(task_id) - resume_title = (task_obj or {}).get("title", f"Task #{task_id}") - running_card = self._build_streaming_card(task_id, resume_title, "") - running_msg_id = self._create_reply( - parent_message_id=thread_root, card=running_card - ) - if running_msg_id: - self._start_streaming(task_id, running_msg_id, resume_title) - print(f"[Feishu] Auto-resuming task {task_id} from thread reply") - return - else: - self._reply_message( - thread_root, - f"❌ Task #{task_id} not found or has no saved session.", - ) - print(f"[Feishu] Task {task_id} cannot be resumed") - return - else: - print("[Feishu] Thread message but no matching task found, creating new task") - else: - print("[Feishu] Message is not a reply (no parent_id or root_id)") - - # ── default: create a new task from message text ───────── - print("[Feishu] Creating new task from message") - print(f"[Feishu] image_paths to attach: {image_paths}") - from channels.dir_utils import resolve_working_dir - - working_dir = resolve_working_dir(content, "feishu", self.db) - title = content[:60] + ("…" if len(content) > 60 else "") - - # Convert image_paths to prompt_images for frontend display - prompt_images = [] - if image_paths: - for img_path in image_paths: - try: - with open(img_path, "rb") as f: - img_data = base64.b64encode(f.read()).decode("utf-8") - - # Detect media type from file extension - ext = Path(img_path).suffix.lower() - media_type_map = { - ".jpg": "image/jpeg", - ".jpeg": "image/jpeg", - ".png": "image/png", - ".gif": "image/gif", - ".webp": "image/webp", - } - media_type = media_type_map.get(ext, "image/jpeg") - - prompt_images.append( - {"name": Path(img_path).name, "media_type": media_type, "data": img_data} - ) - print( - f"[Feishu] Converted {img_path} to prompt_images ({media_type}, {len(img_data)} bytes)" - ) - except Exception as e: - print(f"[Feishu] Failed to convert image {img_path} to base64: {e}") - - from channels.agent_utils import resolve_agent - from taskboard import ScheduleType, Task - - new_task = Task( - title=f"[Feishu] {title}", - prompt=content, - working_dir=working_dir, - schedule_type=ScheduleType.IMMEDIATE, - tags="feishu", - image_paths=image_paths, - prompt_images=prompt_images, - feishu_root_msg_id=message.message_id, - agent=resolve_agent("feishu", self.db), - ) - print( - f"[Feishu] Task object created with {len(image_paths)} image_paths and {len(prompt_images)} prompt_images" - ) - task_id = self.scheduler.submit_task(new_task) - print(f"[Feishu] Task {task_id} submitted, verifying in DB...") - created_task = self.db.get_task(task_id) - print( - f"[Feishu] Task {task_id} in DB has image_paths: {created_task.get('image_paths')}, prompt_images: {len(created_task.get('prompt_images', []))} items" - ) - img_info = ( - f" (with {len(image_paths)} image{'s' if len(image_paths) != 1 else ''})" - if image_paths - else "" - ) - - # Send running card and start streaming - task_title = f"[Feishu] {title}" - running_card = self._build_streaming_card(task_id, task_title, "") - running_msg_id = self._create_reply(parent_message_id=message.message_id, card=running_card) - with self._origin_lock: - self._task_origin[task_id] = (reply_to, message.message_id, message.message_id) - with self._root_msg_lock: - self._root_msg_map[message.message_id] = task_id - if running_msg_id: - self._start_streaming(task_id, running_msg_id, task_title) - print( - f"[Feishu] Task {task_id} origin tracked: reply_to={reply_to}, root_msg={message.message_id}" - ) - print(f"[Feishu] New task {task_id} created and queued with {len(image_paths)} images") diff --git a/channels/slack_channel.py b/channels/slack_channel.py deleted file mode 100644 index 21d3d41..0000000 --- a/channels/slack_channel.py +++ /dev/null @@ -1,646 +0,0 @@ -""" -AgentForge Slack Channel - -Listens for @bot mentions and DMs via Slack Socket Mode (no public IP required). -Send any message to create a task; reply to a completion notification to resume. -Slash commands (/status, /cancel, /resume) are also supported. - -Required environment variables: - SLACK_BOT_TOKEN — xoxb-... bot token - SLACK_APP_TOKEN — xapp-... app-level token (for Socket Mode) -""" - -import os -import threading -import traceback -from typing import TYPE_CHECKING, Optional - -from taskboard_bus import Channel, MessageBus, OutboundMessage, OutboundMessageType - -if TYPE_CHECKING: - from taskboard import TaskDB, TaskScheduler - - -def _require_slack(): - try: - from slack_sdk import WebClient - from slack_sdk.socket_mode import SocketModeClient - from slack_sdk.socket_mode.request import SocketModeRequest - from slack_sdk.socket_mode.response import SocketModeResponse - - return WebClient, SocketModeClient, SocketModeResponse, SocketModeRequest - except ImportError as e: - raise ImportError( - "slack-sdk is required for SlackChannel. Install it with: uv add slack-sdk" - ) from e - - -HELP_TEXT = """\ -*AgentForge Bot* 👋 -Send me any message and I'll create a task from it. -Reply to a completion/failure notification to resume that task. - -*Commands:* -• `/status <id>` — show task details -• `/cancel <id>` — cancel a task -• `/resume <id> <message>` — resume a task with a message -• `/dir <path>` — set default working directory -  e.g. `/dir ~/workspace/myproject` -• `/agent <name>` — switch coding agent (`claude` / `codex`) -• `/help` — show this message - -*Tips:* -• You can also mention a path in your message and it will be used automatically. - e.g. _在 ~/myapp 里帮我修复登录 bug_ -• Reply to any result notification to continue the conversation. -""" - - -class SlackChannel(Channel): - """Slack channel integration using Socket Mode.""" - - def __init__( - self, - bus: MessageBus, - db: "TaskDB", - scheduler: "TaskScheduler", - bot_token: str = "", - app_token: str = "", - ): - super().__init__("slack", bus, db) - self.scheduler = scheduler - - self.bot_token = bot_token or os.environ.get("SLACK_BOT_TOKEN", "") - self.app_token = app_token or os.environ.get("SLACK_APP_TOKEN", "") - - self._web_client = None - self._socket_client = None - self._bot_user_id: Optional[str] = None - - # Maps task_id → (channel_id, thread_ts, reaction_ts) for reply-back on completion - # thread_ts: used for posting reply messages in the correct thread - # reaction_ts: used for adding emoji reactions (may differ from thread_ts on resume) - self._task_origin: dict[int, tuple[str, Optional[str], Optional[str]]] = {} - self._origin_lock = threading.Lock() - - # DM channel cache for P2P fallback - self._dm_channel_cache: dict[str, str] = {} # user_id → DM channel_id - - # Maps notification thread_ts → task_id for resume-by-reply - self._notification_map: dict[str, int] = {} - self._notification_lock = threading.Lock() - - # Maps thread root ts → task_id for thread-based session resume - self._thread_ts_map: dict[str, int] = {} - self._thread_ts_lock = threading.Lock() - - # Subscribe to outbound bus messages for task notifications - bus.subscribe_outbound(self._on_outbound) - - print( - f"[Slack] Initialized. bot_token={'set' if self.bot_token else 'MISSING'}, " - f"app_token={'set' if self.app_token else 'MISSING'}" - ) - - # ── lifecycle ──────────────────────────────────────────────── - - def start(self) -> None: - if not self.bot_token or not self.app_token: - print("[Slack] Missing SLACK_BOT_TOKEN or SLACK_APP_TOKEN — channel disabled") - return - - print("[Slack] Starting... importing slack_sdk") - WebClient, SocketModeClient, SocketModeResponse, SocketModeRequest = _require_slack() - print("[Slack] slack_sdk imported successfully") - - self._web_client = WebClient(token=self.bot_token) - print("[Slack] WebClient created, calling auth_test()...") - - # Resolve bot's own user ID so we can ignore self-messages - try: - resp = self._web_client.auth_test() - self._bot_user_id = resp["user_id"] - print( - f"[Slack] auth_test OK — bot_user_id={self._bot_user_id}, team={resp.get('team', '?')}, user={resp.get('user', '?')}" - ) - except Exception as e: - print(f"[Slack] auth_test FAILED: {e}") - traceback.print_exc() - return - - print("[Slack] Creating SocketModeClient...") - self._socket_client = SocketModeClient( - app_token=self.app_token, - web_client=self._web_client, - ) - - # Register event handler - self._socket_client.socket_mode_request_listeners.append(self._handle_socket_request) - print("[Slack] Registered socket_mode_request_listeners") - - self._running = True - print("[Slack] Calling socket_client.connect()...") - self._socket_client.connect() - print("[Slack] Socket Mode connected — listening for events") - - def stop(self) -> None: - print("[Slack] Stopping...") - self._running = False - self.bus.unsubscribe_outbound(self._on_outbound) - if self._socket_client: - try: - self._socket_client.disconnect() - except Exception: - pass - print("[Slack] Stopped") - - # ── socket mode handler ────────────────────────────────────── - - def _handle_socket_request(self, client, req) -> None: - from slack_sdk.socket_mode.response import SocketModeResponse - - print( - f"[Slack] <<< Socket request received: type={req.type}, envelope_id={req.envelope_id[:12]}..." - ) - - # Acknowledge immediately (Slack requires < 3s ack) - client.send_socket_mode_response(SocketModeResponse(envelope_id=req.envelope_id)) - print(f"[Slack] ACK sent for envelope {req.envelope_id[:12]}") - - if req.type != "events_api": - print(f"[Slack] Ignoring non-events_api request type: {req.type}") - return - - payload = req.payload - event = payload.get("event", {}) - event_type = event.get("type", "") - - print( - f"[Slack] Event type={event_type}, " - f"user={event.get('user', '?')}, " - f"channel={event.get('channel', '?')}, " - f"channel_type={event.get('channel_type', '?')}, " - f"bot_id={event.get('bot_id', 'none')}, " - f"subtype={event.get('subtype', 'none')}, " - f"text={repr((event.get('text', '') or '')[:80])}" - ) - - # Handle message events - try: - if event_type == "message": - self._handle_message_event(event) - elif event_type == "app_mention": - self._handle_mention_event(event) - elif event_type == "app_home_opened": - self._handle_app_home_opened(event) - else: - print(f"[Slack] Unhandled event type: {event_type}") - except Exception as e: - print(f"[Slack] ERROR handling {event_type} event: {e}") - traceback.print_exc() - - def _handle_message_event(self, event: dict) -> None: - """Handle DM messages (channel_type == 'im').""" - # Only process DMs, not channel messages (those come via app_mention) - if event.get("channel_type") != "im": - print( - f"[Slack] message event skipped: channel_type={event.get('channel_type')!r} (not 'im')" - ) - return - # Ignore bot messages and message edits - if event.get("bot_id") or event.get("subtype"): - print( - f"[Slack] message event skipped: bot_id={event.get('bot_id')}, subtype={event.get('subtype')}" - ) - return - - user_id = event.get("user", "") - if user_id == self._bot_user_id: - print("[Slack] message event skipped: message from self (bot)") - return - - text = event.get("text", "").strip() - channel_id = event.get("channel", "") - thread_ts = event.get("thread_ts") - msg_ts = event.get("ts") - - print(f"[Slack] DM from user={user_id}, channel={channel_id}, text={repr(text[:80])}") - self._handle_user_message(text, channel_id, thread_ts, msg_ts) - - def _handle_mention_event(self, event: dict) -> None: - """Handle @bot mentions in channels.""" - if event.get("bot_id") or event.get("subtype"): - print( - f"[Slack] mention event skipped: bot_id={event.get('bot_id')}, subtype={event.get('subtype')}" - ) - return - - user_id = event.get("user", "") - if user_id == self._bot_user_id: - print("[Slack] mention event skipped: mention from self (bot)") - return - - # Strip the mention prefix (<@BOTID> ...) from the text - text = event.get("text", "").strip() - if self._bot_user_id: - mention_prefix = f"<@{self._bot_user_id}>" - if text.startswith(mention_prefix): - text = text[len(mention_prefix) :].strip() - - channel_id = event.get("channel", "") - thread_ts = event.get("thread_ts") - msg_ts = event.get("ts") - - print( - f"[Slack] Mention from user={user_id}, channel={channel_id}, text={repr(text[:80])}" - ) - self._handle_user_message(text, channel_id, thread_ts, msg_ts) - - def _handle_app_home_opened(self, event: dict) -> None: - """Handle app_home_opened event — send HELP_TEXT DM on first open.""" - user_id = event.get("user", "") - if not user_id or user_id == self._bot_user_id: - return - # Only send on the first open (tab == "home", not "messages") - tab = event.get("tab", "") - if tab != "home": - return - print(f"[Slack] app_home_opened by user={user_id}, sending HELP_TEXT via DM") - dm_ch = self._open_dm_channel(user_id) - if dm_ch: - self._reply(dm_ch, None, HELP_TEXT) - else: - print(f"[Slack] Failed to open DM channel with user {user_id}") - - # ── unified message handler ─────────────────────────────────── - - def _handle_user_message( - self, text: str, channel_id: str, thread_ts: Optional[str], msg_ts: str - ) -> None: - """Handle any user message: commands, resume-by-reply, or create task.""" - if not text: - self._reply(channel_id, msg_ts, HELP_TEXT) - return - - # ── slash commands ──────────────────────────────────────── - if text.startswith("/"): - parts = text.split(None, 1) - cmd = parts[0].lower() - args = parts[1].strip() if len(parts) > 1 else "" - - if cmd == "/status": - self._cmd_status(args, channel_id, msg_ts) - elif cmd == "/cancel": - self._cmd_cancel(args, channel_id, msg_ts) - elif cmd == "/resume": - self._cmd_resume(args, channel_id, msg_ts) - elif cmd in ("/dir", "/cd"): - from channels.dir_utils import handle_dir_command - - reply = handle_dir_command(text, "slack", self.db) - self._reply(channel_id, msg_ts, reply or HELP_TEXT) - elif cmd == "/agent": - from channels.agent_utils import handle_agent_command - - reply = handle_agent_command(text, "slack", self.db) - self._reply(channel_id, msg_ts, reply or HELP_TEXT) - elif cmd == "/help": - self._reply(channel_id, msg_ts, HELP_TEXT) - else: - self._reply(channel_id, msg_ts, HELP_TEXT) - return - - if text.lower() == "help": - self._reply(channel_id, msg_ts, HELP_TEXT) - return - - # ── reply to a notification thread → resume task ────────── - if thread_ts: - # Look up task_id: first from notification_map, then from thread_ts_map - with self._notification_lock: - task_id = self._notification_map.get(thread_ts) - if not task_id: - with self._thread_ts_lock: - task_id = self._thread_ts_map.get(thread_ts) - if task_id: - task = self.db.get_task(task_id) - if task and task.get("session_id"): - self.db.update_task( - task_id, - status="pending", - prompt=text, - result=None, - error=None, - question=None, - ) - with self._origin_lock: - self._task_origin[task_id] = (channel_id, thread_ts, msg_ts) - self._add_reaction(channel_id, msg_ts, "eyes") - self._reply(channel_id, thread_ts, ":arrow_forward:") - print(f"[Slack] Auto-resuming task {task_id} from thread reply") - return - else: - self._reply( - channel_id, - thread_ts, - f":x: Task *#{task_id}* has no saved session to resume.", - ) - return - - # ── default: create a new task from message text ────────── - self._create_task(text, channel_id, msg_ts) - - # ── task creation ───────────────────────────────────────────── - - def _create_task(self, text: str, channel_id: str, thread_ts: str) -> None: - """Create a new task from any message.""" - from taskboard import ScheduleType, Task - - title = text[:60] + ("…" if len(text) > 60 else "") - from channels.agent_utils import resolve_agent - from channels.dir_utils import resolve_working_dir - - task = Task( - title=f"[Slack] {title}", - prompt=text, - working_dir=resolve_working_dir(text, "slack", self.db), - schedule_type=ScheduleType.IMMEDIATE, - tags="slack", - agent=resolve_agent("slack", self.db), - ) - task_id = self.scheduler.submit_task(task) - print(f"[Slack] Task #{task_id} created from message") - - with self._origin_lock: - self._task_origin[task_id] = (channel_id, thread_ts, thread_ts) - print( - f"[Slack] Origin set for task #{task_id}: channel={channel_id}, thread_ts={thread_ts}, " - f"self_id={id(self)}, origin_dict_id={id(self._task_origin)}" - ) - - # Track thread root ts → task_id so replies in the thread can resume - with self._thread_ts_lock: - self._thread_ts_map[thread_ts] = task_id - - # Acknowledge with an eyes reaction and a brief running hint - self._add_reaction(channel_id, thread_ts, "eyes") - self._reply(channel_id, thread_ts, f"Task #{task_id} is running…") - - # ── commands ────────────────────────────────────────────────── - - def _cmd_status(self, args: str, channel_id: str, thread_ts: str) -> None: - task_id = self._parse_task_id(args) - if task_id is None: - self._reply(channel_id, thread_ts, ":warning: Usage: `/status <task_id>`") - return - - task = self.db.get_task(task_id) - if not task: - self._reply(channel_id, thread_ts, f":x: Task #{task_id} not found.") - return - - status_emoji = { - "pending": ":hourglass:", - "scheduled": ":calendar:", - "running": ":runner:", - "completed": ":white_check_mark:", - "failed": ":x:", - "cancelled": ":no_entry_sign:", - } - emoji = status_emoji.get(task["status"], ":grey_question:") - lines = [ - f"{emoji} *Task #{task['id']}* — *{task['title']}*", - f"Status: `{task['status']}`", - f"Created: {task.get('created_at', '—')}", - f"Last run: {task.get('last_run_at') or '—'}", - ] - if task.get("error"): - lines.append(f"Error: `{task['error'][:300]}`") - if task.get("result"): - lines.append(f"Result: {task['result'][:500]}") - - self._reply(channel_id, thread_ts, "\n".join(lines)) - - def _cmd_cancel(self, args: str, channel_id: str, thread_ts: str) -> None: - task_id = self._parse_task_id(args) - if task_id is None: - self._reply(channel_id, thread_ts, ":warning: Usage: `/cancel <task_id>`") - return - - task = self.db.get_task(task_id) - if not task: - self._reply(channel_id, thread_ts, f":x: Task #{task_id} not found.") - return - - if task["status"] in ("completed", "failed", "cancelled"): - self._reply( - channel_id, - thread_ts, - f":information_source: Task #{task_id} is already `{task['status']}`.", - ) - return - - self.db.update_task(task_id, status="cancelled") - self._reply(channel_id, thread_ts, f":no_entry_sign: Task #{task_id} cancelled.") - - def _cmd_resume(self, args: str, channel_id: str, thread_ts: str) -> None: - parts = args.strip().split(" ", 1) - if not parts or not parts[0].lstrip("#").isdigit(): - self._reply(channel_id, thread_ts, ":warning: Usage: `/resume <task_id> <message>`") - return - - tid = int(parts[0].lstrip("#")) - resume_msg = parts[1].strip() if len(parts) > 1 else "" - if not resume_msg: - self._reply(channel_id, thread_ts, ":warning: Please provide a message to resume with.") - return - - task = self.db.get_task(tid) - if not task or not task.get("session_id"): - self._reply( - channel_id, thread_ts, f":x: Task #{tid} not found or has no saved session." - ) - return - - self.db.update_task( - tid, - status="pending", - prompt=resume_msg, - result=None, - error=None, - question=None, - ) - with self._origin_lock: - self._task_origin[tid] = (channel_id, thread_ts, thread_ts) - self._add_reaction(channel_id, thread_ts, "eyes") - self._reply(channel_id, thread_ts, ":arrow_forward:") - - # ── Channel ABC: send outbound message ─────────────────────── - - def send(self, msg: OutboundMessage) -> None: - """Forward task completion/failure to the originating Slack thread.""" - if msg.type not in (OutboundMessageType.TASK_COMPLETED, OutboundMessageType.TASK_FAILED): - return - - task_id = msg.task_id - with self._origin_lock: - origin = self._task_origin.get(task_id) - print( - f"[Slack] send() task_id={task_id} (type={type(task_id).__name__}), " - f"origin={origin}, keys={list(self._task_origin.keys())}, " - f"self_id={id(self)}, origin_dict_id={id(self._task_origin)}" - ) - - # Build notification text - if msg.type == OutboundMessageType.TASK_COMPLETED: - result_text = (msg.payload.get("result") or "").strip()[:10000] - title = msg.payload.get("title") or f"Task #{task_id}" - text = result_text or "Done." - else: - error_text = (msg.payload.get("error") or "Unknown error").strip()[:800] - title = msg.payload.get("title") or f"Task #{task_id}" - text = error_text - - if origin: - channel_id, thread_ts, reaction_ts = origin - # Add emoji reaction to the message that triggered the task (or resume) - react_target = reaction_ts or thread_ts - if msg.type == OutboundMessageType.TASK_COMPLETED: - self._add_reaction(channel_id, react_target, "white_check_mark") - else: - self._add_reaction(channel_id, react_target, "x") - else: - # Fallback: P2P DM to configured user, or default channel - dm_user = self.db.get_setting("slack_default_user") - default_channel = self.db.get_setting("slack_default_channel") - if dm_user: - dm_ch = self._open_dm_channel(dm_user) - if dm_ch: - channel_id = dm_ch - thread_ts = None - status_emoji = ( - ":white_check_mark:" - if msg.type == OutboundMessageType.TASK_COMPLETED - else ":x:" - ) - text = f"{status_emoji} *{title}*\n{text}" - print(f"[Slack] Falling back to P2P DM with user {dm_user}") - else: - print(f"[Slack] Failed to open DM with user {dm_user}, skipping") - return - elif default_channel: - channel_id = default_channel - thread_ts = None - status_emoji = ( - ":white_check_mark:" - if msg.type == OutboundMessageType.TASK_COMPLETED - else ":x:" - ) - text = f"{status_emoji} *{title}*\n{text}" - else: - print( - f"[Slack] No origin, no known user, no slack_default_channel for task #{task_id}, skipping" - ) - return - - print(f"[Slack] Sending outbound notification for task #{task_id}: {msg.type.name}") - - def _send_and_track(): - sent_ts = self._reply_return_ts(channel_id, thread_ts, text) - if sent_ts: - with self._notification_lock: - self._notification_map[sent_ts] = task_id - print(f"[Slack] Notification ts={sent_ts} mapped to task #{task_id}") - - threading.Thread(target=_send_and_track, daemon=True).start() - - # Free origin memory after terminal state - with self._origin_lock: - self._task_origin.pop(task_id, None) - - def _on_outbound(self, msg: OutboundMessage) -> None: - """MessageBus outbound subscriber callback.""" - self.send(msg) - - # ── helpers ────────────────────────────────────────────────── - - def _open_dm_channel(self, user_id: str) -> Optional[str]: - """Open (or retrieve cached) DM channel with a user.""" - if user_id in self._dm_channel_cache: - return self._dm_channel_cache[user_id] - if not self._web_client: - return None - try: - resp = self._web_client.conversations_open(users=[user_id]) - ch_id = resp["channel"]["id"] - self._dm_channel_cache[user_id] = ch_id - print(f"[Slack] Opened DM channel {ch_id} with user {user_id}") - return ch_id - except Exception as e: - print(f"[Slack] conversations.open failed for user {user_id}: {e}") - return None - - def _add_reaction(self, channel_id: str, timestamp: str, emoji: str) -> None: - """Add an emoji reaction to a message (non-blocking).""" - if not self._web_client: - return - - def _do(): - try: - self._web_client.reactions_add( - channel=channel_id, - timestamp=timestamp, - name=emoji, - ) - except Exception as e: - if "already_reacted" in str(e): - pass # Reaction already exists, ignore - else: - print(f"[Slack] Failed to add reaction {emoji}: {e}") - - threading.Thread(target=_do, daemon=True).start() - - def _reply(self, channel_id: str, thread_ts: Optional[str], text: str) -> None: - if not self._web_client: - print("[Slack] _reply skipped: no web_client") - return - try: - print( - f"[Slack] >>> Sending message to channel={channel_id}, thread={thread_ts}, len={len(text)}" - ) - self._web_client.chat_postMessage( - channel=channel_id, - thread_ts=thread_ts, - text=text, - mrkdwn=True, - ) - print("[Slack] >>> Message sent OK") - except Exception as e: - print(f"[Slack] >>> chat_postMessage FAILED: {e}") - traceback.print_exc() - - def _reply_return_ts( - self, channel_id: str, thread_ts: Optional[str], text: str - ) -> Optional[str]: - """Send a message and return its ts (for tracking notification threads).""" - if not self._web_client: - return None - try: - resp = self._web_client.chat_postMessage( - channel=channel_id, - thread_ts=thread_ts, - text=text, - mrkdwn=True, - ) - return resp.get("ts") - except Exception as e: - print(f"[Slack] >>> chat_postMessage FAILED: {e}") - traceback.print_exc() - return None - - @staticmethod - def _parse_task_id(s: str) -> Optional[int]: - try: - return int(s.strip().lstrip("#")) - except (ValueError, AttributeError): - return None diff --git a/channels/telegram_channel.py b/channels/telegram_channel.py deleted file mode 100644 index d4a1c78..0000000 --- a/channels/telegram_channel.py +++ /dev/null @@ -1,621 +0,0 @@ -""" -Telegram channel for AgentForge. - -Send any message to create a task. Reply to a completion/failure notification -to resume that task. Slash commands also supported: - - /help — show help - /status <id> — task details - /cancel <id> — cancel a task - /resume <id> <message> — resume a task with a message - /dir <path> — set default working directory - -When a task completes or fails the bot sends a notification to the chat where -the task was created. - -Configuration via environment variables: - TELEGRAM_BOT_TOKEN — required, bot token from @BotFather - TELEGRAM_ALLOWED_USERS — optional, comma-separated Telegram user IDs - (numeric). When set, any other user is rejected. -""" - -import asyncio -import os -import threading -from datetime import datetime, timedelta, timezone -from typing import TYPE_CHECKING, Optional - -try: - from telegram import Update - from telegram.constants import ParseMode - from telegram.ext import ( - Application, - CommandHandler, - ContextTypes, - MessageHandler, - filters, - ) - - TELEGRAM_AVAILABLE = True -except ImportError: - TELEGRAM_AVAILABLE = False - -from taskboard_bus import Channel, MessageBus, OutboundMessage, OutboundMessageType - -if TYPE_CHECKING: - from taskboard import TaskDB, TaskScheduler - - -HELP_TEXT = ( - "👋 *AgentForge Bot*\n\n" - "Send me any message and I'll create a task from it\\.\n" - "Reply to a completion/failure notification to resume that task\\.\n\n" - "*Commands:*\n" - "/status `<id>` — task details\n" - "/cancel `<id>` — cancel a task\n" - "/resume `<id> <message>` — resume a task\n" - "/dir `<path>` — set default working directory\n" - "    e\\.g\\. `/dir ~/workspace/myproject`\n" - "/agent `<name>` — switch coding agent \\(`claude` / `codex`\\)\n" - "/help — show this message\n\n" - "*Tips:*\n" - "• You can also mention a path in your message and it will be used automatically\\.\n" - " e\\.g\\. _在 ~/myapp 里帮我修复登录 bug_\n" - "• Reply to any result notification to continue the conversation\\." -) - - -class TelegramChannel(Channel): - """Telegram bot integration for AgentForge. - - Runs an async Application (python-telegram-bot v21+) inside its own - event loop on a dedicated daemon thread, so it doesn't interfere with - the synchronous HTTP server. - """ - - def __init__( - self, - bus: MessageBus, - db: "TaskDB", - scheduler: "TaskScheduler", - token: str, - allowed_users: Optional[list[int]] = None, - ): - super().__init__("telegram", bus, db) - self.scheduler = scheduler - self._token = token - self._allowed_users: set[int] = set(allowed_users or []) - self._app: Optional["Application"] = None - self._loop: Optional[asyncio.AbstractEventLoop] = None - self._loop_ready = threading.Event() - self._thread: Optional[threading.Thread] = None - - # Maps task_id → (chat_id, reply_message_id, reaction_message_id) for reply-back and reactions - # reply_message_id: used for reply_to_message_id when posting completion - # reaction_message_id: used for adding emoji reactions (may differ on resume) - self._task_origin: dict[int, tuple[int, int, int]] = {} - self._origin_lock = threading.Lock() - - # Maps notification message_id → task_id for resume-by-reply - self._notification_map: dict[int, int] = {} - self._notification_lock = threading.Lock() - - # Subscribe to bus so send() is called on task updates - bus.subscribe_outbound(self._on_outbound) - - # ── lifecycle ──────────────────────────────────────────────── - - def start(self) -> None: - if not TELEGRAM_AVAILABLE: - print("[Telegram] python-telegram-bot not installed. Run: uv add python-telegram-bot") - return - self._running = True - self._thread = threading.Thread(target=self._run_bot, daemon=True, name="telegram-bot") - self._thread.start() - print("[Telegram] Bot thread started") - - def stop(self) -> None: - print("[Telegram] Stopping bot…") - self._running = False - self.bus.unsubscribe_outbound(self._on_outbound) - if self._loop and self._app: - asyncio.run_coroutine_threadsafe(self._app.updater.stop(), self._loop) - asyncio.run_coroutine_threadsafe(self._app.stop(), self._loop) - asyncio.run_coroutine_threadsafe(self._app.shutdown(), self._loop) - if self._thread: - self._thread.join(timeout=10) - print("[Telegram] Bot stopped") - - # ── Channel ABC: send outbound message ─────────────────────── - - def _on_outbound(self, msg: OutboundMessage) -> None: - """MessageBus outbound subscriber callback.""" - self.send(msg) - - def send(self, msg: OutboundMessage) -> None: - """Forward a task completion/failure notification to the originating chat.""" - if not self._running: - return - if msg.type not in (OutboundMessageType.TASK_COMPLETED, OutboundMessageType.TASK_FAILED): - return - if not self._loop_ready.wait(timeout=30): - print("[Telegram] send() called before event loop ready, dropping message") - return - if not self._app or not self._loop: - return - - task_id = msg.task_id - with self._origin_lock: - origin = self._task_origin.get(task_id) - - title = msg.payload.get("title") or f"Task #{task_id}" - - is_completed = msg.type == OutboundMessageType.TASK_COMPLETED - if is_completed: - result_text = (msg.payload.get("result") or "").strip() - if len(result_text) > 10000: - result_text = result_text[:10000] + "\n…(truncated)" - body = result_text or "Done." - else: - error_text = (msg.payload.get("error") or "Unknown error").strip() - # Smart truncation: keep beginning (most informative) and signal cut - if len(error_text) > 800: - error_text = error_text[:800] + "\n…(truncated — use /status for full details)" - body = error_text - - orig_message_id = None - reaction_message_id = None - if origin: - chat_id, orig_message_id, reaction_message_id = origin - # Always include task title and status emoji for clarity - status_emoji = "✅" if is_completed else "❌" - text = f"{status_emoji} Task #{task_id}: {title}\n{body}" - if not is_completed: - text += f"\n\n/status {task_id}" - else: - default_chat_id = self.db.get_setting("telegram_default_chat_id", "") - if not default_chat_id: - print( - f"[Telegram] No origin and no telegram_default_chat_id configured for task #{task_id}, skipping" - ) - return - chat_id = ( - int(default_chat_id) - if str(default_chat_id).lstrip("-").isdigit() - else default_chat_id - ) - status_emoji = "✅" if is_completed else "❌" - text = f"{status_emoji} Task #{task_id}: {title}\n{body}" - if not is_completed: - text += f"\n\n/status {task_id}" - print(f"[Telegram] Using default chat_id={chat_id} for task #{task_id}") - - async def _send_and_track(): - try: - react_target = reaction_message_id or orig_message_id - if react_target: - # Add emoji reaction to the message that triggered the task (or resume) - emoji = "👍" if msg.type == OutboundMessageType.TASK_COMPLETED else "👎" - try: - from telegram import ReactionTypeEmoji - - await self._app.bot.set_message_reaction( - chat_id=chat_id, - message_id=react_target, - reaction=[ReactionTypeEmoji(emoji=emoji)], - ) - except Exception as e: - print(f"[Telegram] Failed to set reaction on message {react_target}: {e}") - - sent = await self._app.bot.send_message( - chat_id=chat_id, - text=text, - reply_to_message_id=orig_message_id, - ) - if sent: - with self._notification_lock: - self._notification_map[sent.message_id] = task_id - print( - f"[Telegram] Notification msg_id={sent.message_id} mapped to task #{task_id}" - ) - except Exception as e: - print(f"[Telegram] Failed to send notification to {chat_id}: {e}") - - asyncio.run_coroutine_threadsafe(_send_and_track(), self._loop) - - # Free origin memory after terminal state - with self._origin_lock: - self._task_origin.pop(task_id, None) - - # ── private helpers ────────────────────────────────────────── - - def _run_bot(self) -> None: - """Entry point for the bot thread — creates and runs the event loop.""" - self._loop = asyncio.new_event_loop() - asyncio.set_event_loop(self._loop) - self._loop_ready.set() - try: - self._loop.run_until_complete(self._start_app()) - except Exception as e: - print(f"[Telegram] Bot error: {e}") - finally: - self._loop.close() - - async def _start_app(self) -> None: - self._app = Application.builder().token(self._token).build() - - # Slash commands - self._app.add_handler(CommandHandler("start", self._cmd_help)) - self._app.add_handler(CommandHandler("help", self._cmd_help)) - self._app.add_handler(CommandHandler("status", self._cmd_status)) - self._app.add_handler(CommandHandler("cancel", self._cmd_cancel)) - self._app.add_handler(CommandHandler("resume", self._cmd_resume)) - - # Any non-command text message → create task or resume by reply - self._app.add_handler( - MessageHandler(filters.TEXT & ~filters.COMMAND, self._handle_text_message) - ) - - await self._app.initialize() - await self._app.start() - await self._app.updater.start_polling(drop_pending_updates=True) - print("[Telegram] Bot polling started") - - while self._running: - await asyncio.sleep(1) - - await self._app.updater.stop() - await self._app.stop() - await self._app.shutdown() - - async def _send_text(self, chat_id: int, text: str) -> None: - try: - await self._app.bot.send_message(chat_id=chat_id, text=text) - except Exception as e: - print(f"[Telegram] Failed to send message to {chat_id}: {e}") - - def _is_allowed(self, user_id: int) -> bool: - if not self._allowed_users: - return True - return user_id in self._allowed_users - - # ── unified text message handler ────────────────────────────── - - def _format_forwarded_text(self, text: str, update: "Update") -> str: - """格式化转发的消息文本,添加发送者和时间信息 - - Args: - text: 消息文本 - update: Telegram Update 对象 - - Returns: - 格式化后的文本 - """ - msg = update.message - is_forwarded = msg.forward_from or msg.forward_date - - if not is_forwarded: - return text - - parts = ["📨 [转发消息]"] - - # 获取发送者信息 - sender_name = "未知用户" - if msg.forward_from: - sender = msg.forward_from - if sender.username: - sender_name = f"@{sender.username}" - else: - name_parts = [sender.first_name or ""] - if sender.last_name: - name_parts.append(sender.last_name) - sender_name = " ".join(filter(None, name_parts)) - parts.append(f"转发自: {sender_name}") - elif msg.forward_from_chat: - chat = msg.forward_from_chat - sender_name = chat.title or chat.username or "未知频道" - if chat.type == "channel": - parts.append(f"转发自频道: {sender_name}") - elif chat.type == "group" or chat.type == "supergroup": - parts.append(f"转发自群组: {sender_name}") - else: - parts.append(f"转发自: {sender_name}") - else: - parts.append(f"转发自: {sender_name}") - - # 添加时间戳 - if msg.forward_date: - ts = datetime.fromtimestamp(msg.forward_date, tz=timezone(timedelta(hours=8))) - parts.append(f"时间: {ts.strftime('%Y-%m-%d %H:%M')}") - - parts.append("\n--- 转发内容 ---") - parts.append(text) - - return "\n".join(parts) - - async def _handle_text_message( - self, update: "Update", context: "ContextTypes.DEFAULT_TYPE" - ) -> None: - """Handle any non-command text: resume-by-reply or create task.""" - if not self._is_allowed(update.effective_user.id): - await update.message.reply_text("⛔ You are not authorised to use this bot.") - return - - text = (update.message.text or "").strip() - if not text: - return - - # ── /dir command: switch working directory ───────────────── - from channels.dir_utils import handle_dir_command - - dir_reply = handle_dir_command(text, "telegram", self.db) - if dir_reply is not None: - await update.message.reply_text(dir_reply) - return - - # ── /agent command: switch coding agent ────────────────── - from channels.agent_utils import handle_agent_command - - agent_reply = handle_agent_command(text, "telegram", self.db) - if agent_reply is not None: - await update.message.reply_text(agent_reply) - return - - # ── 检测转发消息 ─────────────────────────────────────── - text = self._format_forwarded_text(text, update) - - chat_id = update.effective_chat.id - - # ── reply to a notification → resume task ───────────────── - reply = update.message.reply_to_message - if reply: - with self._notification_lock: - task_id = self._notification_map.get(reply.message_id) - if task_id: - task = self.db.get_task(task_id) - if task and task.get("session_id"): - self.db.update_task( - task_id, - status="pending", - prompt=text, - result=None, - error=None, - question=None, - ) - with self._origin_lock: - self._task_origin[task_id] = ( - chat_id, - update.message.message_id, - update.message.message_id, - ) - - # Add "eyes" reaction and send resuming message - try: - from telegram import ReactionTypeEmoji - - await self._app.bot.set_message_reaction( - chat_id=chat_id, - message_id=update.message.message_id, - reaction=[ReactionTypeEmoji(emoji="👀")], - ) - except Exception as e: - print(f"[Telegram] Failed to set resume reaction: {e}") - await update.message.reply_text("▶️") - print(f"[Telegram] Auto-resuming task {task_id} from reply") - return - else: - await update.message.reply_text( - f"❌ Task #{task_id} has no saved session to resume." - ) - return - - # ── default: create a new task ──────────────────────────── - self._create_task(text, chat_id, update) - - def _create_task(self, text: str, chat_id: int, update: "Update") -> None: - """Create a new task from any message text.""" - from taskboard import ScheduleType, Task - - msg = update.message - - # 检查是否为转发消息,用于添加标题标记 - is_forwarded = msg.forward_from or msg.forward_date - title_prefix = "📨 " if is_forwarded else "" - title = text[:60] + ("…" if len(text) > 60 else "") - - from channels.dir_utils import resolve_working_dir - - working_dir = resolve_working_dir(text, "telegram", self.db) - - from channels.agent_utils import resolve_agent - - task = Task( - title=f"[Telegram] {title_prefix}{title}", - prompt=text, - working_dir=working_dir, - schedule_type=ScheduleType.IMMEDIATE, - tags="telegram" + (", forwarded" if is_forwarded else ""), - agent=resolve_agent("telegram", self.db), - ) - task_id = self.scheduler.submit_task(task) - print( - f"[Telegram] Task #{task_id} created from message{' (forwarded)' if is_forwarded else ''}" - ) - - message_id = update.message.message_id - with self._origin_lock: - self._task_origin[task_id] = (chat_id, message_id, message_id) - - # Acknowledge with an "eyes" reaction and a brief running hint - async def _react(): - try: - from telegram import ReactionTypeEmoji - - await self._app.bot.set_message_reaction( - chat_id=chat_id, - message_id=message_id, - reaction=[ReactionTypeEmoji(emoji="👀")], - ) - await self._app.bot.send_message( - chat_id=chat_id, - text=f"Task #{task_id} is running…", - reply_to_message_id=message_id, - ) - except Exception as e: - print(f"[Telegram] Failed to set reaction: {e}") - - asyncio.run_coroutine_threadsafe(_react(), self._loop) - - # ── command handlers ────────────────────────────────────────── - - async def _cmd_help(self, update: "Update", context: "ContextTypes.DEFAULT_TYPE") -> None: - if not self._is_allowed(update.effective_user.id): - await update.message.reply_text("⛔ You are not authorised to use this bot.") - return - await update.message.reply_text(HELP_TEXT, parse_mode=ParseMode.MARKDOWN_V2) - - async def _cmd_status(self, update: "Update", context: "ContextTypes.DEFAULT_TYPE") -> None: - if not self._is_allowed(update.effective_user.id): - await update.message.reply_text("⛔ Not authorised.") - return - - if not context.args or not context.args[0].lstrip("#").isdigit(): - await update.message.reply_text("Usage: /status <task_id>") - return - - task_id = int(context.args[0].lstrip("#")) - task = self.db.get_task(task_id) - if not task: - await update.message.reply_text(f"❌ Task #{task_id} not found.") - return - - status_icon = { - "pending": "🕐", - "scheduled": "📅", - "running": "⏳", - "completed": "✅", - "failed": "❌", - "cancelled": "🚫", - } - icon = status_icon.get(task["status"], "•") - lines = [ - f"{icon} Task #{task_id} — {task['status']}", - f"{task['title']}", - f"Created: {task.get('created_at', '—')[:16]}", - f"Last run: {(task.get('last_run_at') or '—')[:16]}", - ] - if task.get("error"): - lines.append(f"\nError: {task['error'][:300]}") - if task.get("result"): - lines.append(f"\nResult: {task['result'][:500]}") - - await update.message.reply_text("\n".join(lines)) - - async def _cmd_cancel(self, update: "Update", context: "ContextTypes.DEFAULT_TYPE") -> None: - if not self._is_allowed(update.effective_user.id): - await update.message.reply_text("⛔ Not authorised.") - return - - if not context.args or not context.args[0].lstrip("#").isdigit(): - await update.message.reply_text("Usage: /cancel <task_id>") - return - - task_id = int(context.args[0].lstrip("#")) - task = self.db.get_task(task_id) - if not task: - await update.message.reply_text(f"❌ Task #{task_id} not found.") - return - if task["status"] in ("completed", "failed", "cancelled"): - await update.message.reply_text(f"ℹ️ Task #{task_id} is already {task['status']}.") - return - - self.db.update_task(task_id, status="cancelled") - await update.message.reply_text(f"🚫 Task #{task_id} cancelled.") - - async def _cmd_resume(self, update: "Update", context: "ContextTypes.DEFAULT_TYPE") -> None: - if not self._is_allowed(update.effective_user.id): - await update.message.reply_text("⛔ Not authorised.") - return - - if not context.args or not context.args[0].lstrip("#").isdigit(): - await update.message.reply_text("Usage: /resume <task_id> <message>") - return - - tid = int(context.args[0].lstrip("#")) - resume_msg = " ".join(context.args[1:]).strip() - if not resume_msg: - await update.message.reply_text("Please provide a message to resume with.") - return - - task = self.db.get_task(tid) - if not task or not task.get("session_id"): - await update.message.reply_text(f"❌ Task #{tid} not found or has no saved session.") - return - - self.db.update_task( - tid, - status="pending", - prompt=resume_msg, - result=None, - error=None, - question=None, - ) - chat_id = update.effective_chat.id - with self._origin_lock: - self._task_origin[tid] = (chat_id, update.message.message_id, update.message.message_id) - - # Add "eyes" reaction to the user's command message - try: - from telegram import ReactionTypeEmoji - - await self._app.bot.set_message_reaction( - chat_id=chat_id, - message_id=update.message.message_id, - reaction=[ReactionTypeEmoji(emoji="👀")], - ) - except Exception as e: - print(f"[Telegram] Failed to set resume reaction: {e}") - - await update.message.reply_text("▶️") - - -# ── helpers ────────────────────────────────────────────────────────────────── - - -def _escape_md(text: str) -> str: - """Escape special MarkdownV2 characters.""" - special = r"\_*[]()~`>#+-=|{}.!" - return "".join(f"\\{c}" if c in special else c for c in text) - - -# ── factory helper ─────────────────────────────────────────────────────────── - - -def create_telegram_channel( - db, scheduler, bus=None, token: str = "", allowed_users_str: str = "" -) -> Optional["TelegramChannel"]: - """Create a TelegramChannel from explicit params or environment variables.""" - token = (token or os.environ.get("TELEGRAM_BOT_TOKEN", "")).strip() - if not token: - return None - - allowed_raw = (allowed_users_str or os.environ.get("TELEGRAM_ALLOWED_USERS", "")).strip() - allowed_users: list[int] = [] - if allowed_raw: - for uid in allowed_raw.split(","): - uid = uid.strip() - if uid.isdigit(): - allowed_users.append(int(uid)) - - if bus is None: - from taskboard_bus import MessageBus - - bus = MessageBus() - - return TelegramChannel( - bus=bus, - db=db, - scheduler=scheduler, - token=token, - allowed_users=allowed_users, - ) diff --git a/channels/weixin_bridge/index.mjs b/channels/weixin_bridge/index.mjs deleted file mode 100644 index 31d1ddd..0000000 --- a/channels/weixin_bridge/index.mjs +++ /dev/null @@ -1,824 +0,0 @@ -import crypto from "node:crypto"; -import fs from "node:fs"; -import path from "node:path"; -import readline from "node:readline"; - -const DEFAULT_BASE_URL = "https://ilinkai.weixin.qq.com"; -const INITIAL_BASE_URL = process.env.AGENTFORGE_WEIXIN_BASE_URL || DEFAULT_BASE_URL; -const BOT_TYPE = process.env.AGENTFORGE_WEIXIN_BOT_TYPE || "3"; -const DATA_DIR = process.env.AGENTFORGE_WEIXIN_DATA_DIR || path.join(process.env.HOME || ".", ".agentforge", "weixin"); -const ACCOUNT_FILE = path.join(DATA_DIR, "account.json"); -const AUTO_LOGIN = (process.env.AGENTFORGE_WEIXIN_AUTO_LOGIN || "true") !== "false"; -const ACCOUNT_ID_OVERRIDE = process.env.AGENTFORGE_WEIXIN_ACCOUNT_ID || ""; -const CHANNEL_VERSION = "agentforge-weixin-bridge/0.2.0"; -const DEFAULT_CDN_BASE_URL = process.env.AGENTFORGE_WEIXIN_CDN_BASE_URL || ""; -const MESSAGE_TYPE = { - USER: 1, - BOT: 2, -}; -const MESSAGE_STATE = { - FINISH: 2, -}; -const MESSAGE_ITEM_TYPE = { - TEXT: 1, - IMAGE: 2, -}; -const UPLOAD_MEDIA_TYPE = { - IMAGE: 1, -}; -const IMAGE_MIME_BY_EXT = { - ".png": "image/png", - ".jpg": "image/jpeg", - ".jpeg": "image/jpeg", - ".gif": "image/gif", - ".webp": "image/webp", -}; - -let shuttingDown = false; -let loginInFlight = null; -let pollerStarted = false; -let pollTimer = null; -let state = loadState(); -const pendingSentMessages = new Map(); - -function emit(event) { - process.stdout.write(`${JSON.stringify(event)}\n`); -} - -function log(message) { - process.stderr.write(`[WeixinBridge] ${message}\n`); -} - -function ensureDataDir() { - fs.mkdirSync(DATA_DIR, { recursive: true }); -} - -function ensureMediaDir(kind) { - const dir = path.join(DATA_DIR, "media", kind); - fs.mkdirSync(dir, { recursive: true }); - return dir; -} - -function mediaFileName(prefix, ext) { - const stamp = new Date().toISOString().replace(/[:.]/g, "-"); - return `${prefix}-${stamp}-${crypto.randomBytes(6).toString("hex")}${ext}`; -} - -function imageExtFromBuffer(buf, fallback = ".jpg") { - if (buf.subarray(0, 8).equals(Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]))) { - return ".png"; - } - if (buf.subarray(0, 3).equals(Buffer.from([0xff, 0xd8, 0xff]))) { - return ".jpg"; - } - if (buf.subarray(0, 6).toString("ascii") === "GIF87a" || buf.subarray(0, 6).toString("ascii") === "GIF89a") { - return ".gif"; - } - if (buf.subarray(0, 4).toString("ascii") === "RIFF" && buf.subarray(8, 12).toString("ascii") === "WEBP") { - return ".webp"; - } - return fallback; -} - -function getImageMimeFromFilename(filePath) { - return IMAGE_MIME_BY_EXT[path.extname(filePath).toLowerCase()] || "image/jpeg"; -} - -function encryptAesEcb(plaintext, key) { - const cipher = crypto.createCipheriv("aes-128-ecb", key, null); - return Buffer.concat([cipher.update(plaintext), cipher.final()]); -} - -function decryptAesEcb(ciphertext, key) { - const decipher = crypto.createDecipheriv("aes-128-ecb", key, null); - return Buffer.concat([decipher.update(ciphertext), decipher.final()]); -} - -function aesEcbPaddedSize(plaintextSize) { - return Math.ceil((plaintextSize + 1) / 16) * 16; -} - -function parseAesKey(aesKeyBase64, label) { - const decoded = Buffer.from(aesKeyBase64, "base64"); - if (decoded.length === 16) { - return decoded; - } - if (decoded.length === 32 && /^[0-9a-fA-F]{32}$/.test(decoded.toString("ascii"))) { - return Buffer.from(decoded.toString("ascii"), "hex"); - } - throw new Error(`${label}: aes_key must decode to 16 raw bytes or a 32-char hex string`); -} - -function resolveCdnBaseUrl() { - return DEFAULT_CDN_BASE_URL || state?.baseUrl || process.env.AGENTFORGE_WEIXIN_BASE_URL || DEFAULT_BASE_URL; -} - -function buildCdnDownloadUrl(encryptedQueryParam, cdnBaseUrl = resolveCdnBaseUrl()) { - return `${cdnBaseUrl.replace(/\/$/, "")}/download?encrypted_query_param=${encodeURIComponent(encryptedQueryParam)}`; -} - -function buildCdnUploadUrl(uploadParam, filekey, cdnBaseUrl = resolveCdnBaseUrl()) { - return `${cdnBaseUrl.replace(/\/$/, "")}/upload?encrypted_query_param=${encodeURIComponent(uploadParam)}&filekey=${encodeURIComponent(filekey)}`; -} - -async function fetchCdnBytes(url, label) { - const response = await fetch(url); - if (!response.ok) { - const body = await response.text().catch(() => ""); - throw new Error(`${label}: CDN download ${response.status} ${response.statusText}: ${body}`); - } - return Buffer.from(await response.arrayBuffer()); -} - -async function downloadAndDecryptBuffer(encryptedQueryParam, aesKeyBase64, label, fullUrl) { - const key = parseAesKey(aesKeyBase64, label); - const url = fullUrl || buildCdnDownloadUrl(encryptedQueryParam); - const encrypted = await fetchCdnBytes(url, label); - return decryptAesEcb(encrypted, key); -} - -async function downloadPlainCdnBuffer(encryptedQueryParam, label, fullUrl) { - const url = fullUrl || buildCdnDownloadUrl(encryptedQueryParam); - return fetchCdnBytes(url, label); -} - -function loadState() { - try { - if (!fs.existsSync(ACCOUNT_FILE)) { - return { - accountId: ACCOUNT_ID_OVERRIDE, - baseUrl: process.env.AGENTFORGE_WEIXIN_BASE_URL || DEFAULT_BASE_URL, - token: "", - userId: "", - syncCursor: "", - }; - } - const parsed = JSON.parse(fs.readFileSync(ACCOUNT_FILE, "utf8")); - return { - accountId: ACCOUNT_ID_OVERRIDE || parsed.accountId || "", - baseUrl: parsed.baseUrl || process.env.AGENTFORGE_WEIXIN_BASE_URL || DEFAULT_BASE_URL, - token: parsed.token || "", - userId: parsed.userId || "", - syncCursor: parsed.syncCursor || "", - }; - } catch (error) { - log(`failed to load state: ${String(error)}`); - return { - accountId: ACCOUNT_ID_OVERRIDE, - baseUrl: process.env.AGENTFORGE_WEIXIN_BASE_URL || DEFAULT_BASE_URL, - token: "", - userId: "", - syncCursor: "", - }; - } -} - -function saveState() { - ensureDataDir(); - fs.writeFileSync( - ACCOUNT_FILE, - JSON.stringify( - { - accountId: state.accountId, - baseUrl: state.baseUrl, - token: state.token, - userId: state.userId, - syncCursor: state.syncCursor, - }, - null, - 2, - ), - "utf8", - ); -} - -function clearSession() { - state = { - ...state, - token: "", - syncCursor: "", - baseUrl: INITIAL_BASE_URL, - }; - saveState(); -} - -function ensureTrailingSlash(url) { - return url.endsWith("/") ? url : `${url}/`; -} - -function randomWechatUin() { - const uint32 = crypto.randomBytes(4).readUInt32BE(0); - return Buffer.from(String(uint32), "utf8").toString("base64"); -} - -function buildHeaders(body, token) { - const headers = { - "Content-Type": "application/json", - AuthorizationType: "ilink_bot_token", - "Content-Length": String(Buffer.byteLength(body, "utf8")), - "X-WECHAT-UIN": randomWechatUin(), - }; - if (token) { - headers.Authorization = `Bearer ${token}`; - } - return headers; -} - -async function postJson(endpoint, payload, token, timeoutMs = 15000) { - const body = JSON.stringify({ ...payload, base_info: { channel_version: CHANNEL_VERSION } }); - const controller = new AbortController(); - const timeout = setTimeout(() => controller.abort(), timeoutMs); - try { - const response = await fetch(new URL(endpoint, ensureTrailingSlash(state.baseUrl)), { - method: "POST", - headers: buildHeaders(body, token), - body, - signal: controller.signal, - }); - const raw = await response.text(); - if (!response.ok) { - throw new Error(`${response.status} ${response.statusText}: ${raw}`); - } - return raw ? JSON.parse(raw) : {}; - } finally { - clearTimeout(timeout); - } -} - -async function getUploadUrl(params) { - return postJson( - "ilink/bot/getuploadurl", - { - filekey: params.filekey, - media_type: params.media_type, - to_user_id: params.to_user_id, - rawsize: params.rawsize, - rawfilemd5: params.rawfilemd5, - filesize: params.filesize, - no_need_thumb: true, - aeskey: params.aeskey, - }, - state.token, - 15000, - ); -} - -async function uploadBufferToCdn(params) { - const ciphertext = encryptAesEcb(params.buf, params.aeskey); - const uploadUrl = params.uploadFullUrl?.trim() - || (params.uploadParam ? buildCdnUploadUrl(params.uploadParam, params.filekey) : ""); - if (!uploadUrl) { - throw new Error(`${params.label}: CDN upload URL missing`); - } - - let lastError = null; - for (let attempt = 1; attempt <= 3; attempt += 1) { - try { - const response = await fetch(uploadUrl, { - method: "POST", - headers: { "Content-Type": "application/octet-stream" }, - body: new Uint8Array(ciphertext), - }); - if (response.status >= 400 && response.status < 500) { - const body = response.headers.get("x-error-message") || (await response.text()); - throw new Error(`${params.label}: CDN upload client error ${response.status}: ${body}`); - } - if (response.status !== 200) { - const body = response.headers.get("x-error-message") || `status ${response.status}`; - throw new Error(`${params.label}: CDN upload server error: ${body}`); - } - const downloadParam = response.headers.get("x-encrypted-param") || ""; - if (!downloadParam) { - throw new Error(`${params.label}: CDN response missing x-encrypted-param`); - } - return { downloadParam }; - } catch (error) { - lastError = error; - if (error instanceof Error && error.message.includes("client error")) { - throw error; - } - if (attempt < 3) { - log(`${params.label}: CDN upload attempt ${attempt} failed: ${String(error)}`); - } - } - } - throw lastError || new Error(`${params.label}: CDN upload failed`); -} - -async function uploadImageToWeixin(filePath, toUserId) { - const plaintext = fs.readFileSync(filePath); - const rawsize = plaintext.length; - const rawfilemd5 = crypto.createHash("md5").update(plaintext).digest("hex"); - const filesize = aesEcbPaddedSize(rawsize); - const filekey = crypto.randomBytes(16).toString("hex"); - const aeskey = crypto.randomBytes(16); - const uploadUrlResp = await getUploadUrl({ - filekey, - media_type: UPLOAD_MEDIA_TYPE.IMAGE, - to_user_id: toUserId, - rawsize, - rawfilemd5, - filesize, - aeskey: aeskey.toString("hex"), - }); - const uploaded = await uploadBufferToCdn({ - buf: plaintext, - uploadFullUrl: uploadUrlResp.upload_full_url, - uploadParam: uploadUrlResp.upload_param, - filekey, - aeskey, - label: `uploadImageToWeixin:${path.basename(filePath)}`, - }); - return { - filekey, - downloadEncryptedQueryParam: uploaded.downloadParam, - aeskey: aeskey.toString("hex"), - fileSize: rawsize, - fileSizeCiphertext: filesize, - }; -} - -function buildImageItem(uploaded) { - return { - type: MESSAGE_ITEM_TYPE.IMAGE, - image_item: { - media: { - encrypt_query_param: uploaded.downloadEncryptedQueryParam, - aes_key: Buffer.from(uploaded.aeskey).toString("base64"), - encrypt_type: 1, - }, - mid_size: uploaded.fileSizeCiphertext, - }, - }; -} - -async function fetchQrCode() { - const controller = new AbortController(); - const timeout = setTimeout(() => controller.abort(), 15000); - try { - const url = new URL(`ilink/bot/get_bot_qrcode?bot_type=${encodeURIComponent(BOT_TYPE)}`, ensureTrailingSlash(INITIAL_BASE_URL)); - log(`fetchQrCode: GET ${url}`); - const response = await fetch(url, { signal: controller.signal }); - log(`fetchQrCode: status=${response.status} ok=${response.ok}`); - const raw = await response.text(); - if (!response.ok) { - log(`fetchQrCode: error body=${raw.slice(0, 200)}`); - throw new Error(`${response.status} ${response.statusText}: ${raw}`); - } - const data = JSON.parse(raw); - log(`fetchQrCode: qrcode=${data?.qrcode || "MISSING"} img_len=${String(data?.qrcode_img_content || "").length}`); - return data; - } finally { - clearTimeout(timeout); - } -} - -async function pollQrStatus(qrcode, baseUrl = INITIAL_BASE_URL) { - const controller = new AbortController(); - const timeout = setTimeout(() => controller.abort(), 35000); - try { - const url = new URL(`ilink/bot/get_qrcode_status?qrcode=${encodeURIComponent(qrcode)}`, ensureTrailingSlash(baseUrl)); - const response = await fetch(url, { - headers: { "iLink-App-ClientVersion": "1" }, - signal: controller.signal, - }); - const raw = await response.text(); - if (!response.ok) { - throw new Error(`${response.status} ${response.statusText}: ${raw}`); - } - return JSON.parse(raw); - } catch (error) { - if (error instanceof Error && error.name === "AbortError") { - return { status: "wait" }; - } - throw error; - } finally { - clearTimeout(timeout); - } -} - -function extractText(itemList = []) { - const parts = []; - for (const item of itemList) { - if (item?.type === MESSAGE_ITEM_TYPE.TEXT && item.text_item?.text) { - parts.push(String(item.text_item.text)); - } else if (item?.type === 3 && item.voice_item?.text) { - parts.push(String(item.voice_item.text)); - } - } - return parts.join("\n").trim(); -} - -function extractReplyToMessageId(itemList = []) { - for (const item of itemList) { - const refMessageId = item?.ref_msg?.message_item?.msg_id; - if (refMessageId) { - return String(refMessageId); - } - } - return ""; -} - -function extractReplyReference(itemList = []) { - for (const item of itemList) { - const ref = item?.ref_msg; - if (!ref) { - continue; - } - return { - messageId: ref?.message_item?.msg_id ? String(ref.message_item.msg_id) : "", - title: ref?.title ? String(ref.title) : "", - text: ref?.message_item ? extractText([ref.message_item]) : "", - }; - } - return { messageId: "", title: "", text: "" }; -} - -async function downloadInboundImage(item) { - const imageItem = item?.image_item; - const media = imageItem?.media; - if (!media?.encrypt_query_param && !media?.full_url) { - return null; - } - const aesKeyBase64 = imageItem.aeskey - ? Buffer.from(imageItem.aeskey, "hex").toString("base64") - : media.aes_key; - const label = "inbound image"; - const buf = aesKeyBase64 - ? await downloadAndDecryptBuffer(media.encrypt_query_param || "", aesKeyBase64, label, media.full_url) - : await downloadPlainCdnBuffer(media.encrypt_query_param || "", label, media.full_url); - const ext = imageExtFromBuffer(buf); - const filePath = path.join(ensureMediaDir("inbound"), mediaFileName("weixin-inbound", ext)); - fs.writeFileSync(filePath, buf); - return { - path: filePath, - media_type: IMAGE_MIME_BY_EXT[ext] || getImageMimeFromFilename(filePath), - size: buf.length, - }; -} - -async function extractInboundImages(itemList = []) { - const images = []; - const errors = []; - for (const item of itemList) { - if (item?.type !== MESSAGE_ITEM_TYPE.IMAGE) { - continue; - } - try { - const image = await downloadInboundImage(item); - if (image) { - images.push(image); - } - } catch (error) { - const message = String(error); - errors.push(message); - log(`inbound image download failed: ${message}`); - } - } - return { images, errors }; -} - -function extractQuotedMessageId(msg) { - for (const item of msg?.item_list || []) { - if (item?.msg_id) { - return String(item.msg_id); - } - } - if (msg?.message_id != null) { - return String(msg.message_id); - } - return ""; -} - -function maybeEmitSentConfirmation(msg) { - const clientId = String(msg?.client_id || ""); - if (!clientId) { - return; - } - const pending = pendingSentMessages.get(clientId); - if (!pending) { - return; - } - const quotedMessageId = extractQuotedMessageId(msg); - if (!quotedMessageId) { - return; - } - pendingSentMessages.delete(clientId); - emit({ - type: "sent", - request_id: pending.requestId, - message_id: clientId, - quoted_message_id: quotedMessageId, - peer_id: pending.peerId, - }); -} - -async function normalizeInboundMessage(msg) { - if (msg?.message_type !== MESSAGE_TYPE.USER) { - return null; - } - const peerId = msg.from_user_id || ""; - const text = extractText(msg.item_list || []); - const { images, errors } = await extractInboundImages(msg.item_list || []); - if (!peerId || (!text && !images.length)) { - return null; - } - const replyRef = extractReplyReference(msg.item_list || []); - return { - type: "message", - account_id: state.accountId || ACCOUNT_ID_OVERRIDE || "", - peer_id: peerId, - context_token: msg.context_token || "", - message_id: String(msg.message_id || msg.client_id || crypto.randomUUID()), - reply_to_message_id: replyRef.messageId, - reply_to_message_title: replyRef.title, - reply_to_message_text: replyRef.text, - text, - image_paths: images.map((image) => image.path), - images, - image_errors: errors, - raw_message_type: msg.message_type || 0, - }; -} - -async function sendMessageItem(command, item) { - if (!state.token) { - throw new Error("weixin account is not logged in"); - } - const messageId = crypto.randomUUID(); - await postJson( - "ilink/bot/sendmessage", - { - msg: { - from_user_id: "", - to_user_id: command.peer_id, - client_id: messageId, - message_type: MESSAGE_TYPE.BOT, - message_state: MESSAGE_STATE.FINISH, - item_list: [item], - context_token: command.context_token || undefined, - }, - }, - state.token, - 15000, - ); - pendingSentMessages.set(messageId, { - requestId: command.request_id || "", - peerId: command.peer_id || "", - }); - emit({ - type: "accepted", - request_id: command.request_id || "", - client_id: messageId, - peer_id: command.peer_id, - }); - return messageId; -} - -async function sendTextMessage(command) { - return sendMessageItem(command, { - type: MESSAGE_ITEM_TYPE.TEXT, - text_item: { text: command.text || "" }, - }); -} - -async function sendMessageWithImages(command) { - const imagePaths = Array.isArray(command.image_paths) - ? command.image_paths.filter((imagePath) => typeof imagePath === "string" && imagePath) - : []; - if (!imagePaths.length) { - await sendTextMessage(command); - return; - } - - if ((command.text || "").trim()) { - await sendTextMessage(command); - } - for (const imagePath of imagePaths) { - const uploaded = await uploadImageToWeixin(imagePath, command.peer_id); - await sendMessageItem(command, buildImageItem(uploaded)); - } -} - -async function pollUpdatesOnce() { - if (!state.token || shuttingDown) { - return; - } - - const response = await postJson( - "ilink/bot/getupdates", - { - get_updates_buf: state.syncCursor || "", - }, - state.token, - 40000, - ); - - if (response?.errcode === -14) { - emit({ type: "error", message: "session_expired" }); - clearSession(); - pollerStarted = false; - if (AUTO_LOGIN) { - await ensureLogin(); - } - return; - } - - if (typeof response?.get_updates_buf === "string") { - state.syncCursor = response.get_updates_buf; - saveState(); - } - - for (const msg of response?.msgs || []) { - maybeEmitSentConfirmation(msg); - const normalized = await normalizeInboundMessage(msg); - if (normalized) { - emit(normalized); - } - } -} - -async function pollLoop() { - if (pollerStarted) { - return; - } - pollerStarted = true; - emit({ type: "ready", account_id: state.accountId || "" }); - while (!shuttingDown && state.token) { - try { - await pollUpdatesOnce(); - } catch (error) { - emit({ type: "error", message: String(error) }); - await new Promise((resolve) => { - pollTimer = setTimeout(resolve, 2000); - }); - } - } - pollerStarted = false; -} - -async function startPollingIfReady() { - if (state.token && !pollerStarted) { - void pollLoop(); - } -} - -async function loginFlow() { - const MAX_QR_RETRIES = 3; - log(`loginFlow: start INITIAL_BASE_URL=${INITIAL_BASE_URL} state.baseUrl=${state.baseUrl}`); - try { - for (let attempt = 0; attempt < MAX_QR_RETRIES; attempt++) { - log(`loginFlow: fetchQrCode attempt ${attempt + 1}/${MAX_QR_RETRIES}`); - const qr = await fetchQrCode(); - if (!qr?.qrcode || !qr?.qrcode_img_content) { - throw new Error("QR code response missing qrcode image content"); - } - log( - `qr payload received: len=${String(qr.qrcode_img_content).length} prefix=${String(qr.qrcode_img_content).slice(0, 80)}`, - ); - - emit({ - type: "qr", - qrcode_url: qr.qrcode_img_content, - account_id: state.accountId || ACCOUNT_ID_OVERRIDE || "", - }); - - let currentPollBaseUrl = INITIAL_BASE_URL; - let expired = false; - - while (!shuttingDown) { - const status = await pollQrStatus(qr.qrcode, currentPollBaseUrl); - if (status?.status === "confirmed" && status?.bot_token) { - state = { - ...state, - accountId: ACCOUNT_ID_OVERRIDE || status.ilink_bot_id || state.accountId, - baseUrl: status.baseurl || state.baseUrl, - token: status.bot_token, - userId: status.ilink_user_id || state.userId, - syncCursor: "", - }; - saveState(); - emit({ - type: "login_success", - account_id: state.accountId, - user_id: state.userId, - }); - await startPollingIfReady(); - return; - } - if (status?.status === "scaned_but_redirect") { - const redirect = String(status.redirect_host || "").trim(); - if (redirect) { - currentPollBaseUrl = redirect.startsWith("http") ? redirect : `https://${redirect}`; - } - continue; - } - if (status?.status === "expired") { - expired = true; - break; - } - if (status?.status === "scaned") { - emit({ type: "scaned" }); - } - } - - if (!expired) return; - if (attempt + 1 < MAX_QR_RETRIES) { - log(`QR code expired, retrying (attempt ${attempt + 2}/${MAX_QR_RETRIES})`); - } - } - throw new Error("QR code expired"); - } catch (error) { - emit({ type: "error", message: `login_failed: ${String(error)}` }); - throw error; - } finally { - loginInFlight = null; - } -} - -async function ensureLogin() { - if (loginInFlight) { - log("ensureLogin: login already in flight, reusing"); - return loginInFlight; - } - log("ensureLogin: starting new loginFlow"); - loginInFlight = loginFlow().catch(() => undefined); - return loginInFlight; -} - -async function handleCommand(command) { - if (!command?.type) { - return; - } - - if (command.type === "send_message") { - await sendMessageWithImages(command); - return; - } - - if (command.type === "login") { - log(`handleCommand: login — token=${state.token ? "present" : "absent"} baseUrl=${state.baseUrl} loginInFlight=${loginInFlight != null}`); - clearSession(); - log(`handleCommand: login — session cleared, INITIAL_BASE_URL=${INITIAL_BASE_URL}`); - await ensureLogin(); - return; - } - - if (command.type === "logout") { - log(`handleCommand: logout — token=${state.token ? "present" : "absent"} baseUrl=${state.baseUrl} loginInFlight=${loginInFlight != null}`); - loginInFlight = null; - clearSession(); - log(`handleCommand: logout — session cleared, INITIAL_BASE_URL=${INITIAL_BASE_URL}`); - emit({ type: "logged_out" }); - await ensureLogin(); - } -} - -ensureDataDir(); - -const rl = readline.createInterface({ - input: process.stdin, - crlfDelay: Infinity, -}); - -rl.on("line", (line) => { - if (!line.trim()) { - return; - } - let command; - try { - command = JSON.parse(line); - } catch { - emit({ type: "error", message: "invalid_json" }); - return; - } - void handleCommand(command).catch((error) => { - emit({ - type: "error", - request_id: command?.request_id || "", - message: String(error), - }); - }); -}); - -process.on("SIGINT", () => { - shuttingDown = true; - if (pollTimer) { - clearTimeout(pollTimer); - } - process.exit(0); -}); - -process.on("SIGTERM", () => { - shuttingDown = true; - if (pollTimer) { - clearTimeout(pollTimer); - } - process.exit(0); -}); - -if (state.token) { - void startPollingIfReady(); -} else if (AUTO_LOGIN) { - void ensureLogin(); -} diff --git a/channels/weixin_bridge/package.json b/channels/weixin_bridge/package.json deleted file mode 100644 index 444597f..0000000 --- a/channels/weixin_bridge/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "agentforge-weixin-bridge", - "private": true, - "type": "module", - "version": "0.1.0", - "description": "Node sidecar bridge for AgentForge Weixin channel", - "engines": { - "node": ">=22" - } -} diff --git a/channels/weixin_channel.py b/channels/weixin_channel.py deleted file mode 100644 index 050c2e7..0000000 --- a/channels/weixin_channel.py +++ /dev/null @@ -1,725 +0,0 @@ -""" -Weixin channel for AgentForge. - -Text-only MVP backed by a Node sidecar bridge that communicates with Python via -newline-delimited JSON over stdio. -""" - -from __future__ import annotations - -import base64 -import json -import os -import re -import shutil -import subprocess -import sys -import threading -import uuid -from pathlib import Path -from typing import TYPE_CHECKING, Any, Optional -from urllib.parse import unquote, urlparse - -from taskboard_bus import Channel, MessageBus, OutboundMessage, OutboundMessageType - - -def _find_node_executable() -> Optional[str]: - """Locate the Node.js binary. - - macOS apps launched from Finder/Dock inherit a minimal PATH that excludes - Homebrew (`/opt/homebrew/bin`), so ``shutil.which("node")`` misses even when - node is installed. Fall back to the common install locations. - """ - found = shutil.which("node") - if found: - return found - for candidate in ("/opt/homebrew/bin/node", "/usr/local/bin/node", "/usr/bin/node"): - if os.path.exists(candidate): - return candidate - return None - - -if TYPE_CHECKING: - from taskboard import TaskDB, TaskScheduler - - -WEIXIN_UPLOADABLE_IMAGE_SUFFIXES = {".png", ".jpg", ".jpeg", ".gif", ".webp"} -WEIXIN_MARKDOWN_IMAGE_RE = re.compile(r"!\[[^\]]*]\(([^)]+)\)") -WEIXIN_NEW_SESSION_RE = re.compile(r"^/new(?:\s+(.*))?$", re.IGNORECASE | re.DOTALL) - - -class WeixinChannel(Channel): - """Weixin integration using a Node bridge process.""" - - def __init__( - self, - bus: MessageBus, - db: "TaskDB", - scheduler: "TaskScheduler", - bridge_cmd: Optional[list[str]] = None, - ): - super().__init__("weixin", bus, db) - self.scheduler = scheduler - self.bridge_cmd = bridge_cmd or self._default_bridge_cmd() - self._bridge_proc: Optional[subprocess.Popen] = None - self._reader_thread: Optional[threading.Thread] = None - - # task_id -> origin metadata used for notifications and resume - self._task_origin: dict[int, dict[str, str]] = {} - self._origin_lock = threading.Lock() - - # account_id:peer_id -> current task_id. Weixin has no thread, so this - # gives each peer a current AgentForge session until /new starts another. - self._peer_current_task: dict[str, int] = {} - self._peer_lock = threading.Lock() - - # notification message_id -> task_id for resume-by-reply - self._notification_map: dict[str, int] = {} - self._notification_lock = threading.Lock() - - # request_id -> task_id for sent acknowledgements from the bridge - self._pending_notifications: dict[str, int] = {} - self._pending_lock = threading.Lock() - - self._status_lock = threading.Lock() - self._status = { - "configured": False, - "login_status": "idle", - "qr_code_url": "", - "last_error": "", - "account_id": "", - "user_id": "", - } - - bus.subscribe_outbound(self._on_outbound) - - def _bridge_script_path(self) -> Path: - # In the PyInstaller bundle the bridge is shipped under sys._MEIPASS - # (via --add-data), not beside the frozen source module. - if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"): - return Path(sys._MEIPASS) / "channels" / "weixin_bridge" / "index.mjs" - return Path(__file__).resolve().parent / "weixin_bridge" / "index.mjs" - - def _default_bridge_cmd(self) -> list[str]: - # Resolve node to a full path so it's found even under the minimal PATH - # a packaged macOS app inherits. Falls back to bare "node" when missing; - # start() then surfaces the FileNotFoundError as an error status. - return [_find_node_executable() or "node", str(self._bridge_script_path())] - - def start(self) -> None: - self._running = True - try: - env = os.environ.copy() - env.setdefault( - "AGENTFORGE_WEIXIN_DATA_DIR", str(Path.home() / ".agentforge" / "weixin") - ) - env.setdefault( - "AGENTFORGE_WEIXIN_BASE_URL", - self.db.get_setting("weixin_base_url", "https://ilinkai.weixin.qq.com"), - ) - env.setdefault( - "AGENTFORGE_WEIXIN_ACCOUNT_ID", - self.db.get_setting("weixin_account_id", ""), - ) - self._bridge_proc = subprocess.Popen( - self.bridge_cmd, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - text=True, - bufsize=1, - env=env, - ) - except FileNotFoundError: - self._running = False - self._bridge_proc = None - msg = ( - "Node.js not found. Install Node.js (https://nodejs.org) to use the Weixin channel." - ) - print(f"[Weixin] {msg}") - self._update_status(login_status="error", last_error=msg) - return - except Exception as exc: - self._running = False - self._bridge_proc = None - msg = f"Failed to start Weixin bridge: {exc}" - print(f"[Weixin] {msg}") - self._update_status(login_status="error", last_error=msg) - return - - self._reader_thread = threading.Thread(target=self._read_bridge_events, daemon=True) - self._reader_thread.start() - print("[Weixin] Bridge started") - - def stop(self) -> None: - self._running = False - self.bus.unsubscribe_outbound(self._on_outbound) - if self._bridge_proc and self._bridge_proc.poll() is None: - try: - self._bridge_proc.terminate() - self._bridge_proc.wait(timeout=5) - except Exception: - pass - self._bridge_proc = None - - def send(self, msg: OutboundMessage) -> None: - if not self._running: - return - if msg.type not in (OutboundMessageType.TASK_COMPLETED, OutboundMessageType.TASK_FAILED): - return - - task_id = msg.task_id - with self._origin_lock: - origin = self._task_origin.get(task_id) - if not origin: - print(f"[Weixin] No origin for task #{task_id}, skipping outbound notification") - return - - title = msg.payload.get("title") or f"Task #{task_id}" - task = self.db.get_task(task_id) or {} - if msg.type == OutboundMessageType.TASK_COMPLETED: - body = (msg.payload.get("result") or "").strip() or "Done." - image_paths = self._collect_generated_image_paths(task_id, body, task) - if image_paths: - body = self._hide_generated_image_paths(body, len(image_paths), image_paths) - text = f"✅ Task #{task_id} · {title}\n{body}" - else: - body = (msg.payload.get("error") or "Unknown error").strip() - image_paths = [] - text = f"❌ Task #{task_id} · {title}\n{body}" - - request_id = uuid.uuid4().hex - with self._pending_lock: - self._pending_notifications[request_id] = task_id - command = { - "type": "send_message", - "request_id": request_id, - "account_id": origin.get("account_id", ""), - "peer_id": origin["peer_id"], - "context_token": origin.get("context_token", ""), - "reply_to_message_id": origin.get("message_id", ""), - "text": text, - } - if image_paths: - command["image_paths"] = image_paths - self._send_command(command) - - with self._origin_lock: - self._task_origin.pop(task_id, None) - - def _on_outbound(self, msg: OutboundMessage) -> None: - self.send(msg) - - def _read_bridge_events(self) -> None: - if not self._bridge_proc or not self._bridge_proc.stdout: - return - - for line in self._bridge_proc.stdout: - if not self._running: - return - line = line.strip() - if not line: - continue - try: - event = json.loads(line) - except json.JSONDecodeError: - print(f"[Weixin] Ignoring non-JSON bridge output: {line}") - continue - self._handle_bridge_event(event) - - def _handle_bridge_event(self, event: dict[str, Any]) -> None: - event_type = event.get("type") - if event_type == "message": - self._handle_message_event(event) - elif event_type == "sent": - self._handle_sent_event(event) - elif event_type == "qr": - qr_value = event.get("qrcode_url", "") or "" - print(f"[Weixin] QR payload len={len(qr_value)} prefix={qr_value[:80]!r}") - self._update_status( - login_status="waiting_for_scan", - qr_code_url=qr_value, - account_id=event.get("account_id", ""), - last_error="", - ) - print("[Weixin] Bridge event: qr") - elif event_type == "scaned": - self._update_status(login_status="scanned", last_error="") - print("[Weixin] Bridge event: scaned") - elif event_type == "login_success": - self._update_status( - configured=True, - login_status="connected", - qr_code_url="", - account_id=event.get("account_id", ""), - user_id=event.get("user_id", ""), - last_error="", - ) - print("[Weixin] Bridge event: login_success") - elif event_type == "ready": - self._update_status( - configured=True, - login_status="connected", - qr_code_url="", - account_id=event.get("account_id", ""), - last_error="", - ) - print("[Weixin] Bridge event: ready") - elif event_type == "logged_out": - self._update_status( - configured=False, - login_status="idle", - qr_code_url="", - last_error="", - user_id="", - ) - print("[Weixin] Bridge event: logged_out") - elif event_type == "error": - self._update_status( - login_status="error", - last_error=event.get("message", "unknown_error"), - ) - print("[Weixin] Bridge event: error") - - def _handle_sent_event(self, event: dict[str, Any]) -> None: - request_id = event.get("request_id") or "" - message_id = event.get("message_id") or "" - quoted_message_id = event.get("quoted_message_id") or "" - if not request_id or (not message_id and not quoted_message_id): - return - with self._pending_lock: - task_id = self._pending_notifications.get(request_id) - if task_id is None: - return - with self._notification_lock: - if message_id: - self._notification_map[message_id] = task_id - if quoted_message_id: - self._notification_map[quoted_message_id] = task_id - if quoted_message_id: - with self._pending_lock: - self._pending_notifications.pop(request_id, None) - - def _handle_message_event(self, event: dict[str, Any]) -> None: - text = (event.get("text") or "").strip() - image_paths = self._extract_image_paths(event) - if not text and not image_paths: - return - - from channels.agent_utils import handle_agent_command, resolve_agent - from channels.dir_utils import handle_dir_command, resolve_working_dir - from taskboard import ScheduleType, Task - - reply_to_message_id = event.get("reply_to_message_id") or "" - reply_to_message_title = event.get("reply_to_message_title") or "" - reply_to_message_text = event.get("reply_to_message_text") or "" - peer_id = event.get("peer_id") or event.get("from_user_id") or "" - account_id = event.get("account_id") or "" - context_token = event.get("context_token") or "" - message_id = event.get("message_id") or "" - peer_key = self._peer_key(account_id, peer_id) - - new_match = WEIXIN_NEW_SESSION_RE.match(text) if text else None - force_new_session = bool(new_match) - if force_new_session: - text = (new_match.group(1) or "").strip() - self._clear_peer_current_task(peer_key) - if not text and not image_paths: - self._reply_to_event(event, "🆕 已开启新的 Weixin session,请发送新的任务内容。") - return - - dir_reply = handle_dir_command(text, "weixin", self.db) - if dir_reply is not None: - self._reply_to_event(event, dir_reply) - return - - agent_reply = handle_agent_command(text, "weixin", self.db) - if agent_reply is not None: - self._reply_to_event(event, agent_reply) - return - - task_id = None - if reply_to_message_id: - with self._notification_lock: - task_id = self._notification_map.get(reply_to_message_id) - - if task_id is None: - task_id = self._extract_task_id_from_reply_reference( - reply_to_message_title, - reply_to_message_text, - ) - - if task_id is None and not force_new_session: - task_id = self._get_peer_current_task(peer_key) - - if task_id is not None and not force_new_session: - task = self.db.get_task(task_id) - if task and task.get("session_id"): - updates = self._build_resume_updates(text, image_paths) - self.db.update_task(task_id, **updates) - with self._origin_lock: - self._task_origin[task_id] = { - "account_id": account_id, - "peer_id": peer_id, - "context_token": context_token, - "message_id": message_id, - } - self._set_peer_current_task(peer_key, task_id) - self._reply_to_event(event, f"▶️ 收到!正在唤醒 Task #{task_id},请稍候~") - return - if reply_to_message_id or reply_to_message_title or reply_to_message_text: - self._reply_to_event(event, f"❌ Task #{task_id} has no saved session to resume.") - return - - prompt = text or self._default_image_prompt(image_paths) - prompt_images = self._build_prompt_images(image_paths) - task = Task( - title=f"[Weixin] {prompt[:60]}{'…' if len(prompt) > 60 else ''}", - prompt=prompt, - working_dir=resolve_working_dir(prompt, "weixin", self.db), - schedule_type=ScheduleType.IMMEDIATE, - tags="weixin", - image_paths=image_paths, - prompt_images=prompt_images, - agent=resolve_agent("weixin", self.db), - ) - task_id = self.scheduler.submit_task(task) - with self._origin_lock: - self._task_origin[task_id] = { - "account_id": account_id, - "peer_id": peer_id, - "context_token": context_token, - "message_id": message_id, - } - self._set_peer_current_task(peer_key, task_id) - self._reply_to_event(event, f"Task #{task_id} is running…") - - def _peer_key(self, account_id: str, peer_id: str) -> str: - return f"{account_id}:{peer_id}" - - def _get_peer_current_task(self, peer_key: str) -> Optional[int]: - with self._peer_lock: - return self._peer_current_task.get(peer_key) - - def _set_peer_current_task(self, peer_key: str, task_id: int) -> None: - if not peer_key: - return - with self._peer_lock: - self._peer_current_task[peer_key] = task_id - - def _clear_peer_current_task(self, peer_key: str) -> None: - with self._peer_lock: - self._peer_current_task.pop(peer_key, None) - - def _default_image_prompt(self, image_paths: list[str]) -> str: - if len(image_paths) == 1: - return "请分析这张图片。" - return f"请分析这 {len(image_paths)} 张图片。" - - def _extract_image_paths(self, event: dict[str, Any]) -> list[str]: - paths: list[str] = [] - raw_paths = event.get("image_paths") - if isinstance(raw_paths, list): - paths.extend(str(path) for path in raw_paths if path) - raw_images = event.get("images") - if isinstance(raw_images, list): - for image in raw_images: - if not isinstance(image, dict): - continue - path = image.get("path") or image.get("local_path") - if path: - paths.append(str(path)) - return self._dedupe_image_paths(paths) - - def _build_resume_updates(self, prompt: str, image_paths: list[str]) -> dict[str, Any]: - resume_prompt = prompt or self._default_image_prompt(image_paths) - updates: dict[str, Any] = { - "status": "pending", - "prompt": resume_prompt, - "result": None, - "error": None, - "question": None, - } - if image_paths: - updates["image_paths"] = json.dumps(image_paths, ensure_ascii=False) - updates["prompt_images"] = json.dumps( - self._build_prompt_images(image_paths), - ensure_ascii=False, - ) - return updates - - def _build_prompt_images(self, image_paths: list[str]) -> list[dict[str, str]]: - prompt_images = [] - for image_path in image_paths: - try: - with open(image_path, "rb") as image_file: - data = base64.b64encode(image_file.read()).decode("utf-8") - except OSError as exc: - print(f"[Weixin] Failed to read inbound image {image_path}: {exc}") - continue - prompt_images.append( - { - "name": Path(image_path).name, - "media_type": self._image_media_type(image_path), - "data": data, - } - ) - return prompt_images - - def _image_media_type(self, image_path: str) -> str: - suffix = Path(image_path).suffix.lower() - if suffix == ".png": - return "image/png" - if suffix in {".jpg", ".jpeg"}: - return "image/jpeg" - if suffix == ".gif": - return "image/gif" - if suffix == ".webp": - return "image/webp" - try: - with open(image_path, "rb") as image_file: - header = image_file.read(12) - except OSError: - return "image/jpeg" - if header.startswith(b"\x89PNG\r\n\x1a\n"): - return "image/png" - if header.startswith(b"\xff\xd8\xff"): - return "image/jpeg" - if header.startswith((b"GIF87a", b"GIF89a")): - return "image/gif" - if header.startswith(b"RIFF") and b"WEBP" in header: - return "image/webp" - return "image/jpeg" - - def _collect_generated_image_paths( - self, - task_id: int, - content: str, - task: Optional[dict[str, Any]] = None, - ) -> list[str]: - paths = self._generated_image_paths_for_task(task_id) - paths.extend( - self._generated_image_paths_from_markdown( - content, - working_dir=(task or {}).get("working_dir"), - ) - ) - return self._dedupe_image_paths(paths) - - def _generated_image_paths_for_task(self, task_id: int) -> list[str]: - try: - runs = self.db.get_task_runs(task_id, limit=1) - except Exception as exc: - print(f"[Weixin] Failed to load runs for generated images: {exc}") - return [] - if not isinstance(runs, list) or not runs: - return [] - - run_id = runs[0].get("id") if isinstance(runs[0], dict) else None - if not run_id: - return [] - try: - events = self.db.get_run_output_events(run_id, limit=1000) - except Exception as exc: - print(f"[Weixin] Failed to load output events for generated images: {exc}") - return [] - if not isinstance(events, list): - return [] - - paths = [] - for event in events: - if not isinstance(event, dict) or event.get("event_type") != "generated_image": - continue - try: - payload = json.loads(event.get("content") or "{}") - except json.JSONDecodeError: - continue - path = payload.get("path") if isinstance(payload, dict) else None - if path: - paths.append(path) - return paths - - def _generated_image_paths_from_markdown( - self, - content: str, - working_dir: Optional[str] = None, - ) -> list[str]: - paths = [] - for match in WEIXIN_MARKDOWN_IMAGE_RE.finditer(content or ""): - image_path = self._local_image_path_from_reference(match.group(1), working_dir) - if image_path: - paths.append(image_path) - return paths - - def _local_image_path_from_reference( - self, - reference: str, - working_dir: Optional[str] = None, - ) -> Optional[str]: - target = self._markdown_image_reference_target(reference) - if not target or target.startswith(("http://", "https://", "data:")): - return None - if target.startswith("file://"): - parsed = urlparse(target) - target = parsed.path - elif target.startswith("sandbox:"): - target = target[len("sandbox:") :] - target = unquote(target).strip() - if not target: - return None - - path = Path(target).expanduser() - if not path.is_absolute() and working_dir: - path = Path(working_dir).expanduser() / path - return self._canonical_image_path(str(path)) - - def _markdown_image_reference_target(self, reference: str) -> str: - raw = (reference or "").strip() - if not raw: - return "" - if raw.startswith("<"): - end = raw.find(">") - if end >= 0: - return raw[1:end].strip() - if raw[0] in ("'", '"'): - end = raw.find(raw[0], 1) - if end > 0: - return raw[1:end].strip() - titled = re.match(r"(.+?)\s+['\"][^'\"]*['\"]\s*$", raw) - return (titled.group(1) if titled else raw).strip() - - def _dedupe_image_paths(self, image_paths: list[str]) -> list[str]: - deduped = [] - seen = set() - for image_path in image_paths: - canonical = self._canonical_image_path(image_path) - if not canonical or canonical in seen: - continue - seen.add(canonical) - deduped.append(canonical) - return deduped - - def _canonical_image_path(self, image_path: str) -> Optional[str]: - try: - path = Path(image_path).expanduser() - if path.suffix.lower() not in WEIXIN_UPLOADABLE_IMAGE_SUFFIXES: - return None - if not path.is_file(): - return None - return str(path.resolve()) - except OSError: - return None - - def _hide_generated_image_paths( - self, - content: str, - image_count: int, - uploaded_paths: Optional[list[str]] = None, - ) -> str: - uploaded = { - canonical - for path in (uploaded_paths or []) - if (canonical := self._canonical_image_path(path)) - } - lines = [] - for line in (content or "").splitlines(): - stripped = line.strip() - if not stripped: - lines.append("") - continue - if self._line_is_uploaded_image_path(stripped, uploaded): - continue - cleaned_line = self._remove_uploaded_markdown_image_refs(line, uploaded) - visible = cleaned_line.strip() - if visible and visible not in {"-", "*", "+"}: - lines.append(cleaned_line.rstrip()) - cleaned = "\n".join(lines).strip() - if not cleaned or cleaned.startswith("已生成"): - return f"已生成 {image_count} 张图片。" - return cleaned - - def _line_is_uploaded_image_path(self, stripped_line: str, uploaded_paths: set[str]) -> bool: - if not stripped_line.startswith("- "): - return False - candidate = stripped_line[2:].strip() - canonical = self._canonical_image_path(candidate) - if canonical and canonical in uploaded_paths: - return True - return "/.codex/generated_images/" in stripped_line - - def _remove_uploaded_markdown_image_refs(self, line: str, uploaded_paths: set[str]) -> str: - if not uploaded_paths: - return line - - def replace(match: re.Match) -> str: - image_path = self._local_image_path_from_reference(match.group(1)) - canonical = self._canonical_image_path(image_path) if image_path else None - return "" if canonical in uploaded_paths else match.group(0) - - return WEIXIN_MARKDOWN_IMAGE_RE.sub(replace, line) - - def _reply_to_event(self, event: dict[str, Any], text: str) -> None: - peer_id = event.get("peer_id") or event.get("from_user_id") - if not peer_id: - return - self._send_command( - { - "type": "send_message", - "account_id": event.get("account_id", ""), - "peer_id": peer_id, - "context_token": event.get("context_token", ""), - "reply_to_message_id": event.get("message_id", ""), - "text": text, - } - ) - - def _extract_task_id_from_reply_reference(self, *parts: str) -> Optional[int]: - for part in parts: - if not part: - continue - match = re.search(r"\bTask\s+#(\d+)\b", part) - if match: - return int(match.group(1)) - return None - - def _send_command(self, payload: dict[str, Any]) -> None: - proc_alive = self._bridge_proc and self._bridge_proc.poll() is None - stdin_ok = bool(self._bridge_proc and self._bridge_proc.stdin) - print( - f"[Weixin] _send_command: type={payload.get('type')} proc_alive={proc_alive} stdin_ok={stdin_ok}" - ) - if not self._bridge_proc or not self._bridge_proc.stdin: - print("[Weixin] _send_command: bridge not running, command dropped") - return - self._bridge_proc.stdin.write(json.dumps(payload, ensure_ascii=False) + "\n") - self._bridge_proc.stdin.flush() - - def request_login(self) -> None: - print("[Weixin] request_login: called") - self._update_status( - configured=False, - login_status="idle", - qr_code_url="", - last_error="", - user_id="", - ) - self._send_command({"type": "login"}) - - def request_logout(self) -> None: - print("[Weixin] request_logout: called") - self._update_status( - configured=False, - login_status="idle", - qr_code_url="", - last_error="", - user_id="", - ) - self._send_command({"type": "logout"}) - - def _update_status(self, **updates: Any) -> None: - with self._status_lock: - self._status.update({k: v for k, v in updates.items() if v is not None}) - - def get_status_snapshot(self) -> dict[str, Any]: - with self._status_lock: - return dict(self._status) diff --git a/index.html b/index.html index fbc1f8c..cf9ce14 100644 --- a/index.html +++ b/index.html @@ -327,7 +327,7 @@ <h2 class="section-title fade-in-up">Your agents compound your skills</h2> <section id="architecture"> <div class="container"> <h2 class="section-title fade-in-up">Two-process architecture</h2> -<p class="section-sub fade-in-up">Electron spawns a Python backend. React talks REST. No WebSocket needed.</p> +<p class="section-sub fade-in-up">Electron spawns a Bun/TypeScript backend. React talks REST. No WebSocket needed.</p> <div class="arch-diagram fade-in-up"> <div class="arch-row"> <div class="arch-box frontend">React Frontend</div> @@ -463,7 +463,7 @@ <h3>Download</h3> <div class="step-card fade-in-up"> <div class="step-num">2</div> <h3>Install</h3> -<p>Drag AgentForge to your Applications folder. The app bundles its own Python backend — no extra setup.</p> +<p>Drag AgentForge to your Applications folder. The app bundles its own Bun-compiled backend — no extra setup.</p> </div> <div class="step-card fade-in-up"> <div class="step-num">3</div> diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index 5decf0d..0000000 --- a/pyproject.toml +++ /dev/null @@ -1,59 +0,0 @@ -[project] -name = "agentforge" -version = "0.1.0" -description = "Add your description here" -readme = "README.md" -requires-python = ">=3.12" -dependencies = [ - "croniter>=6.0.0", - "requests>=2.32.5", - "lark-oapi>=1.3.0", - "python-telegram-bot>=21.0", - "slack-sdk>=3.0.0", - "claude-monitor>=3.1.0", - "pyinstaller>=6.18.0", - "python-dateutil>=2.9.0.post0", - "pytz>=2025.2", - "python-socks>=2.8.1", -] - -[dependency-groups] -dev = [ - "pyinstaller>=6.18.0", - "pytest>=9.0.2", - "pytest-cov>=7.0.0", - "ruff>=0.11.0", -] - -[tool.ruff] -line-length = 100 -target-version = "py312" -extend-exclude = [ - "skills", - "taskboard-electron", -] - -[tool.ruff.lint] -select = ["E", "F", "I", "B"] -ignore = ["E501"] - -[tool.pytest.ini_options] -testpaths = ["tests"] -pythonpath = ["."] -addopts = "-q" - -[tool.coverage.run] -branch = true -source = [ - "taskboard", - "taskboard_bus", - "channels", -] -omit = [ - "tests/*", -] - -[tool.coverage.report] -show_missing = true -skip_covered = false -fail_under = 90 diff --git a/taskboard-electron/.bun/renderer/chunk-nbmpy57s.js b/taskboard-electron/.bun/renderer/chunk-qgtap3d3.js similarity index 99% rename from taskboard-electron/.bun/renderer/chunk-nbmpy57s.js rename to taskboard-electron/.bun/renderer/chunk-qgtap3d3.js index 50dacc4..37d6718 100644 --- a/taskboard-electron/.bun/renderer/chunk-nbmpy57s.js +++ b/taskboard-electron/.bun/renderer/chunk-qgtap3d3.js @@ -13150,23 +13150,48 @@ function createInitialChannelsState(initial = {}) { const base = cloneState(DEFAULT_CHANNELS_STATE); return mergeChannelsStatus(base, initial); } -function mergeChannelsStatus(current, status = {}) { - return { +function mergeChannelsStatus(current, status = {}, options2 = {}) { + const merged = { telegram: { ...current.telegram, ...status.telegram || {} }, slack: { ...current.slack, ...status.slack || {} }, weixin: { ...current.weixin, ...status.weixin || {} } }; + if (!options2.preserveEditableFields) + return merged; + return { + telegram: { + ...merged.telegram, + enabled: current.telegram.enabled, + bot_token: current.telegram.bot_token, + allowed_users: current.telegram.allowed_users, + default_working_dir: current.telegram.default_working_dir, + default_chat_id: current.telegram.default_chat_id + }, + slack: { + ...merged.slack, + enabled: current.slack.enabled, + bot_token: current.slack.bot_token, + app_token: current.slack.app_token, + default_working_dir: current.slack.default_working_dir, + default_channel: current.slack.default_channel, + default_user: current.slack.default_user + }, + weixin: { + ...merged.weixin, + enabled: current.weixin.enabled, + default_working_dir: current.weixin.default_working_dir, + base_url: current.weixin.base_url, + account_id: current.weixin.account_id + } + }; } function buildChannelsSavePayload(channels) { - return { + const payload = { telegram_enabled: channels.telegram.enabled ? "true" : "false", - telegram_bot_token: channels.telegram.bot_token, telegram_allowed_users: channels.telegram.allowed_users, telegram_default_working_dir: channels.telegram.default_working_dir, telegram_default_chat_id: channels.telegram.default_chat_id, slack_enabled: channels.slack.enabled ? "true" : "false", - slack_bot_token: channels.slack.bot_token, - slack_app_token: channels.slack.app_token, slack_default_working_dir: channels.slack.default_working_dir, slack_default_channel: channels.slack.default_channel, slack_default_user: channels.slack.default_user, @@ -13175,6 +13200,16 @@ function buildChannelsSavePayload(channels) { weixin_base_url: channels.weixin.base_url, weixin_account_id: channels.weixin.account_id }; + if (channels.telegram.bot_token.trim()) { + payload.telegram_bot_token = channels.telegram.bot_token; + } + if (channels.slack.bot_token.trim()) { + payload.slack_bot_token = channels.slack.bot_token; + } + if (channels.slack.app_token.trim()) { + payload.slack_app_token = channels.slack.app_token; + } + return payload; } function isWeixinQrImageSource(value) { const normalized = (value || "").trim(); @@ -16841,14 +16876,9 @@ function SettingsModal({ const status = await fetchChannelsStatus(); if (!cancelled) { setChannels((c) => { - const merged = mergeChannelsStatus(c, status); - if (!preserveUserEdits) - return merged; - return { - telegram: { ...merged.telegram, enabled: c.telegram.enabled }, - slack: { ...merged.slack, enabled: c.slack.enabled }, - weixin: { ...merged.weixin, enabled: c.weixin.enabled } - }; + return mergeChannelsStatus(c, status, { + preserveEditableFields: preserveUserEdits + }); }); } }; @@ -19444,7 +19474,7 @@ function App() { children: "● Connected" }) : /* @__PURE__ */ jsx_runtime.jsx("span", { style: { color: theme.red }, - children: "● Disconnected — run `python taskboard.py`" + children: "● Disconnected — run `bun taskboard.ts`" }), connected && ` · ${runningCount} running · ${scheduledCount} scheduled · ${enabledHeartbeatCount} heartbeats` ] @@ -19743,9 +19773,9 @@ function App() { /* @__PURE__ */ jsx_runtime.jsxs("code", { style: { fontSize: 11, color: theme.text, lineHeight: 1.8, display: "block" }, children: [ - "pip install croniter", + "cd backend", /* @__PURE__ */ jsx_runtime.jsx("br", {}), - "python taskboard.py" + "bun taskboard.ts" ] }) ] @@ -19801,5 +19831,5 @@ import_client.createRoot(document.getElementById("root")).render(/* @__PURE__ */ children: /* @__PURE__ */ jsx_runtime2.jsx(App, {}) })); -//# debugId=018A608DD777E92F64756E2164756E21 -//# sourceMappingURL=chunk-nbmpy57s.js.map +//# debugId=6D6D54C3905035A964756E2164756E21 +//# sourceMappingURL=chunk-qgtap3d3.js.map diff --git a/taskboard-electron/.bun/renderer/chunk-nbmpy57s.js.map b/taskboard-electron/.bun/renderer/chunk-qgtap3d3.js.map similarity index 82% rename from taskboard-electron/.bun/renderer/chunk-nbmpy57s.js.map rename to taskboard-electron/.bun/renderer/chunk-qgtap3d3.js.map index fee645c..a660534 100644 --- a/taskboard-electron/.bun/renderer/chunk-nbmpy57s.js.map +++ b/taskboard-electron/.bun/renderer/chunk-qgtap3d3.js.map @@ -41,12 +41,12 @@ "/**\n * @license React\n * react-jsx-runtime.production.js\n *\n * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\n\"use strict\";\nvar REACT_ELEMENT_TYPE = Symbol.for(\"react.transitional.element\"),\n REACT_FRAGMENT_TYPE = Symbol.for(\"react.fragment\");\nfunction jsxProd(type, config, maybeKey) {\n var key = null;\n void 0 !== maybeKey && (key = \"\" + maybeKey);\n void 0 !== config.key && (key = \"\" + config.key);\n if (\"key\" in config) {\n maybeKey = {};\n for (var propName in config)\n \"key\" !== propName && (maybeKey[propName] = config[propName]);\n } else maybeKey = config;\n config = maybeKey.ref;\n return {\n $$typeof: REACT_ELEMENT_TYPE,\n type: type,\n key: key,\n ref: void 0 !== config ? config : null,\n props: maybeKey\n };\n}\nexports.Fragment = REACT_FRAGMENT_TYPE;\nexports.jsx = jsxProd;\nexports.jsxs = jsxProd;\n", "'use strict';\n\nif (process.env.NODE_ENV === 'production') {\n module.exports = require('./cjs/react-jsx-runtime.production.js');\n} else {\n module.exports = require('./cjs/react-jsx-runtime.development.js');\n}\n", "import { StrictMode } from \"react\";\nimport { createRoot } from \"react-dom/client\";\nimport App from \"./App.tsx\";\n\ncreateRoot(document.getElementById(\"root\")).render(\n <StrictMode>\n <App />\n </StrictMode>,\n);\n", - "import { useState, useEffect, useCallback, useRef, type CSSProperties } from \"react\";\nimport QRCode from \"qrcode\";\nimport {\n formatDateTimeLocalInput,\n formatTaskDateTime,\n formatTaskTime,\n parseTaskDateTime,\n serializeDateTimeLocalInput,\n} from \"./dateTime.ts\";\nimport {\n buildChannelsSavePayload,\n createInitialChannelsState,\n isWeixinQrImageSource,\n mergeChannelsStatus,\n} from \"./channelsSettings.ts\";\nimport { buildExecutionSteps } from \"./traceSteps.ts\";\n\nconst API = \"http://127.0.0.1:9712/api\";\n\n// ─── Theme ───\nconst THEMES: Record<string, Record<string, string>> = {\n dark: {\n bg: \"#0a0a0f\",\n surface: \"#12121a\",\n surfaceHover: \"#1a1a26\",\n border: \"#1e1e2e\",\n borderActive: \"#2d2d44\",\n text: \"#e2e2ef\",\n textMuted: \"#6b6b8a\",\n textDim: \"#44445e\",\n accent: \"#7c6aff\",\n accentGlow: \"rgba(124, 106, 255, 0.15)\",\n green: \"#34d399\",\n greenBg: \"rgba(52, 211, 153, 0.08)\",\n orange: \"#fbbf24\",\n orangeBg: \"rgba(251, 191, 36, 0.08)\",\n red: \"#f87171\",\n redBg: \"rgba(248, 113, 113, 0.08)\",\n blue: \"#60a5fa\",\n blueBg: \"rgba(96, 165, 250, 0.08)\",\n cyan: \"#22d3ee\",\n cyanBg: \"rgba(34, 211, 238, 0.08)\",\n },\n light: {\n bg: \"#f5f5fa\",\n surface: \"#ffffff\",\n surfaceHover: \"#eeeef7\",\n border: \"#dcdce8\",\n borderActive: \"#b8b8d0\",\n text: \"#1a1a2e\",\n textMuted: \"#6b6b8a\",\n textDim: \"#a0a0bc\",\n accent: \"#5b4ecc\",\n accentGlow: \"rgba(91, 78, 204, 0.12)\",\n green: \"#059669\",\n greenBg: \"rgba(5, 150, 105, 0.08)\",\n orange: \"#d97706\",\n orangeBg: \"rgba(217, 119, 6, 0.08)\",\n red: \"#dc2626\",\n redBg: \"rgba(220, 38, 38, 0.08)\",\n blue: \"#2563eb\",\n blueBg: \"rgba(37, 99, 235, 0.08)\",\n cyan: \"#0891b2\",\n cyanBg: \"rgba(8, 145, 178, 0.08)\",\n },\n};\n\n// Mutable module-level theme reference — updated before each App render\nlet theme = THEMES.dark;\n\nfunction getStatusConfig() {\n return {\n pending: { label: \"Pending\", color: theme.orange, bg: theme.orangeBg, icon: \"◌\" },\n scheduled: { label: \"Scheduled\", color: theme.cyan, bg: theme.cyanBg, icon: \"⏱\" },\n running: { label: \"Running\", color: theme.blue, bg: theme.blueBg, icon: \"⟳\" },\n completed: { label: \"Completed\", color: theme.green, bg: theme.greenBg, icon: \"✓\" },\n failed: { label: \"Failed\", color: theme.red, bg: theme.redBg, icon: \"✕\" },\n cancelled: {\n label: \"Cancelled\",\n color: theme.textMuted,\n bg: \"rgba(107,107,138,0.08)\",\n icon: \"◻\",\n },\n blocked: { label: \"Blocked\", color: theme.textMuted, bg: \"rgba(107,107,138,0.1)\", icon: \"⊘\" },\n };\n}\n\nconst COLUMNS = [\n { key: \"queued\", label: \"Queue\", statuses: [\"pending\", \"scheduled\", \"blocked\"], icon: \"⧖\" },\n { key: \"running\", label: \"Running\", statuses: [\"running\"], icon: \"▸\" },\n { key: \"done\", label: \"Done\", statuses: [\"completed\", \"failed\", \"cancelled\"], icon: \"◆\" },\n];\n\nconst AGENTS = {\n claude: { label: \"Claude Code\", icon: \"⌘\", color: \"#7c6aff\" },\n codex: { label: \"Codex CLI\", icon: \"◈\", color: \"#10a37f\" },\n};\nconst DEFAULT_AGENT = \"codex\";\nconst DEFAULT_TIMEOUT_SECONDS = 12000;\n\n// ─── Formatted Output Component ───\nfunction FormattedOutput({ content, theme }) {\n if (!content) return null;\n\n // 解析JSON流数据,只显示关键信息\n const parseStreamJSON = (text) => {\n const lines = text.split(\"\\n\");\n const parsedLines = [];\n\n lines.forEach((line) => {\n if (!line.trim()) return;\n\n try {\n const event = JSON.parse(line);\n const eventType = event.type;\n\n switch (eventType) {\n case \"user\":\n case \"assistant\": {\n const isUser = eventType === \"user\";\n const msg = event.message || {};\n const msgContent = msg.content || [];\n const prefix = isUser ? \"👤 User: \" : \"🤖 Assistant: \";\n const color = isUser ? theme.accent : theme.green;\n let textBuf = \"\";\n const flushText = () => {\n if (textBuf.trim()) {\n parsedLines.push({\n type: eventType,\n text: prefix + textBuf,\n style: { color, fontWeight: isUser ? \"bold\" : \"normal\" },\n });\n textBuf = \"\";\n }\n };\n for (const c of msgContent) {\n if (typeof c === \"string\") {\n textBuf += c;\n } else if (c && typeof c === \"object\") {\n if (c.type === \"text\") {\n textBuf += c.text || \"\";\n } else if (c.type === \"image\") {\n flushText();\n const src =\n c.source && c.source.type === \"base64\"\n ? `data:${c.source.media_type || \"image/jpeg\"};base64,${c.source.data}`\n : null;\n if (src) parsedLines.push({ type: \"image\", src });\n } else if (c.type === \"tool_use\") {\n flushText();\n const rows = buildTraceRows(\n \"tool_call\",\n {\n id: c.id,\n name: c.name,\n input: c.input,\n },\n \"\",\n );\n parsedLines.push({\n type: \"tool_call\",\n text: rows.map((row) => `${row.label}: ${row.value}`).join(\"\\n\"),\n style: { color: theme.cyan, fontSize: \"11px\", fontFamily: \"monospace\" },\n });\n } else if (c.type === \"tool_result\") {\n flushText();\n const rows = buildTraceRows(\n \"tool_result\",\n {\n tool_use_id: c.tool_use_id,\n content: Array.isArray(c.content)\n ? c.content\n .map((part) =>\n part && part.type === \"text\" ? part.text || \"\" : JSON.stringify(part),\n )\n .join(\"\")\n : c.content,\n is_error: c.is_error,\n },\n \"\",\n );\n parsedLines.push({\n type: \"tool_result\",\n text: rows.map((row) => `${row.label}: ${row.value}`).join(\"\\n\"),\n style: {\n color: c.is_error ? theme.red : theme.blue,\n fontSize: \"11px\",\n fontFamily: \"monospace\",\n },\n });\n }\n }\n }\n flushText();\n break;\n }\n\n case \"item.completed\": {\n const item = event.item || {};\n if (item.type === \"command_execution\") {\n const rows = buildTraceRows(\n \"command_execution\",\n {\n command: item.command,\n output: item.aggregated_output,\n exit_code: item.exit_code,\n status: item.status,\n },\n \"\",\n );\n parsedLines.push({\n type: \"command_execution\",\n text: rows.map((row) => `${row.label}: ${row.value}`).join(\"\\n\"),\n style: { color: theme.orange, fontSize: \"11px\", fontFamily: \"monospace\" },\n });\n } else if (item.type === \"mcp_tool_call\" || item.type === \"collab_tool_call\") {\n const rows = buildTraceRows(\n \"tool_call\",\n {\n server: item.server,\n name: item.tool || item.name,\n input: item.arguments || item.input,\n result: item.result,\n status: item.status,\n error: item.error,\n },\n \"\",\n );\n parsedLines.push({\n type: \"tool_call\",\n text: rows.map((row) => `${row.label}: ${row.value}`).join(\"\\n\"),\n style: { color: theme.cyan, fontSize: \"11px\", fontFamily: \"monospace\" },\n });\n } else if (item.type === \"web_search\") {\n const rows = buildTraceRows(\"web_search\", item, \"\");\n parsedLines.push({\n type: \"web_search\",\n text: rows.map((row) => `${row.label}: ${row.value}`).join(\"\\n\"),\n style: { color: theme.cyan, fontSize: \"11px\", fontFamily: \"monospace\" },\n });\n } else if (item.type === \"file_change\") {\n const rows = buildTraceRows(\"file_change\", item, \"\");\n parsedLines.push({\n type: \"file_change\",\n text: rows.map((row) => `${row.label}: ${row.value}`).join(\"\\n\"),\n style: { color: theme.accent, fontSize: \"11px\", fontFamily: \"monospace\" },\n });\n }\n break;\n }\n\n case \"result\":\n // 最终结果\n if (event.result) {\n parsedLines.push({\n type: \"result\",\n text: `✅ Result: ${event.result}`,\n style: { color: theme.green, fontWeight: \"bold\" },\n });\n }\n break;\n\n case \"error\":\n // 错误信息\n parsedLines.push({\n type: \"error\",\n text: `❌ Error: ${event.error || \"Unknown error\"}`,\n style: { color: theme.red, fontWeight: \"bold\" },\n });\n break;\n\n default:\n // 其他事件类型 - 显示更多信息\n if (eventType) {\n let displayText = `[${eventType}]`;\n // 尝试显示事件中的关键信息\n if (event.message) {\n const msg = event.message;\n if (msg.content && Array.isArray(msg.content)) {\n const textContent = msg.content\n .filter(\n (c) =>\n typeof c === \"string\" || (c && typeof c === \"object\" && c.type === \"text\"),\n )\n .map((c) => (typeof c === \"string\" ? c : c.text || \"\"))\n .join(\"\");\n if (textContent.trim()) {\n displayText = textContent.slice(0, 200);\n }\n }\n } else if (event.result) {\n displayText = `Result: ${event.result.slice(0, 200)}`;\n } else if (event.error) {\n displayText = `Error: ${event.error.slice(0, 200)}`;\n }\n\n parsedLines.push({\n type: \"event\",\n text: displayText,\n style: { color: theme.textDim, fontSize: \"11px\", fontFamily: \"monospace\" },\n });\n }\n }\n } catch (_error) {\n // 如果不是有效的JSON,可能是普通文本输出\n if (line.trim() && !line.startsWith(\"{\")) {\n // 只显示有意义的非JSON行\n if (line.includes(\"error\") || line.includes(\"Error\")) {\n parsedLines.push({\n type: \"error\",\n text: line,\n style: { color: theme.red },\n });\n } else if (line.includes(\"success\") || line.includes(\"Success\")) {\n parsedLines.push({\n type: \"success\",\n text: line,\n style: { color: theme.green },\n });\n } else if (line.length > 10) {\n // 只显示较长的非JSON行\n parsedLines.push({\n type: \"text\",\n text: line,\n style: { color: theme.textDim },\n });\n }\n }\n }\n });\n\n return parsedLines;\n };\n\n const parsedContent = parseStreamJSON(content);\n\n if (parsedContent.length === 0) {\n return (\n <div style={{ color: theme.textDim, fontStyle: \"italic\", fontSize: \"12px\" }}>\n Waiting for agent output...\n </div>\n );\n }\n\n return (\n <div style={{ fontFamily: \"'JetBrains Mono', monospace\", fontSize: \"12px\", lineHeight: \"1.6\" }}>\n {parsedContent.map((item, index) =>\n item.type === \"image\" ? (\n <div key={index} style={{ margin: \"6px 0\" }}>\n <img\n src={item.src}\n alt=\"output image\"\n style={{ maxWidth: \"100%\", borderRadius: \"4px\", display: \"block\" }}\n />\n </div>\n ) : (\n <div\n key={index}\n style={{\n ...item.style,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n marginBottom: \"2px\",\n padding: \"2px 0\",\n }}\n >\n {item.text}\n </div>\n ),\n )}\n </div>\n );\n}\n\nfunction ExecutionTimeline({ events }) {\n const [expanded, setExpanded] = useState(true);\n const steps = buildExecutionSteps(events);\n\n if (steps.length === 0) {\n return (\n <div style={{ fontSize: 12, color: theme.textDim, padding: \"12px 0\", textAlign: \"center\" }}>\n No output events recorded — events are recorded for new task runs.\n </div>\n );\n }\n\n return (\n <div\n style={{\n border: `1px solid ${theme.border}`,\n borderRadius: 8,\n overflow: \"hidden\",\n background: theme.bg,\n }}\n >\n <button\n onClick={() => setExpanded(!expanded)}\n style={{\n width: \"100%\",\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n gap: 12,\n padding: \"10px 12px\",\n background: theme.surface,\n border: \"none\",\n borderBottom: expanded ? `1px solid ${theme.border}` : \"none\",\n color: theme.text,\n cursor: \"pointer\",\n fontFamily: \"'JetBrains Mono', monospace\",\n fontSize: 12,\n textAlign: \"left\",\n }}\n >\n <span style={{ display: \"flex\", alignItems: \"center\", gap: 8, minWidth: 0 }}>\n <span style={{ color: theme.textMuted }}>{expanded ? \"⌄\" : \"›\"}</span>\n <span>\n Show {steps.length} {steps.length === 1 ? \"step\" : \"steps\"}\n </span>\n </span>\n <span style={{ color: theme.textDim, fontSize: 10, whiteSpace: \"nowrap\" }}>\n {events.length} events\n </span>\n </button>\n\n {expanded && (\n <div style={{ padding: \"12px 12px 14px\" }}>\n {steps.map((step, index) => (\n <ExecutionTimelineStep\n key={`${step.id}-${step.number}`}\n step={step}\n isLast={index === steps.length - 1}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction ExecutionTimelineStep({ step, isLast }) {\n const config = getExecutionStepConfig(step.type);\n const detail = (step.detail || \"\").trim();\n const hasRows = step.rows && step.rows.length > 0;\n const hasImage = Boolean(step.imageSrc);\n const showDetail = detail && detail !== step.title && !hasRows && !hasImage;\n\n return (\n <div style={{ display: \"grid\", gridTemplateColumns: \"28px 1fr\", columnGap: 10 }}>\n <div style={{ display: \"flex\", flexDirection: \"column\", alignItems: \"center\" }}>\n <div\n style={{\n width: 20,\n height: 20,\n borderRadius: 6,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: config.bg,\n border: `1px solid ${config.color}55`,\n color: config.color,\n fontSize: 10,\n fontWeight: 800,\n lineHeight: 1,\n }}\n >\n {config.icon}\n </div>\n {!isLast && (\n <div\n style={{ width: 1, flex: 1, minHeight: 16, background: theme.border, marginTop: 4 }}\n />\n )}\n </div>\n\n <div style={{ paddingBottom: isLast ? 0 : 14, minWidth: 0 }}>\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n gap: 10,\n alignItems: \"baseline\",\n }}\n >\n <div\n style={{\n color: theme.text,\n fontSize: 12,\n lineHeight: 1.55,\n wordBreak: \"break-word\",\n minWidth: 0,\n }}\n >\n {step.title}\n </div>\n <div\n style={{\n color: theme.textDim,\n fontSize: 9,\n whiteSpace: \"nowrap\",\n flexShrink: 0,\n fontFamily: \"'JetBrains Mono', monospace\",\n }}\n >\n {formatTaskTime(step.timestamp)}\n </div>\n </div>\n\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n marginTop: 3,\n marginBottom: hasRows || showDetail ? 7 : 0,\n }}\n >\n <span\n style={{\n color: config.color,\n fontSize: 10,\n fontWeight: 700,\n textTransform: \"uppercase\",\n letterSpacing: 0,\n }}\n >\n {config.label}\n </span>\n {step.count > 1 && (\n <span style={{ color: theme.textDim, fontSize: 10 }}>{step.count} chunks</span>\n )}\n </div>\n\n {hasImage && (\n <img\n src={step.imageSrc}\n alt=\"image output\"\n style={{\n maxWidth: \"100%\",\n borderRadius: 6,\n display: \"block\",\n marginTop: 7,\n border: `1px solid ${theme.border}`,\n }}\n />\n )}\n\n {hasRows && (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n gap: 5,\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 6,\n padding: \"8px 10px\",\n maxHeight: 220,\n overflow: \"auto\",\n }}\n >\n {step.rows.map((row, i) => (\n <div\n key={i}\n style={{ display: \"grid\", gridTemplateColumns: \"72px 1fr\", gap: 8, minWidth: 0 }}\n >\n <span style={{ color: theme.textMuted, fontWeight: 700 }}>{row.label}</span>\n <span\n style={{ whiteSpace: \"pre-wrap\", wordBreak: \"break-word\", color: theme.text }}\n >\n {row.value}\n </span>\n </div>\n ))}\n </div>\n )}\n\n {showDetail && (\n <pre\n style={{\n margin: 0,\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 6,\n padding: \"8px 10px\",\n color: theme.textMuted,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n fontFamily: \"'JetBrains Mono', monospace\",\n fontSize: 11,\n lineHeight: 1.5,\n maxHeight: 220,\n overflow: \"auto\",\n }}\n >\n {detail}\n </pre>\n )}\n </div>\n </div>\n );\n}\n\nfunction getExecutionStepConfig(type) {\n switch (type) {\n case \"thinking\":\n return { label: \"Thinking\", icon: \"⌁\", color: theme.textMuted, bg: \"rgba(107,107,138,0.08)\" };\n case \"tool_call\":\n return { label: \"Tool Call\", icon: \"▣\", color: theme.cyan, bg: theme.cyanBg };\n case \"tool_result\":\n return { label: \"Tool Result\", icon: \"↵\", color: theme.blue, bg: theme.blueBg };\n case \"command_execution\":\n return { label: \"Command\", icon: \"$\", color: theme.orange, bg: theme.orangeBg };\n case \"file_change\":\n return { label: \"File\", icon: \"◇\", color: theme.accent, bg: theme.accentGlow };\n case \"generated_image\":\n return { label: \"Image\", icon: \"□\", color: theme.accent, bg: theme.accentGlow };\n case \"image_content\":\n return { label: \"Image\", icon: \"□\", color: theme.accent, bg: theme.accentGlow };\n case \"web_search\":\n return { label: \"Search\", icon: \"⌕\", color: theme.cyan, bg: theme.cyanBg };\n case \"result\":\n return { label: \"Result\", icon: \"✓\", color: theme.green, bg: theme.greenBg };\n case \"error\":\n return { label: \"Error\", icon: \"!\", color: theme.red, bg: theme.redBg };\n case \"user\":\n return { label: \"User\", icon: \"U\", color: theme.accent, bg: theme.accentGlow };\n case \"assistant\":\n return { label: \"Assistant\", icon: \"AI\", color: theme.green, bg: theme.greenBg };\n default:\n return { label: \"Event\", icon: \"•\", color: theme.textMuted, bg: \"rgba(107,107,138,0.08)\" };\n }\n}\n\nfunction formatTraceValue(value) {\n if (value === undefined || value === null) return \"\";\n if (typeof value === \"string\") return value;\n return JSON.stringify(value, null, 2);\n}\n\nfunction buildTraceRows(eventType, payload, rawContent) {\n const row = (label, value) => {\n const formatted = formatTraceValue(value);\n return formatted === \"\" ? null : { label, value: formatted };\n };\n const compact = (rows) => rows.filter(Boolean);\n\n if (eventType === \"tool_call\") {\n const name = payload.server\n ? `${payload.server}.${payload.name || payload.tool || \"unknown\"}`\n : payload.name || payload.tool || \"unknown\";\n return compact([\n row(\"Tool\", name),\n row(\"Input\", payload.input || payload.arguments),\n row(\"Result\", payload.result),\n row(\"Status\", payload.status),\n row(\"Error\", payload.error),\n ]);\n }\n\n if (eventType === \"tool_result\") {\n return compact([\n row(payload.is_error ? \"Tool Error\" : \"Tool Result\", payload.tool_use_id || \"result\"),\n row(\"Content\", payload.content),\n ]);\n }\n\n if (eventType === \"command_execution\") {\n return compact([\n row(\"Command\", payload.command),\n row(\"Output\", payload.output),\n row(\"Exit\", payload.exit_code),\n row(\"Status\", payload.status),\n ]);\n }\n\n if (eventType === \"file_change\") {\n const changes = Array.isArray(payload.changes)\n ? payload.changes\n .map((change) => {\n if (!change || typeof change !== \"object\") return formatTraceValue(change);\n const kind = change.kind || change.type || \"changed\";\n const path = change.path || change.file || \"\";\n return path ? `${kind}: ${path}` : kind;\n })\n .join(\"\\n\")\n : payload.changes;\n return compact([row(\"Changes\", changes), row(\"Status\", payload.status)]);\n }\n\n if (eventType === \"web_search\") {\n return compact([\n row(\"Query\", payload.query),\n row(\"Action\", payload.action),\n row(\"Status\", payload.status),\n ]);\n }\n\n return [{ label: eventType, value: rawContent }];\n}\n\n// ─── CSRF token ───\n// Fetched once at startup; reused for all state-changing requests.\nlet _csrfTokenPromise = null;\nfunction getCsrfToken() {\n if (!_csrfTokenPromise) {\n _csrfTokenPromise = fetch(`${API}/csrf-token`)\n .then((r) => r.json())\n .then((d) => d.csrf_token || \"\")\n .catch(() => \"\");\n }\n return _csrfTokenPromise;\n}\n\nasync function csrfHeaders(extra = {}) {\n const token = await getCsrfToken();\n return { \"Content-Type\": \"application/json\", \"X-CSRF-Token\": token, ...extra };\n}\n\n// ─── API helpers ───\nasync function fetchTasks() {\n const res = await fetch(`${API}/tasks`);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n return res.json();\n}\n\nasync function fetchHeartbeats() {\n const res = await fetch(`${API}/heartbeats`);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n return res.json();\n}\n\nasync function createTask(data) {\n const res = await fetch(`${API}/tasks`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify(data),\n });\n return res.json();\n}\n\nasync function fetchSkillPatterns() {\n const res = await fetch(`${API}/skill-patterns`);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n return res.json();\n}\n\nasync function triggerSkillSweep(agent?: string) {\n const res = await fetch(`${API}/skills/sweep`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify(agent ? { agent } : {}),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function triggerSkillDraft(id, agent?: string) {\n const res = await fetch(`${API}/skill-patterns/${id}/draft`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify(agent ? { agent } : {}),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function approveSkill(id, data) {\n const res = await fetch(`${API}/skill-patterns/${id}/approve`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify(data),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function dismissSkillPattern(id) {\n const res = await fetch(`${API}/skill-patterns/${id}/dismiss`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: \"{}\",\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function fetchSkills() {\n const res = await fetch(`${API}/skills`);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n return res.json();\n}\n\nasync function setSkillEnabledApi(id, enabled) {\n const res = await fetch(`${API}/skills/${id}`, {\n method: \"PUT\",\n headers: await csrfHeaders(),\n body: JSON.stringify({ enabled }),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function deleteSkillApi(id) {\n const res = await fetch(`${API}/skills/${id}`, {\n method: \"DELETE\",\n headers: await csrfHeaders(),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function createHeartbeat(data) {\n const res = await fetch(`${API}/heartbeats`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify(data),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function updateHeartbeat(id, data) {\n const res = await fetch(`${API}/heartbeats/${id}`, {\n method: \"PUT\",\n headers: await csrfHeaders(),\n body: JSON.stringify(data),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function deleteHeartbeat(id) {\n const res = await fetch(`${API}/heartbeats/${id}`, {\n method: \"DELETE\",\n headers: await csrfHeaders(),\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n}\n\nasync function runHeartbeatNow(id) {\n const res = await fetch(`${API}/heartbeats/${id}/run-now`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function pauseHeartbeat(id) {\n const res = await fetch(`${API}/heartbeats/${id}/pause`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function resumeHeartbeatApi(id) {\n const res = await fetch(`${API}/heartbeats/${id}/resume`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function fetchHeartbeatTicks(id) {\n const res = await fetch(`${API}/heartbeats/${id}/ticks?limit=20`);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const payload = await res.json();\n return payload.ticks || [];\n}\n\nasync function fetchHeartbeatTickOutput(heartbeatId, tickId) {\n const res = await fetch(`${API}/heartbeats/${heartbeatId}/ticks/${tickId}/output`);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n return res.json();\n}\n\nasync function cancelTask(id) {\n await fetch(`${API}/tasks/${id}/cancel`, { method: \"POST\", headers: await csrfHeaders() });\n}\n\nasync function retryTask(id) {\n await fetch(`${API}/tasks/${id}/retry`, { method: \"POST\", headers: await csrfHeaders() });\n}\n\nasync function deleteTask(id) {\n await fetch(`${API}/tasks/${id}`, { method: \"DELETE\", headers: await csrfHeaders() });\n}\n\nasync function updateTask(id, data) {\n const res = await fetch(`${API}/tasks/${id}`, {\n method: \"PUT\",\n headers: await csrfHeaders(),\n body: JSON.stringify(data),\n });\n if (!res.ok) {\n const err = await res.json().catch(() => ({}));\n throw new Error(err.error || `HTTP ${res.status}`);\n }\n return res.json();\n}\n\nasync function respondToTask(id, answer) {\n await fetch(`${API}/tasks/${id}/respond`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify({ answer }),\n });\n}\n\nasync function resumeTask(id, message) {\n const res = await fetch(`${API}/tasks/${id}/resume`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify({ message }),\n });\n return res.json();\n}\n\nasync function fetchTaskMessages(id) {\n try {\n const res = await fetch(`${API}/tasks/${id}/messages`);\n return res.ok ? await res.json() : [];\n } catch {\n return [];\n }\n}\n\nasync function fetchTaskEvents(id) {\n try {\n const res = await fetch(`${API}/tasks/${id}/events?limit=1000`);\n if (res.ok) {\n const data = await res.json();\n return data.events || [];\n }\n return [];\n } catch {\n return [];\n }\n}\n\nasync function fetchSettings() {\n try {\n const res = await fetch(`${API}/settings`);\n return res.ok ? await res.json() : {};\n } catch {\n return {};\n }\n}\n\nasync function updateSettings(data) {\n await fetch(`${API}/settings`, {\n method: \"PUT\",\n headers: await csrfHeaders(),\n body: JSON.stringify(data),\n });\n}\n\nasync function fetchFeishuSettings() {\n try {\n const res = await fetch(`${API}/feishu/settings`);\n return res.ok ? await res.json() : {};\n } catch {\n return {};\n }\n}\n\nasync function updateFeishuSettings(data) {\n await fetch(`${API}/feishu/settings`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify(data),\n });\n}\n\nasync function fetchChannelsStatus() {\n try {\n const res = await fetch(`${API}/channels/status`);\n return res.ok ? await res.json() : {};\n } catch {\n return {};\n }\n}\n\nasync function updateChannelsSettings(data) {\n await fetch(`${API}/channels/settings`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify(data),\n });\n}\n\nasync function runWeixinAction(action) {\n const res = await fetch(`${API}/channels/weixin/action`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify({ action }),\n });\n if (!res.ok) {\n const data = await res.json().catch(() => ({}));\n throw new Error(data.error || `HTTP ${res.status}`);\n }\n}\n\n// ─── Components ───\n\nfunction Tooltip({ text, children }) {\n const [visible, setVisible] = useState(false);\n return (\n <div\n style={{ position: \"relative\", display: \"inline-flex\" }}\n onMouseEnter={() => setVisible(true)}\n onMouseLeave={() => setVisible(false)}\n >\n {children}\n {visible && (\n <div\n style={{\n position: \"absolute\",\n bottom: \"calc(100% + 6px)\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n color: theme.textMuted,\n fontSize: 11,\n padding: \"4px 8px\",\n borderRadius: 6,\n whiteSpace: \"nowrap\",\n pointerEvents: \"none\",\n boxShadow: \"0 4px 12px rgba(0,0,0,0.3)\",\n zIndex: 9999,\n }}\n >\n {text}\n </div>\n )}\n </div>\n );\n}\n\nfunction Badge({ status }) {\n const cfg = getStatusConfig()[status] || getStatusConfig().pending;\n return (\n <span\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 5,\n padding: \"3px 10px\",\n borderRadius: 20,\n fontSize: 11,\n fontWeight: 600,\n color: cfg.color,\n background: cfg.bg,\n letterSpacing: 0.3,\n }}\n >\n <span style={{ fontSize: 10 }}>{cfg.icon}</span>\n {cfg.label}\n </span>\n );\n}\n\nfunction Tag({ children }) {\n return (\n <span\n style={{\n padding: \"2px 8px\",\n borderRadius: 4,\n fontSize: 10,\n fontWeight: 500,\n background: theme.accentGlow,\n color: theme.accent,\n letterSpacing: 0.4,\n }}\n >\n {children}\n </span>\n );\n}\n\nfunction AgentBadge({ agent }) {\n const cfg = AGENTS[agent] || AGENTS.claude;\n return (\n <span\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 4,\n padding: \"2px 8px\",\n borderRadius: 4,\n fontSize: 10,\n fontWeight: 600,\n color: cfg.color,\n background: `${cfg.color}18`,\n letterSpacing: 0.3,\n }}\n >\n <span style={{ fontSize: 9 }}>{cfg.icon}</span>\n {cfg.label}\n </span>\n );\n}\n\nfunction TaskCard({ task, onAction, onViewDetail }) {\n const [hovered, setHovered] = useState(false);\n const cfg = getStatusConfig()[task.status] || getStatusConfig().pending;\n const tags = task.tags ? task.tags.split(\",\").filter(Boolean) : [];\n\n return (\n <div\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n onClick={() => onViewDetail(task)}\n style={{\n background: hovered ? theme.surfaceHover : theme.surface,\n border: `1px solid ${hovered ? theme.borderActive : theme.border}`,\n borderLeft: `3px solid ${cfg.color}`,\n borderRadius: 10,\n padding: \"14px 16px\",\n cursor: \"pointer\",\n transition: \"all 0.2s ease\",\n transform: hovered ? \"translateY(-1px)\" : \"none\",\n boxShadow: hovered ? `0 4px 20px rgba(0,0,0,0.3)` : \"none\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"flex-start\",\n marginBottom: 8,\n }}\n >\n <span\n style={{\n fontSize: 13,\n fontWeight: 600,\n color: theme.text,\n lineHeight: 1.4,\n flex: 1,\n marginRight: 8,\n fontFamily: \"'JetBrains Mono', 'SF Mono', monospace\",\n }}\n >\n {task.title}\n </span>\n <Badge status={task.status} />\n </div>\n\n <div\n style={{\n fontSize: 12,\n color: theme.textMuted,\n marginBottom: 10,\n lineHeight: 1.5,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n display: \"-webkit-box\",\n WebkitLineClamp: 2,\n WebkitBoxOrient: \"vertical\",\n }}\n >\n {task.prompt}\n </div>\n\n <div style={{ display: \"flex\", justifyContent: \"space-between\", alignItems: \"center\" }}>\n <div style={{ display: \"flex\", gap: 4, flexWrap: \"wrap\" }}>\n <AgentBadge agent={task.agent} />\n {task.schedule_type === \"delayed\" && <Tag>⏳ {task.delay_seconds}s</Tag>}\n {task.schedule_type === \"scheduled_at\" && task.next_run_at && (\n <Tag>📅 {formatTaskDateTime(task.next_run_at)}</Tag>\n )}\n {task.schedule_type === \"cron\" && <Tag>⏲ {task.cron_expr}</Tag>}\n {tags.map((t, i) => (\n <Tag key={i}>{t.trim()}</Tag>\n ))}\n </div>\n\n <div style={{ display: \"flex\", gap: 4 }} onClick={(e) => e.stopPropagation()}>\n {[\"pending\", \"scheduled\", \"blocked\"].includes(task.status) && (\n <ActionBtn\n label=\"✎\"\n title=\"Edit\"\n onClick={() => onAction(\"edit\", task.id)}\n color={theme.blue || theme.accent}\n />\n )}\n {[\"completed\", \"cancelled\", \"failed\"].includes(task.status) && (\n <ActionBtn\n label=\"⑂\"\n title=\"Fork\"\n onClick={() => onAction(\"fork\", task.id)}\n color={theme.cyan || theme.accent}\n />\n )}\n {task.status === \"failed\" && (\n <ActionBtn\n label=\"↻\"\n title=\"Retry\"\n onClick={() => onAction(\"retry\", task.id)}\n color={theme.orange}\n />\n )}\n {[\"pending\", \"scheduled\", \"running\"].includes(task.status) && (\n <ActionBtn\n label=\"■\"\n title=\"Cancel\"\n onClick={() => onAction(\"cancel\", task.id)}\n color={theme.red}\n />\n )}\n <ActionBtn\n label=\"×\"\n title=\"Delete\"\n onClick={() => onAction(\"delete\", task.id)}\n color={theme.textMuted}\n />\n </div>\n </div>\n\n {task.run_count > 0 && (\n <div style={{ fontSize: 10, color: theme.textDim, marginTop: 8, fontFamily: \"monospace\" }}>\n Runs: {task.run_count}\n {task.max_runs ? ` / ${task.max_runs}` : \"\"}\n {task.last_run_at && ` · Last: ${formatTaskTime(task.last_run_at)}`}\n </div>\n )}\n\n {/* DAG info */}\n {task.status === \"blocked\" && task.dependencies && task.dependencies.length > 0 && (\n <div style={{ fontSize: 10, color: theme.textDim, marginTop: 6, fontFamily: \"monospace\" }}>\n ⊘ Waiting for: {task.dependencies.map((d) => `#${d.depends_on_task_id}`).join(\", \")}\n </div>\n )}\n {task.dependents && task.dependents.length > 0 && task.status === \"completed\" && (\n <div style={{ fontSize: 10, color: theme.textDim, marginTop: 6, fontFamily: \"monospace\" }}>\n → Unlocks: {task.dependents.map((id) => `#${id}`).join(\", \")}\n </div>\n )}\n {task.dag_id && (\n <div\n style={{\n fontSize: 10,\n color: theme.accent,\n marginTop: 4,\n opacity: 0.6,\n fontFamily: \"monospace\",\n }}\n >\n dag: {task.dag_id}\n </div>\n )}\n </div>\n );\n}\n\nfunction ActionBtn({ label, title, onClick, color }) {\n const [hovered, setHovered] = useState(false);\n return (\n <button\n title={title}\n onClick={onClick}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n style={{\n background: hovered ? `${color}22` : \"transparent\",\n border: \"none\",\n color: color,\n cursor: \"pointer\",\n width: 24,\n height: 24,\n borderRadius: 6,\n fontSize: 14,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"background 0.15s\",\n }}\n >\n {label}\n </button>\n );\n}\n\nfunction Column({ col, tasks, onAction, onViewDetail }) {\n return (\n <div style={{ flex: 1, minWidth: 300 }}>\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n marginBottom: 16,\n padding: \"0 4px\",\n }}\n >\n <span style={{ fontSize: 16, opacity: 0.4 }}>{col.icon}</span>\n <span\n style={{\n fontSize: 12,\n fontWeight: 700,\n color: theme.textMuted,\n letterSpacing: 1.5,\n textTransform: \"uppercase\",\n }}\n >\n {col.label}\n </span>\n <span\n style={{\n background: theme.border,\n borderRadius: 10,\n padding: \"2px 8px\",\n fontSize: 11,\n color: theme.textDim,\n fontWeight: 600,\n }}\n >\n {tasks.length}\n </span>\n </div>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 8 }}>\n {tasks.map((t) => (\n <TaskCard key={t.id} task={t} onAction={onAction} onViewDetail={onViewDetail} />\n ))}\n {tasks.length === 0 && (\n <div\n style={{\n border: `1px dashed ${theme.border}`,\n borderRadius: 10,\n padding: 32,\n textAlign: \"center\",\n color: theme.textDim,\n fontSize: 12,\n }}\n >\n No tasks\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction HeartbeatBadge({ enabled }) {\n return (\n <span\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 5,\n padding: \"3px 10px\",\n borderRadius: 20,\n fontSize: 11,\n fontWeight: 600,\n color: enabled ? theme.green : theme.textMuted,\n background: enabled ? theme.greenBg : \"rgba(107,107,138,0.08)\",\n letterSpacing: 0.3,\n }}\n >\n <span style={{ fontSize: 10 }}>{enabled ? \"●\" : \"◌\"}</span>\n {enabled ? \"Enabled\" : \"Paused\"}\n </span>\n );\n}\n\nfunction HeartbeatModal({ onClose, onSubmit, initialData, defaultAgent, mode = \"create\" }: any) {\n const savedDir = localStorage.getItem(\"agentforge_working_dir\") || \"~/papers\";\n const [form, setForm] = useState(() => ({\n name: initialData?.name || \"\",\n working_dir: initialData?.working_dir || savedDir,\n schedule_type: initialData?.schedule_type || \"interval\",\n interval_seconds: initialData?.interval_seconds || 600,\n cron_expr: initialData?.cron_expr || \"\",\n check_prompt: initialData?.check_prompt || \"\",\n action_prompt_template: initialData?.action_prompt_template || \"\",\n default_agent: initialData?.default_agent || defaultAgent || DEFAULT_AGENT,\n cooldown_seconds: initialData?.cooldown_seconds || 1800,\n enabled: initialData?.enabled ?? true,\n }));\n\n const set = (k, v) => setForm((prev) => ({ ...prev, [k]: v }));\n\n const inputStyle: CSSProperties = {\n width: \"100%\",\n padding: \"10px 14px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n color: theme.text,\n fontSize: 13,\n outline: \"none\",\n boxSizing: \"border-box\",\n fontFamily: \"'JetBrains Mono', 'SF Mono', monospace\",\n };\n const labelStyle = {\n fontSize: 11,\n fontWeight: 600,\n color: theme.textMuted,\n letterSpacing: 0.8,\n textTransform: \"uppercase\",\n marginBottom: 6,\n display: \"block\",\n };\n\n const handleSubmit = () => {\n localStorage.setItem(\"agentforge_working_dir\", form.working_dir);\n onSubmit({\n ...form,\n name: form.name || \"Untitled heartbeat\",\n interval_seconds:\n form.schedule_type === \"interval\" ? parseInt(form.interval_seconds) || 600 : null,\n cooldown_seconds: parseInt(form.cooldown_seconds) || 0,\n cron_expr: form.schedule_type === \"cron\" ? form.cron_expr : null,\n });\n };\n\n return (\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n background: \"rgba(0,0,0,0.7)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex: 1000,\n backdropFilter: \"blur(8px)\",\n }}\n onClick={onClose}\n >\n <div\n onClick={(e) => e.stopPropagation()}\n style={{\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 16,\n padding: 32,\n width: 640,\n maxHeight: \"84vh\",\n overflow: \"auto\",\n boxShadow: \"0 24px 80px rgba(0,0,0,0.5)\",\n }}\n >\n <h2\n style={{\n margin: \"0 0 24px\",\n fontSize: 18,\n fontWeight: 700,\n color: theme.text,\n fontFamily: \"'JetBrains Mono', monospace\",\n }}\n >\n {mode === \"edit\" ? \"Edit Heartbeat\" : \"New Heartbeat\"}\n </h2>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 16 }}>\n <div>\n <label style={labelStyle}>Name</label>\n <input\n style={inputStyle}\n value={form.name}\n onChange={(e) => set(\"name\", e.target.value)}\n placeholder=\"Repo review watcher\"\n />\n </div>\n <div>\n <label style={labelStyle}>Working Directory</label>\n <div style={{ display: \"flex\", gap: 8 }}>\n <input\n style={{ ...inputStyle, flex: 1 }}\n value={form.working_dir}\n onChange={(e) => set(\"working_dir\", e.target.value)}\n />\n {window.electronAPI?.selectDirectory && (\n <button\n onClick={async () => {\n const dir = await window.electronAPI.selectDirectory();\n if (dir) set(\"working_dir\", dir);\n }}\n style={{\n padding: \"8px 14px\",\n borderRadius: 8,\n cursor: \"pointer\",\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n color: theme.textMuted,\n fontSize: 12,\n fontWeight: 600,\n whiteSpace: \"nowrap\",\n }}\n >\n Browse\n </button>\n )}\n </div>\n </div>\n <div>\n <label style={labelStyle}>Schedule Type</label>\n <div style={{ display: \"flex\", gap: 8 }}>\n {[\"interval\", \"cron\"].map((t) => (\n <button\n key={t}\n onClick={() => set(\"schedule_type\", t)}\n style={{\n flex: 1,\n padding: \"8px 12px\",\n borderRadius: 8,\n cursor: \"pointer\",\n border: `1px solid ${form.schedule_type === t ? theme.accent : theme.border}`,\n background: form.schedule_type === t ? theme.accentGlow : \"transparent\",\n color: form.schedule_type === t ? theme.accent : theme.textMuted,\n fontSize: 12,\n fontWeight: 600,\n textTransform: \"capitalize\",\n }}\n >\n {t === \"interval\" ? \"⟳ Interval\" : \"⏲ Cron\"}\n </button>\n ))}\n </div>\n </div>\n {form.schedule_type === \"interval\" ? (\n <div>\n <label style={labelStyle}>Interval (seconds)</label>\n <input\n type=\"number\"\n style={inputStyle}\n value={form.interval_seconds}\n onChange={(e) => set(\"interval_seconds\", e.target.value)}\n />\n </div>\n ) : (\n <div>\n <label style={labelStyle}>Cron Expression</label>\n <input\n style={inputStyle}\n value={form.cron_expr}\n onChange={(e) => set(\"cron_expr\", e.target.value)}\n placeholder=\"*/10 * * * *\"\n />\n </div>\n )}\n <div>\n <label style={labelStyle}>Decision Prompt *</label>\n <textarea\n style={{ ...inputStyle, height: 110, resize: \"vertical\" }}\n value={form.check_prompt}\n onChange={(e) => set(\"check_prompt\", e.target.value)}\n placeholder=\"Check whether there are new meaningful code changes that deserve a review task. Return JSON only.\"\n />\n </div>\n <div>\n <label style={labelStyle}>Triggered Task Prompt Template</label>\n <textarea\n style={{ ...inputStyle, height: 90, resize: \"vertical\" }}\n value={form.action_prompt_template}\n onChange={(e) => set(\"action_prompt_template\", e.target.value)}\n placeholder=\"Review the latest code changes and summarize bugs, regressions, and missing tests.\"\n />\n </div>\n <div style={{ display: \"grid\", gridTemplateColumns: \"1fr 1fr\", gap: 12 }}>\n <div>\n <label style={labelStyle}>Default Agent</label>\n <select\n style={inputStyle}\n value={form.default_agent}\n onChange={(e) => set(\"default_agent\", e.target.value)}\n >\n {Object.entries(AGENTS).map(([key, cfg]) => (\n <option key={key} value={key}>\n {cfg.label}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label style={labelStyle}>Cooldown (seconds)</label>\n <input\n type=\"number\"\n style={inputStyle}\n value={form.cooldown_seconds}\n onChange={(e) => set(\"cooldown_seconds\", e.target.value)}\n />\n </div>\n </div>\n <label\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n fontSize: 13,\n color: theme.textMuted,\n }}\n >\n <input\n type=\"checkbox\"\n checked={!!form.enabled}\n onChange={(e) => set(\"enabled\", e.target.checked)}\n />\n Enabled\n </label>\n </div>\n <div style={{ display: \"flex\", gap: 10, justifyContent: \"flex-end\", marginTop: 24 }}>\n <button\n onClick={onClose}\n style={{\n padding: \"10px 20px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: \"transparent\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n }}\n >\n Cancel\n </button>\n <button\n onClick={handleSubmit}\n style={{\n padding: \"10px 24px\",\n borderRadius: 8,\n border: \"none\",\n background: theme.accent,\n color: \"#fff\",\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n boxShadow: `0 0 20px ${theme.accentGlow}`,\n }}\n >\n {mode === \"edit\" ? \"Save\" : \"Create Heartbeat\"}\n </button>\n </div>\n </div>\n </div>\n );\n}\n\nfunction HeartbeatCard({ heartbeat, onAction, onViewDetail }) {\n const tags = [];\n if (heartbeat.schedule_type === \"interval\" && heartbeat.interval_seconds)\n tags.push(`⟳ ${heartbeat.interval_seconds}s`);\n if (heartbeat.schedule_type === \"cron\" && heartbeat.cron_expr)\n tags.push(`⏲ ${heartbeat.cron_expr}`);\n if (heartbeat.last_decision) tags.push(`Last: ${heartbeat.last_decision}`);\n\n return (\n <div\n onClick={() => onViewDetail(heartbeat)}\n style={{\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 12,\n padding: \"16px 18px\",\n cursor: \"pointer\",\n transition: \"all 0.2s ease\",\n }}\n >\n <div style={{ display: \"flex\", justifyContent: \"space-between\", gap: 16, marginBottom: 8 }}>\n <div style={{ flex: 1 }}>\n <div\n style={{\n fontSize: 14,\n fontWeight: 700,\n color: theme.text,\n fontFamily: \"'JetBrains Mono', monospace\",\n marginBottom: 6,\n }}\n >\n {heartbeat.name}\n </div>\n <div\n style={{\n fontSize: 12,\n color: theme.textMuted,\n lineHeight: 1.5,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n display: \"-webkit-box\",\n WebkitLineClamp: 2,\n WebkitBoxOrient: \"vertical\",\n }}\n >\n {heartbeat.check_prompt}\n </div>\n </div>\n <HeartbeatBadge enabled={heartbeat.enabled} />\n </div>\n\n <div\n style={{ display: \"flex\", justifyContent: \"space-between\", alignItems: \"center\", gap: 12 }}\n >\n <div style={{ display: \"flex\", gap: 6, flexWrap: \"wrap\" }}>\n <AgentBadge agent={heartbeat.default_agent} />\n {tags.map((tag, idx) => (\n <Tag key={idx}>{tag}</Tag>\n ))}\n </div>\n <div style={{ display: \"flex\", gap: 4 }} onClick={(e) => e.stopPropagation()}>\n <ActionBtn\n label=\"⚡\"\n title=\"Run now\"\n onClick={() => onAction(\"run\", heartbeat.id)}\n color={theme.orange}\n />\n <ActionBtn\n label=\"✎\"\n title=\"Edit\"\n onClick={() => onAction(\"edit\", heartbeat.id)}\n color={theme.blue}\n />\n {heartbeat.enabled ? (\n <ActionBtn\n label=\"❚❚\"\n title=\"Pause\"\n onClick={() => onAction(\"pause\", heartbeat.id)}\n color={theme.textMuted}\n />\n ) : (\n <ActionBtn\n label=\"▶\"\n title=\"Resume\"\n onClick={() => onAction(\"resume\", heartbeat.id)}\n color={theme.green}\n />\n )}\n <ActionBtn\n label=\"×\"\n title=\"Delete\"\n onClick={() => onAction(\"delete\", heartbeat.id)}\n color={theme.red}\n />\n </div>\n </div>\n\n <div\n style={{\n fontSize: 11,\n color: theme.textDim,\n marginTop: 10,\n fontFamily: \"monospace\",\n lineHeight: 1.6,\n }}\n >\n Next: {heartbeat.next_run_at ? formatTaskDateTime(heartbeat.next_run_at) : \"n/a\"}\n {\" · \"}\n Triggered:{\" \"}\n {heartbeat.last_triggered_at ? formatTaskDateTime(heartbeat.last_triggered_at) : \"never\"}\n </div>\n {heartbeat.last_error && (\n <div style={{ fontSize: 11, color: theme.red, marginTop: 6, lineHeight: 1.4 }}>\n Last error: {heartbeat.last_error}\n </div>\n )}\n </div>\n );\n}\n\nfunction HeartbeatDetailPanel({ heartbeat, ticks, onClose }) {\n const [selectedTickId, setSelectedTickId] = useState<any>(null);\n const [tickOutput, setTickOutput] = useState(\"\");\n const [tickRunning, setTickRunning] = useState(false);\n const outputRef = useRef<any>(null);\n\n useEffect(() => {\n setSelectedTickId(ticks[0]?.id || null);\n }, [heartbeat.id, ticks]);\n\n useEffect(() => {\n if (!selectedTickId) {\n setTickOutput(\"\");\n setTickRunning(false);\n return;\n }\n let cancelled = false;\n const load = async () => {\n try {\n const data = await fetchHeartbeatTickOutput(heartbeat.id, selectedTickId);\n if (cancelled) return;\n setTickOutput(data.output || \"\");\n setTickRunning(!!data.is_running);\n } catch {\n if (!cancelled) {\n setTickOutput(\"\");\n setTickRunning(false);\n }\n }\n };\n load();\n const interval = setInterval(load, 1000);\n return () => {\n cancelled = true;\n clearInterval(interval);\n };\n }, [heartbeat.id, selectedTickId]);\n\n useEffect(() => {\n if (outputRef.current) {\n outputRef.current.scrollTop = outputRef.current.scrollHeight;\n }\n }, [tickOutput]);\n\n return (\n <div\n style={{\n position: \"fixed\",\n top: 0,\n right: 0,\n width: 520,\n height: \"100vh\",\n background: theme.surface,\n borderLeft: `1px solid ${theme.border}`,\n boxShadow: \"-20px 0 60px rgba(0,0,0,0.4)\",\n zIndex: 500,\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n <div\n style={{\n padding: \"22px 24px\",\n borderBottom: `1px solid ${theme.border}`,\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"flex-start\",\n gap: 12,\n }}\n >\n <div>\n <div\n style={{\n fontSize: 18,\n fontWeight: 700,\n color: theme.text,\n fontFamily: \"'JetBrains Mono', monospace\",\n }}\n >\n {heartbeat.name}\n </div>\n <div style={{ fontSize: 12, color: theme.textMuted, marginTop: 6 }}>\n {heartbeat.working_dir}\n </div>\n </div>\n <button\n onClick={onClose}\n style={{\n background: \"transparent\",\n border: \"none\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 22,\n lineHeight: 1,\n }}\n >\n ×\n </button>\n </div>\n <div style={{ padding: 24, overflow: \"auto\", flex: 1 }}>\n <div style={{ display: \"flex\", gap: 8, flexWrap: \"wrap\", marginBottom: 16 }}>\n <HeartbeatBadge enabled={heartbeat.enabled} />\n <AgentBadge agent={heartbeat.default_agent} />\n {heartbeat.schedule_type === \"interval\" ? (\n <Tag>⟳ {heartbeat.interval_seconds}s</Tag>\n ) : (\n <Tag>⏲ {heartbeat.cron_expr}</Tag>\n )}\n {heartbeat.last_decision && <Tag>{heartbeat.last_decision}</Tag>}\n </div>\n <div style={{ fontSize: 12, color: theme.textMuted, lineHeight: 1.7, marginBottom: 18 }}>\n <div>\n Next run: {heartbeat.next_run_at ? formatTaskDateTime(heartbeat.next_run_at) : \"n/a\"}\n </div>\n <div>\n Last tick:{\" \"}\n {heartbeat.last_tick_at ? formatTaskDateTime(heartbeat.last_tick_at) : \"never\"}\n </div>\n <div>\n Last trigger:{\" \"}\n {heartbeat.last_triggered_at\n ? formatTaskDateTime(heartbeat.last_triggered_at)\n : \"never\"}\n </div>\n <div>Cooldown: {heartbeat.cooldown_seconds || 0}s</div>\n </div>\n <div style={{ marginBottom: 20 }}>\n <div\n style={{\n fontSize: 11,\n fontWeight: 700,\n color: theme.textMuted,\n letterSpacing: 0.8,\n textTransform: \"uppercase\",\n marginBottom: 8,\n }}\n >\n Decision Prompt\n </div>\n <div\n style={{\n fontSize: 12,\n lineHeight: 1.7,\n color: theme.text,\n background: theme.bg,\n border: `1px solid ${theme.border}`,\n borderRadius: 10,\n padding: 14,\n whiteSpace: \"pre-wrap\",\n }}\n >\n {heartbeat.check_prompt}\n </div>\n </div>\n <div style={{ marginBottom: 20 }}>\n <div\n style={{\n fontSize: 11,\n fontWeight: 700,\n color: theme.textMuted,\n letterSpacing: 0.8,\n textTransform: \"uppercase\",\n marginBottom: 8,\n }}\n >\n Triggered Task Template\n </div>\n <div\n style={{\n fontSize: 12,\n lineHeight: 1.7,\n color: theme.text,\n background: theme.bg,\n border: `1px solid ${theme.border}`,\n borderRadius: 10,\n padding: 14,\n whiteSpace: \"pre-wrap\",\n }}\n >\n {heartbeat.action_prompt_template || \"No template configured\"}\n </div>\n </div>\n <div>\n <div\n style={{\n fontSize: 11,\n fontWeight: 700,\n color: theme.textMuted,\n letterSpacing: 0.8,\n textTransform: \"uppercase\",\n marginBottom: 8,\n }}\n >\n Recent Ticks\n </div>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 8 }}>\n {ticks.map((tick) => {\n let payload = null;\n try {\n payload = tick.decision_payload ? JSON.parse(tick.decision_payload) : null;\n } catch {}\n return (\n <div\n key={tick.id}\n style={{\n background: theme.bg,\n border: `1px solid ${theme.border}`,\n borderRadius: 10,\n padding: 12,\n cursor: \"pointer\",\n boxShadow:\n selectedTickId === tick.id ? `0 0 0 1px ${theme.accent} inset` : \"none\",\n }}\n >\n <div\n onClick={() => setSelectedTickId(tick.id)}\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n gap: 8,\n marginBottom: 6,\n }}\n >\n <div style={{ fontSize: 12, fontWeight: 600, color: theme.text }}>\n {tick.decision_type || tick.status}\n </div>\n <div style={{ fontSize: 11, color: theme.textDim, fontFamily: \"monospace\" }}>\n {tick.started_at ? formatTaskDateTime(tick.started_at) : \"\"}\n </div>\n </div>\n {payload?.reason && (\n <div style={{ fontSize: 12, color: theme.textMuted, lineHeight: 1.5 }}>\n {payload.reason}\n </div>\n )}\n {tick.error && (\n <div style={{ fontSize: 12, color: theme.red, lineHeight: 1.5 }}>\n {tick.error}\n </div>\n )}\n {tick.task_id && (\n <div\n style={{\n fontSize: 11,\n color: theme.accent,\n marginTop: 6,\n fontFamily: \"monospace\",\n }}\n >\n Triggered task #{tick.task_id}\n </div>\n )}\n </div>\n );\n })}\n {ticks.length === 0 && (\n <div\n style={{\n border: `1px dashed ${theme.border}`,\n borderRadius: 10,\n padding: 24,\n textAlign: \"center\",\n color: theme.textDim,\n fontSize: 12,\n }}\n >\n No ticks yet\n </div>\n )}\n </div>\n </div>\n <div style={{ marginTop: 20 }}>\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n marginBottom: 8,\n }}\n >\n <div\n style={{\n fontSize: 11,\n fontWeight: 700,\n color: theme.textMuted,\n letterSpacing: 0.8,\n textTransform: \"uppercase\",\n }}\n >\n Tick Log\n </div>\n {selectedTickId && (\n <div\n style={{\n fontSize: 11,\n color: tickRunning ? theme.orange : theme.textDim,\n fontFamily: \"monospace\",\n }}\n >\n {tickRunning ? \"LIVE\" : \"Stored\"} · tick #{selectedTickId}\n </div>\n )}\n </div>\n <div\n ref={outputRef}\n style={{\n background: theme.bg,\n border: `1px solid ${theme.border}`,\n borderRadius: 10,\n padding: 14,\n minHeight: 180,\n maxHeight: 320,\n overflow: \"auto\",\n fontFamily: \"'JetBrains Mono', monospace\",\n fontSize: 12,\n lineHeight: 1.6,\n whiteSpace: \"pre-wrap\",\n color: theme.text,\n }}\n >\n {selectedTickId\n ? tickOutput || \"No output captured for this tick.\"\n : \"Select a tick to view its log.\"}\n </div>\n </div>\n </div>\n </div>\n );\n}\n\nfunction NewTaskModal({ onClose, onSubmit, initialData, mode = \"create\" }) {\n const savedDir = localStorage.getItem(\"agentforge_working_dir\") || \"~/papers\";\n const [form, setForm] = useState(() => {\n if (initialData) {\n return {\n title: initialData.title || \"\",\n prompt: initialData.prompt || \"\",\n working_dir: initialData.working_dir || savedDir,\n schedule_type: initialData.schedule_type || \"immediate\",\n cron_expr: initialData.cron_expr || \"\",\n delay_seconds: initialData.delay_seconds || 60,\n scheduled_at: initialData.next_run_at\n ? formatDateTimeLocalInput(initialData.next_run_at)\n : \"\",\n max_runs: initialData.max_runs || \"\",\n tags: initialData.tags || \"\",\n agent: initialData.agent || DEFAULT_AGENT,\n dag_id: initialData.dag_id || \"\",\n };\n }\n return {\n title: \"\",\n prompt: \"\",\n working_dir: savedDir,\n schedule_type: \"immediate\",\n cron_expr: \"\",\n delay_seconds: 60,\n scheduled_at: \"\",\n max_runs: \"\",\n tags: \"\",\n agent: DEFAULT_AGENT,\n dag_id: \"\",\n };\n });\n const [promptImages, setPromptImages] = useState(() => {\n if (initialData?.prompt_images && Array.isArray(initialData.prompt_images)) {\n return initialData.prompt_images.map((img) => ({\n name: img.name || \"image\",\n media_type: img.media_type || \"image/jpeg\",\n data: img.data || \"\",\n preview: img.data ? `data:${img.media_type || \"image/jpeg\"};base64,${img.data}` : \"\",\n }));\n }\n return [];\n });\n // DAG dependencies: [{task_id, inject_result, _input}] — _input is the text box value\n const [depRows, setDepRows] = useState(() => {\n if (initialData?.dependencies && Array.isArray(initialData.dependencies)) {\n return initialData.dependencies.map((dep) => ({\n task_id: dep.depends_on_task_id,\n inject_result: !!dep.inject_result,\n _input: String(dep.depends_on_task_id),\n }));\n }\n return [];\n });\n const [scheduledAtError, setScheduledAtError] = useState(\"\");\n\n const set = (k, v) => setForm((prev) => ({ ...prev, [k]: v }));\n\n const handleImageSelect = (e) => {\n const files = Array.from(e.target.files || []);\n files.forEach((file: any) => {\n const reader = new FileReader();\n reader.onload = (ev) => {\n const dataUrl = ev.target.result as string; // \"data:image/jpeg;base64,...\"\n const [meta, data] = dataUrl.split(\",\");\n const media_type = meta.match(/:(.*?);/)?.[1] || \"image/jpeg\";\n setPromptImages((prev) => [\n ...prev,\n { name: file.name, media_type, data, preview: dataUrl },\n ]);\n };\n reader.readAsDataURL(file);\n });\n e.target.value = \"\";\n };\n\n const removeImage = (idx) => setPromptImages((prev) => prev.filter((_, i) => i !== idx));\n\n const handleSubmit = () => {\n if (!form.prompt.trim()) return;\n localStorage.setItem(\"agentforge_working_dir\", form.working_dir);\n\n // Build depends_on list (only valid numeric IDs)\n const depends_on = depRows\n .filter((r) => r.task_id)\n .map((r) => ({ task_id: r.task_id, inject_result: r.inject_result }));\n\n const data: any = {\n ...form,\n title: form.title || form.prompt.slice(0, 60),\n delay_seconds: form.schedule_type === \"delayed\" ? parseInt(form.delay_seconds) || 60 : null,\n cron_expr: form.schedule_type === \"cron\" ? form.cron_expr : null,\n max_runs: form.max_runs ? parseInt(form.max_runs) : null,\n prompt_images: promptImages.map(({ name, media_type, data }) => ({ name, media_type, data })),\n depends_on: mode === \"edit\" ? depends_on : depends_on.length > 0 ? depends_on : undefined,\n dag_id: form.dag_id || undefined,\n };\n\n // Handle scheduled_at: convert datetime-local to ISO timestamp\n if (form.schedule_type === \"scheduled_at\") {\n const localDate = parseTaskDateTime(form.scheduled_at);\n const serialized = serializeDateTimeLocalInput(form.scheduled_at);\n if (!form.scheduled_at || !serialized || !localDate || isNaN(localDate.getTime())) {\n setScheduledAtError(\"Please enter a valid date and time.\");\n return;\n }\n setScheduledAtError(\"\");\n data.next_run_at = serialized;\n }\n\n onSubmit(data);\n };\n\n const inputStyle: CSSProperties = {\n width: \"100%\",\n padding: \"10px 14px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n color: theme.text,\n fontSize: 13,\n outline: \"none\",\n boxSizing: \"border-box\",\n fontFamily: \"'JetBrains Mono', 'SF Mono', monospace\",\n transition: \"border-color 0.2s\",\n };\n\n const labelStyle = {\n fontSize: 11,\n fontWeight: 600,\n color: theme.textMuted,\n letterSpacing: 0.8,\n textTransform: \"uppercase\",\n marginBottom: 6,\n display: \"block\",\n };\n\n return (\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n background: \"rgba(0,0,0,0.7)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex: 1000,\n backdropFilter: \"blur(8px)\",\n }}\n onClick={onClose}\n >\n <div\n onClick={(e) => e.stopPropagation()}\n style={{\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 16,\n padding: 32,\n width: 520,\n maxHeight: \"80vh\",\n overflow: \"auto\",\n boxShadow: \"0 24px 80px rgba(0,0,0,0.5)\",\n }}\n >\n <h2\n style={{\n margin: \"0 0 24px\",\n fontSize: 18,\n fontWeight: 700,\n color: theme.text,\n fontFamily: \"'JetBrains Mono', monospace\",\n }}\n >\n {mode === \"edit\" ? \"Edit Task\" : mode === \"fork\" ? \"Fork Task\" : \"New Task\"}\n </h2>\n\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 16 }}>\n <div>\n <label style={labelStyle}>Title</label>\n <input\n style={inputStyle}\n placeholder=\"Task title...\"\n value={form.title}\n onChange={(e) => set(\"title\", e.target.value)}\n />\n </div>\n\n <div>\n <label style={labelStyle}>Prompt *</label>\n <textarea\n style={{ ...inputStyle, height: 100, resize: \"vertical\" }}\n placeholder=\"The prompt to send to Claude Code...\"\n value={form.prompt}\n onChange={(e) => set(\"prompt\", e.target.value)}\n />\n </div>\n\n <div>\n <label style={labelStyle}>Images (optional)</label>\n <div\n style={{\n display: \"flex\",\n flexWrap: \"wrap\",\n gap: 8,\n marginBottom: promptImages.length ? 8 : 0,\n }}\n >\n {promptImages.map((img, idx) => (\n <div key={idx} style={{ position: \"relative\", width: 72, height: 72 }}>\n <img\n src={img.preview}\n alt={img.name}\n style={{\n width: 72,\n height: 72,\n objectFit: \"cover\",\n borderRadius: 6,\n border: `1px solid ${theme.border}`,\n }}\n />\n <button\n onClick={() => removeImage(idx)}\n style={{\n position: \"absolute\",\n top: -6,\n right: -6,\n width: 18,\n height: 18,\n borderRadius: \"50%\",\n border: \"none\",\n background: theme.red || \"#e74c3c\",\n color: \"#fff\",\n fontSize: 11,\n cursor: \"pointer\",\n lineHeight: \"18px\",\n padding: 0,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n >\n ×\n </button>\n </div>\n ))}\n <label\n style={{\n width: 72,\n height: 72,\n borderRadius: 6,\n border: `1px dashed ${theme.border}`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"pointer\",\n color: theme.textDim,\n fontSize: 22,\n flexShrink: 0,\n }}\n >\n +\n <input\n type=\"file\"\n accept=\"image/*\"\n multiple\n style={{ display: \"none\" }}\n onChange={handleImageSelect}\n />\n </label>\n </div>\n {promptImages.length > 0 && (\n <div style={{ fontSize: 10, color: theme.textDim }}>\n {promptImages.length} image{promptImages.length > 1 ? \"s\" : \"\"} attached\n </div>\n )}\n </div>\n\n <div>\n <label style={labelStyle}>Working Directory</label>\n <div style={{ display: \"flex\", gap: 8 }}>\n <input\n style={{ ...inputStyle, flex: 1 }}\n placeholder=\"~/papers\"\n value={form.working_dir}\n onChange={(e) => set(\"working_dir\", e.target.value)}\n />\n {window.electronAPI?.selectDirectory && (\n <button\n onClick={async () => {\n const dir = await window.electronAPI.selectDirectory();\n if (dir) set(\"working_dir\", dir);\n }}\n style={{\n padding: \"8px 14px\",\n borderRadius: 8,\n cursor: \"pointer\",\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n color: theme.textMuted,\n fontSize: 12,\n fontWeight: 600,\n whiteSpace: \"nowrap\",\n transition: \"all 0.15s\",\n }}\n >\n Browse\n </button>\n )}\n </div>\n </div>\n\n <div>\n <label style={labelStyle}>Schedule Type</label>\n <div style={{ display: \"flex\", gap: 8, flexWrap: \"wrap\" }}>\n {[\"immediate\", \"delayed\", \"scheduled_at\", \"cron\"].map((t) => (\n <button\n key={t}\n onClick={() => set(\"schedule_type\", t)}\n style={{\n flex: 1,\n padding: \"8px 12px\",\n borderRadius: 8,\n cursor: \"pointer\",\n border: `1px solid ${form.schedule_type === t ? theme.accent : theme.border}`,\n background: form.schedule_type === t ? theme.accentGlow : \"transparent\",\n color: form.schedule_type === t ? theme.accent : theme.textMuted,\n fontSize: 12,\n fontWeight: 600,\n textTransform: \"capitalize\",\n transition: \"all 0.15s\",\n minWidth: 100,\n }}\n >\n {t === \"immediate\"\n ? \"⚡ Immediate\"\n : t === \"delayed\"\n ? \"⏳ Delayed\"\n : t === \"scheduled_at\"\n ? \"📅 At Time\"\n : \"⏲ Cron\"}\n </button>\n ))}\n </div>\n </div>\n\n {form.schedule_type === \"delayed\" && (\n <div>\n <label style={labelStyle}>Delay (seconds)</label>\n <input\n type=\"number\"\n style={inputStyle}\n value={form.delay_seconds}\n onChange={(e) => set(\"delay_seconds\", e.target.value)}\n />\n </div>\n )}\n\n {form.schedule_type === \"scheduled_at\" && (\n <div>\n <label style={labelStyle}>Run At (Local Time)</label>\n <input\n type=\"datetime-local\"\n style={inputStyle}\n value={form.scheduled_at}\n onChange={(e) => {\n set(\"scheduled_at\", e.target.value);\n setScheduledAtError(\"\");\n }}\n />\n {scheduledAtError && (\n <div style={{ fontSize: 11, color: \"#ff5f5f\", marginTop: 4 }}>\n {scheduledAtError}\n </div>\n )}\n <div style={{ fontSize: 10, color: theme.textDim, marginTop: 4 }}>\n Select a specific date and time to execute this task once\n </div>\n </div>\n )}\n\n {form.schedule_type === \"cron\" && (\n <>\n <div>\n <label style={labelStyle}>Cron Expression</label>\n <input\n style={inputStyle}\n placeholder=\"*/30 * * * *\"\n value={form.cron_expr}\n onChange={(e) => set(\"cron_expr\", e.target.value)}\n />\n <div style={{ fontSize: 10, color: theme.textDim, marginTop: 4 }}>\n e.g. \"0 9 * * *\" = daily 9am, \"*/30 * * * *\" = every 30 min\n </div>\n </div>\n <div>\n <label style={labelStyle}>Max Runs (empty = unlimited)</label>\n <input\n type=\"number\"\n style={inputStyle}\n value={form.max_runs}\n onChange={(e) => set(\"max_runs\", e.target.value)}\n />\n </div>\n </>\n )}\n\n <div>\n <label style={labelStyle}>Tags (comma separated)</label>\n <input\n style={inputStyle}\n placeholder=\"paper, review, arxiv\"\n value={form.tags}\n onChange={(e) => set(\"tags\", e.target.value)}\n />\n </div>\n\n {/* ── DAG Dependencies ── */}\n <div>\n <label style={labelStyle}>Dependencies (optional)</label>\n <div style={{ fontSize: 10, color: theme.textDim, marginBottom: 8 }}>\n This task will be blocked until all upstream tasks complete.\n </div>\n {depRows.map((row, idx) => (\n <div\n key={idx}\n style={{ display: \"flex\", gap: 6, alignItems: \"center\", marginBottom: 6 }}\n >\n <input\n type=\"number\"\n placeholder=\"Task ID\"\n value={row._input || \"\"}\n onChange={(e) => {\n const val = e.target.value;\n const parsed = parseInt(val);\n setDepRows((prev) =>\n prev.map((r, i) =>\n i === idx\n ? { ...r, _input: val, task_id: isNaN(parsed) ? null : parsed }\n : r,\n ),\n );\n }}\n style={{ ...inputStyle, width: 100, flex: \"none\" }}\n />\n <label\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 4,\n fontSize: 11,\n color: theme.textMuted,\n cursor: \"pointer\",\n flex: 1,\n }}\n >\n <input\n type=\"checkbox\"\n checked={row.inject_result}\n onChange={(e) =>\n setDepRows((prev) =>\n prev.map((r, i) =>\n i === idx ? { ...r, inject_result: e.target.checked } : r,\n ),\n )\n }\n style={{ accentColor: theme.accent }}\n />\n Inject result into prompt\n </label>\n <button\n onClick={() => setDepRows((prev) => prev.filter((_, i) => i !== idx))}\n style={{\n background: \"transparent\",\n border: \"none\",\n color: theme.red,\n cursor: \"pointer\",\n fontSize: 16,\n padding: \"0 4px\",\n }}\n >\n ×\n </button>\n </div>\n ))}\n <button\n onClick={() =>\n setDepRows((prev) => [...prev, { task_id: null, inject_result: false, _input: \"\" }])\n }\n style={{\n padding: \"5px 12px\",\n borderRadius: 6,\n border: `1px dashed ${theme.border}`,\n background: \"transparent\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 11,\n fontWeight: 600,\n }}\n >\n + Add dependency\n </button>\n </div>\n\n <div>\n <label style={labelStyle}>DAG ID (optional)</label>\n <input\n style={inputStyle}\n placeholder=\"my-pipeline\"\n value={form.dag_id}\n onChange={(e) => set(\"dag_id\", e.target.value)}\n />\n <div style={{ fontSize: 10, color: theme.textDim, marginTop: 4 }}>\n Group tasks into a named workflow\n </div>\n </div>\n\n <div>\n <label style={labelStyle}>Agent</label>\n <select\n style={inputStyle}\n value={form.agent}\n onChange={(e) => set(\"agent\", e.target.value)}\n >\n <option value=\"claude\">Claude Code (claude CLI)</option>\n <option value=\"codex\">Codex CLI (openai/codex)</option>\n </select>\n </div>\n </div>\n\n <div style={{ display: \"flex\", gap: 10, marginTop: 28, justifyContent: \"flex-end\" }}>\n <button\n onClick={onClose}\n style={{\n padding: \"10px 20px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: \"transparent\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n }}\n >\n Cancel\n </button>\n <button\n onClick={handleSubmit}\n style={{\n padding: \"10px 24px\",\n borderRadius: 8,\n border: \"none\",\n background: theme.accent,\n color: \"#fff\",\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n boxShadow: `0 0 20px ${theme.accentGlow}`,\n }}\n >\n {mode === \"edit\" ? \"Save Changes\" : mode === \"fork\" ? \"Create Fork\" : \"Create Task\"}\n </button>\n </div>\n </div>\n </div>\n );\n}\n\nfunction DetailPanel({ task, onClose, onResume }: any) {\n // `task` is always truthy here — the only caller renders this inside\n // `{detail && <DetailPanel task={... || detail} />}`. Hooks must stay\n // unconditional, so do not early-return before them.\n const [liveOutput, setLiveOutput] = useState(\"\");\n const [resumeText, setResumeText] = useState(\"\");\n const [resumeError, setResumeError] = useState(\"\");\n const [resumeSent, setResumeSent] = useState(false);\n const [messages, setMessages] = useState<any[]>([]);\n const [events, setEvents] = useState<any[]>([]);\n const [showMessages, setShowMessages] = useState(false);\n const [showEvents, setShowEvents] = useState(false);\n const [showLiveOutput, setShowLiveOutput] = useState(true);\n const liveOutputRef = useRef<any>(null);\n const messagesRef = useRef<any>(null);\n const eventsRef = useRef<any>(null);\n\n useEffect(() => {\n if (task.status !== \"running\") {\n setLiveOutput(\"\");\n return;\n }\n let cancelled = false;\n let lastOutputLength = 0;\n const poll = async () => {\n try {\n const res = await fetch(`${API}/tasks/${task.id}/output`);\n if (res.ok && !cancelled) {\n const data = await res.json();\n const currentOutput = data.output || \"\";\n // 增量更新:只添加新内容\n if (currentOutput.length > lastOutputLength) {\n const newContent = currentOutput.slice(lastOutputLength);\n setLiveOutput((prev) => prev + newContent);\n lastOutputLength = currentOutput.length;\n }\n }\n } catch {}\n };\n poll();\n const interval = setInterval(poll, 1000); // 缩短轮询间隔到1秒\n return () => {\n cancelled = true;\n clearInterval(interval);\n };\n }, [task.id, task.status]);\n\n useEffect(() => {\n if (liveOutputRef.current) {\n liveOutputRef.current.scrollTop = liveOutputRef.current.scrollHeight;\n }\n }, [liveOutput]);\n\n useEffect(() => {\n if (showMessages) {\n fetchTaskMessages(task.id).then(setMessages);\n }\n }, [task.id, showMessages]);\n\n useEffect(() => {\n if (!showEvents) return;\n let cancelled = false;\n const load = async () => {\n const nextEvents = await fetchTaskEvents(task.id);\n if (!cancelled) setEvents(nextEvents);\n };\n load();\n if (task.status !== \"running\") {\n return () => {\n cancelled = true;\n };\n }\n const interval = setInterval(load, 1000);\n return () => {\n cancelled = true;\n clearInterval(interval);\n };\n }, [task.id, task.status, showEvents]);\n\n useEffect(() => {\n if (messagesRef.current) {\n messagesRef.current.scrollTop = messagesRef.current.scrollHeight;\n }\n }, [messages]);\n\n const handleResume = async () => {\n if (!resumeText.trim()) return;\n setResumeError(\"\");\n const result = await resumeTask(task.id, resumeText.trim());\n if (result.error) {\n setResumeError(result.error);\n } else {\n setResumeText(\"\");\n setResumeSent(true);\n setTimeout(() => setResumeSent(false), 3000);\n onResume();\n }\n };\n\n return (\n <div\n style={{\n position: \"fixed\",\n right: 0,\n top: 0,\n bottom: 0,\n width: 480,\n background: theme.surface,\n borderLeft: `1px solid ${theme.border}`,\n zIndex: 999,\n overflow: \"auto\",\n padding: 28,\n boxShadow: \"-8px 0 40px rgba(0,0,0,0.4)\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n marginBottom: 24,\n }}\n >\n <Badge status={task.status} />\n <button\n onClick={onClose}\n style={{\n background: \"transparent\",\n border: \"none\",\n color: theme.textMuted,\n fontSize: 20,\n cursor: \"pointer\",\n }}\n >\n ×\n </button>\n </div>\n\n <h2\n style={{\n fontSize: 18,\n fontWeight: 700,\n color: theme.text,\n margin: \"0 0 8px\",\n fontFamily: \"'JetBrains Mono', monospace\",\n }}\n >\n {task.title}\n </h2>\n\n <div\n style={{ fontSize: 11, color: theme.textDim, marginBottom: 24, fontFamily: \"monospace\" }}\n >\n ID: {task.id} · Created: {formatTaskDateTime(task.created_at)}\n </div>\n\n <Section title=\"Prompt\">\n <pre\n style={{\n background: theme.bg,\n border: `1px solid ${theme.border}`,\n borderRadius: 8,\n padding: 14,\n fontSize: 12,\n color: theme.text,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n margin: 0,\n fontFamily: \"'JetBrains Mono', monospace\",\n lineHeight: 1.6,\n }}\n >\n {task.prompt}\n </pre>\n {task.prompt_images && task.prompt_images.length > 0 && (\n <div style={{ marginTop: 12 }}>\n <div\n style={{\n fontSize: 10,\n color: theme.textMuted,\n fontWeight: 600,\n letterSpacing: 0.8,\n textTransform: \"uppercase\",\n marginBottom: 8,\n }}\n >\n Attached Images ({task.prompt_images.length})\n </div>\n <div style={{ display: \"flex\", flexWrap: \"wrap\", gap: 8 }}>\n {task.prompt_images.map((img, i) => (\n <img\n key={i}\n src={`data:${img.media_type};base64,${img.data}`}\n alt={img.name || `image ${i + 1}`}\n style={{\n width: 80,\n height: 80,\n objectFit: \"cover\",\n borderRadius: 6,\n border: `1px solid ${theme.border}`,\n }}\n />\n ))}\n </div>\n </div>\n )}\n </Section>\n\n <Section title=\"Configuration\">\n <InfoRow label=\"Working Dir\" value={task.working_dir} />\n <InfoRow label=\"Agent\" value={task.agent || DEFAULT_AGENT} />\n <InfoRow label=\"Schedule\" value={task.schedule_type} />\n {task.cron_expr && <InfoRow label=\"Cron\" value={task.cron_expr} />}\n {task.delay_seconds && <InfoRow label=\"Delay\" value={`${task.delay_seconds}s`} />}\n {task.next_run_at && (\n <InfoRow label=\"Next Run\" value={formatTaskDateTime(task.next_run_at)} />\n )}\n <InfoRow\n label=\"Runs\"\n value={`${task.run_count}${task.max_runs ? ` / ${task.max_runs}` : \"\"}`}\n />\n {task.dag_id && <InfoRow label=\"DAG\" value={task.dag_id} />}\n </Section>\n\n {/* DAG dependency info */}\n {task.dependencies && task.dependencies.length > 0 && (\n <Section title=\"Upstream Dependencies\">\n {task.dependencies.map((dep) => (\n <div\n key={dep.id}\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n padding: \"5px 0\",\n borderBottom: `1px solid ${theme.border}`,\n fontSize: 12,\n }}\n >\n <span style={{ color: theme.text, fontFamily: \"monospace\" }}>\n #{dep.depends_on_task_id}\n {dep.depends_on_title ? ` — ${dep.depends_on_title}` : \"\"}\n </span>\n <div style={{ display: \"flex\", gap: 8, alignItems: \"center\" }}>\n {dep.inject_result ? (\n <span style={{ fontSize: 10, color: theme.accent }}>↳ inject</span>\n ) : null}\n <span\n style={{\n fontSize: 10,\n fontWeight: 600,\n color:\n dep.depends_on_status === \"completed\"\n ? theme.green\n : dep.depends_on_status === \"failed\"\n ? theme.red\n : theme.orange,\n }}\n >\n {dep.depends_on_status}\n </span>\n </div>\n </div>\n ))}\n </Section>\n )}\n\n {task.dependents && task.dependents.length > 0 && (\n <Section title=\"Downstream Tasks\">\n <div style={{ fontSize: 12, color: theme.textMuted, fontFamily: \"monospace\" }}>\n {task.dependents.map((id) => `#${id}`).join(\", \")}\n </div>\n </Section>\n )}\n\n {task.status === \"running\" && (\n <Section\n title={\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8 }}>\n <span>Live Output</span>\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n fontSize: 10,\n color: theme.blue,\n }}\n >\n <span\n style={{\n width: 6,\n height: 6,\n borderRadius: \"50%\",\n background: theme.blue,\n animation: \"pulse 1.2s ease-in-out infinite\",\n }}\n />\n live\n </div>\n </div>\n }\n >\n <div\n style={{\n background: theme.bg,\n border: `1px solid ${theme.borderActive}`,\n borderRadius: 8,\n overflow: \"hidden\",\n }}\n >\n {/* 工具栏 */}\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n padding: \"8px 12px\",\n background: theme.surface,\n borderBottom: `1px solid ${theme.border}`,\n fontSize: 11,\n color: theme.textMuted,\n }}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 12 }}>\n <button\n onClick={() => setShowLiveOutput(!showLiveOutput)}\n style={{\n background: \"transparent\",\n border: \"none\",\n color: theme.textMuted,\n fontSize: 11,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n gap: 4,\n }}\n >\n {showLiveOutput ? \"▼\" : \"▶\"} {showLiveOutput ? \"Hide\" : \"Show\"}\n </button>\n <span style={{ fontFamily: \"monospace\" }}>\n {liveOutput.length.toLocaleString()} chars\n </span>\n </div>\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8 }}>\n <button\n onClick={() => {\n navigator.clipboard.writeText(liveOutput);\n }}\n style={{\n background: \"transparent\",\n border: \"none\",\n color: theme.textMuted,\n fontSize: 11,\n cursor: \"pointer\",\n padding: \"4px 8px\",\n borderRadius: 4,\n fontFamily: \"'JetBrains Mono', monospace\",\n }}\n >\n 📋 Copy\n </button>\n <button\n onClick={() => setLiveOutput(\"\")}\n style={{\n background: \"transparent\",\n border: \"none\",\n color: theme.textMuted,\n fontSize: 11,\n cursor: \"pointer\",\n padding: \"4px 8px\",\n borderRadius: 4,\n fontFamily: \"'JetBrains Mono', monospace\",\n }}\n >\n 🗑️ Clear\n </button>\n </div>\n </div>\n\n {/* 输出内容区域 */}\n {showLiveOutput && (\n <div\n style={{\n maxHeight: 400,\n overflow: \"auto\",\n position: \"relative\",\n }}\n ref={liveOutputRef}\n >\n <pre\n style={{\n fontSize: 12,\n color: theme.text,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n margin: 0,\n padding: 14,\n fontFamily: \"'JetBrains Mono', monospace\",\n lineHeight: 1.6,\n minHeight: 60,\n }}\n >\n {liveOutput ? (\n <FormattedOutput content={liveOutput} theme={theme} />\n ) : (\n <span style={{ color: theme.textDim, fontStyle: \"italic\" }}>\n Waiting for agent output...\n </span>\n )}\n </pre>\n </div>\n )}\n </div>\n </Section>\n )}\n\n {task.result && (\n <Section title=\"Result\">\n <pre\n style={{\n background: theme.bg,\n border: `1px solid ${theme.border}`,\n borderRadius: 8,\n padding: 14,\n fontSize: 12,\n color: theme.green,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n margin: 0,\n fontFamily: \"'JetBrains Mono', monospace\",\n lineHeight: 1.6,\n maxHeight: 300,\n overflow: \"auto\",\n }}\n >\n {task.result}\n </pre>\n </Section>\n )}\n\n {task.error && (\n <Section title=\"Error\">\n <pre\n style={{\n background: theme.redBg,\n border: `1px solid rgba(248,113,113,0.2)`,\n borderRadius: 8,\n padding: 14,\n fontSize: 12,\n color: theme.red,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n margin: 0,\n fontFamily: \"'JetBrains Mono', monospace\",\n lineHeight: 1.6,\n }}\n >\n {task.error}\n </pre>\n </Section>\n )}\n\n {/* Output History Tabs */}\n <div style={{ marginBottom: 20 }}>\n <div style={{ display: \"flex\", gap: 8, marginBottom: 12 }}>\n <button\n onClick={() => {\n setShowMessages(!showMessages);\n setShowEvents(false);\n }}\n style={{\n flex: 1,\n padding: \"8px 12px\",\n borderRadius: 8,\n background: showMessages ? theme.accentGlow : theme.surface,\n color: showMessages ? theme.accent : theme.textMuted,\n fontSize: 11,\n fontWeight: 600,\n cursor: \"pointer\",\n border: `1px solid ${showMessages ? theme.accent : theme.border}`,\n transition: \"all 0.15s\",\n }}\n >\n Conversation\n </button>\n <button\n onClick={() => {\n setShowEvents(!showEvents);\n setShowMessages(false);\n }}\n style={{\n flex: 1,\n padding: \"8px 12px\",\n borderRadius: 8,\n background: showEvents ? theme.accentGlow : theme.surface,\n color: showEvents ? theme.accent : theme.textMuted,\n fontSize: 11,\n fontWeight: 600,\n cursor: \"pointer\",\n border: `1px solid ${showEvents ? theme.accent : theme.border}`,\n transition: \"all 0.15s\",\n }}\n >\n Execution Events\n </button>\n </div>\n\n {/* Conversation History */}\n {showMessages && (\n <div\n ref={messagesRef}\n style={{\n maxHeight: 400,\n overflow: \"auto\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: 8,\n }}\n >\n {messages.length === 0 ? (\n <div\n style={{\n fontSize: 12,\n color: theme.textDim,\n padding: \"12px 0\",\n textAlign: \"center\",\n }}\n >\n No conversation data — only tasks run after this feature was added have logs.\n </div>\n ) : (\n messages.map((msg, i) => (\n <div\n key={i}\n style={{\n background: msg.role === \"user\" ? theme.accentGlow : theme.bg,\n border: `1px solid ${msg.role === \"user\" ? theme.accent + \"33\" : theme.border}`,\n borderRadius: 8,\n padding: \"10px 14px\",\n borderLeft: `3px solid ${msg.role === \"user\" ? theme.accent : theme.green}`,\n }}\n >\n <div\n style={{\n fontSize: 10,\n fontWeight: 700,\n letterSpacing: 0.8,\n color: msg.role === \"user\" ? theme.accent : theme.green,\n textTransform: \"uppercase\",\n marginBottom: 6,\n }}\n >\n {msg.role}\n </div>\n <pre\n style={{\n fontSize: 12,\n color: theme.text,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n margin: 0,\n fontFamily: \"'JetBrains Mono', monospace\",\n lineHeight: 1.6,\n maxHeight: 200,\n overflow: \"auto\",\n }}\n >\n {msg.text}\n </pre>\n </div>\n ))\n )}\n </div>\n )}\n\n {/* Execution Events History */}\n {showEvents && (\n <div ref={eventsRef} style={{ maxHeight: 520, overflow: \"auto\" }}>\n <ExecutionTimeline events={events} />\n </div>\n )}\n </div>\n\n {/* Resume completed/failed session */}\n {[\"completed\", \"failed\"].includes(task.status) && task.session_id && (\n <Section title=\"Resume Session\">\n <div\n style={{\n fontSize: 11,\n color: theme.textDim,\n marginBottom: 10,\n fontFamily: \"monospace\",\n }}\n >\n Session: {task.session_id}\n </div>\n <textarea\n placeholder=\"Send a follow-up message to continue this conversation…\"\n value={resumeText}\n onChange={(e) => setResumeText(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && (e.metaKey || e.ctrlKey)) handleResume();\n }}\n style={{\n width: \"100%\",\n padding: \"10px 14px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n color: theme.text,\n fontSize: 13,\n outline: \"none\",\n boxSizing: \"border-box\",\n fontFamily: \"'JetBrains Mono', 'SF Mono', monospace\",\n resize: \"vertical\",\n minHeight: 80,\n }}\n />\n {resumeError && (\n <div style={{ fontSize: 11, color: theme.red, marginTop: 6 }}>{resumeError}</div>\n )}\n {resumeSent && (\n <div style={{ fontSize: 12, color: theme.green, marginTop: 6 }}>\n ✨ 已发送!任务正在重新唤醒,请稍候~\n </div>\n )}\n <button\n onClick={handleResume}\n style={{\n marginTop: 10,\n padding: \"8px 20px\",\n borderRadius: 8,\n border: \"none\",\n background: theme.accent,\n color: \"#fff\",\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n boxShadow: `0 0 20px ${theme.accentGlow}`,\n }}\n >\n ↩ Resume (⌘↵)\n </button>\n </Section>\n )}\n </div>\n );\n}\n\nfunction Section({ title, children }) {\n return (\n <div style={{ marginBottom: 20 }}>\n <div\n style={{\n fontSize: 10,\n fontWeight: 700,\n color: theme.textDim,\n letterSpacing: 1.2,\n textTransform: \"uppercase\",\n marginBottom: 10,\n }}\n >\n {title}\n </div>\n {children}\n </div>\n );\n}\n\nfunction InfoRow({ label, value }) {\n return (\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n padding: \"6px 0\",\n borderBottom: `1px solid ${theme.border}`,\n fontSize: 12,\n }}\n >\n <span style={{ color: theme.textMuted }}>{label}</span>\n <span style={{ color: theme.text, fontFamily: \"monospace\" }}>{value}</span>\n </div>\n );\n}\n\nfunction SettingsModal({\n onClose,\n timeout: initialTimeout,\n defaultAgent: initialDefaultAgent,\n onSave,\n feishu: initialFeishu,\n onFeishuSave,\n channelsStatus: initialChannelsStatus,\n onChannelsSave,\n}) {\n const [tab, setTab] = useState(\"general\");\n const [timeout, setTimeout] = useState(initialTimeout ?? DEFAULT_TIMEOUT_SECONDS);\n const [defaultAgent, setDefaultAgent] = useState(initialDefaultAgent ?? DEFAULT_AGENT);\n const [skillEnabled, setSkillEnabled] = useState(false);\n const [skillSweepAgent, setSkillSweepAgent] = useState(DEFAULT_AGENT);\n const [skillSweepCron, setSkillSweepCron] = useState(\"0 3 * * *\");\n const [feishu, setFeishu] = useState({\n feishu_app_id: \"\",\n feishu_app_secret: \"\",\n feishu_default_chat_id: \"\",\n feishu_default_working_dir: \"~\",\n feishu_enabled: \"false\",\n ...initialFeishu,\n });\n const [feishuSaving, setFeishuSaving] = useState(false);\n const [feishuMsg, setFeishuMsg] = useState<any>(null); // {ok, text}\n const [channels, setChannels] = useState(createInitialChannelsState(initialChannelsStatus));\n const [channelsSaving, setChannelsSaving] = useState(false);\n const [channelsMsg, setChannelsMsg] = useState<any>(null);\n const [weixinQrSrc, setWeixinQrSrc] = useState(\"\");\n const [weixinActionBusy, setWeixinActionBusy] = useState(false);\n const [collapsedChannels, setCollapsedChannels] = useState({\n telegram: true,\n slack: true,\n weixin: true,\n });\n\n // Refresh all channel settings when the modal opens so bot-side /dir changes are visible\n useEffect(() => {\n let cancelled = false;\n const refreshChannels = async (preserveUserEdits = true) => {\n const status = await fetchChannelsStatus();\n if (!cancelled) {\n setChannels((c) => {\n const merged = mergeChannelsStatus(c, status);\n if (!preserveUserEdits) return merged;\n // During background polling, keep user-edited config fields untouched\n // so toggling enabled / editing URLs isn't overwritten before Save.\n return {\n telegram: { ...merged.telegram, enabled: c.telegram.enabled },\n slack: { ...merged.slack, enabled: c.slack.enabled },\n weixin: { ...merged.weixin, enabled: c.weixin.enabled },\n };\n });\n }\n };\n refreshChannels(false); // initial load: full merge to populate fields\n const intervalId = setInterval(refreshChannels, 2000); // polling: preserve edits\n fetchFeishuSettings().then((s) => {\n if (s && Object.keys(s).length) setFeishu((f) => ({ ...f, ...s }));\n });\n fetchSettings().then((s) => {\n if (s && typeof s === \"object\") {\n if (typeof s.skill_library_enabled === \"boolean\") setSkillEnabled(s.skill_library_enabled);\n if (s.skill_sweep_agent) setSkillSweepAgent(s.skill_sweep_agent);\n if (s.skill_sweep_cron) setSkillSweepCron(s.skill_sweep_cron);\n }\n });\n return () => {\n cancelled = true;\n clearInterval(intervalId);\n };\n }, []);\n\n useEffect(() => {\n let cancelled = false;\n const qrValue = channels.weixin?.qr_code_url || \"\";\n if (!qrValue) {\n setWeixinQrSrc(\"\");\n return () => {\n cancelled = true;\n };\n }\n\n if (isWeixinQrImageSource(qrValue)) {\n setWeixinQrSrc(qrValue);\n return () => {\n cancelled = true;\n };\n }\n\n QRCode.toDataURL(qrValue, {\n errorCorrectionLevel: \"M\",\n margin: 2,\n width: 440,\n })\n .then((dataUrl) => {\n if (!cancelled) setWeixinQrSrc(dataUrl);\n })\n .catch((error) => {\n console.error(\"Failed to generate Weixin QR code\", error);\n if (!cancelled) setWeixinQrSrc(\"\");\n });\n\n return () => {\n cancelled = true;\n };\n }, [channels.weixin?.qr_code_url]);\n\n const handleWeixinAction = async (action) => {\n setWeixinActionBusy(true);\n setChannelsMsg(null);\n try {\n await runWeixinAction(action);\n const updated = await fetchChannelsStatus();\n setChannels((c) => mergeChannelsStatus(c, updated));\n if (onChannelsSave) onChannelsSave(updated);\n setChannelsMsg({\n ok: true,\n text: action === \"logout\" ? \"Wechat logged out.\" : \"Wechat login restarted.\",\n });\n } catch (e) {\n setChannelsMsg({ ok: false, text: String(e) });\n } finally {\n setWeixinActionBusy(false);\n }\n };\n\n const handleSaveGeneral = async () => {\n await updateSettings({\n timeout: parseInt(timeout) || DEFAULT_TIMEOUT_SECONDS,\n default_agent: defaultAgent,\n skill_library_enabled: skillEnabled ? \"1\" : \"0\",\n skill_sweep_agent: skillSweepAgent,\n skill_sweep_cron: skillSweepCron,\n });\n onSave(parseInt(timeout) || DEFAULT_TIMEOUT_SECONDS, defaultAgent);\n onClose();\n };\n\n const handleSaveFeishu = async () => {\n setFeishuSaving(true);\n setFeishuMsg(null);\n try {\n await updateFeishuSettings(feishu);\n setFeishuMsg({ ok: true, text: \"Saved. Bridge restarted.\" });\n // Reload settings after save\n if (onFeishuSave) {\n const updated = await fetchFeishuSettings();\n onFeishuSave(updated);\n }\n } catch (e) {\n setFeishuMsg({ ok: false, text: String(e) });\n } finally {\n setFeishuSaving(false);\n }\n };\n\n const handleSaveChannels = async () => {\n setChannelsSaving(true);\n setChannelsMsg(null);\n try {\n await updateChannelsSettings(buildChannelsSavePayload(channels));\n // Reload channel status after save to reflect new running state\n const updated = await fetchChannelsStatus();\n setChannels((c) => mergeChannelsStatus(c, updated));\n if (onChannelsSave) onChannelsSave(updated);\n setChannelsMsg({ ok: true, text: \"Saved. Channels restarted.\" });\n } catch (e) {\n setChannelsMsg({ ok: false, text: String(e) });\n } finally {\n setChannelsSaving(false);\n }\n };\n\n const fieldStyle: CSSProperties = {\n width: \"100%\",\n padding: \"10px 14px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n color: theme.text,\n fontSize: 13,\n outline: \"none\",\n boxSizing: \"border-box\",\n fontFamily: \"'JetBrains Mono', 'SF Mono', monospace\",\n };\n const labelStyle = {\n fontSize: 11,\n fontWeight: 600,\n color: theme.textMuted,\n letterSpacing: 0.8,\n textTransform: \"uppercase\",\n marginBottom: 8,\n display: \"block\",\n };\n const hintStyle = { fontSize: 10, color: theme.textDim, marginTop: 4 };\n\n const tabs = [\"general\", \"channels\", \"feishu\"];\n const tabLabel = { general: \"General\", channels: \"Channels\", feishu: \"Feishu / Lark\" };\n\n return (\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n background: \"rgba(0,0,0,0.7)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex: 1000,\n backdropFilter: \"blur(8px)\",\n }}\n onClick={onClose}\n >\n <div\n onClick={(e) => e.stopPropagation()}\n style={{\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 16,\n padding: 32,\n width: 480,\n maxHeight: \"85vh\",\n overflowY: \"auto\",\n boxShadow: \"0 24px 80px rgba(0,0,0,0.5)\",\n }}\n >\n <h2\n style={{\n margin: \"0 0 20px\",\n fontSize: 18,\n fontWeight: 700,\n color: theme.text,\n fontFamily: \"'JetBrains Mono', monospace\",\n }}\n >\n Settings\n </h2>\n\n {/* Tab bar */}\n <div\n style={{\n display: \"flex\",\n gap: 4,\n marginBottom: 24,\n borderBottom: `1px solid ${theme.border}`,\n paddingBottom: 0,\n }}\n >\n {tabs.map((t) => (\n <button\n key={t}\n onClick={() => setTab(t)}\n style={{\n padding: \"7px 16px\",\n borderRadius: \"8px 8px 0 0\",\n border: \"none\",\n cursor: \"pointer\",\n fontSize: 12,\n fontWeight: 600,\n background: tab === t ? theme.bg : \"transparent\",\n color: tab === t ? theme.text : theme.textMuted,\n borderBottom: tab === t ? `2px solid ${theme.accent}` : \"2px solid transparent\",\n marginBottom: -1,\n }}\n >\n {tabLabel[t]}\n </button>\n ))}\n </div>\n\n {/* ── General tab ── */}\n {tab === \"general\" && (\n <>\n <div style={{ marginBottom: 20 }}>\n <label style={labelStyle}>Task Timeout (seconds)</label>\n <input\n type=\"number\"\n min=\"10\"\n step=\"10\"\n value={timeout}\n onChange={(e) => setTimeout(e.target.value)}\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Default: 12000s (200 min). Max time before a running task is killed.\n </div>\n </div>\n <div style={{ marginBottom: 20 }}>\n <label style={labelStyle}>Default Agent</label>\n <select\n value={defaultAgent}\n onChange={(e) => setDefaultAgent(e.target.value)}\n style={fieldStyle}\n >\n <option value=\"claude\">Claude Code (claude CLI)</option>\n <option value=\"codex\">Codex CLI (openai/codex)</option>\n </select>\n <div style={hintStyle}>Agent used for new tasks unless overridden per-task.</div>\n </div>\n\n {/* ── Skill Library ── */}\n <div\n style={{\n marginBottom: 20,\n paddingTop: 16,\n borderTop: `1px solid ${theme.border}`,\n }}\n >\n <label\n style={{\n ...labelStyle,\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n cursor: \"pointer\",\n }}\n >\n <input\n type=\"checkbox\"\n checked={skillEnabled}\n onChange={(e) => setSkillEnabled(e.target.checked)}\n style={{ width: 16, height: 16, cursor: \"pointer\" }}\n />\n Skill Library 自动扫描\n </label>\n <div style={hintStyle}>\n 定时让 agent 扫描已完成任务、检测复发模式(消耗 token,默认关闭)。\n 手动「扫一遍」按钮不受此开关影响。\n </div>\n </div>\n {skillEnabled && (\n <>\n <div style={{ marginBottom: 20 }}>\n <label style={labelStyle}>扫描 Agent</label>\n <select\n value={skillSweepAgent}\n onChange={(e) => setSkillSweepAgent(e.target.value)}\n style={fieldStyle}\n >\n <option value=\"claude\">Claude Code (claude CLI)</option>\n <option value=\"codex\">Codex CLI (openai/codex)</option>\n </select>\n <div style={hintStyle}>运行 sweep 的 agent。</div>\n </div>\n <div style={{ marginBottom: 20 }}>\n <label style={labelStyle}>扫描节奏 (cron)</label>\n <input\n value={skillSweepCron}\n onChange={(e) => setSkillSweepCron(e.target.value)}\n placeholder=\"0 3 * * *\"\n style={{ ...fieldStyle, fontFamily: \"monospace\" }}\n />\n <div style={hintStyle}>默认每日凌晨 3 点。增量扫描,只看上次以来的新任务。</div>\n </div>\n </>\n )}\n\n <div style={{ display: \"flex\", gap: 10, justifyContent: \"flex-end\" }}>\n <button\n onClick={onClose}\n style={{\n padding: \"10px 20px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: \"transparent\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n }}\n >\n Cancel\n </button>\n <button\n onClick={handleSaveGeneral}\n style={{\n padding: \"10px 24px\",\n borderRadius: 8,\n border: \"none\",\n background: theme.accent,\n color: \"#fff\",\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n boxShadow: `0 0 20px ${theme.accentGlow}`,\n }}\n >\n Save\n </button>\n </div>\n </>\n )}\n\n {/* ── Channels tab ── */}\n {tab === \"channels\" && (\n <>\n {/* ── Telegram ── */}\n {(() => {\n const ch = channels.telegram;\n const collapsed = collapsedChannels.telegram;\n const statusDot = ch.running\n ? { bg: theme.green, label: \"Connected\" }\n : ch.configured\n ? { bg: theme.yellow || \"#f59e0b\", label: \"Configured (not running)\" }\n : { bg: theme.textDim, label: \"Not configured\" };\n return (\n <div\n style={{\n marginBottom: 16,\n borderRadius: 10,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n overflow: \"hidden\",\n }}\n >\n {/* Header row - clickable to collapse */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n padding: \"12px 16px\",\n cursor: \"pointer\",\n userSelect: \"none\",\n }}\n onClick={() => setCollapsedChannels((c) => ({ ...c, telegram: !c.telegram }))}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 10 }}>\n <span\n style={{\n fontSize: 10,\n color: theme.textMuted,\n transition: \"transform 0.2s\",\n transform: collapsed ? \"rotate(-90deg)\" : \"rotate(0deg)\",\n display: \"inline-block\",\n }}\n >\n {\"▼\"}\n </span>\n <span\n style={{\n display: \"inline-flex\",\n width: 22,\n height: 22,\n alignItems: \"center\",\n justifyContent: \"center\",\n color: \"#2AABEE\",\n flexShrink: 0,\n }}\n >\n <svg\n viewBox=\"0 0 24 24\"\n width=\"22\"\n height=\"22\"\n aria-hidden=\"true\"\n fill=\"currentColor\"\n >\n <path d=\"M21.4 4.6a1.2 1.2 0 0 0-1.24-.2L3.8 11.15c-.6.25-.57 1.12.05 1.33l4.6 1.62 1.62 4.6c.22.62 1.08.65 1.33.05l6.75-16.36a1.2 1.2 0 0 0-.2-1.24 1.18 1.18 0 0 0-1.22-.3Z\" />\n </svg>\n </span>\n <span style={{ fontWeight: 700, fontSize: 14, color: theme.text }}>\n Telegram\n </span>\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 6, marginLeft: 8 }}>\n <span\n style={{\n width: 8,\n height: 8,\n borderRadius: \"50%\",\n background: statusDot.bg,\n display: \"inline-block\",\n boxShadow: ch.running ? `0 0 6px ${statusDot.bg}` : \"none\",\n }}\n />\n <span style={{ fontSize: 11, color: theme.textMuted }}>\n {statusDot.label}\n </span>\n </div>\n </div>\n <button\n onClick={(e) => {\n e.stopPropagation();\n setChannels((c) => ({\n ...c,\n telegram: { ...c.telegram, enabled: !c.telegram.enabled },\n }));\n }}\n style={{\n width: 44,\n height: 24,\n borderRadius: 12,\n border: \"none\",\n cursor: \"pointer\",\n background: ch.enabled ? theme.accent : theme.border,\n position: \"relative\",\n transition: \"background 0.2s\",\n flexShrink: 0,\n }}\n >\n <span\n style={{\n position: \"absolute\",\n top: 3,\n width: 18,\n height: 18,\n borderRadius: \"50%\",\n background: \"#fff\",\n transition: \"left 0.2s\",\n left: ch.enabled ? 23 : 3,\n }}\n />\n </button>\n </div>\n\n {/* Collapsible body */}\n {!collapsed && (\n <div style={{ padding: \"0 16px 16px\" }}>\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Bot Token</label>\n <input\n type=\"password\"\n value={ch.bot_token}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n telegram: { ...c.telegram, bot_token: e.target.value },\n }))\n }\n placeholder=\"123456:ABC-DEF...\"\n style={fieldStyle}\n />\n <div style={hintStyle}>Token from @BotFather</div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Allowed User IDs</label>\n <input\n value={ch.allowed_users}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n telegram: { ...c.telegram, allowed_users: e.target.value },\n }))\n }\n placeholder=\"123456789,987654321 (optional)\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Comma-separated numeric Telegram user IDs. Leave empty to allow all.\n </div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Default Working Directory</label>\n <input\n value={ch.default_working_dir}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n telegram: { ...c.telegram, default_working_dir: e.target.value },\n }))\n }\n placeholder=\"~/my-project\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Working directory for tasks created via the Telegram bot.\n </div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Default Notification Chat ID</label>\n <input\n value={ch.default_chat_id}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n telegram: { ...c.telegram, default_chat_id: e.target.value },\n }))\n }\n placeholder=\"-1001234567890 or 123456789\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Fallback chat for notifications from UI-created tasks (group or user chat\n ID).\n </div>\n </div>\n\n <div\n style={{\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 6,\n padding: \"10px 12px\",\n fontSize: 11,\n fontFamily: \"monospace\",\n color: theme.textMuted,\n lineHeight: 1.8,\n }}\n >\n <div style={{ color: theme.textDim, marginBottom: 4 }}>Bot commands:</div>\n {[\n \"/newtask <title> | <prompt>\",\n \"/list\",\n \"/status <id>\",\n \"/cancel <id>\",\n ].map((cmd) => (\n <div key={cmd}>\n <span style={{ color: theme.cyan }}>{cmd}</span>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n );\n })()}\n\n {/* ── Slack ── */}\n {(() => {\n const ch = channels.slack;\n const collapsed = collapsedChannels.slack;\n const statusDot = ch.running\n ? { bg: theme.green, label: \"Connected\" }\n : ch.configured\n ? { bg: theme.yellow || \"#f59e0b\", label: \"Configured (not running)\" }\n : { bg: theme.textDim, label: \"Not configured\" };\n return (\n <div\n style={{\n marginBottom: 16,\n borderRadius: 10,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n overflow: \"hidden\",\n }}\n >\n {/* Header row - clickable to collapse */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n padding: \"12px 16px\",\n cursor: \"pointer\",\n userSelect: \"none\",\n }}\n onClick={() => setCollapsedChannels((c) => ({ ...c, slack: !c.slack }))}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 10 }}>\n <span\n style={{\n fontSize: 10,\n color: theme.textMuted,\n transition: \"transform 0.2s\",\n transform: collapsed ? \"rotate(-90deg)\" : \"rotate(0deg)\",\n display: \"inline-block\",\n }}\n >\n {\"▼\"}\n </span>\n <span\n style={{\n display: \"inline-flex\",\n width: 22,\n height: 22,\n alignItems: \"center\",\n justifyContent: \"center\",\n flexShrink: 0,\n }}\n >\n <svg viewBox=\"0 0 24 24\" width=\"22\" height=\"22\" aria-hidden=\"true\">\n <path\n fill=\"#36C5F0\"\n d=\"M10.1 3.2A2.2 2.2 0 0 1 12.2 1h.7v5.1h-2.8V3.2Z\"\n />\n <path\n fill=\"#2EB67D\"\n d=\"M20.8 10.1A2.2 2.2 0 0 1 23 12.2v.7h-5.1v-2.8h2.9Z\"\n />\n <path\n fill=\"#ECB22E\"\n d=\"M13.9 20.8A2.2 2.2 0 0 1 11.8 23h-.7v-5.1h2.8v2.9Z\"\n />\n <path\n fill=\"#E01E5A\"\n d=\"M3.2 13.9A2.2 2.2 0 0 1 1 11.8v-.7h5.1v2.8H3.2Z\"\n />\n <path\n fill=\"#36C5F0\"\n d=\"M13.2 4.3a2.7 2.7 0 1 1 5.4 0 2.7 2.7 0 0 1-5.4 0Z\"\n />\n <path\n fill=\"#2EB67D\"\n d=\"M16.9 13.2a2.7 2.7 0 1 1 0 5.4 2.7 2.7 0 0 1 0-5.4Z\"\n />\n <path\n fill=\"#ECB22E\"\n d=\"M5.4 16.9a2.7 2.7 0 1 1 5.4 0 2.7 2.7 0 0 1-5.4 0Z\"\n />\n <path\n fill=\"#E01E5A\"\n d=\"M4.3 5.4a2.7 2.7 0 1 1 0 5.4 2.7 2.7 0 0 1 0-5.4Z\"\n />\n </svg>\n </span>\n <span style={{ fontWeight: 700, fontSize: 14, color: theme.text }}>\n Slack\n </span>\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 6, marginLeft: 8 }}>\n <span\n style={{\n width: 8,\n height: 8,\n borderRadius: \"50%\",\n background: statusDot.bg,\n display: \"inline-block\",\n boxShadow: ch.running ? `0 0 6px ${statusDot.bg}` : \"none\",\n }}\n />\n <span style={{ fontSize: 11, color: theme.textMuted }}>\n {statusDot.label}\n </span>\n </div>\n </div>\n <button\n onClick={(e) => {\n e.stopPropagation();\n setChannels((c) => ({\n ...c,\n slack: { ...c.slack, enabled: !c.slack.enabled },\n }));\n }}\n style={{\n width: 44,\n height: 24,\n borderRadius: 12,\n border: \"none\",\n cursor: \"pointer\",\n background: ch.enabled ? theme.accent : theme.border,\n position: \"relative\",\n transition: \"background 0.2s\",\n flexShrink: 0,\n }}\n >\n <span\n style={{\n position: \"absolute\",\n top: 3,\n width: 18,\n height: 18,\n borderRadius: \"50%\",\n background: \"#fff\",\n transition: \"left 0.2s\",\n left: ch.enabled ? 23 : 3,\n }}\n />\n </button>\n </div>\n\n {/* Collapsible body */}\n {!collapsed && (\n <div style={{ padding: \"0 16px 16px\" }}>\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Bot Token</label>\n <input\n type=\"password\"\n value={ch.bot_token}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n slack: { ...c.slack, bot_token: e.target.value },\n }))\n }\n placeholder=\"xoxb-...\"\n style={fieldStyle}\n />\n <div style={hintStyle}>Bot token from OAuth & Permissions</div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>App Token</label>\n <input\n type=\"password\"\n value={ch.app_token}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n slack: { ...c.slack, app_token: e.target.value },\n }))\n }\n placeholder=\"xapp-...\"\n style={fieldStyle}\n />\n <div style={hintStyle}>App-level token for Socket Mode</div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Default Working Directory</label>\n <input\n value={ch.default_working_dir}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n slack: { ...c.slack, default_working_dir: e.target.value },\n }))\n }\n placeholder=\"~/my-project\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Working directory for tasks created via the Slack bot.\n </div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Default DM User</label>\n <input\n value={ch.default_user}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n slack: { ...c.slack, default_user: e.target.value },\n }))\n }\n placeholder=\"U0123456789\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Slack user ID to DM when tasks have no origin thread (e.g. subtasks\n created via API). Find your ID in Slack profile → ⋯ → Copy member ID.\n </div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Default Notification Channel</label>\n <input\n value={ch.default_channel}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n slack: { ...c.slack, default_channel: e.target.value },\n }))\n }\n placeholder=\"#general or C0123456789\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Optional. Fallback channel if Default DM User is not set.\n </div>\n </div>\n\n <div\n style={{\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 6,\n padding: \"10px 12px\",\n fontSize: 11,\n fontFamily: \"monospace\",\n color: theme.textMuted,\n lineHeight: 1.8,\n }}\n >\n <div style={{ color: theme.textDim, marginBottom: 4 }}>Bot commands:</div>\n {[\n \"newtask <title> | <prompt>\",\n \"list\",\n \"status <id>\",\n \"cancel <id>\",\n \"help\",\n ].map((cmd) => (\n <div key={cmd}>\n <span style={{ color: theme.cyan }}>{cmd}</span>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n );\n })()}\n\n {/* ── Weixin ── */}\n {(() => {\n const ch = channels.weixin;\n const collapsed = collapsedChannels.weixin;\n const statusLabelMap = {\n idle: \"Idle\",\n waiting_for_scan: \"Waiting for scan\",\n scanned: \"Scanned on phone\",\n connected: \"Connected\",\n error: \"Error\",\n };\n const statusDot = ch.running\n ? { bg: theme.green, label: statusLabelMap[ch.login_status] || \"Connected\" }\n : ch.login_status === \"waiting_for_scan\" || ch.login_status === \"scanned\"\n ? { bg: theme.orange || \"#f59e0b\", label: statusLabelMap[ch.login_status] }\n : ch.login_status === \"error\"\n ? { bg: theme.red, label: \"Error\" }\n : ch.configured\n ? { bg: theme.yellow || \"#f59e0b\", label: \"Configured\" }\n : { bg: theme.textDim, label: \"Login required\" };\n return (\n <div\n style={{\n marginBottom: 16,\n borderRadius: 10,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n overflow: \"hidden\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n padding: \"12px 16px\",\n cursor: \"pointer\",\n userSelect: \"none\",\n }}\n onClick={() => setCollapsedChannels((c) => ({ ...c, weixin: !c.weixin }))}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 10 }}>\n <span\n style={{\n fontSize: 10,\n color: theme.textMuted,\n transition: \"transform 0.2s\",\n transform: collapsed ? \"rotate(-90deg)\" : \"rotate(0deg)\",\n display: \"inline-block\",\n }}\n >\n {\"▼\"}\n </span>\n <span\n style={{\n display: \"inline-flex\",\n width: 22,\n height: 22,\n alignItems: \"center\",\n justifyContent: \"center\",\n color: \"#07C160\",\n flexShrink: 0,\n }}\n >\n <svg\n viewBox=\"0 0 24 24\"\n width=\"22\"\n height=\"22\"\n aria-hidden=\"true\"\n fill=\"currentColor\"\n >\n <path d=\"M9.2 4.2c-4 0-7.2 2.6-7.2 5.9 0 1.9 1.1 3.6 2.9 4.7l-.9 2.5 2.9-1.5c.7.1 1.4.2 2.2.2 4 0 7.2-2.6 7.2-5.9S13.2 4.2 9.2 4.2Zm-2.7 4.8a.9.9 0 1 1 0-1.8.9.9 0 0 1 0 1.8Zm5.4 0a.9.9 0 1 1 0-1.8.9.9 0 0 1 0 1.8Z\" />\n <path\n d=\"M16.8 9.1c-3 0-5.5 2-5.5 4.5 0 2.5 2.4 4.5 5.5 4.5.6 0 1.2-.1 1.8-.2l2.4 1.2-.7-2c1.5-.8 2.5-2.1 2.5-3.6 0-2.5-2.4-4.4-5.5-4.4Zm-1.9 4a.7.7 0 1 1 0-1.4.7.7 0 0 1 0 1.4Zm3.8 0a.7.7 0 1 1 0-1.4.7.7 0 0 1 0 1.4Z\"\n opacity=\"0.88\"\n />\n </svg>\n </span>\n <span style={{ fontWeight: 700, fontSize: 14, color: theme.text }}>\n Wechat\n </span>\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 6, marginLeft: 8 }}>\n <span\n style={{\n width: 8,\n height: 8,\n borderRadius: \"50%\",\n background: statusDot.bg,\n display: \"inline-block\",\n boxShadow: ch.running ? `0 0 6px ${statusDot.bg}` : \"none\",\n }}\n />\n <span style={{ fontSize: 11, color: theme.textMuted }}>\n {statusDot.label}\n </span>\n </div>\n </div>\n <button\n onClick={(e) => {\n e.stopPropagation();\n setChannels((c) => ({\n ...c,\n weixin: { ...c.weixin, enabled: !c.weixin.enabled },\n }));\n }}\n style={{\n width: 44,\n height: 24,\n borderRadius: 12,\n border: \"none\",\n cursor: \"pointer\",\n background: ch.enabled ? theme.accent : theme.border,\n position: \"relative\",\n transition: \"background 0.2s\",\n flexShrink: 0,\n }}\n >\n <span\n style={{\n position: \"absolute\",\n top: 3,\n width: 18,\n height: 18,\n borderRadius: \"50%\",\n background: \"#fff\",\n transition: \"left 0.2s\",\n left: ch.enabled ? 23 : 3,\n }}\n />\n </button>\n </div>\n\n {!collapsed && (\n <div style={{ padding: \"0 16px 16px\" }}>\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Default Working Directory</label>\n <input\n value={ch.default_working_dir}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n weixin: { ...c.weixin, default_working_dir: e.target.value },\n }))\n }\n placeholder=\"~/my-project\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Working directory for tasks created from incoming Weixin messages.\n </div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Base URL</label>\n <input\n value={ch.base_url}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n weixin: { ...c.weixin, base_url: e.target.value },\n }))\n }\n placeholder=\"https://ilinkai.weixin.qq.com\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Gateway API base URL used for QR login, long-polling, and sendmessage.\n </div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Account ID</label>\n <input\n value={ch.account_id}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n weixin: { ...c.weixin, account_id: e.target.value },\n }))\n }\n placeholder=\"Optional fixed account id\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Optional. Leave empty to let the bridge adopt the account id returned by\n QR login.\n </div>\n </div>\n\n <div style={{ display: \"flex\", gap: 8, marginBottom: 12 }}>\n <button\n onClick={() => handleWeixinAction(\"reconnect\")}\n disabled={weixinActionBusy}\n style={{\n padding: \"9px 14px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: theme.surface,\n color: theme.text,\n cursor: weixinActionBusy ? \"not-allowed\" : \"pointer\",\n fontSize: 12,\n fontWeight: 600,\n opacity: weixinActionBusy ? 0.6 : 1,\n }}\n >\n Reconnect\n </button>\n <button\n onClick={() => handleWeixinAction(\"logout\")}\n disabled={weixinActionBusy}\n style={{\n padding: \"9px 14px\",\n borderRadius: 8,\n border: `1px solid ${theme.red}`,\n background: theme.redBg,\n color: theme.red,\n cursor: weixinActionBusy ? \"not-allowed\" : \"pointer\",\n fontSize: 12,\n fontWeight: 600,\n opacity: weixinActionBusy ? 0.6 : 1,\n }}\n >\n Logout\n </button>\n </div>\n\n {(ch.qr_code_url ||\n ch.login_status === \"waiting_for_scan\" ||\n ch.login_status === \"scanned\" ||\n ch.last_error) && (\n <div\n style={{\n marginBottom: 12,\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: theme.surface,\n padding: 12,\n }}\n >\n <div\n style={{\n fontSize: 12,\n fontWeight: 700,\n color: theme.text,\n marginBottom: 8,\n }}\n >\n Weixin Login Status\n </div>\n <div\n style={{\n fontSize: 11,\n color: theme.textMuted,\n marginBottom: ch.qr_code_url ? 10 : 0,\n }}\n >\n {statusLabelMap[ch.login_status] || \"Idle\"}\n {ch.user_id ? ` · ${ch.user_id}` : \"\"}\n </div>\n {ch.account_id && (\n <div style={{ fontSize: 11, color: theme.textMuted, marginBottom: 10 }}>\n Account ID: {ch.account_id}\n </div>\n )}\n {weixinQrSrc && (\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 8 }}>\n <img\n src={weixinQrSrc}\n alt=\"Weixin QR code\"\n style={{\n width: 220,\n height: 220,\n objectFit: \"contain\",\n borderRadius: 10,\n border: `1px solid ${theme.border}`,\n background: \"#fff\",\n }}\n />\n <div style={hintStyle}>\n Open Weixin on your phone and scan this QR code. The status updates\n automatically.\n </div>\n </div>\n )}\n {ch.last_error && (\n <div style={{ marginTop: 10, fontSize: 11, color: theme.red }}>\n {ch.last_error}\n </div>\n )}\n </div>\n )}\n\n <div\n style={{\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 6,\n padding: \"10px 12px\",\n fontSize: 11,\n fontFamily: \"monospace\",\n color: theme.textMuted,\n lineHeight: 1.8,\n }}\n >\n <div style={{ color: theme.textDim, marginBottom: 4 }}>Notes:</div>\n {[\n \"Enabling Weixin starts the local bridge process\",\n \"First launch without a saved session will trigger QR login\",\n \"Reply to a result message to resume the same task session\",\n ].map((note) => (\n <div key={note}>\n <span style={{ color: theme.cyan }}>{note}</span>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n );\n })()}\n\n {channelsMsg && (\n <div\n style={{\n padding: \"8px 12px\",\n borderRadius: 8,\n marginBottom: 16,\n fontSize: 12,\n background: channelsMsg.ok ? theme.greenBg : theme.redBg,\n color: channelsMsg.ok ? theme.green : theme.red,\n border: `1px solid ${channelsMsg.ok ? theme.green : theme.red}`,\n }}\n >\n {channelsMsg.text}\n </div>\n )}\n\n <div style={{ display: \"flex\", gap: 10, justifyContent: \"flex-end\" }}>\n <button\n onClick={onClose}\n style={{\n padding: \"10px 20px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: \"transparent\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n }}\n >\n Close\n </button>\n <button\n onClick={handleSaveChannels}\n disabled={channelsSaving}\n style={{\n padding: \"10px 24px\",\n borderRadius: 8,\n border: \"none\",\n background: channelsSaving ? theme.border : theme.accent,\n color: channelsSaving ? theme.textMuted : \"#fff\",\n cursor: channelsSaving ? \"not-allowed\" : \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n boxShadow: channelsSaving ? \"none\" : `0 0 20px ${theme.accentGlow}`,\n }}\n >\n {channelsSaving ? \"Saving…\" : \"Save\"}\n </button>\n </div>\n </>\n )}\n\n {/* ── Feishu tab ── */}\n {tab === \"feishu\" && (\n <>\n {/* Enable toggle */}\n <div\n style={{\n marginBottom: 20,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n }}\n >\n <div>\n <div style={{ fontSize: 13, fontWeight: 600, color: theme.text }}>\n Enable Feishu Bot\n </div>\n <div style={{ fontSize: 11, color: theme.textMuted, marginTop: 2 }}>\n WebSocket long-connection, no public IP required\n </div>\n </div>\n <button\n onClick={() =>\n setFeishu((f) => ({\n ...f,\n feishu_enabled: f.feishu_enabled === \"true\" ? \"false\" : \"true\",\n }))\n }\n style={{\n width: 44,\n height: 24,\n borderRadius: 12,\n border: \"none\",\n cursor: \"pointer\",\n background: feishu.feishu_enabled === \"true\" ? theme.accent : theme.border,\n position: \"relative\",\n transition: \"background 0.2s\",\n flexShrink: 0,\n }}\n >\n <span\n style={{\n position: \"absolute\",\n top: 3,\n width: 18,\n height: 18,\n borderRadius: \"50%\",\n background: \"#fff\",\n transition: \"left 0.2s\",\n left: feishu.feishu_enabled === \"true\" ? 23 : 3,\n }}\n />\n </button>\n </div>\n\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 16, marginBottom: 20 }}>\n <div>\n <label style={labelStyle}>App ID</label>\n <input\n value={feishu.feishu_app_id}\n onChange={(e) => setFeishu((f) => ({ ...f, feishu_app_id: e.target.value }))}\n placeholder=\"cli_xxxxxxxxxxxxxxxx\"\n style={fieldStyle}\n />\n </div>\n <div>\n <label style={labelStyle}>App Secret</label>\n <input\n type=\"password\"\n value={feishu.feishu_app_secret}\n onChange={(e) => setFeishu((f) => ({ ...f, feishu_app_secret: e.target.value }))}\n placeholder=\"••••••••••••••••\"\n style={fieldStyle}\n />\n </div>\n <div>\n <label style={labelStyle}>Default Chat ID</label>\n <input\n value={feishu.feishu_default_chat_id}\n onChange={(e) =>\n setFeishu((f) => ({ ...f, feishu_default_chat_id: e.target.value }))\n }\n placeholder=\"oc_xxxxxxxx (group) or ou_xxxxxxxx (DM)\"\n style={fieldStyle}\n />\n <div style={hintStyle}>Task completion notifications will be sent here.</div>\n </div>\n <div>\n <label style={labelStyle}>Default Working Directory</label>\n <input\n value={feishu.feishu_default_working_dir}\n onChange={(e) =>\n setFeishu((f) => ({ ...f, feishu_default_working_dir: e.target.value }))\n }\n placeholder=\"~/my-project\"\n style={fieldStyle}\n />\n <div style={hintStyle}>Working directory for tasks created via the bot.</div>\n </div>\n </div>\n\n {/* Bot commands cheatsheet */}\n <div\n style={{\n background: theme.bg,\n border: `1px solid ${theme.border}`,\n borderRadius: 8,\n padding: \"12px 14px\",\n marginBottom: 20,\n fontSize: 11,\n fontFamily: \"monospace\",\n color: theme.textMuted,\n lineHeight: 1.8,\n }}\n >\n <div style={{ color: theme.textDim, marginBottom: 6, fontFamily: \"inherit\" }}>\n Bot commands:\n </div>\n <div>\n <span style={{ color: theme.cyan }}><any text></span> — create a new task\n </div>\n <div>\n <span style={{ color: theme.cyan }}>/resume <id> <msg></span> — resume a\n task session\n </div>\n <div>\n <span style={{ color: theme.cyan }}>/status <id></span> — query task status\n </div>\n </div>\n\n {feishuMsg && (\n <div\n style={{\n padding: \"8px 12px\",\n borderRadius: 8,\n marginBottom: 16,\n fontSize: 12,\n background: feishuMsg.ok ? theme.greenBg : theme.redBg,\n color: feishuMsg.ok ? theme.green : theme.red,\n border: `1px solid ${feishuMsg.ok ? theme.green : theme.red}`,\n }}\n >\n {feishuMsg.text}\n </div>\n )}\n\n <div style={{ display: \"flex\", gap: 10, justifyContent: \"flex-end\" }}>\n <button\n onClick={onClose}\n style={{\n padding: \"10px 20px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: \"transparent\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n }}\n >\n Close\n </button>\n <button\n onClick={handleSaveFeishu}\n disabled={feishuSaving}\n style={{\n padding: \"10px 24px\",\n borderRadius: 8,\n border: \"none\",\n background: feishuSaving ? theme.border : theme.accent,\n color: feishuSaving ? theme.textMuted : \"#fff\",\n cursor: feishuSaving ? \"not-allowed\" : \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n boxShadow: feishuSaving ? \"none\" : `0 0 20px ${theme.accentGlow}`,\n }}\n >\n {feishuSaving ? \"Saving…\" : \"Save & Apply\"}\n </button>\n </div>\n </>\n )}\n </div>\n </div>\n );\n}\n\n// ─── App ───\n\nfunction parseSkillFrontmatter(body) {\n const m = (body || \"\").match(/^---\\s*\\n([\\s\\S]*?)\\n---/);\n if (!m) return { name: \"\", description: \"\" };\n const out = { name: \"\", description: \"\" };\n for (const line of m[1].split(\"\\n\")) {\n const i = line.indexOf(\":\");\n if (i === -1) continue;\n const k = line.slice(0, i).trim().toLowerCase();\n const v = line.slice(i + 1).trim();\n if (k === \"name\" && !out.name) out.name = v;\n if (k === \"description\" && !out.description) out.description = v;\n }\n return out;\n}\n\nfunction SkillKindBadge({ kind }) {\n const isPitfall = kind === \"pitfall\";\n return (\n <span\n style={{\n fontSize: 10,\n fontWeight: 700,\n padding: \"2px 7px\",\n borderRadius: 6,\n letterSpacing: 0.4,\n background: isPitfall ? \"rgba(239,68,68,0.15)\" : \"rgba(34,197,94,0.15)\",\n color: isPitfall ? theme.red : theme.green,\n }}\n >\n {isPitfall ? \"PITFALL\" : \"RECIPE\"}\n </span>\n );\n}\n\nfunction SkillPatternCard({ p, tasks, onDraft, onApprove, onDismiss }) {\n let taskIds = [];\n try {\n taskIds = JSON.parse(p.contributing_task_ids || \"[]\");\n } catch {\n /* ignore */\n }\n const taskCount = taskIds.length;\n const ready = p.recurrence_count >= 3 && taskCount >= 2;\n const draftStatus = p.draft_status;\n const [expanded, setExpanded] = useState(false);\n const [body, setBody] = useState(p.draft_body || \"\");\n // The full SKILL.md is the single source of truth (name + description live in\n // its frontmatter). Sync the buffer when a fresh draft arrives.\n useEffect(() => {\n if (draftStatus === \"ready\") setBody(p.draft_body || \"\");\n }, [draftStatus, p.draft_body]);\n\n const borderColor =\n p.status === \"promoted\" ? theme.green : p.status === \"candidate\" ? theme.accent : theme.border;\n const muted = p.status === \"dismissed\";\n\n const btn = (bg, color) => ({\n padding: \"6px 14px\",\n borderRadius: 7,\n border: bg === \"transparent\" ? `1px solid ${theme.border}` : \"none\",\n background: bg,\n color,\n cursor: \"pointer\",\n fontSize: 11,\n fontWeight: 700,\n });\n\n return (\n <div\n style={{\n background: theme.surface,\n border: `1px solid ${borderColor}`,\n borderRadius: 12,\n padding: 16,\n opacity: muted ? 0.5 : 1,\n }}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8, marginBottom: 8 }}>\n <SkillKindBadge kind={p.kind} />\n <span style={{ fontFamily: \"monospace\", fontSize: 12, color: theme.text, fontWeight: 700 }}>\n {p.pattern_key}\n </span>\n </div>\n <div style={{ color: theme.textMuted, fontSize: 13, marginBottom: 10 }}>\n {p.summary || \"—\"}\n </div>\n <div\n style={{\n display: \"flex\",\n gap: 12,\n fontSize: 11,\n color: theme.textDim,\n marginBottom: 10,\n alignItems: \"center\",\n }}\n >\n <span>复发 {p.recurrence_count}×</span>\n <span>{taskCount} 个任务</span>\n <span>{p.status}</span>\n {ready && p.status !== \"promoted\" && (\n <span style={{ color: theme.accent, fontWeight: 700 }}>✓ 达标</span>\n )}\n <button\n onClick={() => setExpanded((v) => !v)}\n style={{\n marginLeft: \"auto\",\n background: \"transparent\",\n border: \"none\",\n color: theme.accent,\n cursor: \"pointer\",\n fontSize: 11,\n fontWeight: 700,\n }}\n >\n {expanded ? \"收起 ▲\" : \"详情 ▼\"}\n </button>\n </div>\n\n {expanded && (\n <div\n style={{\n background: theme.bg,\n border: `1px solid ${theme.border}`,\n borderRadius: 8,\n padding: 10,\n marginBottom: 10,\n fontSize: 11,\n color: theme.textMuted,\n }}\n >\n <div style={{ marginBottom: 6 }}>\n <span style={{ color: theme.textDim }}>首次 </span>\n {(p.first_seen || \"\").replace(\"T\", \" \").slice(0, 19) || \"—\"}\n <span style={{ color: theme.textDim }}> 最近 </span>\n {(p.last_seen || \"\").replace(\"T\", \" \").slice(0, 19) || \"—\"}\n </div>\n <div style={{ color: theme.textDim, marginBottom: 4 }}>贡献的任务({taskCount}):</div>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 3 }}>\n {taskIds.length === 0 && <span style={{ color: theme.textDim }}>—</span>}\n {taskIds.map((tid) => {\n const t = (tasks || []).find((x) => x.id === tid);\n return (\n <span key={tid} style={{ fontFamily: \"monospace\" }}>\n #{tid} {t ? t.title : <span style={{ color: theme.textDim }}>(已删除)</span>}\n </span>\n );\n })}\n </div>\n </div>\n )}\n\n {draftStatus === \"ready\" && p.draft_worthy !== null && p.draft_worthy !== undefined && (\n <div\n style={{\n fontSize: 11,\n padding: \"7px 10px\",\n borderRadius: 7,\n marginBottom: 8,\n background: p.draft_worthy ? \"rgba(34,197,94,0.12)\" : \"rgba(245,158,11,0.14)\",\n color: p.draft_worthy ? theme.green : \"#f59e0b\",\n border: `1px solid ${p.draft_worthy ? \"rgba(34,197,94,0.3)\" : \"rgba(245,158,11,0.35)\"}`,\n }}\n >\n {p.draft_worthy ? \"✓ agent 建议沉淀\" : \"⚠ agent 认为价值有限(可仍批准或驳回)\"}\n {p.draft_worthiness_reason ? `:${p.draft_worthiness_reason}` : \"\"}\n </div>\n )}\n\n {p.status === \"promoted\" && (\n <div style={{ fontSize: 12, color: theme.green, fontWeight: 700 }}>✓ 已沉淀为 Skill</div>\n )}\n\n {(p.status === \"candidate\" || p.status === \"tracking\") &&\n draftStatus !== \"ready\" &&\n draftStatus !== \"drafting\" && (\n <div style={{ display: \"flex\", gap: 8, alignItems: \"center\", flexWrap: \"wrap\" }}>\n <button onClick={() => onDraft(p.id)} style={btn(theme.accent, \"#fff\")}>\n {draftStatus === \"error\" ? \"重试蒸馏\" : \"蒸馏成 Skill\"}\n </button>\n <button onClick={() => onDismiss(p.id)} style={btn(\"transparent\", theme.textMuted)}>\n 驳回\n </button>\n {p.status === \"tracking\" && (\n <span style={{ color: theme.textDim, fontSize: 11 }}>\n 未达自动阈值,可手动蒸馏(agent 会判断是否值得)\n </span>\n )}\n {draftStatus === \"error\" && (\n <span style={{ color: theme.red, fontSize: 11 }}>蒸馏失败:{p.draft_error}</span>\n )}\n </div>\n )}\n\n {draftStatus === \"drafting\" && (\n <div style={{ fontSize: 12, color: theme.textMuted }}>蒸馏中…</div>\n )}\n\n {draftStatus === \"ready\" &&\n (() => {\n const fm = parseSkillFrontmatter(body);\n return (\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 10 }}>\n {/* preview header */}\n <div style={{ display: \"flex\", alignItems: \"baseline\", gap: 8, flexWrap: \"wrap\" }}>\n <span\n style={{\n fontFamily: \"ui-monospace, Menlo, monospace\",\n fontSize: 12,\n fontWeight: 800,\n color: theme.accent,\n background: theme.accentGlow,\n padding: \"3px 9px\",\n borderRadius: 6,\n }}\n >\n {fm.name || \"(无 name)\"}\n </span>\n <span style={{ fontSize: 11, color: theme.textDim }}>\n → ~/.claude/skills/{fm.name || \"…\"}/SKILL.md\n </span>\n </div>\n {fm.description && (\n <div style={{ fontSize: 12, color: theme.textMuted, lineHeight: 1.55 }}>\n {fm.description}\n </div>\n )}\n {/* editor */}\n <div>\n <div\n style={{\n fontSize: 10.5,\n color: theme.textDim,\n marginBottom: 5,\n fontWeight: 600,\n letterSpacing: 0.3,\n }}\n >\n SKILL.md · 可编辑(frontmatter 决定名称与触发描述)\n </div>\n <textarea\n value={body}\n onChange={(e) => setBody(e.target.value)}\n rows={16}\n spellCheck={false}\n style={{\n width: \"100%\",\n boxSizing: \"border-box\",\n padding: \"12px 14px\",\n borderRadius: 10,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n color: theme.text,\n fontSize: 12,\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, monospace\",\n lineHeight: 1.65,\n resize: \"vertical\",\n outline: \"none\",\n }}\n />\n </div>\n <div style={{ display: \"flex\", gap: 8 }}>\n <button\n onClick={() => onApprove(p.id, { body })}\n style={{ ...btn(theme.green, \"#fff\"), padding: \"8px 18px\", fontSize: 12 }}\n >\n ✓ 批准并写入\n </button>\n <button\n onClick={() => onDismiss(p.id)}\n style={{\n ...btn(\"transparent\", theme.textMuted),\n padding: \"8px 18px\",\n fontSize: 12,\n }}\n >\n 驳回\n </button>\n </div>\n </div>\n );\n })()}\n </div>\n );\n}\n\nfunction SkillRegistryCard({ s, tasks, onToggle, onDelete }) {\n const [expanded, setExpanded] = useState(false);\n const [content, setContent] = useState<any>(null);\n const [loading, setLoading] = useState(false);\n\n let sourceTaskIds = [];\n try {\n sourceTaskIds = JSON.parse(s.source_task_ids || \"[]\");\n } catch {\n /* ignore */\n }\n\n const toggleDetail = async () => {\n const next = !expanded;\n setExpanded(next);\n if (next && content === null) {\n setLoading(true);\n try {\n const res = await fetch(`${API}/skills/${s.id}/content`);\n const d = await res.json();\n setContent(d.content ?? \"\");\n } catch (e) {\n setContent(`(加载失败:${e.message})`);\n } finally {\n setLoading(false);\n }\n }\n };\n\n return (\n <div\n style={{\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 12,\n padding: 14,\n opacity: s.enabled ? 1 : 0.55,\n }}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8, marginBottom: 6 }}>\n <SkillKindBadge kind={s.kind} />\n <span style={{ fontFamily: \"monospace\", fontSize: 12, color: theme.text, fontWeight: 700 }}>\n {s.name}\n </span>\n <button\n onClick={toggleDetail}\n style={{\n marginLeft: \"auto\",\n background: \"transparent\",\n border: \"none\",\n color: theme.accent,\n cursor: \"pointer\",\n fontSize: 11,\n fontWeight: 700,\n }}\n >\n {expanded ? \"收起 ▲\" : \"查看 SKILL.md ▼\"}\n </button>\n </div>\n <div style={{ color: theme.textMuted, fontSize: 12, marginBottom: 10, lineHeight: 1.5 }}>\n {s.description || \"—\"}\n </div>\n\n {expanded && (\n <div style={{ marginBottom: 10 }}>\n <div style={{ fontSize: 11, color: theme.textDim, marginBottom: 6 }}>\n <span style={{ fontFamily: \"monospace\" }}>{s.path}</span>\n {s.source_pattern_key && <span> 来源 pattern:{s.source_pattern_key}</span>}\n {sourceTaskIds.length > 0 && (\n <span>\n  来源任务:\n {sourceTaskIds\n .map((tid) => {\n const t = (tasks || []).find((x) => x.id === tid);\n return `#${tid}${t ? \"(\" + t.title + \")\" : \"\"}`;\n })\n .join(\"、\")}\n </span>\n )}\n </div>\n <pre\n style={{\n margin: 0,\n padding: \"12px 14px\",\n borderRadius: 10,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n color: theme.text,\n fontSize: 12,\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, monospace\",\n lineHeight: 1.6,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n maxHeight: 360,\n overflow: \"auto\",\n }}\n >\n {loading ? \"加载中…\" : content}\n </pre>\n </div>\n )}\n\n <div style={{ display: \"flex\", gap: 8, alignItems: \"center\" }}>\n <label\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n fontSize: 11,\n color: theme.textDim,\n cursor: \"pointer\",\n }}\n >\n <input\n type=\"checkbox\"\n checked={!!s.enabled}\n onChange={(e) => onToggle(s.id, e.target.checked)}\n style={{ cursor: \"pointer\" }}\n />\n {s.enabled ? \"已启用(claude/codex 加载中)\" : \"已停用(symlink 已摘除)\"}\n </label>\n <button\n onClick={() => onDelete(s.id)}\n style={{\n marginLeft: \"auto\",\n padding: \"4px 10px\",\n borderRadius: 6,\n border: `1px solid ${theme.border}`,\n background: \"transparent\",\n color: theme.red,\n cursor: \"pointer\",\n fontSize: 11,\n fontWeight: 700,\n }}\n >\n 删除\n </button>\n </div>\n </div>\n );\n}\n\nfunction SkillsView({\n skillData,\n skills,\n tasks,\n onSweep,\n onDraft,\n onApprove,\n onDismiss,\n onToggleSkill,\n onDeleteSkill,\n}) {\n // Only recurrence >= 2 is worth surfacing; single-occurrence rows are noise.\n // (The backend still tracks them so the count can accumulate across sweeps.)\n const patterns = (skillData.patterns || []).filter((p) => p.recurrence_count >= 2);\n const sweep = skillData.sweep || {};\n const running = sweep.running;\n const last = sweep.last;\n let lastNote = null;\n if (last) {\n lastNote = last.error\n ? `上次扫描失败:${last.error}`\n : last.scanned === 0\n ? `上次扫描:没有已完成的任务可分析(agent ${last.agent})`\n : `上次扫描:分析 ${last.scanned} 个任务、新增 ${last.new ?? 0} 次复发、候选 ${last.candidates ?? 0}(agent ${last.agent})`;\n }\n const [showRegistry, setShowRegistry] = useState(true);\n const [showPatterns, setShowPatterns] = useState(true);\n\n const sectionHeader = (label, count, open, toggle) => (\n <button\n onClick={toggle}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n width: \"100%\",\n background: \"transparent\",\n border: \"none\",\n cursor: \"pointer\",\n color: theme.text,\n fontSize: 13,\n fontWeight: 700,\n padding: 0,\n marginBottom: 10,\n }}\n >\n <span style={{ color: theme.textDim, fontSize: 11 }}>{open ? \"▼\" : \"▶\"}</span>\n {label}\n <span style={{ color: theme.textDim, fontWeight: 600 }}>({count})</span>\n </button>\n );\n\n return (\n <div style={{ padding: 28, minHeight: \"calc(100vh - 72px)\" }}>\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n marginBottom: 16,\n gap: 12,\n }}\n >\n <div style={{ color: theme.textMuted, fontSize: 12 }}>\n 跨任务复发模式账本 · 复发 ≥2 即可手动蒸馏为 Skill(达 ≥3 且跨 ≥2 任务自动标记候选)\n {lastNote && <span style={{ marginLeft: 10, color: theme.textDim }}>· {lastNote}</span>}\n </div>\n <button\n onClick={onSweep}\n disabled={running}\n style={{\n padding: \"8px 18px\",\n borderRadius: 8,\n border: \"none\",\n background: running ? theme.border : theme.accent,\n color: \"#fff\",\n cursor: running ? \"default\" : \"pointer\",\n fontSize: 12,\n fontWeight: 700,\n letterSpacing: 0.3,\n whiteSpace: \"nowrap\",\n boxShadow: running ? \"none\" : `0 0 24px ${theme.accentGlow}`,\n }}\n >\n {running ? \"扫描中…\" : \"扫一遍\"}\n </button>\n </div>\n\n {(skills || []).length > 0 && (\n <div style={{ marginBottom: 26 }}>\n {sectionHeader(\"已沉淀 Skills\", skills.length, showRegistry, () =>\n setShowRegistry((v) => !v),\n )}\n {showRegistry && (\n <div\n style={{\n display: \"grid\",\n gridTemplateColumns: \"repeat(auto-fit, minmax(360px, 1fr))\",\n gap: 12,\n }}\n >\n {skills.map((s) => (\n <SkillRegistryCard\n key={s.id}\n s={s}\n tasks={tasks}\n onToggle={onToggleSkill}\n onDelete={onDeleteSkill}\n />\n ))}\n </div>\n )}\n </div>\n )}\n\n {sectionHeader(\"检测到的模式\", patterns.length, showPatterns, () =>\n setShowPatterns((v) => !v),\n )}\n {showPatterns &&\n (patterns.length === 0 ? (\n <div\n style={{\n border: `1px dashed ${theme.border}`,\n borderRadius: 12,\n padding: 32,\n textAlign: \"center\",\n color: theme.textDim,\n fontSize: 12,\n }}\n >\n 还没有复发 ≥2 的模式 — 点「扫一遍」让 agent 分析最近完成的任务(复发 1 次的暂不展示)\n </div>\n ) : (\n <div\n style={{\n display: \"grid\",\n gridTemplateColumns: \"repeat(auto-fit, minmax(360px, 1fr))\",\n gap: 14,\n }}\n >\n {patterns.map((p) => (\n <SkillPatternCard\n key={p.id}\n p={p}\n tasks={tasks}\n onDraft={onDraft}\n onApprove={onApprove}\n onDismiss={onDismiss}\n />\n ))}\n </div>\n ))}\n </div>\n );\n}\n\nexport default function App() {\n const [tasks, setTasks] = useState<any[]>([]);\n const [heartbeats, setHeartbeats] = useState<any[]>([]);\n const [heartbeatTicks, setHeartbeatTicks] = useState<any[]>([]);\n const [skillData, setSkillData] = useState({\n patterns: [],\n sweep: { running: false, last: null },\n });\n const [skills, setSkills] = useState<any[]>([]);\n const [activeView, setActiveView] = useState(\"tasks\");\n const [showNew, setShowNew] = useState(false);\n const [showNewHeartbeat, setShowNewHeartbeat] = useState(false);\n const [showSettings, setShowSettings] = useState(false);\n const [detail, setDetail] = useState<any>(null);\n const [heartbeatDetail, setHeartbeatDetail] = useState<any>(null);\n const [connected, setConnected] = useState(false);\n const [filter, setFilter] = useState(\"\");\n const [taskTimeout, setTaskTimeout] = useState(DEFAULT_TIMEOUT_SECONDS);\n const [defaultAgent, setDefaultAgent] = useState(DEFAULT_AGENT);\n const [feishuSettings, setFeishuSettings] = useState<any>({});\n const [channelsStatus, setChannelsStatus] = useState<any>({});\n const [backendReady, setBackendReady] = useState(false);\n const [backendError, setBackendError] = useState<any>(null);\n const [apiError, setApiError] = useState<any>(null);\n const [editingTask, setEditingTask] = useState<any>(null);\n const [forkingTask, setForkingTask] = useState<any>(null);\n const [editingHeartbeat, setEditingHeartbeat] = useState<any>(null);\n\n // ─── Color mode ───\n const [colorMode, setColorMode] = useState(() => localStorage.getItem(\"colorMode\") || \"system\");\n const [systemDark, setSystemDark] = useState(\n () => window.matchMedia(\"(prefers-color-scheme: dark)\").matches,\n );\n const resolvedMode = colorMode === \"system\" ? (systemDark ? \"dark\" : \"light\") : colorMode;\n theme = THEMES[resolvedMode];\n\n useEffect(() => {\n localStorage.setItem(\"colorMode\", colorMode);\n document.body.style.background = THEMES[resolvedMode].bg;\n }, [colorMode, resolvedMode]);\n\n useEffect(() => {\n const mq = window.matchMedia(\"(prefers-color-scheme: dark)\");\n const handler = (e) => setSystemDark(e.matches);\n mq.addEventListener(\"change\", handler);\n return () => mq.removeEventListener(\"change\", handler);\n }, []);\n\n useEffect(() => {\n let cancelled = false;\n const deadline = Date.now() + 20000;\n const probe = async () => {\n try {\n const res = await fetch(`${API}/health`, { signal: AbortSignal.timeout(800) });\n if (res.ok) {\n if (!cancelled) setBackendReady(true);\n return;\n }\n } catch {\n /* not ready yet */\n }\n if (cancelled) return;\n if (Date.now() >= deadline) {\n setBackendError(\"Backend did not start within 20 seconds.\");\n return;\n }\n setTimeout(probe, 300);\n };\n probe();\n return () => {\n cancelled = true;\n };\n }, []);\n\n const poll = useCallback(async () => {\n try {\n const [taskData, heartbeatData, skillRes, skillsRes] = await Promise.all([\n fetchTasks(),\n fetchHeartbeats(),\n fetchSkillPatterns(),\n fetchSkills(),\n ]);\n setTasks(taskData);\n setHeartbeats(heartbeatData);\n setSkillData(skillRes);\n setSkills(skillsRes.skills || []);\n setConnected(true);\n setApiError(null);\n } catch (err) {\n setConnected(false);\n setApiError(`Failed to fetch tasks: ${err.message}`);\n }\n }, []);\n\n useEffect(() => {\n if (!backendReady) return;\n poll();\n const interval = setInterval(poll, 3000);\n return () => clearInterval(interval);\n }, [poll, backendReady]);\n\n useEffect(() => {\n if (!backendReady) return;\n fetchSettings().then((s) => {\n if (s.timeout) setTaskTimeout(s.timeout);\n if (s.default_agent) setDefaultAgent(s.default_agent);\n });\n fetchFeishuSettings().then((s) => setFeishuSettings(s));\n fetchChannelsStatus().then((s) => setChannelsStatus(s));\n }, [backendReady]);\n\n const handleAction = async (action, id) => {\n try {\n if (action === \"cancel\") await cancelTask(id);\n else if (action === \"retry\") await retryTask(id);\n else if (action === \"delete\") {\n await deleteTask(id);\n if (detail?.id === id) setDetail(null);\n } else if (action === \"edit\") {\n const task = tasks.find((t) => t.id === id);\n if (task) setEditingTask(task);\n return;\n } else if (action === \"fork\") {\n const task = tasks.find((t) => t.id === id);\n if (task) setForkingTask(task);\n return;\n }\n poll();\n } catch (e) {\n setApiError(`${action} failed: ${e.message}`);\n }\n };\n\n const handleHeartbeatAction = async (action, id) => {\n try {\n if (action === \"run\") {\n await runHeartbeatNow(id);\n } else if (action === \"pause\") {\n await pauseHeartbeat(id);\n } else if (action === \"resume\") {\n await resumeHeartbeatApi(id);\n } else if (action === \"delete\") {\n await deleteHeartbeat(id);\n if (heartbeatDetail?.id === id) {\n setHeartbeatDetail(null);\n setHeartbeatTicks([]);\n }\n } else if (action === \"edit\") {\n const heartbeat = heartbeats.find((h) => h.id === id);\n if (heartbeat) setEditingHeartbeat(heartbeat);\n return;\n }\n poll();\n if (heartbeatDetail?.id === id && action !== \"delete\") {\n const [updatedHeartbeat, ticks] = await Promise.all([\n fetch(`${API}/heartbeats/${id}`).then((r) => r.json()),\n fetchHeartbeatTicks(id),\n ]);\n setHeartbeatDetail(updatedHeartbeat);\n setHeartbeatTicks(ticks);\n }\n } catch (e) {\n setApiError(`Heartbeat ${action} failed: ${e.message}`);\n }\n };\n\n const handleSweep = async () => {\n try {\n await triggerSkillSweep();\n // Optimistically reflect the running state; poll picks up the real status.\n setSkillData((prev) => ({ ...prev, sweep: { ...prev.sweep, running: true } }));\n setTimeout(poll, 1500);\n } catch (e) {\n setApiError(`Sweep failed: ${e.message}`);\n }\n };\n\n const handleSkillDraft = async (id) => {\n try {\n await triggerSkillDraft(id);\n setTimeout(poll, 1500);\n } catch (e) {\n setApiError(`Distill failed: ${e.message}`);\n }\n };\n\n const handleSkillApprove = async (id, data) => {\n try {\n await approveSkill(id, data);\n poll();\n } catch (e) {\n setApiError(`Approve failed: ${e.message}`);\n }\n };\n\n const handleSkillDismiss = async (id) => {\n try {\n await dismissSkillPattern(id);\n poll();\n } catch (e) {\n setApiError(`Dismiss failed: ${e.message}`);\n }\n };\n\n const handleSkillToggle = async (id, enabled) => {\n try {\n await setSkillEnabledApi(id, enabled);\n poll();\n } catch (e) {\n setApiError(`Toggle skill failed: ${e.message}`);\n }\n };\n\n const handleSkillDelete = async (id) => {\n try {\n await deleteSkillApi(id);\n poll();\n } catch (e) {\n setApiError(`Delete skill failed: ${e.message}`);\n }\n };\n\n const handleCreate = async (data) => {\n try {\n await createTask(data);\n setShowNew(false);\n poll();\n } catch (e) {\n setApiError(`Create task failed: ${e.message}`);\n }\n };\n\n const handleEdit = async (data) => {\n try {\n await updateTask(editingTask.id, data);\n setEditingTask(null);\n poll();\n } catch (e) {\n setApiError(`Edit task failed: ${e.message}`);\n }\n };\n\n const handleFork = async (data) => {\n try {\n await createTask(data);\n setForkingTask(null);\n poll();\n } catch (e) {\n setApiError(`Fork task failed: ${e.message}`);\n }\n };\n\n const handleRespond = async (id, answer) => {\n try {\n await respondToTask(id, answer);\n poll();\n } catch (e) {\n setApiError(`Respond failed: ${e.message}`);\n }\n };\n\n const handleResume = () => {\n poll();\n };\n\n const handleCreateHeartbeat = async (data) => {\n try {\n await createHeartbeat(data);\n setShowNewHeartbeat(false);\n poll();\n } catch (e) {\n setApiError(`Create heartbeat failed: ${e.message}`);\n }\n };\n\n const handleEditHeartbeat = async (data) => {\n try {\n await updateHeartbeat(editingHeartbeat.id, data);\n setEditingHeartbeat(null);\n poll();\n } catch (e) {\n setApiError(`Edit heartbeat failed: ${e.message}`);\n }\n };\n\n const openHeartbeatDetail = async (heartbeat) => {\n setHeartbeatDetail(heartbeat);\n try {\n const ticks = await fetchHeartbeatTicks(heartbeat.id);\n setHeartbeatTicks(ticks);\n } catch (e) {\n setApiError(`Failed to fetch heartbeat ticks: ${e.message}`);\n setHeartbeatTicks([]);\n }\n };\n\n const filtered = filter\n ? tasks.filter(\n (t) =>\n t.title.toLowerCase().includes(filter.toLowerCase()) ||\n t.tags?.toLowerCase().includes(filter.toLowerCase()),\n )\n : tasks;\n\n const runningCount = tasks.filter((t) => t.status === \"running\").length;\n const scheduledCount = tasks.filter((t) => t.status === \"scheduled\").length;\n const enabledHeartbeatCount = heartbeats.filter((h) => h.enabled).length;\n\n if (backendError) {\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"100vh\",\n background: theme.bg,\n color: theme.red,\n gap: 12,\n fontFamily: \"inherit\",\n }}\n >\n <div style={{ fontSize: 32 }}>✕</div>\n <div style={{ fontSize: 15, fontWeight: 600 }}>Backend failed to start</div>\n <div style={{ fontSize: 12, color: theme.textMuted, maxWidth: 400, textAlign: \"center\" }}>\n {backendError}\n </div>\n </div>\n );\n }\n\n if (!backendReady) {\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"100vh\",\n background: theme.bg,\n color: theme.textMuted,\n gap: 16,\n fontFamily: \"inherit\",\n }}\n >\n <div\n style={{\n width: 32,\n height: 32,\n borderRadius: \"50%\",\n border: `3px solid ${theme.border}`,\n borderTopColor: theme.accent,\n animation: \"spin 0.8s linear infinite\",\n }}\n />\n <div style={{ fontSize: 13 }}>Starting backend…</div>\n <style>{`@keyframes spin { to { transform: rotate(360deg); } }`}</style>\n </div>\n );\n }\n\n return (\n <div\n style={{\n minHeight: \"100vh\",\n background: theme.bg,\n color: theme.text,\n fontFamily: \"-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n }}\n >\n <style>{`@keyframes pulse { 0%,100%{opacity:1} 50%{opacity:0.3} }`}</style>\n {/* API error toast */}\n {apiError && (\n <div\n style={{\n position: \"fixed\",\n bottom: 24,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n zIndex: 9999,\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n background: theme.surface,\n border: `1px solid ${theme.red}`,\n borderRadius: 8,\n padding: \"10px 16px\",\n boxShadow: `0 4px 24px rgba(0,0,0,0.5)`,\n color: theme.red,\n fontSize: 12,\n fontWeight: 500,\n maxWidth: 480,\n }}\n >\n <span style={{ flexShrink: 0 }}>✕</span>\n <span style={{ flex: 1 }}>{apiError}</span>\n <button\n onClick={() => setApiError(null)}\n style={{\n background: \"none\",\n border: \"none\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 14,\n lineHeight: 1,\n padding: \"0 0 0 8px\",\n flexShrink: 0,\n }}\n title=\"Dismiss\"\n >\n ×\n </button>\n </div>\n )}\n {/* Header */}\n <div\n style={{\n borderBottom: `1px solid ${theme.border}`,\n padding: \"16px 28px\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n backdropFilter: \"blur(10px)\",\n position: \"sticky\",\n top: 0,\n zIndex: 100,\n background: `${theme.bg}ee`,\n }}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 14 }}>\n <div\n style={{\n width: 32,\n height: 32,\n borderRadius: 8,\n background: `linear-gradient(135deg, ${theme.accent}, #a855f7)`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontSize: 16,\n fontWeight: 800,\n color: \"#fff\",\n }}\n >\n ⌘\n </div>\n <div>\n <div\n style={{\n fontSize: 15,\n fontWeight: 700,\n fontFamily: \"'JetBrains Mono', monospace\",\n letterSpacing: -0.3,\n }}\n >\n AgentForge\n </div>\n <div style={{ fontSize: 11, color: theme.textDim, marginTop: 1 }}>\n {connected ? (\n <span style={{ color: theme.green }}>● Connected</span>\n ) : (\n <span style={{ color: theme.red }}>● Disconnected — run `python taskboard.py`</span>\n )}\n {connected &&\n ` · ${runningCount} running · ${scheduledCount} scheduled · ${enabledHeartbeatCount} heartbeats`}\n </div>\n </div>\n </div>\n\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 10 }}>\n <div\n style={{\n display: \"flex\",\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 10,\n padding: 4,\n gap: 4,\n }}\n >\n {[\n { key: \"tasks\", label: \"Tasks\" },\n { key: \"heartbeats\", label: \"Heartbeats\" },\n { key: \"skills\", label: \"Skills\" },\n ].map((tab) => (\n <button\n key={tab.key}\n onClick={() => setActiveView(tab.key)}\n style={{\n padding: \"6px 10px\",\n borderRadius: 8,\n border: \"none\",\n background: activeView === tab.key ? theme.accentGlow : \"transparent\",\n color: activeView === tab.key ? theme.accent : theme.textMuted,\n cursor: \"pointer\",\n fontSize: 12,\n fontWeight: 700,\n }}\n >\n {tab.label}\n </button>\n ))}\n </div>\n <input\n placeholder={activeView === \"tasks\" ? \"Filter tasks...\" : \"Filter heartbeats...\"}\n value={filter}\n onChange={(e) => setFilter(e.target.value)}\n style={{\n padding: \"8px 14px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: theme.surface,\n color: theme.text,\n fontSize: 12,\n outline: \"none\",\n width: 180,\n }}\n />\n {/* Color mode toggle */}\n {(() => {\n const cycle = { system: \"light\", light: \"dark\", dark: \"system\" };\n const icons = { system: \"⊙\", light: \"☀\", dark: \"☾\" };\n const labels = { system: \"System theme\", light: \"Light mode\", dark: \"Dark mode\" };\n return (\n <Tooltip text={labels[colorMode]}>\n <button\n onClick={() => setColorMode(cycle[colorMode])}\n style={{\n padding: \"8px 10px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: \"transparent\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 15,\n display: \"flex\",\n alignItems: \"center\",\n transition: \"all 0.15s\",\n }}\n >\n {icons[colorMode]}\n </button>\n </Tooltip>\n );\n })()}\n <Tooltip text=\"Settings\">\n <button\n onClick={() => setShowSettings(true)}\n style={{\n padding: \"8px 12px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: \"transparent\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 15,\n display: \"flex\",\n alignItems: \"center\",\n transition: \"all 0.15s\",\n }}\n >\n ⚙\n </button>\n </Tooltip>\n {activeView !== \"skills\" && (\n <button\n onClick={() =>\n activeView === \"tasks\" ? setShowNew(true) : setShowNewHeartbeat(true)\n }\n style={{\n padding: \"8px 18px\",\n borderRadius: 8,\n border: \"none\",\n background: theme.accent,\n color: \"#fff\",\n cursor: \"pointer\",\n fontSize: 12,\n fontWeight: 700,\n letterSpacing: 0.3,\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n boxShadow: `0 0 24px ${theme.accentGlow}`,\n transition: \"transform 0.15s\",\n }}\n >\n {activeView === \"tasks\" ? \"+ New Task\" : \"+ New Heartbeat\"}\n </button>\n )}\n </div>\n </div>\n\n {activeView === \"tasks\" ? (\n <div\n style={{\n display: \"flex\",\n gap: 20,\n padding: 28,\n minHeight: \"calc(100vh - 72px)\",\n }}\n >\n {COLUMNS.map((col) => (\n <Column\n key={col.key}\n col={col}\n tasks={filtered.filter((t) => col.statuses.includes(t.status))}\n onAction={handleAction}\n onViewDetail={setDetail}\n />\n ))}\n </div>\n ) : activeView === \"heartbeats\" ? (\n <div style={{ padding: 28, minHeight: \"calc(100vh - 72px)\" }}>\n <div\n style={{\n display: \"grid\",\n gridTemplateColumns: \"repeat(auto-fit, minmax(360px, 1fr))\",\n gap: 14,\n }}\n >\n {(filter\n ? heartbeats.filter(\n (h) =>\n h.name.toLowerCase().includes(filter.toLowerCase()) ||\n h.check_prompt.toLowerCase().includes(filter.toLowerCase()),\n )\n : heartbeats\n ).map((h) => (\n <HeartbeatCard\n key={h.id}\n heartbeat={h}\n onAction={handleHeartbeatAction}\n onViewDetail={openHeartbeatDetail}\n />\n ))}\n {heartbeats.length === 0 && (\n <div\n style={{\n border: `1px dashed ${theme.border}`,\n borderRadius: 12,\n padding: 32,\n textAlign: \"center\",\n color: theme.textDim,\n fontSize: 12,\n gridColumn: \"1 / -1\",\n }}\n >\n No heartbeats yet\n </div>\n )}\n </div>\n </div>\n ) : (\n <SkillsView\n skillData={skillData}\n skills={skills}\n tasks={tasks}\n onSweep={handleSweep}\n onDraft={handleSkillDraft}\n onApprove={handleSkillApprove}\n onDismiss={handleSkillDismiss}\n onToggleSkill={handleSkillToggle}\n onDeleteSkill={handleSkillDelete}\n />\n )}\n\n {/* Modals */}\n {showNew && (\n <NewTaskModal\n onClose={() => setShowNew(false)}\n onSubmit={handleCreate}\n initialData={{ agent: defaultAgent }}\n />\n )}\n {showNewHeartbeat && (\n <HeartbeatModal\n onClose={() => setShowNewHeartbeat(false)}\n onSubmit={handleCreateHeartbeat}\n defaultAgent={defaultAgent}\n />\n )}\n {editingTask && (\n <NewTaskModal\n onClose={() => setEditingTask(null)}\n onSubmit={handleEdit}\n initialData={editingTask}\n mode=\"edit\"\n />\n )}\n {editingHeartbeat && (\n <HeartbeatModal\n onClose={() => setEditingHeartbeat(null)}\n onSubmit={handleEditHeartbeat}\n initialData={editingHeartbeat}\n defaultAgent={defaultAgent}\n mode=\"edit\"\n />\n )}\n {forkingTask && (\n <NewTaskModal\n onClose={() => setForkingTask(null)}\n onSubmit={handleFork}\n initialData={forkingTask}\n mode=\"fork\"\n />\n )}\n {showSettings && (\n <SettingsModal\n onClose={() => setShowSettings(false)}\n timeout={taskTimeout}\n defaultAgent={defaultAgent}\n onSave={(timeout, agent) => {\n setTaskTimeout(timeout);\n if (agent) setDefaultAgent(agent);\n }}\n feishu={feishuSettings}\n onFeishuSave={(updated) => setFeishuSettings(updated)}\n channelsStatus={channelsStatus}\n onChannelsSave={(updated) => setChannelsStatus(updated)}\n />\n )}\n {detail && (\n <DetailPanel\n task={tasks.find((t) => t.id === detail.id) || detail}\n onClose={() => setDetail(null)}\n onRespond={handleRespond}\n onResume={handleResume}\n />\n )}\n {heartbeatDetail && (\n <HeartbeatDetailPanel\n heartbeat={heartbeats.find((h) => h.id === heartbeatDetail.id) || heartbeatDetail}\n ticks={heartbeatTicks}\n onClose={() => {\n setHeartbeatDetail(null);\n setHeartbeatTicks([]);\n }}\n />\n )}\n\n {/* Startup guide when no tasks */}\n {connected && activeView === \"tasks\" && tasks.length === 0 && (\n <div\n style={{\n position: \"fixed\",\n bottom: 28,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 12,\n padding: \"16px 24px\",\n maxWidth: 500,\n boxShadow: \"0 8px 32px rgba(0,0,0,0.3)\",\n }}\n >\n <div style={{ fontSize: 13, color: theme.text, fontWeight: 600, marginBottom: 6 }}>\n Ready to go! Click \"+ New Task\" to create your first task.\n </div>\n <div style={{ fontSize: 11, color: theme.textDim, lineHeight: 1.6 }}>\n Tasks are dispatched to Claude Code in your specified working directory. Set cron\n schedules for recurring tasks, or delay execution.\n </div>\n </div>\n )}\n {connected && activeView === \"heartbeats\" && heartbeats.length === 0 && (\n <div\n style={{\n position: \"fixed\",\n bottom: 28,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 12,\n padding: \"16px 24px\",\n maxWidth: 560,\n boxShadow: \"0 8px 32px rgba(0,0,0,0.3)\",\n }}\n >\n <div style={{ fontSize: 13, color: theme.text, fontWeight: 600, marginBottom: 6 }}>\n Heartbeats let AgentForge check first and only create work when needed.\n </div>\n <div style={{ fontSize: 11, color: theme.textDim, lineHeight: 1.6 }}>\n Create one to run a stateless agent decision tick on an interval or cron schedule, then\n trigger a real task only when the signal is actionable.\n </div>\n </div>\n )}\n\n {!connected && (\n <div\n style={{\n position: \"fixed\",\n bottom: 28,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n background: theme.redBg,\n border: `1px solid rgba(248,113,113,0.2)`,\n borderRadius: 12,\n padding: \"16px 24px\",\n maxWidth: 520,\n }}\n >\n <div style={{ fontSize: 13, color: theme.red, fontWeight: 600, marginBottom: 4 }}>\n Backend not running\n </div>\n <code style={{ fontSize: 11, color: theme.text, lineHeight: 1.8, display: \"block\" }}>\n pip install croniter\n <br />\n python taskboard.py\n </code>\n </div>\n )}\n </div>\n );\n}\n\n// CSS动画定义\nconst styles = `\n @keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n\n .live-output-line {\n transition: color 0.2s ease;\n }\n\n .live-output-line.error {\n color: ${theme.red};\n }\n\n .live-output-line.success {\n color: ${theme.green};\n }\n\n .live-output-line.warning {\n color: ${theme.orange};\n }\n\n .live-output-line.info {\n color: ${theme.blue};\n }\n\n .live-output-line.command {\n color: ${theme.cyan};\n font-weight: bold;\n }\n\n .live-output-line.path {\n color: ${theme.accent};\n }\n`;\n\n// 注入样式\nif (typeof document !== \"undefined\" && !document.querySelector(\"#live-output-styles\")) {\n const styleEl = document.createElement(\"style\");\n styleEl.id = \"live-output-styles\";\n styleEl.textContent = styles;\n document.head.appendChild(styleEl);\n}\n", + "import { useState, useEffect, useCallback, useRef, type CSSProperties } from \"react\";\nimport QRCode from \"qrcode\";\nimport {\n formatDateTimeLocalInput,\n formatTaskDateTime,\n formatTaskTime,\n parseTaskDateTime,\n serializeDateTimeLocalInput,\n} from \"./dateTime.ts\";\nimport {\n buildChannelsSavePayload,\n createInitialChannelsState,\n isWeixinQrImageSource,\n mergeChannelsStatus,\n} from \"./channelsSettings.ts\";\nimport { buildExecutionSteps } from \"./traceSteps.ts\";\n\nconst API = \"http://127.0.0.1:9712/api\";\n\n// ─── Theme ───\nconst THEMES: Record<string, Record<string, string>> = {\n dark: {\n bg: \"#0a0a0f\",\n surface: \"#12121a\",\n surfaceHover: \"#1a1a26\",\n border: \"#1e1e2e\",\n borderActive: \"#2d2d44\",\n text: \"#e2e2ef\",\n textMuted: \"#6b6b8a\",\n textDim: \"#44445e\",\n accent: \"#7c6aff\",\n accentGlow: \"rgba(124, 106, 255, 0.15)\",\n green: \"#34d399\",\n greenBg: \"rgba(52, 211, 153, 0.08)\",\n orange: \"#fbbf24\",\n orangeBg: \"rgba(251, 191, 36, 0.08)\",\n red: \"#f87171\",\n redBg: \"rgba(248, 113, 113, 0.08)\",\n blue: \"#60a5fa\",\n blueBg: \"rgba(96, 165, 250, 0.08)\",\n cyan: \"#22d3ee\",\n cyanBg: \"rgba(34, 211, 238, 0.08)\",\n },\n light: {\n bg: \"#f5f5fa\",\n surface: \"#ffffff\",\n surfaceHover: \"#eeeef7\",\n border: \"#dcdce8\",\n borderActive: \"#b8b8d0\",\n text: \"#1a1a2e\",\n textMuted: \"#6b6b8a\",\n textDim: \"#a0a0bc\",\n accent: \"#5b4ecc\",\n accentGlow: \"rgba(91, 78, 204, 0.12)\",\n green: \"#059669\",\n greenBg: \"rgba(5, 150, 105, 0.08)\",\n orange: \"#d97706\",\n orangeBg: \"rgba(217, 119, 6, 0.08)\",\n red: \"#dc2626\",\n redBg: \"rgba(220, 38, 38, 0.08)\",\n blue: \"#2563eb\",\n blueBg: \"rgba(37, 99, 235, 0.08)\",\n cyan: \"#0891b2\",\n cyanBg: \"rgba(8, 145, 178, 0.08)\",\n },\n};\n\n// Mutable module-level theme reference — updated before each App render\nlet theme = THEMES.dark;\n\nfunction getStatusConfig() {\n return {\n pending: { label: \"Pending\", color: theme.orange, bg: theme.orangeBg, icon: \"◌\" },\n scheduled: { label: \"Scheduled\", color: theme.cyan, bg: theme.cyanBg, icon: \"⏱\" },\n running: { label: \"Running\", color: theme.blue, bg: theme.blueBg, icon: \"⟳\" },\n completed: { label: \"Completed\", color: theme.green, bg: theme.greenBg, icon: \"✓\" },\n failed: { label: \"Failed\", color: theme.red, bg: theme.redBg, icon: \"✕\" },\n cancelled: {\n label: \"Cancelled\",\n color: theme.textMuted,\n bg: \"rgba(107,107,138,0.08)\",\n icon: \"◻\",\n },\n blocked: { label: \"Blocked\", color: theme.textMuted, bg: \"rgba(107,107,138,0.1)\", icon: \"⊘\" },\n };\n}\n\nconst COLUMNS = [\n { key: \"queued\", label: \"Queue\", statuses: [\"pending\", \"scheduled\", \"blocked\"], icon: \"⧖\" },\n { key: \"running\", label: \"Running\", statuses: [\"running\"], icon: \"▸\" },\n { key: \"done\", label: \"Done\", statuses: [\"completed\", \"failed\", \"cancelled\"], icon: \"◆\" },\n];\n\nconst AGENTS = {\n claude: { label: \"Claude Code\", icon: \"⌘\", color: \"#7c6aff\" },\n codex: { label: \"Codex CLI\", icon: \"◈\", color: \"#10a37f\" },\n};\nconst DEFAULT_AGENT = \"codex\";\nconst DEFAULT_TIMEOUT_SECONDS = 12000;\n\n// ─── Formatted Output Component ───\nfunction FormattedOutput({ content, theme }) {\n if (!content) return null;\n\n // 解析JSON流数据,只显示关键信息\n const parseStreamJSON = (text) => {\n const lines = text.split(\"\\n\");\n const parsedLines = [];\n\n lines.forEach((line) => {\n if (!line.trim()) return;\n\n try {\n const event = JSON.parse(line);\n const eventType = event.type;\n\n switch (eventType) {\n case \"user\":\n case \"assistant\": {\n const isUser = eventType === \"user\";\n const msg = event.message || {};\n const msgContent = msg.content || [];\n const prefix = isUser ? \"👤 User: \" : \"🤖 Assistant: \";\n const color = isUser ? theme.accent : theme.green;\n let textBuf = \"\";\n const flushText = () => {\n if (textBuf.trim()) {\n parsedLines.push({\n type: eventType,\n text: prefix + textBuf,\n style: { color, fontWeight: isUser ? \"bold\" : \"normal\" },\n });\n textBuf = \"\";\n }\n };\n for (const c of msgContent) {\n if (typeof c === \"string\") {\n textBuf += c;\n } else if (c && typeof c === \"object\") {\n if (c.type === \"text\") {\n textBuf += c.text || \"\";\n } else if (c.type === \"image\") {\n flushText();\n const src =\n c.source && c.source.type === \"base64\"\n ? `data:${c.source.media_type || \"image/jpeg\"};base64,${c.source.data}`\n : null;\n if (src) parsedLines.push({ type: \"image\", src });\n } else if (c.type === \"tool_use\") {\n flushText();\n const rows = buildTraceRows(\n \"tool_call\",\n {\n id: c.id,\n name: c.name,\n input: c.input,\n },\n \"\",\n );\n parsedLines.push({\n type: \"tool_call\",\n text: rows.map((row) => `${row.label}: ${row.value}`).join(\"\\n\"),\n style: { color: theme.cyan, fontSize: \"11px\", fontFamily: \"monospace\" },\n });\n } else if (c.type === \"tool_result\") {\n flushText();\n const rows = buildTraceRows(\n \"tool_result\",\n {\n tool_use_id: c.tool_use_id,\n content: Array.isArray(c.content)\n ? c.content\n .map((part) =>\n part && part.type === \"text\" ? part.text || \"\" : JSON.stringify(part),\n )\n .join(\"\")\n : c.content,\n is_error: c.is_error,\n },\n \"\",\n );\n parsedLines.push({\n type: \"tool_result\",\n text: rows.map((row) => `${row.label}: ${row.value}`).join(\"\\n\"),\n style: {\n color: c.is_error ? theme.red : theme.blue,\n fontSize: \"11px\",\n fontFamily: \"monospace\",\n },\n });\n }\n }\n }\n flushText();\n break;\n }\n\n case \"item.completed\": {\n const item = event.item || {};\n if (item.type === \"command_execution\") {\n const rows = buildTraceRows(\n \"command_execution\",\n {\n command: item.command,\n output: item.aggregated_output,\n exit_code: item.exit_code,\n status: item.status,\n },\n \"\",\n );\n parsedLines.push({\n type: \"command_execution\",\n text: rows.map((row) => `${row.label}: ${row.value}`).join(\"\\n\"),\n style: { color: theme.orange, fontSize: \"11px\", fontFamily: \"monospace\" },\n });\n } else if (item.type === \"mcp_tool_call\" || item.type === \"collab_tool_call\") {\n const rows = buildTraceRows(\n \"tool_call\",\n {\n server: item.server,\n name: item.tool || item.name,\n input: item.arguments || item.input,\n result: item.result,\n status: item.status,\n error: item.error,\n },\n \"\",\n );\n parsedLines.push({\n type: \"tool_call\",\n text: rows.map((row) => `${row.label}: ${row.value}`).join(\"\\n\"),\n style: { color: theme.cyan, fontSize: \"11px\", fontFamily: \"monospace\" },\n });\n } else if (item.type === \"web_search\") {\n const rows = buildTraceRows(\"web_search\", item, \"\");\n parsedLines.push({\n type: \"web_search\",\n text: rows.map((row) => `${row.label}: ${row.value}`).join(\"\\n\"),\n style: { color: theme.cyan, fontSize: \"11px\", fontFamily: \"monospace\" },\n });\n } else if (item.type === \"file_change\") {\n const rows = buildTraceRows(\"file_change\", item, \"\");\n parsedLines.push({\n type: \"file_change\",\n text: rows.map((row) => `${row.label}: ${row.value}`).join(\"\\n\"),\n style: { color: theme.accent, fontSize: \"11px\", fontFamily: \"monospace\" },\n });\n }\n break;\n }\n\n case \"result\":\n // 最终结果\n if (event.result) {\n parsedLines.push({\n type: \"result\",\n text: `✅ Result: ${event.result}`,\n style: { color: theme.green, fontWeight: \"bold\" },\n });\n }\n break;\n\n case \"error\":\n // 错误信息\n parsedLines.push({\n type: \"error\",\n text: `❌ Error: ${event.error || \"Unknown error\"}`,\n style: { color: theme.red, fontWeight: \"bold\" },\n });\n break;\n\n default:\n // 其他事件类型 - 显示更多信息\n if (eventType) {\n let displayText = `[${eventType}]`;\n // 尝试显示事件中的关键信息\n if (event.message) {\n const msg = event.message;\n if (msg.content && Array.isArray(msg.content)) {\n const textContent = msg.content\n .filter(\n (c) =>\n typeof c === \"string\" || (c && typeof c === \"object\" && c.type === \"text\"),\n )\n .map((c) => (typeof c === \"string\" ? c : c.text || \"\"))\n .join(\"\");\n if (textContent.trim()) {\n displayText = textContent.slice(0, 200);\n }\n }\n } else if (event.result) {\n displayText = `Result: ${event.result.slice(0, 200)}`;\n } else if (event.error) {\n displayText = `Error: ${event.error.slice(0, 200)}`;\n }\n\n parsedLines.push({\n type: \"event\",\n text: displayText,\n style: { color: theme.textDim, fontSize: \"11px\", fontFamily: \"monospace\" },\n });\n }\n }\n } catch (_error) {\n // 如果不是有效的JSON,可能是普通文本输出\n if (line.trim() && !line.startsWith(\"{\")) {\n // 只显示有意义的非JSON行\n if (line.includes(\"error\") || line.includes(\"Error\")) {\n parsedLines.push({\n type: \"error\",\n text: line,\n style: { color: theme.red },\n });\n } else if (line.includes(\"success\") || line.includes(\"Success\")) {\n parsedLines.push({\n type: \"success\",\n text: line,\n style: { color: theme.green },\n });\n } else if (line.length > 10) {\n // 只显示较长的非JSON行\n parsedLines.push({\n type: \"text\",\n text: line,\n style: { color: theme.textDim },\n });\n }\n }\n }\n });\n\n return parsedLines;\n };\n\n const parsedContent = parseStreamJSON(content);\n\n if (parsedContent.length === 0) {\n return (\n <div style={{ color: theme.textDim, fontStyle: \"italic\", fontSize: \"12px\" }}>\n Waiting for agent output...\n </div>\n );\n }\n\n return (\n <div style={{ fontFamily: \"'JetBrains Mono', monospace\", fontSize: \"12px\", lineHeight: \"1.6\" }}>\n {parsedContent.map((item, index) =>\n item.type === \"image\" ? (\n <div key={index} style={{ margin: \"6px 0\" }}>\n <img\n src={item.src}\n alt=\"output image\"\n style={{ maxWidth: \"100%\", borderRadius: \"4px\", display: \"block\" }}\n />\n </div>\n ) : (\n <div\n key={index}\n style={{\n ...item.style,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n marginBottom: \"2px\",\n padding: \"2px 0\",\n }}\n >\n {item.text}\n </div>\n ),\n )}\n </div>\n );\n}\n\nfunction ExecutionTimeline({ events }) {\n const [expanded, setExpanded] = useState(true);\n const steps = buildExecutionSteps(events);\n\n if (steps.length === 0) {\n return (\n <div style={{ fontSize: 12, color: theme.textDim, padding: \"12px 0\", textAlign: \"center\" }}>\n No output events recorded — events are recorded for new task runs.\n </div>\n );\n }\n\n return (\n <div\n style={{\n border: `1px solid ${theme.border}`,\n borderRadius: 8,\n overflow: \"hidden\",\n background: theme.bg,\n }}\n >\n <button\n onClick={() => setExpanded(!expanded)}\n style={{\n width: \"100%\",\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n gap: 12,\n padding: \"10px 12px\",\n background: theme.surface,\n border: \"none\",\n borderBottom: expanded ? `1px solid ${theme.border}` : \"none\",\n color: theme.text,\n cursor: \"pointer\",\n fontFamily: \"'JetBrains Mono', monospace\",\n fontSize: 12,\n textAlign: \"left\",\n }}\n >\n <span style={{ display: \"flex\", alignItems: \"center\", gap: 8, minWidth: 0 }}>\n <span style={{ color: theme.textMuted }}>{expanded ? \"⌄\" : \"›\"}</span>\n <span>\n Show {steps.length} {steps.length === 1 ? \"step\" : \"steps\"}\n </span>\n </span>\n <span style={{ color: theme.textDim, fontSize: 10, whiteSpace: \"nowrap\" }}>\n {events.length} events\n </span>\n </button>\n\n {expanded && (\n <div style={{ padding: \"12px 12px 14px\" }}>\n {steps.map((step, index) => (\n <ExecutionTimelineStep\n key={`${step.id}-${step.number}`}\n step={step}\n isLast={index === steps.length - 1}\n />\n ))}\n </div>\n )}\n </div>\n );\n}\n\nfunction ExecutionTimelineStep({ step, isLast }) {\n const config = getExecutionStepConfig(step.type);\n const detail = (step.detail || \"\").trim();\n const hasRows = step.rows && step.rows.length > 0;\n const hasImage = Boolean(step.imageSrc);\n const showDetail = detail && detail !== step.title && !hasRows && !hasImage;\n\n return (\n <div style={{ display: \"grid\", gridTemplateColumns: \"28px 1fr\", columnGap: 10 }}>\n <div style={{ display: \"flex\", flexDirection: \"column\", alignItems: \"center\" }}>\n <div\n style={{\n width: 20,\n height: 20,\n borderRadius: 6,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n background: config.bg,\n border: `1px solid ${config.color}55`,\n color: config.color,\n fontSize: 10,\n fontWeight: 800,\n lineHeight: 1,\n }}\n >\n {config.icon}\n </div>\n {!isLast && (\n <div\n style={{ width: 1, flex: 1, minHeight: 16, background: theme.border, marginTop: 4 }}\n />\n )}\n </div>\n\n <div style={{ paddingBottom: isLast ? 0 : 14, minWidth: 0 }}>\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n gap: 10,\n alignItems: \"baseline\",\n }}\n >\n <div\n style={{\n color: theme.text,\n fontSize: 12,\n lineHeight: 1.55,\n wordBreak: \"break-word\",\n minWidth: 0,\n }}\n >\n {step.title}\n </div>\n <div\n style={{\n color: theme.textDim,\n fontSize: 9,\n whiteSpace: \"nowrap\",\n flexShrink: 0,\n fontFamily: \"'JetBrains Mono', monospace\",\n }}\n >\n {formatTaskTime(step.timestamp)}\n </div>\n </div>\n\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n marginTop: 3,\n marginBottom: hasRows || showDetail ? 7 : 0,\n }}\n >\n <span\n style={{\n color: config.color,\n fontSize: 10,\n fontWeight: 700,\n textTransform: \"uppercase\",\n letterSpacing: 0,\n }}\n >\n {config.label}\n </span>\n {step.count > 1 && (\n <span style={{ color: theme.textDim, fontSize: 10 }}>{step.count} chunks</span>\n )}\n </div>\n\n {hasImage && (\n <img\n src={step.imageSrc}\n alt=\"image output\"\n style={{\n maxWidth: \"100%\",\n borderRadius: 6,\n display: \"block\",\n marginTop: 7,\n border: `1px solid ${theme.border}`,\n }}\n />\n )}\n\n {hasRows && (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n gap: 5,\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 6,\n padding: \"8px 10px\",\n maxHeight: 220,\n overflow: \"auto\",\n }}\n >\n {step.rows.map((row, i) => (\n <div\n key={i}\n style={{ display: \"grid\", gridTemplateColumns: \"72px 1fr\", gap: 8, minWidth: 0 }}\n >\n <span style={{ color: theme.textMuted, fontWeight: 700 }}>{row.label}</span>\n <span\n style={{ whiteSpace: \"pre-wrap\", wordBreak: \"break-word\", color: theme.text }}\n >\n {row.value}\n </span>\n </div>\n ))}\n </div>\n )}\n\n {showDetail && (\n <pre\n style={{\n margin: 0,\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 6,\n padding: \"8px 10px\",\n color: theme.textMuted,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n fontFamily: \"'JetBrains Mono', monospace\",\n fontSize: 11,\n lineHeight: 1.5,\n maxHeight: 220,\n overflow: \"auto\",\n }}\n >\n {detail}\n </pre>\n )}\n </div>\n </div>\n );\n}\n\nfunction getExecutionStepConfig(type) {\n switch (type) {\n case \"thinking\":\n return { label: \"Thinking\", icon: \"⌁\", color: theme.textMuted, bg: \"rgba(107,107,138,0.08)\" };\n case \"tool_call\":\n return { label: \"Tool Call\", icon: \"▣\", color: theme.cyan, bg: theme.cyanBg };\n case \"tool_result\":\n return { label: \"Tool Result\", icon: \"↵\", color: theme.blue, bg: theme.blueBg };\n case \"command_execution\":\n return { label: \"Command\", icon: \"$\", color: theme.orange, bg: theme.orangeBg };\n case \"file_change\":\n return { label: \"File\", icon: \"◇\", color: theme.accent, bg: theme.accentGlow };\n case \"generated_image\":\n return { label: \"Image\", icon: \"□\", color: theme.accent, bg: theme.accentGlow };\n case \"image_content\":\n return { label: \"Image\", icon: \"□\", color: theme.accent, bg: theme.accentGlow };\n case \"web_search\":\n return { label: \"Search\", icon: \"⌕\", color: theme.cyan, bg: theme.cyanBg };\n case \"result\":\n return { label: \"Result\", icon: \"✓\", color: theme.green, bg: theme.greenBg };\n case \"error\":\n return { label: \"Error\", icon: \"!\", color: theme.red, bg: theme.redBg };\n case \"user\":\n return { label: \"User\", icon: \"U\", color: theme.accent, bg: theme.accentGlow };\n case \"assistant\":\n return { label: \"Assistant\", icon: \"AI\", color: theme.green, bg: theme.greenBg };\n default:\n return { label: \"Event\", icon: \"•\", color: theme.textMuted, bg: \"rgba(107,107,138,0.08)\" };\n }\n}\n\nfunction formatTraceValue(value) {\n if (value === undefined || value === null) return \"\";\n if (typeof value === \"string\") return value;\n return JSON.stringify(value, null, 2);\n}\n\nfunction buildTraceRows(eventType, payload, rawContent) {\n const row = (label, value) => {\n const formatted = formatTraceValue(value);\n return formatted === \"\" ? null : { label, value: formatted };\n };\n const compact = (rows) => rows.filter(Boolean);\n\n if (eventType === \"tool_call\") {\n const name = payload.server\n ? `${payload.server}.${payload.name || payload.tool || \"unknown\"}`\n : payload.name || payload.tool || \"unknown\";\n return compact([\n row(\"Tool\", name),\n row(\"Input\", payload.input || payload.arguments),\n row(\"Result\", payload.result),\n row(\"Status\", payload.status),\n row(\"Error\", payload.error),\n ]);\n }\n\n if (eventType === \"tool_result\") {\n return compact([\n row(payload.is_error ? \"Tool Error\" : \"Tool Result\", payload.tool_use_id || \"result\"),\n row(\"Content\", payload.content),\n ]);\n }\n\n if (eventType === \"command_execution\") {\n return compact([\n row(\"Command\", payload.command),\n row(\"Output\", payload.output),\n row(\"Exit\", payload.exit_code),\n row(\"Status\", payload.status),\n ]);\n }\n\n if (eventType === \"file_change\") {\n const changes = Array.isArray(payload.changes)\n ? payload.changes\n .map((change) => {\n if (!change || typeof change !== \"object\") return formatTraceValue(change);\n const kind = change.kind || change.type || \"changed\";\n const path = change.path || change.file || \"\";\n return path ? `${kind}: ${path}` : kind;\n })\n .join(\"\\n\")\n : payload.changes;\n return compact([row(\"Changes\", changes), row(\"Status\", payload.status)]);\n }\n\n if (eventType === \"web_search\") {\n return compact([\n row(\"Query\", payload.query),\n row(\"Action\", payload.action),\n row(\"Status\", payload.status),\n ]);\n }\n\n return [{ label: eventType, value: rawContent }];\n}\n\n// ─── CSRF token ───\n// Fetched once at startup; reused for all state-changing requests.\nlet _csrfTokenPromise = null;\nfunction getCsrfToken() {\n if (!_csrfTokenPromise) {\n _csrfTokenPromise = fetch(`${API}/csrf-token`)\n .then((r) => r.json())\n .then((d) => d.csrf_token || \"\")\n .catch(() => \"\");\n }\n return _csrfTokenPromise;\n}\n\nasync function csrfHeaders(extra = {}) {\n const token = await getCsrfToken();\n return { \"Content-Type\": \"application/json\", \"X-CSRF-Token\": token, ...extra };\n}\n\n// ─── API helpers ───\nasync function fetchTasks() {\n const res = await fetch(`${API}/tasks`);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n return res.json();\n}\n\nasync function fetchHeartbeats() {\n const res = await fetch(`${API}/heartbeats`);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n return res.json();\n}\n\nasync function createTask(data) {\n const res = await fetch(`${API}/tasks`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify(data),\n });\n return res.json();\n}\n\nasync function fetchSkillPatterns() {\n const res = await fetch(`${API}/skill-patterns`);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n return res.json();\n}\n\nasync function triggerSkillSweep(agent?: string) {\n const res = await fetch(`${API}/skills/sweep`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify(agent ? { agent } : {}),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function triggerSkillDraft(id, agent?: string) {\n const res = await fetch(`${API}/skill-patterns/${id}/draft`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify(agent ? { agent } : {}),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function approveSkill(id, data) {\n const res = await fetch(`${API}/skill-patterns/${id}/approve`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify(data),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function dismissSkillPattern(id) {\n const res = await fetch(`${API}/skill-patterns/${id}/dismiss`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: \"{}\",\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function fetchSkills() {\n const res = await fetch(`${API}/skills`);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n return res.json();\n}\n\nasync function setSkillEnabledApi(id, enabled) {\n const res = await fetch(`${API}/skills/${id}`, {\n method: \"PUT\",\n headers: await csrfHeaders(),\n body: JSON.stringify({ enabled }),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function deleteSkillApi(id) {\n const res = await fetch(`${API}/skills/${id}`, {\n method: \"DELETE\",\n headers: await csrfHeaders(),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function createHeartbeat(data) {\n const res = await fetch(`${API}/heartbeats`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify(data),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function updateHeartbeat(id, data) {\n const res = await fetch(`${API}/heartbeats/${id}`, {\n method: \"PUT\",\n headers: await csrfHeaders(),\n body: JSON.stringify(data),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function deleteHeartbeat(id) {\n const res = await fetch(`${API}/heartbeats/${id}`, {\n method: \"DELETE\",\n headers: await csrfHeaders(),\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n}\n\nasync function runHeartbeatNow(id) {\n const res = await fetch(`${API}/heartbeats/${id}/run-now`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function pauseHeartbeat(id) {\n const res = await fetch(`${API}/heartbeats/${id}/pause`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function resumeHeartbeatApi(id) {\n const res = await fetch(`${API}/heartbeats/${id}/resume`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n });\n const payload = await res.json().catch(() => ({}));\n if (!res.ok) throw new Error(payload.error || `HTTP ${res.status}`);\n return payload;\n}\n\nasync function fetchHeartbeatTicks(id) {\n const res = await fetch(`${API}/heartbeats/${id}/ticks?limit=20`);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const payload = await res.json();\n return payload.ticks || [];\n}\n\nasync function fetchHeartbeatTickOutput(heartbeatId, tickId) {\n const res = await fetch(`${API}/heartbeats/${heartbeatId}/ticks/${tickId}/output`);\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n return res.json();\n}\n\nasync function cancelTask(id) {\n await fetch(`${API}/tasks/${id}/cancel`, { method: \"POST\", headers: await csrfHeaders() });\n}\n\nasync function retryTask(id) {\n await fetch(`${API}/tasks/${id}/retry`, { method: \"POST\", headers: await csrfHeaders() });\n}\n\nasync function deleteTask(id) {\n await fetch(`${API}/tasks/${id}`, { method: \"DELETE\", headers: await csrfHeaders() });\n}\n\nasync function updateTask(id, data) {\n const res = await fetch(`${API}/tasks/${id}`, {\n method: \"PUT\",\n headers: await csrfHeaders(),\n body: JSON.stringify(data),\n });\n if (!res.ok) {\n const err = await res.json().catch(() => ({}));\n throw new Error(err.error || `HTTP ${res.status}`);\n }\n return res.json();\n}\n\nasync function respondToTask(id, answer) {\n await fetch(`${API}/tasks/${id}/respond`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify({ answer }),\n });\n}\n\nasync function resumeTask(id, message) {\n const res = await fetch(`${API}/tasks/${id}/resume`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify({ message }),\n });\n return res.json();\n}\n\nasync function fetchTaskMessages(id) {\n try {\n const res = await fetch(`${API}/tasks/${id}/messages`);\n return res.ok ? await res.json() : [];\n } catch {\n return [];\n }\n}\n\nasync function fetchTaskEvents(id) {\n try {\n const res = await fetch(`${API}/tasks/${id}/events?limit=1000`);\n if (res.ok) {\n const data = await res.json();\n return data.events || [];\n }\n return [];\n } catch {\n return [];\n }\n}\n\nasync function fetchSettings() {\n try {\n const res = await fetch(`${API}/settings`);\n return res.ok ? await res.json() : {};\n } catch {\n return {};\n }\n}\n\nasync function updateSettings(data) {\n await fetch(`${API}/settings`, {\n method: \"PUT\",\n headers: await csrfHeaders(),\n body: JSON.stringify(data),\n });\n}\n\nasync function fetchFeishuSettings() {\n try {\n const res = await fetch(`${API}/feishu/settings`);\n return res.ok ? await res.json() : {};\n } catch {\n return {};\n }\n}\n\nasync function updateFeishuSettings(data) {\n await fetch(`${API}/feishu/settings`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify(data),\n });\n}\n\nasync function fetchChannelsStatus() {\n try {\n const res = await fetch(`${API}/channels/status`);\n return res.ok ? await res.json() : {};\n } catch {\n return {};\n }\n}\n\nasync function updateChannelsSettings(data) {\n await fetch(`${API}/channels/settings`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify(data),\n });\n}\n\nasync function runWeixinAction(action) {\n const res = await fetch(`${API}/channels/weixin/action`, {\n method: \"POST\",\n headers: await csrfHeaders(),\n body: JSON.stringify({ action }),\n });\n if (!res.ok) {\n const data = await res.json().catch(() => ({}));\n throw new Error(data.error || `HTTP ${res.status}`);\n }\n}\n\n// ─── Components ───\n\nfunction Tooltip({ text, children }) {\n const [visible, setVisible] = useState(false);\n return (\n <div\n style={{ position: \"relative\", display: \"inline-flex\" }}\n onMouseEnter={() => setVisible(true)}\n onMouseLeave={() => setVisible(false)}\n >\n {children}\n {visible && (\n <div\n style={{\n position: \"absolute\",\n bottom: \"calc(100% + 6px)\",\n left: \"50%\",\n transform: \"translateX(-50%)\",\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n color: theme.textMuted,\n fontSize: 11,\n padding: \"4px 8px\",\n borderRadius: 6,\n whiteSpace: \"nowrap\",\n pointerEvents: \"none\",\n boxShadow: \"0 4px 12px rgba(0,0,0,0.3)\",\n zIndex: 9999,\n }}\n >\n {text}\n </div>\n )}\n </div>\n );\n}\n\nfunction Badge({ status }) {\n const cfg = getStatusConfig()[status] || getStatusConfig().pending;\n return (\n <span\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 5,\n padding: \"3px 10px\",\n borderRadius: 20,\n fontSize: 11,\n fontWeight: 600,\n color: cfg.color,\n background: cfg.bg,\n letterSpacing: 0.3,\n }}\n >\n <span style={{ fontSize: 10 }}>{cfg.icon}</span>\n {cfg.label}\n </span>\n );\n}\n\nfunction Tag({ children }) {\n return (\n <span\n style={{\n padding: \"2px 8px\",\n borderRadius: 4,\n fontSize: 10,\n fontWeight: 500,\n background: theme.accentGlow,\n color: theme.accent,\n letterSpacing: 0.4,\n }}\n >\n {children}\n </span>\n );\n}\n\nfunction AgentBadge({ agent }) {\n const cfg = AGENTS[agent] || AGENTS.claude;\n return (\n <span\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 4,\n padding: \"2px 8px\",\n borderRadius: 4,\n fontSize: 10,\n fontWeight: 600,\n color: cfg.color,\n background: `${cfg.color}18`,\n letterSpacing: 0.3,\n }}\n >\n <span style={{ fontSize: 9 }}>{cfg.icon}</span>\n {cfg.label}\n </span>\n );\n}\n\nfunction TaskCard({ task, onAction, onViewDetail }) {\n const [hovered, setHovered] = useState(false);\n const cfg = getStatusConfig()[task.status] || getStatusConfig().pending;\n const tags = task.tags ? task.tags.split(\",\").filter(Boolean) : [];\n\n return (\n <div\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n onClick={() => onViewDetail(task)}\n style={{\n background: hovered ? theme.surfaceHover : theme.surface,\n border: `1px solid ${hovered ? theme.borderActive : theme.border}`,\n borderLeft: `3px solid ${cfg.color}`,\n borderRadius: 10,\n padding: \"14px 16px\",\n cursor: \"pointer\",\n transition: \"all 0.2s ease\",\n transform: hovered ? \"translateY(-1px)\" : \"none\",\n boxShadow: hovered ? `0 4px 20px rgba(0,0,0,0.3)` : \"none\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"flex-start\",\n marginBottom: 8,\n }}\n >\n <span\n style={{\n fontSize: 13,\n fontWeight: 600,\n color: theme.text,\n lineHeight: 1.4,\n flex: 1,\n marginRight: 8,\n fontFamily: \"'JetBrains Mono', 'SF Mono', monospace\",\n }}\n >\n {task.title}\n </span>\n <Badge status={task.status} />\n </div>\n\n <div\n style={{\n fontSize: 12,\n color: theme.textMuted,\n marginBottom: 10,\n lineHeight: 1.5,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n display: \"-webkit-box\",\n WebkitLineClamp: 2,\n WebkitBoxOrient: \"vertical\",\n }}\n >\n {task.prompt}\n </div>\n\n <div style={{ display: \"flex\", justifyContent: \"space-between\", alignItems: \"center\" }}>\n <div style={{ display: \"flex\", gap: 4, flexWrap: \"wrap\" }}>\n <AgentBadge agent={task.agent} />\n {task.schedule_type === \"delayed\" && <Tag>⏳ {task.delay_seconds}s</Tag>}\n {task.schedule_type === \"scheduled_at\" && task.next_run_at && (\n <Tag>📅 {formatTaskDateTime(task.next_run_at)}</Tag>\n )}\n {task.schedule_type === \"cron\" && <Tag>⏲ {task.cron_expr}</Tag>}\n {tags.map((t, i) => (\n <Tag key={i}>{t.trim()}</Tag>\n ))}\n </div>\n\n <div style={{ display: \"flex\", gap: 4 }} onClick={(e) => e.stopPropagation()}>\n {[\"pending\", \"scheduled\", \"blocked\"].includes(task.status) && (\n <ActionBtn\n label=\"✎\"\n title=\"Edit\"\n onClick={() => onAction(\"edit\", task.id)}\n color={theme.blue || theme.accent}\n />\n )}\n {[\"completed\", \"cancelled\", \"failed\"].includes(task.status) && (\n <ActionBtn\n label=\"⑂\"\n title=\"Fork\"\n onClick={() => onAction(\"fork\", task.id)}\n color={theme.cyan || theme.accent}\n />\n )}\n {task.status === \"failed\" && (\n <ActionBtn\n label=\"↻\"\n title=\"Retry\"\n onClick={() => onAction(\"retry\", task.id)}\n color={theme.orange}\n />\n )}\n {[\"pending\", \"scheduled\", \"running\"].includes(task.status) && (\n <ActionBtn\n label=\"■\"\n title=\"Cancel\"\n onClick={() => onAction(\"cancel\", task.id)}\n color={theme.red}\n />\n )}\n <ActionBtn\n label=\"×\"\n title=\"Delete\"\n onClick={() => onAction(\"delete\", task.id)}\n color={theme.textMuted}\n />\n </div>\n </div>\n\n {task.run_count > 0 && (\n <div style={{ fontSize: 10, color: theme.textDim, marginTop: 8, fontFamily: \"monospace\" }}>\n Runs: {task.run_count}\n {task.max_runs ? ` / ${task.max_runs}` : \"\"}\n {task.last_run_at && ` · Last: ${formatTaskTime(task.last_run_at)}`}\n </div>\n )}\n\n {/* DAG info */}\n {task.status === \"blocked\" && task.dependencies && task.dependencies.length > 0 && (\n <div style={{ fontSize: 10, color: theme.textDim, marginTop: 6, fontFamily: \"monospace\" }}>\n ⊘ Waiting for: {task.dependencies.map((d) => `#${d.depends_on_task_id}`).join(\", \")}\n </div>\n )}\n {task.dependents && task.dependents.length > 0 && task.status === \"completed\" && (\n <div style={{ fontSize: 10, color: theme.textDim, marginTop: 6, fontFamily: \"monospace\" }}>\n → Unlocks: {task.dependents.map((id) => `#${id}`).join(\", \")}\n </div>\n )}\n {task.dag_id && (\n <div\n style={{\n fontSize: 10,\n color: theme.accent,\n marginTop: 4,\n opacity: 0.6,\n fontFamily: \"monospace\",\n }}\n >\n dag: {task.dag_id}\n </div>\n )}\n </div>\n );\n}\n\nfunction ActionBtn({ label, title, onClick, color }) {\n const [hovered, setHovered] = useState(false);\n return (\n <button\n title={title}\n onClick={onClick}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n style={{\n background: hovered ? `${color}22` : \"transparent\",\n border: \"none\",\n color: color,\n cursor: \"pointer\",\n width: 24,\n height: 24,\n borderRadius: 6,\n fontSize: 14,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n transition: \"background 0.15s\",\n }}\n >\n {label}\n </button>\n );\n}\n\nfunction Column({ col, tasks, onAction, onViewDetail }) {\n return (\n <div style={{ flex: 1, minWidth: 300 }}>\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n marginBottom: 16,\n padding: \"0 4px\",\n }}\n >\n <span style={{ fontSize: 16, opacity: 0.4 }}>{col.icon}</span>\n <span\n style={{\n fontSize: 12,\n fontWeight: 700,\n color: theme.textMuted,\n letterSpacing: 1.5,\n textTransform: \"uppercase\",\n }}\n >\n {col.label}\n </span>\n <span\n style={{\n background: theme.border,\n borderRadius: 10,\n padding: \"2px 8px\",\n fontSize: 11,\n color: theme.textDim,\n fontWeight: 600,\n }}\n >\n {tasks.length}\n </span>\n </div>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 8 }}>\n {tasks.map((t) => (\n <TaskCard key={t.id} task={t} onAction={onAction} onViewDetail={onViewDetail} />\n ))}\n {tasks.length === 0 && (\n <div\n style={{\n border: `1px dashed ${theme.border}`,\n borderRadius: 10,\n padding: 32,\n textAlign: \"center\",\n color: theme.textDim,\n fontSize: 12,\n }}\n >\n No tasks\n </div>\n )}\n </div>\n </div>\n );\n}\n\nfunction HeartbeatBadge({ enabled }) {\n return (\n <span\n style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 5,\n padding: \"3px 10px\",\n borderRadius: 20,\n fontSize: 11,\n fontWeight: 600,\n color: enabled ? theme.green : theme.textMuted,\n background: enabled ? theme.greenBg : \"rgba(107,107,138,0.08)\",\n letterSpacing: 0.3,\n }}\n >\n <span style={{ fontSize: 10 }}>{enabled ? \"●\" : \"◌\"}</span>\n {enabled ? \"Enabled\" : \"Paused\"}\n </span>\n );\n}\n\nfunction HeartbeatModal({ onClose, onSubmit, initialData, defaultAgent, mode = \"create\" }: any) {\n const savedDir = localStorage.getItem(\"agentforge_working_dir\") || \"~/papers\";\n const [form, setForm] = useState(() => ({\n name: initialData?.name || \"\",\n working_dir: initialData?.working_dir || savedDir,\n schedule_type: initialData?.schedule_type || \"interval\",\n interval_seconds: initialData?.interval_seconds || 600,\n cron_expr: initialData?.cron_expr || \"\",\n check_prompt: initialData?.check_prompt || \"\",\n action_prompt_template: initialData?.action_prompt_template || \"\",\n default_agent: initialData?.default_agent || defaultAgent || DEFAULT_AGENT,\n cooldown_seconds: initialData?.cooldown_seconds || 1800,\n enabled: initialData?.enabled ?? true,\n }));\n\n const set = (k, v) => setForm((prev) => ({ ...prev, [k]: v }));\n\n const inputStyle: CSSProperties = {\n width: \"100%\",\n padding: \"10px 14px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n color: theme.text,\n fontSize: 13,\n outline: \"none\",\n boxSizing: \"border-box\",\n fontFamily: \"'JetBrains Mono', 'SF Mono', monospace\",\n };\n const labelStyle = {\n fontSize: 11,\n fontWeight: 600,\n color: theme.textMuted,\n letterSpacing: 0.8,\n textTransform: \"uppercase\",\n marginBottom: 6,\n display: \"block\",\n };\n\n const handleSubmit = () => {\n localStorage.setItem(\"agentforge_working_dir\", form.working_dir);\n onSubmit({\n ...form,\n name: form.name || \"Untitled heartbeat\",\n interval_seconds:\n form.schedule_type === \"interval\" ? parseInt(form.interval_seconds) || 600 : null,\n cooldown_seconds: parseInt(form.cooldown_seconds) || 0,\n cron_expr: form.schedule_type === \"cron\" ? form.cron_expr : null,\n });\n };\n\n return (\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n background: \"rgba(0,0,0,0.7)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex: 1000,\n backdropFilter: \"blur(8px)\",\n }}\n onClick={onClose}\n >\n <div\n onClick={(e) => e.stopPropagation()}\n style={{\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 16,\n padding: 32,\n width: 640,\n maxHeight: \"84vh\",\n overflow: \"auto\",\n boxShadow: \"0 24px 80px rgba(0,0,0,0.5)\",\n }}\n >\n <h2\n style={{\n margin: \"0 0 24px\",\n fontSize: 18,\n fontWeight: 700,\n color: theme.text,\n fontFamily: \"'JetBrains Mono', monospace\",\n }}\n >\n {mode === \"edit\" ? \"Edit Heartbeat\" : \"New Heartbeat\"}\n </h2>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 16 }}>\n <div>\n <label style={labelStyle}>Name</label>\n <input\n style={inputStyle}\n value={form.name}\n onChange={(e) => set(\"name\", e.target.value)}\n placeholder=\"Repo review watcher\"\n />\n </div>\n <div>\n <label style={labelStyle}>Working Directory</label>\n <div style={{ display: \"flex\", gap: 8 }}>\n <input\n style={{ ...inputStyle, flex: 1 }}\n value={form.working_dir}\n onChange={(e) => set(\"working_dir\", e.target.value)}\n />\n {window.electronAPI?.selectDirectory && (\n <button\n onClick={async () => {\n const dir = await window.electronAPI.selectDirectory();\n if (dir) set(\"working_dir\", dir);\n }}\n style={{\n padding: \"8px 14px\",\n borderRadius: 8,\n cursor: \"pointer\",\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n color: theme.textMuted,\n fontSize: 12,\n fontWeight: 600,\n whiteSpace: \"nowrap\",\n }}\n >\n Browse\n </button>\n )}\n </div>\n </div>\n <div>\n <label style={labelStyle}>Schedule Type</label>\n <div style={{ display: \"flex\", gap: 8 }}>\n {[\"interval\", \"cron\"].map((t) => (\n <button\n key={t}\n onClick={() => set(\"schedule_type\", t)}\n style={{\n flex: 1,\n padding: \"8px 12px\",\n borderRadius: 8,\n cursor: \"pointer\",\n border: `1px solid ${form.schedule_type === t ? theme.accent : theme.border}`,\n background: form.schedule_type === t ? theme.accentGlow : \"transparent\",\n color: form.schedule_type === t ? theme.accent : theme.textMuted,\n fontSize: 12,\n fontWeight: 600,\n textTransform: \"capitalize\",\n }}\n >\n {t === \"interval\" ? \"⟳ Interval\" : \"⏲ Cron\"}\n </button>\n ))}\n </div>\n </div>\n {form.schedule_type === \"interval\" ? (\n <div>\n <label style={labelStyle}>Interval (seconds)</label>\n <input\n type=\"number\"\n style={inputStyle}\n value={form.interval_seconds}\n onChange={(e) => set(\"interval_seconds\", e.target.value)}\n />\n </div>\n ) : (\n <div>\n <label style={labelStyle}>Cron Expression</label>\n <input\n style={inputStyle}\n value={form.cron_expr}\n onChange={(e) => set(\"cron_expr\", e.target.value)}\n placeholder=\"*/10 * * * *\"\n />\n </div>\n )}\n <div>\n <label style={labelStyle}>Decision Prompt *</label>\n <textarea\n style={{ ...inputStyle, height: 110, resize: \"vertical\" }}\n value={form.check_prompt}\n onChange={(e) => set(\"check_prompt\", e.target.value)}\n placeholder=\"Check whether there are new meaningful code changes that deserve a review task. Return JSON only.\"\n />\n </div>\n <div>\n <label style={labelStyle}>Triggered Task Prompt Template</label>\n <textarea\n style={{ ...inputStyle, height: 90, resize: \"vertical\" }}\n value={form.action_prompt_template}\n onChange={(e) => set(\"action_prompt_template\", e.target.value)}\n placeholder=\"Review the latest code changes and summarize bugs, regressions, and missing tests.\"\n />\n </div>\n <div style={{ display: \"grid\", gridTemplateColumns: \"1fr 1fr\", gap: 12 }}>\n <div>\n <label style={labelStyle}>Default Agent</label>\n <select\n style={inputStyle}\n value={form.default_agent}\n onChange={(e) => set(\"default_agent\", e.target.value)}\n >\n {Object.entries(AGENTS).map(([key, cfg]) => (\n <option key={key} value={key}>\n {cfg.label}\n </option>\n ))}\n </select>\n </div>\n <div>\n <label style={labelStyle}>Cooldown (seconds)</label>\n <input\n type=\"number\"\n style={inputStyle}\n value={form.cooldown_seconds}\n onChange={(e) => set(\"cooldown_seconds\", e.target.value)}\n />\n </div>\n </div>\n <label\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n fontSize: 13,\n color: theme.textMuted,\n }}\n >\n <input\n type=\"checkbox\"\n checked={!!form.enabled}\n onChange={(e) => set(\"enabled\", e.target.checked)}\n />\n Enabled\n </label>\n </div>\n <div style={{ display: \"flex\", gap: 10, justifyContent: \"flex-end\", marginTop: 24 }}>\n <button\n onClick={onClose}\n style={{\n padding: \"10px 20px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: \"transparent\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n }}\n >\n Cancel\n </button>\n <button\n onClick={handleSubmit}\n style={{\n padding: \"10px 24px\",\n borderRadius: 8,\n border: \"none\",\n background: theme.accent,\n color: \"#fff\",\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n boxShadow: `0 0 20px ${theme.accentGlow}`,\n }}\n >\n {mode === \"edit\" ? \"Save\" : \"Create Heartbeat\"}\n </button>\n </div>\n </div>\n </div>\n );\n}\n\nfunction HeartbeatCard({ heartbeat, onAction, onViewDetail }) {\n const tags = [];\n if (heartbeat.schedule_type === \"interval\" && heartbeat.interval_seconds)\n tags.push(`⟳ ${heartbeat.interval_seconds}s`);\n if (heartbeat.schedule_type === \"cron\" && heartbeat.cron_expr)\n tags.push(`⏲ ${heartbeat.cron_expr}`);\n if (heartbeat.last_decision) tags.push(`Last: ${heartbeat.last_decision}`);\n\n return (\n <div\n onClick={() => onViewDetail(heartbeat)}\n style={{\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 12,\n padding: \"16px 18px\",\n cursor: \"pointer\",\n transition: \"all 0.2s ease\",\n }}\n >\n <div style={{ display: \"flex\", justifyContent: \"space-between\", gap: 16, marginBottom: 8 }}>\n <div style={{ flex: 1 }}>\n <div\n style={{\n fontSize: 14,\n fontWeight: 700,\n color: theme.text,\n fontFamily: \"'JetBrains Mono', monospace\",\n marginBottom: 6,\n }}\n >\n {heartbeat.name}\n </div>\n <div\n style={{\n fontSize: 12,\n color: theme.textMuted,\n lineHeight: 1.5,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n display: \"-webkit-box\",\n WebkitLineClamp: 2,\n WebkitBoxOrient: \"vertical\",\n }}\n >\n {heartbeat.check_prompt}\n </div>\n </div>\n <HeartbeatBadge enabled={heartbeat.enabled} />\n </div>\n\n <div\n style={{ display: \"flex\", justifyContent: \"space-between\", alignItems: \"center\", gap: 12 }}\n >\n <div style={{ display: \"flex\", gap: 6, flexWrap: \"wrap\" }}>\n <AgentBadge agent={heartbeat.default_agent} />\n {tags.map((tag, idx) => (\n <Tag key={idx}>{tag}</Tag>\n ))}\n </div>\n <div style={{ display: \"flex\", gap: 4 }} onClick={(e) => e.stopPropagation()}>\n <ActionBtn\n label=\"⚡\"\n title=\"Run now\"\n onClick={() => onAction(\"run\", heartbeat.id)}\n color={theme.orange}\n />\n <ActionBtn\n label=\"✎\"\n title=\"Edit\"\n onClick={() => onAction(\"edit\", heartbeat.id)}\n color={theme.blue}\n />\n {heartbeat.enabled ? (\n <ActionBtn\n label=\"❚❚\"\n title=\"Pause\"\n onClick={() => onAction(\"pause\", heartbeat.id)}\n color={theme.textMuted}\n />\n ) : (\n <ActionBtn\n label=\"▶\"\n title=\"Resume\"\n onClick={() => onAction(\"resume\", heartbeat.id)}\n color={theme.green}\n />\n )}\n <ActionBtn\n label=\"×\"\n title=\"Delete\"\n onClick={() => onAction(\"delete\", heartbeat.id)}\n color={theme.red}\n />\n </div>\n </div>\n\n <div\n style={{\n fontSize: 11,\n color: theme.textDim,\n marginTop: 10,\n fontFamily: \"monospace\",\n lineHeight: 1.6,\n }}\n >\n Next: {heartbeat.next_run_at ? formatTaskDateTime(heartbeat.next_run_at) : \"n/a\"}\n {\" · \"}\n Triggered:{\" \"}\n {heartbeat.last_triggered_at ? formatTaskDateTime(heartbeat.last_triggered_at) : \"never\"}\n </div>\n {heartbeat.last_error && (\n <div style={{ fontSize: 11, color: theme.red, marginTop: 6, lineHeight: 1.4 }}>\n Last error: {heartbeat.last_error}\n </div>\n )}\n </div>\n );\n}\n\nfunction HeartbeatDetailPanel({ heartbeat, ticks, onClose }) {\n const [selectedTickId, setSelectedTickId] = useState<any>(null);\n const [tickOutput, setTickOutput] = useState(\"\");\n const [tickRunning, setTickRunning] = useState(false);\n const outputRef = useRef<any>(null);\n\n useEffect(() => {\n setSelectedTickId(ticks[0]?.id || null);\n }, [heartbeat.id, ticks]);\n\n useEffect(() => {\n if (!selectedTickId) {\n setTickOutput(\"\");\n setTickRunning(false);\n return;\n }\n let cancelled = false;\n const load = async () => {\n try {\n const data = await fetchHeartbeatTickOutput(heartbeat.id, selectedTickId);\n if (cancelled) return;\n setTickOutput(data.output || \"\");\n setTickRunning(!!data.is_running);\n } catch {\n if (!cancelled) {\n setTickOutput(\"\");\n setTickRunning(false);\n }\n }\n };\n load();\n const interval = setInterval(load, 1000);\n return () => {\n cancelled = true;\n clearInterval(interval);\n };\n }, [heartbeat.id, selectedTickId]);\n\n useEffect(() => {\n if (outputRef.current) {\n outputRef.current.scrollTop = outputRef.current.scrollHeight;\n }\n }, [tickOutput]);\n\n return (\n <div\n style={{\n position: \"fixed\",\n top: 0,\n right: 0,\n width: 520,\n height: \"100vh\",\n background: theme.surface,\n borderLeft: `1px solid ${theme.border}`,\n boxShadow: \"-20px 0 60px rgba(0,0,0,0.4)\",\n zIndex: 500,\n display: \"flex\",\n flexDirection: \"column\",\n }}\n >\n <div\n style={{\n padding: \"22px 24px\",\n borderBottom: `1px solid ${theme.border}`,\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"flex-start\",\n gap: 12,\n }}\n >\n <div>\n <div\n style={{\n fontSize: 18,\n fontWeight: 700,\n color: theme.text,\n fontFamily: \"'JetBrains Mono', monospace\",\n }}\n >\n {heartbeat.name}\n </div>\n <div style={{ fontSize: 12, color: theme.textMuted, marginTop: 6 }}>\n {heartbeat.working_dir}\n </div>\n </div>\n <button\n onClick={onClose}\n style={{\n background: \"transparent\",\n border: \"none\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 22,\n lineHeight: 1,\n }}\n >\n ×\n </button>\n </div>\n <div style={{ padding: 24, overflow: \"auto\", flex: 1 }}>\n <div style={{ display: \"flex\", gap: 8, flexWrap: \"wrap\", marginBottom: 16 }}>\n <HeartbeatBadge enabled={heartbeat.enabled} />\n <AgentBadge agent={heartbeat.default_agent} />\n {heartbeat.schedule_type === \"interval\" ? (\n <Tag>⟳ {heartbeat.interval_seconds}s</Tag>\n ) : (\n <Tag>⏲ {heartbeat.cron_expr}</Tag>\n )}\n {heartbeat.last_decision && <Tag>{heartbeat.last_decision}</Tag>}\n </div>\n <div style={{ fontSize: 12, color: theme.textMuted, lineHeight: 1.7, marginBottom: 18 }}>\n <div>\n Next run: {heartbeat.next_run_at ? formatTaskDateTime(heartbeat.next_run_at) : \"n/a\"}\n </div>\n <div>\n Last tick:{\" \"}\n {heartbeat.last_tick_at ? formatTaskDateTime(heartbeat.last_tick_at) : \"never\"}\n </div>\n <div>\n Last trigger:{\" \"}\n {heartbeat.last_triggered_at\n ? formatTaskDateTime(heartbeat.last_triggered_at)\n : \"never\"}\n </div>\n <div>Cooldown: {heartbeat.cooldown_seconds || 0}s</div>\n </div>\n <div style={{ marginBottom: 20 }}>\n <div\n style={{\n fontSize: 11,\n fontWeight: 700,\n color: theme.textMuted,\n letterSpacing: 0.8,\n textTransform: \"uppercase\",\n marginBottom: 8,\n }}\n >\n Decision Prompt\n </div>\n <div\n style={{\n fontSize: 12,\n lineHeight: 1.7,\n color: theme.text,\n background: theme.bg,\n border: `1px solid ${theme.border}`,\n borderRadius: 10,\n padding: 14,\n whiteSpace: \"pre-wrap\",\n }}\n >\n {heartbeat.check_prompt}\n </div>\n </div>\n <div style={{ marginBottom: 20 }}>\n <div\n style={{\n fontSize: 11,\n fontWeight: 700,\n color: theme.textMuted,\n letterSpacing: 0.8,\n textTransform: \"uppercase\",\n marginBottom: 8,\n }}\n >\n Triggered Task Template\n </div>\n <div\n style={{\n fontSize: 12,\n lineHeight: 1.7,\n color: theme.text,\n background: theme.bg,\n border: `1px solid ${theme.border}`,\n borderRadius: 10,\n padding: 14,\n whiteSpace: \"pre-wrap\",\n }}\n >\n {heartbeat.action_prompt_template || \"No template configured\"}\n </div>\n </div>\n <div>\n <div\n style={{\n fontSize: 11,\n fontWeight: 700,\n color: theme.textMuted,\n letterSpacing: 0.8,\n textTransform: \"uppercase\",\n marginBottom: 8,\n }}\n >\n Recent Ticks\n </div>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 8 }}>\n {ticks.map((tick) => {\n let payload = null;\n try {\n payload = tick.decision_payload ? JSON.parse(tick.decision_payload) : null;\n } catch {}\n return (\n <div\n key={tick.id}\n style={{\n background: theme.bg,\n border: `1px solid ${theme.border}`,\n borderRadius: 10,\n padding: 12,\n cursor: \"pointer\",\n boxShadow:\n selectedTickId === tick.id ? `0 0 0 1px ${theme.accent} inset` : \"none\",\n }}\n >\n <div\n onClick={() => setSelectedTickId(tick.id)}\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n gap: 8,\n marginBottom: 6,\n }}\n >\n <div style={{ fontSize: 12, fontWeight: 600, color: theme.text }}>\n {tick.decision_type || tick.status}\n </div>\n <div style={{ fontSize: 11, color: theme.textDim, fontFamily: \"monospace\" }}>\n {tick.started_at ? formatTaskDateTime(tick.started_at) : \"\"}\n </div>\n </div>\n {payload?.reason && (\n <div style={{ fontSize: 12, color: theme.textMuted, lineHeight: 1.5 }}>\n {payload.reason}\n </div>\n )}\n {tick.error && (\n <div style={{ fontSize: 12, color: theme.red, lineHeight: 1.5 }}>\n {tick.error}\n </div>\n )}\n {tick.task_id && (\n <div\n style={{\n fontSize: 11,\n color: theme.accent,\n marginTop: 6,\n fontFamily: \"monospace\",\n }}\n >\n Triggered task #{tick.task_id}\n </div>\n )}\n </div>\n );\n })}\n {ticks.length === 0 && (\n <div\n style={{\n border: `1px dashed ${theme.border}`,\n borderRadius: 10,\n padding: 24,\n textAlign: \"center\",\n color: theme.textDim,\n fontSize: 12,\n }}\n >\n No ticks yet\n </div>\n )}\n </div>\n </div>\n <div style={{ marginTop: 20 }}>\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n marginBottom: 8,\n }}\n >\n <div\n style={{\n fontSize: 11,\n fontWeight: 700,\n color: theme.textMuted,\n letterSpacing: 0.8,\n textTransform: \"uppercase\",\n }}\n >\n Tick Log\n </div>\n {selectedTickId && (\n <div\n style={{\n fontSize: 11,\n color: tickRunning ? theme.orange : theme.textDim,\n fontFamily: \"monospace\",\n }}\n >\n {tickRunning ? \"LIVE\" : \"Stored\"} · tick #{selectedTickId}\n </div>\n )}\n </div>\n <div\n ref={outputRef}\n style={{\n background: theme.bg,\n border: `1px solid ${theme.border}`,\n borderRadius: 10,\n padding: 14,\n minHeight: 180,\n maxHeight: 320,\n overflow: \"auto\",\n fontFamily: \"'JetBrains Mono', monospace\",\n fontSize: 12,\n lineHeight: 1.6,\n whiteSpace: \"pre-wrap\",\n color: theme.text,\n }}\n >\n {selectedTickId\n ? tickOutput || \"No output captured for this tick.\"\n : \"Select a tick to view its log.\"}\n </div>\n </div>\n </div>\n </div>\n );\n}\n\nfunction NewTaskModal({ onClose, onSubmit, initialData, mode = \"create\" }) {\n const savedDir = localStorage.getItem(\"agentforge_working_dir\") || \"~/papers\";\n const [form, setForm] = useState(() => {\n if (initialData) {\n return {\n title: initialData.title || \"\",\n prompt: initialData.prompt || \"\",\n working_dir: initialData.working_dir || savedDir,\n schedule_type: initialData.schedule_type || \"immediate\",\n cron_expr: initialData.cron_expr || \"\",\n delay_seconds: initialData.delay_seconds || 60,\n scheduled_at: initialData.next_run_at\n ? formatDateTimeLocalInput(initialData.next_run_at)\n : \"\",\n max_runs: initialData.max_runs || \"\",\n tags: initialData.tags || \"\",\n agent: initialData.agent || DEFAULT_AGENT,\n dag_id: initialData.dag_id || \"\",\n };\n }\n return {\n title: \"\",\n prompt: \"\",\n working_dir: savedDir,\n schedule_type: \"immediate\",\n cron_expr: \"\",\n delay_seconds: 60,\n scheduled_at: \"\",\n max_runs: \"\",\n tags: \"\",\n agent: DEFAULT_AGENT,\n dag_id: \"\",\n };\n });\n const [promptImages, setPromptImages] = useState(() => {\n if (initialData?.prompt_images && Array.isArray(initialData.prompt_images)) {\n return initialData.prompt_images.map((img) => ({\n name: img.name || \"image\",\n media_type: img.media_type || \"image/jpeg\",\n data: img.data || \"\",\n preview: img.data ? `data:${img.media_type || \"image/jpeg\"};base64,${img.data}` : \"\",\n }));\n }\n return [];\n });\n // DAG dependencies: [{task_id, inject_result, _input}] — _input is the text box value\n const [depRows, setDepRows] = useState(() => {\n if (initialData?.dependencies && Array.isArray(initialData.dependencies)) {\n return initialData.dependencies.map((dep) => ({\n task_id: dep.depends_on_task_id,\n inject_result: !!dep.inject_result,\n _input: String(dep.depends_on_task_id),\n }));\n }\n return [];\n });\n const [scheduledAtError, setScheduledAtError] = useState(\"\");\n\n const set = (k, v) => setForm((prev) => ({ ...prev, [k]: v }));\n\n const handleImageSelect = (e) => {\n const files = Array.from(e.target.files || []);\n files.forEach((file: any) => {\n const reader = new FileReader();\n reader.onload = (ev) => {\n const dataUrl = ev.target.result as string; // \"data:image/jpeg;base64,...\"\n const [meta, data] = dataUrl.split(\",\");\n const media_type = meta.match(/:(.*?);/)?.[1] || \"image/jpeg\";\n setPromptImages((prev) => [\n ...prev,\n { name: file.name, media_type, data, preview: dataUrl },\n ]);\n };\n reader.readAsDataURL(file);\n });\n e.target.value = \"\";\n };\n\n const removeImage = (idx) => setPromptImages((prev) => prev.filter((_, i) => i !== idx));\n\n const handleSubmit = () => {\n if (!form.prompt.trim()) return;\n localStorage.setItem(\"agentforge_working_dir\", form.working_dir);\n\n // Build depends_on list (only valid numeric IDs)\n const depends_on = depRows\n .filter((r) => r.task_id)\n .map((r) => ({ task_id: r.task_id, inject_result: r.inject_result }));\n\n const data: any = {\n ...form,\n title: form.title || form.prompt.slice(0, 60),\n delay_seconds: form.schedule_type === \"delayed\" ? parseInt(form.delay_seconds) || 60 : null,\n cron_expr: form.schedule_type === \"cron\" ? form.cron_expr : null,\n max_runs: form.max_runs ? parseInt(form.max_runs) : null,\n prompt_images: promptImages.map(({ name, media_type, data }) => ({ name, media_type, data })),\n depends_on: mode === \"edit\" ? depends_on : depends_on.length > 0 ? depends_on : undefined,\n dag_id: form.dag_id || undefined,\n };\n\n // Handle scheduled_at: convert datetime-local to ISO timestamp\n if (form.schedule_type === \"scheduled_at\") {\n const localDate = parseTaskDateTime(form.scheduled_at);\n const serialized = serializeDateTimeLocalInput(form.scheduled_at);\n if (!form.scheduled_at || !serialized || !localDate || isNaN(localDate.getTime())) {\n setScheduledAtError(\"Please enter a valid date and time.\");\n return;\n }\n setScheduledAtError(\"\");\n data.next_run_at = serialized;\n }\n\n onSubmit(data);\n };\n\n const inputStyle: CSSProperties = {\n width: \"100%\",\n padding: \"10px 14px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n color: theme.text,\n fontSize: 13,\n outline: \"none\",\n boxSizing: \"border-box\",\n fontFamily: \"'JetBrains Mono', 'SF Mono', monospace\",\n transition: \"border-color 0.2s\",\n };\n\n const labelStyle = {\n fontSize: 11,\n fontWeight: 600,\n color: theme.textMuted,\n letterSpacing: 0.8,\n textTransform: \"uppercase\",\n marginBottom: 6,\n display: \"block\",\n };\n\n return (\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n background: \"rgba(0,0,0,0.7)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex: 1000,\n backdropFilter: \"blur(8px)\",\n }}\n onClick={onClose}\n >\n <div\n onClick={(e) => e.stopPropagation()}\n style={{\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 16,\n padding: 32,\n width: 520,\n maxHeight: \"80vh\",\n overflow: \"auto\",\n boxShadow: \"0 24px 80px rgba(0,0,0,0.5)\",\n }}\n >\n <h2\n style={{\n margin: \"0 0 24px\",\n fontSize: 18,\n fontWeight: 700,\n color: theme.text,\n fontFamily: \"'JetBrains Mono', monospace\",\n }}\n >\n {mode === \"edit\" ? \"Edit Task\" : mode === \"fork\" ? \"Fork Task\" : \"New Task\"}\n </h2>\n\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 16 }}>\n <div>\n <label style={labelStyle}>Title</label>\n <input\n style={inputStyle}\n placeholder=\"Task title...\"\n value={form.title}\n onChange={(e) => set(\"title\", e.target.value)}\n />\n </div>\n\n <div>\n <label style={labelStyle}>Prompt *</label>\n <textarea\n style={{ ...inputStyle, height: 100, resize: \"vertical\" }}\n placeholder=\"The prompt to send to Claude Code...\"\n value={form.prompt}\n onChange={(e) => set(\"prompt\", e.target.value)}\n />\n </div>\n\n <div>\n <label style={labelStyle}>Images (optional)</label>\n <div\n style={{\n display: \"flex\",\n flexWrap: \"wrap\",\n gap: 8,\n marginBottom: promptImages.length ? 8 : 0,\n }}\n >\n {promptImages.map((img, idx) => (\n <div key={idx} style={{ position: \"relative\", width: 72, height: 72 }}>\n <img\n src={img.preview}\n alt={img.name}\n style={{\n width: 72,\n height: 72,\n objectFit: \"cover\",\n borderRadius: 6,\n border: `1px solid ${theme.border}`,\n }}\n />\n <button\n onClick={() => removeImage(idx)}\n style={{\n position: \"absolute\",\n top: -6,\n right: -6,\n width: 18,\n height: 18,\n borderRadius: \"50%\",\n border: \"none\",\n background: theme.red || \"#e74c3c\",\n color: \"#fff\",\n fontSize: 11,\n cursor: \"pointer\",\n lineHeight: \"18px\",\n padding: 0,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n >\n ×\n </button>\n </div>\n ))}\n <label\n style={{\n width: 72,\n height: 72,\n borderRadius: 6,\n border: `1px dashed ${theme.border}`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"pointer\",\n color: theme.textDim,\n fontSize: 22,\n flexShrink: 0,\n }}\n >\n +\n <input\n type=\"file\"\n accept=\"image/*\"\n multiple\n style={{ display: \"none\" }}\n onChange={handleImageSelect}\n />\n </label>\n </div>\n {promptImages.length > 0 && (\n <div style={{ fontSize: 10, color: theme.textDim }}>\n {promptImages.length} image{promptImages.length > 1 ? \"s\" : \"\"} attached\n </div>\n )}\n </div>\n\n <div>\n <label style={labelStyle}>Working Directory</label>\n <div style={{ display: \"flex\", gap: 8 }}>\n <input\n style={{ ...inputStyle, flex: 1 }}\n placeholder=\"~/papers\"\n value={form.working_dir}\n onChange={(e) => set(\"working_dir\", e.target.value)}\n />\n {window.electronAPI?.selectDirectory && (\n <button\n onClick={async () => {\n const dir = await window.electronAPI.selectDirectory();\n if (dir) set(\"working_dir\", dir);\n }}\n style={{\n padding: \"8px 14px\",\n borderRadius: 8,\n cursor: \"pointer\",\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n color: theme.textMuted,\n fontSize: 12,\n fontWeight: 600,\n whiteSpace: \"nowrap\",\n transition: \"all 0.15s\",\n }}\n >\n Browse\n </button>\n )}\n </div>\n </div>\n\n <div>\n <label style={labelStyle}>Schedule Type</label>\n <div style={{ display: \"flex\", gap: 8, flexWrap: \"wrap\" }}>\n {[\"immediate\", \"delayed\", \"scheduled_at\", \"cron\"].map((t) => (\n <button\n key={t}\n onClick={() => set(\"schedule_type\", t)}\n style={{\n flex: 1,\n padding: \"8px 12px\",\n borderRadius: 8,\n cursor: \"pointer\",\n border: `1px solid ${form.schedule_type === t ? theme.accent : theme.border}`,\n background: form.schedule_type === t ? theme.accentGlow : \"transparent\",\n color: form.schedule_type === t ? theme.accent : theme.textMuted,\n fontSize: 12,\n fontWeight: 600,\n textTransform: \"capitalize\",\n transition: \"all 0.15s\",\n minWidth: 100,\n }}\n >\n {t === \"immediate\"\n ? \"⚡ Immediate\"\n : t === \"delayed\"\n ? \"⏳ Delayed\"\n : t === \"scheduled_at\"\n ? \"📅 At Time\"\n : \"⏲ Cron\"}\n </button>\n ))}\n </div>\n </div>\n\n {form.schedule_type === \"delayed\" && (\n <div>\n <label style={labelStyle}>Delay (seconds)</label>\n <input\n type=\"number\"\n style={inputStyle}\n value={form.delay_seconds}\n onChange={(e) => set(\"delay_seconds\", e.target.value)}\n />\n </div>\n )}\n\n {form.schedule_type === \"scheduled_at\" && (\n <div>\n <label style={labelStyle}>Run At (Local Time)</label>\n <input\n type=\"datetime-local\"\n style={inputStyle}\n value={form.scheduled_at}\n onChange={(e) => {\n set(\"scheduled_at\", e.target.value);\n setScheduledAtError(\"\");\n }}\n />\n {scheduledAtError && (\n <div style={{ fontSize: 11, color: \"#ff5f5f\", marginTop: 4 }}>\n {scheduledAtError}\n </div>\n )}\n <div style={{ fontSize: 10, color: theme.textDim, marginTop: 4 }}>\n Select a specific date and time to execute this task once\n </div>\n </div>\n )}\n\n {form.schedule_type === \"cron\" && (\n <>\n <div>\n <label style={labelStyle}>Cron Expression</label>\n <input\n style={inputStyle}\n placeholder=\"*/30 * * * *\"\n value={form.cron_expr}\n onChange={(e) => set(\"cron_expr\", e.target.value)}\n />\n <div style={{ fontSize: 10, color: theme.textDim, marginTop: 4 }}>\n e.g. \"0 9 * * *\" = daily 9am, \"*/30 * * * *\" = every 30 min\n </div>\n </div>\n <div>\n <label style={labelStyle}>Max Runs (empty = unlimited)</label>\n <input\n type=\"number\"\n style={inputStyle}\n value={form.max_runs}\n onChange={(e) => set(\"max_runs\", e.target.value)}\n />\n </div>\n </>\n )}\n\n <div>\n <label style={labelStyle}>Tags (comma separated)</label>\n <input\n style={inputStyle}\n placeholder=\"paper, review, arxiv\"\n value={form.tags}\n onChange={(e) => set(\"tags\", e.target.value)}\n />\n </div>\n\n {/* ── DAG Dependencies ── */}\n <div>\n <label style={labelStyle}>Dependencies (optional)</label>\n <div style={{ fontSize: 10, color: theme.textDim, marginBottom: 8 }}>\n This task will be blocked until all upstream tasks complete.\n </div>\n {depRows.map((row, idx) => (\n <div\n key={idx}\n style={{ display: \"flex\", gap: 6, alignItems: \"center\", marginBottom: 6 }}\n >\n <input\n type=\"number\"\n placeholder=\"Task ID\"\n value={row._input || \"\"}\n onChange={(e) => {\n const val = e.target.value;\n const parsed = parseInt(val);\n setDepRows((prev) =>\n prev.map((r, i) =>\n i === idx\n ? { ...r, _input: val, task_id: isNaN(parsed) ? null : parsed }\n : r,\n ),\n );\n }}\n style={{ ...inputStyle, width: 100, flex: \"none\" }}\n />\n <label\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 4,\n fontSize: 11,\n color: theme.textMuted,\n cursor: \"pointer\",\n flex: 1,\n }}\n >\n <input\n type=\"checkbox\"\n checked={row.inject_result}\n onChange={(e) =>\n setDepRows((prev) =>\n prev.map((r, i) =>\n i === idx ? { ...r, inject_result: e.target.checked } : r,\n ),\n )\n }\n style={{ accentColor: theme.accent }}\n />\n Inject result into prompt\n </label>\n <button\n onClick={() => setDepRows((prev) => prev.filter((_, i) => i !== idx))}\n style={{\n background: \"transparent\",\n border: \"none\",\n color: theme.red,\n cursor: \"pointer\",\n fontSize: 16,\n padding: \"0 4px\",\n }}\n >\n ×\n </button>\n </div>\n ))}\n <button\n onClick={() =>\n setDepRows((prev) => [...prev, { task_id: null, inject_result: false, _input: \"\" }])\n }\n style={{\n padding: \"5px 12px\",\n borderRadius: 6,\n border: `1px dashed ${theme.border}`,\n background: \"transparent\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 11,\n fontWeight: 600,\n }}\n >\n + Add dependency\n </button>\n </div>\n\n <div>\n <label style={labelStyle}>DAG ID (optional)</label>\n <input\n style={inputStyle}\n placeholder=\"my-pipeline\"\n value={form.dag_id}\n onChange={(e) => set(\"dag_id\", e.target.value)}\n />\n <div style={{ fontSize: 10, color: theme.textDim, marginTop: 4 }}>\n Group tasks into a named workflow\n </div>\n </div>\n\n <div>\n <label style={labelStyle}>Agent</label>\n <select\n style={inputStyle}\n value={form.agent}\n onChange={(e) => set(\"agent\", e.target.value)}\n >\n <option value=\"claude\">Claude Code (claude CLI)</option>\n <option value=\"codex\">Codex CLI (openai/codex)</option>\n </select>\n </div>\n </div>\n\n <div style={{ display: \"flex\", gap: 10, marginTop: 28, justifyContent: \"flex-end\" }}>\n <button\n onClick={onClose}\n style={{\n padding: \"10px 20px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: \"transparent\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n }}\n >\n Cancel\n </button>\n <button\n onClick={handleSubmit}\n style={{\n padding: \"10px 24px\",\n borderRadius: 8,\n border: \"none\",\n background: theme.accent,\n color: \"#fff\",\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n boxShadow: `0 0 20px ${theme.accentGlow}`,\n }}\n >\n {mode === \"edit\" ? \"Save Changes\" : mode === \"fork\" ? \"Create Fork\" : \"Create Task\"}\n </button>\n </div>\n </div>\n </div>\n );\n}\n\nfunction DetailPanel({ task, onClose, onResume }: any) {\n // `task` is always truthy here — the only caller renders this inside\n // `{detail && <DetailPanel task={... || detail} />}`. Hooks must stay\n // unconditional, so do not early-return before them.\n const [liveOutput, setLiveOutput] = useState(\"\");\n const [resumeText, setResumeText] = useState(\"\");\n const [resumeError, setResumeError] = useState(\"\");\n const [resumeSent, setResumeSent] = useState(false);\n const [messages, setMessages] = useState<any[]>([]);\n const [events, setEvents] = useState<any[]>([]);\n const [showMessages, setShowMessages] = useState(false);\n const [showEvents, setShowEvents] = useState(false);\n const [showLiveOutput, setShowLiveOutput] = useState(true);\n const liveOutputRef = useRef<any>(null);\n const messagesRef = useRef<any>(null);\n const eventsRef = useRef<any>(null);\n\n useEffect(() => {\n if (task.status !== \"running\") {\n setLiveOutput(\"\");\n return;\n }\n let cancelled = false;\n let lastOutputLength = 0;\n const poll = async () => {\n try {\n const res = await fetch(`${API}/tasks/${task.id}/output`);\n if (res.ok && !cancelled) {\n const data = await res.json();\n const currentOutput = data.output || \"\";\n // 增量更新:只添加新内容\n if (currentOutput.length > lastOutputLength) {\n const newContent = currentOutput.slice(lastOutputLength);\n setLiveOutput((prev) => prev + newContent);\n lastOutputLength = currentOutput.length;\n }\n }\n } catch {}\n };\n poll();\n const interval = setInterval(poll, 1000); // 缩短轮询间隔到1秒\n return () => {\n cancelled = true;\n clearInterval(interval);\n };\n }, [task.id, task.status]);\n\n useEffect(() => {\n if (liveOutputRef.current) {\n liveOutputRef.current.scrollTop = liveOutputRef.current.scrollHeight;\n }\n }, [liveOutput]);\n\n useEffect(() => {\n if (showMessages) {\n fetchTaskMessages(task.id).then(setMessages);\n }\n }, [task.id, showMessages]);\n\n useEffect(() => {\n if (!showEvents) return;\n let cancelled = false;\n const load = async () => {\n const nextEvents = await fetchTaskEvents(task.id);\n if (!cancelled) setEvents(nextEvents);\n };\n load();\n if (task.status !== \"running\") {\n return () => {\n cancelled = true;\n };\n }\n const interval = setInterval(load, 1000);\n return () => {\n cancelled = true;\n clearInterval(interval);\n };\n }, [task.id, task.status, showEvents]);\n\n useEffect(() => {\n if (messagesRef.current) {\n messagesRef.current.scrollTop = messagesRef.current.scrollHeight;\n }\n }, [messages]);\n\n const handleResume = async () => {\n if (!resumeText.trim()) return;\n setResumeError(\"\");\n const result = await resumeTask(task.id, resumeText.trim());\n if (result.error) {\n setResumeError(result.error);\n } else {\n setResumeText(\"\");\n setResumeSent(true);\n setTimeout(() => setResumeSent(false), 3000);\n onResume();\n }\n };\n\n return (\n <div\n style={{\n position: \"fixed\",\n right: 0,\n top: 0,\n bottom: 0,\n width: 480,\n background: theme.surface,\n borderLeft: `1px solid ${theme.border}`,\n zIndex: 999,\n overflow: \"auto\",\n padding: 28,\n boxShadow: \"-8px 0 40px rgba(0,0,0,0.4)\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n marginBottom: 24,\n }}\n >\n <Badge status={task.status} />\n <button\n onClick={onClose}\n style={{\n background: \"transparent\",\n border: \"none\",\n color: theme.textMuted,\n fontSize: 20,\n cursor: \"pointer\",\n }}\n >\n ×\n </button>\n </div>\n\n <h2\n style={{\n fontSize: 18,\n fontWeight: 700,\n color: theme.text,\n margin: \"0 0 8px\",\n fontFamily: \"'JetBrains Mono', monospace\",\n }}\n >\n {task.title}\n </h2>\n\n <div\n style={{ fontSize: 11, color: theme.textDim, marginBottom: 24, fontFamily: \"monospace\" }}\n >\n ID: {task.id} · Created: {formatTaskDateTime(task.created_at)}\n </div>\n\n <Section title=\"Prompt\">\n <pre\n style={{\n background: theme.bg,\n border: `1px solid ${theme.border}`,\n borderRadius: 8,\n padding: 14,\n fontSize: 12,\n color: theme.text,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n margin: 0,\n fontFamily: \"'JetBrains Mono', monospace\",\n lineHeight: 1.6,\n }}\n >\n {task.prompt}\n </pre>\n {task.prompt_images && task.prompt_images.length > 0 && (\n <div style={{ marginTop: 12 }}>\n <div\n style={{\n fontSize: 10,\n color: theme.textMuted,\n fontWeight: 600,\n letterSpacing: 0.8,\n textTransform: \"uppercase\",\n marginBottom: 8,\n }}\n >\n Attached Images ({task.prompt_images.length})\n </div>\n <div style={{ display: \"flex\", flexWrap: \"wrap\", gap: 8 }}>\n {task.prompt_images.map((img, i) => (\n <img\n key={i}\n src={`data:${img.media_type};base64,${img.data}`}\n alt={img.name || `image ${i + 1}`}\n style={{\n width: 80,\n height: 80,\n objectFit: \"cover\",\n borderRadius: 6,\n border: `1px solid ${theme.border}`,\n }}\n />\n ))}\n </div>\n </div>\n )}\n </Section>\n\n <Section title=\"Configuration\">\n <InfoRow label=\"Working Dir\" value={task.working_dir} />\n <InfoRow label=\"Agent\" value={task.agent || DEFAULT_AGENT} />\n <InfoRow label=\"Schedule\" value={task.schedule_type} />\n {task.cron_expr && <InfoRow label=\"Cron\" value={task.cron_expr} />}\n {task.delay_seconds && <InfoRow label=\"Delay\" value={`${task.delay_seconds}s`} />}\n {task.next_run_at && (\n <InfoRow label=\"Next Run\" value={formatTaskDateTime(task.next_run_at)} />\n )}\n <InfoRow\n label=\"Runs\"\n value={`${task.run_count}${task.max_runs ? ` / ${task.max_runs}` : \"\"}`}\n />\n {task.dag_id && <InfoRow label=\"DAG\" value={task.dag_id} />}\n </Section>\n\n {/* DAG dependency info */}\n {task.dependencies && task.dependencies.length > 0 && (\n <Section title=\"Upstream Dependencies\">\n {task.dependencies.map((dep) => (\n <div\n key={dep.id}\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n padding: \"5px 0\",\n borderBottom: `1px solid ${theme.border}`,\n fontSize: 12,\n }}\n >\n <span style={{ color: theme.text, fontFamily: \"monospace\" }}>\n #{dep.depends_on_task_id}\n {dep.depends_on_title ? ` — ${dep.depends_on_title}` : \"\"}\n </span>\n <div style={{ display: \"flex\", gap: 8, alignItems: \"center\" }}>\n {dep.inject_result ? (\n <span style={{ fontSize: 10, color: theme.accent }}>↳ inject</span>\n ) : null}\n <span\n style={{\n fontSize: 10,\n fontWeight: 600,\n color:\n dep.depends_on_status === \"completed\"\n ? theme.green\n : dep.depends_on_status === \"failed\"\n ? theme.red\n : theme.orange,\n }}\n >\n {dep.depends_on_status}\n </span>\n </div>\n </div>\n ))}\n </Section>\n )}\n\n {task.dependents && task.dependents.length > 0 && (\n <Section title=\"Downstream Tasks\">\n <div style={{ fontSize: 12, color: theme.textMuted, fontFamily: \"monospace\" }}>\n {task.dependents.map((id) => `#${id}`).join(\", \")}\n </div>\n </Section>\n )}\n\n {task.status === \"running\" && (\n <Section\n title={\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8 }}>\n <span>Live Output</span>\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n fontSize: 10,\n color: theme.blue,\n }}\n >\n <span\n style={{\n width: 6,\n height: 6,\n borderRadius: \"50%\",\n background: theme.blue,\n animation: \"pulse 1.2s ease-in-out infinite\",\n }}\n />\n live\n </div>\n </div>\n }\n >\n <div\n style={{\n background: theme.bg,\n border: `1px solid ${theme.borderActive}`,\n borderRadius: 8,\n overflow: \"hidden\",\n }}\n >\n {/* 工具栏 */}\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n padding: \"8px 12px\",\n background: theme.surface,\n borderBottom: `1px solid ${theme.border}`,\n fontSize: 11,\n color: theme.textMuted,\n }}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 12 }}>\n <button\n onClick={() => setShowLiveOutput(!showLiveOutput)}\n style={{\n background: \"transparent\",\n border: \"none\",\n color: theme.textMuted,\n fontSize: 11,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n gap: 4,\n }}\n >\n {showLiveOutput ? \"▼\" : \"▶\"} {showLiveOutput ? \"Hide\" : \"Show\"}\n </button>\n <span style={{ fontFamily: \"monospace\" }}>\n {liveOutput.length.toLocaleString()} chars\n </span>\n </div>\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8 }}>\n <button\n onClick={() => {\n navigator.clipboard.writeText(liveOutput);\n }}\n style={{\n background: \"transparent\",\n border: \"none\",\n color: theme.textMuted,\n fontSize: 11,\n cursor: \"pointer\",\n padding: \"4px 8px\",\n borderRadius: 4,\n fontFamily: \"'JetBrains Mono', monospace\",\n }}\n >\n 📋 Copy\n </button>\n <button\n onClick={() => setLiveOutput(\"\")}\n style={{\n background: \"transparent\",\n border: \"none\",\n color: theme.textMuted,\n fontSize: 11,\n cursor: \"pointer\",\n padding: \"4px 8px\",\n borderRadius: 4,\n fontFamily: \"'JetBrains Mono', monospace\",\n }}\n >\n 🗑️ Clear\n </button>\n </div>\n </div>\n\n {/* 输出内容区域 */}\n {showLiveOutput && (\n <div\n style={{\n maxHeight: 400,\n overflow: \"auto\",\n position: \"relative\",\n }}\n ref={liveOutputRef}\n >\n <pre\n style={{\n fontSize: 12,\n color: theme.text,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n margin: 0,\n padding: 14,\n fontFamily: \"'JetBrains Mono', monospace\",\n lineHeight: 1.6,\n minHeight: 60,\n }}\n >\n {liveOutput ? (\n <FormattedOutput content={liveOutput} theme={theme} />\n ) : (\n <span style={{ color: theme.textDim, fontStyle: \"italic\" }}>\n Waiting for agent output...\n </span>\n )}\n </pre>\n </div>\n )}\n </div>\n </Section>\n )}\n\n {task.result && (\n <Section title=\"Result\">\n <pre\n style={{\n background: theme.bg,\n border: `1px solid ${theme.border}`,\n borderRadius: 8,\n padding: 14,\n fontSize: 12,\n color: theme.green,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n margin: 0,\n fontFamily: \"'JetBrains Mono', monospace\",\n lineHeight: 1.6,\n maxHeight: 300,\n overflow: \"auto\",\n }}\n >\n {task.result}\n </pre>\n </Section>\n )}\n\n {task.error && (\n <Section title=\"Error\">\n <pre\n style={{\n background: theme.redBg,\n border: `1px solid rgba(248,113,113,0.2)`,\n borderRadius: 8,\n padding: 14,\n fontSize: 12,\n color: theme.red,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n margin: 0,\n fontFamily: \"'JetBrains Mono', monospace\",\n lineHeight: 1.6,\n }}\n >\n {task.error}\n </pre>\n </Section>\n )}\n\n {/* Output History Tabs */}\n <div style={{ marginBottom: 20 }}>\n <div style={{ display: \"flex\", gap: 8, marginBottom: 12 }}>\n <button\n onClick={() => {\n setShowMessages(!showMessages);\n setShowEvents(false);\n }}\n style={{\n flex: 1,\n padding: \"8px 12px\",\n borderRadius: 8,\n background: showMessages ? theme.accentGlow : theme.surface,\n color: showMessages ? theme.accent : theme.textMuted,\n fontSize: 11,\n fontWeight: 600,\n cursor: \"pointer\",\n border: `1px solid ${showMessages ? theme.accent : theme.border}`,\n transition: \"all 0.15s\",\n }}\n >\n Conversation\n </button>\n <button\n onClick={() => {\n setShowEvents(!showEvents);\n setShowMessages(false);\n }}\n style={{\n flex: 1,\n padding: \"8px 12px\",\n borderRadius: 8,\n background: showEvents ? theme.accentGlow : theme.surface,\n color: showEvents ? theme.accent : theme.textMuted,\n fontSize: 11,\n fontWeight: 600,\n cursor: \"pointer\",\n border: `1px solid ${showEvents ? theme.accent : theme.border}`,\n transition: \"all 0.15s\",\n }}\n >\n Execution Events\n </button>\n </div>\n\n {/* Conversation History */}\n {showMessages && (\n <div\n ref={messagesRef}\n style={{\n maxHeight: 400,\n overflow: \"auto\",\n display: \"flex\",\n flexDirection: \"column\",\n gap: 8,\n }}\n >\n {messages.length === 0 ? (\n <div\n style={{\n fontSize: 12,\n color: theme.textDim,\n padding: \"12px 0\",\n textAlign: \"center\",\n }}\n >\n No conversation data — only tasks run after this feature was added have logs.\n </div>\n ) : (\n messages.map((msg, i) => (\n <div\n key={i}\n style={{\n background: msg.role === \"user\" ? theme.accentGlow : theme.bg,\n border: `1px solid ${msg.role === \"user\" ? theme.accent + \"33\" : theme.border}`,\n borderRadius: 8,\n padding: \"10px 14px\",\n borderLeft: `3px solid ${msg.role === \"user\" ? theme.accent : theme.green}`,\n }}\n >\n <div\n style={{\n fontSize: 10,\n fontWeight: 700,\n letterSpacing: 0.8,\n color: msg.role === \"user\" ? theme.accent : theme.green,\n textTransform: \"uppercase\",\n marginBottom: 6,\n }}\n >\n {msg.role}\n </div>\n <pre\n style={{\n fontSize: 12,\n color: theme.text,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n margin: 0,\n fontFamily: \"'JetBrains Mono', monospace\",\n lineHeight: 1.6,\n maxHeight: 200,\n overflow: \"auto\",\n }}\n >\n {msg.text}\n </pre>\n </div>\n ))\n )}\n </div>\n )}\n\n {/* Execution Events History */}\n {showEvents && (\n <div ref={eventsRef} style={{ maxHeight: 520, overflow: \"auto\" }}>\n <ExecutionTimeline events={events} />\n </div>\n )}\n </div>\n\n {/* Resume completed/failed session */}\n {[\"completed\", \"failed\"].includes(task.status) && task.session_id && (\n <Section title=\"Resume Session\">\n <div\n style={{\n fontSize: 11,\n color: theme.textDim,\n marginBottom: 10,\n fontFamily: \"monospace\",\n }}\n >\n Session: {task.session_id}\n </div>\n <textarea\n placeholder=\"Send a follow-up message to continue this conversation…\"\n value={resumeText}\n onChange={(e) => setResumeText(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" && (e.metaKey || e.ctrlKey)) handleResume();\n }}\n style={{\n width: \"100%\",\n padding: \"10px 14px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n color: theme.text,\n fontSize: 13,\n outline: \"none\",\n boxSizing: \"border-box\",\n fontFamily: \"'JetBrains Mono', 'SF Mono', monospace\",\n resize: \"vertical\",\n minHeight: 80,\n }}\n />\n {resumeError && (\n <div style={{ fontSize: 11, color: theme.red, marginTop: 6 }}>{resumeError}</div>\n )}\n {resumeSent && (\n <div style={{ fontSize: 12, color: theme.green, marginTop: 6 }}>\n ✨ 已发送!任务正在重新唤醒,请稍候~\n </div>\n )}\n <button\n onClick={handleResume}\n style={{\n marginTop: 10,\n padding: \"8px 20px\",\n borderRadius: 8,\n border: \"none\",\n background: theme.accent,\n color: \"#fff\",\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n boxShadow: `0 0 20px ${theme.accentGlow}`,\n }}\n >\n ↩ Resume (⌘↵)\n </button>\n </Section>\n )}\n </div>\n );\n}\n\nfunction Section({ title, children }) {\n return (\n <div style={{ marginBottom: 20 }}>\n <div\n style={{\n fontSize: 10,\n fontWeight: 700,\n color: theme.textDim,\n letterSpacing: 1.2,\n textTransform: \"uppercase\",\n marginBottom: 10,\n }}\n >\n {title}\n </div>\n {children}\n </div>\n );\n}\n\nfunction InfoRow({ label, value }) {\n return (\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n padding: \"6px 0\",\n borderBottom: `1px solid ${theme.border}`,\n fontSize: 12,\n }}\n >\n <span style={{ color: theme.textMuted }}>{label}</span>\n <span style={{ color: theme.text, fontFamily: \"monospace\" }}>{value}</span>\n </div>\n );\n}\n\nfunction SettingsModal({\n onClose,\n timeout: initialTimeout,\n defaultAgent: initialDefaultAgent,\n onSave,\n feishu: initialFeishu,\n onFeishuSave,\n channelsStatus: initialChannelsStatus,\n onChannelsSave,\n}) {\n const [tab, setTab] = useState(\"general\");\n const [timeout, setTimeout] = useState(initialTimeout ?? DEFAULT_TIMEOUT_SECONDS);\n const [defaultAgent, setDefaultAgent] = useState(initialDefaultAgent ?? DEFAULT_AGENT);\n const [skillEnabled, setSkillEnabled] = useState(false);\n const [skillSweepAgent, setSkillSweepAgent] = useState(DEFAULT_AGENT);\n const [skillSweepCron, setSkillSweepCron] = useState(\"0 3 * * *\");\n const [feishu, setFeishu] = useState({\n feishu_app_id: \"\",\n feishu_app_secret: \"\",\n feishu_default_chat_id: \"\",\n feishu_default_working_dir: \"~\",\n feishu_enabled: \"false\",\n ...initialFeishu,\n });\n const [feishuSaving, setFeishuSaving] = useState(false);\n const [feishuMsg, setFeishuMsg] = useState<any>(null); // {ok, text}\n const [channels, setChannels] = useState(createInitialChannelsState(initialChannelsStatus));\n const [channelsSaving, setChannelsSaving] = useState(false);\n const [channelsMsg, setChannelsMsg] = useState<any>(null);\n const [weixinQrSrc, setWeixinQrSrc] = useState(\"\");\n const [weixinActionBusy, setWeixinActionBusy] = useState(false);\n const [collapsedChannels, setCollapsedChannels] = useState({\n telegram: true,\n slack: true,\n weixin: true,\n });\n\n // Refresh all channel settings when the modal opens so bot-side /dir changes are visible\n useEffect(() => {\n let cancelled = false;\n const refreshChannels = async (preserveUserEdits = true) => {\n const status = await fetchChannelsStatus();\n if (!cancelled) {\n setChannels((c) => {\n return mergeChannelsStatus(c, status, {\n preserveEditableFields: preserveUserEdits,\n });\n });\n }\n };\n refreshChannels(false); // initial load: full merge to populate fields\n const intervalId = setInterval(refreshChannels, 2000); // polling: preserve edits\n fetchFeishuSettings().then((s) => {\n if (s && Object.keys(s).length) setFeishu((f) => ({ ...f, ...s }));\n });\n fetchSettings().then((s) => {\n if (s && typeof s === \"object\") {\n if (typeof s.skill_library_enabled === \"boolean\") setSkillEnabled(s.skill_library_enabled);\n if (s.skill_sweep_agent) setSkillSweepAgent(s.skill_sweep_agent);\n if (s.skill_sweep_cron) setSkillSweepCron(s.skill_sweep_cron);\n }\n });\n return () => {\n cancelled = true;\n clearInterval(intervalId);\n };\n }, []);\n\n useEffect(() => {\n let cancelled = false;\n const qrValue = channels.weixin?.qr_code_url || \"\";\n if (!qrValue) {\n setWeixinQrSrc(\"\");\n return () => {\n cancelled = true;\n };\n }\n\n if (isWeixinQrImageSource(qrValue)) {\n setWeixinQrSrc(qrValue);\n return () => {\n cancelled = true;\n };\n }\n\n QRCode.toDataURL(qrValue, {\n errorCorrectionLevel: \"M\",\n margin: 2,\n width: 440,\n })\n .then((dataUrl) => {\n if (!cancelled) setWeixinQrSrc(dataUrl);\n })\n .catch((error) => {\n console.error(\"Failed to generate Weixin QR code\", error);\n if (!cancelled) setWeixinQrSrc(\"\");\n });\n\n return () => {\n cancelled = true;\n };\n }, [channels.weixin?.qr_code_url]);\n\n const handleWeixinAction = async (action) => {\n setWeixinActionBusy(true);\n setChannelsMsg(null);\n try {\n await runWeixinAction(action);\n const updated = await fetchChannelsStatus();\n setChannels((c) => mergeChannelsStatus(c, updated));\n if (onChannelsSave) onChannelsSave(updated);\n setChannelsMsg({\n ok: true,\n text: action === \"logout\" ? \"Wechat logged out.\" : \"Wechat login restarted.\",\n });\n } catch (e) {\n setChannelsMsg({ ok: false, text: String(e) });\n } finally {\n setWeixinActionBusy(false);\n }\n };\n\n const handleSaveGeneral = async () => {\n await updateSettings({\n timeout: parseInt(timeout) || DEFAULT_TIMEOUT_SECONDS,\n default_agent: defaultAgent,\n skill_library_enabled: skillEnabled ? \"1\" : \"0\",\n skill_sweep_agent: skillSweepAgent,\n skill_sweep_cron: skillSweepCron,\n });\n onSave(parseInt(timeout) || DEFAULT_TIMEOUT_SECONDS, defaultAgent);\n onClose();\n };\n\n const handleSaveFeishu = async () => {\n setFeishuSaving(true);\n setFeishuMsg(null);\n try {\n await updateFeishuSettings(feishu);\n setFeishuMsg({ ok: true, text: \"Saved. Bridge restarted.\" });\n // Reload settings after save\n if (onFeishuSave) {\n const updated = await fetchFeishuSettings();\n onFeishuSave(updated);\n }\n } catch (e) {\n setFeishuMsg({ ok: false, text: String(e) });\n } finally {\n setFeishuSaving(false);\n }\n };\n\n const handleSaveChannels = async () => {\n setChannelsSaving(true);\n setChannelsMsg(null);\n try {\n await updateChannelsSettings(buildChannelsSavePayload(channels));\n // Reload channel status after save to reflect new running state\n const updated = await fetchChannelsStatus();\n setChannels((c) => mergeChannelsStatus(c, updated));\n if (onChannelsSave) onChannelsSave(updated);\n setChannelsMsg({ ok: true, text: \"Saved. Channels restarted.\" });\n } catch (e) {\n setChannelsMsg({ ok: false, text: String(e) });\n } finally {\n setChannelsSaving(false);\n }\n };\n\n const fieldStyle: CSSProperties = {\n width: \"100%\",\n padding: \"10px 14px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n color: theme.text,\n fontSize: 13,\n outline: \"none\",\n boxSizing: \"border-box\",\n fontFamily: \"'JetBrains Mono', 'SF Mono', monospace\",\n };\n const labelStyle = {\n fontSize: 11,\n fontWeight: 600,\n color: theme.textMuted,\n letterSpacing: 0.8,\n textTransform: \"uppercase\",\n marginBottom: 8,\n display: \"block\",\n };\n const hintStyle = { fontSize: 10, color: theme.textDim, marginTop: 4 };\n\n const tabs = [\"general\", \"channels\", \"feishu\"];\n const tabLabel = { general: \"General\", channels: \"Channels\", feishu: \"Feishu / Lark\" };\n\n return (\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n background: \"rgba(0,0,0,0.7)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex: 1000,\n backdropFilter: \"blur(8px)\",\n }}\n onClick={onClose}\n >\n <div\n onClick={(e) => e.stopPropagation()}\n style={{\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 16,\n padding: 32,\n width: 480,\n maxHeight: \"85vh\",\n overflowY: \"auto\",\n boxShadow: \"0 24px 80px rgba(0,0,0,0.5)\",\n }}\n >\n <h2\n style={{\n margin: \"0 0 20px\",\n fontSize: 18,\n fontWeight: 700,\n color: theme.text,\n fontFamily: \"'JetBrains Mono', monospace\",\n }}\n >\n Settings\n </h2>\n\n {/* Tab bar */}\n <div\n style={{\n display: \"flex\",\n gap: 4,\n marginBottom: 24,\n borderBottom: `1px solid ${theme.border}`,\n paddingBottom: 0,\n }}\n >\n {tabs.map((t) => (\n <button\n key={t}\n onClick={() => setTab(t)}\n style={{\n padding: \"7px 16px\",\n borderRadius: \"8px 8px 0 0\",\n border: \"none\",\n cursor: \"pointer\",\n fontSize: 12,\n fontWeight: 600,\n background: tab === t ? theme.bg : \"transparent\",\n color: tab === t ? theme.text : theme.textMuted,\n borderBottom: tab === t ? `2px solid ${theme.accent}` : \"2px solid transparent\",\n marginBottom: -1,\n }}\n >\n {tabLabel[t]}\n </button>\n ))}\n </div>\n\n {/* ── General tab ── */}\n {tab === \"general\" && (\n <>\n <div style={{ marginBottom: 20 }}>\n <label style={labelStyle}>Task Timeout (seconds)</label>\n <input\n type=\"number\"\n min=\"10\"\n step=\"10\"\n value={timeout}\n onChange={(e) => setTimeout(e.target.value)}\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Default: 12000s (200 min). Max time before a running task is killed.\n </div>\n </div>\n <div style={{ marginBottom: 20 }}>\n <label style={labelStyle}>Default Agent</label>\n <select\n value={defaultAgent}\n onChange={(e) => setDefaultAgent(e.target.value)}\n style={fieldStyle}\n >\n <option value=\"claude\">Claude Code (claude CLI)</option>\n <option value=\"codex\">Codex CLI (openai/codex)</option>\n </select>\n <div style={hintStyle}>Agent used for new tasks unless overridden per-task.</div>\n </div>\n\n {/* ── Skill Library ── */}\n <div\n style={{\n marginBottom: 20,\n paddingTop: 16,\n borderTop: `1px solid ${theme.border}`,\n }}\n >\n <label\n style={{\n ...labelStyle,\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n cursor: \"pointer\",\n }}\n >\n <input\n type=\"checkbox\"\n checked={skillEnabled}\n onChange={(e) => setSkillEnabled(e.target.checked)}\n style={{ width: 16, height: 16, cursor: \"pointer\" }}\n />\n Skill Library 自动扫描\n </label>\n <div style={hintStyle}>\n 定时让 agent 扫描已完成任务、检测复发模式(消耗 token,默认关闭)。\n 手动「扫一遍」按钮不受此开关影响。\n </div>\n </div>\n {skillEnabled && (\n <>\n <div style={{ marginBottom: 20 }}>\n <label style={labelStyle}>扫描 Agent</label>\n <select\n value={skillSweepAgent}\n onChange={(e) => setSkillSweepAgent(e.target.value)}\n style={fieldStyle}\n >\n <option value=\"claude\">Claude Code (claude CLI)</option>\n <option value=\"codex\">Codex CLI (openai/codex)</option>\n </select>\n <div style={hintStyle}>运行 sweep 的 agent。</div>\n </div>\n <div style={{ marginBottom: 20 }}>\n <label style={labelStyle}>扫描节奏 (cron)</label>\n <input\n value={skillSweepCron}\n onChange={(e) => setSkillSweepCron(e.target.value)}\n placeholder=\"0 3 * * *\"\n style={{ ...fieldStyle, fontFamily: \"monospace\" }}\n />\n <div style={hintStyle}>默认每日凌晨 3 点。增量扫描,只看上次以来的新任务。</div>\n </div>\n </>\n )}\n\n <div style={{ display: \"flex\", gap: 10, justifyContent: \"flex-end\" }}>\n <button\n onClick={onClose}\n style={{\n padding: \"10px 20px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: \"transparent\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n }}\n >\n Cancel\n </button>\n <button\n onClick={handleSaveGeneral}\n style={{\n padding: \"10px 24px\",\n borderRadius: 8,\n border: \"none\",\n background: theme.accent,\n color: \"#fff\",\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n boxShadow: `0 0 20px ${theme.accentGlow}`,\n }}\n >\n Save\n </button>\n </div>\n </>\n )}\n\n {/* ── Channels tab ── */}\n {tab === \"channels\" && (\n <>\n {/* ── Telegram ── */}\n {(() => {\n const ch = channels.telegram;\n const collapsed = collapsedChannels.telegram;\n const statusDot = ch.running\n ? { bg: theme.green, label: \"Connected\" }\n : ch.configured\n ? { bg: theme.yellow || \"#f59e0b\", label: \"Configured (not running)\" }\n : { bg: theme.textDim, label: \"Not configured\" };\n return (\n <div\n style={{\n marginBottom: 16,\n borderRadius: 10,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n overflow: \"hidden\",\n }}\n >\n {/* Header row - clickable to collapse */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n padding: \"12px 16px\",\n cursor: \"pointer\",\n userSelect: \"none\",\n }}\n onClick={() => setCollapsedChannels((c) => ({ ...c, telegram: !c.telegram }))}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 10 }}>\n <span\n style={{\n fontSize: 10,\n color: theme.textMuted,\n transition: \"transform 0.2s\",\n transform: collapsed ? \"rotate(-90deg)\" : \"rotate(0deg)\",\n display: \"inline-block\",\n }}\n >\n {\"▼\"}\n </span>\n <span\n style={{\n display: \"inline-flex\",\n width: 22,\n height: 22,\n alignItems: \"center\",\n justifyContent: \"center\",\n color: \"#2AABEE\",\n flexShrink: 0,\n }}\n >\n <svg\n viewBox=\"0 0 24 24\"\n width=\"22\"\n height=\"22\"\n aria-hidden=\"true\"\n fill=\"currentColor\"\n >\n <path d=\"M21.4 4.6a1.2 1.2 0 0 0-1.24-.2L3.8 11.15c-.6.25-.57 1.12.05 1.33l4.6 1.62 1.62 4.6c.22.62 1.08.65 1.33.05l6.75-16.36a1.2 1.2 0 0 0-.2-1.24 1.18 1.18 0 0 0-1.22-.3Z\" />\n </svg>\n </span>\n <span style={{ fontWeight: 700, fontSize: 14, color: theme.text }}>\n Telegram\n </span>\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 6, marginLeft: 8 }}>\n <span\n style={{\n width: 8,\n height: 8,\n borderRadius: \"50%\",\n background: statusDot.bg,\n display: \"inline-block\",\n boxShadow: ch.running ? `0 0 6px ${statusDot.bg}` : \"none\",\n }}\n />\n <span style={{ fontSize: 11, color: theme.textMuted }}>\n {statusDot.label}\n </span>\n </div>\n </div>\n <button\n onClick={(e) => {\n e.stopPropagation();\n setChannels((c) => ({\n ...c,\n telegram: { ...c.telegram, enabled: !c.telegram.enabled },\n }));\n }}\n style={{\n width: 44,\n height: 24,\n borderRadius: 12,\n border: \"none\",\n cursor: \"pointer\",\n background: ch.enabled ? theme.accent : theme.border,\n position: \"relative\",\n transition: \"background 0.2s\",\n flexShrink: 0,\n }}\n >\n <span\n style={{\n position: \"absolute\",\n top: 3,\n width: 18,\n height: 18,\n borderRadius: \"50%\",\n background: \"#fff\",\n transition: \"left 0.2s\",\n left: ch.enabled ? 23 : 3,\n }}\n />\n </button>\n </div>\n\n {/* Collapsible body */}\n {!collapsed && (\n <div style={{ padding: \"0 16px 16px\" }}>\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Bot Token</label>\n <input\n type=\"password\"\n value={ch.bot_token}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n telegram: { ...c.telegram, bot_token: e.target.value },\n }))\n }\n placeholder=\"123456:ABC-DEF...\"\n style={fieldStyle}\n />\n <div style={hintStyle}>Token from @BotFather</div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Allowed User IDs</label>\n <input\n value={ch.allowed_users}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n telegram: { ...c.telegram, allowed_users: e.target.value },\n }))\n }\n placeholder=\"123456789,987654321 (optional)\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Comma-separated numeric Telegram user IDs. Leave empty to allow all.\n </div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Default Working Directory</label>\n <input\n value={ch.default_working_dir}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n telegram: { ...c.telegram, default_working_dir: e.target.value },\n }))\n }\n placeholder=\"~/my-project\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Working directory for tasks created via the Telegram bot.\n </div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Default Notification Chat ID</label>\n <input\n value={ch.default_chat_id}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n telegram: { ...c.telegram, default_chat_id: e.target.value },\n }))\n }\n placeholder=\"-1001234567890 or 123456789\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Fallback chat for notifications from UI-created tasks (group or user chat\n ID).\n </div>\n </div>\n\n <div\n style={{\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 6,\n padding: \"10px 12px\",\n fontSize: 11,\n fontFamily: \"monospace\",\n color: theme.textMuted,\n lineHeight: 1.8,\n }}\n >\n <div style={{ color: theme.textDim, marginBottom: 4 }}>Bot commands:</div>\n {[\n \"/newtask <title> | <prompt>\",\n \"/list\",\n \"/status <id>\",\n \"/cancel <id>\",\n ].map((cmd) => (\n <div key={cmd}>\n <span style={{ color: theme.cyan }}>{cmd}</span>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n );\n })()}\n\n {/* ── Slack ── */}\n {(() => {\n const ch = channels.slack;\n const collapsed = collapsedChannels.slack;\n const statusDot = ch.running\n ? { bg: theme.green, label: \"Connected\" }\n : ch.configured\n ? { bg: theme.yellow || \"#f59e0b\", label: \"Configured (not running)\" }\n : { bg: theme.textDim, label: \"Not configured\" };\n return (\n <div\n style={{\n marginBottom: 16,\n borderRadius: 10,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n overflow: \"hidden\",\n }}\n >\n {/* Header row - clickable to collapse */}\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n padding: \"12px 16px\",\n cursor: \"pointer\",\n userSelect: \"none\",\n }}\n onClick={() => setCollapsedChannels((c) => ({ ...c, slack: !c.slack }))}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 10 }}>\n <span\n style={{\n fontSize: 10,\n color: theme.textMuted,\n transition: \"transform 0.2s\",\n transform: collapsed ? \"rotate(-90deg)\" : \"rotate(0deg)\",\n display: \"inline-block\",\n }}\n >\n {\"▼\"}\n </span>\n <span\n style={{\n display: \"inline-flex\",\n width: 22,\n height: 22,\n alignItems: \"center\",\n justifyContent: \"center\",\n flexShrink: 0,\n }}\n >\n <svg viewBox=\"0 0 24 24\" width=\"22\" height=\"22\" aria-hidden=\"true\">\n <path\n fill=\"#36C5F0\"\n d=\"M10.1 3.2A2.2 2.2 0 0 1 12.2 1h.7v5.1h-2.8V3.2Z\"\n />\n <path\n fill=\"#2EB67D\"\n d=\"M20.8 10.1A2.2 2.2 0 0 1 23 12.2v.7h-5.1v-2.8h2.9Z\"\n />\n <path\n fill=\"#ECB22E\"\n d=\"M13.9 20.8A2.2 2.2 0 0 1 11.8 23h-.7v-5.1h2.8v2.9Z\"\n />\n <path\n fill=\"#E01E5A\"\n d=\"M3.2 13.9A2.2 2.2 0 0 1 1 11.8v-.7h5.1v2.8H3.2Z\"\n />\n <path\n fill=\"#36C5F0\"\n d=\"M13.2 4.3a2.7 2.7 0 1 1 5.4 0 2.7 2.7 0 0 1-5.4 0Z\"\n />\n <path\n fill=\"#2EB67D\"\n d=\"M16.9 13.2a2.7 2.7 0 1 1 0 5.4 2.7 2.7 0 0 1 0-5.4Z\"\n />\n <path\n fill=\"#ECB22E\"\n d=\"M5.4 16.9a2.7 2.7 0 1 1 5.4 0 2.7 2.7 0 0 1-5.4 0Z\"\n />\n <path\n fill=\"#E01E5A\"\n d=\"M4.3 5.4a2.7 2.7 0 1 1 0 5.4 2.7 2.7 0 0 1 0-5.4Z\"\n />\n </svg>\n </span>\n <span style={{ fontWeight: 700, fontSize: 14, color: theme.text }}>\n Slack\n </span>\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 6, marginLeft: 8 }}>\n <span\n style={{\n width: 8,\n height: 8,\n borderRadius: \"50%\",\n background: statusDot.bg,\n display: \"inline-block\",\n boxShadow: ch.running ? `0 0 6px ${statusDot.bg}` : \"none\",\n }}\n />\n <span style={{ fontSize: 11, color: theme.textMuted }}>\n {statusDot.label}\n </span>\n </div>\n </div>\n <button\n onClick={(e) => {\n e.stopPropagation();\n setChannels((c) => ({\n ...c,\n slack: { ...c.slack, enabled: !c.slack.enabled },\n }));\n }}\n style={{\n width: 44,\n height: 24,\n borderRadius: 12,\n border: \"none\",\n cursor: \"pointer\",\n background: ch.enabled ? theme.accent : theme.border,\n position: \"relative\",\n transition: \"background 0.2s\",\n flexShrink: 0,\n }}\n >\n <span\n style={{\n position: \"absolute\",\n top: 3,\n width: 18,\n height: 18,\n borderRadius: \"50%\",\n background: \"#fff\",\n transition: \"left 0.2s\",\n left: ch.enabled ? 23 : 3,\n }}\n />\n </button>\n </div>\n\n {/* Collapsible body */}\n {!collapsed && (\n <div style={{ padding: \"0 16px 16px\" }}>\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Bot Token</label>\n <input\n type=\"password\"\n value={ch.bot_token}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n slack: { ...c.slack, bot_token: e.target.value },\n }))\n }\n placeholder=\"xoxb-...\"\n style={fieldStyle}\n />\n <div style={hintStyle}>Bot token from OAuth & Permissions</div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>App Token</label>\n <input\n type=\"password\"\n value={ch.app_token}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n slack: { ...c.slack, app_token: e.target.value },\n }))\n }\n placeholder=\"xapp-...\"\n style={fieldStyle}\n />\n <div style={hintStyle}>App-level token for Socket Mode</div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Default Working Directory</label>\n <input\n value={ch.default_working_dir}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n slack: { ...c.slack, default_working_dir: e.target.value },\n }))\n }\n placeholder=\"~/my-project\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Working directory for tasks created via the Slack bot.\n </div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Default DM User</label>\n <input\n value={ch.default_user}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n slack: { ...c.slack, default_user: e.target.value },\n }))\n }\n placeholder=\"U0123456789\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Slack user ID to DM when tasks have no origin thread (e.g. subtasks\n created via API). Find your ID in Slack profile → ⋯ → Copy member ID.\n </div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Default Notification Channel</label>\n <input\n value={ch.default_channel}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n slack: { ...c.slack, default_channel: e.target.value },\n }))\n }\n placeholder=\"#general or C0123456789\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Optional. Fallback channel if Default DM User is not set.\n </div>\n </div>\n\n <div\n style={{\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 6,\n padding: \"10px 12px\",\n fontSize: 11,\n fontFamily: \"monospace\",\n color: theme.textMuted,\n lineHeight: 1.8,\n }}\n >\n <div style={{ color: theme.textDim, marginBottom: 4 }}>Bot commands:</div>\n {[\n \"newtask <title> | <prompt>\",\n \"list\",\n \"status <id>\",\n \"cancel <id>\",\n \"help\",\n ].map((cmd) => (\n <div key={cmd}>\n <span style={{ color: theme.cyan }}>{cmd}</span>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n );\n })()}\n\n {/* ── Weixin ── */}\n {(() => {\n const ch = channels.weixin;\n const collapsed = collapsedChannels.weixin;\n const statusLabelMap = {\n idle: \"Idle\",\n waiting_for_scan: \"Waiting for scan\",\n scanned: \"Scanned on phone\",\n connected: \"Connected\",\n error: \"Error\",\n };\n const statusDot = ch.running\n ? { bg: theme.green, label: statusLabelMap[ch.login_status] || \"Connected\" }\n : ch.login_status === \"waiting_for_scan\" || ch.login_status === \"scanned\"\n ? { bg: theme.orange || \"#f59e0b\", label: statusLabelMap[ch.login_status] }\n : ch.login_status === \"error\"\n ? { bg: theme.red, label: \"Error\" }\n : ch.configured\n ? { bg: theme.yellow || \"#f59e0b\", label: \"Configured\" }\n : { bg: theme.textDim, label: \"Login required\" };\n return (\n <div\n style={{\n marginBottom: 16,\n borderRadius: 10,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n overflow: \"hidden\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n padding: \"12px 16px\",\n cursor: \"pointer\",\n userSelect: \"none\",\n }}\n onClick={() => setCollapsedChannels((c) => ({ ...c, weixin: !c.weixin }))}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 10 }}>\n <span\n style={{\n fontSize: 10,\n color: theme.textMuted,\n transition: \"transform 0.2s\",\n transform: collapsed ? \"rotate(-90deg)\" : \"rotate(0deg)\",\n display: \"inline-block\",\n }}\n >\n {\"▼\"}\n </span>\n <span\n style={{\n display: \"inline-flex\",\n width: 22,\n height: 22,\n alignItems: \"center\",\n justifyContent: \"center\",\n color: \"#07C160\",\n flexShrink: 0,\n }}\n >\n <svg\n viewBox=\"0 0 24 24\"\n width=\"22\"\n height=\"22\"\n aria-hidden=\"true\"\n fill=\"currentColor\"\n >\n <path d=\"M9.2 4.2c-4 0-7.2 2.6-7.2 5.9 0 1.9 1.1 3.6 2.9 4.7l-.9 2.5 2.9-1.5c.7.1 1.4.2 2.2.2 4 0 7.2-2.6 7.2-5.9S13.2 4.2 9.2 4.2Zm-2.7 4.8a.9.9 0 1 1 0-1.8.9.9 0 0 1 0 1.8Zm5.4 0a.9.9 0 1 1 0-1.8.9.9 0 0 1 0 1.8Z\" />\n <path\n d=\"M16.8 9.1c-3 0-5.5 2-5.5 4.5 0 2.5 2.4 4.5 5.5 4.5.6 0 1.2-.1 1.8-.2l2.4 1.2-.7-2c1.5-.8 2.5-2.1 2.5-3.6 0-2.5-2.4-4.4-5.5-4.4Zm-1.9 4a.7.7 0 1 1 0-1.4.7.7 0 0 1 0 1.4Zm3.8 0a.7.7 0 1 1 0-1.4.7.7 0 0 1 0 1.4Z\"\n opacity=\"0.88\"\n />\n </svg>\n </span>\n <span style={{ fontWeight: 700, fontSize: 14, color: theme.text }}>\n Wechat\n </span>\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 6, marginLeft: 8 }}>\n <span\n style={{\n width: 8,\n height: 8,\n borderRadius: \"50%\",\n background: statusDot.bg,\n display: \"inline-block\",\n boxShadow: ch.running ? `0 0 6px ${statusDot.bg}` : \"none\",\n }}\n />\n <span style={{ fontSize: 11, color: theme.textMuted }}>\n {statusDot.label}\n </span>\n </div>\n </div>\n <button\n onClick={(e) => {\n e.stopPropagation();\n setChannels((c) => ({\n ...c,\n weixin: { ...c.weixin, enabled: !c.weixin.enabled },\n }));\n }}\n style={{\n width: 44,\n height: 24,\n borderRadius: 12,\n border: \"none\",\n cursor: \"pointer\",\n background: ch.enabled ? theme.accent : theme.border,\n position: \"relative\",\n transition: \"background 0.2s\",\n flexShrink: 0,\n }}\n >\n <span\n style={{\n position: \"absolute\",\n top: 3,\n width: 18,\n height: 18,\n borderRadius: \"50%\",\n background: \"#fff\",\n transition: \"left 0.2s\",\n left: ch.enabled ? 23 : 3,\n }}\n />\n </button>\n </div>\n\n {!collapsed && (\n <div style={{ padding: \"0 16px 16px\" }}>\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Default Working Directory</label>\n <input\n value={ch.default_working_dir}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n weixin: { ...c.weixin, default_working_dir: e.target.value },\n }))\n }\n placeholder=\"~/my-project\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Working directory for tasks created from incoming Weixin messages.\n </div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Base URL</label>\n <input\n value={ch.base_url}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n weixin: { ...c.weixin, base_url: e.target.value },\n }))\n }\n placeholder=\"https://ilinkai.weixin.qq.com\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Gateway API base URL used for QR login, long-polling, and sendmessage.\n </div>\n </div>\n\n <div style={{ marginBottom: 12 }}>\n <label style={labelStyle}>Account ID</label>\n <input\n value={ch.account_id}\n onChange={(e) =>\n setChannels((c) => ({\n ...c,\n weixin: { ...c.weixin, account_id: e.target.value },\n }))\n }\n placeholder=\"Optional fixed account id\"\n style={fieldStyle}\n />\n <div style={hintStyle}>\n Optional. Leave empty to let the bridge adopt the account id returned by\n QR login.\n </div>\n </div>\n\n <div style={{ display: \"flex\", gap: 8, marginBottom: 12 }}>\n <button\n onClick={() => handleWeixinAction(\"reconnect\")}\n disabled={weixinActionBusy}\n style={{\n padding: \"9px 14px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: theme.surface,\n color: theme.text,\n cursor: weixinActionBusy ? \"not-allowed\" : \"pointer\",\n fontSize: 12,\n fontWeight: 600,\n opacity: weixinActionBusy ? 0.6 : 1,\n }}\n >\n Reconnect\n </button>\n <button\n onClick={() => handleWeixinAction(\"logout\")}\n disabled={weixinActionBusy}\n style={{\n padding: \"9px 14px\",\n borderRadius: 8,\n border: `1px solid ${theme.red}`,\n background: theme.redBg,\n color: theme.red,\n cursor: weixinActionBusy ? \"not-allowed\" : \"pointer\",\n fontSize: 12,\n fontWeight: 600,\n opacity: weixinActionBusy ? 0.6 : 1,\n }}\n >\n Logout\n </button>\n </div>\n\n {(ch.qr_code_url ||\n ch.login_status === \"waiting_for_scan\" ||\n ch.login_status === \"scanned\" ||\n ch.last_error) && (\n <div\n style={{\n marginBottom: 12,\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: theme.surface,\n padding: 12,\n }}\n >\n <div\n style={{\n fontSize: 12,\n fontWeight: 700,\n color: theme.text,\n marginBottom: 8,\n }}\n >\n Weixin Login Status\n </div>\n <div\n style={{\n fontSize: 11,\n color: theme.textMuted,\n marginBottom: ch.qr_code_url ? 10 : 0,\n }}\n >\n {statusLabelMap[ch.login_status] || \"Idle\"}\n {ch.user_id ? ` · ${ch.user_id}` : \"\"}\n </div>\n {ch.account_id && (\n <div style={{ fontSize: 11, color: theme.textMuted, marginBottom: 10 }}>\n Account ID: {ch.account_id}\n </div>\n )}\n {weixinQrSrc && (\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 8 }}>\n <img\n src={weixinQrSrc}\n alt=\"Weixin QR code\"\n style={{\n width: 220,\n height: 220,\n objectFit: \"contain\",\n borderRadius: 10,\n border: `1px solid ${theme.border}`,\n background: \"#fff\",\n }}\n />\n <div style={hintStyle}>\n Open Weixin on your phone and scan this QR code. The status updates\n automatically.\n </div>\n </div>\n )}\n {ch.last_error && (\n <div style={{ marginTop: 10, fontSize: 11, color: theme.red }}>\n {ch.last_error}\n </div>\n )}\n </div>\n )}\n\n <div\n style={{\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 6,\n padding: \"10px 12px\",\n fontSize: 11,\n fontFamily: \"monospace\",\n color: theme.textMuted,\n lineHeight: 1.8,\n }}\n >\n <div style={{ color: theme.textDim, marginBottom: 4 }}>Notes:</div>\n {[\n \"Enabling Weixin starts the local bridge process\",\n \"First launch without a saved session will trigger QR login\",\n \"Reply to a result message to resume the same task session\",\n ].map((note) => (\n <div key={note}>\n <span style={{ color: theme.cyan }}>{note}</span>\n </div>\n ))}\n </div>\n </div>\n )}\n </div>\n );\n })()}\n\n {channelsMsg && (\n <div\n style={{\n padding: \"8px 12px\",\n borderRadius: 8,\n marginBottom: 16,\n fontSize: 12,\n background: channelsMsg.ok ? theme.greenBg : theme.redBg,\n color: channelsMsg.ok ? theme.green : theme.red,\n border: `1px solid ${channelsMsg.ok ? theme.green : theme.red}`,\n }}\n >\n {channelsMsg.text}\n </div>\n )}\n\n <div style={{ display: \"flex\", gap: 10, justifyContent: \"flex-end\" }}>\n <button\n onClick={onClose}\n style={{\n padding: \"10px 20px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: \"transparent\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n }}\n >\n Close\n </button>\n <button\n onClick={handleSaveChannels}\n disabled={channelsSaving}\n style={{\n padding: \"10px 24px\",\n borderRadius: 8,\n border: \"none\",\n background: channelsSaving ? theme.border : theme.accent,\n color: channelsSaving ? theme.textMuted : \"#fff\",\n cursor: channelsSaving ? \"not-allowed\" : \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n boxShadow: channelsSaving ? \"none\" : `0 0 20px ${theme.accentGlow}`,\n }}\n >\n {channelsSaving ? \"Saving…\" : \"Save\"}\n </button>\n </div>\n </>\n )}\n\n {/* ── Feishu tab ── */}\n {tab === \"feishu\" && (\n <>\n {/* Enable toggle */}\n <div\n style={{\n marginBottom: 20,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n }}\n >\n <div>\n <div style={{ fontSize: 13, fontWeight: 600, color: theme.text }}>\n Enable Feishu Bot\n </div>\n <div style={{ fontSize: 11, color: theme.textMuted, marginTop: 2 }}>\n WebSocket long-connection, no public IP required\n </div>\n </div>\n <button\n onClick={() =>\n setFeishu((f) => ({\n ...f,\n feishu_enabled: f.feishu_enabled === \"true\" ? \"false\" : \"true\",\n }))\n }\n style={{\n width: 44,\n height: 24,\n borderRadius: 12,\n border: \"none\",\n cursor: \"pointer\",\n background: feishu.feishu_enabled === \"true\" ? theme.accent : theme.border,\n position: \"relative\",\n transition: \"background 0.2s\",\n flexShrink: 0,\n }}\n >\n <span\n style={{\n position: \"absolute\",\n top: 3,\n width: 18,\n height: 18,\n borderRadius: \"50%\",\n background: \"#fff\",\n transition: \"left 0.2s\",\n left: feishu.feishu_enabled === \"true\" ? 23 : 3,\n }}\n />\n </button>\n </div>\n\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 16, marginBottom: 20 }}>\n <div>\n <label style={labelStyle}>App ID</label>\n <input\n value={feishu.feishu_app_id}\n onChange={(e) => setFeishu((f) => ({ ...f, feishu_app_id: e.target.value }))}\n placeholder=\"cli_xxxxxxxxxxxxxxxx\"\n style={fieldStyle}\n />\n </div>\n <div>\n <label style={labelStyle}>App Secret</label>\n <input\n type=\"password\"\n value={feishu.feishu_app_secret}\n onChange={(e) => setFeishu((f) => ({ ...f, feishu_app_secret: e.target.value }))}\n placeholder=\"••••••••••••••••\"\n style={fieldStyle}\n />\n </div>\n <div>\n <label style={labelStyle}>Default Chat ID</label>\n <input\n value={feishu.feishu_default_chat_id}\n onChange={(e) =>\n setFeishu((f) => ({ ...f, feishu_default_chat_id: e.target.value }))\n }\n placeholder=\"oc_xxxxxxxx (group) or ou_xxxxxxxx (DM)\"\n style={fieldStyle}\n />\n <div style={hintStyle}>Task completion notifications will be sent here.</div>\n </div>\n <div>\n <label style={labelStyle}>Default Working Directory</label>\n <input\n value={feishu.feishu_default_working_dir}\n onChange={(e) =>\n setFeishu((f) => ({ ...f, feishu_default_working_dir: e.target.value }))\n }\n placeholder=\"~/my-project\"\n style={fieldStyle}\n />\n <div style={hintStyle}>Working directory for tasks created via the bot.</div>\n </div>\n </div>\n\n {/* Bot commands cheatsheet */}\n <div\n style={{\n background: theme.bg,\n border: `1px solid ${theme.border}`,\n borderRadius: 8,\n padding: \"12px 14px\",\n marginBottom: 20,\n fontSize: 11,\n fontFamily: \"monospace\",\n color: theme.textMuted,\n lineHeight: 1.8,\n }}\n >\n <div style={{ color: theme.textDim, marginBottom: 6, fontFamily: \"inherit\" }}>\n Bot commands:\n </div>\n <div>\n <span style={{ color: theme.cyan }}><any text></span> — create a new task\n </div>\n <div>\n <span style={{ color: theme.cyan }}>/resume <id> <msg></span> — resume a\n task session\n </div>\n <div>\n <span style={{ color: theme.cyan }}>/status <id></span> — query task status\n </div>\n </div>\n\n {feishuMsg && (\n <div\n style={{\n padding: \"8px 12px\",\n borderRadius: 8,\n marginBottom: 16,\n fontSize: 12,\n background: feishuMsg.ok ? theme.greenBg : theme.redBg,\n color: feishuMsg.ok ? theme.green : theme.red,\n border: `1px solid ${feishuMsg.ok ? theme.green : theme.red}`,\n }}\n >\n {feishuMsg.text}\n </div>\n )}\n\n <div style={{ display: \"flex\", gap: 10, justifyContent: \"flex-end\" }}>\n <button\n onClick={onClose}\n style={{\n padding: \"10px 20px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: \"transparent\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n }}\n >\n Close\n </button>\n <button\n onClick={handleSaveFeishu}\n disabled={feishuSaving}\n style={{\n padding: \"10px 24px\",\n borderRadius: 8,\n border: \"none\",\n background: feishuSaving ? theme.border : theme.accent,\n color: feishuSaving ? theme.textMuted : \"#fff\",\n cursor: feishuSaving ? \"not-allowed\" : \"pointer\",\n fontSize: 13,\n fontWeight: 600,\n boxShadow: feishuSaving ? \"none\" : `0 0 20px ${theme.accentGlow}`,\n }}\n >\n {feishuSaving ? \"Saving…\" : \"Save & Apply\"}\n </button>\n </div>\n </>\n )}\n </div>\n </div>\n );\n}\n\n// ─── App ───\n\nfunction parseSkillFrontmatter(body) {\n const m = (body || \"\").match(/^---\\s*\\n([\\s\\S]*?)\\n---/);\n if (!m) return { name: \"\", description: \"\" };\n const out = { name: \"\", description: \"\" };\n for (const line of m[1].split(\"\\n\")) {\n const i = line.indexOf(\":\");\n if (i === -1) continue;\n const k = line.slice(0, i).trim().toLowerCase();\n const v = line.slice(i + 1).trim();\n if (k === \"name\" && !out.name) out.name = v;\n if (k === \"description\" && !out.description) out.description = v;\n }\n return out;\n}\n\nfunction SkillKindBadge({ kind }) {\n const isPitfall = kind === \"pitfall\";\n return (\n <span\n style={{\n fontSize: 10,\n fontWeight: 700,\n padding: \"2px 7px\",\n borderRadius: 6,\n letterSpacing: 0.4,\n background: isPitfall ? \"rgba(239,68,68,0.15)\" : \"rgba(34,197,94,0.15)\",\n color: isPitfall ? theme.red : theme.green,\n }}\n >\n {isPitfall ? \"PITFALL\" : \"RECIPE\"}\n </span>\n );\n}\n\nfunction SkillPatternCard({ p, tasks, onDraft, onApprove, onDismiss }) {\n let taskIds = [];\n try {\n taskIds = JSON.parse(p.contributing_task_ids || \"[]\");\n } catch {\n /* ignore */\n }\n const taskCount = taskIds.length;\n const ready = p.recurrence_count >= 3 && taskCount >= 2;\n const draftStatus = p.draft_status;\n const [expanded, setExpanded] = useState(false);\n const [body, setBody] = useState(p.draft_body || \"\");\n // The full SKILL.md is the single source of truth (name + description live in\n // its frontmatter). Sync the buffer when a fresh draft arrives.\n useEffect(() => {\n if (draftStatus === \"ready\") setBody(p.draft_body || \"\");\n }, [draftStatus, p.draft_body]);\n\n const borderColor =\n p.status === \"promoted\" ? theme.green : p.status === \"candidate\" ? theme.accent : theme.border;\n const muted = p.status === \"dismissed\";\n\n const btn = (bg, color) => ({\n padding: \"6px 14px\",\n borderRadius: 7,\n border: bg === \"transparent\" ? `1px solid ${theme.border}` : \"none\",\n background: bg,\n color,\n cursor: \"pointer\",\n fontSize: 11,\n fontWeight: 700,\n });\n\n return (\n <div\n style={{\n background: theme.surface,\n border: `1px solid ${borderColor}`,\n borderRadius: 12,\n padding: 16,\n opacity: muted ? 0.5 : 1,\n }}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8, marginBottom: 8 }}>\n <SkillKindBadge kind={p.kind} />\n <span style={{ fontFamily: \"monospace\", fontSize: 12, color: theme.text, fontWeight: 700 }}>\n {p.pattern_key}\n </span>\n </div>\n <div style={{ color: theme.textMuted, fontSize: 13, marginBottom: 10 }}>\n {p.summary || \"—\"}\n </div>\n <div\n style={{\n display: \"flex\",\n gap: 12,\n fontSize: 11,\n color: theme.textDim,\n marginBottom: 10,\n alignItems: \"center\",\n }}\n >\n <span>复发 {p.recurrence_count}×</span>\n <span>{taskCount} 个任务</span>\n <span>{p.status}</span>\n {ready && p.status !== \"promoted\" && (\n <span style={{ color: theme.accent, fontWeight: 700 }}>✓ 达标</span>\n )}\n <button\n onClick={() => setExpanded((v) => !v)}\n style={{\n marginLeft: \"auto\",\n background: \"transparent\",\n border: \"none\",\n color: theme.accent,\n cursor: \"pointer\",\n fontSize: 11,\n fontWeight: 700,\n }}\n >\n {expanded ? \"收起 ▲\" : \"详情 ▼\"}\n </button>\n </div>\n\n {expanded && (\n <div\n style={{\n background: theme.bg,\n border: `1px solid ${theme.border}`,\n borderRadius: 8,\n padding: 10,\n marginBottom: 10,\n fontSize: 11,\n color: theme.textMuted,\n }}\n >\n <div style={{ marginBottom: 6 }}>\n <span style={{ color: theme.textDim }}>首次 </span>\n {(p.first_seen || \"\").replace(\"T\", \" \").slice(0, 19) || \"—\"}\n <span style={{ color: theme.textDim }}> 最近 </span>\n {(p.last_seen || \"\").replace(\"T\", \" \").slice(0, 19) || \"—\"}\n </div>\n <div style={{ color: theme.textDim, marginBottom: 4 }}>贡献的任务({taskCount}):</div>\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 3 }}>\n {taskIds.length === 0 && <span style={{ color: theme.textDim }}>—</span>}\n {taskIds.map((tid) => {\n const t = (tasks || []).find((x) => x.id === tid);\n return (\n <span key={tid} style={{ fontFamily: \"monospace\" }}>\n #{tid} {t ? t.title : <span style={{ color: theme.textDim }}>(已删除)</span>}\n </span>\n );\n })}\n </div>\n </div>\n )}\n\n {draftStatus === \"ready\" && p.draft_worthy !== null && p.draft_worthy !== undefined && (\n <div\n style={{\n fontSize: 11,\n padding: \"7px 10px\",\n borderRadius: 7,\n marginBottom: 8,\n background: p.draft_worthy ? \"rgba(34,197,94,0.12)\" : \"rgba(245,158,11,0.14)\",\n color: p.draft_worthy ? theme.green : \"#f59e0b\",\n border: `1px solid ${p.draft_worthy ? \"rgba(34,197,94,0.3)\" : \"rgba(245,158,11,0.35)\"}`,\n }}\n >\n {p.draft_worthy ? \"✓ agent 建议沉淀\" : \"⚠ agent 认为价值有限(可仍批准或驳回)\"}\n {p.draft_worthiness_reason ? `:${p.draft_worthiness_reason}` : \"\"}\n </div>\n )}\n\n {p.status === \"promoted\" && (\n <div style={{ fontSize: 12, color: theme.green, fontWeight: 700 }}>✓ 已沉淀为 Skill</div>\n )}\n\n {(p.status === \"candidate\" || p.status === \"tracking\") &&\n draftStatus !== \"ready\" &&\n draftStatus !== \"drafting\" && (\n <div style={{ display: \"flex\", gap: 8, alignItems: \"center\", flexWrap: \"wrap\" }}>\n <button onClick={() => onDraft(p.id)} style={btn(theme.accent, \"#fff\")}>\n {draftStatus === \"error\" ? \"重试蒸馏\" : \"蒸馏成 Skill\"}\n </button>\n <button onClick={() => onDismiss(p.id)} style={btn(\"transparent\", theme.textMuted)}>\n 驳回\n </button>\n {p.status === \"tracking\" && (\n <span style={{ color: theme.textDim, fontSize: 11 }}>\n 未达自动阈值,可手动蒸馏(agent 会判断是否值得)\n </span>\n )}\n {draftStatus === \"error\" && (\n <span style={{ color: theme.red, fontSize: 11 }}>蒸馏失败:{p.draft_error}</span>\n )}\n </div>\n )}\n\n {draftStatus === \"drafting\" && (\n <div style={{ fontSize: 12, color: theme.textMuted }}>蒸馏中…</div>\n )}\n\n {draftStatus === \"ready\" &&\n (() => {\n const fm = parseSkillFrontmatter(body);\n return (\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 10 }}>\n {/* preview header */}\n <div style={{ display: \"flex\", alignItems: \"baseline\", gap: 8, flexWrap: \"wrap\" }}>\n <span\n style={{\n fontFamily: \"ui-monospace, Menlo, monospace\",\n fontSize: 12,\n fontWeight: 800,\n color: theme.accent,\n background: theme.accentGlow,\n padding: \"3px 9px\",\n borderRadius: 6,\n }}\n >\n {fm.name || \"(无 name)\"}\n </span>\n <span style={{ fontSize: 11, color: theme.textDim }}>\n → ~/.claude/skills/{fm.name || \"…\"}/SKILL.md\n </span>\n </div>\n {fm.description && (\n <div style={{ fontSize: 12, color: theme.textMuted, lineHeight: 1.55 }}>\n {fm.description}\n </div>\n )}\n {/* editor */}\n <div>\n <div\n style={{\n fontSize: 10.5,\n color: theme.textDim,\n marginBottom: 5,\n fontWeight: 600,\n letterSpacing: 0.3,\n }}\n >\n SKILL.md · 可编辑(frontmatter 决定名称与触发描述)\n </div>\n <textarea\n value={body}\n onChange={(e) => setBody(e.target.value)}\n rows={16}\n spellCheck={false}\n style={{\n width: \"100%\",\n boxSizing: \"border-box\",\n padding: \"12px 14px\",\n borderRadius: 10,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n color: theme.text,\n fontSize: 12,\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, monospace\",\n lineHeight: 1.65,\n resize: \"vertical\",\n outline: \"none\",\n }}\n />\n </div>\n <div style={{ display: \"flex\", gap: 8 }}>\n <button\n onClick={() => onApprove(p.id, { body })}\n style={{ ...btn(theme.green, \"#fff\"), padding: \"8px 18px\", fontSize: 12 }}\n >\n ✓ 批准并写入\n </button>\n <button\n onClick={() => onDismiss(p.id)}\n style={{\n ...btn(\"transparent\", theme.textMuted),\n padding: \"8px 18px\",\n fontSize: 12,\n }}\n >\n 驳回\n </button>\n </div>\n </div>\n );\n })()}\n </div>\n );\n}\n\nfunction SkillRegistryCard({ s, tasks, onToggle, onDelete }) {\n const [expanded, setExpanded] = useState(false);\n const [content, setContent] = useState<any>(null);\n const [loading, setLoading] = useState(false);\n\n let sourceTaskIds = [];\n try {\n sourceTaskIds = JSON.parse(s.source_task_ids || \"[]\");\n } catch {\n /* ignore */\n }\n\n const toggleDetail = async () => {\n const next = !expanded;\n setExpanded(next);\n if (next && content === null) {\n setLoading(true);\n try {\n const res = await fetch(`${API}/skills/${s.id}/content`);\n const d = await res.json();\n setContent(d.content ?? \"\");\n } catch (e) {\n setContent(`(加载失败:${e.message})`);\n } finally {\n setLoading(false);\n }\n }\n };\n\n return (\n <div\n style={{\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 12,\n padding: 14,\n opacity: s.enabled ? 1 : 0.55,\n }}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 8, marginBottom: 6 }}>\n <SkillKindBadge kind={s.kind} />\n <span style={{ fontFamily: \"monospace\", fontSize: 12, color: theme.text, fontWeight: 700 }}>\n {s.name}\n </span>\n <button\n onClick={toggleDetail}\n style={{\n marginLeft: \"auto\",\n background: \"transparent\",\n border: \"none\",\n color: theme.accent,\n cursor: \"pointer\",\n fontSize: 11,\n fontWeight: 700,\n }}\n >\n {expanded ? \"收起 ▲\" : \"查看 SKILL.md ▼\"}\n </button>\n </div>\n <div style={{ color: theme.textMuted, fontSize: 12, marginBottom: 10, lineHeight: 1.5 }}>\n {s.description || \"—\"}\n </div>\n\n {expanded && (\n <div style={{ marginBottom: 10 }}>\n <div style={{ fontSize: 11, color: theme.textDim, marginBottom: 6 }}>\n <span style={{ fontFamily: \"monospace\" }}>{s.path}</span>\n {s.source_pattern_key && <span> 来源 pattern:{s.source_pattern_key}</span>}\n {sourceTaskIds.length > 0 && (\n <span>\n  来源任务:\n {sourceTaskIds\n .map((tid) => {\n const t = (tasks || []).find((x) => x.id === tid);\n return `#${tid}${t ? \"(\" + t.title + \")\" : \"\"}`;\n })\n .join(\"、\")}\n </span>\n )}\n </div>\n <pre\n style={{\n margin: 0,\n padding: \"12px 14px\",\n borderRadius: 10,\n border: `1px solid ${theme.border}`,\n background: theme.bg,\n color: theme.text,\n fontSize: 12,\n fontFamily: \"ui-monospace, SFMono-Regular, Menlo, monospace\",\n lineHeight: 1.6,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-word\",\n maxHeight: 360,\n overflow: \"auto\",\n }}\n >\n {loading ? \"加载中…\" : content}\n </pre>\n </div>\n )}\n\n <div style={{ display: \"flex\", gap: 8, alignItems: \"center\" }}>\n <label\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n fontSize: 11,\n color: theme.textDim,\n cursor: \"pointer\",\n }}\n >\n <input\n type=\"checkbox\"\n checked={!!s.enabled}\n onChange={(e) => onToggle(s.id, e.target.checked)}\n style={{ cursor: \"pointer\" }}\n />\n {s.enabled ? \"已启用(claude/codex 加载中)\" : \"已停用(symlink 已摘除)\"}\n </label>\n <button\n onClick={() => onDelete(s.id)}\n style={{\n marginLeft: \"auto\",\n padding: \"4px 10px\",\n borderRadius: 6,\n border: `1px solid ${theme.border}`,\n background: \"transparent\",\n color: theme.red,\n cursor: \"pointer\",\n fontSize: 11,\n fontWeight: 700,\n }}\n >\n 删除\n </button>\n </div>\n </div>\n );\n}\n\nfunction SkillsView({\n skillData,\n skills,\n tasks,\n onSweep,\n onDraft,\n onApprove,\n onDismiss,\n onToggleSkill,\n onDeleteSkill,\n}) {\n // Only recurrence >= 2 is worth surfacing; single-occurrence rows are noise.\n // (The backend still tracks them so the count can accumulate across sweeps.)\n const patterns = (skillData.patterns || []).filter((p) => p.recurrence_count >= 2);\n const sweep = skillData.sweep || {};\n const running = sweep.running;\n const last = sweep.last;\n let lastNote = null;\n if (last) {\n lastNote = last.error\n ? `上次扫描失败:${last.error}`\n : last.scanned === 0\n ? `上次扫描:没有已完成的任务可分析(agent ${last.agent})`\n : `上次扫描:分析 ${last.scanned} 个任务、新增 ${last.new ?? 0} 次复发、候选 ${last.candidates ?? 0}(agent ${last.agent})`;\n }\n const [showRegistry, setShowRegistry] = useState(true);\n const [showPatterns, setShowPatterns] = useState(true);\n\n const sectionHeader = (label, count, open, toggle) => (\n <button\n onClick={toggle}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n width: \"100%\",\n background: \"transparent\",\n border: \"none\",\n cursor: \"pointer\",\n color: theme.text,\n fontSize: 13,\n fontWeight: 700,\n padding: 0,\n marginBottom: 10,\n }}\n >\n <span style={{ color: theme.textDim, fontSize: 11 }}>{open ? \"▼\" : \"▶\"}</span>\n {label}\n <span style={{ color: theme.textDim, fontWeight: 600 }}>({count})</span>\n </button>\n );\n\n return (\n <div style={{ padding: 28, minHeight: \"calc(100vh - 72px)\" }}>\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n marginBottom: 16,\n gap: 12,\n }}\n >\n <div style={{ color: theme.textMuted, fontSize: 12 }}>\n 跨任务复发模式账本 · 复发 ≥2 即可手动蒸馏为 Skill(达 ≥3 且跨 ≥2 任务自动标记候选)\n {lastNote && <span style={{ marginLeft: 10, color: theme.textDim }}>· {lastNote}</span>}\n </div>\n <button\n onClick={onSweep}\n disabled={running}\n style={{\n padding: \"8px 18px\",\n borderRadius: 8,\n border: \"none\",\n background: running ? theme.border : theme.accent,\n color: \"#fff\",\n cursor: running ? \"default\" : \"pointer\",\n fontSize: 12,\n fontWeight: 700,\n letterSpacing: 0.3,\n whiteSpace: \"nowrap\",\n boxShadow: running ? \"none\" : `0 0 24px ${theme.accentGlow}`,\n }}\n >\n {running ? \"扫描中…\" : \"扫一遍\"}\n </button>\n </div>\n\n {(skills || []).length > 0 && (\n <div style={{ marginBottom: 26 }}>\n {sectionHeader(\"已沉淀 Skills\", skills.length, showRegistry, () =>\n setShowRegistry((v) => !v),\n )}\n {showRegistry && (\n <div\n style={{\n display: \"grid\",\n gridTemplateColumns: \"repeat(auto-fit, minmax(360px, 1fr))\",\n gap: 12,\n }}\n >\n {skills.map((s) => (\n <SkillRegistryCard\n key={s.id}\n s={s}\n tasks={tasks}\n onToggle={onToggleSkill}\n onDelete={onDeleteSkill}\n />\n ))}\n </div>\n )}\n </div>\n )}\n\n {sectionHeader(\"检测到的模式\", patterns.length, showPatterns, () =>\n setShowPatterns((v) => !v),\n )}\n {showPatterns &&\n (patterns.length === 0 ? (\n <div\n style={{\n border: `1px dashed ${theme.border}`,\n borderRadius: 12,\n padding: 32,\n textAlign: \"center\",\n color: theme.textDim,\n fontSize: 12,\n }}\n >\n 还没有复发 ≥2 的模式 — 点「扫一遍」让 agent 分析最近完成的任务(复发 1 次的暂不展示)\n </div>\n ) : (\n <div\n style={{\n display: \"grid\",\n gridTemplateColumns: \"repeat(auto-fit, minmax(360px, 1fr))\",\n gap: 14,\n }}\n >\n {patterns.map((p) => (\n <SkillPatternCard\n key={p.id}\n p={p}\n tasks={tasks}\n onDraft={onDraft}\n onApprove={onApprove}\n onDismiss={onDismiss}\n />\n ))}\n </div>\n ))}\n </div>\n );\n}\n\nexport default function App() {\n const [tasks, setTasks] = useState<any[]>([]);\n const [heartbeats, setHeartbeats] = useState<any[]>([]);\n const [heartbeatTicks, setHeartbeatTicks] = useState<any[]>([]);\n const [skillData, setSkillData] = useState({\n patterns: [],\n sweep: { running: false, last: null },\n });\n const [skills, setSkills] = useState<any[]>([]);\n const [activeView, setActiveView] = useState(\"tasks\");\n const [showNew, setShowNew] = useState(false);\n const [showNewHeartbeat, setShowNewHeartbeat] = useState(false);\n const [showSettings, setShowSettings] = useState(false);\n const [detail, setDetail] = useState<any>(null);\n const [heartbeatDetail, setHeartbeatDetail] = useState<any>(null);\n const [connected, setConnected] = useState(false);\n const [filter, setFilter] = useState(\"\");\n const [taskTimeout, setTaskTimeout] = useState(DEFAULT_TIMEOUT_SECONDS);\n const [defaultAgent, setDefaultAgent] = useState(DEFAULT_AGENT);\n const [feishuSettings, setFeishuSettings] = useState<any>({});\n const [channelsStatus, setChannelsStatus] = useState<any>({});\n const [backendReady, setBackendReady] = useState(false);\n const [backendError, setBackendError] = useState<any>(null);\n const [apiError, setApiError] = useState<any>(null);\n const [editingTask, setEditingTask] = useState<any>(null);\n const [forkingTask, setForkingTask] = useState<any>(null);\n const [editingHeartbeat, setEditingHeartbeat] = useState<any>(null);\n\n // ─── Color mode ───\n const [colorMode, setColorMode] = useState(() => localStorage.getItem(\"colorMode\") || \"system\");\n const [systemDark, setSystemDark] = useState(\n () => window.matchMedia(\"(prefers-color-scheme: dark)\").matches,\n );\n const resolvedMode = colorMode === \"system\" ? (systemDark ? \"dark\" : \"light\") : colorMode;\n theme = THEMES[resolvedMode];\n\n useEffect(() => {\n localStorage.setItem(\"colorMode\", colorMode);\n document.body.style.background = THEMES[resolvedMode].bg;\n }, [colorMode, resolvedMode]);\n\n useEffect(() => {\n const mq = window.matchMedia(\"(prefers-color-scheme: dark)\");\n const handler = (e) => setSystemDark(e.matches);\n mq.addEventListener(\"change\", handler);\n return () => mq.removeEventListener(\"change\", handler);\n }, []);\n\n useEffect(() => {\n let cancelled = false;\n const deadline = Date.now() + 20000;\n const probe = async () => {\n try {\n const res = await fetch(`${API}/health`, { signal: AbortSignal.timeout(800) });\n if (res.ok) {\n if (!cancelled) setBackendReady(true);\n return;\n }\n } catch {\n /* not ready yet */\n }\n if (cancelled) return;\n if (Date.now() >= deadline) {\n setBackendError(\"Backend did not start within 20 seconds.\");\n return;\n }\n setTimeout(probe, 300);\n };\n probe();\n return () => {\n cancelled = true;\n };\n }, []);\n\n const poll = useCallback(async () => {\n try {\n const [taskData, heartbeatData, skillRes, skillsRes] = await Promise.all([\n fetchTasks(),\n fetchHeartbeats(),\n fetchSkillPatterns(),\n fetchSkills(),\n ]);\n setTasks(taskData);\n setHeartbeats(heartbeatData);\n setSkillData(skillRes);\n setSkills(skillsRes.skills || []);\n setConnected(true);\n setApiError(null);\n } catch (err) {\n setConnected(false);\n setApiError(`Failed to fetch tasks: ${err.message}`);\n }\n }, []);\n\n useEffect(() => {\n if (!backendReady) return;\n poll();\n const interval = setInterval(poll, 3000);\n return () => clearInterval(interval);\n }, [poll, backendReady]);\n\n useEffect(() => {\n if (!backendReady) return;\n fetchSettings().then((s) => {\n if (s.timeout) setTaskTimeout(s.timeout);\n if (s.default_agent) setDefaultAgent(s.default_agent);\n });\n fetchFeishuSettings().then((s) => setFeishuSettings(s));\n fetchChannelsStatus().then((s) => setChannelsStatus(s));\n }, [backendReady]);\n\n const handleAction = async (action, id) => {\n try {\n if (action === \"cancel\") await cancelTask(id);\n else if (action === \"retry\") await retryTask(id);\n else if (action === \"delete\") {\n await deleteTask(id);\n if (detail?.id === id) setDetail(null);\n } else if (action === \"edit\") {\n const task = tasks.find((t) => t.id === id);\n if (task) setEditingTask(task);\n return;\n } else if (action === \"fork\") {\n const task = tasks.find((t) => t.id === id);\n if (task) setForkingTask(task);\n return;\n }\n poll();\n } catch (e) {\n setApiError(`${action} failed: ${e.message}`);\n }\n };\n\n const handleHeartbeatAction = async (action, id) => {\n try {\n if (action === \"run\") {\n await runHeartbeatNow(id);\n } else if (action === \"pause\") {\n await pauseHeartbeat(id);\n } else if (action === \"resume\") {\n await resumeHeartbeatApi(id);\n } else if (action === \"delete\") {\n await deleteHeartbeat(id);\n if (heartbeatDetail?.id === id) {\n setHeartbeatDetail(null);\n setHeartbeatTicks([]);\n }\n } else if (action === \"edit\") {\n const heartbeat = heartbeats.find((h) => h.id === id);\n if (heartbeat) setEditingHeartbeat(heartbeat);\n return;\n }\n poll();\n if (heartbeatDetail?.id === id && action !== \"delete\") {\n const [updatedHeartbeat, ticks] = await Promise.all([\n fetch(`${API}/heartbeats/${id}`).then((r) => r.json()),\n fetchHeartbeatTicks(id),\n ]);\n setHeartbeatDetail(updatedHeartbeat);\n setHeartbeatTicks(ticks);\n }\n } catch (e) {\n setApiError(`Heartbeat ${action} failed: ${e.message}`);\n }\n };\n\n const handleSweep = async () => {\n try {\n await triggerSkillSweep();\n // Optimistically reflect the running state; poll picks up the real status.\n setSkillData((prev) => ({ ...prev, sweep: { ...prev.sweep, running: true } }));\n setTimeout(poll, 1500);\n } catch (e) {\n setApiError(`Sweep failed: ${e.message}`);\n }\n };\n\n const handleSkillDraft = async (id) => {\n try {\n await triggerSkillDraft(id);\n setTimeout(poll, 1500);\n } catch (e) {\n setApiError(`Distill failed: ${e.message}`);\n }\n };\n\n const handleSkillApprove = async (id, data) => {\n try {\n await approveSkill(id, data);\n poll();\n } catch (e) {\n setApiError(`Approve failed: ${e.message}`);\n }\n };\n\n const handleSkillDismiss = async (id) => {\n try {\n await dismissSkillPattern(id);\n poll();\n } catch (e) {\n setApiError(`Dismiss failed: ${e.message}`);\n }\n };\n\n const handleSkillToggle = async (id, enabled) => {\n try {\n await setSkillEnabledApi(id, enabled);\n poll();\n } catch (e) {\n setApiError(`Toggle skill failed: ${e.message}`);\n }\n };\n\n const handleSkillDelete = async (id) => {\n try {\n await deleteSkillApi(id);\n poll();\n } catch (e) {\n setApiError(`Delete skill failed: ${e.message}`);\n }\n };\n\n const handleCreate = async (data) => {\n try {\n await createTask(data);\n setShowNew(false);\n poll();\n } catch (e) {\n setApiError(`Create task failed: ${e.message}`);\n }\n };\n\n const handleEdit = async (data) => {\n try {\n await updateTask(editingTask.id, data);\n setEditingTask(null);\n poll();\n } catch (e) {\n setApiError(`Edit task failed: ${e.message}`);\n }\n };\n\n const handleFork = async (data) => {\n try {\n await createTask(data);\n setForkingTask(null);\n poll();\n } catch (e) {\n setApiError(`Fork task failed: ${e.message}`);\n }\n };\n\n const handleRespond = async (id, answer) => {\n try {\n await respondToTask(id, answer);\n poll();\n } catch (e) {\n setApiError(`Respond failed: ${e.message}`);\n }\n };\n\n const handleResume = () => {\n poll();\n };\n\n const handleCreateHeartbeat = async (data) => {\n try {\n await createHeartbeat(data);\n setShowNewHeartbeat(false);\n poll();\n } catch (e) {\n setApiError(`Create heartbeat failed: ${e.message}`);\n }\n };\n\n const handleEditHeartbeat = async (data) => {\n try {\n await updateHeartbeat(editingHeartbeat.id, data);\n setEditingHeartbeat(null);\n poll();\n } catch (e) {\n setApiError(`Edit heartbeat failed: ${e.message}`);\n }\n };\n\n const openHeartbeatDetail = async (heartbeat) => {\n setHeartbeatDetail(heartbeat);\n try {\n const ticks = await fetchHeartbeatTicks(heartbeat.id);\n setHeartbeatTicks(ticks);\n } catch (e) {\n setApiError(`Failed to fetch heartbeat ticks: ${e.message}`);\n setHeartbeatTicks([]);\n }\n };\n\n const filtered = filter\n ? tasks.filter(\n (t) =>\n t.title.toLowerCase().includes(filter.toLowerCase()) ||\n t.tags?.toLowerCase().includes(filter.toLowerCase()),\n )\n : tasks;\n\n const runningCount = tasks.filter((t) => t.status === \"running\").length;\n const scheduledCount = tasks.filter((t) => t.status === \"scheduled\").length;\n const enabledHeartbeatCount = heartbeats.filter((h) => h.enabled).length;\n\n if (backendError) {\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"100vh\",\n background: theme.bg,\n color: theme.red,\n gap: 12,\n fontFamily: \"inherit\",\n }}\n >\n <div style={{ fontSize: 32 }}>✕</div>\n <div style={{ fontSize: 15, fontWeight: 600 }}>Backend failed to start</div>\n <div style={{ fontSize: 12, color: theme.textMuted, maxWidth: 400, textAlign: \"center\" }}>\n {backendError}\n </div>\n </div>\n );\n }\n\n if (!backendReady) {\n return (\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"100vh\",\n background: theme.bg,\n color: theme.textMuted,\n gap: 16,\n fontFamily: \"inherit\",\n }}\n >\n <div\n style={{\n width: 32,\n height: 32,\n borderRadius: \"50%\",\n border: `3px solid ${theme.border}`,\n borderTopColor: theme.accent,\n animation: \"spin 0.8s linear infinite\",\n }}\n />\n <div style={{ fontSize: 13 }}>Starting backend…</div>\n <style>{`@keyframes spin { to { transform: rotate(360deg); } }`}</style>\n </div>\n );\n }\n\n return (\n <div\n style={{\n minHeight: \"100vh\",\n background: theme.bg,\n color: theme.text,\n fontFamily: \"-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif\",\n }}\n >\n <style>{`@keyframes pulse { 0%,100%{opacity:1} 50%{opacity:0.3} }`}</style>\n {/* API error toast */}\n {apiError && (\n <div\n style={{\n position: \"fixed\",\n bottom: 24,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n zIndex: 9999,\n display: \"flex\",\n alignItems: \"center\",\n gap: 10,\n background: theme.surface,\n border: `1px solid ${theme.red}`,\n borderRadius: 8,\n padding: \"10px 16px\",\n boxShadow: `0 4px 24px rgba(0,0,0,0.5)`,\n color: theme.red,\n fontSize: 12,\n fontWeight: 500,\n maxWidth: 480,\n }}\n >\n <span style={{ flexShrink: 0 }}>✕</span>\n <span style={{ flex: 1 }}>{apiError}</span>\n <button\n onClick={() => setApiError(null)}\n style={{\n background: \"none\",\n border: \"none\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 14,\n lineHeight: 1,\n padding: \"0 0 0 8px\",\n flexShrink: 0,\n }}\n title=\"Dismiss\"\n >\n ×\n </button>\n </div>\n )}\n {/* Header */}\n <div\n style={{\n borderBottom: `1px solid ${theme.border}`,\n padding: \"16px 28px\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n backdropFilter: \"blur(10px)\",\n position: \"sticky\",\n top: 0,\n zIndex: 100,\n background: `${theme.bg}ee`,\n }}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 14 }}>\n <div\n style={{\n width: 32,\n height: 32,\n borderRadius: 8,\n background: `linear-gradient(135deg, ${theme.accent}, #a855f7)`,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n fontSize: 16,\n fontWeight: 800,\n color: \"#fff\",\n }}\n >\n ⌘\n </div>\n <div>\n <div\n style={{\n fontSize: 15,\n fontWeight: 700,\n fontFamily: \"'JetBrains Mono', monospace\",\n letterSpacing: -0.3,\n }}\n >\n AgentForge\n </div>\n <div style={{ fontSize: 11, color: theme.textDim, marginTop: 1 }}>\n {connected ? (\n <span style={{ color: theme.green }}>● Connected</span>\n ) : (\n <span style={{ color: theme.red }}>● Disconnected — run `bun taskboard.ts`</span>\n )}\n {connected &&\n ` · ${runningCount} running · ${scheduledCount} scheduled · ${enabledHeartbeatCount} heartbeats`}\n </div>\n </div>\n </div>\n\n <div style={{ display: \"flex\", alignItems: \"center\", gap: 10 }}>\n <div\n style={{\n display: \"flex\",\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 10,\n padding: 4,\n gap: 4,\n }}\n >\n {[\n { key: \"tasks\", label: \"Tasks\" },\n { key: \"heartbeats\", label: \"Heartbeats\" },\n { key: \"skills\", label: \"Skills\" },\n ].map((tab) => (\n <button\n key={tab.key}\n onClick={() => setActiveView(tab.key)}\n style={{\n padding: \"6px 10px\",\n borderRadius: 8,\n border: \"none\",\n background: activeView === tab.key ? theme.accentGlow : \"transparent\",\n color: activeView === tab.key ? theme.accent : theme.textMuted,\n cursor: \"pointer\",\n fontSize: 12,\n fontWeight: 700,\n }}\n >\n {tab.label}\n </button>\n ))}\n </div>\n <input\n placeholder={activeView === \"tasks\" ? \"Filter tasks...\" : \"Filter heartbeats...\"}\n value={filter}\n onChange={(e) => setFilter(e.target.value)}\n style={{\n padding: \"8px 14px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: theme.surface,\n color: theme.text,\n fontSize: 12,\n outline: \"none\",\n width: 180,\n }}\n />\n {/* Color mode toggle */}\n {(() => {\n const cycle = { system: \"light\", light: \"dark\", dark: \"system\" };\n const icons = { system: \"⊙\", light: \"☀\", dark: \"☾\" };\n const labels = { system: \"System theme\", light: \"Light mode\", dark: \"Dark mode\" };\n return (\n <Tooltip text={labels[colorMode]}>\n <button\n onClick={() => setColorMode(cycle[colorMode])}\n style={{\n padding: \"8px 10px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: \"transparent\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 15,\n display: \"flex\",\n alignItems: \"center\",\n transition: \"all 0.15s\",\n }}\n >\n {icons[colorMode]}\n </button>\n </Tooltip>\n );\n })()}\n <Tooltip text=\"Settings\">\n <button\n onClick={() => setShowSettings(true)}\n style={{\n padding: \"8px 12px\",\n borderRadius: 8,\n border: `1px solid ${theme.border}`,\n background: \"transparent\",\n color: theme.textMuted,\n cursor: \"pointer\",\n fontSize: 15,\n display: \"flex\",\n alignItems: \"center\",\n transition: \"all 0.15s\",\n }}\n >\n ⚙\n </button>\n </Tooltip>\n {activeView !== \"skills\" && (\n <button\n onClick={() =>\n activeView === \"tasks\" ? setShowNew(true) : setShowNewHeartbeat(true)\n }\n style={{\n padding: \"8px 18px\",\n borderRadius: 8,\n border: \"none\",\n background: theme.accent,\n color: \"#fff\",\n cursor: \"pointer\",\n fontSize: 12,\n fontWeight: 700,\n letterSpacing: 0.3,\n display: \"flex\",\n alignItems: \"center\",\n gap: 6,\n boxShadow: `0 0 24px ${theme.accentGlow}`,\n transition: \"transform 0.15s\",\n }}\n >\n {activeView === \"tasks\" ? \"+ New Task\" : \"+ New Heartbeat\"}\n </button>\n )}\n </div>\n </div>\n\n {activeView === \"tasks\" ? (\n <div\n style={{\n display: \"flex\",\n gap: 20,\n padding: 28,\n minHeight: \"calc(100vh - 72px)\",\n }}\n >\n {COLUMNS.map((col) => (\n <Column\n key={col.key}\n col={col}\n tasks={filtered.filter((t) => col.statuses.includes(t.status))}\n onAction={handleAction}\n onViewDetail={setDetail}\n />\n ))}\n </div>\n ) : activeView === \"heartbeats\" ? (\n <div style={{ padding: 28, minHeight: \"calc(100vh - 72px)\" }}>\n <div\n style={{\n display: \"grid\",\n gridTemplateColumns: \"repeat(auto-fit, minmax(360px, 1fr))\",\n gap: 14,\n }}\n >\n {(filter\n ? heartbeats.filter(\n (h) =>\n h.name.toLowerCase().includes(filter.toLowerCase()) ||\n h.check_prompt.toLowerCase().includes(filter.toLowerCase()),\n )\n : heartbeats\n ).map((h) => (\n <HeartbeatCard\n key={h.id}\n heartbeat={h}\n onAction={handleHeartbeatAction}\n onViewDetail={openHeartbeatDetail}\n />\n ))}\n {heartbeats.length === 0 && (\n <div\n style={{\n border: `1px dashed ${theme.border}`,\n borderRadius: 12,\n padding: 32,\n textAlign: \"center\",\n color: theme.textDim,\n fontSize: 12,\n gridColumn: \"1 / -1\",\n }}\n >\n No heartbeats yet\n </div>\n )}\n </div>\n </div>\n ) : (\n <SkillsView\n skillData={skillData}\n skills={skills}\n tasks={tasks}\n onSweep={handleSweep}\n onDraft={handleSkillDraft}\n onApprove={handleSkillApprove}\n onDismiss={handleSkillDismiss}\n onToggleSkill={handleSkillToggle}\n onDeleteSkill={handleSkillDelete}\n />\n )}\n\n {/* Modals */}\n {showNew && (\n <NewTaskModal\n onClose={() => setShowNew(false)}\n onSubmit={handleCreate}\n initialData={{ agent: defaultAgent }}\n />\n )}\n {showNewHeartbeat && (\n <HeartbeatModal\n onClose={() => setShowNewHeartbeat(false)}\n onSubmit={handleCreateHeartbeat}\n defaultAgent={defaultAgent}\n />\n )}\n {editingTask && (\n <NewTaskModal\n onClose={() => setEditingTask(null)}\n onSubmit={handleEdit}\n initialData={editingTask}\n mode=\"edit\"\n />\n )}\n {editingHeartbeat && (\n <HeartbeatModal\n onClose={() => setEditingHeartbeat(null)}\n onSubmit={handleEditHeartbeat}\n initialData={editingHeartbeat}\n defaultAgent={defaultAgent}\n mode=\"edit\"\n />\n )}\n {forkingTask && (\n <NewTaskModal\n onClose={() => setForkingTask(null)}\n onSubmit={handleFork}\n initialData={forkingTask}\n mode=\"fork\"\n />\n )}\n {showSettings && (\n <SettingsModal\n onClose={() => setShowSettings(false)}\n timeout={taskTimeout}\n defaultAgent={defaultAgent}\n onSave={(timeout, agent) => {\n setTaskTimeout(timeout);\n if (agent) setDefaultAgent(agent);\n }}\n feishu={feishuSettings}\n onFeishuSave={(updated) => setFeishuSettings(updated)}\n channelsStatus={channelsStatus}\n onChannelsSave={(updated) => setChannelsStatus(updated)}\n />\n )}\n {detail && (\n <DetailPanel\n task={tasks.find((t) => t.id === detail.id) || detail}\n onClose={() => setDetail(null)}\n onRespond={handleRespond}\n onResume={handleResume}\n />\n )}\n {heartbeatDetail && (\n <HeartbeatDetailPanel\n heartbeat={heartbeats.find((h) => h.id === heartbeatDetail.id) || heartbeatDetail}\n ticks={heartbeatTicks}\n onClose={() => {\n setHeartbeatDetail(null);\n setHeartbeatTicks([]);\n }}\n />\n )}\n\n {/* Startup guide when no tasks */}\n {connected && activeView === \"tasks\" && tasks.length === 0 && (\n <div\n style={{\n position: \"fixed\",\n bottom: 28,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 12,\n padding: \"16px 24px\",\n maxWidth: 500,\n boxShadow: \"0 8px 32px rgba(0,0,0,0.3)\",\n }}\n >\n <div style={{ fontSize: 13, color: theme.text, fontWeight: 600, marginBottom: 6 }}>\n Ready to go! Click \"+ New Task\" to create your first task.\n </div>\n <div style={{ fontSize: 11, color: theme.textDim, lineHeight: 1.6 }}>\n Tasks are dispatched to Claude Code in your specified working directory. Set cron\n schedules for recurring tasks, or delay execution.\n </div>\n </div>\n )}\n {connected && activeView === \"heartbeats\" && heartbeats.length === 0 && (\n <div\n style={{\n position: \"fixed\",\n bottom: 28,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n background: theme.surface,\n border: `1px solid ${theme.border}`,\n borderRadius: 12,\n padding: \"16px 24px\",\n maxWidth: 560,\n boxShadow: \"0 8px 32px rgba(0,0,0,0.3)\",\n }}\n >\n <div style={{ fontSize: 13, color: theme.text, fontWeight: 600, marginBottom: 6 }}>\n Heartbeats let AgentForge check first and only create work when needed.\n </div>\n <div style={{ fontSize: 11, color: theme.textDim, lineHeight: 1.6 }}>\n Create one to run a stateless agent decision tick on an interval or cron schedule, then\n trigger a real task only when the signal is actionable.\n </div>\n </div>\n )}\n\n {!connected && (\n <div\n style={{\n position: \"fixed\",\n bottom: 28,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n background: theme.redBg,\n border: `1px solid rgba(248,113,113,0.2)`,\n borderRadius: 12,\n padding: \"16px 24px\",\n maxWidth: 520,\n }}\n >\n <div style={{ fontSize: 13, color: theme.red, fontWeight: 600, marginBottom: 4 }}>\n Backend not running\n </div>\n <code style={{ fontSize: 11, color: theme.text, lineHeight: 1.8, display: \"block\" }}>\n cd backend\n <br />\n bun taskboard.ts\n </code>\n </div>\n )}\n </div>\n );\n}\n\n// CSS动画定义\nconst styles = `\n @keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n\n .live-output-line {\n transition: color 0.2s ease;\n }\n\n .live-output-line.error {\n color: ${theme.red};\n }\n\n .live-output-line.success {\n color: ${theme.green};\n }\n\n .live-output-line.warning {\n color: ${theme.orange};\n }\n\n .live-output-line.info {\n color: ${theme.blue};\n }\n\n .live-output-line.command {\n color: ${theme.cyan};\n font-weight: bold;\n }\n\n .live-output-line.path {\n color: ${theme.accent};\n }\n`;\n\n// 注入样式\nif (typeof document !== \"undefined\" && !document.querySelector(\"#live-output-styles\")) {\n const styleEl = document.createElement(\"style\");\n styleEl.id = \"live-output-styles\";\n styleEl.textContent = styles;\n document.head.appendChild(styleEl);\n}\n", "interface LocalDateTimeParts {\n year: number;\n month: number;\n day: number;\n hour: number;\n minute: number;\n second: number;\n}\n\nfunction pad(value: number | string): string {\n return String(value).padStart(2, \"0\");\n}\n\nfunction hasExplicitTimezone(value: string): boolean {\n return /(?:Z|[+-]\\d{2}:\\d{2})$/i.test(value);\n}\n\nfunction parseLocalDateTimeParts(value: unknown): LocalDateTimeParts | null {\n const match = String(value)\n .trim()\n .match(/^(\\d{4})-(\\d{2})-(\\d{2})[T ](\\d{2}):(\\d{2})(?::(\\d{2})(?:\\.\\d+)?)?$/);\n if (!match) return null;\n const [, year, month, day, hour, minute, second = \"00\"] = match;\n return {\n year: Number(year),\n month: Number(month),\n day: Number(day),\n hour: Number(hour),\n minute: Number(minute),\n second: Number(second),\n };\n}\n\nexport function parseTaskDateTime(value: unknown): Date | null {\n if (!value) return null;\n const raw = String(value).trim();\n if (!raw) return null;\n\n if (hasExplicitTimezone(raw)) {\n const date = new Date(raw);\n return Number.isNaN(date.getTime()) ? null : date;\n }\n\n const parts = parseLocalDateTimeParts(raw);\n if (parts) {\n return new Date(\n parts.year,\n parts.month - 1,\n parts.day,\n parts.hour,\n parts.minute,\n parts.second,\n 0,\n );\n }\n\n const fallback = new Date(raw);\n return Number.isNaN(fallback.getTime()) ? null : fallback;\n}\n\nexport function formatTaskDateTime(value: unknown, options?: Intl.DateTimeFormatOptions): string {\n const date = parseTaskDateTime(value);\n return date ? date.toLocaleString(undefined, options) : \"\";\n}\n\nexport function formatTaskTime(value: unknown, options?: Intl.DateTimeFormatOptions): string {\n const date = parseTaskDateTime(value);\n return date ? date.toLocaleTimeString(undefined, options) : \"\";\n}\n\nexport function formatDateTimeLocalInput(value: unknown): string {\n const date = parseTaskDateTime(value);\n if (!date) return \"\";\n return [\n date.getFullYear(),\n \"-\",\n pad(date.getMonth() + 1),\n \"-\",\n pad(date.getDate()),\n \"T\",\n pad(date.getHours()),\n \":\",\n pad(date.getMinutes()),\n ].join(\"\");\n}\n\nexport function serializeDateTimeLocalInput(value: unknown): string | null {\n const parts = parseLocalDateTimeParts(value);\n if (!parts) return null;\n return [\n parts.year,\n \"-\",\n pad(parts.month),\n \"-\",\n pad(parts.day),\n \"T\",\n pad(parts.hour),\n \":\",\n pad(parts.minute),\n \":\",\n pad(parts.second),\n ].join(\"\");\n}\n", - "export interface TelegramChannelState {\n enabled: boolean;\n configured: boolean;\n running: boolean;\n default_working_dir: string;\n default_chat_id: string;\n bot_token: string;\n allowed_users: string;\n}\n\nexport interface SlackChannelState {\n enabled: boolean;\n configured: boolean;\n running: boolean;\n default_working_dir: string;\n default_channel: string;\n default_user: string;\n bot_token: string;\n app_token: string;\n}\n\nexport interface WeixinChannelState {\n enabled: boolean;\n configured: boolean;\n running: boolean;\n default_working_dir: string;\n base_url: string;\n account_id: string;\n login_status: string;\n qr_code_url: string;\n last_error: string;\n user_id: string;\n}\n\nexport interface ChannelsState {\n telegram: TelegramChannelState;\n slack: SlackChannelState;\n weixin: WeixinChannelState;\n}\n\nexport interface ChannelsStatusUpdate {\n telegram?: Partial<TelegramChannelState>;\n slack?: Partial<SlackChannelState>;\n weixin?: Partial<WeixinChannelState>;\n}\n\nexport interface ChannelsSavePayload {\n telegram_enabled: string;\n telegram_bot_token: string;\n telegram_allowed_users: string;\n telegram_default_working_dir: string;\n telegram_default_chat_id: string;\n slack_enabled: string;\n slack_bot_token: string;\n slack_app_token: string;\n slack_default_working_dir: string;\n slack_default_channel: string;\n slack_default_user: string;\n weixin_enabled: string;\n weixin_default_working_dir: string;\n weixin_base_url: string;\n weixin_account_id: string;\n}\n\nconst DEFAULT_CHANNELS_STATE: ChannelsState = {\n telegram: {\n enabled: false,\n configured: false,\n running: false,\n default_working_dir: \"~\",\n default_chat_id: \"\",\n bot_token: \"\",\n allowed_users: \"\",\n },\n slack: {\n enabled: false,\n configured: false,\n running: false,\n default_working_dir: \"~\",\n default_channel: \"\",\n default_user: \"\",\n bot_token: \"\",\n app_token: \"\",\n },\n weixin: {\n enabled: false,\n configured: false,\n running: false,\n default_working_dir: \"~\",\n base_url: \"https://ilinkai.weixin.qq.com\",\n account_id: \"\",\n login_status: \"idle\",\n qr_code_url: \"\",\n last_error: \"\",\n user_id: \"\",\n },\n};\n\nfunction cloneState(state: ChannelsState): ChannelsState {\n return {\n telegram: { ...state.telegram },\n slack: { ...state.slack },\n weixin: { ...state.weixin },\n };\n}\n\nexport function createInitialChannelsState(initial: ChannelsStatusUpdate = {}): ChannelsState {\n const base = cloneState(DEFAULT_CHANNELS_STATE);\n return mergeChannelsStatus(base, initial);\n}\n\nexport function mergeChannelsStatus(\n current: ChannelsState,\n status: ChannelsStatusUpdate = {},\n): ChannelsState {\n return {\n telegram: { ...current.telegram, ...(status.telegram || {}) },\n slack: { ...current.slack, ...(status.slack || {}) },\n weixin: { ...current.weixin, ...(status.weixin || {}) },\n };\n}\n\nexport function buildChannelsSavePayload(channels: ChannelsState): ChannelsSavePayload {\n return {\n telegram_enabled: channels.telegram.enabled ? \"true\" : \"false\",\n telegram_bot_token: channels.telegram.bot_token,\n telegram_allowed_users: channels.telegram.allowed_users,\n telegram_default_working_dir: channels.telegram.default_working_dir,\n telegram_default_chat_id: channels.telegram.default_chat_id,\n slack_enabled: channels.slack.enabled ? \"true\" : \"false\",\n slack_bot_token: channels.slack.bot_token,\n slack_app_token: channels.slack.app_token,\n slack_default_working_dir: channels.slack.default_working_dir,\n slack_default_channel: channels.slack.default_channel,\n slack_default_user: channels.slack.default_user,\n weixin_enabled: channels.weixin.enabled ? \"true\" : \"false\",\n weixin_default_working_dir: channels.weixin.default_working_dir,\n weixin_base_url: channels.weixin.base_url,\n weixin_account_id: channels.weixin.account_id,\n };\n}\n\nexport function isWeixinQrImageSource(value: string | null | undefined): boolean {\n const normalized = (value || \"\").trim();\n if (!normalized) return false;\n if (normalized.startsWith(\"data:image/\")) return true;\n if (/\\.(png|jpg|jpeg|gif|webp|svg)(\\?|#|$)/i.test(normalized)) return true;\n return false;\n}\n", + "export interface TelegramChannelState {\n enabled: boolean;\n configured: boolean;\n running: boolean;\n default_working_dir: string;\n default_chat_id: string;\n bot_token: string;\n allowed_users: string;\n}\n\nexport interface SlackChannelState {\n enabled: boolean;\n configured: boolean;\n running: boolean;\n default_working_dir: string;\n default_channel: string;\n default_user: string;\n bot_token: string;\n app_token: string;\n}\n\nexport interface WeixinChannelState {\n enabled: boolean;\n configured: boolean;\n running: boolean;\n default_working_dir: string;\n base_url: string;\n account_id: string;\n login_status: string;\n qr_code_url: string;\n last_error: string;\n user_id: string;\n}\n\nexport interface ChannelsState {\n telegram: TelegramChannelState;\n slack: SlackChannelState;\n weixin: WeixinChannelState;\n}\n\nexport interface ChannelsStatusUpdate {\n telegram?: Partial<TelegramChannelState>;\n slack?: Partial<SlackChannelState>;\n weixin?: Partial<WeixinChannelState>;\n}\n\nexport interface ChannelsSavePayload {\n telegram_enabled: string;\n telegram_bot_token?: string;\n telegram_allowed_users: string;\n telegram_default_working_dir: string;\n telegram_default_chat_id: string;\n slack_enabled: string;\n slack_bot_token?: string;\n slack_app_token?: string;\n slack_default_working_dir: string;\n slack_default_channel: string;\n slack_default_user: string;\n weixin_enabled: string;\n weixin_default_working_dir: string;\n weixin_base_url: string;\n weixin_account_id: string;\n}\n\ninterface MergeChannelsStatusOptions {\n preserveEditableFields?: boolean;\n}\n\nconst DEFAULT_CHANNELS_STATE: ChannelsState = {\n telegram: {\n enabled: false,\n configured: false,\n running: false,\n default_working_dir: \"~\",\n default_chat_id: \"\",\n bot_token: \"\",\n allowed_users: \"\",\n },\n slack: {\n enabled: false,\n configured: false,\n running: false,\n default_working_dir: \"~\",\n default_channel: \"\",\n default_user: \"\",\n bot_token: \"\",\n app_token: \"\",\n },\n weixin: {\n enabled: false,\n configured: false,\n running: false,\n default_working_dir: \"~\",\n base_url: \"https://ilinkai.weixin.qq.com\",\n account_id: \"\",\n login_status: \"idle\",\n qr_code_url: \"\",\n last_error: \"\",\n user_id: \"\",\n },\n};\n\nfunction cloneState(state: ChannelsState): ChannelsState {\n return {\n telegram: { ...state.telegram },\n slack: { ...state.slack },\n weixin: { ...state.weixin },\n };\n}\n\nexport function createInitialChannelsState(initial: ChannelsStatusUpdate = {}): ChannelsState {\n const base = cloneState(DEFAULT_CHANNELS_STATE);\n return mergeChannelsStatus(base, initial);\n}\n\nexport function mergeChannelsStatus(\n current: ChannelsState,\n status: ChannelsStatusUpdate = {},\n options: MergeChannelsStatusOptions = {},\n): ChannelsState {\n const merged = {\n telegram: { ...current.telegram, ...(status.telegram || {}) },\n slack: { ...current.slack, ...(status.slack || {}) },\n weixin: { ...current.weixin, ...(status.weixin || {}) },\n };\n if (!options.preserveEditableFields) return merged;\n\n return {\n telegram: {\n ...merged.telegram,\n enabled: current.telegram.enabled,\n bot_token: current.telegram.bot_token,\n allowed_users: current.telegram.allowed_users,\n default_working_dir: current.telegram.default_working_dir,\n default_chat_id: current.telegram.default_chat_id,\n },\n slack: {\n ...merged.slack,\n enabled: current.slack.enabled,\n bot_token: current.slack.bot_token,\n app_token: current.slack.app_token,\n default_working_dir: current.slack.default_working_dir,\n default_channel: current.slack.default_channel,\n default_user: current.slack.default_user,\n },\n weixin: {\n ...merged.weixin,\n enabled: current.weixin.enabled,\n default_working_dir: current.weixin.default_working_dir,\n base_url: current.weixin.base_url,\n account_id: current.weixin.account_id,\n },\n };\n}\n\nexport function buildChannelsSavePayload(channels: ChannelsState): ChannelsSavePayload {\n const payload: ChannelsSavePayload = {\n telegram_enabled: channels.telegram.enabled ? \"true\" : \"false\",\n telegram_allowed_users: channels.telegram.allowed_users,\n telegram_default_working_dir: channels.telegram.default_working_dir,\n telegram_default_chat_id: channels.telegram.default_chat_id,\n slack_enabled: channels.slack.enabled ? \"true\" : \"false\",\n slack_default_working_dir: channels.slack.default_working_dir,\n slack_default_channel: channels.slack.default_channel,\n slack_default_user: channels.slack.default_user,\n weixin_enabled: channels.weixin.enabled ? \"true\" : \"false\",\n weixin_default_working_dir: channels.weixin.default_working_dir,\n weixin_base_url: channels.weixin.base_url,\n weixin_account_id: channels.weixin.account_id,\n };\n if (channels.telegram.bot_token.trim()) {\n payload.telegram_bot_token = channels.telegram.bot_token;\n }\n if (channels.slack.bot_token.trim()) {\n payload.slack_bot_token = channels.slack.bot_token;\n }\n if (channels.slack.app_token.trim()) {\n payload.slack_app_token = channels.slack.app_token;\n }\n return payload;\n}\n\nexport function isWeixinQrImageSource(value: string | null | undefined): boolean {\n const normalized = (value || \"\").trim();\n if (!normalized) return false;\n if (normalized.startsWith(\"data:image/\")) return true;\n if (/\\.(png|jpg|jpeg|gif|webp|svg)(\\?|#|$)/i.test(normalized)) return true;\n return false;\n}\n", "export const TRACE_EVENT_TYPES = new Set([\n \"tool_call\",\n \"tool_result\",\n \"command_execution\",\n \"file_change\",\n \"web_search\",\n]);\n\nconst THINKING_PREFIX = \"[thinking] \";\n\nexport interface TraceRow {\n label: string;\n value: string;\n}\n\nexport type TracePayload = Record<string, any>;\n\nexport interface TraceEventInput {\n id?: number;\n event_type?: string;\n type?: string;\n content?: string;\n timestamp?: string;\n}\n\nexport interface ExecutionStep {\n id: string;\n eventIds: number[];\n rawEventType: string;\n timestamp: string;\n rows: TraceRow[];\n detail: string;\n count: number;\n type: string;\n title: string;\n imageSrc?: string;\n number?: number;\n}\n\nfunction compact(rows: Array<TraceRow | null>): TraceRow[] {\n return rows.filter(Boolean) as TraceRow[];\n}\n\nfunction row(label: string, value: unknown): TraceRow | null {\n const formatted = formatTraceValue(value);\n return formatted === \"\" ? null : { label, value: formatted };\n}\n\nexport function parseTracePayload(content: string): TracePayload | null {\n try {\n const payload = JSON.parse(content);\n return payload && typeof payload === \"object\" && !Array.isArray(payload) ? payload : null;\n } catch {\n return null;\n }\n}\n\nexport function formatTraceValue(value: unknown): string {\n if (value === undefined || value === null) return \"\";\n if (typeof value === \"string\") return value;\n return JSON.stringify(value, null, 2);\n}\n\nexport function buildTraceRows(\n eventType: string,\n payload: TracePayload,\n rawContent = \"\",\n): TraceRow[] {\n if (eventType === \"tool_call\") {\n const name = payload.server\n ? `${payload.server}.${payload.name || payload.tool || \"unknown\"}`\n : payload.name || payload.tool || \"unknown\";\n return compact([\n row(\"Tool\", name),\n row(\"Input\", payload.input || payload.arguments),\n row(\"Result\", payload.result),\n row(\"Status\", payload.status),\n row(\"Error\", payload.error),\n ]);\n }\n\n if (eventType === \"tool_result\") {\n return compact([\n row(payload.is_error ? \"Tool Error\" : \"Tool Result\", payload.tool_use_id || \"result\"),\n row(\"Content\", payload.content),\n ]);\n }\n\n if (eventType === \"command_execution\") {\n return compact([\n row(\"Command\", payload.command),\n row(\"Output\", payload.output),\n row(\"Exit\", payload.exit_code),\n row(\"Status\", payload.status),\n ]);\n }\n\n if (eventType === \"file_change\") {\n const changes = Array.isArray(payload.changes)\n ? payload.changes\n .map((change: any) => {\n if (!change || typeof change !== \"object\") return formatTraceValue(change);\n const kind = change.kind || change.type || \"changed\";\n const path = change.path || change.file || \"\";\n return path ? `${kind}: ${path}` : kind;\n })\n .join(\"\\n\")\n : payload.changes;\n return compact([row(\"Changes\", changes), row(\"Status\", payload.status)]);\n }\n\n if (eventType === \"web_search\") {\n return compact([\n row(\"Query\", payload.query),\n row(\"Action\", payload.action),\n row(\"Status\", payload.status),\n ]);\n }\n\n return [{ label: eventType, value: rawContent }];\n}\n\nexport function buildExecutionSteps(events: TraceEventInput[] | null | undefined): ExecutionStep[] {\n const sortedEvents = [...(events || [])].sort(compareEventsChronologically);\n const steps: ExecutionStep[] = [];\n\n for (const event of sortedEvents) {\n const step = eventToStep(event);\n if (!step) continue;\n\n const previous = steps[steps.length - 1];\n if (canMergeSteps(previous, step)) {\n previous.detail = appendDetail(previous.detail, step.detail);\n previous.title = summarizeTitle(previous.detail) || previous.title;\n previous.eventIds.push(...step.eventIds);\n previous.count += step.count;\n previous.timestamp = step.timestamp;\n continue;\n }\n\n steps.push(step);\n }\n\n return steps.map((step, index) => ({\n ...step,\n number: index + 1,\n }));\n}\n\nfunction compareEventsChronologically(a: TraceEventInput, b: TraceEventInput): number {\n const timestampComparison = String(a.timestamp || \"\").localeCompare(String(b.timestamp || \"\"));\n if (timestampComparison !== 0) return timestampComparison;\n return Number(a.id || 0) - Number(b.id || 0);\n}\n\nfunction eventToStep(event: TraceEventInput): ExecutionStep | null {\n const eventType = event.event_type || event.type || \"unknown\";\n const content = event.content || \"\";\n const base = {\n id: event.id ? `event-${event.id}` : `${eventType}-${event.timestamp || \"\"}-${content.length}`,\n eventIds: event.id ? [event.id] : [],\n rawEventType: eventType,\n timestamp: event.timestamp || \"\",\n rows: [] as TraceRow[],\n detail: content,\n count: 1,\n };\n\n if (eventType === \"assistant\") {\n if (content.startsWith(THINKING_PREFIX)) {\n const detail = content.slice(THINKING_PREFIX.length);\n return {\n ...base,\n type: \"thinking\",\n title: summarizeTitle(detail) || \"Thinking\",\n detail,\n };\n }\n return {\n ...base,\n type: \"assistant\",\n title: summarizeTitle(content) || \"Assistant message\",\n };\n }\n\n if (eventType === \"user\") {\n return {\n ...base,\n type: \"user\",\n title: summarizeTitle(content) || \"User message\",\n };\n }\n\n if (eventType === \"result\") {\n return {\n ...base,\n type: \"result\",\n title: summarizeTitle(content, \"Result\") || \"Result\",\n };\n }\n\n if (eventType === \"error\") {\n return {\n ...base,\n type: \"error\",\n title: summarizeTitle(content, \"Error\") || \"Error\",\n };\n }\n\n if (eventType === \"image_content\") {\n const payload = parseTracePayload(content) || {};\n const mediaType = payload.media_type || \"image/jpeg\";\n const imageSrc = payload.data ? `data:${mediaType};base64,${payload.data}` : \"\";\n return {\n ...base,\n type: \"image_content\",\n title: \"Image output\",\n rows: compact([row(\"Media\", mediaType)]),\n detail: \"[image]\",\n imageSrc,\n };\n }\n\n if (eventType === \"generated_image\") {\n const payload = parseTracePayload(content) || { content };\n const imagePath = payload.path || payload.content || \"\";\n return {\n ...base,\n type: \"generated_image\",\n title: imagePath ? `Generated image: ${basename(imagePath)}` : \"Generated image\",\n rows: compact([row(\"Path\", imagePath), row(\"Media\", payload.media_type)]),\n detail: imagePath,\n };\n }\n\n if (!TRACE_EVENT_TYPES.has(eventType)) {\n return {\n ...base,\n type: \"event\",\n title: summarizeTitle(content, eventType) || eventType,\n };\n }\n\n const payload = parseTracePayload(content) || { content };\n const rows = buildTraceRows(eventType, payload, content);\n return {\n ...base,\n type: eventType,\n title: titleForTraceEvent(eventType, payload),\n rows,\n detail: rows.map((item) => `${item.label}: ${item.value}`).join(\"\\n\"),\n };\n}\n\nfunction titleForTraceEvent(eventType: string, payload: TracePayload): string {\n if (eventType === \"tool_call\") {\n const name = payload.server\n ? `${payload.server}.${payload.name || payload.tool || \"unknown\"}`\n : payload.name || payload.tool || \"unknown\";\n return `Call tool: ${name}`;\n }\n\n if (eventType === \"tool_result\") {\n const label = payload.is_error ? \"Tool error\" : \"Tool result\";\n return `${label}: ${payload.tool_use_id || \"result\"}`;\n }\n\n if (eventType === \"command_execution\") {\n return `Run command: ${payload.command || payload.content || \"command\"}`;\n }\n\n if (eventType === \"web_search\") {\n return `Search web: ${payload.query || payload.content || \"query\"}`;\n }\n\n if (eventType === \"file_change\") {\n const changes = Array.isArray(payload.changes) ? payload.changes : [];\n const firstPath = changes.find(\n (change: any) => change && typeof change === \"object\" && (change.path || change.file),\n );\n return firstPath ? `Change file: ${firstPath.path || firstPath.file}` : \"Change files\";\n }\n\n return eventType;\n}\n\nfunction canMergeSteps(previous: ExecutionStep | undefined, next: ExecutionStep): boolean {\n return Boolean(\n previous &&\n previous.type === next.type &&\n (next.type === \"thinking\" || next.type === \"assistant\") &&\n previous.rawEventType === next.rawEventType,\n );\n}\n\nfunction appendDetail(previous: string, next: string): string {\n if (!previous) return next || \"\";\n if (!next) return previous;\n if (\n previous.endsWith(\"\\n\") ||\n previous.endsWith(\" \") ||\n next.startsWith(\"\\n\") ||\n next.startsWith(\" \")\n ) {\n return previous + next;\n }\n return `${previous}\\n${next}`;\n}\n\nfunction summarizeTitle(text: unknown, prefix = \"\"): string {\n const normalized = String(text || \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n if (!normalized) return prefix;\n const title = normalized.length > 120 ? `${normalized.slice(0, 117).trim()}...` : normalized;\n return prefix ? `${prefix}: ${title}` : title;\n}\n\nfunction basename(value: unknown): string {\n const parts = String(value || \"\")\n .split(/[\\\\/]/)\n .filter(Boolean);\n return parts[parts.length - 1] || String(value || \"\");\n}\n" ], - "mappings": "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AAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IACd;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IACd;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IACd;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IACd;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAM;AAAA,IAChB;AAAA,IAAK;AAAA,IAAK;AAAA,IAAM;AAAA,IAChB;AAAA,IAAK;AAAA,IAAK;AAAA,IAAM;AAAA,IAChB;AAAA,IAAK;AAAA,IAAK;AAAA,IAAM;AAAA,IAChB;AAAA,IAAK;AAAA,IAAK;AAAA,IAAM;AAAA,IAChB;AAAA,IAAK;AAAA,IAAK;AAAA,IAAM;AAAA,IAChB;AAAA,IAAK;AAAA,IAAK;AAAA,IAAM;AAAA,IAChB;AAAA,IAAK;AAAA,IAAM;AAAA,IAAM;AAAA,IACjB;AAAA,IAAK;AAAA,IAAM;AAAA,IAAM;AAAA,IACjB;AAAA,IAAK;AAAA,IAAM;AAAA,IAAM;AAAA,IACjB;AAAA,IAAK;AAAA,IAAM;AAAA,IAAM;AAAA,IACjB;AAAA,IAAK;AAAA,IAAM;AAAA,IAAM;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", - "debugId": "018A608DD777E92F64756E2164756E21", + "mappings": "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AAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IACd;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IACd;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IACd;AAAA,IAAI;AAAA,IAAK;AAAA,IAAK;AAAA,IACd;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAK;AAAA,IACf;AAAA,IAAK;AAAA,IAAK;AAAA,IAAM;AAAA,IAChB;AAAA,IAAK;AAAA,IAAK;AAAA,IAAM;AAAA,IAChB;AAAA,IAAK;AAAA,IAAK;AAAA,IAAM;AAAA,IAChB;AAAA,IAAK;AAAA,IAAK;AAAA,IAAM;AAAA,IAChB;AAAA,IAAK;AAAA,IAAK;AAAA,IAAM;AAAA,IAChB;AAAA,IAAK;AAAA,IAAK;AAAA,IAAM;AAAA,IAChB;AAAA,IAAK;AAAA,IAAK;AAAA,IAAM;AAAA,IAChB;AAAA,IAAK;AAAA,IAAM;AAAA,IAAM;AAAA,IACjB;AAAA,IAAK;AAAA,IAAM;AAAA,IAAM;AAAA,IACjB;AAAA,IAAK;AAAA,IAAM;AAAA,IAAM;AAAA,IACjB;AAAA,IAAK;AAAA,IAAM;AAAA,IAAM;AAAA,IACjB;AAAA,IAAK;AAAA,IAAM;AAAA,IAAM;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", + "debugId": "6D6D54C3905035A964756E2164756E21", "names": [] } \ No newline at end of file diff --git a/taskboard-electron/.bun/renderer/index.html b/taskboard-electron/.bun/renderer/index.html index a40d4f2..8283b35 100644 --- a/taskboard-electron/.bun/renderer/index.html +++ b/taskboard-electron/.bun/renderer/index.html @@ -3,7 +3,7 @@ <head> <meta charset="UTF-8" /> <title>AgentForge - +
diff --git a/taskboard-electron/forge.config.js b/taskboard-electron/forge.config.js index 3e64c16..1b8813c 100644 --- a/taskboard-electron/forge.config.js +++ b/taskboard-electron/forge.config.js @@ -6,7 +6,11 @@ module.exports = { asar: true, name: "AgentForge", appBundleId: "com.agentforge.app", - extraResource: ["./resources/taskboard"], + extraResource: [ + "./resources/taskboard", + "./resources/weixin-bridge", + "../vendor/skill-creator", + ], // Bun builds the app into .bun/ (see scripts/build.ts); ship only the // built output, package.json, and pruned node_modules. ignore: [ diff --git a/taskboard-electron/scripts/build-backend.ts b/taskboard-electron/scripts/build-backend.ts index 21967b4..a104af7 100644 --- a/taskboard-electron/scripts/build-backend.ts +++ b/taskboard-electron/scripts/build-backend.ts @@ -1,6 +1,7 @@ -// Compile the Bun TypeScript backend into a single-file binary bundled with -// the Electron app (replaces the PyInstaller build of taskboard.py). +// Compile the Bun TypeScript backend into the single-file binary bundled with +// the Electron app. import { spawnSync } from "node:child_process"; +import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; @@ -12,16 +13,32 @@ if (process.env.SKIP_BACKEND_BUILD === "1") { const scriptDir = path.dirname(fileURLToPath(import.meta.url)); const appRoot = path.resolve(scriptDir, ".."); const backendDir = path.resolve(appRoot, "..", "backend"); -const outfile = path.join(appRoot, "resources", "taskboard"); +const resourcesDir = path.join(appRoot, "resources"); +const backendOutfile = path.join(resourcesDir, "taskboard"); +const weixinBridgeOutfile = path.join(resourcesDir, "weixin-bridge"); -console.log("[build-backend] Compiling Bun backend binary..."); +fs.mkdirSync(resourcesDir, { recursive: true }); -const result = spawnSync("bun", ["build", "--compile", "taskboard.ts", "--outfile", outfile], { - cwd: backendDir, - stdio: "inherit", -}); +function runBuild(label: string, args: string[]): void { + console.log(`[build-backend] Compiling ${label}...`); + const result = spawnSync("bun", args, { + cwd: backendDir, + stdio: "inherit", + }); -if (result.status !== 0) { - process.exit(result.status ?? 1); + if (result.status !== 0) { + process.exit(result.status ?? 1); + } } -console.log(`[build-backend] Backend binary written to ${outfile}`); + +runBuild("Bun backend binary", ["build", "--compile", "taskboard.ts", "--outfile", backendOutfile]); +console.log(`[build-backend] Backend binary written to ${backendOutfile}`); + +runBuild("Weixin bridge binary", [ + "build", + "--compile", + path.join("src", "channels", "weixin_bridge", "index.ts"), + "--outfile", + weixinBridgeOutfile, +]); +console.log(`[build-backend] Weixin bridge binary written to ${weixinBridgeOutfile}`); diff --git a/taskboard-electron/scripts/build.ts b/taskboard-electron/scripts/build.ts index 206a13d..2224c10 100644 --- a/taskboard-electron/scripts/build.ts +++ b/taskboard-electron/scripts/build.ts @@ -4,9 +4,12 @@ // .bun/build/preload.js - context-bridge preload (CJS) // .bun/renderer/index.html (+ hashed assets) - React renderer import path from "node:path"; +import fs from "node:fs/promises"; import { fileURLToPath } from "node:url"; const appRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); +const mainOutDir = path.join(appRoot, ".bun/build"); +const rendererOutDir = path.join(appRoot, ".bun/renderer"); function reportFailure(label: string, result: Awaited>): never { console.error(`[build] ${label} failed`); @@ -17,7 +20,7 @@ function reportFailure(label: string, result: Awaited { const result = await Bun.build({ entrypoints: [path.join(appRoot, "src/main.ts")], - outdir: path.join(appRoot, ".bun/build"), + outdir: mainOutDir, target: "node", format: "cjs", // Runtime deps resolved from packaged node_modules; electron is provided @@ -33,7 +36,7 @@ export async function buildMain(): Promise { export async function buildPreload(): Promise { const result = await Bun.build({ entrypoints: [path.join(appRoot, "src/preload.ts")], - outdir: path.join(appRoot, ".bun/build"), + outdir: mainOutDir, target: "node", format: "cjs", external: ["electron"], @@ -47,7 +50,7 @@ export async function buildPreload(): Promise { export async function buildRenderer(): Promise { const result = await Bun.build({ entrypoints: [path.join(appRoot, "index.html")], - outdir: path.join(appRoot, ".bun/renderer"), + outdir: rendererOutDir, target: "browser", sourcemap: "linked", define: { "process.env.NODE_ENV": '"production"' }, @@ -58,6 +61,10 @@ export async function buildRenderer(): Promise { } export async function buildAll(): Promise { + await Promise.all([ + fs.rm(mainOutDir, { recursive: true, force: true }), + fs.rm(rendererOutDir, { recursive: true, force: true }), + ]); await Promise.all([buildMain(), buildPreload(), buildRenderer()]); } diff --git a/taskboard-electron/src/main.ts b/taskboard-electron/src/main.ts index a21a2bf..5f396b4 100644 --- a/taskboard-electron/src/main.ts +++ b/taskboard-electron/src/main.ts @@ -10,6 +10,7 @@ interface BackendCommand { cmd: string; args: string[]; cwd: string | undefined; + env?: Record; } if (started) { @@ -24,7 +25,14 @@ function getBackendCommand(): BackendCommand { if (app.isPackaged) { // Single-file binary produced by `bun build --compile`. const binaryPath = path.join(process.resourcesPath, "taskboard"); - return { cmd: binaryPath, args: [], cwd: undefined }; + return { + cmd: binaryPath, + args: [], + cwd: undefined, + env: { + AGENTFORGE_WEIXIN_BRIDGE: path.join(process.resourcesPath, "weixin-bridge"), + }, + }; } else { // In dev mode, app.getAppPath() returns taskboard-electron/ dir; // the project root (containing backend/) is one level up. Keep cwd at @@ -99,10 +107,10 @@ function augmentedPath(): string { function startBackend(): Promise { killPortSync(9712); - const { cmd, args, cwd } = getBackendCommand(); + const { cmd, args, cwd, env } = getBackendCommand(); backendProcess = spawn(cmd, args, { stdio: ["ignore", "pipe", "pipe"], - env: { ...process.env, PATH: augmentedPath() }, + env: { ...process.env, PATH: augmentedPath(), ...env }, ...(cwd ? { cwd } : {}), }); diff --git a/taskboard-electron/src/renderer/App.tsx b/taskboard-electron/src/renderer/App.tsx index 1c2291b..c286d1a 100644 --- a/taskboard-electron/src/renderer/App.tsx +++ b/taskboard-electron/src/renderer/App.tsx @@ -3404,15 +3404,9 @@ function SettingsModal({ const status = await fetchChannelsStatus(); if (!cancelled) { setChannels((c) => { - const merged = mergeChannelsStatus(c, status); - if (!preserveUserEdits) return merged; - // During background polling, keep user-edited config fields untouched - // so toggling enabled / editing URLs isn't overwritten before Save. - return { - telegram: { ...merged.telegram, enabled: c.telegram.enabled }, - slack: { ...merged.slack, enabled: c.slack.enabled }, - weixin: { ...merged.weixin, enabled: c.weixin.enabled }, - }; + return mergeChannelsStatus(c, status, { + preserveEditableFields: preserveUserEdits, + }); }); } }; @@ -5854,7 +5848,7 @@ export default function App() { {connected ? ( ● Connected ) : ( - ● Disconnected — run `python taskboard.py` + ● Disconnected — run `bun taskboard.ts` )} {connected && ` · ${runningCount} running · ${scheduledCount} scheduled · ${enabledHeartbeatCount} heartbeats`} @@ -6201,9 +6195,9 @@ export default function App() { Backend not running - pip install croniter + cd backend
- python taskboard.py + bun taskboard.ts
)} diff --git a/taskboard-electron/src/renderer/channelsSettings.test.ts b/taskboard-electron/src/renderer/channelsSettings.test.ts index bc45dd2..cfbf301 100644 --- a/taskboard-electron/src/renderer/channelsSettings.test.ts +++ b/taskboard-electron/src/renderer/channelsSettings.test.ts @@ -44,6 +44,45 @@ test("mergeChannelsStatus overlays weixin status onto existing state", () => { expect(merged.weixin.account_id).toBe("wx-demo"); }); +test("mergeChannelsStatus keeps telegram edits when preserving editable fields", () => { + const current = createInitialChannelsState({ + telegram: { + enabled: true, + bot_token: "123456:edited", + allowed_users: "42,99", + default_working_dir: "~/workspace/edited", + default_chat_id: "-100edited", + running: false, + configured: false, + }, + }); + + const merged = mergeChannelsStatus( + current, + { + telegram: { + enabled: false, + allowed_users: "", + default_working_dir: "~", + default_chat_id: "", + running: true, + configured: true, + }, + }, + { preserveEditableFields: true }, + ); + + expect(merged.telegram).toEqual({ + enabled: true, + bot_token: "123456:edited", + allowed_users: "42,99", + default_working_dir: "~/workspace/edited", + default_chat_id: "-100edited", + running: true, + configured: true, + }); +}); + test("buildChannelsSavePayload serializes weixin settings for the API", () => { const payload = buildChannelsSavePayload({ ...createInitialChannelsState(), @@ -63,6 +102,34 @@ test("buildChannelsSavePayload serializes weixin settings for the API", () => { expect(payload.weixin_account_id).toBe("wx-primary"); }); +test("buildChannelsSavePayload omits blank channel secrets", () => { + const payload = buildChannelsSavePayload({ + ...createInitialChannelsState(), + telegram: { + ...createInitialChannelsState().telegram, + enabled: true, + bot_token: "", + allowed_users: "42", + default_working_dir: "~/workspace/agentforge", + default_chat_id: "-100123", + }, + slack: { + ...createInitialChannelsState().slack, + enabled: true, + bot_token: "", + app_token: "", + default_channel: "C123", + }, + }); + + expect("telegram_bot_token" in payload).toBe(false); + expect("slack_bot_token" in payload).toBe(false); + expect("slack_app_token" in payload).toBe(false); + expect(payload.telegram_allowed_users).toBe("42"); + expect(payload.telegram_default_chat_id).toBe("-100123"); + expect(payload.slack_default_channel).toBe("C123"); +}); + test("isWeixinQrImageSource recognizes real image sources only", () => { expect(isWeixinQrImageSource("data:image/png;base64,abc")).toBe(true); expect(isWeixinQrImageSource("https://example.test/qr.png")).toBe(true); diff --git a/taskboard-electron/src/renderer/channelsSettings.ts b/taskboard-electron/src/renderer/channelsSettings.ts index 2605580..58521db 100644 --- a/taskboard-electron/src/renderer/channelsSettings.ts +++ b/taskboard-electron/src/renderer/channelsSettings.ts @@ -46,13 +46,13 @@ export interface ChannelsStatusUpdate { export interface ChannelsSavePayload { telegram_enabled: string; - telegram_bot_token: string; + telegram_bot_token?: string; telegram_allowed_users: string; telegram_default_working_dir: string; telegram_default_chat_id: string; slack_enabled: string; - slack_bot_token: string; - slack_app_token: string; + slack_bot_token?: string; + slack_app_token?: string; slack_default_working_dir: string; slack_default_channel: string; slack_default_user: string; @@ -62,6 +62,10 @@ export interface ChannelsSavePayload { weixin_account_id: string; } +interface MergeChannelsStatusOptions { + preserveEditableFields?: boolean; +} + const DEFAULT_CHANNELS_STATE: ChannelsState = { telegram: { enabled: false, @@ -112,24 +116,50 @@ export function createInitialChannelsState(initial: ChannelsStatusUpdate = {}): export function mergeChannelsStatus( current: ChannelsState, status: ChannelsStatusUpdate = {}, + options: MergeChannelsStatusOptions = {}, ): ChannelsState { - return { + const merged = { telegram: { ...current.telegram, ...(status.telegram || {}) }, slack: { ...current.slack, ...(status.slack || {}) }, weixin: { ...current.weixin, ...(status.weixin || {}) }, }; + if (!options.preserveEditableFields) return merged; + + return { + telegram: { + ...merged.telegram, + enabled: current.telegram.enabled, + bot_token: current.telegram.bot_token, + allowed_users: current.telegram.allowed_users, + default_working_dir: current.telegram.default_working_dir, + default_chat_id: current.telegram.default_chat_id, + }, + slack: { + ...merged.slack, + enabled: current.slack.enabled, + bot_token: current.slack.bot_token, + app_token: current.slack.app_token, + default_working_dir: current.slack.default_working_dir, + default_channel: current.slack.default_channel, + default_user: current.slack.default_user, + }, + weixin: { + ...merged.weixin, + enabled: current.weixin.enabled, + default_working_dir: current.weixin.default_working_dir, + base_url: current.weixin.base_url, + account_id: current.weixin.account_id, + }, + }; } export function buildChannelsSavePayload(channels: ChannelsState): ChannelsSavePayload { - return { + const payload: ChannelsSavePayload = { telegram_enabled: channels.telegram.enabled ? "true" : "false", - telegram_bot_token: channels.telegram.bot_token, telegram_allowed_users: channels.telegram.allowed_users, telegram_default_working_dir: channels.telegram.default_working_dir, telegram_default_chat_id: channels.telegram.default_chat_id, slack_enabled: channels.slack.enabled ? "true" : "false", - slack_bot_token: channels.slack.bot_token, - slack_app_token: channels.slack.app_token, slack_default_working_dir: channels.slack.default_working_dir, slack_default_channel: channels.slack.default_channel, slack_default_user: channels.slack.default_user, @@ -138,6 +168,16 @@ export function buildChannelsSavePayload(channels: ChannelsState): ChannelsSaveP weixin_base_url: channels.weixin.base_url, weixin_account_id: channels.weixin.account_id, }; + if (channels.telegram.bot_token.trim()) { + payload.telegram_bot_token = channels.telegram.bot_token; + } + if (channels.slack.bot_token.trim()) { + payload.slack_bot_token = channels.slack.bot_token; + } + if (channels.slack.app_token.trim()) { + payload.slack_app_token = channels.slack.app_token; + } + return payload; } export function isWeixinQrImageSource(value: string | null | undefined): boolean { diff --git a/taskboard.py b/taskboard.py deleted file mode 100644 index accf733..0000000 --- a/taskboard.py +++ /dev/null @@ -1,5240 +0,0 @@ -""" -AgentForge - macOS App -A kanban-style task board for orchestrating AI coding agents with cron scheduling and delayed execution. -""" - -import base64 -import json -import logging -import os -import secrets -import signal -import sqlite3 -import subprocess -import sys -import threading -import time -from contextlib import contextmanager -from dataclasses import dataclass, field -from datetime import datetime, timedelta -from enum import Enum -from http.server import BaseHTTPRequestHandler, HTTPServer -from pathlib import Path -from typing import Callable, Optional -from urllib.parse import parse_qs, urlparse - -from croniter import croniter - -from taskboard_bus import ( - BusAwareSchedulerMixin, - MessageBus, - OutboundMessageType, - UIChannel, -) - -log_level = os.environ.get("AGENTFORGE_LOG_LEVEL", "INFO").upper() -logging.basicConfig( - level=getattr(logging, log_level, logging.INFO), - format="%(asctime)s %(levelname)s %(name)s: %(message)s", - datefmt="%Y-%m-%d %H:%M:%S", -) -logger = logging.getLogger("agentforge") - -CLAUDE_STREAM_JSON_ARGS = [ - "--output-format", - "stream-json", - "--include-partial-messages", - "--verbose", - "--permission-mode", - "bypassPermissions", -] -DEFAULT_AGENT = "codex" -DEFAULT_TIMEOUT_SECONDS = 12000 - -LIVE_OUTPUT_EVENT_TYPES = { - "assistant", - "tool_call", - "tool_result", - "command_execution", - "file_change", - "web_search", - "error", -} -SECRET_KEY_FRAGMENTS = ( - "api_key", - "apikey", - "authorization", - "auth_token", - "credential", - "password", - "secret", - "token", -) -GENERATED_IMAGE_MEDIA_TYPES = { - ".png": "image/png", - ".jpg": "image/jpeg", - ".jpeg": "image/jpeg", - ".gif": "image/gif", - ".webp": "image/webp", -} - -try: - from channels.feishu_channel import FeishuChannel - - FEISHU_CHANNEL_AVAILABLE = True -except ImportError: - FEISHU_CHANNEL_AVAILABLE = False - FeishuChannel = None - -try: - from channels.telegram_channel import create_telegram_channel - - TELEGRAM_CHANNEL_AVAILABLE = True -except ImportError: - TELEGRAM_CHANNEL_AVAILABLE = False - create_telegram_channel = None - -try: - from channels.slack_channel import SlackChannel - - SLACK_CHANNEL_AVAILABLE = True -except ImportError: - SLACK_CHANNEL_AVAILABLE = False - SlackChannel = None - -try: - from channels.weixin_channel import WeixinChannel - - WEIXIN_CHANNEL_AVAILABLE = True -except ImportError: - WEIXIN_CHANNEL_AVAILABLE = False - WeixinChannel = None - - -# ──────────────────────────── Helpers ──────────────────────────── - - -def _get_env() -> dict: - """Return os.environ augmented with common macOS tool install paths. - Electron (and other GUI launchers) inherit a stripped PATH that often - misses npm globals, Homebrew, and ~/.local/bin. - """ - env = os.environ.copy() - home = os.path.expanduser("~") - extra = [ - f"{home}/.local/bin", - "/usr/local/bin", - "/opt/homebrew/bin", # Apple-silicon Homebrew - "/usr/local/opt/node/bin", - f"{home}/.npm/bin", - f"{home}/.nvm/current/bin", - "/usr/bin", - "/bin", - ] - current = env.get("PATH", "") - env["PATH"] = ":".join(p for p in extra if p not in current) + ( - f":{current}" if current else "" - ) - return env - - -def _parse_comparable_datetime(value: Optional[str]) -> Optional[datetime]: - """Parse ISO datetimes and collapse aware values into local naive datetimes. - - The app historically stored naive local timestamps, but the Electron UI can - submit offset-aware ISO strings for `scheduled_at`. Converting aware values - into the local timezone and stripping tzinfo keeps storage/comparisons - consistent with the rest of the backend while remaining backward compatible - with legacy rows. - """ - if not value: - return None - dt = datetime.fromisoformat(value) - if dt.tzinfo is not None: - return dt.astimezone().replace(tzinfo=None) - return dt - - -def _normalize_datetime_for_storage(value: Optional[str]) -> Optional[str]: - if value is None: - return None - try: - dt = _parse_comparable_datetime(value) - except ValueError: - return value - return dt.isoformat() if dt else None - - -def _build_weixin_channel_status(db, weixin_channel) -> dict: - weixin_status = ( - weixin_channel.get_status_snapshot() - if weixin_channel and hasattr(weixin_channel, "get_status_snapshot") - else {} - ) - runtime_account_id = weixin_status.get("account_id", "") - configured_account_id = db.get_setting("weixin_account_id", "") - return { - "enabled": db.get_setting("weixin_enabled", "false") == "true", - "configured": bool(weixin_status.get("configured", False)), - "running": bool(weixin_channel and getattr(weixin_channel, "_running", False)), - "default_working_dir": db.get_setting("weixin_default_working_dir", "~"), - "base_url": db.get_setting("weixin_base_url", "https://ilinkai.weixin.qq.com"), - "account_id": runtime_account_id or configured_account_id, - "login_status": weixin_status.get("login_status", "idle"), - "qr_code_url": weixin_status.get("qr_code_url", ""), - "last_error": weixin_status.get("last_error", ""), - "user_id": weixin_status.get("user_id", ""), - } - - -# ──────────────────────────── Models ──────────────────────────── - - -class TaskStatus(str, Enum): - PENDING = "pending" - SCHEDULED = "scheduled" - RUNNING = "running" - COMPLETED = "completed" - FAILED = "failed" - CANCELLED = "cancelled" - BLOCKED = "blocked" # has unmet upstream dependencies - - -class ScheduleType(str, Enum): - IMMEDIATE = "immediate" - DELAYED = "delayed" # run after N seconds - SCHEDULED_AT = "scheduled_at" # run at a specific datetime - CRON = "cron" # recurring cron expression - - -class HeartbeatScheduleType(str, Enum): - CRON = "cron" - INTERVAL = "interval" - - -class HeartbeatDecisionType(str, Enum): - IDLE = "idle" - TRIGGER_TASK = "trigger_task" - RESUME_TASK = "resume_task" - NOTIFY_ONLY = "notify_only" - ERROR = "error" - - -@dataclass -class Task: - id: Optional[int] = None - title: str = "" - prompt: str = "" - working_dir: str = "." - status: TaskStatus = TaskStatus.PENDING - schedule_type: ScheduleType = ScheduleType.IMMEDIATE - cron_expr: Optional[str] = None # e.g. "*/30 * * * *" - delay_seconds: Optional[int] = None # e.g. 300 - next_run_at: Optional[str] = None # ISO timestamp - last_run_at: Optional[str] = None - result: Optional[str] = None - error: Optional[str] = None - run_count: int = 0 - max_runs: Optional[int] = None # None = unlimited for cron - created_at: Optional[str] = None - updated_at: Optional[str] = None - tags: str = "" # comma-separated - agent: str = DEFAULT_AGENT - question: Optional[str] = None # question the agent asked - answer: Optional[str] = None # user's answer - session_id: Optional[str] = None # agent session/thread id for resume - prompt_images: list = field(default_factory=list) # [{media_type, data, name}] - image_paths: list = field(default_factory=list) # list of local image file paths - dag_id: Optional[str] = None # optional DAG workflow group label - feishu_root_msg_id: Optional[str] = None # Feishu root message_id that created this task - - -@dataclass -class Heartbeat: - id: Optional[int] = None - name: str = "" - enabled: bool = True - working_dir: str = "." - schedule_type: HeartbeatScheduleType = HeartbeatScheduleType.INTERVAL - cron_expr: Optional[str] = None - interval_seconds: Optional[int] = None - check_prompt: str = "" - action_prompt_template: str = "" - default_agent: str = DEFAULT_AGENT - cooldown_seconds: int = 0 - next_run_at: Optional[str] = None - last_tick_at: Optional[str] = None - last_decision: Optional[str] = None - last_error: Optional[str] = None - last_triggered_at: Optional[str] = None - last_dedupe_key: Optional[str] = None - created_at: Optional[str] = None - updated_at: Optional[str] = None - - -# ──────────────────────────── Database ──────────────────────────── - - -class TaskDB: - def __init__(self, db_path: str = "~/.agentforge/tasks.db"): - self.db_path = os.path.expanduser(db_path) - os.makedirs(os.path.dirname(self.db_path), exist_ok=True) - self.conn = sqlite3.connect(self.db_path, check_same_thread=False) - self.conn.row_factory = sqlite3.Row - self.lock = threading.RLock() # RLock allows transaction() to nest with per-method locking - self._init_db() - - def _init_db(self): - self.conn.execute(""" - CREATE TABLE IF NOT EXISTS tasks ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - title TEXT NOT NULL, - prompt TEXT NOT NULL, - working_dir TEXT DEFAULT '.', - status TEXT DEFAULT 'pending', - schedule_type TEXT DEFAULT 'immediate', - cron_expr TEXT, - delay_seconds INTEGER, - next_run_at TEXT, - last_run_at TEXT, - result TEXT, - error TEXT, - run_count INTEGER DEFAULT 0, - max_runs INTEGER, - created_at TEXT DEFAULT (datetime('now')), - updated_at TEXT DEFAULT (datetime('now')), - tags TEXT DEFAULT '', - agent TEXT DEFAULT 'codex', - question TEXT, - answer TEXT - ) - """) - # Migration: add agent column if it doesn't exist (for existing DBs) - try: - self.conn.execute("ALTER TABLE tasks ADD COLUMN agent TEXT DEFAULT 'codex'") - self.conn.commit() - except sqlite3.OperationalError: - pass # Column already exists - # Migration: add question/answer columns - try: - self.conn.execute("ALTER TABLE tasks ADD COLUMN question TEXT") - self.conn.execute("ALTER TABLE tasks ADD COLUMN answer TEXT") - self.conn.commit() - except sqlite3.OperationalError: - pass # Columns already exist - # Migration: add session_id column - try: - self.conn.execute("ALTER TABLE tasks ADD COLUMN session_id TEXT") - self.conn.commit() - except sqlite3.OperationalError: - pass # Column already exists - # Migration: add prompt_images column - try: - self.conn.execute("ALTER TABLE tasks ADD COLUMN prompt_images TEXT DEFAULT '[]'") - self.conn.commit() - except sqlite3.OperationalError: - pass # Column already exists - # Migration: add image_paths column - try: - self.conn.execute("ALTER TABLE tasks ADD COLUMN image_paths TEXT DEFAULT '[]'") - self.conn.commit() - except sqlite3.OperationalError: - pass # Column already exists - # Migration: add notify_slack_channel column - try: - self.conn.execute("ALTER TABLE tasks ADD COLUMN notify_slack_channel TEXT") - self.conn.commit() - except sqlite3.OperationalError: - pass # Column already exists - # Migration: add notify_telegram_chat_id column - try: - self.conn.execute("ALTER TABLE tasks ADD COLUMN notify_telegram_chat_id TEXT") - self.conn.commit() - except sqlite3.OperationalError: - pass # Column already exists - self.conn.execute(""" - CREATE TABLE IF NOT EXISTS settings ( - key TEXT PRIMARY KEY, - value TEXT - ) - """) - self.conn.execute(""" - CREATE TABLE IF NOT EXISTS task_runs ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - task_id INTEGER NOT NULL, - started_at TEXT DEFAULT (datetime('now')), - finished_at TEXT, - status TEXT, - result TEXT, - error TEXT, - raw_output TEXT, - FOREIGN KEY (task_id) REFERENCES tasks(id) - ) - """) - # Migration: add raw_output column to task_runs - try: - self.conn.execute("ALTER TABLE task_runs ADD COLUMN raw_output TEXT") - self.conn.commit() - except sqlite3.OperationalError: - pass # Column already exists - - self.conn.execute(""" - CREATE TABLE IF NOT EXISTS heartbeats ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - name TEXT NOT NULL, - enabled INTEGER NOT NULL DEFAULT 1, - working_dir TEXT DEFAULT '.', - schedule_type TEXT NOT NULL, - cron_expr TEXT, - interval_seconds INTEGER, - check_prompt TEXT NOT NULL, - action_prompt_template TEXT DEFAULT '', - default_agent TEXT DEFAULT 'codex', - cooldown_seconds INTEGER DEFAULT 0, - next_run_at TEXT, - last_tick_at TEXT, - last_decision TEXT, - last_error TEXT, - last_triggered_at TEXT, - last_dedupe_key TEXT, - created_at TEXT DEFAULT (datetime('now')), - updated_at TEXT DEFAULT (datetime('now')) - ) - """) - self.conn.execute(""" - CREATE INDEX IF NOT EXISTS idx_heartbeats_next_run - ON heartbeats(enabled, next_run_at) - """) - self.conn.execute(""" - CREATE TABLE IF NOT EXISTS heartbeat_ticks ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - heartbeat_id INTEGER NOT NULL, - started_at TEXT NOT NULL, - finished_at TEXT, - status TEXT NOT NULL, - decision_type TEXT, - decision_payload TEXT, - task_id INTEGER, - raw_output TEXT, - error TEXT, - FOREIGN KEY (heartbeat_id) REFERENCES heartbeats(id), - FOREIGN KEY (task_id) REFERENCES tasks(id) - ) - """) - self.conn.execute(""" - CREATE INDEX IF NOT EXISTS idx_heartbeat_ticks_heartbeat_id - ON heartbeat_ticks(heartbeat_id, started_at DESC) - """) - try: - self.conn.execute("ALTER TABLE heartbeat_ticks ADD COLUMN raw_output TEXT") - self.conn.commit() - except sqlite3.OperationalError: - pass # Column already exists - self.conn.execute(""" - CREATE TABLE IF NOT EXISTS heartbeat_dedup ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - heartbeat_id INTEGER NOT NULL, - dedupe_key TEXT NOT NULL, - task_id INTEGER, - triggered_at TEXT NOT NULL, - FOREIGN KEY (heartbeat_id) REFERENCES heartbeats(id), - FOREIGN KEY (task_id) REFERENCES tasks(id), - UNIQUE(heartbeat_id, dedupe_key) - ) - """) - self.conn.execute(""" - CREATE INDEX IF NOT EXISTS idx_heartbeat_dedup_heartbeat_id - ON heartbeat_dedup(heartbeat_id, triggered_at DESC) - """) - - # Create task_output_events table for structured output recording - self.conn.execute(""" - CREATE TABLE IF NOT EXISTS task_output_events ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - task_id INTEGER NOT NULL, - run_id INTEGER NOT NULL, - event_type TEXT NOT NULL, - content TEXT NOT NULL, - timestamp TEXT DEFAULT (datetime('now')), - FOREIGN KEY (task_id) REFERENCES tasks(id), - FOREIGN KEY (run_id) REFERENCES task_runs(id) - ) - """) - - # Create indexes for performance - self.conn.execute(""" - CREATE INDEX IF NOT EXISTS idx_task_output_events_task_id - ON task_output_events(task_id) - """) - self.conn.execute(""" - CREATE INDEX IF NOT EXISTS idx_task_output_events_run_id - ON task_output_events(run_id) - """) - self.conn.execute(""" - CREATE INDEX IF NOT EXISTS idx_task_output_events_timestamp - ON task_output_events(timestamp) - """) - - # DAG dependency table - self.conn.execute(""" - CREATE TABLE IF NOT EXISTS task_dependencies ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - task_id INTEGER NOT NULL, - depends_on_task_id INTEGER NOT NULL, - inject_result INTEGER DEFAULT 0, - created_at TEXT DEFAULT (datetime('now')), - FOREIGN KEY (task_id) REFERENCES tasks(id), - FOREIGN KEY (depends_on_task_id) REFERENCES tasks(id), - UNIQUE(task_id, depends_on_task_id) - ) - """) - self.conn.execute(""" - CREATE INDEX IF NOT EXISTS idx_task_deps_task_id - ON task_dependencies(task_id) - """) - self.conn.execute(""" - CREATE INDEX IF NOT EXISTS idx_task_deps_depends_on - ON task_dependencies(depends_on_task_id) - """) - - # Skill Library: cross-run pattern ledger. The sweep agent tallies - # recurring task patterns here (dedup by semantic pattern_key); once a - # pattern crosses the recurrence threshold it becomes a skill candidate. - self.conn.execute(""" - CREATE TABLE IF NOT EXISTS skill_patterns ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - pattern_key TEXT NOT NULL UNIQUE, - kind TEXT NOT NULL DEFAULT 'recipe', - summary TEXT NOT NULL DEFAULT '', - recurrence_count INTEGER NOT NULL DEFAULT 1, - first_seen TEXT DEFAULT (datetime('now')), - last_seen TEXT DEFAULT (datetime('now')), - contributing_task_ids TEXT NOT NULL DEFAULT '[]', - contributing_run_ids TEXT NOT NULL DEFAULT '[]', - status TEXT NOT NULL DEFAULT 'tracking', - promoted_skill_id INTEGER, - created_at TEXT DEFAULT (datetime('now')), - updated_at TEXT DEFAULT (datetime('now')) - ) - """) - self.conn.execute(""" - CREATE INDEX IF NOT EXISTS idx_skill_patterns_status - ON skill_patterns(status, recurrence_count DESC) - """) - # Migration: per-run idempotency ledger so a run is only ever counted - # once (lets the manual sweep re-scan recent runs without inflating counts). - try: - self.conn.execute( - "ALTER TABLE skill_patterns ADD COLUMN contributing_run_ids TEXT NOT NULL DEFAULT '[]'" - ) - self.conn.commit() - except sqlite3.OperationalError: - pass # Column already exists - # Backfill run-id sets for pre-existing patterns from their tasks' completed - # runs, so a re-scan dedups against real run ids instead of re-counting them. - try: - legacy = self.conn.execute( - "SELECT id, contributing_task_ids FROM skill_patterns " - "WHERE contributing_run_ids IN ('[]', '') OR contributing_run_ids IS NULL" - ).fetchall() - for row in legacy: - try: - tids = json.loads(row["contributing_task_ids"]) or [] - except (ValueError, TypeError): - tids = [] - if not tids: - continue - placeholders = ",".join("?" for _ in tids) - run_rows = self.conn.execute( - f"SELECT id FROM task_runs WHERE status = 'completed' " - f"AND task_id IN ({placeholders})", - tuple(tids), - ).fetchall() - run_ids = [r["id"] for r in run_rows] - if run_ids: - self.conn.execute( - "UPDATE skill_patterns SET contributing_run_ids = ? WHERE id = ?", - (json.dumps(run_ids), row["id"]), - ) - self.conn.commit() - except sqlite3.OperationalError: - pass - - # Skill Library: registry of distilled, approved skills. The canonical - # SKILL.md lives at `path` (~/.claude/skills//SKILL.md) and is - # symlinked into ~/.agents/skills for codex. `enabled` toggles whether - # the symlinks exist (i.e. whether agents load it). - self.conn.execute(""" - CREATE TABLE IF NOT EXISTS skills ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - name TEXT NOT NULL UNIQUE, - description TEXT NOT NULL DEFAULT '', - path TEXT NOT NULL, - source_pattern_key TEXT, - source_task_ids TEXT, - kind TEXT, - enabled INTEGER NOT NULL DEFAULT 1, - created_at TEXT DEFAULT (datetime('now')) - ) - """) - # Skill Library: one pending draft per candidate pattern (agent-distilled - # SKILL.md awaiting human review/approval). - self.conn.execute(""" - CREATE TABLE IF NOT EXISTS skill_drafts ( - pattern_id INTEGER PRIMARY KEY, - name TEXT DEFAULT '', - description TEXT DEFAULT '', - kind TEXT DEFAULT 'recipe', - body TEXT DEFAULT '', - status TEXT NOT NULL DEFAULT 'drafting', - error TEXT, - worthy INTEGER, - worthiness_reason TEXT DEFAULT '', - updated_at TEXT DEFAULT (datetime('now')), - FOREIGN KEY (pattern_id) REFERENCES skill_patterns(id) - ) - """) - # Migration: add skill-creator worthiness judgment to existing draft tables - for _col, _decl in (("worthy", "INTEGER"), ("worthiness_reason", "TEXT DEFAULT ''")): - try: - self.conn.execute(f"ALTER TABLE skill_drafts ADD COLUMN {_col} {_decl}") - self.conn.commit() - except sqlite3.OperationalError: - pass # Column already exists - - # Migration: add dag_id column to tasks - try: - self.conn.execute("ALTER TABLE tasks ADD COLUMN dag_id TEXT") - self.conn.commit() - except sqlite3.OperationalError: - pass # Column already exists - # Migration: add feishu_root_msg_id column for post-restart resume - try: - self.conn.execute("ALTER TABLE tasks ADD COLUMN feishu_root_msg_id TEXT") - self.conn.commit() - except sqlite3.OperationalError: - pass # Column already exists - - self.conn.commit() - - # On startup, reset any tasks left in 'running' state — they were - # interrupted by a process kill (e.g. hot reload) and will never - # self-transition to completed/failed without this reset. - now = datetime.now().isoformat() - self.conn.execute( - """ - UPDATE tasks - SET status = 'failed', - error = 'Interrupted: process was restarted while task was running', - updated_at = ? - WHERE status = 'running' - """, - (now,), - ) - # Also close out any open task_runs rows that have no finished_at - self.conn.execute( - """ - UPDATE task_runs - SET status = 'failed', - finished_at = ?, - error = 'Interrupted: process was restarted while task was running' - WHERE finished_at IS NULL - """, - (now,), - ) - self.conn.commit() - - @contextmanager - def transaction(self): - """Acquire the DB lock and run statements in an explicit transaction. - - On success the transaction is committed; on any exception it is rolled - back and the exception re-raised. Callers must NOT call commit() or - rollback() themselves inside this block. - """ - with self.lock: - self.conn.execute("BEGIN") - try: - yield self.conn - self.conn.execute("COMMIT") - except Exception: - self.conn.execute("ROLLBACK") - raise - - def add_task(self, task: Task) -> int: - with self.lock: - now = datetime.now().isoformat() - logger.debug(f"add_task called with image_paths: {task.image_paths}") - image_paths_json = json.dumps(task.image_paths, ensure_ascii=False) - logger.debug(f"image_paths JSON: {image_paths_json}") - cur = self.conn.execute( - """ - INSERT INTO tasks (title, prompt, working_dir, status, schedule_type, - cron_expr, delay_seconds, next_run_at, max_runs, created_at, updated_at, tags, agent, prompt_images, image_paths, dag_id, feishu_root_msg_id) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - """, - ( - task.title, - task.prompt, - task.working_dir, - task.status.value, - task.schedule_type.value, - task.cron_expr, - task.delay_seconds, - task.next_run_at, - task.max_runs, - now, - now, - task.tags, - task.agent, - json.dumps(task.prompt_images, ensure_ascii=False), - image_paths_json, - task.dag_id, - task.feishu_root_msg_id, - ), - ) - self.conn.commit() - task_id = cur.lastrowid - logger.debug(f"Task {task_id} inserted with image_paths") - return task_id - - def get_task_by_feishu_root_msg(self, root_msg_id: str) -> Optional[dict]: - """Look up the most recent task created from a given Feishu root message ID.""" - with self.lock: - row = self.conn.execute( - "SELECT * FROM tasks WHERE feishu_root_msg_id = ? ORDER BY id DESC LIMIT 1", - (root_msg_id,), - ).fetchone() - return dict(row) if row else None - - def get_setting(self, key: str, default: str = None) -> Optional[str]: - with self.lock: - row = self.conn.execute("SELECT value FROM settings WHERE key = ?", (key,)).fetchone() - return row["value"] if row else default - - def set_setting(self, key: str, value: str): - with self.lock: - self.conn.execute( - "INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)", (key, value) - ) - self.conn.commit() - - def _deserialize_heartbeat(self, row) -> dict: - d = dict(row) - d["enabled"] = bool(d.get("enabled")) - return d - - def _compute_heartbeat_next_run_at( - self, heartbeat: Heartbeat, now: Optional[datetime] = None - ) -> str: - now = now or datetime.now() - if heartbeat.schedule_type == HeartbeatScheduleType.CRON: - if not heartbeat.cron_expr: - raise ValueError("cron heartbeat requires cron_expr") - return croniter(heartbeat.cron_expr, now).get_next(datetime).isoformat() - if heartbeat.schedule_type == HeartbeatScheduleType.INTERVAL: - if not heartbeat.interval_seconds or heartbeat.interval_seconds <= 0: - raise ValueError("interval heartbeat requires interval_seconds > 0") - return (now + timedelta(seconds=int(heartbeat.interval_seconds))).isoformat() - raise ValueError(f"Unsupported heartbeat schedule_type: {heartbeat.schedule_type}") - - def add_heartbeat(self, heartbeat: Heartbeat) -> int: - with self.lock: - now = datetime.now().isoformat() - if heartbeat.next_run_at is None: - heartbeat.next_run_at = self._compute_heartbeat_next_run_at( - heartbeat, datetime.now() - ) - cur = self.conn.execute( - """ - INSERT INTO heartbeats ( - name, enabled, working_dir, schedule_type, cron_expr, - interval_seconds, check_prompt, action_prompt_template, - default_agent, cooldown_seconds, next_run_at, last_tick_at, - last_decision, last_error, last_triggered_at, last_dedupe_key, - created_at, updated_at - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - """, - ( - heartbeat.name, - 1 if heartbeat.enabled else 0, - heartbeat.working_dir, - heartbeat.schedule_type.value, - heartbeat.cron_expr, - heartbeat.interval_seconds, - heartbeat.check_prompt, - heartbeat.action_prompt_template, - heartbeat.default_agent, - heartbeat.cooldown_seconds, - heartbeat.next_run_at, - heartbeat.last_tick_at, - heartbeat.last_decision, - heartbeat.last_error, - heartbeat.last_triggered_at, - heartbeat.last_dedupe_key, - now, - now, - ), - ) - self.conn.commit() - return cur.lastrowid - - ALLOWED_HEARTBEAT_COLUMNS = frozenset( - { - "name", - "enabled", - "working_dir", - "schedule_type", - "cron_expr", - "interval_seconds", - "check_prompt", - "action_prompt_template", - "default_agent", - "cooldown_seconds", - "next_run_at", - "last_tick_at", - "last_decision", - "last_error", - "last_triggered_at", - "last_dedupe_key", - "updated_at", - } - ) - - def update_heartbeat(self, heartbeat_id: int, **kwargs): - invalid = set(kwargs) - self.ALLOWED_HEARTBEAT_COLUMNS - if invalid: - raise ValueError(f"Invalid heartbeat column(s): {invalid}") - with self.lock: - kwargs["updated_at"] = datetime.now().isoformat() - sets = ", ".join(f"{k} = ?" for k in kwargs) - vals = list(kwargs.values()) + [heartbeat_id] - self.conn.execute(f"UPDATE heartbeats SET {sets} WHERE id = ?", vals) - self.conn.commit() - - def get_heartbeat(self, heartbeat_id: int) -> Optional[dict]: - with self.lock: - row = self.conn.execute( - "SELECT * FROM heartbeats WHERE id = ?", (heartbeat_id,) - ).fetchone() - return self._deserialize_heartbeat(row) if row else None - - def get_all_heartbeats(self) -> list[dict]: - with self.lock: - rows = self.conn.execute("SELECT * FROM heartbeats ORDER BY created_at DESC").fetchall() - return [self._deserialize_heartbeat(r) for r in rows] - - def get_due_heartbeats(self) -> list[dict]: - with self.lock: - rows = self.conn.execute( - """ - SELECT * FROM heartbeats - WHERE enabled = 1 - AND next_run_at IS NOT NULL - """ - ).fetchall() - now = datetime.now() - due = [] - for row in rows: - heartbeat = self._deserialize_heartbeat(row) - try: - next_run_at = _parse_comparable_datetime(heartbeat.get("next_run_at")) - except ValueError: - continue - if next_run_at and next_run_at <= now: - due.append(heartbeat) - return due - - def delete_heartbeat(self, heartbeat_id: int): - with self.transaction(): - self.conn.execute("DELETE FROM heartbeat_ticks WHERE heartbeat_id = ?", (heartbeat_id,)) - self.conn.execute("DELETE FROM heartbeat_dedup WHERE heartbeat_id = ?", (heartbeat_id,)) - self.conn.execute("DELETE FROM heartbeats WHERE id = ?", (heartbeat_id,)) - - def add_heartbeat_tick(self, heartbeat_id: int) -> int: - with self.lock: - cur = self.conn.execute( - """ - INSERT INTO heartbeat_ticks (heartbeat_id, started_at, status) - VALUES (?, ?, 'running') - """, - (heartbeat_id, datetime.now().isoformat()), - ) - self.conn.commit() - return cur.lastrowid - - def finish_heartbeat_tick( - self, - tick_id: int, - status: str, - decision_type: Optional[str] = None, - decision_payload: Optional[dict] = None, - task_id: Optional[int] = None, - raw_output: Optional[str] = None, - error: Optional[str] = None, - ): - payload_json = ( - json.dumps(decision_payload, ensure_ascii=False) - if decision_payload is not None - else None - ) - with self.lock: - self.conn.execute( - """ - UPDATE heartbeat_ticks - SET finished_at = ?, status = ?, decision_type = ?, decision_payload = ?, task_id = ?, raw_output = ?, error = ? - WHERE id = ? - """, - ( - datetime.now().isoformat(), - status, - decision_type, - payload_json, - task_id, - raw_output, - error, - tick_id, - ), - ) - self.conn.commit() - - def get_heartbeat_ticks(self, heartbeat_id: int, limit: int = 50) -> list[dict]: - with self.lock: - rows = self.conn.execute( - """ - SELECT * FROM heartbeat_ticks - WHERE heartbeat_id = ? - ORDER BY started_at DESC - LIMIT ? - """, - (heartbeat_id, limit), - ).fetchall() - return [dict(r) for r in rows] - - def get_heartbeat_tick(self, heartbeat_id: int, tick_id: int) -> Optional[dict]: - with self.lock: - row = self.conn.execute( - """ - SELECT * FROM heartbeat_ticks - WHERE heartbeat_id = ? AND id = ? - """, - (heartbeat_id, tick_id), - ).fetchone() - return dict(row) if row else None - - def get_latest_heartbeat_tick(self, heartbeat_id: int) -> Optional[dict]: - with self.lock: - row = self.conn.execute( - """ - SELECT * FROM heartbeat_ticks - WHERE heartbeat_id = ? - ORDER BY started_at DESC - LIMIT 1 - """, - (heartbeat_id,), - ).fetchone() - return dict(row) if row else None - - def get_heartbeat_dedup(self, heartbeat_id: int, dedupe_key: str) -> Optional[dict]: - with self.lock: - row = self.conn.execute( - """ - SELECT * FROM heartbeat_dedup - WHERE heartbeat_id = ? AND dedupe_key = ? - """, - (heartbeat_id, dedupe_key), - ).fetchone() - return dict(row) if row else None - - def upsert_heartbeat_dedup(self, heartbeat_id: int, dedupe_key: str, task_id: Optional[int]): - with self.lock: - now = datetime.now().isoformat() - self.conn.execute( - """ - INSERT INTO heartbeat_dedup (heartbeat_id, dedupe_key, task_id, triggered_at) - VALUES (?, ?, ?, ?) - ON CONFLICT(heartbeat_id, dedupe_key) - DO UPDATE SET task_id = excluded.task_id, triggered_at = excluded.triggered_at - """, - (heartbeat_id, dedupe_key, task_id, now), - ) - self.conn.commit() - - ALLOWED_TASK_COLUMNS = frozenset( - { - "title", - "prompt", - "working_dir", - "status", - "schedule_type", - "cron_expr", - "delay_seconds", - "next_run_at", - "last_run_at", - "result", - "error", - "run_count", - "max_runs", - "updated_at", - "tags", - "agent", - "question", - "answer", - "session_id", - "prompt_images", - "image_paths", - "dag_id", - } - ) - - def update_task(self, task_id: int, **kwargs): - invalid = set(kwargs) - self.ALLOWED_TASK_COLUMNS - if invalid: - raise ValueError(f"Invalid task column(s): {invalid}") - with self.lock: - if "next_run_at" in kwargs: - kwargs["next_run_at"] = _normalize_datetime_for_storage(kwargs["next_run_at"]) - kwargs["updated_at"] = datetime.now().isoformat() - sets = ", ".join(f"{k} = ?" for k in kwargs) - vals = list(kwargs.values()) + [task_id] - self.conn.execute(f"UPDATE tasks SET {sets} WHERE id = ?", vals) - self.conn.commit() - - def _deserialize_task(self, row) -> dict: - d = dict(row) - # Deserialize prompt_images - raw = d.get("prompt_images") - if isinstance(raw, str): - try: - d["prompt_images"] = json.loads(raw) - except (json.JSONDecodeError, ValueError): - d["prompt_images"] = [] - elif d.get("prompt_images") is None: - d["prompt_images"] = [] - # Deserialize image_paths - raw_paths = d.get("image_paths") - if isinstance(raw_paths, str): - try: - d["image_paths"] = json.loads(raw_paths) - except (json.JSONDecodeError, ValueError): - d["image_paths"] = [] - elif d.get("image_paths") is None: - d["image_paths"] = [] - return d - - def get_task(self, task_id: int) -> Optional[dict]: - with self.lock: - row = self.conn.execute("SELECT * FROM tasks WHERE id = ?", (task_id,)).fetchone() - return self._deserialize_task(row) if row else None - - def get_all_tasks(self) -> list[dict]: - with self.lock: - rows = self.conn.execute("SELECT * FROM tasks ORDER BY created_at DESC").fetchall() - return [self._deserialize_task(r) for r in rows] - - def get_due_tasks(self) -> list[dict]: - with self.lock: - rows = self.conn.execute( - """ - SELECT * FROM tasks - WHERE status IN ('pending', 'scheduled') - """ - ).fetchall() - now = datetime.now() - due = [] - for row in rows: - task = self._deserialize_task(row) - try: - next_run_at = _parse_comparable_datetime(task.get("next_run_at")) - except ValueError: - continue - if next_run_at is None or next_run_at <= now: - due.append(task) - return due - - def add_run(self, task_id: int) -> int: - with self.lock: - cur = self.conn.execute( - "INSERT INTO task_runs (task_id, status) VALUES (?, 'running')", (task_id,) - ) - self.conn.commit() - return cur.lastrowid - - def finish_run( - self, - run_id: int, - status: str, - result: str = None, - error: str = None, - raw_output: str = None, - ): - with self.lock: - self.conn.execute( - """ - UPDATE task_runs SET finished_at = datetime('now'), - status = ?, result = ?, error = ?, raw_output = ? - WHERE id = ? - """, - (status, result, error, raw_output, run_id), - ) - self.conn.commit() - - def finish_run_and_update_task( - self, - run_id: int, - run_status: str, - task_id: int, - task_updates: dict, - run_result: str = None, - run_error: str = None, - raw_output: str = None, - ): - """Atomically finish a run record and update the parent task in one transaction.""" - task_updates = dict(task_updates) - task_updates["updated_at"] = datetime.now().isoformat() - sets = ", ".join(f"{k} = ?" for k in task_updates) - vals = list(task_updates.values()) + [task_id] - with self.transaction(): - self.conn.execute( - """ - UPDATE task_runs SET finished_at = datetime('now'), - status = ?, result = ?, error = ?, raw_output = ? - WHERE id = ? - """, - (run_status, run_result, run_error, raw_output, run_id), - ) - self.conn.execute(f"UPDATE tasks SET {sets} WHERE id = ?", vals) - - def get_task_runs(self, task_id: int, limit: int = 20) -> list[dict]: - with self.lock: - rows = self.conn.execute( - """ - SELECT * FROM task_runs WHERE task_id = ? - ORDER BY started_at DESC LIMIT ? - """, - (task_id, limit), - ).fetchall() - return [dict(r) for r in rows] - - def add_output_event(self, task_id: int, run_id: int, event_type: str, content: str): - """Add a new output event to the database.""" - with self.lock: - self.conn.execute( - """ - INSERT INTO task_output_events (task_id, run_id, event_type, content) - VALUES (?, ?, ?, ?) - """, - (task_id, run_id, event_type, content), - ) - self.conn.commit() - - def get_output_events(self, task_id: int, limit: int = 1000, offset: int = 0) -> list[dict]: - """Get output events for a task, ordered by timestamp.""" - with self.lock: - rows = self.conn.execute( - """ - SELECT * FROM task_output_events - WHERE task_id = ? - ORDER BY timestamp DESC - LIMIT ? OFFSET ? - """, - (task_id, limit, offset), - ).fetchall() - return [dict(r) for r in rows] - - def get_run_output_events(self, run_id: int, limit: int = 1000) -> list[dict]: - """Get output events for a specific run.""" - with self.lock: - rows = self.conn.execute( - """ - SELECT * FROM task_output_events - WHERE run_id = ? - ORDER BY timestamp ASC - LIMIT ? - """, - (run_id, limit), - ).fetchall() - return [dict(r) for r in rows] - - # ── Skill Library: pattern ledger ────────────────────────────────────── - def get_completed_runs_since(self, watermark: str, limit: int = 50) -> list[dict]: - """Completed task runs finished after `watermark`, oldest first. - - Joined with task metadata so the sweep agent can read what each run did. - Ordering ASC + limit makes the watermark advance incrementally so a large - backlog is processed across several sweeps rather than all at once. - """ - with self.lock: - rows = self.conn.execute( - """ - SELECT r.id AS run_id, r.task_id, r.finished_at, r.result, - t.title, t.prompt, t.working_dir, t.agent - FROM task_runs r - JOIN tasks t ON t.id = r.task_id - WHERE r.status = 'completed' - AND r.finished_at IS NOT NULL - AND r.finished_at > ? - ORDER BY r.finished_at ASC - LIMIT ? - """, - (watermark or "", limit), - ).fetchall() - return [dict(r) for r in rows] - - def get_recent_completed_runs(self, limit: int = 100) -> list[dict]: - """The most recent completed runs regardless of watermark (manual re-scan).""" - with self.lock: - rows = self.conn.execute( - """ - SELECT r.id AS run_id, r.task_id, r.finished_at, r.result, - t.title, t.prompt, t.working_dir, t.agent - FROM task_runs r - JOIN tasks t ON t.id = r.task_id - WHERE r.status = 'completed' AND r.finished_at IS NOT NULL - ORDER BY r.finished_at DESC - LIMIT ? - """, - (limit,), - ).fetchall() - # Return oldest-first so watermark math stays consistent. - return [dict(r) for r in reversed(rows)] - - def upsert_skill_pattern( - self, - pattern_key: str, - kind: str, - summary: str, - task_id: Optional[int], - run_id: Optional[int] = None, - ) -> Optional[int]: - """Record one observation of a pattern. Dedup by exact pattern_key. - - Semantic matching is done by the sweep agent (it reuses an existing key). - Counting is idempotent per run: if `run_id` was already counted for this - pattern, only the summary/last_seen refresh — recurrence does NOT bump. - This lets the manual sweep re-scan recent runs without inflating counts. - When run_id is None (legacy / unknown), fall back to bumping per call. - """ - pattern_key = (pattern_key or "").strip() - if not pattern_key: - return None - kind = kind if kind in ("recipe", "pitfall") else "recipe" - now = datetime.now().isoformat() - with self.lock: - row = self.conn.execute( - "SELECT id, contributing_task_ids, contributing_run_ids " - "FROM skill_patterns WHERE pattern_key = ?", - (pattern_key,), - ).fetchone() - if row: - try: - tids = list(json.loads(row["contributing_task_ids"]) or []) - except (ValueError, TypeError): - tids = [] - try: - rids = list(json.loads(row["contributing_run_ids"] or "[]") or []) - except (ValueError, TypeError): - rids = [] - already_counted = run_id is not None and run_id in rids - if task_id is not None and task_id not in tids: - tids.append(task_id) - if run_id is not None and run_id not in rids: - rids.append(run_id) - # Bump only for a genuinely new observation. - bump = 0 if already_counted else 1 - self.conn.execute( - """ - UPDATE skill_patterns - SET recurrence_count = recurrence_count + ?, - last_seen = ?, - updated_at = ?, - summary = CASE WHEN ? != '' THEN ? ELSE summary END, - contributing_task_ids = ?, - contributing_run_ids = ? - WHERE id = ? - """, - ( - bump, - now, - now, - summary or "", - summary or "", - json.dumps(tids, ensure_ascii=False), - json.dumps(rids, ensure_ascii=False), - row["id"], - ), - ) - self.conn.commit() - return row["id"] - tids = [task_id] if task_id is not None else [] - rids = [run_id] if run_id is not None else [] - cur = self.conn.execute( - """ - INSERT INTO skill_patterns - (pattern_key, kind, summary, recurrence_count, - first_seen, last_seen, contributing_task_ids, contributing_run_ids, status) - VALUES (?, ?, ?, 1, ?, ?, ?, ?, 'tracking') - """, - ( - pattern_key, - kind, - summary or "", - now, - now, - json.dumps(tids, ensure_ascii=False), - json.dumps(rids, ensure_ascii=False), - ), - ) - self.conn.commit() - return cur.lastrowid - - def get_skill_patterns(self, limit: int = 200) -> list[dict]: - with self.lock: - rows = self.conn.execute( - """ - SELECT p.*, d.status AS draft_status, d.name AS draft_name, - d.description AS draft_description, d.kind AS draft_kind, - d.body AS draft_body, d.error AS draft_error, - d.worthy AS draft_worthy, d.worthiness_reason AS draft_worthiness_reason - FROM skill_patterns p - LEFT JOIN skill_drafts d ON d.pattern_id = p.id - ORDER BY p.recurrence_count DESC, p.last_seen DESC - LIMIT ? - """, - (limit,), - ).fetchall() - return [dict(r) for r in rows] - - def get_skill_pattern(self, pattern_id: int) -> Optional[dict]: - with self.lock: - row = self.conn.execute( - "SELECT * FROM skill_patterns WHERE id = ?", (pattern_id,) - ).fetchone() - return dict(row) if row else None - - def get_skill_pattern_recurrence(self, pattern_key: str) -> int: - """Current recurrence_count for a pattern_key (0 if it doesn't exist yet).""" - pattern_key = (pattern_key or "").strip() - if not pattern_key: - return 0 - with self.lock: - row = self.conn.execute( - "SELECT recurrence_count FROM skill_patterns WHERE pattern_key = ?", - (pattern_key,), - ).fetchone() - return row["recurrence_count"] if row else 0 - - @staticmethod - def _within_window(first_seen: str, last_seen: str, window_days: int) -> bool: - """True if the pattern's recurrences cluster within `window_days`. - - Tolerant: if timestamps can't be parsed, don't block promotion. - """ - try: - f = _parse_comparable_datetime(first_seen) - ls = _parse_comparable_datetime(last_seen) - except (ValueError, TypeError): - return True - if f is None or ls is None: - return True - return (ls - f).days <= window_days - - def refresh_skill_candidates( - self, min_recurrence: int = 3, min_tasks: int = 2, window_days: int = 30 - ) -> int: - """Promote 'tracking' patterns that cross the threshold to 'candidate'. - - Threshold (borrowed from pskoett self-improvement): recurrence >= 3 AND - >= 2 distinct tasks AND recurrences within a 30-day window. Returns the - number newly marked. - """ - marked = 0 - now = datetime.now().isoformat() - with self.lock: - rows = self.conn.execute( - """ - SELECT id, recurrence_count, contributing_task_ids, first_seen, last_seen - FROM skill_patterns WHERE status = 'tracking' - """ - ).fetchall() - for r in rows: - if r["recurrence_count"] < min_recurrence: - continue - try: - tids = json.loads(r["contributing_task_ids"]) or [] - except (ValueError, TypeError): - tids = [] - if len(set(tids)) < min_tasks: - continue - if not self._within_window(r["first_seen"], r["last_seen"], window_days): - continue - self.conn.execute( - "UPDATE skill_patterns SET status = 'candidate', updated_at = ? WHERE id = ?", - (now, r["id"]), - ) - marked += 1 - if marked: - self.conn.commit() - return marked - - def set_skill_pattern_status( - self, pattern_id: int, status: str, promoted_skill_id: Optional[int] = None - ): - with self.lock: - self.conn.execute( - """ - UPDATE skill_patterns - SET status = ?, promoted_skill_id = ?, updated_at = ? - WHERE id = ? - """, - (status, promoted_skill_id, datetime.now().isoformat(), pattern_id), - ) - self.conn.commit() - - # ── Skill drafts ─────────────────────────────────────────────────────── - def upsert_skill_draft( - self, - pattern_id: int, - status: str, - name: str = "", - description: str = "", - kind: str = "recipe", - body: str = "", - error: Optional[str] = None, - worthy: Optional[bool] = None, - worthiness_reason: str = "", - ): - with self.lock: - self.conn.execute( - """ - INSERT INTO skill_drafts - (pattern_id, name, description, kind, body, status, error, - worthy, worthiness_reason, updated_at) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - ON CONFLICT(pattern_id) DO UPDATE SET - name = excluded.name, - description = excluded.description, - kind = excluded.kind, - body = excluded.body, - status = excluded.status, - error = excluded.error, - worthy = excluded.worthy, - worthiness_reason = excluded.worthiness_reason, - updated_at = excluded.updated_at - """, - ( - pattern_id, - name, - description, - kind, - body, - status, - error, - None if worthy is None else (1 if worthy else 0), - worthiness_reason, - datetime.now().isoformat(), - ), - ) - self.conn.commit() - - def get_skill_draft(self, pattern_id: int) -> Optional[dict]: - with self.lock: - row = self.conn.execute( - "SELECT * FROM skill_drafts WHERE pattern_id = ?", (pattern_id,) - ).fetchone() - return dict(row) if row else None - - def delete_skill_draft(self, pattern_id: int): - with self.lock: - self.conn.execute("DELETE FROM skill_drafts WHERE pattern_id = ?", (pattern_id,)) - self.conn.commit() - - # ── Skill registry ───────────────────────────────────────────────────── - def add_skill( - self, - name: str, - description: str, - path: str, - source_pattern_key: Optional[str] = None, - source_task_ids: Optional[str] = None, - kind: Optional[str] = None, - ) -> int: - with self.lock: - cur = self.conn.execute( - """ - INSERT INTO skills (name, description, path, source_pattern_key, source_task_ids, kind, enabled) - VALUES (?, ?, ?, ?, ?, ?, 1) - ON CONFLICT(name) DO UPDATE SET - description = excluded.description, - path = excluded.path, - source_pattern_key = excluded.source_pattern_key, - source_task_ids = excluded.source_task_ids, - kind = excluded.kind, - enabled = 1 - """, - (name, description, path, source_pattern_key, source_task_ids, kind), - ) - self.conn.commit() - if cur.lastrowid: - return cur.lastrowid - row = self.conn.execute("SELECT id FROM skills WHERE name = ?", (name,)).fetchone() - return row["id"] if row else None - - def get_skills(self) -> list[dict]: - with self.lock: - rows = self.conn.execute("SELECT * FROM skills ORDER BY created_at DESC").fetchall() - return [dict(r) for r in rows] - - def get_skill(self, skill_id: int) -> Optional[dict]: - with self.lock: - row = self.conn.execute("SELECT * FROM skills WHERE id = ?", (skill_id,)).fetchone() - return dict(row) if row else None - - def set_skill_enabled(self, skill_id: int, enabled: bool): - with self.lock: - self.conn.execute( - "UPDATE skills SET enabled = ? WHERE id = ?", (1 if enabled else 0, skill_id) - ) - self.conn.commit() - - def delete_skill(self, skill_id: int): - with self.lock: - self.conn.execute("DELETE FROM skills WHERE id = ?", (skill_id,)) - self.conn.commit() - - def add_dependency(self, task_id: int, depends_on_task_id: int, inject_result: bool = False): - with self.lock: - self.conn.execute( - """ - INSERT OR IGNORE INTO task_dependencies (task_id, depends_on_task_id, inject_result) - VALUES (?, ?, ?) - """, - (task_id, depends_on_task_id, 1 if inject_result else 0), - ) - self.conn.commit() - - def add_dependencies_batch(self, task_id: int, dep_list: list): - """Insert multiple dependency rows for task_id in a single transaction. - - dep_list: list of dicts with keys task_id (upstream) and inject_result. - Rolls back all inserts if any one fails. - """ - with self.transaction(): - for dep in dep_list: - self.conn.execute( - """ - INSERT OR IGNORE INTO task_dependencies (task_id, depends_on_task_id, inject_result) - VALUES (?, ?, ?) - """, - (task_id, dep["task_id"], 1 if dep["inject_result"] else 0), - ) - - def remove_dependency(self, task_id: int, depends_on_task_id: int): - with self.lock: - self.conn.execute( - """ - DELETE FROM task_dependencies WHERE task_id = ? AND depends_on_task_id = ? - """, - (task_id, depends_on_task_id), - ) - self.conn.commit() - - def clear_dependencies(self, task_id: int): - """Remove all upstream dependencies for a task.""" - with self.lock: - self.conn.execute("DELETE FROM task_dependencies WHERE task_id = ?", (task_id,)) - self.conn.commit() - - def get_dependencies(self, task_id: int) -> list[dict]: - """Return upstream tasks that task_id depends on.""" - with self.lock: - rows = self.conn.execute( - """ - SELECT td.*, t.title as depends_on_title, t.status as depends_on_status - FROM task_dependencies td - JOIN tasks t ON t.id = td.depends_on_task_id - WHERE td.task_id = ? - """, - (task_id,), - ).fetchall() - return [dict(r) for r in rows] - - def get_dependents(self, task_id: int) -> list[dict]: - """Return downstream tasks that depend on task_id.""" - with self.lock: - rows = self.conn.execute( - """ - SELECT td.*, t.title as task_title, t.status as task_status - FROM task_dependencies td - JOIN tasks t ON t.id = td.task_id - WHERE td.depends_on_task_id = ? - """, - (task_id,), - ).fetchall() - return [dict(r) for r in rows] - - def get_dag_tasks(self, dag_id: str) -> list[dict]: - with self.lock: - rows = self.conn.execute( - "SELECT * FROM tasks WHERE dag_id = ? ORDER BY created_at ASC", (dag_id,) - ).fetchall() - return [self._deserialize_task(r) for r in rows] - - def delete_task(self, task_id: int): - with self.transaction(): - self.conn.execute("DELETE FROM task_output_events WHERE task_id = ?", (task_id,)) - self.conn.execute("DELETE FROM task_runs WHERE task_id = ?", (task_id,)) - self.conn.execute( - "DELETE FROM task_dependencies WHERE task_id = ? OR depends_on_task_id = ?", - (task_id, task_id), - ) - self.conn.execute("DELETE FROM tasks WHERE id = ?", (task_id,)) - - -# ──────────────────────────── Agent Executor ──────────────────────────── - - -class AgentExecutor: - """Executes prompts via configurable AI agent CLIs.""" - - @staticmethod - def run( - prompt: str, - working_dir: str = ".", - timeout: int = DEFAULT_TIMEOUT_SECONDS, - image_paths: list[str] = None, - ) -> tuple[bool, str]: - """ - Run a prompt through Claude Code CLI. - Returns (success: bool, output: str) - - Args: - prompt: The text prompt to send - working_dir: Working directory for the command - timeout: Command timeout in seconds - image_paths: Optional list of image file paths to include - """ - try: - cmd = ["claude", "-p", prompt] - - # Add image paths if provided - if image_paths: - for img_path in image_paths: - cmd.extend(["-i", img_path]) - - cmd.extend(CLAUDE_STREAM_JSON_ARGS) - - result = subprocess.run( - cmd, - capture_output=True, - text=True, - cwd=os.path.expanduser(working_dir), - timeout=timeout, - env=_get_env(), - ) - if result.returncode == 0: - output = result.stdout - for line in reversed(result.stdout.splitlines()): - line = line.strip() - if not line: - continue - try: - event = json.loads(line) - if event.get("type") == "result": - output = event.get("result", result.stdout) - break - except json.JSONDecodeError: - pass - return True, output - else: - return False, result.stderr or result.stdout - except FileNotFoundError: - return False, "claude CLI not found. Is it installed?" - except subprocess.TimeoutExpired: - return False, f"claude CLI timed out after {timeout}s" - except OSError as e: - return False, str(e) - - -# ──────────────────────────── Scheduler ──────────────────────────── - - -# ── Skill Library: on-disk skill files ───────────────────────────────────── -# Canonical SKILL.md lives in an AgentForge-owned dir and is symlinked into -# each agent's native skill dir. Both agents load via their own progressive -# disclosure; enable/disable just adds/removes the two symlinks (canonical kept). -def _skill_library_dirs() -> tuple[str, str, str]: - return ( - os.path.expanduser("~/.agentforge/skills"), # canonical (AgentForge-owned) - os.path.expanduser("~/.claude/skills"), # claude consumer - os.path.expanduser("~/.agents/skills"), # codex consumer - ) - - -def _skill_creator_dir() -> str: - """Path to the vendored Anthropic skill-creator skill (dev tree or PyInstaller bundle).""" - base = getattr(sys, "_MEIPASS", os.path.dirname(os.path.abspath(__file__))) - return os.path.join(base, "vendor", "skill-creator") - - -def _sanitize_skill_name(name: str) -> str: - """Lowercase kebab slug safe as a directory name (no path traversal).""" - name = (name or "").strip().lower() - slug = "".join(ch if ch.isalnum() else "-" for ch in name) - while "--" in slug: - slug = slug.replace("--", "-") - return slug.strip("-") - - -def link_skill(name: str) -> list[str]: - """Create/refresh the claude + codex symlinks pointing at the canonical dir.""" - canonical_root, claude_root, agents_root = _skill_library_dirs() - skill_dir = os.path.join(canonical_root, name) - links = [] - for root in (claude_root, agents_root): - os.makedirs(root, exist_ok=True) - link = os.path.join(root, name) - if os.path.islink(link): - os.unlink(link) - if not os.path.exists(link): - try: - os.symlink(skill_dir, link, target_is_directory=True) - except OSError as e: - logger.warning(f"symlink {link} failed: {e}") - links.append(link) - return links - - -def unlink_skill(name: str) -> None: - """Remove both consumer symlinks; leave the canonical dir intact.""" - _canonical_root, claude_root, agents_root = _skill_library_dirs() - for root in (claude_root, agents_root): - link = os.path.join(root, name) - if os.path.islink(link): - try: - os.unlink(link) - except OSError: - pass - - -def write_skill_to_disk(name: str, body: str) -> tuple[str, str]: - """Write canonical SKILL.md and create both symlinks. Returns (md_path, dir).""" - canonical_root, _claude_root, _agents_root = _skill_library_dirs() - skill_dir = os.path.join(canonical_root, name) - os.makedirs(skill_dir, exist_ok=True) - skill_md = os.path.join(skill_dir, "SKILL.md") - with open(skill_md, "w", encoding="utf-8") as f: - f.write(body) - link_skill(name) - return skill_md, skill_dir - - -def remove_skill_from_disk(name: str) -> None: - """Remove symlinks and the canonical dir entirely (used on delete).""" - unlink_skill(name) - canonical_root, _claude_root, _agents_root = _skill_library_dirs() - skill_dir = os.path.join(canonical_root, name) - if os.path.isdir(skill_dir): - import shutil - - shutil.rmtree(skill_dir, ignore_errors=True) - - -def _compose_skill_md(name: str, description: str, body_markdown: str) -> str: - desc = (description or "").replace("\n", " ").strip() - body = (body_markdown or "").strip() - return f"---\nname: {name}\ndescription: {desc}\n---\n\n{body}\n" - - -def _parse_skill_frontmatter(body: str) -> tuple[str, str]: - """Pull name + description out of a SKILL.md's YAML frontmatter (best-effort).""" - name, description = "", "" - text = (body or "").lstrip() - if not text.startswith("---"): - return name, description - end = text.find("\n---", 3) - if end == -1: - return name, description - for line in text[3:end].splitlines(): - key, sep, val = line.partition(":") - if not sep: - continue - key = key.strip().lower() - val = val.strip() - if key == "name" and not name: - name = val - elif key == "description" and not description: - description = val - return name, description - - -def _parse_json_object(raw_text: str) -> dict: - text = (raw_text or "").strip() - if text.startswith("```"): - lines = [ln for ln in text.splitlines() if not ln.strip().startswith("```")] - text = "\n".join(lines).strip() - if not text.startswith("{"): - start = text.find("{") - end = text.rfind("}") - if start != -1 and end != -1 and end > start: - text = text[start : end + 1] - data = json.loads(text) - if not isinstance(data, dict): - raise ValueError("expected JSON object") - return data - - -class TaskScheduler(BusAwareSchedulerMixin): - """Background scheduler that checks and runs due tasks.""" - - def __init__( - self, - db: TaskDB, - on_task_update: Optional[Callable] = None, - bus: Optional[MessageBus] = None, - ): - self.db = db - self.executor = AgentExecutor() - self.on_task_update = on_task_update - self.bus = bus # MessageBus integration (optional) - self._channels: list = [] # generic Channel instances (e.g. TelegramChannel) - self._output_event_listeners: list = [] # callables(task_id, run_id, event_type, content) - self._listeners_lock = threading.Lock() - self._running = False - self._shutting_down = False - self._thread: Optional[threading.Thread] = None - self._active_tasks: dict[int, threading.Thread] = {} - self._active_heartbeats: dict[int, threading.Thread] = {} - self._live_output: dict[int, str] = {} # task_id -> accumulated stdout - self._live_heartbeat_output: dict[int, str] = {} # tick_id -> accumulated stdout/stderr - self._active_pgids: dict[int, int] = {} # task_id -> process group id - self._codex_item_text: dict[tuple[Optional[int], str], str] = {} - self._claude_message_text: dict[tuple[Optional[int], str], str] = {} - # Skill Library sweep state (manual + scheduled share this guard) - self._skill_sweep_lock = threading.Lock() - self._skill_sweep_running = False - self._last_skill_sweep: Optional[dict] = None - - def start(self): - self._running = True - self._thread = threading.Thread(target=self._loop, daemon=True) - self._thread.start() - logger.info("Scheduler started") - - def stop(self): - self._shutting_down = True - self._running = False - if self._thread: - self._thread.join(timeout=5) - # Wait up to 5 seconds for running tasks to finish - deadline = time.time() + 5 - running = {tid: t for tid, t in self._active_tasks.items() if t.is_alive()} - if running: - logger.info(f"Waiting for {len(running)} running task(s) to finish...") - for _tid, t in running.items(): - remaining = max(0, deadline - time.time()) - t.join(timeout=remaining) - heartbeat_running = {hid: t for hid, t in self._active_heartbeats.items() if t.is_alive()} - if heartbeat_running: - logger.info(f"Waiting for {len(heartbeat_running)} heartbeat(s) to finish...") - for _hid, t in heartbeat_running.items(): - remaining = max(0, deadline - time.time()) - t.join(timeout=remaining) - # Gracefully terminate any processes still alive, then force-kill if needed - for tid, pgid in list(self._active_pgids.items()): - try: - os.killpg(pgid, signal.SIGTERM) - logger.info(f"Sent SIGTERM to task {tid} (pgid {pgid})") - except OSError: - continue - # Wait up to 5 seconds for the process group to exit - deadline = time.time() + 5 - while time.time() < deadline: - try: - os.killpg(pgid, 0) # check if still alive - except OSError: - break # process group is gone - time.sleep(0.1) - else: - # Still alive — escalate to SIGKILL - logger.warning(f"Force-killing task {tid} (pgid {pgid}) after SIGTERM timeout") - try: - os.killpg(pgid, signal.SIGKILL) - except OSError as e: - logger.error(f"killpg({pgid}) SIGKILL failed: {e}") - logger.info("Scheduler stopped") - - def _loop(self): - while self._running: - try: - self._tick() - except Exception as e: - logger.error(f"Scheduler error: {e}") - time.sleep(2) # check every 2 seconds - - def _tick(self): - if self._shutting_down: - return - due_tasks = self.db.get_due_tasks() - for task in due_tasks: - tid = task["id"] - if tid in self._active_tasks and self._active_tasks[tid].is_alive(): - continue # already running - # Check if it's time - if task["schedule_type"] == "immediate" and task["status"] == "pending": - self._spawn_task(task) - elif task["schedule_type"] == "delayed" and task["status"] == "pending": - self._schedule_delayed(task) - elif task["schedule_type"] == "delayed" and task["status"] == "scheduled": - nra = task.get("next_run_at") - run_at = _parse_comparable_datetime(nra) if nra else None - if run_at and run_at <= datetime.now(): - self._spawn_task(task) - elif task["schedule_type"] == "scheduled_at" and task["status"] == "scheduled": - nra = task.get("next_run_at") - run_at = _parse_comparable_datetime(nra) if nra else None - if run_at and run_at <= datetime.now(): - self._spawn_task(task) - elif task["schedule_type"] == "cron" and task["status"] == "scheduled": - nra = task.get("next_run_at") - run_at = _parse_comparable_datetime(nra) if nra else None - if run_at and run_at <= datetime.now(): - self._spawn_task(task) - due_heartbeats = self.db.get_due_heartbeats() - for heartbeat in due_heartbeats: - hid = heartbeat["id"] - if hid in self._active_heartbeats and self._active_heartbeats[hid].is_alive(): - continue - self._spawn_heartbeat(heartbeat) - self._maybe_run_scheduled_sweep() - - def _maybe_run_scheduled_sweep(self): - """Built-in "skill-distiller": cron-driven auto sweep, gated by the toggle. - - Gated by skill_library_enabled (default OFF). Agent + cadence come from - skill_sweep_agent / skill_sweep_cron. The manual button bypasses this - entirely. When disabled, returns immediately — never calls an agent. - """ - if self.db.get_setting("skill_library_enabled", "0") not in ("1", "true", "True"): - return - cron = self.db.get_setting("skill_sweep_cron", "0 3 * * *") - if not cron or not croniter.is_valid(cron): - return - now = datetime.now() - next_run_raw = self.db.get_setting("skill_sweep_next_run", "") - if not next_run_raw: - # First tick after enabling: schedule forward, don't run immediately. - self.db.set_setting( - "skill_sweep_next_run", croniter(cron, now).get_next(datetime).isoformat() - ) - return - try: - next_run = _parse_comparable_datetime(next_run_raw) - except (ValueError, TypeError): - next_run = None - if next_run is None or next_run <= now: - self.trigger_skill_sweep(self.db.get_setting("skill_sweep_agent", None)) - self.db.set_setting( - "skill_sweep_next_run", croniter(cron, now).get_next(datetime).isoformat() - ) - - def _schedule_delayed(self, task: dict): - delay = task.get("delay_seconds", 0) or 0 - run_at = datetime.now() + timedelta(seconds=delay) - self.db.update_task(task["id"], status="scheduled", next_run_at=run_at.isoformat()) - self._notify(task["id"]) - - def _spawn_heartbeat(self, heartbeat: dict): - t = threading.Thread(target=self._execute_heartbeat, args=(heartbeat,), daemon=True) - self._active_heartbeats[heartbeat["id"]] = t - t.start() - - def _spawn_task(self, task: dict): - # Register the thread in _active_tasks *before* updating the DB so - # that if the thread crashes immediately after the DB write, the task - # is still visible in _active_tasks and won't be re-picked by _tick(). - t = threading.Thread(target=self._execute_task, args=(task,), daemon=True) - self._active_tasks[task["id"]] = t - self.db.update_task(task["id"], status="running") - t.start() - - def _render_heartbeat_check_prompt(self, heartbeat: dict) -> str: - lines = [ - "You are AgentForge heartbeat decision engine.", - "Return JSON only. No markdown, no explanation, no code fences.", - "JSON schema:", - '{"decision":"idle|trigger_task|error","reason":"string","dedupe_key":"string","title":"string","prompt":"string","metadata":{}}', - "", - f"Heartbeat name: {heartbeat['name']}", - f"Working directory: {heartbeat['working_dir']}", - f"Current time: {datetime.now().isoformat()}", - f"Last tick at: {heartbeat.get('last_tick_at') or ''}", - f"Last decision: {heartbeat.get('last_decision') or ''}", - f"Last triggered at: {heartbeat.get('last_triggered_at') or ''}", - f"Last dedupe key: {heartbeat.get('last_dedupe_key') or ''}", - "", - "User-defined check instructions:", - heartbeat["check_prompt"], - ] - if heartbeat.get("action_prompt_template"): - lines.extend( - [ - "", - "When decision is trigger_task, use this action prompt template as the base prompt to expand or adapt:", - heartbeat["action_prompt_template"], - ] - ) - return "\n".join(lines) - - def _parse_heartbeat_decision(self, raw_text: str) -> dict: - text = raw_text.strip() - if text.startswith("```"): - lines = [line for line in text.splitlines() if not line.strip().startswith("```")] - text = "\n".join(lines).strip() - if not text.startswith("{"): - start = text.find("{") - end = text.rfind("}") - if start != -1 and end != -1 and end > start: - text = text[start : end + 1] - payload = json.loads(text) - decision = payload.get("decision") - if decision not in {d.value for d in HeartbeatDecisionType}: - raise ValueError(f"Invalid heartbeat decision: {decision}") - normalized = { - "decision": decision, - "reason": str(payload.get("reason", "")), - "dedupe_key": str(payload.get("dedupe_key", "")), - "title": str(payload.get("title", "")), - "prompt": str(payload.get("prompt", "")), - "metadata": payload.get("metadata", {}) or {}, - } - if not isinstance(normalized["metadata"], dict): - raise ValueError("Heartbeat decision metadata must be an object") - return normalized - - # ── Skill Library: cross-run sweep ───────────────────────────────────── - SKILL_SWEEP_RUN_LIMIT = 50 - - def run_skill_sweep(self, agent: Optional[str] = None, full: bool = False) -> dict: - """Synchronous sweep core (tested directly). - - full=False (scheduled): only runs since the watermark — incremental, cheap. - full=True (manual button): re-scans the most recent completed runs ignoring - the watermark, so the button always analyzes something. Counting is - idempotent per run_id, so re-scanning never inflates recurrence counts. - """ - agent = ( - agent - or self.db.get_setting("skill_sweep_agent", None) - or self.db.get_setting("default_agent", DEFAULT_AGENT) - ) - watermark = self.db.get_setting("skill_sweep_watermark", "") or "" - if full: - runs = self.db.get_recent_completed_runs(limit=self.SKILL_SWEEP_RUN_LIMIT) - else: - runs = self.db.get_completed_runs_since(watermark, limit=self.SKILL_SWEEP_RUN_LIMIT) - if not runs: - result = { - "scanned": 0, - "detected": 0, - "new": 0, - "candidates": 0, - "watermark": watermark, - "agent": agent, - "full": full, - } - self._last_skill_sweep = result - return result - - existing = self.db.get_skill_patterns() - prompt = self._build_sweep_prompt(runs, existing) - ok, raw = self._run_agent_prompt_once(agent, prompt, ".") - if not ok: - raise RuntimeError(raw or "skill sweep agent failed") - - detected = 0 - new_occurrences = 0 - for item in self._parse_sweep_output(raw): - if not isinstance(item, dict): - continue - - def _int(v): - try: - return int(v) if v is not None else None - except (ValueError, TypeError): - return None - - tid = _int(item.get("task_id")) - rid = _int(item.get("run_id")) - before = self.db.get_skill_pattern_recurrence(item.get("pattern_key", "")) - pid = self.db.upsert_skill_pattern( - item.get("pattern_key", ""), - item.get("kind", "recipe"), - str(item.get("summary", "")), - tid, - run_id=rid, - ) - if pid is not None: - detected += 1 - after = self.db.get_skill_pattern_recurrence(item.get("pattern_key", "")) - if after > before: - new_occurrences += 1 - - new_watermark = max( - (r["finished_at"] for r in runs if r.get("finished_at")), default=watermark - ) - if new_watermark and new_watermark > watermark: - self.db.set_setting("skill_sweep_watermark", new_watermark) - candidates = self.db.refresh_skill_candidates() - result = { - "scanned": len(runs), - "detected": detected, - "new": new_occurrences, - "candidates": candidates, - "watermark": new_watermark, - "agent": agent, - "full": full, - } - self._last_skill_sweep = result - return result - - def trigger_skill_sweep(self, agent: Optional[str] = None, full: bool = False) -> bool: - """Start a sweep in the background. Returns False if one is already running. - - The HTTP server is single-threaded, so a sweep (which can take minutes) - must not block the request thread. - """ - with self._skill_sweep_lock: - if self._skill_sweep_running: - return False - self._skill_sweep_running = True - - def _worker(): - try: - self.run_skill_sweep(agent, full=full) - except Exception as e: # noqa: BLE001 - surface to status, never crash thread - logger.error(f"Skill sweep failed: {e}") - self._last_skill_sweep = {"error": str(e)} - finally: - with self._skill_sweep_lock: - self._skill_sweep_running = False - - threading.Thread(target=_worker, daemon=True).start() - return True - - def skill_sweep_status(self) -> dict: - with self._skill_sweep_lock: - running = self._skill_sweep_running - return {"running": running, "last": self._last_skill_sweep} - - # ── Skill Library: distillation / approval ───────────────────────────── - def _build_distill_context(self, tids: list) -> str: - blocks = [] - for tid in tids[:5]: - task = self.db.get_task(tid) - if not task: - continue - runs = self.db.get_task_runs(tid, limit=1) - result = (runs[0].get("result") if runs else "") or "" - blocks.append( - f"[task #{tid}] {task.get('title') or 'Untitled'}\n" - f" prompt: {(task.get('prompt') or '').strip()[:600]}\n" - f" result: {result.strip()[:600]}" - ) - return "\n\n".join(blocks) - - def _build_distill_prompt( - self, pattern: dict, context: str, skill_creator_rel: Optional[str] = None - ) -> str: - kind = pattern.get("kind", "recipe") - if skill_creator_rel: - header = ( - "You are creating a reusable Claude Code skill from a recurring task pattern. " - "You MUST author it USING the skill-creator skill, whose full authoring guidance " - "is on disk in this working directory at:\n" - f" {skill_creator_rel}\n" - "Read that file first and follow its conventions for skill structure, the " - "description (triggering accuracy), progressive disclosure, and body style. " - "Do NOT run any of skill-creator's scripts, do NOT scaffold a directory on disk, " - "do NOT run evals or package anything — your ONLY output is the JSON described " - "below.\n\n" - ) - else: - header = ( - "You are creating a reusable Claude Code skill from a recurring task pattern, " - "following Anthropic's skill-creator conventions (concise description that states " - "what AND when with concrete triggers; imperative body that explains why; " - "progressive disclosure; well under 500 lines).\n\n" - ) - return ( - header + f"Pattern key: {pattern['pattern_key']}\n" - f"Kind: {kind}\n" - f"Summary: {pattern.get('summary', '')}\n" - f"Observed {pattern.get('recurrence_count', 0)} times across these task runs:\n\n" - f"{context}\n\n" - "STEP 1 — Decide if a skill is genuinely warranted. A skill IS warranted when the " - "pattern is one of:\n" - " - a repeatable, multi-step workflow run many times across different inputs;\n" - " - produces an objectively verifiable output (file transform, data extraction, " - "code generation, fixed procedure);\n" - " - encodes specialized/domain knowledge or best practices worth codifying.\n" - "A skill is NOT warranted for one-off, trivial, or purely subjective work (taste, " - "writing style) with no reusable procedure. Be honest — most patterns are not " - "skill-worthy.\n\n" - "STEP 2 — If worthy, author the SKILL.md using the skill-creator guidance above. " - "The description is the PRIMARY trigger: state BOTH what it does AND when to use it, " - "third person, concrete trigger phrasing. The body_markdown must NOT include YAML " - "frontmatter (it is added separately).\n\n" - "Respond with ONLY a JSON object, no prose, no code fence:\n" - '{"worthy": true, "worthiness_reason": "one sentence on why it is / is not ' - 'skill-worthy", "name": "short-kebab-name", "description": "what AND when, with ' - 'concrete triggers", "body_markdown": "the skill body, no frontmatter"}\n' - "If NOT worthy, set worthy=false and give the reason, but still fill name/" - "description/body_markdown with your best attempt — the human makes the final call." - ) - - def distill_skill_draft(self, pattern_id: int, agent: Optional[str] = None) -> dict: - """Synchronous distill core (tested directly). Saves a 'ready' draft.""" - pattern = self.db.get_skill_pattern(pattern_id) - if not pattern: - raise ValueError("pattern not found") - agent = ( - agent - or self.db.get_setting("skill_sweep_agent", None) - or self.db.get_setting("default_agent", DEFAULT_AGENT) - ) - try: - tids = json.loads(pattern["contributing_task_ids"]) or [] - except (ValueError, TypeError): - tids = [] - context = self._build_distill_context(tids) - - # Run the distill in a throwaway working dir that has the vendored - # skill-creator skill loaded, so the agent actually authors the SKILL.md - # *using* skill-creator (not just "in its style"). - import shutil - import tempfile - - creator_src = _skill_creator_dir() - creator_rel = None - workdir = tempfile.mkdtemp(prefix="agentforge-distill-") - try: - if os.path.isfile(os.path.join(creator_src, "SKILL.md")): - dest = os.path.join(workdir, ".claude", "skills", "skill-creator") - os.makedirs(dest, exist_ok=True) - shutil.copy(os.path.join(creator_src, "SKILL.md"), os.path.join(dest, "SKILL.md")) - creator_rel = ".claude/skills/skill-creator/SKILL.md" - prompt = self._build_distill_prompt(pattern, context, skill_creator_rel=creator_rel) - ok, raw = self._run_agent_prompt_once(agent, prompt, workdir) - finally: - shutil.rmtree(workdir, ignore_errors=True) - if not ok: - raise RuntimeError(raw or "distill agent failed") - obj = _parse_json_object(raw) - name = _sanitize_skill_name(obj.get("name") or pattern["pattern_key"]) - description = str(obj.get("description", "")).strip() - body_md = str(obj.get("body_markdown") or obj.get("body") or "").strip() - worthy = obj.get("worthy") - worthy = bool(worthy) if isinstance(worthy, bool) else None - worthiness_reason = str(obj.get("worthiness_reason", "")).strip() - skill_md = _compose_skill_md(name, description, body_md) - self.db.upsert_skill_draft( - pattern_id, - "ready", - name=name, - description=description, - kind=pattern["kind"], - body=skill_md, - worthy=worthy, - worthiness_reason=worthiness_reason, - ) - return { - "pattern_id": pattern_id, - "name": name, - "description": description, - "kind": pattern["kind"], - "body": skill_md, - "worthy": worthy, - "worthiness_reason": worthiness_reason, - } - - def trigger_skill_draft(self, pattern_id: int, agent: Optional[str] = None) -> bool: - """Start distillation in the background (single-threaded server).""" - pattern = self.db.get_skill_pattern(pattern_id) - if not pattern: - return False - self.db.upsert_skill_draft(pattern_id, "drafting", kind=pattern["kind"]) - - def _worker(): - try: - self.distill_skill_draft(pattern_id, agent) - except Exception as e: # noqa: BLE001 - surface to draft row, never crash - logger.error(f"Skill distill failed: {e}") - self.db.upsert_skill_draft(pattern_id, "error", kind=pattern["kind"], error=str(e)) - - threading.Thread(target=_worker, daemon=True).start() - return True - - def approve_skill( - self, pattern_id: int, name: str, description: str, body: str - ) -> Optional[dict]: - """Write the approved SKILL.md, symlink it for both agents, register it.""" - pattern = self.db.get_skill_pattern(pattern_id) - if not pattern: - raise ValueError("pattern not found") - if not (body or "").strip(): - raise ValueError("skill body is empty") - # The edited SKILL.md is the single source of truth: derive the skill name - # and registry description from its frontmatter, falling back to the args. - fm_name, fm_desc = _parse_skill_frontmatter(body) - name = _sanitize_skill_name(fm_name or name or pattern["pattern_key"]) - if not name: - raise ValueError("invalid skill name") - description = fm_desc or description or "" - skill_md_path, _ = write_skill_to_disk(name, body) - skill_id = self.db.add_skill( - name=name, - description=description or "", - path=skill_md_path, - source_pattern_key=pattern["pattern_key"], - source_task_ids=pattern["contributing_task_ids"], - kind=pattern["kind"], - ) - self.db.set_skill_pattern_status(pattern_id, "promoted", promoted_skill_id=skill_id) - self.db.delete_skill_draft(pattern_id) - return self.db.get_skill(skill_id) - - def dismiss_skill_pattern(self, pattern_id: int) -> None: - if not self.db.get_skill_pattern(pattern_id): - raise ValueError("pattern not found") - self.db.set_skill_pattern_status(pattern_id, "dismissed") - self.db.delete_skill_draft(pattern_id) - - # ── Skill Library: registry management (#19) ─────────────────────────── - def toggle_skill(self, skill_id: int, enabled: bool) -> Optional[dict]: - """Enable/disable a registered skill by adding/removing both symlinks. - - Canonical SKILL.md is preserved either way — disabling just stops the - agents from loading it. - """ - skill = self.db.get_skill(skill_id) - if not skill: - raise ValueError("skill not found") - if enabled: - link_skill(skill["name"]) - else: - unlink_skill(skill["name"]) - self.db.set_skill_enabled(skill_id, enabled) - return self.db.get_skill(skill_id) - - def remove_skill(self, skill_id: int) -> None: - """Delete a skill: remove symlinks, canonical dir, and registry row.""" - skill = self.db.get_skill(skill_id) - if not skill: - raise ValueError("skill not found") - remove_skill_from_disk(skill["name"]) - self.db.delete_skill(skill_id) - - def _build_sweep_prompt(self, runs: list[dict], existing: list[dict]) -> str: - if existing: - existing_block = "\n".join( - f"- {p['pattern_key']} ({p['kind']}, seen {p['recurrence_count']}x): {p['summary']}" - for p in existing - ) - else: - existing_block = "(none yet)" - run_lines = [] - for r in runs: - p = (r.get("prompt") or "").strip().replace("\n", " ")[:400] - res = (r.get("result") or "").strip().replace("\n", " ")[:300] - run_lines.append( - f"[run #{r['run_id']} · task #{r['task_id']}] {r.get('title') or 'Untitled'}\n" - f" prompt: {p}\n" - f" result: {res}" - ) - runs_block = "\n".join(run_lines) - return ( - "You analyze a developer's recently completed AI-agent task runs to detect " - "RECURRING patterns of work worth distilling into a reusable skill.\n\n" - "Existing tracked patterns — REUSE an existing pattern_key verbatim when a run " - "matches one semantically; otherwise mint a new short kebab-case key:\n" - f"{existing_block}\n\n" - "Recently completed task runs to analyze (each line is ONE run):\n" - f"{runs_block}\n\n" - "Emit ONE entry PER RUN that represents a meaningful, repeatable capability. Kinds:\n" - '- "recipe": a successful repeatable approach/workflow worth reusing.\n' - '- "pitfall": a failure that was diagnosed and fixed, worth avoiding next time.\n' - "CRITICAL: when several runs share the same capability, they MUST reuse the SAME " - "pattern_key (so occurrences aggregate), but each run still gets its OWN entry with " - "its own run_id and task_id. Do NOT collapse multiple matching runs into a single " - "entry — one entry per run is how recurrence is counted. Reuse an existing tracked " - "pattern_key verbatim when it matches. Skip trivial or truly one-off runs.\n\n" - "Respond with ONLY a JSON array, no prose, no code fence (example shows two runs of " - "the same pattern):\n" - '[{"pattern_key":"run-pytest-suite","kind":"recipe","summary":"one concise line","run_id":12,"task_id":3},' - '{"pattern_key":"run-pytest-suite","kind":"recipe","summary":"one concise line","run_id":15,"task_id":4}]\n' - "If nothing is worth tracking, respond with []." - ) - - @staticmethod - def _parse_sweep_output(raw_text: str) -> list: - text = (raw_text or "").strip() - if text.startswith("```"): - lines = [ln for ln in text.splitlines() if not ln.strip().startswith("```")] - text = "\n".join(lines).strip() - if not text.startswith("["): - start = text.find("[") - end = text.rfind("]") - if start != -1 and end != -1 and end > start: - text = text[start : end + 1] - try: - data = json.loads(text) - except (ValueError, TypeError): - return [] - return data if isinstance(data, list) else [] - - def _run_agent_prompt_once(self, agent: str, prompt: str, working_dir: str) -> tuple[bool, str]: - working_dir_expanded = os.path.expanduser(working_dir) - if agent == "codex": - cmd = [ - "codex", - "exec", - "--json", - "--dangerously-bypass-approvals-and-sandbox", - "--skip-git-repo-check", - "--cd", - working_dir_expanded, - prompt, - ] - else: - cmd = ["claude", "-p", prompt, *CLAUDE_STREAM_JSON_ARGS] - return self._run_agent_command(agent, cmd, working_dir_expanded) - - def _run_agent_command( - self, - agent: str, - cmd: list[str], - working_dir_expanded: str, - on_stdout_line: Optional[Callable[[str], None]] = None, - on_stderr_line: Optional[Callable[[str], None]] = None, - ) -> tuple[bool, str]: - try: - proc = subprocess.Popen( - cmd, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - text=True, - cwd=working_dir_expanded, - env=_get_env(), - ) - except FileNotFoundError: - return False, f"{agent} CLI not found" - except OSError as e: - return False, str(e) - timeout_secs = int(self.db.get_setting("timeout", str(DEFAULT_TIMEOUT_SECONDS))) - stdout_chunks = [] - stderr_chunks = [] - - def _read_stream(stream, chunks, callback): - for line in stream: - chunks.append(line) - if callback: - callback(line) - - stdout_thread = threading.Thread( - target=_read_stream, - args=(proc.stdout, stdout_chunks, on_stdout_line), - daemon=True, - ) - stderr_thread = threading.Thread( - target=_read_stream, - args=(proc.stderr, stderr_chunks, on_stderr_line), - daemon=True, - ) - stdout_thread.start() - stderr_thread.start() - try: - proc.wait(timeout=timeout_secs) - except subprocess.TimeoutExpired: - try: - proc.kill() - except OSError: - pass - stdout_thread.join(timeout=1) - stderr_thread.join(timeout=1) - return False, f"{agent} heartbeat decision timed out" - - stdout_thread.join(timeout=1) - stderr_thread.join(timeout=1) - raw_stdout = "".join(stdout_chunks) - raw_stderr = "".join(stderr_chunks) - if proc.returncode != 0: - return False, raw_stderr or raw_stdout or f"{agent} heartbeat decision failed" - - if agent == "codex": - out = "" - for line in raw_stdout.splitlines(): - line = line.strip() - if not line: - continue - try: - event = json.loads(line) - except json.JSONDecodeError: - continue - if ( - event.get("type") == "item.completed" - and event.get("item", {}).get("type") == "agent_message" - ): - out = event["item"].get("text", "") - return True, out or raw_stdout - - out = "" - last_assistant_text = "" - for line in raw_stdout.splitlines(): - line = line.strip() - if not line: - continue - try: - event = json.loads(line) - except json.JSONDecodeError: - continue - if event.get("type") == "assistant": - msg = event.get("message", {}) - content = msg.get("content", []) - text_parts = [] - for c in content: - if isinstance(c, str): - text_parts.append(c) - elif isinstance(c, dict) and c.get("type") == "text": - text_parts.append(c.get("text", "")) - if text_parts: - last_assistant_text = "".join(text_parts) - elif event.get("type") == "result": - result_text = event.get("result") - if result_text: - out = result_text - return True, out or last_assistant_text or raw_stdout - - def _heartbeat_trigger_suppressed(self, heartbeat: dict, dedupe_key: str) -> bool: - if not dedupe_key: - return False - existing = self.db.get_heartbeat_dedup(heartbeat["id"], dedupe_key) - if not existing: - return False - cooldown = int(heartbeat.get("cooldown_seconds") or 0) - triggered_at = existing.get("triggered_at") - if triggered_at: - try: - triggered_dt = _parse_comparable_datetime(triggered_at) - if cooldown > 0 and datetime.now() < triggered_dt + timedelta(seconds=cooldown): - return True - except ValueError: - pass - existing_task_id = existing.get("task_id") - if existing_task_id: - task = self.db.get_task(existing_task_id) - if task and task.get("status") in ("pending", "scheduled", "blocked", "running"): - return True - return False - - def _execute_heartbeat(self, heartbeat: dict): - hid = heartbeat["id"] - tick_id = self.db.add_heartbeat_tick(hid) - now = datetime.now() - output_chunks: list[str] = [] - self._live_heartbeat_output[tick_id] = "" - next_run_at = self.db._compute_heartbeat_next_run_at( - Heartbeat( - id=hid, - name=heartbeat["name"], - enabled=heartbeat["enabled"], - working_dir=heartbeat["working_dir"], - schedule_type=HeartbeatScheduleType(heartbeat["schedule_type"]), - cron_expr=heartbeat.get("cron_expr"), - interval_seconds=heartbeat.get("interval_seconds"), - check_prompt=heartbeat["check_prompt"], - action_prompt_template=heartbeat.get("action_prompt_template") or "", - default_agent=heartbeat.get("default_agent") or DEFAULT_AGENT, - cooldown_seconds=int(heartbeat.get("cooldown_seconds") or 0), - ), - now, - ) - try: - - def _append_tick_output(line: str): - output_chunks.append(line) - self._live_heartbeat_output[tick_id] = "".join(output_chunks) - - agent = heartbeat.get("default_agent") or DEFAULT_AGENT - prompt = self._render_heartbeat_check_prompt(heartbeat) - working_dir_expanded = os.path.expanduser(heartbeat["working_dir"]) - if agent == "codex": - cmd = [ - "codex", - "exec", - "--json", - "--dangerously-bypass-approvals-and-sandbox", - "--skip-git-repo-check", - "--cd", - working_dir_expanded, - prompt, - ] - else: - cmd = [ - "claude", - "-p", - prompt, - "--output-format", - "stream-json", - "--verbose", - "--permission-mode", - "bypassPermissions", - ] - success, raw_output = self._run_agent_command( - agent, - cmd, - working_dir_expanded, - on_stdout_line=_append_tick_output, - on_stderr_line=_append_tick_output, - ) - if not success: - raise RuntimeError(raw_output) - decision = self._parse_heartbeat_decision(raw_output) - decision_type = decision["decision"] - if decision_type == HeartbeatDecisionType.TRIGGER_TASK.value: - dedupe_key = decision.get("dedupe_key", "") - if self._heartbeat_trigger_suppressed(heartbeat, dedupe_key): - decision_type = HeartbeatDecisionType.IDLE.value - decision["decision"] = decision_type - decision["reason"] = ( - "Suppressed duplicate signal during cooldown or while prior task is still active" - ) - else: - task_prompt = ( - decision.get("prompt") - or heartbeat.get("action_prompt_template") - or heartbeat["check_prompt"] - ) - task_title = decision.get("title") or f"Heartbeat: {heartbeat['name']}" - task = Task( - title=task_title, - prompt=task_prompt, - working_dir=heartbeat["working_dir"], - schedule_type=ScheduleType.IMMEDIATE, - agent=heartbeat.get("default_agent") or DEFAULT_AGENT, - tags="heartbeat", - ) - task_id = self.submit_task(task) - if dedupe_key: - self.db.upsert_heartbeat_dedup(hid, dedupe_key, task_id) - self.db.update_heartbeat( - hid, - next_run_at=next_run_at, - last_tick_at=now.isoformat(), - last_decision=decision_type, - last_error=None, - last_triggered_at=now.isoformat(), - last_dedupe_key=dedupe_key, - ) - self.db.finish_heartbeat_tick( - tick_id, - status="triggered", - decision_type=decision_type, - decision_payload=decision, - task_id=task_id, - raw_output=("".join(output_chunks)[:500000] if output_chunks else None), - ) - return - self.db.update_heartbeat( - hid, - next_run_at=next_run_at, - last_tick_at=now.isoformat(), - last_decision=decision_type, - last_error=None, - last_dedupe_key=decision.get("dedupe_key", "") or heartbeat.get("last_dedupe_key"), - ) - self.db.finish_heartbeat_tick( - tick_id, - status="idle" - if decision_type == HeartbeatDecisionType.IDLE.value - else decision_type, - decision_type=decision_type, - decision_payload=decision, - raw_output=("".join(output_chunks)[:500000] if output_chunks else None), - ) - except Exception as e: - logger.error(f"Heartbeat {hid} failed: {e}") - self.db.update_heartbeat( - hid, - next_run_at=next_run_at, - last_tick_at=now.isoformat(), - last_decision=HeartbeatDecisionType.ERROR.value, - last_error=str(e), - ) - self.db.finish_heartbeat_tick( - tick_id, - status="error", - decision_type=HeartbeatDecisionType.ERROR.value, - raw_output=("".join(output_chunks)[:500000] if output_chunks else None), - error=str(e), - ) - finally: - self._live_heartbeat_output.pop(tick_id, None) - self._active_heartbeats.pop(hid, None) - - def _codex_text_delta( - self, run_id: Optional[int], item_id: str, current_text: str - ) -> Optional[str]: - """Return only the newly emitted text for a cumulative Codex message item.""" - key = (run_id, item_id) - previous = self._codex_item_text.get(key, "") - self._codex_item_text[key] = current_text - if not current_text: - return None - if previous and current_text.startswith(previous): - delta = current_text[len(previous) :] - return delta or None - if current_text == previous: - return None - return current_text - - def _codex_append_text_delta( - self, run_id: Optional[int], item_id: str, delta: str - ) -> Optional[str]: - if delta == "": - return None - key = (run_id, item_id) - self._codex_item_text[key] = self._codex_item_text.get(key, "") + delta - return delta - - def _codex_event_delta_text(self, event: dict, item: dict) -> Optional[str]: - delta = item.get("delta", event.get("delta")) - if isinstance(delta, str): - return delta - if isinstance(delta, dict): - text = delta.get("text") - return text if isinstance(text, str) else None - return None - - def _clear_codex_run_state(self, run_id: int) -> None: - for key in [key for key in self._codex_item_text if key[0] == run_id]: - self._codex_item_text.pop(key, None) - - def _extract_codex_thread_id(self, raw_stdout: str) -> Optional[str]: - for line in raw_stdout.splitlines(): - line = line.strip() - if not line: - continue - try: - event = json.loads(line) - except json.JSONDecodeError: - continue - if event.get("type") == "thread.started" and event.get("thread_id"): - return str(event["thread_id"]) - return None - - def _codex_generated_images_root(self) -> Path: - codex_home = os.environ.get("CODEX_HOME") or os.path.join(os.path.expanduser("~"), ".codex") - return Path(codex_home).expanduser() / "generated_images" - - def _find_codex_generated_images( - self, thread_id: Optional[str], since_timestamp: Optional[float] = None - ) -> list[str]: - if not thread_id: - return [] - image_dir = self._codex_generated_images_root() / thread_id - if not image_dir.is_dir(): - return [] - paths = [] - for path in image_dir.rglob("*"): - if not path.is_file() or path.suffix.lower() not in GENERATED_IMAGE_MEDIA_TYPES: - continue - if since_timestamp is not None: - try: - if path.stat().st_mtime < since_timestamp: - continue - except OSError: - continue - paths.append(path) - return [str(path) for path in sorted(paths)] - - def _image_media_type(self, image_path: str) -> str: - return GENERATED_IMAGE_MEDIA_TYPES.get(Path(image_path).suffix.lower(), "image/png") - - def _extract_codex_success_output( - self, raw_stdout: str, generated_images: Optional[list[str]] = None - ) -> str: - out = "" - for line in raw_stdout.splitlines(): - line = line.strip() - if not line: - continue - try: - event = json.loads(line) - except json.JSONDecodeError: - continue - if ( - event.get("type") == "item.completed" - and event.get("item", {}).get("type") == "agent_message" - ): - out = event["item"].get("text", "") - - parts = [] - if out.strip(): - parts.append(out.strip()) - if generated_images: - image_lines = "\n".join(f"- {path}" for path in generated_images) - parts.append(f"已生成 {len(generated_images)} 张图片:\n{image_lines}") - return "\n\n".join(parts) - - def _store_generated_image_events( - self, task_id: int, run_id: int, generated_images: list[str] - ) -> None: - for image_path in generated_images: - media_type = self._image_media_type(image_path) - metadata = {"path": image_path, "media_type": media_type} - self._store_output_event(task_id, run_id, "generated_image", self._trace_json(metadata)) - try: - with open(image_path, "rb") as f: - image_data = base64.b64encode(f.read()).decode("utf-8") - except OSError as e: - logger.warning(f"Task {task_id}: failed to read generated image {image_path}: {e}") - continue - self.db.add_output_event( - task_id, - run_id, - "image_content", - json.dumps({**metadata, "data": image_data}, ensure_ascii=False), - ) - - def _claude_text_delta( - self, run_id: Optional[int], message_id: str, current_text: str - ) -> Optional[str]: - """Return newly emitted text for Claude partial/cumulative assistant messages.""" - key = (run_id, message_id) - previous = self._claude_message_text.get(key, "") - if not current_text: - return None - - if not previous: - self._claude_message_text[key] = current_text - return current_text - - if current_text == previous: - return None - - if current_text.startswith(previous): - self._claude_message_text[key] = current_text - delta = current_text[len(previous) :] - return delta or None - - # Claude can emit either cumulative partial messages or text chunks. For - # same-message non-cumulative chunks, keep our own accumulated state. - self._claude_message_text[key] = previous + current_text - return current_text - - def _claude_message_id(self, event: dict, run_id: Optional[int]) -> str: - message = event.get("message", {}) - if isinstance(message, dict): - message_id = message.get("id") or message.get("message_id") - if message_id: - return str(message_id) - return f"assistant:{run_id}" - - def _clear_claude_run_state(self, run_id: int) -> None: - for key in [key for key in self._claude_message_text if key[0] == run_id]: - self._claude_message_text.pop(key, None) - - def _redact_display_payload(self, value): - if isinstance(value, dict): - redacted = {} - for key, child in value.items(): - key_str = str(key) - if any(fragment in key_str.lower() for fragment in SECRET_KEY_FRAGMENTS): - redacted[key] = "[redacted]" - else: - redacted[key] = self._redact_display_payload(child) - return redacted - if isinstance(value, list): - return [self._redact_display_payload(item) for item in value] - return value - - def _compact_payload(self, payload: dict) -> dict: - return {key: value for key, value in payload.items() if value is not None} - - def _trace_json(self, payload: dict) -> str: - return json.dumps(self._redact_display_payload(payload), ensure_ascii=False) - - def _content_to_display_text(self, content) -> str: - if content is None: - return "" - if isinstance(content, str): - return content - if isinstance(content, list): - parts = [] - for item in content: - if isinstance(item, str): - parts.append(item) - elif isinstance(item, dict) and item.get("type") == "text": - parts.append(item.get("text", "")) - elif isinstance(item, dict) and item.get("type") == "image": - parts.append("[image]") - else: - parts.append(json.dumps(self._redact_display_payload(item), ensure_ascii=False)) - return "".join(parts) - if isinstance(content, dict): - if content.get("type") == "text": - return content.get("text", "") - return json.dumps(self._redact_display_payload(content), ensure_ascii=False) - return str(content) - - def _should_stream_event(self, event_type: str) -> bool: - return event_type in LIVE_OUTPUT_EVENT_TYPES - - def _store_output_event(self, task_id: int, run_id: int, event_type: str, content: str) -> None: - if not content: - return - self.db.add_output_event(task_id, run_id, event_type, content) - if self._should_stream_event(event_type): - self._fire_output_listeners(task_id, run_id, event_type, content) - - def _parse_codex_event(self, event: dict, run_id: Optional[int] = None) -> tuple: - """Normalize a Codex JSONL event into (event_type, content) for storage. - - Returns (None, None) to skip events that carry no displayable content. - """ - etype = event.get("type", "") - if etype in ("item.updated", "item.completed"): - item = event.get("item", {}) - itype = item.get("type", "") - if itype == "agent_message": - item_id = str(item.get("id") or item.get("item_id") or "agent_message") - event_delta = self._codex_event_delta_text(event, item) - if etype == "item.updated" and event_delta is not None: - delta = self._codex_append_text_delta(run_id, item_id, event_delta) - else: - delta = self._codex_text_delta(run_id, item_id, item.get("text", "")) - return ("assistant", delta) if delta is not None else (None, None) - elif itype == "reasoning": - item_id = str(item.get("id") or item.get("item_id") or "reasoning") - event_delta = self._codex_event_delta_text(event, item) - if etype == "item.updated" and event_delta is not None: - text = self._codex_append_text_delta(run_id, item_id, event_delta) or "" - else: - text = self._codex_text_delta(run_id, item_id, item.get("text", "")) or "" - return ("assistant", f"[thinking] {text}") if text else (None, None) - elif itype == "command_execution": - return "command_execution", self._trace_json( - self._compact_payload( - { - "id": item.get("id") or item.get("item_id"), - "command": item.get("command", ""), - "output": item.get("aggregated_output", ""), - "exit_code": item.get("exit_code"), - "status": item.get("status"), - } - ) - ) - elif itype in ("mcp_tool_call", "collab_tool_call"): - return "tool_call", self._trace_json( - self._compact_payload( - { - "id": item.get("id") or item.get("item_id"), - "server": item.get("server"), - "name": item.get("tool") or item.get("name"), - "input": item.get("arguments") or item.get("input"), - "result": item.get("result"), - "status": item.get("status"), - "error": item.get("error"), - } - ) - ) - elif itype == "web_search": - return "web_search", self._trace_json( - self._compact_payload( - { - "id": item.get("id") or item.get("item_id"), - "query": item.get("query"), - "action": item.get("action"), - "status": item.get("status"), - } - ) - ) - elif itype == "file_change": - return "file_change", self._trace_json( - self._compact_payload( - { - "id": item.get("id") or item.get("item_id"), - "changes": item.get("changes"), - "status": item.get("status"), - } - ) - ) - else: - return etype, json.dumps(event, ensure_ascii=False) - elif etype == "turn.failed": - err = event.get("error", {}) - msg = err.get("message", "") if isinstance(err, dict) else str(err) - return "error", msg - elif etype == "error": - return "error", event.get("message", "") - elif etype == "turn.completed": - # turn.completed only carries usage stats; final text comes from agent_message items - return None, None - elif etype in ("thread.started", "turn.started", "item.started"): - return None, None - else: - return etype, json.dumps(event, ensure_ascii=False) - - def _parse_and_store_event(self, task_id: int, run_id: int, line: str, agent: str = "claude"): - """Parse a line from the output stream and store it as an event.""" - if not line.strip(): - return - - try: - event = json.loads(line) - - if agent == "codex": - event_type, content = self._parse_codex_event(event, run_id) - if event_type and content: - self._store_output_event(task_id, run_id, event_type, content) - return - - # Claude stream-json - event_type = event.get("type", "unknown") - if event_type == "assistant": - text_content, image_events, trace_events = self._extract_message_content(event) - if text_content: - message_id = self._claude_message_id(event, run_id) - text_content = self._claude_text_delta(run_id, message_id, text_content) - if text_content: - self._store_output_event(task_id, run_id, event_type, text_content) - for img_json in image_events: - self.db.add_output_event(task_id, run_id, "image_content", img_json) - for trace_type, trace_content in trace_events: - self._store_output_event(task_id, run_id, trace_type, trace_content) - elif event_type == "user": - text_content, image_events, trace_events = self._extract_message_content(event) - if text_content: - self.db.add_output_event(task_id, run_id, event_type, text_content) - for img_json in image_events: - self.db.add_output_event(task_id, run_id, "image_content", img_json) - for trace_type, trace_content in trace_events: - self._store_output_event(task_id, run_id, trace_type, trace_content) - else: - content = "" - if event_type == "result": - content = event.get("result", "") - elif event_type == "error": - content = event.get("error", "") - else: - # For other event types, store the full JSON - content = json.dumps(event, ensure_ascii=False) - - if content: - self._store_output_event(task_id, run_id, event_type, content) - except json.JSONDecodeError: - # If it's not valid JSON, store as raw text - if line.strip() and len(line.strip()) > 10: # Only store meaningful non-JSON lines - self.db.add_output_event(task_id, run_id, "text", line.strip()) - - def _extract_message_content(self, event: dict) -> tuple: - """Extract text and image content from user/assistant messages. - - Returns (text, image_events, trace_events), where image_events and - trace_events contain already serialized display payloads. - """ - message = event.get("message", {}) - content = message.get("content", []) - text_parts = [] - image_events = [] - trace_events = [] - - for item in content: - if isinstance(item, str): - text_parts.append(item) - elif isinstance(item, dict): - if item.get("type") == "text": - text_parts.append(item.get("text", "")) - elif item.get("type") == "image": - source = item.get("source", {}) - if source.get("type") == "base64": - img_json = json.dumps( - { - "media_type": source.get("media_type", "image/jpeg"), - "data": source.get("data", ""), - }, - ensure_ascii=False, - ) - image_events.append(img_json) - # Non-base64 image sources (url, etc.) are ignored silently - elif item.get("type") == "tool_use": - trace_events.append( - ( - "tool_call", - self._trace_json( - self._compact_payload( - { - "id": item.get("id"), - "name": item.get("name"), - "input": item.get("input"), - } - ) - ), - ) - ) - elif item.get("type") == "tool_result": - trace_events.append( - ( - "tool_result", - self._trace_json( - self._compact_payload( - { - "tool_use_id": item.get("tool_use_id"), - "content": self._content_to_display_text( - item.get("content") - ), - "is_error": item.get("is_error", False), - } - ) - ), - ) - ) - - return "".join(text_parts), image_events, trace_events - - def _extract_error_summary(self, raw_stderr: str, raw_stdout: str) -> str: - """Extract a clean, human-readable error summary from raw CLI output. - - The full raw output is already stored in run.raw_output; this produces - a concise message for task.error and notification channels. - """ - # If stderr is short and not JSON, it's likely a plain error message - if raw_stderr and len(raw_stderr) < 2000: - first_line = raw_stderr.strip().split("\n")[0].strip() - if first_line and not first_line.startswith("{"): - return raw_stderr.strip()[:1000] - - # Try to parse stdout as stream-json to find error events - error_messages = [] - last_assistant_text = "" - source = raw_stdout if raw_stdout else raw_stderr - for line in source.splitlines(): - line = line.strip() - if not line: - continue - try: - event = json.loads(line) - event_type = event.get("type", "") - if event_type == "error": - err = event.get("error", "") - if err: - error_messages.append(err) - elif event_type == "result": - if event.get("subtype") == "error_during_execution": - err = event.get("error", event.get("result", "")) - if err: - error_messages.append(str(err)) - elif event_type == "assistant": - msg = event.get("message", {}) - content = msg.get("content", []) - text_parts = [ - (c if isinstance(c, str) else c.get("text", "")) - for c in content - if isinstance(c, str) or (isinstance(c, dict) and c.get("type") == "text") - ] - if text_parts: - last_assistant_text = "".join(text_parts) - except json.JSONDecodeError: - pass - - if error_messages: - return "\n".join(error_messages)[:1000] - - if last_assistant_text: - return last_assistant_text[:1000] - - # Fall back to raw stderr or first 500 chars of stdout - return (raw_stderr or raw_stdout or "Unknown error").strip()[:500] - - def _execute_task(self, task: dict): - tid = task["id"] - self._live_output[tid] = "" - # Status already set to "running" by _spawn_task() before thread start. - self._notify(tid) - - run_id = self.db.add_run(tid) - - # Build command — inject upstream results if configured - prompt = self._build_injected_prompt(task) - prompt_images = task.get("prompt_images") or [] - image_paths = task.get("image_paths") or [] # List of local image file paths - - # Convert image_paths to prompt_images format (base64 encoded) - if image_paths and not prompt_images: # Only if not already using prompt_images - import base64 - - _ALLOWED_IMAGE_ROOTS = [ - os.path.expanduser("~"), - "/tmp", - ] - - def _is_safe_image_path(path: str) -> bool: - """Return True only if path resolves inside an allowed directory.""" - try: - resolved = os.path.realpath(os.path.abspath(path)) - except Exception: - return False - for root in _ALLOWED_IMAGE_ROOTS: - try: - resolved_root = os.path.realpath(root) - if resolved.startswith(resolved_root + os.sep) or resolved == resolved_root: - return True - except Exception: - continue - return False - - for img_path in image_paths: - if not _is_safe_image_path(img_path): - logger.warning( - f"Task {tid}: Rejected image path outside allowed directories: {img_path}" - ) - continue - try: - with open(img_path, "rb") as f: - img_data = base64.b64encode(f.read()).decode("utf-8") - - # Detect media type from file extension - img_path_lower = img_path.lower() - if img_path_lower.endswith(".png"): - media_type = "image/png" - elif img_path_lower.endswith((".jpg", ".jpeg")): - media_type = "image/jpeg" - elif img_path_lower.endswith(".gif"): - media_type = "image/gif" - elif img_path_lower.endswith(".webp"): - media_type = "image/webp" - else: - # Try to detect from magic bytes - with open(img_path, "rb") as f: - header = f.read(12) - if header.startswith(b"\xff\xd8\xff"): - media_type = "image/jpeg" - elif header.startswith(b"\x89PNG\r\n\x1a\n"): - media_type = "image/png" - elif header.startswith(b"GIF87a") or header.startswith(b"GIF89a"): - media_type = "image/gif" - elif header.startswith(b"RIFF") and b"WEBP" in header: - media_type = "image/webp" - else: - media_type = "image/jpeg" # default fallback - - prompt_images.append( - { - "media_type": media_type, - "data": img_data, - "name": os.path.basename(img_path), - } - ) - logger.debug( - f"Task {tid}: Loaded image {img_path} as {media_type} ({len(img_data)} bytes base64)" - ) - except Exception as e: - logger.error(f"Task {tid}: Failed to load image {img_path}: {e}") - - agent = task.get("agent") or DEFAULT_AGENT - use_stdin = bool(prompt_images) and agent == "claude" - - if agent == "codex": - working_dir_expanded = os.path.expanduser(task["working_dir"]) - if task.get("session_id"): - cmd = [ - "codex", - "exec", - "resume", - "--json", - "--dangerously-bypass-approvals-and-sandbox", - "--skip-git-repo-check", - task["session_id"], - prompt, - ] - else: - cmd = [ - "codex", - "exec", - "--json", - "--dangerously-bypass-approvals-and-sandbox", - "--skip-git-repo-check", - "--cd", - working_dir_expanded, - prompt, - ] - for img_path in image_paths or []: - cmd.extend(["--image", img_path]) - elif use_stdin: - # Claude multimodal input: pass via stdin with --input-format stream-json - cmd = [ - "claude", - "-p", - "--input-format", - "stream-json", - *CLAUDE_STREAM_JSON_ARGS, - ] - else: - cmd = ["claude", "-p", prompt, *CLAUDE_STREAM_JSON_ARGS] - if agent == "claude" and task.get("session_id"): - cmd.extend(["--resume", task["session_id"]]) - raw_stdout = "" - raw_stderr = "" - # Initialized before the try so the failure branch can read it even when - # Popen itself raises (e.g. CLI not found) before the timer is armed. - timed_out = [False] - try: - timeout_secs = int(self.db.get_setting("timeout", str(DEFAULT_TIMEOUT_SECONDS))) - start_time = time.time() - proc = subprocess.Popen( - cmd, - stdin=subprocess.PIPE if use_stdin else None, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - text=True, - cwd=os.path.expanduser(task["working_dir"]), - env=_get_env(), - start_new_session=True, # Create a new process group so all sub-agents are tracked - ) - if use_stdin: - # Build multimodal message content - content = [{"type": "text", "text": prompt}] - for img in prompt_images: - content.append( - { - "type": "image", - "source": { - "type": "base64", - "media_type": img.get("media_type", "image/jpeg"), - "data": img.get("data", ""), - }, - } - ) - stdin_msg = json.dumps( - {"type": "user", "message": {"role": "user", "content": content}} - ) - proc.stdin.write(stdin_msg + "\n") - proc.stdin.close() - pgid = os.getpgid(proc.pid) - self._active_pgids[tid] = pgid - - # Read stderr in a background thread so it never blocks stdout reading - stderr_chunks = [] - - def _read_stderr(): - for line in proc.stderr: - stderr_chunks.append(line) - - stderr_thread = threading.Thread(target=_read_stderr, daemon=True) - stderr_thread.start() - - # Timer that kills the entire process group if it exceeds the configured timeout - def _kill(): - timed_out[0] = True - try: - os.killpg(pgid, signal.SIGKILL) - except OSError as e: - logger.error( - f"Task {tid}: killpg({pgid}) failed: {e}, falling back to kill({proc.pid})" - ) - try: - os.kill(proc.pid, signal.SIGKILL) - except OSError as e2: - logger.error(f"Task {tid}: kill({proc.pid}) also failed: {e2}") - - timer = threading.Timer(timeout_secs, _kill) - timer.start() - - chunks = [] - try: - for line in proc.stdout: - chunks.append(line) - self._live_output[tid] = "".join(chunks) - # Parse and store each line as an event - self._parse_and_store_event(tid, run_id, line, agent) - proc.wait() - finally: - timer.cancel() - stderr_thread.join(timeout=2) - - # Wait for any sub-agents still running in the process group. - # Claude Code may spawn background Task agents that outlive the main process. - if not timed_out[0] and proc.returncode == 0: - elapsed = time.time() - start_time - remaining = max(0, timeout_secs - elapsed) - subagent_deadline = time.time() + remaining - waiting_logged = False - while time.time() < subagent_deadline: - try: - os.killpg(pgid, 0) # raises ProcessLookupError when group is gone - except ProcessLookupError: - break - if not waiting_logged: - waiting_logged = True - logger.info(f"Task {tid}: main process exited, waiting for sub-agents...") - self._live_output[tid] = ( - "".join(chunks) + "\n[⏳ Waiting for sub-agents to complete...]" - ) - time.sleep(1) - else: - # Sub-agents exceeded remaining timeout — kill the group - timed_out[0] = True - try: - os.killpg(pgid, signal.SIGKILL) - except OSError as e: - logger.error(f"Task {tid}: killpg({pgid}) on sub-agent timeout failed: {e}") - - self._active_pgids.pop(tid, None) - - raw_stdout = "".join(chunks) - raw_stderr = "".join(stderr_chunks) - - if timed_out[0]: - success, output = False, f"Task timed out after {timeout_secs}s" - elif proc.returncode == 0: - if agent == "codex": - thread_id = self._extract_codex_thread_id(raw_stdout) - generated_images = self._find_codex_generated_images( - thread_id, since_timestamp=start_time - ) - if generated_images: - self._store_generated_image_events(tid, run_id, generated_images) - success = True - output = self._extract_codex_success_output(raw_stdout, generated_images) - else: - # Claude stream-json: find the last result event and last assistant text - out = "" - last_assistant_text = "" - for line in raw_stdout.splitlines(): - line = line.strip() - if not line: - continue - try: - event = json.loads(line) - if event.get("type") == "assistant": - msg = event.get("message", {}) - content = msg.get("content", []) - text_parts = [] - for c in content: - if isinstance(c, str): - text_parts.append(c) - elif isinstance(c, dict) and c.get("type") == "text": - text_parts.append(c.get("text", "")) - if text_parts: - last_assistant_text = "".join(text_parts) - elif event.get("type") == "result": - result_text = event.get("result") - if result_text: - out = result_text - except json.JSONDecodeError: - pass - # If result event had no result field (e.g. error_during_execution - # with 0 output tokens), fall back to last assistant message text - if not out: - out = last_assistant_text - success, output = True, out - else: - success, output = False, raw_stderr or raw_stdout - except FileNotFoundError: - cli_name = "codex" if task.get("agent") == "codex" else "claude" - install_hint = ( - "Install with: npm install -g @openai/codex" - if cli_name == "codex" - else "Is it installed?" - ) - success, output = False, f"{cli_name} CLI not found. {install_hint}" - self._active_pgids.pop(tid, None) - except (OSError, subprocess.SubprocessError) as e: - logger.error(f"Task {tid} subprocess error: {e}") - success, output = False, str(e) - self._active_pgids.pop(tid, None) - - self._live_output.pop(tid, None) - if agent == "codex": - self._clear_codex_run_state(run_id) - elif agent == "claude": - self._clear_claude_run_state(run_id) - - # Extract session_id from output (format differs by agent) - extracted_session_id = None - if agent == "codex": - # Codex emits session_id in the thread.started event at the beginning - extracted_session_id = self._extract_codex_thread_id(raw_stdout) - else: - # Claude emits session_id in the result event at the end - for line in reversed(raw_stdout.splitlines()): - line = line.strip() - if not line: - continue - try: - event = json.loads(line) - if event.get("type") == "result" and event.get("session_id"): - extracted_session_id = event["session_id"] - break - except json.JSONDecodeError: - pass - - # Truncate raw_output for storage (max 500KB) - raw_output_stored = raw_stdout[:500000] if raw_stdout else None - - new_count = (task.get("run_count") or 0) + 1 - if success: - updates = { - "result": output[:50000], # truncate for storage - "last_run_at": datetime.now().isoformat(), - "run_count": new_count, - } - if extracted_session_id: - updates["session_id"] = extracted_session_id - # Handle cron rescheduling - cron_will_reschedule = False - if task["schedule_type"] == "cron" and task.get("cron_expr"): - max_runs = task.get("max_runs") - if max_runs and new_count >= max_runs: - updates["status"] = "completed" - else: - nxt = croniter(task["cron_expr"], datetime.now()).get_next(datetime) - updates["status"] = "scheduled" - updates["next_run_at"] = nxt.isoformat() - cron_will_reschedule = True - else: - updates["status"] = "completed" - self.db.finish_run_and_update_task( - run_id, "completed", tid, updates, run_result=output, raw_output=raw_output_stored - ) - # For cron tasks that get rescheduled, notify channels with TASK_COMPLETED - # before the status flips to "scheduled", so channels actually fire. - if cron_will_reschedule: - self._bus_notify(tid, override_type=OutboundMessageType.TASK_COMPLETED) - else: - # Extract a clean, human-readable error summary for task.error and - # notification channels. The full raw output is preserved in run_error. - if timed_out[0]: - # The timeout IS the reason — don't let an unrelated stderr line - # (e.g. codex's "Reading additional input from stdin…") mask it. - error_summary = output - else: - error_summary = ( - self._extract_error_summary(raw_stderr, raw_stdout) - if (raw_stderr or raw_stdout) - else (output or "Unknown error") - ) - updates = { - "status": "failed", - "error": error_summary, - "last_run_at": datetime.now().isoformat(), - "run_count": new_count, - } - # Persist the conversation id even on failure so the task stays - # resumable (e.g. replying in a Feishu/Slack/Telegram thread to - # retry). Codex emits thread_id in the opening thread.started event, - # so even a started-then-failed run has one to recover. - if extracted_session_id: - updates["session_id"] = extracted_session_id - self.db.finish_run_and_update_task( - run_id, - "failed", - tid, - updates, - run_error=output, - raw_output=raw_output_stored, - ) - - self._notify(tid) - self._active_tasks.pop(tid, None) - - # DAG: trigger downstream cascade after task finishes - if success: - self._on_task_completed(tid) - else: - self._on_task_failed(tid) - - def _fire_output_listeners( - self, task_id: int, run_id: int, event_type: str, content: str - ) -> None: - """Fire all registered output listeners (non-blocking; errors are swallowed).""" - with self._listeners_lock: - listeners = list(self._output_event_listeners) - for cb in listeners: - try: - cb(task_id, run_id, event_type, content) - except Exception as e: - logger.error(f"Output listener error: {e}") - - def add_output_listener(self, cb) -> None: - """Register a callback invoked for each assistant output event. - - Signature: cb(task_id: int, run_id: int, event_type: str, content: str) - Called from the task execution thread — must be non-blocking. - """ - with self._listeners_lock: - self._output_event_listeners.append(cb) - - def remove_output_listener(self, cb) -> None: - with self._listeners_lock: - try: - self._output_event_listeners.remove(cb) - except ValueError: - pass - - def _notify(self, task_id: int): - if self.on_task_update: - self.on_task_update(task_id) - for ch in self._channels: - threading.Thread( - target=ch.notify_task, - args=(task_id,), - daemon=True, - ).start() - # Publish to MessageBus (non-blocking; subscribers notified synchronously) - self._bus_notify(task_id) - - def submit_task(self, task: Task, depends_on: list = None) -> int: - """Add and schedule a new task. - - depends_on: list of dicts [{task_id, inject_result}] or list of ints. - If any upstream task is not yet completed, the task starts as BLOCKED. - """ - now = datetime.now() - - # Resolve depends_on to normalized list - dep_list = [] - if depends_on: - for dep in depends_on: - if isinstance(dep, int): - dep_list.append({"task_id": dep, "inject_result": False}) - elif isinstance(dep, dict): - dep_list.append( - { - "task_id": dep["task_id"], - "inject_result": bool(dep.get("inject_result", False)), - } - ) - - # Determine initial status: BLOCKED if any upstream not completed - has_unmet = False - if dep_list: - for dep in dep_list: - upstream = self.db.get_task(dep["task_id"]) - if not upstream or upstream["status"] != "completed": - has_unmet = True - break - - if has_unmet: - task.status = TaskStatus.BLOCKED - elif task.schedule_type == ScheduleType.IMMEDIATE: - task.status = TaskStatus.PENDING - elif task.schedule_type == ScheduleType.DELAYED: - task.status = TaskStatus.PENDING - elif task.schedule_type == ScheduleType.SCHEDULED_AT: - task.status = TaskStatus.SCHEDULED - if not task.next_run_at: - raise ValueError("scheduled_at requires next_run_at to be set") - task.next_run_at = _normalize_datetime_for_storage(task.next_run_at) - elif task.schedule_type == ScheduleType.CRON: - task.status = TaskStatus.SCHEDULED - if task.cron_expr: - nxt = croniter(task.cron_expr, now).get_next(datetime) - task.next_run_at = nxt.isoformat() - - task_id = self.db.add_task(task) - - # Store dependency rows atomically — if any insert fails the whole - # batch is rolled back so we never leave a task with partial deps. - if dep_list: - self.db.add_dependencies_batch(task_id, dep_list) - - return task_id - - # ──────────────────────── DAG helpers ──────────────────────── - - def _build_injected_prompt(self, task: dict) -> str: - """Prepend upstream results to the prompt for deps with inject_result=True.""" - deps = self.db.get_dependencies(task["id"]) - injections = [] - for dep in deps: - if dep.get("inject_result"): - upstream = self.db.get_task(dep["depends_on_task_id"]) - if upstream and upstream.get("result"): - injections.append( - f"=== Result from upstream task #{upstream['id']} ({upstream['title']}) ===\n" - f"{upstream['result']}\n" - f"=== End of upstream result ===" - ) - if injections: - return "\n\n".join(injections) + "\n\n---\n\n" + task["prompt"] - return task["prompt"] - - def _on_task_completed(self, task_id: int): - """Check whether any blocked downstream tasks can now be unblocked.""" - dependents = self.db.get_dependents(task_id) - for dep in dependents: - downstream_id = dep["task_id"] - if dep["task_status"] != "blocked": - continue - # Check all upstream deps of this downstream task - all_deps = self.db.get_dependencies(downstream_id) - if all(d["depends_on_status"] == "completed" for d in all_deps): - # All upstream done — unblock - downstream = self.db.get_task(downstream_id) - if not downstream: - continue - # Determine next status based on schedule_type - stype = downstream.get("schedule_type", "immediate") - if stype == "immediate": - new_status = "pending" - elif stype == "delayed": - new_status = "pending" - elif stype == "scheduled_at": - new_status = "scheduled" - elif stype == "cron": - new_status = "scheduled" - else: - new_status = "pending" - self.db.update_task(downstream_id, status=new_status) - logger.info(f"DAG: Task {downstream_id} unblocked (all upstream done)") - self._notify(downstream_id) - - def _on_task_failed(self, task_id: int): - """Cascade-cancel all blocked downstream tasks recursively.""" - to_cancel = [] - visited = set() - queue = [task_id] - while queue: - current = queue.pop() - for dep in self.db.get_dependents(current): - downstream_id = dep["task_id"] - if downstream_id in visited: - continue - visited.add(downstream_id) - task_status = dep["task_status"] - if task_status in ("blocked", "pending", "scheduled"): - to_cancel.append((downstream_id, task_id)) - queue.append(downstream_id) - for downstream_id, origin_id in to_cancel: - self.db.update_task( - downstream_id, - status="cancelled", - error=f"Cancelled: upstream task #{origin_id} failed", - ) - logger.info( - f"DAG: Task {downstream_id} cascade-cancelled (upstream #{origin_id} failed)" - ) - self._notify(downstream_id) - - # ───────────────────────────────────────────────────────────── - - def cancel_task(self, task_id: int): - pgid = self._active_pgids.get(task_id) - if pgid: - try: - os.killpg(pgid, signal.SIGKILL) - except OSError: - pass - self.db.update_task(task_id, status="cancelled") - self._notify(task_id) - - def retry_task(self, task_id: int): - self.db.update_task(task_id, status="pending", error=None) - self._notify(task_id) - - def trigger_heartbeat_now(self, heartbeat_id: int): - heartbeat = self.db.get_heartbeat(heartbeat_id) - if not heartbeat: - raise ValueError("heartbeat not found") - if ( - heartbeat_id in self._active_heartbeats - and self._active_heartbeats[heartbeat_id].is_alive() - ): - raise ValueError("heartbeat already running") - self._spawn_heartbeat(heartbeat) - - def pause_heartbeat(self, heartbeat_id: int): - heartbeat = self.db.get_heartbeat(heartbeat_id) - if not heartbeat: - raise ValueError("heartbeat not found") - self.db.update_heartbeat(heartbeat_id, enabled=0) - - def resume_heartbeat(self, heartbeat_id: int): - heartbeat = self.db.get_heartbeat(heartbeat_id) - if not heartbeat: - raise ValueError("heartbeat not found") - next_run_at = self.db._compute_heartbeat_next_run_at( - Heartbeat( - id=heartbeat_id, - name=heartbeat["name"], - enabled=True, - working_dir=heartbeat["working_dir"], - schedule_type=HeartbeatScheduleType(heartbeat["schedule_type"]), - cron_expr=heartbeat.get("cron_expr"), - interval_seconds=heartbeat.get("interval_seconds"), - check_prompt=heartbeat["check_prompt"], - action_prompt_template=heartbeat.get("action_prompt_template") or "", - default_agent=heartbeat.get("default_agent") or DEFAULT_AGENT, - cooldown_seconds=int(heartbeat.get("cooldown_seconds") or 0), - ), - datetime.now(), - ) - self.db.update_heartbeat(heartbeat_id, enabled=1, next_run_at=next_run_at) - - -# ──────────────────────────── HTTP API Server ──────────────────────────── -# Single CSRF token for the lifetime of this server process. -# The frontend fetches it once via GET /api/csrf-token and includes it as -# the X-CSRF-Token header on all state-changing requests. -_CSRF_TOKEN = secrets.token_hex(32) - -# Origins allowed to call this API. The Electron renderer uses file:// in -# production (Origin header is "null") and http://localhost: in dev -# (Vite). We also accept any http://localhost:* origin for tooling. -_ALLOWED_ORIGINS = {"null", "http://localhost"} - - -class TaskAPIHandler(BaseHTTPRequestHandler): - """Simple REST API for the frontend to communicate with.""" - - scheduler: TaskScheduler = None - db: TaskDB = None - feishu_channel = None - telegram_channel = None - slack_channel = None - weixin_channel = None - - def do_OPTIONS(self): - origin = self.headers.get("Origin", "") - if origin and not self._is_allowed_origin(origin): - self.send_response(403) - self.end_headers() - return - self.send_response(200) - self._cors_headers() - self.end_headers() - - def _task_output_payload(self, task_id: int) -> dict: - is_running = task_id in self.scheduler._live_output - if is_running: - output = self.scheduler._live_output.get(task_id, "") - else: - runs = self.db.get_task_runs(task_id, limit=1) - output = (runs[0].get("raw_output") or "") if runs else "" - return {"output": output, "is_running": is_running} - - def _validate_heartbeat_payload( - self, body: dict, existing: Optional[dict] = None - ) -> tuple[Optional[Heartbeat], Optional[tuple[dict, int]]]: - def _coerce_bool(value): - if isinstance(value, bool): - return value - if isinstance(value, str): - return value.lower() == "true" - return bool(value) - - name = body.get("name", existing.get("name") if existing else "Untitled heartbeat") - check_prompt = body.get("check_prompt", existing.get("check_prompt") if existing else "") - if not check_prompt or not str(check_prompt).strip(): - return None, ({"error": "check_prompt cannot be empty", "field": "check_prompt"}, 400) - - working_dir = body.get("working_dir", existing.get("working_dir") if existing else ".") - if working_dir and working_dir != ".": - expanded = os.path.expanduser(working_dir) - if not os.path.isdir(expanded): - return None, ( - { - "error": f"working_dir does not exist or is not a directory: {working_dir}", - "field": "working_dir", - }, - 400, - ) - - schedule_value = body.get( - "schedule_type", existing.get("schedule_type") if existing else "interval" - ) - try: - schedule_type = HeartbeatScheduleType(schedule_value) - except ValueError: - return None, ( - { - "error": f"invalid heartbeat schedule_type: {schedule_value}", - "field": "schedule_type", - }, - 400, - ) - - cron_expr = body.get("cron_expr", existing.get("cron_expr") if existing else None) - interval_seconds = body.get( - "interval_seconds", existing.get("interval_seconds") if existing else None - ) - if schedule_type == HeartbeatScheduleType.CRON: - if not cron_expr or not str(cron_expr).strip(): - return None, ( - {"error": "cron_expr is required for cron heartbeat", "field": "cron_expr"}, - 400, - ) - if not croniter.is_valid(cron_expr): - return None, ( - {"error": f"invalid cron expression: {cron_expr}", "field": "cron_expr"}, - 400, - ) - interval_seconds = None - else: - try: - interval_seconds = int(interval_seconds) - except (TypeError, ValueError): - return None, ( - { - "error": "interval_seconds must be a positive integer", - "field": "interval_seconds", - }, - 400, - ) - if interval_seconds <= 0: - return None, ( - { - "error": "interval_seconds must be a positive integer", - "field": "interval_seconds", - }, - 400, - ) - cron_expr = None - - cooldown_seconds = body.get( - "cooldown_seconds", existing.get("cooldown_seconds") if existing else 0 - ) - try: - cooldown_seconds = int(cooldown_seconds or 0) - except (TypeError, ValueError): - return None, ( - {"error": "cooldown_seconds must be an integer", "field": "cooldown_seconds"}, - 400, - ) - if cooldown_seconds < 0: - return None, ( - {"error": "cooldown_seconds cannot be negative", "field": "cooldown_seconds"}, - 400, - ) - - heartbeat = Heartbeat( - id=existing.get("id") if existing else None, - name=name, - enabled=_coerce_bool( - body.get("enabled", existing.get("enabled") if existing else True) - ), - working_dir=working_dir, - schedule_type=schedule_type, - cron_expr=cron_expr, - interval_seconds=interval_seconds, - check_prompt=str(check_prompt), - action_prompt_template=str( - body.get( - "action_prompt_template", - existing.get("action_prompt_template") if existing else "", - ) - ), - default_agent=str( - body.get( - "default_agent", - existing.get("default_agent") - if existing - else self.db.get_setting("default_agent", DEFAULT_AGENT), - ) - ), - cooldown_seconds=cooldown_seconds, - next_run_at=existing.get("next_run_at") if existing else None, - last_tick_at=existing.get("last_tick_at") if existing else None, - last_decision=existing.get("last_decision") if existing else None, - last_error=existing.get("last_error") if existing else None, - last_triggered_at=existing.get("last_triggered_at") if existing else None, - last_dedupe_key=existing.get("last_dedupe_key") if existing else None, - ) - heartbeat.next_run_at = self.db._compute_heartbeat_next_run_at(heartbeat, datetime.now()) - return heartbeat, None - - def do_GET(self): - parsed = urlparse(self.path) - path = parsed.path - - if path == "/api/heartbeats": - self._json_response(self.db.get_all_heartbeats()) - - elif path.startswith("/api/heartbeats/") and "/ticks/" in path and path.endswith("/output"): - parts = path.split("/") - hid = int(parts[3]) - tick_id = int(parts[5]) - tick = self.db.get_heartbeat_tick(hid, tick_id) - if not tick: - self._json_response({"error": "not found"}, 404) - return - live = self.scheduler._live_heartbeat_output.get(tick_id, tick.get("raw_output") or "") - self._json_response( - {"output": live, "is_running": tick_id in self.scheduler._live_heartbeat_output} - ) - - elif path.startswith("/api/heartbeats/") and path.endswith("/ticks"): - hid = int(path.split("/")[3]) - query = parse_qs(urlparse(self.path).query) - limit = int(query.get("limit", ["50"])[0]) - self._json_response({"ticks": self.db.get_heartbeat_ticks(hid, limit=limit)}) - - elif path.startswith("/api/heartbeats/"): - hid = int(path.split("/")[3]) - heartbeat = self.db.get_heartbeat(hid) - if heartbeat: - self._json_response(heartbeat) - else: - self._json_response({"error": "not found"}, 404) - - elif path == "/api/tasks": - tasks = self.db.get_all_tasks() - # Attach dependency metadata to each task - for t in tasks: - t["dependencies"] = self.db.get_dependencies(t["id"]) - t["dependents"] = [d["task_id"] for d in self.db.get_dependents(t["id"])] - self._json_response(tasks) - - elif path.startswith("/api/tasks/") and path.endswith("/runs"): - tid = int(path.split("/")[3]) - runs = self.db.get_task_runs(tid) - self._json_response(runs) - - elif path.startswith("/api/tasks/") and path.endswith("/output"): - tid = int(path.split("/")[3]) - self._json_response(self._task_output_payload(tid)) - - elif path.startswith("/api/tasks/") and path.endswith("/events"): - tid = int(path.split("/")[3]) - # Parse query parameters for pagination - query = parse_qs(urlparse(self.path).query) - limit = int(query.get("limit", ["1000"])[0]) - offset = int(query.get("offset", ["0"])[0]) - events = self.db.get_output_events(tid, limit=limit, offset=offset) - self._json_response({"events": events, "total": len(events)}) - - elif path.startswith("/api/tasks/") and path.endswith("/messages"): - tid = int(path.split("/")[3]) - runs = self.db.get_task_runs(tid, limit=50) - messages = [] - for run in reversed(runs): # oldest first - raw = run.get("raw_output") or "" - run_messages = [] - for line in raw.splitlines(): - line = line.strip() - if not line: - continue - try: - event = json.loads(line) - etype = event.get("type") - if etype == "user": - msg = event.get("message", {}) - content = msg.get("content", []) - text = "" - for c in content: - if isinstance(c, dict) and c.get("type") == "text": - text += c.get("text", "") - elif isinstance(c, str): - text += c - if text.strip(): - run_messages.append( - {"role": "user", "text": text, "run_id": run["id"]} - ) - elif etype == "assistant": - msg = event.get("message", {}) - content = msg.get("content", []) - text = "" - for c in content: - if isinstance(c, dict) and c.get("type") == "text": - text += c.get("text", "") - if text.strip(): - run_messages.append( - {"role": "assistant", "text": text, "run_id": run["id"]} - ) - except json.JSONDecodeError: - pass - messages.extend(run_messages) - self._json_response(messages) - - elif path.startswith("/api/tasks/") and path.endswith("/dependencies"): - tid = int(path.split("/")[3]) - self._json_response(self.db.get_dependencies(tid)) - - elif path.startswith("/api/tasks/") and path.endswith("/dependents"): - tid = int(path.split("/")[3]) - self._json_response(self.db.get_dependents(tid)) - - elif path.startswith("/api/dag/"): - dag_id = path[len("/api/dag/") :] - tasks = self.db.get_dag_tasks(dag_id) - for t in tasks: - t["dependencies"] = self.db.get_dependencies(t["id"]) - t["dependents"] = [d["task_id"] for d in self.db.get_dependents(t["id"])] - self._json_response(tasks) - - elif path.startswith("/api/tasks/"): - tid = int(path.split("/")[3]) - task = self.db.get_task(tid) - if task: - task["dependencies"] = self.db.get_dependencies(tid) - task["dependents"] = [d["task_id"] for d in self.db.get_dependents(tid)] - self._json_response(task) - else: - self._json_response({"error": "not found"}, 404) - - elif path == "/api/skill-patterns": - self._json_response( - { - "patterns": self.db.get_skill_patterns(), - "sweep": self.scheduler.skill_sweep_status(), - } - ) - - elif path == "/api/skills": - self._json_response({"skills": self.db.get_skills()}) - - elif path.startswith("/api/skills/") and path.endswith("/content"): - sid = int(path.split("/")[3]) - skill = self.db.get_skill(sid) - if not skill: - self._json_response({"error": "not found"}, 404) - return - try: - with open(skill["path"], encoding="utf-8") as f: - content = f.read() - except OSError as e: - content = f"(无法读取 SKILL.md:{e})" - self._json_response({"content": content, "path": skill["path"], "skill": skill}) - - elif path == "/api/csrf-token": - self._json_response({"csrf_token": _CSRF_TOKEN}) - - elif path == "/api/health": - self._json_response({"status": "ok", "tasks": len(self.db.get_all_tasks())}) - - elif path == "/api/settings": - self._json_response( - { - "default_agent": self.db.get_setting("default_agent", DEFAULT_AGENT), - "timeout": int(self.db.get_setting("timeout", str(DEFAULT_TIMEOUT_SECONDS))), - "skill_library_enabled": self.db.get_setting("skill_library_enabled", "0") - == "1", - "skill_sweep_agent": self.db.get_setting("skill_sweep_agent", DEFAULT_AGENT), - "skill_sweep_cron": self.db.get_setting("skill_sweep_cron", "0 3 * * *"), - } - ) - - elif path == "/api/feishu/settings": - self._json_response( - { - "feishu_app_id": self.db.get_setting("feishu_app_id", ""), - "feishu_app_secret": self.db.get_setting("feishu_app_secret", ""), - "feishu_default_chat_id": self.db.get_setting("feishu_default_chat_id", ""), - "feishu_default_working_dir": self.db.get_setting( - "feishu_default_working_dir", "~" - ), - "feishu_enabled": self.db.get_setting("feishu_enabled", "false"), - } - ) - - elif path == "/api/channels/status": - import os as _os - - # Tokens can come from settings DB or env vars - tg_token = self.db.get_setting("telegram_bot_token", "") or _os.environ.get( - "TELEGRAM_BOT_TOKEN", "" - ) - sl_bot = self.db.get_setting("slack_bot_token", "") or _os.environ.get( - "SLACK_BOT_TOKEN", "" - ) - sl_app = self.db.get_setting("slack_app_token", "") or _os.environ.get( - "SLACK_APP_TOKEN", "" - ) - self._json_response( - { - "telegram": { - "enabled": self.db.get_setting("telegram_enabled", "false") == "true", - "configured": bool(tg_token), - "running": bool( - self.telegram_channel - and getattr(self.telegram_channel, "_running", False) - ), - "default_working_dir": self.db.get_setting( - "telegram_default_working_dir", "~" - ), - "default_chat_id": self.db.get_setting("telegram_default_chat_id", ""), - "allowed_users": self.db.get_setting("telegram_allowed_users", ""), - }, - "slack": { - "enabled": self.db.get_setting("slack_enabled", "false") == "true", - "configured": bool(sl_bot and sl_app), - "running": bool( - self.slack_channel and getattr(self.slack_channel, "_running", False) - ), - "default_working_dir": self.db.get_setting( - "slack_default_working_dir", "~" - ), - "default_channel": self.db.get_setting("slack_default_channel", ""), - "default_user": self.db.get_setting("slack_default_user", ""), - }, - "weixin": _build_weixin_channel_status(self.db, self.weixin_channel), - "feishu": { - "configured": self.db.get_setting("feishu_enabled", "false") == "true", - "running": bool( - self.feishu_channel and getattr(self.feishu_channel, "_running", False) - ), - }, - } - ) - - else: - self._json_response({"error": "not found"}, 404) - - def do_POST(self): - if not self._check_csrf(): - self._drain_body() - self._json_response({"error": "CSRF token missing or invalid"}, 403) - return - parsed = urlparse(self.path) - path = parsed.path - body = self._read_body() - if body is None: - return - - if path == "/api/heartbeats": - heartbeat, error = self._validate_heartbeat_payload(body) - if error: - payload, status = error - self._json_response(payload, status) - return - heartbeat_id = self.db.add_heartbeat(heartbeat) - self._json_response({"id": heartbeat_id, "status": "created"}, 201) - - elif path.startswith("/api/heartbeats/") and path.endswith("/run-now"): - hid = int(path.split("/")[3]) - try: - self.scheduler.trigger_heartbeat_now(hid) - except ValueError as e: - status = 404 if "not found" in str(e) else 409 - self._json_response({"error": str(e)}, status) - return - self._json_response({"status": "scheduled"}) - - elif path.startswith("/api/heartbeats/") and path.endswith("/pause"): - hid = int(path.split("/")[3]) - try: - self.scheduler.pause_heartbeat(hid) - except ValueError as e: - self._json_response({"error": str(e)}, 404) - return - self._json_response({"status": "paused"}) - - elif path.startswith("/api/heartbeats/") and path.endswith("/resume"): - hid = int(path.split("/")[3]) - try: - self.scheduler.resume_heartbeat(hid) - except ValueError as e: - self._json_response({"error": str(e)}, 404) - return - self._json_response({"status": "resumed"}) - - elif path == "/api/skills/sweep": - # Manual "扫一遍" — runs in the background (single-threaded server). - # Always available, independent of the skill_library_enabled toggle. - started = self.scheduler.trigger_skill_sweep( - body.get("agent"), full=bool(body.get("full", True)) - ) - if not started: - self._json_response({"error": "sweep already running"}, 409) - return - self._json_response({"status": "started"}) - - elif path.startswith("/api/skill-patterns/") and path.endswith("/draft"): - pid = int(path.split("/")[3]) - if not self.scheduler.trigger_skill_draft(pid, body.get("agent")): - self._json_response({"error": "pattern not found"}, 404) - return - self._json_response({"status": "drafting"}) - - elif path.startswith("/api/skill-patterns/") and path.endswith("/approve"): - pid = int(path.split("/")[3]) - draft = self.db.get_skill_draft(pid) - name = body.get("name") or (draft or {}).get("name", "") - description = body.get("description") - if description is None: - description = (draft or {}).get("description", "") - skill_body = body.get("body") or (draft or {}).get("body", "") - try: - skill = self.scheduler.approve_skill(pid, name, description, skill_body) - except ValueError as e: - status = 404 if "not found" in str(e) else 400 - self._json_response({"error": str(e)}, status) - return - self._json_response({"status": "approved", "skill": skill}) - - elif path.startswith("/api/skill-patterns/") and path.endswith("/dismiss"): - pid = int(path.split("/")[3]) - try: - self.scheduler.dismiss_skill_pattern(pid) - except ValueError as e: - self._json_response({"error": str(e)}, 404) - return - self._json_response({"status": "dismissed"}) - - elif path == "/api/tasks": - # ── Input validation ────────────────────────────────────── - prompt = body.get("prompt", "") - if not prompt or not prompt.strip(): - self._json_response({"error": "prompt cannot be empty", "field": "prompt"}, 400) - return - - working_dir = body.get("working_dir", ".") - if working_dir and working_dir != ".": - expanded = os.path.expanduser(working_dir) - if not os.path.isdir(expanded): - self._json_response( - { - "error": f"working_dir does not exist or is not a directory: {working_dir}", - "field": "working_dir", - }, - 400, - ) - return - - schedule_type = body.get("schedule_type", "immediate") - cron_expr = body.get("cron_expr") - if schedule_type == "cron": - if not cron_expr or not cron_expr.strip(): - self._json_response( - {"error": "cron_expr is required for cron schedule", "field": "cron_expr"}, - 400, - ) - return - if not croniter.is_valid(cron_expr): - self._json_response( - {"error": f"invalid cron expression: {cron_expr}", "field": "cron_expr"}, - 400, - ) - return - # ───────────────────────────────────────────────────────── - - prompt_images = body.get("prompt_images", []) - if isinstance(prompt_images, str): - try: - prompt_images = json.loads(prompt_images) - except (json.JSONDecodeError, ValueError): - prompt_images = [] - - # Parse image_paths - image_paths = body.get("image_paths", []) - if isinstance(image_paths, str): - try: - image_paths = json.loads(image_paths) - except (json.JSONDecodeError, ValueError): - image_paths = [] - if not isinstance(image_paths, list): - image_paths = [] - - # Parse depends_on: accept list of ints or list of {task_id, inject_result} - depends_on_raw = body.get("depends_on", []) - depends_on = [] - if isinstance(depends_on_raw, list): - for item in depends_on_raw: - if isinstance(item, int): - depends_on.append({"task_id": item, "inject_result": False}) - elif isinstance(item, dict) and "task_id" in item: - depends_on.append( - { - "task_id": int(item["task_id"]), - "inject_result": bool(item.get("inject_result", False)), - } - ) - # Shorthand: global inject_result flag applies to all deps if not per-dep - if body.get("inject_result") and depends_on: - for d in depends_on: - d["inject_result"] = True - - task = Task( - title=body.get("title", "Untitled"), - prompt=body["prompt"], - working_dir=body.get("working_dir", "."), - schedule_type=ScheduleType(body.get("schedule_type", "immediate")), - cron_expr=body.get("cron_expr"), - delay_seconds=body.get("delay_seconds"), - next_run_at=body.get("next_run_at"), # Allow setting next_run_at directly - max_runs=body.get("max_runs"), - tags=body.get("tags", ""), - agent=body.get("agent") or self.db.get_setting("default_agent", DEFAULT_AGENT), - prompt_images=prompt_images, - image_paths=image_paths, - dag_id=body.get("dag_id"), - ) - task_id = self.scheduler.submit_task(task, depends_on=depends_on) - self._json_response({"id": task_id, "status": "created"}, 201) - - elif path == "/api/settings": - for key, value in body.items(): - self.db.set_setting(key, str(value)) - self._json_response({"status": "updated"}) - - elif path == "/api/feishu/settings": - logger.info("POST /api/feishu/settings - updating Feishu settings") - allowed = { - "feishu_app_id", - "feishu_app_secret", - "feishu_default_chat_id", - "feishu_default_working_dir", - "feishu_enabled", - } - for key, value in body.items(): - if key in allowed: - # Mask sensitive values in logs - display_value = ( - value[:8] + "..." - if key in ("feishu_app_id", "feishu_app_secret") - else value - ) - logger.debug(f" Setting {key} = {display_value}") - self.db.set_setting(key, str(value)) - # Restart the Feishu channel with new credentials - logger.info("Restarting Feishu channel with new settings...") - if self.__class__.feishu_channel: - logger.info("Stopping existing channel...") - self.__class__.feishu_channel.stop() - self.__class__.feishu_channel = None - if FEISHU_CHANNEL_AVAILABLE and body.get("feishu_enabled", "").lower() == "true": - channel = FeishuChannel( - bus=self.__class__.bus, - db=self.db, - scheduler=self.__class__.scheduler, - ) - logger.info("Starting new Feishu channel (enabled)...") - channel.start() - self.__class__.feishu_channel = channel - else: - logger.info("Feishu channel disabled, not creating") - logger.info("Feishu settings updated successfully") - self._json_response({"status": "updated"}) - - elif path == "/api/channels/settings": - logger.info("POST /api/channels/settings - updating channel settings") - allowed = { - "telegram_bot_token", - "telegram_allowed_users", - "telegram_default_working_dir", - "telegram_enabled", - "telegram_default_chat_id", - "slack_bot_token", - "slack_app_token", - "slack_default_working_dir", - "slack_default_channel", - "slack_default_user", - "slack_enabled", - "weixin_default_working_dir", - "weixin_base_url", - "weixin_account_id", - "weixin_enabled", - } - for key, value in body.items(): - if key in allowed: - # Mask sensitive values in logs - display_value = ( - value[:8] + "..." if "token" in key or "secret" in key else value - ) - logger.debug(f" Setting {key} = {display_value}") - self.db.set_setting(key, str(value)) - - # ── Restart Telegram channel ── - tg_enabled = ( - body.get("telegram_enabled") or self.db.get_setting("telegram_enabled", "false") - ) == "true" - if self.__class__.telegram_channel: - logger.info("Stopping existing Telegram channel...") - self.__class__.telegram_channel.stop() - self.__class__.telegram_channel = None - if tg_enabled and TELEGRAM_CHANNEL_AVAILABLE: - tg_token = self.db.get_setting("telegram_bot_token", "") or os.environ.get( - "TELEGRAM_BOT_TOKEN", "" - ) - tg_allowed = self.db.get_setting("telegram_allowed_users", "") or os.environ.get( - "TELEGRAM_ALLOWED_USERS", "" - ) - if tg_token: - logger.info("Starting Telegram channel with new settings...") - ch = create_telegram_channel( - self.db, - self.__class__.scheduler, - bus=self.__class__.bus, - token=tg_token, - allowed_users_str=tg_allowed, - ) - if ch: - ch.start() - self.__class__.telegram_channel = ch - logger.info("Telegram channel started") - else: - logger.error("Failed to create Telegram channel") - else: - logger.warning("Telegram enabled but no bot token set") - else: - logger.info("Telegram channel disabled") - - # ── Restart Slack channel ── - sl_enabled = ( - body.get("slack_enabled") or self.db.get_setting("slack_enabled", "false") - ) == "true" - if self.__class__.slack_channel: - logger.info("Stopping existing Slack channel...") - self.__class__.slack_channel.stop() - self.__class__.slack_channel = None - if sl_enabled and SLACK_CHANNEL_AVAILABLE: - sl_bot = self.db.get_setting("slack_bot_token", "") or os.environ.get( - "SLACK_BOT_TOKEN", "" - ) - sl_app = self.db.get_setting("slack_app_token", "") or os.environ.get( - "SLACK_APP_TOKEN", "" - ) - if sl_bot and sl_app: - logger.info("Starting Slack channel with new settings...") - ch = SlackChannel( - bus=self.__class__.bus, - db=self.db, - scheduler=self.__class__.scheduler, - bot_token=sl_bot, - app_token=sl_app, - ) - ch.start() - self.__class__.slack_channel = ch - logger.info("Slack channel started") - else: - logger.warning("Slack enabled but missing tokens") - else: - logger.info("Slack channel disabled") - - # ── Restart Weixin channel ── - wx_enabled = ( - body.get("weixin_enabled") or self.db.get_setting("weixin_enabled", "false") - ) == "true" - if self.__class__.weixin_channel: - logger.info("Stopping existing Weixin channel...") - self.__class__.weixin_channel.stop() - self.__class__.weixin_channel = None - if wx_enabled and WEIXIN_CHANNEL_AVAILABLE: - logger.info("Starting Weixin channel with new settings...") - ch = WeixinChannel( - bus=self.__class__.bus, - db=self.db, - scheduler=self.__class__.scheduler, - ) - ch.start() - self.__class__.weixin_channel = ch - logger.info("Weixin channel started") - else: - logger.info("Weixin channel disabled") - - logger.info("Channel settings updated successfully") - self._json_response({"status": "updated"}) - - elif path == "/api/channels/weixin/action": - action = (body.get("action") or "").strip().lower() - if not self.__class__.weixin_channel: - print( - f"[Weixin] action={action!r} rejected: weixin_channel is None (not enabled/started)" - ) - self._json_response({"error": "weixin channel not running"}, 400) - return - if action in {"login", "reconnect"}: - self.__class__.weixin_channel.request_login() - self._json_response({"status": "ok", "action": action}) - elif action == "logout": - self.__class__.weixin_channel.request_logout() - self._json_response({"status": "ok", "action": action}) - else: - self._json_response({"error": "unsupported action"}, 400) - - elif path == "/api/dag": - # Batch-create a full DAG in one call. - # Body: {dag_id, tasks: [{ref, title, prompt, working_dir, schedule_type, depends_on_refs, inject_result, ...}]} - dag_id = body.get("dag_id", f"dag-{int(datetime.now().timestamp())}") - task_defs = body.get("tasks", []) - if not task_defs: - self._json_response({"error": "tasks list is required"}, 400) - return - - ref_to_id: dict[str, int] = {} - results = {} - for tdef in task_defs: - ref = tdef.get("ref", str(len(ref_to_id))) - depends_on_refs = tdef.get("depends_on_refs", []) - # Resolve refs → task_ids (upstream must already be created) - depends_on = [] - for r in depends_on_refs: - if r not in ref_to_id: - self._json_response( - {"error": f"ref '{r}' not found — declare tasks in topological order"}, - 400, - ) - return - depends_on.append( - { - "task_id": ref_to_id[r], - "inject_result": bool(tdef.get("inject_result", False)), - } - ) - - prompt_images = tdef.get("prompt_images", []) - if isinstance(prompt_images, str): - try: - prompt_images = json.loads(prompt_images) - except (json.JSONDecodeError, ValueError): - prompt_images = [] - - t = Task( - title=tdef.get("title", tdef.get("prompt", "")[:60]), - prompt=tdef.get("prompt", ""), - working_dir=tdef.get("working_dir", "."), - schedule_type=ScheduleType(tdef.get("schedule_type", "immediate")), - cron_expr=tdef.get("cron_expr"), - delay_seconds=tdef.get("delay_seconds"), - next_run_at=tdef.get("next_run_at"), - max_runs=tdef.get("max_runs"), - tags=tdef.get("tags", ""), - agent=tdef.get("agent") or self.db.get_setting("default_agent", DEFAULT_AGENT), - prompt_images=prompt_images, - dag_id=dag_id, - ) - task_id = self.scheduler.submit_task(t, depends_on=depends_on) - ref_to_id[ref] = task_id - results[ref] = task_id - - self._json_response({"dag_id": dag_id, "task_ids": results}, 201) - - elif path.startswith("/api/tasks/") and path.endswith("/dependencies"): - # POST /api/tasks/:id/dependencies — add a dependency to an existing task - tid = int(path.split("/")[3]) - dep_task_id = body.get("depends_on_task_id") - if not dep_task_id: - self._json_response({"error": "depends_on_task_id required"}, 400) - return - task = self.db.get_task(tid) - upstream = self.db.get_task(int(dep_task_id)) - if not task or not upstream: - self._json_response({"error": "task not found"}, 404) - return - inject_result = bool(body.get("inject_result", False)) - should_block = upstream["status"] != "completed" and task["status"] in ( - "pending", - "scheduled", - ) - # Insert dependency and (if needed) update task status atomically. - with self.db.transaction(): - self.db.conn.execute( - """ - INSERT OR IGNORE INTO task_dependencies (task_id, depends_on_task_id, inject_result) - VALUES (?, ?, ?) - """, - (tid, int(dep_task_id), 1 if inject_result else 0), - ) - if should_block: - self.db.conn.execute( - "UPDATE tasks SET status = ?, updated_at = ? WHERE id = ?", - ("blocked", datetime.now().isoformat(), tid), - ) - if should_block: - self.scheduler._notify(tid) - self._json_response({"status": "added"}) - - elif path.startswith("/api/tasks/") and path.endswith("/cancel"): - tid = int(path.split("/")[3]) - self.scheduler.cancel_task(tid) - self._json_response({"status": "cancelled"}) - - elif path.startswith("/api/tasks/") and path.endswith("/retry"): - tid = int(path.split("/")[3]) - self.scheduler.retry_task(tid) - self._json_response({"status": "retrying"}) - - elif path.startswith("/api/tasks/") and path.endswith("/respond"): - tid = int(path.split("/")[3]) - answer = body.get("answer", "") - task = self.db.get_task(tid) - if task: - self.db.update_task( - tid, status="pending", prompt=answer, answer=answer, question=None, error=None - ) - self._json_response({"status": "responding"}) - else: - self._json_response({"error": "not found"}, 404) - - elif path.startswith("/api/tasks/") and path.endswith("/resume"): - tid = int(path.split("/")[3]) - message = body.get("message", "").strip() - task = self.db.get_task(tid) - if not task: - self._json_response({"error": "not found"}, 404) - elif not message: - self._json_response({"error": "message required"}, 400) - elif not task.get("session_id"): - self._json_response({"error": "no session_id — cannot resume"}, 400) - else: - self.db.update_task( - tid, status="pending", prompt=message, result=None, error=None, question=None - ) - self._json_response({"status": "resuming"}) - - else: - self._json_response({"error": "not found"}, 404) - - def do_PUT(self): - if not self._check_csrf(): - self._drain_body() - self._json_response({"error": "CSRF token missing or invalid"}, 403) - return - parsed = urlparse(self.path) - path = parsed.path - body = self._read_body() - if body is None: - return - - if path == "/api/settings": - for key, value in body.items(): - self.db.set_setting(key, str(value)) - self._json_response({"status": "updated"}) - - elif path.startswith("/api/skills/"): - try: - sid = int(path.split("/")[3]) - except (ValueError, IndexError): - self._json_response({"error": "invalid skill id"}, 400) - return - enabled = bool(body.get("enabled", True)) - try: - skill = self.scheduler.toggle_skill(sid, enabled) - except ValueError as e: - self._json_response({"error": str(e)}, 404) - return - self._json_response({"status": "updated", "skill": skill}) - - elif path.startswith("/api/heartbeats/") and path.count("/") == 3: - try: - hid = int(path.split("/")[3]) - except (ValueError, IndexError): - self._json_response({"error": "invalid heartbeat id"}, 400) - return - heartbeat = self.db.get_heartbeat(hid) - if not heartbeat: - self._json_response({"error": "not found"}, 404) - return - validated, error = self._validate_heartbeat_payload(body, existing=heartbeat) - if error: - payload, status = error - self._json_response(payload, status) - return - updates = { - "name": validated.name, - "enabled": 1 if validated.enabled else 0, - "working_dir": validated.working_dir, - "schedule_type": validated.schedule_type.value, - "cron_expr": validated.cron_expr, - "interval_seconds": validated.interval_seconds, - "check_prompt": validated.check_prompt, - "action_prompt_template": validated.action_prompt_template, - "default_agent": validated.default_agent, - "cooldown_seconds": validated.cooldown_seconds, - "next_run_at": validated.next_run_at, - } - self.db.update_heartbeat(hid, **updates) - self._json_response(self.db.get_heartbeat(hid)) - - elif path.startswith("/api/tasks/") and path.count("/") == 3: - # PUT /api/tasks/{id} — edit a pending/scheduled/blocked task - try: - tid = int(path.split("/")[3]) - except (ValueError, IndexError): - self._json_response({"error": "invalid task id"}, 400) - return - - task = self.db.get_task(tid) - if not task: - self._json_response({"error": "not found"}, 404) - return - - if task["status"] not in ("pending", "scheduled", "blocked"): - self._json_response( - { - "error": f"Cannot edit task with status '{task['status']}'. Only pending, scheduled, or blocked tasks can be edited." - }, - 409, - ) - return - - # ── Validate prompt ── - prompt = body.get("prompt", task["prompt"]) - if not prompt or not prompt.strip(): - self._json_response({"error": "prompt cannot be empty", "field": "prompt"}, 400) - return - - # ── Validate working_dir ── - working_dir = body.get("working_dir", task["working_dir"]) - if working_dir and working_dir != ".": - expanded = os.path.expanduser(working_dir) - if not os.path.isdir(expanded): - self._json_response( - { - "error": f"working_dir does not exist: {working_dir}", - "field": "working_dir", - }, - 400, - ) - return - - # ── Validate schedule_type / cron_expr ── - schedule_type = body.get("schedule_type", task["schedule_type"]) - cron_expr = body.get("cron_expr", task.get("cron_expr")) - if schedule_type == "cron": - if not cron_expr or not cron_expr.strip(): - self._json_response( - {"error": "cron_expr required for cron schedule", "field": "cron_expr"}, 400 - ) - return - if not croniter.is_valid(cron_expr): - self._json_response( - {"error": f"invalid cron expression: {cron_expr}", "field": "cron_expr"}, - 400, - ) - return - - # ── Build updates from editable fields ── - EDITABLE_FIELDS = { - "title", - "prompt", - "working_dir", - "schedule_type", - "cron_expr", - "delay_seconds", - "max_runs", - "tags", - "agent", - "dag_id", - } - updates = {} - for field in EDITABLE_FIELDS: - if field in body: - updates[field] = body[field] - - # Handle prompt_images - if "prompt_images" in body: - pi = body["prompt_images"] - if isinstance(pi, str): - try: - pi = json.loads(pi) - except (json.JSONDecodeError, ValueError): - pi = [] - updates["prompt_images"] = json.dumps(pi, ensure_ascii=False) - - # Handle image_paths - if "image_paths" in body: - ip = body["image_paths"] - if isinstance(ip, str): - try: - ip = json.loads(ip) - except (json.JSONDecodeError, ValueError): - ip = [] - if not isinstance(ip, list): - ip = [] - updates["image_paths"] = json.dumps(ip, ensure_ascii=False) - - # ── Recalculate status and next_run_at based on schedule_type ── - new_stype = updates.get("schedule_type", task["schedule_type"]) - if new_stype == "immediate": - updates["status"] = "pending" - updates["next_run_at"] = None - updates["cron_expr"] = None - updates["delay_seconds"] = None - elif new_stype == "delayed": - updates["status"] = "pending" - updates["next_run_at"] = None # scheduler will calculate - updates["cron_expr"] = None - elif new_stype == "scheduled_at": - nra = body.get("next_run_at", task.get("next_run_at")) - if not nra: - self._json_response( - {"error": "next_run_at required for scheduled_at", "field": "next_run_at"}, - 400, - ) - return - updates["next_run_at"] = nra - updates["status"] = "scheduled" - updates["cron_expr"] = None - updates["delay_seconds"] = None - elif new_stype == "cron": - new_cron = updates.get("cron_expr", task.get("cron_expr")) - nxt = croniter(new_cron, datetime.now()).get_next(datetime) - updates["next_run_at"] = nxt.isoformat() - updates["status"] = "scheduled" - updates["delay_seconds"] = None - - # ── Handle dependency updates ── - if "depends_on" in body: - self.db.clear_dependencies(tid) - dep_list = [] - depends_on_raw = body["depends_on"] - if isinstance(depends_on_raw, list): - for item in depends_on_raw: - if isinstance(item, int): - dep_list.append({"task_id": item, "inject_result": False}) - elif isinstance(item, dict) and "task_id" in item: - dep_list.append( - { - "task_id": int(item["task_id"]), - "inject_result": bool(item.get("inject_result", False)), - } - ) - if dep_list: - self.db.add_dependencies_batch(tid, dep_list) - # Check if any deps are unmet → set blocked - for dep in dep_list: - upstream = self.db.get_task(dep["task_id"]) - if not upstream or upstream["status"] != "completed": - updates["status"] = "blocked" - break - - if updates: - self.db.update_task(tid, **updates) - - updated_task = self.db.get_task(tid) - # Include dependencies in response - updated_task["dependencies"] = self.db.get_dependencies(tid) - self._json_response(updated_task) - - else: - self._json_response({"error": "not found"}, 404) - - def do_DELETE(self): - if not self._check_csrf(): - self._drain_body() - self._json_response({"error": "CSRF token missing or invalid"}, 403) - return - parsed = urlparse(self.path) - parts = parsed.path.split("/") - # DELETE /api/tasks/:id/dependencies/:dep_id - if len(parts) == 6 and parts[2] == "tasks" and parts[4] == "dependencies": - tid = int(parts[3]) - dep_id = int(parts[5]) - self.db.remove_dependency(tid, dep_id) - self._json_response({"status": "removed"}) - elif parsed.path.startswith("/api/heartbeats/"): - hid = int(parsed.path.split("/")[3]) - self.db.delete_heartbeat(hid) - self._json_response({"status": "deleted"}) - elif parsed.path.startswith("/api/skills/"): - try: - sid = int(parsed.path.split("/")[3]) - except (ValueError, IndexError): - self._json_response({"error": "invalid skill id"}, 400) - return - try: - self.scheduler.remove_skill(sid) - except ValueError as e: - self._json_response({"error": str(e)}, 404) - return - self._json_response({"status": "deleted"}) - elif parsed.path.startswith("/api/tasks/"): - tid = int(parsed.path.split("/")[3]) - self.db.delete_task(tid) - self._json_response({"status": "deleted"}) - else: - self._json_response({"error": "not found"}, 404) - - MAX_BODY_SIZE = 10 * 1024 * 1024 # 10 MB - - def _drain_body(self, length: Optional[int] = None): - """Consume and discard the request body so an early rejection doesn't - desync the keep-alive connection and surface to the client as a - connection reset instead of the intended response.""" - try: - length = int(self.headers.get("Content-Length", 0)) if length is None else length - except (TypeError, ValueError): - return - remaining = max(length, 0) - while remaining > 0: - chunk = self.rfile.read(min(remaining, 65536)) - if not chunk: - break - remaining -= len(chunk) - - def _read_body(self): - """Read and JSON-parse the request body. - - Returns the parsed dict, or None if the request was rejected (in which - case a response has already been sent — the caller must return). The - declared body is always consumed before responding so the connection - stays in sync. - """ - try: - length = int(self.headers.get("Content-Length", 0)) - except (TypeError, ValueError): - length = 0 - if length > self.MAX_BODY_SIZE: - self._drain_body(length) - self._json_response({"error": "request body too large"}, 413) - return None - raw = self.rfile.read(length) if length > 0 else b"" - if not raw: - return {} - try: - return json.loads(raw) - except json.JSONDecodeError: - self._json_response({"error": "invalid JSON body"}, 400) - return None - - def _json_response(self, data, status=200): - try: - self.send_response(status) - self._cors_headers() - self.send_header("Content-Type", "application/json") - self.end_headers() - self.wfile.write(json.dumps(data, default=str).encode()) - except BrokenPipeError: - pass - - def _cors_headers(self): - origin = self.headers.get("Origin", "") - # Allow the exact origin when it matches; fall back to no header so - # the browser blocks it — never reflect an arbitrary untrusted origin. - if self._is_allowed_origin(origin): - self.send_header("Access-Control-Allow-Origin", origin) - self.send_header("Vary", "Origin") - self.send_header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS") - self.send_header("Access-Control-Allow-Headers", "Content-Type, X-CSRF-Token") - - @staticmethod - def _is_allowed_origin(origin: str) -> bool: - """Return True for file:// (Electron production) and localhost origins.""" - if origin == "null": # Electron / file:// - return True - if not origin: - return True # same-origin request with no Origin header - # Accept http://localhost or http://localhost: - if origin == "http://localhost" or origin.startswith("http://localhost:"): - return True - return False - - def _check_csrf(self) -> bool: - """Validate the CSRF token on state-changing requests. - - Returns True if the request is allowed, False if it should be rejected. - Requests without an Origin header (e.g. curl from localhost, the skill - API client) skip the CSRF check so programmatic access still works. - """ - origin = self.headers.get("Origin", "") - # Only enforce CSRF for browser-originated cross-origin requests. - # Requests with no Origin header come from non-browser clients - # (curl, the agentforge skill) — skip the check. - if not origin: - return True - token = self.headers.get("X-CSRF-Token", "") - return secrets.compare_digest(token, _CSRF_TOKEN) - - def log_message(self, format, *args): - # Suppress default logging - pass - - -class QuietHTTPServer(HTTPServer): - allow_reuse_address = True - - def handle_error(self, request, client_address): - import sys - - if isinstance(sys.exc_info()[1], BrokenPipeError): - return - super().handle_error(request, client_address) - - -def _kill_stale_process_on_port(port: int): - """Kill any leftover process occupying the port (e.g. orphaned from a previous run).""" - import socket - - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - try: - sock.settimeout(1) - sock.connect(("127.0.0.1", port)) - sock.close() - except (ConnectionRefusedError, OSError): - return # port is free - # Port is occupied — try to find and kill the process - try: - result = subprocess.run( - ["lsof", "-ti", f":{port}"], capture_output=True, text=True, timeout=5 - ) - pids = [] - for pid_str in result.stdout.strip().split("\n"): - pid_str = pid_str.strip() - if pid_str and pid_str.isdigit(): - pid = int(pid_str) - if pid != os.getpid(): - pids.append(pid) - logger.info(f"Killing stale process {pid} on port {port}") - os.kill(pid, signal.SIGTERM) - # Wait for processes to exit, then SIGKILL if still alive - for _ in range(10): - time.sleep(0.3) - pids = [p for p in pids if _pid_alive(p)] - if not pids: - return - for pid in pids: - logger.warning(f"Force-killing stale process {pid}") - os.kill(pid, signal.SIGKILL) - time.sleep(0.3) - except Exception as e: - logger.warning(f"Could not clean up port {port}: {e}") - - -def _pid_alive(pid: int) -> bool: - try: - os.kill(pid, 0) - return True - except OSError: - return False - - -def run_server(port: int = 9712): - _kill_stale_process_on_port(port) - - logger.info("Initializing database...") - db = TaskDB() - - # Initialise MessageBus and channels - logger.info("Initializing MessageBus...") - bus = MessageBus() - ui_channel = UIChannel(bus=bus, db=db) - ui_channel.start() - - logger.info("Initializing scheduler...") - scheduler = TaskScheduler(db, on_task_update=lambda tid: None, bus=bus) - - # ── Feishu channel ───────────────────────────────────────────────────── - feishu_channel = None - feishu_enabled = db.get_setting("feishu_enabled", "false").lower() == "true" - logger.info(f"Feishu enabled: {feishu_enabled}") - if FEISHU_CHANNEL_AVAILABLE and feishu_enabled: - logger.info("Starting Feishu channel...") - feishu_channel = FeishuChannel(bus=bus, db=db, scheduler=scheduler) - feishu_channel.start() - else: - logger.info("Feishu channel disabled") - # ───────────────────────────────────────────────────────────────────── - - # ── Telegram channel ────────────────────────────────────────────────── - telegram_channel = None - tg_enabled = db.get_setting("telegram_enabled", "false") == "true" - tg_token = db.get_setting("telegram_bot_token", "") or os.environ.get("TELEGRAM_BOT_TOKEN", "") - tg_allowed = db.get_setting("telegram_allowed_users", "") or os.environ.get( - "TELEGRAM_ALLOWED_USERS", "" - ) - # Auto-enable if env var set but settings not yet configured - if not tg_enabled and os.environ.get("TELEGRAM_BOT_TOKEN"): - tg_enabled = True - if TELEGRAM_CHANNEL_AVAILABLE and tg_enabled and tg_token: - logger.info("Starting Telegram channel...") - telegram_channel = create_telegram_channel( - db, - scheduler, - bus=bus, - token=tg_token, - allowed_users_str=tg_allowed, - ) - if telegram_channel: - telegram_channel.start() - else: - logger.info("Telegram channel disabled") - # ───────────────────────────────────────────────────────────────────── - - # ── Slack channel ───────────────────────────────────────────────────── - slack_channel = None - sl_enabled = db.get_setting("slack_enabled", "false") == "true" - sl_bot = db.get_setting("slack_bot_token", "") or os.environ.get("SLACK_BOT_TOKEN", "") - sl_app = db.get_setting("slack_app_token", "") or os.environ.get("SLACK_APP_TOKEN", "") - # Auto-enable if env vars set but settings not yet configured - if not sl_enabled and os.environ.get("SLACK_BOT_TOKEN") and os.environ.get("SLACK_APP_TOKEN"): - sl_enabled = True - if SLACK_CHANNEL_AVAILABLE and sl_enabled and sl_bot and sl_app: - logger.info("Starting Slack channel...") - slack_channel = SlackChannel( - bus=bus, - db=db, - scheduler=scheduler, - bot_token=sl_bot, - app_token=sl_app, - ) - slack_channel.start() - else: - logger.info("Slack channel disabled") - # ───────────────────────────────────────────────────────────────────── - - # ── Weixin channel ─────────────────────────────────────────────────── - weixin_channel = None - wx_enabled = db.get_setting("weixin_enabled", "false") == "true" - if WEIXIN_CHANNEL_AVAILABLE and wx_enabled: - logger.info("Starting Weixin channel...") - weixin_channel = WeixinChannel( - bus=bus, - db=db, - scheduler=scheduler, - ) - weixin_channel.start() - else: - logger.info("Weixin channel disabled") - # ───────────────────────────────────────────────────────────────────── - - scheduler.start() - - TaskAPIHandler.scheduler = scheduler - TaskAPIHandler.db = db - TaskAPIHandler.feishu_channel = feishu_channel - TaskAPIHandler.bus = bus - TaskAPIHandler.ui_channel = ui_channel - TaskAPIHandler.telegram_channel = telegram_channel - TaskAPIHandler.slack_channel = slack_channel - TaskAPIHandler.weixin_channel = weixin_channel - - server = QuietHTTPServer(("127.0.0.1", port), TaskAPIHandler) - logger.info(f"API server running on http://127.0.0.1:{port}") - logger.info(f"Database at {db.db_path}") - - def shutdown(sig, frame): - logger.info("Shutting down...") - if feishu_channel: - logger.info("Stopping Feishu channel...") - feishu_channel.stop() - if telegram_channel: - logger.info("Stopping Telegram channel...") - telegram_channel.stop() - if slack_channel: - logger.info("Stopping Slack channel...") - slack_channel.stop() - logger.info("Stopping scheduler...") - scheduler.stop() - logger.info("Closing database...") - db.conn.close() - logger.info("Shutting down server...") - server.shutdown() - sys.exit(0) - - signal.signal(signal.SIGINT, shutdown) - signal.signal(signal.SIGTERM, shutdown) - - server.serve_forever() - - -if __name__ == "__main__": - port = int(sys.argv[1]) if len(sys.argv) > 1 else 9712 - logger.info( - f"=== Python backend starting at {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} on port {port} ===" - ) - run_server(port) -# Test comment for hot reload 2026年 2月13日 星期五 23时08分26秒 CST -# Hot reload test at 23:09:11 diff --git a/taskboard.spec b/taskboard.spec deleted file mode 100644 index c07e15e..0000000 --- a/taskboard.spec +++ /dev/null @@ -1,38 +0,0 @@ -# -*- mode: python ; coding: utf-8 -*- - - -a = Analysis( - ['taskboard.py'], - pathex=[], - binaries=[], - datas=[('vendor/skill-creator', 'vendor/skill-creator'), ('channels/weixin_bridge', 'channels/weixin_bridge')], - hiddenimports=['croniter', 'dateutil', 'pytz'], - hookspath=[], - hooksconfig={}, - runtime_hooks=[], - excludes=[], - noarchive=False, - optimize=0, -) -pyz = PYZ(a.pure) - -exe = EXE( - pyz, - a.scripts, - a.binaries, - a.datas, - [], - name='taskboard', - debug=False, - bootloader_ignore_signals=False, - strip=False, - upx=True, - upx_exclude=[], - runtime_tmpdir=None, - console=True, - disable_windowed_traceback=False, - argv_emulation=False, - target_arch=None, - codesign_identity=None, - entitlements_file=None, -) diff --git a/taskboard_bus.py b/taskboard_bus.py deleted file mode 100644 index 6e16431..0000000 --- a/taskboard_bus.py +++ /dev/null @@ -1,410 +0,0 @@ -""" -AgentForge Message Bus -===================== - -架构设计 --------- -MessageBus 是 AgentForge 的消息中枢,解耦消息来源(channels)与任务执行器。 - - ┌─────────────────────────────────┐ - │ MessageBus │ - │ │ - FeishuChannel ──► │ inbound_queue (Queue) │──► TaskScheduler - UIChannel ──► │ │ - SlackChannel ──► │ outbound_queue (Queue) │◄── TaskScheduler._notify() - ... ──► │ │ - └──────────┬───────────────────────┘ - │ subscribe_outbound() - ▼ - Channel.send(OutboundMessage) - -核心概念: -- InboundMessage: 任何来源(Feishu、HTTP UI、Slack 等)发向 bus 的消息, - 触发新建任务或恢复现有任务。 -- OutboundMessage: 任务执行完毕后由 Scheduler 发布到 bus 的结果通知, - 由各注册的 Channel 分发给对应来源(Feishu 卡片、UI 轮询等)。 -- Channel (ABC): 代表一个通信通道。 - - send(OutboundMessage): 将结果推送回外部系统。 - - start(): 开启后台监听(如 WebSocket 长连接)。 - - stop(): 关闭连接。 - - notify_task(task_id): 兼容旧式直接回调接口(调用 send)。 -- UIChannel: 包装现有 HTTP REST API,保持向后兼容。 - -线程模型: -- MessageBus 使用 threading.Queue(与现有同步线程代码兼容)。 -- 各 Channel 在自己的线程内调用 bus.publish_inbound()。 -- TaskScheduler._notify() 调用 bus.publish_outbound(),同步触发所有 - subscribe_outbound() 注册的回调。 - -向后兼容: -- Channel.notify_task(task_id) 默认实现通过 db 读取任务并调用 send(), - 保持与旧式 feishu_bridge.notify_task() 相同的调用约定。 -- UIChannel 封装原有 HTTP handler + TaskScheduler,对外暴露相同接口。 -""" - -import queue -import threading -from abc import ABC, abstractmethod -from dataclasses import dataclass, field -from datetime import datetime -from enum import Enum -from typing import TYPE_CHECKING, Callable, Optional - -if TYPE_CHECKING: - from taskboard import TaskDB - - -# ──────────────────────────── Message Types ──────────────────────────── - - -class InboundMessageType(str, Enum): - """Inbound message 的动作类型。""" - - CREATE_TASK = "create_task" # 创建新任务 - RESUME_TASK = "resume_task" # 恢复已有任务(使用 session_id) - RESPOND_TASK = "respond_task" # 回答任务等待的问题 - CANCEL_TASK = "cancel_task" # 取消任务 - STATUS_QUERY = "status_query" # 查询任务状态 - - -class OutboundMessageType(str, Enum): - """Outbound message 的事件类型。""" - - TASK_COMPLETED = "task_completed" - TASK_FAILED = "task_failed" - TASK_STARTED = "task_started" - TASK_UPDATED = "task_updated" - STATUS_RESPONSE = "status_response" - - -@dataclass -class InboundMessage: - """从某个 Channel 发往 MessageBus 的入站消息。 - - Attributes: - type: 消息动作,见 InboundMessageType。 - source: 来源 channel 名称,如 "feishu"、"ui"、"slack"。 - payload: 消息载荷,内容依 type 而定: - CREATE_TASK -> {"title", "prompt", "working_dir", ...} - RESUME_TASK -> {"task_id", "message"} - RESPOND_TASK -> {"task_id", "answer"} - CANCEL_TASK -> {"task_id"} - STATUS_QUERY -> {"task_id"} - reply_to: 可选回复目标(如 Feishu chat_id / open_id),Channel 自行解释。 - metadata: 扩展字段,Channel 可存放任意上下文(如 Feishu message_id)。 - created_at: 消息创建时间(UTC ISO 格式)。 - """ - - type: InboundMessageType - source: str - payload: dict = field(default_factory=dict) - reply_to: Optional[str] = None - metadata: dict = field(default_factory=dict) - created_at: str = field(default_factory=lambda: datetime.utcnow().isoformat()) - - -@dataclass -class OutboundMessage: - """Scheduler 完成任务后发布到 MessageBus 的出站消息。 - - Attributes: - type: 事件类型,见 OutboundMessageType。 - task_id: 关联任务 ID。 - payload: 事件载荷,如 {"status", "result", "error", "title"}。 - source_msg: 触发此结果的原始 InboundMessage(可选,用于关联回复)。 - metadata: 扩展字段。 - created_at: 消息创建时间(UTC ISO 格式)。 - """ - - type: OutboundMessageType - task_id: int - payload: dict = field(default_factory=dict) - source_msg: Optional[InboundMessage] = None - metadata: dict = field(default_factory=dict) - created_at: str = field(default_factory=lambda: datetime.utcnow().isoformat()) - - -# ──────────────────────────── Message Bus ──────────────────────────── - - -class MessageBus: - """AgentForge 的消息总线。 - - 提供两个线程安全的队列: - - inbound_queue: 各 Channel 向 Scheduler 发送任务请求。 - - outbound_queue: Scheduler 向各 Channel 发布任务结果通知。 - - 使用 threading.Queue 以便与现有同步线程代码无缝集成。 - """ - - def __init__(self, maxsize: int = 0): - """ - Args: - maxsize: 队列容量上限,0 表示无限制。 - """ - self.inbound_queue: queue.Queue[InboundMessage] = queue.Queue(maxsize=maxsize) - self.outbound_queue: queue.Queue[OutboundMessage] = queue.Queue(maxsize=maxsize) - self._outbound_listeners: list[Callable[[OutboundMessage], None]] = [] - - # ── inbound helpers ────────────────────────────────────────── - - def publish_inbound(self, msg: InboundMessage) -> None: - """Channel 调用此方法将入站消息放入队列。""" - self.inbound_queue.put_nowait(msg) - - def get_inbound( - self, block: bool = True, timeout: Optional[float] = None - ) -> Optional[InboundMessage]: - """Scheduler 调用此方法取出下一条入站消息(可选使用)。""" - try: - return self.inbound_queue.get(block=block, timeout=timeout) - except queue.Empty: - return None - - # ── outbound helpers ───────────────────────────────────────── - - def publish_outbound(self, msg: OutboundMessage) -> None: - """Scheduler 调用此方法发布任务结果。 - 消息放入 outbound_queue 并同步触发所有注册的监听回调。 - """ - self.outbound_queue.put_nowait(msg) - for listener in self._outbound_listeners: - try: - listener(msg) - except Exception as e: - print(f"[MessageBus] outbound listener error: {e}") - - def subscribe_outbound(self, listener: Callable[[OutboundMessage], None]) -> None: - """注册 outbound 监听器(如 FeishuChannel 的通知函数)。""" - self._outbound_listeners.append(listener) - - def unsubscribe_outbound(self, listener: Callable[[OutboundMessage], None]) -> None: - """移除 outbound 监听器。""" - try: - self._outbound_listeners.remove(listener) - except ValueError: - pass - - def get_outbound( - self, block: bool = True, timeout: Optional[float] = None - ) -> Optional[OutboundMessage]: - """Channel 轮询模式下调用此方法取出出站消息。""" - try: - return self.outbound_queue.get(block=block, timeout=timeout) - except queue.Empty: - return None - - -# ──────────────────────────── Channel ABC ──────────────────────────── - - -class Channel(ABC): - """消息通道抽象基类。 - - 每个具体 Channel 代表一个外部系统(HTTP UI、Feishu、Slack 等)。 - Channel 负责: - 1. 从外部系统接收消息,封装为 InboundMessage,放入 bus.inbound_queue。 - 2. 通过 send() 将任务结果推送回外部系统。 - - 兼容旧式调用:notify_task(task_id) 读取 DB 并调用 send(), - 保持与原 FeishuBridge.notify_task() 相同的调用约定。 - """ - - def __init__(self, name: str, bus: MessageBus, db: "TaskDB"): - self.name = name - self.bus = bus - self.db = db - self._running = False - - @abstractmethod - def send(self, msg: OutboundMessage) -> None: - """将出站消息推送给此 channel 对应的外部系统。 - - 例如 FeishuChannel.send() 向 Feishu 发送卡片通知; - UIChannel.send() 写入内存缓存供轮询端点读取。 - """ - ... - - @abstractmethod - def start(self) -> None: - """启动 channel 的后台监听(开始接收外部消息)。""" - ... - - def stop(self) -> None: - """停止 channel(可选覆盖)。""" - self._running = False - - def notify_task(self, task_id: int) -> None: - """兼容旧式直接回调接口。 - - TaskScheduler._notify() 或外部代码可继续调用此方法。 - 默认实现:读取任务状态,构造 OutboundMessage,调用 send()。 - """ - task = self.db.get_task(task_id) - if not task: - return - status = task.get("status", "") - type_map = { - "running": OutboundMessageType.TASK_STARTED, - "completed": OutboundMessageType.TASK_COMPLETED, - "failed": OutboundMessageType.TASK_FAILED, - } - msg_type = type_map.get(status, OutboundMessageType.TASK_UPDATED) - outbound = OutboundMessage( - type=msg_type, - task_id=task_id, - payload={ - "status": status, - "result": task.get("result"), - "error": task.get("error"), - "title": task.get("title"), - }, - ) - self.send(outbound) - - def _make_inbound( - self, - msg_type: InboundMessageType, - payload: dict, - reply_to: Optional[str] = None, - metadata: Optional[dict] = None, - ) -> InboundMessage: - """便捷工厂方法,自动填充 source 字段。""" - return InboundMessage( - type=msg_type, - source=self.name, - payload=payload, - reply_to=reply_to, - metadata=metadata or {}, - ) - - -# ──────────────────────────── UIChannel ──────────────────────────── - - -class UIChannel(Channel): - """HTTP REST API channel(包装现有 TaskAPIHandler + TaskScheduler)。 - - 将来自浏览器 React UI 的 HTTP 请求转换为 InboundMessage 并放入 bus; - 同时将 outbound 事件缓存到内存,供 /api/tasks/{id}/events 轮询端点读取。 - - 当前为桥接层:HTTP handler 仍直接操作 scheduler/db, - 此 Channel 在操作后补发对应的 InboundMessage,完整记录事件流。 - """ - - def __init__(self, bus: MessageBus, db: "TaskDB"): - super().__init__("ui", bus, db) - # outbound 事件缓存:task_id -> list[OutboundMessage] - self._outbound_cache: dict[int, list[OutboundMessage]] = {} - self._cache_lock = threading.Lock() - bus.subscribe_outbound(self._on_outbound) - - def start(self) -> None: - """UI channel 通过 HTTP server 被动接收请求,无需主动轮询。""" - self._running = True - print("[UIChannel] Ready (HTTP REST API)") - - _CACHE_MAX_TASKS = 1000 # max number of task IDs to keep in the outbound cache - - def send(self, msg: OutboundMessage) -> None: - """缓存出站消息,供 HTTP 轮询端点读取。""" - with self._cache_lock: - self._outbound_cache.setdefault(msg.task_id, []).append(msg) - # Evict oldest task entries when the cache grows too large - while len(self._outbound_cache) > self._CACHE_MAX_TASKS: - self._outbound_cache.pop(next(iter(self._outbound_cache))) - - def get_cached_outbound(self, task_id: int) -> list[OutboundMessage]: - """返回指定任务的所有出站事件副本。""" - with self._cache_lock: - return list(self._outbound_cache.get(task_id, [])) - - def notify_task_created( - self, task_id: int, prompt: str, working_dir: str = ".", **kwargs - ) -> None: - """HTTP handler 创建任务后调用,发布 InboundMessage 到 bus。""" - self.bus.publish_inbound( - self._make_inbound( - InboundMessageType.CREATE_TASK, - payload={ - "task_id": task_id, - "prompt": prompt, - "working_dir": working_dir, - **kwargs, - }, - ) - ) - - def notify_task_resumed(self, task_id: int, message: str) -> None: - """HTTP handler 恢复任务后调用。""" - self.bus.publish_inbound( - self._make_inbound( - InboundMessageType.RESUME_TASK, - payload={"task_id": task_id, "message": message}, - ) - ) - - def _on_outbound(self, msg: OutboundMessage) -> None: - """订阅回调:将出站消息写入本地缓存。""" - self.send(msg) - - -# ──────────────────────────── BusAwareSchedulerMixin ──────────────────────────── - - -class BusAwareSchedulerMixin: - """可混入 TaskScheduler 的工具方法,让 _notify() 同时发布到 MessageBus。 - - 使用方式(在 taskboard.py 中,在 TaskScheduler._notify() 末尾追加): - - # 在 run_server() 中: - bus = MessageBus() - scheduler.bus = bus - - # 在 TaskScheduler._notify() 末尾: - if hasattr(self, 'bus') and self.bus: - self._bus_notify(task_id) - """ - - bus: Optional[MessageBus] = None - - def _bus_notify( - self, task_id: int, override_type: "Optional[OutboundMessageType]" = None - ) -> None: - """根据任务状态向 bus 发布对应的 OutboundMessage。 - - override_type: 强制使用指定消息类型(用于 cron 任务重调度场景, - 此时 DB 状态已变为 "scheduled",但本次运行结果应通知为 TASK_COMPLETED)。 - """ - if not self.bus: - return - try: - task = self.db.get_task(task_id) - if not task: - return - status = task.get("status", "") - if override_type is not None: - msg_type = override_type - else: - type_map = { - "running": OutboundMessageType.TASK_STARTED, - "completed": OutboundMessageType.TASK_COMPLETED, - "failed": OutboundMessageType.TASK_FAILED, - "cancelled": OutboundMessageType.TASK_UPDATED, - "scheduled": OutboundMessageType.TASK_UPDATED, - "pending": OutboundMessageType.TASK_UPDATED, - } - msg_type = type_map.get(status, OutboundMessageType.TASK_UPDATED) - outbound = OutboundMessage( - type=msg_type, - task_id=task_id, - payload={ - "status": status, - "result": task.get("result"), - "error": task.get("error"), - "title": task.get("title"), - }, - ) - self.bus.publish_outbound(outbound) - except Exception as e: - print(f"[BusAwareSchedulerMixin] _bus_notify error: {e}") diff --git a/tests/__init__.py b/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/tests/conftest.py b/tests/conftest.py deleted file mode 100644 index 2260c02..0000000 --- a/tests/conftest.py +++ /dev/null @@ -1,10 +0,0 @@ -""" -Test configuration for AgentForge. -""" - -import sys -from pathlib import Path - -# Add project root to Python path -project_root = Path(__file__).parent.parent -sys.path.insert(0, str(project_root)) diff --git a/tests/test_api_handler.py b/tests/test_api_handler.py deleted file mode 100644 index 650e8ef..0000000 --- a/tests/test_api_handler.py +++ /dev/null @@ -1,910 +0,0 @@ -"""Integration tests for the TaskAPIHandler HTTP routes. - -A real QuietHTTPServer is bound to an ephemeral port and driven over HTTP with -urllib. The scheduler is constructed but never started (no background thread), -and any method that would spawn a real agent CLI is monkeypatched to a no-op so -the tests stay hermetic and fast. Requests are made WITHOUT an Origin header so -the CSRF check is skipped (see TaskAPIHandler._check_csrf). -""" - -import json -import socket -import threading -import urllib.error -import urllib.request - -import pytest - -import taskboard -from taskboard import ( - Heartbeat, - HeartbeatScheduleType, - QuietHTTPServer, - TaskAPIHandler, - TaskDB, - TaskScheduler, -) - - -class _Client: - def __init__(self, base, host, port): - self.base = base - self.host = host - self.port = port - - def request(self, method, path, body=None, headers=None): - url = self.base + path - data = None - hdrs = dict(headers or {}) - if body is not None: - data = json.dumps(body).encode() - hdrs.setdefault("Content-Type", "application/json") - req = urllib.request.Request(url, data=data, method=method, headers=hdrs) - try: - with urllib.request.urlopen(req, timeout=10) as resp: - raw = resp.read() - status = resp.status - except urllib.error.HTTPError as e: - raw = e.read() - status = e.code - parsed = json.loads(raw) if raw else None - return status, parsed - - def get(self, path, headers=None): - return self.request("GET", path, headers=headers) - - def post(self, path, body=None, headers=None): - return self.request("POST", path, body=body, headers=headers) - - def put(self, path, body=None, headers=None): - return self.request("PUT", path, body=body, headers=headers) - - def delete(self, path, headers=None): - return self.request("DELETE", path, headers=headers) - - def options(self, path, headers=None): - return self.request("OPTIONS", path, headers=headers) - - -@pytest.fixture -def api(tmp_path, monkeypatch): - db = TaskDB(str(tmp_path / "test.db")) - scheduler = TaskScheduler(db) # NOT started — no background thread - - # Guard against anything that would spawn a real agent CLI / background work. - monkeypatch.setattr(scheduler, "run_skill_sweep", lambda *a, **k: None) - monkeypatch.setattr(scheduler, "distill_skill_draft", lambda *a, **k: None) - - # Avoid touching the real filesystem when writing/removing skills on disk. - monkeypatch.setattr( - taskboard, "write_skill_to_disk", lambda name, body: (f"/tmp/{name}.md", "") - ) - monkeypatch.setattr(taskboard, "link_skill", lambda name: None) - monkeypatch.setattr(taskboard, "unlink_skill", lambda name: None) - monkeypatch.setattr(taskboard, "remove_skill_from_disk", lambda name: None) - - TaskAPIHandler.db = db - TaskAPIHandler.scheduler = scheduler - TaskAPIHandler.feishu_channel = None - TaskAPIHandler.telegram_channel = None - TaskAPIHandler.slack_channel = None - TaskAPIHandler.weixin_channel = None - TaskAPIHandler.bus = None - TaskAPIHandler.ui_channel = None - - server = QuietHTTPServer(("127.0.0.1", 0), TaskAPIHandler) - port = server.server_address[1] - thread = threading.Thread(target=server.serve_forever, daemon=True) - thread.start() - - client = _Client(f"http://127.0.0.1:{port}", "127.0.0.1", port) - try: - yield client, db, scheduler - finally: - server.shutdown() - server.server_close() - thread.join(timeout=5) - db.conn.close() - - -# ── helpers ────────────────────────────────────────────────────────────────── - - -def _make_task(client, **overrides): - """Create a delayed task (won't run immediately) and return its id.""" - body = { - "title": "T", - "prompt": "do something", - "schedule_type": "delayed", - "delay_seconds": 999, - } - body.update(overrides) - status, data = client.post("/api/tasks", body) - assert status == 201, data - return data["id"] - - -def _make_heartbeat_payload(**overrides): - body = { - "name": "watcher", - "check_prompt": "look around", - "schedule_type": "interval", - "interval_seconds": 60, - } - body.update(overrides) - return body - - -# ── GET routes ─────────────────────────────────────────────────────────────── - - -def test_health(api): - client, _, _ = api - status, data = client.get("/api/health") - assert status == 200 - assert data["status"] == "ok" - assert data["tasks"] == 0 - - -def test_get_tasks_empty_then_populated(api): - client, _, _ = api - status, data = client.get("/api/tasks") - assert status == 200 - assert data == [] - - tid = _make_task(client) - status, data = client.get("/api/tasks") - assert status == 200 - assert len(data) == 1 - assert data[0]["id"] == tid - assert data[0]["dependencies"] == [] - assert data[0]["dependents"] == [] - - -def test_get_single_task_and_404(api): - client, _, _ = api - tid = _make_task(client, title="hello") - status, data = client.get(f"/api/tasks/{tid}") - assert status == 200 - assert data["title"] == "hello" - assert "dependencies" in data - - status, data = client.get("/api/tasks/99999") - assert status == 404 - assert data["error"] == "not found" - - -def test_get_task_output_and_events(api): - client, _, _ = api - tid = _make_task(client) - - status, data = client.get(f"/api/tasks/{tid}/output") - assert status == 200 - assert data == {"output": "", "is_running": False} - - status, data = client.get(f"/api/tasks/{tid}/events") - assert status == 200 - assert data == {"events": [], "total": 0} - - status, data = client.get(f"/api/tasks/{tid}/runs") - assert status == 200 - assert data == [] - - status, data = client.get(f"/api/tasks/{tid}/messages") - assert status == 200 - assert data == [] - - status, data = client.get(f"/api/tasks/{tid}/dependencies") - assert status == 200 - assert data == [] - - status, data = client.get(f"/api/tasks/{tid}/dependents") - assert status == 200 - assert data == [] - - -def test_get_settings_defaults(api): - client, _, _ = api - status, data = client.get("/api/settings") - assert status == 200 - assert data["default_agent"] == "codex" - assert data["timeout"] == 12000 - assert data["skill_library_enabled"] is False - - -def test_get_skill_patterns_and_skills(api): - client, _, _ = api - status, data = client.get("/api/skill-patterns") - assert status == 200 - assert data["patterns"] == [] - assert data["sweep"]["running"] is False - - status, data = client.get("/api/skills") - assert status == 200 - assert data == {"skills": []} - - -def test_get_channels_status(api): - client, _, _ = api - status, data = client.get("/api/channels/status") - assert status == 200 - for key in ("telegram", "slack", "weixin", "feishu"): - assert key in data - assert data["telegram"]["running"] is False - assert data["feishu"]["running"] is False - - -def test_get_feishu_settings(api): - client, _, _ = api - status, data = client.get("/api/feishu/settings") - assert status == 200 - assert data["feishu_app_id"] == "" - assert data["feishu_enabled"] == "false" - - -def test_get_csrf_token(api): - client, _, _ = api - status, data = client.get("/api/csrf-token") - assert status == 200 - assert data["csrf_token"] == taskboard._CSRF_TOKEN - - -def test_get_heartbeats_empty_and_404(api): - client, _, _ = api - status, data = client.get("/api/heartbeats") - assert status == 200 - assert data == [] - - status, data = client.get("/api/heartbeats/99999") - assert status == 404 - assert data["error"] == "not found" - - -def test_get_unknown_path_404(api): - client, _, _ = api - status, data = client.get("/api/nope") - assert status == 404 - assert data["error"] == "not found" - - -# ── POST: task creation validation ─────────────────────────────────────────── - - -def test_create_task_immediate(api): - client, db, _ = api - status, data = client.post( - "/api/tasks", {"title": "now", "prompt": "go", "schedule_type": "immediate"} - ) - assert status == 201 - assert data["status"] == "created" - task = db.get_task(data["id"]) - assert task["status"] == "pending" - assert task["title"] == "now" - - -def test_create_task_empty_prompt(api): - client, _, _ = api - status, data = client.post("/api/tasks", {"prompt": " "}) - assert status == 400 - assert data["field"] == "prompt" - - -def test_create_task_bad_working_dir(api): - client, _, _ = api - status, data = client.post( - "/api/tasks", {"prompt": "go", "working_dir": "/nonexistent/dir/xyz"} - ) - assert status == 400 - assert data["field"] == "working_dir" - - -def test_create_task_cron_missing_expr(api): - client, _, _ = api - status, data = client.post("/api/tasks", {"prompt": "go", "schedule_type": "cron"}) - assert status == 400 - assert data["field"] == "cron_expr" - - -def test_create_task_cron_invalid_expr(api): - client, _, _ = api - status, data = client.post( - "/api/tasks", {"prompt": "go", "schedule_type": "cron", "cron_expr": "not a cron"} - ) - assert status == 400 - assert data["field"] == "cron_expr" - - -def test_create_task_cron_valid(api): - client, db, _ = api - status, data = client.post( - "/api/tasks", {"prompt": "go", "schedule_type": "cron", "cron_expr": "0 3 * * *"} - ) - assert status == 201 - task = db.get_task(data["id"]) - assert task["status"] == "scheduled" - assert task["next_run_at"] - - -def test_create_task_with_dependency_blocks(api): - client, db, _ = api - upstream = _make_task(client) - status, data = client.post( - "/api/tasks", - {"prompt": "downstream", "schedule_type": "immediate", "depends_on": [upstream]}, - ) - assert status == 201 - task = db.get_task(data["id"]) - assert task["status"] == "blocked" - deps = db.get_dependencies(data["id"]) - assert deps[0]["depends_on_task_id"] == upstream - - -def test_malformed_json_body(api): - client, db, _ = api - # Regression: a malformed JSON body used to make _read_body raise an - # unhandled exception, so no response was sent and the client saw a - # connection reset. It should now drain the body and return a clean 400. - payload = b"{bad json" - lines = [ - "POST /api/tasks HTTP/1.1", - f"Host: {client.host}:{client.port}", - "Connection: close", - "Content-Type: application/json", - f"Content-Length: {len(payload)}", - ] - request = ("\r\n".join(lines) + "\r\n\r\n").encode() + payload - sock = socket.create_connection((client.host, client.port), timeout=10) - try: - sock.sendall(request) - raw = b"" - while True: - chunk = sock.recv(4096) - if not chunk: - break - raw += chunk - finally: - sock.close() - status_line = raw.split(b"\r\n", 1)[0].decode(errors="replace") - assert " 400 " in status_line, status_line - assert db.get_all_tasks() == [] - - -# ── POST: heartbeats ───────────────────────────────────────────────────────── - - -def test_create_heartbeat_valid(api): - client, db, _ = api - status, data = client.post("/api/heartbeats", _make_heartbeat_payload()) - assert status == 201 - assert data["status"] == "created" - hb = db.get_heartbeat(data["id"]) - assert hb["name"] == "watcher" - - -def test_create_heartbeat_empty_check_prompt(api): - client, _, _ = api - status, data = client.post("/api/heartbeats", _make_heartbeat_payload(check_prompt=" ")) - assert status == 400 - assert data["field"] == "check_prompt" - - -def test_create_heartbeat_invalid_schedule_type(api): - client, _, _ = api - status, data = client.post("/api/heartbeats", _make_heartbeat_payload(schedule_type="bogus")) - assert status == 400 - assert data["field"] == "schedule_type" - - -def test_create_heartbeat_cron_missing_expr(api): - client, _, _ = api - payload = _make_heartbeat_payload(schedule_type="cron") - payload.pop("interval_seconds", None) - status, data = client.post("/api/heartbeats", payload) - assert status == 400 - assert data["field"] == "cron_expr" - - -def test_create_heartbeat_cron_invalid_expr(api): - client, _, _ = api - payload = _make_heartbeat_payload(schedule_type="cron", cron_expr="nope nope") - status, data = client.post("/api/heartbeats", payload) - assert status == 400 - assert data["field"] == "cron_expr" - - -def test_create_heartbeat_interval_not_int(api): - client, _, _ = api - status, data = client.post("/api/heartbeats", _make_heartbeat_payload(interval_seconds="abc")) - assert status == 400 - assert data["field"] == "interval_seconds" - - -def test_create_heartbeat_interval_non_positive(api): - client, _, _ = api - status, data = client.post("/api/heartbeats", _make_heartbeat_payload(interval_seconds=0)) - assert status == 400 - assert data["field"] == "interval_seconds" - - -def test_create_heartbeat_negative_cooldown(api): - client, _, _ = api - status, data = client.post("/api/heartbeats", _make_heartbeat_payload(cooldown_seconds=-1)) - assert status == 400 - assert data["field"] == "cooldown_seconds" - - -def test_create_heartbeat_bad_working_dir(api): - client, _, _ = api - status, data = client.post( - "/api/heartbeats", _make_heartbeat_payload(working_dir="/nonexistent/xyz") - ) - assert status == 400 - assert data["field"] == "working_dir" - - -def test_heartbeat_run_now_not_found(api): - client, _, _ = api - status, data = client.post("/api/heartbeats/99999/run-now") - assert status == 404 - - -def test_heartbeat_pause_resume(api): - client, db, _ = api - _, created = client.post("/api/heartbeats", _make_heartbeat_payload()) - hid = created["id"] - - status, data = client.post(f"/api/heartbeats/{hid}/pause") - assert status == 200 - assert data["status"] == "paused" - assert db.get_heartbeat(hid)["enabled"] is False - - status, data = client.post(f"/api/heartbeats/{hid}/resume") - assert status == 200 - assert data["status"] == "resumed" - assert db.get_heartbeat(hid)["enabled"] is True - - -def test_heartbeat_pause_not_found(api): - client, _, _ = api - status, data = client.post("/api/heartbeats/99999/pause") - assert status == 404 - - -def test_get_heartbeat_ticks(api): - client, _, _ = api - _, created = client.post("/api/heartbeats", _make_heartbeat_payload()) - hid = created["id"] - status, data = client.get(f"/api/heartbeats/{hid}/ticks") - assert status == 200 - assert data == {"ticks": []} - - -# ── POST: settings & channels ──────────────────────────────────────────────── - - -def test_post_settings(api): - client, db, _ = api - status, data = client.post("/api/settings", {"default_agent": "codex", "timeout": "900"}) - assert status == 200 - assert data["status"] == "updated" - assert db.get_setting("default_agent") == "codex" - assert db.get_setting("timeout") == "900" - - -def test_post_channels_settings_disabled(api): - client, db, _ = api - status, data = client.post( - "/api/channels/settings", - {"telegram_bot_token": "abc", "telegram_enabled": "false"}, - ) - assert status == 200 - assert data["status"] == "updated" - assert db.get_setting("telegram_bot_token") == "abc" - - -def test_weixin_action_not_running(api): - client, _, _ = api - status, data = client.post("/api/channels/weixin/action", {"action": "login"}) - assert status == 400 - assert "not running" in data["error"] - - -# ── POST: skills ───────────────────────────────────────────────────────────── - - -def test_skills_sweep_started(api): - client, _, _ = api - status, data = client.post("/api/skills/sweep", {"full": True}) - assert status == 200 - assert data["status"] == "started" - - -def test_skill_draft_pattern_not_found(api): - client, _, _ = api - status, data = client.post("/api/skill-patterns/99999/draft", {}) - assert status == 404 - - -def test_skill_approve_pattern_not_found(api): - client, _, _ = api - status, data = client.post("/api/skill-patterns/99999/approve", {"name": "x", "body": "y"}) - assert status == 404 - - -def test_skill_dismiss_not_found(api): - client, _, _ = api - status, data = client.post("/api/skill-patterns/99999/dismiss", {}) - assert status == 404 - - -# ── POST: task lifecycle actions ───────────────────────────────────────────── - - -def test_task_cancel(api): - client, db, _ = api - tid = _make_task(client) - status, data = client.post(f"/api/tasks/{tid}/cancel") - assert status == 200 - assert data["status"] == "cancelled" - assert db.get_task(tid)["status"] == "cancelled" - - -def test_task_retry(api): - client, db, _ = api - tid = _make_task(client) - db.update_task(tid, status="failed", error="boom") - status, data = client.post(f"/api/tasks/{tid}/retry") - assert status == 200 - assert data["status"] == "retrying" - assert db.get_task(tid)["status"] == "pending" - - -def test_task_respond(api): - client, db, _ = api - tid = _make_task(client) - db.update_task(tid, status="awaiting_input", question="what?") - status, data = client.post(f"/api/tasks/{tid}/respond", {"answer": "42"}) - assert status == 200 - assert data["status"] == "responding" - task = db.get_task(tid) - assert task["status"] == "pending" - assert task["answer"] == "42" - - -def test_task_respond_not_found(api): - client, _, _ = api - status, data = client.post("/api/tasks/99999/respond", {"answer": "x"}) - assert status == 404 - - -def test_task_resume_no_session(api): - client, _, _ = api - tid = _make_task(client) - status, data = client.post(f"/api/tasks/{tid}/resume", {"message": "continue"}) - assert status == 400 - assert "session_id" in data["error"] - - -def test_task_resume_missing_message(api): - client, _, _ = api - tid = _make_task(client) - status, data = client.post(f"/api/tasks/{tid}/resume", {"message": " "}) - assert status == 400 - assert "message required" in data["error"] - - -def test_task_resume_with_session(api): - client, db, _ = api - tid = _make_task(client) - db.update_task(tid, session_id="sess-1", status="completed") - status, data = client.post(f"/api/tasks/{tid}/resume", {"message": "continue"}) - assert status == 200 - assert data["status"] == "resuming" - assert db.get_task(tid)["status"] == "pending" - - -def test_add_dependency_to_task(api): - client, db, _ = api - upstream = _make_task(client) - db.update_task(upstream, status="completed") # already done → no blocking branch - downstream = _make_task(client) - status, data = client.post( - f"/api/tasks/{downstream}/dependencies", {"depends_on_task_id": upstream} - ) - assert status == 200 - assert data["status"] == "added" - deps = db.get_dependencies(downstream) - assert deps[0]["depends_on_task_id"] == upstream - - -def test_add_dependency_blocking_path_marks_task_blocked(api): - # Regression: when the upstream is not yet completed, the handler takes the - # should_block branch and calls self.scheduler._notify(tid). This used to - # crash with AttributeError (self._notify doesn't exist on the handler), - # resetting the connection. It should now return 200 and block the task. - client, db, _ = api - upstream = _make_task(client) # not completed - downstream = _make_task(client) - status, data = client.post( - f"/api/tasks/{downstream}/dependencies", {"depends_on_task_id": upstream} - ) - assert status == 200 - assert data["status"] == "added" - assert db.get_task(downstream)["status"] == "blocked" - - -def test_add_dependency_missing_field(api): - client, _, _ = api - tid = _make_task(client) - status, data = client.post(f"/api/tasks/{tid}/dependencies", {}) - assert status == 400 - - -def test_add_dependency_task_not_found(api): - client, _, _ = api - status, data = client.post("/api/tasks/99999/dependencies", {"depends_on_task_id": 88888}) - assert status == 404 - - -def test_create_dag(api): - client, db, _ = api - status, data = client.post( - "/api/dag", - { - "dag_id": "mydag", - "tasks": [ - {"ref": "a", "prompt": "first", "schedule_type": "immediate"}, - { - "ref": "b", - "prompt": "second", - "schedule_type": "immediate", - "depends_on_refs": ["a"], - }, - ], - }, - ) - assert status == 201 - assert data["dag_id"] == "mydag" - assert set(data["task_ids"]) == {"a", "b"} - b_id = data["task_ids"]["b"] - assert db.get_task(b_id)["status"] == "blocked" - - -def test_create_dag_empty(api): - client, _, _ = api - status, data = client.post("/api/dag", {"tasks": []}) - assert status == 400 - - -def test_create_dag_unknown_ref(api): - client, _, _ = api - status, data = client.post( - "/api/dag", - {"tasks": [{"ref": "b", "prompt": "x", "depends_on_refs": ["missing"]}]}, - ) - assert status == 400 - assert "missing" in data["error"] - - -def test_post_unknown_path(api): - client, _, _ = api - status, data = client.post("/api/nope", {}) - assert status == 404 - - -# ── PUT routes ─────────────────────────────────────────────────────────────── - - -def test_put_settings(api): - client, db, _ = api - status, data = client.put("/api/settings", {"timeout": "1200"}) - assert status == 200 - assert db.get_setting("timeout") == "1200" - - -def test_put_task_edit(api): - client, db, _ = api - tid = _make_task(client) - status, data = client.put(f"/api/tasks/{tid}", {"prompt": "new prompt", "title": "new title"}) - assert status == 200 - assert data["prompt"] == "new prompt" - assert data["title"] == "new title" - assert db.get_task(tid)["prompt"] == "new prompt" - - -def test_put_task_not_found(api): - client, _, _ = api - status, data = client.put("/api/tasks/99999", {"prompt": "x"}) - assert status == 404 - - -def test_put_task_wrong_status(api): - client, db, _ = api - tid = _make_task(client) - db.update_task(tid, status="completed") - status, data = client.put(f"/api/tasks/{tid}", {"prompt": "x"}) - assert status == 409 - - -def test_put_task_empty_prompt(api): - client, _, _ = api - tid = _make_task(client) - status, data = client.put(f"/api/tasks/{tid}", {"prompt": " "}) - assert status == 400 - assert data["field"] == "prompt" - - -def test_put_task_cron_invalid(api): - client, _, _ = api - tid = _make_task(client) - status, data = client.put( - f"/api/tasks/{tid}", {"schedule_type": "cron", "cron_expr": "garbage here"} - ) - assert status == 400 - assert data["field"] == "cron_expr" - - -def test_put_task_scheduled_at_requires_next_run(api): - client, _, _ = api - tid = _make_task(client) - status, data = client.put(f"/api/tasks/{tid}", {"schedule_type": "scheduled_at"}) - assert status == 400 - assert data["field"] == "next_run_at" - - -def test_put_heartbeat_update(api): - client, db, _ = api - _, created = client.post("/api/heartbeats", _make_heartbeat_payload()) - hid = created["id"] - status, data = client.put( - f"/api/heartbeats/{hid}", _make_heartbeat_payload(name="renamed", interval_seconds=120) - ) - assert status == 200 - assert data["name"] == "renamed" - assert db.get_heartbeat(hid)["interval_seconds"] == 120 - - -def test_put_heartbeat_not_found(api): - client, _, _ = api - status, data = client.put("/api/heartbeats/99999", _make_heartbeat_payload()) - assert status == 404 - - -def test_put_skill_toggle(api): - client, db, _ = api - sid = db.add_skill(name="myskill", description="d", path="/tmp/myskill.md") - status, data = client.put(f"/api/skills/{sid}", {"enabled": False}) - assert status == 200 - assert not data["skill"]["enabled"] - - -def test_put_skill_not_found(api): - client, _, _ = api - status, data = client.put("/api/skills/99999", {"enabled": True}) - assert status == 404 - - -def test_put_unknown_path(api): - client, _, _ = api - status, data = client.put("/api/nope", {}) - assert status == 404 - - -# ── DELETE routes ──────────────────────────────────────────────────────────── - - -def test_delete_task(api): - client, db, _ = api - tid = _make_task(client) - status, data = client.delete(f"/api/tasks/{tid}") - assert status == 200 - assert data["status"] == "deleted" - assert db.get_task(tid) is None - - -def test_delete_heartbeat(api): - client, db, _ = api - _, created = client.post("/api/heartbeats", _make_heartbeat_payload()) - hid = created["id"] - status, data = client.delete(f"/api/heartbeats/{hid}") - assert status == 200 - assert data["status"] == "deleted" - assert db.get_heartbeat(hid) is None - - -def test_delete_skill(api): - client, db, _ = api - sid = db.add_skill(name="goner", description="d", path="/tmp/goner.md") - status, data = client.delete(f"/api/skills/{sid}") - assert status == 200 - assert data["status"] == "deleted" - assert db.get_skill(sid) is None - - -def test_delete_skill_not_found(api): - client, _, _ = api - status, data = client.delete("/api/skills/99999") - assert status == 404 - - -def test_delete_task_dependency(api): - client, db, _ = api - upstream = _make_task(client) - downstream = _make_task(client) - db.add_dependencies_batch(downstream, [{"task_id": upstream, "inject_result": False}]) - status, data = client.delete(f"/api/tasks/{downstream}/dependencies/{upstream}") - assert status == 200 - assert data["status"] == "removed" - assert db.get_dependencies(downstream) == [] - - -def test_delete_unknown_path(api): - client, _, _ = api - status, data = client.delete("/api/nope") - assert status == 404 - - -# ── CORS / CSRF ────────────────────────────────────────────────────────────── - - -def test_options_preflight_allowed_origin(api): - client, _, _ = api - status, _ = client.options("/api/tasks", headers={"Origin": "http://localhost:5173"}) - assert status == 200 - - -def test_options_preflight_rejected_origin(api): - client, _, _ = api - status, _ = client.options("/api/tasks", headers={"Origin": "http://evil.example.com"}) - assert status == 403 - - -def test_csrf_rejected_with_bad_token(api): - # Regression: a bad CSRF token now drains the request body before replying, - # so a normal urllib client gets a clean 403 instead of a connection reset - # (which previously forced the raw-socket workaround). - client, db, _ = api - status, data = client.post( - "/api/settings", - {"default_agent": "codex"}, - headers={"Origin": "http://localhost:5173", "X-CSRF-Token": "wrong"}, - ) - assert status == 403 - # State change must not have been applied. - assert db.get_setting("default_agent", "codex") == "codex" - - -def test_csrf_accepted_with_valid_token(api): - client, db, _ = api - status, data = client.post( - "/api/settings", - {"default_agent": "codex"}, - headers={ - "Origin": "http://localhost:5173", - "X-CSRF-Token": taskboard._CSRF_TOKEN, - }, - ) - assert status == 200 - assert db.get_setting("default_agent") == "codex" - - -# ── direct unit checks on validation helper ────────────────────────────────── - - -def test_validate_heartbeat_payload_cron_clears_interval(api): - _, db, scheduler = api - handler = object.__new__(TaskAPIHandler) - handler.db = db - hb, err = handler._validate_heartbeat_payload( - { - "name": "c", - "check_prompt": "p", - "schedule_type": "cron", - "cron_expr": "0 0 * * *", - } - ) - assert err is None - assert isinstance(hb, Heartbeat) - assert hb.schedule_type == HeartbeatScheduleType.CRON - assert hb.interval_seconds is None - assert hb.next_run_at is not None diff --git a/tests/test_api_handler_more.py b/tests/test_api_handler_more.py deleted file mode 100644 index 145b0ea..0000000 --- a/tests/test_api_handler_more.py +++ /dev/null @@ -1,762 +0,0 @@ -"""Additional integration tests for TaskAPIHandler HTTP routes. - -This file complements tests/test_api_handler.py (which it does NOT touch) by -exercising the less-common handler branches that the first pass left uncovered: -heartbeat tick output, task /messages parsing, the skill draft/approve/dismiss -variants, feishu/channel settings restart branches, DAG GET, skill /content, -and the PUT/DELETE edge cases (validation + recalculated schedule). - -Same hermetic harness as the sibling file: a real QuietHTTPServer bound to an -ephemeral port, an UNSTARTED TaskScheduler, agent/skill entrypoints monkeypatched -to no-ops, and requests made WITHOUT an Origin header so CSRF is skipped. -""" - -import json -import threading -import urllib.error -import urllib.request - -import pytest - -import taskboard -from taskboard import ( - QuietHTTPServer, - TaskAPIHandler, - TaskDB, - TaskScheduler, -) - - -class _Client: - def __init__(self, base): - self.base = base - - def request(self, method, path, body=None, headers=None): - url = self.base + path - data = None - hdrs = dict(headers or {}) - if body is not None: - data = json.dumps(body).encode() - hdrs.setdefault("Content-Type", "application/json") - req = urllib.request.Request(url, data=data, method=method, headers=hdrs) - try: - with urllib.request.urlopen(req, timeout=10) as resp: - raw = resp.read() - status = resp.status - except urllib.error.HTTPError as e: - raw = e.read() - status = e.code - parsed = json.loads(raw) if raw else None - return status, parsed - - def get(self, path, headers=None): - return self.request("GET", path, headers=headers) - - def post(self, path, body=None, headers=None): - return self.request("POST", path, body=body, headers=headers) - - def put(self, path, body=None, headers=None): - return self.request("PUT", path, body=body, headers=headers) - - def delete(self, path, headers=None): - return self.request("DELETE", path, headers=headers) - - -@pytest.fixture -def api(tmp_path, monkeypatch): - db = TaskDB(str(tmp_path / "test.db")) - scheduler = TaskScheduler(db) # NOT started — no background thread - - # Guard against anything that would spawn a real agent CLI / background work. - monkeypatch.setattr(scheduler, "run_skill_sweep", lambda *a, **k: None) - monkeypatch.setattr(scheduler, "distill_skill_draft", lambda *a, **k: None) - - # Avoid touching the real filesystem when writing/removing skills on disk. - monkeypatch.setattr( - taskboard, "write_skill_to_disk", lambda name, body: (f"/tmp/{name}.md", "") - ) - monkeypatch.setattr(taskboard, "link_skill", lambda name: None) - monkeypatch.setattr(taskboard, "unlink_skill", lambda name: None) - monkeypatch.setattr(taskboard, "remove_skill_from_disk", lambda name: None) - - TaskAPIHandler.db = db - TaskAPIHandler.scheduler = scheduler - TaskAPIHandler.feishu_channel = None - TaskAPIHandler.telegram_channel = None - TaskAPIHandler.slack_channel = None - TaskAPIHandler.weixin_channel = None - TaskAPIHandler.bus = None - TaskAPIHandler.ui_channel = None - - server = QuietHTTPServer(("127.0.0.1", 0), TaskAPIHandler) - port = server.server_address[1] - thread = threading.Thread(target=server.serve_forever, daemon=True) - thread.start() - - client = _Client(f"http://127.0.0.1:{port}") - try: - yield client, db, scheduler - finally: - server.shutdown() - server.server_close() - thread.join(timeout=5) - db.conn.close() - - -# ── helpers ────────────────────────────────────────────────────────────────── - - -def _make_task(client, **overrides): - body = { - "title": "T", - "prompt": "do something", - "schedule_type": "delayed", - "delay_seconds": 999, - } - body.update(overrides) - status, data = client.post("/api/tasks", body) - assert status == 201, data - return data["id"] - - -def _make_heartbeat(client, db, **overrides): - body = { - "name": "watcher", - "check_prompt": "look around", - "schedule_type": "interval", - "interval_seconds": 60, - } - body.update(overrides) - status, created = client.post("/api/heartbeats", body) - assert status == 201, created - return created["id"] - - -def _make_pattern(db, **overrides): - """Create a skill pattern row and return its id.""" - kwargs = { - "pattern_key": "deploy-flow", - "kind": "recipe", - "summary": "deploy the thing", - "task_id": None, - "run_id": None, - } - kwargs.update(overrides) - return db.upsert_skill_pattern(**kwargs) - - -# ── GET: heartbeat tick output ─────────────────────────────────────────────── - - -def test_get_heartbeat_tick_output_persisted(api): - client, db, _ = api - hid = _make_heartbeat(client, db) - tick_id = db.add_heartbeat_tick(hid) - db.finish_heartbeat_tick(tick_id, "idle", raw_output="hello world output") - - status, data = client.get(f"/api/heartbeats/{hid}/ticks/{tick_id}/output") - assert status == 200 - assert data == {"output": "hello world output", "is_running": False} - - -def test_get_heartbeat_tick_output_live(api): - client, db, scheduler = api - hid = _make_heartbeat(client, db) - tick_id = db.add_heartbeat_tick(hid) - # Simulate a running tick with buffered live output. - scheduler._live_heartbeat_output[tick_id] = "streaming..." - - status, data = client.get(f"/api/heartbeats/{hid}/ticks/{tick_id}/output") - assert status == 200 - assert data == {"output": "streaming...", "is_running": True} - - -def test_get_heartbeat_tick_output_not_found(api): - client, db, _ = api - hid = _make_heartbeat(client, db) - status, data = client.get(f"/api/heartbeats/{hid}/ticks/99999/output") - assert status == 404 - assert data["error"] == "not found" - - -# ── GET: task /messages parsing ────────────────────────────────────────────── - - -def test_get_task_messages_parses_stream_json(api): - client, db, _ = api - tid = _make_task(client) - run_id = db.add_run(tid) - # A user turn + an assistant turn + a non-text event + a malformed line. - lines = [ - json.dumps( - { - "type": "user", - "message": {"content": [{"type": "text", "text": "do X"}]}, - } - ), - json.dumps( - { - "type": "user", - "message": {"content": ["string-content-too"]}, - } - ), - json.dumps( - { - "type": "assistant", - "message": { - "content": [ - {"type": "text", "text": "did X"}, - {"type": "tool_use", "name": "bash"}, - ] - }, - } - ), - json.dumps({"type": "result", "subtype": "success"}), - "", # blank line skipped - "{not valid json", # JSONDecodeError swallowed - ] - db.finish_run(run_id, "completed", raw_output="\n".join(lines)) - - status, data = client.get(f"/api/tasks/{tid}/messages") - assert status == 200 - roles = [(m["role"], m["text"]) for m in data] - assert ("user", "do X") in roles - assert ("user", "string-content-too") in roles - assert ("assistant", "did X") in roles - # tool_use / result produce no message rows. - assert all(m["run_id"] == run_id for m in data) - assert len(data) == 3 - - -# ── GET: DAG listing + task output from a persisted run ────────────────────── - - -def test_get_dag_tasks(api): - client, db, _ = api - tid = _make_task(client, dag_id="dag-abc") - status, data = client.get("/api/dag/dag-abc") - assert status == 200 - assert len(data) == 1 - assert data[0]["id"] == tid - assert data[0]["dependencies"] == [] - assert data[0]["dependents"] == [] - - -def test_task_output_from_finished_run(api): - client, db, _ = api - tid = _make_task(client) - run_id = db.add_run(tid) - db.finish_run(run_id, "completed", raw_output="final output text") - status, data = client.get(f"/api/tasks/{tid}/output") - assert status == 200 - assert data == {"output": "final output text", "is_running": False} - - -# ── GET: skill content ─────────────────────────────────────────────────────── - - -def test_get_skill_content_ok(api, tmp_path): - client, db, _ = api - skill_path = tmp_path / "SKILL.md" - skill_path.write_text("---\nname: s\n---\nbody here", encoding="utf-8") - sid = db.add_skill(name="s", description="d", path=str(skill_path)) - status, data = client.get(f"/api/skills/{sid}/content") - assert status == 200 - assert "body here" in data["content"] - assert data["path"] == str(skill_path) - assert data["skill"]["id"] == sid - - -def test_get_skill_content_missing_file(api): - client, db, _ = api - sid = db.add_skill(name="ghost", description="d", path="/no/such/path/SKILL.md") - status, data = client.get(f"/api/skills/{sid}/content") - assert status == 200 - assert "无法读取" in data["content"] - - -def test_get_skill_content_not_found(api): - client, _, _ = api - status, data = client.get("/api/skills/99999/content") - assert status == 404 - assert data["error"] == "not found" - - -# ── POST: heartbeat run-now / pause / resume found paths ───────────────────── - - -def test_heartbeat_run_now_ok(api): - client, db, _ = api - hid = _make_heartbeat(client, db) - status, data = client.post(f"/api/heartbeats/{hid}/run-now") - assert status == 200 - assert data["status"] == "scheduled" - # next_run_at should have been pulled to "now" so the scheduler picks it up. - assert db.get_heartbeat(hid)["next_run_at"] is not None - - -# ── POST: skill draft / approve / dismiss with real patterns ───────────────── - - -def test_skill_draft_started(api): - client, db, _ = api - pid = _make_pattern(db) - status, data = client.post(f"/api/skill-patterns/{pid}/draft", {"agent": "claude"}) - assert status == 200 - assert data["status"] == "drafting" - # A draft row in 'drafting' state should now exist. - draft = db.get_skill_draft(pid) - assert draft is not None - assert draft["status"] == "drafting" - - -def test_skill_approve_ok(api): - client, db, _ = api - pid = _make_pattern(db) - body_md = "---\nname: deploy-flow\ndescription: Deploy the thing reliably\n---\n# Deploy\n" - status, data = client.post( - f"/api/skill-patterns/{pid}/approve", - {"name": "deploy-flow", "description": "ignored", "body": body_md}, - ) - assert status == 200 - assert data["status"] == "approved" - assert data["skill"]["name"] == "deploy-flow" - # Frontmatter description wins over the body arg. - assert data["skill"]["description"] == "Deploy the thing reliably" - # Pattern promoted, draft cleared. - assert db.get_skill_pattern(pid)["status"] == "promoted" - assert db.get_skill_draft(pid) is None - - -def test_skill_approve_empty_body_400(api): - client, db, _ = api - pid = _make_pattern(db) - status, data = client.post(f"/api/skill-patterns/{pid}/approve", {"name": "x", "body": " "}) - assert status == 400 - assert "empty" in data["error"] - - -def test_skill_approve_uses_draft_fallback(api): - client, db, _ = api - pid = _make_pattern(db) - # Pre-seed a draft so the handler falls back to it when body is omitted. - db.upsert_skill_draft( - pid, - "ready", - name="from-draft", - description="draft desc", - body="---\nname: from-draft\ndescription: draft desc\n---\nbody", - ) - status, data = client.post(f"/api/skill-patterns/{pid}/approve", {}) - assert status == 200 - assert data["skill"]["name"] == "from-draft" - - -def test_skill_dismiss_ok(api): - client, db, _ = api - pid = _make_pattern(db) - status, data = client.post(f"/api/skill-patterns/{pid}/dismiss", {}) - assert status == 200 - assert data["status"] == "dismissed" - assert db.get_skill_pattern(pid)["status"] == "dismissed" - - -def test_skill_sweep_already_running_409(api, monkeypatch): - client, _, scheduler = api - monkeypatch.setattr(scheduler, "trigger_skill_sweep", lambda *a, **k: False) - status, data = client.post("/api/skills/sweep", {"full": False}) - assert status == 409 - assert "already running" in data["error"] - - -# ── POST: settings sub-key branches ────────────────────────────────────────── - - -def test_post_feishu_settings_disabled(api): - client, db, _ = api - status, data = client.post( - "/api/feishu/settings", - { - "feishu_app_id": "cli_app_12345", - "feishu_app_secret": "secret_value_here", - "feishu_default_chat_id": "oc_chat", - "feishu_enabled": "false", - "ignored_key": "nope", # not in the allowed set - }, - ) - assert status == 200 - assert data["status"] == "updated" - assert db.get_setting("feishu_app_id") == "cli_app_12345" - assert db.get_setting("feishu_default_chat_id") == "oc_chat" - # Disallowed key must not be persisted. - assert db.get_setting("ignored_key", "__absent__") == "__absent__" - # No channel should have been started. - assert TaskAPIHandler.feishu_channel is None - - -def test_post_channels_settings_all_disabled(api): - client, db, _ = api - status, data = client.post( - "/api/channels/settings", - { - "telegram_bot_token": "tg-token", - "telegram_enabled": "false", - "slack_bot_token": "sl-bot", - "slack_app_token": "sl-app", - "slack_enabled": "false", - "weixin_enabled": "false", - "weixin_base_url": "http://localhost:1234", - "bogus": "x", # filtered out - }, - ) - assert status == 200 - assert data["status"] == "updated" - assert db.get_setting("telegram_bot_token") == "tg-token" - assert db.get_setting("slack_app_token") == "sl-app" - assert db.get_setting("weixin_base_url") == "http://localhost:1234" - assert db.get_setting("bogus", "__absent__") == "__absent__" - # None of the channels were enabled, so all remain unset. - assert TaskAPIHandler.telegram_channel is None - assert TaskAPIHandler.slack_channel is None - assert TaskAPIHandler.weixin_channel is None - - -# ── POST: weixin action variants ───────────────────────────────────────────── - - -def test_weixin_action_logout_not_running(api): - client, _, _ = api - status, data = client.post("/api/channels/weixin/action", {"action": "logout"}) - assert status == 400 - assert "not running" in data["error"] - - -class _FakeWeixinChannel: - def __init__(self): - self.login_calls = 0 - self.logout_calls = 0 - - def request_login(self): - self.login_calls += 1 - - def request_logout(self): - self.logout_calls += 1 - - -def test_weixin_action_login_running(api): - client, _, _ = api - fake = _FakeWeixinChannel() - TaskAPIHandler.weixin_channel = fake - try: - status, data = client.post("/api/channels/weixin/action", {"action": "login"}) - assert status == 200 - assert data == {"status": "ok", "action": "login"} - assert fake.login_calls == 1 - finally: - TaskAPIHandler.weixin_channel = None - - -def test_weixin_action_logout_running(api): - client, _, _ = api - fake = _FakeWeixinChannel() - TaskAPIHandler.weixin_channel = fake - try: - status, data = client.post("/api/channels/weixin/action", {"action": "logout"}) - assert status == 200 - assert data == {"status": "ok", "action": "logout"} - assert fake.logout_calls == 1 - finally: - TaskAPIHandler.weixin_channel = None - - -def test_weixin_action_unsupported_running(api): - client, _, _ = api - fake = _FakeWeixinChannel() - TaskAPIHandler.weixin_channel = fake - try: - status, data = client.post("/api/channels/weixin/action", {"action": "frobnicate"}) - assert status == 400 - assert "unsupported" in data["error"] - finally: - TaskAPIHandler.weixin_channel = None - - -# ── POST /api/tasks: JSON-string image fields ──────────────────────────────── - - -def test_create_task_image_fields_as_json_strings(api): - client, db, _ = api - status, data = client.post( - "/api/tasks", - { - "prompt": "go", - "schedule_type": "delayed", - "delay_seconds": 999, - "prompt_images": json.dumps(["data:image/png;base64,AAA"]), - "image_paths": json.dumps(["/tmp/x.png"]), - }, - ) - assert status == 201 - task = db.get_task(data["id"]) - # get_task deserializes both columns back into Python lists. - assert task["prompt_images"] == ["data:image/png;base64,AAA"] - assert task["image_paths"] == ["/tmp/x.png"] - - -def test_create_task_image_fields_invalid_json_strings(api): - client, db, _ = api - status, data = client.post( - "/api/tasks", - { - "prompt": "go", - "schedule_type": "delayed", - "delay_seconds": 999, - "prompt_images": "{bad", - "image_paths": "{also bad", - }, - ) - assert status == 201 - task = db.get_task(data["id"]) - # Malformed JSON strings fall back to empty lists. - assert task["prompt_images"] == [] - assert task["image_paths"] == [] - - -# ── _validate_heartbeat_payload: bool fallback for non-str / non-bool ──────── - - -def test_create_heartbeat_enabled_numeric_coerces(api): - client, db, _ = api - # enabled=1 (an int) exercises the `return bool(value)` fallback branch. - status, created = client.post( - "/api/heartbeats", - { - "name": "hbnum", - "check_prompt": "watch", - "schedule_type": "interval", - "interval_seconds": 60, - "enabled": 1, - }, - ) - assert status == 201 - assert db.get_heartbeat(created["id"])["enabled"] is True - - -# ── POST: add-dependency non-blocking path (upstream already completed) ─────── - - -def test_add_dependency_non_blocking_with_inject(api): - client, db, _ = api - upstream = _make_task(client) - db.update_task(upstream, status="completed") # done → no blocking branch (avoids _notify bug) - downstream = _make_task(client) - status, data = client.post( - f"/api/tasks/{downstream}/dependencies", - {"depends_on_task_id": upstream, "inject_result": True}, - ) - assert status == 200 - assert data["status"] == "added" - deps = db.get_dependencies(downstream) - assert deps[0]["depends_on_task_id"] == upstream - assert deps[0]["inject_result"] in (1, True) - # Downstream stayed unblocked because the upstream is already complete. - assert db.get_task(downstream)["status"] != "blocked" - - -# ── PUT: task schedule recalculation branches ──────────────────────────────── - - -def test_put_task_to_immediate_clears_schedule(api): - client, db, _ = api - tid = _make_task(client, schedule_type="cron", cron_expr="0 3 * * *") - status, data = client.put(f"/api/tasks/{tid}", {"schedule_type": "immediate"}) - assert status == 200 - assert data["status"] == "pending" - task = db.get_task(tid) - assert task["next_run_at"] is None - assert task["cron_expr"] is None - - -def test_put_task_to_delayed(api): - client, db, _ = api - tid = _make_task(client, schedule_type="cron", cron_expr="0 3 * * *") - status, data = client.put( - f"/api/tasks/{tid}", {"schedule_type": "delayed", "delay_seconds": 30} - ) - assert status == 200 - task = db.get_task(tid) - assert task["status"] == "pending" - assert task["cron_expr"] is None - - -def test_put_task_to_scheduled_at_ok(api): - client, db, _ = api - tid = _make_task(client) - status, data = client.put( - f"/api/tasks/{tid}", - {"schedule_type": "scheduled_at", "next_run_at": "2030-01-01T09:00:00"}, - ) - assert status == 200 - task = db.get_task(tid) - assert task["status"] == "scheduled" - assert task["next_run_at"] == "2030-01-01T09:00:00" - assert task["cron_expr"] is None - - -def test_put_task_to_cron_computes_next_run(api): - client, db, _ = api - tid = _make_task(client) - status, data = client.put( - f"/api/tasks/{tid}", {"schedule_type": "cron", "cron_expr": "0 3 * * *"} - ) - assert status == 200 - task = db.get_task(tid) - assert task["status"] == "scheduled" - assert task["next_run_at"] is not None - assert task["delay_seconds"] is None - - -def test_put_task_with_images_and_deps(api): - client, db, _ = api - upstream = _make_task(client) # delayed, NOT completed → downstream should block - tid = _make_task(client) - status, data = client.put( - f"/api/tasks/{tid}", - { - "prompt_images": json.dumps(["data:image/png;base64,AAA"]), - "image_paths": '["/tmp/a.png"]', - "depends_on": [{"task_id": upstream, "inject_result": True}], - }, - ) - assert status == 200 - task = db.get_task(tid) - # Unmet dependency → blocked. - assert task["status"] == "blocked" - deps = db.get_dependencies(tid) - assert deps[0]["depends_on_task_id"] == upstream - assert deps[0]["inject_result"] in (1, True) - assert data["dependencies"][0]["depends_on_task_id"] == upstream - - -def test_put_task_invalid_image_strings_default_to_empty(api): - client, db, _ = api - tid = _make_task(client) - status, data = client.put( - f"/api/tasks/{tid}", - {"prompt_images": "{bad json", "image_paths": "{also bad"}, - ) - assert status == 200 - task = db.get_task(tid) - assert task["prompt_images"] == [] - assert task["image_paths"] == [] - - -def test_put_task_invalid_id_400(api): - client, _, _ = api - status, data = client.put("/api/tasks/notanumber", {"prompt": "x"}) - assert status == 400 - assert data["error"] == "invalid task id" - - -def test_put_task_bad_working_dir(api): - client, _, _ = api - tid = _make_task(client) - status, data = client.put(f"/api/tasks/{tid}", {"working_dir": "/nonexistent/zzz"}) - assert status == 400 - assert data["field"] == "working_dir" - - -def test_put_task_cron_missing_expr(api): - client, db, _ = api - tid = _make_task(client) - # Clear cron_expr so the cron branch hits the "required" error. - db.update_task(tid, cron_expr=None) - status, data = client.put(f"/api/tasks/{tid}", {"schedule_type": "cron"}) - assert status == 400 - assert data["field"] == "cron_expr" - - -# ── PUT: skill invalid id ──────────────────────────────────────────────────── - - -def test_put_skill_invalid_id_400(api): - client, _, _ = api - status, data = client.put("/api/skills/notanumber", {"enabled": True}) - assert status == 400 - assert data["error"] == "invalid skill id" - - -# ── PUT: heartbeat invalid-payload branch (validation error surfaced) ──────── - - -def test_put_heartbeat_invalid_interval(api): - client, db, _ = api - hid = _make_heartbeat(client, db) - status, data = client.put( - f"/api/heartbeats/{hid}", - {"schedule_type": "interval", "interval_seconds": 0}, - ) - assert status == 400 - assert data["field"] == "interval_seconds" - - -def test_put_heartbeat_invalid_id_400(api): - client, _, _ = api - status, data = client.put("/api/heartbeats/notanumber", {"name": "x"}) - # path.count("/") == 3 but int() fails → invalid id branch - assert status == 400 - assert data["error"] == "invalid heartbeat id" - - -# ── DELETE: skill invalid id + not found ───────────────────────────────────── - - -def test_delete_skill_invalid_id_400(api): - client, _, _ = api - status, data = client.delete("/api/skills/notanumber") - assert status == 400 - assert data["error"] == "invalid skill id" - - -def test_delete_skill_ok(api): - client, db, _ = api - sid = db.add_skill(name="bye", description="d", path="/tmp/bye.md") - status, data = client.delete(f"/api/skills/{sid}") - assert status == 200 - assert data["status"] == "deleted" - assert db.get_skill(sid) is None - - -# ── _validate_heartbeat_payload bool coercion (string "true"/"false") ──────── - - -def test_create_heartbeat_enabled_string_true(api): - client, db, _ = api - status, created = client.post( - "/api/heartbeats", - { - "name": "hb", - "check_prompt": "watch", - "schedule_type": "interval", - "interval_seconds": 60, - "enabled": "true", - }, - ) - assert status == 201 - assert db.get_heartbeat(created["id"])["enabled"] is True - - -def test_create_heartbeat_enabled_string_false(api): - client, db, _ = api - status, created = client.post( - "/api/heartbeats", - { - "name": "hb2", - "check_prompt": "watch", - "schedule_type": "interval", - "interval_seconds": 60, - "enabled": "false", - }, - ) - assert status == 201 - assert db.get_heartbeat(created["id"])["enabled"] is False diff --git a/tests/test_channel_utils.py b/tests/test_channel_utils.py deleted file mode 100644 index 459798e..0000000 --- a/tests/test_channel_utils.py +++ /dev/null @@ -1,96 +0,0 @@ -import os - -from channels.agent_utils import ( - SUPPORTED_AGENTS, - handle_agent_command, - parse_agent_command, - resolve_agent, -) -from channels.dir_utils import handle_dir_command, parse_dir_command, resolve_working_dir -from taskboard import _get_env - - -class StubDB: - def __init__(self): - self.settings = {} - - def set_setting(self, key, value): - self.settings[key] = value - - def get_setting(self, key, default=None): - return self.settings.get(key, default) - - -def test_parse_dir_command_accepts_supported_forms(): - assert parse_dir_command("/dir ~/repo") == "~/repo" - assert parse_dir_command("/cd ./repo") == "./repo" - assert parse_dir_command("cd /tmp/work") == "/tmp/work" - assert parse_dir_command("pwd") is None - - -def test_handle_dir_command_persists_setting(): - db = StubDB() - - result = handle_dir_command("/dir ~/repo", "telegram", db) - - assert result == "📁 Working directory set to: ~/repo" - assert db.get_setting("telegram_default_working_dir") == "~/repo" - - -def test_resolve_working_dir_uses_saved_default_when_no_explicit_path(monkeypatch): - db = StubDB() - db.set_setting("slack_default_working_dir", "~/saved") - monkeypatch.setattr("channels.dir_utils.extract_working_dir_with_claude", lambda prompt: None) - - assert resolve_working_dir("please help", "slack", db) == "~/saved" - - -def test_resolve_working_dir_prefers_extracted_path(monkeypatch): - db = StubDB() - db.set_setting("slack_default_working_dir", "~/saved") - monkeypatch.setattr( - "channels.dir_utils.extract_working_dir_with_claude", - lambda prompt: "~/explicit", - ) - - assert resolve_working_dir("work in ~/explicit", "slack", db) == "~/explicit" - - -def test_parse_agent_command_normalizes_name(): - assert parse_agent_command("/agent codex") == "codex" - assert parse_agent_command("/agent CLAUDE") == "claude" - assert parse_agent_command("/help") is None - - -def test_handle_agent_command_rejects_unknown_agent(): - db = StubDB() - - result = handle_agent_command("/agent unknown", "telegram", db) - - assert result == "❌ Unknown agent `unknown`. Supported: `claude`, `codex`" - - -def test_handle_agent_command_persists_default_agent(): - db = StubDB() - - result = handle_agent_command("/agent codex", "telegram", db) - - assert result == f"🤖 Default agent switched to: **{SUPPORTED_AGENTS['codex']}**" - assert db.get_setting("default_agent") == "codex" - assert resolve_agent("telegram", db) == "codex" - - -def test_resolve_agent_defaults_to_codex(): - assert resolve_agent("telegram", StubDB()) == "codex" - - -def test_get_env_prepends_common_tool_paths(monkeypatch): - monkeypatch.setenv("PATH", "/usr/bin:/bin") - monkeypatch.setattr(os.path, "expanduser", lambda path: path.replace("~", "/Users/tester")) - - env = _get_env() - - assert env["PATH"].startswith( - "/Users/tester/.local/bin:/usr/local/bin:/opt/homebrew/bin:/usr/local/opt/node/bin:" - "/Users/tester/.npm/bin:/Users/tester/.nvm/current/bin:/usr/bin:/bin" - ) diff --git a/tests/test_claude_streaming_events.py b/tests/test_claude_streaming_events.py deleted file mode 100644 index 6277f5c..0000000 --- a/tests/test_claude_streaming_events.py +++ /dev/null @@ -1,157 +0,0 @@ -import json -from unittest.mock import Mock - -from taskboard import CLAUDE_STREAM_JSON_ARGS, TaskScheduler - - -def _scheduler(): - scheduler = TaskScheduler(Mock()) - scheduler.db.add_output_event = Mock() - return scheduler - - -def _assistant_event(text: str, message_id: str = "msg_1") -> dict: - return { - "type": "assistant", - "message": { - "id": message_id, - "role": "assistant", - "content": [{"type": "text", "text": text}], - }, - } - - -def test_claude_stream_json_args_include_partial_messages(): - assert "--include-partial-messages" in CLAUDE_STREAM_JSON_ARGS - - -def test_claude_partial_assistant_events_emit_only_deltas(): - scheduler = _scheduler() - listener = Mock() - scheduler.add_output_listener(listener) - - events = [ - _assistant_event("Hel"), - _assistant_event("Hello "), - _assistant_event("Hello world"), - _assistant_event("Hello world"), - ] - - for event in events: - scheduler._parse_and_store_event(1, 2, json.dumps(event), "claude") - - stored = [call.args[3] for call in scheduler.db.add_output_event.call_args_list] - assert stored == ["Hel", "lo ", "world"] - assert [call.args[3] for call in listener.call_args_list] == ["Hel", "lo ", "world"] - - -def test_claude_chunk_assistant_events_do_not_duplicate_final_message(): - scheduler = _scheduler() - listener = Mock() - scheduler.add_output_listener(listener) - - events = [ - _assistant_event("Hel"), - _assistant_event("lo "), - _assistant_event("world"), - _assistant_event("Hello world"), - ] - - for event in events: - scheduler._parse_and_store_event(1, 2, json.dumps(event), "claude") - - stored = [call.args[3] for call in scheduler.db.add_output_event.call_args_list] - assert stored == ["Hel", "lo ", "world"] - assert [call.args[3] for call in listener.call_args_list] == ["Hel", "lo ", "world"] - - -def test_claude_new_assistant_message_id_starts_fresh_stream(): - scheduler = _scheduler() - listener = Mock() - scheduler.add_output_listener(listener) - - events = [ - _assistant_event("First", "msg_1"), - _assistant_event("Second", "msg_2"), - ] - - for event in events: - scheduler._parse_and_store_event(1, 2, json.dumps(event), "claude") - - stored = [call.args[3] for call in scheduler.db.add_output_event.call_args_list] - assert stored == ["First", "Second"] - assert [call.args[3] for call in listener.call_args_list] == ["First", "Second"] - - -def test_claude_tool_use_blocks_are_stored_and_streamed_as_tool_calls(): - scheduler = _scheduler() - listener = Mock() - scheduler.add_output_listener(listener) - - event = { - "type": "assistant", - "message": { - "id": "msg_tool", - "role": "assistant", - "content": [ - { - "type": "tool_use", - "id": "toolu_1", - "name": "Bash", - "input": { - "command": "pytest -q", - "api_key": "sk-secret", - }, - } - ], - }, - } - - scheduler._parse_and_store_event(1, 2, json.dumps(event), "claude") - - scheduler.db.add_output_event.assert_called_once() - task_id, run_id, event_type, content = scheduler.db.add_output_event.call_args.args - payload = json.loads(content) - assert (task_id, run_id, event_type) == (1, 2, "tool_call") - assert payload == { - "id": "toolu_1", - "name": "Bash", - "input": { - "command": "pytest -q", - "api_key": "[redacted]", - }, - } - listener.assert_called_once_with(1, 2, "tool_call", content) - - -def test_claude_tool_result_blocks_are_stored_and_streamed_as_tool_results(): - scheduler = _scheduler() - listener = Mock() - scheduler.add_output_listener(listener) - - event = { - "type": "user", - "message": { - "role": "user", - "content": [ - { - "type": "tool_result", - "tool_use_id": "toolu_1", - "content": [{"type": "text", "text": "42 passed"}], - "is_error": False, - } - ], - }, - } - - scheduler._parse_and_store_event(1, 2, json.dumps(event), "claude") - - scheduler.db.add_output_event.assert_called_once() - task_id, run_id, event_type, content = scheduler.db.add_output_event.call_args.args - assert (task_id, run_id, event_type) == (1, 2, "tool_result") - assert json.loads(content) == { - "tool_use_id": "toolu_1", - "content": "42 passed", - "is_error": False, - } - listener.assert_called_once_with(1, 2, "tool_result", content) diff --git a/tests/test_codex_streaming_events.py b/tests/test_codex_streaming_events.py deleted file mode 100644 index ac4211a..0000000 --- a/tests/test_codex_streaming_events.py +++ /dev/null @@ -1,283 +0,0 @@ -import json -from unittest.mock import Mock - -from taskboard import TaskScheduler - - -def _scheduler(): - scheduler = TaskScheduler(Mock()) - scheduler.db.add_output_event = Mock() - return scheduler - - -def test_codex_item_updated_cumulative_text_emits_only_deltas(): - scheduler = _scheduler() - listener = Mock() - scheduler.add_output_listener(listener) - - events = [ - {"type": "item.updated", "item": {"id": "msg_1", "type": "agent_message", "text": "Hel"}}, - { - "type": "item.updated", - "item": {"id": "msg_1", "type": "agent_message", "text": "Hello "}, - }, - { - "type": "item.updated", - "item": {"id": "msg_1", "type": "agent_message", "text": "Hello world"}, - }, - { - "type": "item.completed", - "item": {"id": "msg_1", "type": "agent_message", "text": "Hello world"}, - }, - ] - - for event in events: - scheduler._parse_and_store_event(1, 2, json.dumps(event), "codex") - - stored = [call.args[3] for call in scheduler.db.add_output_event.call_args_list] - assert stored == ["Hel", "lo ", "world"] - assert [call.args[3] for call in listener.call_args_list] == ["Hel", "lo ", "world"] - - -def test_codex_item_updated_delta_text_does_not_duplicate_completed_text(): - scheduler = _scheduler() - listener = Mock() - scheduler.add_output_listener(listener) - - events = [ - { - "type": "item.updated", - "delta": {"text": "Hello"}, - "item": {"id": "msg_1", "type": "agent_message"}, - }, - { - "type": "item.updated", - "delta": {"text": " world"}, - "item": {"id": "msg_1", "type": "agent_message"}, - }, - { - "type": "item.completed", - "item": {"id": "msg_1", "type": "agent_message", "text": "Hello world"}, - }, - ] - - for event in events: - scheduler._parse_and_store_event(1, 2, json.dumps(event), "codex") - - stored = [call.args[3] for call in scheduler.db.add_output_event.call_args_list] - assert stored == ["Hello", " world"] - assert [call.args[3] for call in listener.call_args_list] == ["Hello", " world"] - - -def test_codex_reasoning_updated_text_does_not_duplicate_completed_text(): - scheduler = _scheduler() - listener = Mock() - scheduler.add_output_listener(listener) - - events = [ - { - "type": "item.updated", - "delta": {"text": "Think"}, - "item": {"id": "reasoning_1", "type": "reasoning"}, - }, - { - "type": "item.updated", - "delta": {"text": " carefully"}, - "item": {"id": "reasoning_1", "type": "reasoning"}, - }, - { - "type": "item.completed", - "item": {"id": "reasoning_1", "type": "reasoning", "text": "Think carefully"}, - }, - ] - - for event in events: - scheduler._parse_and_store_event(1, 2, json.dumps(event), "codex") - - stored = [call.args[3] for call in scheduler.db.add_output_event.call_args_list] - assert stored == ["[thinking] Think", "[thinking] carefully"] - assert [call.args[3] for call in listener.call_args_list] == [ - "[thinking] Think", - "[thinking] carefully", - ] - - -def test_codex_command_execution_is_stored_and_streamed(): - scheduler = _scheduler() - listener = Mock() - scheduler.add_output_listener(listener) - - event = { - "type": "item.completed", - "item": { - "id": "cmd_1", - "type": "command_execution", - "command": "pytest -q", - "aggregated_output": "42 passed", - "exit_code": 0, - "status": "completed", - }, - } - - scheduler._parse_and_store_event(1, 2, json.dumps(event), "codex") - - scheduler.db.add_output_event.assert_called_once() - task_id, run_id, event_type, content = scheduler.db.add_output_event.call_args.args - assert (task_id, run_id, event_type) == (1, 2, "command_execution") - assert json.loads(content) == { - "id": "cmd_1", - "command": "pytest -q", - "output": "42 passed", - "exit_code": 0, - "status": "completed", - } - listener.assert_called_once_with(1, 2, "command_execution", content) - - -def test_codex_mcp_tool_call_is_stored_and_streamed_with_redacted_arguments(): - scheduler = _scheduler() - listener = Mock() - scheduler.add_output_listener(listener) - - event = { - "type": "item.completed", - "item": { - "id": "mcp_1", - "type": "mcp_tool_call", - "server": "github", - "tool": "search_issues", - "arguments": { - "query": "is:open", - "token": "ghp_secret", - }, - "result": {"total_count": 1}, - "status": "completed", - }, - } - - scheduler._parse_and_store_event(1, 2, json.dumps(event), "codex") - - task_id, run_id, event_type, content = scheduler.db.add_output_event.call_args.args - assert (task_id, run_id, event_type) == (1, 2, "tool_call") - assert json.loads(content) == { - "id": "mcp_1", - "server": "github", - "name": "search_issues", - "input": { - "query": "is:open", - "token": "[redacted]", - }, - "result": {"total_count": 1}, - "status": "completed", - } - listener.assert_called_once_with(1, 2, "tool_call", content) - - -def test_codex_web_search_and_file_change_events_are_stored_and_streamed(): - scheduler = _scheduler() - listener = Mock() - scheduler.add_output_listener(listener) - - events = [ - { - "type": "item.completed", - "item": { - "id": "search_1", - "type": "web_search", - "query": "AgentForge taskboard", - "action": "search", - }, - }, - { - "type": "item.completed", - "item": { - "id": "file_1", - "type": "file_change", - "changes": [{"path": "taskboard.py", "kind": "modified"}], - "status": "completed", - }, - }, - ] - - for event in events: - scheduler._parse_and_store_event(1, 2, json.dumps(event), "codex") - - stored = [ - (call.args[2], json.loads(call.args[3])) - for call in scheduler.db.add_output_event.call_args_list - ] - assert stored == [ - ( - "web_search", - { - "id": "search_1", - "query": "AgentForge taskboard", - "action": "search", - }, - ), - ( - "file_change", - { - "id": "file_1", - "changes": [{"path": "taskboard.py", "kind": "modified"}], - "status": "completed", - }, - ), - ] - assert [call.args[2] for call in listener.call_args_list] == [ - "web_search", - "file_change", - ] - - -def test_codex_empty_final_message_uses_generated_images_not_raw_json(tmp_path, monkeypatch): - codex_home = tmp_path / "codex" - thread_id = "019e6224-test" - image_dir = codex_home / "generated_images" / thread_id - image_dir.mkdir(parents=True) - image_path = image_dir / "skills-overview.png" - image_path.write_bytes(b"\x89PNG\r\n\x1a\nfakepng") - monkeypatch.setenv("CODEX_HOME", str(codex_home)) - - raw_stdout = "\n".join( - [ - json.dumps({"type": "thread.started", "thread_id": thread_id}), - json.dumps( - { - "type": "item.completed", - "item": {"id": "msg_1", "type": "agent_message", "text": ""}, - } - ), - json.dumps({"type": "turn.completed", "usage": {"output_tokens": 10}}), - ] - ) - - scheduler = _scheduler() - generated_images = scheduler._find_codex_generated_images(thread_id) - output = scheduler._extract_codex_success_output(raw_stdout, generated_images) - - assert generated_images == [str(image_path)] - assert output == f"已生成 1 张图片:\n- {image_path}" - assert "thread.started" not in output - assert "item.completed" not in output - - -def test_store_generated_image_events_adds_path_and_renderable_image(tmp_path): - image_path = tmp_path / "result.png" - image_path.write_bytes(b"\x89PNG\r\n\x1a\nfakepng") - - scheduler = _scheduler() - scheduler._store_generated_image_events(1, 2, [str(image_path)]) - - stored = [ - (call.args[2], json.loads(call.args[3])) - for call in scheduler.db.add_output_event.call_args_list - ] - assert stored[0] == ( - "generated_image", - {"path": str(image_path), "media_type": "image/png"}, - ) - assert stored[1][0] == "image_content" - assert stored[1][1]["path"] == str(image_path) - assert stored[1][1]["media_type"] == "image/png" - assert stored[1][1]["data"] diff --git a/tests/test_dir_utils.py b/tests/test_dir_utils.py deleted file mode 100644 index ed843c9..0000000 --- a/tests/test_dir_utils.py +++ /dev/null @@ -1,137 +0,0 @@ -"""Tests for channels.dir_utils — /dir command parsing and Claude path extraction.""" - -from unittest.mock import Mock - -import pytest - -from channels import dir_utils - -# ── parse_dir_command / handle_dir_command ──────────────────────────────── - - -@pytest.mark.parametrize( - "text,expected", - [ - ("/dir ~/foo", "~/foo"), - ("cd /home/user/bar", "/home/user/bar"), - ("/cd ./app", "./app"), - (" CD ~/spaced ", "~/spaced"), - ("just a normal message", None), - ("/dir", None), # no argument - ("/dir a b", None), # too many args - ], -) -def test_parse_dir_command(text, expected): - assert dir_utils.parse_dir_command(text) == expected - - -def test_handle_dir_command_persists_and_confirms(): - db = Mock() - out = dir_utils.handle_dir_command("/dir ~/proj", "telegram", db) - db.set_setting.assert_called_once_with("telegram_default_working_dir", "~/proj") - assert out == "📁 Working directory set to: ~/proj" - - -def test_handle_dir_command_ignores_non_command(): - db = Mock() - assert dir_utils.handle_dir_command("hello there", "slack", db) is None - db.set_setting.assert_not_called() - - -# ── extract_working_dir_with_claude ─────────────────────────────────────── - - -def _resp(status=200, payload=None): - r = Mock() - r.status_code = status - r.json.return_value = payload or {} - return r - - -def test_extract_returns_none_without_api_key(monkeypatch): - monkeypatch.delenv("ANTHROPIC_API_KEY", raising=False) - assert dir_utils.extract_working_dir_with_claude("work in ~/x") is None - - -def test_extract_parses_path_from_claude(monkeypatch): - monkeypatch.setenv("ANTHROPIC_API_KEY", "sk-test") - import requests - - captured = {} - - def fake_post(url, headers=None, json=None, timeout=None): - captured["url"] = url - captured["model"] = json["model"] - return _resp(200, {"content": [{"text": '{"path": "~/projects/foo"}'}]}) - - monkeypatch.setattr(requests, "post", fake_post) - assert ( - dir_utils.extract_working_dir_with_claude("在 ~/projects/foo 帮我跑测试") - == "~/projects/foo" - ) - assert captured["url"] == "https://api.anthropic.com/v1/messages" - assert captured["model"] == "claude-haiku-4-5" - - -def test_extract_returns_none_on_null_path(monkeypatch): - monkeypatch.setenv("ANTHROPIC_API_KEY", "sk-test") - import requests - - monkeypatch.setattr( - requests, "post", lambda *a, **k: _resp(200, {"content": [{"text": '{"path": null}'}]}) - ) - assert dir_utils.extract_working_dir_with_claude("no path here") is None - - -def test_extract_returns_none_on_non_200(monkeypatch): - monkeypatch.setenv("ANTHROPIC_API_KEY", "sk-test") - import requests - - monkeypatch.setattr(requests, "post", lambda *a, **k: _resp(500, {})) - assert dir_utils.extract_working_dir_with_claude("anything") is None - - -def test_extract_swallows_exceptions(monkeypatch): - monkeypatch.setenv("ANTHROPIC_API_KEY", "sk-test") - import requests - - def boom(*a, **k): - raise RuntimeError("network down") - - monkeypatch.setattr(requests, "post", boom) - assert dir_utils.extract_working_dir_with_claude("anything") is None - - -def test_extract_returns_none_on_malformed_json(monkeypatch): - monkeypatch.setenv("ANTHROPIC_API_KEY", "sk-test") - import requests - - monkeypatch.setattr( - requests, "post", lambda *a, **k: _resp(200, {"content": [{"text": "not json"}]}) - ) - assert dir_utils.extract_working_dir_with_claude("anything") is None - - -# ── resolve_working_dir ─────────────────────────────────────────────────── - - -def test_resolve_prefers_extracted_path(monkeypatch): - monkeypatch.setattr(dir_utils, "extract_working_dir_with_claude", lambda p: "~/extracted") - db = Mock() - assert dir_utils.resolve_working_dir("prompt", "telegram", db) == "~/extracted" - db.get_setting.assert_not_called() - - -def test_resolve_falls_back_to_db_default(monkeypatch): - monkeypatch.setattr(dir_utils, "extract_working_dir_with_claude", lambda p: None) - db = Mock() - db.get_setting.return_value = "~/from-db" - assert dir_utils.resolve_working_dir("prompt", "slack", db) == "~/from-db" - db.get_setting.assert_called_once_with("slack_default_working_dir") - - -def test_resolve_falls_back_to_home(monkeypatch): - monkeypatch.setattr(dir_utils, "extract_working_dir_with_claude", lambda p: None) - db = Mock() - db.get_setting.return_value = None - assert dir_utils.resolve_working_dir("prompt", "feishu", db) == "~" diff --git a/tests/test_execute_task.py b/tests/test_execute_task.py deleted file mode 100644 index 51b5256..0000000 --- a/tests/test_execute_task.py +++ /dev/null @@ -1,695 +0,0 @@ -"""Hermetic tests for the agent subprocess execution + stream-parsing paths. - -Targets the largest uncovered region in ``taskboard.py``: - -* ``TaskScheduler._execute_task`` — spawns the agent CLI, reads the stdout - NDJSON ``stream-json`` stream line-by-line, parses + persists each event, - reads stderr in a background thread, arms a kill timer, and finalizes the - run/task in the DB (success vs. failure). -* ``TaskScheduler._run_agent_command`` — the heartbeat / skill-sweep agent - invocation path that also drains stdout/stderr in threads. -* ``AgentExecutor.run`` — builds the ``claude`` CLI command line. -* ``TaskScheduler._extract_error_summary``. - -Strategy: patch ``taskboard.subprocess.Popen`` with a finite fake process so -the read loop always terminates, and patch the process-group ``os`` calls -(``getpgid`` / ``killpg``) so they don't touch a real PID. A real -``TaskDB`` on a tmp_path SQLite file lets us assert the persisted run status -and the parsed output events afterwards. -""" - -import json -import os -import tempfile -import time -from unittest.mock import patch - -import pytest - -import taskboard -from taskboard import AgentExecutor, ScheduleType, Task, TaskDB, TaskScheduler - - -# ── Fakes ──────────────────────────────────────────────────────────────────── -class FakePopen: - """Minimal stand-in for the subprocess.Popen object used by taskboard. - - ``_execute_task`` (and ``_run_agent_command``) iterate ``proc.stdout`` / - ``proc.stderr`` directly and call ``.wait()``. The stdout/stderr iterables - are finite so the read loop never hangs. - """ - - _next_pid = 4242 - - def __init__(self, stdout_lines, stderr_lines=None, returncode=0): - FakePopen._next_pid += 1 - self.pid = FakePopen._next_pid - # text=True in the real call → lines are str - self.stdout = iter(list(stdout_lines)) - self.stderr = iter(list(stderr_lines or [])) - self.returncode = returncode - self._killed = False - self.stdin = _FakeStdin() - - def wait(self, timeout=None): - return self.returncode - - def poll(self): - return self.returncode - - def kill(self): - self._killed = True - - -class _FakeStdin: - def __init__(self): - self.buffer = "" - self.closed = False - - def write(self, data): - self.buffer += data - - def close(self): - self.closed = True - - -@pytest.fixture -def scheduler(tmp_path): - db = TaskDB(str(tmp_path / "t.db")) - sched = TaskScheduler(db) # NOTE: never .start() — keep it hermetic - return sched - - -@pytest.fixture(autouse=True) -def _stub_process_group(monkeypatch): - """Make the process-group bookkeeping in ``_execute_task`` inert. - - The real code calls ``os.getpgid(pid)`` then loops on ``os.killpg(pgid, 0)`` - to wait for sub-agents. With a fake PID we substitute deterministic stubs: - ``killpg(_, 0)`` immediately raises ProcessLookupError so the sub-agent - wait loop exits at once (no sleeps, no hangs). - """ - - def fake_getpgid(pid): - return pid - - def fake_killpg(pgid, sig): - # sig == 0 is the "is the group alive?" probe → report it's gone. - raise ProcessLookupError - - monkeypatch.setattr(taskboard.os, "getpgid", fake_getpgid) - monkeypatch.setattr(taskboard.os, "killpg", fake_killpg) - - -# ── Stream fixtures (realistic stream-json lines for both agents) ──────────── -def _claude_lines(result_text="All done.", session_id="sess-abc"): - return [ - json.dumps({"type": "system", "subtype": "init", "session_id": session_id}) + "\n", - json.dumps( - { - "type": "assistant", - "message": { - "id": "msg_1", - "role": "assistant", - "content": [{"type": "text", "text": "Working on it. "}], - }, - } - ) - + "\n", - json.dumps( - { - "type": "assistant", - "message": { - "id": "msg_2", - "role": "assistant", - "content": [ - { - "type": "tool_use", - "id": "toolu_1", - "name": "Bash", - "input": {"command": "ls"}, - } - ], - }, - } - ) - + "\n", - json.dumps( - { - "type": "user", - "message": { - "role": "user", - "content": [ - { - "type": "tool_result", - "tool_use_id": "toolu_1", - "content": [{"type": "text", "text": "file.txt"}], - "is_error": False, - } - ], - }, - } - ) - + "\n", - " \n", # blank line — tolerated - "this is not json at all and is longer than ten chars\n", # raw-text branch - json.dumps( - { - "type": "result", - "subtype": "success", - "result": result_text, - "session_id": session_id, - } - ) - + "\n", - ] - - -def _codex_lines(thread_id="thread-xyz", final_text="Codex finished."): - return [ - json.dumps({"type": "thread.started", "thread_id": thread_id}) + "\n", - json.dumps( - { - "type": "item.completed", - "item": { - "id": "cmd_1", - "type": "command_execution", - "command": "pytest -q", - "aggregated_output": "1 passed", - "exit_code": 0, - "status": "completed", - }, - } - ) - + "\n", - json.dumps( - { - "type": "item.completed", - "item": {"id": "msg_1", "type": "agent_message", "text": final_text}, - } - ) - + "\n", - json.dumps({"type": "turn.completed", "usage": {"output_tokens": 5}}) + "\n", - ] - - -# ── AgentExecutor.run: command-line construction + flags ───────────────────── -def test_agent_executor_run_builds_claude_command_with_permission_flags(): - captured = {} - - class _Result: - returncode = 0 - stdout = json.dumps({"type": "result", "result": "hi"}) + "\n" - stderr = "" - - def fake_run(cmd, **kwargs): - captured["cmd"] = cmd - captured["kwargs"] = kwargs - return _Result() - - with patch.object(taskboard.subprocess, "run", side_effect=fake_run): - ok, output = AgentExecutor.run("do a thing", working_dir=".", timeout=30) - - assert ok is True - assert output == "hi" # result event text extracted, not raw stdout - cmd = captured["cmd"] - assert cmd[:3] == ["claude", "-p", "do a thing"] - # stream-json + bypassPermissions flags appended - assert "--output-format" in cmd and "stream-json" in cmd - assert "--permission-mode" in cmd - assert cmd[cmd.index("--permission-mode") + 1] == "bypassPermissions" - assert captured["kwargs"]["timeout"] == 30 - - -def test_agent_executor_run_includes_image_flags(): - with patch.object(taskboard.subprocess, "run") as mrun: - mrun.return_value.returncode = 0 - mrun.return_value.stdout = "" - mrun.return_value.stderr = "" - AgentExecutor.run("p", image_paths=["/tmp/a.png", "/tmp/b.jpg"]) - cmd = mrun.call_args.args[0] - # each image passed via -i - assert cmd.count("-i") == 2 - assert "/tmp/a.png" in cmd and "/tmp/b.jpg" in cmd - - -def test_agent_executor_run_nonzero_returns_stderr(): - with patch.object(taskboard.subprocess, "run") as mrun: - mrun.return_value.returncode = 1 - mrun.return_value.stdout = "" - mrun.return_value.stderr = "boom from cli" - ok, output = AgentExecutor.run("p") - assert ok is False - assert output == "boom from cli" - - -def test_agent_executor_run_handles_missing_cli(): - with patch.object(taskboard.subprocess, "run", side_effect=FileNotFoundError()): - ok, output = AgentExecutor.run("p") - assert ok is False - assert "not found" in output - - -# ── _execute_task: claude success path ─────────────────────────────────────── -def test_execute_task_claude_success_persists_completed_and_events(scheduler): - db = scheduler.db - tid = db.add_task(Task(title="claude task", prompt="hello", working_dir=".", agent="claude")) - task = db.get_task(tid) - scheduler._active_tasks[tid] = object() # _execute_task pops this at the end - - fake = FakePopen(_claude_lines(result_text="All done.", session_id="sess-abc")) - with patch.object(taskboard.subprocess, "Popen", return_value=fake): - scheduler._execute_task(task) - - refreshed = db.get_task(tid) - assert refreshed["status"] == "completed" - assert refreshed["result"] == "All done." - assert refreshed["run_count"] == 1 - # session_id extracted from the trailing result event - assert refreshed["session_id"] == "sess-abc" - - runs = db.get_task_runs(tid) - assert len(runs) == 1 - assert runs[0]["status"] == "completed" - assert runs[0]["raw_output"] # raw stdout stored - - events = db.get_output_events(tid) - types = {e["event_type"] for e in events} - # assistant text, a tool_call, a tool_result, the result event, and the raw - # non-JSON line all persisted. - assert "assistant" in types - assert "tool_call" in types - assert "tool_result" in types - assert "result" in types - assert "text" in types # the malformed/non-JSON line - - -# ── _execute_task: codex success path ──────────────────────────────────────── -def test_execute_task_codex_success_persists_completed_and_events(scheduler, monkeypatch): - db = scheduler.db - tid = db.add_task(Task(title="codex task", prompt="hello", working_dir=".", agent="codex")) - task = db.get_task(tid) - scheduler._active_tasks[tid] = object() - - # No generated images for this run. - monkeypatch.setattr(scheduler, "_find_codex_generated_images", lambda *a, **k: []) - - fake = FakePopen(_codex_lines(thread_id="thread-xyz", final_text="Codex finished.")) - with patch.object(taskboard.subprocess, "Popen", return_value=fake): - scheduler._execute_task(task) - - refreshed = db.get_task(tid) - assert refreshed["status"] == "completed" - assert refreshed["result"] == "Codex finished." - # thread.started thread_id captured as session_id - assert refreshed["session_id"] == "thread-xyz" - - events = db.get_output_events(tid) - types = {e["event_type"] for e in events} - assert "command_execution" in types - # codex agent_message text stored as assistant output - assert "assistant" in types - - -def test_execute_task_codex_builds_resume_command_when_session_present(scheduler, monkeypatch): - db = scheduler.db - tid = db.add_task(Task(title="codex resume", prompt="again", working_dir=".", agent="codex")) - db.update_task(tid, session_id="prev-thread") - task = db.get_task(tid) - scheduler._active_tasks[tid] = object() - monkeypatch.setattr(scheduler, "_find_codex_generated_images", lambda *a, **k: []) - - captured = {} - - def fake_popen(cmd, **kwargs): - captured["cmd"] = cmd - return FakePopen(_codex_lines(thread_id="prev-thread", final_text="ok")) - - with patch.object(taskboard.subprocess, "Popen", side_effect=fake_popen): - scheduler._execute_task(task) - - cmd = captured["cmd"] - assert cmd[:4] == ["codex", "exec", "resume", "--json"] - assert "prev-thread" in cmd - assert "--dangerously-bypass-approvals-and-sandbox" in cmd - - -# ── _execute_task: failure path (non-zero exit) ────────────────────────────── -def test_execute_task_failure_sets_failed_with_error_summary(scheduler): - db = scheduler.db - tid = db.add_task(Task(title="boom", prompt="fail please", working_dir=".", agent="claude")) - task = db.get_task(tid) - scheduler._active_tasks[tid] = object() - - fake = FakePopen( - stdout_lines=[], - stderr_lines=["fatal: something exploded\n"], - returncode=1, - ) - with patch.object(taskboard.subprocess, "Popen", return_value=fake): - scheduler._execute_task(task) - - refreshed = db.get_task(tid) - assert refreshed["status"] == "failed" - assert "exploded" in (refreshed["error"] or "") - - runs = db.get_task_runs(tid) - assert runs[0]["status"] == "failed" - - -# ── _execute_task: failure still persists session_id (resumable retry) ─────── -def test_execute_task_codex_failure_still_persists_session_id(scheduler, monkeypatch): - """A codex run that emits ``thread.started`` then fails must still persist - the ``thread_id`` as ``session_id``. Otherwise a failed task cannot be - resumed (e.g. replying in the Feishu thread to retry) → "no saved session". - """ - db = scheduler.db - tid = db.add_task(Task(title="codex boom", prompt="x", working_dir=".", agent="codex")) - task = db.get_task(tid) - scheduler._active_tasks[tid] = object() - monkeypatch.setattr(scheduler, "_find_codex_generated_images", lambda *a, **k: []) - - stdout_lines = [ - json.dumps({"type": "thread.started", "thread_id": "thread-fail-1"}) + "\n", - ] - fake = FakePopen( - stdout_lines, - stderr_lines=["codex error: model overloaded\n"], - returncode=1, - ) - with patch.object(taskboard.subprocess, "Popen", return_value=fake): - scheduler._execute_task(task) - - refreshed = db.get_task(tid) - assert refreshed["status"] == "failed" - # The conversation id is preserved despite the failure → resumable. - assert refreshed["session_id"] == "thread-fail-1" - - -def test_execute_task_claude_failure_still_persists_session_id(scheduler): - """A claude run whose trailing ``result`` event carries a ``session_id`` - (e.g. ``error_during_execution``) must persist it on failure too. - """ - db = scheduler.db - tid = db.add_task(Task(title="claude boom", prompt="x", working_dir=".", agent="claude")) - task = db.get_task(tid) - scheduler._active_tasks[tid] = object() - - stdout_lines = [ - json.dumps({"type": "system", "subtype": "init", "session_id": "sess-fail-9"}) + "\n", - json.dumps( - { - "type": "result", - "subtype": "error_during_execution", - "session_id": "sess-fail-9", - } - ) - + "\n", - ] - fake = FakePopen(stdout_lines, stderr_lines=["boom\n"], returncode=1) - with patch.object(taskboard.subprocess, "Popen", return_value=fake): - scheduler._execute_task(task) - - refreshed = db.get_task(tid) - assert refreshed["status"] == "failed" - assert refreshed["session_id"] == "sess-fail-9" - - -# ── _execute_task: missing CLI binary ──────────────────────────────────────── -def test_execute_task_missing_binary_fails_with_install_hint(scheduler): - db = scheduler.db - tid = db.add_task(Task(title="no cli", prompt="x", working_dir=".", agent="codex")) - task = db.get_task(tid) - scheduler._active_tasks[tid] = object() - - with patch.object(taskboard.subprocess, "Popen", side_effect=FileNotFoundError()): - scheduler._execute_task(task) - - refreshed = db.get_task(tid) - assert refreshed["status"] == "failed" - assert "codex" in (refreshed["error"] or "") - assert "not found" in (refreshed["error"] or "") - - -# ── _execute_task: cron reschedule on success ──────────────────────────────── -def test_execute_task_cron_success_reschedules_instead_of_completing(scheduler): - db = scheduler.db - tid = db.add_task( - Task( - title="cron task", - prompt="tick", - working_dir=".", - agent="claude", - schedule_type=ScheduleType.CRON, - cron_expr="*/5 * * * *", - ) - ) - task = db.get_task(tid) - scheduler._active_tasks[tid] = object() - - fake = FakePopen(_claude_lines(result_text="tick done")) - with patch.object(taskboard.subprocess, "Popen", return_value=fake): - scheduler._execute_task(task) - - refreshed = db.get_task(tid) - # cron task with remaining runs reschedules rather than completing - assert refreshed["status"] == "scheduled" - assert refreshed["next_run_at"] - assert refreshed["run_count"] == 1 - - -# ── _execute_task: image path handling (safe load + unsafe reject) ─────────── -def test_execute_task_claude_loads_safe_image_and_streams_via_stdin(scheduler): - """A real PNG under /tmp is a safe path → base64-loaded → claude switches to - the stdin ``--input-format stream-json`` multimodal command; an unsafe path - outside the allowed roots is rejected and never loaded. - """ - db = scheduler.db - # /tmp is one of the hard-coded allowed roots (realpaths cleanly on mac/linux). - fd_dir = tempfile.mkdtemp(dir="/tmp") - img = os.path.join(fd_dir, "pic.png") - with open(img, "wb") as f: - f.write(b"\x89PNG\r\n\x1a\nfakepng") - - tid = db.add_task( - Task( - title="img task", - prompt="see image", - working_dir=".", - agent="claude", - image_paths=[img, "/etc/shadow"], # one safe, one rejected - ) - ) - task = db.get_task(tid) - scheduler._active_tasks[tid] = object() - - captured = {} - - def fake_popen(cmd, **kwargs): - captured["cmd"] = cmd - captured["stdin"] = kwargs.get("stdin") - return FakePopen(_claude_lines(result_text="saw it")) - - with patch.object(taskboard.subprocess, "Popen", side_effect=fake_popen): - scheduler._execute_task(task) - - refreshed = db.get_task(tid) - assert refreshed["status"] == "completed" - # Safe image loaded → multimodal stdin path selected. - cmd = captured["cmd"] - assert "--input-format" in cmd - assert cmd[cmd.index("--input-format") + 1] == "stream-json" - assert captured["stdin"] is taskboard.subprocess.PIPE - - -def test_execute_task_codex_passes_image_flag(scheduler, monkeypatch): - db = scheduler.db - fd_dir = tempfile.mkdtemp(dir="/tmp") - img = os.path.join(fd_dir, "shot.png") - with open(img, "wb") as f: - f.write(b"\x89PNG\r\n\x1a\nfakepng") - - tid = db.add_task( - Task(title="codex img", prompt="render", working_dir=".", agent="codex", image_paths=[img]) - ) - task = db.get_task(tid) - scheduler._active_tasks[tid] = object() - monkeypatch.setattr(scheduler, "_find_codex_generated_images", lambda *a, **k: []) - - captured = {} - - def fake_popen(cmd, **kwargs): - captured["cmd"] = cmd - return FakePopen(_codex_lines(final_text="rendered")) - - with patch.object(taskboard.subprocess, "Popen", side_effect=fake_popen): - scheduler._execute_task(task) - - cmd = captured["cmd"] - assert "--image" in cmd - assert cmd[cmd.index("--image") + 1] == img - - -def test_execute_task_claude_resume_appends_session_flag(scheduler): - db = scheduler.db - tid = db.add_task(Task(title="resume", prompt="continue", working_dir=".", agent="claude")) - db.update_task(tid, session_id="claude-sess-1") - task = db.get_task(tid) - scheduler._active_tasks[tid] = object() - - captured = {} - - def fake_popen(cmd, **kwargs): - captured["cmd"] = cmd - return FakePopen(_claude_lines(result_text="resumed", session_id="claude-sess-1")) - - with patch.object(taskboard.subprocess, "Popen", side_effect=fake_popen): - scheduler._execute_task(task) - - cmd = captured["cmd"] - assert "--resume" in cmd - assert cmd[cmd.index("--resume") + 1] == "claude-sess-1" - - -# ── _execute_task: timeout / kill path ─────────────────────────────────────── -def test_execute_task_timeout_kills_group_and_marks_failed(scheduler): - """A short configured timeout fires the kill timer while stdout is still - streaming, exercising ``_kill`` (killpg → kill fallback) and the - ``timed_out`` failure branch. - """ - db = scheduler.db - db.set_setting("timeout", "0") # threading.Timer(0, _kill) fires immediately - tid = db.add_task(Task(title="slow", prompt="hang", working_dir=".", agent="claude")) - task = db.get_task(tid) - scheduler._active_tasks[tid] = object() - - def slow_lines(): - # Give the timer (delay 0) a moment to fire mid-stream. - time.sleep(0.2) - yield json.dumps({"type": "system", "subtype": "init"}) + "\n" - - fake = FakePopen(slow_lines()) - with patch.object(taskboard.subprocess, "Popen", return_value=fake): - scheduler._execute_task(task) - - refreshed = db.get_task(tid) - assert refreshed["status"] == "failed" - # The run record preserves the raw "Task timed out after Ns" message. - runs = db.get_task_runs(tid) - assert runs[0]["status"] == "failed" - assert "timed out" in (runs[0]["error"] or "") - - -def test_execute_task_timeout_error_summary_states_timeout_not_stderr(scheduler, monkeypatch): - """On timeout the human-readable ``task.error`` must say it timed out, not - surface an unrelated stderr line. Regression: codex prints "Reading - additional input from stdin…" to stderr, which ``_extract_error_summary`` - picked over the real "Task timed out after Ns" reason. - """ - db = scheduler.db - db.set_setting("timeout", "0") # kill timer (delay 0) fires immediately - tid = db.add_task(Task(title="slow review", prompt="hang", working_dir=".", agent="codex")) - task = db.get_task(tid) - scheduler._active_tasks[tid] = object() - monkeypatch.setattr(scheduler, "_find_codex_generated_images", lambda *a, **k: []) - - def slow_lines(): - time.sleep(0.2) # let the delay-0 timer fire mid-stream - yield json.dumps({"type": "thread.started", "thread_id": "t-1"}) + "\n" - - fake = FakePopen( - slow_lines(), - stderr_lines=["Reading additional input from stdin...\n"], - returncode=0, - ) - with patch.object(taskboard.subprocess, "Popen", return_value=fake): - scheduler._execute_task(task) - - refreshed = db.get_task(tid) - assert refreshed["status"] == "failed" - # error summary states the timeout, not the stderr noise - assert "timed out" in (refreshed["error"] or "") - assert "stdin" not in (refreshed["error"] or "") - - -# ── _run_agent_command: heartbeat/skill-sweep invocation ───────────────────── -def test_run_agent_command_claude_returns_result_text(scheduler): - db = scheduler.db - lines = [ - json.dumps( - { - "type": "assistant", - "message": { - "id": "m1", - "content": [{"type": "text", "text": "intermediate"}], - }, - } - ) - + "\n", - json.dumps({"type": "result", "result": "FINAL DECISION"}) + "\n", - ] - fake = FakePopen(lines, returncode=0) - seen = [] - with patch.object(taskboard.subprocess, "Popen", return_value=fake): - ok, out = scheduler._run_agent_command( - "claude", - ["claude", "-p", "decide"], - ".", - on_stdout_line=seen.append, - ) - assert ok is True - assert out == "FINAL DECISION" - assert any("FINAL DECISION" in s for s in seen) - # db unused here but keep reference to satisfy fixture wiring - assert db is not None - - -def test_run_agent_command_codex_returns_last_agent_message(scheduler): - fake = FakePopen(_codex_lines(final_text="codex decision"), returncode=0) - with patch.object(taskboard.subprocess, "Popen", return_value=fake): - ok, out = scheduler._run_agent_command("codex", ["codex", "exec"], ".") - assert ok is True - assert out == "codex decision" - - -def test_run_agent_command_nonzero_returns_stderr(scheduler): - fake = FakePopen([], stderr_lines=["heartbeat blew up\n"], returncode=2) - with patch.object(taskboard.subprocess, "Popen", return_value=fake): - ok, out = scheduler._run_agent_command("claude", ["claude", "-p", "x"], ".") - assert ok is False - assert "blew up" in out - - -def test_run_agent_command_missing_binary(scheduler): - with patch.object(taskboard.subprocess, "Popen", side_effect=FileNotFoundError()): - ok, out = scheduler._run_agent_command("claude", ["claude"], ".") - assert ok is False - assert "not found" in out - - -# ── _extract_error_summary: branches ───────────────────────────────────────── -def test_extract_error_summary_prefers_short_plain_stderr(scheduler): - summary = scheduler._extract_error_summary("permission denied", "") - assert summary == "permission denied" - - -def test_extract_error_summary_parses_stream_json_error_event(scheduler): - stdout = "\n".join( - [ - json.dumps({"type": "system", "subtype": "init"}), - json.dumps({"type": "error", "error": "rate limited"}), - ] - ) - summary = scheduler._extract_error_summary("", stdout) - assert summary == "rate limited" - - -def test_extract_error_summary_falls_back_to_last_assistant_text(scheduler): - stdout = json.dumps( - { - "type": "assistant", - "message": {"content": [{"type": "text", "text": "I could not finish."}]}, - } - ) - summary = scheduler._extract_error_summary("", stdout) - assert summary == "I could not finish." diff --git a/tests/test_feishu_forwarded_messages.py b/tests/test_feishu_forwarded_messages.py deleted file mode 100644 index 9f51a25..0000000 --- a/tests/test_feishu_forwarded_messages.py +++ /dev/null @@ -1,316 +0,0 @@ -""" -Tests for Feishu forwarded/quoted message handling functionality. -""" - -import json -from unittest.mock import Mock, patch - -import pytest - - -@pytest.fixture -def mock_feishu_channel(): - """Create a mock FeishuChannel instance for testing.""" - with patch("channels.feishu_channel.FEISHU_AVAILABLE", True): - from channels.feishu_channel import FeishuChannel - - bus = Mock() - db = Mock() - scheduler = Mock() - - channel = FeishuChannel(bus, db, scheduler) - - # Mock the lark client - channel._client = Mock() - - return channel - - -class TestForwardedMessageDetection: - """Test the detection and parsing of forwarded/quoted messages.""" - - def test_extract_forwarded_content_forward_type(self, mock_feishu_channel): - """Test extraction of 'forward' type messages.""" - message = Mock() - message.message_type = "forward" - message.content = json.dumps( - { - "sender_name": "张三", - "sender_id": "ou_123456789", - "create_time": 1738080000, - "text": "这是一条转发的消息", - "images": [], - } - ) - - result = mock_feishu_channel._extract_forwarded_content(message) - - assert result is not None - assert result["type"] == "forward" - assert result["sender_name"] == "张三" - assert result["sender_id"] == "ou_123456789" - assert result["timestamp"] == 1738080000 - assert result["text"] == "这是一条转发的消息" - - def test_extract_forwarded_content_quote_type(self, mock_feishu_channel): - """Test extraction of quote type messages.""" - message = Mock() - message.message_type = "post" - message.content = json.dumps( - { - "zh_cn": { - "content": [ - [ - { - "tag": "quote", - "text": "被引用的文本内容", - "user": {"name": "李四", "open_id": "ou_987654321"}, - "create_time": 1738083600, - } - ] - ] - } - } - ) - - result = mock_feishu_channel._extract_forwarded_content(message) - - assert result is not None - assert result["type"] == "quote" - assert result["sender_name"] == "李四" - assert result["sender_id"] == "ou_987654321" - assert result["text"] == "被引用的文本内容" - assert result["timestamp"] == 1738083600 - - def test_extract_forwarded_content_nested_message(self, mock_feishu_channel): - """Test extraction of nested_message type (forward) in post.""" - message = Mock() - message.message_type = "post" - message.content = json.dumps( - { - "content": [ - [ - { - "tag": "nested_message", - "nested_message": { - "sender_name": "王五", - "sender_id": "ou_555555555", - "create_time": 1738087200, - "text": "嵌套消息内容", - "images": [{"image_key": "img_v2_abcd1234"}], - }, - } - ] - ] - } - ) - - result = mock_feishu_channel._extract_forwarded_content(message) - - assert result is not None - assert result["type"] == "forward" - assert result["sender_name"] == "王五" - assert result["text"] == "嵌套消息内容" - assert len(result["images"]) == 1 - assert result["images"][0]["image_key"] == "img_v2_abcd1234" - - def test_extract_forwarded_content_no_forward(self, mock_feishu_channel): - """Test that regular messages return None.""" - message = Mock() - message.message_type = "text" - message.content = json.dumps({"text": "普通消息"}) - - result = mock_feishu_channel._extract_forwarded_content(message) - - assert result is None - - def test_extract_forwarded_content_malformed_json(self, mock_feishu_channel): - """Test handling of malformed JSON.""" - message = Mock() - message.message_type = "forward" - message.content = "{invalid json" - - result = mock_feishu_channel._extract_forwarded_content(message) - - assert result is None - - -class TestForwardedPromptFormatting: - """Test the formatting of forwarded content into prompts.""" - - def test_format_forwarded_prompt_basic(self, mock_feishu_channel): - """Test basic formatting of forwarded content.""" - forwarded = { - "type": "forward", - "sender_name": "张三", - "sender_id": "ou_123456", - "timestamp": 1738080000, - "text": "这是转发的内容", - "images": [], - } - original_content = "请帮我分析上述消息" - - result = mock_feishu_channel._format_forwarded_prompt(original_content, forwarded) - - assert "📨 [转发消息]" in result - assert "转发自: 张三" in result - assert "时间: 2025-01-29 00:00" in result # Local timezone (UTC+8) - assert "--- 转发内容 ---" in result - assert "这是转发的内容" in result - assert "--- 用户附加消息 ---" in result - assert "请帮我分析上述消息" in result - - def test_format_forwarded_prompt_no_timestamp(self, mock_feishu_channel): - """Test formatting when timestamp is missing.""" - forwarded = { - "type": "forward", - "sender_name": "李四", - "text": "无时间戳的转发", - "images": [], - } - original_content = "看看这个" - - result = mock_feishu_channel._format_forwarded_prompt(original_content, forwarded) - - assert "转发自: 李四" in result - assert "时间:" not in result - - def test_format_forwarded_prompt_with_images(self, mock_feishu_channel): - """Test formatting when forwarded content includes images.""" - forwarded = { - "type": "forward", - "sender_name": "王五", - "text": "一张图片", - "images": [{"image_key": "img1"}, {"image_key": "img2"}], - } - original_content = "" - - result = mock_feishu_channel._format_forwarded_prompt(original_content, forwarded) - - assert "[包含 2 张图片]" in result - - def test_format_forwarded_prompt_no附加消息(self, mock_feishu_channel): - """Test formatting when user didn't add additional message.""" - forwarded = { - "type": "quote", - "sender_name": "赵六", - "text": "只是引用没有附加消息", - "images": [], - } - original_content = " " # Only spaces - - result = mock_feishu_channel._format_forwarded_prompt(original_content, forwarded) - - assert "--- 转发内容 ---" in result - # Should not have "用户附加消息" section when original is empty - assert "--- 用户附加消息 ---" not in result - - def test_format_forwarded_prompt_none_forwarded(self, mock_feishu_channel): - """Test that None forwarded returns original content unchanged.""" - original_content = "这是一条普通消息" - - result = mock_feishu_channel._format_forwarded_prompt(original_content, None) - - assert result == original_content - - def test_format_forwarded_prompt_empty_forwarded(self, mock_feishu_channel): - """Test that empty dict forwarded returns original content.""" - original_content = "这是一条普通消息" - - result = mock_feishu_channel._format_forwarded_prompt(original_content, {}) - - assert result == original_content - - -class TestForwardedImageHandling: - """Test handling of images in forwarded messages.""" - - def test_download_image_called_for_forwarded_images(self, mock_feishu_channel): - """Test that images in forwarded messages are downloaded.""" - # Simulate forwarded message with images - forwarded = { - "type": "forward", - "sender_name": "测试用户", - "text": "带图片的转发", - "images": [{"image_key": "img_key_1"}, {"image_key": "img_key_2"}], - } - - message = Mock() - message.message_type = "post" - message.message_id = "msg_123" - message.content = json.dumps({"zh_cn": {"content": [[]]}}) - - # Mock image download to return paths - mock_feishu_channel._download_image = Mock(return_value="/tmp/test.jpg") - - # Simulate the integration in _handle_inbound - image_paths = [] - for img_info in forwarded.get("images", []): - img_key = img_info.get("image_key") - if img_key: - img_path = mock_feishu_channel._download_image(message.message_id, img_key) - if img_path: - image_paths.append(img_path) - - assert len(image_paths) == 2 - assert all("/tmp/test.jpg" in path for path in image_paths) - - -class TestForwardedMessageScenarios: - """Test real-world scenarios of forwarded messages.""" - - def test_telegram_forwarded_from_user(self, mock_feishu_channel): - """Simulate a Telegram-style forwarded message converted to Feishu format.""" - forwarded = { - "type": "forward", - "sender_name": "Alice", - "sender_id": "telegram_user_12345", - "timestamp": 1738080000, - "text": "Hey, did you see the new feature?", - "images": [], - } - original_content = "Can you explain this feature?" - - result = mock_feishu_channel._format_forwarded_prompt(original_content, forwarded) - - assert "转发自: Alice" in result - assert "Hey, did you see the new feature?" in result - assert "Can you explain this feature?" in result - - def test_channel_forwarded_post(self, mock_feishu_channel): - """Simulate a forwarded post from a channel.""" - forwarded = { - "type": "forward", - "sender_name": "技术资讯频道", - "text": "发布了一个新的AI模型,效果惊人...\n\nLink: https://example.com", - "images": [{"image_key": "chart_123"}], - "timestamp": 1738087200, - } - original_content = "帮我总结一下这个新闻" - - result = mock_feishu_channel._format_forwarded_prompt(original_content, forwarded) - - assert "转发自: 技术资讯频道" in result - assert "发布了一个新的AI模型" in result - assert "[包含 1 张图片]" in result - assert "帮我总结一下这个新闻" in result - - def test_nested_forward_chain(self, mock_feishu_channel): - """Test handling of a message that has been forwarded multiple times.""" - forwarded = { - "type": "forward", - "sender_name": "传播者B", - "text": "传播者A: 原始发布者: 这是最初的消息", - "timestamp": 1738090800, - "images": [], - } - original_content = "" - - result = mock_feishu_channel._format_forwarded_prompt(original_content, forwarded) - - assert "转发自: 传播者B" in result - assert "传播者A: 原始发布者: 这是最初的消息" in result - - -if __name__ == "__main__": - pytest.main([__file__, "-v"]) diff --git a/tests/test_feishu_inbound.py b/tests/test_feishu_inbound.py deleted file mode 100644 index 49baf21..0000000 --- a/tests/test_feishu_inbound.py +++ /dev/null @@ -1,597 +0,0 @@ -""" -Tests for Feishu inbound event handling: the WebSocket dispatch layer. - -Covers _on_reaction, _on_bot_added, _on_message_sync and the big -_handle_inbound dispatcher (command parsing, plain-message task creation, -resume-by-reply via thread, and malformed-payload handling). - -These tests isolate the dispatch logic by mocking the lark client, the DB, -the scheduler, the bus, and the card/reply/reaction helpers, so nothing here -opens a real WebSocket or hits the network. -""" - -import json -from types import SimpleNamespace -from unittest.mock import Mock, patch - -import pytest - - -@pytest.fixture -def mock_feishu_channel(): - """Create a FeishuChannel with all external dependencies mocked.""" - with patch("channels.feishu_channel.FEISHU_AVAILABLE", True): - from channels.feishu_channel import FeishuChannel - - channel = FeishuChannel(Mock(), Mock(), Mock()) - channel._client = Mock() - channel._running = True - - # Stub every outbound helper so dispatch logic is isolated. - channel._send_message = Mock(return_value="om_sent") - channel._reply_message = Mock(return_value="om_reply") - channel._add_reaction = Mock() - channel._create_reply = Mock(return_value="om_running") - channel._build_streaming_card = Mock(return_value={"card": True}) - channel._start_streaming = Mock() - channel._download_image = Mock(return_value=None) - channel._extract_forwarded_content = Mock(return_value=None) - return channel - - -def _make_event( - *, - content, - msg_type="text", - sender_type="user", - open_id="ou_sender", - chat_type="p2p", - chat_id="oc_chat", - message_id="om_msg", - parent_id=None, - root_id=None, -): - """Build a synthetic lark im.message.receive_v1 event object.""" - sender_id = SimpleNamespace(open_id=open_id) if open_id is not None else None - sender = SimpleNamespace(sender_type=sender_type, sender_id=sender_id) - message = SimpleNamespace( - message_type=msg_type, - content=content, - message_id=message_id, - chat_type=chat_type, - chat_id=chat_id, - parent_id=parent_id, - root_id=root_id, - ) - event = SimpleNamespace(message=message, sender=sender) - return SimpleNamespace(event=event) - - -def _text(text): - return json.dumps({"text": text}) - - -# ───────────────────────── trivial handlers ───────────────────────── - - -class TestSimpleHandlers: - def test_on_reaction_is_noop(self, mock_feishu_channel): - # Should never raise and never touch any helper. - assert mock_feishu_channel._on_reaction(SimpleNamespace(event=None)) is None - mock_feishu_channel._send_message.assert_not_called() - - def test_on_bot_added_sends_help(self, mock_feishu_channel): - from channels.feishu_channel import HELP_TEXT - - data = SimpleNamespace(event=SimpleNamespace(chat_id="oc_new")) - mock_feishu_channel._on_bot_added(data) - - mock_feishu_channel._send_message.assert_called_once_with("oc_new", HELP_TEXT) - - def test_on_bot_added_without_chat_id(self, mock_feishu_channel): - data = SimpleNamespace(event=SimpleNamespace(chat_id=None)) - mock_feishu_channel._on_bot_added(data) - - mock_feishu_channel._send_message.assert_not_called() - - def test_on_bot_added_swallows_errors(self, mock_feishu_channel): - # event has no chat_id attribute at all -> getattr returns None, no raise. - bad = SimpleNamespace(event=object()) - mock_feishu_channel._on_bot_added(bad) - mock_feishu_channel._send_message.assert_not_called() - - def test_on_bot_added_swallows_send_errors(self, mock_feishu_channel): - # _send_message raising inside the handler must be caught (traceback path). - mock_feishu_channel._send_message = Mock(side_effect=RuntimeError("send failed")) - data = SimpleNamespace(event=SimpleNamespace(chat_id="oc_new")) - # Should not raise. - mock_feishu_channel._on_bot_added(data) - - def test_on_message_sync_delegates_to_handle_inbound(self, mock_feishu_channel): - mock_feishu_channel._handle_inbound = Mock() - sentinel = object() - mock_feishu_channel._on_message_sync(sentinel) - mock_feishu_channel._handle_inbound.assert_called_once_with(sentinel) - - def test_on_message_sync_swallows_handler_errors(self, mock_feishu_channel): - mock_feishu_channel._handle_inbound = Mock(side_effect=RuntimeError("boom")) - # Should not propagate. - mock_feishu_channel._on_message_sync(object()) - - def test_on_message_sync_ignores_after_stop(self, mock_feishu_channel): - mock_feishu_channel._running = False - mock_feishu_channel._handle_inbound = Mock() - - mock_feishu_channel._on_message_sync(object()) - - mock_feishu_channel._handle_inbound.assert_not_called() - - -# ───────────────────────── message parsing ────────────────────────── - - -class TestInboundParsing: - def test_bot_self_message_ignored(self, mock_feishu_channel): - data = _make_event(content=_text("hi"), sender_type="bot") - mock_feishu_channel._handle_inbound(data) - mock_feishu_channel._add_reaction.assert_not_called() - mock_feishu_channel.scheduler.submit_task.assert_not_called() - - def test_unsupported_message_type_ignored(self, mock_feishu_channel): - data = _make_event(content=json.dumps({}), msg_type="audio") - mock_feishu_channel._handle_inbound(data) - mock_feishu_channel._add_reaction.assert_not_called() - mock_feishu_channel.scheduler.submit_task.assert_not_called() - - def test_empty_text_after_strip_ignored(self, mock_feishu_channel): - data = _make_event(content=_text(" ")) - mock_feishu_channel._handle_inbound(data) - mock_feishu_channel._add_reaction.assert_not_called() - mock_feishu_channel.scheduler.submit_task.assert_not_called() - - def test_malformed_text_json_falls_back_to_raw(self, mock_feishu_channel): - # Invalid JSON -> uses raw content; "{bad" is non-empty so it creates a task. - mock_feishu_channel.scheduler.submit_task.return_value = 1 - mock_feishu_channel.db.get_task.return_value = {"image_paths": [], "prompt_images": []} - with ( - patch("channels.dir_utils.resolve_working_dir", return_value="/tmp"), - patch("channels.agent_utils.resolve_agent", return_value="claude"), - ): - mock_feishu_channel._handle_inbound(_make_event(content="{bad")) - mock_feishu_channel.scheduler.submit_task.assert_called_once() - - def test_post_message_extracts_text(self, mock_feishu_channel): - post = json.dumps( - { - "zh_cn": { - "title": "标题", - "content": [[{"tag": "text", "text": "正文内容"}]], - } - } - ) - mock_feishu_channel.scheduler.submit_task.return_value = 7 - mock_feishu_channel.db.get_task.return_value = {"image_paths": [], "prompt_images": []} - with ( - patch("channels.dir_utils.resolve_working_dir", return_value="/tmp"), - patch("channels.agent_utils.resolve_agent", return_value="claude"), - ): - mock_feishu_channel._handle_inbound(_make_event(content=post, msg_type="post")) - - task = mock_feishu_channel.scheduler.submit_task.call_args.args[0] - assert task.prompt == "标题\n正文内容" - - def test_post_message_with_image_default_prompt(self, mock_feishu_channel): - post = json.dumps({"content": [[{"tag": "img", "image_key": "img_x"}]]}) - mock_feishu_channel._download_image = Mock(return_value="/tmp/pic.png") - mock_feishu_channel.scheduler.submit_task.return_value = 8 - mock_feishu_channel.db.get_task.return_value = {"image_paths": [], "prompt_images": []} - with ( - patch("channels.dir_utils.resolve_working_dir", return_value="/tmp"), - patch("channels.agent_utils.resolve_agent", return_value="claude"), - patch("builtins.open", side_effect=OSError("no file")), - ): - mock_feishu_channel._handle_inbound(_make_event(content=post, msg_type="post")) - - task = mock_feishu_channel.scheduler.submit_task.call_args.args[0] - assert task.prompt == "请分析这些图片的内容" - assert task.image_paths == ["/tmp/pic.png"] - - def test_post_message_image_download_failure(self, mock_feishu_channel): - # img download returns None -> no image attached, default prompt, no task - # (empty content + no images). - post = json.dumps({"content": [[{"tag": "img", "image_key": "img_x"}]]}) - mock_feishu_channel._download_image = Mock(return_value=None) - mock_feishu_channel.scheduler.submit_task.return_value = 8 - mock_feishu_channel.db.get_task.return_value = {"image_paths": [], "prompt_images": []} - with ( - patch("channels.dir_utils.resolve_working_dir", return_value="/tmp"), - patch("channels.agent_utils.resolve_agent", return_value="claude"), - ): - mock_feishu_channel._handle_inbound(_make_event(content=post, msg_type="post")) - # No image and no text -> content stays empty -> ignored. - mock_feishu_channel.scheduler.submit_task.assert_not_called() - - def test_single_image_download_failure(self, mock_feishu_channel): - img = json.dumps({"image_key": "img_single"}) - mock_feishu_channel._download_image = Mock(return_value=None) - mock_feishu_channel.scheduler.submit_task.return_value = 9 - mock_feishu_channel.db.get_task.return_value = {"image_paths": [], "prompt_images": []} - with ( - patch("channels.dir_utils.resolve_working_dir", return_value="/tmp"), - patch("channels.agent_utils.resolve_agent", return_value="claude"), - ): - mock_feishu_channel._handle_inbound(_make_event(content=img, msg_type="image")) - # Still creates a task with default prompt but no image_paths. - task = mock_feishu_channel.scheduler.submit_task.call_args.args[0] - assert task.prompt == "请分析这张图片的内容" - assert task.image_paths == [] - - def test_post_message_malformed_json_ignored(self, mock_feishu_channel): - mock_feishu_channel._handle_inbound(_make_event(content="{not json", msg_type="post")) - # content becomes "" -> ignored before reaction. - mock_feishu_channel._add_reaction.assert_not_called() - mock_feishu_channel.scheduler.submit_task.assert_not_called() - - def test_single_image_message_downloads_and_creates_task(self, mock_feishu_channel): - img = json.dumps({"image_key": "img_single"}) - mock_feishu_channel._download_image = Mock(return_value="/tmp/single.jpg") - mock_feishu_channel.scheduler.submit_task.return_value = 9 - mock_feishu_channel.db.get_task.return_value = {"image_paths": [], "prompt_images": []} - with ( - patch("channels.dir_utils.resolve_working_dir", return_value="/tmp"), - patch("channels.agent_utils.resolve_agent", return_value="claude"), - patch("builtins.open", side_effect=OSError("no file")), - ): - mock_feishu_channel._handle_inbound(_make_event(content=img, msg_type="image")) - - mock_feishu_channel._download_image.assert_called_once_with("om_msg", "img_single") - task = mock_feishu_channel.scheduler.submit_task.call_args.args[0] - assert task.prompt == "请分析这张图片的内容" - assert task.image_paths == ["/tmp/single.jpg"] - - def test_single_image_message_malformed_json(self, mock_feishu_channel): - mock_feishu_channel.scheduler.submit_task.return_value = 10 - mock_feishu_channel.db.get_task.return_value = {"image_paths": [], "prompt_images": []} - with ( - patch("channels.dir_utils.resolve_working_dir", return_value="/tmp"), - patch("channels.agent_utils.resolve_agent", return_value="claude"), - ): - mock_feishu_channel._handle_inbound(_make_event(content="{bad", msg_type="image")) - # Falls back to default image prompt -> still creates a task. - task = mock_feishu_channel.scheduler.submit_task.call_args.args[0] - assert task.prompt == "请分析这张图片的内容" - - def test_forwarded_content_merged_into_prompt(self, mock_feishu_channel): - mock_feishu_channel._extract_forwarded_content = Mock( - return_value={"sender_name": "Bob", "images": [{"image_key": "img_fwd"}]} - ) - mock_feishu_channel._format_forwarded_prompt = Mock(return_value="FORMATTED PROMPT") - mock_feishu_channel._download_image = Mock(return_value="/tmp/fwd.png") - mock_feishu_channel.scheduler.submit_task.return_value = 11 - mock_feishu_channel.db.get_task.return_value = {"image_paths": [], "prompt_images": []} - with ( - patch("channels.dir_utils.resolve_working_dir", return_value="/tmp"), - patch("channels.agent_utils.resolve_agent", return_value="claude"), - patch("builtins.open", side_effect=OSError("no file")), - ): - mock_feishu_channel._handle_inbound(_make_event(content=_text("看看这个"))) - - task = mock_feishu_channel.scheduler.submit_task.call_args.args[0] - assert task.prompt == "FORMATTED PROMPT" - assert "/tmp/fwd.png" in task.image_paths - - -# ───────────────────────── command parsing ────────────────────────── - - -class TestCommands: - def test_help_command(self, mock_feishu_channel): - from channels.feishu_channel import HELP_TEXT - - mock_feishu_channel._handle_inbound(_make_event(content=_text("/help"))) - mock_feishu_channel._send_message.assert_called_once_with("ou_sender", HELP_TEXT) - mock_feishu_channel.scheduler.submit_task.assert_not_called() - - def test_start_command(self, mock_feishu_channel): - from channels.feishu_channel import HELP_TEXT - - mock_feishu_channel._handle_inbound(_make_event(content=_text("/start"))) - mock_feishu_channel._send_message.assert_called_once_with("ou_sender", HELP_TEXT) - - def test_group_chat_replies_to_chat_id(self, mock_feishu_channel): - from channels.feishu_channel import HELP_TEXT - - data = _make_event(content=_text("/help"), chat_type="group", chat_id="oc_group") - mock_feishu_channel._handle_inbound(data) - mock_feishu_channel._send_message.assert_called_once_with("oc_group", HELP_TEXT) - - def test_dir_command(self, mock_feishu_channel): - with patch("channels.dir_utils.handle_dir_command", return_value="dir set") as handler: - mock_feishu_channel._handle_inbound(_make_event(content=_text("/dir ~/proj"))) - handler.assert_called_once_with("/dir ~/proj", "feishu", mock_feishu_channel.db) - mock_feishu_channel._send_message.assert_called_once_with("ou_sender", "dir set") - mock_feishu_channel.scheduler.submit_task.assert_not_called() - - def test_cd_alias_command(self, mock_feishu_channel): - with patch("channels.dir_utils.handle_dir_command", return_value=None) as handler: - mock_feishu_channel._handle_inbound(_make_event(content=_text("/cd ~/x"))) - handler.assert_called_once() - # reply is None -> nothing sent. - mock_feishu_channel._send_message.assert_not_called() - - def test_agent_command(self, mock_feishu_channel): - with patch( - "channels.agent_utils.handle_agent_command", return_value="agent=codex" - ) as handler: - mock_feishu_channel._handle_inbound(_make_event(content=_text("/agent codex"))) - handler.assert_called_once_with("/agent codex", "feishu", mock_feishu_channel.db) - mock_feishu_channel._send_message.assert_called_once_with("ou_sender", "agent=codex") - - def test_ccu_command(self, mock_feishu_channel): - mock_feishu_channel._get_usage_stats = Mock(return_value="usage report") - mock_feishu_channel._handle_inbound(_make_event(content=_text("/ccu 5"))) - mock_feishu_channel._get_usage_stats.assert_called_once() - mock_feishu_channel._send_message.assert_called_once_with("ou_sender", "usage report") - - def test_status_command_found(self, mock_feishu_channel): - mock_feishu_channel.db.get_task.return_value = { - "status": "completed", - "title": "My Task", - } - mock_feishu_channel._handle_inbound(_make_event(content=_text("/status 42"))) - mock_feishu_channel.db.get_task.assert_called_once_with(42) - sent = mock_feishu_channel._send_message.call_args.args[1] - assert "Task #42" in sent - assert "completed" in sent - assert "✅" in sent - assert "My Task" in sent - - def test_status_command_not_found(self, mock_feishu_channel): - mock_feishu_channel.db.get_task.return_value = None - mock_feishu_channel._handle_inbound(_make_event(content=_text("/status 99"))) - sent = mock_feishu_channel._send_message.call_args.args[1] - assert "❌" in sent and "#99 not found" in sent - - def test_status_command_non_numeric_is_noop(self, mock_feishu_channel): - mock_feishu_channel._handle_inbound(_make_event(content=_text("/status abc"))) - mock_feishu_channel._send_message.assert_not_called() - mock_feishu_channel.scheduler.submit_task.assert_not_called() - - def test_system_notification_filtered_out(self, mock_feishu_channel): - data = _make_event(content=_text("✅ 任务完成 Task #1")) - mock_feishu_channel._handle_inbound(data) - # Reaction added (passes parse) but no task created and no reply. - mock_feishu_channel._add_reaction.assert_called_once() - mock_feishu_channel.scheduler.submit_task.assert_not_called() - - -# ───────────────────────── /resume command ────────────────────────── - - -class TestResumeCommand: - def test_resume_success(self, mock_feishu_channel): - mock_feishu_channel.db.get_task.side_effect = [ - {"session_id": "sess_1", "title": "Resumed"}, # initial check - {"session_id": "sess_1", "title": "Resumed"}, # after update - ] - mock_feishu_channel._handle_inbound(_make_event(content=_text("/resume 5 keep going"))) - - mock_feishu_channel.db.update_task.assert_called_once() - args, kwargs = mock_feishu_channel.db.update_task.call_args - assert args[0] == 5 - assert kwargs["status"] == "pending" - assert kwargs["prompt"] == "keep going" - assert mock_feishu_channel._task_origin[5] == ("ou_sender", "om_msg", "om_msg") - mock_feishu_channel._create_reply.assert_called_once() - mock_feishu_channel._start_streaming.assert_called_once_with(5, "om_running", "Resumed") - - def test_resume_task_without_session(self, mock_feishu_channel): - mock_feishu_channel.db.get_task.return_value = {"session_id": None, "title": "x"} - mock_feishu_channel._handle_inbound(_make_event(content=_text("/resume 5 continue"))) - mock_feishu_channel.db.update_task.assert_not_called() - sent = mock_feishu_channel._send_message.call_args.args[1] - assert "#5 not found or has no saved session" in sent - - def test_resume_invalid_syntax(self, mock_feishu_channel): - mock_feishu_channel._handle_inbound(_make_event(content=_text("/resume 5"))) - mock_feishu_channel.db.update_task.assert_not_called() - sent = mock_feishu_channel._send_message.call_args.args[1] - assert "Usage:" in sent and "/resume" in sent - - def test_resume_non_numeric_id(self, mock_feishu_channel): - mock_feishu_channel._handle_inbound(_make_event(content=_text("/resume abc hello"))) - mock_feishu_channel.db.update_task.assert_not_called() - sent = mock_feishu_channel._send_message.call_args.args[1] - assert "Usage:" in sent - - def test_resume_no_running_msg_skips_streaming(self, mock_feishu_channel): - mock_feishu_channel._create_reply = Mock(return_value=None) - mock_feishu_channel.db.get_task.return_value = { - "session_id": "sess", - "title": "T", - } - mock_feishu_channel._handle_inbound(_make_event(content=_text("/resume 3 go"))) - mock_feishu_channel._start_streaming.assert_not_called() - - -# ────────────────────── resume-by-reply in thread ─────────────────── - - -class TestThreadResume: - def test_thread_reply_resumes_via_notification_map(self, mock_feishu_channel): - mock_feishu_channel._notification_map["om_parent"] = 12 - mock_feishu_channel.db.get_task.return_value = { - "session_id": "sess", - "title": "Threaded", - } - data = _make_event(content=_text("继续"), parent_id="om_parent") - mock_feishu_channel._handle_inbound(data) - - mock_feishu_channel.db.update_task.assert_called_once() - args, kwargs = mock_feishu_channel.db.update_task.call_args - assert args[0] == 12 - assert kwargs["prompt"] == "继续" - # thread_root is parent_id (no root_id) -> create_reply parent + origin. - assert mock_feishu_channel._task_origin[12] == ("ou_sender", "om_parent", "om_msg") - mock_feishu_channel._start_streaming.assert_called_once() - # Must NOT also create a brand new task. - mock_feishu_channel.scheduler.submit_task.assert_not_called() - - def test_thread_reply_resumes_via_root_msg_map(self, mock_feishu_channel): - mock_feishu_channel._root_msg_map["om_root"] = 20 - mock_feishu_channel.db.get_task.return_value = { - "session_id": "sess", - "title": "RootTask", - } - data = _make_event(content=_text("more"), root_id="om_root") - mock_feishu_channel._handle_inbound(data) - assert mock_feishu_channel.db.update_task.call_args.args[0] == 20 - mock_feishu_channel.scheduler.submit_task.assert_not_called() - - def test_thread_reply_recovers_task_from_db(self, mock_feishu_channel): - mock_feishu_channel.db.get_task_by_feishu_root_msg.return_value = {"id": 33} - mock_feishu_channel.db.get_task.return_value = { - "session_id": "sess", - "title": "DBTask", - } - data = _make_event(content=_text("again"), root_id="om_db_root") - mock_feishu_channel._handle_inbound(data) - - mock_feishu_channel.db.get_task_by_feishu_root_msg.assert_called_with("om_db_root") - assert mock_feishu_channel.db.update_task.call_args.args[0] == 33 - - def test_thread_reply_task_without_session_replies_error(self, mock_feishu_channel): - mock_feishu_channel._notification_map["om_parent"] = 14 - mock_feishu_channel.db.get_task.return_value = {"session_id": None} - data = _make_event(content=_text("继续"), parent_id="om_parent") - mock_feishu_channel._handle_inbound(data) - - mock_feishu_channel.db.update_task.assert_not_called() - mock_feishu_channel._reply_message.assert_called_once() - msg = mock_feishu_channel._reply_message.call_args.args[1] - assert "#14 not found or has no saved session" in msg - mock_feishu_channel.scheduler.submit_task.assert_not_called() - - def test_thread_reply_no_match_creates_new_task(self, mock_feishu_channel): - # No mapping anywhere and DB lookup returns None -> falls through to create. - mock_feishu_channel.db.get_task_by_feishu_root_msg.return_value = None - mock_feishu_channel.scheduler.submit_task.return_value = 50 - mock_feishu_channel.db.get_task.return_value = { - "image_paths": [], - "prompt_images": [], - } - data = _make_event(content=_text("new in thread"), parent_id="om_unknown") - with ( - patch("channels.dir_utils.resolve_working_dir", return_value="/tmp"), - patch("channels.agent_utils.resolve_agent", return_value="claude"), - ): - mock_feishu_channel._handle_inbound(data) - mock_feishu_channel.scheduler.submit_task.assert_called_once() - - -# ─────────────────────── plain task creation ──────────────────────── - - -class TestTaskCreation: - def test_plain_message_creates_task_with_expected_fields(self, mock_feishu_channel): - mock_feishu_channel.scheduler.submit_task.return_value = 77 - mock_feishu_channel.db.get_task.return_value = { - "image_paths": [], - "prompt_images": [], - } - with ( - patch("channels.dir_utils.resolve_working_dir", return_value="/Users/x/proj") as rwd, - patch("channels.agent_utils.resolve_agent", return_value="codex") as ra, - ): - mock_feishu_channel._handle_inbound(_make_event(content=_text("修复登录 bug"))) - - rwd.assert_called_once_with("修复登录 bug", "feishu", mock_feishu_channel.db) - ra.assert_called_once_with("feishu", mock_feishu_channel.db) - - task = mock_feishu_channel.scheduler.submit_task.call_args.args[0] - assert task.prompt == "修复登录 bug" - assert task.working_dir == "/Users/x/proj" - assert task.agent == "codex" - assert task.tags == "feishu" - assert task.title == "[Feishu] 修复登录 bug" - assert task.feishu_root_msg_id == "om_msg" - - # Reaction acknowledged, streaming started, origin + root maps tracked. - mock_feishu_channel._add_reaction.assert_called_once_with("om_msg", "OK") - assert mock_feishu_channel._task_origin[77] == ("ou_sender", "om_msg", "om_msg") - assert mock_feishu_channel._root_msg_map["om_msg"] == 77 - mock_feishu_channel._start_streaming.assert_called_once_with( - 77, "om_running", "[Feishu] 修复登录 bug" - ) - - def test_long_title_is_truncated_with_ellipsis(self, mock_feishu_channel): - long_text = "x" * 80 - mock_feishu_channel.scheduler.submit_task.return_value = 1 - mock_feishu_channel.db.get_task.return_value = { - "image_paths": [], - "prompt_images": [], - } - with ( - patch("channels.dir_utils.resolve_working_dir", return_value="/tmp"), - patch("channels.agent_utils.resolve_agent", return_value="claude"), - ): - mock_feishu_channel._handle_inbound(_make_event(content=_text(long_text))) - task = mock_feishu_channel.scheduler.submit_task.call_args.args[0] - assert task.title == "[Feishu] " + "x" * 60 + "…" - - def test_sender_without_sender_id_uses_unknown(self, mock_feishu_channel): - mock_feishu_channel.scheduler.submit_task.return_value = 2 - mock_feishu_channel.db.get_task.return_value = { - "image_paths": [], - "prompt_images": [], - } - data = _make_event(content=_text("hello"), open_id=None) - with ( - patch("channels.dir_utils.resolve_working_dir", return_value="/tmp"), - patch("channels.agent_utils.resolve_agent", return_value="claude"), - ): - mock_feishu_channel._handle_inbound(data) - # p2p reply_to falls back to "unknown" sender id. - assert mock_feishu_channel._task_origin[2][0] == "unknown" - - def test_image_converted_to_prompt_images(self, mock_feishu_channel, tmp_path): - img_file = tmp_path / "pic.png" - img_file.write_bytes(b"\x89PNG\r\n\x1a\nfake") - post = json.dumps({"content": [[{"tag": "img", "image_key": "k"}]]}) - mock_feishu_channel._download_image = Mock(return_value=str(img_file)) - mock_feishu_channel.scheduler.submit_task.return_value = 3 - mock_feishu_channel.db.get_task.return_value = { - "image_paths": [str(img_file)], - "prompt_images": [{}], - } - with ( - patch("channels.dir_utils.resolve_working_dir", return_value="/tmp"), - patch("channels.agent_utils.resolve_agent", return_value="claude"), - ): - mock_feishu_channel._handle_inbound(_make_event(content=post, msg_type="post")) - - task = mock_feishu_channel.scheduler.submit_task.call_args.args[0] - assert task.image_paths == [str(img_file)] - assert len(task.prompt_images) == 1 - assert task.prompt_images[0]["media_type"] == "image/png" - assert task.prompt_images[0]["name"] == "pic.png" - - def test_no_running_msg_skips_streaming_on_create(self, mock_feishu_channel): - mock_feishu_channel._create_reply = Mock(return_value=None) - mock_feishu_channel.scheduler.submit_task.return_value = 4 - mock_feishu_channel.db.get_task.return_value = { - "image_paths": [], - "prompt_images": [], - } - with ( - patch("channels.dir_utils.resolve_working_dir", return_value="/tmp"), - patch("channels.agent_utils.resolve_agent", return_value="claude"), - ): - mock_feishu_channel._handle_inbound(_make_event(content=_text("hi"))) - mock_feishu_channel._start_streaming.assert_not_called() - # Task still created and tracked. - assert mock_feishu_channel._root_msg_map["om_msg"] == 4 - - -if __name__ == "__main__": - pytest.main([__file__, "-v"]) diff --git a/tests/test_feishu_lifecycle.py b/tests/test_feishu_lifecycle.py deleted file mode 100644 index 0764d77..0000000 --- a/tests/test_feishu_lifecycle.py +++ /dev/null @@ -1,834 +0,0 @@ -""" -Tests for Feishu channel lifecycle, image upload/download, stream-writer -plumbing, and forwarded-content helper branches not covered elsewhere. - -These complement (and intentionally do not duplicate) the assertions in -tests/test_feishu_message_rendering.py and tests/test_feishu_forwarded_messages.py. -""" - -import asyncio -import json -import threading -import time -from types import SimpleNamespace -from unittest.mock import Mock, patch - -import pytest - - -@pytest.fixture -def channel(): - """A FeishuChannel with mocked bus/db/scheduler and a mocked lark client.""" - with patch("channels.feishu_channel.FEISHU_AVAILABLE", True): - from channels.feishu_channel import FeishuChannel - - ch = FeishuChannel(Mock(), Mock(), Mock()) - ch._client = Mock() - return ch - - -def _writer(channel, task_id=12, msg_id="om_msg", title="Streaming task"): - from channels.feishu_channel import _FeishuStreamWriter - - return _FeishuStreamWriter(task_id, msg_id, channel, title) - - -# ── lifecycle: start / stop / _run_ws ─────────────────────────────── - - -class TestLifecycle: - def test_start_not_configured_does_not_build_client(self): - with patch("channels.feishu_channel.FEISHU_AVAILABLE", True): - from channels.feishu_channel import FeishuChannel - - ch = FeishuChannel(Mock(), Mock(), Mock()) - ch.db.get_setting.return_value = "" # no app_id / secret - - ch.start() - - assert ch._client is None - assert ch._ws_client is None - assert ch._ws_thread is None - - def test_start_unavailable_short_circuits(self): - with patch("channels.feishu_channel.FEISHU_AVAILABLE", False): - from channels.feishu_channel import FeishuChannel - - ch = FeishuChannel(Mock(), Mock(), Mock()) - ch.start() - assert ch._ws_client is None - - def test_start_wires_handlers_and_spawns_thread_without_connecting(self): - with patch("channels.feishu_channel.FEISHU_AVAILABLE", True): - from channels.feishu_channel import FeishuChannel - - ch = FeishuChannel(Mock(), Mock(), Mock()) - ch.db.get_setting.side_effect = lambda key: { - "feishu_app_id": "cli_app_id_value", - "feishu_app_secret": "secret_value", - }.get(key, "") - - fake_lark = Mock() - built_client = Mock() - fake_lark.Client.builder.return_value.app_id.return_value.app_secret.return_value.log_level.return_value.build.return_value = built_client - # The event dispatcher builder must return itself for each register call. - dispatcher_builder = fake_lark.EventDispatcherHandler.builder.return_value - for name in ( - "register_p2_im_message_receive_v1", - "register_p2_im_chat_member_bot_added_v1", - "register_p2_im_message_reaction_created_v1", - "register_p2_im_message_reaction_deleted_v1", - "register_p2_im_message_message_read_v1", - "register_p2_im_message_recalled_v1", - ): - getattr(dispatcher_builder, name).return_value = dispatcher_builder - built_handler = Mock() - dispatcher_builder.build.return_value = built_handler - ws_client = Mock() - fake_lark.ws.Client.return_value = ws_client - - started_threads = [] - - class _FakeThread: - def __init__(self, target=None, daemon=None): - self._target = target - self.daemon = daemon - self.started = False - - def start(self): - self.started = True - started_threads.append(self) - - with ( - patch("channels.feishu_channel.lark", fake_lark), - patch("channels.feishu_channel.threading.Thread", _FakeThread), - ): - ch.start() - - # client + ws client built, but no real ws_client.start() invoked - assert ch._client is built_client - assert ch._ws_client is ws_client - assert ch._running is True - # event handlers registered - for name in ( - "register_p2_im_message_receive_v1", - "register_p2_im_chat_member_bot_added_v1", - "register_p2_im_message_reaction_created_v1", - "register_p2_im_message_reaction_deleted_v1", - ): - getattr(dispatcher_builder, name).assert_called_once() - # ws client constructed with credentials + handler - _, kwargs = fake_lark.ws.Client.call_args - assert kwargs["event_handler"] is built_handler - # the ws thread was spawned (but never connected) - assert len(started_threads) == 1 - assert started_threads[0].started is True - ws_client.start.assert_not_called() - - def test_start_registers_readonly_event_noops(self): - """message_read / recalled receipts must have (no-op) processors, else - the lark SDK logs 'processor not found, type: im.message.message_read_v1' - on every read receipt. - """ - with patch("channels.feishu_channel.FEISHU_AVAILABLE", True): - from channels.feishu_channel import FeishuChannel - - ch = FeishuChannel(Mock(), Mock(), Mock()) - ch.db.get_setting.side_effect = lambda key: { - "feishu_app_id": "cli_app_id_value", - "feishu_app_secret": "secret_value", - }.get(key, "") - - fake_lark = Mock() - built_client = Mock() - fake_lark.Client.builder.return_value.app_id.return_value.app_secret.return_value.log_level.return_value.build.return_value = built_client - dispatcher_builder = fake_lark.EventDispatcherHandler.builder.return_value - # every register call returns the builder so the fluent chain holds - for name in ( - "register_p2_im_message_receive_v1", - "register_p2_im_chat_member_bot_added_v1", - "register_p2_im_message_reaction_created_v1", - "register_p2_im_message_reaction_deleted_v1", - "register_p2_im_message_message_read_v1", - "register_p2_im_message_recalled_v1", - ): - getattr(dispatcher_builder, name).return_value = dispatcher_builder - dispatcher_builder.build.return_value = Mock() - fake_lark.ws.Client.return_value = Mock() - - with ( - patch("channels.feishu_channel.lark", fake_lark), - patch("channels.feishu_channel.threading.Thread", Mock()), - ): - ch.start() - - dispatcher_builder.register_p2_im_message_message_read_v1.assert_called_once() - dispatcher_builder.register_p2_im_message_recalled_v1.assert_called_once() - - def test_start_disables_lark_logger_propagation(self): - """The lark SDK's 'Lark' logger has its own handler; if it also - propagates to the root logger (basicConfig) every line prints twice. - start() must turn propagation off. - """ - import logging - - logging.getLogger("Lark").propagate = True # reset global state - - with patch("channels.feishu_channel.FEISHU_AVAILABLE", True): - from channels.feishu_channel import FeishuChannel - - ch = FeishuChannel(Mock(), Mock(), Mock()) - ch.db.get_setting.side_effect = lambda key: { - "feishu_app_id": "cli_app_id_value", - "feishu_app_secret": "secret_value", - }.get(key, "") - - fake_lark = Mock() - with ( - patch("channels.feishu_channel.lark", fake_lark), - patch("channels.feishu_channel.threading.Thread", Mock()), - ): - ch.start() - - assert logging.getLogger("Lark").propagate is False - - def test_start_handles_build_exception(self): - with patch("channels.feishu_channel.FEISHU_AVAILABLE", True): - from channels.feishu_channel import FeishuChannel - - ch = FeishuChannel(Mock(), Mock(), Mock()) - ch.db.get_setting.side_effect = lambda key: { - "feishu_app_id": "cli_app_id_value", - "feishu_app_secret": "secret_value", - }.get(key, "") - - fake_lark = Mock() - fake_lark.Client.builder.side_effect = RuntimeError("boom") - - with patch("channels.feishu_channel.lark", fake_lark): - # Must not raise — exception is caught and logged. - ch.start() - - assert ch._ws_client is None - - def test_stop_tears_down_cleanly(self, channel): - ws_client = Mock() - channel._ws_client = ws_client - channel._running = True - - channel.stop() - - assert channel._running is False - channel.bus.unsubscribe_outbound.assert_called_once_with(channel._on_outbound) - ws_client.stop.assert_called_once() - assert channel._client is None - assert channel._ws_client is None - - def test_stop_without_ws_client_is_safe(self, channel): - channel._ws_client = None - channel._running = True - channel.stop() - assert channel._running is False - assert channel._ws_client is None - - def test_stop_swallows_ws_stop_error(self, channel): - ws_client = Mock() - ws_client.stop.side_effect = RuntimeError("already closed") - channel._ws_client = ws_client - channel.stop() - assert channel._ws_client is None - - def test_run_ws_calls_start_and_swallows_errors(self, channel): - ws_client = Mock() - channel._ws_client = ws_client - channel._running = True - channel._run_ws() - ws_client.start.assert_called_once() - - def test_run_ws_handles_start_exception(self, channel): - ws_client = Mock() - ws_client.start.side_effect = RuntimeError("connection refused") - channel._ws_client = ws_client - channel._running = True - # Must not propagate. - channel._run_ws() - ws_client.start.assert_called_once() - - def test_run_ws_suppresses_expected_stop_exception(self, channel): - def _start(): - channel._running = False - raise RuntimeError("Event loop stopped before Future completed.") - - ws_client = Mock() - ws_client.start.side_effect = _start - channel._ws_client = ws_client - channel._running = True - - with patch("traceback.print_exc") as print_exc: - channel._run_ws() - - ws_client.start.assert_called_once() - print_exc.assert_not_called() - - def test_run_ws_installs_private_sdk_loop(self, channel): - old_loop = asyncio.new_event_loop() - fake_ws_module = SimpleNamespace(loop=old_loop) - captured = {} - - class _WsClient: - def start(self): - captured["loop"] = fake_ws_module.loop - assert asyncio.get_event_loop() is fake_ws_module.loop - - channel._ws_client = _WsClient() - channel._running = True - with patch("channels.feishu_channel.lark_ws_client", fake_ws_module, create=True): - channel._run_ws() - - assert captured["loop"] is not old_loop - assert captured["loop"].is_closed() - assert channel._ws_loop is None - old_loop.close() - - def test_stop_stops_sdk_loop_without_stop_method(self, channel): - loop = asyncio.new_event_loop() - - class _WsClientWithoutStop: - def __init__(self): - self.disconnected = False - - async def _disconnect(self): - self.disconnected = True - - ws_client = _WsClientWithoutStop() - - def _run_loop(): - asyncio.set_event_loop(loop) - loop.run_forever() - - thread = threading.Thread(target=_run_loop, daemon=True) - thread.start() - channel._ws_client = ws_client - channel._ws_loop = loop - channel._ws_thread = thread - channel._running = True - - try: - channel.stop() - - assert ws_client.disconnected is True - assert thread.is_alive() is False - assert channel._client is None - assert channel._ws_client is None - assert channel._ws_loop is None - finally: - if thread.is_alive(): - loop.call_soon_threadsafe(loop.stop) - thread.join(timeout=2) - if not loop.is_closed(): - loop.close() - - -# ── _FeishuStreamWriter plumbing ──────────────────────────────────── - - -class TestStreamWriterPlumbing: - def test_schedule_marks_dirty_and_starts_when_interval_elapsed(self, channel): - writer = _writer(channel) - writer._start_patch_locked = Mock() - writer._last_patch = 0.0 # long ago -> delay <= 0 - - writer._schedule() - - assert writer._dirty is True - writer._start_patch_locked.assert_called_once() - - def test_schedule_noop_when_stopped(self, channel): - writer = _writer(channel) - writer._start_patch_locked = Mock() - writer._stopped = True - - writer._schedule() - - assert writer._dirty is False - writer._start_patch_locked.assert_not_called() - - def test_schedule_dirty_locked_starts_timer_when_throttled(self, channel): - writer = _writer(channel) - writer._dirty = True - writer._last_patch = time.time() # just patched -> must wait - - timers = [] - - class _FakeTimer: - def __init__(self, delay, fn): - self.delay = delay - self.fn = fn - self.daemon = False - self.started = False - timers.append(self) - - def start(self): - self.started = True - - def cancel(self): - pass - - with patch("channels.feishu_channel.threading.Timer", _FakeTimer): - writer._schedule_dirty_locked() - - assert len(timers) == 1 - assert timers[0].delay > 0 - assert timers[0].started is True - assert writer._timer is timers[0] - - def test_schedule_dirty_locked_noop_when_patch_in_flight(self, channel): - writer = _writer(channel) - writer._dirty = True - writer._patch_in_flight = True - writer._start_patch_locked = Mock() - - writer._schedule_dirty_locked() - - writer._start_patch_locked.assert_not_called() - assert writer._timer is None - - def test_start_patch_locked_clears_dirty_and_spawns_thread(self, channel): - writer = _writer(channel) - writer._dirty = True - - spawned = [] - - class _FakeThread: - def __init__(self, target=None, daemon=None): - self.target = target - self.daemon = daemon - - def start(self): - spawned.append(self.target) - - with patch("channels.feishu_channel.threading.Thread", _FakeThread): - writer._start_patch_locked() - - assert writer._patch_in_flight is True - assert writer._dirty is False - assert spawned == [writer._do_patch] - - def test_timer_fired_reschedules(self, channel): - writer = _writer(channel) - writer._timer = Mock() - writer._dirty = True - writer._schedule_dirty_locked = Mock() - - writer._timer_fired() - - assert writer._timer is None - writer._schedule_dirty_locked.assert_called_once() - - def test_do_patch_builds_card_and_patches_then_reschedules(self, channel): - writer = _writer(channel) - with writer._parts_lock: - writer._parts.append("hello world") - channel._build_streaming_card = Mock(return_value={"card": True}) - channel._patch_message = Mock() - writer._schedule_dirty_locked = Mock() - - writer._do_patch() - - channel._build_streaming_card.assert_called_once_with( - writer.task_id, writer._task_title, "hello world" - ) - channel._patch_message.assert_called_once_with(writer.msg_id, {"card": True}) - assert writer._patch_in_flight is False - writer._schedule_dirty_locked.assert_called_once() - - def test_do_patch_clears_in_flight_even_when_patch_raises(self, channel): - writer = _writer(channel) - channel._build_streaming_card = Mock(return_value={"card": True}) - channel._patch_message = Mock(side_effect=RuntimeError("patch failed")) - writer._patch_in_flight = True - - with pytest.raises(RuntimeError): - writer._do_patch() - - # finally-block still ran - assert writer._patch_in_flight is False - - def test_snapshot_text_joins_parts(self, channel): - writer = _writer(channel) - with writer._parts_lock: - writer._parts.extend(["a", "b", "c"]) - assert writer.snapshot_text() == "abc" - - def test_stop_marks_stopped_and_cancels_timer(self, channel): - writer = _writer(channel) - timer = Mock() - writer._timer = timer - - writer.stop() - - assert writer._stopped is True - timer.cancel.assert_called_once() - assert writer._timer is None - - def test_schedule_coalesces_while_in_flight(self, channel): - writer = _writer(channel) - writer._start_patch_locked = Mock() - with writer._state_lock: - writer._patch_in_flight = True - - writer._schedule() - - # Patch already running -> just mark dirty, don't start another. - assert writer._dirty is True - writer._start_patch_locked.assert_not_called() - - -# ── image path collection / canonicalization ──────────────────────── - - -class TestImagePathHelpers: - def test_generated_image_paths_for_task_filters_missing(self, channel, tmp_path): - real = tmp_path / "a.png" - real.write_bytes(b"\x89PNG\r\n\x1a\nx") - channel.db.get_task_runs.return_value = [{"id": 5}] - channel.db.get_run_output_events.return_value = [ - {"event_type": "generated_image", "content": json.dumps({"path": str(real)})}, - {"event_type": "generated_image", "content": json.dumps({"path": str(real)})}, # dup - { - "event_type": "generated_image", - "content": json.dumps({"path": str(tmp_path / "missing.png")}), - }, - {"event_type": "other", "content": "{}"}, - {"event_type": "generated_image", "content": "{not json"}, - ] - - paths = channel._generated_image_paths_for_task(7) - - assert paths == [str(real)] - - def test_generated_image_paths_for_task_no_runs(self, channel): - channel.db.get_task_runs.return_value = [] - assert channel._generated_image_paths_for_task(7) == [] - - def test_generated_image_paths_for_task_run_load_error(self, channel): - channel.db.get_task_runs.side_effect = RuntimeError("db down") - assert channel._generated_image_paths_for_task(7) == [] - - def test_generated_image_paths_for_task_events_error(self, channel): - channel.db.get_task_runs.return_value = [{"id": 5}] - channel.db.get_run_output_events.side_effect = RuntimeError("db down") - assert channel._generated_image_paths_for_task(7) == [] - - def test_collect_generated_image_paths_merges_and_dedupes(self, channel, tmp_path): - img = tmp_path / "shared.png" - img.write_bytes(b"\x89PNG\r\n\x1a\nx") - channel.db.get_task_runs.return_value = [{"id": 1}] - channel.db.get_run_output_events.return_value = [ - {"event_type": "generated_image", "content": json.dumps({"path": str(img)})}, - ] - content = f"see ![pic]({img})" - - result = channel._collect_generated_image_paths(7, content, task={"working_dir": None}) - - # Same file referenced twice -> deduped to one canonical path. - assert result == [str(img.resolve())] - - def test_generated_image_paths_from_markdown_relative_to_working_dir(self, channel, tmp_path): - img = tmp_path / "rel.png" - img.write_bytes(b"\x89PNG\r\n\x1a\nx") - content = "here is ![alt](rel.png)" - - paths = channel._generated_image_paths_from_markdown(content, working_dir=str(tmp_path)) - - assert paths == [str(img.resolve())] - - def test_local_image_path_from_reference_skips_remote(self, channel): - assert channel._local_image_path_from_reference("https://x/y.png") is None - assert channel._local_image_path_from_reference("data:image/png;base64,AAAA") is None - - def test_local_image_path_from_reference_file_uri(self, channel, tmp_path): - img = tmp_path / "f.png" - img.write_bytes(b"\x89PNG\r\n\x1a\nx") - ref = f"file://{img}" - assert channel._local_image_path_from_reference(ref) == str(img.resolve()) - - def test_local_image_path_from_reference_sandbox_prefix(self, channel, tmp_path): - img = tmp_path / "s.png" - img.write_bytes(b"\x89PNG\r\n\x1a\nx") - ref = f"sandbox:{img}" - assert channel._local_image_path_from_reference(ref) == str(img.resolve()) - - def test_local_image_path_from_reference_rejects_non_image_suffix(self, channel, tmp_path): - txt = tmp_path / "note.txt" - txt.write_text("hi") - assert channel._local_image_path_from_reference(str(txt)) is None - - def test_local_image_path_from_reference_missing_file(self, channel, tmp_path): - assert channel._local_image_path_from_reference(str(tmp_path / "nope.png")) is None - - def test_markdown_image_reference_target_angle_brackets(self, channel): - assert channel._markdown_image_reference_target("") == "a b.png" - - def test_markdown_image_reference_target_quoted(self, channel): - assert channel._markdown_image_reference_target("'quoted.png'") == "quoted.png" - - def test_markdown_image_reference_target_with_title(self, channel): - assert channel._markdown_image_reference_target('pic.png "a title"') == "pic.png" - - def test_markdown_image_reference_target_empty(self, channel): - assert channel._markdown_image_reference_target(" ") == "" - - def test_dedupe_image_paths_drops_missing_and_dups(self, channel, tmp_path): - a = tmp_path / "a.png" - a.write_bytes(b"x") - paths = [str(a), str(a), str(tmp_path / "ghost.png")] - assert channel._dedupe_image_paths(paths) == [str(a.resolve())] - - def test_canonical_image_path_resolves(self, channel, tmp_path): - a = tmp_path / "a.png" - a.write_bytes(b"x") - assert channel._canonical_image_path(str(a)) == str(a.resolve()) - - def test_canonical_image_path_missing(self, channel, tmp_path): - assert channel._canonical_image_path(str(tmp_path / "no.png")) is None - - -# ── image upload ──────────────────────────────────────────────────── - - -class TestImageUpload: - def _ok_response(self, image_key="img_v2_ok"): - response = Mock() - response.success.return_value = True - response.data.image_key = image_key - return response - - def test_upload_image_success(self, channel, tmp_path): - img = tmp_path / "u.png" - img.write_bytes(b"\x89PNG\r\n\x1a\nx") - channel._client.im.v1.image.create.return_value = self._ok_response("img_v2_xyz") - - key = channel._upload_image(str(img)) - - assert key == "img_v2_xyz" - channel._client.im.v1.image.create.assert_called_once() - - def test_upload_image_api_failure(self, channel, tmp_path): - img = tmp_path / "u.png" - img.write_bytes(b"\x89PNG\r\n\x1a\nx") - response = Mock() - response.success.return_value = False - response.code = 1234 - response.msg = "nope" - channel._client.im.v1.image.create.return_value = response - - assert channel._upload_image(str(img)) is None - - def test_upload_image_exception(self, channel, tmp_path): - img = tmp_path / "u.png" - img.write_bytes(b"\x89PNG\r\n\x1a\nx") - channel._client.im.v1.image.create.side_effect = RuntimeError("boom") - assert channel._upload_image(str(img)) is None - - def test_upload_image_no_client(self, channel, tmp_path): - img = tmp_path / "u.png" - img.write_bytes(b"x") - channel._client = None - assert channel._upload_image(str(img)) is None - - def test_upload_image_entries_skips_failures(self, channel, tmp_path): - a = tmp_path / "a.png" - b = tmp_path / "b.png" - a.write_bytes(b"\x89PNG\r\n\x1a\na") - b.write_bytes(b"\x89PNG\r\n\x1a\nb") - channel._upload_image = Mock(side_effect=["img_a", None]) - - entries = channel._upload_image_entries([str(a), str(b)]) - - assert entries == [(str(a), "img_a")] - - def test_upload_images_returns_keys(self, channel): - channel._upload_image_entries = Mock( - return_value=[("/a.png", "img_a"), ("/b.png", "img_b")] - ) - assert channel._upload_images(["/a.png", "/b.png"]) == ["img_a", "img_b"] - - -# ── hiding generated image references ─────────────────────────────── - - -class TestHideGeneratedImagePaths: - def test_hide_removes_uploaded_path_line(self, channel, tmp_path): - img = tmp_path / "g.png" - img.write_bytes(b"\x89PNG\r\n\x1a\nx") - canonical = str(img.resolve()) - content = f"结果如下\n- {canonical}\n收工" - - cleaned = channel._hide_generated_image_paths( - content, image_count=1, uploaded_paths=[canonical] - ) - - assert canonical not in cleaned - assert "结果如下" in cleaned - assert "收工" in cleaned - - def test_hide_removes_codex_generated_lines(self, channel): - content = "ok\n- /home/u/.codex/generated_images/t/a.png" - cleaned = channel._hide_generated_image_paths(content, image_count=1) - assert "/.codex/generated_images/" not in cleaned - assert "ok" in cleaned - - def test_hide_falls_back_when_nothing_visible(self, channel): - content = "- /home/u/.codex/generated_images/t/a.png" - cleaned = channel._hide_generated_image_paths(content, image_count=3) - assert cleaned == "已生成 3 张图片。" - - def test_hide_collapses_already_generated_header(self, channel): - content = "已生成 2 张图片:\n- whatever" - cleaned = channel._hide_generated_image_paths(content, image_count=2) - assert cleaned == "已生成 2 张图片。" - - def test_hide_strips_bare_list_marker_lines(self, channel, tmp_path): - img = tmp_path / "h.png" - img.write_bytes(b"\x89PNG\r\n\x1a\nx") - canonical = str(img.resolve()) - content = f"intro\n- ![pic]({canonical})" - - cleaned = channel._hide_generated_image_paths( - content, image_count=1, uploaded_paths=[canonical] - ) - - # The markdown ref is removed, leaving only "intro" (the bare "-" dropped). - assert cleaned == "intro" - - def test_line_is_uploaded_image_path_true_for_canonical(self, channel, tmp_path): - img = tmp_path / "p.png" - img.write_bytes(b"\x89PNG\r\n\x1a\nx") - canonical = str(img.resolve()) - assert channel._line_is_uploaded_image_path(f"- {canonical}", {canonical}) is True - - def test_line_is_uploaded_image_path_codex_match(self, channel): - assert ( - channel._line_is_uploaded_image_path("- /x/.codex/generated_images/y/z.png", set()) - is True - ) - - def test_line_is_uploaded_image_path_non_list(self, channel): - assert channel._line_is_uploaded_image_path("plain text", set()) is False - - def test_remove_uploaded_markdown_image_refs_noop_without_uploaded(self, channel): - line = "see ![x](/a.png)" - assert channel._remove_uploaded_markdown_image_refs(line, set()) == line - - def test_remove_uploaded_markdown_image_refs_strips_matching(self, channel, tmp_path): - img = tmp_path / "m.png" - img.write_bytes(b"\x89PNG\r\n\x1a\nx") - canonical = str(img.resolve()) - line = f"before ![pic]({canonical}) after" - out = channel._remove_uploaded_markdown_image_refs(line, {canonical}) - assert "![pic]" not in out - assert "before" in out and "after" in out - - -# ── image download ────────────────────────────────────────────────── - - -class TestDownloadImage: - def _resp(self, raw_bytes, success=True, code=0, msg="ok"): - response = Mock() - response.success.return_value = success - response.code = code - response.msg = msg - response.raw.content = raw_bytes - return response - - def test_download_image_writes_png(self, channel, tmp_path): - channel._client.im.v1.message_resource.get.return_value = self._resp( - b"\x89PNG\r\n\x1a\nbody" - ) - with patch("channels.feishu_channel.Path.home", return_value=tmp_path): - path = channel._download_image("msg_1", "img_key_1") - - assert path is not None - assert path.endswith("img_key_1.png") - with open(path, "rb") as f: - assert f.read() == b"\x89PNG\r\n\x1a\nbody" - - def test_download_image_detects_jpg(self, channel, tmp_path): - channel._client.im.v1.message_resource.get.return_value = self._resp(b"\xff\xd8\xff\xe0jpg") - with patch("channels.feishu_channel.Path.home", return_value=tmp_path): - path = channel._download_image("msg_1", "jpg_key") - assert path.endswith("jpg_key.jpg") - - def test_download_image_unknown_defaults_jpg(self, channel, tmp_path): - channel._client.im.v1.message_resource.get.return_value = self._resp(b"random-bytes") - with patch("channels.feishu_channel.Path.home", return_value=tmp_path): - path = channel._download_image("msg_1", "unk_key") - assert path.endswith("unk_key.jpg") - - def test_download_image_api_failure(self, channel, tmp_path): - channel._client.im.v1.message_resource.get.return_value = self._resp( - b"", success=False, code=99, msg="denied" - ) - with patch("channels.feishu_channel.Path.home", return_value=tmp_path): - assert channel._download_image("msg_1", "bad_key") is None - - def test_download_image_exception(self, channel, tmp_path): - channel._client.im.v1.message_resource.get.side_effect = RuntimeError("net") - with patch("channels.feishu_channel.Path.home", return_value=tmp_path): - assert channel._download_image("msg_1", "err_key") is None - - def test_download_image_no_client(self, channel): - channel._client = None - assert channel._download_image("msg_1", "k") is None - - -# ── forwarded-content helper branches not covered elsewhere ───────── - - -class TestForwardedExtraBranches: - def test_extract_forwarded_post_lang_body_list(self, channel): - # post content where the top-level value is itself a list of paragraphs - # (no content/zh_cn/en_us keys) -> hits the next(iter(...)) fallback. - message = Mock() - message.message_type = "post" - message.content = json.dumps( - {"other": [[{"tag": "quote", "text": "引用文本", "user": {"name": "甲"}}]]} - ) - - result = channel._extract_forwarded_content(message) - - assert result["type"] == "quote" - assert result["sender_name"] == "甲" - assert result["text"] == "引用文本" - - def test_extract_forwarded_post_no_quote_or_nested_returns_none(self, channel): - message = Mock() - message.message_type = "post" - message.content = json.dumps( - {"zh_cn": {"content": [[{"tag": "text", "text": "just text"}]]}} - ) - assert channel._extract_forwarded_content(message) is None - - def test_extract_forwarded_post_malformed(self, channel): - message = Mock() - message.message_type = "post" - message.content = "{bad json" - assert channel._extract_forwarded_content(message) is None - - def test_extract_forwarded_nested_message_default_sender(self, channel): - message = Mock() - message.message_type = "post" - message.content = json.dumps( - {"content": [[{"tag": "nested_message", "nested_message": {"text": "n"}}]]} - ) - result = channel._extract_forwarded_content(message) - assert result["type"] == "forward" - assert result["sender_name"] == "未知用户" - - def test_format_forwarded_prompt_default_sender_name(self, channel): - # forwarded without sender_name -> falls back to 未知用户 - forwarded = {"type": "forward", "text": "x"} - out = channel._format_forwarded_prompt("", forwarded) - assert "转发自: 未知用户" in out diff --git a/tests/test_feishu_message_rendering.py b/tests/test_feishu_message_rendering.py deleted file mode 100644 index fdba387..0000000 --- a/tests/test_feishu_message_rendering.py +++ /dev/null @@ -1,741 +0,0 @@ -""" -Tests for Feishu outbound message card rendering. -""" - -import json -from unittest.mock import Mock, patch - -import pytest - -from taskboard_bus import OutboundMessage, OutboundMessageType - - -@pytest.fixture -def mock_feishu_channel(): - """Create a FeishuChannel instance with mocked dependencies.""" - with patch("channels.feishu_channel.FEISHU_AVAILABLE", True): - from channels.feishu_channel import FeishuChannel - - bus = Mock() - db = Mock() - scheduler = Mock() - - channel = FeishuChannel(bus, db, scheduler) - channel._client = Mock() - return channel - - -def _panel_texts(panel): - return [element["text"]["content"] for element in panel["elements"] if element["tag"] == "div"] - - -def _count_card_elements(value): - if not isinstance(value, dict): - return 0 - count = 1 if isinstance(value.get("tag"), str) else 0 - for child in value.values(): - if isinstance(child, list): - count += sum(_count_card_elements(item) for item in child) - elif isinstance(child, dict): - count += _count_card_elements(child) - return count - - -class TestFeishuNotificationCards: - def test_build_completed_card_shows_result_only(self, mock_feishu_channel): - task = { - "id": 42, - "title": "Fix Feishu rendering", - "prompt": "请优化飞书结果展示,让内容更容易扫读。", - "agent": "codex", - "working_dir": "~/workspace/agentforge", - } - result_text = "已完成优化。\n\n- 增加摘要\n- 增加结果预览\n- 增加折叠面板" - - card = mock_feishu_channel._build_notification_card( - task_id=42, - task=task, - is_completed=True, - body_text=result_text, - ) - - assert card["schema"] == "2.0" - assert card["config"]["summary"]["content"] == "已完成优化。" - assert len(card["body"]["elements"]) == 1 - assert any( - element.get("tag") == "markdown" and "增加摘要" in element.get("content", "") - for element in card["body"]["elements"] - ) - assert not any( - "Task #42" in element.get("content", "") or "Prompt" in element.get("content", "") - for element in card["body"]["elements"] - if isinstance(element, dict) - ) - - def test_build_failed_card_adds_status_hint(self, mock_feishu_channel): - task = { - "id": 7, - "title": "Broken task", - "prompt": "调试失败任务", - "agent": "claude", - "working_dir": "~/workspace/agentforge", - } - - card = mock_feishu_channel._build_notification_card( - task_id=7, - task=task, - is_completed=False, - body_text="Traceback: something went wrong", - ) - - assert any( - element.get("tag") == "markdown" and "/status 7" in element.get("content", "") - for element in card["body"]["elements"] - ) - - def test_build_completed_card_keeps_long_body_visible(self, mock_feishu_channel): - task = { - "id": 99, - "title": "Long output task", - "prompt": "输出一份很长的结果", - "agent": "codex", - "working_dir": "~/workspace/agentforge", - } - long_text = "A" * 2200 - - card = mock_feishu_channel._build_notification_card( - task_id=99, - task=task, - is_completed=True, - body_text=long_text, - ) - - assert card["body"]["elements"][0]["tag"] == "markdown" - assert card["body"]["elements"] == [{"tag": "markdown", "content": long_text}] - assert not any( - element.get("tag") == "collapsible_panel" for element in card["body"]["elements"] - ) - - def test_build_completed_card_long_body_keeps_full_remainder(self, mock_feishu_channel): - task = { - "id": 100, - "title": "Long output task", - "prompt": "输出一份很长的结果", - "agent": "codex", - "working_dir": "~/workspace/agentforge", - } - long_text = "A" * 500 + "B" * 7600 - - card = mock_feishu_channel._build_notification_card( - task_id=100, - task=task, - is_completed=True, - body_text=long_text, - ) - assert card["body"]["elements"][0]["content"].startswith("A" * 20) - assert "".join(element["content"] for element in card["body"]["elements"]) == long_text - assert "truncated" not in "".join( - element["content"] for element in card["body"]["elements"] - ) - - def test_build_completed_card_long_body_uses_summary_plus_full_content( - self, mock_feishu_channel - ): - task = { - "id": 101, - "title": "Long output task", - "prompt": "输出一份很长的结果", - "agent": "codex", - "working_dir": "~/workspace/agentforge", - } - long_text = "Summary line\n" + ("A" * 1600) - - card = mock_feishu_channel._build_notification_card( - task_id=101, - task=task, - is_completed=True, - body_text=long_text, - ) - - assert card["config"]["summary"]["content"] == "Summary line" - assert card["body"]["elements"] == [{"tag": "markdown", "content": long_text}] - - def test_build_completed_card_long_body_has_no_collapsible_panel(self, mock_feishu_channel): - task = { - "id": 102, - "title": "Long output task", - "prompt": "输出一份很长的结果", - "agent": "codex", - "working_dir": "~/workspace/agentforge", - } - long_text = "Intro line\n" + ("B" * 1400) - - card = mock_feishu_channel._build_notification_card( - task_id=102, - task=task, - is_completed=True, - body_text=long_text, - ) - - assert not any( - element.get("tag") == "collapsible_panel" for element in card["body"]["elements"] - ) - assert "".join(element["content"] for element in card["body"]["elements"]) == long_text - - def test_build_completed_card_places_streaming_history_above_result(self, mock_feishu_channel): - task = { - "id": 103, - "title": "Finished task", - "prompt": "输出最终结果", - "agent": "codex", - "working_dir": "~/workspace/agentforge", - } - - card = mock_feishu_channel._build_notification_card( - task_id=103, - task=task, - is_completed=True, - body_text="最终结果", - streaming_history="思考第一步\n思考第二步", - ) - - panel = card["body"]["elements"][0] - result = card["body"]["elements"][1] - assert panel["tag"] == "collapsible_panel" - assert panel["expanded"] is False - assert panel["header"]["title"]["content"] == "执行过程" - assert _panel_texts(panel) == ["思考第一步", "思考第二步"] - assert result == {"tag": "markdown", "content": "最终结果"} - - def test_send_uses_structured_card_and_fallback_content(self, mock_feishu_channel): - task = { - "id": 5, - "title": "Ship update", - "prompt": "发布更新", - "result": "done", - "error": None, - "agent": "codex", - "working_dir": "~/workspace/agentforge", - } - mock_feishu_channel.db.get_task.return_value = task - mock_feishu_channel.db.get_setting.return_value = "oc_test_chat" - mock_feishu_channel._send_message = Mock(return_value="msg_123") - - msg = OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, - task_id=5, - payload={"result": "done", "title": "Ship update"}, - ) - - mock_feishu_channel.send(msg) - - _, kwargs = mock_feishu_channel._send_message.call_args - assert kwargs["fallback_content"] == "done" - assert kwargs["card"]["schema"] == "2.0" - - def test_send_completed_notification_keeps_full_result_for_card(self, mock_feishu_channel): - task = { - "id": 6, - "title": "Long result", - "prompt": "发布长结果", - "result": None, - "error": None, - "agent": "codex", - "working_dir": "~/workspace/agentforge", - } - long_result = "A" * 12050 - mock_feishu_channel.db.get_task.return_value = task - mock_feishu_channel.db.get_setting.return_value = "oc_test_chat" - mock_feishu_channel._send_message = Mock(return_value="msg_456") - mock_feishu_channel._build_notification_card = Mock( - wraps=mock_feishu_channel._build_notification_card - ) - - msg = OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, - task_id=6, - payload={"result": long_result, "title": "Long result"}, - ) - - mock_feishu_channel.send(msg) - - _, kwargs = mock_feishu_channel._build_notification_card.call_args - assert kwargs["body_text"] == long_result - - def test_build_completed_card_includes_generated_image_elements(self, mock_feishu_channel): - task = { - "id": 7, - "title": "Image result", - "prompt": "生成图片", - "agent": "codex", - "working_dir": "~/workspace/agentforge", - } - - card = mock_feishu_channel._build_notification_card( - task_id=7, - task=task, - is_completed=True, - body_text="已生成 1 张图片:", - image_keys=["img_v2_result"], - ) - - assert card["body"]["elements"][-1] == { - "tag": "img", - "img_key": "img_v2_result", - "alt": {"tag": "plain_text", "content": "generated image 1"}, - } - - def test_send_uploads_generated_images_from_run_events(self, mock_feishu_channel, tmp_path): - image_path = tmp_path / ".codex" / "generated_images" / "thread_1" / "result.png" - image_path.parent.mkdir(parents=True) - image_path.write_bytes(b"\x89PNG\r\n\x1a\nfakepng") - task = { - "id": 7, - "title": "Image result", - "prompt": "生成图片", - "result": f"已生成 1 张图片:\n- {image_path}", - "error": None, - "agent": "codex", - "working_dir": "~/workspace/agentforge", - } - mock_feishu_channel.db.get_task.return_value = task - mock_feishu_channel.db.get_setting.return_value = "oc_test_chat" - mock_feishu_channel.db.get_task_runs.return_value = [{"id": 99}] - mock_feishu_channel.db.get_run_output_events.return_value = [ - { - "event_type": "generated_image", - "content": json.dumps({"path": str(image_path), "media_type": "image/png"}), - } - ] - mock_feishu_channel._upload_image = Mock(return_value="img_v2_result") - mock_feishu_channel._send_message = Mock(return_value="msg_456") - - msg = OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, - task_id=7, - payload={"result": task["result"], "title": "Image result"}, - ) - - mock_feishu_channel.send(msg) - - _, kwargs = mock_feishu_channel._send_message.call_args - assert kwargs["card"]["body"]["elements"][0]["content"] == "已生成 1 张图片。" - assert "/.codex/generated_images/" not in kwargs["card"]["body"]["elements"][0]["content"] - assert kwargs["card"]["body"]["elements"][-1]["img_key"] == "img_v2_result" - mock_feishu_channel._upload_image.assert_called_once_with(str(image_path)) - - def test_send_uploads_markdown_generated_image_references(self, mock_feishu_channel, tmp_path): - image_dir = tmp_path / ".codex" / "generated_images" / "thread_2" - image_dir.mkdir(parents=True) - first_image = image_dir / "first.png" - second_image = image_dir / "second.png" - first_image.write_bytes(b"\x89PNG\r\n\x1a\nfirst") - second_image.write_bytes(b"\x89PNG\r\n\x1a\nsecond") - result_text = f"生成好了:\n\n- ![第一张图]({first_image})\n- ![第二张图]({second_image})" - task = { - "id": 11, - "title": "Multi image result", - "prompt": "生成两张图片", - "result": result_text, - "error": None, - "agent": "codex", - "working_dir": "~/workspace/agentforge", - } - mock_feishu_channel.db.get_task.return_value = task - mock_feishu_channel.db.get_setting.return_value = "oc_test_chat" - mock_feishu_channel.db.get_task_runs.return_value = [] - mock_feishu_channel._upload_image = Mock(side_effect=["img_first", "img_second"]) - mock_feishu_channel._send_message = Mock(return_value="msg_789") - - msg = OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, - task_id=11, - payload={"result": result_text, "title": "Multi image result"}, - ) - - mock_feishu_channel.send(msg) - - _, kwargs = mock_feishu_channel._send_message.call_args - elements = kwargs["card"]["body"]["elements"] - markdown_text = "\n".join( - element.get("content", "") for element in elements if element.get("tag") == "markdown" - ) - assert "![第一张图]" not in markdown_text - assert "![第二张图]" not in markdown_text - assert str(first_image) not in markdown_text - assert str(second_image) not in markdown_text - assert markdown_text.strip() == "生成好了:" - assert [element.get("img_key") for element in elements[-2:]] == [ - "img_first", - "img_second", - ] - assert [call.args[0] for call in mock_feishu_channel._upload_image.call_args_list] == [ - str(first_image), - str(second_image), - ] - - def test_send_final_patch_preserves_streaming_history(self, mock_feishu_channel): - from channels.feishu_channel import _FeishuStreamWriter - - task = { - "id": 8, - "title": "Streaming final", - "prompt": "发布最终结果", - "result": "final result", - "error": None, - "agent": "codex", - "working_dir": "~/workspace/agentforge", - } - writer = _FeishuStreamWriter(8, "om_stream", mock_feishu_channel, "Streaming final") - writer._schedule = Mock() - writer.on_event(8, 44, "assistant", "[thinking] thinking line\n") - writer.on_event(8, 44, "assistant", "[thinking] more thinking") - writer.on_event(8, 44, "assistant", "final result") - - mock_feishu_channel.db.get_task.return_value = task - mock_feishu_channel._task_origin[8] = ("oc_chat", "root_msg", "reaction_msg") - mock_feishu_channel._streaming_msg[8] = "om_stream" - mock_feishu_channel._writers[8] = writer - mock_feishu_channel._add_reaction = Mock() - mock_feishu_channel._patch_message = Mock(return_value=True) - - msg = OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, - task_id=8, - payload={"result": "final result", "title": "Streaming final"}, - ) - - mock_feishu_channel.send(msg) - - _, patched_card = mock_feishu_channel._patch_message.call_args.args - panel = patched_card["body"]["elements"][0] - result = patched_card["body"]["elements"][1] - assert panel["tag"] == "collapsible_panel" - assert panel["header"]["title"]["content"] == "执行过程" - assert _panel_texts(panel) == ["thinking line", "more thinking"] - assert "final result" not in "".join(_panel_texts(panel)) - assert result == {"tag": "markdown", "content": "final result"} - mock_feishu_channel.scheduler.remove_output_listener.assert_called_once_with( - writer.on_event - ) - - def test_build_completed_card_removes_final_answer_from_history(self, mock_feishu_channel): - task = { - "id": 9, - "title": "Streaming final", - "prompt": "发布最终结果", - "agent": "claude", - "working_dir": "~/workspace/agentforge", - } - - card = mock_feishu_channel._build_notification_card( - task_id=9, - task=task, - is_completed=True, - body_text="final result", - streaming_history="working...\nfinal result", - ) - - panel = card["body"]["elements"][0] - result = card["body"]["elements"][1] - assert panel["tag"] == "collapsible_panel" - assert _panel_texts(panel) == ["working..."] - assert result == {"tag": "markdown", "content": "final result"} - - def test_build_completed_card_keeps_panel_when_history_is_only_final_answer( - self, mock_feishu_channel - ): - # When the streamed history is only the final answer (no separate trace - # events, e.g. a simple/codex run), still keep the folded 执行过程 panel - # rather than dropping it — the process should always be foldable. - task = { - "id": 10, - "title": "Streaming final", - "prompt": "发布最终结果", - "agent": "claude", - "working_dir": "~/workspace/agentforge", - } - - card = mock_feishu_channel._build_notification_card( - task_id=10, - task=task, - is_completed=True, - body_text="final result", - streaming_history="final result", - ) - - panel = card["body"]["elements"][0] - result = card["body"]["elements"][1] - assert panel["tag"] == "collapsible_panel" - assert _panel_texts(panel) == ["final result"] - assert result == {"tag": "markdown", "content": "final result"} - - -class TestFeishuStreaming: - def test_streaming_card_uses_thinking_placeholder(self, mock_feishu_channel): - card = mock_feishu_channel._build_streaming_card(12, "Streaming task", "") - - assert card["body"]["elements"][0]["content"] == "Thinking ▌" - - def test_streaming_card_preserves_single_newlines(self, mock_feishu_channel): - card = mock_feishu_channel._build_streaming_card( - 12, "Streaming task", "first line\nsecond line\n" - ) - - panel = card["body"]["elements"][0] - assert len(card["body"]["elements"]) == 1 - assert panel["tag"] == "collapsible_panel" - assert panel["expanded"] is True - assert _panel_texts(panel) == ["first line", "second line"] - - def test_streaming_card_normalizes_crlf_newlines(self, mock_feishu_channel): - card = mock_feishu_channel._build_streaming_card( - 12, "Streaming task", "first line\r\nsecond line" - ) - - panel = card["body"]["elements"][0] - assert _panel_texts(panel) == ["first line", "second line"] - - def test_streaming_card_preserves_blank_lines_as_separate_rows(self, mock_feishu_channel): - card = mock_feishu_channel._build_streaming_card( - 12, "Streaming task", "first line\n\nthird line" - ) - - panel = card["body"]["elements"][0] - assert _panel_texts(panel) == ["first line", " ", "third line"] - - def test_streaming_card_keeps_full_output_in_collapsible_panel(self, mock_feishu_channel): - long_text = "start\n" + ("A" * 1600) + "\nend" - - card = mock_feishu_channel._build_streaming_card(12, "Streaming task", long_text) - - panel = card["body"]["elements"][0] - assert len(card["body"]["elements"]) == 1 - assert panel["tag"] == "collapsible_panel" - assert panel["expanded"] is True - assert panel["header"]["title"]["content"] == "执行过程" - assert _panel_texts(panel) == ["start", "A" * 1600, "end"] - - def test_streaming_card_uses_plain_markdown_fallback_for_many_lines(self, mock_feishu_channel): - long_text = "\n".join(f"line {i}" for i in range(220)) - - card = mock_feishu_channel._build_streaming_card(12, "Streaming task", long_text) - - panel = card["body"]["elements"][0] - assert panel["elements"] == [{"tag": "markdown", "content": long_text}] - assert "```" not in panel["elements"][0]["content"] - assert _count_card_elements(card) <= 200 - - def test_notification_card_keeps_history_and_image_under_feishu_element_limit( - self, mock_feishu_channel - ): - history = "\n".join(f"line {i}" for i in range(165)) - - card = mock_feishu_channel._build_notification_card( - task_id=12, - task={"id": 12, "title": "Image task"}, - is_completed=True, - body_text="已生成 1 张图片:\n- /tmp/generated.png", - streaming_history=history, - image_keys=["img_v3_generated"], - ) - - panel = card["body"]["elements"][0] - assert panel["tag"] == "collapsible_panel" - assert panel["elements"][0]["tag"] == "markdown" - assert card["body"]["elements"][-1]["img_key"] == "img_v3_generated" - assert _count_card_elements(card) <= 200 - - def test_streaming_history_markdown_fallback_chunks_long_content(self, mock_feishu_channel): - long_text = "\n".join(f"{i}: {'A' * 120}" for i in range(140)) - - card = mock_feishu_channel._build_streaming_card(12, "Streaming task", long_text) - - panel = card["body"]["elements"][0] - assert len(panel["elements"]) > 1 - assert all(element["tag"] == "markdown" for element in panel["elements"]) - assert all("```" not in element["content"] for element in panel["elements"]) - assert _count_card_elements(card) <= 200 - - def test_stream_writer_appends_thinking_events_without_resplitting(self, mock_feishu_channel): - from channels.feishu_channel import _FeishuStreamWriter - - writer = _FeishuStreamWriter(12, "om_msg", mock_feishu_channel, "Streaming task") - writer._schedule = Mock() - - writer.on_event(12, 34, "assistant", "[thinking] Hello") - writer.on_event(12, 34, "assistant", "[thinking] ") - writer.on_event(12, 34, "assistant", "[thinking] world") - - mock_feishu_channel._build_streaming_card = Mock(return_value={"card": True}) - mock_feishu_channel._patch_message = Mock() - - writer._do_patch() - - mock_feishu_channel._build_streaming_card.assert_called_once_with( - 12, "Streaming task", "Hello world" - ) - - def test_stream_writer_appends_tool_trace_events(self, mock_feishu_channel): - from channels.feishu_channel import _FeishuStreamWriter - - writer = _FeishuStreamWriter(12, "om_msg", mock_feishu_channel, "Streaming task") - writer._schedule = Mock() - - writer.on_event( - 12, - 34, - "tool_call", - json.dumps({"id": "toolu_1", "name": "Bash", "input": {"command": "pytest -q"}}), - ) - writer.on_event( - 12, - 34, - "tool_result", - json.dumps({"tool_use_id": "toolu_1", "content": "42 passed", "is_error": False}), - ) - writer.on_event( - 12, - 34, - "command_execution", - json.dumps( - { - "command": "pytest -q", - "output": "42 passed", - "exit_code": 0, - } - ), - ) - - assert writer.snapshot_text() == ( - "▣ 调用工具 Bash · pytest -q\n" - "↵ 工具返回 toolu_1 · 42 passed\n" - "$ 执行命令 pytest -q · 42 passed · 退出码 0\n" - ) - assert writer._schedule.call_count == 3 - - def test_stream_writer_formats_trace_events_as_icon_summaries(self, mock_feishu_channel): - from channels.feishu_channel import _FeishuStreamWriter - - writer = _FeishuStreamWriter(12, "om_msg", mock_feishu_channel, "Streaming task") - writer._schedule = Mock() - - writer.on_event( - 12, - 34, - "web_search", - json.dumps( - { - "query": "site:github.com agent memory", - "action": {"type": "search", "query": "agent memory"}, - "status": "completed", - } - ), - ) - writer.on_event( - 12, - 34, - "tool_call", - json.dumps( - { - "server": "github", - "name": "search_issues", - "input": {"query": "is:open label:bug", "token": "[redacted]"}, - "status": "completed", - } - ), - ) - - text = writer.snapshot_text() - assert text == ( - "⌕ 网页搜索 site:github.com agent memory · completed\n" - "▣ 调用工具 github.search_issues · is:open label:bug · completed\n" - ) - assert "{" not in text - assert "动作:" not in text - assert "参数:" not in text - - def test_stream_writer_keeps_long_command_output_as_one_summary_line(self, mock_feishu_channel): - from channels.feishu_channel import _FeishuStreamWriter - - writer = _FeishuStreamWriter(12, "om_msg", mock_feishu_channel, "Streaming task") - writer._schedule = Mock() - long_output = "\n".join(f"line {i}: {'x' * 40}" for i in range(120)) - - writer.on_event( - 12, - 34, - "command_execution", - json.dumps({"command": "/bin/zsh -lc npm test", "output": long_output, "exit_code": 0}), - ) - - text = writer.snapshot_text() - assert text.count("\n") == 1 - assert text.startswith("$ 执行命令 /bin/zsh -lc npm test · line 0:") - assert "line 1:" not in text - assert "输出:" not in text - - elements = mock_feishu_channel._build_streaming_history_elements(text) - assert len(elements) == 1 - assert elements[0]["tag"] == "div" - - def test_stream_writer_keeps_full_text_for_folded_history(self, mock_feishu_channel): - from channels.feishu_channel import _FeishuStreamWriter - - long_text = "A" * 5000 - writer = _FeishuStreamWriter(12, "om_msg", mock_feishu_channel, "Streaming task") - writer._schedule = Mock() - - writer.on_event(12, 34, "assistant", f"[thinking] {long_text}") - - mock_feishu_channel._build_streaming_card = Mock(return_value={"card": True}) - mock_feishu_channel._patch_message = Mock() - - writer._do_patch() - - mock_feishu_channel._build_streaming_card.assert_called_once_with( - 12, "Streaming task", long_text - ) - - def test_stream_writer_resets_when_run_changes(self, mock_feishu_channel): - from channels.feishu_channel import _FeishuStreamWriter - - writer = _FeishuStreamWriter(12, "om_msg", mock_feishu_channel, "Streaming task") - writer._schedule = Mock() - - writer.on_event(12, 34, "assistant", "[thinking] old") - writer.on_event(12, 35, "assistant", "[thinking] new") - - mock_feishu_channel._build_streaming_card = Mock(return_value={"card": True}) - mock_feishu_channel._patch_message = Mock() - - writer._do_patch() - - mock_feishu_channel._build_streaming_card.assert_called_once_with( - 12, "Streaming task", "new" - ) - - def test_stream_writer_keeps_plain_assistant_text_for_live_card(self, mock_feishu_channel): - from channels.feishu_channel import _FeishuStreamWriter - - writer = _FeishuStreamWriter(12, "om_msg", mock_feishu_channel, "Streaming task") - writer._schedule = Mock() - - writer.on_event(12, 34, "assistant", "Hello world") - - assert writer._parts == ["Hello world"] - writer._schedule.assert_called_once() - - def test_stream_writer_does_not_overlap_patch_requests(self, mock_feishu_channel): - from channels.feishu_channel import _FeishuStreamWriter - - writer = _FeishuStreamWriter(12, "om_msg", mock_feishu_channel, "Streaming task") - writer._start_patch_locked = Mock() - - with writer._state_lock: - writer._patch_in_flight = True - - writer.on_event(12, 34, "assistant", "[thinking] Hello world") - - writer._start_patch_locked.assert_not_called() - assert writer._dirty is True diff --git a/tests/test_feishu_outbound.py b/tests/test_feishu_outbound.py deleted file mode 100644 index 2b5b3bd..0000000 --- a/tests/test_feishu_outbound.py +++ /dev/null @@ -1,552 +0,0 @@ -""" -Tests for Feishu outbound dispatch, SDK wrappers, usage stats and small card -builder helpers. Complements tests/test_feishu_message_rendering.py (which covers -notification/streaming card layout) without duplicating it. -""" - -from unittest.mock import Mock, patch - -import pytest - -from taskboard_bus import OutboundMessage, OutboundMessageType - - -@pytest.fixture -def channel(): - with patch("channels.feishu_channel.FEISHU_AVAILABLE", True): - from channels.feishu_channel import FeishuChannel - - ch = FeishuChannel(Mock(), Mock(), Mock()) - ch._client = Mock() - return ch - - -def _lark_response(success=True, message_id="om_new", code=0, msg="ok"): - """Build a lark-style response object with .success()/.code/.msg/.data.""" - resp = Mock() - resp.success.return_value = success - resp.code = code - resp.msg = msg - resp.data = Mock() - resp.data.message_id = message_id - return resp - - -# ── send() / _on_outbound dispatch ──────────────────────────────────── - - -class TestSendDispatch: - def test_send_ignores_non_terminal_types(self, channel): - channel.db.get_task = Mock() - msg = OutboundMessage(type=OutboundMessageType.TASK_STARTED, task_id=1, payload={}) - channel.send(msg) - channel.db.get_task.assert_not_called() - - def test_send_skips_when_client_missing(self, channel): - channel._client = None - channel.db.get_task = Mock() - msg = OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, task_id=1, payload={"result": "x"} - ) - channel.send(msg) - channel.db.get_task.assert_not_called() - - def test_send_skips_when_task_not_found(self, channel): - channel.db.get_task = Mock(return_value=None) - channel._send_message = Mock() - msg = OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, task_id=1, payload={"result": "x"} - ) - channel.send(msg) - channel._send_message.assert_not_called() - - def test_send_failed_uses_error_and_status_hint(self, channel): - task = {"id": 3, "title": "Boom", "prompt": "p", "agent": "claude", "result": None} - channel.db.get_task = Mock(return_value=task) - channel.db.get_setting = Mock(return_value="oc_default") - channel._stop_streaming = Mock(return_value=None) - channel._send_message = Mock(return_value="om_sent") - - msg = OutboundMessage( - type=OutboundMessageType.TASK_FAILED, - task_id=3, - payload={"error": "boom happened"}, - ) - channel.send(msg) - - args, kwargs = channel._send_message.call_args - assert args[1] == "boom happened" # content (error) - card = kwargs["card"] - assert any( - el.get("tag") == "markdown" and "/status 3" in el.get("content", "") - for el in card["body"]["elements"] - ) - - def test_send_failed_truncates_long_error_to_800(self, channel): - task = {"id": 4, "title": "Boom", "prompt": "p", "agent": "claude", "result": None} - channel.db.get_task = Mock(return_value=task) - channel.db.get_setting = Mock(return_value="oc_default") - channel._stop_streaming = Mock(return_value=None) - channel._send_message = Mock(return_value="om_sent") - - msg = OutboundMessage( - type=OutboundMessageType.TASK_FAILED, - task_id=4, - payload={"error": "E" * 2000}, - ) - channel.send(msg) - content = channel._send_message.call_args.args[1] - assert content == "E" * 800 - - def test_send_falls_back_to_default_chat_when_no_origin(self, channel): - task = {"id": 5, "title": "Done", "prompt": "p", "agent": "codex", "result": "all good"} - channel.db.get_task = Mock(return_value=task) - channel.db.get_setting = Mock(return_value="oc_default") - channel._stop_streaming = Mock(return_value=None) - channel._collect_generated_image_paths = Mock(return_value=[]) - channel._send_message = Mock(return_value="om_sent") - - msg = OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, task_id=5, payload={"result": "all good"} - ) - channel.send(msg) - - channel.db.get_setting.assert_called_with("feishu_default_chat_id") - assert channel._send_message.call_args.args[0] == "oc_default" - # Successful send registers the notification mapping. - assert channel._notification_map["om_sent"] == 5 - - def test_send_no_default_chat_logs_failure_without_mapping(self, channel): - task = {"id": 6, "title": "Done", "prompt": "p", "agent": "codex", "result": "ok"} - channel.db.get_task = Mock(return_value=task) - channel.db.get_setting = Mock(return_value=None) # no default chat - channel._stop_streaming = Mock(return_value=None) - channel._collect_generated_image_paths = Mock(return_value=[]) - channel._send_message = Mock(return_value="om_sent") - - msg = OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, task_id=6, payload={"result": "ok"} - ) - channel.send(msg) - - channel._send_message.assert_not_called() - assert channel._notification_map == {} - - def test_send_with_origin_replies_in_thread_and_reacts(self, channel): - task = {"id": 7, "title": "Done", "prompt": "p", "agent": "codex", "result": "yay"} - channel.db.get_task = Mock(return_value=task) - channel._stop_streaming = Mock(return_value=None) - channel._collect_generated_image_paths = Mock(return_value=[]) - channel._add_reaction = Mock() - channel._reply_message = Mock(return_value="om_reply") - channel._send_message = Mock() - channel._task_origin[7] = ("oc_chat", "root_msg", "reaction_msg") - - msg = OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, task_id=7, payload={"result": "yay"} - ) - channel.send(msg) - - channel._add_reaction.assert_called_once_with("reaction_msg", "DONE") - channel._reply_message.assert_called_once() - assert channel._reply_message.call_args.args[0] == "root_msg" - channel._send_message.assert_not_called() - # Origin freed after terminal state. - assert 7 not in channel._task_origin - - def test_send_failed_with_origin_uses_cry_reaction(self, channel): - task = {"id": 8, "title": "Boom", "prompt": "p", "agent": "codex", "result": None} - channel.db.get_task = Mock(return_value=task) - channel._stop_streaming = Mock(return_value=None) - channel._add_reaction = Mock() - channel._reply_message = Mock(return_value="om_reply") - channel._task_origin[8] = ("oc_chat", "root_msg", "reaction_msg") - - msg = OutboundMessage( - type=OutboundMessageType.TASK_FAILED, task_id=8, payload={"error": "nope"} - ) - channel.send(msg) - channel._add_reaction.assert_called_once_with("reaction_msg", "Cry") - - def test_send_patches_streaming_card_when_present(self, channel): - task = {"id": 9, "title": "Done", "prompt": "p", "agent": "codex", "result": "final"} - channel.db.get_task = Mock(return_value=task) - channel._stop_streaming = Mock(return_value="history line") - channel._collect_generated_image_paths = Mock(return_value=[]) - channel._add_reaction = Mock() - channel._patch_message = Mock(return_value=True) - channel._reply_message = Mock() - channel._task_origin[9] = ("oc_chat", "root_msg", "reaction_msg") - channel._streaming_msg[9] = "om_stream" - - msg = OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, task_id=9, payload={"result": "final"} - ) - channel.send(msg) - - channel._patch_message.assert_called_once() - assert channel._patch_message.call_args.args[0] == "om_stream" - channel._reply_message.assert_not_called() - assert channel._notification_map["om_stream"] == 9 - - def test_send_falls_back_to_reply_when_patch_fails(self, channel): - task = {"id": 10, "title": "Done", "prompt": "p", "agent": "codex", "result": "final"} - channel.db.get_task = Mock(return_value=task) - channel._stop_streaming = Mock(return_value=None) - channel._collect_generated_image_paths = Mock(return_value=[]) - channel._add_reaction = Mock() - channel._patch_message = Mock(return_value=False) - channel._reply_message = Mock(return_value="om_reply") - channel._task_origin[10] = ("oc_chat", "root_msg", "reaction_msg") - channel._streaming_msg[10] = "om_stream" - - msg = OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, task_id=10, payload={"result": "final"} - ) - channel.send(msg) - - channel._patch_message.assert_called_once() - channel._reply_message.assert_called_once() - assert channel._notification_map["om_reply"] == 10 - - def test_send_attaches_generated_image_keys(self, channel): - task = {"id": 11, "title": "Img", "prompt": "p", "agent": "codex", "result": "see image"} - channel.db.get_task = Mock(return_value=task) - channel.db.get_setting = Mock(return_value="oc_default") - channel._stop_streaming = Mock(return_value=None) - channel._collect_generated_image_paths = Mock(return_value=["/tmp/a.png"]) - channel._upload_image_entries = Mock(return_value=[("/tmp/a.png", "img_key_1")]) - channel._hide_generated_image_paths = Mock(return_value="see image") - channel._send_message = Mock(return_value="om_sent") - - msg = OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, task_id=11, payload={"result": "see image"} - ) - channel.send(msg) - - channel._hide_generated_image_paths.assert_called_once() - card = channel._send_message.call_args.kwargs["card"] - assert card["body"]["elements"][-1] == { - "tag": "img", - "img_key": "img_key_1", - "alt": {"tag": "plain_text", "content": "generated image 1"}, - } - - def test_on_outbound_delegates_to_send(self, channel): - channel.send = Mock() - msg = OutboundMessage(type=OutboundMessageType.TASK_COMPLETED, task_id=1, payload={}) - channel._on_outbound(msg) - channel.send.assert_called_once_with(msg) - - -# ── SDK wrappers ────────────────────────────────────────────────────── - - -class TestCreateMessage: - def test_create_message_success_returns_id(self, channel): - channel._client.im.v1.message.create.return_value = _lark_response(message_id="om_ok") - result = channel._create_message( - receive_id_type="chat_id", chat_id="oc_x", card={"schema": "2.0"} - ) - assert result == "om_ok" - req = channel._client.im.v1.message.create.call_args.args[0] - body = req.request_body - assert body.receive_id == "oc_x" - assert body.msg_type == "interactive" - assert "schema" in body.content - - def test_create_message_failure_returns_none(self, channel): - channel._client.im.v1.message.create.return_value = _lark_response( - success=False, code=99, msg="bad" - ) - assert channel._create_message("chat_id", "oc_x", {"k": "v"}) is None - - -class TestCreateReply: - def test_create_reply_success_sets_thread_flag(self, channel): - channel._client.im.v1.message.reply.return_value = _lark_response(message_id="om_reply") - result = channel._create_reply(parent_message_id="om_parent", card={"a": 1}) - assert result == "om_reply" - req = channel._client.im.v1.message.reply.call_args.args[0] - assert req.message_id == "om_parent" - assert req.request_body.reply_in_thread is True - assert req.request_body.msg_type == "interactive" - - def test_create_reply_failure_returns_none(self, channel): - channel._client.im.v1.message.reply.return_value = _lark_response( - success=False, code=5, msg="nope" - ) - assert channel._create_reply("om_parent", {"a": 1}) is None - - def test_create_reply_no_client_returns_none(self, channel): - channel._client = None - assert channel._create_reply("om_parent", {"a": 1}) is None - - -class TestSendMessage: - def test_send_message_returns_id_on_success(self, channel): - channel._create_message = Mock(return_value="om_1") - result = channel._send_message("oc_chat", "hi", card={"schema": "2.0"}) - assert result == "om_1" - assert channel._create_message.call_args.kwargs["receive_id_type"] == "chat_id" - - def test_send_message_uses_open_id_for_non_oc(self, channel): - channel._create_message = Mock(return_value="om_1") - channel._send_message("ou_user", "hi", card={"schema": "2.0"}) - assert channel._create_message.call_args.kwargs["receive_id_type"] == "open_id" - - def test_send_message_no_client_returns_none(self, channel): - channel._client = None - assert channel._send_message("oc_x", "hi") is None - - def test_send_message_builds_legacy_card_when_no_card(self, channel): - channel._create_message = Mock(return_value="om_1") - channel._send_message("oc_x", "plain text") - sent_card = channel._create_message.call_args.kwargs["card"] - assert sent_card == channel._build_legacy_markdown_card("plain text") - - def test_send_message_retries_with_legacy_on_card_failure(self, channel): - channel._create_message = Mock(side_effect=[None, "om_retry"]) - result = channel._send_message( - "oc_x", "content", card={"schema": "2.0"}, fallback_content="fb" - ) - assert result == "om_retry" - assert channel._create_message.call_count == 2 - retry_card = channel._create_message.call_args_list[1].kwargs["card"] - assert retry_card == channel._build_legacy_markdown_card("fb") - - def test_send_message_no_retry_when_legacy_card_originally(self, channel): - # card=None path: a single failure returns None (no retry). - channel._create_message = Mock(return_value=None) - assert channel._send_message("oc_x", "content") is None - assert channel._create_message.call_count == 1 - - def test_send_message_handles_exception(self, channel): - channel._create_message = Mock(side_effect=RuntimeError("boom")) - assert channel._send_message("oc_x", "content", card={"a": 1}) is None - - -class TestReplyMessage: - def test_reply_message_returns_id_on_success(self, channel): - channel._create_reply = Mock(return_value="om_r") - assert channel._reply_message("om_parent", "hi", card={"a": 1}) == "om_r" - - def test_reply_message_no_client_returns_none(self, channel): - channel._client = None - assert channel._reply_message("om_parent", "hi") is None - - def test_reply_message_retries_with_legacy_on_failure(self, channel): - channel._create_reply = Mock(side_effect=[None, "om_retry"]) - result = channel._reply_message("om_parent", "content", card={"schema": "2.0"}) - assert result == "om_retry" - assert channel._create_reply.call_count == 2 - retry_card = channel._create_reply.call_args_list[1].kwargs["card"] - assert retry_card == channel._build_legacy_markdown_card("content") - - def test_reply_message_no_retry_when_legacy_card(self, channel): - channel._create_reply = Mock(return_value=None) - assert channel._reply_message("om_parent", "content") is None - assert channel._create_reply.call_count == 1 - - def test_reply_message_handles_exception(self, channel): - channel._create_reply = Mock(side_effect=RuntimeError("boom")) - assert channel._reply_message("om_parent", "content", card={"a": 1}) is None - - -class TestPatchMessage: - def test_patch_message_success(self, channel): - channel._client.im.v1.message.patch.return_value = _lark_response() - assert channel._patch_message("om_x", {"schema": "2.0"}) is True - req = channel._client.im.v1.message.patch.call_args.args[0] - assert req.message_id == "om_x" - assert "schema" in req.request_body.content - - def test_patch_message_failure_returns_false(self, channel): - channel._client.im.v1.message.patch.return_value = _lark_response( - success=False, code=7, msg="nope" - ) - assert channel._patch_message("om_x", {"a": 1}) is False - - def test_patch_message_no_client_returns_false(self, channel): - channel._client = None - assert channel._patch_message("om_x", {"a": 1}) is False - - def test_patch_message_handles_exception(self, channel): - channel._client.im.v1.message.patch.side_effect = RuntimeError("boom") - assert channel._patch_message("om_x", {"a": 1}) is False - - -# ── _add_reaction ───────────────────────────────────────────────────── - - -class TestAddReaction: - def test_add_reaction_success_calls_sdk(self, channel): - with patch("channels.feishu_channel.threading.Thread") as thread_cls: - thread_cls.side_effect = lambda target, daemon: _RunNowThread(target) - channel._add_reaction("om_x", "DONE") - channel._client.im.v1.message_reaction.create.assert_called_once() - - def test_add_reaction_swallows_exception(self, channel): - channel._client.im.v1.message_reaction.create.side_effect = RuntimeError("boom") - with patch("channels.feishu_channel.threading.Thread") as thread_cls: - thread_cls.side_effect = lambda target, daemon: _RunNowThread(target) - channel._add_reaction("om_x", "DONE") # must not raise - - def test_add_reaction_no_client_noop(self, channel): - channel._client = None - channel._add_reaction("om_x") # must not raise - - -class _RunNowThread: - """Thread stand-in that runs the target synchronously on start().""" - - def __init__(self, target): - self._target = target - - def start(self): - self._target() - - -# ── small builders / text helpers ───────────────────────────────────── - - -class TestTextHelpers: - def test_build_legacy_markdown_card(self, channel): - card = channel._build_legacy_markdown_card("hello") - assert card == { - "config": {"wide_screen_mode": True}, - "elements": [{"tag": "markdown", "content": "hello"}], - } - - def test_truncate_text_under_limit_unchanged(self, channel): - assert channel._truncate_text("short", 100) == "short" - - def test_truncate_text_over_limit_marks_truncated(self, channel): - out = channel._truncate_text("A" * 50, 10) - assert out.startswith("A" * 10) - assert out.endswith("…(truncated)") - - def test_truncate_text_normalizes_crlf(self, channel): - assert channel._truncate_text("a\r\nb", 100) == "a\nb" - - def test_chunk_text_empty_returns_single_empty(self, channel): - assert channel._chunk_text("", 10) == [""] - - def test_chunk_text_splits_on_limit(self, channel): - assert channel._chunk_text("abcdef", 2) == ["ab", "cd", "ef"] - - def test_escape_feishu_markdown_doubles_backslash(self, channel): - assert channel._escape_feishu_markdown(r"a\b") == r"a\\b" - - def test_build_result_elements_chunks_and_appends_images(self, channel): - elements = channel._build_result_elements("body", image_keys=["k1", "k2"]) - assert elements[0] == {"tag": "markdown", "content": "body"} - assert elements[-2:] == [ - { - "tag": "img", - "img_key": "k1", - "alt": {"tag": "plain_text", "content": "generated image 1"}, - }, - { - "tag": "img", - "img_key": "k2", - "alt": {"tag": "plain_text", "content": "generated image 2"}, - }, - ] - - def test_build_result_elements_empty_body_defaults_done(self, channel): - assert channel._build_result_elements("") == [{"tag": "markdown", "content": "Done."}] - - def test_strip_final_result_from_history_removes_suffix(self, channel): - out = channel._strip_final_result_from_history("trace step\nfinal answer", "final answer") - assert out == "trace step" - - def test_strip_final_result_keeps_history_when_not_suffix(self, channel): - out = channel._strip_final_result_from_history("trace step\nfinal", "other text") - assert out == "trace step\nfinal" - - def test_strip_final_result_empty_final_returns_history(self, channel): - assert channel._strip_final_result_from_history("hist", "") == "hist" - - def test_build_streaming_history_elements_empty(self, channel): - assert channel._build_streaming_history_elements("\n\n") == [] - - def test_build_streaming_history_elements_lines(self, channel): - elements = channel._build_streaming_history_elements("a\n\nb") - assert [e["text"]["content"] for e in elements] == ["a", " ", "b"] - assert all(e["text"]["text_color"] == "grey" for e in elements) - - -# ── _get_usage_stats ────────────────────────────────────────────────── - - -def _block(**overrides): - base = { - "isGap": False, - "isActive": True, - "startTime": "2026-06-04T08:00:00+00:00", - "endTime": "2026-06-04T13:00:00+00:00", - "totalTokens": 9500, - "costUSD": 9.0, - "sentMessagesCount": 125, - "durationMinutes": 120, - } - base.update(overrides) - return base - - -class TestUsageStats: - def test_no_data_returns_no_records(self, channel): - with patch("claude_monitor.data.analysis.analyze_usage", return_value=None): - assert channel._get_usage_stats() == "📊 未找到 Claude Code 用量记录" - - def test_no_blocks_key_returns_no_records(self, channel): - with patch("claude_monitor.data.analysis.analyze_usage", return_value={"blocks": []}): - assert channel._get_usage_stats() == "📊 未找到 Claude Code 用量记录" - - def test_only_gap_blocks_returns_no_records(self, channel): - data = {"blocks": [{"isGap": True}]} - with patch("claude_monitor.data.analysis.analyze_usage", return_value=data): - assert channel._get_usage_stats() == "📊 未找到 Claude Code 用量记录" - - def test_active_block_renders_full_stats(self, channel): - channel.db.get_setting = Mock(return_value="pro") - data = {"blocks": [_block()]} - with patch("claude_monitor.data.analysis.analyze_usage", return_value=data): - out = channel._get_usage_stats() - - assert out.startswith("**📊 Claude Code 用量**") - assert "(活跃)" in out - assert "Plan: pro" in out - # 9500 tokens / 19000 limit = 50% - assert "📊 Token: **[" in out - assert "50.0%" in out - assert "9,500 / 19,000" in out - # 125 msgs / 250 limit = 50% - assert "125 / 250" in out - # cost 9 / 18 = 50% - assert "$9.00 / $18" in out - assert "🔥 Burn:" in out - - def test_inactive_block_shows_ended_label(self, channel): - channel.db.get_setting = Mock(return_value="pro") - data = {"blocks": [_block(isActive=False)]} - with patch("claude_monitor.data.analysis.analyze_usage", return_value=data): - out = channel._get_usage_stats() - assert "(已结束)" in out - - def test_percentages_capped_at_100(self, channel): - channel.db.get_setting = Mock(return_value="pro") - data = {"blocks": [_block(totalTokens=10**9, costUSD=10**6, sentMessagesCount=10**6)]} - with patch("claude_monitor.data.analysis.analyze_usage", return_value=data): - out = channel._get_usage_stats() - assert "100.0%" in out - - def test_exception_returns_error_message(self, channel): - with patch( - "claude_monitor.data.analysis.analyze_usage", - side_effect=RuntimeError("kaboom"), - ): - out = channel._get_usage_stats() - assert out.startswith("❌ 获取用量统计失败:") - assert "kaboom" in out diff --git a/tests/test_heartbeat.py b/tests/test_heartbeat.py deleted file mode 100644 index cce0e4a..0000000 --- a/tests/test_heartbeat.py +++ /dev/null @@ -1,149 +0,0 @@ -import json - -from taskboard import ( - Heartbeat, - HeartbeatDecisionType, - HeartbeatScheduleType, - ScheduleType, - TaskDB, - TaskScheduler, -) - - -def make_db(tmp_path): - return TaskDB(str(tmp_path / "agentforge-test.db")) - - -def make_heartbeat(**overrides): - data = { - "name": "Repo watcher", - "working_dir": ".", - "schedule_type": HeartbeatScheduleType.INTERVAL, - "interval_seconds": 60, - "check_prompt": "Inspect repo and decide whether work is needed.", - "action_prompt_template": "Review the latest changes.", - "default_agent": "claude", - "cooldown_seconds": 300, - } - data.update(overrides) - return Heartbeat(**data) - - -def test_add_and_get_heartbeat(tmp_path): - db = make_db(tmp_path) - heartbeat_id = db.add_heartbeat(make_heartbeat()) - - heartbeat = db.get_heartbeat(heartbeat_id) - - assert heartbeat is not None - assert heartbeat["name"] == "Repo watcher" - assert heartbeat["enabled"] is True - assert heartbeat["schedule_type"] == HeartbeatScheduleType.INTERVAL.value - assert heartbeat["next_run_at"] is not None - - -def test_heartbeat_trigger_creates_task_and_tick(tmp_path, monkeypatch): - db = make_db(tmp_path) - scheduler = TaskScheduler(db) - heartbeat_id = db.add_heartbeat(make_heartbeat()) - heartbeat = db.get_heartbeat(heartbeat_id) - - decision = { - "decision": HeartbeatDecisionType.TRIGGER_TASK.value, - "reason": "Found new changes", - "dedupe_key": "repo:abc123", - "title": "Review latest changes", - "prompt": "Review commit abc123.", - "metadata": {}, - } - - def fake_run(agent, cmd, cwd, on_stdout_line=None, on_stderr_line=None): - payload = json.dumps(decision) - if on_stdout_line: - on_stdout_line(payload) - return True, payload - - monkeypatch.setattr(scheduler, "_run_agent_command", fake_run) - - scheduler._execute_heartbeat(heartbeat) - - tasks = db.get_all_tasks() - assert len(tasks) == 1 - assert tasks[0]["title"] == "Review latest changes" - assert tasks[0]["prompt"] == "Review commit abc123." - assert tasks[0]["schedule_type"] == ScheduleType.IMMEDIATE.value - - updated = db.get_heartbeat(heartbeat_id) - assert updated["last_decision"] == HeartbeatDecisionType.TRIGGER_TASK.value - assert updated["last_triggered_at"] is not None - assert updated["last_dedupe_key"] == "repo:abc123" - - ticks = db.get_heartbeat_ticks(heartbeat_id) - assert len(ticks) == 1 - assert ticks[0]["status"] == "triggered" - assert ticks[0]["task_id"] == tasks[0]["id"] - assert ticks[0]["raw_output"] == json.dumps(decision) - - -def test_heartbeat_duplicate_signal_is_suppressed(tmp_path, monkeypatch): - db = make_db(tmp_path) - scheduler = TaskScheduler(db) - heartbeat_id = db.add_heartbeat(make_heartbeat()) - heartbeat = db.get_heartbeat(heartbeat_id) - - decision = { - "decision": HeartbeatDecisionType.TRIGGER_TASK.value, - "reason": "Found new changes", - "dedupe_key": "repo:abc123", - "title": "Review latest changes", - "prompt": "Review commit abc123.", - "metadata": {}, - } - - def fake_run(agent, cmd, cwd, on_stdout_line=None, on_stderr_line=None): - payload = json.dumps(decision) - if on_stdout_line: - on_stdout_line(payload) - return True, payload - - monkeypatch.setattr(scheduler, "_run_agent_command", fake_run) - - scheduler._execute_heartbeat(heartbeat) - scheduler._execute_heartbeat(db.get_heartbeat(heartbeat_id)) - - tasks = db.get_all_tasks() - assert len(tasks) == 1 - - heartbeat = db.get_heartbeat(heartbeat_id) - assert heartbeat["last_decision"] == HeartbeatDecisionType.IDLE.value - - ticks = db.get_heartbeat_ticks(heartbeat_id) - assert len(ticks) == 2 - assert ticks[0]["status"] == "idle" - assert "Suppressed duplicate signal" in json.loads(ticks[0]["decision_payload"])["reason"] - - -def test_heartbeat_invalid_json_records_error(tmp_path, monkeypatch): - db = make_db(tmp_path) - scheduler = TaskScheduler(db) - heartbeat_id = db.add_heartbeat(make_heartbeat()) - heartbeat = db.get_heartbeat(heartbeat_id) - - def fake_run(agent, cmd, cwd, on_stdout_line=None, on_stderr_line=None): - if on_stdout_line: - on_stdout_line("not json") - return True, "not json" - - monkeypatch.setattr(scheduler, "_run_agent_command", fake_run) - - scheduler._execute_heartbeat(heartbeat) - - updated = db.get_heartbeat(heartbeat_id) - assert updated["last_decision"] == HeartbeatDecisionType.ERROR.value - assert updated["last_error"] - - ticks = db.get_heartbeat_ticks(heartbeat_id) - assert len(ticks) == 1 - assert ticks[0]["status"] == "error" - assert ticks[0]["error"] - assert ticks[0]["raw_output"] == "not json" diff --git a/tests/test_scheduler_logic.py b/tests/test_scheduler_logic.py deleted file mode 100644 index 5245b6f..0000000 --- a/tests/test_scheduler_logic.py +++ /dev/null @@ -1,689 +0,0 @@ -"""Direct unit tests for TaskScheduler logic not exercised by HTTP tests. - -Covers schedule computation / due dispatch (_tick, _schedule_delayed), heartbeat -decision flow (idle / notify / suppressed / error), heartbeat next-run + cooldown -suppression, skill sweep core (run_skill_sweep, _parse_sweep_output, -_build_sweep_prompt), distill prompt building, submit_task dependency gating, and -the DAG unblock / cascade-cancel helpers. All agent execution is mocked — no real -subprocess or network is ever spawned, and the background loop is never started. -""" - -import json -from datetime import datetime, timedelta, timezone - -import pytest - -from taskboard import ( - Heartbeat, - HeartbeatDecisionType, - HeartbeatScheduleType, - ScheduleType, - Task, - TaskDB, - TaskScheduler, -) - - -def make_db(tmp_path): - return TaskDB(str(tmp_path / "sched-test.db")) - - -def make_heartbeat(**overrides): - data = { - "name": "Repo watcher", - "working_dir": ".", - "schedule_type": HeartbeatScheduleType.INTERVAL, - "interval_seconds": 60, - "check_prompt": "Inspect repo.", - "action_prompt_template": "Review the latest changes.", - "default_agent": "claude", - "cooldown_seconds": 300, - } - data.update(overrides) - return Heartbeat(**data) - - -# ── heartbeat next-run computation ────────────────────────────────────────── -def test_compute_next_run_interval(tmp_path): - db = make_db(tmp_path) - now = datetime(2024, 1, 1, 12, 0, 0) - nxt = db._compute_heartbeat_next_run_at(make_heartbeat(interval_seconds=90), now) - assert nxt == (now + timedelta(seconds=90)).isoformat() - - -def test_compute_next_run_cron(tmp_path): - db = make_db(tmp_path) - now = datetime(2024, 1, 1, 12, 30, 0) - hb = make_heartbeat( - schedule_type=HeartbeatScheduleType.CRON, cron_expr="0 * * * *", interval_seconds=None - ) - nxt = db._compute_heartbeat_next_run_at(hb, now) - assert nxt == datetime(2024, 1, 1, 13, 0, 0).isoformat() - - -def test_compute_next_run_invalid_raises(tmp_path): - db = make_db(tmp_path) - with pytest.raises(ValueError, match="interval_seconds"): - db._compute_heartbeat_next_run_at(make_heartbeat(interval_seconds=0), datetime.now()) - with pytest.raises(ValueError, match="cron_expr"): - db._compute_heartbeat_next_run_at( - make_heartbeat(schedule_type=HeartbeatScheduleType.CRON, cron_expr=None), - datetime.now(), - ) - - -# ── _tick dispatch by schedule type ───────────────────────────────────────── -def test_tick_promotes_delayed_pending_to_scheduled(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - tid = db.add_task( - Task( - title="delayed", - prompt="p", - working_dir=".", - schedule_type=ScheduleType.DELAYED, - delay_seconds=120, - ) - ) - spawned = [] - monkeypatch.setattr(sched, "_spawn_task", lambda t: spawned.append(t["id"])) - - sched._tick() # pending delayed → schedules forward, does not spawn yet - - assert spawned == [] - task = db.get_task(tid) - assert task["status"] == "scheduled" - nra = datetime.fromisoformat(task["next_run_at"]) - assert nra > datetime.now() - - -def test_tick_spawns_immediate_and_due_cron(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - imm = db.add_task(Task(title="imm", prompt="p", working_dir=".")) - cron = db.add_task( - Task( - title="cron", - prompt="p", - working_dir=".", - schedule_type=ScheduleType.CRON, - cron_expr="* * * * *", - next_run_at=(datetime.now() - timedelta(minutes=1)).isoformat(), - ) - ) - db.update_task(cron, status="scheduled") - - spawned = [] - monkeypatch.setattr(sched, "_spawn_task", lambda t: spawned.append(t["id"])) - - sched._tick() - - assert imm in spawned - assert cron in spawned - - -def test_tick_skips_active_task(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - tid = db.add_task(Task(title="imm", prompt="p", working_dir=".")) - - class _AliveThread: - def is_alive(self): - return True - - sched._active_tasks[tid] = _AliveThread() - spawned = [] - monkeypatch.setattr(sched, "_spawn_task", lambda t: spawned.append(t["id"])) - - sched._tick() - assert spawned == [] # already running, not re-picked - - -def test_tick_shutting_down_is_noop(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - db.add_task(Task(title="imm", prompt="p", working_dir=".")) - sched._shutting_down = True - called = [] - monkeypatch.setattr(sched, "_spawn_task", lambda t: called.append(t)) - sched._tick() - assert called == [] - - -def test_schedule_delayed_uses_delay_seconds(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - tid = db.add_task( - Task( - title="d", - prompt="p", - working_dir=".", - schedule_type=ScheduleType.DELAYED, - delay_seconds=300, - ) - ) - before = datetime.now() - sched._schedule_delayed(db.get_task(tid)) - task = db.get_task(tid) - assert task["status"] == "scheduled" - nra = datetime.fromisoformat(task["next_run_at"]) - assert before + timedelta(seconds=299) <= nra <= before + timedelta(seconds=301) - - -# ── submit_task scheduling / dependency gating ────────────────────────────── -def test_submit_task_cron_sets_next_run(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - tid = sched.submit_task( - Task( - title="c", - prompt="p", - working_dir=".", - schedule_type=ScheduleType.CRON, - cron_expr="0 0 * * *", - ) - ) - task = db.get_task(tid) - assert task["status"] == "scheduled" - assert task["next_run_at"] is not None - assert datetime.fromisoformat(task["next_run_at"]) > datetime.now() - - -def test_submit_task_scheduled_at_requires_next_run(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - with pytest.raises(ValueError, match="next_run_at"): - sched.submit_task( - Task(title="s", prompt="p", working_dir=".", schedule_type=ScheduleType.SCHEDULED_AT) - ) - - -def test_submit_task_blocks_on_unmet_dependency(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - upstream = db.add_task(Task(title="up", prompt="p", working_dir=".")) # pending, not completed - down = sched.submit_task( - Task(title="down", prompt="p", working_dir="."), - depends_on=[{"task_id": upstream, "inject_result": True}], - ) - assert db.get_task(down)["status"] == "blocked" - deps = db.get_dependencies(down) - assert deps[0]["depends_on_task_id"] == upstream - assert deps[0]["inject_result"] == 1 - - -def test_submit_task_ready_when_dependency_completed(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - upstream = db.add_task(Task(title="up", prompt="p", working_dir=".")) - db.update_task(upstream, status="completed") - down = sched.submit_task( - Task(title="down", prompt="p", working_dir="."), - depends_on=[upstream], # bare int form - ) - assert db.get_task(down)["status"] == "pending" - - -# ── DAG unblock / cascade-cancel ──────────────────────────────────────────── -def test_on_task_completed_unblocks_downstream(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - up = db.add_task(Task(title="up", prompt="p", working_dir=".")) - down = sched.submit_task(Task(title="down", prompt="p", working_dir="."), depends_on=[up]) - assert db.get_task(down)["status"] == "blocked" - - db.update_task(up, status="completed") - sched._on_task_completed(up) - - assert db.get_task(down)["status"] == "pending" - - -def test_on_task_completed_keeps_blocked_when_other_dep_pending(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - a = db.add_task(Task(title="a", prompt="p", working_dir=".")) - b = db.add_task(Task(title="b", prompt="p", working_dir=".")) - down = sched.submit_task(Task(title="down", prompt="p", working_dir="."), depends_on=[a, b]) - - db.update_task(a, status="completed") - sched._on_task_completed(a) - # b still pending → stays blocked - assert db.get_task(down)["status"] == "blocked" - - -def test_on_task_failed_cascade_cancels(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - root = db.add_task(Task(title="root", prompt="p", working_dir=".")) - mid = sched.submit_task(Task(title="mid", prompt="p", working_dir="."), depends_on=[root]) - leaf = sched.submit_task(Task(title="leaf", prompt="p", working_dir="."), depends_on=[mid]) - - sched._on_task_failed(root) - - assert db.get_task(mid)["status"] == "cancelled" - assert db.get_task(leaf)["status"] == "cancelled" # recursive cascade - assert f"#{root}" in db.get_task(mid)["error"] - - -def test_build_injected_prompt_prepends_upstream_result(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - up = db.add_task(Task(title="upstream", prompt="p", working_dir=".")) - db.update_task(up, status="completed", result="UPSTREAM OUTPUT") - down = db.add_task(Task(title="down", prompt="DO THE THING", working_dir=".")) - db.add_dependency(down, up, inject_result=True) - - injected = sched._build_injected_prompt(db.get_task(down)) - assert "UPSTREAM OUTPUT" in injected - assert injected.strip().endswith("DO THE THING") - - -def test_build_injected_prompt_without_inject_returns_original(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - up = db.add_task(Task(title="upstream", prompt="p", working_dir=".")) - db.update_task(up, status="completed", result="X") - down = db.add_task(Task(title="down", prompt="ORIGINAL", working_dir=".")) - db.add_dependency(down, up, inject_result=False) - assert sched._build_injected_prompt(db.get_task(down)) == "ORIGINAL" - - -# ── cancel / retry ────────────────────────────────────────────────────────── -def test_cancel_and_retry_task(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - tid = db.add_task(Task(title="t", prompt="p", working_dir=".")) - db.update_task(tid, status="running") - - sched.cancel_task(tid) - assert db.get_task(tid)["status"] == "cancelled" - - db.update_task(tid, status="failed", error="boom") - sched.retry_task(tid) - retried = db.get_task(tid) - assert retried["status"] == "pending" - assert retried["error"] is None - - -# ── heartbeat decision parsing ────────────────────────────────────────────── -def test_parse_heartbeat_decision_strips_fence_and_normalizes(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - raw = '```json\n{"decision":"idle","reason":"nothing"}\n```' - decision = sched._parse_heartbeat_decision(raw) - assert decision["decision"] == "idle" - assert decision["reason"] == "nothing" - # missing fields are coerced to defaults - assert decision["title"] == "" - assert decision["metadata"] == {} - - -def test_parse_heartbeat_decision_extracts_embedded_object(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - raw = 'noise before {"decision":"trigger_task","dedupe_key":"k"} noise after' - decision = sched._parse_heartbeat_decision(raw) - assert decision["decision"] == "trigger_task" - assert decision["dedupe_key"] == "k" - - -def test_parse_heartbeat_decision_invalid_decision_raises(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - with pytest.raises(ValueError, match="Invalid heartbeat decision"): - sched._parse_heartbeat_decision('{"decision":"explode"}') - - -def test_parse_heartbeat_decision_non_dict_metadata_raises(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - with pytest.raises(ValueError, match="metadata must be an object"): - sched._parse_heartbeat_decision('{"decision":"idle","metadata":[1,2]}') - - -def test_render_heartbeat_check_prompt_includes_action_template(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - hid = db.add_heartbeat(make_heartbeat(action_prompt_template="REVIEW THE DIFF")) - prompt = sched._render_heartbeat_check_prompt(db.get_heartbeat(hid)) - assert "Inspect repo." in prompt - assert "REVIEW THE DIFF" in prompt - assert "trigger_task" in prompt - - -# ── heartbeat tick execution flow ─────────────────────────────────────────── -def _mock_agent(sched, monkeypatch, payload): - def fake_run(agent, cmd, cwd, on_stdout_line=None, on_stderr_line=None): - if on_stdout_line: - on_stdout_line(payload) - return True, payload - - monkeypatch.setattr(sched, "_run_agent_command", fake_run) - - -def test_execute_heartbeat_idle_decision(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - hid = db.add_heartbeat(make_heartbeat()) - _mock_agent(sched, monkeypatch, json.dumps({"decision": "idle", "reason": "calm"})) - - sched._execute_heartbeat(db.get_heartbeat(hid)) - - assert db.get_all_tasks() == [] - hb = db.get_heartbeat(hid) - assert hb["last_decision"] == HeartbeatDecisionType.IDLE.value - assert hb["last_error"] is None - # next_run_at advanced - assert datetime.fromisoformat(hb["next_run_at"]) > datetime.now() - tick = db.get_latest_heartbeat_tick(hid) - assert tick["status"] == "idle" - - -def test_execute_heartbeat_notify_only_records_decision(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - hid = db.add_heartbeat(make_heartbeat()) - _mock_agent( - sched, - monkeypatch, - json.dumps({"decision": "notify_only", "reason": "FYI", "dedupe_key": "n1"}), - ) - - sched._execute_heartbeat(db.get_heartbeat(hid)) - - assert db.get_all_tasks() == [] # notify does not create a task - hb = db.get_heartbeat(hid) - assert hb["last_decision"] == HeartbeatDecisionType.NOTIFY_ONLY.value - tick = db.get_latest_heartbeat_tick(hid) - assert tick["status"] == HeartbeatDecisionType.NOTIFY_ONLY.value - - -def test_execute_heartbeat_trigger_falls_back_to_action_template(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - hid = db.add_heartbeat(make_heartbeat(action_prompt_template="DEFAULT ACTION")) - # decision has no prompt/title → falls back to action_prompt_template + default title - _mock_agent( - sched, - monkeypatch, - json.dumps({"decision": "trigger_task", "dedupe_key": "dk"}), - ) - - sched._execute_heartbeat(db.get_heartbeat(hid)) - - tasks = db.get_all_tasks() - assert len(tasks) == 1 - assert tasks[0]["prompt"] == "DEFAULT ACTION" - assert tasks[0]["title"] == "Heartbeat: Repo watcher" - assert tasks[0]["tags"] == "heartbeat" - # dedup row recorded - assert db.get_heartbeat_dedup(hid, "dk") is not None - - -def test_execute_heartbeat_agent_failure_records_error(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - hid = db.add_heartbeat(make_heartbeat()) - - def fail(agent, cmd, cwd, on_stdout_line=None, on_stderr_line=None): - return False, "agent crashed" - - monkeypatch.setattr(sched, "_run_agent_command", fail) - - sched._execute_heartbeat(db.get_heartbeat(hid)) - - hb = db.get_heartbeat(hid) - assert hb["last_decision"] == HeartbeatDecisionType.ERROR.value - assert "agent crashed" in hb["last_error"] - assert db.get_latest_heartbeat_tick(hid)["status"] == "error" - - -# ── heartbeat cooldown suppression ────────────────────────────────────────── -def test_trigger_suppressed_empty_key_is_false(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - assert sched._heartbeat_trigger_suppressed({"id": 1, "cooldown_seconds": 300}, "") is False - - -def test_trigger_suppressed_during_cooldown(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - hid = db.add_heartbeat(make_heartbeat(cooldown_seconds=600)) - db.upsert_heartbeat_dedup(hid, "k", None) # triggered now - assert sched._heartbeat_trigger_suppressed(db.get_heartbeat(hid), "k") is True - - -def test_trigger_not_suppressed_after_cooldown_when_no_active_task(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - hid = db.add_heartbeat(make_heartbeat(cooldown_seconds=60)) - db.upsert_heartbeat_dedup(hid, "k", None) - # age the dedup row past the cooldown - old = (datetime.now() - timedelta(seconds=120)).isoformat() - db.conn.execute( - "UPDATE heartbeat_dedup SET triggered_at=? WHERE heartbeat_id=? AND dedupe_key=?", - (old, hid, "k"), - ) - db.conn.commit() - assert sched._heartbeat_trigger_suppressed(db.get_heartbeat(hid), "k") is False - - -def test_trigger_suppressed_while_prior_task_active(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - hid = db.add_heartbeat(make_heartbeat(cooldown_seconds=0)) # no cooldown - task_id = db.add_task(Task(title="t", prompt="p", working_dir=".")) # pending = active - db.upsert_heartbeat_dedup(hid, "k", task_id) - assert sched._heartbeat_trigger_suppressed(db.get_heartbeat(hid), "k") is True - - # once that task completes, the signal is no longer suppressed - db.update_task(task_id, status="completed") - assert sched._heartbeat_trigger_suppressed(db.get_heartbeat(hid), "k") is False - - -# ── trigger_heartbeat_now ─────────────────────────────────────────────────── -def test_trigger_heartbeat_now_unknown_raises(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - with pytest.raises(ValueError, match="not found"): - sched.trigger_heartbeat_now(99999) - - -# ── skill sweep core ──────────────────────────────────────────────────────── -def test_parse_sweep_output_variants(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - assert sched._parse_sweep_output("[]") == [] - fenced = '```json\n[{"pattern_key":"k"}]\n```' - assert sched._parse_sweep_output(fenced) == [{"pattern_key": "k"}] - embedded = 'prose [{"pattern_key":"k2"}] tail' - assert sched._parse_sweep_output(embedded) == [{"pattern_key": "k2"}] - # non-array / garbage → empty list, never raises - assert sched._parse_sweep_output('{"a":1}') == [] - assert sched._parse_sweep_output("not json") == [] - assert sched._parse_sweep_output("") == [] - - -def test_run_skill_sweep_no_runs_short_circuits(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - called = [] - monkeypatch.setattr( - sched, "_run_agent_prompt_once", lambda *a, **k: called.append(a) or (True, "[]") - ) - - result = sched.run_skill_sweep(agent="claude") - - assert result["scanned"] == 0 - assert result["detected"] == 0 - assert called == [] # never invokes the agent when there's nothing to scan - - -def test_run_skill_sweep_detects_and_advances_watermark(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - tid = db.add_task(Task(title="t", prompt="run pytest", working_dir=".")) - r1 = db.add_run(tid) - r2 = db.add_run(tid) - db.conn.execute( - "UPDATE task_runs SET status='completed', finished_at=? WHERE id=?", - ("2024-01-01T00:00:00", r1), - ) - db.conn.execute( - "UPDATE task_runs SET status='completed', finished_at=? WHERE id=?", - ("2024-01-02T00:00:00", r2), - ) - db.conn.commit() - - # agent reuses the same pattern_key across both runs → recurrence aggregates - sweep_output = json.dumps( - [ - { - "pattern_key": "run-pytest", - "kind": "recipe", - "summary": "s", - "run_id": r1, - "task_id": tid, - }, - { - "pattern_key": "run-pytest", - "kind": "recipe", - "summary": "s", - "run_id": r2, - "task_id": tid, - }, - ] - ) - monkeypatch.setattr(sched, "_run_agent_prompt_once", lambda *a, **k: (True, sweep_output)) - - result = sched.run_skill_sweep(agent="claude", full=True) - - assert result["scanned"] == 2 - assert result["detected"] == 2 - assert result["new"] == 2 - assert db.get_skill_pattern_recurrence("run-pytest") == 2 - # watermark advanced to the newest finished_at - assert db.get_setting("skill_sweep_watermark") == "2024-01-02T00:00:00" - - -def test_run_skill_sweep_agent_failure_raises(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - tid = db.add_task(Task(title="t", prompt="p", working_dir=".")) - rid = db.add_run(tid) - db.conn.execute( - "UPDATE task_runs SET status='completed', finished_at=? WHERE id=?", - ("2024-01-01T00:00:00", rid), - ) - db.conn.commit() - monkeypatch.setattr(sched, "_run_agent_prompt_once", lambda *a, **k: (False, "kaboom")) - with pytest.raises(RuntimeError, match="kaboom"): - sched.run_skill_sweep(agent="claude", full=True) - - -def test_run_skill_sweep_full_ignores_watermark(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - tid = db.add_task(Task(title="t", prompt="p", working_dir=".")) - rid = db.add_run(tid) - db.conn.execute( - "UPDATE task_runs SET status='completed', finished_at=? WHERE id=?", - ("2024-01-01T00:00:00", rid), - ) - db.conn.commit() - # watermark is past the run; full=True must still re-scan it - db.set_setting("skill_sweep_watermark", "2030-01-01T00:00:00") - monkeypatch.setattr(sched, "_run_agent_prompt_once", lambda *a, **k: (True, "[]")) - - result = sched.run_skill_sweep(agent="claude", full=True) - assert result["scanned"] == 1 - - -def test_skill_sweep_status_reflects_last_result(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - monkeypatch.setattr(sched, "_run_agent_prompt_once", lambda *a, **k: (True, "[]")) - sched.run_skill_sweep(agent="claude") # no runs → cached as last - status = sched.skill_sweep_status() - assert status["running"] is False - assert status["last"]["scanned"] == 0 - - -# ── prompt builders ───────────────────────────────────────────────────────── -def test_build_sweep_prompt_lists_existing_and_runs(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - runs = [ - { - "run_id": 5, - "task_id": 2, - "title": "Run tests", - "prompt": "uv run pytest", - "result": "all green", - } - ] - existing = [ - {"pattern_key": "run-pytest", "kind": "recipe", "recurrence_count": 3, "summary": "tests"} - ] - prompt = sched._build_sweep_prompt(runs, existing) - assert "run-pytest" in prompt - assert "run #5" in prompt - assert "uv run pytest" in prompt - # empty existing renders the placeholder - assert "(none yet)" in sched._build_sweep_prompt(runs, []) - - -def test_build_distill_context_and_prompt(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - tid = db.add_task(Task(title="Run tests", prompt="run pytest", working_dir=".")) - rid = db.add_run(tid) - db.finish_run(rid, status="completed", result="green") - - context = sched._build_distill_context([tid]) - assert f"task #{tid}" in context - assert "run pytest" in context - assert "green" in context - - pattern = db.get_skill_pattern(db.upsert_skill_pattern("k", "recipe", "summary", tid)) - with_creator = sched._build_distill_prompt(pattern, context, skill_creator_rel="a/SKILL.md") - assert "skill-creator" in with_creator - assert "a/SKILL.md" in with_creator - without_creator = sched._build_distill_prompt(pattern, context, skill_creator_rel=None) - assert "a/SKILL.md" not in without_creator - assert "skill-creator conventions" in without_creator - - -# ── timezone normalization on submit (scheduled_at) ───────────────────────── -def test_submit_scheduled_at_naive_passthrough(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - naive = (datetime.now() + timedelta(hours=2)).replace(microsecond=0).isoformat() - tid = sched.submit_task( - Task( - title="s", - prompt="p", - working_dir=".", - schedule_type=ScheduleType.SCHEDULED_AT, - next_run_at=naive, - ) - ) - # naive input is stored unchanged (no tz shift) - assert db.get_task(tid)["next_run_at"] == naive - - -def test_submit_scheduled_at_aware_is_localized(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - aware = datetime.now(timezone.utc) + timedelta(hours=3) - tid = sched.submit_task( - Task( - title="s", - prompt="p", - working_dir=".", - schedule_type=ScheduleType.SCHEDULED_AT, - next_run_at=aware.isoformat(), - ) - ) - expected = aware.astimezone().replace(tzinfo=None).isoformat() - assert db.get_task(tid)["next_run_at"] == expected diff --git a/tests/test_scheduler_more.py b/tests/test_scheduler_more.py deleted file mode 100644 index 166b932..0000000 --- a/tests/test_scheduler_more.py +++ /dev/null @@ -1,731 +0,0 @@ -"""Additional direct unit tests for TaskScheduler / heartbeat / skill-sweep -branches that the existing suites don't reach. - -Everything here constructs ``TaskDB`` + ``TaskScheduler`` directly, never starts -the background loop, and mocks every agent invocation so no real CLI is spawned. -Skill-library file I/O is sandboxed under a temp ``$HOME``. - -Deliberately does NOT duplicate tests in test_scheduler_logic.py, test_heartbeat.py, -test_skill_distill.py, test_skill_registry.py, test_skill_patterns.py or -test_skill_scheduler.py — it targets the still-uncovered edges of: - -* on-disk skill helpers (link/unlink/write/remove, frontmatter parse edges) -* AgentExecutor.run output extraction (subprocess mocked, not the executor path) -* heartbeat decision branches (codex prompt path, suppression, resume/pause) -* skill-sweep distillation + draft handling edge cases -* DAG post-execution hooks (scheduled-at/cron unblock, pause/resume/cancel) -""" - -import json -import os -from datetime import datetime, timedelta - -import pytest - -from taskboard import ( - AgentExecutor, - Heartbeat, - HeartbeatDecisionType, - HeartbeatScheduleType, - ScheduleType, - Task, - TaskDB, - TaskScheduler, - _compose_skill_md, - _parse_skill_frontmatter, - _sanitize_skill_name, - link_skill, - remove_skill_from_disk, - unlink_skill, - write_skill_to_disk, -) - - -def make_db(tmp_path): - return TaskDB(str(tmp_path / "t.db")) - - -def make_heartbeat(**overrides): - data = { - "name": "Repo watcher", - "working_dir": ".", - "schedule_type": HeartbeatScheduleType.INTERVAL, - "interval_seconds": 60, - "check_prompt": "Inspect repo.", - "action_prompt_template": "Review the latest changes.", - "default_agent": "claude", - "cooldown_seconds": 300, - } - data.update(overrides) - return Heartbeat(**data) - - -def make_pattern(db, key="k", recurrence=3, tasks=(1, 2, 3), kind="recipe"): - db.upsert_skill_pattern(key, kind, "summary", tasks[0]) - db.conn.execute( - "UPDATE skill_patterns SET recurrence_count=?, contributing_task_ids=? WHERE pattern_key=?", - (recurrence, json.dumps(list(tasks)), key), - ) - db.conn.commit() - return db.conn.execute("SELECT id FROM skill_patterns WHERE pattern_key=?", (key,)).fetchone()[ - "id" - ] - - -# ── on-disk skill helpers (module-level functions) ────────────────────────── -def test_write_skill_to_disk_creates_canonical_and_symlinks(tmp_path, monkeypatch): - monkeypatch.setenv("HOME", str(tmp_path)) - md_path, skill_dir = write_skill_to_disk("My Skill", "---\nname: my-skill\n---\nbody") - assert os.path.isfile(md_path) - assert os.path.basename(md_path) == "SKILL.md" - assert skill_dir.endswith("My Skill") - claude = os.path.expanduser("~/.claude/skills/My Skill") - agents = os.path.expanduser("~/.agents/skills/My Skill") - assert os.path.islink(claude) and os.path.islink(agents) - # symlink target resolves back to canonical SKILL.md - assert os.path.isfile(os.path.join(claude, "SKILL.md")) - - -def test_link_skill_replaces_stale_symlink(tmp_path, monkeypatch): - monkeypatch.setenv("HOME", str(tmp_path)) - write_skill_to_disk("s1", "body-1") - claude = os.path.expanduser("~/.claude/skills/s1") - # Point the consumer symlink somewhere stale, then re-link. - os.unlink(claude) - os.symlink(str(tmp_path / "nowhere"), claude, target_is_directory=True) - assert os.readlink(claude).endswith("nowhere") - - links = link_skill("s1") - assert claude in links - # re-link removed the stale link and recreated it at the canonical dir - assert os.path.realpath(claude).endswith(os.path.join(".agentforge", "skills", "s1")) - - -def test_unlink_skill_removes_only_symlinks(tmp_path, monkeypatch): - monkeypatch.setenv("HOME", str(tmp_path)) - write_skill_to_disk("s2", "body-2") - canonical = os.path.expanduser("~/.agentforge/skills/s2/SKILL.md") - unlink_skill("s2") - assert not os.path.lexists(os.path.expanduser("~/.claude/skills/s2")) - assert not os.path.lexists(os.path.expanduser("~/.agents/skills/s2")) - assert os.path.isfile(canonical) # canonical preserved - # unlinking again is a no-op (no symlink present) - unlink_skill("s2") - assert os.path.isfile(canonical) - - -def test_remove_skill_from_disk_wipes_everything(tmp_path, monkeypatch): - monkeypatch.setenv("HOME", str(tmp_path)) - write_skill_to_disk("s3", "body-3") - remove_skill_from_disk("s3") - assert not os.path.isdir(os.path.expanduser("~/.agentforge/skills/s3")) - assert not os.path.lexists(os.path.expanduser("~/.claude/skills/s3")) - # removing a non-existent skill is harmless - remove_skill_from_disk("never-existed") - - -# ── frontmatter / compose / sanitize edges ────────────────────────────────── -def test_parse_skill_frontmatter_edges(): - # no frontmatter at all - assert _parse_skill_frontmatter("just a body") == ("", "") - # opening fence but no closing fence - assert _parse_skill_frontmatter("---\nname: x") == ("", "") - # well-formed, with a non key:value line and a duplicate that is ignored - name, desc = _parse_skill_frontmatter( - "---\nname: my-skill\nbare line without colon\ndescription: does x\nname: ignored\n---\nbody" - ) - assert name == "my-skill" - assert desc == "does x" - # leading whitespace is tolerated - assert _parse_skill_frontmatter(" \n---\nname: lead\n---\n")[0] == "lead" - - -def test_compose_skill_md_flattens_and_strips(): - md = _compose_skill_md("nm", " multi\nline desc ", " body here ") - assert "name: nm" in md - assert "description: multi line desc" in md - assert md.strip().endswith("body here") - # None inputs don't blow up - assert "name: nm" in _compose_skill_md("nm", None, None) - - -def test_sanitize_skill_name_edges(): - assert _sanitize_skill_name(" Hello World ") == "hello-world" - assert _sanitize_skill_name("-leading-and-trailing-") == "leading-and-trailing" - assert _sanitize_skill_name(None) == "" - - -# ── AgentExecutor.run (subprocess mocked — not the _execute_task path) ─────── -class _FakeProc: - def __init__(self, returncode=0, stdout="", stderr=""): - self.returncode = returncode - self.stdout = stdout - self.stderr = stderr - - -def test_agent_executor_run_extracts_result_event(monkeypatch): - stdout = "\n".join( - [ - json.dumps({"type": "assistant", "message": "thinking"}), - json.dumps({"type": "result", "result": "FINAL ANSWER"}), - "", # blank line skipped - ] - ) - captured = {} - - def fake_run(cmd, **kwargs): - captured["cmd"] = cmd - return _FakeProc(returncode=0, stdout=stdout) - - monkeypatch.setattr("taskboard.subprocess.run", fake_run) - ok, out = AgentExecutor.run("do it", working_dir=".", image_paths=["/tmp/a.png"]) - assert ok is True - assert out == "FINAL ANSWER" - # image path threaded through as -i - assert "-i" in captured["cmd"] and "/tmp/a.png" in captured["cmd"] - - -def test_agent_executor_run_no_result_event_returns_full_stdout(monkeypatch): - stdout = json.dumps({"type": "assistant", "message": "no result line"}) - monkeypatch.setattr("taskboard.subprocess.run", lambda cmd, **k: _FakeProc(0, stdout)) - ok, out = AgentExecutor.run("p") - assert ok is True - assert out == stdout # falls back to full stdout when no result event - - -def test_agent_executor_run_nonzero_returns_stderr(monkeypatch): - monkeypatch.setattr("taskboard.subprocess.run", lambda cmd, **k: _FakeProc(1, "", "the error")) - ok, out = AgentExecutor.run("p") - assert ok is False - assert out == "the error" - - -def test_agent_executor_run_tolerates_garbage_lines(monkeypatch): - # A non-JSON line precedes the result event; the JSONDecodeError is swallowed. - stdout = "\n".join( - [ - "this is not json", - json.dumps({"type": "result", "result": "OK"}), - ] - ) - monkeypatch.setattr("taskboard.subprocess.run", lambda cmd, **k: _FakeProc(0, stdout)) - ok, out = AgentExecutor.run("p") - assert ok is True and out == "OK" - - -def test_agent_executor_run_timeout(monkeypatch): - import subprocess as _sp - - def boom(cmd, **k): - raise _sp.TimeoutExpired(cmd, 600) - - monkeypatch.setattr("taskboard.subprocess.run", boom) - ok, out = AgentExecutor.run("p", timeout=600) - assert ok is False - assert "timed out" in out - - -def test_agent_executor_run_missing_cli(monkeypatch): - def boom(cmd, **k): - raise FileNotFoundError() - - monkeypatch.setattr("taskboard.subprocess.run", boom) - ok, out = AgentExecutor.run("p") - assert ok is False - assert "not found" in out - - -def test_agent_executor_run_oserror(monkeypatch): - def boom(cmd, **k): - raise OSError("disk gone") - - monkeypatch.setattr("taskboard.subprocess.run", boom) - ok, out = AgentExecutor.run("p") - assert ok is False - assert "disk gone" in out - - -# ── _run_agent_prompt_once builds the right CLI per agent ──────────────────── -def test_run_agent_prompt_once_codex_command(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - seen = {} - - def fake_cmd(agent, cmd, cwd, **kwargs): - seen["agent"] = agent - seen["cmd"] = cmd - seen["cwd"] = cwd - return True, "ok" - - monkeypatch.setattr(sched, "_run_agent_command", fake_cmd) - ok, out = sched._run_agent_prompt_once("codex", "the prompt", ".") - assert ok and out == "ok" - assert seen["cmd"][0] == "codex" - assert "--json" in seen["cmd"] - assert seen["cmd"][-1] == "the prompt" - - -def test_run_agent_prompt_once_claude_command(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - seen = {} - monkeypatch.setattr( - sched, - "_run_agent_command", - lambda agent, cmd, cwd, **k: seen.update(cmd=cmd) or (True, "ok"), - ) - sched._run_agent_prompt_once("claude", "p2", ".") - assert seen["cmd"][0] == "claude" and seen["cmd"][1] == "-p" - - -# ── heartbeat: codex prompt path + resume decision ────────────────────────── -def _mock_agent(sched, monkeypatch, payload, success=True): - def fake_run(agent, cmd, cwd, on_stdout_line=None, on_stderr_line=None): - if on_stdout_line: - on_stdout_line(payload) - return success, payload - - monkeypatch.setattr(sched, "_run_agent_command", fake_run) - - -def test_execute_heartbeat_codex_agent_builds_codex_cmd(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - hid = db.add_heartbeat(make_heartbeat(default_agent="codex")) - seen = {} - - def fake_run(agent, cmd, cwd, on_stdout_line=None, on_stderr_line=None): - seen["cmd"] = cmd - seen["agent"] = agent - return True, json.dumps({"decision": "idle", "reason": "calm"}) - - monkeypatch.setattr(sched, "_run_agent_command", fake_run) - sched._execute_heartbeat(db.get_heartbeat(hid)) - - assert seen["agent"] == "codex" - assert seen["cmd"][0] == "codex" and "--json" in seen["cmd"] - assert db.get_heartbeat(hid)["last_decision"] == HeartbeatDecisionType.IDLE.value - - -def test_execute_heartbeat_resume_decision_records_status(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - hid = db.add_heartbeat(make_heartbeat()) - # A non-idle, non-trigger decision flows down the generic finish branch. - _mock_agent( - sched, - monkeypatch, - json.dumps({"decision": "error", "reason": "self-reported error"}), - ) - sched._execute_heartbeat(db.get_heartbeat(hid)) - hb = db.get_heartbeat(hid) - assert hb["last_decision"] == HeartbeatDecisionType.ERROR.value - tick = db.get_latest_heartbeat_tick(hid) - assert tick["status"] == HeartbeatDecisionType.ERROR.value - - -def test_execute_heartbeat_trigger_then_suppressed_records_idle(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - hid = db.add_heartbeat(make_heartbeat(cooldown_seconds=600)) - payload = json.dumps({"decision": "trigger_task", "dedupe_key": "dk", "prompt": "do it"}) - _mock_agent(sched, monkeypatch, payload) - - sched._execute_heartbeat(db.get_heartbeat(hid)) # first → triggers a task - assert len(db.get_all_tasks()) == 1 - sched._execute_heartbeat(db.get_heartbeat(hid)) # second → suppressed → idle - - assert len(db.get_all_tasks()) == 1 - hb = db.get_heartbeat(hid) - assert hb["last_decision"] == HeartbeatDecisionType.IDLE.value - tick = db.get_latest_heartbeat_tick(hid) - assert "Suppressed duplicate" in json.loads(tick["decision_payload"])["reason"] - - -def test_execute_heartbeat_trigger_uses_decision_prompt_over_template(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - hid = db.add_heartbeat(make_heartbeat(action_prompt_template="TEMPLATE")) - _mock_agent( - sched, - monkeypatch, - json.dumps({"decision": "trigger_task", "prompt": "CUSTOM PROMPT", "title": "Custom"}), - ) - sched._execute_heartbeat(db.get_heartbeat(hid)) - tasks = db.get_all_tasks() - assert tasks[0]["prompt"] == "CUSTOM PROMPT" - assert tasks[0]["title"] == "Custom" - - -def test_execute_heartbeat_codex_agent_failure_raises_inline(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - hid = db.add_heartbeat(make_heartbeat(default_agent="codex")) - - def fail(agent, cmd, cwd, on_stdout_line=None, on_stderr_line=None): - return False, "codex crashed" - - monkeypatch.setattr(sched, "_run_agent_command", fail) - sched._execute_heartbeat(db.get_heartbeat(hid)) - hb = db.get_heartbeat(hid) - assert hb["last_decision"] == HeartbeatDecisionType.ERROR.value - assert "codex crashed" in hb["last_error"] - - -# ── _heartbeat_trigger_suppressed edge: unparseable triggered_at ──────────── -def test_trigger_suppressed_bad_timestamp_falls_through(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - hid = db.add_heartbeat(make_heartbeat(cooldown_seconds=600)) - db.upsert_heartbeat_dedup(hid, "k", None) - db.conn.execute( - "UPDATE heartbeat_dedup SET triggered_at=? WHERE heartbeat_id=? AND dedupe_key=?", - ("not-a-date", hid, "k"), - ) - db.conn.commit() - # bad timestamp → cooldown check skipped, no active task → not suppressed - assert sched._heartbeat_trigger_suppressed(db.get_heartbeat(hid), "k") is False - - -# ── pause / resume heartbeat ──────────────────────────────────────────────── -def test_pause_heartbeat_disables(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - hid = db.add_heartbeat(make_heartbeat()) - sched.pause_heartbeat(hid) - assert db.get_heartbeat(hid)["enabled"] is False - - -def test_resume_heartbeat_enables_and_schedules(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - hid = db.add_heartbeat(make_heartbeat()) - sched.pause_heartbeat(hid) - sched.resume_heartbeat(hid) - hb = db.get_heartbeat(hid) - assert hb["enabled"] is True - assert datetime.fromisoformat(hb["next_run_at"]) > datetime.now() - - -def test_pause_resume_unknown_raises(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - with pytest.raises(ValueError, match="not found"): - sched.pause_heartbeat(99999) - with pytest.raises(ValueError, match="not found"): - sched.resume_heartbeat(99999) - - -# ── trigger_heartbeat_now: already running guard ──────────────────────────── -def test_trigger_heartbeat_now_already_running_raises(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - hid = db.add_heartbeat(make_heartbeat()) - - class _Alive: - def is_alive(self): - return True - - sched._active_heartbeats[hid] = _Alive() - with pytest.raises(ValueError, match="already running"): - sched.trigger_heartbeat_now(hid) - - -# ── distill: contributing_task_ids parse fallbacks ────────────────────────── -def test_distill_skill_draft_bad_task_ids_json(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - pid = make_pattern(db) - # Corrupt the JSON so json.loads raises → tids defaults to [] - db.conn.execute( - "UPDATE skill_patterns SET contributing_task_ids=? WHERE id=?", ("not json", pid) - ) - db.conn.commit() - obj = {"name": "X", "description": "d", "body_markdown": "b"} - monkeypatch.setattr(sched, "_run_agent_command", lambda *a, **k: (True, json.dumps(obj))) - - draft = sched.distill_skill_draft(pid, agent="claude") - assert draft["name"] == "x" - assert db.get_skill_draft(pid)["status"] == "ready" - - -def test_distill_skill_draft_unknown_pattern_raises(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - with pytest.raises(ValueError, match="pattern not found"): - sched.distill_skill_draft(99999) - - -def test_distill_falls_back_to_pattern_key_when_no_name(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - pid = make_pattern(db, key="my-recurring-thing") - obj = {"description": "d", "body_markdown": "b"} # no name - monkeypatch.setattr(sched, "_run_agent_command", lambda *a, **k: (True, json.dumps(obj))) - draft = sched.distill_skill_draft(pid, agent="claude") - assert draft["name"] == "my-recurring-thing" - - -# ── trigger_skill_draft: marks 'drafting' for a real pattern ──────────────── -def test_trigger_skill_draft_sets_drafting_status(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - pid = make_pattern(db) - # keep the agent from doing anything real; the worker thread will use it - monkeypatch.setattr( - sched, - "distill_skill_draft", - lambda *a, **k: db.upsert_skill_draft(pid, "ready", name="x", body="b"), - ) - assert sched.trigger_skill_draft(pid) is True - # row exists (either still 'drafting' or already 'ready' from the worker) - draft = db.get_skill_draft(pid) - assert draft is not None - assert draft["status"] in ("drafting", "ready") - - -# ── distill prompt building: codex agent default resolution ───────────────── -def test_distill_agent_resolution_uses_setting(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - db.set_setting("skill_sweep_agent", "codex") - pid = make_pattern(db) - seen = {} - obj = {"name": "x", "description": "d", "body_markdown": "b"} - - def fake_cmd(agent, cmd, cwd, **k): - seen["agent"] = agent - return True, json.dumps(obj) - - monkeypatch.setattr(sched, "_run_agent_command", fake_cmd) - sched.distill_skill_draft(pid) # no agent arg → resolves from setting - assert seen["agent"] == "codex" - - -# ── skill-sweep: non-dict items skipped, recurrence drives 'new' ──────────── -def test_run_skill_sweep_skips_non_dict_items(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - tid = db.add_task(Task(title="t", prompt="p", working_dir=".")) - rid = db.add_run(tid) - db.finish_run(rid, status="completed", result="ok") - - payload = json.dumps( - [ - "garbage-string", # non-dict → skipped - {"pattern_key": "real", "kind": "recipe", "summary": "s", "task_id": tid}, - {"pattern_key": "", "kind": "recipe", "summary": "s"}, # blank key → not upserted - ] - ) - monkeypatch.setattr(sched, "_run_agent_command", lambda *a, **k: (True, payload)) - - result = sched.run_skill_sweep(agent="claude", full=True) - assert result["scanned"] == 1 - assert result["detected"] == 1 # only the valid keyed entry - assert db.get_skill_pattern_recurrence("real") == 1 - - -def test_run_skill_sweep_resolves_default_agent_setting(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - db.set_setting("default_agent", "codex") - result = sched.run_skill_sweep() # no runs → short-circuits but resolves agent - assert result["agent"] == "codex" - - -# ── trigger_skill_sweep background worker captures error ──────────────────── -def test_trigger_skill_sweep_worker_records_error(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - tid = db.add_task(Task(title="t", prompt="p", working_dir=".")) - rid = db.add_run(tid) - db.finish_run(rid, status="completed", result="ok") - - def boom(*a, **k): - raise RuntimeError("worker boom") - - monkeypatch.setattr(sched, "run_skill_sweep", boom) - assert sched.trigger_skill_sweep(full=True) is True - # poll until the background worker records the error to sweep status - import time as _time - - for _ in range(50): - status = sched.skill_sweep_status() - if status["last"] and "error" in status["last"]: - break - _time.sleep(0.02) - status = sched.skill_sweep_status() - assert status["running"] is False - assert status["last"]["error"] == "worker boom" - - -# ── DAG post-execution hooks: scheduled_at / cron unblock to 'scheduled' ───── -def test_on_task_completed_unblocks_scheduled_at_to_scheduled(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - up = db.add_task(Task(title="up", prompt="p", working_dir=".")) - future = (datetime.now() + timedelta(hours=2)).replace(microsecond=0).isoformat() - down = sched.submit_task( - Task( - title="down", - prompt="p", - working_dir=".", - schedule_type=ScheduleType.SCHEDULED_AT, - next_run_at=future, - ), - depends_on=[up], - ) - assert db.get_task(down)["status"] == "blocked" - - db.update_task(up, status="completed") - sched._on_task_completed(up) - # scheduled_at downstream unblocks into 'scheduled', not 'pending' - assert db.get_task(down)["status"] == "scheduled" - - -def test_on_task_completed_unblocks_cron_to_scheduled(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - up = db.add_task(Task(title="up", prompt="p", working_dir=".")) - down = sched.submit_task( - Task( - title="down", - prompt="p", - working_dir=".", - schedule_type=ScheduleType.CRON, - cron_expr="0 0 * * *", - ), - depends_on=[up], - ) - db.update_task(up, status="completed") - sched._on_task_completed(up) - assert db.get_task(down)["status"] == "scheduled" - - -def test_on_task_completed_unblocks_delayed_to_pending(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - up = db.add_task(Task(title="up", prompt="p", working_dir=".")) - down = sched.submit_task( - Task( - title="down", - prompt="p", - working_dir=".", - schedule_type=ScheduleType.DELAYED, - delay_seconds=30, - ), - depends_on=[up], - ) - db.update_task(up, status="completed") - sched._on_task_completed(up) - assert db.get_task(down)["status"] == "pending" - - -def test_on_task_completed_unblocks_immediate_to_pending(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - up = db.add_task(Task(title="up", prompt="p", working_dir=".")) - down = sched.submit_task( - Task(title="down", prompt="p", working_dir="."), # immediate - depends_on=[up], - ) - assert db.get_task(down)["status"] == "blocked" - db.update_task(up, status="completed") - sched._on_task_completed(up) - assert db.get_task(down)["status"] == "pending" - - -def test_on_task_failed_cancels_pending_and_scheduled_downstream(tmp_path): - # The existing suite covers the blocked→cancelled chain; here we exercise the - # pending/scheduled cancellable states and a diamond (shared downstream). - db = make_db(tmp_path) - sched = TaskScheduler(db) - root = db.add_task(Task(title="root", prompt="p", working_dir=".")) - a = db.add_task(Task(title="a", prompt="p", working_dir=".")) - b = db.add_task(Task(title="b", prompt="p", working_dir=".")) - db.add_dependency(a, root) - db.add_dependency(b, root) - db.update_task(a, status="pending") - db.update_task(b, status="scheduled") - sched._on_task_failed(root) - assert db.get_task(a)["status"] == "cancelled" - assert db.get_task(b)["status"] == "cancelled" - - -def test_on_task_completed_ignores_non_blocked_dependents(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - up = db.add_task(Task(title="up", prompt="p", working_dir=".")) - down = db.add_task(Task(title="down", prompt="p", working_dir=".")) - db.add_dependency(down, up) - # downstream is 'pending', not 'blocked' → hook leaves it alone - db.update_task(up, status="completed") - sched._on_task_completed(up) - assert db.get_task(down)["status"] == "pending" - - -def test_on_task_failed_skips_already_running_downstream(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - root = db.add_task(Task(title="root", prompt="p", working_dir=".")) - down = db.add_task(Task(title="down", prompt="p", working_dir=".")) - db.add_dependency(down, root) - db.update_task(down, status="running") # not a cancellable state - sched._on_task_failed(root) - assert db.get_task(down)["status"] == "running" # untouched - - -# ── cancel_task with a registered pgid path ───────────────────────────────── -def test_cancel_task_with_pgid_attempts_killpg(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - tid = db.add_task(Task(title="t", prompt="p", working_dir=".")) - db.update_task(tid, status="running") - sched._active_pgids[tid] = 424242 - killed = [] - monkeypatch.setattr("taskboard.os.killpg", lambda pgid, sig: killed.append(pgid)) - sched.cancel_task(tid) - assert killed == [424242] - assert db.get_task(tid)["status"] == "cancelled" - - -def test_cancel_task_pgid_killpg_oserror_swallowed(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - tid = db.add_task(Task(title="t", prompt="p", working_dir=".")) - sched._active_pgids[tid] = 999 - - def boom(pgid, sig): - raise OSError("no such pgid") - - monkeypatch.setattr("taskboard.os.killpg", boom) - sched.cancel_task(tid) # must not raise - assert db.get_task(tid)["status"] == "cancelled" - - -# ── _build_injected_prompt: multiple upstreams concatenated ───────────────── -def test_build_injected_prompt_multiple_upstreams(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - u1 = db.add_task(Task(title="u1", prompt="p", working_dir=".")) - u2 = db.add_task(Task(title="u2", prompt="p", working_dir=".")) - db.update_task(u1, status="completed", result="RESULT ONE") - db.update_task(u2, status="completed", result="RESULT TWO") - down = db.add_task(Task(title="down", prompt="MAIN", working_dir=".")) - db.add_dependency(down, u1, inject_result=True) - db.add_dependency(down, u2, inject_result=True) - - injected = sched._build_injected_prompt(db.get_task(down)) - assert "RESULT ONE" in injected and "RESULT TWO" in injected - assert injected.strip().endswith("MAIN") - - -def test_build_injected_prompt_skips_upstream_without_result(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - up = db.add_task(Task(title="up", prompt="p", working_dir=".")) - db.update_task(up, status="completed") # no result set - down = db.add_task(Task(title="down", prompt="ORIG", working_dir=".")) - db.add_dependency(down, up, inject_result=True) - # inject requested but upstream has no result → original prompt unchanged - assert sched._build_injected_prompt(db.get_task(down)) == "ORIG" diff --git a/tests/test_scheduler_timezones.py b/tests/test_scheduler_timezones.py deleted file mode 100644 index d4c87ed..0000000 --- a/tests/test_scheduler_timezones.py +++ /dev/null @@ -1,96 +0,0 @@ -from datetime import datetime, timedelta, timezone - -from taskboard import ScheduleType, Task, TaskDB, TaskScheduler - - -def make_db(tmp_path): - return TaskDB(str(tmp_path / "agentforge-test.db")) - - -def test_submit_task_normalizes_aware_scheduled_at_to_local_naive(tmp_path): - db = make_db(tmp_path) - scheduler = TaskScheduler(db) - future_utc = datetime.now(timezone.utc) + timedelta(hours=1) - - task_id = scheduler.submit_task( - Task( - title="Timezone test", - prompt="Run later", - schedule_type=ScheduleType.SCHEDULED_AT, - next_run_at=future_utc.isoformat(), - ) - ) - - task = db.get_task(task_id) - expected = future_utc.astimezone().replace(tzinfo=None).isoformat() - - assert task is not None - assert task["next_run_at"] == expected - - -def test_tick_accepts_legacy_aware_next_run_at_without_type_error(tmp_path, monkeypatch): - db = make_db(tmp_path) - scheduler = TaskScheduler(db) - triggered = [] - - now = datetime.now().isoformat() - cur = db.conn.execute( - """ - INSERT INTO tasks ( - title, prompt, working_dir, status, schedule_type, - cron_expr, delay_seconds, next_run_at, max_runs, - created_at, updated_at, tags, agent, prompt_images, image_paths - ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) - """, - ( - "Legacy aware task", - "Run now", - ".", - "scheduled", - ScheduleType.SCHEDULED_AT.value, - None, - None, - (datetime.now(timezone.utc) - timedelta(minutes=1)).isoformat(), - None, - now, - now, - "", - "claude", - "[]", - "[]", - ), - ) - db.conn.commit() - task_id = cur.lastrowid - - monkeypatch.setattr(scheduler, "_spawn_task", lambda task: triggered.append(task["id"])) - - scheduler._tick() - - assert triggered == [task_id] - - -def test_heartbeat_dedupe_handles_aware_triggered_at_without_type_error(tmp_path): - db = make_db(tmp_path) - scheduler = TaskScheduler(db) - - db.conn.execute( - """ - INSERT INTO heartbeat_dedup (heartbeat_id, dedupe_key, task_id, triggered_at) - VALUES (?, ?, ?, ?) - """, - ( - 1, - "repo:abc123", - None, - (datetime.now(timezone.utc) - timedelta(seconds=30)).isoformat(), - ), - ) - db.conn.commit() - - suppressed = scheduler._heartbeat_trigger_suppressed( - {"id": 1, "cooldown_seconds": 300}, - "repo:abc123", - ) - - assert suppressed is True diff --git a/tests/test_server_lifecycle.py b/tests/test_server_lifecycle.py deleted file mode 100644 index 56adcb0..0000000 --- a/tests/test_server_lifecycle.py +++ /dev/null @@ -1,206 +0,0 @@ -"""Coverage for process/server lifecycle helpers in taskboard.py. - -Covers _kill_stale_process_on_port, _pid_alive, QuietHTTPServer.handle_error, -and run_server's channel-enable wiring (with serve_forever/signal/channels -patched to no-ops so nothing real spawns or blocks). -""" - -import os -from unittest import mock - -import taskboard - -# ── _pid_alive ───────────────────────────────────────────────────────────── - - -def test_pid_alive_true_when_no_exception(): - with mock.patch.object(taskboard.os, "kill", return_value=None) as kill: - assert taskboard._pid_alive(1234) is True - kill.assert_called_once_with(1234, 0) - - -def test_pid_alive_false_on_oserror(): - with mock.patch.object(taskboard.os, "kill", side_effect=ProcessLookupError()): - assert taskboard._pid_alive(1234) is False - - -def test_pid_alive_false_on_generic_oserror(): - with mock.patch.object(taskboard.os, "kill", side_effect=OSError()): - assert taskboard._pid_alive(1234) is False - - -# ── _kill_stale_process_on_port ──────────────────────────────────────────── - - -def _fake_free_socket(): - """A socket whose connect() refuses — i.e. the port is free.""" - sock = mock.Mock() - sock.connect.side_effect = ConnectionRefusedError() - return sock - - -def _fake_occupied_socket(): - """A socket whose connect() succeeds — i.e. the port is occupied.""" - sock = mock.Mock() - sock.connect.return_value = None - return sock - - -def test_kill_stale_returns_when_port_free(): - with mock.patch("socket.socket", return_value=_fake_free_socket()): - with mock.patch.object(taskboard, "subprocess") as sub: - taskboard._kill_stale_process_on_port(9712) - sub.run.assert_not_called() - - -def test_kill_stale_kills_found_pid(): - occupied = _fake_occupied_socket() - lsof_result = mock.Mock() - lsof_result.stdout = "4242\n" - - with ( - mock.patch("socket.socket", return_value=occupied), - mock.patch.object(taskboard.subprocess, "run", return_value=lsof_result), - mock.patch.object(taskboard.os, "kill") as kill, - mock.patch.object(taskboard.os, "getpid", return_value=1), - mock.patch.object(taskboard.time, "sleep", return_value=None), - mock.patch.object(taskboard, "_pid_alive", return_value=False), - ): - taskboard._kill_stale_process_on_port(9712) - - # SIGTERM was sent to the stale pid. - kill.assert_any_call(4242, taskboard.signal.SIGTERM) - - -def test_kill_stale_force_kills_survivor(): - occupied = _fake_occupied_socket() - lsof_result = mock.Mock() - lsof_result.stdout = "4242\n" - - with ( - mock.patch("socket.socket", return_value=occupied), - mock.patch.object(taskboard.subprocess, "run", return_value=lsof_result), - mock.patch.object(taskboard.os, "kill") as kill, - mock.patch.object(taskboard.os, "getpid", return_value=1), - mock.patch.object(taskboard.time, "sleep", return_value=None), - mock.patch.object( - taskboard, - "_pid_alive", - return_value=True, # never dies → force kill - ), - ): - taskboard._kill_stale_process_on_port(9712) - - kill.assert_any_call(4242, taskboard.signal.SIGTERM) - kill.assert_any_call(4242, taskboard.signal.SIGKILL) - - -def test_kill_stale_skips_self_pid(): - occupied = _fake_occupied_socket() - lsof_result = mock.Mock() - lsof_result.stdout = "999\n" # equals our pid → skipped - - with ( - mock.patch("socket.socket", return_value=occupied), - mock.patch.object(taskboard.subprocess, "run", return_value=lsof_result), - mock.patch.object(taskboard.os, "kill") as kill, - mock.patch.object(taskboard.os, "getpid", return_value=999), - mock.patch.object(taskboard.time, "sleep", return_value=None), - ): - taskboard._kill_stale_process_on_port(9712) - - kill.assert_not_called() - - -def test_kill_stale_handles_empty_and_nondigit_lsof(): - occupied = _fake_occupied_socket() - lsof_result = mock.Mock() - lsof_result.stdout = "\nabc\n" # nothing usable - - with ( - mock.patch("socket.socket", return_value=occupied), - mock.patch.object(taskboard.subprocess, "run", return_value=lsof_result), - mock.patch.object(taskboard.os, "kill") as kill, - mock.patch.object(taskboard.os, "getpid", return_value=1), - mock.patch.object(taskboard.time, "sleep", return_value=None), - ): - taskboard._kill_stale_process_on_port(9712) - - kill.assert_not_called() - - -def test_kill_stale_swallows_subprocess_error(): - occupied = _fake_occupied_socket() - - with ( - mock.patch("socket.socket", return_value=occupied), - mock.patch.object(taskboard.subprocess, "run", side_effect=RuntimeError("lsof exploded")), - ): - # Should not raise — the except branch logs a warning. - taskboard._kill_stale_process_on_port(9712) - - -# ── QuietHTTPServer.handle_error ─────────────────────────────────────────── - - -def test_handle_error_swallows_broken_pipe(): - server = taskboard.QuietHTTPServer.__new__(taskboard.QuietHTTPServer) - try: - raise BrokenPipeError() - except BrokenPipeError: - # Must not raise and must not call super().handle_error. - with mock.patch.object(taskboard.HTTPServer, "handle_error") as super_handle: - server.handle_error(object(), ("127.0.0.1", 1234)) - super_handle.assert_not_called() - - -def test_handle_error_delegates_other_errors(): - server = taskboard.QuietHTTPServer.__new__(taskboard.QuietHTTPServer) - try: - raise ValueError("not a pipe") - except ValueError: - with mock.patch.object(taskboard.HTTPServer, "handle_error") as super_handle: - server.handle_error(object(), ("127.0.0.1", 1234)) - super_handle.assert_called_once() - - -# ── run_server wiring (channels disabled by default) ─────────────────────── - - -def test_run_server_wires_disabled_channels(tmp_path): - """run_server with all channels off: confirms it reaches serve_forever and - leaves every channel reference None on the handler.""" - - db = taskboard.TaskDB(str(tmp_path / "t.db")) - - fake_scheduler = mock.Mock() - fake_ui = mock.Mock() - - # Strip channel-autoenable env vars so nothing real tries to start. - clean_env = { - k: v - for k, v in os.environ.items() - if k not in {"TELEGRAM_BOT_TOKEN", "SLACK_BOT_TOKEN", "SLACK_APP_TOKEN"} - } - - with ( - mock.patch.dict(os.environ, clean_env, clear=True), - mock.patch.object(taskboard, "_kill_stale_process_on_port"), - mock.patch.object(taskboard, "TaskDB", return_value=db), - mock.patch.object(taskboard, "UIChannel", return_value=fake_ui), - mock.patch.object(taskboard, "TaskScheduler", return_value=fake_scheduler), - mock.patch.object(taskboard.QuietHTTPServer, "serve_forever", return_value=None) as serve, - mock.patch.object(taskboard.QuietHTTPServer, "server_bind", return_value=None), - mock.patch.object(taskboard.QuietHTTPServer, "server_activate", return_value=None), - mock.patch.object(taskboard.signal, "signal", return_value=None), - ): - taskboard.run_server(port=0) - - serve.assert_called_once() - fake_ui.start.assert_called_once() - fake_scheduler.start.assert_called_once() - assert taskboard.TaskAPIHandler.feishu_channel is None - assert taskboard.TaskAPIHandler.telegram_channel is None - assert taskboard.TaskAPIHandler.slack_channel is None - assert taskboard.TaskAPIHandler.weixin_channel is None - assert taskboard.TaskAPIHandler.scheduler is fake_scheduler diff --git a/tests/test_skill_distill.py b/tests/test_skill_distill.py deleted file mode 100644 index d4667d8..0000000 --- a/tests/test_skill_distill.py +++ /dev/null @@ -1,225 +0,0 @@ -import json -import os -from datetime import datetime, timedelta - -import pytest - -from taskboard import ( - Task, - TaskDB, - TaskScheduler, - _compose_skill_md, - _parse_json_object, - _sanitize_skill_name, -) - - -def make_db(tmp_path): - return TaskDB(str(tmp_path / "agentforge-test.db")) - - -def make_pattern(db, key="k", recurrence=3, tasks=(1, 2, 3), kind="recipe"): - db.upsert_skill_pattern(key, kind, "summary", tasks[0]) - db.conn.execute( - "UPDATE skill_patterns SET recurrence_count=?, contributing_task_ids=? WHERE pattern_key=?", - (recurrence, json.dumps(list(tasks)), key), - ) - db.conn.commit() - return db.conn.execute("SELECT id FROM skill_patterns WHERE pattern_key=?", (key,)).fetchone()[ - "id" - ] - - -# ── helpers ──────────────────────────────────────────────────────────────── -def test_sanitize_skill_name(): - assert _sanitize_skill_name("Run Pytest Suite!") == "run-pytest-suite" - assert _sanitize_skill_name("../etc/passwd") == "etc-passwd" # no traversal - assert _sanitize_skill_name("a__b") == "a-b" - assert _sanitize_skill_name("") == "" - - -def test_compose_and_parse(): - md = _compose_skill_md("x", "desc\nline", "body text") - assert "name: x" in md - assert "description: desc line" in md # newline flattened - assert md.strip().endswith("body text") - assert _parse_json_object('```json\n{"a":1}\n```')["a"] == 1 - assert _parse_json_object('prefix {"a":2} suffix')["a"] == 2 - with pytest.raises(ValueError): - _parse_json_object("[1,2,3]") # not an object - - -# ── threshold → candidate ────────────────────────────────────────────────── -def test_refresh_marks_candidate(tmp_path): - db = make_db(tmp_path) - pid = make_pattern(db, recurrence=3, tasks=(1, 2, 3)) - assert db.refresh_skill_candidates() == 1 - assert db.get_skill_pattern(pid)["status"] == "candidate" - # idempotent: already promoted out of 'tracking' - assert db.refresh_skill_candidates() == 0 - - -def test_refresh_below_recurrence(tmp_path): - db = make_db(tmp_path) - make_pattern(db, recurrence=2, tasks=(1, 2)) - assert db.refresh_skill_candidates() == 0 - - -def test_refresh_below_distinct_tasks(tmp_path): - db = make_db(tmp_path) - make_pattern(db, recurrence=5, tasks=(1,)) - assert db.refresh_skill_candidates() == 0 - - -def test_refresh_out_of_window(tmp_path): - db = make_db(tmp_path) - pid = make_pattern(db, recurrence=3, tasks=(1, 2, 3)) - old = (datetime.now() - timedelta(days=60)).isoformat() - db.conn.execute("UPDATE skill_patterns SET first_seen=? WHERE id=?", (old, pid)) - db.conn.commit() - assert db.refresh_skill_candidates() == 0 - assert db.get_skill_pattern(pid)["status"] == "tracking" - - -# ── distillation ─────────────────────────────────────────────────────────── -def test_distill_skill_draft(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - tid = db.add_task(Task(title="Run tests", prompt="run pytest", working_dir=".")) - rid = db.add_run(tid) - db.finish_run(rid, status="completed", result="all green") - pid = make_pattern(db, recurrence=3, tasks=(tid, tid + 1, tid + 2)) - - obj = { - "name": "Run Pytest Suite", - "description": "run the test suite", - "body_markdown": "## Steps\n1. uv run pytest", - } - monkeypatch.setattr(sched, "_run_agent_command", lambda *a, **k: (True, json.dumps(obj))) - - draft = sched.distill_skill_draft(pid, agent="claude") - assert draft["name"] == "run-pytest-suite" - assert draft["body"].startswith("---\nname: run-pytest-suite") - assert "description: run the test suite" in draft["body"] - assert "## Steps" in draft["body"] - - saved = db.get_skill_draft(pid) - assert saved["status"] == "ready" - assert saved["name"] == "run-pytest-suite" - - -def test_distill_captures_worthiness(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - tid = db.add_task(Task(title="x", prompt="p", working_dir=".")) - rid = db.add_run(tid) - db.finish_run(rid, status="completed", result="ok") - pid = make_pattern(db, recurrence=3, tasks=(tid, tid + 1, tid + 2)) - - obj = { - "worthy": False, - "worthiness_reason": "one-off, no reusable procedure", - "name": "meh", - "description": "d", - "body_markdown": "b", - } - monkeypatch.setattr(sched, "_run_agent_command", lambda *a, **k: (True, json.dumps(obj))) - - draft = sched.distill_skill_draft(pid, agent="claude") - assert draft["worthy"] is False - assert "one-off" in draft["worthiness_reason"] - - # surfaced through get_skill_patterns for the UI - row = [x for x in db.get_skill_patterns() if x["id"] == pid][0] - assert row["draft_worthy"] == 0 - assert "one-off" in row["draft_worthiness_reason"] - - -def test_distill_worthiness_absent_is_none(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - pid = make_pattern(db) - obj = {"name": "x", "description": "d", "body_markdown": "b"} # no "worthy" key - monkeypatch.setattr(sched, "_run_agent_command", lambda *a, **k: (True, json.dumps(obj))) - draft = sched.distill_skill_draft(pid, agent="claude") - assert draft["worthy"] is None - assert db.get_skill_draft(pid)["worthy"] is None - - -def test_distill_agent_failure_marks_error(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - pid = make_pattern(db) - monkeypatch.setattr(sched, "_run_agent_command", lambda *a, **k: (False, "boom")) - with pytest.raises(RuntimeError, match="boom"): - sched.distill_skill_draft(pid, agent="claude") - - -def test_trigger_skill_draft_unknown_pattern(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - assert sched.trigger_skill_draft(99999) is False - - -# ── approval (writes files + symlinks) ───────────────────────────────────── -def test_approve_skill_writes_files_and_symlinks(tmp_path, monkeypatch): - monkeypatch.setenv("HOME", str(tmp_path)) - db = make_db(tmp_path) - sched = TaskScheduler(db) - pid = make_pattern(db, recurrence=3, tasks=(1, 2, 3)) - - body = "---\nname: my-skill\ndescription: do x\n---\n\nbody" - skill = sched.approve_skill(pid, "My Skill", "do x", body) - assert skill["name"] == "my-skill" - assert skill["enabled"] == 1 - - canonical = os.path.expanduser("~/.agentforge/skills/my-skill/SKILL.md") - claude_link = os.path.expanduser("~/.claude/skills/my-skill") - agents_link = os.path.expanduser("~/.agents/skills/my-skill") - assert os.path.isfile(canonical) - assert os.path.islink(claude_link) - assert os.path.islink(agents_link) - # both symlinks resolve to the canonical SKILL.md - assert os.path.isfile(os.path.join(claude_link, "SKILL.md")) - assert os.path.isfile(os.path.join(agents_link, "SKILL.md")) - - # pattern promoted, draft cleared - pattern = db.get_skill_pattern(pid) - assert pattern["status"] == "promoted" - assert pattern["promoted_skill_id"] == skill["id"] - assert db.get_skill_draft(pid) is None - - -def test_approve_rejects_empty_body(tmp_path, monkeypatch): - monkeypatch.setenv("HOME", str(tmp_path)) - db = make_db(tmp_path) - sched = TaskScheduler(db) - pid = make_pattern(db) - with pytest.raises(ValueError, match="empty"): - sched.approve_skill(pid, "x", "d", " ") - - -def test_approve_unknown_pattern(tmp_path, monkeypatch): - monkeypatch.setenv("HOME", str(tmp_path)) - db = make_db(tmp_path) - sched = TaskScheduler(db) - with pytest.raises(ValueError, match="not found"): - sched.approve_skill(99999, "x", "d", "body") - - -# ── dismissal ────────────────────────────────────────────────────────────── -def test_dismiss_pattern(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - pid = make_pattern(db) - db.upsert_skill_draft(pid, "ready", name="x", body="b") - sched.dismiss_skill_pattern(pid) - assert db.get_skill_pattern(pid)["status"] == "dismissed" - assert db.get_skill_draft(pid) is None - - -def test_dismiss_unknown_pattern(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - with pytest.raises(ValueError, match="not found"): - sched.dismiss_skill_pattern(99999) diff --git a/tests/test_skill_patterns.py b/tests/test_skill_patterns.py deleted file mode 100644 index 89a1c36..0000000 --- a/tests/test_skill_patterns.py +++ /dev/null @@ -1,232 +0,0 @@ -import json - -import pytest - -from taskboard import Task, TaskDB, TaskScheduler - - -def make_db(tmp_path): - return TaskDB(str(tmp_path / "agentforge-test.db")) - - -def add_completed_task(db, title="Run tests", prompt="run the test suite", result="ok"): - tid = db.add_task(Task(title=title, prompt=prompt, working_dir=".")) - run_id = db.add_run(tid) - db.finish_run(run_id, status="completed", result=result, raw_output="") - return tid - - -# ── upsert / dedup ledger ────────────────────────────────────────────────── -def test_upsert_new_then_bump(tmp_path): - db = make_db(tmp_path) - pid = db.upsert_skill_pattern("run-pytest", "recipe", "run pytest suite", 1) - assert pid is not None - - patterns = db.get_skill_patterns() - assert len(patterns) == 1 - assert patterns[0]["recurrence_count"] == 1 - assert json.loads(patterns[0]["contributing_task_ids"]) == [1] - assert patterns[0]["status"] == "tracking" - - db.upsert_skill_pattern("run-pytest", "recipe", "updated summary", 2) - patterns = db.get_skill_patterns() - assert len(patterns) == 1 - assert patterns[0]["recurrence_count"] == 2 - assert set(json.loads(patterns[0]["contributing_task_ids"])) == {1, 2} - assert patterns[0]["summary"] == "updated summary" - - -def test_upsert_distinct_keys(tmp_path): - db = make_db(tmp_path) - db.upsert_skill_pattern("a", "recipe", "s", 1) - db.upsert_skill_pattern("b", "pitfall", "s", 1) - patterns = db.get_skill_patterns() - assert len(patterns) == 2 - assert {p["kind"] for p in patterns} == {"recipe", "pitfall"} - - -def test_upsert_ignores_blank_key(tmp_path): - db = make_db(tmp_path) - assert db.upsert_skill_pattern("", "recipe", "s", 1) is None - assert db.upsert_skill_pattern(" ", "recipe", "s", 1) is None - assert db.get_skill_patterns() == [] - - -def test_upsert_invalid_kind_defaults_to_recipe(tmp_path): - db = make_db(tmp_path) - db.upsert_skill_pattern("k", "bogus", "s", 1) - assert db.get_skill_patterns()[0]["kind"] == "recipe" - - -def test_same_task_counts_occurrence_but_not_distinct(tmp_path): - db = make_db(tmp_path) - db.upsert_skill_pattern("k", "recipe", "s", 5) - db.upsert_skill_pattern("k", "recipe", "s", 5) - p = db.get_skill_patterns()[0] - assert p["recurrence_count"] == 2 # each observation bumps the count - assert json.loads(p["contributing_task_ids"]) == [5] # but distinct tasks stay = 1 - - -# ── completed-runs watermark query ───────────────────────────────────────── -def test_get_completed_runs_since_watermark(tmp_path): - db = make_db(tmp_path) - add_completed_task(db) - add_completed_task(db, title="Deploy") - assert len(db.get_completed_runs_since("")) == 2 - assert db.get_completed_runs_since("2999-01-01T00:00:00") == [] - - -def test_get_completed_runs_excludes_unfinished(tmp_path): - db = make_db(tmp_path) - tid = db.add_task(Task(title="Pending", prompt="x")) - db.add_run(tid) # left running, no finish - assert db.get_completed_runs_since("") == [] - - -# ── sweep output parsing ─────────────────────────────────────────────────── -def test_parse_sweep_output_variants(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - arr = '[{"pattern_key":"x","kind":"recipe","summary":"s","task_id":1}]' - assert sched._parse_sweep_output(arr)[0]["pattern_key"] == "x" - assert sched._parse_sweep_output("```json\n" + arr + "\n```")[0]["pattern_key"] == "x" - assert sched._parse_sweep_output("Here you go:\n" + arr + "\nDone.")[0]["pattern_key"] == "x" - assert sched._parse_sweep_output("nonsense") == [] - assert sched._parse_sweep_output("[]") == [] - assert sched._parse_sweep_output("") == [] - - -# ── full sweep (mocked agent) ────────────────────────────────────────────── -def test_run_skill_sweep_upserts_and_advances_watermark(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - t1 = add_completed_task(db, title="Run tests", prompt="run pytest") - t2 = add_completed_task(db, title="Run tests again", prompt="run the suite") - - payload = json.dumps( - [ - { - "pattern_key": "run-test-suite", - "kind": "recipe", - "summary": "run pytest", - "task_id": t1, - }, - { - "pattern_key": "run-test-suite", - "kind": "recipe", - "summary": "run pytest", - "task_id": t2, - }, - ] - ) - - def fake_run(agent, cmd, cwd, on_stdout_line=None, on_stderr_line=None): - return True, payload - - monkeypatch.setattr(sched, "_run_agent_command", fake_run) - - result = sched.run_skill_sweep(agent="claude") - assert result["scanned"] == 2 - assert result["detected"] == 2 - - patterns = db.get_skill_patterns() - assert len(patterns) == 1 - assert patterns[0]["recurrence_count"] == 2 - assert set(json.loads(patterns[0]["contributing_task_ids"])) == {t1, t2} - - assert db.get_setting("skill_sweep_watermark", "") != "" - - # second sweep: watermark consumed everything → nothing new - result2 = sched.run_skill_sweep(agent="claude") - assert result2["scanned"] == 0 - assert result2["detected"] == 0 - - -def test_run_skill_sweep_empty_history(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - result = sched.run_skill_sweep(agent="claude") - assert result["scanned"] == 0 - assert result["detected"] == 0 - assert result["agent"] == "claude" - assert result["watermark"] == "" - - -def test_upsert_run_id_idempotent(tmp_path): - db = make_db(tmp_path) - # same run_id seen twice → counted once - db.upsert_skill_pattern("k", "recipe", "s", task_id=1, run_id=100) - db.upsert_skill_pattern("k", "recipe", "s", task_id=1, run_id=100) - p = db.get_skill_patterns()[0] - assert p["recurrence_count"] == 1 - assert json.loads(p["contributing_run_ids"]) == [100] - # a different run of the same task → new occurrence - db.upsert_skill_pattern("k", "recipe", "s", task_id=1, run_id=101) - p = db.get_skill_patterns()[0] - assert p["recurrence_count"] == 2 - assert set(json.loads(p["contributing_run_ids"])) == {100, 101} - assert json.loads(p["contributing_task_ids"]) == [1] # still one distinct task - - -def test_full_sweep_rescan_does_not_inflate(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - t1 = add_completed_task(db, title="ETL", prompt="run weekly etl") - t2 = add_completed_task(db, title="ETL", prompt="run weekly etl again") - run1 = db.get_task_runs(t1)[0]["id"] - run2 = db.get_task_runs(t2)[0]["id"] - - payload = json.dumps( - [ - { - "pattern_key": "weekly-etl", - "kind": "recipe", - "summary": "etl", - "run_id": run1, - "task_id": t1, - }, - { - "pattern_key": "weekly-etl", - "kind": "recipe", - "summary": "etl", - "run_id": run2, - "task_id": t2, - }, - ] - ) - monkeypatch.setattr(sched, "_run_agent_command", lambda *a, **k: (True, payload)) - - r1 = sched.run_skill_sweep(agent="claude", full=True) - assert r1["scanned"] == 2 and r1["new"] == 2 - assert db.get_skill_patterns()[0]["recurrence_count"] == 2 - - # Re-scan the SAME runs → idempotent: recurrence unchanged, no new occurrences - r2 = sched.run_skill_sweep(agent="claude", full=True) - assert r2["scanned"] == 2 and r2["new"] == 0 - assert db.get_skill_patterns()[0]["recurrence_count"] == 2 - - -def test_run_skill_sweep_agent_failure_raises(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - add_completed_task(db) - - def fake_run(agent, cmd, cwd, on_stdout_line=None, on_stderr_line=None): - return False, "agent exploded" - - monkeypatch.setattr(sched, "_run_agent_command", fake_run) - - with pytest.raises(RuntimeError, match="agent exploded"): - sched.run_skill_sweep(agent="claude") - # failed sweep must not advance the watermark - assert db.get_setting("skill_sweep_watermark", "") == "" - - -def test_trigger_skill_sweep_guards_concurrency(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - # Simulate an in-flight sweep - sched._skill_sweep_running = True - assert sched.trigger_skill_sweep() is False - status = sched.skill_sweep_status() - assert status["running"] is True diff --git a/tests/test_skill_registry.py b/tests/test_skill_registry.py deleted file mode 100644 index 88e2df0..0000000 --- a/tests/test_skill_registry.py +++ /dev/null @@ -1,106 +0,0 @@ -import os - -import pytest - -from taskboard import TaskDB, TaskScheduler - - -def make_db(tmp_path): - return TaskDB(str(tmp_path / "agentforge-test.db")) - - -def register(sched, db, name="my-skill"): - # Use the real approval path so files + symlinks exist on disk. - db.upsert_skill_pattern(name, "recipe", "summary", 1) - pid = db.conn.execute("SELECT id FROM skill_patterns WHERE pattern_key=?", (name,)).fetchone()[ - "id" - ] - body = f"---\nname: {name}\ndescription: d\n---\n\nbody" - skill = sched.approve_skill(pid, name, "d", body) - return skill["id"] - - -def test_disable_removes_symlinks_keeps_canonical(tmp_path, monkeypatch): - monkeypatch.setenv("HOME", str(tmp_path)) - db = make_db(tmp_path) - sched = TaskScheduler(db) - sid = register(sched, db) - - claude = os.path.expanduser("~/.claude/skills/my-skill") - agents = os.path.expanduser("~/.agents/skills/my-skill") - canonical = os.path.expanduser("~/.agentforge/skills/my-skill/SKILL.md") - assert os.path.islink(claude) and os.path.islink(agents) - - sched.toggle_skill(sid, False) - assert not os.path.lexists(claude) # symlink gone - assert not os.path.lexists(agents) - assert os.path.isfile(canonical) # canonical preserved - assert db.get_skill(sid)["enabled"] == 0 - - -def test_enable_recreates_symlinks(tmp_path, monkeypatch): - monkeypatch.setenv("HOME", str(tmp_path)) - db = make_db(tmp_path) - sched = TaskScheduler(db) - sid = register(sched, db) - sched.toggle_skill(sid, False) - - sched.toggle_skill(sid, True) - claude = os.path.expanduser("~/.claude/skills/my-skill") - agents = os.path.expanduser("~/.agents/skills/my-skill") - assert os.path.islink(claude) and os.path.islink(agents) - assert os.path.isfile(os.path.join(claude, "SKILL.md")) - assert db.get_skill(sid)["enabled"] == 1 - - -def test_toggle_idempotent(tmp_path, monkeypatch): - monkeypatch.setenv("HOME", str(tmp_path)) - db = make_db(tmp_path) - sched = TaskScheduler(db) - sid = register(sched, db) - # disable twice, enable twice — no errors, stable end state - sched.toggle_skill(sid, False) - sched.toggle_skill(sid, False) - sched.toggle_skill(sid, True) - sched.toggle_skill(sid, True) - assert db.get_skill(sid)["enabled"] == 1 - assert os.path.islink(os.path.expanduser("~/.claude/skills/my-skill")) - - -def test_delete_removes_everything(tmp_path, monkeypatch): - monkeypatch.setenv("HOME", str(tmp_path)) - db = make_db(tmp_path) - sched = TaskScheduler(db) - sid = register(sched, db) - - sched.remove_skill(sid) - assert db.get_skill(sid) is None - assert not os.path.lexists(os.path.expanduser("~/.claude/skills/my-skill")) - assert not os.path.lexists(os.path.expanduser("~/.agents/skills/my-skill")) - assert not os.path.isdir(os.path.expanduser("~/.agentforge/skills/my-skill")) - - -def test_toggle_unknown_skill(tmp_path, monkeypatch): - monkeypatch.setenv("HOME", str(tmp_path)) - db = make_db(tmp_path) - sched = TaskScheduler(db) - with pytest.raises(ValueError, match="not found"): - sched.toggle_skill(99999, True) - - -def test_delete_unknown_skill(tmp_path, monkeypatch): - monkeypatch.setenv("HOME", str(tmp_path)) - db = make_db(tmp_path) - sched = TaskScheduler(db) - with pytest.raises(ValueError, match="not found"): - sched.remove_skill(99999) - - -def test_get_skills_lists_registry(tmp_path, monkeypatch): - monkeypatch.setenv("HOME", str(tmp_path)) - db = make_db(tmp_path) - sched = TaskScheduler(db) - register(sched, db, "skill-a") - register(sched, db, "skill-b") - names = {s["name"] for s in db.get_skills()} - assert names == {"skill-a", "skill-b"} diff --git a/tests/test_skill_scheduler.py b/tests/test_skill_scheduler.py deleted file mode 100644 index 6f7c677..0000000 --- a/tests/test_skill_scheduler.py +++ /dev/null @@ -1,79 +0,0 @@ -from datetime import datetime, timedelta - -from taskboard import TaskDB, TaskScheduler, _parse_comparable_datetime - - -def make_db(tmp_path): - return TaskDB(str(tmp_path / "agentforge-test.db")) - - -def recorder(sched): - calls = [] - sched.trigger_skill_sweep = lambda agent=None: calls.append(agent) or True - return calls - - -def test_scheduled_sweep_disabled_by_default(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - calls = recorder(sched) - sched._maybe_run_scheduled_sweep() - assert calls == [] - # disabled → never even schedules - assert db.get_setting("skill_sweep_next_run", "") == "" - - -def test_scheduled_sweep_first_enable_schedules_only(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - db.set_setting("skill_library_enabled", "1") - calls = recorder(sched) - sched._maybe_run_scheduled_sweep() - assert calls == [] # first tick just schedules forward - assert db.get_setting("skill_sweep_next_run", "") != "" - - -def test_scheduled_sweep_fires_when_due(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - db.set_setting("skill_library_enabled", "1") - db.set_setting("skill_sweep_agent", "codex") - db.set_setting("skill_sweep_next_run", (datetime.now() - timedelta(minutes=1)).isoformat()) - calls = recorder(sched) - sched._maybe_run_scheduled_sweep() - assert calls == ["codex"] - nxt = db.get_setting("skill_sweep_next_run", "") - assert nxt and _parse_comparable_datetime(nxt) > datetime.now() - - -def test_scheduled_sweep_not_due(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - db.set_setting("skill_library_enabled", "1") - future = (datetime.now() + timedelta(hours=1)).isoformat() - db.set_setting("skill_sweep_next_run", future) - calls = recorder(sched) - sched._maybe_run_scheduled_sweep() - assert calls == [] - assert db.get_setting("skill_sweep_next_run", "") == future - - -def test_scheduled_sweep_invalid_cron_skips(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - db.set_setting("skill_library_enabled", "1") - db.set_setting("skill_sweep_cron", "not a cron") - calls = recorder(sched) - sched._maybe_run_scheduled_sweep() - assert calls == [] - - -def test_scheduled_sweep_re_enable_catches_up(tmp_path): - # Disabled for a while leaves a stale past next_run → fires once on re-enable. - db = make_db(tmp_path) - sched = TaskScheduler(db) - db.set_setting("skill_library_enabled", "1") - db.set_setting("skill_sweep_next_run", (datetime.now() - timedelta(days=3)).isoformat()) - calls = recorder(sched) - sched._maybe_run_scheduled_sweep() - assert len(calls) == 1 diff --git a/tests/test_slack_channel.py b/tests/test_slack_channel.py deleted file mode 100644 index 9ce9e3b..0000000 --- a/tests/test_slack_channel.py +++ /dev/null @@ -1,508 +0,0 @@ -import threading -from unittest.mock import MagicMock, patch - -from taskboard_bus import MessageBus, OutboundMessage, OutboundMessageType - - -class StubDB: - def __init__(self): - self.settings = {} - self.tasks = {} - self.updated = [] - - def get_setting(self, key, default=None): - return self.settings.get(key, default) - - def set_setting(self, key, value): - self.settings[key] = value - - def get_task(self, task_id): - return self.tasks.get(task_id) - - def update_task(self, task_id, **updates): - self.updated.append((task_id, updates)) - self.tasks.setdefault(task_id, {"id": task_id}).update(updates) - - -class StubScheduler: - def __init__(self): - self.submitted = [] - - def submit_task(self, task): - self.submitted.append(task) - return len(self.submitted) - - -def _make_channel(db=None, scheduler=None): - from channels.slack_channel import SlackChannel - - bus = MessageBus() - db = db or StubDB() - scheduler = scheduler or StubScheduler() - channel = SlackChannel( - bus=bus, - db=db, - scheduler=scheduler, - bot_token="xoxb-test", - app_token="xapp-test", - ) - # Inject a mock web client and bot id so helpers don't hit the network. - channel._web_client = MagicMock() - channel._web_client.chat_postMessage.return_value = {"ts": "1700.0001"} - channel._bot_user_id = "UBOT" - return channel - - -# ── construction / config ──────────────────────────────────────── - - -def test_init_reads_tokens_and_subscribes(): - channel = _make_channel() - assert channel.bot_token == "xoxb-test" - assert channel.app_token == "xapp-test" - assert channel.name == "slack" - assert channel._on_outbound in channel.bus._outbound_listeners - - -def test_init_falls_back_to_env(monkeypatch): - from channels.slack_channel import SlackChannel - - monkeypatch.setenv("SLACK_BOT_TOKEN", "xoxb-env") - monkeypatch.setenv("SLACK_APP_TOKEN", "xapp-env") - channel = SlackChannel(bus=MessageBus(), db=StubDB(), scheduler=StubScheduler()) - assert channel.bot_token == "xoxb-env" - assert channel.app_token == "xapp-env" - - -def test_start_disabled_without_tokens(capsys): - from channels.slack_channel import SlackChannel - - channel = SlackChannel(bus=MessageBus(), db=StubDB(), scheduler=StubScheduler()) - channel.bot_token = "" - channel.app_token = "" - channel.start() - assert "disabled" in capsys.readouterr().out - assert channel._running is False - - -def test_parse_task_id(): - from channels.slack_channel import SlackChannel - - assert SlackChannel._parse_task_id("#42") == 42 - assert SlackChannel._parse_task_id(" 7 ") == 7 - assert SlackChannel._parse_task_id("nope") is None - assert SlackChannel._parse_task_id("") is None - - -# ── task creation ──────────────────────────────────────────────── - - -def test_create_task_submits_and_tracks_origin(monkeypatch): - from channels import slack_channel - - monkeypatch.setattr(slack_channel, "_require_slack", lambda: None, raising=False) - scheduler = StubScheduler() - channel = _make_channel(scheduler=scheduler) - - with patch("channels.dir_utils.resolve_working_dir", return_value="~/myapp"): - channel._handle_user_message("fix login bug", "C1", None, "100.1") - - assert len(scheduler.submitted) == 1 - task = scheduler.submitted[0] - assert task.prompt == "fix login bug" - assert task.title == "[Slack] fix login bug" - assert task.tags == "slack" - assert task.working_dir == "~/myapp" - # origin tracked: (channel_id, thread_ts, reaction_ts) - assert channel._task_origin[1] == ("C1", "100.1", "100.1") - assert channel._thread_ts_map["100.1"] == 1 - - -def test_empty_message_replies_help(): - channel = _make_channel() - channel._handle_user_message("", "C1", None, "100.1") - sent = channel._web_client.chat_postMessage.call_args.kwargs["text"] - assert "AgentForge Bot" in sent - - -def test_help_command_and_word(): - channel = _make_channel() - channel._handle_user_message("/help", "C1", None, "1.0") - channel._handle_user_message("help", "C1", None, "2.0") - texts = [c.kwargs["text"] for c in channel._web_client.chat_postMessage.call_args_list] - assert all("AgentForge Bot" in t for t in texts) - - -def test_unknown_command_replies_help(): - channel = _make_channel() - channel._handle_user_message("/bogus", "C1", None, "1.0") - sent = channel._web_client.chat_postMessage.call_args.kwargs["text"] - assert "AgentForge Bot" in sent - - -# ── commands ───────────────────────────────────────────────────── - - -def test_cmd_status_usage_and_not_found(): - channel = _make_channel() - channel._cmd_status("", "C1", "1.0") - assert "Usage" in channel._web_client.chat_postMessage.call_args.kwargs["text"] - - channel._cmd_status("99", "C1", "1.0") - assert "not found" in channel._web_client.chat_postMessage.call_args.kwargs["text"] - - -def test_cmd_status_renders_task(): - db = StubDB() - db.tasks[5] = { - "id": 5, - "title": "Build feature", - "status": "completed", - "created_at": "2026-01-01", - "last_run_at": "2026-01-02", - "result": "all green", - "error": None, - } - channel = _make_channel(db=db) - channel._cmd_status("#5", "C1", "1.0") - text = channel._web_client.chat_postMessage.call_args.kwargs["text"] - assert ":white_check_mark:" in text - assert "Task #5" in text - assert "Build feature" in text - assert "all green" in text - - -def test_cmd_cancel_paths(): - db = StubDB() - db.tasks[1] = {"id": 1, "title": "t", "status": "running"} - db.tasks[2] = {"id": 2, "title": "t", "status": "completed"} - channel = _make_channel(db=db) - - channel._cmd_cancel("", "C1", "1.0") - assert "Usage" in channel._web_client.chat_postMessage.call_args.kwargs["text"] - - channel._cmd_cancel("99", "C1", "1.0") - assert "not found" in channel._web_client.chat_postMessage.call_args.kwargs["text"] - - channel._cmd_cancel("2", "C1", "1.0") - assert "already" in channel._web_client.chat_postMessage.call_args.kwargs["text"] - - channel._cmd_cancel("1", "C1", "1.0") - assert db.updated[-1] == (1, {"status": "cancelled"}) - assert "cancelled" in channel._web_client.chat_postMessage.call_args.kwargs["text"] - - -def test_cmd_resume_paths(): - db = StubDB() - db.tasks[1] = {"id": 1, "title": "t", "status": "completed", "session_id": "s1"} - db.tasks[2] = {"id": 2, "title": "t", "status": "completed"} # no session - channel = _make_channel(db=db) - - channel._cmd_resume("", "C1", "1.0") - assert "Usage" in channel._web_client.chat_postMessage.call_args.kwargs["text"] - - channel._cmd_resume("1", "C1", "1.0") - assert "provide a message" in channel._web_client.chat_postMessage.call_args.kwargs["text"] - - channel._cmd_resume("2 keep going", "C1", "1.0") - assert "no saved session" in channel._web_client.chat_postMessage.call_args.kwargs["text"] - - channel._cmd_resume("#1 keep going", "C1", "1.0") - assert db.updated[-1][0] == 1 - assert db.updated[-1][1]["prompt"] == "keep going" - assert db.updated[-1][1]["status"] == "pending" - assert channel._task_origin[1] == ("C1", "1.0", "1.0") - - -def test_slash_command_dispatch_dir_and_agent(): - db = StubDB() - channel = _make_channel(db=db) - - channel._handle_user_message("/dir ~/proj", "C1", None, "1.0") - assert db.get_setting("slack_default_working_dir") == "~/proj" - - channel._handle_user_message("/agent codex", "C1", None, "2.0") - assert db.get_setting("default_agent") == "codex" - - -# ── resume by thread reply ─────────────────────────────────────── - - -def test_thread_reply_resumes_task(): - db = StubDB() - db.tasks[8] = {"id": 8, "title": "t", "status": "completed", "session_id": "s8"} - channel = _make_channel(db=db) - channel._notification_map["root.1"] = 8 - - channel._handle_user_message("continue please", "C1", "root.1", "200.1") - - assert db.updated[-1][0] == 8 - assert db.updated[-1][1]["prompt"] == "continue please" - assert channel._task_origin[8] == ("C1", "root.1", "200.1") - - -def test_thread_reply_via_thread_ts_map(): - db = StubDB() - db.tasks[9] = {"id": 9, "title": "t", "status": "completed", "session_id": "s9"} - channel = _make_channel(db=db) - channel._thread_ts_map["root.9"] = 9 - - channel._handle_user_message("more work", "C1", "root.9", "300.1") - assert db.updated[-1][0] == 9 - - -def test_thread_reply_no_session_warns(): - db = StubDB() - db.tasks[10] = {"id": 10, "title": "t", "status": "completed"} # no session - channel = _make_channel(db=db) - channel._notification_map["root.10"] = 10 - - channel._handle_user_message("go", "C1", "root.10", "400.1") - assert db.updated == [] - assert "no saved session" in channel._web_client.chat_postMessage.call_args.kwargs["text"] - - -# ── event dispatch ─────────────────────────────────────────────── - - -def test_handle_message_event_dm(): - db = StubDB() - channel = _make_channel(db=db) - with patch("channels.dir_utils.resolve_working_dir", return_value="~"): - channel._handle_message_event( - { - "channel_type": "im", - "user": "U1", - "text": "do something", - "channel": "D1", - "ts": "10.1", - } - ) - assert len(channel.scheduler.submitted) == 1 - - -def test_handle_message_event_skips_non_dm_and_bot(): - channel = _make_channel() - channel._handle_message_event({"channel_type": "channel", "text": "x"}) - channel._handle_message_event({"channel_type": "im", "bot_id": "B1", "text": "x"}) - channel._handle_message_event( - {"channel_type": "im", "user": "UBOT", "text": "x", "channel": "D1", "ts": "1"} - ) - assert len(channel.scheduler.submitted) == 0 - - -def test_handle_mention_event_strips_prefix(): - channel = _make_channel() - with patch("channels.dir_utils.resolve_working_dir", return_value="~"): - channel._handle_mention_event( - { - "user": "U1", - "text": "<@UBOT> build the thing", - "channel": "C9", - "ts": "50.1", - } - ) - task = channel.scheduler.submitted[0] - assert task.prompt == "build the thing" - - -def test_handle_mention_event_skips_bot(): - channel = _make_channel() - channel._handle_mention_event({"bot_id": "B1", "text": "x"}) - channel._handle_mention_event({"user": "UBOT", "text": "x"}) - assert len(channel.scheduler.submitted) == 0 - - -def test_app_home_opened_sends_help(): - channel = _make_channel() - channel._web_client.conversations_open.return_value = {"channel": {"id": "D5"}} - channel._handle_app_home_opened({"user": "U7", "tab": "home"}) - text = channel._web_client.chat_postMessage.call_args.kwargs["text"] - assert "AgentForge Bot" in text - - -def test_app_home_opened_ignores_non_home_tab(): - channel = _make_channel() - channel._handle_app_home_opened({"user": "U7", "tab": "messages"}) - channel._web_client.chat_postMessage.assert_not_called() - - -def test_handle_socket_request_dispatches_message(): - channel = _make_channel() - client = MagicMock() - - class Req: - type = "events_api" - envelope_id = "envelope-1234567890" - payload = { - "event": { - "type": "message", - "channel_type": "im", - "user": "U1", - "text": "hello there", - "channel": "D1", - "ts": "9.9", - } - } - - with patch("channels.dir_utils.resolve_working_dir", return_value="~"): - channel._handle_socket_request(client, Req()) - client.send_socket_mode_response.assert_called_once() - assert len(channel.scheduler.submitted) == 1 - - -def test_handle_socket_request_ignores_non_events_api(): - channel = _make_channel() - client = MagicMock() - - class Req: - type = "hello" - envelope_id = "envelope-abcdefghijkl" - payload = {} - - channel._handle_socket_request(client, Req()) - client.send_socket_mode_response.assert_called_once() - assert len(channel.scheduler.submitted) == 0 - - -# ── outbound send ──────────────────────────────────────────────── - - -def _wait_threads(): - for t in threading.enumerate(): - if t is not threading.current_thread() and t.daemon: - t.join(timeout=2) - - -def test_send_completion_to_origin(): - db = StubDB() - channel = _make_channel(db=db) - channel._task_origin[3] = ("C1", "100.1", "100.1") - - channel.send( - OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, - task_id=3, - payload={"title": "Fix login", "result": "all done"}, - ) - ) - _wait_threads() - # Reaction added + reply posted with the result text. - react_names = [c.kwargs.get("name") for c in channel._web_client.reactions_add.call_args_list] - assert "white_check_mark" in react_names - posted = [c.kwargs["text"] for c in channel._web_client.chat_postMessage.call_args_list] - assert any("all done" in t for t in posted) - # Notification ts mapped to task and origin freed. - assert channel._notification_map.get("1700.0001") == 3 - assert 3 not in channel._task_origin - - -def test_send_failure_to_origin_adds_x_reaction(): - db = StubDB() - channel = _make_channel(db=db) - channel._task_origin[4] = ("C1", "100.1", "100.1") - - channel.send( - OutboundMessage( - type=OutboundMessageType.TASK_FAILED, - task_id=4, - payload={"title": "Broke", "error": "boom"}, - ) - ) - _wait_threads() - react_names = [c.kwargs.get("name") for c in channel._web_client.reactions_add.call_args_list] - assert "x" in react_names - posted = [c.kwargs["text"] for c in channel._web_client.chat_postMessage.call_args_list] - assert any("boom" in t for t in posted) - - -def test_send_ignores_non_terminal_types(): - channel = _make_channel() - channel.send(OutboundMessage(type=OutboundMessageType.TASK_STARTED, task_id=1, payload={})) - channel._web_client.chat_postMessage.assert_not_called() - - -def test_send_fallback_to_default_channel(): - db = StubDB() - db.settings["slack_default_channel"] = "C-DEFAULT" - channel = _make_channel(db=db) - - channel.send( - OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, - task_id=11, - payload={"title": "Job", "result": "ok"}, - ) - ) - _wait_threads() - call = channel._web_client.chat_postMessage.call_args - assert call.kwargs["channel"] == "C-DEFAULT" - assert "Job" in call.kwargs["text"] - - -def test_send_fallback_to_dm_user(): - db = StubDB() - db.settings["slack_default_user"] = "U-DM" - channel = _make_channel(db=db) - channel._web_client.conversations_open.return_value = {"channel": {"id": "D-DM"}} - - channel.send( - OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, - task_id=12, - payload={"title": "Job", "result": "ok"}, - ) - ) - _wait_threads() - call = channel._web_client.chat_postMessage.call_args - assert call.kwargs["channel"] == "D-DM" - - -def test_send_no_origin_no_default_skips(capsys): - channel = _make_channel() - channel.send( - OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, - task_id=13, - payload={"title": "Job", "result": "ok"}, - ) - ) - _wait_threads() - channel._web_client.chat_postMessage.assert_not_called() - - -# ── low-level helpers ──────────────────────────────────────────── - - -def test_open_dm_channel_caches(): - channel = _make_channel() - channel._web_client.conversations_open.return_value = {"channel": {"id": "D1"}} - assert channel._open_dm_channel("U1") == "D1" - # Second call should hit the cache, not the API. - channel._web_client.conversations_open.reset_mock() - assert channel._open_dm_channel("U1") == "D1" - channel._web_client.conversations_open.assert_not_called() - - -def test_open_dm_channel_handles_error(): - channel = _make_channel() - channel._web_client.conversations_open.side_effect = RuntimeError("nope") - assert channel._open_dm_channel("U2") is None - - -def test_reply_return_ts(): - channel = _make_channel() - channel._web_client.chat_postMessage.return_value = {"ts": "999.1"} - assert channel._reply_return_ts("C1", None, "hi") == "999.1" - - channel._web_client.chat_postMessage.side_effect = RuntimeError("fail") - assert channel._reply_return_ts("C1", None, "hi") is None - - -def test_stop_unsubscribes(): - channel = _make_channel() - channel._socket_client = MagicMock() - channel.stop() - assert channel._running is False - channel._socket_client.disconnect.assert_called_once() - assert channel._on_outbound not in channel.bus._outbound_listeners diff --git a/tests/test_slack_more.py b/tests/test_slack_more.py deleted file mode 100644 index 400b643..0000000 --- a/tests/test_slack_more.py +++ /dev/null @@ -1,433 +0,0 @@ -"""Additional Slack channel coverage. - -Focuses on branches not exercised by tests/test_slack_channel.py: - - the _require_slack import guard (success + ImportError) - - the start() / Socket Mode bootstrap (SDK fully mocked, no network) - - _handle_socket_request error dispatch + unhandled event types - - mention/app_home edge branches - - send() default-channel fallback + reaction/reply error paths - - low-level helper guards (no web client, postMessage failures) -""" - -import sys -from types import SimpleNamespace -from unittest.mock import MagicMock, patch - -from taskboard_bus import MessageBus, OutboundMessage, OutboundMessageType - - -class StubDB: - def __init__(self): - self.settings = {} - self.tasks = {} - self.updated = [] - - def get_setting(self, key, default=None): - return self.settings.get(key, default) - - def set_setting(self, key, value): - self.settings[key] = value - - def get_task(self, task_id): - return self.tasks.get(task_id) - - def update_task(self, task_id, **updates): - self.updated.append((task_id, updates)) - self.tasks.setdefault(task_id, {"id": task_id}).update(updates) - - -class StubScheduler: - def __init__(self): - self.submitted = [] - - def submit_task(self, task): - self.submitted.append(task) - return len(self.submitted) - - -def _make_channel(db=None, scheduler=None): - from channels.slack_channel import SlackChannel - - channel = SlackChannel( - bus=MessageBus(), - db=db or StubDB(), - scheduler=scheduler or StubScheduler(), - bot_token="xoxb-test", - app_token="xapp-test", - ) - channel._web_client = MagicMock() - channel._web_client.chat_postMessage.return_value = {"ts": "1700.0001"} - channel._bot_user_id = "UBOT" - return channel - - -# ── _require_slack import guard (lines 25-33) ──────────────────── - - -def test_require_slack_returns_sdk_symbols(): - from channels.slack_channel import _require_slack - - WebClient, SocketModeClient, SocketModeResponse, SocketModeRequest = _require_slack() - # The real slack_sdk is installed in this environment; just confirm callables. - assert all(x is not None for x in (WebClient, SocketModeClient)) - assert SocketModeResponse is not None - assert SocketModeRequest is not None - - -def test_require_slack_raises_on_missing_dependency(monkeypatch): - from channels.slack_channel import _require_slack - - # Hide the slack_sdk package so the import inside _require_slack fails. - for mod in list(sys.modules): - if mod == "slack_sdk" or mod.startswith("slack_sdk."): - monkeypatch.delitem(sys.modules, mod, raising=False) - monkeypatch.setitem(sys.modules, "slack_sdk", None) - - try: - _require_slack() - raise AssertionError("expected ImportError") - except ImportError as e: - assert "slack-sdk is required" in str(e) - - -# ── start() Socket Mode bootstrap (lines 112-144) ──────────────── - - -def _install_fake_slack_sdk(monkeypatch, *, auth_raises=False): - """Build a stand-in slack_sdk so start() runs without a real connection.""" - web_instances = [] - - class FakeWebClient: - def __init__(self, token=None): - self.token = token - self._auth_raises = auth_raises - web_instances.append(self) - - def auth_test(self): - if self._auth_raises: - raise RuntimeError("bad token") - return {"user_id": "UBOT99", "team": "T1", "user": "agentbot"} - - class FakeSocketModeClient: - def __init__(self, app_token=None, web_client=None): - self.app_token = app_token - self.web_client = web_client - self.socket_mode_request_listeners = [] - self.connected = False - - def connect(self): - # No-op: never opens a real socket, returns immediately. - self.connected = True - - def disconnect(self): - self.connected = False - - fake = SimpleNamespace( - WebClient=FakeWebClient, - SocketModeClient=FakeSocketModeClient, - SocketModeResponse=MagicMock(), - SocketModeRequest=MagicMock(), - ) - from channels import slack_channel - - monkeypatch.setattr( - slack_channel, - "_require_slack", - lambda: ( - fake.WebClient, - fake.SocketModeClient, - fake.SocketModeResponse, - fake.SocketModeRequest, - ), - ) - return fake - - -def test_start_bootstraps_socket_mode(monkeypatch): - from channels.slack_channel import SlackChannel - - _install_fake_slack_sdk(monkeypatch) - channel = SlackChannel( - bus=MessageBus(), - db=StubDB(), - scheduler=StubScheduler(), - bot_token="xoxb-real", - app_token="xapp-real", - ) - channel.start() - - assert channel._running is True - assert channel._bot_user_id == "UBOT99" - # Connected (no real network) and our listener registered. - assert channel._socket_client.connected is True - assert channel._handle_socket_request in channel._socket_client.socket_mode_request_listeners - - -def test_start_aborts_when_auth_test_fails(monkeypatch): - from channels.slack_channel import SlackChannel - - _install_fake_slack_sdk(monkeypatch, auth_raises=True) - channel = SlackChannel( - bus=MessageBus(), - db=StubDB(), - scheduler=StubScheduler(), - bot_token="xoxb-real", - app_token="xapp-real", - ) - channel.start() - - # auth_test failed → bootstrap returns before creating the socket client. - assert channel._bot_user_id is None - assert channel._socket_client is None - - -# ── _handle_socket_request dispatch branches (lines 192-200) ───── - - -def test_socket_request_dispatches_mention(monkeypatch): - channel = _make_channel() - client = MagicMock() - - class Req: - type = "events_api" - envelope_id = "envelope-mention-1" - payload = { - "event": { - "type": "app_mention", - "user": "U1", - "text": "<@UBOT> do the thing", - "channel": "C1", - "ts": "1.0", - } - } - - with patch("channels.dir_utils.resolve_working_dir", return_value="~"): - channel._handle_socket_request(client, Req()) - assert len(channel.scheduler.submitted) == 1 - assert channel.scheduler.submitted[0].prompt == "do the thing" - - -def test_socket_request_dispatches_app_home_opened(): - channel = _make_channel() - channel._web_client.conversations_open.return_value = {"channel": {"id": "D9"}} - client = MagicMock() - - class Req: - type = "events_api" - envelope_id = "envelope-home-12345" - payload = {"event": {"type": "app_home_opened", "user": "U2", "tab": "home"}} - - channel._handle_socket_request(client, Req()) - text = channel._web_client.chat_postMessage.call_args.kwargs["text"] - assert "AgentForge Bot" in text - - -def test_socket_request_unhandled_event_type(): - channel = _make_channel() - client = MagicMock() - - class Req: - type = "events_api" - envelope_id = "envelope-unknown-99" - payload = {"event": {"type": "reaction_added"}} - - channel._handle_socket_request(client, Req()) - client.send_socket_mode_response.assert_called_once() - assert len(channel.scheduler.submitted) == 0 - - -def test_socket_request_swallows_handler_exception(): - channel = _make_channel() - client = MagicMock() - - class Req: - type = "events_api" - envelope_id = "envelope-boom-123" - payload = {"event": {"type": "message", "channel_type": "im"}} - - # Force the message handler to blow up so the except branch (198-200) runs. - with patch.object(channel, "_handle_message_event", side_effect=RuntimeError("kaboom")): - channel._handle_socket_request(client, Req()) - # Ack still sent; exception is caught, not propagated. - client.send_socket_mode_response.assert_called_once() - - -# ── message/mention strip-prefix branches (245->250, 247->250, 263, 273) ── - - -def test_mention_without_prefix_keeps_text(): - channel = _make_channel() - with patch("channels.dir_utils.resolve_working_dir", return_value="~"): - # No leading "<@UBOT>" so the strip branch is skipped. - channel._handle_mention_event( - {"user": "U1", "text": "just build it", "channel": "C1", "ts": "2.0"} - ) - assert channel.scheduler.submitted[0].prompt == "just build it" - - -def test_mention_when_bot_user_id_unset(): - channel = _make_channel() - channel._bot_user_id = None # skip the "if self._bot_user_id" strip block - with patch("channels.dir_utils.resolve_working_dir", return_value="~"): - channel._handle_mention_event( - {"user": "U1", "text": "<@UX> hi", "channel": "C1", "ts": "3.0"} - ) - assert channel.scheduler.submitted[0].prompt == "<@UX> hi" - - -def test_app_home_opened_ignores_self_and_empty_user(): - channel = _make_channel() - channel._handle_app_home_opened({"user": "UBOT", "tab": "home"}) # self - channel._handle_app_home_opened({"user": "", "tab": "home"}) # empty - channel._web_client.chat_postMessage.assert_not_called() - - -def test_app_home_opened_dm_open_fails(capsys): - channel = _make_channel() - channel._web_client.conversations_open.side_effect = RuntimeError("nope") - channel._handle_app_home_opened({"user": "U7", "tab": "home"}) - # _open_dm_channel returned None → the else branch (273) logs a failure. - assert "Failed to open DM channel" in capsys.readouterr().out - channel._web_client.chat_postMessage.assert_not_called() - - -# ── _cmd_status error/result rendering (418, 419->422) ─────────── - - -def test_cmd_status_renders_error_only(): - db = StubDB() - db.tasks[3] = { - "id": 3, - "title": "Broke", - "status": "failed", - "created_at": "2026-01-01", - "last_run_at": None, - "error": "stack trace here", - "result": None, - } - channel = _make_channel(db=db) - channel._cmd_status("#3", "C1", "1.0") - text = channel._web_client.chat_postMessage.call_args.kwargs["text"] - assert "Error:" in text - assert "stack trace here" in text - assert "Result:" not in text - - -# ── send() default-channel fallback message format (line 550) ──── - - -def test_send_default_channel_failure_prefixes_x_emoji(): - db = StubDB() - db.settings["slack_default_channel"] = "C-DEF" - channel = _make_channel(db=db) - - channel.send( - OutboundMessage( - type=OutboundMessageType.TASK_FAILED, - task_id=21, - payload={"title": "Job", "error": "broke"}, - ) - ) - # _send_and_track runs in a thread; drain it. - import threading - - for t in threading.enumerate(): - if t is not threading.current_thread() and t.daemon: - t.join(timeout=2) - - call = channel._web_client.chat_postMessage.call_args - assert call.kwargs["channel"] == "C-DEF" - assert ":x:" in call.kwargs["text"] - assert "broke" in call.kwargs["text"] - # The sent ts was tracked back to the task. - assert channel._notification_map.get("1700.0001") == 21 - - -def test_send_dm_fallback_fails_to_open_skips(capsys): - db = StubDB() - db.settings["slack_default_user"] = "U-DM" - channel = _make_channel(db=db) - channel._web_client.conversations_open.side_effect = RuntimeError("denied") - - channel.send( - OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, - task_id=22, - payload={"title": "Job", "result": "ok"}, - ) - ) - import threading - - for t in threading.enumerate(): - if t is not threading.current_thread() and t.daemon: - t.join(timeout=2) - - out = capsys.readouterr().out - assert "Failed to open DM" in out - channel._web_client.chat_postMessage.assert_not_called() - - -# ── _on_outbound passthrough (line 563) ────────────────────────── - - -def test_on_outbound_delegates_to_send(): - channel = _make_channel() - with patch.object(channel, "send") as send: - msg = OutboundMessage(type=OutboundMessageType.TASK_STARTED, task_id=1, payload={}) - channel._on_outbound(msg) - send.assert_called_once_with(msg) - - -# ── helper no-web-client / failure guards ──────────────────────── - - -def test_open_dm_channel_returns_none_without_web_client(): - channel = _make_channel() - channel._web_client = None # line 572 - assert channel._open_dm_channel("U1") is None - - -def test_add_reaction_noop_without_web_client(): - channel = _make_channel() - channel._web_client = None # line 586 - # Should simply return without spawning a thread or raising. - channel._add_reaction("C1", "1.0", "eyes") - - -def test_add_reaction_handles_already_reacted_and_errors(): - channel = _make_channel() - - # already_reacted is swallowed silently (lines 596-597). - channel._web_client.reactions_add.side_effect = RuntimeError("already_reacted") - channel._add_reaction("C1", "1.0", "eyes") - - # other errors are logged (lines 598-599). - channel._web_client.reactions_add.side_effect = RuntimeError("rate_limited") - channel._add_reaction("C1", "1.0", "eyes") - - import threading - - for t in threading.enumerate(): - if t is not threading.current_thread() and t.daemon: - t.join(timeout=2) - assert channel._web_client.reactions_add.call_count == 2 - - -def test_reply_skips_without_web_client(capsys): - channel = _make_channel() - channel._web_client = None # lines 605-606 - channel._reply("C1", None, "hi") - assert "no web_client" in capsys.readouterr().out - - -def test_reply_logs_postmessage_failure(capsys): - channel = _make_channel() - channel._web_client.chat_postMessage.side_effect = RuntimeError("api down") - channel._reply("C1", None, "hi") # lines 618-620 - assert "chat_postMessage FAILED" in capsys.readouterr().out - - -def test_reply_return_ts_none_without_web_client(): - channel = _make_channel() - channel._web_client = None # line 627 - assert channel._reply_return_ts("C1", None, "hi") is None diff --git a/tests/test_task_output_api.py b/tests/test_task_output_api.py deleted file mode 100644 index 24c61c3..0000000 --- a/tests/test_task_output_api.py +++ /dev/null @@ -1,30 +0,0 @@ -from unittest.mock import Mock - -from taskboard import TaskAPIHandler - - -def _handler(live_output=None, runs=None): - handler = object.__new__(TaskAPIHandler) - handler.scheduler = Mock() - handler.scheduler._live_output = live_output or {} - handler.db = Mock() - handler.db.get_task_runs.return_value = runs or [] - return handler - - -def test_task_output_payload_returns_live_output_while_running(): - handler = _handler(live_output={12: "live stdout"}) - - payload = handler._task_output_payload(12) - - assert payload == {"output": "live stdout", "is_running": True} - handler.db.get_task_runs.assert_not_called() - - -def test_task_output_payload_falls_back_to_latest_run_raw_output_when_finished(): - handler = _handler(runs=[{"raw_output": "persisted stdout"}]) - - payload = handler._task_output_payload(12) - - assert payload == {"output": "persisted stdout", "is_running": False} - handler.db.get_task_runs.assert_called_once_with(12, limit=1) diff --git a/tests/test_taskboard_bus.py b/tests/test_taskboard_bus.py deleted file mode 100644 index da49af3..0000000 --- a/tests/test_taskboard_bus.py +++ /dev/null @@ -1,230 +0,0 @@ -from taskboard_bus import ( - BusAwareSchedulerMixin, - Channel, - InboundMessageType, - MessageBus, - OutboundMessage, - OutboundMessageType, - UIChannel, -) - - -class StubDB: - def __init__(self, tasks=None): - self.tasks = tasks or {} - - def get_task(self, task_id): - return self.tasks.get(task_id) - - -class RecordingChannel(Channel): - def __init__(self, bus, db): - super().__init__("test", bus, db) - self.sent = [] - - def send(self, msg): - self.sent.append(msg) - - def start(self): - self._running = True - - -class FakeScheduler(BusAwareSchedulerMixin): - def __init__(self, db, bus=None): - self.db = db - self.bus = bus - - -def test_message_bus_round_trips_inbound_and_outbound_messages(): - bus = MessageBus() - inbound = RecordingChannel(bus, StubDB())._make_inbound( - InboundMessageType.CREATE_TASK, - {"title": "hello"}, - reply_to="chat-1", - metadata={"source_message_id": "m1"}, - ) - outbound = OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, - task_id=1, - payload={"status": "completed"}, - ) - - bus.publish_inbound(inbound) - bus.publish_outbound(outbound) - - assert bus.get_inbound() == inbound - assert bus.get_outbound() == outbound - - -def test_message_bus_returns_none_when_queue_is_empty(): - bus = MessageBus() - - assert bus.get_inbound(block=False) is None - assert bus.get_outbound(block=False) is None - - -def test_message_bus_notifies_and_unsubscribes_outbound_listeners(): - bus = MessageBus() - seen = [] - - def listener(msg): - seen.append(msg.task_id) - - bus.subscribe_outbound(listener) - bus.publish_outbound( - OutboundMessage( - type=OutboundMessageType.TASK_STARTED, - task_id=7, - ) - ) - bus.unsubscribe_outbound(listener) - bus.publish_outbound( - OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, - task_id=8, - ) - ) - - assert seen == [7] - - -def test_message_bus_tolerates_listener_errors_and_missing_unsubscribe(): - bus = MessageBus() - - def bad_listener(msg): - raise RuntimeError("boom") - - bus.subscribe_outbound(bad_listener) - bus.publish_outbound( - OutboundMessage( - type=OutboundMessageType.TASK_UPDATED, - task_id=9, - ) - ) - bus.unsubscribe_outbound(bad_listener) - bus.unsubscribe_outbound(bad_listener) - - assert bus.get_outbound().task_id == 9 - - -def test_channel_notify_task_maps_task_status_to_outbound_type(): - bus = MessageBus() - db = StubDB( - { - 1: {"status": "completed", "result": "ok", "error": None, "title": "done"}, - 2: {"status": "failed", "result": None, "error": "boom", "title": "bad"}, - } - ) - channel = RecordingChannel(bus, db) - - channel.notify_task(1) - channel.notify_task(2) - channel.notify_task(999) - - assert [msg.type for msg in channel.sent] == [ - OutboundMessageType.TASK_COMPLETED, - OutboundMessageType.TASK_FAILED, - ] - assert channel.sent[0].payload["result"] == "ok" - assert channel.sent[1].payload["error"] == "boom" - - -def test_channel_stop_marks_channel_as_not_running(): - channel = RecordingChannel(MessageBus(), StubDB()) - channel.start() - - channel.stop() - - assert channel._running is False - - -def test_ui_channel_caches_outbound_messages_and_inbound_notifications(): - bus = MessageBus() - db = StubDB() - channel = UIChannel(bus, db) - - channel.start() - created = channel._make_inbound( - InboundMessageType.CREATE_TASK, - {"task_id": 1, "prompt": "hello"}, - ) - bus.publish_inbound(created) - channel.notify_task_created(1, "hello", "~/repo", tags="ops") - channel.notify_task_resumed(1, "continue") - bus.publish_outbound( - OutboundMessage( - type=OutboundMessageType.TASK_UPDATED, - task_id=1, - payload={"status": "running"}, - ) - ) - - inbound_messages = [bus.get_inbound(), bus.get_inbound(), bus.get_inbound()] - cached = channel.get_cached_outbound(1) - - assert channel._running is True - assert [msg.type for msg in inbound_messages] == [ - InboundMessageType.CREATE_TASK, - InboundMessageType.CREATE_TASK, - InboundMessageType.RESUME_TASK, - ] - assert inbound_messages[1].payload["working_dir"] == "~/repo" - assert inbound_messages[1].payload["tags"] == "ops" - assert inbound_messages[2].payload["message"] == "continue" - assert len(cached) == 1 - assert cached[0].payload["status"] == "running" - - -def test_ui_channel_evicts_oldest_task_cache_entries(): - bus = MessageBus() - channel = UIChannel(bus, StubDB()) - channel._CACHE_MAX_TASKS = 2 - - for task_id in (1, 2, 3): - channel.send( - OutboundMessage( - type=OutboundMessageType.TASK_UPDATED, - task_id=task_id, - ) - ) - - assert sorted(channel._outbound_cache) == [2, 3] - - -def test_bus_aware_scheduler_mixin_publishes_task_updates(): - bus = MessageBus() - db = StubDB( - { - 1: {"status": "completed", "result": "ok", "error": None, "title": "done"}, - 2: {"status": "running", "result": None, "error": None, "title": "work"}, - } - ) - scheduler = FakeScheduler(db, bus) - - scheduler._bus_notify(1) - scheduler._bus_notify(2, override_type=OutboundMessageType.STATUS_RESPONSE) - scheduler._bus_notify(999) - - first = bus.get_outbound() - second = bus.get_outbound() - - assert first.type == OutboundMessageType.TASK_COMPLETED - assert first.payload["title"] == "done" - assert second.type == OutboundMessageType.STATUS_RESPONSE - assert second.payload["status"] == "running" - - -def test_bus_aware_scheduler_mixin_noops_without_bus(): - scheduler = FakeScheduler(StubDB({1: {"status": "completed"}}), bus=None) - - scheduler._bus_notify(1) - - -def test_bus_aware_scheduler_mixin_tolerates_db_errors(): - class BrokenDB: - def get_task(self, task_id): - raise RuntimeError("db down") - - scheduler = FakeScheduler(BrokenDB(), MessageBus()) - - scheduler._bus_notify(1) diff --git a/tests/test_taskboard_gaps.py b/tests/test_taskboard_gaps.py deleted file mode 100644 index 61e3009..0000000 --- a/tests/test_taskboard_gaps.py +++ /dev/null @@ -1,522 +0,0 @@ -"""Final mop-up coverage for still-uncovered, reachable branches in taskboard.py. - -Everything here constructs ``TaskDB`` + ``TaskScheduler`` directly, never starts -the background loop, and mocks every agent / subprocess / network call. The -``run_server`` tests patch ``serve_forever`` (and bind/activate) to no-ops so -nothing real spawns or blocks. - -Targets (current source line numbers): -* run_server ENABLED-channel wiring + shutdown() closure (5064-5167) -* env-var auto-enable for Telegram / Slack (5080-5081, 5103-5104) -* _run_agent_command subprocess branches (OSError, timeout, codex/claude parse) -* skill-draft worker error path + approve_skill invalid-name guard -* output-listener error swallow + remove_output_listener ValueError -* DAG _on_task_completed / _on_task_failed edge branches -""" - -import json -import os -from unittest import mock - -import pytest - -import taskboard -from taskboard import ( - ScheduleType, - Task, - TaskDB, - TaskScheduler, -) - - -def make_db(tmp_path): - return TaskDB(str(tmp_path / "t.db")) - - -# ── run_server: every channel ENABLED ─────────────────────────────────────── -def _run_server_with_enabled_channels(tmp_path, env, settings): - """Drive run_server with the given env + settings, all channel classes mocked. - - Returns a dict of the mock constructors / instances so the caller can assert - on .start() calls and exercise the shutdown() closure (captured via the - registered SIGINT signal handler). - """ - db = TaskDB(str(tmp_path / "t.db")) - for key, val in settings.items(): - db.set_setting(key, val) - - feishu_inst = mock.Mock(name="feishu_inst") - slack_inst = mock.Mock(name="slack_inst") - weixin_inst = mock.Mock(name="weixin_inst") - telegram_inst = mock.Mock(name="telegram_inst") - ui_inst = mock.Mock(name="ui_inst") - scheduler_inst = mock.Mock(name="scheduler_inst") - - feishu_cls = mock.Mock(return_value=feishu_inst) - slack_cls = mock.Mock(return_value=slack_inst) - weixin_cls = mock.Mock(return_value=weixin_inst) - telegram_factory = mock.Mock(return_value=telegram_inst) - ui_cls = mock.Mock(return_value=ui_inst) - scheduler_cls = mock.Mock(return_value=scheduler_inst) - - captured = {} - - def fake_signal(sig, handler): - captured[sig] = handler - - with ( - mock.patch.dict(os.environ, env, clear=True), - mock.patch.object(taskboard, "_kill_stale_process_on_port"), - mock.patch.object(taskboard, "TaskDB", return_value=db), - mock.patch.object(taskboard, "FEISHU_CHANNEL_AVAILABLE", True), - mock.patch.object(taskboard, "TELEGRAM_CHANNEL_AVAILABLE", True), - mock.patch.object(taskboard, "SLACK_CHANNEL_AVAILABLE", True), - mock.patch.object(taskboard, "WEIXIN_CHANNEL_AVAILABLE", True), - mock.patch.object(taskboard, "FeishuChannel", feishu_cls), - mock.patch.object(taskboard, "create_telegram_channel", telegram_factory), - mock.patch.object(taskboard, "SlackChannel", slack_cls), - mock.patch.object(taskboard, "WeixinChannel", weixin_cls), - mock.patch.object(taskboard, "UIChannel", ui_cls), - mock.patch.object(taskboard, "TaskScheduler", scheduler_cls), - mock.patch.object(taskboard.QuietHTTPServer, "serve_forever", return_value=None) as serve, - mock.patch.object(taskboard.QuietHTTPServer, "server_bind", return_value=None), - mock.patch.object(taskboard.QuietHTTPServer, "server_activate", return_value=None), - mock.patch.object(taskboard.QuietHTTPServer, "shutdown", return_value=None) as srv_shutdown, - mock.patch.object(taskboard.signal, "signal", side_effect=fake_signal), - ): - taskboard.run_server(port=0) - - serve.assert_called_once() - - # Exercise the shutdown() closure via the registered SIGINT handler. - handler = captured[taskboard.signal.SIGINT] - with mock.patch.object(taskboard.sys, "exit") as sys_exit: - handler(taskboard.signal.SIGINT, None) - sys_exit.assert_called_once_with(0) - srv_shutdown.assert_called_once() - - return { - "feishu_cls": feishu_cls, - "feishu_inst": feishu_inst, - "slack_cls": slack_cls, - "slack_inst": slack_inst, - "weixin_cls": weixin_cls, - "weixin_inst": weixin_inst, - "telegram_factory": telegram_factory, - "telegram_inst": telegram_inst, - "ui_inst": ui_inst, - "scheduler_inst": scheduler_inst, - "serve": serve, - } - - -def test_run_server_starts_all_channels_via_settings(tmp_path): - """Every channel ENABLED through DB settings → each constructor + .start() - is called, the API handler is wired, and shutdown() stops each channel.""" - env = {} # no auto-enable env vars; settings drive everything - settings = { - "feishu_enabled": "true", - "telegram_enabled": "true", - "telegram_bot_token": "tg-token", - "telegram_allowed_users": "u1,u2", - "slack_enabled": "true", - "slack_bot_token": "xoxb-bot", - "slack_app_token": "xapp-app", - "weixin_enabled": "true", - } - m = _run_server_with_enabled_channels(tmp_path, env, settings) - - # Each channel constructed + started. - m["feishu_cls"].assert_called_once() - m["feishu_inst"].start.assert_called_once() - m["telegram_factory"].assert_called_once() - m["telegram_inst"].start.assert_called_once() - m["slack_cls"].assert_called_once() - m["slack_inst"].start.assert_called_once() - m["weixin_cls"].assert_called_once() - m["weixin_inst"].start.assert_called_once() - m["ui_inst"].start.assert_called_once() - m["scheduler_inst"].start.assert_called_once() - - # Telegram factory received the configured token + allowed users. - _, kwargs = m["telegram_factory"].call_args - assert kwargs["token"] == "tg-token" - assert kwargs["allowed_users_str"] == "u1,u2" - - # Slack got both tokens. - _, sl_kwargs = m["slack_cls"].call_args - assert sl_kwargs["bot_token"] == "xoxb-bot" - assert sl_kwargs["app_token"] == "xapp-app" - - # API handler wired with the started channel instances. - assert taskboard.TaskAPIHandler.feishu_channel is m["feishu_inst"] - assert taskboard.TaskAPIHandler.telegram_channel is m["telegram_inst"] - assert taskboard.TaskAPIHandler.slack_channel is m["slack_inst"] - assert taskboard.TaskAPIHandler.weixin_channel is m["weixin_inst"] - assert taskboard.TaskAPIHandler.scheduler is m["scheduler_inst"] - - # shutdown() closure stopped each channel + the scheduler. - m["feishu_inst"].stop.assert_called_once() - m["telegram_inst"].stop.assert_called_once() - m["slack_inst"].stop.assert_called_once() - m["scheduler_inst"].stop.assert_called_once() - - -def test_run_server_auto_enables_telegram_and_slack_via_env(tmp_path): - """Env vars (but no enabling settings) auto-enable Telegram + Slack.""" - env = { - "TELEGRAM_BOT_TOKEN": "env-tg", - "SLACK_BOT_TOKEN": "env-bot", - "SLACK_APP_TOKEN": "env-app", - } - settings = {} # nothing enabled in DB — env must flip them on - m = _run_server_with_enabled_channels(tmp_path, env, settings) - - m["telegram_factory"].assert_called_once() - m["telegram_inst"].start.assert_called_once() - m["slack_cls"].assert_called_once() - m["slack_inst"].start.assert_called_once() - - # Tokens came from the environment. - _, tg_kwargs = m["telegram_factory"].call_args - assert tg_kwargs["token"] == "env-tg" - _, sl_kwargs = m["slack_cls"].call_args - assert sl_kwargs["bot_token"] == "env-bot" - assert sl_kwargs["app_token"] == "env-app" - - # Feishu / Weixin not enabled → not constructed, and the handler refs are None. - m["feishu_cls"].assert_not_called() - m["weixin_cls"].assert_not_called() - assert taskboard.TaskAPIHandler.feishu_channel is None - assert taskboard.TaskAPIHandler.weixin_channel is None - - -def test_run_server_telegram_factory_returns_none_no_start(tmp_path): - """When create_telegram_channel returns None, .start() is never reached. - - Also enables Feishu while leaving Telegram/Slack off so the shutdown() - closure exercises the "channel is None → skip stop" branches for - telegram_channel and slack_channel. - """ - db = TaskDB(str(tmp_path / "t.db")) - db.set_setting("telegram_enabled", "true") - db.set_setting("telegram_bot_token", "tok") - db.set_setting("feishu_enabled", "true") - - scheduler_inst = mock.Mock() - feishu_inst = mock.Mock() - telegram_factory = mock.Mock(return_value=None) # factory declines - - captured = {} - - def fake_signal(sig, handler): - captured[sig] = handler - - with ( - mock.patch.dict(os.environ, {}, clear=True), - mock.patch.object(taskboard, "_kill_stale_process_on_port"), - mock.patch.object(taskboard, "TaskDB", return_value=db), - mock.patch.object(taskboard, "TELEGRAM_CHANNEL_AVAILABLE", True), - mock.patch.object(taskboard, "FEISHU_CHANNEL_AVAILABLE", True), - mock.patch.object(taskboard, "FeishuChannel", mock.Mock(return_value=feishu_inst)), - mock.patch.object(taskboard, "create_telegram_channel", telegram_factory), - mock.patch.object(taskboard, "UIChannel", mock.Mock()), - mock.patch.object(taskboard, "TaskScheduler", mock.Mock(return_value=scheduler_inst)), - mock.patch.object(taskboard.QuietHTTPServer, "serve_forever", return_value=None), - mock.patch.object(taskboard.QuietHTTPServer, "server_bind", return_value=None), - mock.patch.object(taskboard.QuietHTTPServer, "server_activate", return_value=None), - mock.patch.object(taskboard.QuietHTTPServer, "shutdown", return_value=None), - mock.patch.object(taskboard.signal, "signal", side_effect=fake_signal), - ): - taskboard.run_server(port=0) - - # Run shutdown() with telegram/slack absent → those stop branches skip. - handler = captured[taskboard.signal.SIGTERM] - with mock.patch.object(taskboard.sys, "exit"): - handler(taskboard.signal.SIGTERM, None) - - telegram_factory.assert_called_once() - assert taskboard.TaskAPIHandler.telegram_channel is None - assert taskboard.TaskAPIHandler.slack_channel is None - feishu_inst.stop.assert_called_once() # feishu present → stopped - scheduler_inst.stop.assert_called_once() - - -# ── _run_agent_command: subprocess branches (Popen mocked) ─────────────────── -class _FakePopen: - def __init__(self, returncode=0, stdout_lines=None, stderr_lines=None, wait_raises=None): - self.returncode = returncode - self.stdout = list(stdout_lines or []) - self.stderr = list(stderr_lines or []) - self._wait_raises = wait_raises - self.killed = False - - def wait(self, timeout=None): - if self._wait_raises is not None: - raise self._wait_raises - return self.returncode - - def kill(self): - self.killed = True - - -def test_run_agent_command_filenotfound(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - monkeypatch.setattr( - "taskboard.subprocess.Popen", lambda *a, **k: (_ for _ in ()).throw(FileNotFoundError()) - ) - ok, out = sched._run_agent_command("claude", ["claude"], ".") - assert ok is False - assert "not found" in out - - -def test_run_agent_command_oserror(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - monkeypatch.setattr( - "taskboard.subprocess.Popen", lambda *a, **k: (_ for _ in ()).throw(OSError("boom")) - ) - ok, out = sched._run_agent_command("claude", ["claude"], ".") - assert ok is False - assert "boom" in out - - -def test_run_agent_command_timeout_kills_proc(tmp_path, monkeypatch): - import subprocess as _sp - - db = make_db(tmp_path) - sched = TaskScheduler(db) - proc = _FakePopen(wait_raises=_sp.TimeoutExpired(["claude"], 1)) - monkeypatch.setattr("taskboard.subprocess.Popen", lambda *a, **k: proc) - ok, out = sched._run_agent_command("claude", ["claude"], ".") - assert ok is False - assert "timed out" in out - assert proc.killed is True - - -def test_run_agent_command_nonzero_returns_stderr(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - proc = _FakePopen(returncode=2, stdout_lines=[], stderr_lines=["the error\n"]) - monkeypatch.setattr("taskboard.subprocess.Popen", lambda *a, **k: proc) - ok, out = sched._run_agent_command("claude", ["claude"], ".") - assert ok is False - assert "the error" in out - - -def test_run_agent_command_codex_parses_agent_message(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - lines = [ - "\n", # blank → skipped - "not json\n", # JSONDecodeError → skipped - json.dumps({"type": "thread.started", "thread_id": "t1"}) + "\n", - json.dumps( - {"type": "item.completed", "item": {"type": "agent_message", "text": "CODEX FINAL"}} - ) - + "\n", - ] - proc = _FakePopen(returncode=0, stdout_lines=lines) - monkeypatch.setattr("taskboard.subprocess.Popen", lambda *a, **k: proc) - ok, out = sched._run_agent_command("codex", ["codex"], ".") - assert ok is True - assert out == "CODEX FINAL" - - -def test_run_agent_command_claude_parses_result_and_assistant(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - lines = [ - "\n", # blank → skipped - "garbage\n", # JSONDecodeError → skipped - json.dumps( - { - "type": "assistant", - "message": {"content": [{"type": "text", "text": "thinking"}, "raw-str"]}, - } - ) - + "\n", - json.dumps({"type": "result", "result": "CLAUDE RESULT"}) + "\n", - ] - proc = _FakePopen(returncode=0, stdout_lines=lines) - monkeypatch.setattr("taskboard.subprocess.Popen", lambda *a, **k: proc) - ok, out = sched._run_agent_command("claude", ["claude"], ".") - assert ok is True - assert out == "CLAUDE RESULT" - - -def test_run_agent_command_claude_falls_back_to_assistant_text(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - # No result event → falls back to the last assistant text. - lines = [ - json.dumps( - {"type": "assistant", "message": {"content": [{"type": "text", "text": "ONLY TEXT"}]}} - ) - + "\n", - ] - proc = _FakePopen(returncode=0, stdout_lines=lines) - monkeypatch.setattr("taskboard.subprocess.Popen", lambda *a, **k: proc) - ok, out = sched._run_agent_command("claude", ["claude"], ".") - assert ok is True - assert out == "ONLY TEXT" - - -# ── skill draft worker error path + approve_skill guards ───────────────────── -def _make_pattern(db, key="pk"): - db.upsert_skill_pattern(key, "recipe", "summary", 1) - return db.conn.execute("SELECT id FROM skill_patterns WHERE pattern_key=?", (key,)).fetchone()[ - "id" - ] - - -def test_trigger_skill_draft_worker_records_error(tmp_path, monkeypatch): - import time as _time - - db = make_db(tmp_path) - sched = TaskScheduler(db) - pid = _make_pattern(db) - - def boom(*a, **k): - raise RuntimeError("distill kaboom") - - monkeypatch.setattr(sched, "distill_skill_draft", boom) - assert sched.trigger_skill_draft(pid) is True - - # Poll until the background worker persists the error to the draft row. - for _ in range(50): - draft = db.get_skill_draft(pid) - if draft and draft["status"] == "error": - break - _time.sleep(0.02) - draft = db.get_skill_draft(pid) - assert draft["status"] == "error" - assert "distill kaboom" in (draft["error"] or "") - - -def test_trigger_skill_draft_unknown_pattern_returns_false(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - assert sched.trigger_skill_draft(99999) is False - - -def test_approve_skill_invalid_name_raises(tmp_path, monkeypatch): - monkeypatch.setenv("HOME", str(tmp_path)) - db = make_db(tmp_path) - sched = TaskScheduler(db) - pid = _make_pattern(db, key="!!!") # sanitizes to empty - # Body with frontmatter whose name also sanitizes to empty. - body = "---\nname: !!!\n---\nbody" - with pytest.raises(ValueError, match="invalid skill name"): - sched.approve_skill(pid, name="!!!", description="d", body=body) - - -def test_approve_skill_empty_body_raises(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - pid = _make_pattern(db) - with pytest.raises(ValueError, match="skill body is empty"): - sched.approve_skill(pid, name="ok", description="d", body=" ") - - -# ── output listeners: error swallow + remove edge ──────────────────────────── -def test_fire_output_listeners_swallows_callback_error(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - calls = [] - - def bad(task_id, run_id, event_type, content): - raise RuntimeError("listener boom") - - def good(task_id, run_id, event_type, content): - calls.append((task_id, content)) - - sched.add_output_listener(bad) - sched.add_output_listener(good) - # Must not raise even though `bad` throws; `good` still runs. - sched._fire_output_listeners(1, 2, "assistant", "hello") - assert calls == [(1, "hello")] - - -def test_remove_output_listener_unregistered_is_noop(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - # Removing a callback that was never added hits the ValueError branch. - sched.remove_output_listener(lambda *a: None) # must not raise - - -# ── DAG hooks: edge branches ───────────────────────────────────────────────── -def test_on_task_completed_skips_when_downstream_deleted(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - up = db.add_task(Task(title="up", prompt="p", working_dir=".")) - down = sched.submit_task(Task(title="down", prompt="p", working_dir="."), depends_on=[up]) - assert db.get_task(down)["status"] == "blocked" - - db.update_task(up, status="completed") - # get_task(downstream) returns None → the `continue` branch is taken. - real_get_task = db.get_task - - def get_task_none_for_down(task_id): - if task_id == down: - return None - return real_get_task(task_id) - - with mock.patch.object(db, "get_task", side_effect=get_task_none_for_down): - sched._on_task_completed(up) - # Downstream never updated because it "vanished" mid-hook. - assert db.get_task(down)["status"] == "blocked" - - -def test_on_task_completed_unknown_schedule_type_defaults_pending(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - up = db.add_task(Task(title="up", prompt="p", working_dir=".")) - down = sched.submit_task(Task(title="down", prompt="p", working_dir="."), depends_on=[up]) - # Force an unrecognized schedule_type so the else-branch (pending) runs. - db.conn.execute("UPDATE tasks SET schedule_type='weird' WHERE id=?", (down,)) - db.conn.commit() - db.update_task(up, status="completed") - sched._on_task_completed(up) - assert db.get_task(down)["status"] == "pending" - - -def test_on_task_failed_diamond_visits_shared_downstream_once(tmp_path): - # root → a, root → b, both a & b → leaf. The `already visited` continue - # branch fires for leaf the second time it's reached. - db = make_db(tmp_path) - sched = TaskScheduler(db) - root = db.add_task(Task(title="root", prompt="p", working_dir=".")) - a = db.add_task(Task(title="a", prompt="p", working_dir=".")) - b = db.add_task(Task(title="b", prompt="p", working_dir=".")) - leaf = db.add_task(Task(title="leaf", prompt="p", working_dir=".")) - db.add_dependency(a, root) - db.add_dependency(b, root) - db.add_dependency(leaf, a) - db.add_dependency(leaf, b) - for t in (a, b, leaf): - db.update_task(t, status="blocked") - sched._on_task_failed(root) - assert db.get_task(a)["status"] == "cancelled" - assert db.get_task(b)["status"] == "cancelled" - assert db.get_task(leaf)["status"] == "cancelled" - - -# ── _schedule_delayed transitions pending → scheduled with next_run_at ─────── -def test_schedule_delayed_sets_scheduled_and_next_run(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - tid = db.add_task( - Task( - title="t", - prompt="p", - working_dir=".", - schedule_type=ScheduleType.DELAYED, - delay_seconds=30, - ) - ) - sched._schedule_delayed(db.get_task(tid)) - row = db.get_task(tid) - assert row["status"] == "scheduled" - assert row["next_run_at"] is not None diff --git a/tests/test_taskboard_gaps2.py b/tests/test_taskboard_gaps2.py deleted file mode 100644 index 12f0c8b..0000000 --- a/tests/test_taskboard_gaps2.py +++ /dev/null @@ -1,792 +0,0 @@ -"""Second mop-up coverage pass for still-reachable branches in taskboard.py. - -This file targets gaps that the existing suites (test_scheduler_logic.py, -test_scheduler_more.py, test_taskboard_gaps.py, test_execute_task.py, -test_api_handler.py, test_api_handler_more.py, test_heartbeat.py) leave behind. - -Everything constructs ``TaskDB`` + ``TaskScheduler`` directly, never starts the -background loop, and mocks every agent / subprocess call. The HTTP tests reuse -the same hermetic QuietHTTPServer harness (unstarted scheduler, skill/disk -entrypoints monkeypatched, no Origin header so CSRF is skipped). - -Distinct from the existing files; targeted areas: -* Codex/Claude streaming delta + event-normalization helpers - (_codex_text_delta, _codex_append_text_delta, _codex_event_delta_text, - _extract_codex_thread_id, _find_codex_generated_images, _image_media_type, - _extract_codex_success_output, _store_generated_image_events, - _claude_text_delta, _claude_message_id, _content_to_display_text, - _parse_codex_event variants, _store_output_event empty-skip). -* _execute_task EDGE branches: magic-byte media sniffing for extension-less - images, unsafe-path rejection paired with a sniffed image, the sub-agent wait - loop, and the on_task_update/_channels notify fan-out. -* HTTP handler edges: channel restart paths (feishu/telegram/slack/weixin), - DAG prompt_images JSON fallback, /resume not-found, DELETE CSRF rejection, - request-body-too-large 413. -""" - -import io -import json -import os -import tempfile -import threading -import time -import urllib.error -import urllib.request -from unittest import mock -from unittest.mock import patch - -import pytest - -import taskboard -from taskboard import ( - QuietHTTPServer, - Task, - TaskAPIHandler, - TaskDB, - TaskScheduler, -) - - -def make_db(tmp_path): - return TaskDB(str(tmp_path / "t.db")) - - -# ── shared FakePopen for _execute_task drives ─────────────────────────────── -class FakePopen: - _next_pid = 9000 - - def __init__(self, stdout_lines, stderr_lines=None, returncode=0): - FakePopen._next_pid += 1 - self.pid = FakePopen._next_pid - self.stdout = iter(list(stdout_lines)) - self.stderr = iter(list(stderr_lines or [])) - self.returncode = returncode - self.stdin = _FakeStdin() - - def wait(self, timeout=None): - return self.returncode - - def poll(self): - return self.returncode - - def kill(self): - pass - - -class _FakeStdin: - def __init__(self): - self.buffer = "" - - def write(self, data): - self.buffer += data - - def close(self): - pass - - -@pytest.fixture -def _stub_process_group(monkeypatch): - monkeypatch.setattr(taskboard.os, "getpgid", lambda pid: pid) - - def fake_killpg(pgid, sig): - raise ProcessLookupError - - monkeypatch.setattr(taskboard.os, "killpg", fake_killpg) - - -def _claude_lines(result_text="done", session_id="s1"): - return [ - json.dumps({"type": "system", "subtype": "init", "session_id": session_id}) + "\n", - json.dumps( - { - "type": "result", - "subtype": "success", - "result": result_text, - "session_id": session_id, - } - ) - + "\n", - ] - - -# ── Codex streaming delta helpers ─────────────────────────────────────────── -def test_codex_text_delta_cumulative_and_reset(tmp_path): - sched = TaskScheduler(make_db(tmp_path)) - # First emission returns the whole text (no previous). - assert sched._codex_text_delta(1, "item", "Hello") == "Hello" - # Cumulative continuation returns only the new suffix. - assert sched._codex_text_delta(1, "item", "Hello World") == " World" - # Identical text → no new delta. - assert sched._codex_text_delta(1, "item", "Hello World") is None - # Empty current text → None. - assert sched._codex_text_delta(1, "item2", "") is None - # Non-prefix (a full rewrite) returns the new text as-is. - assert sched._codex_text_delta(1, "item", "Totally different") == "Totally different" - - -def test_codex_append_text_delta_accumulates(tmp_path): - sched = TaskScheduler(make_db(tmp_path)) - assert sched._codex_append_text_delta(2, "a", "") is None - assert sched._codex_append_text_delta(2, "a", "foo") == "foo" - assert sched._codex_append_text_delta(2, "a", "bar") == "bar" - assert sched._codex_item_text[(2, "a")] == "foobar" - - -def test_codex_event_delta_text_variants(tmp_path): - sched = TaskScheduler(make_db(tmp_path)) - # string delta on item - assert sched._codex_event_delta_text({}, {"delta": "abc"}) == "abc" - # dict delta with text on event - assert sched._codex_event_delta_text({"delta": {"text": "xyz"}}, {}) == "xyz" - # dict delta whose text is not a string → None - assert sched._codex_event_delta_text({}, {"delta": {"text": 5}}) is None - # no delta anywhere → None - assert sched._codex_event_delta_text({}, {}) is None - - -def test_extract_codex_thread_id_skips_noise(tmp_path): - sched = TaskScheduler(make_db(tmp_path)) - raw = "\n".join( - [ - " ", # blank - "not json", # JSONDecodeError - json.dumps({"type": "turn.started"}), # no thread id - json.dumps({"type": "thread.started", "thread_id": "TH-42"}), - ] - ) - assert sched._extract_codex_thread_id(raw) == "TH-42" - assert sched._extract_codex_thread_id("only noise here") is None - - -def test_image_media_type_extension_map(tmp_path): - sched = TaskScheduler(make_db(tmp_path)) - assert sched._image_media_type("/x/a.png") == "image/png" - assert sched._image_media_type("/x/a.JPG") == "image/jpeg" - assert sched._image_media_type("/x/a.webp") == "image/webp" - # unknown extension → default png - assert sched._image_media_type("/x/a.bmp") == "image/png" - - -def test_find_codex_generated_images_filters_and_sorts(tmp_path, monkeypatch): - monkeypatch.setenv("HOME", str(tmp_path)) - monkeypatch.delenv("CODEX_HOME", raising=False) - sched = TaskScheduler(make_db(tmp_path)) - - # No thread id → empty. - assert sched._find_codex_generated_images(None) == [] - # Thread id with no directory → empty. - assert sched._find_codex_generated_images("ghost") == [] - - img_dir = tmp_path / ".codex" / "generated_images" / "TH" - img_dir.mkdir(parents=True) - (img_dir / "b.png").write_bytes(b"x") - (img_dir / "a.webp").write_bytes(b"y") - (img_dir / "note.txt").write_bytes(b"skip me") # non-image suffix - - found = sched._find_codex_generated_images("TH") - assert [os.path.basename(p) for p in found] == ["a.webp", "b.png"] - - -def test_find_codex_generated_images_since_timestamp(tmp_path, monkeypatch): - monkeypatch.setenv("HOME", str(tmp_path)) - monkeypatch.delenv("CODEX_HOME", raising=False) - sched = TaskScheduler(make_db(tmp_path)) - img_dir = tmp_path / ".codex" / "generated_images" / "TH" - img_dir.mkdir(parents=True) - old = img_dir / "old.png" - old.write_bytes(b"x") - os.utime(old, (1000, 1000)) # ancient mtime - new = img_dir / "new.png" - new.write_bytes(b"y") # current mtime - - # Only the freshly written file passes the since_timestamp filter. - found = sched._find_codex_generated_images("TH", since_timestamp=time.time() - 60) - assert [os.path.basename(p) for p in found] == ["new.png"] - - -def test_extract_codex_success_output_with_images(tmp_path): - sched = TaskScheduler(make_db(tmp_path)) - raw = "\n".join( - [ - " ", # blank skipped - "not json", # decode error skipped - json.dumps( - {"type": "item.completed", "item": {"type": "agent_message", "text": "Done"}} - ), - ] - ) - out = sched._extract_codex_success_output(raw, generated_images=["/a.png", "/b.png"]) - assert "Done" in out - assert "2 张图片" in out - assert "/a.png" in out and "/b.png" in out - # No images and no agent_message text → empty string. - assert sched._extract_codex_success_output("nothing here") == "" - - -def test_store_generated_image_events_persists_metadata_and_data(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - tid = db.add_task(Task(title="t", prompt="p", working_dir=".")) - run_id = db.add_run(tid) - - real = tempfile.mkdtemp(dir="/tmp") - img = os.path.join(real, "pic.png") - with open(img, "wb") as f: - f.write(b"\x89PNG\r\n\x1a\nbytes") - missing = os.path.join(real, "gone.png") # never created → OSError branch - - sched._store_generated_image_events(tid, run_id, [img, missing]) - - events = db.get_output_events(tid) - types = [e["event_type"] for e in events] - # The real image yields both a generated_image trace and an image_content row; - # the missing one yields only the trace (read fails → continue). - assert types.count("generated_image") == 2 - assert types.count("image_content") == 1 - content = next(e for e in events if e["event_type"] == "image_content") - parsed = json.loads(content["content"]) - assert parsed["media_type"] == "image/png" - assert parsed["data"] # base64 payload present - - -# ── Claude streaming delta helpers ────────────────────────────────────────── -def test_claude_text_delta_paths(tmp_path): - sched = TaskScheduler(make_db(tmp_path)) - # empty current → None - assert sched._claude_text_delta(1, "m", "") is None - # first emission returns whole text - assert sched._claude_text_delta(1, "m", "abc") == "abc" - # identical → None - assert sched._claude_text_delta(1, "m", "abc") is None - # cumulative continuation → suffix - assert sched._claude_text_delta(1, "m", "abcdef") == "def" - # non-cumulative chunk on same message → returns chunk, accumulates state - assert sched._claude_text_delta(1, "m", "ZZZ") == "ZZZ" - assert sched._claude_message_text[(1, "m")] == "abcdefZZZ" - - -def test_claude_message_id_fallback(tmp_path): - sched = TaskScheduler(make_db(tmp_path)) - assert sched._claude_message_id({"message": {"id": "msg-7"}}, 1) == "msg-7" - assert sched._claude_message_id({"message": {"message_id": "mm"}}, 1) == "mm" - # no id at all → synthesized from run id - assert sched._claude_message_id({"message": {}}, 3) == "assistant:3" - assert sched._claude_message_id({"message": "not-a-dict"}, 4) == "assistant:4" - - -def test_content_to_display_text_variants(tmp_path): - sched = TaskScheduler(make_db(tmp_path)) - assert sched._content_to_display_text(None) == "" - assert sched._content_to_display_text("plain") == "plain" - mixed = [ - "raw", - {"type": "text", "text": "T"}, - {"type": "image"}, - {"type": "other", "k": "v"}, - ] - out = sched._content_to_display_text(mixed) - assert "raw" in out and "T" in out and "[image]" in out and "other" in out - # dict with text type - assert sched._content_to_display_text({"type": "text", "text": "hi"}) == "hi" - # dict without text type → JSON dump - assert "foo" in sched._content_to_display_text({"foo": "bar"}) - # non-str/list/dict → str() - assert sched._content_to_display_text(42) == "42" - - -def test_store_output_event_skips_empty(tmp_path): - db = make_db(tmp_path) - sched = TaskScheduler(db) - tid = db.add_task(Task(title="t", prompt="p", working_dir=".")) - run_id = db.add_run(tid) - sched._store_output_event(tid, run_id, "assistant", "") # empty → no row - assert db.get_output_events(tid) == [] - sched._store_output_event(tid, run_id, "assistant", "real") - assert len(db.get_output_events(tid)) == 1 - - -# ── _parse_codex_event normalization branches ─────────────────────────────── -def test_parse_codex_event_reasoning_and_kinds(tmp_path): - sched = TaskScheduler(make_db(tmp_path)) - - # reasoning delta → "[thinking] ..." assistant content - etype, content = sched._parse_codex_event( - {"type": "item.updated", "item": {"id": "r1", "type": "reasoning", "delta": "ponder"}}, - run_id=1, - ) - assert etype == "assistant" and content == "[thinking] ponder" - - # command_execution - etype, content = sched._parse_codex_event( - { - "type": "item.completed", - "item": { - "id": "c1", - "type": "command_execution", - "command": "ls", - "aggregated_output": "files", - "exit_code": 0, - "status": "completed", - }, - } - ) - assert etype == "command_execution" - assert json.loads(content)["command"] == "ls" - - # mcp_tool_call → tool_call - etype, _ = sched._parse_codex_event( - {"type": "item.completed", "item": {"type": "mcp_tool_call", "tool": "x"}} - ) - assert etype == "tool_call" - - # web_search - etype, _ = sched._parse_codex_event( - {"type": "item.completed", "item": {"type": "web_search", "query": "q"}} - ) - assert etype == "web_search" - - # file_change - etype, _ = sched._parse_codex_event( - {"type": "item.completed", "item": {"type": "file_change", "changes": []}} - ) - assert etype == "file_change" - - # unknown item type → passthrough (etype, full json) - etype, content = sched._parse_codex_event( - {"type": "item.completed", "item": {"type": "mystery"}} - ) - assert etype == "item.completed" - - -def test_parse_codex_event_errors_and_skips(tmp_path): - sched = TaskScheduler(make_db(tmp_path)) - # turn.failed → error with message - assert sched._parse_codex_event({"type": "turn.failed", "error": {"message": "boom"}}) == ( - "error", - "boom", - ) - # turn.failed with non-dict error - assert sched._parse_codex_event({"type": "turn.failed", "error": "plain"}) == ( - "error", - "plain", - ) - # plain error event - assert sched._parse_codex_event({"type": "error", "message": "bad"}) == ("error", "bad") - # silent skips - assert sched._parse_codex_event({"type": "turn.completed"}) == (None, None) - assert sched._parse_codex_event({"type": "thread.started"}) == (None, None) - # truly unknown top-level type → passthrough - etype, content = sched._parse_codex_event({"type": "weird.thing", "a": 1}) - assert etype == "weird.thing" - - -# ── _execute_task EDGE: magic-byte media sniff + unsafe-path reject ────────── -@pytest.mark.usefixtures("_stub_process_group") -def test_execute_task_sniffs_media_type_for_extensionless_images(tmp_path, monkeypatch): - """An extension-less safe image is loaded and its media type detected from - magic bytes; an unsafe path (outside allowed roots) is rejected. The Claude - multimodal stdin path is then taken with the sniffed media type.""" - db = make_db(tmp_path) - sched = TaskScheduler(db) - - real = tempfile.mkdtemp(dir="/tmp") - gif = os.path.join(real, "noext_gif") # no extension → magic-byte branch - with open(gif, "wb") as f: - f.write(b"GIF89a" + b"\x00" * 16) - - tid = db.add_task( - Task( - title="img", - prompt="see", - working_dir=".", - agent="claude", - image_paths=[gif, "/etc/shadow"], # one safe extensionless, one rejected - ) - ) - task = db.get_task(tid) - sched._active_tasks[tid] = object() - - captured = {} - - def fake_popen(cmd, **kwargs): - captured["cmd"] = cmd - captured["stdin_obj"] = kwargs.get("stdin") - return FakePopen(_claude_lines(result_text="ok")) - - with patch.object(taskboard.subprocess, "Popen", side_effect=fake_popen): - sched._execute_task(task) - - assert db.get_task(tid)["status"] == "completed" - # multimodal stdin path selected because exactly one image loaded - cmd = captured["cmd"] - assert "--input-format" in cmd - # the GIF magic bytes were sniffed → image/gif written into the stdin message - stdin_written = captured["stdin_obj"] - # stdin is subprocess.PIPE constant; the message content lives on the fake stdin - # object, which fake_popen returns — assert via the produced FakePopen instead. - assert stdin_written is taskboard.subprocess.PIPE - - -@pytest.mark.usefixtures("_stub_process_group") -def test_execute_task_sniffs_jpeg_magic_bytes(tmp_path, monkeypatch): - db = make_db(tmp_path) - sched = TaskScheduler(db) - real = tempfile.mkdtemp(dir="/tmp") - jpg = os.path.join(real, "noext_jpeg") - with open(jpg, "wb") as f: - f.write(b"\xff\xd8\xff" + b"\x00" * 16) - - tid = db.add_task( - Task(title="j", prompt="p", working_dir=".", agent="claude", image_paths=[jpg]) - ) - task = db.get_task(tid) - sched._active_tasks[tid] = object() - - written = {} - - def fake_popen(cmd, **kwargs): - fp = FakePopen(_claude_lines()) - written["fp"] = fp - return fp - - with patch.object(taskboard.subprocess, "Popen", side_effect=fake_popen): - sched._execute_task(task) - - assert db.get_task(tid)["status"] == "completed" - # The multimodal stdin message embeds the jpeg media type sniffed from bytes. - assert "image/jpeg" in written["fp"].stdin.buffer - - -@pytest.mark.usefixtures("_stub_process_group") -def test_execute_task_notify_fans_out_to_channels_and_callback(tmp_path): - """_notify (called several times during execution) fires the on_task_update - callback and starts a notify thread for each registered channel.""" - db = make_db(tmp_path) - updates = [] - - class _Chan: - def __init__(self): - self.notified = [] - - def notify_task(self, task_id): - self.notified.append(task_id) - - chan = _Chan() - sched = TaskScheduler(db, on_task_update=lambda tid: updates.append(tid)) - sched._channels.append(chan) - - tid = db.add_task(Task(title="t", prompt="p", working_dir=".", agent="claude")) - task = db.get_task(tid) - sched._active_tasks[tid] = object() - - fake = FakePopen(_claude_lines(result_text="fine")) - with patch.object(taskboard.subprocess, "Popen", return_value=fake): - sched._execute_task(task) - - # Give the daemon notify threads a moment to run. - for _ in range(50): - if tid in chan.notified: - break - time.sleep(0.02) - - assert db.get_task(tid)["status"] == "completed" - assert tid in updates # on_task_update callback fired - assert tid in chan.notified # channel notify_task fired - - -def test_execute_task_waits_for_subagents_then_group_exits(tmp_path, monkeypatch): - """Drive the sub-agent wait loop: the first killpg(pgid, 0) probe reports the - group alive (enters the wait body once), the second reports it gone (breaks). - time.sleep is stubbed so the 1s pause is instant.""" - db = make_db(tmp_path) - sched = TaskScheduler(db) - tid = db.add_task(Task(title="sub", prompt="p", working_dir=".", agent="claude")) - task = db.get_task(tid) - sched._active_tasks[tid] = object() - - monkeypatch.setattr(taskboard.os, "getpgid", lambda pid: pid) - - probe_calls = {"n": 0} - - def staged_killpg(pgid, sig): - if sig == 0: - probe_calls["n"] += 1 - if probe_calls["n"] == 1: - return # group still alive → loop body runs once - raise ProcessLookupError # gone → loop breaks - raise ProcessLookupError - - monkeypatch.setattr(taskboard.os, "killpg", staged_killpg) - # Make the 1s wait-loop sleep instant. - monkeypatch.setattr(taskboard.time, "sleep", lambda *a, **k: None) - - fake = FakePopen(_claude_lines(result_text="ok")) - with patch.object(taskboard.subprocess, "Popen", return_value=fake): - sched._execute_task(task) - - assert db.get_task(tid)["status"] == "completed" - # The loop probed at least twice (alive, then gone). - assert probe_calls["n"] >= 2 - - -# ── HTTP harness (mirrors tests/test_api_handler.py) ──────────────────────── -class _Client: - def __init__(self, base, host, port): - self.base = base - self.host = host - self.port = port - - def request(self, method, path, body=None, headers=None): - url = self.base + path - data = None - hdrs = dict(headers or {}) - if body is not None: - data = json.dumps(body).encode() - hdrs.setdefault("Content-Type", "application/json") - req = urllib.request.Request(url, data=data, method=method, headers=hdrs) - try: - with urllib.request.urlopen(req, timeout=10) as resp: - raw = resp.read() - status = resp.status - except urllib.error.HTTPError as e: - raw = e.read() - status = e.code - parsed = json.loads(raw) if raw else None - return status, parsed - - def post(self, path, body=None, headers=None): - return self.request("POST", path, body=body, headers=headers) - - def delete(self, path, headers=None): - return self.request("DELETE", path, headers=headers) - - -@pytest.fixture -def api(tmp_path, monkeypatch): - db = TaskDB(str(tmp_path / "test.db")) - scheduler = TaskScheduler(db) # NOT started - - monkeypatch.setattr(scheduler, "run_skill_sweep", lambda *a, **k: None) - monkeypatch.setattr(scheduler, "distill_skill_draft", lambda *a, **k: None) - monkeypatch.setattr( - taskboard, "write_skill_to_disk", lambda name, body: (f"/tmp/{name}.md", "") - ) - monkeypatch.setattr(taskboard, "link_skill", lambda name: None) - monkeypatch.setattr(taskboard, "unlink_skill", lambda name: None) - monkeypatch.setattr(taskboard, "remove_skill_from_disk", lambda name: None) - - TaskAPIHandler.db = db - TaskAPIHandler.scheduler = scheduler - TaskAPIHandler.feishu_channel = None - TaskAPIHandler.telegram_channel = None - TaskAPIHandler.slack_channel = None - TaskAPIHandler.weixin_channel = None - TaskAPIHandler.bus = None - TaskAPIHandler.ui_channel = None - - server = QuietHTTPServer(("127.0.0.1", 0), TaskAPIHandler) - port = server.server_address[1] - thread = threading.Thread(target=server.serve_forever, daemon=True) - thread.start() - - client = _Client(f"http://127.0.0.1:{port}", "127.0.0.1", port) - try: - yield client, db, scheduler - finally: - server.shutdown() - server.server_close() - thread.join(timeout=5) - TaskAPIHandler.feishu_channel = None - TaskAPIHandler.telegram_channel = None - TaskAPIHandler.slack_channel = None - TaskAPIHandler.weixin_channel = None - db.conn.close() - - -def _make_task(client, **overrides): - body = {"title": "T", "prompt": "go", "schedule_type": "delayed", "delay_seconds": 999} - body.update(overrides) - status, data = client.post("/api/tasks", body) - assert status == 201, data - return data["id"] - - -# ── channel restart branches (existing channel stopped + new one started) ──── -def test_feishu_settings_restart_stops_old_and_starts_new(api, monkeypatch): - client, db, _ = api - old = mock.Mock(name="old_feishu") - TaskAPIHandler.feishu_channel = old - - new_inst = mock.Mock(name="new_feishu") - monkeypatch.setattr(taskboard, "FEISHU_CHANNEL_AVAILABLE", True) - monkeypatch.setattr(taskboard, "FeishuChannel", mock.Mock(return_value=new_inst)) - - status, data = client.post( - "/api/feishu/settings", - {"feishu_app_id": "cli_x", "feishu_app_secret": "sek", "feishu_enabled": "true"}, - ) - assert status == 200 - old.stop.assert_called_once() # existing channel stopped - new_inst.start.assert_called_once() # new channel started - assert TaskAPIHandler.feishu_channel is new_inst - assert db.get_setting("feishu_app_id") == "cli_x" - - -def test_channels_settings_restart_all_three(api, monkeypatch): - client, db, _ = api - old_tg = mock.Mock(name="old_tg") - old_sl = mock.Mock(name="old_sl") - old_wx = mock.Mock(name="old_wx") - TaskAPIHandler.telegram_channel = old_tg - TaskAPIHandler.slack_channel = old_sl - TaskAPIHandler.weixin_channel = old_wx - - tg_inst = mock.Mock(name="tg_inst") - sl_inst = mock.Mock(name="sl_inst") - wx_inst = mock.Mock(name="wx_inst") - monkeypatch.setattr(taskboard, "TELEGRAM_CHANNEL_AVAILABLE", True) - monkeypatch.setattr(taskboard, "SLACK_CHANNEL_AVAILABLE", True) - monkeypatch.setattr(taskboard, "WEIXIN_CHANNEL_AVAILABLE", True) - monkeypatch.setattr(taskboard, "create_telegram_channel", mock.Mock(return_value=tg_inst)) - monkeypatch.setattr(taskboard, "SlackChannel", mock.Mock(return_value=sl_inst)) - monkeypatch.setattr(taskboard, "WeixinChannel", mock.Mock(return_value=wx_inst)) - - status, data = client.post( - "/api/channels/settings", - { - "telegram_bot_token": "tg-tok", - "telegram_enabled": "true", - "slack_bot_token": "sl-bot", - "slack_app_token": "sl-app", - "slack_enabled": "true", - "weixin_enabled": "true", - }, - ) - assert status == 200 - old_tg.stop.assert_called_once() - old_sl.stop.assert_called_once() - old_wx.stop.assert_called_once() - tg_inst.start.assert_called_once() - sl_inst.start.assert_called_once() - wx_inst.start.assert_called_once() - assert TaskAPIHandler.telegram_channel is tg_inst - assert TaskAPIHandler.slack_channel is sl_inst - assert TaskAPIHandler.weixin_channel is wx_inst - - -def test_telegram_restart_factory_returns_none(api, monkeypatch): - """Telegram enabled with a token but the factory declines → no start, ref - stays None (covers the 'else: failed to create' branch).""" - client, db, _ = api - monkeypatch.setattr(taskboard, "TELEGRAM_CHANNEL_AVAILABLE", True) - monkeypatch.setattr(taskboard, "create_telegram_channel", mock.Mock(return_value=None)) - status, data = client.post( - "/api/channels/settings", - {"telegram_bot_token": "tok", "telegram_enabled": "true"}, - ) - assert status == 200 - assert TaskAPIHandler.telegram_channel is None - - -# ── DAG prompt_images JSON-string fallback ────────────────────────────────── -def test_create_dag_prompt_images_json_string(api): - client, db, _ = api - status, data = client.post( - "/api/dag", - { - "dag_id": "imgdag", - "tasks": [ - { - "ref": "a", - "prompt": "first", - "schedule_type": "immediate", - "prompt_images": json.dumps([{"media_type": "image/png", "data": "AAA"}]), - } - ], - }, - ) - assert status == 201 - tid = data["task_ids"]["a"] - assert db.get_task(tid)["prompt_images"] == [{"media_type": "image/png", "data": "AAA"}] - - -def test_create_dag_prompt_images_bad_json_falls_back(api): - client, db, _ = api - status, data = client.post( - "/api/dag", - { - "tasks": [ - { - "ref": "a", - "prompt": "x", - "schedule_type": "immediate", - "prompt_images": "{not json", - } - ] - }, - ) - assert status == 201 - tid = data["task_ids"]["a"] - assert db.get_task(tid)["prompt_images"] == [] - - -# ── /resume not-found branch ──────────────────────────────────────────────── -def test_task_resume_not_found(api): - client, _, _ = api - status, data = client.post("/api/tasks/99999/resume", {"message": "go"}) - assert status == 404 - assert data["error"] == "not found" - - -# ── DELETE CSRF rejection ─────────────────────────────────────────────────── -def test_delete_csrf_rejected(api): - client, db, _ = api - tid = _make_task(client) - status, data = client.delete( - f"/api/tasks/{tid}", - headers={"Origin": "http://localhost:5173", "X-CSRF-Token": "wrong"}, - ) - assert status == 403 - assert "CSRF" in data["error"] - # Task not deleted because the request was rejected before the handler ran. - assert db.get_task(tid) is not None - - -def test_delete_csrf_accepted_with_token(api): - client, db, _ = api - tid = _make_task(client) - status, data = client.delete( - f"/api/tasks/{tid}", - headers={ - "Origin": "http://localhost:5173", - "X-CSRF-Token": taskboard._CSRF_TOKEN, - }, - ) - assert status == 200 - assert data["status"] == "deleted" - assert db.get_task(tid) is None - - -# ── request body too large → 413 ──────────────────────────────────────────── -def test_post_body_too_large_returns_413(api, monkeypatch): - client, _, _ = api - # Shrink the cap so we don't have to send 10 MB over the wire. - monkeypatch.setattr(TaskAPIHandler, "MAX_BODY_SIZE", 16) - status, data = client.post("/api/tasks", {"prompt": "x" * 200, "schedule_type": "immediate"}) - assert status == 413 - assert "too large" in data["error"] - - -def test_read_body_too_large_drains_declared_body(monkeypatch): - handler = object.__new__(TaskAPIHandler) - handler.headers = {"Content-Length": "32"} - handler.rfile = io.BytesIO(b"x" * 32) - handler.MAX_BODY_SIZE = 16 - responses = [] - monkeypatch.setattr( - handler, "_json_response", lambda data, status=200: responses.append((data, status)) - ) - - assert handler._read_body() is None - assert handler.rfile.read() == b"" - assert responses == [({"error": "request body too large"}, 413)] diff --git a/tests/test_taskdb.py b/tests/test_taskdb.py deleted file mode 100644 index 36f81bc..0000000 --- a/tests/test_taskdb.py +++ /dev/null @@ -1,333 +0,0 @@ -"""Direct unit tests for TaskDB internals not exercised by HTTP CRUD tests. - -Covers: settings, run history, output events, completed-run queries used by the -skill sweep, skill_patterns ledger (idempotent recurrence counting), draft -upsert/clear, candidate refresh windowing, dependency rows, and cascading -delete. Constructs TaskDB directly against a tmp_path SQLite file. -""" - -import json -from datetime import datetime, timedelta - -from taskboard import ScheduleType, Task, TaskDB - - -def make_db(tmp_path): - return TaskDB(str(tmp_path / "taskdb-test.db")) - - -# ── settings ──────────────────────────────────────────────────────────────── -def test_settings_get_default_and_set_overwrite(tmp_path): - db = make_db(tmp_path) - assert db.get_setting("missing") is None - assert db.get_setting("missing", "fallback") == "fallback" - db.set_setting("k", "v1") - assert db.get_setting("k") == "v1" - db.set_setting("k", "v2") # INSERT OR REPLACE - assert db.get_setting("k") == "v2" - - -# ── run history ───────────────────────────────────────────────────────────── -def test_run_lifecycle_and_ordering(tmp_path): - db = make_db(tmp_path) - tid = db.add_task(Task(title="t", prompt="p", working_dir=".")) - run1 = db.add_run(tid) - db.finish_run(run1, status="completed", result="ok", raw_output="raw1") - run2 = db.add_run(tid) - db.finish_run(run2, status="failed", error="boom") - - runs = db.get_task_runs(tid) - assert {r["status"] for r in runs} == {"completed", "failed"} - assert {r["id"] for r in runs} == {run1, run2} - completed = next(r for r in runs if r["id"] == run1) - assert completed["result"] == "ok" - assert completed["raw_output"] == "raw1" - assert completed["finished_at"] is not None - - -def test_finish_run_and_update_task_is_atomic(tmp_path): - db = make_db(tmp_path) - tid = db.add_task(Task(title="t", prompt="p", working_dir=".")) - rid = db.add_run(tid) - - db.finish_run_and_update_task( - rid, - run_status="completed", - task_id=tid, - task_updates={"status": "completed", "result": "done", "run_count": 1}, - run_result="done", - ) - - run = db.get_task_runs(tid)[0] - assert run["status"] == "completed" - assert run["result"] == "done" - task = db.get_task(tid) - assert task["status"] == "completed" - assert task["result"] == "done" - assert task["run_count"] == 1 - - -# ── output events ─────────────────────────────────────────────────────────── -def test_output_events_per_task_and_per_run(tmp_path): - db = make_db(tmp_path) - tid = db.add_task(Task(title="t", prompt="p", working_dir=".")) - run1 = db.add_run(tid) - run2 = db.add_run(tid) - db.add_output_event(tid, run1, "assistant", "hello") - db.add_output_event(tid, run1, "result", "done") - db.add_output_event(tid, run2, "assistant", "second run") - - all_events = db.get_output_events(tid) - assert len(all_events) == 3 - - # offset/limit paging (events ordered DESC by timestamp) - page = db.get_output_events(tid, limit=1, offset=0) - assert len(page) == 1 - - run1_events = db.get_run_output_events(run1) - assert [e["content"] for e in run1_events] == ["hello", "done"] # ASC order - run2_events = db.get_run_output_events(run2) - assert [e["content"] for e in run2_events] == ["second run"] - - -# ── completed-run queries (skill sweep inputs) ────────────────────────────── -def _finish_with_timestamp(db, run_id, finished_at): - db.conn.execute( - "UPDATE task_runs SET status='completed', finished_at=? WHERE id=?", - (finished_at, run_id), - ) - db.conn.commit() - - -def test_get_completed_runs_since_watermark(tmp_path): - db = make_db(tmp_path) - tid = db.add_task(Task(title="t", prompt="p", working_dir=".")) - old = db.add_run(tid) - new = db.add_run(tid) - _finish_with_timestamp(db, old, "2020-01-01T00:00:00") - _finish_with_timestamp(db, new, "2025-01-01T00:00:00") - - after = db.get_completed_runs_since("2023-01-01T00:00:00") - assert [r["run_id"] for r in after] == [new] - # joined task metadata is present - assert after[0]["title"] == "t" - assert after[0]["prompt"] == "p" - - everything = db.get_completed_runs_since("") - assert [r["run_id"] for r in everything] == [old, new] # oldest first - - -def test_get_recent_completed_runs_oldest_first_with_limit(tmp_path): - db = make_db(tmp_path) - tid = db.add_task(Task(title="t", prompt="p", working_dir=".")) - r1 = db.add_run(tid) - r2 = db.add_run(tid) - r3 = db.add_run(tid) - _finish_with_timestamp(db, r1, "2024-01-01T00:00:00") - _finish_with_timestamp(db, r2, "2024-01-02T00:00:00") - _finish_with_timestamp(db, r3, "2024-01-03T00:00:00") - - recent = db.get_recent_completed_runs(limit=2) - # picks the 2 newest, returns them oldest-first - assert [r["run_id"] for r in recent] == [r2, r3] - - -# ── skill_patterns ledger ─────────────────────────────────────────────────── -def test_upsert_skill_pattern_blank_key_returns_none(tmp_path): - db = make_db(tmp_path) - assert db.upsert_skill_pattern(" ", "recipe", "s", 1) is None - - -def test_upsert_skill_pattern_idempotent_per_run(tmp_path): - db = make_db(tmp_path) - pid = db.upsert_skill_pattern("k", "recipe", "first", 1, run_id=10) - assert db.get_skill_pattern_recurrence("k") == 1 - - # same run_id again → no recurrence bump, but summary refreshes - same = db.upsert_skill_pattern("k", "recipe", "updated", 1, run_id=10) - assert same == pid - assert db.get_skill_pattern_recurrence("k") == 1 - assert db.get_skill_pattern(pid)["summary"] == "updated" - - # new run_id → recurrence bumps and task list grows - db.upsert_skill_pattern("k", "recipe", "", 2, run_id=11) - assert db.get_skill_pattern_recurrence("k") == 2 - pattern = db.get_skill_pattern(pid) - assert sorted(json.loads(pattern["contributing_task_ids"])) == [1, 2] - assert sorted(json.loads(pattern["contributing_run_ids"])) == [10, 11] - # empty summary must NOT clobber the prior one - assert pattern["summary"] == "updated" - - -def test_upsert_skill_pattern_no_run_id_bumps_each_call(tmp_path): - db = make_db(tmp_path) - db.upsert_skill_pattern("legacy", "recipe", "s", 1) - db.upsert_skill_pattern("legacy", "recipe", "s", 1) - assert db.get_skill_pattern_recurrence("legacy") == 2 - - -def test_upsert_skill_pattern_invalid_kind_falls_back(tmp_path): - db = make_db(tmp_path) - pid = db.upsert_skill_pattern("k", "nonsense-kind", "s", 1) - assert db.get_skill_pattern(pid)["kind"] == "recipe" - - -def test_get_skill_pattern_recurrence_unknown_is_zero(tmp_path): - db = make_db(tmp_path) - assert db.get_skill_pattern_recurrence("does-not-exist") == 0 - assert db.get_skill_pattern_recurrence("") == 0 - - -def test_within_window(tmp_path): - db = make_db(tmp_path) - first = "2024-01-01T00:00:00" - inside = "2024-01-20T00:00:00" - outside = "2024-03-01T00:00:00" - assert db._within_window(first, inside, 30) is True - assert db._within_window(first, outside, 30) is False - # unparseable timestamps don't block promotion - assert db._within_window("garbage", "garbage", 30) is True - - -def test_set_skill_pattern_status_with_promoted_id(tmp_path): - db = make_db(tmp_path) - pid = db.upsert_skill_pattern("k", "recipe", "s", 1) - db.set_skill_pattern_status(pid, "promoted", promoted_skill_id=42) - row = db.get_skill_pattern(pid) - assert row["status"] == "promoted" - assert row["promoted_skill_id"] == 42 - - -# ── skill drafts ──────────────────────────────────────────────────────────── -def test_skill_draft_upsert_conflict_and_delete(tmp_path): - db = make_db(tmp_path) - pid = db.upsert_skill_pattern("k", "recipe", "s", 1) - db.upsert_skill_draft(pid, "drafting", kind="recipe") - assert db.get_skill_draft(pid)["status"] == "drafting" - - # ON CONFLICT(pattern_id) updates in place - db.upsert_skill_draft( - pid, "ready", name="my-skill", body="b", worthy=True, worthiness_reason="reusable" - ) - draft = db.get_skill_draft(pid) - assert draft["status"] == "ready" - assert draft["name"] == "my-skill" - assert draft["worthy"] == 1 - - db.delete_skill_draft(pid) - assert db.get_skill_draft(pid) is None - - -def test_skill_draft_worthy_none_stored_as_null(tmp_path): - db = make_db(tmp_path) - pid = db.upsert_skill_pattern("k", "recipe", "s", 1) - db.upsert_skill_draft(pid, "ready", worthy=None) - assert db.get_skill_draft(pid)["worthy"] is None - - -# ── dependencies / DAG ────────────────────────────────────────────────────── -def test_dependency_crud_and_views(tmp_path): - db = make_db(tmp_path) - up = db.add_task(Task(title="up", prompt="p", working_dir=".")) - down = db.add_task(Task(title="down", prompt="p", working_dir=".")) - - db.add_dependency(down, up, inject_result=True) - # duplicate insert is ignored - db.add_dependency(down, up, inject_result=True) - - deps = db.get_dependencies(down) - assert len(deps) == 1 - assert deps[0]["depends_on_task_id"] == up - assert deps[0]["depends_on_title"] == "up" - assert deps[0]["inject_result"] == 1 - - dependents = db.get_dependents(up) - assert len(dependents) == 1 - assert dependents[0]["task_id"] == down - assert dependents[0]["task_title"] == "down" - - db.remove_dependency(down, up) - assert db.get_dependencies(down) == [] - - -def test_add_dependencies_batch_and_clear(tmp_path): - db = make_db(tmp_path) - a = db.add_task(Task(title="a", prompt="p", working_dir=".")) - b = db.add_task(Task(title="b", prompt="p", working_dir=".")) - down = db.add_task(Task(title="d", prompt="p", working_dir=".")) - - db.add_dependencies_batch( - down, - [{"task_id": a, "inject_result": True}, {"task_id": b, "inject_result": False}], - ) - deps = db.get_dependencies(down) - assert {d["depends_on_task_id"] for d in deps} == {a, b} - - db.clear_dependencies(down) - assert db.get_dependencies(down) == [] - - -def test_get_dag_tasks_filters_by_dag_id(tmp_path): - db = make_db(tmp_path) - db.add_task(Task(title="x", prompt="p", working_dir=".", dag_id="flow-1")) - db.add_task(Task(title="y", prompt="p", working_dir=".", dag_id="flow-1")) - db.add_task(Task(title="z", prompt="p", working_dir=".", dag_id="other")) - - flow = db.get_dag_tasks("flow-1") - assert {t["title"] for t in flow} == {"x", "y"} - - -# ── cascading delete ──────────────────────────────────────────────────────── -def test_delete_task_removes_runs_events_and_deps(tmp_path): - db = make_db(tmp_path) - up = db.add_task(Task(title="up", prompt="p", working_dir=".")) - tid = db.add_task(Task(title="t", prompt="p", working_dir=".")) - db.add_dependency(tid, up) - rid = db.add_run(tid) - db.add_output_event(tid, rid, "assistant", "hi") - - db.delete_task(tid) - - assert db.get_task(tid) is None - assert db.get_task_runs(tid) == [] - assert db.get_output_events(tid) == [] - # the dependency row referencing the deleted task is gone too - assert db.get_dependents(up) == [] - - -# ── due-task selection ────────────────────────────────────────────────────── -def test_get_due_tasks_selects_only_ready(tmp_path): - db = make_db(tmp_path) - now = datetime.now() - past = (now - timedelta(minutes=5)).isoformat() - future = (now + timedelta(hours=1)).isoformat() - - immediate = db.add_task(Task(title="now", prompt="p", working_dir=".")) - due_scheduled = db.add_task( - Task( - title="due", - prompt="p", - working_dir=".", - schedule_type=ScheduleType.SCHEDULED_AT, - next_run_at=past, - ) - ) - db.update_task(due_scheduled, status="scheduled") - not_yet = db.add_task( - Task( - title="later", - prompt="p", - working_dir=".", - schedule_type=ScheduleType.SCHEDULED_AT, - next_run_at=future, - ) - ) - db.update_task(not_yet, status="scheduled") - running = db.add_task(Task(title="running", prompt="p", working_dir=".")) - db.update_task(running, status="running") - - due_ids = {t["id"] for t in db.get_due_tasks()} - assert immediate in due_ids # pending + no next_run_at - assert due_scheduled in due_ids # scheduled in the past - assert not_yet not in due_ids # future - assert running not in due_ids # not pending/scheduled diff --git a/tests/test_telegram_channel.py b/tests/test_telegram_channel.py deleted file mode 100644 index 1829a1f..0000000 --- a/tests/test_telegram_channel.py +++ /dev/null @@ -1,580 +0,0 @@ -import asyncio -from types import SimpleNamespace -from unittest.mock import AsyncMock, MagicMock, patch - -from taskboard_bus import MessageBus, OutboundMessage, OutboundMessageType - - -class StubDB: - def __init__(self): - self.settings = {} - self.tasks = {} - self.updated = [] - - def get_setting(self, key, default=None): - return self.settings.get(key, default) - - def set_setting(self, key, value): - self.settings[key] = value - - def get_task(self, task_id): - return self.tasks.get(task_id) - - def update_task(self, task_id, **updates): - self.updated.append((task_id, updates)) - self.tasks.setdefault(task_id, {"id": task_id}).update(updates) - - -class StubScheduler: - def __init__(self): - self.submitted = [] - - def submit_task(self, task): - self.submitted.append(task) - return len(self.submitted) - - -def _make_channel(db=None, scheduler=None, allowed_users=None): - from channels.telegram_channel import TelegramChannel - - channel = TelegramChannel( - bus=MessageBus(), - db=db or StubDB(), - scheduler=scheduler or StubScheduler(), - token="123:ABC", - allowed_users=allowed_users, - ) - # Give it a fake app/loop so async helpers can run without a real bot. - channel._app = MagicMock() - channel._app.bot = AsyncMock() - channel._loop = MagicMock() - return channel - - -def _fake_update(text="hello", user_id=1, chat_id=10, message_id=100, reply=None): - message = SimpleNamespace( - text=text, - message_id=message_id, - reply_to_message=reply, - forward_from=None, - forward_from_chat=None, - forward_date=None, - reply_text=AsyncMock(), - ) - return SimpleNamespace( - message=message, - effective_user=SimpleNamespace(id=user_id), - effective_chat=SimpleNamespace(id=chat_id), - ) - - -def _ctx(args=None): - return SimpleNamespace(args=args or []) - - -def _consume_coro(coro, loop=None): - """Drain a coroutine scheduled via run_coroutine_threadsafe to avoid warnings.""" - coro.close() - return MagicMock() - - -# ── construction / factory ─────────────────────────────────────── - - -def test_init_sets_allowed_users(): - channel = _make_channel(allowed_users=[1, 2]) - assert channel._allowed_users == {1, 2} - assert channel.name == "telegram" - assert channel._on_outbound in channel.bus._outbound_listeners - - -def test_create_telegram_channel_no_token_returns_none(monkeypatch): - from channels.telegram_channel import create_telegram_channel - - monkeypatch.delenv("TELEGRAM_BOT_TOKEN", raising=False) - assert create_telegram_channel(StubDB(), StubScheduler(), token="") is None - - -def test_create_telegram_channel_parses_allowed_users(): - from channels.telegram_channel import create_telegram_channel - - channel = create_telegram_channel( - StubDB(), - StubScheduler(), - token="123:ABC", - allowed_users_str="10, 20 , bad, 30", - ) - assert channel is not None - assert channel._allowed_users == {10, 20, 30} - - -def test_create_telegram_channel_empty_allowed_users(): - from channels.telegram_channel import create_telegram_channel - - channel = create_telegram_channel( - StubDB(), StubScheduler(), token="123:ABC", allowed_users_str="" - ) - assert channel._allowed_users == set() - - -def test_create_telegram_channel_from_env(monkeypatch): - from channels.telegram_channel import create_telegram_channel - - monkeypatch.setenv("TELEGRAM_BOT_TOKEN", "999:ZZZ") - monkeypatch.setenv("TELEGRAM_ALLOWED_USERS", "5,6") - channel = create_telegram_channel(StubDB(), StubScheduler()) - assert channel is not None - assert channel._token == "999:ZZZ" - assert channel._allowed_users == {5, 6} - - -def test_create_telegram_channel_makes_bus_when_none(): - from channels.telegram_channel import create_telegram_channel - - channel = create_telegram_channel(StubDB(), StubScheduler(), token="123:ABC") - assert channel.bus is not None - - -# ── allowed-user check ─────────────────────────────────────────── - - -def test_is_allowed(): - open_channel = _make_channel() - assert open_channel._is_allowed(999) is True # no allowlist → all allowed - - restricted = _make_channel(allowed_users=[42]) - assert restricted._is_allowed(42) is True - assert restricted._is_allowed(7) is False - - -# ── escape helper ──────────────────────────────────────────────── - - -def test_escape_md(): - from channels.telegram_channel import _escape_md - - assert _escape_md("a.b-c!") == "a\\.b\\-c\\!" - assert _escape_md("plain") == "plain" - - -# ── forwarded-message formatting ───────────────────────────────── - - -def test_format_forwarded_not_forwarded_returns_text(): - channel = _make_channel() - update = _fake_update(text="just text") - assert channel._format_forwarded_text("just text", update) == "just text" - - -def test_format_forwarded_from_user_with_username(): - channel = _make_channel() - update = _fake_update() - update.message.forward_from = SimpleNamespace( - username="alice", first_name="Alice", last_name=None - ) - update.message.forward_date = 1700000000 - out = channel._format_forwarded_text("body", update) - assert "📨 [转发消息]" in out - assert "转发自: @alice" in out - assert "--- 转发内容 ---" in out - assert out.endswith("body") - assert "时间:" in out - - -def test_format_forwarded_from_user_without_username(): - channel = _make_channel() - update = _fake_update() - update.message.forward_from = SimpleNamespace(username=None, first_name="Bob", last_name="Lee") - update.message.forward_date = None - out = channel._format_forwarded_text("body", update) - assert "转发自: Bob Lee" in out - - -def test_format_forwarded_from_channel_chat(): - channel = _make_channel() - update = _fake_update() - update.message.forward_from = None - update.message.forward_date = 1700000000 - update.message.forward_from_chat = SimpleNamespace( - title="News", username="news", type="channel" - ) - out = channel._format_forwarded_text("body", update) - assert "转发自频道: News" in out - - -def test_format_forwarded_from_group_chat(): - channel = _make_channel() - update = _fake_update() - update.message.forward_from = None - update.message.forward_date = 1700000000 - update.message.forward_from_chat = SimpleNamespace( - title="Devs", username=None, type="supergroup" - ) - out = channel._format_forwarded_text("body", update) - assert "转发自群组: Devs" in out - - -# ── text message handler ───────────────────────────────────────── - - -def test_handle_text_message_unauthorised(): - channel = _make_channel(allowed_users=[42]) - update = _fake_update(user_id=7) - asyncio.run(channel._handle_text_message(update, _ctx())) - update.message.reply_text.assert_awaited_once() - assert "not authorised" in update.message.reply_text.call_args.args[0] - - -def test_handle_text_message_empty_ignored(): - channel = _make_channel() - update = _fake_update(text=" ") - asyncio.run(channel._handle_text_message(update, _ctx())) - assert len(channel.scheduler.submitted) == 0 - update.message.reply_text.assert_not_awaited() - - -def test_handle_text_message_dir_command(): - db = StubDB() - channel = _make_channel(db=db) - update = _fake_update(text="/dir ~/proj") - asyncio.run(channel._handle_text_message(update, _ctx())) - assert db.get_setting("telegram_default_working_dir") == "~/proj" - update.message.reply_text.assert_awaited_once() - - -def test_handle_text_message_agent_command(): - db = StubDB() - channel = _make_channel(db=db) - update = _fake_update(text="/agent codex") - asyncio.run(channel._handle_text_message(update, _ctx())) - assert db.get_setting("default_agent") == "codex" - - -def test_handle_text_message_creates_task(): - db = StubDB() - scheduler = StubScheduler() - channel = _make_channel(db=db, scheduler=scheduler) - update = _fake_update(text="fix the bug") - with ( - patch("channels.dir_utils.resolve_working_dir", return_value="~/app"), - patch("asyncio.run_coroutine_threadsafe", side_effect=_consume_coro), - ): - asyncio.run(channel._handle_text_message(update, _ctx())) - assert len(scheduler.submitted) == 1 - task = scheduler.submitted[0] - assert task.prompt == "fix the bug" - assert task.title == "[Telegram] fix the bug" - assert task.tags == "telegram" - assert task.working_dir == "~/app" - assert channel._task_origin[1] == (10, 100, 100) - - -def test_handle_text_message_resume_by_reply(): - db = StubDB() - db.tasks[5] = {"id": 5, "status": "completed", "session_id": "s5"} - channel = _make_channel(db=db) - channel._notification_map[200] = 5 - reply = SimpleNamespace(message_id=200) - update = _fake_update(text="continue", message_id=300, reply=reply) - asyncio.run(channel._handle_text_message(update, _ctx())) - assert db.updated[-1][0] == 5 - assert db.updated[-1][1]["prompt"] == "continue" - assert channel._task_origin[5] == (10, 300, 300) - channel._app.bot.set_message_reaction.assert_awaited() - update.message.reply_text.assert_awaited_with("▶️") - - -def test_handle_text_message_resume_no_session(): - db = StubDB() - db.tasks[6] = {"id": 6, "status": "completed"} # no session_id - channel = _make_channel(db=db) - channel._notification_map[201] = 6 - reply = SimpleNamespace(message_id=201) - update = _fake_update(text="continue", reply=reply) - asyncio.run(channel._handle_text_message(update, _ctx())) - assert db.updated == [] - assert "no saved session" in update.message.reply_text.call_args.args[0] - - -def test_handle_text_message_reply_unknown_notification_creates_task(): - db = StubDB() - scheduler = StubScheduler() - channel = _make_channel(db=db, scheduler=scheduler) - reply = SimpleNamespace(message_id=12345) # not in notification_map - update = _fake_update(text="new task", reply=reply) - with ( - patch("channels.dir_utils.resolve_working_dir", return_value="~"), - patch("asyncio.run_coroutine_threadsafe", side_effect=_consume_coro), - ): - asyncio.run(channel._handle_text_message(update, _ctx())) - assert len(scheduler.submitted) == 1 - - -def test_create_task_forwarded_tags(): - db = StubDB() - scheduler = StubScheduler() - channel = _make_channel(db=db, scheduler=scheduler) - update = _fake_update(text="forwarded body") - update.message.forward_date = 1700000000 - with ( - patch("channels.dir_utils.resolve_working_dir", return_value="~"), - patch("asyncio.run_coroutine_threadsafe", side_effect=_consume_coro), - ): - channel._create_task("forwarded body", 10, update) - task = scheduler.submitted[0] - assert "forwarded" in task.tags - assert task.title.startswith("[Telegram] 📨") - - -# ── command handlers ───────────────────────────────────────────── - - -def test_cmd_help_authorised_and_not(): - channel = _make_channel(allowed_users=[1]) - ok = _fake_update(user_id=1) - asyncio.run(channel._cmd_help(ok, _ctx())) - ok.message.reply_text.assert_awaited_once() - - denied = _fake_update(user_id=99) - asyncio.run(channel._cmd_help(denied, _ctx())) - assert "not authorised" in denied.message.reply_text.call_args.args[0] - - -def test_cmd_status_usage_and_not_found(): - db = StubDB() - channel = _make_channel(db=db) - u = _fake_update() - asyncio.run(channel._cmd_status(u, _ctx(args=[]))) - assert "Usage" in u.message.reply_text.call_args.args[0] - - u2 = _fake_update() - asyncio.run(channel._cmd_status(u2, _ctx(args=["99"]))) - assert "not found" in u2.message.reply_text.call_args.args[0] - - -def test_cmd_status_renders(): - db = StubDB() - db.tasks[7] = { - "id": 7, - "title": "Build it", - "status": "completed", - "created_at": "2026-01-01T10:00:00", - "last_run_at": "2026-01-02T11:00:00", - "result": "green", - "error": None, - } - channel = _make_channel(db=db) - u = _fake_update() - asyncio.run(channel._cmd_status(u, _ctx(args=["#7"]))) - text = u.message.reply_text.call_args.args[0] - assert "✅" in text - assert "Task #7" in text - assert "green" in text - - -def test_cmd_status_unauthorised(): - channel = _make_channel(allowed_users=[1]) - u = _fake_update(user_id=2) - asyncio.run(channel._cmd_status(u, _ctx(args=["1"]))) - assert "Not authorised" in u.message.reply_text.call_args.args[0] - - -def test_cmd_cancel_paths(): - db = StubDB() - db.tasks[1] = {"id": 1, "title": "t", "status": "running"} - db.tasks[2] = {"id": 2, "title": "t", "status": "completed"} - channel = _make_channel(db=db) - - u = _fake_update() - asyncio.run(channel._cmd_cancel(u, _ctx(args=[]))) - assert "Usage" in u.message.reply_text.call_args.args[0] - - u = _fake_update() - asyncio.run(channel._cmd_cancel(u, _ctx(args=["99"]))) - assert "not found" in u.message.reply_text.call_args.args[0] - - u = _fake_update() - asyncio.run(channel._cmd_cancel(u, _ctx(args=["2"]))) - assert "already" in u.message.reply_text.call_args.args[0] - - u = _fake_update() - asyncio.run(channel._cmd_cancel(u, _ctx(args=["1"]))) - assert db.updated[-1] == (1, {"status": "cancelled"}) - assert "cancelled" in u.message.reply_text.call_args.args[0] - - -def test_cmd_resume_paths(): - db = StubDB() - db.tasks[1] = {"id": 1, "title": "t", "status": "completed", "session_id": "s1"} - db.tasks[2] = {"id": 2, "title": "t", "status": "completed"} - channel = _make_channel(db=db) - - u = _fake_update() - asyncio.run(channel._cmd_resume(u, _ctx(args=[]))) - assert "Usage" in u.message.reply_text.call_args.args[0] - - u = _fake_update() - asyncio.run(channel._cmd_resume(u, _ctx(args=["1"]))) - assert "provide a message" in u.message.reply_text.call_args.args[0] - - u = _fake_update() - asyncio.run(channel._cmd_resume(u, _ctx(args=["2", "go"]))) - assert "no saved session" in u.message.reply_text.call_args.args[0] - - u = _fake_update(message_id=555) - asyncio.run(channel._cmd_resume(u, _ctx(args=["#1", "keep", "going"]))) - assert db.updated[-1][0] == 1 - assert db.updated[-1][1]["prompt"] == "keep going" - assert channel._task_origin[1] == (10, 555, 555) - u.message.reply_text.assert_awaited_with("▶️") - - -def test_cmd_resume_unauthorised(): - channel = _make_channel(allowed_users=[1]) - u = _fake_update(user_id=2) - asyncio.run(channel._cmd_resume(u, _ctx(args=["1", "x"]))) - assert "Not authorised" in u.message.reply_text.call_args.args[0] - - -# ── outbound send ──────────────────────────────────────────────── - - -def _patch_loop(channel): - channel._loop_ready.set() - channel._running = True - - -def test_send_completion_to_origin(): - db = StubDB() - channel = _make_channel(db=db) - _patch_loop(channel) - channel._task_origin[3] = (10, 100, 100) - - with patch("asyncio.run_coroutine_threadsafe") as rct: - channel.send( - OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, - task_id=3, - payload={"title": "Fix login", "result": "done"}, - ) - ) - coro = rct.call_args.args[0] - sent = SimpleNamespace(message_id=777) - channel._app.bot.send_message = AsyncMock(return_value=sent) - asyncio.run(coro) - - channel._app.bot.send_message.assert_awaited_once() - call = channel._app.bot.send_message.call_args - assert "✅ Task #3: Fix login" in call.kwargs["text"] - assert "done" in call.kwargs["text"] - assert channel._notification_map[777] == 3 - assert 3 not in channel._task_origin - - -def test_send_failure_to_origin(): - db = StubDB() - channel = _make_channel(db=db) - _patch_loop(channel) - channel._task_origin[4] = (10, 100, 100) - - with patch("asyncio.run_coroutine_threadsafe") as rct: - channel.send( - OutboundMessage( - type=OutboundMessageType.TASK_FAILED, - task_id=4, - payload={"title": "Broke", "error": "boom"}, - ) - ) - coro = rct.call_args.args[0] - channel._app.bot.send_message = AsyncMock(return_value=SimpleNamespace(message_id=1)) - asyncio.run(coro) - text = channel._app.bot.send_message.call_args.kwargs["text"] - assert "❌ Task #4: Broke" in text - assert "boom" in text - assert "/status 4" in text - - -def test_send_not_running_drops(): - channel = _make_channel() - channel._running = False - with patch("asyncio.run_coroutine_threadsafe") as rct: - channel.send( - OutboundMessage(type=OutboundMessageType.TASK_COMPLETED, task_id=1, payload={}) - ) - rct.assert_not_called() - - -def test_send_ignores_non_terminal(): - channel = _make_channel() - _patch_loop(channel) - with patch("asyncio.run_coroutine_threadsafe") as rct: - channel.send(OutboundMessage(type=OutboundMessageType.TASK_STARTED, task_id=1, payload={})) - rct.assert_not_called() - - -def test_send_uses_default_chat_id(): - db = StubDB() - db.settings["telegram_default_chat_id"] = "-100123" - channel = _make_channel(db=db) - _patch_loop(channel) - - with patch("asyncio.run_coroutine_threadsafe") as rct: - channel.send( - OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, - task_id=8, - payload={"title": "Job", "result": "ok"}, - ) - ) - coro = rct.call_args.args[0] - channel._app.bot.send_message = AsyncMock(return_value=SimpleNamespace(message_id=2)) - asyncio.run(coro) - assert channel._app.bot.send_message.call_args.kwargs["chat_id"] == -100123 - - -def test_send_no_origin_no_default_skips(): - db = StubDB() - channel = _make_channel(db=db) - _patch_loop(channel) - with patch("asyncio.run_coroutine_threadsafe") as rct: - channel.send( - OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, - task_id=9, - payload={"title": "Job", "result": "ok"}, - ) - ) - rct.assert_not_called() - - -def test_send_truncates_long_result(): - db = StubDB() - channel = _make_channel(db=db) - _patch_loop(channel) - channel._task_origin[10] = (10, 100, 100) - long = "x" * 20000 - - with patch("asyncio.run_coroutine_threadsafe") as rct: - channel.send( - OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, - task_id=10, - payload={"title": "Big", "result": long}, - ) - ) - coro = rct.call_args.args[0] - channel._app.bot.send_message = AsyncMock(return_value=SimpleNamespace(message_id=3)) - asyncio.run(coro) - assert "(truncated)" in channel._app.bot.send_message.call_args.kwargs["text"] - - -# ── lifecycle ──────────────────────────────────────────────────── - - -def test_start_without_telegram(monkeypatch, capsys): - from channels import telegram_channel - - monkeypatch.setattr(telegram_channel, "TELEGRAM_AVAILABLE", False) - channel = _make_channel() - channel.start() - assert "not installed" in capsys.readouterr().out diff --git a/tests/test_telegram_forwarded_messages.py b/tests/test_telegram_forwarded_messages.py deleted file mode 100644 index 574a6ac..0000000 --- a/tests/test_telegram_forwarded_messages.py +++ /dev/null @@ -1,503 +0,0 @@ -""" -Tests for Telegram forwarded message handling functionality. -""" - -from dataclasses import dataclass -from unittest.mock import Mock, patch - -import pytest - - -@pytest.fixture -def mock_telegram_channel(): - """Create a mock TelegramChannel instance for testing.""" - with patch("channels.telegram_channel.TELEGRAM_AVAILABLE", True): - from channels.telegram_channel import TelegramChannel - - bus = Mock() - db = Mock() - scheduler = Mock() - - channel = TelegramChannel( - bus=bus, db=db, scheduler=scheduler, token="fake_token", allowed_users=None - ) - - # Mock the app and loop - channel._app = Mock() - channel._loop = Mock() - channel._loop_ready = Mock() - channel._loop_ready.set() - - return channel - - -@dataclass -class MockUser: - """Mock Telegram User object.""" - - id: int - first_name: str - last_name: str = "" - username: str = "" - - def __getattr__(self, name): - # Return None for any attribute not defined - return None - - -@dataclass -class MockChat: - """Mock Telegram Chat object.""" - - id: int - type: str = "private" - title: str = "" - username: str = "" - - def __getattr__(self, name): - return None - - -@dataclass -class MockMessage: - """Mock Telegram Message object.""" - - message_id: int - text: str - from_user: MockUser - chat: MockChat - forward_from: MockUser = None - forward_from_chat: MockChat = None - forward_date: int = None - reply_to_message = None - - def __getattr__(self, name): - return None - - -class TestTelegramForwardMessageDetection: - """Test detection of forwarded messages in Telegram updates.""" - - def test_format_forwarded_text_from_user(self, mock_telegram_channel): - """Test formatting a message forwarded from a user.""" - forward_user = MockUser( - id=12345, first_name="Alice", last_name="Smith", username="alice_smith" - ) - - message = MockMessage( - message_id=100, - text="Original message content", - from_user=MockUser(id=999, first_name="Bob"), - chat=MockChat(id=888, type="private"), - forward_from=forward_user, - forward_date=1738080000, - ) - - update = Mock() - update.message = message - - result = mock_telegram_channel._format_forwarded_text("Original message content", update) - - assert "📨 [转发消息]" in result - assert "转发自: @alice_smith" in result - assert "时间: 2025-01-29 00:00" in result - assert "--- 转发内容 ---" in result - assert "Original message content" in result - - def test_format_forwarded_text_from_user_no_username(self, mock_telegram_channel): - """Test formatting when forwarded user has no username.""" - forward_user = MockUser(id=12345, first_name="张三", last_name="李四", username="") - - message = MockMessage( - message_id=100, - text="测试消息", - from_user=MockUser(id=999, first_name="王五"), - chat=MockChat(id=888, type="private"), - forward_from=forward_user, - forward_date=1738080000, - ) - - update = Mock() - update.message = message - - result = mock_telegram_channel._format_forwarded_text("测试消息", update) - - assert "转发自: 张三 李四" in result - - def test_format_forwarded_text_from_user_only_firstname(self, mock_telegram_channel): - """Test formatting when forwarded user has only first name.""" - forward_user = MockUser(id=12345, first_name="Charlie", last_name="", username="") - - message = MockMessage( - message_id=100, - text="Message", - from_user=MockUser(id=999, first_name="Dave"), - chat=MockChat(id=888, type="private"), - forward_from=forward_user, - forward_date=1738080000, - ) - - update = Mock() - update.message = message - - result = mock_telegram_channel._format_forwarded_text("Message", update) - - assert "转发自: Charlie" in result - - def test_format_forwarded_text_from_channel(self, mock_telegram_channel): - """Test formatting a message forwarded from a channel.""" - forward_chat = MockChat( - id=-100123456789, type="channel", title="Tech News", username="technews" - ) - - message = MockMessage( - message_id=100, - text="Breaking news: API update", - from_user=MockUser(id=999, first_name="Reader"), - chat=MockChat(id=888, type="private"), - forward_from_chat=forward_chat, - forward_date=1738083600, - ) - - update = Mock() - update.message = message - - result = mock_telegram_channel._format_forwarded_text("Breaking news: API update", update) - - assert "📨 [转发消息]" in result - assert "转发自频道: Tech News" in result - - def test_format_forwarded_text_from_group(self, mock_telegram_channel): - """Test formatting a message forwarded from a group.""" - forward_chat = MockChat( - id=-100987654321, type="supergroup", title="Python Developers", username="" - ) - - message = MockMessage( - message_id=100, - text="Check this code snippet", - from_user=MockUser(id=999, first_name="Dev"), - chat=MockChat(id=888, type="private"), - forward_from_chat=forward_chat, - forward_date=1738087200, - ) - - update = Mock() - update.message = message - - result = mock_telegram_channel._format_forwarded_text("Check this code snippet", update) - - assert "转发自群组: Python Developers" in result - - def test_format_forwarded_text_from_chat_no_title(self, mock_telegram_channel): - """Test formatting when forwarded chat has no title.""" - forward_chat = MockChat(id=-100111222333, type="group", title="", username="unknown_group") - - message = MockMessage( - message_id=100, - text="Message", - from_user=MockUser(id=999, first_name="User"), - chat=MockChat(id=888, type="private"), - forward_from_chat=forward_chat, - forward_date=1738080000, - ) - - update = Mock() - update.message = message - - result = mock_telegram_channel._format_forwarded_text("Message", update) - - assert "转发自群组: unknown_group" in result - - def test_format_forwarded_text_no_timestamp(self, mock_telegram_channel): - """Test formatting when forward_date is missing.""" - forward_user = MockUser(id=12345, first_name="Sender") - - message = MockMessage( - message_id=100, - text="Message", - from_user=MockUser(id=999, first_name="User"), - chat=MockChat(id=888, type="private"), - forward_from=forward_user, - forward_date=None, - ) - - update = Mock() - update.message = message - - result = mock_telegram_channel._format_forwarded_text("Message", update) - - assert "📨 [转发消息]" in result - assert "转发自:" in result - # Should not have time component - assert "时间:" not in result - - def test_format_forwarded_text_not_forwarded(self, mock_telegram_channel): - """Test that regular messages are unchanged.""" - message = MockMessage( - message_id=100, - text="Regular message", - from_user=MockUser(id=999, first_name="User"), - chat=MockChat(id=888, type="private"), - ) - - update = Mock() - update.message = message - - result = mock_telegram_channel._format_forwarded_text("Regular message", update) - - assert result == "Regular message" - assert "转发" not in result - - def test_format_forwarded_text_fallback_to_generic_sender(self, mock_telegram_channel): - """Test formatting when forwarded info is incomplete.""" - message = MockMessage( - message_id=100, - text="Message", - from_user=MockUser(id=999, first_name="User"), - chat=MockChat(id=888, type="private"), - forward_from=None, - forward_from_chat=None, - forward_date=1738080000, - ) - - update = Mock() - update.message = message - - # The message has forward_date but no forward_from or forward_from_chat - # This is technically possible in Telegram API - message.forward_date = 1738080000 - - result = mock_telegram_channel._format_forwarded_text("Message", update) - - # Should still show it's forwarded with timestamp - assert "📨 [转发消息]" in result - assert "时间: 2025-01-29 00:00" in result - - -class TestTelegramForwardedTaskCreation: - """Test task creation from forwarded messages.""" - - @patch("taskboard.Task") - @patch("taskboard.ScheduleType") - def test_create_task_from_forwarded_message( - self, mock_schedule_type, mock_task_class, mock_telegram_channel - ): - """Test that forwarded messages create tasks with appropriate tags.""" - forward_user = MockUser(id=12345, first_name="Alice", username="alice") - - message = MockMessage( - message_id=100, - text="Analyze this forwarded post", - from_user=MockUser(id=999, first_name="Bob"), - chat=MockChat(id=888, type="private"), - forward_from=forward_user, - forward_date=1738080000, - ) - - update = Mock() - update.message = message - - # Format the text first (as done in _handle_text_message) - formatted_text = mock_telegram_channel._format_forwarded_text(message.text, update) - - # Mock Task class - mock_task_instance = Mock() - mock_task_class.return_value = mock_task_instance - mock_telegram_channel.scheduler.submit_task.return_value = 123 - mock_telegram_channel.db.get_setting.return_value = "~" - - # Call _create_task - mock_telegram_channel._create_task(formatted_text, 888, update) - - # Verify Task was created with forwarded tag - mock_task_class.assert_called_once() - call_kwargs = mock_task_class.call_args[1] - assert ", forwarded" in call_kwargs["tags"] - assert "📨 " in call_kwargs["title"] - - @patch("taskboard.Task") - @patch("taskboard.ScheduleType") - def test_create_task_from_normal_message( - self, mock_schedule_type, mock_task_class, mock_telegram_channel - ): - """Test that normal messages create tasks without forwarded tag.""" - message = MockMessage( - message_id=100, - text="Regular task", - from_user=MockUser(id=999, first_name="Bob"), - chat=MockChat(id=888, type="private"), - ) - - update = Mock() - update.message = message - - # Mock Task class - mock_task_instance = Mock() - mock_task_class.return_value = mock_task_instance - mock_telegram_channel.scheduler.submit_task.return_value = 456 - mock_telegram_channel.db.get_setting.return_value = "~" - - # Call _create_task - mock_telegram_channel._create_task("Regular task", 888, update) - - # Verify Task was created without forwarded tag - mock_task_class.assert_called_once() - call_kwargs = mock_task_class.call_args[1] - assert call_kwargs["tags"] == "telegram" - assert "📨 " not in call_kwargs["title"] - - -class TestTelegramForwardedMessageScenarios: - """Test real-world scenarios of forwarded messages.""" - - def test_user_forwards_news_article(self, mock_telegram_channel): - """Simulate a user forwarding a news article from a channel.""" - forward_chat = MockChat(id=-100123456789, type="channel", title="Breaking News") - - message = MockMessage( - message_id=100, - text="Stock market hits all-time high amid tech rally...", - from_user=MockUser(id=999, first_name="Investor"), - chat=MockChat(id=888, type="private"), - forward_from_chat=forward_chat, - forward_date=1738080000, - ) - - update = Mock() - update.message = message - - result = mock_telegram_channel._format_forwarded_text(message.text, update) - - assert "转发自频道: Breaking News" in result - assert "Stock market hits all-time high" in result - - def test_user_forwards_another_users_code(self, mock_telegram_channel): - """Simulate forwarding code snippet from another user.""" - forward_user = MockUser(id=12345, first_name="Dev", username="cool_dev") - - message = MockMessage( - message_id=100, - text="```python\ndef hello():\n print('world')\n```", - from_user=MockUser(id=999, first_name="Learner"), - chat=MockChat(id=888, type="private"), - forward_from=forward_user, - forward_date=1738083600, - ) - - update = Mock() - update.message = message - - result = mock_telegram_channel._format_forwarded_text(message.text, update) - - assert "转发自: @cool_dev" in result - assert "def hello():" in result - - def test_forwarded_multiline_message(self, mock_telegram_channel): - """Test handling of forwarded messages with multiple lines.""" - forward_user = MockUser(id=12345, first_name="Announcer") - - text = """This is a forwarded message -with multiple lines -and some bullet points: -- Point 1 -- Point 2 -- Point 3""" - - message = MockMessage( - message_id=100, - text=text, - from_user=MockUser(id=999, first_name="Receiver"), - chat=MockChat(id=888, type="private"), - forward_from=forward_user, - forward_date=1738087200, - ) - - update = Mock() - update.message = message - - result = mock_telegram_channel._format_forwarded_text(text, update) - - assert "转发自: Announcer" in result - assert "--- 转发内容 ---" in result - assert "Point 1" in result - assert "Point 3" in result - - def test_empty_text_with_forward(self, mock_telegram_channel): - """Test when forwarded message has no text (e.g., media-only).""" - forward_user = MockUser(id=12345, first_name="Sender") - - message = MockMessage( - message_id=100, - text="", # Empty text, maybe just a photo - from_user=MockUser(id=999, first_name="User"), - chat=MockChat(id=888, type="private"), - forward_from=forward_user, - forward_date=1738080000, - ) - - update = Mock() - update.message = message - - result = mock_telegram_channel._format_forwarded_text("", update) - - assert "📨 [转发消息]" in result - assert "转发自: Sender" in result - assert "--- 转发内容 ---" in result - - -class TestTelegramForwardedMessageIntegration: - """Integration tests for the complete forwarded message flow.""" - - @patch("taskboard.Task") - @patch("taskboard.ScheduleType") - def test_complete_forwarded_message_flow( - self, mock_schedule_type, mock_task_class, mock_telegram_channel - ): - """Test the complete flow from forwarded message to task creation.""" - # Setup - forward_user = MockUser(id=12345, first_name="Alice", username="alice") - current_user = MockUser(id=999, first_name="Bob") - chat = MockChat(id=888, type="private") - - message = MockMessage( - message_id=100, - text="Review this code", - from_user=current_user, - chat=chat, - forward_from=forward_user, - forward_date=1738080000, - ) - - update = Mock() - update.message = message - update.effective_user = Mock() - update.effective_user.id = 999 - update.effective_chat = chat - - # Mock dependencies - mock_task_instance = Mock() - mock_task_class.return_value = mock_task_instance - mock_telegram_channel.scheduler.submit_task.return_value = 789 - mock_telegram_channel.db.get_setting.return_value = "~" - - # Execute text formatting - # Note: We're simulating just the text processing part - formatted_text = mock_telegram_channel._format_forwarded_text(message.text, update) - - # Verify formatting - assert "📨 [转发消息]" in formatted_text - assert "转发自: @alice" in formatted_text - assert "Review this code" in formatted_text - - # Task creation would normally happen next - mock_telegram_channel._create_task(formatted_text, 888, update) - - # Verify task was created with forwarded content - mock_task_class.assert_called_once() - call_kwargs = mock_task_class.call_args[1] - assert call_kwargs["prompt"] == formatted_text - - -if __name__ == "__main__": - pytest.main([__file__, "-v"]) diff --git a/tests/test_telegram_more.py b/tests/test_telegram_more.py deleted file mode 100644 index 3dfdf22..0000000 --- a/tests/test_telegram_more.py +++ /dev/null @@ -1,507 +0,0 @@ -"""Additional Telegram channel coverage. - -Focuses on branches not exercised by tests/test_telegram_channel.py: - - the import-availability guard - - start()/_run_bot/_start_app bootstrap with the telegram SDK fully mocked - - _send_text helper (success + failure) - - send() early-exit + reaction/send error branches and default-chat-id reaction - - _format_forwarded_text "unknown chat type" fallback - - reaction-failure print branches in resume/create - - command edge cases (status error-only render, cancel already-done, resume reaction failure) -""" - -import asyncio -from types import SimpleNamespace -from unittest.mock import AsyncMock, MagicMock, patch - -from taskboard_bus import MessageBus, OutboundMessage, OutboundMessageType - - -class StubDB: - def __init__(self): - self.settings = {} - self.tasks = {} - self.updated = [] - - def get_setting(self, key, default=None): - return self.settings.get(key, default) - - def set_setting(self, key, value): - self.settings[key] = value - - def get_task(self, task_id): - return self.tasks.get(task_id) - - def update_task(self, task_id, **updates): - self.updated.append((task_id, updates)) - self.tasks.setdefault(task_id, {"id": task_id}).update(updates) - - -class StubScheduler: - def __init__(self): - self.submitted = [] - - def submit_task(self, task): - self.submitted.append(task) - return len(self.submitted) - - -def _make_channel(db=None, scheduler=None, allowed_users=None): - from channels.telegram_channel import TelegramChannel - - channel = TelegramChannel( - bus=MessageBus(), - db=db or StubDB(), - scheduler=scheduler or StubScheduler(), - token="123:ABC", - allowed_users=allowed_users, - ) - channel._app = MagicMock() - channel._app.bot = AsyncMock() - channel._loop = MagicMock() - return channel - - -def _fake_update(text="hello", user_id=1, chat_id=10, message_id=100, reply=None): - message = SimpleNamespace( - text=text, - message_id=message_id, - reply_to_message=reply, - forward_from=None, - forward_from_chat=None, - forward_date=None, - reply_text=AsyncMock(), - ) - return SimpleNamespace( - message=message, - effective_user=SimpleNamespace(id=user_id), - effective_chat=SimpleNamespace(id=chat_id), - ) - - -# ── import-availability guard (lines 40-41) ────────────────────── - - -def test_telegram_available_flag_is_boolean(): - from channels import telegram_channel - - # The module imported fine; the flag reflects whether the SDK is present. - assert isinstance(telegram_channel.TELEGRAM_AVAILABLE, bool) - - -# ── stop() lifecycle (lines 118-127) ───────────────────────────── - - -def test_stop_shuts_down_app_and_joins_thread(): - channel = _make_channel() - channel._running = True - # Real loop + app present → schedules the three shutdown coroutines. - fake_loop = MagicMock() - channel._loop = fake_loop - channel._app = MagicMock() - channel._app.updater = MagicMock() - channel._app.updater.stop = MagicMock() - channel._app.stop = MagicMock() - channel._app.shutdown = MagicMock() - channel._thread = MagicMock() - - with patch("asyncio.run_coroutine_threadsafe", return_value=MagicMock()) as rct: - channel.stop() - - assert channel._running is False - # updater.stop / app.stop / app.shutdown scheduled on the loop. - assert rct.call_count == 3 - channel._thread.join.assert_called_once() - # Outbound subscription removed. - assert channel._on_outbound not in channel.bus._outbound_listeners - - -def test_stop_without_loop_is_safe(): - channel = _make_channel() - channel._loop = None - channel._app = None - channel._thread = None - channel.stop() # no run_coroutine_threadsafe, no thread join - assert channel._running is False - - -# ── start() / _run_bot / _start_app bootstrap (112-127, 234-269) ─ - - -def test_start_spawns_thread_and_runs_loop(monkeypatch): - """Drive start() with a fully mocked telegram Application so nothing connects. - - The real bot loop would block; we stub _start_app so _run_bot completes the - loop immediately, and join the thread to confirm it finishes cleanly. - """ - from channels import telegram_channel - - monkeypatch.setattr(telegram_channel, "TELEGRAM_AVAILABLE", True) - channel = telegram_channel.TelegramChannel( - bus=MessageBus(), - db=StubDB(), - scheduler=StubScheduler(), - token="123:ABC", - ) - - started = {} - - async def fake_start_app(): - # Mimic real _start_app: mark ready, then return at once (no polling). - started["ran"] = True - - monkeypatch.setattr(channel, "_start_app", fake_start_app) - channel.start() - assert channel._running is True - assert channel._thread is not None - channel._thread.join(timeout=5) - assert channel._thread.is_alive() is False - assert started.get("ran") is True - # _run_bot created a real event loop and closed it. - assert channel._loop is not None - assert channel._loop.is_closed() is True - - -def test_run_bot_handles_start_app_exception(monkeypatch, capsys): - from channels import telegram_channel - - channel = telegram_channel.TelegramChannel( - bus=MessageBus(), - db=StubDB(), - scheduler=StubScheduler(), - token="123:ABC", - ) - - async def boom(): - raise RuntimeError("startup failed") - - monkeypatch.setattr(channel, "_start_app", boom) - channel._run_bot() - out = capsys.readouterr().out - assert "Bot error" in out - assert channel._loop.is_closed() is True - - -def test_start_app_builds_application_and_registers_handlers(monkeypatch): - """Exercise _start_app: build app, add handlers, start polling, exit loop.""" - from channels import telegram_channel - - fake_app = MagicMock() - fake_app.initialize = AsyncMock() - fake_app.start = AsyncMock() - fake_app.stop = AsyncMock() - fake_app.shutdown = AsyncMock() - fake_app.updater = MagicMock() - fake_app.updater.start_polling = AsyncMock() - fake_app.updater.stop = AsyncMock() - - builder = MagicMock() - builder.token.return_value = builder - builder.build.return_value = fake_app - - monkeypatch.setattr(telegram_channel.Application, "builder", lambda: builder) - - channel = telegram_channel.TelegramChannel( - bus=MessageBus(), - db=StubDB(), - scheduler=StubScheduler(), - token="123:ABC", - ) - # _running starts False so the `while self._running` loop is skipped and - # _start_app proceeds straight to the shutdown sequence — no hang. - channel._running = False - - asyncio.run(channel._start_app()) - - builder.token.assert_called_once_with("123:ABC") - fake_app.initialize.assert_awaited_once() - fake_app.start.assert_awaited_once() - fake_app.updater.start_polling.assert_awaited_once() - # Handlers were registered (5 commands + 1 message handler). - assert fake_app.add_handler.call_count == 6 - # Shutdown path ran because _running was False. - fake_app.updater.stop.assert_awaited_once() - fake_app.stop.assert_awaited_once() - fake_app.shutdown.assert_awaited_once() - - -# ── _send_text helper (lines 272-275) ──────────────────────────── - - -def test_send_text_success(): - channel = _make_channel() - channel._app.bot.send_message = AsyncMock() - asyncio.run(channel._send_text(42, "hi there")) - channel._app.bot.send_message.assert_awaited_once_with(chat_id=42, text="hi there") - - -def test_send_text_logs_failure(capsys): - channel = _make_channel() - channel._app.bot.send_message = AsyncMock(side_effect=RuntimeError("network")) - asyncio.run(channel._send_text(42, "hi")) - assert "Failed to send message to 42" in capsys.readouterr().out - - -# ── send() early-exit branches (133, 142-145) ──────────────────── - - -def test_send_drops_when_loop_not_ready(): - channel = _make_channel() - channel._running = True - # _loop_ready never set → wait() times out quickly here via patch. - with patch.object(channel._loop_ready, "wait", return_value=False): - with patch("asyncio.run_coroutine_threadsafe") as rct: - channel.send( - OutboundMessage(type=OutboundMessageType.TASK_COMPLETED, task_id=1, payload={}) - ) - rct.assert_not_called() - - -def test_send_drops_when_app_or_loop_missing(): - channel = _make_channel() - channel._running = True - channel._loop_ready.set() - channel._app = None # line 144-145 - with patch("asyncio.run_coroutine_threadsafe") as rct: - channel.send( - OutboundMessage(type=OutboundMessageType.TASK_COMPLETED, task_id=1, payload={}) - ) - rct.assert_not_called() - - -# ── send() coroutine body: reaction + truncation + reaction failure ── - - -def _patch_loop(channel): - channel._loop_ready.set() - channel._running = True - - -def test_send_completion_reaction_failure_still_sends(capsys): - """When set_message_reaction raises, the except branch (207-208) logs and - sending the message proceeds.""" - db = StubDB() - channel = _make_channel(db=db) - _patch_loop(channel) - channel._task_origin[5] = (10, 100, 100) - - with patch("asyncio.run_coroutine_threadsafe") as rct: - channel.send( - OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, - task_id=5, - payload={"title": "Job", "result": "done"}, - ) - ) - coro = rct.call_args.args[0] - - channel._app.bot.set_message_reaction = AsyncMock(side_effect=RuntimeError("no react")) - channel._app.bot.send_message = AsyncMock(return_value=SimpleNamespace(message_id=900)) - asyncio.run(coro) - - assert "Failed to set reaction on message 100" in capsys.readouterr().out - channel._app.bot.send_message.assert_awaited_once() - assert channel._notification_map[900] == 5 - - -def test_send_failure_default_chat_includes_status_link(capsys): - """Default-chat-id failure path covers lines 187-190 and the body branch.""" - db = StubDB() - db.settings["telegram_default_chat_id"] = "-100777" - channel = _make_channel(db=db) - _patch_loop(channel) - - with patch("asyncio.run_coroutine_threadsafe") as rct: - channel.send( - OutboundMessage( - type=OutboundMessageType.TASK_FAILED, - task_id=8, - payload={"title": "Broke", "error": "x" * 1500}, - ) - ) - coro = rct.call_args.args[0] - - channel._app.bot.send_message = AsyncMock(return_value=SimpleNamespace(message_id=2)) - asyncio.run(coro) - text = channel._app.bot.send_message.call_args.kwargs["text"] - assert "❌ Task #8: Broke" in text - assert "truncated" in text # error > 800 → smart truncation (line 163) - assert "/status 8" in text # line 190 - - -def test_send_coroutine_swallows_send_failure(capsys): - db = StubDB() - channel = _make_channel(db=db) - _patch_loop(channel) - channel._task_origin[9] = (10, 100, 100) - - with patch("asyncio.run_coroutine_threadsafe") as rct: - channel.send( - OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, - task_id=9, - payload={"title": "Job", "result": "ok"}, - ) - ) - coro = rct.call_args.args[0] - - channel._app.bot.set_message_reaction = AsyncMock() - channel._app.bot.send_message = AsyncMock(side_effect=RuntimeError("send down")) - asyncio.run(coro) # lines 221-222 - assert "Failed to send notification" in capsys.readouterr().out - - -def test_send_default_chat_id_non_numeric_string(): - db = StubDB() - db.settings["telegram_default_chat_id"] = "@mychannel" - channel = _make_channel(db=db) - _patch_loop(channel) - - with patch("asyncio.run_coroutine_threadsafe") as rct: - channel.send( - OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, - task_id=11, - payload={"title": "Job", "result": "ok"}, - ) - ) - coro = rct.call_args.args[0] - channel._app.bot.set_message_reaction = AsyncMock() - channel._app.bot.send_message = AsyncMock(return_value=SimpleNamespace(message_id=3)) - asyncio.run(coro) - # Non-numeric chat id stays a string (not int-cast). - assert channel._app.bot.send_message.call_args.kwargs["chat_id"] == "@mychannel" - - -# ── _format_forwarded_text unknown chat type (line 322) ────────── - - -def test_format_forwarded_from_unknown_chat_type(): - channel = _make_channel() - update = _fake_update() - update.message.forward_date = 1700000000 - update.message.forward_from_chat = SimpleNamespace( - title="Mystery", username=None, type="private" - ) - out = channel._format_forwarded_text("body", update) - # type not channel/group/supergroup → generic "转发自:" line (322). - assert "转发自: Mystery" in out - - -# ── resume-by-reply reaction failure branch (401-402) ──────────── - - -def test_resume_by_reply_reaction_failure_logged(capsys): - db = StubDB() - db.tasks[5] = {"id": 5, "status": "completed", "session_id": "s5"} - channel = _make_channel(db=db) - channel._notification_map[200] = 5 - channel._app.bot.set_message_reaction = AsyncMock(side_effect=RuntimeError("no react")) - reply = SimpleNamespace(message_id=200) - update = _fake_update(text="continue", message_id=300, reply=reply) - - asyncio.run(channel._handle_text_message(update, SimpleNamespace(args=[]))) - - assert db.updated[-1][0] == 5 - assert "Failed to set resume reaction" in capsys.readouterr().out - update.message.reply_text.assert_awaited_with("▶️") - - -# ── _create_task _react coroutine (lines 451-465) ──────────────── - - -def test_create_task_react_coroutine_runs(): - db = StubDB() - scheduler = StubScheduler() - channel = _make_channel(db=db, scheduler=scheduler) - update = _fake_update(text="build it", chat_id=10, message_id=100) - channel._app.bot.set_message_reaction = AsyncMock() - channel._app.bot.send_message = AsyncMock() - - captured = {} - - def capture(coro, loop=None): - captured["coro"] = coro - return MagicMock() - - with ( - patch("channels.dir_utils.resolve_working_dir", return_value="~"), - patch("asyncio.run_coroutine_threadsafe", side_effect=capture), - ): - channel._create_task("build it", 10, update) - - asyncio.run(captured["coro"]) - channel._app.bot.set_message_reaction.assert_awaited_once() - channel._app.bot.send_message.assert_awaited_once() - assert "running" in channel._app.bot.send_message.call_args.kwargs["text"] - - -def test_create_task_react_coroutine_logs_failure(capsys): - db = StubDB() - channel = _make_channel(db=db) - update = _fake_update(text="build it") - channel._app.bot.set_message_reaction = AsyncMock(side_effect=RuntimeError("nope")) - - captured = {} - - def capture(coro, loop=None): - captured["coro"] = coro - return MagicMock() - - with ( - patch("channels.dir_utils.resolve_working_dir", return_value="~"), - patch("asyncio.run_coroutine_threadsafe", side_effect=capture), - ): - channel._create_task("build it", 10, update) - - asyncio.run(captured["coro"]) # lines 464-465 - assert "Failed to set reaction" in capsys.readouterr().out - - -# ── _cmd_status error-only render (line 508) ───────────────────── - - -def test_cmd_status_renders_error_only(): - db = StubDB() - db.tasks[7] = { - "id": 7, - "title": "Broke", - "status": "failed", - "created_at": "2026-01-01T10:00:00", - "last_run_at": None, - "error": "stack trace", - "result": None, - } - channel = _make_channel(db=db) - u = _fake_update() - asyncio.run(channel._cmd_status(u, SimpleNamespace(args=["7"]))) - text = u.message.reply_text.call_args.args[0] - assert "Error: stack trace" in text - assert "Result:" not in text - - -# ── _cmd_cancel unauthorised + already-done (516-517) ──────────── - - -def test_cmd_cancel_unauthorised(): - channel = _make_channel(allowed_users=[1]) - u = _fake_update(user_id=2) - asyncio.run(channel._cmd_cancel(u, SimpleNamespace(args=["1"]))) - assert "Not authorised" in u.message.reply_text.call_args.args[0] - - -# ── _cmd_resume reaction failure branch (576-577) ──────────────── - - -def test_cmd_resume_reaction_failure_logged(capsys): - db = StubDB() - db.tasks[1] = {"id": 1, "title": "t", "status": "completed", "session_id": "s1"} - channel = _make_channel(db=db) - channel._app.bot.set_message_reaction = AsyncMock(side_effect=RuntimeError("no react")) - u = _fake_update(message_id=555) - asyncio.run(channel._cmd_resume(u, SimpleNamespace(args=["#1", "keep", "going"]))) - - assert db.updated[-1][0] == 1 - assert db.updated[-1][1]["prompt"] == "keep going" - assert "Failed to set resume reaction" in capsys.readouterr().out - u.message.reply_text.assert_awaited_with("▶️") diff --git a/tests/test_weixin_channel.py b/tests/test_weixin_channel.py deleted file mode 100644 index dd99901..0000000 --- a/tests/test_weixin_channel.py +++ /dev/null @@ -1,538 +0,0 @@ -import io -import json - -from taskboard_bus import MessageBus, OutboundMessage, OutboundMessageType - - -class StubDB: - def __init__(self): - self.settings = {} - self.tasks = {} - self.updated = [] - self.task_runs = {} - self.run_output_events = {} - - def get_setting(self, key, default=None): - return self.settings.get(key, default) - - def set_setting(self, key, value): - self.settings[key] = value - - def get_task(self, task_id): - return self.tasks.get(task_id) - - def update_task(self, task_id, **updates): - self.updated.append((task_id, updates)) - self.tasks.setdefault(task_id, {"id": task_id}).update(updates) - - def get_task_runs(self, task_id, limit=20): - return self.task_runs.get(task_id, [])[:limit] - - def get_run_output_events(self, run_id, limit=1000): - return self.run_output_events.get(run_id, [])[:limit] - - -class StubScheduler: - def __init__(self): - self.submitted = [] - - def submit_task(self, task): - task_id = len(self.submitted) + 1 - self.submitted.append(task) - return task_id - - -class FakeProcess: - def __init__(self): - self.stdin = io.StringIO() - self.stdout = io.StringIO() - self.terminated = False - - def poll(self): - return None - - def terminate(self): - self.terminated = True - - def wait(self, timeout=None): - return 0 - - -def test_weixin_channel_creates_task_from_bridge_message(): - from channels.weixin_channel import WeixinChannel - - bus = MessageBus() - db = StubDB() - scheduler = StubScheduler() - channel = WeixinChannel(bus=bus, db=db, scheduler=scheduler) - - channel._handle_bridge_event( - { - "type": "message", - "account_id": "wx-1", - "peer_id": "user-1", - "context_token": "ctx-1", - "message_id": "msg-1", - "text": "请帮我修复登录问题", - } - ) - - assert len(scheduler.submitted) == 1 - task = scheduler.submitted[0] - assert task.prompt == "请帮我修复登录问题" - assert task.tags == "weixin" - assert task.title.startswith("[Weixin]") - assert channel._task_origin[1]["peer_id"] == "user-1" - assert channel._task_origin[1]["context_token"] == "ctx-1" - - -def test_weixin_channel_continues_current_peer_session_by_default(): - from channels.weixin_channel import WeixinChannel - - bus = MessageBus() - db = StubDB() - scheduler = StubScheduler() - channel = WeixinChannel(bus=bus, db=db, scheduler=scheduler) - - channel._handle_bridge_event( - { - "type": "message", - "account_id": "wx-1", - "peer_id": "user-1", - "context_token": "ctx-1", - "message_id": "msg-1", - "text": "先检查登录问题", - } - ) - db.tasks[1] = {"id": 1, "session_id": "sess-1", "status": "completed"} - - channel._handle_bridge_event( - { - "type": "message", - "account_id": "wx-1", - "peer_id": "user-1", - "context_token": "ctx-2", - "message_id": "msg-2", - "text": "继续补测试", - } - ) - - assert len(scheduler.submitted) == 1 - assert db.updated == [ - ( - 1, - { - "status": "pending", - "prompt": "继续补测试", - "result": None, - "error": None, - "question": None, - }, - ) - ] - assert channel._task_origin[1]["message_id"] == "msg-2" - assert channel._task_origin[1]["context_token"] == "ctx-2" - - -def test_weixin_channel_new_command_starts_fresh_peer_session(): - from channels.weixin_channel import WeixinChannel - - bus = MessageBus() - db = StubDB() - db.tasks[42] = {"id": 42, "session_id": "sess-42", "status": "completed"} - scheduler = StubScheduler() - channel = WeixinChannel(bus=bus, db=db, scheduler=scheduler) - channel._peer_current_task["wx-1:user-1"] = 42 - - channel._handle_bridge_event( - { - "type": "message", - "account_id": "wx-1", - "peer_id": "user-1", - "context_token": "ctx-new", - "message_id": "msg-new", - "text": "/new 重新设计配置页", - } - ) - - assert db.updated == [] - assert len(scheduler.submitted) == 1 - task = scheduler.submitted[0] - assert task.prompt == "重新设计配置页" - assert task.title.startswith("[Weixin]") - assert channel._peer_current_task["wx-1:user-1"] == 1 - assert channel._task_origin[1]["message_id"] == "msg-new" - - -def test_weixin_channel_attaches_inbound_images_to_created_task(tmp_path): - from channels.weixin_channel import WeixinChannel - - image_path = tmp_path / "inbound.png" - image_path.write_bytes(b"\x89PNG\r\n\x1a\nfakepng") - bus = MessageBus() - db = StubDB() - scheduler = StubScheduler() - channel = WeixinChannel(bus=bus, db=db, scheduler=scheduler) - - channel._handle_bridge_event( - { - "type": "message", - "account_id": "wx-1", - "peer_id": "user-img", - "context_token": "ctx-img", - "message_id": "msg-img", - "text": "看图修一下 UI", - "image_paths": [str(image_path)], - } - ) - - assert len(scheduler.submitted) == 1 - task = scheduler.submitted[0] - assert task.prompt == "看图修一下 UI" - assert task.image_paths == [str(image_path)] - assert len(task.prompt_images) == 1 - assert task.prompt_images[0]["name"] == "inbound.png" - assert task.prompt_images[0]["media_type"] == "image/png" - assert task.prompt_images[0]["data"] - - -def test_weixin_channel_image_only_resume_uses_default_prompt(tmp_path): - from channels.weixin_channel import WeixinChannel - - image_path = tmp_path / "resume.png" - image_path.write_bytes(b"\x89PNG\r\n\x1a\nfakepng") - bus = MessageBus() - db = StubDB() - db.tasks[7] = {"id": 7, "session_id": "sess-7", "status": "completed"} - scheduler = StubScheduler() - channel = WeixinChannel(bus=bus, db=db, scheduler=scheduler) - channel._peer_current_task["wx-1:user-img"] = 7 - - channel._handle_bridge_event( - { - "type": "message", - "account_id": "wx-1", - "peer_id": "user-img", - "context_token": "ctx-img", - "message_id": "msg-img", - "text": "", - "image_paths": [str(image_path)], - } - ) - - assert len(scheduler.submitted) == 0 - assert db.updated[0][0] == 7 - updates = db.updated[0][1] - assert updates["prompt"] == "请分析这张图片。" - assert json.loads(updates["image_paths"]) == [str(image_path)] - assert json.loads(updates["prompt_images"])[0]["media_type"] == "image/png" - - -def test_weixin_channel_sends_generated_images_to_bridge(tmp_path): - from channels.weixin_channel import WeixinChannel - - image_path = tmp_path / "result.png" - image_path.write_bytes(b"\x89PNG\r\n\x1a\nresult") - bus = MessageBus() - db = StubDB() - db.tasks[3] = {"id": 3, "working_dir": str(tmp_path)} - db.task_runs[3] = [{"id": 30}] - db.run_output_events[30] = [ - { - "event_type": "generated_image", - "content": json.dumps({"path": str(image_path), "media_type": "image/png"}), - } - ] - scheduler = StubScheduler() - channel = WeixinChannel(bus=bus, db=db, scheduler=scheduler) - channel._running = True - channel._bridge_proc = FakeProcess() - channel._task_origin[3] = { - "account_id": "wx-1", - "peer_id": "user-3", - "context_token": "ctx-3", - "message_id": "msg-3", - } - - channel.send( - OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, - task_id=3, - payload={ - "title": "Generate image", - "result": f"已生成 1 张图片:\n- {image_path}", - }, - ) - ) - - command = json.loads(channel._bridge_proc.stdin.getvalue().strip()) - assert command["type"] == "send_message" - assert command["image_paths"] == [str(image_path)] - assert str(image_path) not in command["text"] - assert "已生成 1 张图片" in command["text"] - - -def test_weixin_channel_resumes_task_when_reply_matches_notification(): - from channels.weixin_channel import WeixinChannel - - bus = MessageBus() - db = StubDB() - db.tasks[7] = {"id": 7, "session_id": "sess-7", "status": "completed"} - scheduler = StubScheduler() - channel = WeixinChannel(bus=bus, db=db, scheduler=scheduler) - channel._notification_map["notif-7"] = 7 - - channel._handle_bridge_event( - { - "type": "message", - "account_id": "wx-1", - "peer_id": "user-1", - "context_token": "ctx-2", - "message_id": "msg-2", - "reply_to_message_id": "notif-7", - "text": "继续,并补上测试", - } - ) - - assert db.updated == [ - ( - 7, - { - "status": "pending", - "prompt": "继续,并补上测试", - "result": None, - "error": None, - "question": None, - }, - ) - ] - assert channel._task_origin[7]["message_id"] == "msg-2" - assert channel._task_origin[7]["context_token"] == "ctx-2" - commands = ( - [ - json.loads(line) - for line in channel._bridge_proc.stdin.getvalue().splitlines() - if line.strip() - ] - if channel._bridge_proc - else [] - ) - if commands: - assert commands[-1]["text"] == "▶️ 收到!正在唤醒 Task #7,请稍候~" - - -def test_weixin_channel_sends_outbound_notifications_to_bridge(): - from channels.weixin_channel import WeixinChannel - - bus = MessageBus() - db = StubDB() - scheduler = StubScheduler() - channel = WeixinChannel(bus=bus, db=db, scheduler=scheduler) - channel._running = True - channel._bridge_proc = FakeProcess() - channel._task_origin[3] = { - "account_id": "wx-1", - "peer_id": "user-3", - "context_token": "ctx-3", - "message_id": "msg-3", - } - - channel.send( - OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, - task_id=3, - payload={"title": "Fix login", "result": "修好了"}, - ) - ) - - written = channel._bridge_proc.stdin.getvalue().strip() - command = json.loads(written) - assert command["type"] == "send_message" - assert command["request_id"] - assert command["peer_id"] == "user-3" - assert command["context_token"] == "ctx-3" - assert "Task #3" in command["text"] - assert "修好了" in command["text"] - - channel._handle_bridge_event( - { - "type": "sent", - "request_id": command["request_id"], - "message_id": "wx-out-3", - } - ) - - assert channel._notification_map["wx-out-3"] == 3 - - -def test_weixin_channel_resumes_task_when_reply_matches_real_weixin_msg_id(): - from channels.weixin_channel import WeixinChannel - - bus = MessageBus() - db = StubDB() - db.tasks[9] = {"id": 9, "session_id": "sess-9", "status": "completed"} - scheduler = StubScheduler() - channel = WeixinChannel(bus=bus, db=db, scheduler=scheduler) - channel._running = True - channel._bridge_proc = FakeProcess() - channel._task_origin[9] = { - "account_id": "wx-1", - "peer_id": "user-9", - "context_token": "ctx-9", - "message_id": "incoming-9", - } - - channel.send( - OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, - task_id=9, - payload={"title": "Fix resume", "result": "done"}, - ) - ) - - command = json.loads(channel._bridge_proc.stdin.getvalue().strip()) - channel._handle_bridge_event( - { - "type": "sent", - "request_id": command["request_id"], - "message_id": command["request_id"], - "quoted_message_id": "wx-real-msg-9", - } - ) - - channel._handle_bridge_event( - { - "type": "message", - "account_id": "wx-1", - "peer_id": "user-9", - "context_token": "ctx-9b", - "message_id": "incoming-9b", - "reply_to_message_id": "wx-real-msg-9", - "text": "继续这个任务", - } - ) - - assert db.updated == [ - ( - 9, - { - "status": "pending", - "prompt": "继续这个任务", - "result": None, - "error": None, - "question": None, - }, - ) - ] - assert channel._task_origin[9]["message_id"] == "incoming-9b" - assert channel._task_origin[9]["context_token"] == "ctx-9b" - commands = [ - json.loads(line) - for line in channel._bridge_proc.stdin.getvalue().splitlines() - if line.strip() - ] - assert commands[-1]["text"] == "▶️ 收到!正在唤醒 Task #9,请稍候~" - - -def test_weixin_channel_resumes_task_when_reply_quotes_task_number_without_msg_id(): - from channels.weixin_channel import WeixinChannel - - bus = MessageBus() - db = StubDB() - db.tasks[11] = {"id": 11, "session_id": "sess-11", "status": "completed"} - scheduler = StubScheduler() - channel = WeixinChannel(bus=bus, db=db, scheduler=scheduler) - - channel._handle_bridge_event( - { - "type": "message", - "account_id": "wx-1", - "peer_id": "user-11", - "context_token": "ctx-11b", - "message_id": "incoming-11b", - "reply_to_message_id": "", - "reply_to_message_title": "✅ Task #11 · [Weixin] 你好", - "reply_to_message_text": "Task #11 已完成", - "text": "继续这个任务", - } - ) - - assert db.updated == [ - ( - 11, - { - "status": "pending", - "prompt": "继续这个任务", - "result": None, - "error": None, - "question": None, - }, - ) - ] - assert channel._task_origin[11]["message_id"] == "incoming-11b" - assert channel._task_origin[11]["context_token"] == "ctx-11b" - - -def test_weixin_channel_tracks_qr_and_login_status_from_bridge_events(): - from channels.weixin_channel import WeixinChannel - - channel = WeixinChannel(bus=MessageBus(), db=StubDB(), scheduler=StubScheduler()) - - channel._handle_bridge_event( - { - "type": "qr", - "qrcode_url": "https://example.test/qr.png", - "account_id": "wx-login", - } - ) - snapshot = channel.get_status_snapshot() - assert snapshot["login_status"] == "waiting_for_scan" - assert snapshot["qr_code_url"] == "https://example.test/qr.png" - assert snapshot["account_id"] == "wx-login" - - channel._handle_bridge_event({"type": "scaned"}) - assert channel.get_status_snapshot()["login_status"] == "scanned" - - channel._handle_bridge_event( - { - "type": "login_success", - "account_id": "wx-login", - "user_id": "user-42", - } - ) - snapshot = channel.get_status_snapshot() - assert snapshot["login_status"] == "connected" - assert snapshot["qr_code_url"] == "" - assert snapshot["configured"] is True - assert snapshot["user_id"] == "user-42" - - -def test_weixin_channel_can_request_relogin_and_logout_via_bridge_commands(): - from channels.weixin_channel import WeixinChannel - - channel = WeixinChannel(bus=MessageBus(), db=StubDB(), scheduler=StubScheduler()) - channel._bridge_proc = FakeProcess() - channel._running = True - channel._handle_bridge_event( - { - "type": "login_success", - "account_id": "wx-login", - "user_id": "user-42", - } - ) - - channel.request_login() - channel.request_logout() - - commands = [ - json.loads(line) - for line in channel._bridge_proc.stdin.getvalue().splitlines() - if line.strip() - ] - assert commands[0]["type"] == "login" - assert commands[1]["type"] == "logout" - - snapshot = channel.get_status_snapshot() - assert snapshot["configured"] is False - assert snapshot["login_status"] == "idle" - assert snapshot["qr_code_url"] == "" diff --git a/tests/test_weixin_more.py b/tests/test_weixin_more.py deleted file mode 100644 index 29eeb58..0000000 --- a/tests/test_weixin_more.py +++ /dev/null @@ -1,844 +0,0 @@ -"""Additional coverage for channels/weixin_channel.py. - -These tests target branches not already covered by test_weixin_channel.py: -constructor/start/stop, the bridge reader, dir/agent command replies, the -/new-with-no-content path, the resume-without-session error, image media-type -sniffing, markdown image reference parsing, generated-image collection error -branches, and the path-hiding renderer. -""" - -import io -import json -from unittest import mock - -from taskboard_bus import MessageBus, OutboundMessage, OutboundMessageType - - -class StubDB: - def __init__(self): - self.settings = {} - self.tasks = {} - self.updated = [] - self.task_runs = {} - self.run_output_events = {} - self.runs_error = None - self.events_error = None - - def get_setting(self, key, default=None): - return self.settings.get(key, default) - - def set_setting(self, key, value): - self.settings[key] = value - - def get_task(self, task_id): - return self.tasks.get(task_id) - - def update_task(self, task_id, **updates): - self.updated.append((task_id, updates)) - self.tasks.setdefault(task_id, {"id": task_id}).update(updates) - - def get_task_runs(self, task_id, limit=20): - if self.runs_error is not None: - raise self.runs_error - return self.task_runs.get(task_id, [])[:limit] - - def get_run_output_events(self, run_id, limit=1000): - if self.events_error is not None: - raise self.events_error - return self.run_output_events.get(run_id, [])[:limit] - - -class StubScheduler: - def __init__(self): - self.submitted = [] - - def submit_task(self, task): - task_id = len(self.submitted) + 1 - self.submitted.append(task) - return task_id - - -class FakeProcess: - def __init__(self, alive=True): - self.stdin = io.StringIO() - self.stdout = io.StringIO() - self.terminated = False - self.waited = False - self._alive = alive - - def poll(self): - return None if self._alive else 0 - - def terminate(self): - self.terminated = True - - def wait(self, timeout=None): - self.waited = True - return 0 - - -def _make_channel(): - from channels.weixin_channel import WeixinChannel - - return WeixinChannel(bus=MessageBus(), db=StubDB(), scheduler=StubScheduler()) - - -# ── constructor / default bridge command ────────────────────────────────── - - -def test_default_bridge_cmd_points_at_index_mjs(): - channel = _make_channel() - cmd = channel._default_bridge_cmd() - # cmd[0] is now a resolved node path (or bare "node" when none is found) - assert cmd[0] == "node" or cmd[0].endswith("/node") - assert cmd[1].endswith("weixin_bridge/index.mjs") - - -def test_default_bridge_cmd_resolves_full_node_path(monkeypatch): - channel = _make_channel() - monkeypatch.setattr("channels.weixin_channel.shutil.which", lambda exe: "/fake/bin/node") - cmd = channel._default_bridge_cmd() - assert cmd[0] == "/fake/bin/node" - assert cmd[1].endswith("weixin_bridge/index.mjs") - - -def test_default_bridge_cmd_falls_back_to_homebrew_when_node_not_on_path(monkeypatch): - """macOS GUI-launched apps inherit a minimal PATH without Homebrew, so - `shutil.which("node")` misses — we must fall back to common install dirs.""" - channel = _make_channel() - monkeypatch.setattr("channels.weixin_channel.shutil.which", lambda exe: None) - monkeypatch.setattr( - "channels.weixin_channel.os.path.exists", - lambda p: p == "/opt/homebrew/bin/node", - ) - cmd = channel._default_bridge_cmd() - assert cmd[0] == "/opt/homebrew/bin/node" - - -def test_bridge_script_path_uses_meipass_when_frozen(monkeypatch): - """In the PyInstaller bundle the bridge lives under sys._MEIPASS, not next - to the (frozen) source module.""" - channel = _make_channel() - monkeypatch.setattr("channels.weixin_channel.sys.frozen", True, raising=False) - monkeypatch.setattr("channels.weixin_channel.sys._MEIPASS", "/tmp/meipass", raising=False) - path = channel._bridge_script_path() - assert str(path) == "/tmp/meipass/channels/weixin_bridge/index.mjs" - - -def test_start_surfaces_missing_node_as_error_status(monkeypatch): - """When node is genuinely absent, Popen raises FileNotFoundError. Instead of - silently failing (blank QR), the channel must report an error status.""" - channel = _make_channel() - - def no_node(cmd, **kwargs): - raise FileNotFoundError("node") - - monkeypatch.setattr("channels.weixin_channel.subprocess.Popen", no_node) - channel.start() - assert channel._running is False - assert channel._bridge_proc is None - snap = channel.get_status_snapshot() - assert snap["login_status"] == "error" - assert "Node" in (snap["last_error"] or "") - - -def test_explicit_bridge_cmd_overrides_default(): - from channels.weixin_channel import WeixinChannel - - channel = WeixinChannel( - bus=MessageBus(), - db=StubDB(), - scheduler=StubScheduler(), - bridge_cmd=["custom", "bridge"], - ) - assert channel.bridge_cmd == ["custom", "bridge"] - - -# ── start() / stop() ─────────────────────────────────────────────────────── - - -def test_start_spawns_bridge_and_reader(monkeypatch): - channel = _make_channel() - channel.db.settings["weixin_account_id"] = "wx-acct" - - fake_proc = FakeProcess() - fake_proc.stdout = io.StringIO("") # reader exits immediately - popen_calls = {} - - def fake_popen(cmd, **kwargs): - popen_calls["cmd"] = cmd - popen_calls["env"] = kwargs.get("env") - return fake_proc - - monkeypatch.setattr("channels.weixin_channel.subprocess.Popen", fake_popen) - - channel.start() - assert channel._running is True - assert channel._bridge_proc is fake_proc - assert popen_calls["env"]["AGENTFORGE_WEIXIN_ACCOUNT_ID"] == "wx-acct" - if channel._reader_thread: - channel._reader_thread.join(timeout=2) - - -def test_start_handles_popen_failure(monkeypatch): - channel = _make_channel() - - def boom(cmd, **kwargs): - raise OSError("node not found") - - monkeypatch.setattr("channels.weixin_channel.subprocess.Popen", boom) - - channel.start() - assert channel._running is False - assert channel._bridge_proc is None - - -def test_stop_terminates_live_bridge(): - channel = _make_channel() - channel._running = True - proc = FakeProcess(alive=True) - channel._bridge_proc = proc - - channel.stop() - - assert channel._running is False - assert proc.terminated is True - assert proc.waited is True - assert channel._bridge_proc is None - - -def test_stop_with_dead_bridge_does_not_terminate(): - channel = _make_channel() - channel._running = True - proc = FakeProcess(alive=False) - channel._bridge_proc = proc - - channel.stop() - - assert proc.terminated is False - assert channel._bridge_proc is None - - -def test_stop_swallows_terminate_exception(): - channel = _make_channel() - channel._running = True - proc = FakeProcess(alive=True) - proc.terminate = mock.Mock(side_effect=RuntimeError("boom")) - channel._bridge_proc = proc - - channel.stop() # should not raise - assert channel._bridge_proc is None - - -# ── _read_bridge_events ──────────────────────────────────────────────────── - - -def test_read_bridge_events_dispatches_and_skips_garbage(): - channel = _make_channel() - channel._running = True - proc = FakeProcess() - proc.stdout = io.StringIO( - "\n" # blank line skipped - "not-json\n" # JSONDecodeError branch - '{"type": "scaned"}\n' # valid event dispatched - ) - channel._bridge_proc = proc - - channel._read_bridge_events() - - assert channel.get_status_snapshot()["login_status"] == "scanned" - - -def test_read_bridge_events_returns_when_no_proc(): - channel = _make_channel() - channel._bridge_proc = None - # Should simply return without error. - channel._read_bridge_events() - - -def test_read_bridge_events_stops_when_not_running(): - channel = _make_channel() - channel._running = False - proc = FakeProcess() - proc.stdout = io.StringIO('{"type": "scaned"}\n') - channel._bridge_proc = proc - - channel._read_bridge_events() - # Not running, so the event was not handled. - assert channel.get_status_snapshot()["login_status"] == "idle" - - -# ── ready / error bridge events ──────────────────────────────────────────── - - -def test_ready_event_marks_connected(): - channel = _make_channel() - channel._handle_bridge_event({"type": "ready", "account_id": "wx-ready"}) - snap = channel.get_status_snapshot() - assert snap["login_status"] == "connected" - assert snap["configured"] is True - assert snap["account_id"] == "wx-ready" - - -def test_error_event_records_last_error(): - channel = _make_channel() - channel._handle_bridge_event({"type": "error", "message": "kaboom"}) - snap = channel.get_status_snapshot() - assert snap["login_status"] == "error" - assert snap["last_error"] == "kaboom" - - -# ── dir / agent command replies ──────────────────────────────────────────── - - -def test_dir_command_reply_short_circuits(monkeypatch): - channel = _make_channel() - channel._bridge_proc = FakeProcess() - channel._running = True - monkeypatch.setattr( - "channels.dir_utils.handle_dir_command", - lambda text, key, db: "dir reply", - ) - - channel._handle_bridge_event( - { - "type": "message", - "account_id": "wx-1", - "peer_id": "user-d", - "message_id": "m-d", - "text": "/dir", - } - ) - - assert channel.scheduler.submitted == [] - sent = json.loads(channel._bridge_proc.stdin.getvalue().strip()) - assert sent["text"] == "dir reply" - - -def test_agent_command_reply_short_circuits(monkeypatch): - channel = _make_channel() - channel._bridge_proc = FakeProcess() - channel._running = True - monkeypatch.setattr( - "channels.agent_utils.handle_agent_command", - lambda text, key, db: "agent reply", - ) - - channel._handle_bridge_event( - { - "type": "message", - "account_id": "wx-1", - "peer_id": "user-a", - "message_id": "m-a", - "text": "/agent", - } - ) - - assert channel.scheduler.submitted == [] - sent = json.loads(channel._bridge_proc.stdin.getvalue().strip()) - assert sent["text"] == "agent reply" - - -# ── message edge cases ───────────────────────────────────────────────────── - - -def test_empty_message_with_no_images_is_ignored(): - channel = _make_channel() - channel._handle_bridge_event({"type": "message", "peer_id": "user-x", "text": " "}) - assert channel.scheduler.submitted == [] - - -def test_new_command_without_content_prompts_for_task(): - channel = _make_channel() - channel._bridge_proc = FakeProcess() - channel._running = True - - channel._handle_bridge_event( - { - "type": "message", - "account_id": "wx-1", - "peer_id": "user-n", - "message_id": "m-n", - "text": "/new", - } - ) - - assert channel.scheduler.submitted == [] - sent = json.loads(channel._bridge_proc.stdin.getvalue().strip()) - assert "已开启新的 Weixin session" in sent["text"] - - -def test_resume_target_without_session_replies_error(): - channel = _make_channel() - channel._bridge_proc = FakeProcess() - channel._running = True - # Task exists but has no session_id, referenced by reply title. - channel.db.tasks[5] = {"id": 5, "status": "completed"} - - channel._handle_bridge_event( - { - "type": "message", - "account_id": "wx-1", - "peer_id": "user-r", - "message_id": "m-r", - "reply_to_message_title": "Task #5", - "text": "继续", - } - ) - - assert channel.scheduler.submitted == [] - assert channel.db.updated == [] - sent = json.loads(channel._bridge_proc.stdin.getvalue().strip()) - assert "no saved session to resume" in sent["text"] - - -def test_reply_to_event_without_peer_is_noop(): - channel = _make_channel() - channel._bridge_proc = FakeProcess() - channel._running = True - channel._reply_to_event({"text": "hi"}, "nothing") - assert channel._bridge_proc.stdin.getvalue() == "" - - -# ── _extract_image_paths with images list ────────────────────────────────── - - -def test_extract_image_paths_from_images_list(tmp_path): - channel = _make_channel() - img = tmp_path / "a.png" - img.write_bytes(b"\x89PNG\r\n\x1a\nx") - paths = channel._extract_image_paths( - { - "images": [ - {"path": str(img)}, - {"local_path": str(img)}, # dedup - "not-a-dict", - {"no_path": "x"}, - ] - } - ) - assert paths == [str(img.resolve())] - - -# ── _image_media_type header sniffing ────────────────────────────────────── - - -def test_image_media_type_by_extension(): - channel = _make_channel() - assert channel._image_media_type("/x/a.PNG") == "image/png" - assert channel._image_media_type("/x/a.jpg") == "image/jpeg" - assert channel._image_media_type("/x/a.jpeg") == "image/jpeg" - assert channel._image_media_type("/x/a.gif") == "image/gif" - assert channel._image_media_type("/x/a.webp") == "image/webp" - - -def test_image_media_type_sniffs_header(tmp_path): - channel = _make_channel() - - png = tmp_path / "noext_png" - png.write_bytes(b"\x89PNG\r\n\x1a\n" + b"0" * 4) - assert channel._image_media_type(str(png)) == "image/png" - - jpg = tmp_path / "noext_jpg" - jpg.write_bytes(b"\xff\xd8\xff" + b"0" * 9) - assert channel._image_media_type(str(jpg)) == "image/jpeg" - - gif = tmp_path / "noext_gif" - gif.write_bytes(b"GIF89a" + b"0" * 6) - assert channel._image_media_type(str(gif)) == "image/gif" - - webp = tmp_path / "noext_webp" - webp.write_bytes(b"RIFF0000WEBP") - assert channel._image_media_type(str(webp)) == "image/webp" - - unknown = tmp_path / "noext_bin" - unknown.write_bytes(b"\x00\x01\x02\x03" + b"0" * 8) - assert channel._image_media_type(str(unknown)) == "image/jpeg" - - -def test_image_media_type_missing_file_defaults_jpeg(): - channel = _make_channel() - assert channel._image_media_type("/nonexistent/no_ext_file") == "image/jpeg" - - -def test_build_prompt_images_skips_unreadable(tmp_path): - channel = _make_channel() - good = tmp_path / "good.png" - good.write_bytes(b"\x89PNG\r\n\x1a\nx") - images = channel._build_prompt_images([str(good), "/nope/missing.png"]) - assert len(images) == 1 - assert images[0]["name"] == "good.png" - - -# ── generated image collection error branches ────────────────────────────── - - -def test_generated_image_paths_for_task_runs_error(): - channel = _make_channel() - channel.db.runs_error = RuntimeError("db down") - assert channel._generated_image_paths_for_task(1) == [] - - -def test_generated_image_paths_for_task_no_runs(): - channel = _make_channel() - channel.db.task_runs[1] = [] - assert channel._generated_image_paths_for_task(1) == [] - - -def test_generated_image_paths_for_task_run_without_id(): - channel = _make_channel() - channel.db.task_runs[1] = [{"no_id": True}] - assert channel._generated_image_paths_for_task(1) == [] - - -def test_generated_image_paths_for_task_events_error(): - channel = _make_channel() - channel.db.task_runs[1] = [{"id": 11}] - channel.db.events_error = RuntimeError("events down") - assert channel._generated_image_paths_for_task(1) == [] - - -def test_generated_image_paths_for_task_parses_events(tmp_path): - channel = _make_channel() - img = tmp_path / "g.png" - img.write_bytes(b"\x89PNG\r\n\x1a\nx") - channel.db.task_runs[1] = [{"id": 11}] - channel.db.run_output_events[11] = [ - "not-a-dict", - {"event_type": "other"}, - {"event_type": "generated_image", "content": "not-json{"}, - {"event_type": "generated_image", "content": json.dumps({"path": str(img)})}, - {"event_type": "generated_image", "content": json.dumps({"no_path": 1})}, - ] - assert channel._generated_image_paths_for_task(1) == [str(img)] - - -# ── markdown reference parsing ───────────────────────────────────────────── - - -def test_local_image_path_from_reference_variants(tmp_path): - channel = _make_channel() - img = tmp_path / "ref.png" - img.write_bytes(b"\x89PNG\r\n\x1a\nx") - - # http / data references are rejected - assert channel._local_image_path_from_reference("https://x/y.png") is None - assert channel._local_image_path_from_reference("data:image/png;base64,AAA") is None - assert channel._local_image_path_from_reference("") is None - - # file:// scheme - assert channel._local_image_path_from_reference(f"file://{img}") == str(img.resolve()) - # sandbox: scheme - assert channel._local_image_path_from_reference(f"sandbox:{img}") == str(img.resolve()) - # relative path resolved against working_dir - assert channel._local_image_path_from_reference("ref.png", working_dir=str(tmp_path)) == str( - img.resolve() - ) - - -def test_markdown_image_reference_target_quotes_and_titles(): - channel = _make_channel() - assert channel._markdown_image_reference_target("") == "" - assert channel._markdown_image_reference_target("") == "path/x.png" - assert channel._markdown_image_reference_target("'quoted.png'") == "quoted.png" - assert channel._markdown_image_reference_target('"dq.png"') == "dq.png" - assert channel._markdown_image_reference_target('a.png "title"') == "a.png" - assert channel._markdown_image_reference_target("plain.png") == "plain.png" - - -def test_generated_image_paths_from_markdown(tmp_path): - channel = _make_channel() - img = tmp_path / "md.png" - img.write_bytes(b"\x89PNG\r\n\x1a\nx") - content = f"see ![alt]({img}) and ![x](https://remote/y.png)" - assert channel._generated_image_paths_from_markdown(content) == [str(img.resolve())] - - -# ── _hide_generated_image_paths renderer ─────────────────────────────────── - - -def test_hide_generated_image_paths_removes_listed_paths(tmp_path): - channel = _make_channel() - img = tmp_path / "out.png" - img.write_bytes(b"\x89PNG\r\n\x1a\nx") - canonical = str(img.resolve()) - content = f"这是结果\n- {canonical}\n\n下一行" - cleaned = channel._hide_generated_image_paths(content, 1, [canonical]) - assert canonical not in cleaned - assert "这是结果" in cleaned - assert "下一行" in cleaned - - -def test_hide_generated_image_paths_codex_dir_line(): - channel = _make_channel() - content = "- /home/u/.codex/generated_images/foo.png" - cleaned = channel._hide_generated_image_paths(content, 1, []) - assert cleaned == "已生成 1 张图片。" - - -def test_hide_generated_image_paths_strips_markdown_refs(tmp_path): - channel = _make_channel() - img = tmp_path / "in.png" - img.write_bytes(b"\x89PNG\r\n\x1a\nx") - canonical = str(img.resolve()) - content = f"前缀 ![a]({canonical}) 后缀" - cleaned = channel._hide_generated_image_paths(content, 1, [canonical]) - assert canonical not in cleaned - assert "前缀" in cleaned and "后缀" in cleaned - - -def test_hide_generated_image_paths_empty_becomes_default(): - channel = _make_channel() - cleaned = channel._hide_generated_image_paths(" \n ", 2, []) - assert cleaned == "已生成 2 张图片。" - - -def test_line_is_uploaded_image_path_non_dash_line(): - channel = _make_channel() - assert channel._line_is_uploaded_image_path("just text", set()) is False - - -def test_remove_uploaded_markdown_image_refs_no_uploads(): - channel = _make_channel() - line = "![a](x.png)" - assert channel._remove_uploaded_markdown_image_refs(line, set()) == line - - -# ── canonical path edge cases ────────────────────────────────────────────── - - -def test_canonical_image_path_rejects_non_image(tmp_path): - channel = _make_channel() - txt = tmp_path / "a.txt" - txt.write_text("hi") - assert channel._canonical_image_path(str(txt)) is None - - -def test_canonical_image_path_rejects_missing(tmp_path): - channel = _make_channel() - assert channel._canonical_image_path(str(tmp_path / "missing.png")) is None - - -# ── send() guards ────────────────────────────────────────────────────────── - - -def test_send_noop_when_not_running(): - channel = _make_channel() - channel._running = False - channel.send( - OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, - task_id=1, - payload={"result": "x"}, - ) - ) # no error, nothing sent - assert channel._bridge_proc is None - - -def test_send_ignores_irrelevant_message_type(): - channel = _make_channel() - channel._running = True - channel._bridge_proc = FakeProcess() - channel.send( - OutboundMessage( - type=OutboundMessageType.TASK_STARTED, - task_id=1, - payload={}, - ) - ) - assert channel._bridge_proc.stdin.getvalue() == "" - - -def test_send_without_origin_skips(): - channel = _make_channel() - channel._running = True - channel._bridge_proc = FakeProcess() - channel.send( - OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, - task_id=99, - payload={"result": "x"}, - ) - ) - assert channel._bridge_proc.stdin.getvalue() == "" - - -def test_send_failed_task_formats_error(): - channel = _make_channel() - channel._running = True - channel._bridge_proc = FakeProcess() - channel._task_origin[4] = { - "account_id": "wx-1", - "peer_id": "user-4", - "context_token": "ctx-4", - "message_id": "msg-4", - } - channel.send( - OutboundMessage( - type=OutboundMessageType.TASK_FAILED, - task_id=4, - payload={"title": "Broke", "error": " boom "}, - ) - ) - sent = json.loads(channel._bridge_proc.stdin.getvalue().strip()) - assert sent["text"].startswith("❌ Task #4 · Broke") - assert "boom" in sent["text"] - # origin consumed after send - assert 4 not in channel._task_origin - - -# ── _extract_task_id_from_reply_reference ────────────────────────────────── - - -def test_extract_task_id_from_reply_reference(): - channel = _make_channel() - assert channel._extract_task_id_from_reply_reference("", "Task #88 done") == 88 - assert channel._extract_task_id_from_reply_reference("no number here") is None - - -# ── request_login / request_logout ───────────────────────────────────────── - - -def test_request_login_resets_status_and_sends_command(): - channel = _make_channel() - channel._running = True - channel._bridge_proc = FakeProcess() - channel._update_status(configured=True, login_status="connected", user_id="u") - - channel.request_login() - - snap = channel.get_status_snapshot() - assert snap["configured"] is False - assert snap["login_status"] == "idle" - sent = json.loads(channel._bridge_proc.stdin.getvalue().strip()) - assert sent["type"] == "login" - - -def test_request_logout_resets_status_and_sends_command(): - channel = _make_channel() - channel._running = True - channel._bridge_proc = FakeProcess() - - channel.request_logout() - - sent = json.loads(channel._bridge_proc.stdin.getvalue().strip()) - assert sent["type"] == "logout" - assert channel.get_status_snapshot()["login_status"] == "idle" - - -# ── send() with generated images ─────────────────────────────────────────── - - -def test_send_completed_with_generated_images(tmp_path): - channel = _make_channel() - channel._running = True - channel._bridge_proc = FakeProcess() - img = tmp_path / "gen.png" - img.write_bytes(b"\x89PNG\r\n\x1a\nx") - canonical = str(img.resolve()) - - channel.db.tasks[7] = {"id": 7, "working_dir": str(tmp_path)} - channel.db.task_runs[7] = [{"id": 70}] - channel.db.run_output_events[70] = [ - {"event_type": "generated_image", "content": json.dumps({"path": canonical})} - ] - channel._task_origin[7] = { - "account_id": "wx-1", - "peer_id": "user-7", - "context_token": "ctx-7", - "message_id": "msg-7", - } - - channel.send( - OutboundMessage( - type=OutboundMessageType.TASK_COMPLETED, - task_id=7, - payload={"title": "img task", "result": f"done\n- {canonical}"}, - ) - ) - - sent = json.loads(channel._bridge_proc.stdin.getvalue().strip()) - assert sent["image_paths"] == [canonical] - assert canonical not in sent["text"] - - -# ── sent-event handling ──────────────────────────────────────────────────── - - -def test_handle_sent_event_maps_message_and_quoted_ids(): - channel = _make_channel() - channel._pending_notifications["req-1"] = 5 - - channel._handle_sent_event( - { - "type": "sent", - "request_id": "req-1", - "message_id": "mid-1", - "quoted_message_id": "qid-1", - } - ) - - assert channel._notification_map["mid-1"] == 5 - assert channel._notification_map["qid-1"] == 5 - # quoted id present → pending entry cleared - assert "req-1" not in channel._pending_notifications - - -def test_handle_sent_event_ignored_without_ids(): - channel = _make_channel() - channel._pending_notifications["req-2"] = 9 - channel._handle_sent_event({"request_id": "req-2"}) - assert channel._notification_map == {} - - -def test_handle_sent_event_unknown_request_id(): - channel = _make_channel() - channel._handle_sent_event({"request_id": "missing", "message_id": "m"}) - assert channel._notification_map == {} - - -# ── full resume flow via peer current task ───────────────────────────────── - - -def test_resume_via_peer_current_task_updates_and_sets_origin(): - channel = _make_channel() - channel._running = True - channel._bridge_proc = FakeProcess() - channel.db.tasks[3] = {"id": 3, "session_id": "sess-3", "status": "completed"} - channel._peer_current_task["wx-1:user-3"] = 3 - - channel._handle_bridge_event( - { - "type": "message", - "account_id": "wx-1", - "peer_id": "user-3", - "context_token": "ctx-3b", - "message_id": "msg-3b", - "text": "继续做", - } - ) - - assert channel.scheduler.submitted == [] - assert channel.db.updated[0][0] == 3 - assert channel._task_origin[3]["message_id"] == "msg-3b" - sent = [ - json.loads(line) - for line in channel._bridge_proc.stdin.getvalue().splitlines() - if line.strip() - ] - assert sent[-1]["text"] == "▶️ 收到!正在唤醒 Task #3,请稍候~" - - -def test_build_resume_updates_with_images(tmp_path): - channel = _make_channel() - img = tmp_path / "r.png" - img.write_bytes(b"\x89PNG\r\n\x1a\nx") - updates = channel._build_resume_updates("", [str(img)]) - assert updates["prompt"] == "请分析这张图片。" - assert json.loads(updates["image_paths"]) == [str(img)] - assert json.loads(updates["prompt_images"])[0]["media_type"] == "image/png" - - -def test_default_image_prompt_plural(): - channel = _make_channel() - assert channel._default_image_prompt(["a", "b"]) == "请分析这 2 张图片。" diff --git a/tests/test_weixin_status.py b/tests/test_weixin_status.py deleted file mode 100644 index 0c1d5a1..0000000 --- a/tests/test_weixin_status.py +++ /dev/null @@ -1,38 +0,0 @@ -from taskboard import _build_weixin_channel_status - - -class StubDB: - def __init__(self): - self.settings = { - "weixin_enabled": "true", - "weixin_default_working_dir": "~/repo", - "weixin_base_url": "https://ilinkai.weixin.qq.com", - "weixin_account_id": "", - } - - def get_setting(self, key, default=None): - return self.settings.get(key, default) - - -class StubWeixinChannel: - _running = True - - def get_status_snapshot(self): - return { - "configured": True, - "login_status": "connected", - "qr_code_url": "", - "last_error": "", - "account_id": "wx-live-account", - "user_id": "user-42", - } - - -def test_build_weixin_channel_status_prefers_runtime_account_id(): - status = _build_weixin_channel_status(StubDB(), StubWeixinChannel()) - - assert status["enabled"] is True - assert status["configured"] is True - assert status["running"] is True - assert status["account_id"] == "wx-live-account" - assert status["user_id"] == "user-42" diff --git a/uv.lock b/uv.lock deleted file mode 100644 index 4d8fbef..0000000 --- a/uv.lock +++ /dev/null @@ -1,959 +0,0 @@ -version = 1 -revision = 2 -requires-python = ">=3.12" -resolution-markers = [ - "python_full_version >= '3.14'", - "python_full_version < '3.14'", -] - -[[package]] -name = "agentforge" -version = "0.1.0" -source = { virtual = "." } -dependencies = [ - { name = "claude-monitor" }, - { name = "croniter" }, - { name = "lark-oapi" }, - { name = "pyinstaller" }, - { name = "python-dateutil" }, - { name = "python-socks" }, - { name = "python-telegram-bot" }, - { name = "pytz" }, - { name = "requests" }, - { name = "slack-sdk" }, -] - -[package.dev-dependencies] -dev = [ - { name = "pyinstaller" }, - { name = "pytest" }, - { name = "pytest-cov" }, - { name = "ruff" }, -] - -[package.metadata] -requires-dist = [ - { name = "claude-monitor", specifier = ">=3.1.0" }, - { name = "croniter", specifier = ">=6.0.0" }, - { name = "lark-oapi", specifier = ">=1.3.0" }, - { name = "pyinstaller", specifier = ">=6.18.0" }, - { name = "python-dateutil", specifier = ">=2.9.0.post0" }, - { name = "python-socks", specifier = ">=2.8.1" }, - { name = "python-telegram-bot", specifier = ">=21.0" }, - { name = "pytz", specifier = ">=2025.2" }, - { name = "requests", specifier = ">=2.32.5" }, - { name = "slack-sdk", specifier = ">=3.0.0" }, -] - -[package.metadata.requires-dev] -dev = [ - { name = "pyinstaller", specifier = ">=6.18.0" }, - { name = "pytest", specifier = ">=9.0.2" }, - { name = "pytest-cov", specifier = ">=7.0.0" }, - { name = "ruff", specifier = ">=0.11.0" }, -] - -[[package]] -name = "altgraph" -version = "0.17.5" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7e/f8/97fdf103f38fed6792a1601dbc16cc8aac56e7459a9fff08c812d8ae177a/altgraph-0.17.5.tar.gz", hash = "sha256:c87b395dd12fabde9c99573a9749d67da8d29ef9de0125c7f536699b4a9bc9e7", size = 48428, upload-time = "2025-11-21T20:35:50.583Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a9/ba/000a1996d4308bc65120167c21241a3b205464a2e0b58deda26ae8ac21d1/altgraph-0.17.5-py2.py3-none-any.whl", hash = "sha256:f3a22400bce1b0c701683820ac4f3b159cd301acab067c51c653e06961600597", size = 21228, upload-time = "2025-11-21T20:35:49.444Z" }, -] - -[[package]] -name = "annotated-types" -version = "0.7.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ee/67/531ea369ba64dcff5ec9c3402f9f51bf748cec26dde048a2f973a4eea7f5/annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89", size = 16081, upload-time = "2024-05-20T21:33:25.928Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/78/b6/6307fbef88d9b5ee7421e68d78a9f162e0da4900bc5f5793f6d3d0e34fb8/annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", size = 13643, upload-time = "2024-05-20T21:33:24.1Z" }, -] - -[[package]] -name = "anyio" -version = "4.12.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "idna" }, - { name = "typing-extensions", marker = "python_full_version < '3.13'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/96/f0/5eb65b2bb0d09ac6776f2eb54adee6abe8228ea05b20a5ad0e4945de8aac/anyio-4.12.1.tar.gz", hash = "sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703", size = 228685, upload-time = "2026-01-06T11:45:21.246Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/38/0e/27be9fdef66e72d64c0cdc3cc2823101b80585f8119b5c112c2e8f5f7dab/anyio-4.12.1-py3-none-any.whl", hash = "sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c", size = 113592, upload-time = "2026-01-06T11:45:19.497Z" }, -] - -[[package]] -name = "certifi" -version = "2026.1.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/e0/2d/a891ca51311197f6ad14a7ef42e2399f36cf2f9bd44752b3dc4eab60fdc5/certifi-2026.1.4.tar.gz", hash = "sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120", size = 154268, upload-time = "2026-01-04T02:42:41.825Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl", hash = "sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c", size = 152900, upload-time = "2026-01-04T02:42:40.15Z" }, -] - -[[package]] -name = "charset-normalizer" -version = "3.4.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/13/69/33ddede1939fdd074bce5434295f38fae7136463422fe4fd3e0e89b98062/charset_normalizer-3.4.4.tar.gz", hash = "sha256:94537985111c35f28720e43603b8e7b43a6ecfb2ce1d3058bbe955b73404e21a", size = 129418, upload-time = "2025-10-14T04:42:32.879Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/f3/85/1637cd4af66fa687396e757dec650f28025f2a2f5a5531a3208dc0ec43f2/charset_normalizer-3.4.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:0a98e6759f854bd25a58a73fa88833fba3b7c491169f86ce1180c948ab3fd394", size = 208425, upload-time = "2025-10-14T04:40:53.353Z" }, - { url = "https://files.pythonhosted.org/packages/9d/6a/04130023fef2a0d9c62d0bae2649b69f7b7d8d24ea5536feef50551029df/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5b290ccc2a263e8d185130284f8501e3e36c5e02750fc6b6bdeb2e9e96f1e25", size = 148162, upload-time = "2025-10-14T04:40:54.558Z" }, - { url = "https://files.pythonhosted.org/packages/78/29/62328d79aa60da22c9e0b9a66539feae06ca0f5a4171ac4f7dc285b83688/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74bb723680f9f7a6234dcf67aea57e708ec1fbdf5699fb91dfd6f511b0a320ef", size = 144558, upload-time = "2025-10-14T04:40:55.677Z" }, - { url = "https://files.pythonhosted.org/packages/86/bb/b32194a4bf15b88403537c2e120b817c61cd4ecffa9b6876e941c3ee38fe/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f1e34719c6ed0b92f418c7c780480b26b5d9c50349e9a9af7d76bf757530350d", size = 161497, upload-time = "2025-10-14T04:40:57.217Z" }, - { url = "https://files.pythonhosted.org/packages/19/89/a54c82b253d5b9b111dc74aca196ba5ccfcca8242d0fb64146d4d3183ff1/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2437418e20515acec67d86e12bf70056a33abdacb5cb1655042f6538d6b085a8", size = 159240, upload-time = "2025-10-14T04:40:58.358Z" }, - { url = "https://files.pythonhosted.org/packages/c0/10/d20b513afe03acc89ec33948320a5544d31f21b05368436d580dec4e234d/charset_normalizer-3.4.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11d694519d7f29d6cd09f6ac70028dba10f92f6cdd059096db198c283794ac86", size = 153471, upload-time = "2025-10-14T04:40:59.468Z" }, - { url = "https://files.pythonhosted.org/packages/61/fa/fbf177b55bdd727010f9c0a3c49eefa1d10f960e5f09d1d887bf93c2e698/charset_normalizer-3.4.4-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ac1c4a689edcc530fc9d9aa11f5774b9e2f33f9a0c6a57864e90908f5208d30a", size = 150864, upload-time = "2025-10-14T04:41:00.623Z" }, - { url = "https://files.pythonhosted.org/packages/05/12/9fbc6a4d39c0198adeebbde20b619790e9236557ca59fc40e0e3cebe6f40/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:21d142cc6c0ec30d2efee5068ca36c128a30b0f2c53c1c07bd78cb6bc1d3be5f", size = 150647, upload-time = "2025-10-14T04:41:01.754Z" }, - { url = "https://files.pythonhosted.org/packages/ad/1f/6a9a593d52e3e8c5d2b167daf8c6b968808efb57ef4c210acb907c365bc4/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:5dbe56a36425d26d6cfb40ce79c314a2e4dd6211d51d6d2191c00bed34f354cc", size = 145110, upload-time = "2025-10-14T04:41:03.231Z" }, - { url = "https://files.pythonhosted.org/packages/30/42/9a52c609e72471b0fc54386dc63c3781a387bb4fe61c20231a4ebcd58bdd/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:5bfbb1b9acf3334612667b61bd3002196fe2a1eb4dd74d247e0f2a4d50ec9bbf", size = 162839, upload-time = "2025-10-14T04:41:04.715Z" }, - { url = "https://files.pythonhosted.org/packages/c4/5b/c0682bbf9f11597073052628ddd38344a3d673fda35a36773f7d19344b23/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:d055ec1e26e441f6187acf818b73564e6e6282709e9bcb5b63f5b23068356a15", size = 150667, upload-time = "2025-10-14T04:41:05.827Z" }, - { url = "https://files.pythonhosted.org/packages/e4/24/a41afeab6f990cf2daf6cb8c67419b63b48cf518e4f56022230840c9bfb2/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:af2d8c67d8e573d6de5bc30cdb27e9b95e49115cd9baad5ddbd1a6207aaa82a9", size = 160535, upload-time = "2025-10-14T04:41:06.938Z" }, - { url = "https://files.pythonhosted.org/packages/2a/e5/6a4ce77ed243c4a50a1fecca6aaaab419628c818a49434be428fe24c9957/charset_normalizer-3.4.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:780236ac706e66881f3b7f2f32dfe90507a09e67d1d454c762cf642e6e1586e0", size = 154816, upload-time = "2025-10-14T04:41:08.101Z" }, - { url = "https://files.pythonhosted.org/packages/a8/ef/89297262b8092b312d29cdb2517cb1237e51db8ecef2e9af5edbe7b683b1/charset_normalizer-3.4.4-cp312-cp312-win32.whl", hash = "sha256:5833d2c39d8896e4e19b689ffc198f08ea58116bee26dea51e362ecc7cd3ed26", size = 99694, upload-time = "2025-10-14T04:41:09.23Z" }, - { url = "https://files.pythonhosted.org/packages/3d/2d/1e5ed9dd3b3803994c155cd9aacb60c82c331bad84daf75bcb9c91b3295e/charset_normalizer-3.4.4-cp312-cp312-win_amd64.whl", hash = "sha256:a79cfe37875f822425b89a82333404539ae63dbdddf97f84dcbc3d339aae9525", size = 107131, upload-time = "2025-10-14T04:41:10.467Z" }, - { url = "https://files.pythonhosted.org/packages/d0/d9/0ed4c7098a861482a7b6a95603edce4c0d9db2311af23da1fb2b75ec26fc/charset_normalizer-3.4.4-cp312-cp312-win_arm64.whl", hash = "sha256:376bec83a63b8021bb5c8ea75e21c4ccb86e7e45ca4eb81146091b56599b80c3", size = 100390, upload-time = "2025-10-14T04:41:11.915Z" }, - { url = "https://files.pythonhosted.org/packages/97/45/4b3a1239bbacd321068ea6e7ac28875b03ab8bc0aa0966452db17cd36714/charset_normalizer-3.4.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:e1f185f86a6f3403aa2420e815904c67b2f9ebc443f045edd0de921108345794", size = 208091, upload-time = "2025-10-14T04:41:13.346Z" }, - { url = "https://files.pythonhosted.org/packages/7d/62/73a6d7450829655a35bb88a88fca7d736f9882a27eacdca2c6d505b57e2e/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b39f987ae8ccdf0d2642338faf2abb1862340facc796048b604ef14919e55ed", size = 147936, upload-time = "2025-10-14T04:41:14.461Z" }, - { url = "https://files.pythonhosted.org/packages/89/c5/adb8c8b3d6625bef6d88b251bbb0d95f8205831b987631ab0c8bb5d937c2/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3162d5d8ce1bb98dd51af660f2121c55d0fa541b46dff7bb9b9f86ea1d87de72", size = 144180, upload-time = "2025-10-14T04:41:15.588Z" }, - { url = "https://files.pythonhosted.org/packages/91/ed/9706e4070682d1cc219050b6048bfd293ccf67b3d4f5a4f39207453d4b99/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:81d5eb2a312700f4ecaa977a8235b634ce853200e828fbadf3a9c50bab278328", size = 161346, upload-time = "2025-10-14T04:41:16.738Z" }, - { url = "https://files.pythonhosted.org/packages/d5/0d/031f0d95e4972901a2f6f09ef055751805ff541511dc1252ba3ca1f80cf5/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5bd2293095d766545ec1a8f612559f6b40abc0eb18bb2f5d1171872d34036ede", size = 158874, upload-time = "2025-10-14T04:41:17.923Z" }, - { url = "https://files.pythonhosted.org/packages/f5/83/6ab5883f57c9c801ce5e5677242328aa45592be8a00644310a008d04f922/charset_normalizer-3.4.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a8a8b89589086a25749f471e6a900d3f662d1d3b6e2e59dcecf787b1cc3a1894", size = 153076, upload-time = "2025-10-14T04:41:19.106Z" }, - { url = "https://files.pythonhosted.org/packages/75/1e/5ff781ddf5260e387d6419959ee89ef13878229732732ee73cdae01800f2/charset_normalizer-3.4.4-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bc7637e2f80d8530ee4a78e878bce464f70087ce73cf7c1caf142416923b98f1", size = 150601, upload-time = "2025-10-14T04:41:20.245Z" }, - { url = "https://files.pythonhosted.org/packages/d7/57/71be810965493d3510a6ca79b90c19e48696fb1ff964da319334b12677f0/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f8bf04158c6b607d747e93949aa60618b61312fe647a6369f88ce2ff16043490", size = 150376, upload-time = "2025-10-14T04:41:21.398Z" }, - { url = "https://files.pythonhosted.org/packages/e5/d5/c3d057a78c181d007014feb7e9f2e65905a6c4ef182c0ddf0de2924edd65/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:554af85e960429cf30784dd47447d5125aaa3b99a6f0683589dbd27e2f45da44", size = 144825, upload-time = "2025-10-14T04:41:22.583Z" }, - { url = "https://files.pythonhosted.org/packages/e6/8c/d0406294828d4976f275ffbe66f00266c4b3136b7506941d87c00cab5272/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:74018750915ee7ad843a774364e13a3db91682f26142baddf775342c3f5b1133", size = 162583, upload-time = "2025-10-14T04:41:23.754Z" }, - { url = "https://files.pythonhosted.org/packages/d7/24/e2aa1f18c8f15c4c0e932d9287b8609dd30ad56dbe41d926bd846e22fb8d/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:c0463276121fdee9c49b98908b3a89c39be45d86d1dbaa22957e38f6321d4ce3", size = 150366, upload-time = "2025-10-14T04:41:25.27Z" }, - { url = "https://files.pythonhosted.org/packages/e4/5b/1e6160c7739aad1e2df054300cc618b06bf784a7a164b0f238360721ab86/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:362d61fd13843997c1c446760ef36f240cf81d3ebf74ac62652aebaf7838561e", size = 160300, upload-time = "2025-10-14T04:41:26.725Z" }, - { url = "https://files.pythonhosted.org/packages/7a/10/f882167cd207fbdd743e55534d5d9620e095089d176d55cb22d5322f2afd/charset_normalizer-3.4.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9a26f18905b8dd5d685d6d07b0cdf98a79f3c7a918906af7cc143ea2e164c8bc", size = 154465, upload-time = "2025-10-14T04:41:28.322Z" }, - { url = "https://files.pythonhosted.org/packages/89/66/c7a9e1b7429be72123441bfdbaf2bc13faab3f90b933f664db506dea5915/charset_normalizer-3.4.4-cp313-cp313-win32.whl", hash = "sha256:9b35f4c90079ff2e2edc5b26c0c77925e5d2d255c42c74fdb70fb49b172726ac", size = 99404, upload-time = "2025-10-14T04:41:29.95Z" }, - { url = "https://files.pythonhosted.org/packages/c4/26/b9924fa27db384bdcd97ab83b4f0a8058d96ad9626ead570674d5e737d90/charset_normalizer-3.4.4-cp313-cp313-win_amd64.whl", hash = "sha256:b435cba5f4f750aa6c0a0d92c541fb79f69a387c91e61f1795227e4ed9cece14", size = 107092, upload-time = "2025-10-14T04:41:31.188Z" }, - { url = "https://files.pythonhosted.org/packages/af/8f/3ed4bfa0c0c72a7ca17f0380cd9e4dd842b09f664e780c13cff1dcf2ef1b/charset_normalizer-3.4.4-cp313-cp313-win_arm64.whl", hash = "sha256:542d2cee80be6f80247095cc36c418f7bddd14f4a6de45af91dfad36d817bba2", size = 100408, upload-time = "2025-10-14T04:41:32.624Z" }, - { url = "https://files.pythonhosted.org/packages/2a/35/7051599bd493e62411d6ede36fd5af83a38f37c4767b92884df7301db25d/charset_normalizer-3.4.4-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:da3326d9e65ef63a817ecbcc0df6e94463713b754fe293eaa03da99befb9a5bd", size = 207746, upload-time = "2025-10-14T04:41:33.773Z" }, - { url = "https://files.pythonhosted.org/packages/10/9a/97c8d48ef10d6cd4fcead2415523221624bf58bcf68a802721a6bc807c8f/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8af65f14dc14a79b924524b1e7fffe304517b2bff5a58bf64f30b98bbc5079eb", size = 147889, upload-time = "2025-10-14T04:41:34.897Z" }, - { url = "https://files.pythonhosted.org/packages/10/bf/979224a919a1b606c82bd2c5fa49b5c6d5727aa47b4312bb27b1734f53cd/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:74664978bb272435107de04e36db5a9735e78232b85b77d45cfb38f758efd33e", size = 143641, upload-time = "2025-10-14T04:41:36.116Z" }, - { url = "https://files.pythonhosted.org/packages/ba/33/0ad65587441fc730dc7bd90e9716b30b4702dc7b617e6ba4997dc8651495/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:752944c7ffbfdd10c074dc58ec2d5a8a4cd9493b314d367c14d24c17684ddd14", size = 160779, upload-time = "2025-10-14T04:41:37.229Z" }, - { url = "https://files.pythonhosted.org/packages/67/ed/331d6b249259ee71ddea93f6f2f0a56cfebd46938bde6fcc6f7b9a3d0e09/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1f13550535ad8cff21b8d757a3257963e951d96e20ec82ab44bc64aeb62a191", size = 159035, upload-time = "2025-10-14T04:41:38.368Z" }, - { url = "https://files.pythonhosted.org/packages/67/ff/f6b948ca32e4f2a4576aa129d8bed61f2e0543bf9f5f2b7fc3758ed005c9/charset_normalizer-3.4.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ecaae4149d99b1c9e7b88bb03e3221956f68fd6d50be2ef061b2381b61d20838", size = 152542, upload-time = "2025-10-14T04:41:39.862Z" }, - { url = "https://files.pythonhosted.org/packages/16/85/276033dcbcc369eb176594de22728541a925b2632f9716428c851b149e83/charset_normalizer-3.4.4-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cb6254dc36b47a990e59e1068afacdcd02958bdcce30bb50cc1700a8b9d624a6", size = 149524, upload-time = "2025-10-14T04:41:41.319Z" }, - { url = "https://files.pythonhosted.org/packages/9e/f2/6a2a1f722b6aba37050e626530a46a68f74e63683947a8acff92569f979a/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c8ae8a0f02f57a6e61203a31428fa1d677cbe50c93622b4149d5c0f319c1d19e", size = 150395, upload-time = "2025-10-14T04:41:42.539Z" }, - { url = "https://files.pythonhosted.org/packages/60/bb/2186cb2f2bbaea6338cad15ce23a67f9b0672929744381e28b0592676824/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:47cc91b2f4dd2833fddaedd2893006b0106129d4b94fdb6af1f4ce5a9965577c", size = 143680, upload-time = "2025-10-14T04:41:43.661Z" }, - { url = "https://files.pythonhosted.org/packages/7d/a5/bf6f13b772fbb2a90360eb620d52ed8f796f3c5caee8398c3b2eb7b1c60d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:82004af6c302b5d3ab2cfc4cc5f29db16123b1a8417f2e25f9066f91d4411090", size = 162045, upload-time = "2025-10-14T04:41:44.821Z" }, - { url = "https://files.pythonhosted.org/packages/df/c5/d1be898bf0dc3ef9030c3825e5d3b83f2c528d207d246cbabe245966808d/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2b7d8f6c26245217bd2ad053761201e9f9680f8ce52f0fcd8d0755aeae5b2152", size = 149687, upload-time = "2025-10-14T04:41:46.442Z" }, - { url = "https://files.pythonhosted.org/packages/a5/42/90c1f7b9341eef50c8a1cb3f098ac43b0508413f33affd762855f67a410e/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:799a7a5e4fb2d5898c60b640fd4981d6a25f1c11790935a44ce38c54e985f828", size = 160014, upload-time = "2025-10-14T04:41:47.631Z" }, - { url = "https://files.pythonhosted.org/packages/76/be/4d3ee471e8145d12795ab655ece37baed0929462a86e72372fd25859047c/charset_normalizer-3.4.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:99ae2cffebb06e6c22bdc25801d7b30f503cc87dbd283479e7b606f70aff57ec", size = 154044, upload-time = "2025-10-14T04:41:48.81Z" }, - { url = "https://files.pythonhosted.org/packages/b0/6f/8f7af07237c34a1defe7defc565a9bc1807762f672c0fde711a4b22bf9c0/charset_normalizer-3.4.4-cp314-cp314-win32.whl", hash = "sha256:f9d332f8c2a2fcbffe1378594431458ddbef721c1769d78e2cbc06280d8155f9", size = 99940, upload-time = "2025-10-14T04:41:49.946Z" }, - { url = "https://files.pythonhosted.org/packages/4b/51/8ade005e5ca5b0d80fb4aff72a3775b325bdc3d27408c8113811a7cbe640/charset_normalizer-3.4.4-cp314-cp314-win_amd64.whl", hash = "sha256:8a6562c3700cce886c5be75ade4a5db4214fda19fede41d9792d100288d8f94c", size = 107104, upload-time = "2025-10-14T04:41:51.051Z" }, - { url = "https://files.pythonhosted.org/packages/da/5f/6b8f83a55bb8278772c5ae54a577f3099025f9ade59d0136ac24a0df4bde/charset_normalizer-3.4.4-cp314-cp314-win_arm64.whl", hash = "sha256:de00632ca48df9daf77a2c65a484531649261ec9f25489917f09e455cb09ddb2", size = 100743, upload-time = "2025-10-14T04:41:52.122Z" }, - { url = "https://files.pythonhosted.org/packages/0a/4c/925909008ed5a988ccbb72dcc897407e5d6d3bd72410d69e051fc0c14647/charset_normalizer-3.4.4-py3-none-any.whl", hash = "sha256:7a32c560861a02ff789ad905a2fe94e3f840803362c84fecf1851cb4cf3dc37f", size = 53402, upload-time = "2025-10-14T04:42:31.76Z" }, -] - -[[package]] -name = "claude-monitor" -version = "3.1.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "numpy" }, - { name = "pydantic" }, - { name = "pydantic-settings" }, - { name = "pytz" }, - { name = "pyyaml" }, - { name = "rich" }, - { name = "tzdata", marker = "sys_platform == 'win32'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/1c/c7/e7b6969df3a474c19c85d53f56623d66fe0c9f3c81545ef1aad027b196cb/claude_monitor-3.1.0.tar.gz", hash = "sha256:9391e0efc01eb9643e46223e6f498b8d03e7c6a4f37ebba09c9f355a0453e7fc", size = 100561, upload-time = "2025-07-23T22:13:33.031Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/bf/ea/2a99169cee47a998b5a76e5419e6bfa3bb24bc2f81deea3fd4f3964e94ac/claude_monitor-3.1.0-py3-none-any.whl", hash = "sha256:587845e91f1d18f47da3d349266e689f9df6601ff83bee65e35429047c82de34", size = 93138, upload-time = "2025-07-23T22:13:31.389Z" }, -] - -[[package]] -name = "colorama" -version = "0.4.6" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, -] - -[[package]] -name = "coverage" -version = "7.13.5" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9d/e0/70553e3000e345daff267cec284ce4cbf3fc141b6da229ac52775b5428f1/coverage-7.13.5.tar.gz", hash = "sha256:c81f6515c4c40141f83f502b07bbfa5c240ba25bbe73da7b33f1e5b6120ff179", size = 915967, upload-time = "2026-03-17T10:33:18.341Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a0/c3/a396306ba7db865bf96fc1fb3b7fd29bcbf3d829df642e77b13555163cd6/coverage-7.13.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:460cf0114c5016fa841214ff5564aa4864f11948da9440bc97e21ad1f4ba1e01", size = 219554, upload-time = "2026-03-17T10:30:42.208Z" }, - { url = "https://files.pythonhosted.org/packages/a6/16/a68a19e5384e93f811dccc51034b1fd0b865841c390e3c931dcc4699e035/coverage-7.13.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0e223ce4b4ed47f065bfb123687686512e37629be25cc63728557ae7db261422", size = 219908, upload-time = "2026-03-17T10:30:43.906Z" }, - { url = "https://files.pythonhosted.org/packages/29/72/20b917c6793af3a5ceb7fb9c50033f3ec7865f2911a1416b34a7cfa0813b/coverage-7.13.5-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6e3370441f4513c6252bf042b9c36d22491142385049243253c7e48398a15a9f", size = 251419, upload-time = "2026-03-17T10:30:45.545Z" }, - { url = "https://files.pythonhosted.org/packages/8c/49/cd14b789536ac6a4778c453c6a2338bc0a2fb60c5a5a41b4008328b9acc1/coverage-7.13.5-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:03ccc709a17a1de074fb1d11f217342fb0d2b1582ed544f554fc9fc3f07e95f5", size = 254159, upload-time = "2026-03-17T10:30:47.204Z" }, - { url = "https://files.pythonhosted.org/packages/9d/00/7b0edcfe64e2ed4c0340dac14a52ad0f4c9bd0b8b5e531af7d55b703db7c/coverage-7.13.5-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3f4818d065964db3c1c66dc0fbdac5ac692ecbc875555e13374fdbe7eedb4376", size = 255270, upload-time = "2026-03-17T10:30:48.812Z" }, - { url = "https://files.pythonhosted.org/packages/93/89/7ffc4ba0f5d0a55c1e84ea7cee39c9fc06af7b170513d83fbf3bbefce280/coverage-7.13.5-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:012d5319e66e9d5a218834642d6c35d265515a62f01157a45bcc036ecf947256", size = 257538, upload-time = "2026-03-17T10:30:50.77Z" }, - { url = "https://files.pythonhosted.org/packages/81/bd/73ddf85f93f7e6fa83e77ccecb6162d9415c79007b4bc124008a4995e4a7/coverage-7.13.5-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8dd02af98971bdb956363e4827d34425cb3df19ee550ef92855b0acb9c7ce51c", size = 251821, upload-time = "2026-03-17T10:30:52.5Z" }, - { url = "https://files.pythonhosted.org/packages/a0/81/278aff4e8dec4926a0bcb9486320752811f543a3ce5b602cc7a29978d073/coverage-7.13.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:f08fd75c50a760c7eb068ae823777268daaf16a80b918fa58eea888f8e3919f5", size = 253191, upload-time = "2026-03-17T10:30:54.543Z" }, - { url = "https://files.pythonhosted.org/packages/70/ee/fe1621488e2e0a58d7e94c4800f0d96f79671553488d401a612bebae324b/coverage-7.13.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:843ea8643cf967d1ac7e8ecd4bb00c99135adf4816c0c0593fdcc47b597fcf09", size = 251337, upload-time = "2026-03-17T10:30:56.663Z" }, - { url = "https://files.pythonhosted.org/packages/37/a6/f79fb37aa104b562207cc23cb5711ab6793608e246cae1e93f26b2236ed9/coverage-7.13.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:9d44d7aa963820b1b971dbecd90bfe5fe8f81cff79787eb6cca15750bd2f79b9", size = 255404, upload-time = "2026-03-17T10:30:58.427Z" }, - { url = "https://files.pythonhosted.org/packages/75/f0/ed15262a58ec81ce457ceb717b7f78752a1713556b19081b76e90896e8d4/coverage-7.13.5-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:7132bed4bd7b836200c591410ae7d97bf7ae8be6fc87d160b2bd881df929e7bf", size = 250903, upload-time = "2026-03-17T10:31:00.093Z" }, - { url = "https://files.pythonhosted.org/packages/0f/e9/9129958f20e7e9d4d56d51d42ccf708d15cac355ff4ac6e736e97a9393d2/coverage-7.13.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a698e363641b98843c517817db75373c83254781426e94ada3197cabbc2c919c", size = 252780, upload-time = "2026-03-17T10:31:01.916Z" }, - { url = "https://files.pythonhosted.org/packages/a4/d7/0ad9b15812d81272db94379fe4c6df8fd17781cc7671fdfa30c76ba5ff7b/coverage-7.13.5-cp312-cp312-win32.whl", hash = "sha256:bdba0a6b8812e8c7df002d908a9a2ea3c36e92611b5708633c50869e6d922fdf", size = 222093, upload-time = "2026-03-17T10:31:03.642Z" }, - { url = "https://files.pythonhosted.org/packages/29/3d/821a9a5799fac2556bcf0bd37a70d1d11fa9e49784b6d22e92e8b2f85f18/coverage-7.13.5-cp312-cp312-win_amd64.whl", hash = "sha256:d2c87e0c473a10bffe991502eac389220533024c8082ec1ce849f4218dded810", size = 222900, upload-time = "2026-03-17T10:31:05.651Z" }, - { url = "https://files.pythonhosted.org/packages/d4/fa/2238c2ad08e35cf4f020ea721f717e09ec3152aea75d191a7faf3ef009a8/coverage-7.13.5-cp312-cp312-win_arm64.whl", hash = "sha256:bf69236a9a81bdca3bff53796237aab096cdbf8d78a66ad61e992d9dac7eb2de", size = 221515, upload-time = "2026-03-17T10:31:07.293Z" }, - { url = "https://files.pythonhosted.org/packages/74/8c/74fedc9663dcf168b0a059d4ea756ecae4da77a489048f94b5f512a8d0b3/coverage-7.13.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5ec4af212df513e399cf11610cc27063f1586419e814755ab362e50a85ea69c1", size = 219576, upload-time = "2026-03-17T10:31:09.045Z" }, - { url = "https://files.pythonhosted.org/packages/0c/c9/44fb661c55062f0818a6ffd2685c67aa30816200d5f2817543717d4b92eb/coverage-7.13.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:941617e518602e2d64942c88ec8499f7fbd49d3f6c4327d3a71d43a1973032f3", size = 219942, upload-time = "2026-03-17T10:31:10.708Z" }, - { url = "https://files.pythonhosted.org/packages/5f/13/93419671cee82b780bab7ea96b67c8ef448f5f295f36bf5031154ec9a790/coverage-7.13.5-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:da305e9937617ee95c2e39d8ff9f040e0487cbf1ac174f777ed5eddd7a7c1f26", size = 250935, upload-time = "2026-03-17T10:31:12.392Z" }, - { url = "https://files.pythonhosted.org/packages/ac/68/1666e3a4462f8202d836920114fa7a5ee9275d1fa45366d336c551a162dd/coverage-7.13.5-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:78e696e1cc714e57e8b25760b33a8b1026b7048d270140d25dafe1b0a1ee05a3", size = 253541, upload-time = "2026-03-17T10:31:14.247Z" }, - { url = "https://files.pythonhosted.org/packages/4e/5e/3ee3b835647be646dcf3c65a7c6c18f87c27326a858f72ab22c12730773d/coverage-7.13.5-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:02ca0eed225b2ff301c474aeeeae27d26e2537942aa0f87491d3e147e784a82b", size = 254780, upload-time = "2026-03-17T10:31:16.193Z" }, - { url = "https://files.pythonhosted.org/packages/44/b3/cb5bd1a04cfcc49ede6cd8409d80bee17661167686741e041abc7ee1b9a9/coverage-7.13.5-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:04690832cbea4e4663d9149e05dba142546ca05cb1848816760e7f58285c970a", size = 256912, upload-time = "2026-03-17T10:31:17.89Z" }, - { url = "https://files.pythonhosted.org/packages/1b/66/c1dceb7b9714473800b075f5c8a84f4588f887a90eb8645282031676e242/coverage-7.13.5-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0590e44dd2745c696a778f7bab6aa95256de2cbc8b8cff4f7db8ff09813d6969", size = 251165, upload-time = "2026-03-17T10:31:19.605Z" }, - { url = "https://files.pythonhosted.org/packages/b7/62/5502b73b97aa2e53ea22a39cf8649ff44827bef76d90bf638777daa27a9d/coverage-7.13.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d7cfad2d6d81dd298ab6b89fe72c3b7b05ec7544bdda3b707ddaecff8d25c161", size = 252908, upload-time = "2026-03-17T10:31:21.312Z" }, - { url = "https://files.pythonhosted.org/packages/7d/37/7792c2d69854397ca77a55c4646e5897c467928b0e27f2d235d83b5d08c6/coverage-7.13.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e092b9499de38ae0fbfbc603a74660eb6ff3e869e507b50d85a13b6db9863e15", size = 250873, upload-time = "2026-03-17T10:31:23.565Z" }, - { url = "https://files.pythonhosted.org/packages/a3/23/bc866fb6163be52a8a9e5d708ba0d3b1283c12158cefca0a8bbb6e247a43/coverage-7.13.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:48c39bc4a04d983a54a705a6389512883d4a3b9862991b3617d547940e9f52b1", size = 255030, upload-time = "2026-03-17T10:31:25.58Z" }, - { url = "https://files.pythonhosted.org/packages/7d/8b/ef67e1c222ef49860701d346b8bbb70881bef283bd5f6cbba68a39a086c7/coverage-7.13.5-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:2d3807015f138ffea1ed9afeeb8624fd781703f2858b62a8dd8da5a0994c57b6", size = 250694, upload-time = "2026-03-17T10:31:27.316Z" }, - { url = "https://files.pythonhosted.org/packages/46/0d/866d1f74f0acddbb906db212e096dee77a8e2158ca5e6bb44729f9d93298/coverage-7.13.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ee2aa19e03161671ec964004fb74b2257805d9710bf14a5c704558b9d8dbaf17", size = 252469, upload-time = "2026-03-17T10:31:29.472Z" }, - { url = "https://files.pythonhosted.org/packages/7a/f5/be742fec31118f02ce42b21c6af187ad6a344fed546b56ca60caacc6a9a0/coverage-7.13.5-cp313-cp313-win32.whl", hash = "sha256:ce1998c0483007608c8382f4ff50164bfc5bd07a2246dd272aa4043b75e61e85", size = 222112, upload-time = "2026-03-17T10:31:31.526Z" }, - { url = "https://files.pythonhosted.org/packages/66/40/7732d648ab9d069a46e686043241f01206348e2bbf128daea85be4d6414b/coverage-7.13.5-cp313-cp313-win_amd64.whl", hash = "sha256:631efb83f01569670a5e866ceb80fe483e7c159fac6f167e6571522636104a0b", size = 222923, upload-time = "2026-03-17T10:31:33.633Z" }, - { url = "https://files.pythonhosted.org/packages/48/af/fea819c12a095781f6ccd504890aaddaf88b8fab263c4940e82c7b770124/coverage-7.13.5-cp313-cp313-win_arm64.whl", hash = "sha256:f4cd16206ad171cbc2470dbea9103cf9a7607d5fe8c242fdf1edf36174020664", size = 221540, upload-time = "2026-03-17T10:31:35.445Z" }, - { url = "https://files.pythonhosted.org/packages/23/d2/17879af479df7fbbd44bd528a31692a48f6b25055d16482fdf5cdb633805/coverage-7.13.5-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:0428cbef5783ad91fe240f673cc1f76b25e74bbfe1a13115e4aa30d3f538162d", size = 220262, upload-time = "2026-03-17T10:31:37.184Z" }, - { url = "https://files.pythonhosted.org/packages/5b/4c/d20e554f988c8f91d6a02c5118f9abbbf73a8768a3048cb4962230d5743f/coverage-7.13.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e0b216a19534b2427cc201a26c25da4a48633f29a487c61258643e89d28200c0", size = 220617, upload-time = "2026-03-17T10:31:39.245Z" }, - { url = "https://files.pythonhosted.org/packages/29/9c/f9f5277b95184f764b24e7231e166dfdb5780a46d408a2ac665969416d61/coverage-7.13.5-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:972a9cd27894afe4bc2b1480107054e062df08e671df7c2f18c205e805ccd806", size = 261912, upload-time = "2026-03-17T10:31:41.324Z" }, - { url = "https://files.pythonhosted.org/packages/d5/f6/7f1ab39393eeb50cfe4747ae8ef0e4fc564b989225aa1152e13a180d74f8/coverage-7.13.5-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4b59148601efcd2bac8c4dbf1f0ad6391693ccf7a74b8205781751637076aee3", size = 263987, upload-time = "2026-03-17T10:31:43.724Z" }, - { url = "https://files.pythonhosted.org/packages/a0/d7/62c084fb489ed9c6fbdf57e006752e7c516ea46fd690e5ed8b8617c7d52e/coverage-7.13.5-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:505d7083c8b0c87a8fa8c07370c285847c1f77739b22e299ad75a6af6c32c5c9", size = 266416, upload-time = "2026-03-17T10:31:45.769Z" }, - { url = "https://files.pythonhosted.org/packages/a9/f6/df63d8660e1a0bff6125947afda112a0502736f470d62ca68b288ea762d8/coverage-7.13.5-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:60365289c3741e4db327e7baff2a4aaacf22f788e80fa4683393891b70a89fbd", size = 267558, upload-time = "2026-03-17T10:31:48.293Z" }, - { url = "https://files.pythonhosted.org/packages/5b/02/353ca81d36779bd108f6d384425f7139ac3c58c750dcfaafe5d0bee6436b/coverage-7.13.5-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:1b88c69c8ef5d4b6fe7dea66d6636056a0f6a7527c440e890cf9259011f5e606", size = 261163, upload-time = "2026-03-17T10:31:50.125Z" }, - { url = "https://files.pythonhosted.org/packages/2c/16/2e79106d5749bcaf3aee6d309123548e3276517cd7851faa8da213bc61bf/coverage-7.13.5-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5b13955d31d1633cf9376908089b7cebe7d15ddad7aeaabcbe969a595a97e95e", size = 263981, upload-time = "2026-03-17T10:31:51.961Z" }, - { url = "https://files.pythonhosted.org/packages/29/c7/c29e0c59ffa6942030ae6f50b88ae49988e7e8da06de7ecdbf49c6d4feae/coverage-7.13.5-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:f70c9ab2595c56f81a89620e22899eea8b212a4041bd728ac6f4a28bf5d3ddd0", size = 261604, upload-time = "2026-03-17T10:31:53.872Z" }, - { url = "https://files.pythonhosted.org/packages/40/48/097cdc3db342f34006a308ab41c3a7c11c3f0d84750d340f45d88a782e00/coverage-7.13.5-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:084b84a8c63e8d6fc7e3931b316a9bcafca1458d753c539db82d31ed20091a87", size = 265321, upload-time = "2026-03-17T10:31:55.997Z" }, - { url = "https://files.pythonhosted.org/packages/bb/1f/4994af354689e14fd03a75f8ec85a9a68d94e0188bbdab3fc1516b55e512/coverage-7.13.5-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:ad14385487393e386e2ea988b09d62dd42c397662ac2dabc3832d71253eee479", size = 260502, upload-time = "2026-03-17T10:31:58.308Z" }, - { url = "https://files.pythonhosted.org/packages/22/c6/9bb9ef55903e628033560885f5c31aa227e46878118b63ab15dc7ba87797/coverage-7.13.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:7f2c47b36fe7709a6e83bfadf4eefb90bd25fbe4014d715224c4316f808e59a2", size = 262688, upload-time = "2026-03-17T10:32:00.141Z" }, - { url = "https://files.pythonhosted.org/packages/14/4f/f5df9007e50b15e53e01edea486814783a7f019893733d9e4d6caad75557/coverage-7.13.5-cp313-cp313t-win32.whl", hash = "sha256:67e9bc5449801fad0e5dff329499fb090ba4c5800b86805c80617b4e29809b2a", size = 222788, upload-time = "2026-03-17T10:32:02.246Z" }, - { url = "https://files.pythonhosted.org/packages/e1/98/aa7fccaa97d0f3192bec013c4e6fd6d294a6ed44b640e6bb61f479e00ed5/coverage-7.13.5-cp313-cp313t-win_amd64.whl", hash = "sha256:da86cdcf10d2519e10cabb8ac2de03da1bcb6e4853790b7fbd48523332e3a819", size = 223851, upload-time = "2026-03-17T10:32:04.416Z" }, - { url = "https://files.pythonhosted.org/packages/3d/8b/e5c469f7352651e5f013198e9e21f97510b23de957dd06a84071683b4b60/coverage-7.13.5-cp313-cp313t-win_arm64.whl", hash = "sha256:0ecf12ecb326fe2c339d93fc131816f3a7367d223db37817208905c89bded911", size = 222104, upload-time = "2026-03-17T10:32:06.65Z" }, - { url = "https://files.pythonhosted.org/packages/8e/77/39703f0d1d4b478bfd30191d3c14f53caf596fac00efb3f8f6ee23646439/coverage-7.13.5-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fbabfaceaeb587e16f7008f7795cd80d20ec548dc7f94fbb0d4ec2e038ce563f", size = 219621, upload-time = "2026-03-17T10:32:08.589Z" }, - { url = "https://files.pythonhosted.org/packages/e2/3e/51dff36d99ae14639a133d9b164d63e628532e2974d8b1edb99dd1ebc733/coverage-7.13.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:9bb2a28101a443669a423b665939381084412b81c3f8c0fcfbac57f4e30b5b8e", size = 219953, upload-time = "2026-03-17T10:32:10.507Z" }, - { url = "https://files.pythonhosted.org/packages/6a/6c/1f1917b01eb647c2f2adc9962bd66c79eb978951cab61bdc1acab3290c07/coverage-7.13.5-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bd3a2fbc1c6cccb3c5106140d87cc6a8715110373ef42b63cf5aea29df8c217a", size = 250992, upload-time = "2026-03-17T10:32:12.41Z" }, - { url = "https://files.pythonhosted.org/packages/22/e5/06b1f88f42a5a99df42ce61208bdec3bddb3d261412874280a19796fc09c/coverage-7.13.5-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:6c36ddb64ed9d7e496028d1d00dfec3e428e0aabf4006583bb1839958d280510", size = 253503, upload-time = "2026-03-17T10:32:14.449Z" }, - { url = "https://files.pythonhosted.org/packages/80/28/2a148a51e5907e504fa7b85490277734e6771d8844ebcc48764a15e28155/coverage-7.13.5-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:380e8e9084d8eb38db3a9176a1a4f3c0082c3806fa0dc882d1d87abc3c789247", size = 254852, upload-time = "2026-03-17T10:32:16.56Z" }, - { url = "https://files.pythonhosted.org/packages/61/77/50e8d3d85cc0b7ebe09f30f151d670e302c7ff4a1bf6243f71dd8b0981fa/coverage-7.13.5-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e808af52a0513762df4d945ea164a24b37f2f518cbe97e03deaa0ee66139b4d6", size = 257161, upload-time = "2026-03-17T10:32:19.004Z" }, - { url = "https://files.pythonhosted.org/packages/3b/c4/b5fd1d4b7bf8d0e75d997afd3925c59ba629fc8616f1b3aae7605132e256/coverage-7.13.5-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e301d30dd7e95ae068671d746ba8c34e945a82682e62918e41b2679acd2051a0", size = 251021, upload-time = "2026-03-17T10:32:21.344Z" }, - { url = "https://files.pythonhosted.org/packages/f8/66/6ea21f910e92d69ef0b1c3346ea5922a51bad4446c9126db2ae96ee24c4c/coverage-7.13.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:800bc829053c80d240a687ceeb927a94fd108bbdc68dfbe505d0d75ab578a882", size = 252858, upload-time = "2026-03-17T10:32:23.506Z" }, - { url = "https://files.pythonhosted.org/packages/9e/ea/879c83cb5d61aa2a35fb80e72715e92672daef8191b84911a643f533840c/coverage-7.13.5-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:0b67af5492adb31940ee418a5a655c28e48165da5afab8c7fa6fd72a142f8740", size = 250823, upload-time = "2026-03-17T10:32:25.516Z" }, - { url = "https://files.pythonhosted.org/packages/8a/fb/616d95d3adb88b9803b275580bdeee8bd1b69a886d057652521f83d7322f/coverage-7.13.5-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c9136ff29c3a91e25b1d1552b5308e53a1e0653a23e53b6366d7c2dcbbaf8a16", size = 255099, upload-time = "2026-03-17T10:32:27.944Z" }, - { url = "https://files.pythonhosted.org/packages/1c/93/25e6917c90ec1c9a56b0b26f6cad6408e5f13bb6b35d484a0d75c9cf000d/coverage-7.13.5-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:cff784eef7f0b8f6cb28804fbddcfa99f89efe4cc35fb5627e3ac58f91ed3ac0", size = 250638, upload-time = "2026-03-17T10:32:29.914Z" }, - { url = "https://files.pythonhosted.org/packages/fc/7b/dc1776b0464145a929deed214aef9fb1493f159b59ff3c7eeeedf91eddd0/coverage-7.13.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:68a4953be99b17ac3c23b6efbc8a38330d99680c9458927491d18700ef23ded0", size = 252295, upload-time = "2026-03-17T10:32:31.981Z" }, - { url = "https://files.pythonhosted.org/packages/ea/fb/99cbbc56a26e07762a2740713f3c8f9f3f3106e3a3dd8cc4474954bccd34/coverage-7.13.5-cp314-cp314-win32.whl", hash = "sha256:35a31f2b1578185fbe6aa2e74cea1b1d0bbf4c552774247d9160d29b80ed56cc", size = 222360, upload-time = "2026-03-17T10:32:34.233Z" }, - { url = "https://files.pythonhosted.org/packages/8d/b7/4758d4f73fb536347cc5e4ad63662f9d60ba9118cb6785e9616b2ce5d7fa/coverage-7.13.5-cp314-cp314-win_amd64.whl", hash = "sha256:2aa055ae1857258f9e0045be26a6d62bdb47a72448b62d7b55f4820f361a2633", size = 223174, upload-time = "2026-03-17T10:32:36.369Z" }, - { url = "https://files.pythonhosted.org/packages/2c/f2/24d84e1dfe70f8ac9fdf30d338239860d0d1d5da0bda528959d0ebc9da28/coverage-7.13.5-cp314-cp314-win_arm64.whl", hash = "sha256:1b11eef33edeae9d142f9b4358edb76273b3bfd30bc3df9a4f95d0e49caf94e8", size = 221739, upload-time = "2026-03-17T10:32:38.736Z" }, - { url = "https://files.pythonhosted.org/packages/60/5b/4a168591057b3668c2428bff25dd3ebc21b629d666d90bcdfa0217940e84/coverage-7.13.5-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:10a0c37f0b646eaff7cce1874c31d1f1ccb297688d4c747291f4f4c70741cc8b", size = 220351, upload-time = "2026-03-17T10:32:41.196Z" }, - { url = "https://files.pythonhosted.org/packages/f5/21/1fd5c4dbfe4a58b6b99649125635df46decdfd4a784c3cd6d410d303e370/coverage-7.13.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b5db73ba3c41c7008037fa731ad5459fc3944cb7452fc0aa9f822ad3533c583c", size = 220612, upload-time = "2026-03-17T10:32:43.204Z" }, - { url = "https://files.pythonhosted.org/packages/d6/fe/2a924b3055a5e7e4512655a9d4609781b0d62334fa0140c3e742926834e2/coverage-7.13.5-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:750db93a81e3e5a9831b534be7b1229df848b2e125a604fe6651e48aa070e5f9", size = 261985, upload-time = "2026-03-17T10:32:45.514Z" }, - { url = "https://files.pythonhosted.org/packages/d7/0d/c8928f2bd518c45990fe1a2ab8db42e914ef9b726c975facc4282578c3eb/coverage-7.13.5-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9ddb4f4a5479f2539644be484da179b653273bca1a323947d48ab107b3ed1f29", size = 264107, upload-time = "2026-03-17T10:32:47.971Z" }, - { url = "https://files.pythonhosted.org/packages/ef/ae/4ae35bbd9a0af9d820362751f0766582833c211224b38665c0f8de3d487f/coverage-7.13.5-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8a7a2049c14f413163e2bdabd37e41179b1d1ccb10ffc6ccc4b7a718429c607", size = 266513, upload-time = "2026-03-17T10:32:50.1Z" }, - { url = "https://files.pythonhosted.org/packages/9c/20/d326174c55af36f74eac6ae781612d9492f060ce8244b570bb9d50d9d609/coverage-7.13.5-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e1c85e0b6c05c592ea6d8768a66a254bfb3874b53774b12d4c89c481eb78cb90", size = 267650, upload-time = "2026-03-17T10:32:52.391Z" }, - { url = "https://files.pythonhosted.org/packages/7a/5e/31484d62cbd0eabd3412e30d74386ece4a0837d4f6c3040a653878bfc019/coverage-7.13.5-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:777c4d1eff1b67876139d24288aaf1817f6c03d6bae9c5cc8d27b83bcfe38fe3", size = 261089, upload-time = "2026-03-17T10:32:54.544Z" }, - { url = "https://files.pythonhosted.org/packages/e9/d8/49a72d6de146eebb0b7e48cc0f4bc2c0dd858e3d4790ab2b39a2872b62bd/coverage-7.13.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6697e29b93707167687543480a40f0db8f356e86d9f67ddf2e37e2dfd91a9dab", size = 263982, upload-time = "2026-03-17T10:32:56.803Z" }, - { url = "https://files.pythonhosted.org/packages/06/3b/0351f1bd566e6e4dd39e978efe7958bde1d32f879e85589de147654f57bb/coverage-7.13.5-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:8fdf453a942c3e4d99bd80088141c4c6960bb232c409d9c3558e2dbaa3998562", size = 261579, upload-time = "2026-03-17T10:32:59.466Z" }, - { url = "https://files.pythonhosted.org/packages/5d/ce/796a2a2f4017f554d7810f5c573449b35b1e46788424a548d4d19201b222/coverage-7.13.5-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:32ca0c0114c9834a43f045a87dcebd69d108d8ffb666957ea65aa132f50332e2", size = 265316, upload-time = "2026-03-17T10:33:01.847Z" }, - { url = "https://files.pythonhosted.org/packages/3d/16/d5ae91455541d1a78bc90abf495be600588aff8f6db5c8b0dae739fa39c9/coverage-7.13.5-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:8769751c10f339021e2638cd354e13adeac54004d1941119b2c96fe5276d45ea", size = 260427, upload-time = "2026-03-17T10:33:03.945Z" }, - { url = "https://files.pythonhosted.org/packages/48/11/07f413dba62db21fb3fad5d0de013a50e073cc4e2dc4306e770360f6dfc8/coverage-7.13.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cec2d83125531bd153175354055cdb7a09987af08a9430bd173c937c6d0fba2a", size = 262745, upload-time = "2026-03-17T10:33:06.285Z" }, - { url = "https://files.pythonhosted.org/packages/91/15/d792371332eb4663115becf4bad47e047d16234b1aff687b1b18c58d60ae/coverage-7.13.5-cp314-cp314t-win32.whl", hash = "sha256:0cd9ed7a8b181775459296e402ca4fb27db1279740a24e93b3b41942ebe4b215", size = 223146, upload-time = "2026-03-17T10:33:08.756Z" }, - { url = "https://files.pythonhosted.org/packages/db/51/37221f59a111dca5e85be7dbf09696323b5b9f13ff65e0641d535ed06ea8/coverage-7.13.5-cp314-cp314t-win_amd64.whl", hash = "sha256:301e3b7dfefecaca37c9f1aa6f0049b7d4ab8dd933742b607765d757aca77d43", size = 224254, upload-time = "2026-03-17T10:33:11.174Z" }, - { url = "https://files.pythonhosted.org/packages/54/83/6acacc889de8987441aa7d5adfbdbf33d288dad28704a67e574f1df9bcbb/coverage-7.13.5-cp314-cp314t-win_arm64.whl", hash = "sha256:9dacc2ad679b292709e0f5fc1ac74a6d4d5562e424058962c7bb0c658ad25e45", size = 222276, upload-time = "2026-03-17T10:33:13.466Z" }, - { url = "https://files.pythonhosted.org/packages/9e/ee/a4cf96b8ce1e566ed238f0659ac2d3f007ed1d14b181bcb684e19561a69a/coverage-7.13.5-py3-none-any.whl", hash = "sha256:34b02417cf070e173989b3db962f7ed56d2f644307b2cf9d5a0f258e13084a61", size = 211346, upload-time = "2026-03-17T10:33:15.691Z" }, -] - -[[package]] -name = "croniter" -version = "6.0.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "python-dateutil" }, - { name = "pytz" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ad/2f/44d1ae153a0e27be56be43465e5cb39b9650c781e001e7864389deb25090/croniter-6.0.0.tar.gz", hash = "sha256:37c504b313956114a983ece2c2b07790b1f1094fe9d81cc94739214748255577", size = 64481, upload-time = "2024-12-17T17:17:47.32Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/07/4b/290b4c3efd6417a8b0c284896de19b1d5855e6dbdb97d2a35e68fa42de85/croniter-6.0.0-py2.py3-none-any.whl", hash = "sha256:2f878c3856f17896979b2a4379ba1f09c83e374931ea15cc835c5dd2eee9b368", size = 25468, upload-time = "2024-12-17T17:17:45.359Z" }, -] - -[[package]] -name = "h11" -version = "0.16.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/01/ee/02a2c011bdab74c6fb3c75474d40b3052059d95df7e73351460c8588d963/h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", size = 101250, upload-time = "2025-04-24T03:35:25.427Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/04/4b/29cac41a4d98d144bf5f6d33995617b185d14b22401f75ca86f384e87ff1/h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86", size = 37515, upload-time = "2025-04-24T03:35:24.344Z" }, -] - -[[package]] -name = "httpcore" -version = "1.0.9" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "certifi" }, - { name = "h11" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/06/94/82699a10bca87a5556c9c59b5963f2d039dbd239f25bc2a63907a05a14cb/httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8", size = 85484, upload-time = "2025-04-24T22:06:22.219Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/f5/f66802a942d491edb555dd61e3a9961140fd64c90bce1eafd741609d334d/httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", size = 78784, upload-time = "2025-04-24T22:06:20.566Z" }, -] - -[[package]] -name = "httpx" -version = "0.28.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "anyio" }, - { name = "certifi" }, - { name = "httpcore" }, - { name = "idna" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b1/df/48c586a5fe32a0f01324ee087459e112ebb7224f646c0b5023f5e79e9956/httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", size = 141406, upload-time = "2024-12-06T15:37:23.222Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/2a/39/e50c7c3a983047577ee07d2a9e53faf5a69493943ec3f6a384bdc792deb2/httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad", size = 73517, upload-time = "2024-12-06T15:37:21.509Z" }, -] - -[[package]] -name = "idna" -version = "3.11" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/6f/6d/0703ccc57f3a7233505399edb88de3cbd678da106337b9fcde432b65ed60/idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902", size = 194582, upload-time = "2025-10-12T14:55:20.501Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, -] - -[[package]] -name = "iniconfig" -version = "2.3.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" }, -] - -[[package]] -name = "lark-oapi" -version = "1.5.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "httpx" }, - { name = "pycryptodome" }, - { name = "requests" }, - { name = "requests-toolbelt" }, - { name = "websockets" }, -] -wheels = [ - { url = "https://files.pythonhosted.org/packages/bf/ff/2ece5d735ebfa2af600a53176f2636ae47af2bf934e08effab64f0d1e047/lark_oapi-1.5.3-py3-none-any.whl", hash = "sha256:fda6b32bb38d21b6bdaae94979c600b94c7c521e985adade63a54e4b3e20cc36", size = 6993016, upload-time = "2026-01-27T08:21:49.307Z" }, -] - -[[package]] -name = "macholib" -version = "1.16.4" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "altgraph" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/10/2f/97589876ea967487978071c9042518d28b958d87b17dceb7cdc1d881f963/macholib-1.16.4.tar.gz", hash = "sha256:f408c93ab2e995cd2c46e34fe328b130404be143469e41bc366c807448979362", size = 59427, upload-time = "2025-11-22T08:28:38.373Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c7/d1/a9f36f8ecdf0fb7c9b1e78c8d7af12b8c8754e74851ac7b94a8305540fc7/macholib-1.16.4-py2.py3-none-any.whl", hash = "sha256:da1a3fa8266e30f0ce7e97c6a54eefaae8edd1e5f86f3eb8b95457cae90265ea", size = 38117, upload-time = "2025-11-22T08:28:36.939Z" }, -] - -[[package]] -name = "markdown-it-py" -version = "4.0.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "mdurl" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" }, -] - -[[package]] -name = "mdurl" -version = "0.1.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, -] - -[[package]] -name = "numpy" -version = "2.4.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/57/fd/0005efbd0af48e55eb3c7208af93f2862d4b1a56cd78e84309a2d959208d/numpy-2.4.2.tar.gz", hash = "sha256:659a6107e31a83c4e33f763942275fd278b21d095094044eb35569e86a21ddae", size = 20723651, upload-time = "2026-01-31T23:13:10.135Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/51/6e/6f394c9c77668153e14d4da83bcc247beb5952f6ead7699a1a2992613bea/numpy-2.4.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:21982668592194c609de53ba4933a7471880ccbaadcc52352694a59ecc860b3a", size = 16667963, upload-time = "2026-01-31T23:10:52.147Z" }, - { url = "https://files.pythonhosted.org/packages/1f/f8/55483431f2b2fd015ae6ed4fe62288823ce908437ed49db5a03d15151678/numpy-2.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40397bda92382fcec844066efb11f13e1c9a3e2a8e8f318fb72ed8b6db9f60f1", size = 14693571, upload-time = "2026-01-31T23:10:54.789Z" }, - { url = "https://files.pythonhosted.org/packages/2f/20/18026832b1845cdc82248208dd929ca14c9d8f2bac391f67440707fff27c/numpy-2.4.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:b3a24467af63c67829bfaa61eecf18d5432d4f11992688537be59ecd6ad32f5e", size = 5203469, upload-time = "2026-01-31T23:10:57.343Z" }, - { url = "https://files.pythonhosted.org/packages/7d/33/2eb97c8a77daaba34eaa3fa7241a14ac5f51c46a6bd5911361b644c4a1e2/numpy-2.4.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:805cc8de9fd6e7a22da5aed858e0ab16be5a4db6c873dde1d7451c541553aa27", size = 6550820, upload-time = "2026-01-31T23:10:59.429Z" }, - { url = "https://files.pythonhosted.org/packages/b1/91/b97fdfd12dc75b02c44e26c6638241cc004d4079a0321a69c62f51470c4c/numpy-2.4.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d82351358ffbcdcd7b686b90742a9b86632d6c1c051016484fa0b326a0a1548", size = 15663067, upload-time = "2026-01-31T23:11:01.291Z" }, - { url = "https://files.pythonhosted.org/packages/f5/c6/a18e59f3f0b8071cc85cbc8d80cd02d68aa9710170b2553a117203d46936/numpy-2.4.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e35d3e0144137d9fdae62912e869136164534d64a169f86438bc9561b6ad49f", size = 16619782, upload-time = "2026-01-31T23:11:03.669Z" }, - { url = "https://files.pythonhosted.org/packages/b7/83/9751502164601a79e18847309f5ceec0b1446d7b6aa12305759b72cf98b2/numpy-2.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:adb6ed2ad29b9e15321d167d152ee909ec73395901b70936f029c3bc6d7f4460", size = 17013128, upload-time = "2026-01-31T23:11:05.913Z" }, - { url = "https://files.pythonhosted.org/packages/61/c4/c4066322256ec740acc1c8923a10047818691d2f8aec254798f3dd90f5f2/numpy-2.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8906e71fd8afcb76580404e2a950caef2685df3d2a57fe82a86ac8d33cc007ba", size = 18345324, upload-time = "2026-01-31T23:11:08.248Z" }, - { url = "https://files.pythonhosted.org/packages/ab/af/6157aa6da728fa4525a755bfad486ae7e3f76d4c1864138003eb84328497/numpy-2.4.2-cp312-cp312-win32.whl", hash = "sha256:ec055f6dae239a6299cace477b479cca2fc125c5675482daf1dd886933a1076f", size = 5960282, upload-time = "2026-01-31T23:11:10.497Z" }, - { url = "https://files.pythonhosted.org/packages/92/0f/7ceaaeaacb40567071e94dbf2c9480c0ae453d5bb4f52bea3892c39dc83c/numpy-2.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:209fae046e62d0ce6435fcfe3b1a10537e858249b3d9b05829e2a05218296a85", size = 12314210, upload-time = "2026-01-31T23:11:12.176Z" }, - { url = "https://files.pythonhosted.org/packages/2f/a3/56c5c604fae6dd40fa2ed3040d005fca97e91bd320d232ac9931d77ba13c/numpy-2.4.2-cp312-cp312-win_arm64.whl", hash = "sha256:fbde1b0c6e81d56f5dccd95dd4a711d9b95df1ae4009a60887e56b27e8d903fa", size = 10220171, upload-time = "2026-01-31T23:11:14.684Z" }, - { url = "https://files.pythonhosted.org/packages/a1/22/815b9fe25d1d7ae7d492152adbc7226d3eff731dffc38fe970589fcaaa38/numpy-2.4.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:25f2059807faea4b077a2b6837391b5d830864b3543627f381821c646f31a63c", size = 16663696, upload-time = "2026-01-31T23:11:17.516Z" }, - { url = "https://files.pythonhosted.org/packages/09/f0/817d03a03f93ba9c6c8993de509277d84e69f9453601915e4a69554102a1/numpy-2.4.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bd3a7a9f5847d2fb8c2c6d1c862fa109c31a9abeca1a3c2bd5a64572955b2979", size = 14688322, upload-time = "2026-01-31T23:11:19.883Z" }, - { url = "https://files.pythonhosted.org/packages/da/b4/f805ab79293c728b9a99438775ce51885fd4f31b76178767cfc718701a39/numpy-2.4.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:8e4549f8a3c6d13d55041925e912bfd834285ef1dd64d6bc7d542583355e2e98", size = 5198157, upload-time = "2026-01-31T23:11:22.375Z" }, - { url = "https://files.pythonhosted.org/packages/74/09/826e4289844eccdcd64aac27d13b0fd3f32039915dd5b9ba01baae1f436c/numpy-2.4.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:aea4f66ff44dfddf8c2cffd66ba6538c5ec67d389285292fe428cb2c738c8aef", size = 6546330, upload-time = "2026-01-31T23:11:23.958Z" }, - { url = "https://files.pythonhosted.org/packages/19/fb/cbfdbfa3057a10aea5422c558ac57538e6acc87ec1669e666d32ac198da7/numpy-2.4.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c3cd545784805de05aafe1dde61752ea49a359ccba9760c1e5d1c88a93bbf2b7", size = 15660968, upload-time = "2026-01-31T23:11:25.713Z" }, - { url = "https://files.pythonhosted.org/packages/04/dc/46066ce18d01645541f0186877377b9371b8fa8017fa8262002b4ef22612/numpy-2.4.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d0d9b7c93578baafcbc5f0b83eaf17b79d345c6f36917ba0c67f45226911d499", size = 16607311, upload-time = "2026-01-31T23:11:28.117Z" }, - { url = "https://files.pythonhosted.org/packages/14/d9/4b5adfc39a43fa6bf918c6d544bc60c05236cc2f6339847fc5b35e6cb5b0/numpy-2.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f74f0f7779cc7ae07d1810aab8ac6b1464c3eafb9e283a40da7309d5e6e48fbb", size = 17012850, upload-time = "2026-01-31T23:11:30.888Z" }, - { url = "https://files.pythonhosted.org/packages/b7/20/adb6e6adde6d0130046e6fdfb7675cc62bc2f6b7b02239a09eb58435753d/numpy-2.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c7ac672d699bf36275c035e16b65539931347d68b70667d28984c9fb34e07fa7", size = 18334210, upload-time = "2026-01-31T23:11:33.214Z" }, - { url = "https://files.pythonhosted.org/packages/78/0e/0a73b3dff26803a8c02baa76398015ea2a5434d9b8265a7898a6028c1591/numpy-2.4.2-cp313-cp313-win32.whl", hash = "sha256:8e9afaeb0beff068b4d9cd20d322ba0ee1cecfb0b08db145e4ab4dd44a6b5110", size = 5958199, upload-time = "2026-01-31T23:11:35.385Z" }, - { url = "https://files.pythonhosted.org/packages/43/bc/6352f343522fcb2c04dbaf94cb30cca6fd32c1a750c06ad6231b4293708c/numpy-2.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:7df2de1e4fba69a51c06c28f5a3de36731eb9639feb8e1cf7e4a7b0daf4cf622", size = 12310848, upload-time = "2026-01-31T23:11:38.001Z" }, - { url = "https://files.pythonhosted.org/packages/6e/8d/6da186483e308da5da1cc6918ce913dcfe14ffde98e710bfeff2a6158d4e/numpy-2.4.2-cp313-cp313-win_arm64.whl", hash = "sha256:0fece1d1f0a89c16b03442eae5c56dc0be0c7883b5d388e0c03f53019a4bfd71", size = 10221082, upload-time = "2026-01-31T23:11:40.392Z" }, - { url = "https://files.pythonhosted.org/packages/25/a1/9510aa43555b44781968935c7548a8926274f815de42ad3997e9e83680dd/numpy-2.4.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5633c0da313330fd20c484c78cdd3f9b175b55e1a766c4a174230c6b70ad8262", size = 14815866, upload-time = "2026-01-31T23:11:42.495Z" }, - { url = "https://files.pythonhosted.org/packages/36/30/6bbb5e76631a5ae46e7923dd16ca9d3f1c93cfa8d4ed79a129814a9d8db3/numpy-2.4.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:d9f64d786b3b1dd742c946c42d15b07497ed14af1a1f3ce840cce27daa0ce913", size = 5325631, upload-time = "2026-01-31T23:11:44.7Z" }, - { url = "https://files.pythonhosted.org/packages/46/00/3a490938800c1923b567b3a15cd17896e68052e2145d8662aaf3e1ffc58f/numpy-2.4.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:b21041e8cb6a1eb5312dd1d2f80a94d91efffb7a06b70597d44f1bd2dfc315ab", size = 6646254, upload-time = "2026-01-31T23:11:46.341Z" }, - { url = "https://files.pythonhosted.org/packages/d3/e9/fac0890149898a9b609caa5af7455a948b544746e4b8fe7c212c8edd71f8/numpy-2.4.2-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:00ab83c56211a1d7c07c25e3217ea6695e50a3e2f255053686b081dc0b091a82", size = 15720138, upload-time = "2026-01-31T23:11:48.082Z" }, - { url = "https://files.pythonhosted.org/packages/ea/5c/08887c54e68e1e28df53709f1893ce92932cc6f01f7c3d4dc952f61ffd4e/numpy-2.4.2-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2fb882da679409066b4603579619341c6d6898fc83a8995199d5249f986e8e8f", size = 16655398, upload-time = "2026-01-31T23:11:50.293Z" }, - { url = "https://files.pythonhosted.org/packages/4d/89/253db0fa0e66e9129c745e4ef25631dc37d5f1314dad2b53e907b8538e6d/numpy-2.4.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:66cb9422236317f9d44b67b4d18f44efe6e9c7f8794ac0462978513359461554", size = 17079064, upload-time = "2026-01-31T23:11:52.927Z" }, - { url = "https://files.pythonhosted.org/packages/2a/d5/cbade46ce97c59c6c3da525e8d95b7abe8a42974a1dc5c1d489c10433e88/numpy-2.4.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0f01dcf33e73d80bd8dc0f20a71303abbafa26a19e23f6b68d1aa9990af90257", size = 18379680, upload-time = "2026-01-31T23:11:55.22Z" }, - { url = "https://files.pythonhosted.org/packages/40/62/48f99ae172a4b63d981babe683685030e8a3df4f246c893ea5c6ef99f018/numpy-2.4.2-cp313-cp313t-win32.whl", hash = "sha256:52b913ec40ff7ae845687b0b34d8d93b60cb66dcee06996dd5c99f2fc9328657", size = 6082433, upload-time = "2026-01-31T23:11:58.096Z" }, - { url = "https://files.pythonhosted.org/packages/07/38/e054a61cfe48ad9f1ed0d188e78b7e26859d0b60ef21cd9de4897cdb5326/numpy-2.4.2-cp313-cp313t-win_amd64.whl", hash = "sha256:5eea80d908b2c1f91486eb95b3fb6fab187e569ec9752ab7d9333d2e66bf2d6b", size = 12451181, upload-time = "2026-01-31T23:11:59.782Z" }, - { url = "https://files.pythonhosted.org/packages/6e/a4/a05c3a6418575e185dd84d0b9680b6bb2e2dc3e4202f036b7b4e22d6e9dc/numpy-2.4.2-cp313-cp313t-win_arm64.whl", hash = "sha256:fd49860271d52127d61197bb50b64f58454e9f578cb4b2c001a6de8b1f50b0b1", size = 10290756, upload-time = "2026-01-31T23:12:02.438Z" }, - { url = "https://files.pythonhosted.org/packages/18/88/b7df6050bf18fdcfb7046286c6535cabbdd2064a3440fca3f069d319c16e/numpy-2.4.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:444be170853f1f9d528428eceb55f12918e4fda5d8805480f36a002f1415e09b", size = 16663092, upload-time = "2026-01-31T23:12:04.521Z" }, - { url = "https://files.pythonhosted.org/packages/25/7a/1fee4329abc705a469a4afe6e69b1ef7e915117747886327104a8493a955/numpy-2.4.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d1240d50adff70c2a88217698ca844723068533f3f5c5fa6ee2e3220e3bdb000", size = 14698770, upload-time = "2026-01-31T23:12:06.96Z" }, - { url = "https://files.pythonhosted.org/packages/fb/0b/f9e49ba6c923678ad5bc38181c08ac5e53b7a5754dbca8e581aa1a56b1ff/numpy-2.4.2-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:7cdde6de52fb6664b00b056341265441192d1291c130e99183ec0d4b110ff8b1", size = 5208562, upload-time = "2026-01-31T23:12:09.632Z" }, - { url = "https://files.pythonhosted.org/packages/7d/12/d7de8f6f53f9bb76997e5e4c069eda2051e3fe134e9181671c4391677bb2/numpy-2.4.2-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:cda077c2e5b780200b6b3e09d0b42205a3d1c68f30c6dceb90401c13bff8fe74", size = 6543710, upload-time = "2026-01-31T23:12:11.969Z" }, - { url = "https://files.pythonhosted.org/packages/09/63/c66418c2e0268a31a4cf8a8b512685748200f8e8e8ec6c507ce14e773529/numpy-2.4.2-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d30291931c915b2ab5717c2974bb95ee891a1cf22ebc16a8006bd59cd210d40a", size = 15677205, upload-time = "2026-01-31T23:12:14.33Z" }, - { url = "https://files.pythonhosted.org/packages/5d/6c/7f237821c9642fb2a04d2f1e88b4295677144ca93285fd76eff3bcba858d/numpy-2.4.2-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bba37bc29d4d85761deed3954a1bc62be7cf462b9510b51d367b769a8c8df325", size = 16611738, upload-time = "2026-01-31T23:12:16.525Z" }, - { url = "https://files.pythonhosted.org/packages/c2/a7/39c4cdda9f019b609b5c473899d87abff092fc908cfe4d1ecb2fcff453b0/numpy-2.4.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b2f0073ed0868db1dcd86e052d37279eef185b9c8db5bf61f30f46adac63c909", size = 17028888, upload-time = "2026-01-31T23:12:19.306Z" }, - { url = "https://files.pythonhosted.org/packages/da/b3/e84bb64bdfea967cc10950d71090ec2d84b49bc691df0025dddb7c26e8e3/numpy-2.4.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7f54844851cdb630ceb623dcec4db3240d1ac13d4990532446761baede94996a", size = 18339556, upload-time = "2026-01-31T23:12:21.816Z" }, - { url = "https://files.pythonhosted.org/packages/88/f5/954a291bc1192a27081706862ac62bb5920fbecfbaa302f64682aa90beed/numpy-2.4.2-cp314-cp314-win32.whl", hash = "sha256:12e26134a0331d8dbd9351620f037ec470b7c75929cb8a1537f6bfe411152a1a", size = 6006899, upload-time = "2026-01-31T23:12:24.14Z" }, - { url = "https://files.pythonhosted.org/packages/05/cb/eff72a91b2efdd1bc98b3b8759f6a1654aa87612fc86e3d87d6fe4f948c4/numpy-2.4.2-cp314-cp314-win_amd64.whl", hash = "sha256:068cdb2d0d644cdb45670810894f6a0600797a69c05f1ac478e8d31670b8ee75", size = 12443072, upload-time = "2026-01-31T23:12:26.33Z" }, - { url = "https://files.pythonhosted.org/packages/37/75/62726948db36a56428fce4ba80a115716dc4fad6a3a4352487f8bb950966/numpy-2.4.2-cp314-cp314-win_arm64.whl", hash = "sha256:6ed0be1ee58eef41231a5c943d7d1375f093142702d5723ca2eb07db9b934b05", size = 10494886, upload-time = "2026-01-31T23:12:28.488Z" }, - { url = "https://files.pythonhosted.org/packages/36/2f/ee93744f1e0661dc267e4b21940870cabfae187c092e1433b77b09b50ac4/numpy-2.4.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:98f16a80e917003a12c0580f97b5f875853ebc33e2eaa4bccfc8201ac6869308", size = 14818567, upload-time = "2026-01-31T23:12:30.709Z" }, - { url = "https://files.pythonhosted.org/packages/a7/24/6535212add7d76ff938d8bdc654f53f88d35cddedf807a599e180dcb8e66/numpy-2.4.2-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:20abd069b9cda45874498b245c8015b18ace6de8546bf50dfa8cea1696ed06ef", size = 5328372, upload-time = "2026-01-31T23:12:32.962Z" }, - { url = "https://files.pythonhosted.org/packages/5e/9d/c48f0a035725f925634bf6b8994253b43f2047f6778a54147d7e213bc5a7/numpy-2.4.2-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:e98c97502435b53741540a5717a6749ac2ada901056c7db951d33e11c885cc7d", size = 6649306, upload-time = "2026-01-31T23:12:34.797Z" }, - { url = "https://files.pythonhosted.org/packages/81/05/7c73a9574cd4a53a25907bad38b59ac83919c0ddc8234ec157f344d57d9a/numpy-2.4.2-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:da6cad4e82cb893db4b69105c604d805e0c3ce11501a55b5e9f9083b47d2ffe8", size = 15722394, upload-time = "2026-01-31T23:12:36.565Z" }, - { url = "https://files.pythonhosted.org/packages/35/fa/4de10089f21fc7d18442c4a767ab156b25c2a6eaf187c0db6d9ecdaeb43f/numpy-2.4.2-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e4424677ce4b47fe73c8b5556d876571f7c6945d264201180db2dc34f676ab5", size = 16653343, upload-time = "2026-01-31T23:12:39.188Z" }, - { url = "https://files.pythonhosted.org/packages/b8/f9/d33e4ffc857f3763a57aa85650f2e82486832d7492280ac21ba9efda80da/numpy-2.4.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2b8f157c8a6f20eb657e240f8985cc135598b2b46985c5bccbde7616dc9c6b1e", size = 17078045, upload-time = "2026-01-31T23:12:42.041Z" }, - { url = "https://files.pythonhosted.org/packages/c8/b8/54bdb43b6225badbea6389fa038c4ef868c44f5890f95dd530a218706da3/numpy-2.4.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5daf6f3914a733336dab21a05cdec343144600e964d2fcdabaac0c0269874b2a", size = 18380024, upload-time = "2026-01-31T23:12:44.331Z" }, - { url = "https://files.pythonhosted.org/packages/a5/55/6e1a61ded7af8df04016d81b5b02daa59f2ea9252ee0397cb9f631efe9e5/numpy-2.4.2-cp314-cp314t-win32.whl", hash = "sha256:8c50dd1fc8826f5b26a5ee4d77ca55d88a895f4e4819c7ecc2a9f5905047a443", size = 6153937, upload-time = "2026-01-31T23:12:47.229Z" }, - { url = "https://files.pythonhosted.org/packages/45/aa/fa6118d1ed6d776b0983f3ceac9b1a5558e80df9365b1c3aa6d42bf9eee4/numpy-2.4.2-cp314-cp314t-win_amd64.whl", hash = "sha256:fcf92bee92742edd401ba41135185866f7026c502617f422eb432cfeca4fe236", size = 12631844, upload-time = "2026-01-31T23:12:48.997Z" }, - { url = "https://files.pythonhosted.org/packages/32/0a/2ec5deea6dcd158f254a7b372fb09cfba5719419c8d66343bab35237b3fb/numpy-2.4.2-cp314-cp314t-win_arm64.whl", hash = "sha256:1f92f53998a17265194018d1cc321b2e96e900ca52d54c7c77837b71b9465181", size = 10565379, upload-time = "2026-01-31T23:12:51.345Z" }, -] - -[[package]] -name = "packaging" -version = "26.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/65/ee/299d360cdc32edc7d2cf530f3accf79c4fca01e96ffc950d8a52213bd8e4/packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", size = 143416, upload-time = "2026-01-21T20:50:39.064Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529", size = 74366, upload-time = "2026-01-21T20:50:37.788Z" }, -] - -[[package]] -name = "pefile" -version = "2024.8.26" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/03/4f/2750f7f6f025a1507cd3b7218691671eecfd0bbebebe8b39aa0fe1d360b8/pefile-2024.8.26.tar.gz", hash = "sha256:3ff6c5d8b43e8c37bb6e6dd5085658d658a7a0bdcd20b6a07b1fcfc1c4e9d632", size = 76008, upload-time = "2024-08-26T20:58:38.155Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/54/16/12b82f791c7f50ddec566873d5bdd245baa1491bac11d15ffb98aecc8f8b/pefile-2024.8.26-py3-none-any.whl", hash = "sha256:76f8b485dcd3b1bb8166f1128d395fa3d87af26360c2358fb75b80019b957c6f", size = 74766, upload-time = "2024-08-26T21:01:02.632Z" }, -] - -[[package]] -name = "pluggy" -version = "1.6.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, -] - -[[package]] -name = "pycryptodome" -version = "3.23.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/8e/a6/8452177684d5e906854776276ddd34eca30d1b1e15aa1ee9cefc289a33f5/pycryptodome-3.23.0.tar.gz", hash = "sha256:447700a657182d60338bab09fdb27518f8856aecd80ae4c6bdddb67ff5da44ef", size = 4921276, upload-time = "2025-05-17T17:21:45.242Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/04/5d/bdb09489b63cd34a976cc9e2a8d938114f7a53a74d3dd4f125ffa49dce82/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:0011f7f00cdb74879142011f95133274741778abba114ceca229adbf8e62c3e4", size = 2495152, upload-time = "2025-05-17T17:20:20.833Z" }, - { url = "https://files.pythonhosted.org/packages/a7/ce/7840250ed4cc0039c433cd41715536f926d6e86ce84e904068eb3244b6a6/pycryptodome-3.23.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:90460fc9e088ce095f9ee8356722d4f10f86e5be06e2354230a9880b9c549aae", size = 1639348, upload-time = "2025-05-17T17:20:23.171Z" }, - { url = "https://files.pythonhosted.org/packages/ee/f0/991da24c55c1f688d6a3b5a11940567353f74590734ee4a64294834ae472/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4764e64b269fc83b00f682c47443c2e6e85b18273712b98aa43bcb77f8570477", size = 2184033, upload-time = "2025-05-17T17:20:25.424Z" }, - { url = "https://files.pythonhosted.org/packages/54/16/0e11882deddf00f68b68dd4e8e442ddc30641f31afeb2bc25588124ac8de/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb8f24adb74984aa0e5d07a2368ad95276cf38051fe2dc6605cbcf482e04f2a7", size = 2270142, upload-time = "2025-05-17T17:20:27.808Z" }, - { url = "https://files.pythonhosted.org/packages/d5/fc/4347fea23a3f95ffb931f383ff28b3f7b1fe868739182cb76718c0da86a1/pycryptodome-3.23.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d97618c9c6684a97ef7637ba43bdf6663a2e2e77efe0f863cce97a76af396446", size = 2309384, upload-time = "2025-05-17T17:20:30.765Z" }, - { url = "https://files.pythonhosted.org/packages/6e/d9/c5261780b69ce66d8cfab25d2797bd6e82ba0241804694cd48be41add5eb/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9a53a4fe5cb075075d515797d6ce2f56772ea7e6a1e5e4b96cf78a14bac3d265", size = 2183237, upload-time = "2025-05-17T17:20:33.736Z" }, - { url = "https://files.pythonhosted.org/packages/5a/6f/3af2ffedd5cfa08c631f89452c6648c4d779e7772dfc388c77c920ca6bbf/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:763d1d74f56f031788e5d307029caef067febf890cd1f8bf61183ae142f1a77b", size = 2343898, upload-time = "2025-05-17T17:20:36.086Z" }, - { url = "https://files.pythonhosted.org/packages/9a/dc/9060d807039ee5de6e2f260f72f3d70ac213993a804f5e67e0a73a56dd2f/pycryptodome-3.23.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:954af0e2bd7cea83ce72243b14e4fb518b18f0c1649b576d114973e2073b273d", size = 2269197, upload-time = "2025-05-17T17:20:38.414Z" }, - { url = "https://files.pythonhosted.org/packages/f9/34/e6c8ca177cb29dcc4967fef73f5de445912f93bd0343c9c33c8e5bf8cde8/pycryptodome-3.23.0-cp313-cp313t-win32.whl", hash = "sha256:257bb3572c63ad8ba40b89f6fc9d63a2a628e9f9708d31ee26560925ebe0210a", size = 1768600, upload-time = "2025-05-17T17:20:40.688Z" }, - { url = "https://files.pythonhosted.org/packages/e4/1d/89756b8d7ff623ad0160f4539da571d1f594d21ee6d68be130a6eccb39a4/pycryptodome-3.23.0-cp313-cp313t-win_amd64.whl", hash = "sha256:6501790c5b62a29fcb227bd6b62012181d886a767ce9ed03b303d1f22eb5c625", size = 1799740, upload-time = "2025-05-17T17:20:42.413Z" }, - { url = "https://files.pythonhosted.org/packages/5d/61/35a64f0feaea9fd07f0d91209e7be91726eb48c0f1bfc6720647194071e4/pycryptodome-3.23.0-cp313-cp313t-win_arm64.whl", hash = "sha256:9a77627a330ab23ca43b48b130e202582e91cc69619947840ea4d2d1be21eb39", size = 1703685, upload-time = "2025-05-17T17:20:44.388Z" }, - { url = "https://files.pythonhosted.org/packages/db/6c/a1f71542c969912bb0e106f64f60a56cc1f0fabecf9396f45accbe63fa68/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:187058ab80b3281b1de11c2e6842a357a1f71b42cb1e15bce373f3d238135c27", size = 2495627, upload-time = "2025-05-17T17:20:47.139Z" }, - { url = "https://files.pythonhosted.org/packages/6e/4e/a066527e079fc5002390c8acdd3aca431e6ea0a50ffd7201551175b47323/pycryptodome-3.23.0-cp37-abi3-macosx_10_9_x86_64.whl", hash = "sha256:cfb5cd445280c5b0a4e6187a7ce8de5a07b5f3f897f235caa11f1f435f182843", size = 1640362, upload-time = "2025-05-17T17:20:50.392Z" }, - { url = "https://files.pythonhosted.org/packages/50/52/adaf4c8c100a8c49d2bd058e5b551f73dfd8cb89eb4911e25a0c469b6b4e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:67bd81fcbe34f43ad9422ee8fd4843c8e7198dd88dd3d40e6de42ee65fbe1490", size = 2182625, upload-time = "2025-05-17T17:20:52.866Z" }, - { url = "https://files.pythonhosted.org/packages/5f/e9/a09476d436d0ff1402ac3867d933c61805ec2326c6ea557aeeac3825604e/pycryptodome-3.23.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8987bd3307a39bc03df5c8e0e3d8be0c4c3518b7f044b0f4c15d1aa78f52575", size = 2268954, upload-time = "2025-05-17T17:20:55.027Z" }, - { url = "https://files.pythonhosted.org/packages/f9/c5/ffe6474e0c551d54cab931918127c46d70cab8f114e0c2b5a3c071c2f484/pycryptodome-3.23.0-cp37-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa0698f65e5b570426fc31b8162ed4603b0c2841cbb9088e2b01641e3065915b", size = 2308534, upload-time = "2025-05-17T17:20:57.279Z" }, - { url = "https://files.pythonhosted.org/packages/18/28/e199677fc15ecf43010f2463fde4c1a53015d1fe95fb03bca2890836603a/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:53ecbafc2b55353edcebd64bf5da94a2a2cdf5090a6915bcca6eca6cc452585a", size = 2181853, upload-time = "2025-05-17T17:20:59.322Z" }, - { url = "https://files.pythonhosted.org/packages/ce/ea/4fdb09f2165ce1365c9eaefef36625583371ee514db58dc9b65d3a255c4c/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_i686.whl", hash = "sha256:156df9667ad9f2ad26255926524e1c136d6664b741547deb0a86a9acf5ea631f", size = 2342465, upload-time = "2025-05-17T17:21:03.83Z" }, - { url = "https://files.pythonhosted.org/packages/22/82/6edc3fc42fe9284aead511394bac167693fb2b0e0395b28b8bedaa07ef04/pycryptodome-3.23.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:dea827b4d55ee390dc89b2afe5927d4308a8b538ae91d9c6f7a5090f397af1aa", size = 2267414, upload-time = "2025-05-17T17:21:06.72Z" }, - { url = "https://files.pythonhosted.org/packages/59/fe/aae679b64363eb78326c7fdc9d06ec3de18bac68be4b612fc1fe8902693c/pycryptodome-3.23.0-cp37-abi3-win32.whl", hash = "sha256:507dbead45474b62b2bbe318eb1c4c8ee641077532067fec9c1aa82c31f84886", size = 1768484, upload-time = "2025-05-17T17:21:08.535Z" }, - { url = "https://files.pythonhosted.org/packages/54/2f/e97a1b8294db0daaa87012c24a7bb714147c7ade7656973fd6c736b484ff/pycryptodome-3.23.0-cp37-abi3-win_amd64.whl", hash = "sha256:c75b52aacc6c0c260f204cbdd834f76edc9fb0d8e0da9fbf8352ef58202564e2", size = 1799636, upload-time = "2025-05-17T17:21:10.393Z" }, - { url = "https://files.pythonhosted.org/packages/18/3d/f9441a0d798bf2b1e645adc3265e55706aead1255ccdad3856dbdcffec14/pycryptodome-3.23.0-cp37-abi3-win_arm64.whl", hash = "sha256:11eeeb6917903876f134b56ba11abe95c0b0fd5e3330def218083c7d98bbcb3c", size = 1703675, upload-time = "2025-05-17T17:21:13.146Z" }, -] - -[[package]] -name = "pydantic" -version = "2.12.5" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "annotated-types" }, - { name = "pydantic-core" }, - { name = "typing-extensions" }, - { name = "typing-inspection" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/69/44/36f1a6e523abc58ae5f928898e4aca2e0ea509b5aa6f6f392a5d882be928/pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49", size = 821591, upload-time = "2025-11-26T15:11:46.471Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d", size = 463580, upload-time = "2025-11-26T15:11:44.605Z" }, -] - -[[package]] -name = "pydantic-core" -version = "2.41.5" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/71/70/23b021c950c2addd24ec408e9ab05d59b035b39d97cdc1130e1bce647bb6/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", size = 460952, upload-time = "2025-11-04T13:43:49.098Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/5f/5d/5f6c63eebb5afee93bcaae4ce9a898f3373ca23df3ccaef086d0233a35a7/pydantic_core-2.41.5-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f41a7489d32336dbf2199c8c0a215390a751c5b014c2c1c5366e817202e9cdf7", size = 2110990, upload-time = "2025-11-04T13:39:58.079Z" }, - { url = "https://files.pythonhosted.org/packages/aa/32/9c2e8ccb57c01111e0fd091f236c7b371c1bccea0fa85247ac55b1e2b6b6/pydantic_core-2.41.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:070259a8818988b9a84a449a2a7337c7f430a22acc0859c6b110aa7212a6d9c0", size = 1896003, upload-time = "2025-11-04T13:39:59.956Z" }, - { url = "https://files.pythonhosted.org/packages/68/b8/a01b53cb0e59139fbc9e4fda3e9724ede8de279097179be4ff31f1abb65a/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e96cea19e34778f8d59fe40775a7a574d95816eb150850a85a7a4c8f4b94ac69", size = 1919200, upload-time = "2025-11-04T13:40:02.241Z" }, - { url = "https://files.pythonhosted.org/packages/38/de/8c36b5198a29bdaade07b5985e80a233a5ac27137846f3bc2d3b40a47360/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ed2e99c456e3fadd05c991f8f437ef902e00eedf34320ba2b0842bd1c3ca3a75", size = 2052578, upload-time = "2025-11-04T13:40:04.401Z" }, - { url = "https://files.pythonhosted.org/packages/00/b5/0e8e4b5b081eac6cb3dbb7e60a65907549a1ce035a724368c330112adfdd/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65840751b72fbfd82c3c640cff9284545342a4f1eb1586ad0636955b261b0b05", size = 2208504, upload-time = "2025-11-04T13:40:06.072Z" }, - { url = "https://files.pythonhosted.org/packages/77/56/87a61aad59c7c5b9dc8caad5a41a5545cba3810c3e828708b3d7404f6cef/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e536c98a7626a98feb2d3eaf75944ef6f3dbee447e1f841eae16f2f0a72d8ddc", size = 2335816, upload-time = "2025-11-04T13:40:07.835Z" }, - { url = "https://files.pythonhosted.org/packages/0d/76/941cc9f73529988688a665a5c0ecff1112b3d95ab48f81db5f7606f522d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eceb81a8d74f9267ef4081e246ffd6d129da5d87e37a77c9bde550cb04870c1c", size = 2075366, upload-time = "2025-11-04T13:40:09.804Z" }, - { url = "https://files.pythonhosted.org/packages/d3/43/ebef01f69baa07a482844faaa0a591bad1ef129253ffd0cdaa9d8a7f72d3/pydantic_core-2.41.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d38548150c39b74aeeb0ce8ee1d8e82696f4a4e16ddc6de7b1d8823f7de4b9b5", size = 2171698, upload-time = "2025-11-04T13:40:12.004Z" }, - { url = "https://files.pythonhosted.org/packages/b1/87/41f3202e4193e3bacfc2c065fab7706ebe81af46a83d3e27605029c1f5a6/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:c23e27686783f60290e36827f9c626e63154b82b116d7fe9adba1fda36da706c", size = 2132603, upload-time = "2025-11-04T13:40:13.868Z" }, - { url = "https://files.pythonhosted.org/packages/49/7d/4c00df99cb12070b6bccdef4a195255e6020a550d572768d92cc54dba91a/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:482c982f814460eabe1d3bb0adfdc583387bd4691ef00b90575ca0d2b6fe2294", size = 2329591, upload-time = "2025-11-04T13:40:15.672Z" }, - { url = "https://files.pythonhosted.org/packages/cc/6a/ebf4b1d65d458f3cda6a7335d141305dfa19bdc61140a884d165a8a1bbc7/pydantic_core-2.41.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:bfea2a5f0b4d8d43adf9d7b8bf019fb46fdd10a2e5cde477fbcb9d1fa08c68e1", size = 2319068, upload-time = "2025-11-04T13:40:17.532Z" }, - { url = "https://files.pythonhosted.org/packages/49/3b/774f2b5cd4192d5ab75870ce4381fd89cf218af999515baf07e7206753f0/pydantic_core-2.41.5-cp312-cp312-win32.whl", hash = "sha256:b74557b16e390ec12dca509bce9264c3bbd128f8a2c376eaa68003d7f327276d", size = 1985908, upload-time = "2025-11-04T13:40:19.309Z" }, - { url = "https://files.pythonhosted.org/packages/86/45/00173a033c801cacf67c190fef088789394feaf88a98a7035b0e40d53dc9/pydantic_core-2.41.5-cp312-cp312-win_amd64.whl", hash = "sha256:1962293292865bca8e54702b08a4f26da73adc83dd1fcf26fbc875b35d81c815", size = 2020145, upload-time = "2025-11-04T13:40:21.548Z" }, - { url = "https://files.pythonhosted.org/packages/f9/22/91fbc821fa6d261b376a3f73809f907cec5ca6025642c463d3488aad22fb/pydantic_core-2.41.5-cp312-cp312-win_arm64.whl", hash = "sha256:1746d4a3d9a794cacae06a5eaaccb4b8643a131d45fbc9af23e353dc0a5ba5c3", size = 1976179, upload-time = "2025-11-04T13:40:23.393Z" }, - { url = "https://files.pythonhosted.org/packages/87/06/8806241ff1f70d9939f9af039c6c35f2360cf16e93c2ca76f184e76b1564/pydantic_core-2.41.5-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:941103c9be18ac8daf7b7adca8228f8ed6bb7a1849020f643b3a14d15b1924d9", size = 2120403, upload-time = "2025-11-04T13:40:25.248Z" }, - { url = "https://files.pythonhosted.org/packages/94/02/abfa0e0bda67faa65fef1c84971c7e45928e108fe24333c81f3bfe35d5f5/pydantic_core-2.41.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:112e305c3314f40c93998e567879e887a3160bb8689ef3d2c04b6cc62c33ac34", size = 1896206, upload-time = "2025-11-04T13:40:27.099Z" }, - { url = "https://files.pythonhosted.org/packages/15/df/a4c740c0943e93e6500f9eb23f4ca7ec9bf71b19e608ae5b579678c8d02f/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbaad15cb0c90aa221d43c00e77bb33c93e8d36e0bf74760cd00e732d10a6a0", size = 1919307, upload-time = "2025-11-04T13:40:29.806Z" }, - { url = "https://files.pythonhosted.org/packages/9a/e3/6324802931ae1d123528988e0e86587c2072ac2e5394b4bc2bc34b61ff6e/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:03ca43e12fab6023fc79d28ca6b39b05f794ad08ec2feccc59a339b02f2b3d33", size = 2063258, upload-time = "2025-11-04T13:40:33.544Z" }, - { url = "https://files.pythonhosted.org/packages/c9/d4/2230d7151d4957dd79c3044ea26346c148c98fbf0ee6ebd41056f2d62ab5/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc799088c08fa04e43144b164feb0c13f9a0bc40503f8df3e9fde58a3c0c101e", size = 2214917, upload-time = "2025-11-04T13:40:35.479Z" }, - { url = "https://files.pythonhosted.org/packages/e6/9f/eaac5df17a3672fef0081b6c1bb0b82b33ee89aa5cec0d7b05f52fd4a1fa/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:97aeba56665b4c3235a0e52b2c2f5ae9cd071b8a8310ad27bddb3f7fb30e9aa2", size = 2332186, upload-time = "2025-11-04T13:40:37.436Z" }, - { url = "https://files.pythonhosted.org/packages/cf/4e/35a80cae583a37cf15604b44240e45c05e04e86f9cfd766623149297e971/pydantic_core-2.41.5-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:406bf18d345822d6c21366031003612b9c77b3e29ffdb0f612367352aab7d586", size = 2073164, upload-time = "2025-11-04T13:40:40.289Z" }, - { url = "https://files.pythonhosted.org/packages/bf/e3/f6e262673c6140dd3305d144d032f7bd5f7497d3871c1428521f19f9efa2/pydantic_core-2.41.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b93590ae81f7010dbe380cdeab6f515902ebcbefe0b9327cc4804d74e93ae69d", size = 2179146, upload-time = "2025-11-04T13:40:42.809Z" }, - { url = "https://files.pythonhosted.org/packages/75/c7/20bd7fc05f0c6ea2056a4565c6f36f8968c0924f19b7d97bbfea55780e73/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:01a3d0ab748ee531f4ea6c3e48ad9dac84ddba4b0d82291f87248f2f9de8d740", size = 2137788, upload-time = "2025-11-04T13:40:44.752Z" }, - { url = "https://files.pythonhosted.org/packages/3a/8d/34318ef985c45196e004bc46c6eab2eda437e744c124ef0dbe1ff2c9d06b/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:6561e94ba9dacc9c61bce40e2d6bdc3bfaa0259d3ff36ace3b1e6901936d2e3e", size = 2340133, upload-time = "2025-11-04T13:40:46.66Z" }, - { url = "https://files.pythonhosted.org/packages/9c/59/013626bf8c78a5a5d9350d12e7697d3d4de951a75565496abd40ccd46bee/pydantic_core-2.41.5-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:915c3d10f81bec3a74fbd4faebe8391013ba61e5a1a8d48c4455b923bdda7858", size = 2324852, upload-time = "2025-11-04T13:40:48.575Z" }, - { url = "https://files.pythonhosted.org/packages/1a/d9/c248c103856f807ef70c18a4f986693a46a8ffe1602e5d361485da502d20/pydantic_core-2.41.5-cp313-cp313-win32.whl", hash = "sha256:650ae77860b45cfa6e2cdafc42618ceafab3a2d9a3811fcfbd3bbf8ac3c40d36", size = 1994679, upload-time = "2025-11-04T13:40:50.619Z" }, - { url = "https://files.pythonhosted.org/packages/9e/8b/341991b158ddab181cff136acd2552c9f35bd30380422a639c0671e99a91/pydantic_core-2.41.5-cp313-cp313-win_amd64.whl", hash = "sha256:79ec52ec461e99e13791ec6508c722742ad745571f234ea6255bed38c6480f11", size = 2019766, upload-time = "2025-11-04T13:40:52.631Z" }, - { url = "https://files.pythonhosted.org/packages/73/7d/f2f9db34af103bea3e09735bb40b021788a5e834c81eedb541991badf8f5/pydantic_core-2.41.5-cp313-cp313-win_arm64.whl", hash = "sha256:3f84d5c1b4ab906093bdc1ff10484838aca54ef08de4afa9de0f5f14d69639cd", size = 1981005, upload-time = "2025-11-04T13:40:54.734Z" }, - { url = "https://files.pythonhosted.org/packages/ea/28/46b7c5c9635ae96ea0fbb779e271a38129df2550f763937659ee6c5dbc65/pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a", size = 2119622, upload-time = "2025-11-04T13:40:56.68Z" }, - { url = "https://files.pythonhosted.org/packages/74/1a/145646e5687e8d9a1e8d09acb278c8535ebe9e972e1f162ed338a622f193/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14", size = 1891725, upload-time = "2025-11-04T13:40:58.807Z" }, - { url = "https://files.pythonhosted.org/packages/23/04/e89c29e267b8060b40dca97bfc64a19b2a3cf99018167ea1677d96368273/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1", size = 1915040, upload-time = "2025-11-04T13:41:00.853Z" }, - { url = "https://files.pythonhosted.org/packages/84/a3/15a82ac7bd97992a82257f777b3583d3e84bdb06ba6858f745daa2ec8a85/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66", size = 2063691, upload-time = "2025-11-04T13:41:03.504Z" }, - { url = "https://files.pythonhosted.org/packages/74/9b/0046701313c6ef08c0c1cf0e028c67c770a4e1275ca73131563c5f2a310a/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869", size = 2213897, upload-time = "2025-11-04T13:41:05.804Z" }, - { url = "https://files.pythonhosted.org/packages/8a/cd/6bac76ecd1b27e75a95ca3a9a559c643b3afcd2dd62086d4b7a32a18b169/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2", size = 2333302, upload-time = "2025-11-04T13:41:07.809Z" }, - { url = "https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375", size = 2064877, upload-time = "2025-11-04T13:41:09.827Z" }, - { url = "https://files.pythonhosted.org/packages/18/66/e9db17a9a763d72f03de903883c057b2592c09509ccfe468187f2a2eef29/pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553", size = 2180680, upload-time = "2025-11-04T13:41:12.379Z" }, - { url = "https://files.pythonhosted.org/packages/d3/9e/3ce66cebb929f3ced22be85d4c2399b8e85b622db77dad36b73c5387f8f8/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90", size = 2138960, upload-time = "2025-11-04T13:41:14.627Z" }, - { url = "https://files.pythonhosted.org/packages/a6/62/205a998f4327d2079326b01abee48e502ea739d174f0a89295c481a2272e/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07", size = 2339102, upload-time = "2025-11-04T13:41:16.868Z" }, - { url = "https://files.pythonhosted.org/packages/3c/0d/f05e79471e889d74d3d88f5bd20d0ed189ad94c2423d81ff8d0000aab4ff/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb", size = 2326039, upload-time = "2025-11-04T13:41:18.934Z" }, - { url = "https://files.pythonhosted.org/packages/ec/e1/e08a6208bb100da7e0c4b288eed624a703f4d129bde2da475721a80cab32/pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23", size = 1995126, upload-time = "2025-11-04T13:41:21.418Z" }, - { url = "https://files.pythonhosted.org/packages/48/5d/56ba7b24e9557f99c9237e29f5c09913c81eeb2f3217e40e922353668092/pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf", size = 2015489, upload-time = "2025-11-04T13:41:24.076Z" }, - { url = "https://files.pythonhosted.org/packages/4e/bb/f7a190991ec9e3e0ba22e4993d8755bbc4a32925c0b5b42775c03e8148f9/pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0", size = 1977288, upload-time = "2025-11-04T13:41:26.33Z" }, - { url = "https://files.pythonhosted.org/packages/92/ed/77542d0c51538e32e15afe7899d79efce4b81eee631d99850edc2f5e9349/pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a", size = 2120255, upload-time = "2025-11-04T13:41:28.569Z" }, - { url = "https://files.pythonhosted.org/packages/bb/3d/6913dde84d5be21e284439676168b28d8bbba5600d838b9dca99de0fad71/pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3", size = 1863760, upload-time = "2025-11-04T13:41:31.055Z" }, - { url = "https://files.pythonhosted.org/packages/5a/f0/e5e6b99d4191da102f2b0eb9687aaa7f5bea5d9964071a84effc3e40f997/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c", size = 1878092, upload-time = "2025-11-04T13:41:33.21Z" }, - { url = "https://files.pythonhosted.org/packages/71/48/36fb760642d568925953bcc8116455513d6e34c4beaa37544118c36aba6d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612", size = 2053385, upload-time = "2025-11-04T13:41:35.508Z" }, - { url = "https://files.pythonhosted.org/packages/20/25/92dc684dd8eb75a234bc1c764b4210cf2646479d54b47bf46061657292a8/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d", size = 2218832, upload-time = "2025-11-04T13:41:37.732Z" }, - { url = "https://files.pythonhosted.org/packages/e2/09/f53e0b05023d3e30357d82eb35835d0f6340ca344720a4599cd663dca599/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9", size = 2327585, upload-time = "2025-11-04T13:41:40Z" }, - { url = "https://files.pythonhosted.org/packages/aa/4e/2ae1aa85d6af35a39b236b1b1641de73f5a6ac4d5a7509f77b814885760c/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660", size = 2041078, upload-time = "2025-11-04T13:41:42.323Z" }, - { url = "https://files.pythonhosted.org/packages/cd/13/2e215f17f0ef326fc72afe94776edb77525142c693767fc347ed6288728d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9", size = 2173914, upload-time = "2025-11-04T13:41:45.221Z" }, - { url = "https://files.pythonhosted.org/packages/02/7a/f999a6dcbcd0e5660bc348a3991c8915ce6599f4f2c6ac22f01d7a10816c/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3", size = 2129560, upload-time = "2025-11-04T13:41:47.474Z" }, - { url = "https://files.pythonhosted.org/packages/3a/b1/6c990ac65e3b4c079a4fb9f5b05f5b013afa0f4ed6780a3dd236d2cbdc64/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf", size = 2329244, upload-time = "2025-11-04T13:41:49.992Z" }, - { url = "https://files.pythonhosted.org/packages/d9/02/3c562f3a51afd4d88fff8dffb1771b30cfdfd79befd9883ee094f5b6c0d8/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470", size = 2331955, upload-time = "2025-11-04T13:41:54.079Z" }, - { url = "https://files.pythonhosted.org/packages/5c/96/5fb7d8c3c17bc8c62fdb031c47d77a1af698f1d7a406b0f79aaa1338f9ad/pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa", size = 1988906, upload-time = "2025-11-04T13:41:56.606Z" }, - { url = "https://files.pythonhosted.org/packages/22/ed/182129d83032702912c2e2d8bbe33c036f342cc735737064668585dac28f/pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c", size = 1981607, upload-time = "2025-11-04T13:41:58.889Z" }, - { url = "https://files.pythonhosted.org/packages/9f/ed/068e41660b832bb0b1aa5b58011dea2a3fe0ba7861ff38c4d4904c1c1a99/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", size = 1974769, upload-time = "2025-11-04T13:42:01.186Z" }, - { url = "https://files.pythonhosted.org/packages/09/32/59b0c7e63e277fa7911c2fc70ccfb45ce4b98991e7ef37110663437005af/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:7da7087d756b19037bc2c06edc6c170eeef3c3bafcb8f532ff17d64dc427adfd", size = 2110495, upload-time = "2025-11-04T13:42:49.689Z" }, - { url = "https://files.pythonhosted.org/packages/aa/81/05e400037eaf55ad400bcd318c05bb345b57e708887f07ddb2d20e3f0e98/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:aabf5777b5c8ca26f7824cb4a120a740c9588ed58df9b2d196ce92fba42ff8dc", size = 1915388, upload-time = "2025-11-04T13:42:52.215Z" }, - { url = "https://files.pythonhosted.org/packages/6e/0d/e3549b2399f71d56476b77dbf3cf8937cec5cd70536bdc0e374a421d0599/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c007fe8a43d43b3969e8469004e9845944f1a80e6acd47c150856bb87f230c56", size = 1942879, upload-time = "2025-11-04T13:42:56.483Z" }, - { url = "https://files.pythonhosted.org/packages/f7/07/34573da085946b6a313d7c42f82f16e8920bfd730665de2d11c0c37a74b5/pydantic_core-2.41.5-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:76d0819de158cd855d1cbb8fcafdf6f5cf1eb8e470abe056d5d161106e38062b", size = 2139017, upload-time = "2025-11-04T13:42:59.471Z" }, -] - -[[package]] -name = "pydantic-settings" -version = "2.13.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "pydantic" }, - { name = "python-dotenv" }, - { name = "typing-inspection" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/52/6d/fffca34caecc4a3f97bda81b2098da5e8ab7efc9a66e819074a11955d87e/pydantic_settings-2.13.1.tar.gz", hash = "sha256:b4c11847b15237fb0171e1462bf540e294affb9b86db4d9aa5c01730bdbe4025", size = 223826, upload-time = "2026-02-19T13:45:08.055Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/00/4b/ccc026168948fec4f7555b9164c724cf4125eac006e176541483d2c959be/pydantic_settings-2.13.1-py3-none-any.whl", hash = "sha256:d56fd801823dbeae7f0975e1f8c8e25c258eb75d278ea7abb5d9cebb01b56237", size = 58929, upload-time = "2026-02-19T13:45:06.034Z" }, -] - -[[package]] -name = "pygments" -version = "2.19.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, -] - -[[package]] -name = "pyinstaller" -version = "6.18.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "altgraph" }, - { name = "macholib", marker = "sys_platform == 'darwin'" }, - { name = "packaging" }, - { name = "pefile", marker = "sys_platform == 'win32'" }, - { name = "pyinstaller-hooks-contrib" }, - { name = "pywin32-ctypes", marker = "sys_platform == 'win32'" }, - { name = "setuptools" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/9f/b8/0fe3359920b0a4e7008e0e93ff383003763e3eee3eb31a07c52868722960/pyinstaller-6.18.0.tar.gz", hash = "sha256:cdc507542783511cad4856fce582fdc37e9f29665ca596889c663c83ec8c6ec9", size = 4034976, upload-time = "2026-01-13T03:13:23.886Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/73/e6/51b0146a1a3eec619e58f5d69fb4e3d0f65a31cbddbeef557c9bb83eeed9/pyinstaller-6.18.0-py3-none-macosx_10_13_universal2.whl", hash = "sha256:cb7aa5a71bfa7c0af17a4a4e21855663c89e4bd7c40f1d337c8370636d8847c3", size = 1040056, upload-time = "2026-01-13T03:12:15.397Z" }, - { url = "https://files.pythonhosted.org/packages/4c/9c/a3634c0ec8e1ed31b373b548848b5c0b39b56edc191cf737e697d484ec23/pyinstaller-6.18.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:07785459b3bf8a48889eac0b4d0667ade84aef8930ce030bc7cbb32f41283b33", size = 734971, upload-time = "2026-01-13T03:12:20.912Z" }, - { url = "https://files.pythonhosted.org/packages/2c/04/6756442078ccfcd552ccce636be1574035e62f827ffa1f5d8a0382682546/pyinstaller-6.18.0-py3-none-manylinux2014_i686.whl", hash = "sha256:f998675b7ccb2dabbb1dc2d6f18af61d55428ad6d38e6c4d700417411b697d37", size = 746637, upload-time = "2026-01-13T03:12:29.302Z" }, - { url = "https://files.pythonhosted.org/packages/54/39/fbc56519000cdbf450f472692a7b9b55d42077ce8529f1be631db7b75a36/pyinstaller-6.18.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:779817a0cf69604cddcdb5be1fd4959dc2ce048d6355c73e5da97884df2f3387", size = 744343, upload-time = "2026-01-13T03:12:33.369Z" }, - { url = "https://files.pythonhosted.org/packages/36/f2/50887badf282fee776e83d1e4feab74c026f50a1ea16e109ed939e32aa28/pyinstaller-6.18.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:31b5d109f8405be0b7cddcede43e7b074792bc9a5bbd54ec000a3e779183c2af", size = 741084, upload-time = "2026-01-13T03:12:37.528Z" }, - { url = "https://files.pythonhosted.org/packages/1c/08/3a1419183e4713ef77d912ecbdd6ef858689ed9deb34d547133f724ca745/pyinstaller-6.18.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:4328c9837f1aef4fe1a127d4ff1b09a12ce53c827ce87c94117628b0e1fd098b", size = 740943, upload-time = "2026-01-13T03:12:41.589Z" }, - { url = "https://files.pythonhosted.org/packages/c2/47/309305e36d116f1434b42d91c420ff951fa79b2c398bbd59930c830450be/pyinstaller-6.18.0-py3-none-musllinux_1_1_aarch64.whl", hash = "sha256:3638fc81eb948e5e5eab1d4ad8f216e3fec6d4a350648304f0adb227b746ee5e", size = 740107, upload-time = "2026-01-13T03:12:45.694Z" }, - { url = "https://files.pythonhosted.org/packages/83/0f/a59a95cd1df59ddbc9e74d5a663387551333bcf19a5dd3086f5c81a2e83c/pyinstaller-6.18.0-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:8fbe59da34269e637f97fd3c43024f764586fc319141d245ff1a2e9af1036aa3", size = 739843, upload-time = "2026-01-13T03:12:49.728Z" }, - { url = "https://files.pythonhosted.org/packages/9a/09/e7a870e7205cdbd2f8785010a5d3fe48a9df2591156ee34a8b29b774fa14/pyinstaller-6.18.0-py3-none-win32.whl", hash = "sha256:496205e4fa92ec944f9696eb597962a83aef4d4c3479abfab83d730e1edf016b", size = 1323811, upload-time = "2026-01-13T03:12:55.717Z" }, - { url = "https://files.pythonhosted.org/packages/fb/d5/48eef2002b6d3937ceac2717fe17e9ca3a43a4c9826bafee367dfc75ba85/pyinstaller-6.18.0-py3-none-win_amd64.whl", hash = "sha256:976fabd90ecfbda47571c87055ad73413ec615ff7dea35e12a4304174de78de9", size = 1384389, upload-time = "2026-01-13T03:13:01.993Z" }, - { url = "https://files.pythonhosted.org/packages/1b/8d/1a88e6e94107de3ea1c842fd59c3aa132d344ad8e52ea458ffa9a748726e/pyinstaller-6.18.0-py3-none-win_arm64.whl", hash = "sha256:dba4b70e3c9ba09aab51152c72a08e58a751851548f77ad35944d32a300c8381", size = 1324869, upload-time = "2026-01-13T03:13:08.192Z" }, -] - -[[package]] -name = "pyinstaller-hooks-contrib" -version = "2026.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "packaging" }, - { name = "setuptools" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/31/8f/8052ff65067697ee80fde45b9731842e160751c41ac5690ba232c22030e8/pyinstaller_hooks_contrib-2026.0.tar.gz", hash = "sha256:0120893de491a000845470ca9c0b39284731ac6bace26f6849dea9627aaed48e", size = 170311, upload-time = "2026-01-20T00:15:23.922Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d5/b1/9da6ec3e88696018ee7bb9dc4a7310c2cfaebf32923a19598cd342767c10/pyinstaller_hooks_contrib-2026.0-py3-none-any.whl", hash = "sha256:0590db8edeba3e6c30c8474937021f5cd39c0602b4d10f74a064c73911efaca5", size = 452318, upload-time = "2026-01-20T00:15:21.88Z" }, -] - -[[package]] -name = "pytest" -version = "9.0.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, - { name = "iniconfig" }, - { name = "packaging" }, - { name = "pluggy" }, - { name = "pygments" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" }, -] - -[[package]] -name = "pytest-cov" -version = "7.0.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "coverage" }, - { name = "pluggy" }, - { name = "pytest" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/5e/f7/c933acc76f5208b3b00089573cf6a2bc26dc80a8aece8f52bb7d6b1855ca/pytest_cov-7.0.0.tar.gz", hash = "sha256:33c97eda2e049a0c5298e91f519302a1334c26ac65c1a483d6206fd458361af1", size = 54328, upload-time = "2025-09-09T10:57:02.113Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ee/49/1377b49de7d0c1ce41292161ea0f721913fa8722c19fb9c1e3aa0367eecb/pytest_cov-7.0.0-py3-none-any.whl", hash = "sha256:3b8e9558b16cc1479da72058bdecf8073661c7f57f7d3c5f22a1c23507f2d861", size = 22424, upload-time = "2025-09-09T10:57:00.695Z" }, -] - -[[package]] -name = "python-dateutil" -version = "2.9.0.post0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "six" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, -] - -[[package]] -name = "python-dotenv" -version = "1.2.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/82/ed/0301aeeac3e5353ef3d94b6ec08bbcabd04a72018415dcb29e588514bba8/python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3", size = 50135, upload-time = "2026-03-01T16:00:26.196Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" }, -] - -[[package]] -name = "python-socks" -version = "2.8.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/36/0b/cd77011c1bc01b76404f7aba07fca18aca02a19c7626e329b40201217624/python_socks-2.8.1.tar.gz", hash = "sha256:698daa9616d46dddaffe65b87db222f2902177a2d2b2c0b9a9361df607ab3687", size = 38909, upload-time = "2026-02-16T05:24:00.745Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/15/fe/9a58cb6eec633ff6afae150ca53c16f8cc8b65862ccb3d088051efdfceb7/python_socks-2.8.1-py3-none-any.whl", hash = "sha256:28232739c4988064e725cdbcd15be194743dd23f1c910f784163365b9d7be035", size = 55087, upload-time = "2026-02-16T05:23:59.147Z" }, -] - -[[package]] -name = "python-telegram-bot" -version = "22.6" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "httpcore", marker = "python_full_version >= '3.14'" }, - { name = "httpx" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/cd/9b/8df90c85404166a6631e857027866263adb27440d8af1dbeffbdc4f0166c/python_telegram_bot-22.6.tar.gz", hash = "sha256:50ae8cc10f8dff01445628687951020721f37956966b92a91df4c1bf2d113742", size = 1503761, upload-time = "2026-01-24T13:57:00.269Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/13/97/7298f0e1afe3a1ae52ff4c5af5087ed4de319ea73eb3b5c8c4dd4e76e708/python_telegram_bot-22.6-py3-none-any.whl", hash = "sha256:e598fe171c3dde2dfd0f001619ee9110eece66761a677b34719fb18934935ce0", size = 737267, upload-time = "2026-01-24T13:56:58.06Z" }, -] - -[[package]] -name = "pytz" -version = "2025.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f8/bf/abbd3cdfb8fbc7fb3d4d38d320f2441b1e7cbe29be4f23797b4a2b5d8aac/pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", size = 320884, upload-time = "2025-03-25T02:25:00.538Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/81/c4/34e93fe5f5429d7570ec1fa436f1986fb1f00c3e0f43a589fe2bbcd22c3f/pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00", size = 509225, upload-time = "2025-03-25T02:24:58.468Z" }, -] - -[[package]] -name = "pywin32-ctypes" -version = "0.2.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/85/9f/01a1a99704853cb63f253eea009390c88e7131c67e66a0a02099a8c917cb/pywin32-ctypes-0.2.3.tar.gz", hash = "sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755", size = 29471, upload-time = "2024-08-14T10:15:34.626Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/de/3d/8161f7711c017e01ac9f008dfddd9410dff3674334c233bde66e7ba65bbf/pywin32_ctypes-0.2.3-py3-none-any.whl", hash = "sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8", size = 30756, upload-time = "2024-08-14T10:15:33.187Z" }, -] - -[[package]] -name = "pyyaml" -version = "6.0.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, - { url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, - { url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, - { url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, - { url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, - { url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, - { url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, - { url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, - { url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, - { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, - { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, - { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, - { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, - { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, - { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, - { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, - { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, - { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, - { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, - { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, - { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, - { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, - { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, - { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, - { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, - { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, - { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, - { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, - { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, - { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, - { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, - { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, - { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, - { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, - { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, - { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, - { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, - { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, -] - -[[package]] -name = "requests" -version = "2.32.5" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "certifi" }, - { name = "charset-normalizer" }, - { name = "idna" }, - { name = "urllib3" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, -] - -[[package]] -name = "requests-toolbelt" -version = "1.0.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "requests" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/f3/61/d7545dafb7ac2230c70d38d31cbfe4cc64f7144dc41f6e4e4b78ecd9f5bb/requests-toolbelt-1.0.0.tar.gz", hash = "sha256:7681a0a3d047012b5bdc0ee37d7f8f07ebe76ab08caeccfc3921ce23c88d5bc6", size = 206888, upload-time = "2023-05-01T04:11:33.229Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3f/51/d4db610ef29373b879047326cbf6fa98b6c1969d6f6dc423279de2b1be2c/requests_toolbelt-1.0.0-py2.py3-none-any.whl", hash = "sha256:cccfdd665f0a24fcf4726e690f65639d272bb0637b9b92dfd91a5568ccf6bd06", size = 54481, upload-time = "2023-05-01T04:11:28.427Z" }, -] - -[[package]] -name = "rich" -version = "14.3.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "markdown-it-py" }, - { name = "pygments" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/b3/c6/f3b320c27991c46f43ee9d856302c70dc2d0fb2dba4842ff739d5f46b393/rich-14.3.3.tar.gz", hash = "sha256:b8daa0b9e4eef54dd8cf7c86c03713f53241884e814f4e2f5fb342fe520f639b", size = 230582, upload-time = "2026-02-19T17:23:12.474Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/14/25/b208c5683343959b670dc001595f2f3737e051da617f66c31f7c4fa93abc/rich-14.3.3-py3-none-any.whl", hash = "sha256:793431c1f8619afa7d3b52b2cdec859562b950ea0d4b6b505397612db8d5362d", size = 310458, upload-time = "2026-02-19T17:23:13.732Z" }, -] - -[[package]] -name = "ruff" -version = "0.15.6" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/51/df/f8629c19c5318601d3121e230f74cbee7a3732339c52b21daa2b82ef9c7d/ruff-0.15.6.tar.gz", hash = "sha256:8394c7bb153a4e3811a4ecdacd4a8e6a4fa8097028119160dffecdcdf9b56ae4", size = 4597916, upload-time = "2026-03-12T23:05:47.51Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/9e/2f/4e03a7e5ce99b517e98d3b4951f411de2b0fa8348d39cf446671adcce9a2/ruff-0.15.6-py3-none-linux_armv6l.whl", hash = "sha256:7c98c3b16407b2cf3d0f2b80c80187384bc92c6774d85fefa913ecd941256fff", size = 10508953, upload-time = "2026-03-12T23:05:17.246Z" }, - { url = "https://files.pythonhosted.org/packages/70/60/55bcdc3e9f80bcf39edf0cd272da6fa511a3d94d5a0dd9e0adf76ceebdb4/ruff-0.15.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ee7dcfaad8b282a284df4aa6ddc2741b3f4a18b0555d626805555a820ea181c3", size = 10942257, upload-time = "2026-03-12T23:05:23.076Z" }, - { url = "https://files.pythonhosted.org/packages/e7/f9/005c29bd1726c0f492bfa215e95154cf480574140cb5f867c797c18c790b/ruff-0.15.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3bd9967851a25f038fc8b9ae88a7fbd1b609f30349231dffaa37b6804923c4bb", size = 10322683, upload-time = "2026-03-12T23:05:33.738Z" }, - { url = "https://files.pythonhosted.org/packages/5f/74/2f861f5fd7cbb2146bddb5501450300ce41562da36d21868c69b7a828169/ruff-0.15.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:13f4594b04e42cd24a41da653886b04d2ff87adbf57497ed4f728b0e8a4866f8", size = 10660986, upload-time = "2026-03-12T23:05:53.245Z" }, - { url = "https://files.pythonhosted.org/packages/c1/a1/309f2364a424eccb763cdafc49df843c282609f47fe53aa83f38272389e0/ruff-0.15.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e2ed8aea2f3fe57886d3f00ea5b8aae5bf68d5e195f487f037a955ff9fbaac9e", size = 10332177, upload-time = "2026-03-12T23:05:56.145Z" }, - { url = "https://files.pythonhosted.org/packages/30/41/7ebf1d32658b4bab20f8ac80972fb19cd4e2c6b78552be263a680edc55ac/ruff-0.15.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:70789d3e7830b848b548aae96766431c0dc01a6c78c13381f423bf7076c66d15", size = 11170783, upload-time = "2026-03-12T23:06:01.742Z" }, - { url = "https://files.pythonhosted.org/packages/76/be/6d488f6adca047df82cd62c304638bcb00821c36bd4881cfca221561fdfc/ruff-0.15.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:542aaf1de3154cea088ced5a819ce872611256ffe2498e750bbae5247a8114e9", size = 12044201, upload-time = "2026-03-12T23:05:28.697Z" }, - { url = "https://files.pythonhosted.org/packages/71/68/e6f125df4af7e6d0b498f8d373274794bc5156b324e8ab4bf5c1b4fc0ec7/ruff-0.15.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1c22e6f02c16cfac3888aa636e9eba857254d15bbacc9906c9689fdecb1953ab", size = 11421561, upload-time = "2026-03-12T23:05:31.236Z" }, - { url = "https://files.pythonhosted.org/packages/f1/9f/f85ef5fd01a52e0b472b26dc1b4bd228b8f6f0435975442ffa4741278703/ruff-0.15.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98893c4c0aadc8e448cfa315bd0cc343a5323d740fe5f28ef8a3f9e21b381f7e", size = 11310928, upload-time = "2026-03-12T23:05:45.288Z" }, - { url = "https://files.pythonhosted.org/packages/8c/26/b75f8c421f5654304b89471ed384ae8c7f42b4dff58fa6ce1626d7f2b59a/ruff-0.15.6-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:70d263770d234912374493e8cc1e7385c5d49376e41dfa51c5c3453169dc581c", size = 11235186, upload-time = "2026-03-12T23:05:50.677Z" }, - { url = "https://files.pythonhosted.org/packages/fc/d4/d5a6d065962ff7a68a86c9b4f5500f7d101a0792078de636526c0edd40da/ruff-0.15.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:55a1ad63c5a6e54b1f21b7514dfadc0c7fb40093fa22e95143cf3f64ebdcd512", size = 10635231, upload-time = "2026-03-12T23:05:37.044Z" }, - { url = "https://files.pythonhosted.org/packages/d6/56/7c3acf3d50910375349016cf33de24be021532042afbed87942858992491/ruff-0.15.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8dc473ba093c5ec238bb1e7429ee676dca24643c471e11fbaa8a857925b061c0", size = 10340357, upload-time = "2026-03-12T23:06:04.748Z" }, - { url = "https://files.pythonhosted.org/packages/06/54/6faa39e9c1033ff6a3b6e76b5df536931cd30caf64988e112bbf91ef5ce5/ruff-0.15.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:85b042377c2a5561131767974617006f99f7e13c63c111b998f29fc1e58a4cfb", size = 10860583, upload-time = "2026-03-12T23:05:58.978Z" }, - { url = "https://files.pythonhosted.org/packages/cb/1e/509a201b843b4dfb0b32acdedf68d951d3377988cae43949ba4c4133a96a/ruff-0.15.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:cef49e30bc5a86a6a92098a7fbf6e467a234d90b63305d6f3ec01225a9d092e0", size = 11410976, upload-time = "2026-03-12T23:05:39.955Z" }, - { url = "https://files.pythonhosted.org/packages/6c/25/3fc9114abf979a41673ce877c08016f8e660ad6cf508c3957f537d2e9fa9/ruff-0.15.6-py3-none-win32.whl", hash = "sha256:bbf67d39832404812a2d23020dda68fee7f18ce15654e96fb1d3ad21a5fe436c", size = 10616872, upload-time = "2026-03-12T23:05:42.451Z" }, - { url = "https://files.pythonhosted.org/packages/89/7a/09ece68445ceac348df06e08bf75db72d0e8427765b96c9c0ffabc1be1d9/ruff-0.15.6-py3-none-win_amd64.whl", hash = "sha256:aee25bc84c2f1007ecb5037dff75cef00414fdf17c23f07dc13e577883dca406", size = 11787271, upload-time = "2026-03-12T23:05:20.168Z" }, - { url = "https://files.pythonhosted.org/packages/7f/d0/578c47dd68152ddddddf31cd7fc67dc30b7cdf639a86275fda821b0d9d98/ruff-0.15.6-py3-none-win_arm64.whl", hash = "sha256:c34de3dd0b0ba203be50ae70f5910b17188556630e2178fd7d79fc030eb0d837", size = 11060497, upload-time = "2026-03-12T23:05:25.968Z" }, -] - -[[package]] -name = "setuptools" -version = "82.0.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/82/f3/748f4d6f65d1756b9ae577f329c951cda23fb900e4de9f70900ced962085/setuptools-82.0.0.tar.gz", hash = "sha256:22e0a2d69474c6ae4feb01951cb69d515ed23728cf96d05513d36e42b62b37cb", size = 1144893, upload-time = "2026-02-08T15:08:40.206Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e1/c6/76dc613121b793286a3f91621d7b75a2b493e0390ddca50f11993eadf192/setuptools-82.0.0-py3-none-any.whl", hash = "sha256:70b18734b607bd1da571d097d236cfcfacaf01de45717d59e6e04b96877532e0", size = 1003468, upload-time = "2026-02-08T15:08:38.723Z" }, -] - -[[package]] -name = "six" -version = "1.17.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, -] - -[[package]] -name = "slack-sdk" -version = "3.40.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/45/f7/4a968e1d091569ff7f6da929695728c3eacf10afcda7c424b70df2c3700b/slack_sdk-3.40.0.tar.gz", hash = "sha256:87b9a79d1d6e19a2b1877727a0ec6f016d82d30a6a410389fba87c221c99f10e", size = 249478, upload-time = "2026-02-10T22:12:13.445Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/27/72/428fb01a1043ddbb3f66297363406d6e69ddff5ad89c4d07945a3753a235/slack_sdk-3.40.0-py2.py3-none-any.whl", hash = "sha256:f2bada5ed3adb10a01e154e90db01d6d8938d0461b5790c12bcb807b2d28bbe2", size = 312786, upload-time = "2026-02-10T22:12:11.258Z" }, -] - -[[package]] -name = "typing-extensions" -version = "4.15.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, -] - -[[package]] -name = "typing-inspection" -version = "0.4.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/55/e3/70399cb7dd41c10ac53367ae42139cf4b1ca5f36bb3dc6c9d33acdb43655/typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464", size = 75949, upload-time = "2025-10-01T02:14:41.687Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/dc/9b/47798a6c91d8bdb567fe2698fe81e0c6b7cb7ef4d13da4114b41d239f65d/typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7", size = 14611, upload-time = "2025-10-01T02:14:40.154Z" }, -] - -[[package]] -name = "tzdata" -version = "2025.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5e/a7/c202b344c5ca7daf398f3b8a477eeb205cf3b6f32e7ec3a6bac0629ca975/tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7", size = 196772, upload-time = "2025-12-13T17:45:35.667Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521, upload-time = "2025-12-13T17:45:33.889Z" }, -] - -[[package]] -name = "urllib3" -version = "2.6.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/c7/24/5f1b3bdffd70275f6661c76461e25f024d5a38a46f04aaca912426a2b1d3/urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed", size = 435556, upload-time = "2026-01-07T16:24:43.925Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4", size = 131584, upload-time = "2026-01-07T16:24:42.685Z" }, -] - -[[package]] -name = "websockets" -version = "16.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/04/24/4b2031d72e840ce4c1ccb255f693b15c334757fc50023e4db9537080b8c4/websockets-16.0.tar.gz", hash = "sha256:5f6261a5e56e8d5c42a4497b364ea24d94d9563e8fbd44e78ac40879c60179b5", size = 179346, upload-time = "2026-01-10T09:23:47.181Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/84/7b/bac442e6b96c9d25092695578dda82403c77936104b5682307bd4deb1ad4/websockets-16.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:71c989cbf3254fbd5e84d3bff31e4da39c43f884e64f2551d14bb3c186230f00", size = 177365, upload-time = "2026-01-10T09:22:46.787Z" }, - { url = "https://files.pythonhosted.org/packages/b0/fe/136ccece61bd690d9c1f715baaeefd953bb2360134de73519d5df19d29ca/websockets-16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8b6e209ffee39ff1b6d0fa7bfef6de950c60dfb91b8fcead17da4ee539121a79", size = 175038, upload-time = "2026-01-10T09:22:47.999Z" }, - { url = "https://files.pythonhosted.org/packages/40/1e/9771421ac2286eaab95b8575b0cb701ae3663abf8b5e1f64f1fd90d0a673/websockets-16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:86890e837d61574c92a97496d590968b23c2ef0aeb8a9bc9421d174cd378ae39", size = 175328, upload-time = "2026-01-10T09:22:49.809Z" }, - { url = "https://files.pythonhosted.org/packages/18/29/71729b4671f21e1eaa5d6573031ab810ad2936c8175f03f97f3ff164c802/websockets-16.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9b5aca38b67492ef518a8ab76851862488a478602229112c4b0d58d63a7a4d5c", size = 184915, upload-time = "2026-01-10T09:22:51.071Z" }, - { url = "https://files.pythonhosted.org/packages/97/bb/21c36b7dbbafc85d2d480cd65df02a1dc93bf76d97147605a8e27ff9409d/websockets-16.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e0334872c0a37b606418ac52f6ab9cfd17317ac26365f7f65e203e2d0d0d359f", size = 186152, upload-time = "2026-01-10T09:22:52.224Z" }, - { url = "https://files.pythonhosted.org/packages/4a/34/9bf8df0c0cf88fa7bfe36678dc7b02970c9a7d5e065a3099292db87b1be2/websockets-16.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a0b31e0b424cc6b5a04b8838bbaec1688834b2383256688cf47eb97412531da1", size = 185583, upload-time = "2026-01-10T09:22:53.443Z" }, - { url = "https://files.pythonhosted.org/packages/47/88/4dd516068e1a3d6ab3c7c183288404cd424a9a02d585efbac226cb61ff2d/websockets-16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:485c49116d0af10ac698623c513c1cc01c9446c058a4e61e3bf6c19dff7335a2", size = 184880, upload-time = "2026-01-10T09:22:55.033Z" }, - { url = "https://files.pythonhosted.org/packages/91/d6/7d4553ad4bf1c0421e1ebd4b18de5d9098383b5caa1d937b63df8d04b565/websockets-16.0-cp312-cp312-win32.whl", hash = "sha256:eaded469f5e5b7294e2bdca0ab06becb6756ea86894a47806456089298813c89", size = 178261, upload-time = "2026-01-10T09:22:56.251Z" }, - { url = "https://files.pythonhosted.org/packages/c3/f0/f3a17365441ed1c27f850a80b2bc680a0fa9505d733fe152fdf5e98c1c0b/websockets-16.0-cp312-cp312-win_amd64.whl", hash = "sha256:5569417dc80977fc8c2d43a86f78e0a5a22fee17565d78621b6bb264a115d4ea", size = 178693, upload-time = "2026-01-10T09:22:57.478Z" }, - { url = "https://files.pythonhosted.org/packages/cc/9c/baa8456050d1c1b08dd0ec7346026668cbc6f145ab4e314d707bb845bf0d/websockets-16.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:878b336ac47938b474c8f982ac2f7266a540adc3fa4ad74ae96fea9823a02cc9", size = 177364, upload-time = "2026-01-10T09:22:59.333Z" }, - { url = "https://files.pythonhosted.org/packages/7e/0c/8811fc53e9bcff68fe7de2bcbe75116a8d959ac699a3200f4847a8925210/websockets-16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:52a0fec0e6c8d9a784c2c78276a48a2bdf099e4ccc2a4cad53b27718dbfd0230", size = 175039, upload-time = "2026-01-10T09:23:01.171Z" }, - { url = "https://files.pythonhosted.org/packages/aa/82/39a5f910cb99ec0b59e482971238c845af9220d3ab9fa76dd9162cda9d62/websockets-16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e6578ed5b6981005df1860a56e3617f14a6c307e6a71b4fff8c48fdc50f3ed2c", size = 175323, upload-time = "2026-01-10T09:23:02.341Z" }, - { url = "https://files.pythonhosted.org/packages/bd/28/0a25ee5342eb5d5f297d992a77e56892ecb65e7854c7898fb7d35e9b33bd/websockets-16.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:95724e638f0f9c350bb1c2b0a7ad0e83d9cc0c9259f3ea94e40d7b02a2179ae5", size = 184975, upload-time = "2026-01-10T09:23:03.756Z" }, - { url = "https://files.pythonhosted.org/packages/f9/66/27ea52741752f5107c2e41fda05e8395a682a1e11c4e592a809a90c6a506/websockets-16.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0204dc62a89dc9d50d682412c10b3542d748260d743500a85c13cd1ee4bde82", size = 186203, upload-time = "2026-01-10T09:23:05.01Z" }, - { url = "https://files.pythonhosted.org/packages/37/e5/8e32857371406a757816a2b471939d51c463509be73fa538216ea52b792a/websockets-16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:52ac480f44d32970d66763115edea932f1c5b1312de36df06d6b219f6741eed8", size = 185653, upload-time = "2026-01-10T09:23:06.301Z" }, - { url = "https://files.pythonhosted.org/packages/9b/67/f926bac29882894669368dc73f4da900fcdf47955d0a0185d60103df5737/websockets-16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6e5a82b677f8f6f59e8dfc34ec06ca6b5b48bc4fcda346acd093694cc2c24d8f", size = 184920, upload-time = "2026-01-10T09:23:07.492Z" }, - { url = "https://files.pythonhosted.org/packages/3c/a1/3d6ccdcd125b0a42a311bcd15a7f705d688f73b2a22d8cf1c0875d35d34a/websockets-16.0-cp313-cp313-win32.whl", hash = "sha256:abf050a199613f64c886ea10f38b47770a65154dc37181bfaff70c160f45315a", size = 178255, upload-time = "2026-01-10T09:23:09.245Z" }, - { url = "https://files.pythonhosted.org/packages/6b/ae/90366304d7c2ce80f9b826096a9e9048b4bb760e44d3b873bb272cba696b/websockets-16.0-cp313-cp313-win_amd64.whl", hash = "sha256:3425ac5cf448801335d6fdc7ae1eb22072055417a96cc6b31b3861f455fbc156", size = 178689, upload-time = "2026-01-10T09:23:10.483Z" }, - { url = "https://files.pythonhosted.org/packages/f3/1d/e88022630271f5bd349ed82417136281931e558d628dd52c4d8621b4a0b2/websockets-16.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8cc451a50f2aee53042ac52d2d053d08bf89bcb31ae799cb4487587661c038a0", size = 177406, upload-time = "2026-01-10T09:23:12.178Z" }, - { url = "https://files.pythonhosted.org/packages/f2/78/e63be1bf0724eeb4616efb1ae1c9044f7c3953b7957799abb5915bffd38e/websockets-16.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:daa3b6ff70a9241cf6c7fc9e949d41232d9d7d26fd3522b1ad2b4d62487e9904", size = 175085, upload-time = "2026-01-10T09:23:13.511Z" }, - { url = "https://files.pythonhosted.org/packages/bb/f4/d3c9220d818ee955ae390cf319a7c7a467beceb24f05ee7aaaa2414345ba/websockets-16.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:fd3cb4adb94a2a6e2b7c0d8d05cb94e6f1c81a0cf9dc2694fb65c7e8d94c42e4", size = 175328, upload-time = "2026-01-10T09:23:14.727Z" }, - { url = "https://files.pythonhosted.org/packages/63/bc/d3e208028de777087e6fb2b122051a6ff7bbcca0d6df9d9c2bf1dd869ae9/websockets-16.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:781caf5e8eee67f663126490c2f96f40906594cb86b408a703630f95550a8c3e", size = 185044, upload-time = "2026-01-10T09:23:15.939Z" }, - { url = "https://files.pythonhosted.org/packages/ad/6e/9a0927ac24bd33a0a9af834d89e0abc7cfd8e13bed17a86407a66773cc0e/websockets-16.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:caab51a72c51973ca21fa8a18bd8165e1a0183f1ac7066a182ff27107b71e1a4", size = 186279, upload-time = "2026-01-10T09:23:17.148Z" }, - { url = "https://files.pythonhosted.org/packages/b9/ca/bf1c68440d7a868180e11be653c85959502efd3a709323230314fda6e0b3/websockets-16.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:19c4dc84098e523fd63711e563077d39e90ec6702aff4b5d9e344a60cb3c0cb1", size = 185711, upload-time = "2026-01-10T09:23:18.372Z" }, - { url = "https://files.pythonhosted.org/packages/c4/f8/fdc34643a989561f217bb477cbc47a3a07212cbda91c0e4389c43c296ebf/websockets-16.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a5e18a238a2b2249c9a9235466b90e96ae4795672598a58772dd806edc7ac6d3", size = 184982, upload-time = "2026-01-10T09:23:19.652Z" }, - { url = "https://files.pythonhosted.org/packages/dd/d1/574fa27e233764dbac9c52730d63fcf2823b16f0856b3329fc6268d6ae4f/websockets-16.0-cp314-cp314-win32.whl", hash = "sha256:a069d734c4a043182729edd3e9f247c3b2a4035415a9172fd0f1b71658a320a8", size = 177915, upload-time = "2026-01-10T09:23:21.458Z" }, - { url = "https://files.pythonhosted.org/packages/8a/f1/ae6b937bf3126b5134ce1f482365fde31a357c784ac51852978768b5eff4/websockets-16.0-cp314-cp314-win_amd64.whl", hash = "sha256:c0ee0e63f23914732c6d7e0cce24915c48f3f1512ec1d079ed01fc629dab269d", size = 178381, upload-time = "2026-01-10T09:23:22.715Z" }, - { url = "https://files.pythonhosted.org/packages/06/9b/f791d1db48403e1f0a27577a6beb37afae94254a8c6f08be4a23e4930bc0/websockets-16.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:a35539cacc3febb22b8f4d4a99cc79b104226a756aa7400adc722e83b0d03244", size = 177737, upload-time = "2026-01-10T09:23:24.523Z" }, - { url = "https://files.pythonhosted.org/packages/bd/40/53ad02341fa33b3ce489023f635367a4ac98b73570102ad2cdd770dacc9a/websockets-16.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:b784ca5de850f4ce93ec85d3269d24d4c82f22b7212023c974c401d4980ebc5e", size = 175268, upload-time = "2026-01-10T09:23:25.781Z" }, - { url = "https://files.pythonhosted.org/packages/74/9b/6158d4e459b984f949dcbbb0c5d270154c7618e11c01029b9bbd1bb4c4f9/websockets-16.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:569d01a4e7fba956c5ae4fc988f0d4e187900f5497ce46339c996dbf24f17641", size = 175486, upload-time = "2026-01-10T09:23:27.033Z" }, - { url = "https://files.pythonhosted.org/packages/e5/2d/7583b30208b639c8090206f95073646c2c9ffd66f44df967981a64f849ad/websockets-16.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:50f23cdd8343b984957e4077839841146f67a3d31ab0d00e6b824e74c5b2f6e8", size = 185331, upload-time = "2026-01-10T09:23:28.259Z" }, - { url = "https://files.pythonhosted.org/packages/45/b0/cce3784eb519b7b5ad680d14b9673a31ab8dcb7aad8b64d81709d2430aa8/websockets-16.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:152284a83a00c59b759697b7f9e9cddf4e3c7861dd0d964b472b70f78f89e80e", size = 186501, upload-time = "2026-01-10T09:23:29.449Z" }, - { url = "https://files.pythonhosted.org/packages/19/60/b8ebe4c7e89fb5f6cdf080623c9d92789a53636950f7abacfc33fe2b3135/websockets-16.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bc59589ab64b0022385f429b94697348a6a234e8ce22544e3681b2e9331b5944", size = 186062, upload-time = "2026-01-10T09:23:31.368Z" }, - { url = "https://files.pythonhosted.org/packages/88/a8/a080593f89b0138b6cba1b28f8df5673b5506f72879322288b031337c0b8/websockets-16.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:32da954ffa2814258030e5a57bc73a3635463238e797c7375dc8091327434206", size = 185356, upload-time = "2026-01-10T09:23:32.627Z" }, - { url = "https://files.pythonhosted.org/packages/c2/b6/b9afed2afadddaf5ebb2afa801abf4b0868f42f8539bfe4b071b5266c9fe/websockets-16.0-cp314-cp314t-win32.whl", hash = "sha256:5a4b4cc550cb665dd8a47f868c8d04c8230f857363ad3c9caf7a0c3bf8c61ca6", size = 178085, upload-time = "2026-01-10T09:23:33.816Z" }, - { url = "https://files.pythonhosted.org/packages/9f/3e/28135a24e384493fa804216b79a6a6759a38cc4ff59118787b9fb693df93/websockets-16.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b14dc141ed6d2dde437cddb216004bcac6a1df0935d79656387bd41632ba0bbd", size = 178531, upload-time = "2026-01-10T09:23:35.016Z" }, - { url = "https://files.pythonhosted.org/packages/6f/28/258ebab549c2bf3e64d2b0217b973467394a9cea8c42f70418ca2c5d0d2e/websockets-16.0-py3-none-any.whl", hash = "sha256:1637db62fad1dc833276dded54215f2c7fa46912301a24bd94d45d46a011ceec", size = 171598, upload-time = "2026-01-10T09:23:45.395Z" }, -]