From 88d6871ee9de5140c742fbe39c4df3d087795e82 Mon Sep 17 00:00:00 2001 From: AlkaidSTART <2595006848@qq.com> Date: Sun, 23 Aug 2026 16:56:10 +0800 Subject: [PATCH 01/10] =?UTF-8?q?feat:=20=E5=B0=86=20.agent-sessions/=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=88=B0=20.gitignore=EF=BC=8C=E4=BB=A5?= =?UTF-8?q?=E9=81=BF=E5=85=8D=E4=B8=8D=E5=BF=85=E8=A6=81=E7=9A=84=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=B9=B2=E6=89=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index cd7381b..6d05f66 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,4 @@ bundle.* docs/* !docs/index.html .DS_Store # macOS +.agent-sessions/* From b92f695288c43118332475c1b2ad384a9ad6164a Mon Sep 17 00:00:00 2001 From: AlkaidSTART <2595006848@qq.com> Date: Sun, 23 Aug 2026 17:08:24 +0800 Subject: [PATCH 02/10] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20Docker=20?= =?UTF-8?q?=E9=95=9C=E5=83=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .dockerignore | 15 +++++++++++++++ Dockerfile | 30 ++++++++++++++++++++++++++++++ README.md | 18 ++++++++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 .dockerignore create mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..80c4e41 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,15 @@ +.git +.github +.gitignore +.agent-sessions +.env +.env.local +.env.* +node_modules +**/node_modules +packages/*/dist +*.tsbuildinfo +bundle.* +docs +tests +.DS_Store diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..72e2e97 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,30 @@ +# 使用 Node 24 提供 node:sqlite 和 npm,Bun 负责按 bun.lock 安装依赖 +FROM node:24-bookworm-slim + +# coding agent 会在挂载的工作区执行命令,补齐常用工具 +RUN apt-get update \ + && apt-get install -y --no-install-recommends bash git ripgrep ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +# 与 packageManager 保持一致,避免 bun.lock 被其他版本改写 +RUN npm install -g bun@1.3.11 + +WORKDIR /app + +# 先复制清单文件,依赖层可以复用 Docker 缓存 +COPY package.json bun.lock bunfig.toml tsconfig.json ./ +COPY packages/agent-core/package.json packages/agent-core/ +COPY packages/client/package.json packages/client/ +COPY packages/session-sqlite/package.json packages/session-sqlite/ + +RUN bun install --frozen-lockfile + +COPY source source +COPY packages/agent-core packages/agent-core +COPY packages/session-sqlite packages/session-sqlite + +# 默认把挂载的用户目录作为工作区,会话和工具执行都落在里面 +WORKDIR /workspace + +# 入口用 tsx 加载 TypeScript,tsconfig 固定指向 /app,避免受工作区影响 +CMD ["node", "/app/node_modules/tsx/dist/cli.mjs", "--tsconfig", "/app/tsconfig.json", "/app/source/app.tsx"] diff --git a/README.md b/README.md index 2d232fa..2af8489 100644 --- a/README.md +++ b/README.md @@ -171,6 +171,24 @@ bun run export:web bun run build:client ``` +## Docker 镜像 + +构建镜像: + +```bash +docker build -t call-code . +``` + +以当前目录作为工作区运行,容器内工作目录固定为 `/workspace`,会话库会写入 `/workspace/.agent-sessions`: + +```bash +docker run --rm -it \ + -v "$PWD":/workspace \ + call-code +``` + +API 配置优先从挂载目录下的 `.env.local` 读取,也可以用 `-e OPENAI_API_KEY=... -e OPENAI_MODEL=...` 传入。 + ## 测试说明 测试文件统一放在项目根目录的 `tests/` 目录下,根目录的 `vitest.config.ts` 会统一收集并运行。 From 67900ff91bff95930af35f6a0324f057c7131591 Mon Sep 17 00:00:00 2001 From: AlkaidSTART <2595006848@qq.com> Date: Sun, 23 Aug 2026 18:23:40 +0800 Subject: [PATCH 03/10] =?UTF-8?q?feat:=20=E5=AE=A2=E6=88=B7=E7=AB=AF?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=E9=80=9A=E8=BF=87=20WebSocket=20=E5=B1=95?= =?UTF-8?q?=E7=A4=BA=E4=BC=9A=E8=AF=9D=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 22 +- bun.lock | 4 + package.json | 3 +- packages/agent-core/package.json | 4 +- packages/agent-core/src/web/export.ts | 2 +- packages/agent-core/src/web/protocol.ts | 28 ++ packages/agent-core/src/web/server.ts | 191 ++++++++++++++ packages/client/README.md | 27 +- packages/client/dist/assets/index-BVFN01-c.js | 9 + packages/client/dist/assets/index-DXeJAcap.js | 9 - packages/client/dist/data.example.json | 169 ------------- packages/client/dist/index.html | 2 +- packages/client/public/data.example.json | 169 ------------- packages/client/src/App.tsx | 45 +++- packages/client/src/data.ts | 58 ----- packages/client/src/ws.ts | 239 ++++++++++++++++++ packages/client/vite.config.ts | 9 + source/web-server.ts | 27 ++ tests/client-ws.spec.ts | 83 ++++++ tests/web-server.spec.ts | 130 ++++++++++ 20 files changed, 786 insertions(+), 444 deletions(-) create mode 100644 packages/agent-core/src/web/protocol.ts create mode 100644 packages/client/dist/assets/index-BVFN01-c.js delete mode 100644 packages/client/dist/assets/index-DXeJAcap.js delete mode 100644 packages/client/dist/data.example.json delete mode 100644 packages/client/public/data.example.json delete mode 100644 packages/client/src/data.ts create mode 100644 packages/client/src/ws.ts create mode 100644 source/web-server.ts create mode 100644 tests/client-ws.spec.ts create mode 100644 tests/web-server.spec.ts diff --git a/README.md b/README.md index 2af8489..006fc7b 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ call-code 是一个本地运行的终端编程 Agent(CLI coding agent),基 - 本地记忆:短期记忆按任务保存,长期记忆按主题沉淀,仅在进程内使用,不写入本地 JSON。 - 上下文预算:运行时基于 token 估算对历史消息做裁剪,减少超出模型上下文的风险。 - 会话持久化:基于 Node 内置 `node:sqlite` 保存会话、条目、泳道、分支、记录、统计、事实和租约,默认写入 `.agent-sessions/sessions.db`。 -- 会话客户端:`packages/client` 提供 React + Vite 会话界面,静态展示已停止,后续用于实时对话展示。 +- 会话客户端:`packages/client` 提供 React + Vite 会话界面,通过 WebSocket 实时展示会话数据。 ## 架构 @@ -63,6 +63,7 @@ OpenAI-compatible LLM 模型层 ```text source/ app.tsx # Ink CLI 入口与交互界面 + web-server.ts # Web 会话面板服务入口 packages/ agent-core/ # 核心 agent、上下文、记忆、工具与协议实现 src/ @@ -80,8 +81,8 @@ packages/ utils/ # shell 与文本截断等工具 types/ # 领域类型 utils/ # JSON、日志工具 - web/ # 会话数据导出 - client/ # TypeScript + React 会话界面客户端 + web/ # 会话导出与 WebSocket 服务 + client/ # TypeScript + React 会话界面客户端(WebSocket 数据) session-sqlite/ # 基于 node:sqlite 的会话历史与运行状态存储 tests/ # 项目统一单元测试 vitest.config.ts # Vitest 测试配置 @@ -121,6 +122,7 @@ bun dev | `AGENT_DESKTOP_DIR` | 可选,覆盖桌面目录路径,便于测试或自定义工作环境。 | | `SESSION_DB_PATH` | 可选,SQLite 会话库文件路径,默认 `.agent-sessions/sessions.db`。 | | `CALL_CODE_WEB_DATA` | 可选,CLI 内 `/export` 的输出路径,默认 `packages/client/public/data.json`。 | +| `CALL_CODE_WEB_PORT` | 可选,Web 会话面板监听端口,默认 4173。 | ## CLI 命令与快捷键 @@ -169,8 +171,22 @@ bun run export:web # 构建会话客户端(本地预览用) bun run build:client + +# 启动 Web 会话面板(静态托管客户端 + WebSocket 数据服务) +bun run web:serve +``` + +## Web 会话面板 + +Web 会话面板由 `source/web-server.ts` 启动:它读取 `SESSION_DB_PATH` 指向的会话库,静态托管 `packages/client/dist`,并在 `/ws` 提供 `sessions.list` / `sessions.snapshot` 消息。客户端默认连接同源 `/ws`,并周期性刷新会话快照;也可以用 `?ws=` 覆盖服务地址,用 `?session=` 直达某个会话。 + +```bash +bun run build:client +bun run web:serve ``` +然后打开 `http://127.0.0.1:4173`。开发模式下先启动 `web:serve`,再运行 `bun run dev:client`,Vite 会把 `/ws` 代理到会话服务。 + ## Docker 镜像 构建镜像: diff --git a/bun.lock b/bun.lock index 21444af..96d85e4 100644 --- a/bun.lock +++ b/bun.lock @@ -32,8 +32,10 @@ "openai": "^6.34.0", "tesseract.js": "^7.0.0", "tiktoken": "^1.0.20", + "ws": "^8.21.3", }, "devDependencies": { + "@types/ws": "^8.18.1", "typescript": "^6.0.3", }, }, @@ -263,6 +265,8 @@ "@types/react-dom": ["@types/react-dom@19.2.4", "", { "peerDependencies": { "@types/react": "^19.2.0" } }, "sha512-Bsc+QHgp+P/F02XDzNCY9jnZNCUuLki36KT7VKrTXXLdHf+vHMNZnW1rVu5DNW/rCK+fya3DATySbLM4yhtKUw=="], + "@types/ws": ["@types/ws@8.18.1", "", { "dependencies": { "@types/node": "*" } }, "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg=="], + "@vitejs/plugin-react": ["@vitejs/plugin-react@6.0.5", "", { "dependencies": { "@rolldown/pluginutils": "^1.0.1" }, "peerDependencies": { "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", "babel-plugin-react-compiler": "^1.0.0", "vite": "^8.0.0" }, "optionalPeers": ["@rolldown/plugin-babel", "babel-plugin-react-compiler"] }, "sha512-BOVzne/NL162sMdResB25mUv+vWMF5NoAjNf09TeGlE7ZpszZWSD3winycicLJw72yeVsoCn/2kOhEuCvEShMA=="], "@vitest/expect": ["@vitest/expect@3.2.7", "", { "dependencies": { "@types/chai": "^5.2.2", "@vitest/spy": "3.2.7", "@vitest/utils": "3.2.7", "chai": "^5.2.0", "tinyrainbow": "^2.0.0" } }, "sha512-E8eBXaKibuvH2pSZErOjdVb5vF4PbKYcrnluBTYxEk1l/VhhwZg1kZQsdtjq+CsF5CFydf2Rdkz7jDHKSisi3w=="], diff --git a/package.json b/package.json index 896b1ec..638a619 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ "export:web": "tsx tests/export-web.ts", "dev:client": "bun run --cwd packages/client dev", "build:client": "bun run --cwd packages/client build", - "preview:client": "bun run --cwd packages/client preview" + "preview:client": "bun run --cwd packages/client preview", + "web:serve": "tsx source/web-server.ts" }, "dependencies": { "dotenv": "^17.4.2", diff --git a/packages/agent-core/package.json b/packages/agent-core/package.json index f07f34a..a7e5922 100644 --- a/packages/agent-core/package.json +++ b/packages/agent-core/package.json @@ -13,9 +13,11 @@ "dotenv": "^17.4.2", "openai": "^6.34.0", "tesseract.js": "^7.0.0", - "tiktoken": "^1.0.20" + "tiktoken": "^1.0.20", + "ws": "^8.21.3" }, "devDependencies": { + "@types/ws": "^8.18.1", "typescript": "^6.0.3" } } diff --git a/packages/agent-core/src/web/export.ts b/packages/agent-core/src/web/export.ts index 2ecf2e7..ff1f5e2 100644 --- a/packages/agent-core/src/web/export.ts +++ b/packages/agent-core/src/web/export.ts @@ -61,7 +61,7 @@ export interface WebExport { } /** export.ts 需要的存储最小接口,兼容 SessionStoreLike 及 SQLite 扩展方法。 */ -type WebStore = SessionStoreLike & { +export type WebStore = SessionStoreLike & { getRecords?: (sessionId: string, options?: { limit?: number; offset?: number }) => WebRecord[]; listFacts?: (sessionId: string) => WebFact[]; }; diff --git a/packages/agent-core/src/web/protocol.ts b/packages/agent-core/src/web/protocol.ts new file mode 100644 index 0000000..4f3732c --- /dev/null +++ b/packages/agent-core/src/web/protocol.ts @@ -0,0 +1,28 @@ +import type { WebExport } from './export'; + +/** 客户端发给 WebSocket 服务的请求。 */ +export type WebSocketClientMessage = { + type: 'sessions.list'; +}; + +/** 服务端发给客户端的响应。 */ +export type WebSocketServerMessage = + | { type: 'sessions.snapshot'; data: WebExport } + | { type: 'error'; message: string }; + +/** 解析客户端文本消息,格式非法或类型未知时返回 null。 */ +export const parseClientMessage = ( + raw: string, +): WebSocketClientMessage | null => { + try { + const value: unknown = JSON.parse(raw); + if (!value || typeof value !== 'object') { + return null; + } + + const message = value as { type?: unknown }; + return message.type === 'sessions.list' ? { type: 'sessions.list' } : null; + } catch { + return null; + } +}; diff --git a/packages/agent-core/src/web/server.ts b/packages/agent-core/src/web/server.ts index e69de29..9d2da98 100644 --- a/packages/agent-core/src/web/server.ts +++ b/packages/agent-core/src/web/server.ts @@ -0,0 +1,191 @@ +import { createServer, type IncomingMessage, type ServerResponse } from 'node:http'; +import { readFile, stat } from 'node:fs/promises'; +import { extname, join, resolve, sep } from 'node:path'; +import { fileURLToPath } from 'node:url'; +import { WebSocket, WebSocketServer } from 'ws'; +import { buildWebExport, type WebStore } from './export'; +import { parseClientMessage, type WebSocketServerMessage } from './protocol'; + +const DEFAULT_CLIENT_DIR = fileURLToPath( + new URL('../../../client/dist', import.meta.url), +); +const DEFAULT_PORT = 4173; + +const MIME_TYPES: Record = { + '.html': 'text/html; charset=utf-8', + '.js': 'text/javascript; charset=utf-8', + '.mjs': 'text/javascript; charset=utf-8', + '.css': 'text/css; charset=utf-8', + '.json': 'application/json; charset=utf-8', + '.png': 'image/png', + '.jpg': 'image/jpeg', + '.jpeg': 'image/jpeg', + '.svg': 'image/svg+xml', + '.webp': 'image/webp', + '.ico': 'image/x-icon', + '.map': 'application/json; charset=utf-8', + '.txt': 'text/plain; charset=utf-8', +}; + +export interface WebServerOptions { + store: WebStore; + clientDir?: string; + host?: string; + port?: number; +} + +export interface WebServerHandle { + host: string; + port: number; + close(): Promise; +} + +const sendJson = (socket: WebSocket, message: WebSocketServerMessage) => { + socket.send(JSON.stringify(message)); +}; + +const safePath = (root: string, pathname: string): string | null => { + const candidate = resolve(root, `.${pathname}`); + if (candidate !== root && !candidate.startsWith(root + sep)) { + return null; + } + return candidate; +}; + +const serveFile = async ( + res: ServerResponse, + target: string, + headOnly: boolean, +): Promise => { + try { + const info = await stat(target); + if (!info.isFile()) { + return false; + } + + const content = await readFile(target); + res.writeHead(200, { + 'Content-Type': MIME_TYPES[extname(target)] ?? 'application/octet-stream', + 'Content-Length': content.length, + }); + res.end(headOnly ? undefined : content); + return true; + } catch { + return false; + } +}; + +const serveStatic = async ( + req: IncomingMessage, + res: ServerResponse, + clientDir: string, +): Promise => { + if (req.method !== 'GET' && req.method !== 'HEAD') { + res.writeHead(405, { Allow: 'GET, HEAD' }); + res.end(); + return; + } + + let pathname = '/'; + try { + pathname = decodeURIComponent( + new URL(req.url ?? '/', 'http://localhost').pathname, + ); + } catch { + res.writeHead(400); + res.end(); + return; + } + + const root = resolve(clientDir); + const requested = pathname === '/' ? '/index.html' : pathname; + const filePath = safePath(root, requested); + if (!filePath) { + res.writeHead(404); + res.end(); + return; + } + + const headOnly = req.method === 'HEAD'; + if (await serveFile(res, filePath, headOnly)) { + return; + } + + // 单页应用回退到入口页,避免刷新子路由时 404 + const fallback = join(root, 'index.html'); + if (await serveFile(res, fallback, headOnly)) { + return; + } + + res.writeHead(404); + res.end(); +}; + +/** + * 启动 Web 会话面板:静态托管客户端构建产物,并在 /ws 提供会话快照。 + */ +export const startWebServer = async ( + options: WebServerOptions, +): Promise => { + const store = options.store; + const clientDir = options.clientDir ?? DEFAULT_CLIENT_DIR; + const host = options.host ?? '127.0.0.1'; + const port = + options.port ?? Number(process.env.CALL_CODE_WEB_PORT ?? DEFAULT_PORT); + + const httpServer = createServer((req, res) => { + void serveStatic(req, res, clientDir); + }); + + const wss = new WebSocketServer({ server: httpServer, path: '/ws' }); + wss.on('connection', (socket) => { + socket.on('message', (raw) => { + const text = typeof raw === 'string' ? raw : raw.toString(); + const message = parseClientMessage(text); + if (!message) { + sendJson(socket, { type: 'error', message: '无法解析请求消息' }); + return; + } + + sendJson(socket, { + type: 'sessions.snapshot', + data: buildWebExport(store), + }); + }); + }); + + await new Promise((resolveListen, rejectListen) => { + httpServer.once('error', rejectListen); + httpServer.listen(port, host, () => { + httpServer.off('error', rejectListen); + resolveListen(); + }); + }); + + const address = httpServer.address(); + if (!address || typeof address === 'string') { + throw new Error('无法获取 Web 服务端口'); + } + + return { + host, + port: address.port, + async close() { + for (const client of wss.clients) { + client.terminate(); + } + await new Promise((resolveClose) => { + wss.close(() => resolveClose()); + }); + await new Promise((resolveClose, rejectClose) => { + httpServer.close((error) => { + if (error) { + rejectClose(error); + } else { + resolveClose(); + } + }); + }); + }, + }; +}; diff --git a/packages/client/README.md b/packages/client/README.md index 80f7bfa..3fa6340 100644 --- a/packages/client/README.md +++ b/packages/client/README.md @@ -1,6 +1,6 @@ # Call Code History Client -这是 CLI 会话历史的静态展示端,基于 TypeScript、React 和 Tailwind CSS 构建,当前仅用于本地预览,不再部署到 GitHub Pages。页面默认读取 `data.json`,如果不存在则回退到 `data.example.json` 预览数据;也可以用 `?data=` 指定数据文件,用 `?session=` 直达某个会话。 +这是 CLI 会话历史的 Web 展示端,基于 TypeScript、React 和 Tailwind CSS 构建。页面通过 WebSocket 从会话服务实时读取数据,不再依赖静态 JSON 文件。 ## 构建 @@ -8,33 +8,22 @@ bun run build:client ``` -产物输出到 `packages/client/dist`,用于本地预览。 +产物输出到 `packages/client/dist`。 ## 本地开发 -```bash -bun run dev:client -``` - -## 导出数据 - -在仓库根目录运行: +先启动会话服务,再启动 Vite 开发服务器: ```bash -bun run export:web +bun run web:serve +bun run dev:client ``` -脚本会把当前 `SESSION_DB_PATH` 指向的会话数据库导出为 `packages/client/public/data.json`。也可以在 CLI 中执行 `/export` 完成同样操作。 - -导出文件包含会话、消息、工具调用、统计和事实数据。若后续公开发布,请先检查内容是否包含不该公开的路径、命令输出或密钥。 - -## 本地预览 +`web:serve` 默认监听 `127.0.0.1:4173`,可通过 `CALL_CODE_WEB_PORT` 修改端口;Vite 会把 `/ws` 代理到会话服务。 -预览构建产物: +## 数据服务 -```bash -bun run preview:client -``` +CLI 会话写入 `SESSION_DB_PATH` 指向的 SQLite 数据库,默认 `.agent-sessions/sessions.db`。`web:serve` 读取同一个数据库,并在 `/ws` 提供 `sessions.list` / `sessions.snapshot` 消息。页面默认连接同源 `/ws`,也可以使用 `?ws=` 覆盖服务地址,使用 `?session=` 直达某个会话。 ## 主题 diff --git a/packages/client/dist/assets/index-BVFN01-c.js b/packages/client/dist/assets/index-BVFN01-c.js new file mode 100644 index 0000000..c9f28f6 --- /dev/null +++ b/packages/client/dist/assets/index-BVFN01-c.js @@ -0,0 +1,9 @@ +var e=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports);(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var t=e((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.consumer`),s=Symbol.for(`react.context`),c=Symbol.for(`react.forward_ref`),l=Symbol.for(`react.suspense`),u=Symbol.for(`react.memo`),d=Symbol.for(`react.lazy`),f=Symbol.for(`react.activity`),p=Symbol.iterator;function m(e){return typeof e!=`object`||!e?null:(e=p&&e[p]||e[`@@iterator`],typeof e==`function`?e:null)}var h={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},g=Object.assign,_={};function v(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}v.prototype.isReactComponent={},v.prototype.setState=function(e,t){if(typeof e!=`object`&&typeof e!=`function`&&e!=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,e,t,`setState`)},v.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,`forceUpdate`)};function y(){}y.prototype=v.prototype;function b(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}var x=b.prototype=new y;x.constructor=b,g(x,v.prototype),x.isPureReactComponent=!0;var ee=Array.isArray;function S(){}var C={H:null,A:null,T:null,S:null},te=Object.prototype.hasOwnProperty;function ne(e,n,r){var i=r.ref;return{$$typeof:t,type:e,key:n,ref:i===void 0?null:i,props:r}}function re(e,t){return ne(e.type,t,e.props)}function w(e){return typeof e==`object`&&!!e&&e.$$typeof===t}function ie(e){var t={"=":`=0`,":":`=2`};return`$`+e.replace(/[=:]/g,function(e){return t[e]})}var ae=/\/+/g;function oe(e,t){return typeof e==`object`&&e&&e.key!=null?ie(``+e.key):t.toString(36)}function se(e){switch(e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason;default:switch(typeof e.status==`string`?e.then(S,S):(e.status=`pending`,e.then(function(t){e.status===`pending`&&(e.status=`fulfilled`,e.value=t)},function(t){e.status===`pending`&&(e.status=`rejected`,e.reason=t)})),e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason}}throw e}function ce(e,r,i,a,o){var s=typeof e;(s===`undefined`||s===`boolean`)&&(e=null);var c=!1;if(e===null)c=!0;else switch(s){case`bigint`:case`string`:case`number`:c=!0;break;case`object`:switch(e.$$typeof){case t:case n:c=!0;break;case d:return c=e._init,ce(c(e._payload),r,i,a,o)}}if(c)return o=o(e),c=a===``?`.`+oe(e,0):a,ee(o)?(i=``,c!=null&&(i=c.replace(ae,`$&/`)+`/`),ce(o,r,i,``,function(e){return e})):o!=null&&(w(o)&&(o=re(o,i+(o.key==null||e&&e.key===o.key?``:(``+o.key).replace(ae,`$&/`)+`/`)+c)),r.push(o)),1;c=0;var l=a===``?`.`:a+`:`;if(ee(e))for(var u=0;u{n.exports=t()})),r=e((e=>{function t(e,t){var n=e.length;e.push(t);a:for(;0>>1,a=e[r];if(0>>1;ri(c,n))li(u,c)?(e[r]=u,e[l]=n,r=l):(e[r]=c,e[s]=n,r=s);else if(li(u,n))e[r]=u,e[l]=n,r=l;else break a}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return n===0?e.id-t.id:n}if(e.unstable_now=void 0,typeof performance==`object`&&typeof performance.now==`function`){var a=performance;e.unstable_now=function(){return a.now()}}else{var o=Date,s=o.now();e.unstable_now=function(){return o.now()-s}}var c=[],l=[],u=1,d=null,f=3,p=!1,m=!1,h=!1,g=!1,_=typeof setTimeout==`function`?setTimeout:null,v=typeof clearTimeout==`function`?clearTimeout:null,y=typeof setImmediate<`u`?setImmediate:null;function b(e){for(var i=n(l);i!==null;){if(i.callback===null)r(l);else if(i.startTime<=e)r(l),i.sortIndex=i.expirationTime,t(c,i);else break;i=n(l)}}function x(e){if(h=!1,b(e),!m){if(n(c)!==null)m=!0,ee||(ee=!0,w());else{var t=n(l);t!==null&&oe(x,t.startTime-e)}}}var ee=!1,S=-1,C=5,te=-1;function ne(){return g?!0:!(e.unstable_now()-tet&&ne());){var o=d.callback;if(typeof o==`function`){d.callback=null,f=d.priorityLevel;var s=o(d.expirationTime<=t);if(t=e.unstable_now(),typeof s==`function`){d.callback=s,b(t),i=!0;break b}d===n(c)&&r(c),b(t)}else r(c);d=n(c)}if(d!==null)i=!0;else{var u=n(l);u!==null&&oe(x,u.startTime-t),i=!1}}break a}finally{d=null,f=a,p=!1}}}finally{i?w():ee=!1}}}var w;if(typeof y==`function`)w=function(){y(re)};else if(typeof MessageChannel<`u`){var ie=new MessageChannel,ae=ie.port2;ie.port1.onmessage=re,w=function(){ae.postMessage(null)}}else w=function(){_(re,0)};function oe(t,n){S=_(function(){t(e.unstable_now())},n)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(e){e.callback=null},e.unstable_forceFrameRate=function(e){0>e||125o?(r.sortIndex=a,t(l,r),n(c)===null&&r===n(l)&&(h?(v(S),S=-1):h=!0,oe(x,a-o))):(r.sortIndex=s,t(c,r),m||p||(m=!0,ee||(ee=!0,w()))),r},e.unstable_shouldYield=ne,e.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}})),i=e(((e,t)=>{t.exports=r()})),a=e((e=>{var t=n();function r(e){var t=`https://react.dev/errors/`+e;if(1{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=a()})),s=e((e=>{var t=i(),r=n(),a=o();function s(e){var t=`https://react.dev/errors/`+e;if(1pe||(e.current=fe[pe],fe[pe]=null,pe--)}function O(e,t){pe++,fe[pe]=e.current,e.current=t}var he=me(null),ge=me(null),_e=me(null),ve=me(null);function ye(e,t){switch(O(_e,t),O(ge,e),O(he,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Vd(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Vd(t),e=Hd(t,e);else switch(e){case`svg`:e=1;break;case`math`:e=2;break;default:e=0}}D(he),O(he,e)}function be(){D(he),D(ge),D(_e)}function xe(e){e.memoizedState!==null&&O(ve,e);var t=he.current,n=Hd(t,e.type);t!==n&&(O(ge,e),O(he,n))}function Se(e){ge.current===e&&(D(he),D(ge)),ve.current===e&&(D(ve),Qf._currentValue=de)}var Ce,we;function Te(e){if(Ce===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);Ce=t&&t[1]||``,we=-1)`:-1i||c[r]!==l[i]){var u=` +`+c[r].replace(` at new `,` at `);return e.displayName&&u.includes(``)&&(u=u.replace(``,e.displayName)),u}while(1<=r&&0<=i);break}}}finally{Ee=!1,Error.prepareStackTrace=n}return(n=e?e.displayName||e.name:``)?Te(n):``}function Oe(e,t){switch(e.tag){case 26:case 27:case 5:return Te(e.type);case 16:return Te(`Lazy`);case 13:return e.child!==t&&t!==null?Te(`Suspense Fallback`):Te(`Suspense`);case 19:return Te(`SuspenseList`);case 0:case 15:return De(e.type,!1);case 11:return De(e.type.render,!1);case 1:return De(e.type,!0);case 31:return Te(`Activity`);default:return``}}function ke(e){try{var t=``,n=null;do t+=Oe(e,n),n=e,e=e.return;while(e);return t}catch(e){return` +Error generating stack: `+e.message+` +`+e.stack}}var Ae=Object.prototype.hasOwnProperty,je=t.unstable_scheduleCallback,Me=t.unstable_cancelCallback,Ne=t.unstable_shouldYield,Pe=t.unstable_requestPaint,Fe=t.unstable_now,Ie=t.unstable_getCurrentPriorityLevel,Le=t.unstable_ImmediatePriority,Re=t.unstable_UserBlockingPriority,ze=t.unstable_NormalPriority,Be=t.unstable_LowPriority,Ve=t.unstable_IdlePriority,He=t.log,Ue=t.unstable_setDisableYieldValue,We=null,Ge=null;function Ke(e){if(typeof He==`function`&&Ue(e),Ge&&typeof Ge.setStrictMode==`function`)try{Ge.setStrictMode(We,e)}catch{}}var qe=Math.clz32?Math.clz32:Xe,Je=Math.log,Ye=Math.LN2;function Xe(e){return e>>>=0,e===0?32:31-(Je(e)/Ye|0)|0}var Ze=256,Qe=262144,$e=4194304;function et(e){var t=e&42;if(t!==0)return t;switch(e&-e){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 e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function tt(e,t,n){var r=e.pendingLanes;if(r===0)return 0;var i=0,a=e.suspendedLanes,o=e.pingedLanes;e=e.warmLanes;var s=r&134217727;return s===0?(s=r&~a,s===0?o===0?n||(n=r&~e,n!==0&&(i=et(n))):i=et(o):i=et(s)):(r=s&~a,r===0?(o&=s,o===0?n||(n=s&~e,n!==0&&(i=et(n))):i=et(o)):i=et(r)),i===0?0:t!==0&&t!==i&&(t&a)===0&&(a=i&-i,n=t&-t,a>=n||a===32&&n&4194048)?t:i}function nt(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function rt(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+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 t+5e3;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 it(){var e=$e;return $e<<=1,!($e&62914560)&&($e=4194304),e}function at(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function ot(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function st(e,t,n,r,i,a){var o=e.pendingLanes;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=n,e.entangledLanes&=n,e.errorRecoveryDisabledLanes&=n,e.shellSuspendCounter=0;var s=e.entanglements,c=e.expirationTimes,l=e.hiddenUpdates;for(n=o&~n;0`u`||window.document===void 0||window.document.createElement===void 0),yn=!1;if(vn)try{var bn={};Object.defineProperty(bn,"passive",{get:function(){yn=!0}}),window.addEventListener(`test`,bn,bn),window.removeEventListener(`test`,bn,bn)}catch{yn=!1}var xn=null,Sn=null,Cn=null;function wn(){if(Cn)return Cn;var e,t=Sn,n=t.length,r,i=`value`in xn?xn.value:xn.textContent,a=i.length;for(e=0;e=nr),ar=` `,or=!1;function sr(e,t){switch(e){case`keyup`:return er.indexOf(t.keyCode)!==-1;case`keydown`:return t.keyCode!==229;case`keypress`:case`mousedown`:case`focusout`:return!0;default:return!1}}function cr(e){return e=e.detail,typeof e==`object`&&`data`in e?e.data:null}var lr=!1;function ur(e,t){switch(e){case`compositionend`:return cr(t);case`keypress`:return t.which===32?(or=!0,ar):null;case`textInput`:return e=t.data,e===ar&&or?null:e;default:return null}}function dr(e,t){if(lr)return e===`compositionend`||!tr&&sr(e,t)?(e=wn(),Cn=Sn=xn=null,lr=!1,e):null;switch(e){case`paste`:return null;case`keypress`:if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}a:{for(;n;){if(n.nextSibling){n=n.nextSibling;break a}n=n.parentNode}n=void 0}n=Nr(n)}}function Fr(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?Fr(e,t.parentNode):`contains`in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Ir(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=Gt(e.document);t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href==`string`}catch{n=!1}if(n)e=t.contentWindow;else break;t=Gt(e.document)}return t}function Lr(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t===`input`&&(e.type===`text`||e.type===`search`||e.type===`tel`||e.type===`url`||e.type===`password`)||t===`textarea`||e.contentEditable===`true`)}var Rr=vn&&`documentMode`in document&&11>=document.documentMode,zr=null,Br=null,Vr=null,Hr=!1;function Ur(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;Hr||zr==null||zr!==Gt(r)||(r=zr,`selectionStart`in r&&Lr(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),Vr&&Mr(Vr,r)||(Vr=r,r=Ed(Br,`onSelect`),0>=o,i-=o,Fi=1<<32-qe(t)+i|n<h?(g=d,d=null):g=d.sibling;var _=p(i,d,s[h],c);if(_===null){d===null&&(d=g);break}e&&d&&_.alternate===null&&t(i,d),o=a(_,o,h),u===null?l=_:u.sibling=_,u=_,d=g}if(h===s.length)return n(i,d),j&&Li(i,h),l;if(d===null){for(;hg?(_=h,h=null):_=h.sibling;var y=p(i,h,v.value,l);if(y===null){h===null&&(h=_);break}e&&h&&y.alternate===null&&t(i,h),o=a(y,o,g),d===null?u=y:d.sibling=y,d=y,h=_}if(v.done)return n(i,h),j&&Li(i,g),u;if(h===null){for(;!v.done;g++,v=c.next())v=f(i,v.value,l),v!==null&&(o=a(v,o,g),d===null?u=v:d.sibling=v,d=v);return j&&Li(i,g),u}for(h=r(h);!v.done;g++,v=c.next())v=m(h,i,g,v.value,l),v!==null&&(e&&v.alternate!==null&&h.delete(v.key===null?g:v.key),o=a(v,o,g),d===null?u=v:d.sibling=v,d=v);return e&&h.forEach(function(e){return t(i,e)}),j&&Li(i,g),u}function b(e,r,a,c){if(typeof a==`object`&&a&&a.type===y&&a.key===null&&(a=a.props.children),typeof a==`object`&&a){switch(a.$$typeof){case _:a:{for(var l=a.key;r!==null;){if(r.key===l){if(l=a.type,l===y){if(r.tag===7){n(e,r.sibling),c=i(r,a.props.children),c.return=e,e=c;break a}}else if(r.elementType===l||typeof l==`object`&&l&&l.$$typeof===w&&Fa(l)===r.type){n(e,r.sibling),c=i(r,a.props),Ha(c,a),c.return=e,e=c;break a}n(e,r);break}t(e,r),r=r.sibling}a.type===y?(c=Si(a.props.children,e.mode,c,a.key),c.return=e,e=c):(c=xi(a.type,a.key,a.props,null,e.mode,c),Ha(c,a),c.return=e,e=c)}return o(e);case v:a:{for(l=a.key;r!==null;){if(r.key===l){if(r.tag===4&&r.stateNode.containerInfo===a.containerInfo&&r.stateNode.implementation===a.implementation){n(e,r.sibling),c=i(r,a.children||[]),c.return=e,e=c;break a}n(e,r);break}t(e,r),r=r.sibling}c=Ti(a,e.mode,c),c.return=e,e=c}return o(e);case w:return a=Fa(a),b(e,r,a,c)}if(ue(a))return h(e,r,a,c);if(se(a)){if(l=se(a),typeof l!=`function`)throw Error(s(150));return a=l.call(a),g(e,r,a,c)}if(typeof a.then==`function`)return b(e,r,Va(a),c);if(a.$$typeof===S)return b(e,r,ua(e,a),c);Ua(e,a)}return typeof a==`string`&&a!==``||typeof a==`number`||typeof a==`bigint`?(a=``+a,r!==null&&r.tag===6?(n(e,r.sibling),c=i(r,a),c.return=e,e=c):(n(e,r),c=Ci(a,e.mode,c),c.return=e,e=c),o(e)):n(e,r)}return function(e,t,n,r){try{Ba=0;var i=b(e,t,n,r);return za=null,i}catch(t){if(t===ka||t===ja)throw t;var a=_i(29,t,null,e.mode);return a.lanes=r,a.return=e,a}}}var Ga=Wa(!0),Ka=Wa(!1),qa=!1;function Ja(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Ya(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function Xa(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function Za(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,W&2){var i=r.pending;return i===null?t.next=t:(t.next=i.next,i.next=t),r.pending=t,t=mi(e),pi(e,null,n),t}return ui(e,r,t,n),mi(e)}function Qa(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,n&4194048)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,lt(e,n)}}function $a(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var i=null,a=null;if(n=n.firstBaseUpdate,n!==null){do{var o={lane:n.lane,tag:n.tag,payload:n.payload,callback:null,next:null};a===null?i=a=o:a=a.next=o,n=n.next}while(n!==null);a===null?i=a=t:a=a.next=t}else i=a=t;n={baseState:r.baseState,firstBaseUpdate:i,lastBaseUpdate:a,shared:r.shared,callbacks:r.callbacks},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}var eo=!1;function to(){if(eo){var e=ba;if(e!==null)throw e}}function no(e,t,n,r){eo=!1;var i=e.updateQueue;qa=!1;var a=i.firstBaseUpdate,o=i.lastBaseUpdate,s=i.shared.pending;if(s!==null){i.shared.pending=null;var c=s,l=c.next;c.next=null,o===null?a=l:o.next=l,o=c;var u=e.alternate;u!==null&&(u=u.updateQueue,s=u.lastBaseUpdate,s!==o&&(s===null?u.firstBaseUpdate=l:s.next=l,u.lastBaseUpdate=c))}if(a!==null){var d=i.baseState;o=0,u=l=c=null,s=a;do{var f=s.lane&-536870913,p=f!==s.lane;if(p?(q&f)===f:(r&f)===f){f!==0&&f===ya&&(eo=!0),u!==null&&(u=u.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});a:{var m=e,g=s;f=t;var _=n;switch(g.tag){case 1:if(m=g.payload,typeof m==`function`){d=m.call(_,d,f);break a}d=m;break a;case 3:m.flags=m.flags&-65537|128;case 0:if(m=g.payload,f=typeof m==`function`?m.call(_,d,f):m,f==null)break a;d=h({},d,f);break a;case 2:qa=!0}}f=s.callback,f!==null&&(e.flags|=64,p&&(e.flags|=8192),p=i.callbacks,p===null?i.callbacks=[f]:p.push(f))}else p={lane:f,tag:s.tag,payload:s.payload,callback:s.callback,next:null},u===null?(l=u=p,c=d):u=u.next=p,o|=f;if(s=s.next,s===null){if(s=i.shared.pending,s===null)break;p=s,s=p.next,p.next=null,i.lastBaseUpdate=p,i.shared.pending=null}}while(1);u===null&&(c=d),i.baseState=c,i.firstBaseUpdate=l,i.lastBaseUpdate=u,a===null&&(i.shared.lanes=0),Kl|=o,e.lanes=o,e.memoizedState=d}}function ro(e,t){if(typeof e!=`function`)throw Error(s(191,e));e.call(t)}function io(e,t){var n=e.callbacks;if(n!==null)for(e.callbacks=null,e=0;ea?a:8;var o=T.T,s={};T.T=s,zs(e,!1,t,n);try{var c=i(),l=T.S;l!==null&&l(s,c),typeof c==`object`&&c&&typeof c.then==`function`?Rs(e,t,Ca(c,r),pu(e)):Rs(e,t,r,pu(e))}catch(n){Rs(e,t,{then:function(){},status:`rejected`,reason:n},pu())}finally{E.p=a,o!==null&&s.types!==null&&(o.types=s.types),T.T=o}}function Os(){}function ks(e,t,n,r){if(e.tag!==5)throw Error(s(476));var i=As(e).queue;Ds(e,i,t,de,n===null?Os:function(){return js(e),n(r)})}function As(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:de,baseState:de,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Bo,lastRenderedState:de},next:null};var n={};return t.next={memoizedState:n,baseState:n,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Bo,lastRenderedState:n},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function js(e){var t=As(e);t.next===null&&(t=e.alternate.memoizedState),Rs(e,t.next.queue,{},pu())}function Ms(){return la(Qf)}function Ns(){return R().memoizedState}function Ps(){return R().memoizedState}function Fs(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var n=pu();e=Xa(n);var r=Za(t,e,n);r!==null&&(hu(r,t,n),Qa(r,t,n)),t={cache:ha()},e.payload=t;return}t=t.return}}function Is(e,t,n){var r=pu();n={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null},Bs(e)?Vs(t,n):(n=di(e,t,n,r),n!==null&&(hu(n,e,r),Hs(n,t,r)))}function Ls(e,t,n){Rs(e,t,n,pu())}function Rs(e,t,n,r){var i={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null};if(Bs(e))Vs(t,i);else{var a=e.alternate;if(e.lanes===0&&(a===null||a.lanes===0)&&(a=t.lastRenderedReducer,a!==null))try{var o=t.lastRenderedState,s=a(o,n);if(i.hasEagerState=!0,i.eagerState=s,jr(s,o))return ui(e,t,i,0),G===null&&li(),!1}catch{}if(n=di(e,t,i,r),n!==null)return hu(n,e,r),Hs(n,t,r),!0}return!1}function zs(e,t,n,r){if(r={lane:2,revertLane:dd(),gesture:null,action:r,hasEagerState:!1,eagerState:null,next:null},Bs(e)){if(t)throw Error(s(479))}else t=di(e,n,r,2),t!==null&&hu(t,e,2)}function Bs(e){var t=e.alternate;return e===P||t!==null&&t===P}function Vs(e,t){xo=bo=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function Hs(e,t,n){if(n&4194048){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,lt(e,n)}}var Us={readContext:la,use:Ro,useCallback:L,useContext:L,useEffect:L,useImperativeHandle:L,useLayoutEffect:L,useInsertionEffect:L,useMemo:L,useReducer:L,useRef:L,useState:L,useDebugValue:L,useDeferredValue:L,useTransition:L,useSyncExternalStore:L,useId:L,useHostTransitionStatus:L,useFormState:L,useActionState:L,useOptimistic:L,useMemoCache:L,useCacheRefresh:L};Us.useEffectEvent=L;var Ws={readContext:la,use:Ro,useCallback:function(e,t){return Fo().memoizedState=[e,t===void 0?null:t],e},useContext:la,useEffect:ms,useImperativeHandle:function(e,t,n){n=n==null?null:n.concat([e]),fs(4194308,4,bs.bind(null,t,e),n)},useLayoutEffect:function(e,t){return fs(4194308,4,e,t)},useInsertionEffect:function(e,t){fs(4,2,e,t)},useMemo:function(e,t){var n=Fo();t=t===void 0?null:t;var r=e();if(So){Ke(!0);try{e()}finally{Ke(!1)}}return n.memoizedState=[r,t],r},useReducer:function(e,t,n){var r=Fo();if(n!==void 0){var i=n(t);if(So){Ke(!0);try{n(t)}finally{Ke(!1)}}}else i=t;return r.memoizedState=r.baseState=i,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:i},r.queue=e,e=e.dispatch=Is.bind(null,P,e),[r.memoizedState,e]},useRef:function(e){var t=Fo();return e={current:e},t.memoizedState=e},useState:function(e){e=Xo(e);var t=e.queue,n=Ls.bind(null,P,t);return t.dispatch=n,[e.memoizedState,n]},useDebugValue:Ss,useDeferredValue:function(e,t){return Ts(Fo(),e,t)},useTransition:function(){var e=Xo(!1);return e=Ds.bind(null,P,e.queue,!0,!1),Fo().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,n){var r=P,i=Fo();if(j){if(n===void 0)throw Error(s(407));n=n()}else{if(n=t(),G===null)throw Error(s(349));q&127||Go(r,t,n)}i.memoizedState=n;var a={value:n,getSnapshot:t};return i.queue=a,ms(qo.bind(null,r,a,e),[e]),r.flags|=2048,us(9,{destroy:void 0},Ko.bind(null,r,a,n,t),null),n},useId:function(){var e=Fo(),t=G.identifierPrefix;if(j){var n=Ii,r=Fi;n=(r&~(1<<32-qe(r)-1)).toString(32)+n,t=`_`+t+`R_`+n,n=Co++,0<\/script>`,a=a.removeChild(a.firstChild);break;case`select`:a=typeof r.is==`string`?o.createElement(`select`,{is:r.is}):o.createElement(`select`),r.multiple?a.multiple=!0:r.size&&(a.size=r.size);break;default:a=typeof r.is==`string`?o.createElement(i,{is:r.is}):o.createElement(i)}}a[gt]=t,a[_t]=r;a:for(o=t.child;o!==null;){if(o.tag===5||o.tag===6)a.appendChild(o.stateNode);else if(o.tag!==4&&o.tag!==27&&o.child!==null){o.child.return=o,o=o.child;continue}if(o===t)break a;for(;o.sibling===null;){if(o.return===null||o.return===t)break a;o=o.return}o.sibling.return=o.return,o=o.sibling}t.stateNode=a;a:switch(Pd(a,i,r),i){case`button`:case`input`:case`select`:case`textarea`:r=!!r.autoFocus;break a;case`img`:r=!0;break a;default:r=!1}r&&Lc(t)}}return B(t),Rc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,n),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==r&&Lc(t);else{if(typeof r!=`string`&&t.stateNode===null)throw Error(s(166));if(e=_e.current,Yi(t)){if(e=t.stateNode,n=t.memoizedProps,r=null,i=Hi,i!==null)switch(i.tag){case 27:case 5:r=i.memoizedProps}e[gt]=t,e=!!(e.nodeValue===n||r!==null&&!0===r.suppressHydrationWarning||Md(e.nodeValue,n)),e||Ki(t,!0)}else e=Bd(e).createTextNode(r),e[gt]=t,t.stateNode=e}return B(t),null;case 31:if(n=t.memoizedState,e===null||e.memoizedState!==null){if(r=Yi(t),n!==null){if(e===null){if(!r)throw Error(s(318));if(e=t.memoizedState,e=e===null?null:e.dehydrated,!e)throw Error(s(557));e[gt]=t}else Xi(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;B(t),e=!1}else n=Zi(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),e=!0;if(!e)return t.flags&256?(_o(t),t):(_o(t),null);if(t.flags&128)throw Error(s(558))}return B(t),null;case 13:if(r=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(i=Yi(t),r!==null&&r.dehydrated!==null){if(e===null){if(!i)throw Error(s(318));if(i=t.memoizedState,i=i===null?null:i.dehydrated,!i)throw Error(s(317));i[gt]=t}else Xi(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;B(t),i=!1}else i=Zi(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=i),i=!0;if(!i)return t.flags&256?(_o(t),t):(_o(t),null)}return _o(t),t.flags&128?(t.lanes=n,t):(n=r!==null,e=e!==null&&e.memoizedState!==null,n&&(r=t.child,i=null,r.alternate!==null&&r.alternate.memoizedState!==null&&r.alternate.memoizedState.cachePool!==null&&(i=r.alternate.memoizedState.cachePool.pool),a=null,r.memoizedState!==null&&r.memoizedState.cachePool!==null&&(a=r.memoizedState.cachePool.pool),a!==i&&(r.flags|=2048)),n!==e&&n&&(t.child.flags|=8192),Bc(t,t.updateQueue),B(t),null);case 4:return be(),e===null&&Sd(t.stateNode.containerInfo),B(t),null;case 10:return ra(t.type),B(t),null;case 19:if(D(N),r=t.memoizedState,r===null)return B(t),null;if(i=!!(t.flags&128),a=r.rendering,a===null){if(i)Vc(r,!1);else{if(Y!==0||e!==null&&e.flags&128)for(e=t.child;e!==null;){if(a=vo(e),a!==null){for(t.flags|=128,Vc(r,!1),e=a.updateQueue,t.updateQueue=e,Bc(t,e),t.subtreeFlags=0,e=n,n=t.child;n!==null;)bi(n,e),n=n.sibling;return O(N,N.current&1|2),j&&Li(t,r.treeForkCount),t.child}e=e.sibling}r.tail!==null&&Fe()>nu&&(t.flags|=128,i=!0,Vc(r,!1),t.lanes=4194304)}}else{if(!i){if(e=vo(a),e!==null){if(t.flags|=128,i=!0,e=e.updateQueue,t.updateQueue=e,Bc(t,e),Vc(r,!0),r.tail===null&&r.tailMode===`hidden`&&!a.alternate&&!j)return B(t),null}else 2*Fe()-r.renderingStartTime>nu&&n!==536870912&&(t.flags|=128,i=!0,Vc(r,!1),t.lanes=4194304)}r.isBackwards?(a.sibling=t.child,t.child=a):(e=r.last,e===null?t.child=a:e.sibling=a,r.last=a)}return r.tail===null?(B(t),null):(e=r.tail,r.rendering=e,r.tail=e.sibling,r.renderingStartTime=Fe(),e.sibling=null,n=N.current,O(N,i?n&1|2:n&1),j&&Li(t,r.treeForkCount),e);case 22:case 23:return _o(t),lo(),r=t.memoizedState!==null,e===null?r&&(t.flags|=8192):e.memoizedState!==null!==r&&(t.flags|=8192),r?n&536870912&&!(t.flags&128)&&(B(t),t.subtreeFlags&6&&(t.flags|=8192)):B(t),n=t.updateQueue,n!==null&&Bc(t,n.retryQueue),n=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(n=e.memoizedState.cachePool.pool),r=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(r=t.memoizedState.cachePool.pool),r!==n&&(t.flags|=2048),e!==null&&D(Ta),null;case 24:return n=null,e!==null&&(n=e.memoizedState.cache),t.memoizedState.cache!==n&&(t.flags|=2048),ra(M),B(t),null;case 25:return null;case 30:return null}throw Error(s(156,t.tag))}function Uc(e,t){switch(Bi(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return ra(M),be(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return Se(t),null;case 31:if(t.memoizedState!==null){if(_o(t),t.alternate===null)throw Error(s(340));Xi()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(_o(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(s(340));Xi()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return D(N),null;case 4:return be(),null;case 10:return ra(t.type),null;case 22:case 23:return _o(t),lo(),e!==null&&D(Ta),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return ra(M),null;case 25:return null;default:return null}}function Wc(e,t){switch(Bi(t),t.tag){case 3:ra(M),be();break;case 26:case 27:case 5:Se(t);break;case 4:be();break;case 31:t.memoizedState!==null&&_o(t);break;case 13:_o(t);break;case 19:D(N);break;case 10:ra(t.type);break;case 22:case 23:_o(t),lo(),e!==null&&D(Ta);break;case 24:ra(M)}}function Gc(e,t){try{var n=t.updateQueue,r=n===null?null:n.lastEffect;if(r!==null){var i=r.next;n=i;do{if((n.tag&e)===e){r=void 0;var a=n.create,o=n.inst;r=a(),o.destroy=r}n=n.next}while(n!==i)}}catch(e){Z(t,t.return,e)}}function Kc(e,t,n){try{var r=t.updateQueue,i=r===null?null:r.lastEffect;if(i!==null){var a=i.next;r=a;do{if((r.tag&e)===e){var o=r.inst,s=o.destroy;if(s!==void 0){o.destroy=void 0,i=t;var c=n,l=s;try{l()}catch(e){Z(i,c,e)}}}r=r.next}while(r!==a)}}catch(e){Z(t,t.return,e)}}function qc(e){var t=e.updateQueue;if(t!==null){var n=e.stateNode;try{io(t,n)}catch(t){Z(e,e.return,t)}}}function Jc(e,t,n){n.props=Zs(e.type,e.memoizedProps),n.state=e.memoizedState;try{n.componentWillUnmount()}catch(n){Z(e,t,n)}}function Yc(e,t){try{var n=e.ref;if(n!==null){switch(e.tag){case 26:case 27:case 5:var r=e.stateNode;break;case 30:r=e.stateNode;break;default:r=e.stateNode}typeof n==`function`?e.refCleanup=n(r):n.current=r}}catch(n){Z(e,t,n)}}function Xc(e,t){var n=e.ref,r=e.refCleanup;if(n!==null){if(typeof r==`function`)try{r()}catch(n){Z(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof n==`function`)try{n(null)}catch(n){Z(e,t,n)}else n.current=null}}function Zc(e){var t=e.type,n=e.memoizedProps,r=e.stateNode;try{a:switch(t){case`button`:case`input`:case`select`:case`textarea`:n.autoFocus&&r.focus();break a;case`img`:n.src?r.src=n.src:n.srcSet&&(r.srcset=n.srcSet)}}catch(t){Z(e,e.return,t)}}function Qc(e,t,n){try{var r=e.stateNode;Fd(r,e.type,n,t),r[_t]=t}catch(t){Z(e,e.return,t)}}function $c(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&Zd(e.type)||e.tag===4}function el(e){a:for(;;){for(;e.sibling===null;){if(e.return===null||$c(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&Zd(e.type)||e.flags&2||e.child===null||e.tag===4)continue a;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function tl(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?(n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n).insertBefore(e,t):(t=n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n,t.appendChild(e),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=ln));else if(r!==4&&(r===27&&Zd(e.type)&&(n=e.stateNode,t=null),e=e.child,e!==null))for(tl(e,t,n),e=e.sibling;e!==null;)tl(e,t,n),e=e.sibling}function nl(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(r!==4&&(r===27&&Zd(e.type)&&(n=e.stateNode),e=e.child,e!==null))for(nl(e,t,n),e=e.sibling;e!==null;)nl(e,t,n),e=e.sibling}function rl(e){var t=e.stateNode,n=e.memoizedProps;try{for(var r=e.type,i=t.attributes;i.length;)t.removeAttributeNode(i[0]);Pd(t,r,n),t[gt]=e,t[_t]=n}catch(t){Z(e,e.return,t)}}var il=!1,V=!1,al=!1,ol=typeof WeakSet==`function`?WeakSet:Set,H=null;function sl(e,t){if(e=e.containerInfo,Rd=sp,e=Ir(e),Lr(e)){if(`selectionStart`in e)var n={start:e.selectionStart,end:e.selectionEnd};else a:{n=(n=e.ownerDocument)&&n.defaultView||window;var r=n.getSelection&&n.getSelection();if(r&&r.rangeCount!==0){n=r.anchorNode;var i=r.anchorOffset,a=r.focusNode;r=r.focusOffset;try{n.nodeType,a.nodeType}catch{n=null;break a}var o=0,c=-1,l=-1,u=0,d=0,f=e,p=null;b:for(;;){for(var m;f!==n||i!==0&&f.nodeType!==3||(c=o+i),f!==a||r!==0&&f.nodeType!==3||(l=o+r),f.nodeType===3&&(o+=f.nodeValue.length),(m=f.firstChild)!==null;)p=f,f=m;for(;;){if(f===e)break b;if(p===n&&++u===i&&(c=o),p===a&&++d===r&&(l=o),(m=f.nextSibling)!==null)break;f=p,p=f.parentNode}f=m}n=c===-1||l===-1?null:{start:c,end:l}}else n=null}n||={start:0,end:0}}else n=null;for(zd={focusedElem:e,selectionRange:n},sp=!1,H=t;H!==null;)if(t=H,e=t.child,t.subtreeFlags&1028&&e!==null)e.return=t,H=e;else for(;H!==null;){switch(t=H,a=t.alternate,e=t.flags,t.tag){case 0:if(e&4&&(e=t.updateQueue,e=e===null?null:e.events,e!==null))for(n=0;n title`))),Pd(a,r,n),a[gt]=e,k(a),r=a;break a;case`link`:var o=Vf(`link`,`href`,i).get(r+(n.href||``));if(o){for(var c=0;cg&&(o=g,g=h,h=o);var _=Pr(s,h),v=Pr(s,g);if(_&&v&&(p.rangeCount!==1||p.anchorNode!==_.node||p.anchorOffset!==_.offset||p.focusNode!==v.node||p.focusOffset!==v.offset)){var y=d.createRange();y.setStart(_.node,_.offset),p.removeAllRanges(),h>g?(p.addRange(y),p.extend(v.node,v.offset)):(y.setEnd(v.node,v.offset),p.addRange(y))}}}}for(d=[],p=s;p=p.parentNode;)p.nodeType===1&&d.push({element:p,left:p.scrollLeft,top:p.scrollTop});for(typeof s.focus==`function`&&s.focus(),s=0;sn?32:n,T.T=null,n=lu,lu=null;var a=au,o=su;if(X=0,ou=au=null,su=0,W&6)throw Error(s(331));var c=W;if(W|=4,Il(a.current),Ol(a,a.current,o,n),W=c,id(0,!1),Ge&&typeof Ge.onPostCommitFiberRoot==`function`)try{Ge.onPostCommitFiberRoot(We,a)}catch{}return!0}finally{E.p=i,T.T=r,Vu(e,t)}}function Wu(e,t,n){t=Di(n,t),t=rc(e.stateNode,t,2),e=Za(e,t,2),e!==null&&(ot(e,2),rd(e))}function Z(e,t,n){if(e.tag===3)Wu(e,e,n);else for(;t!==null;){if(t.tag===3){Wu(t,e,n);break}if(t.tag===1){var r=t.stateNode;if(typeof t.type.getDerivedStateFromError==`function`||typeof r.componentDidCatch==`function`&&(iu===null||!iu.has(r))){e=Di(n,e),n=ic(2),r=Za(t,n,2),r!==null&&(ac(n,r,t,e),ot(r,2),rd(r));break}}t=t.return}}function Gu(e,t,n){var r=e.pingCache;if(r===null){r=e.pingCache=new Bl;var i=new Set;r.set(t,i)}else i=r.get(t),i===void 0&&(i=new Set,r.set(t,i));i.has(n)||(Wl=!0,i.add(n),e=Ku.bind(null,e,t,n),t.then(e,e))}function Ku(e,t,n){var r=e.pingCache;r!==null&&r.delete(t),e.pingedLanes|=e.suspendedLanes&n,e.warmLanes&=~n,G===e&&(q&n)===n&&(Y===4||Y===3&&(q&62914560)===q&&300>Fe()-eu?!(W&2)&&Su(e,0):Jl|=n,Xl===q&&(Xl=0)),rd(e)}function qu(e,t){t===0&&(t=it()),e=fi(e,t),e!==null&&(ot(e,t),rd(e))}function Ju(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),qu(e,n)}function Yu(e,t){var n=0;switch(e.tag){case 31:case 13:var r=e.stateNode,i=e.memoizedState;i!==null&&(n=i.retryLane);break;case 19:r=e.stateNode;break;case 22:r=e.stateNode._retryCache;break;default:throw Error(s(314))}r!==null&&r.delete(t),qu(e,n)}function Xu(e,t){return je(e,t)}var Zu=null,Qu=null,$u=!1,ed=!1,td=!1,nd=0;function rd(e){e!==Qu&&e.next===null&&(Qu===null?Zu=Qu=e:Qu=Qu.next=e),ed=!0,$u||($u=!0,ud())}function id(e,t){if(!td&&ed){td=!0;do for(var n=!1,r=Zu;r!==null;){if(!t){if(e!==0){var i=r.pendingLanes;if(i===0)var a=0;else{var o=r.suspendedLanes,s=r.pingedLanes;a=(1<<31-qe(42|e)+1)-1,a&=i&~(o&~s),a=a&201326741?a&201326741|1:a?a|2:0}a!==0&&(n=!0,ld(r,a))}else a=q,a=tt(r,r===G?a:0,r.cancelPendingCommit!==null||r.timeoutHandle!==-1),!(a&3)||nt(r,a)||(n=!0,ld(r,a))}r=r.next}while(n);td=!1}}function ad(){od()}function od(){ed=$u=!1;var e=0;nd!==0&&Gd()&&(e=nd);for(var t=Fe(),n=null,r=Zu;r!==null;){var i=r.next,a=sd(r,t);a===0?(r.next=null,n===null?Zu=i:n.next=i,i===null&&(Qu=n)):(n=r,(e!==0||a&3)&&(ed=!0)),r=i}X!==0&&X!==5||id(e,!1),nd!==0&&(nd=0)}function sd(e,t){for(var n=e.suspendedLanes,r=e.pingedLanes,i=e.expirationTimes,a=e.pendingLanes&-62914561;0s)break;var u=c.transferSize,d=c.initiatorType;u&&Id(d)&&(c=c.responseEnd,o+=u*(c`u`?null:document;function xf(e,t,n){var r=bf;if(r&&typeof t==`string`&&t){var i=qt(t);i=`link[rel="`+e+`"][href="`+i+`"]`,typeof n==`string`&&(i+=`[crossorigin="`+n+`"]`),hf.has(i)||(hf.add(i),e={rel:e,crossOrigin:n,href:t},r.querySelector(i)===null&&(t=r.createElement(`link`),Pd(t,`link`,e),k(t),r.head.appendChild(t)))}}function Sf(e){_f.D(e),xf(`dns-prefetch`,e,null)}function Cf(e,t){_f.C(e,t),xf(`preconnect`,e,t)}function wf(e,t,n){_f.L(e,t,n);var r=bf;if(r&&e&&t){var i=`link[rel="preload"][as="`+qt(t)+`"]`;t===`image`&&n&&n.imageSrcSet?(i+=`[imagesrcset="`+qt(n.imageSrcSet)+`"]`,typeof n.imageSizes==`string`&&(i+=`[imagesizes="`+qt(n.imageSizes)+`"]`)):i+=`[href="`+qt(e)+`"]`;var a=i;switch(t){case`style`:a=Af(e);break;case`script`:a=Pf(e)}mf.has(a)||(e=h({rel:`preload`,href:t===`image`&&n&&n.imageSrcSet?void 0:e,as:t},n),mf.set(a,e),r.querySelector(i)!==null||t===`style`&&r.querySelector(jf(a))||t===`script`&&r.querySelector(Ff(a))||(t=r.createElement(`link`),Pd(t,`link`,e),k(t),r.head.appendChild(t)))}}function Tf(e,t){_f.m(e,t);var n=bf;if(n&&e){var r=t&&typeof t.as==`string`?t.as:`script`,i=`link[rel="modulepreload"][as="`+qt(r)+`"][href="`+qt(e)+`"]`,a=i;switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:a=Pf(e)}if(!mf.has(a)&&(e=h({rel:`modulepreload`,href:e},t),mf.set(a,e),n.querySelector(i)===null)){switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:if(n.querySelector(Ff(a)))return}r=n.createElement(`link`),Pd(r,`link`,e),k(r),n.head.appendChild(r)}}}function Ef(e,t,n){_f.S(e,t,n);var r=bf;if(r&&e){var i=Ot(r).hoistableStyles,a=Af(e);t||=`default`;var o=i.get(a);if(!o){var s={loading:0,preload:null};if(o=r.querySelector(jf(a)))s.loading=5;else{e=h({rel:`stylesheet`,href:e,"data-precedence":t},n),(n=mf.get(a))&&Rf(e,n);var c=o=r.createElement(`link`);k(c),Pd(c,`link`,e),c._p=new Promise(function(e,t){c.onload=e,c.onerror=t}),c.addEventListener(`load`,function(){s.loading|=1}),c.addEventListener(`error`,function(){s.loading|=2}),s.loading|=4,Lf(o,t,r)}o={type:`stylesheet`,instance:o,count:1,state:s},i.set(a,o)}}}function Df(e,t){_f.X(e,t);var n=bf;if(n&&e){var r=Ot(n).hoistableScripts,i=Pf(e),a=r.get(i);a||(a=n.querySelector(Ff(i)),a||(e=h({src:e,async:!0},t),(t=mf.get(i))&&zf(e,t),a=n.createElement(`script`),k(a),Pd(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function Of(e,t){_f.M(e,t);var n=bf;if(n&&e){var r=Ot(n).hoistableScripts,i=Pf(e),a=r.get(i);a||(a=n.querySelector(Ff(i)),a||(e=h({src:e,async:!0,type:`module`},t),(t=mf.get(i))&&zf(e,t),a=n.createElement(`script`),k(a),Pd(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function kf(e,t,n,r){var i=(i=_e.current)?gf(i):null;if(!i)throw Error(s(446));switch(e){case`meta`:case`title`:return null;case`style`:return typeof n.precedence==`string`&&typeof n.href==`string`?(t=Af(n.href),n=Ot(i).hoistableStyles,r=n.get(t),r||(r={type:`style`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};case`link`:if(n.rel===`stylesheet`&&typeof n.href==`string`&&typeof n.precedence==`string`){e=Af(n.href);var a=Ot(i).hoistableStyles,o=a.get(e);if(o||(i=i.ownerDocument||i,o={type:`stylesheet`,instance:null,count:0,state:{loading:0,preload:null}},a.set(e,o),(a=i.querySelector(jf(e)))&&!a._p&&(o.instance=a,o.state.loading=5),mf.has(e)||(n={rel:`preload`,as:`style`,href:n.href,crossOrigin:n.crossOrigin,integrity:n.integrity,media:n.media,hrefLang:n.hrefLang,referrerPolicy:n.referrerPolicy},mf.set(e,n),a||Nf(i,e,n,o.state))),t&&r===null)throw Error(s(528,``));return o}if(t&&r!==null)throw Error(s(529,``));return null;case`script`:return t=n.async,n=n.src,typeof n==`string`&&t&&typeof t!=`function`&&typeof t!=`symbol`?(t=Pf(n),n=Ot(i).hoistableScripts,r=n.get(t),r||(r={type:`script`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};default:throw Error(s(444,e))}}function Af(e){return`href="`+qt(e)+`"`}function jf(e){return`link[rel="stylesheet"][`+e+`]`}function Mf(e){return h({},e,{"data-precedence":e.precedence,precedence:null})}function Nf(e,t,n,r){e.querySelector(`link[rel="preload"][as="style"][`+t+`]`)?r.loading=1:(t=e.createElement(`link`),r.preload=t,t.addEventListener(`load`,function(){return r.loading|=1}),t.addEventListener(`error`,function(){return r.loading|=2}),Pd(t,`link`,n),k(t),e.head.appendChild(t))}function Pf(e){return`[src="`+qt(e)+`"]`}function Ff(e){return`script[async]`+e}function If(e,t,n){if(t.count++,t.instance===null)switch(t.type){case`style`:var r=e.querySelector(`style[data-href~="`+qt(n.href)+`"]`);if(r)return t.instance=r,k(r),r;var i=h({},n,{"data-href":n.href,"data-precedence":n.precedence,href:null,precedence:null});return r=(e.ownerDocument||e).createElement(`style`),k(r),Pd(r,`style`,i),Lf(r,n.precedence,e),t.instance=r;case`stylesheet`:i=Af(n.href);var a=e.querySelector(jf(i));if(a)return t.state.loading|=4,t.instance=a,k(a),a;r=Mf(n),(i=mf.get(i))&&Rf(r,i),a=(e.ownerDocument||e).createElement(`link`),k(a);var o=a;return o._p=new Promise(function(e,t){o.onload=e,o.onerror=t}),Pd(a,`link`,r),t.state.loading|=4,Lf(a,n.precedence,e),t.instance=a;case`script`:return a=Pf(n.src),(i=e.querySelector(Ff(a)))?(t.instance=i,k(i),i):(r=n,(i=mf.get(a))&&(r=h({},n),zf(r,i)),e=e.ownerDocument||e,i=e.createElement(`script`),k(i),Pd(i,`link`,r),e.head.appendChild(i),t.instance=i);case`void`:return null;default:throw Error(s(443,t.type))}else t.type===`stylesheet`&&!(t.state.loading&4)&&(r=t.instance,t.state.loading|=4,Lf(r,n.precedence,e));return t.instance}function Lf(e,t,n){for(var r=n.querySelectorAll(`link[rel="stylesheet"][data-precedence],style[data-precedence]`),i=r.length?r[r.length-1]:null,a=i,o=0;o title`):null)}function Uf(e,t,n){if(n===1||t.itemProp!=null)return!1;switch(e){case`meta`:case`title`:return!0;case`style`:if(typeof t.precedence!=`string`||typeof t.href!=`string`||t.href===``)break;return!0;case`link`:if(typeof t.rel!=`string`||typeof t.href!=`string`||t.href===``||t.onLoad||t.onError)break;switch(t.rel){case`stylesheet`:return e=t.disabled,typeof t.precedence==`string`&&e==null;default:return!0}case`script`:if(t.async&&typeof t.async!=`function`&&typeof t.async!=`symbol`&&!t.onLoad&&!t.onError&&t.src&&typeof t.src==`string`)return!0}return!1}function Wf(e){return!(e.type===`stylesheet`&&!(e.state.loading&3))}function Gf(e,t,n,r){if(n.type===`stylesheet`&&(typeof r.media!=`string`||!1!==matchMedia(r.media).matches)&&!(n.state.loading&4)){if(n.instance===null){var i=Af(r.href),a=t.querySelector(jf(i));if(a){t=a._p,typeof t==`object`&&t&&typeof t.then==`function`&&(e.count++,e=Jf.bind(e),t.then(e,e)),n.state.loading|=4,n.instance=a,k(a);return}a=t.ownerDocument||t,r=Mf(r),(i=mf.get(i))&&Rf(r,i),a=a.createElement(`link`),k(a);var o=a;o._p=new Promise(function(e,t){o.onload=e,o.onerror=t}),Pd(a,`link`,r),n.instance=a}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(n,t),(t=n.state.preload)&&!(n.state.loading&3)&&(e.count++,n=Jf.bind(e),t.addEventListener(`load`,n),t.addEventListener(`error`,n))}}var Kf=0;function qf(e,t){return e.stylesheets&&e.count===0&&Xf(e,e.stylesheets),0Kf?50:800)+t);return e.unsuspend=n,function(){e.unsuspend=null,clearTimeout(r),clearTimeout(i)}}:null}function Jf(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Xf(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var Yf=null;function Xf(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,Yf=new Map,t.forEach(Zf,e),Yf=null,Jf.call(e))}function Zf(e,t){if(!(t.state.loading&4)){var n=Yf.get(e);if(n)var r=n.get(null);else{n=new Map,Yf.set(e,n);for(var i=e.querySelectorAll(`link[data-precedence],style[data-precedence]`),a=0;a{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=s()})),l=n(),u=c(),d=e=>{let t=e.role||e.type;return t===`user`||t===`assistant`||t===`tool`||t===`system`?t:`assistant`},f=e=>{if(e.text)return e.text;if(e.payload&&typeof e.payload==`object`&&`content`in e.payload){let t=e.payload.content;if(typeof t==`string`)return t}return``},p=e=>{let t=e.entries.find(e=>d(e)===`user`);if(t){let e=f(t).trim();if(e)return e}let n=e.metadata?.objective;return typeof n==`string`&&n.trim()?n:e.id},m=e=>{let t=new Date(e);return Number.isNaN(t.getTime())?``:new Intl.DateTimeFormat(`zh-CN`,{month:`short`,day:`numeric`,hour:`2-digit`,minute:`2-digit`}).format(t)},h=(e,t)=>{let n=t.trim().toLowerCase();if(!n)return!0;let r=[e.id,e.cwd,p(e)].map(e=>e.toLowerCase());for(let t of e.entries)r.push(f(t).toLowerCase()),t.tool&&r.push(t.tool.toLowerCase());return r.some(e=>e.includes(n))},g=(e,t)=>e.filter(e=>h(e,t)),_=(e,t)=>t===`all`?e:e.filter(e=>d(e)===t),v=``+new URL(`call-code-BBgvhvPd.png`,import.meta.url).href,y=e((e=>{var t=Symbol.for(`react.transitional.element`);function n(e,n,r){var i=null;if(r!==void 0&&(i=``+r),n.key!==void 0&&(i=``+n.key),`key`in n)for(var a in r={},n)a!==`key`&&(r[a]=n[a]);else r=n;return n=r.ref,{$$typeof:t,type:e,key:i,ref:n===void 0?null:n,props:r}}e.jsx=n,e.jsxs=n})),b=e(((e,t)=>{t.exports=y()}))();function x({sessions:e,theme:t,onThemeChange:n}){let r=e.reduce((e,t)=>(e.messages+=t.entries.length,e.tools+=t.entries.filter(e=>d(e)===`tool`).length,e),{messages:0,tools:0});return(0,b.jsxs)(`header`,{className:`header-bar`,children:[(0,b.jsxs)(`div`,{className:`flex min-w-0 items-center gap-3`,children:[(0,b.jsx)(`img`,{src:v,alt:`Call Code`,className:`h-9 w-9 shrink-0 rounded-xl border object-contain`,style:{borderColor:`rgb(var(--chip-border))`,background:`rgb(var(--chip-bg))`}}),(0,b.jsxs)(`div`,{className:`min-w-0`,children:[(0,b.jsx)(`h1`,{className:`truncate text-[17px] font-semibold leading-tight`,style:{color:`var(--text-primary)`},children:`Call Code`}),(0,b.jsxs)(`div`,{className:`mt-0.5 truncate text-[11px]`,style:{color:`var(--text-tertiary)`},children:[e.length,` 个会话 · `,r.messages,` 条消息 · `,r.tools,` `,`次工具`]})]})]}),(0,b.jsx)(`div`,{className:`segmented shrink-0`,role:`tablist`,"aria-label":`主题切换`,children:[`light`,`dark`].map(e=>(0,b.jsx)(`button`,{type:`button`,role:`tab`,"aria-pressed":t===e,onClick:()=>n(e),children:e===`light`?`毛玻璃`:`高级黑`},e))})]})}function ee({sessions:e,activeId:t,query:n,onSelect:r,onQueryChange:i}){return(0,b.jsxs)(`aside`,{className:`sidebar-panel max-h-[50vh] lg:max-h-none`,children:[(0,b.jsx)(`header`,{className:`border-b px-3 py-3`,style:{borderColor:`rgb(var(--panel-border))`},children:(0,b.jsxs)(`div`,{className:`search-box flex h-8 min-w-0 items-center gap-2 rounded-lg border px-2.5`,style:{borderColor:`rgb(var(--chip-border))`,background:`rgb(var(--chip-bg))`},children:[(0,b.jsxs)(`svg`,{width:`13`,height:`13`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,style:{color:`var(--text-tertiary)`},"aria-hidden":`true`,children:[(0,b.jsx)(`circle`,{cx:`11`,cy:`11`,r:`7`}),(0,b.jsx)(`path`,{d:`m20 20-3.5-3.5`})]}),(0,b.jsx)(`input`,{type:`search`,value:n,onChange:e=>i(e.target.value),placeholder:`搜索会话`,"aria-label":`搜索会话`,className:`h-full w-full min-w-0 bg-transparent text-[12px] outline-none`,style:{color:`var(--text-primary)`}})]})}),(0,b.jsxs)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-2 pt-3 pb-3`,children:[e.length===0&&(0,b.jsx)(`div`,{className:`grid min-h-[120px] place-items-center text-[12px]`,style:{color:`var(--text-tertiary)`},children:`暂无会话`}),(0,b.jsx)(`div`,{className:`flex flex-col gap-0.5`,children:e.map(e=>{let n=e.id===t;return(0,b.jsxs)(`button`,{type:`button`,onClick:()=>r(e.id),"aria-current":n?`true`:void 0,className:`group relative flex items-start gap-2.5 rounded-xl px-2.5 py-2 text-left transition-all duration-200`,style:n?{background:`rgb(var(--sidebar-active))`,boxShadow:`var(--sidebar-active-shadow)`}:void 0,onMouseEnter:e=>{n||(e.currentTarget.style.background=`rgb(var(--sidebar-hover))`)},onMouseLeave:e=>{n||(e.currentTarget.style.background=``)},children:[(0,b.jsx)(`span`,{className:`mt-1 h-4 w-1 shrink-0 rounded-full transition-opacity`,style:{background:n?`var(--text-primary)`:`transparent`,opacity:+!!n},"aria-hidden":`true`}),(0,b.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,b.jsx)(`div`,{className:`line-clamp-2 text-[13px] font-medium leading-snug`,style:{color:n?`var(--text-primary)`:`var(--text-secondary)`},children:p(e)}),(0,b.jsxs)(`div`,{className:`mt-1 flex items-center gap-1.5 text-[11px]`,style:{color:`var(--text-tertiary)`},children:[(0,b.jsxs)(`span`,{children:[e.entries.length,` 条`]}),(0,b.jsx)(`span`,{style:{opacity:.4},children:`·`}),(0,b.jsx)(`span`,{className:`truncate`,children:m(e.createdAt)})]})]})]},e.id)})})]})]})}var S={user:{label:`用户`,dotClass:`role-dot role-dot--user`,bubbleClass:`msg-bubble--user`},assistant:{label:`助手`,dotClass:`role-dot role-dot--assistant`,bubbleClass:`msg-bubble--assistant`},tool:{label:`工具`,dotClass:`role-dot role-dot--tool`,bubbleClass:`msg-bubble--tool`},system:{label:`系统`,dotClass:`role-dot role-dot--system`,bubbleClass:``}};function C({entry:e}){let t=d(e),n=S[t],r=f(e),i=t===`tool`||r.length>320;return(0,b.jsxs)(`article`,{className:`flex gap-3`,children:[(0,b.jsx)(`div`,{className:`pt-1.5`,children:(0,b.jsx)(`span`,{className:n.dotClass,"aria-hidden":`true`})}),(0,b.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,b.jsxs)(`div`,{className:`mb-1.5 flex items-center gap-2 text-[11px] font-medium`,style:{color:`var(--text-tertiary)`},children:[(0,b.jsx)(`span`,{style:{color:`var(--role-${t})`},children:n.label}),e.tool?(0,b.jsx)(`span`,{className:`chip !py-0 !text-[10px]`,children:e.tool}):null,(0,b.jsx)(`span`,{className:`ml-auto shrink-0`,children:m(e.timestamp)})]}),i?(0,b.jsx)(`pre`,{className:`msg-bubble ${n.bubbleClass} mono m-0 max-h-[480px] overflow-auto px-3.5 py-2.5 text-[12px]`,style:{color:`var(--text-secondary)`},children:r}):(0,b.jsx)(`div`,{className:`msg-bubble ${n.bubbleClass} whitespace-pre-wrap break-words px-3.5 py-2.5 text-[13.5px] leading-relaxed`,style:{color:`var(--text-primary)`},children:r})]})]})}var te=[{value:`all`,label:`全部`},{value:`user`,label:`用户`},{value:`assistant`,label:`助手`},{value:`tool`,label:`工具`}];function ne({session:e}){let t=[[`消息`,`${e.entries.length}`],[`tokens`,e.stats?.totalTokens?.toLocaleString()??`0`],[`成本`,`$${(e.stats?.costTotal??0).toFixed(3)}`],[`目录`,e.cwd]];return(0,b.jsx)(`div`,{className:`flex flex-wrap items-center gap-1.5`,children:t.map(([e,t])=>(0,b.jsxs)(`span`,{className:`chip max-w-[240px] truncate`,children:[(0,b.jsx)(`span`,{style:{opacity:.6},children:e}),(0,b.jsx)(`span`,{className:`truncate`,children:t})]},e))})}function re({facts:e}){return e.length===0?null:(0,b.jsxs)(`section`,{className:`mt-8`,children:[(0,b.jsx)(`div`,{className:`mb-3 text-[11px] font-medium uppercase tracking-wider`,style:{color:`var(--text-tertiary)`},children:`事实`}),(0,b.jsx)(`div`,{className:`grid gap-2 sm:grid-cols-2 lg:grid-cols-3`,children:e.slice(0,12).map((e,t)=>(0,b.jsxs)(`div`,{className:`msg-bubble px-3 py-2.5`,children:[(0,b.jsx)(`div`,{className:`text-[11px]`,style:{color:`var(--text-tertiary)`},children:e.kind}),(0,b.jsx)(`div`,{className:`mt-0.5 truncate text-[13px]`,style:{color:`var(--text-primary)`},children:e.value||e.key||String(e.seq)})]},`${e.seq}-${t}`))})]})}var w=e=>typeof e==`string`?e:e&&typeof e==`object`?JSON.stringify(e,null,2):String(e??``);function ie({records:e}){return e.length===0?null:(0,b.jsxs)(`section`,{className:`mt-8`,children:[(0,b.jsxs)(`div`,{className:`mb-3 text-[11px] font-medium uppercase tracking-wider`,style:{color:`var(--text-tertiary)`},children:[`运行记录 · 最近 `,Math.min(20,e.length),` 条`]}),(0,b.jsx)(`div`,{className:`flex flex-col gap-1.5`,children:e.slice(-20).reverse().map(e=>(0,b.jsxs)(`div`,{className:`msg-bubble px-3 py-2.5`,children:[(0,b.jsxs)(`div`,{className:`flex items-center justify-between gap-2 text-[11px]`,style:{color:`var(--text-tertiary)`},children:[(0,b.jsxs)(`span`,{className:`truncate`,children:[e.type,e.opKind?` / ${e.opKind}`:``]}),(0,b.jsx)(`span`,{className:`shrink-0`,children:m(e.timestamp)})]}),(0,b.jsx)(`div`,{className:`mt-1.5 max-h-40 overflow-auto whitespace-pre-wrap break-words mono`,style:{color:`var(--text-secondary)`},children:w(e.payload)})]},e.id))})]})}function ae({session:e,filter:t,onFilterChange:n}){let r=e?_(e.entries,t):[];return(0,b.jsxs)(`main`,{className:`main-panel`,children:[(0,b.jsxs)(`header`,{className:`flex flex-col gap-3 px-6 pt-5 pb-4`,children:[(0,b.jsx)(`h2`,{className:`truncate text-[15px] font-semibold leading-snug`,style:{color:`var(--text-primary)`},children:e?p(e):`暂无会话`}),e?(0,b.jsx)(ne,{session:e}):null]}),(0,b.jsx)(`div`,{className:`flex items-center gap-3 border-t px-6 py-2.5`,style:{borderColor:`rgb(var(--panel-border))`},children:(0,b.jsx)(`div`,{className:`segmented`,role:`tablist`,"aria-label":`消息过滤`,children:te.map(e=>(0,b.jsx)(`button`,{type:`button`,role:`tab`,"aria-pressed":t===e.value,onClick:()=>n(e.value),children:e.label},e.value))})}),(0,b.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-6 py-6`,children:(0,b.jsx)(`div`,{className:`mx-auto max-w-[760px]`,children:e?r.length===0?(0,b.jsx)(`div`,{className:`grid min-h-[200px] place-items-center text-[13px]`,style:{color:`var(--text-tertiary)`},children:`没有匹配的消息`}):(0,b.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[r.map(e=>(0,b.jsx)(C,{entry:e},e.id)),e.facts?(0,b.jsx)(re,{facts:e.facts}):null,e.records?(0,b.jsx)(ie,{records:e.records}):null]}):(0,b.jsx)(`div`,{className:`grid min-h-[200px] place-items-center text-[13px]`,style:{color:`var(--text-tertiary)`},children:`暂无会话数据`})})})]})}var oe=`/ws`,se=8e3,ce=5e3,le=e=>{if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.id==`string`&&typeof t.createdAt==`string`&&typeof t.cwd==`string`&&Array.isArray(t.entries)},ue=e=>{if(!e||typeof e!=`object`)return!1;let t=e;return t.schemaVersion===1&&typeof t.exportedAt==`string`&&Array.isArray(t.sessions)&&t.sessions.every(le)},T=e=>{if(!e||typeof e!=`object`)return null;let t=e;return t.type===`sessions.snapshot`&&ue(t.data)?t.data:null},E=e=>{if(e)return e;let t=new URLSearchParams(window.location.search);return(t.get(`ws`)??t.get(`wsUrl`))||`${window.location.protocol===`https:`?`wss:`:`ws:`}//${window.location.host}${oe}`},de=e=>{let{onSnapshot:t,url:n,timeoutMs:r=se,refreshMs:i=ce}=e,a=!1,o=null,s=null,c=null,l=null,u=0,d=!1,f=()=>void 0,p=new Promise(e=>{f=e}),m=e=>{d||(d=!0,f(e))},h=()=>{s&&clearTimeout(s),c&&clearTimeout(c),l&&clearTimeout(l),s=null,c=null,l=null},g=()=>{if(h(),!o)return;let e=o;o=null,e.onopen=null,e.onmessage=null,e.onerror=null,e.onclose=null,e.close()},_=()=>{a||(c=setTimeout(()=>{o?.send(JSON.stringify({type:`sessions.list`})),_()},i))},v=()=>{if(a)return;let e=Math.min(1e3*2**u,15e3);u+=1,l=setTimeout(()=>{l=null,b()},e)},y=()=>{s&&clearTimeout(s),s=setTimeout(()=>{g(),m(null),v()},r)},b=()=>{if(a)return;let e;try{e=new WebSocket(E(n))}catch{v();return}o=e,y(),e.onopen=()=>{u=0,e.send(JSON.stringify({type:`sessions.list`})),_()},e.onmessage=e=>{let n;try{n=JSON.parse(String(e.data))}catch{return}let r=T(n);r&&(y(),t(r),m(r))},e.onerror=()=>{},e.onclose=()=>{o===e&&(g(),m(null),a||v())}};return b(),{ready:p,close(){a=!0,h(),g()}}},fe=`call-code-theme`,pe=()=>localStorage.getItem(fe)===`light`?`light`:`dark`;function me(){let[e,t]=(0,l.useState)(null),[n,r]=(0,l.useState)(`loading`),[i,a]=(0,l.useState)(pe),[o,s]=(0,l.useState)(null),[c,u]=(0,l.useState)(``),[d,f]=(0,l.useState)(`all`);(0,l.useEffect)(()=>{let e=!1,n=de({onSnapshot:n=>{e||(t(n),r(`ready`),s(e=>[new URLSearchParams(window.location.search).get(`session`),e,n.sessions[0]?.id??null].find(e=>e!=null&&n.sessions.some(t=>t.id===e))??null))}});return n.ready.then(t=>{e||r(t?`ready`:`error`)}),()=>{e=!0,n.close()}},[]),(0,l.useEffect)(()=>{document.documentElement.classList.toggle(`dark`,i===`dark`),localStorage.setItem(fe,i)},[i]);let p=(0,l.useMemo)(()=>e?.sessions??[],[e]),m=(0,l.useMemo)(()=>g(p,c),[p,c]),h=(0,l.useMemo)(()=>m.find(e=>e.id===o)??m[0]??null,[m,o]);return n===`loading`?(0,b.jsx)(`div`,{className:`app-shell`,children:(0,b.jsx)(`div`,{className:`grid min-h-[60vh] place-items-center text-sm`,style:{color:`var(--text-tertiary)`},children:`正在读取会话`})}):n===`error`||!e?(0,b.jsx)(`div`,{className:`app-shell`,children:(0,b.jsx)(`div`,{className:`grid min-h-[60vh] place-items-center text-sm`,style:{color:`var(--text-tertiary)`},children:`无法读取会话数据`})}):(0,b.jsx)(`div`,{className:`app-shell`,children:(0,b.jsxs)(`div`,{className:`app-frame`,children:[(0,b.jsx)(x,{sessions:m,theme:i,onThemeChange:a}),(0,b.jsxs)(`div`,{className:`app-workspace`,children:[(0,b.jsx)(ee,{sessions:m,activeId:o,query:c,onSelect:s,onQueryChange:u}),(0,b.jsx)(ae,{session:h,filter:d,onFilterChange:f})]})]})})}var D=document.getElementById(`root`);if(!D)throw Error(`未找到 #root 容器`);(0,u.createRoot)(D).render((0,b.jsx)(l.StrictMode,{children:(0,b.jsx)(me,{})})); \ No newline at end of file diff --git a/packages/client/dist/assets/index-DXeJAcap.js b/packages/client/dist/assets/index-DXeJAcap.js deleted file mode 100644 index fd69d5f..0000000 --- a/packages/client/dist/assets/index-DXeJAcap.js +++ /dev/null @@ -1,9 +0,0 @@ -var e=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports);(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var t=e((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.consumer`),s=Symbol.for(`react.context`),c=Symbol.for(`react.forward_ref`),l=Symbol.for(`react.suspense`),u=Symbol.for(`react.memo`),d=Symbol.for(`react.lazy`),f=Symbol.for(`react.activity`),p=Symbol.iterator;function m(e){return typeof e!=`object`||!e?null:(e=p&&e[p]||e[`@@iterator`],typeof e==`function`?e:null)}var h={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},g=Object.assign,_={};function v(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}v.prototype.isReactComponent={},v.prototype.setState=function(e,t){if(typeof e!=`object`&&typeof e!=`function`&&e!=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,e,t,`setState`)},v.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,`forceUpdate`)};function y(){}y.prototype=v.prototype;function b(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}var x=b.prototype=new y;x.constructor=b,g(x,v.prototype),x.isPureReactComponent=!0;var ee=Array.isArray;function S(){}var C={H:null,A:null,T:null,S:null},te=Object.prototype.hasOwnProperty;function ne(e,n,r){var i=r.ref;return{$$typeof:t,type:e,key:n,ref:i===void 0?null:i,props:r}}function re(e,t){return ne(e.type,t,e.props)}function w(e){return typeof e==`object`&&!!e&&e.$$typeof===t}function ie(e){var t={"=":`=0`,":":`=2`};return`$`+e.replace(/[=:]/g,function(e){return t[e]})}var ae=/\/+/g;function oe(e,t){return typeof e==`object`&&e&&e.key!=null?ie(``+e.key):t.toString(36)}function se(e){switch(e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason;default:switch(typeof e.status==`string`?e.then(S,S):(e.status=`pending`,e.then(function(t){e.status===`pending`&&(e.status=`fulfilled`,e.value=t)},function(t){e.status===`pending`&&(e.status=`rejected`,e.reason=t)})),e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason}}throw e}function ce(e,r,i,a,o){var s=typeof e;(s===`undefined`||s===`boolean`)&&(e=null);var c=!1;if(e===null)c=!0;else switch(s){case`bigint`:case`string`:case`number`:c=!0;break;case`object`:switch(e.$$typeof){case t:case n:c=!0;break;case d:return c=e._init,ce(c(e._payload),r,i,a,o)}}if(c)return o=o(e),c=a===``?`.`+oe(e,0):a,ee(o)?(i=``,c!=null&&(i=c.replace(ae,`$&/`)+`/`),ce(o,r,i,``,function(e){return e})):o!=null&&(w(o)&&(o=re(o,i+(o.key==null||e&&e.key===o.key?``:(``+o.key).replace(ae,`$&/`)+`/`)+c)),r.push(o)),1;c=0;var l=a===``?`.`:a+`:`;if(ee(e))for(var u=0;u{n.exports=t()})),r=e((e=>{function t(e,t){var n=e.length;e.push(t);a:for(;0>>1,a=e[r];if(0>>1;ri(c,n))li(u,c)?(e[r]=u,e[l]=n,r=l):(e[r]=c,e[s]=n,r=s);else if(li(u,n))e[r]=u,e[l]=n,r=l;else break a}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return n===0?e.id-t.id:n}if(e.unstable_now=void 0,typeof performance==`object`&&typeof performance.now==`function`){var a=performance;e.unstable_now=function(){return a.now()}}else{var o=Date,s=o.now();e.unstable_now=function(){return o.now()-s}}var c=[],l=[],u=1,d=null,f=3,p=!1,m=!1,h=!1,g=!1,_=typeof setTimeout==`function`?setTimeout:null,v=typeof clearTimeout==`function`?clearTimeout:null,y=typeof setImmediate<`u`?setImmediate:null;function b(e){for(var i=n(l);i!==null;){if(i.callback===null)r(l);else if(i.startTime<=e)r(l),i.sortIndex=i.expirationTime,t(c,i);else break;i=n(l)}}function x(e){if(h=!1,b(e),!m)if(n(c)!==null)m=!0,ee||(ee=!0,w());else{var t=n(l);t!==null&&oe(x,t.startTime-e)}}var ee=!1,S=-1,C=5,te=-1;function ne(){return g?!0:!(e.unstable_now()-tet&&ne());){var o=d.callback;if(typeof o==`function`){d.callback=null,f=d.priorityLevel;var s=o(d.expirationTime<=t);if(t=e.unstable_now(),typeof s==`function`){d.callback=s,b(t),i=!0;break b}d===n(c)&&r(c),b(t)}else r(c);d=n(c)}if(d!==null)i=!0;else{var u=n(l);u!==null&&oe(x,u.startTime-t),i=!1}}break a}finally{d=null,f=a,p=!1}}}finally{i?w():ee=!1}}}var w;if(typeof y==`function`)w=function(){y(re)};else if(typeof MessageChannel<`u`){var ie=new MessageChannel,ae=ie.port2;ie.port1.onmessage=re,w=function(){ae.postMessage(null)}}else w=function(){_(re,0)};function oe(t,n){S=_(function(){t(e.unstable_now())},n)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(e){e.callback=null},e.unstable_forceFrameRate=function(e){0>e||125o?(r.sortIndex=a,t(l,r),n(c)===null&&r===n(l)&&(h?(v(S),S=-1):h=!0,oe(x,a-o))):(r.sortIndex=s,t(c,r),m||p||(m=!0,ee||(ee=!0,w()))),r},e.unstable_shouldYield=ne,e.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}})),i=e(((e,t)=>{t.exports=r()})),a=e((e=>{var t=n();function r(e){var t=`https://react.dev/errors/`+e;if(1{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=a()})),s=e((e=>{var t=i(),r=n(),a=o();function s(e){var t=`https://react.dev/errors/`+e;if(1pe||(e.current=fe[pe],fe[pe]=null,pe--)}function O(e,t){pe++,fe[pe]=e.current,e.current=t}var he=me(null),ge=me(null),_e=me(null),ve=me(null);function ye(e,t){switch(O(_e,t),O(ge,e),O(he,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Vd(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Vd(t),e=Hd(t,e);else switch(e){case`svg`:e=1;break;case`math`:e=2;break;default:e=0}}D(he),O(he,e)}function be(){D(he),D(ge),D(_e)}function xe(e){e.memoizedState!==null&&O(ve,e);var t=he.current,n=Hd(t,e.type);t!==n&&(O(ge,e),O(he,n))}function Se(e){ge.current===e&&(D(he),D(ge)),ve.current===e&&(D(ve),Qf._currentValue=de)}var Ce,we;function Te(e){if(Ce===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);Ce=t&&t[1]||``,we=-1)`:-1i||c[r]!==l[i]){var u=` -`+c[r].replace(` at new `,` at `);return e.displayName&&u.includes(``)&&(u=u.replace(``,e.displayName)),u}while(1<=r&&0<=i);break}}}finally{Ee=!1,Error.prepareStackTrace=n}return(n=e?e.displayName||e.name:``)?Te(n):``}function Oe(e,t){switch(e.tag){case 26:case 27:case 5:return Te(e.type);case 16:return Te(`Lazy`);case 13:return e.child!==t&&t!==null?Te(`Suspense Fallback`):Te(`Suspense`);case 19:return Te(`SuspenseList`);case 0:case 15:return De(e.type,!1);case 11:return De(e.type.render,!1);case 1:return De(e.type,!0);case 31:return Te(`Activity`);default:return``}}function ke(e){try{var t=``,n=null;do t+=Oe(e,n),n=e,e=e.return;while(e);return t}catch(e){return` -Error generating stack: `+e.message+` -`+e.stack}}var Ae=Object.prototype.hasOwnProperty,je=t.unstable_scheduleCallback,Me=t.unstable_cancelCallback,Ne=t.unstable_shouldYield,Pe=t.unstable_requestPaint,Fe=t.unstable_now,Ie=t.unstable_getCurrentPriorityLevel,Le=t.unstable_ImmediatePriority,Re=t.unstable_UserBlockingPriority,ze=t.unstable_NormalPriority,Be=t.unstable_LowPriority,Ve=t.unstable_IdlePriority,He=t.log,Ue=t.unstable_setDisableYieldValue,We=null,Ge=null;function Ke(e){if(typeof He==`function`&&Ue(e),Ge&&typeof Ge.setStrictMode==`function`)try{Ge.setStrictMode(We,e)}catch{}}var qe=Math.clz32?Math.clz32:Xe,Je=Math.log,Ye=Math.LN2;function Xe(e){return e>>>=0,e===0?32:31-(Je(e)/Ye|0)|0}var Ze=256,Qe=262144,$e=4194304;function et(e){var t=e&42;if(t!==0)return t;switch(e&-e){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 e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function tt(e,t,n){var r=e.pendingLanes;if(r===0)return 0;var i=0,a=e.suspendedLanes,o=e.pingedLanes;e=e.warmLanes;var s=r&134217727;return s===0?(s=r&~a,s===0?o===0?n||(n=r&~e,n!==0&&(i=et(n))):i=et(o):i=et(s)):(r=s&~a,r===0?(o&=s,o===0?n||(n=s&~e,n!==0&&(i=et(n))):i=et(o)):i=et(r)),i===0?0:t!==0&&t!==i&&(t&a)===0&&(a=i&-i,n=t&-t,a>=n||a===32&&n&4194048)?t:i}function nt(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function rt(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+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 t+5e3;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 it(){var e=$e;return $e<<=1,!($e&62914560)&&($e=4194304),e}function at(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function ot(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function st(e,t,n,r,i,a){var o=e.pendingLanes;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=n,e.entangledLanes&=n,e.errorRecoveryDisabledLanes&=n,e.shellSuspendCounter=0;var s=e.entanglements,c=e.expirationTimes,l=e.hiddenUpdates;for(n=o&~n;0`u`||window.document===void 0||window.document.createElement===void 0),yn=!1;if(vn)try{var bn={};Object.defineProperty(bn,"passive",{get:function(){yn=!0}}),window.addEventListener(`test`,bn,bn),window.removeEventListener(`test`,bn,bn)}catch{yn=!1}var xn=null,Sn=null,Cn=null;function wn(){if(Cn)return Cn;var e,t=Sn,n=t.length,r,i=`value`in xn?xn.value:xn.textContent,a=i.length;for(e=0;e=nr),ar=` `,or=!1;function sr(e,t){switch(e){case`keyup`:return er.indexOf(t.keyCode)!==-1;case`keydown`:return t.keyCode!==229;case`keypress`:case`mousedown`:case`focusout`:return!0;default:return!1}}function cr(e){return e=e.detail,typeof e==`object`&&`data`in e?e.data:null}var lr=!1;function ur(e,t){switch(e){case`compositionend`:return cr(t);case`keypress`:return t.which===32?(or=!0,ar):null;case`textInput`:return e=t.data,e===ar&&or?null:e;default:return null}}function dr(e,t){if(lr)return e===`compositionend`||!tr&&sr(e,t)?(e=wn(),Cn=Sn=xn=null,lr=!1,e):null;switch(e){case`paste`:return null;case`keypress`:if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}a:{for(;n;){if(n.nextSibling){n=n.nextSibling;break a}n=n.parentNode}n=void 0}n=Nr(n)}}function Fr(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?Fr(e,t.parentNode):`contains`in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Ir(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=Gt(e.document);t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href==`string`}catch{n=!1}if(n)e=t.contentWindow;else break;t=Gt(e.document)}return t}function Lr(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t===`input`&&(e.type===`text`||e.type===`search`||e.type===`tel`||e.type===`url`||e.type===`password`)||t===`textarea`||e.contentEditable===`true`)}var Rr=vn&&`documentMode`in document&&11>=document.documentMode,zr=null,Br=null,Vr=null,Hr=!1;function Ur(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;Hr||zr==null||zr!==Gt(r)||(r=zr,`selectionStart`in r&&Lr(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),Vr&&Mr(Vr,r)||(Vr=r,r=Ed(Br,`onSelect`),0>=o,i-=o,Fi=1<<32-qe(t)+i|n<h?(g=d,d=null):g=d.sibling;var _=p(i,d,s[h],c);if(_===null){d===null&&(d=g);break}e&&d&&_.alternate===null&&t(i,d),o=a(_,o,h),u===null?l=_:u.sibling=_,u=_,d=g}if(h===s.length)return n(i,d),j&&Li(i,h),l;if(d===null){for(;hg?(_=h,h=null):_=h.sibling;var y=p(i,h,v.value,l);if(y===null){h===null&&(h=_);break}e&&h&&y.alternate===null&&t(i,h),o=a(y,o,g),d===null?u=y:d.sibling=y,d=y,h=_}if(v.done)return n(i,h),j&&Li(i,g),u;if(h===null){for(;!v.done;g++,v=c.next())v=f(i,v.value,l),v!==null&&(o=a(v,o,g),d===null?u=v:d.sibling=v,d=v);return j&&Li(i,g),u}for(h=r(h);!v.done;g++,v=c.next())v=m(h,i,g,v.value,l),v!==null&&(e&&v.alternate!==null&&h.delete(v.key===null?g:v.key),o=a(v,o,g),d===null?u=v:d.sibling=v,d=v);return e&&h.forEach(function(e){return t(i,e)}),j&&Li(i,g),u}function b(e,r,a,c){if(typeof a==`object`&&a&&a.type===y&&a.key===null&&(a=a.props.children),typeof a==`object`&&a){switch(a.$$typeof){case _:a:{for(var l=a.key;r!==null;){if(r.key===l){if(l=a.type,l===y){if(r.tag===7){n(e,r.sibling),c=i(r,a.props.children),c.return=e,e=c;break a}}else if(r.elementType===l||typeof l==`object`&&l&&l.$$typeof===w&&Fa(l)===r.type){n(e,r.sibling),c=i(r,a.props),Ha(c,a),c.return=e,e=c;break a}n(e,r);break}t(e,r),r=r.sibling}a.type===y?(c=Si(a.props.children,e.mode,c,a.key),c.return=e,e=c):(c=xi(a.type,a.key,a.props,null,e.mode,c),Ha(c,a),c.return=e,e=c)}return o(e);case v:a:{for(l=a.key;r!==null;){if(r.key===l)if(r.tag===4&&r.stateNode.containerInfo===a.containerInfo&&r.stateNode.implementation===a.implementation){n(e,r.sibling),c=i(r,a.children||[]),c.return=e,e=c;break a}else{n(e,r);break}t(e,r),r=r.sibling}c=Ti(a,e.mode,c),c.return=e,e=c}return o(e);case w:return a=Fa(a),b(e,r,a,c)}if(ue(a))return h(e,r,a,c);if(se(a)){if(l=se(a),typeof l!=`function`)throw Error(s(150));return a=l.call(a),g(e,r,a,c)}if(typeof a.then==`function`)return b(e,r,Va(a),c);if(a.$$typeof===S)return b(e,r,ua(e,a),c);Ua(e,a)}return typeof a==`string`&&a!==``||typeof a==`number`||typeof a==`bigint`?(a=``+a,r!==null&&r.tag===6?(n(e,r.sibling),c=i(r,a),c.return=e,e=c):(n(e,r),c=Ci(a,e.mode,c),c.return=e,e=c),o(e)):n(e,r)}return function(e,t,n,r){try{Ba=0;var i=b(e,t,n,r);return za=null,i}catch(t){if(t===ka||t===ja)throw t;var a=_i(29,t,null,e.mode);return a.lanes=r,a.return=e,a}}}var Ga=Wa(!0),Ka=Wa(!1),qa=!1;function Ja(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Ya(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function Xa(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function Za(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,W&2){var i=r.pending;return i===null?t.next=t:(t.next=i.next,i.next=t),r.pending=t,t=mi(e),pi(e,null,n),t}return ui(e,r,t,n),mi(e)}function Qa(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,n&4194048)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,lt(e,n)}}function $a(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var i=null,a=null;if(n=n.firstBaseUpdate,n!==null){do{var o={lane:n.lane,tag:n.tag,payload:n.payload,callback:null,next:null};a===null?i=a=o:a=a.next=o,n=n.next}while(n!==null);a===null?i=a=t:a=a.next=t}else i=a=t;n={baseState:r.baseState,firstBaseUpdate:i,lastBaseUpdate:a,shared:r.shared,callbacks:r.callbacks},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}var eo=!1;function to(){if(eo){var e=ba;if(e!==null)throw e}}function no(e,t,n,r){eo=!1;var i=e.updateQueue;qa=!1;var a=i.firstBaseUpdate,o=i.lastBaseUpdate,s=i.shared.pending;if(s!==null){i.shared.pending=null;var c=s,l=c.next;c.next=null,o===null?a=l:o.next=l,o=c;var u=e.alternate;u!==null&&(u=u.updateQueue,s=u.lastBaseUpdate,s!==o&&(s===null?u.firstBaseUpdate=l:s.next=l,u.lastBaseUpdate=c))}if(a!==null){var d=i.baseState;o=0,u=l=c=null,s=a;do{var f=s.lane&-536870913,p=f!==s.lane;if(p?(q&f)===f:(r&f)===f){f!==0&&f===ya&&(eo=!0),u!==null&&(u=u.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});a:{var m=e,g=s;f=t;var _=n;switch(g.tag){case 1:if(m=g.payload,typeof m==`function`){d=m.call(_,d,f);break a}d=m;break a;case 3:m.flags=m.flags&-65537|128;case 0:if(m=g.payload,f=typeof m==`function`?m.call(_,d,f):m,f==null)break a;d=h({},d,f);break a;case 2:qa=!0}}f=s.callback,f!==null&&(e.flags|=64,p&&(e.flags|=8192),p=i.callbacks,p===null?i.callbacks=[f]:p.push(f))}else p={lane:f,tag:s.tag,payload:s.payload,callback:s.callback,next:null},u===null?(l=u=p,c=d):u=u.next=p,o|=f;if(s=s.next,s===null){if(s=i.shared.pending,s===null)break;p=s,s=p.next,p.next=null,i.lastBaseUpdate=p,i.shared.pending=null}}while(1);u===null&&(c=d),i.baseState=c,i.firstBaseUpdate=l,i.lastBaseUpdate=u,a===null&&(i.shared.lanes=0),Kl|=o,e.lanes=o,e.memoizedState=d}}function ro(e,t){if(typeof e!=`function`)throw Error(s(191,e));e.call(t)}function io(e,t){var n=e.callbacks;if(n!==null)for(e.callbacks=null,e=0;ea?a:8;var o=T.T,s={};T.T=s,zs(e,!1,t,n);try{var c=i(),l=T.S;l!==null&&l(s,c),typeof c==`object`&&c&&typeof c.then==`function`?Rs(e,t,Ca(c,r),pu(e)):Rs(e,t,r,pu(e))}catch(n){Rs(e,t,{then:function(){},status:`rejected`,reason:n},pu())}finally{E.p=a,o!==null&&s.types!==null&&(o.types=s.types),T.T=o}}function Os(){}function ks(e,t,n,r){if(e.tag!==5)throw Error(s(476));var i=As(e).queue;Ds(e,i,t,de,n===null?Os:function(){return js(e),n(r)})}function As(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:de,baseState:de,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Bo,lastRenderedState:de},next:null};var n={};return t.next={memoizedState:n,baseState:n,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Bo,lastRenderedState:n},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function js(e){var t=As(e);t.next===null&&(t=e.alternate.memoizedState),Rs(e,t.next.queue,{},pu())}function Ms(){return la(Qf)}function Ns(){return R().memoizedState}function Ps(){return R().memoizedState}function Fs(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var n=pu();e=Xa(n);var r=Za(t,e,n);r!==null&&(hu(r,t,n),Qa(r,t,n)),t={cache:ha()},e.payload=t;return}t=t.return}}function Is(e,t,n){var r=pu();n={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null},Bs(e)?Vs(t,n):(n=di(e,t,n,r),n!==null&&(hu(n,e,r),Hs(n,t,r)))}function Ls(e,t,n){Rs(e,t,n,pu())}function Rs(e,t,n,r){var i={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null};if(Bs(e))Vs(t,i);else{var a=e.alternate;if(e.lanes===0&&(a===null||a.lanes===0)&&(a=t.lastRenderedReducer,a!==null))try{var o=t.lastRenderedState,s=a(o,n);if(i.hasEagerState=!0,i.eagerState=s,jr(s,o))return ui(e,t,i,0),G===null&&li(),!1}catch{}if(n=di(e,t,i,r),n!==null)return hu(n,e,r),Hs(n,t,r),!0}return!1}function zs(e,t,n,r){if(r={lane:2,revertLane:dd(),gesture:null,action:r,hasEagerState:!1,eagerState:null,next:null},Bs(e)){if(t)throw Error(s(479))}else t=di(e,n,r,2),t!==null&&hu(t,e,2)}function Bs(e){var t=e.alternate;return e===P||t!==null&&t===P}function Vs(e,t){xo=bo=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function Hs(e,t,n){if(n&4194048){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,lt(e,n)}}var Us={readContext:la,use:Ro,useCallback:L,useContext:L,useEffect:L,useImperativeHandle:L,useLayoutEffect:L,useInsertionEffect:L,useMemo:L,useReducer:L,useRef:L,useState:L,useDebugValue:L,useDeferredValue:L,useTransition:L,useSyncExternalStore:L,useId:L,useHostTransitionStatus:L,useFormState:L,useActionState:L,useOptimistic:L,useMemoCache:L,useCacheRefresh:L};Us.useEffectEvent=L;var Ws={readContext:la,use:Ro,useCallback:function(e,t){return Fo().memoizedState=[e,t===void 0?null:t],e},useContext:la,useEffect:ms,useImperativeHandle:function(e,t,n){n=n==null?null:n.concat([e]),fs(4194308,4,bs.bind(null,t,e),n)},useLayoutEffect:function(e,t){return fs(4194308,4,e,t)},useInsertionEffect:function(e,t){fs(4,2,e,t)},useMemo:function(e,t){var n=Fo();t=t===void 0?null:t;var r=e();if(So){Ke(!0);try{e()}finally{Ke(!1)}}return n.memoizedState=[r,t],r},useReducer:function(e,t,n){var r=Fo();if(n!==void 0){var i=n(t);if(So){Ke(!0);try{n(t)}finally{Ke(!1)}}}else i=t;return r.memoizedState=r.baseState=i,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:i},r.queue=e,e=e.dispatch=Is.bind(null,P,e),[r.memoizedState,e]},useRef:function(e){var t=Fo();return e={current:e},t.memoizedState=e},useState:function(e){e=Xo(e);var t=e.queue,n=Ls.bind(null,P,t);return t.dispatch=n,[e.memoizedState,n]},useDebugValue:Ss,useDeferredValue:function(e,t){return Ts(Fo(),e,t)},useTransition:function(){var e=Xo(!1);return e=Ds.bind(null,P,e.queue,!0,!1),Fo().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,n){var r=P,i=Fo();if(j){if(n===void 0)throw Error(s(407));n=n()}else{if(n=t(),G===null)throw Error(s(349));q&127||Go(r,t,n)}i.memoizedState=n;var a={value:n,getSnapshot:t};return i.queue=a,ms(qo.bind(null,r,a,e),[e]),r.flags|=2048,us(9,{destroy:void 0},Ko.bind(null,r,a,n,t),null),n},useId:function(){var e=Fo(),t=G.identifierPrefix;if(j){var n=Ii,r=Fi;n=(r&~(1<<32-qe(r)-1)).toString(32)+n,t=`_`+t+`R_`+n,n=Co++,0<\/script>`,a=a.removeChild(a.firstChild);break;case`select`:a=typeof r.is==`string`?o.createElement(`select`,{is:r.is}):o.createElement(`select`),r.multiple?a.multiple=!0:r.size&&(a.size=r.size);break;default:a=typeof r.is==`string`?o.createElement(i,{is:r.is}):o.createElement(i)}}a[gt]=t,a[_t]=r;a:for(o=t.child;o!==null;){if(o.tag===5||o.tag===6)a.appendChild(o.stateNode);else if(o.tag!==4&&o.tag!==27&&o.child!==null){o.child.return=o,o=o.child;continue}if(o===t)break a;for(;o.sibling===null;){if(o.return===null||o.return===t)break a;o=o.return}o.sibling.return=o.return,o=o.sibling}t.stateNode=a;a:switch(Pd(a,i,r),i){case`button`:case`input`:case`select`:case`textarea`:r=!!r.autoFocus;break a;case`img`:r=!0;break a;default:r=!1}r&&Lc(t)}}return B(t),Rc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,n),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==r&&Lc(t);else{if(typeof r!=`string`&&t.stateNode===null)throw Error(s(166));if(e=_e.current,Yi(t)){if(e=t.stateNode,n=t.memoizedProps,r=null,i=Hi,i!==null)switch(i.tag){case 27:case 5:r=i.memoizedProps}e[gt]=t,e=!!(e.nodeValue===n||r!==null&&!0===r.suppressHydrationWarning||Md(e.nodeValue,n)),e||Ki(t,!0)}else e=Bd(e).createTextNode(r),e[gt]=t,t.stateNode=e}return B(t),null;case 31:if(n=t.memoizedState,e===null||e.memoizedState!==null){if(r=Yi(t),n!==null){if(e===null){if(!r)throw Error(s(318));if(e=t.memoizedState,e=e===null?null:e.dehydrated,!e)throw Error(s(557));e[gt]=t}else Xi(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;B(t),e=!1}else n=Zi(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),e=!0;if(!e)return t.flags&256?(_o(t),t):(_o(t),null);if(t.flags&128)throw Error(s(558))}return B(t),null;case 13:if(r=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(i=Yi(t),r!==null&&r.dehydrated!==null){if(e===null){if(!i)throw Error(s(318));if(i=t.memoizedState,i=i===null?null:i.dehydrated,!i)throw Error(s(317));i[gt]=t}else Xi(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;B(t),i=!1}else i=Zi(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=i),i=!0;if(!i)return t.flags&256?(_o(t),t):(_o(t),null)}return _o(t),t.flags&128?(t.lanes=n,t):(n=r!==null,e=e!==null&&e.memoizedState!==null,n&&(r=t.child,i=null,r.alternate!==null&&r.alternate.memoizedState!==null&&r.alternate.memoizedState.cachePool!==null&&(i=r.alternate.memoizedState.cachePool.pool),a=null,r.memoizedState!==null&&r.memoizedState.cachePool!==null&&(a=r.memoizedState.cachePool.pool),a!==i&&(r.flags|=2048)),n!==e&&n&&(t.child.flags|=8192),Bc(t,t.updateQueue),B(t),null);case 4:return be(),e===null&&Sd(t.stateNode.containerInfo),B(t),null;case 10:return ra(t.type),B(t),null;case 19:if(D(N),r=t.memoizedState,r===null)return B(t),null;if(i=!!(t.flags&128),a=r.rendering,a===null)if(i)Vc(r,!1);else{if(Y!==0||e!==null&&e.flags&128)for(e=t.child;e!==null;){if(a=vo(e),a!==null){for(t.flags|=128,Vc(r,!1),e=a.updateQueue,t.updateQueue=e,Bc(t,e),t.subtreeFlags=0,e=n,n=t.child;n!==null;)bi(n,e),n=n.sibling;return O(N,N.current&1|2),j&&Li(t,r.treeForkCount),t.child}e=e.sibling}r.tail!==null&&Fe()>nu&&(t.flags|=128,i=!0,Vc(r,!1),t.lanes=4194304)}else{if(!i)if(e=vo(a),e!==null){if(t.flags|=128,i=!0,e=e.updateQueue,t.updateQueue=e,Bc(t,e),Vc(r,!0),r.tail===null&&r.tailMode===`hidden`&&!a.alternate&&!j)return B(t),null}else 2*Fe()-r.renderingStartTime>nu&&n!==536870912&&(t.flags|=128,i=!0,Vc(r,!1),t.lanes=4194304);r.isBackwards?(a.sibling=t.child,t.child=a):(e=r.last,e===null?t.child=a:e.sibling=a,r.last=a)}return r.tail===null?(B(t),null):(e=r.tail,r.rendering=e,r.tail=e.sibling,r.renderingStartTime=Fe(),e.sibling=null,n=N.current,O(N,i?n&1|2:n&1),j&&Li(t,r.treeForkCount),e);case 22:case 23:return _o(t),lo(),r=t.memoizedState!==null,e===null?r&&(t.flags|=8192):e.memoizedState!==null!==r&&(t.flags|=8192),r?n&536870912&&!(t.flags&128)&&(B(t),t.subtreeFlags&6&&(t.flags|=8192)):B(t),n=t.updateQueue,n!==null&&Bc(t,n.retryQueue),n=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(n=e.memoizedState.cachePool.pool),r=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(r=t.memoizedState.cachePool.pool),r!==n&&(t.flags|=2048),e!==null&&D(Ta),null;case 24:return n=null,e!==null&&(n=e.memoizedState.cache),t.memoizedState.cache!==n&&(t.flags|=2048),ra(M),B(t),null;case 25:return null;case 30:return null}throw Error(s(156,t.tag))}function Uc(e,t){switch(Bi(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return ra(M),be(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return Se(t),null;case 31:if(t.memoizedState!==null){if(_o(t),t.alternate===null)throw Error(s(340));Xi()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(_o(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(s(340));Xi()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return D(N),null;case 4:return be(),null;case 10:return ra(t.type),null;case 22:case 23:return _o(t),lo(),e!==null&&D(Ta),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return ra(M),null;case 25:return null;default:return null}}function Wc(e,t){switch(Bi(t),t.tag){case 3:ra(M),be();break;case 26:case 27:case 5:Se(t);break;case 4:be();break;case 31:t.memoizedState!==null&&_o(t);break;case 13:_o(t);break;case 19:D(N);break;case 10:ra(t.type);break;case 22:case 23:_o(t),lo(),e!==null&&D(Ta);break;case 24:ra(M)}}function Gc(e,t){try{var n=t.updateQueue,r=n===null?null:n.lastEffect;if(r!==null){var i=r.next;n=i;do{if((n.tag&e)===e){r=void 0;var a=n.create,o=n.inst;r=a(),o.destroy=r}n=n.next}while(n!==i)}}catch(e){Z(t,t.return,e)}}function Kc(e,t,n){try{var r=t.updateQueue,i=r===null?null:r.lastEffect;if(i!==null){var a=i.next;r=a;do{if((r.tag&e)===e){var o=r.inst,s=o.destroy;if(s!==void 0){o.destroy=void 0,i=t;var c=n,l=s;try{l()}catch(e){Z(i,c,e)}}}r=r.next}while(r!==a)}}catch(e){Z(t,t.return,e)}}function qc(e){var t=e.updateQueue;if(t!==null){var n=e.stateNode;try{io(t,n)}catch(t){Z(e,e.return,t)}}}function Jc(e,t,n){n.props=Zs(e.type,e.memoizedProps),n.state=e.memoizedState;try{n.componentWillUnmount()}catch(n){Z(e,t,n)}}function Yc(e,t){try{var n=e.ref;if(n!==null){switch(e.tag){case 26:case 27:case 5:var r=e.stateNode;break;case 30:r=e.stateNode;break;default:r=e.stateNode}typeof n==`function`?e.refCleanup=n(r):n.current=r}}catch(n){Z(e,t,n)}}function Xc(e,t){var n=e.ref,r=e.refCleanup;if(n!==null)if(typeof r==`function`)try{r()}catch(n){Z(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof n==`function`)try{n(null)}catch(n){Z(e,t,n)}else n.current=null}function Zc(e){var t=e.type,n=e.memoizedProps,r=e.stateNode;try{a:switch(t){case`button`:case`input`:case`select`:case`textarea`:n.autoFocus&&r.focus();break a;case`img`:n.src?r.src=n.src:n.srcSet&&(r.srcset=n.srcSet)}}catch(t){Z(e,e.return,t)}}function Qc(e,t,n){try{var r=e.stateNode;Fd(r,e.type,n,t),r[_t]=t}catch(t){Z(e,e.return,t)}}function $c(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&Zd(e.type)||e.tag===4}function el(e){a:for(;;){for(;e.sibling===null;){if(e.return===null||$c(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&Zd(e.type)||e.flags&2||e.child===null||e.tag===4)continue a;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function tl(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?(n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n).insertBefore(e,t):(t=n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n,t.appendChild(e),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=ln));else if(r!==4&&(r===27&&Zd(e.type)&&(n=e.stateNode,t=null),e=e.child,e!==null))for(tl(e,t,n),e=e.sibling;e!==null;)tl(e,t,n),e=e.sibling}function nl(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(r!==4&&(r===27&&Zd(e.type)&&(n=e.stateNode),e=e.child,e!==null))for(nl(e,t,n),e=e.sibling;e!==null;)nl(e,t,n),e=e.sibling}function rl(e){var t=e.stateNode,n=e.memoizedProps;try{for(var r=e.type,i=t.attributes;i.length;)t.removeAttributeNode(i[0]);Pd(t,r,n),t[gt]=e,t[_t]=n}catch(t){Z(e,e.return,t)}}var il=!1,V=!1,al=!1,ol=typeof WeakSet==`function`?WeakSet:Set,H=null;function sl(e,t){if(e=e.containerInfo,Rd=sp,e=Ir(e),Lr(e)){if(`selectionStart`in e)var n={start:e.selectionStart,end:e.selectionEnd};else a:{n=(n=e.ownerDocument)&&n.defaultView||window;var r=n.getSelection&&n.getSelection();if(r&&r.rangeCount!==0){n=r.anchorNode;var i=r.anchorOffset,a=r.focusNode;r=r.focusOffset;try{n.nodeType,a.nodeType}catch{n=null;break a}var o=0,c=-1,l=-1,u=0,d=0,f=e,p=null;b:for(;;){for(var m;f!==n||i!==0&&f.nodeType!==3||(c=o+i),f!==a||r!==0&&f.nodeType!==3||(l=o+r),f.nodeType===3&&(o+=f.nodeValue.length),(m=f.firstChild)!==null;)p=f,f=m;for(;;){if(f===e)break b;if(p===n&&++u===i&&(c=o),p===a&&++d===r&&(l=o),(m=f.nextSibling)!==null)break;f=p,p=f.parentNode}f=m}n=c===-1||l===-1?null:{start:c,end:l}}else n=null}n||={start:0,end:0}}else n=null;for(zd={focusedElem:e,selectionRange:n},sp=!1,H=t;H!==null;)if(t=H,e=t.child,t.subtreeFlags&1028&&e!==null)e.return=t,H=e;else for(;H!==null;){switch(t=H,a=t.alternate,e=t.flags,t.tag){case 0:if(e&4&&(e=t.updateQueue,e=e===null?null:e.events,e!==null))for(n=0;n title`))),Pd(a,r,n),a[gt]=e,k(a),r=a;break a;case`link`:var o=Vf(`link`,`href`,i).get(r+(n.href||``));if(o){for(var c=0;cg&&(o=g,g=h,h=o);var _=Pr(s,h),v=Pr(s,g);if(_&&v&&(p.rangeCount!==1||p.anchorNode!==_.node||p.anchorOffset!==_.offset||p.focusNode!==v.node||p.focusOffset!==v.offset)){var y=d.createRange();y.setStart(_.node,_.offset),p.removeAllRanges(),h>g?(p.addRange(y),p.extend(v.node,v.offset)):(y.setEnd(v.node,v.offset),p.addRange(y))}}}}for(d=[],p=s;p=p.parentNode;)p.nodeType===1&&d.push({element:p,left:p.scrollLeft,top:p.scrollTop});for(typeof s.focus==`function`&&s.focus(),s=0;sn?32:n,T.T=null,n=lu,lu=null;var a=au,o=su;if(X=0,ou=au=null,su=0,W&6)throw Error(s(331));var c=W;if(W|=4,Il(a.current),Ol(a,a.current,o,n),W=c,id(0,!1),Ge&&typeof Ge.onPostCommitFiberRoot==`function`)try{Ge.onPostCommitFiberRoot(We,a)}catch{}return!0}finally{E.p=i,T.T=r,Vu(e,t)}}function Wu(e,t,n){t=Di(n,t),t=rc(e.stateNode,t,2),e=Za(e,t,2),e!==null&&(ot(e,2),rd(e))}function Z(e,t,n){if(e.tag===3)Wu(e,e,n);else for(;t!==null;){if(t.tag===3){Wu(t,e,n);break}if(t.tag===1){var r=t.stateNode;if(typeof t.type.getDerivedStateFromError==`function`||typeof r.componentDidCatch==`function`&&(iu===null||!iu.has(r))){e=Di(n,e),n=ic(2),r=Za(t,n,2),r!==null&&(ac(n,r,t,e),ot(r,2),rd(r));break}}t=t.return}}function Gu(e,t,n){var r=e.pingCache;if(r===null){r=e.pingCache=new Bl;var i=new Set;r.set(t,i)}else i=r.get(t),i===void 0&&(i=new Set,r.set(t,i));i.has(n)||(Wl=!0,i.add(n),e=Ku.bind(null,e,t,n),t.then(e,e))}function Ku(e,t,n){var r=e.pingCache;r!==null&&r.delete(t),e.pingedLanes|=e.suspendedLanes&n,e.warmLanes&=~n,G===e&&(q&n)===n&&(Y===4||Y===3&&(q&62914560)===q&&300>Fe()-eu?!(W&2)&&Su(e,0):Jl|=n,Xl===q&&(Xl=0)),rd(e)}function qu(e,t){t===0&&(t=it()),e=fi(e,t),e!==null&&(ot(e,t),rd(e))}function Ju(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),qu(e,n)}function Yu(e,t){var n=0;switch(e.tag){case 31:case 13:var r=e.stateNode,i=e.memoizedState;i!==null&&(n=i.retryLane);break;case 19:r=e.stateNode;break;case 22:r=e.stateNode._retryCache;break;default:throw Error(s(314))}r!==null&&r.delete(t),qu(e,n)}function Xu(e,t){return je(e,t)}var Zu=null,Qu=null,$u=!1,ed=!1,td=!1,nd=0;function rd(e){e!==Qu&&e.next===null&&(Qu===null?Zu=Qu=e:Qu=Qu.next=e),ed=!0,$u||($u=!0,ud())}function id(e,t){if(!td&&ed){td=!0;do for(var n=!1,r=Zu;r!==null;){if(!t)if(e!==0){var i=r.pendingLanes;if(i===0)var a=0;else{var o=r.suspendedLanes,s=r.pingedLanes;a=(1<<31-qe(42|e)+1)-1,a&=i&~(o&~s),a=a&201326741?a&201326741|1:a?a|2:0}a!==0&&(n=!0,ld(r,a))}else a=q,a=tt(r,r===G?a:0,r.cancelPendingCommit!==null||r.timeoutHandle!==-1),!(a&3)||nt(r,a)||(n=!0,ld(r,a));r=r.next}while(n);td=!1}}function ad(){od()}function od(){ed=$u=!1;var e=0;nd!==0&&Gd()&&(e=nd);for(var t=Fe(),n=null,r=Zu;r!==null;){var i=r.next,a=sd(r,t);a===0?(r.next=null,n===null?Zu=i:n.next=i,i===null&&(Qu=n)):(n=r,(e!==0||a&3)&&(ed=!0)),r=i}X!==0&&X!==5||id(e,!1),nd!==0&&(nd=0)}function sd(e,t){for(var n=e.suspendedLanes,r=e.pingedLanes,i=e.expirationTimes,a=e.pendingLanes&-62914561;0s)break;var u=c.transferSize,d=c.initiatorType;u&&Id(d)&&(c=c.responseEnd,o+=u*(c`u`?null:document;function xf(e,t,n){var r=bf;if(r&&typeof t==`string`&&t){var i=qt(t);i=`link[rel="`+e+`"][href="`+i+`"]`,typeof n==`string`&&(i+=`[crossorigin="`+n+`"]`),hf.has(i)||(hf.add(i),e={rel:e,crossOrigin:n,href:t},r.querySelector(i)===null&&(t=r.createElement(`link`),Pd(t,`link`,e),k(t),r.head.appendChild(t)))}}function Sf(e){_f.D(e),xf(`dns-prefetch`,e,null)}function Cf(e,t){_f.C(e,t),xf(`preconnect`,e,t)}function wf(e,t,n){_f.L(e,t,n);var r=bf;if(r&&e&&t){var i=`link[rel="preload"][as="`+qt(t)+`"]`;t===`image`&&n&&n.imageSrcSet?(i+=`[imagesrcset="`+qt(n.imageSrcSet)+`"]`,typeof n.imageSizes==`string`&&(i+=`[imagesizes="`+qt(n.imageSizes)+`"]`)):i+=`[href="`+qt(e)+`"]`;var a=i;switch(t){case`style`:a=Af(e);break;case`script`:a=Pf(e)}mf.has(a)||(e=h({rel:`preload`,href:t===`image`&&n&&n.imageSrcSet?void 0:e,as:t},n),mf.set(a,e),r.querySelector(i)!==null||t===`style`&&r.querySelector(jf(a))||t===`script`&&r.querySelector(Ff(a))||(t=r.createElement(`link`),Pd(t,`link`,e),k(t),r.head.appendChild(t)))}}function Tf(e,t){_f.m(e,t);var n=bf;if(n&&e){var r=t&&typeof t.as==`string`?t.as:`script`,i=`link[rel="modulepreload"][as="`+qt(r)+`"][href="`+qt(e)+`"]`,a=i;switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:a=Pf(e)}if(!mf.has(a)&&(e=h({rel:`modulepreload`,href:e},t),mf.set(a,e),n.querySelector(i)===null)){switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:if(n.querySelector(Ff(a)))return}r=n.createElement(`link`),Pd(r,`link`,e),k(r),n.head.appendChild(r)}}}function Ef(e,t,n){_f.S(e,t,n);var r=bf;if(r&&e){var i=Ot(r).hoistableStyles,a=Af(e);t||=`default`;var o=i.get(a);if(!o){var s={loading:0,preload:null};if(o=r.querySelector(jf(a)))s.loading=5;else{e=h({rel:`stylesheet`,href:e,"data-precedence":t},n),(n=mf.get(a))&&Rf(e,n);var c=o=r.createElement(`link`);k(c),Pd(c,`link`,e),c._p=new Promise(function(e,t){c.onload=e,c.onerror=t}),c.addEventListener(`load`,function(){s.loading|=1}),c.addEventListener(`error`,function(){s.loading|=2}),s.loading|=4,Lf(o,t,r)}o={type:`stylesheet`,instance:o,count:1,state:s},i.set(a,o)}}}function Df(e,t){_f.X(e,t);var n=bf;if(n&&e){var r=Ot(n).hoistableScripts,i=Pf(e),a=r.get(i);a||(a=n.querySelector(Ff(i)),a||(e=h({src:e,async:!0},t),(t=mf.get(i))&&zf(e,t),a=n.createElement(`script`),k(a),Pd(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function Of(e,t){_f.M(e,t);var n=bf;if(n&&e){var r=Ot(n).hoistableScripts,i=Pf(e),a=r.get(i);a||(a=n.querySelector(Ff(i)),a||(e=h({src:e,async:!0,type:`module`},t),(t=mf.get(i))&&zf(e,t),a=n.createElement(`script`),k(a),Pd(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function kf(e,t,n,r){var i=(i=_e.current)?gf(i):null;if(!i)throw Error(s(446));switch(e){case`meta`:case`title`:return null;case`style`:return typeof n.precedence==`string`&&typeof n.href==`string`?(t=Af(n.href),n=Ot(i).hoistableStyles,r=n.get(t),r||(r={type:`style`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};case`link`:if(n.rel===`stylesheet`&&typeof n.href==`string`&&typeof n.precedence==`string`){e=Af(n.href);var a=Ot(i).hoistableStyles,o=a.get(e);if(o||(i=i.ownerDocument||i,o={type:`stylesheet`,instance:null,count:0,state:{loading:0,preload:null}},a.set(e,o),(a=i.querySelector(jf(e)))&&!a._p&&(o.instance=a,o.state.loading=5),mf.has(e)||(n={rel:`preload`,as:`style`,href:n.href,crossOrigin:n.crossOrigin,integrity:n.integrity,media:n.media,hrefLang:n.hrefLang,referrerPolicy:n.referrerPolicy},mf.set(e,n),a||Nf(i,e,n,o.state))),t&&r===null)throw Error(s(528,``));return o}if(t&&r!==null)throw Error(s(529,``));return null;case`script`:return t=n.async,n=n.src,typeof n==`string`&&t&&typeof t!=`function`&&typeof t!=`symbol`?(t=Pf(n),n=Ot(i).hoistableScripts,r=n.get(t),r||(r={type:`script`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};default:throw Error(s(444,e))}}function Af(e){return`href="`+qt(e)+`"`}function jf(e){return`link[rel="stylesheet"][`+e+`]`}function Mf(e){return h({},e,{"data-precedence":e.precedence,precedence:null})}function Nf(e,t,n,r){e.querySelector(`link[rel="preload"][as="style"][`+t+`]`)?r.loading=1:(t=e.createElement(`link`),r.preload=t,t.addEventListener(`load`,function(){return r.loading|=1}),t.addEventListener(`error`,function(){return r.loading|=2}),Pd(t,`link`,n),k(t),e.head.appendChild(t))}function Pf(e){return`[src="`+qt(e)+`"]`}function Ff(e){return`script[async]`+e}function If(e,t,n){if(t.count++,t.instance===null)switch(t.type){case`style`:var r=e.querySelector(`style[data-href~="`+qt(n.href)+`"]`);if(r)return t.instance=r,k(r),r;var i=h({},n,{"data-href":n.href,"data-precedence":n.precedence,href:null,precedence:null});return r=(e.ownerDocument||e).createElement(`style`),k(r),Pd(r,`style`,i),Lf(r,n.precedence,e),t.instance=r;case`stylesheet`:i=Af(n.href);var a=e.querySelector(jf(i));if(a)return t.state.loading|=4,t.instance=a,k(a),a;r=Mf(n),(i=mf.get(i))&&Rf(r,i),a=(e.ownerDocument||e).createElement(`link`),k(a);var o=a;return o._p=new Promise(function(e,t){o.onload=e,o.onerror=t}),Pd(a,`link`,r),t.state.loading|=4,Lf(a,n.precedence,e),t.instance=a;case`script`:return a=Pf(n.src),(i=e.querySelector(Ff(a)))?(t.instance=i,k(i),i):(r=n,(i=mf.get(a))&&(r=h({},n),zf(r,i)),e=e.ownerDocument||e,i=e.createElement(`script`),k(i),Pd(i,`link`,r),e.head.appendChild(i),t.instance=i);case`void`:return null;default:throw Error(s(443,t.type))}else t.type===`stylesheet`&&!(t.state.loading&4)&&(r=t.instance,t.state.loading|=4,Lf(r,n.precedence,e));return t.instance}function Lf(e,t,n){for(var r=n.querySelectorAll(`link[rel="stylesheet"][data-precedence],style[data-precedence]`),i=r.length?r[r.length-1]:null,a=i,o=0;o title`):null)}function Uf(e,t,n){if(n===1||t.itemProp!=null)return!1;switch(e){case`meta`:case`title`:return!0;case`style`:if(typeof t.precedence!=`string`||typeof t.href!=`string`||t.href===``)break;return!0;case`link`:if(typeof t.rel!=`string`||typeof t.href!=`string`||t.href===``||t.onLoad||t.onError)break;switch(t.rel){case`stylesheet`:return e=t.disabled,typeof t.precedence==`string`&&e==null;default:return!0}case`script`:if(t.async&&typeof t.async!=`function`&&typeof t.async!=`symbol`&&!t.onLoad&&!t.onError&&t.src&&typeof t.src==`string`)return!0}return!1}function Wf(e){return!(e.type===`stylesheet`&&!(e.state.loading&3))}function Gf(e,t,n,r){if(n.type===`stylesheet`&&(typeof r.media!=`string`||!1!==matchMedia(r.media).matches)&&!(n.state.loading&4)){if(n.instance===null){var i=Af(r.href),a=t.querySelector(jf(i));if(a){t=a._p,typeof t==`object`&&t&&typeof t.then==`function`&&(e.count++,e=Jf.bind(e),t.then(e,e)),n.state.loading|=4,n.instance=a,k(a);return}a=t.ownerDocument||t,r=Mf(r),(i=mf.get(i))&&Rf(r,i),a=a.createElement(`link`),k(a);var o=a;o._p=new Promise(function(e,t){o.onload=e,o.onerror=t}),Pd(a,`link`,r),n.instance=a}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(n,t),(t=n.state.preload)&&!(n.state.loading&3)&&(e.count++,n=Jf.bind(e),t.addEventListener(`load`,n),t.addEventListener(`error`,n))}}var Kf=0;function qf(e,t){return e.stylesheets&&e.count===0&&Xf(e,e.stylesheets),0Kf?50:800)+t);return e.unsuspend=n,function(){e.unsuspend=null,clearTimeout(r),clearTimeout(i)}}:null}function Jf(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Xf(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var Yf=null;function Xf(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,Yf=new Map,t.forEach(Zf,e),Yf=null,Jf.call(e))}function Zf(e,t){if(!(t.state.loading&4)){var n=Yf.get(e);if(n)var r=n.get(null);else{n=new Map,Yf.set(e,n);for(var i=e.querySelectorAll(`link[data-precedence],style[data-precedence]`),a=0;a{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=s()})),l=n(),u=c(),d=e=>{let t=e.role||e.type;return t===`user`||t===`assistant`||t===`tool`||t===`system`?t:`assistant`},f=e=>{if(e.text)return e.text;if(e.payload&&typeof e.payload==`object`&&`content`in e.payload){let t=e.payload.content;if(typeof t==`string`)return t}return``},p=e=>{let t=e.entries.find(e=>d(e)===`user`);if(t){let e=f(t).trim();if(e)return e}let n=e.metadata?.objective;return typeof n==`string`&&n.trim()?n:e.id},m=e=>{let t=new Date(e);return Number.isNaN(t.getTime())?``:new Intl.DateTimeFormat(`zh-CN`,{month:`short`,day:`numeric`,hour:`2-digit`,minute:`2-digit`}).format(t)},h=(e,t)=>{let n=t.trim().toLowerCase();if(!n)return!0;let r=[e.id,e.cwd,p(e)].map(e=>e.toLowerCase());for(let t of e.entries)r.push(f(t).toLowerCase()),t.tool&&r.push(t.tool.toLowerCase());return r.some(e=>e.includes(n))},g=(e,t)=>e.filter(e=>h(e,t)),_=(e,t)=>t===`all`?e:e.filter(e=>d(e)===t),v=``+new URL(`call-code-BBgvhvPd.png`,import.meta.url).href,y=e((e=>{var t=Symbol.for(`react.transitional.element`);function n(e,n,r){var i=null;if(r!==void 0&&(i=``+r),n.key!==void 0&&(i=``+n.key),`key`in n)for(var a in r={},n)a!==`key`&&(r[a]=n[a]);else r=n;return n=r.ref,{$$typeof:t,type:e,key:i,ref:n===void 0?null:n,props:r}}e.jsx=n,e.jsxs=n})),b=e(((e,t)=>{t.exports=y()}))();function x({sessions:e,theme:t,onThemeChange:n}){let r=e.reduce((e,t)=>(e.messages+=t.entries.length,e.tools+=t.entries.filter(e=>d(e)===`tool`).length,e),{messages:0,tools:0});return(0,b.jsxs)(`header`,{className:`header-bar`,children:[(0,b.jsxs)(`div`,{className:`flex min-w-0 items-center gap-3`,children:[(0,b.jsx)(`img`,{src:v,alt:`Call Code`,className:`h-9 w-9 shrink-0 rounded-xl border object-contain`,style:{borderColor:`rgb(var(--chip-border))`,background:`rgb(var(--chip-bg))`}}),(0,b.jsxs)(`div`,{className:`min-w-0`,children:[(0,b.jsx)(`h1`,{className:`truncate text-[17px] font-semibold leading-tight`,style:{color:`var(--text-primary)`},children:`Call Code`}),(0,b.jsxs)(`div`,{className:`mt-0.5 truncate text-[11px]`,style:{color:`var(--text-tertiary)`},children:[e.length,` 个会话 · `,r.messages,` 条消息 · `,r.tools,` `,`次工具`]})]})]}),(0,b.jsx)(`div`,{className:`segmented shrink-0`,role:`tablist`,"aria-label":`主题切换`,children:[`light`,`dark`].map(e=>(0,b.jsx)(`button`,{type:`button`,role:`tab`,"aria-pressed":t===e,onClick:()=>n(e),children:e===`light`?`毛玻璃`:`高级黑`},e))})]})}function ee({sessions:e,activeId:t,query:n,onSelect:r,onQueryChange:i}){return(0,b.jsxs)(`aside`,{className:`sidebar-panel max-h-[50vh] lg:max-h-none`,children:[(0,b.jsx)(`header`,{className:`border-b px-3 py-3`,style:{borderColor:`rgb(var(--panel-border))`},children:(0,b.jsxs)(`div`,{className:`search-box flex h-8 min-w-0 items-center gap-2 rounded-lg border px-2.5`,style:{borderColor:`rgb(var(--chip-border))`,background:`rgb(var(--chip-bg))`},children:[(0,b.jsxs)(`svg`,{width:`13`,height:`13`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,style:{color:`var(--text-tertiary)`},"aria-hidden":`true`,children:[(0,b.jsx)(`circle`,{cx:`11`,cy:`11`,r:`7`}),(0,b.jsx)(`path`,{d:`m20 20-3.5-3.5`})]}),(0,b.jsx)(`input`,{type:`search`,value:n,onChange:e=>i(e.target.value),placeholder:`搜索会话`,"aria-label":`搜索会话`,className:`h-full w-full min-w-0 bg-transparent text-[12px] outline-none`,style:{color:`var(--text-primary)`}})]})}),(0,b.jsxs)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-2 pt-3 pb-3`,children:[e.length===0&&(0,b.jsx)(`div`,{className:`grid min-h-[120px] place-items-center text-[12px]`,style:{color:`var(--text-tertiary)`},children:`暂无会话`}),(0,b.jsx)(`div`,{className:`flex flex-col gap-0.5`,children:e.map(e=>{let n=e.id===t;return(0,b.jsxs)(`button`,{type:`button`,onClick:()=>r(e.id),"aria-current":n?`true`:void 0,className:`group relative flex items-start gap-2.5 rounded-xl px-2.5 py-2 text-left transition-all duration-200`,style:n?{background:`rgb(var(--sidebar-active))`,boxShadow:`var(--sidebar-active-shadow)`}:void 0,onMouseEnter:e=>{n||(e.currentTarget.style.background=`rgb(var(--sidebar-hover))`)},onMouseLeave:e=>{n||(e.currentTarget.style.background=``)},children:[(0,b.jsx)(`span`,{className:`mt-1 h-4 w-1 shrink-0 rounded-full transition-opacity`,style:{background:n?`var(--text-primary)`:`transparent`,opacity:+!!n},"aria-hidden":`true`}),(0,b.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,b.jsx)(`div`,{className:`line-clamp-2 text-[13px] font-medium leading-snug`,style:{color:n?`var(--text-primary)`:`var(--text-secondary)`},children:p(e)}),(0,b.jsxs)(`div`,{className:`mt-1 flex items-center gap-1.5 text-[11px]`,style:{color:`var(--text-tertiary)`},children:[(0,b.jsxs)(`span`,{children:[e.entries.length,` 条`]}),(0,b.jsx)(`span`,{style:{opacity:.4},children:`·`}),(0,b.jsx)(`span`,{className:`truncate`,children:m(e.createdAt)})]})]})]},e.id)})})]})]})}var S={user:{label:`用户`,dotClass:`role-dot role-dot--user`,bubbleClass:`msg-bubble--user`},assistant:{label:`助手`,dotClass:`role-dot role-dot--assistant`,bubbleClass:`msg-bubble--assistant`},tool:{label:`工具`,dotClass:`role-dot role-dot--tool`,bubbleClass:`msg-bubble--tool`},system:{label:`系统`,dotClass:`role-dot role-dot--system`,bubbleClass:``}};function C({entry:e}){let t=d(e),n=S[t],r=f(e),i=t===`tool`||r.length>320;return(0,b.jsxs)(`article`,{className:`flex gap-3`,children:[(0,b.jsx)(`div`,{className:`pt-1.5`,children:(0,b.jsx)(`span`,{className:n.dotClass,"aria-hidden":`true`})}),(0,b.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,b.jsxs)(`div`,{className:`mb-1.5 flex items-center gap-2 text-[11px] font-medium`,style:{color:`var(--text-tertiary)`},children:[(0,b.jsx)(`span`,{style:{color:`var(--role-${t})`},children:n.label}),e.tool?(0,b.jsx)(`span`,{className:`chip !py-0 !text-[10px]`,children:e.tool}):null,(0,b.jsx)(`span`,{className:`ml-auto shrink-0`,children:m(e.timestamp)})]}),i?(0,b.jsx)(`pre`,{className:`msg-bubble ${n.bubbleClass} mono m-0 max-h-[480px] overflow-auto px-3.5 py-2.5 text-[12px]`,style:{color:`var(--text-secondary)`},children:r}):(0,b.jsx)(`div`,{className:`msg-bubble ${n.bubbleClass} whitespace-pre-wrap break-words px-3.5 py-2.5 text-[13.5px] leading-relaxed`,style:{color:`var(--text-primary)`},children:r})]})]})}var te=[{value:`all`,label:`全部`},{value:`user`,label:`用户`},{value:`assistant`,label:`助手`},{value:`tool`,label:`工具`}];function ne({session:e}){let t=[[`消息`,`${e.entries.length}`],[`tokens`,e.stats?.totalTokens?.toLocaleString()??`0`],[`成本`,`$${(e.stats?.costTotal??0).toFixed(3)}`],[`目录`,e.cwd]];return(0,b.jsx)(`div`,{className:`flex flex-wrap items-center gap-1.5`,children:t.map(([e,t])=>(0,b.jsxs)(`span`,{className:`chip max-w-[240px] truncate`,children:[(0,b.jsx)(`span`,{style:{opacity:.6},children:e}),(0,b.jsx)(`span`,{className:`truncate`,children:t})]},e))})}function re({facts:e}){return e.length===0?null:(0,b.jsxs)(`section`,{className:`mt-8`,children:[(0,b.jsx)(`div`,{className:`mb-3 text-[11px] font-medium uppercase tracking-wider`,style:{color:`var(--text-tertiary)`},children:`事实`}),(0,b.jsx)(`div`,{className:`grid gap-2 sm:grid-cols-2 lg:grid-cols-3`,children:e.slice(0,12).map((e,t)=>(0,b.jsxs)(`div`,{className:`msg-bubble px-3 py-2.5`,children:[(0,b.jsx)(`div`,{className:`text-[11px]`,style:{color:`var(--text-tertiary)`},children:e.kind}),(0,b.jsx)(`div`,{className:`mt-0.5 truncate text-[13px]`,style:{color:`var(--text-primary)`},children:e.value||e.key||String(e.seq)})]},`${e.seq}-${t}`))})]})}var w=e=>typeof e==`string`?e:e&&typeof e==`object`?JSON.stringify(e,null,2):String(e??``);function ie({records:e}){return e.length===0?null:(0,b.jsxs)(`section`,{className:`mt-8`,children:[(0,b.jsxs)(`div`,{className:`mb-3 text-[11px] font-medium uppercase tracking-wider`,style:{color:`var(--text-tertiary)`},children:[`运行记录 · 最近 `,Math.min(20,e.length),` 条`]}),(0,b.jsx)(`div`,{className:`flex flex-col gap-1.5`,children:e.slice(-20).reverse().map(e=>(0,b.jsxs)(`div`,{className:`msg-bubble px-3 py-2.5`,children:[(0,b.jsxs)(`div`,{className:`flex items-center justify-between gap-2 text-[11px]`,style:{color:`var(--text-tertiary)`},children:[(0,b.jsxs)(`span`,{className:`truncate`,children:[e.type,e.opKind?` / ${e.opKind}`:``]}),(0,b.jsx)(`span`,{className:`shrink-0`,children:m(e.timestamp)})]}),(0,b.jsx)(`div`,{className:`mt-1.5 max-h-40 overflow-auto whitespace-pre-wrap break-words mono`,style:{color:`var(--text-secondary)`},children:w(e.payload)})]},e.id))})]})}function ae({session:e,filter:t,onFilterChange:n}){let r=e?_(e.entries,t):[];return(0,b.jsxs)(`main`,{className:`main-panel`,children:[(0,b.jsxs)(`header`,{className:`flex flex-col gap-3 px-6 pt-5 pb-4`,children:[(0,b.jsx)(`h2`,{className:`truncate text-[15px] font-semibold leading-snug`,style:{color:`var(--text-primary)`},children:e?p(e):`暂无会话`}),e?(0,b.jsx)(ne,{session:e}):null]}),(0,b.jsx)(`div`,{className:`flex items-center gap-3 border-t px-6 py-2.5`,style:{borderColor:`rgb(var(--panel-border))`},children:(0,b.jsx)(`div`,{className:`segmented`,role:`tablist`,"aria-label":`消息过滤`,children:te.map(e=>(0,b.jsx)(`button`,{type:`button`,role:`tab`,"aria-pressed":t===e.value,onClick:()=>n(e.value),children:e.label},e.value))})}),(0,b.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-6 py-6`,children:(0,b.jsx)(`div`,{className:`mx-auto max-w-[760px]`,children:e?r.length===0?(0,b.jsx)(`div`,{className:`grid min-h-[200px] place-items-center text-[13px]`,style:{color:`var(--text-tertiary)`},children:`没有匹配的消息`}):(0,b.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[r.map(e=>(0,b.jsx)(C,{entry:e},e.id)),e.facts?(0,b.jsx)(re,{facts:e.facts}):null,e.records?(0,b.jsx)(ie,{records:e.records}):null]}):(0,b.jsx)(`div`,{className:`grid min-h-[200px] place-items-center text-[13px]`,style:{color:`var(--text-tertiary)`},children:`暂无会话数据`})})})]})}var oe=[`./data.json`,`./data.example.json`],se=()=>{let e=new URLSearchParams(window.location.search),t=e.get(`data`)||e.get(`dataUrl`);return t?[t,...oe]:oe},ce=e=>{if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.id==`string`&&typeof t.createdAt==`string`&&typeof t.cwd==`string`&&Array.isArray(t.entries)},le=e=>{if(!e||typeof e!=`object`)return!1;let t=e;return t.schemaVersion===1&&typeof t.exportedAt==`string`&&Array.isArray(t.sessions)&&t.sessions.every(ce)},ue=async()=>{for(let e of se())try{let t=new URL(e,window.location.href),n=await fetch(t,{cache:`no-cache`});if(!n.ok)continue;let r=await n.json();if(le(r))return r}catch{}return null},T=`call-code-theme`,E=()=>localStorage.getItem(T)===`light`?`light`:`dark`;function de(){let[e,t]=(0,l.useState)(null),[n,r]=(0,l.useState)(`loading`),[i,a]=(0,l.useState)(E),[o,s]=(0,l.useState)(null),[c,u]=(0,l.useState)(``),[d,f]=(0,l.useState)(`all`);(0,l.useEffect)(()=>{let e=!1;return ue().then(n=>{if(e)return;t(n);let i=new URLSearchParams(window.location.search).get(`session`);s(i&&n?.sessions.some(e=>e.id===i)?i:n?.sessions[0]?.id??null),r(n?`ready`:`error`)}),()=>{e=!0}},[]),(0,l.useEffect)(()=>{document.documentElement.classList.toggle(`dark`,i===`dark`),localStorage.setItem(T,i)},[i]);let p=(0,l.useMemo)(()=>e?.sessions??[],[e]),m=(0,l.useMemo)(()=>g(p,c),[p,c]),h=(0,l.useMemo)(()=>m.find(e=>e.id===o)??m[0]??null,[m,o]);return n===`loading`?(0,b.jsx)(`div`,{className:`app-shell`,children:(0,b.jsx)(`div`,{className:`grid min-h-[60vh] place-items-center text-sm`,style:{color:`var(--text-tertiary)`},children:`正在读取会话`})}):n===`error`||!e?(0,b.jsx)(`div`,{className:`app-shell`,children:(0,b.jsx)(`div`,{className:`grid min-h-[60vh] place-items-center text-sm`,style:{color:`var(--text-tertiary)`},children:`无法读取会话数据`})}):(0,b.jsx)(`div`,{className:`app-shell`,children:(0,b.jsxs)(`div`,{className:`app-frame`,children:[(0,b.jsx)(x,{sessions:m,theme:i,onThemeChange:a}),(0,b.jsxs)(`div`,{className:`app-workspace`,children:[(0,b.jsx)(ee,{sessions:m,activeId:o,query:c,onSelect:s,onQueryChange:u}),(0,b.jsx)(ae,{session:h,filter:d,onFilterChange:f})]})]})})}var fe=document.getElementById(`root`);if(!fe)throw Error(`未找到 #root 容器`);(0,u.createRoot)(fe).render((0,b.jsx)(l.StrictMode,{children:(0,b.jsx)(de,{})})); \ No newline at end of file diff --git a/packages/client/dist/data.example.json b/packages/client/dist/data.example.json deleted file mode 100644 index e8e8f15..0000000 --- a/packages/client/dist/data.example.json +++ /dev/null @@ -1,169 +0,0 @@ -{ - "schemaVersion": 1, - "exportedAt": "2026-08-05T12:00:00.000Z", - "sessions": [ - { - "id": "demo-build", - "createdAt": "2026-08-05T10:10:00.000Z", - "cwd": "/Users/allure/Desktop/demo-app", - "parentSessionId": null, - "metadata": { - "mode": "build", - "objective": "为仪表盘增加搜索过滤" - }, - "stats": { - "messageCount": 4, - "cachedTokens": 1200, - "uncachedTokens": 860, - "totalTokens": 2060, - "costTotal": 0.04 - }, - "entries": [ - { - "seq": 1, - "id": "e-user-1", - "parentId": null, - "type": "user", - "role": "user", - "timestamp": "2026-08-05T10:10:00.000Z", - "text": "给仪表盘加一个搜索框,按任务状态过滤列表。", - "payload": { - "content": "给仪表盘加一个搜索框,按任务状态过滤列表。", - "tags": ["task-input"] - } - }, - { - "seq": 2, - "id": "e-assistant-1", - "parentId": "e-user-1", - "type": "assistant", - "role": "assistant", - "timestamp": "2026-08-05T10:10:12.000Z", - "text": "我会先读取现有仪表盘组件,找出状态字段和列表渲染位置,再补充搜索过滤。", - "payload": { - "content": "我会先读取现有仪表盘组件,找出状态字段和列表渲染位置,再补充搜索过滤。", - "tags": ["model-response"] - } - }, - { - "seq": 3, - "id": "e-tool-1", - "parentId": "e-assistant-1", - "type": "tool", - "role": "tool", - "timestamp": "2026-08-05T10:10:18.000Z", - "tool": "read_file", - "text": "{\"path\":\"src/pages/dashboard.tsx\"}\nsuccess", - "payload": { - "content": "{\"path\":\"src/pages/dashboard.tsx\"}\nsuccess", - "tool": "read_file", - "tags": ["tool-result", "read_file"] - } - }, - { - "seq": 4, - "id": "e-assistant-2", - "parentId": "e-tool-1", - "type": "assistant", - "role": "assistant", - "timestamp": "2026-08-05T10:10:30.000Z", - "text": "已完成搜索框和状态过滤,列表会按状态字段实时过滤。", - "payload": { - "content": "已完成搜索框和状态过滤,列表会按状态字段实时过滤。", - "tags": ["model-response"] - } - } - ], - "records": [ - { - "seq": 3, - "id": "r-tool-1", - "lane": "run", - "runId": "demo-build", - "type": "tool_call", - "opKind": "read_file", - "timestamp": "2026-08-05T10:10:18.000Z", - "payload": { - "tool": "read_file", - "path": "src/pages/dashboard.tsx" - } - } - ], - "facts": [ - { - "seq": 1, - "kind": "task-objective", - "key": "objective", - "value": "为仪表盘增加搜索过滤" - } - ] - }, - { - "id": "demo-plan", - "createdAt": "2026-08-04T09:20:00.000Z", - "cwd": "/Users/allure/Desktop/call-code", - "parentSessionId": null, - "metadata": { - "mode": "plan", - "objective": "评估 GitHub Pages 静态发布方案" - }, - "stats": { - "messageCount": 3, - "cachedTokens": 900, - "uncachedTokens": 640, - "totalTokens": 1540, - "costTotal": 0.02 - }, - "entries": [ - { - "seq": 1, - "id": "e-user-p1", - "parentId": null, - "type": "user", - "role": "user", - "timestamp": "2026-08-04T09:20:00.000Z", - "text": "梳理 GitHub Pages 部署路径和需要提交的静态文件。", - "payload": { - "content": "梳理 GitHub Pages 部署路径和需要提交的静态文件。", - "tags": ["task-input"] - } - }, - { - "seq": 2, - "id": "e-assistant-p1", - "parentId": "e-user-p1", - "type": "assistant", - "role": "assistant", - "timestamp": "2026-08-04T09:20:08.000Z", - "text": "可以使用 GitHub Actions 将 packages/client 发布到 Pages,数据由 pnpm export:web 生成并提交。", - "payload": { - "content": "可以使用 GitHub Actions 将 packages/client 发布到 Pages,数据由 pnpm export:web 生成并提交。", - "tags": ["model-response"] - } - }, - { - "seq": 3, - "id": "e-assistant-p2", - "parentId": "e-assistant-p1", - "type": "assistant", - "role": "assistant", - "timestamp": "2026-08-04T09:20:16.000Z", - "text": "计划完成,确认后进入 BUILD 模式部署工作流。", - "payload": { - "content": "计划完成,确认后进入 BUILD 模式部署工作流。", - "tags": ["model-response"] - } - } - ], - "records": [], - "facts": [ - { - "seq": 1, - "kind": "task-objective", - "key": "objective", - "value": "评估 GitHub Pages 静态发布方案" - } - ] - } - ] -} diff --git a/packages/client/dist/index.html b/packages/client/dist/index.html index e7c1b22..de6e9dc 100644 --- a/packages/client/dist/index.html +++ b/packages/client/dist/index.html @@ -4,7 +4,7 @@ Call Code History - + diff --git a/packages/client/public/data.example.json b/packages/client/public/data.example.json deleted file mode 100644 index e8e8f15..0000000 --- a/packages/client/public/data.example.json +++ /dev/null @@ -1,169 +0,0 @@ -{ - "schemaVersion": 1, - "exportedAt": "2026-08-05T12:00:00.000Z", - "sessions": [ - { - "id": "demo-build", - "createdAt": "2026-08-05T10:10:00.000Z", - "cwd": "/Users/allure/Desktop/demo-app", - "parentSessionId": null, - "metadata": { - "mode": "build", - "objective": "为仪表盘增加搜索过滤" - }, - "stats": { - "messageCount": 4, - "cachedTokens": 1200, - "uncachedTokens": 860, - "totalTokens": 2060, - "costTotal": 0.04 - }, - "entries": [ - { - "seq": 1, - "id": "e-user-1", - "parentId": null, - "type": "user", - "role": "user", - "timestamp": "2026-08-05T10:10:00.000Z", - "text": "给仪表盘加一个搜索框,按任务状态过滤列表。", - "payload": { - "content": "给仪表盘加一个搜索框,按任务状态过滤列表。", - "tags": ["task-input"] - } - }, - { - "seq": 2, - "id": "e-assistant-1", - "parentId": "e-user-1", - "type": "assistant", - "role": "assistant", - "timestamp": "2026-08-05T10:10:12.000Z", - "text": "我会先读取现有仪表盘组件,找出状态字段和列表渲染位置,再补充搜索过滤。", - "payload": { - "content": "我会先读取现有仪表盘组件,找出状态字段和列表渲染位置,再补充搜索过滤。", - "tags": ["model-response"] - } - }, - { - "seq": 3, - "id": "e-tool-1", - "parentId": "e-assistant-1", - "type": "tool", - "role": "tool", - "timestamp": "2026-08-05T10:10:18.000Z", - "tool": "read_file", - "text": "{\"path\":\"src/pages/dashboard.tsx\"}\nsuccess", - "payload": { - "content": "{\"path\":\"src/pages/dashboard.tsx\"}\nsuccess", - "tool": "read_file", - "tags": ["tool-result", "read_file"] - } - }, - { - "seq": 4, - "id": "e-assistant-2", - "parentId": "e-tool-1", - "type": "assistant", - "role": "assistant", - "timestamp": "2026-08-05T10:10:30.000Z", - "text": "已完成搜索框和状态过滤,列表会按状态字段实时过滤。", - "payload": { - "content": "已完成搜索框和状态过滤,列表会按状态字段实时过滤。", - "tags": ["model-response"] - } - } - ], - "records": [ - { - "seq": 3, - "id": "r-tool-1", - "lane": "run", - "runId": "demo-build", - "type": "tool_call", - "opKind": "read_file", - "timestamp": "2026-08-05T10:10:18.000Z", - "payload": { - "tool": "read_file", - "path": "src/pages/dashboard.tsx" - } - } - ], - "facts": [ - { - "seq": 1, - "kind": "task-objective", - "key": "objective", - "value": "为仪表盘增加搜索过滤" - } - ] - }, - { - "id": "demo-plan", - "createdAt": "2026-08-04T09:20:00.000Z", - "cwd": "/Users/allure/Desktop/call-code", - "parentSessionId": null, - "metadata": { - "mode": "plan", - "objective": "评估 GitHub Pages 静态发布方案" - }, - "stats": { - "messageCount": 3, - "cachedTokens": 900, - "uncachedTokens": 640, - "totalTokens": 1540, - "costTotal": 0.02 - }, - "entries": [ - { - "seq": 1, - "id": "e-user-p1", - "parentId": null, - "type": "user", - "role": "user", - "timestamp": "2026-08-04T09:20:00.000Z", - "text": "梳理 GitHub Pages 部署路径和需要提交的静态文件。", - "payload": { - "content": "梳理 GitHub Pages 部署路径和需要提交的静态文件。", - "tags": ["task-input"] - } - }, - { - "seq": 2, - "id": "e-assistant-p1", - "parentId": "e-user-p1", - "type": "assistant", - "role": "assistant", - "timestamp": "2026-08-04T09:20:08.000Z", - "text": "可以使用 GitHub Actions 将 packages/client 发布到 Pages,数据由 pnpm export:web 生成并提交。", - "payload": { - "content": "可以使用 GitHub Actions 将 packages/client 发布到 Pages,数据由 pnpm export:web 生成并提交。", - "tags": ["model-response"] - } - }, - { - "seq": 3, - "id": "e-assistant-p2", - "parentId": "e-assistant-p1", - "type": "assistant", - "role": "assistant", - "timestamp": "2026-08-04T09:20:16.000Z", - "text": "计划完成,确认后进入 BUILD 模式部署工作流。", - "payload": { - "content": "计划完成,确认后进入 BUILD 模式部署工作流。", - "tags": ["model-response"] - } - } - ], - "records": [], - "facts": [ - { - "seq": 1, - "kind": "task-objective", - "key": "objective", - "value": "评估 GitHub Pages 静态发布方案" - } - ] - } - ] -} diff --git a/packages/client/src/App.tsx b/packages/client/src/App.tsx index 81fc869..99e5120 100644 --- a/packages/client/src/App.tsx +++ b/packages/client/src/App.tsx @@ -2,7 +2,7 @@ import { useEffect, useMemo, useState } from 'react'; import { HeaderBar } from './components/HeaderBar'; import { Sidebar } from './components/Sidebar'; import { MainPanel } from './components/MainPanel'; -import { loadWebExport } from './data'; +import { connectLiveExport } from './ws'; import type { Filter, Theme, WebExport } from './types'; import { filterSessions } from './utils'; @@ -26,26 +26,45 @@ export default function App() { useEffect(() => { let cancelled = false; - loadWebExport().then((result) => { + const connection = connectLiveExport({ + onSnapshot: (result) => { + if (cancelled) { + return; + } + + setData(result); + setLoadState('ready'); + setActiveId((current) => { + const requestedId = new URLSearchParams(window.location.search).get( + 'session', + ); + const candidates = [ + requestedId, + current, + result.sessions[0]?.id ?? null, + ]; + return ( + candidates.find( + (id) => + id !== null && + id !== undefined && + result.sessions.some((session) => session.id === id), + ) ?? null + ); + }); + }, + }); + + connection.ready.then((result) => { if (cancelled) { return; } - - setData(result); - const requestedId = new URLSearchParams(window.location.search).get( - 'session', - ); - setActiveId( - requestedId && - result?.sessions.some((session) => session.id === requestedId) - ? requestedId - : (result?.sessions[0]?.id ?? null), - ); setLoadState(result ? 'ready' : 'error'); }); return () => { cancelled = true; + connection.close(); }; }, []); diff --git a/packages/client/src/data.ts b/packages/client/src/data.ts deleted file mode 100644 index e300181..0000000 --- a/packages/client/src/data.ts +++ /dev/null @@ -1,58 +0,0 @@ -import type { WebExport, WebSession } from './types'; - -const DEFAULT_DATA_URLS = ['./data.json', './data.example.json']; - -const resolveDataUrls = (): string[] => { - const params = new URLSearchParams(window.location.search); - const override = params.get('data') || params.get('dataUrl'); - return override ? [override, ...DEFAULT_DATA_URLS] : DEFAULT_DATA_URLS; -}; - -const isWebSession = (value: unknown): value is WebSession => { - if (!value || typeof value !== 'object') { - return false; - } - - const session = value as Partial; - return ( - typeof session.id === 'string' && - typeof session.createdAt === 'string' && - typeof session.cwd === 'string' && - Array.isArray(session.entries) - ); -}; - -const isWebExport = (value: unknown): value is WebExport => { - if (!value || typeof value !== 'object') { - return false; - } - - const data = value as Partial; - return ( - data.schemaVersion === 1 && - typeof data.exportedAt === 'string' && - Array.isArray(data.sessions) && - data.sessions.every(isWebSession) - ); -}; - -export const loadWebExport = async (): Promise => { - for (const url of resolveDataUrls()) { - try { - const target = new URL(url, window.location.href); - const response = await fetch(target, { cache: 'no-cache' }); - if (!response.ok) { - continue; - } - - const value: unknown = await response.json(); - if (isWebExport(value)) { - return value; - } - } catch { - // 继续尝试下一个数据源 - } - } - - return null; -}; diff --git a/packages/client/src/ws.ts b/packages/client/src/ws.ts new file mode 100644 index 0000000..83a3b0f --- /dev/null +++ b/packages/client/src/ws.ts @@ -0,0 +1,239 @@ +import type { WebExport, WebSession } from './types'; + +const DEFAULT_WS_PATH = '/ws'; +const DEFAULT_TIMEOUT_MS = 8000; +const DEFAULT_REFRESH_MS = 5000; + +const isWebSession = (value: unknown): value is WebSession => { + if (!value || typeof value !== 'object') { + return false; + } + + const session = value as Partial; + return ( + typeof session.id === 'string' && + typeof session.createdAt === 'string' && + typeof session.cwd === 'string' && + Array.isArray(session.entries) + ); +}; + +export const isWebExport = (value: unknown): value is WebExport => { + if (!value || typeof value !== 'object') { + return false; + } + + const data = value as Partial; + return ( + data.schemaVersion === 1 && + typeof data.exportedAt === 'string' && + Array.isArray(data.sessions) && + data.sessions.every(isWebSession) + ); +}; + +/** 从服务端消息中提取会话快照,类型不符或结构非法时返回 null。 */ +export const parseSnapshotMessage = (value: unknown): WebExport | null => { + if (!value || typeof value !== 'object') { + return null; + } + + const message = value as { type?: unknown; data?: unknown }; + if (message.type !== 'sessions.snapshot') { + return null; + } + return isWebExport(message.data) ? message.data : null; +}; + +const resolveWsUrl = (override?: string): string => { + if (override) { + return override; + } + + const params = new URLSearchParams(window.location.search); + const fromQuery = params.get('ws') ?? params.get('wsUrl'); + if (fromQuery) { + return fromQuery; + } + + const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; + return `${protocol}//${window.location.host}${DEFAULT_WS_PATH}`; +}; + +export interface LiveExportOptions { + url?: string; + timeoutMs?: number; + refreshMs?: number; + onSnapshot: (data: WebExport) => void; +} + +export interface LiveExportConnection { + ready: Promise; + close(): void; +} + +/** + * 连接 WebSocket 会话服务:连接成功后立即拉取快照,之后按 refreshMs 周期性刷新。 + * 断开时自动退避重连,close 可彻底关闭。 + */ +export const connectLiveExport = ( + options: LiveExportOptions, +): LiveExportConnection => { + const { + onSnapshot, + url, + timeoutMs = DEFAULT_TIMEOUT_MS, + refreshMs = DEFAULT_REFRESH_MS, + } = options; + + let closed = false; + let socket: WebSocket | null = null; + let failTimer: ReturnType | null = null; + let refreshTimer: ReturnType | null = null; + let retryTimer: ReturnType | null = null; + let attempt = 0; + let readySettled = false; + let resolveReady: (value: WebExport | null) => void = () => undefined; + + const ready = new Promise((resolve) => { + resolveReady = resolve; + }); + + const settleReady = (value: WebExport | null) => { + if (readySettled) { + return; + } + readySettled = true; + resolveReady(value); + }; + + const clearTimers = () => { + if (failTimer) { + clearTimeout(failTimer); + } + if (refreshTimer) { + clearTimeout(refreshTimer); + } + if (retryTimer) { + clearTimeout(retryTimer); + } + failTimer = null; + refreshTimer = null; + retryTimer = null; + }; + + const teardownSocket = () => { + clearTimers(); + if (!socket) { + return; + } + + const current = socket; + socket = null; + current.onopen = null; + current.onmessage = null; + current.onerror = null; + current.onclose = null; + current.close(); + }; + + const scheduleRefresh = () => { + if (closed) { + return; + } + refreshTimer = setTimeout(() => { + socket?.send(JSON.stringify({ type: 'sessions.list' })); + scheduleRefresh(); + }, refreshMs); + }; + + const scheduleReconnect = () => { + if (closed) { + return; + } + + const delay = Math.min(1000 * 2 ** attempt, 15000); + attempt += 1; + retryTimer = setTimeout(() => { + retryTimer = null; + openSocket(); + }, delay); + }; + + const armTimeout = () => { + if (failTimer) { + clearTimeout(failTimer); + } + failTimer = setTimeout(() => { + teardownSocket(); + settleReady(null); + scheduleReconnect(); + }, timeoutMs); + }; + + const openSocket = () => { + if (closed) { + return; + } + + let current: WebSocket; + try { + current = new WebSocket(resolveWsUrl(url)); + } catch { + scheduleReconnect(); + return; + } + socket = current; + armTimeout(); + + current.onopen = () => { + attempt = 0; + current.send(JSON.stringify({ type: 'sessions.list' })); + scheduleRefresh(); + }; + + current.onmessage = (event) => { + let parsed: unknown; + try { + parsed = JSON.parse(String(event.data)); + } catch { + return; + } + + const data = parseSnapshotMessage(parsed); + if (!data) { + return; + } + + armTimeout(); + onSnapshot(data); + settleReady(data); + }; + + current.onerror = () => { + // 关闭事件统一负责清理与重连 + }; + + current.onclose = () => { + if (socket !== current) { + return; + } + teardownSocket(); + settleReady(null); + if (!closed) { + scheduleReconnect(); + } + }; + }; + + openSocket(); + + return { + ready, + close() { + closed = true; + clearTimers(); + teardownSocket(); + }, + }; +}; diff --git a/packages/client/vite.config.ts b/packages/client/vite.config.ts index 35dde7f..5e1099f 100644 --- a/packages/client/vite.config.ts +++ b/packages/client/vite.config.ts @@ -7,6 +7,15 @@ export default defineConfig({ root: fileURLToPath(new URL('.', import.meta.url)), plugins: [react(), tailwindcss()], base: './', + server: { + proxy: { + // 开发模式下把 WebSocket 请求转发给 web:serve 会话服务 + '/ws': { + target: 'ws://127.0.0.1:4173', + ws: true, + }, + }, + }, build: { outDir: 'dist', emptyOutDir: true, diff --git a/source/web-server.ts b/source/web-server.ts new file mode 100644 index 0000000..76de6f9 --- /dev/null +++ b/source/web-server.ts @@ -0,0 +1,27 @@ +import { SessionStore } from '../packages/session-sqlite/src/index'; +import { DEFAULT_DB_PATH } from '../packages/session-sqlite/src/store'; +import { startWebServer } from '@web/server'; + +const main = async () => { + const dbPath = process.env.SESSION_DB_PATH ?? DEFAULT_DB_PATH; + const store = new SessionStore({ dbPath }); + const port = Number(process.env.CALL_CODE_WEB_PORT ?? 4173); + const handle = await startWebServer({ store, port }); + + const shutdown = async () => { + await handle.close(); + store.close(); + process.exit(0); + }; + process.on('SIGINT', shutdown); + process.on('SIGTERM', shutdown); + + console.log(`Web 会话面板已启动: http://127.0.0.1:${handle.port}`); +}; + +main().catch((error) => { + console.error( + `启动失败: ${error instanceof Error ? error.message : String(error)}`, + ); + process.exit(1); +}); diff --git a/tests/client-ws.spec.ts b/tests/client-ws.spec.ts new file mode 100644 index 0000000..f4f3ec2 --- /dev/null +++ b/tests/client-ws.spec.ts @@ -0,0 +1,83 @@ +import { afterEach, describe, expect, it } from 'vitest'; +import { SessionStore } from '../packages/session-sqlite/src/index'; +import type { WebExport } from '../packages/client/src/types'; +import { + connectLiveExport, + parseSnapshotMessage, +} from '../packages/client/src/ws'; +import { + startWebServer, + type WebServerHandle, +} from '../packages/agent-core/src/web/server'; + +const stores: SessionStore[] = []; +const handles: WebServerHandle[] = []; + +const createServer = async () => { + const store = new SessionStore({ dbPath: ':memory:' }); + stores.push(store); + const handle = await startWebServer({ store, port: 0 }); + handles.push(handle); + return { store, handle }; +}; + +afterEach(async () => { + for (const handle of handles.splice(0)) { + await handle.close(); + } + for (const store of stores.splice(0)) { + store.close(); + } +}); + +describe('客户端 WebSocket 适配', () => { + it('解析合法的 sessions.snapshot 消息', () => { + const data: WebExport = { + schemaVersion: 1, + exportedAt: '2026-08-23T00:00:00.000Z', + sessions: [], + }; + + expect(parseSnapshotMessage({ type: 'sessions.snapshot', data })).toEqual( + data, + ); + expect(parseSnapshotMessage({ type: 'other', data })).toBeNull(); + expect( + parseSnapshotMessage({ + type: 'sessions.snapshot', + data: { schemaVersion: 2, exportedAt: '', sessions: [] }, + }), + ).toBeNull(); + }); + + it('连接服务后收到快照并周期性刷新', async () => { + const { store, handle } = await createServer(); + store.createSession({ cwd: '/tmp/project', id: 's-client' }); + store.appendEntry('s-client', { + id: 'e1', + type: 'user', + payload: { role: 'user', content: 'ping' }, + }); + + const snapshots: WebExport[] = []; + const connection = connectLiveExport({ + url: `ws://127.0.0.1:${handle.port}/ws`, + timeoutMs: 3000, + refreshMs: 80, + onSnapshot: (data) => snapshots.push(data), + }); + + const first = await connection.ready; + expect(first).not.toBeNull(); + expect(first?.sessions[0].id).toBe('s-client'); + expect(snapshots).toHaveLength(1); + + const deadline = Date.now() + 2000; + while (snapshots.length < 2 && Date.now() < deadline) { + await new Promise((resolve) => setTimeout(resolve, 30)); + } + expect(snapshots.length).toBeGreaterThan(1); + + connection.close(); + }); +}); diff --git a/tests/web-server.spec.ts b/tests/web-server.spec.ts new file mode 100644 index 0000000..724d726 --- /dev/null +++ b/tests/web-server.spec.ts @@ -0,0 +1,130 @@ +import { afterEach, describe, expect, it } from 'vitest'; +import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { join } from 'node:path'; +import { WebSocket } from 'ws'; +import { SessionStore } from '../packages/session-sqlite/src/index'; +import type { WebExport } from '../packages/agent-core/src/web/export'; +import { + startWebServer, + type WebServerHandle, +} from '../packages/agent-core/src/web/server'; + +const stores: SessionStore[] = []; +const handles: WebServerHandle[] = []; + +const createServer = async (clientDir?: string) => { + const store = new SessionStore({ dbPath: ':memory:' }); + stores.push(store); + const handle = await startWebServer({ store, port: 0, clientDir }); + handles.push(handle); + return { store, handle }; +}; + +afterEach(async () => { + for (const handle of handles.splice(0)) { + await handle.close(); + } + for (const store of stores.splice(0)) { + store.close(); + } +}); + +const requestSnapshot = (url: string): Promise => + new Promise((resolve, reject) => { + const socket = new WebSocket(url); + const timeout = setTimeout(() => { + socket.terminate(); + reject(new Error('等待会话快照超时')); + }, 3000); + + socket.on('open', () => { + socket.send(JSON.stringify({ type: 'sessions.list' })); + }); + socket.on('message', (raw) => { + const message = JSON.parse(String(raw)) as { + type?: string; + data?: WebExport; + }; + if (message.type === 'sessions.snapshot' && message.data) { + clearTimeout(timeout); + socket.close(); + resolve(message.data); + } + }); + socket.on('error', (error) => { + clearTimeout(timeout); + reject(error); + }); + }); + +describe('WebSocket 会话服务', () => { + it('响应 sessions.list 并返回完整会话快照', async () => { + const { store, handle } = await createServer(); + store.createSession({ cwd: '/tmp/project', id: 's-live' }); + store.appendEntry('s-live', { + id: 'e1', + type: 'user', + payload: { role: 'user', content: 'hello ws' }, + }); + store.updateStats('s-live', { + messageCount: 1, + cachedTokens: 0, + uncachedTokens: 0, + totalTokens: 0, + costTotal: 0, + }); + + const data = await requestSnapshot(`ws://127.0.0.1:${handle.port}/ws`); + + expect(data.schemaVersion).toBe(1); + expect(data.sessions).toHaveLength(1); + expect(data.sessions[0].entries[0].text).toBe('hello ws'); + }); + + it('无法解析的消息返回 error 响应', async () => { + const { handle } = await createServer(); + const message = await new Promise((resolve, reject) => { + const socket = new WebSocket(`ws://127.0.0.1:${handle.port}/ws`); + const timeout = setTimeout(() => { + socket.terminate(); + reject(new Error('等待错误响应超时')); + }, 3000); + + socket.on('open', () => { + socket.send('not json'); + }); + socket.on('message', (raw) => { + clearTimeout(timeout); + socket.close(); + resolve(JSON.parse(String(raw))); + }); + socket.on('error', (error) => { + clearTimeout(timeout); + reject(error); + }); + }); + + expect(message).toMatchObject({ type: 'error' }); + }); + + it('HTTP 服务返回客户端页面并支持 SPA 回退', async () => { + const dir = mkdtempSync(join(tmpdir(), 'call-code-web-client-')); + writeFileSync(join(dir, 'index.html'), '

Call Code Web

'); + + try { + const { handle } = await createServer(dir); + const home = await fetch(`http://127.0.0.1:${handle.port}/`); + expect(home.status).toBe(200); + expect(await home.text()).toContain('Call Code Web'); + + const fallback = await fetch( + `http://127.0.0.1:${handle.port}/some/route`, + ); + expect(fallback.status).toBe(200); + expect(await fallback.text()).toContain('Call Code Web'); + } finally { + rmSync(dir, { recursive: true, force: true }); + } + }); +}); From b778e859b3970d531377375f55f25a8259ebfbfe Mon Sep 17 00:00:00 2001 From: AlkaidSTART <2595006848@qq.com> Date: Sun, 23 Aug 2026 18:37:46 +0800 Subject: [PATCH 04/10] =?UTF-8?q?feat:=20=E9=87=8D=E6=9E=84=20Call=20Code?= =?UTF-8?q?=20=E7=BD=91=E9=A1=B5=E7=95=8C=E9=9D=A2=E4=B8=BB=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/client/src/App.tsx | 12 +- packages/client/src/components/HeaderBar.tsx | 11 +- .../client/src/components/ParticleField.tsx | 26 ++++ packages/client/src/global.css | 137 +++++++++++++----- packages/client/src/types.ts | 2 +- tests/client-ui.spec.ts | 4 +- 6 files changed, 143 insertions(+), 49 deletions(-) create mode 100644 packages/client/src/components/ParticleField.tsx diff --git a/packages/client/src/App.tsx b/packages/client/src/App.tsx index 99e5120..e2c52c9 100644 --- a/packages/client/src/App.tsx +++ b/packages/client/src/App.tsx @@ -5,12 +5,15 @@ import { MainPanel } from './components/MainPanel'; import { connectLiveExport } from './ws'; import type { Filter, Theme, WebExport } from './types'; import { filterSessions } from './utils'; +import { ParticleField } from './components/ParticleField'; const THEME_KEY = 'call-code-theme'; const initialTheme = (): Theme => { const stored = localStorage.getItem(THEME_KEY); - return stored === 'light' ? 'light' : 'dark'; + return stored === 'clear' || stored === 'frosted' || stored === 'apricot' + ? stored + : 'frosted'; }; export default function App() { @@ -70,8 +73,10 @@ export default function App() { useEffect(() => { const root = document.documentElement; - root.classList.toggle('dark', theme === 'dark'); - localStorage.setItem(THEME_KEY, theme); + const resolvedTheme = theme === 'light' ? 'frosted' : theme === 'dark' ? 'apricot' : theme; + root.classList.remove('dark'); + root.dataset.theme = resolvedTheme; + localStorage.setItem(THEME_KEY, resolvedTheme); }, [theme]); const sessions = useMemo(() => data?.sessions ?? [], [data]); @@ -115,6 +120,7 @@ export default function App() { return (
+
+
LIVE SESSION ARCHIVE

Call Code

{sessions.length} 个会话 · {count.messages} 条消息 · {count.tools}{' '} @@ -49,8 +50,8 @@ export function HeaderBar({ sessions, theme, onThemeChange }: HeaderBarProps) {
-
- {(['light', 'dark'] as const).map((value) => ( +
+ {(['clear', 'frosted', 'apricot'] as const).map((value) => ( ))}
diff --git a/packages/client/src/components/ParticleField.tsx b/packages/client/src/components/ParticleField.tsx new file mode 100644 index 0000000..82aedf1 --- /dev/null +++ b/packages/client/src/components/ParticleField.tsx @@ -0,0 +1,26 @@ +const particles = [ + ['call', 'particle--one'], + ['<>', 'particle--two'], + ['code', 'particle--three'], + ['/', 'particle--four'], + ['cc', 'particle--five'], + ['{ }', 'particle--six'], + ['call', 'particle--seven'], + [';', 'particle--eight'], + ['code', 'particle--nine'], + ['//', 'particle--ten'], + ['()', 'particle--eleven'], + ['cc', 'particle--twelve'], +] as const; + +export function ParticleField() { + return ( + + ); +} diff --git a/packages/client/src/global.css b/packages/client/src/global.css index 60c2e72..f4dd065 100644 --- a/packages/client/src/global.css +++ b/packages/client/src/global.css @@ -1,7 +1,5 @@ @import 'tailwindcss'; -@custom-variant dark (&:where(.dark, .dark *)); - :root { color-scheme: light; --font-ui: @@ -11,17 +9,17 @@ 'SF Mono', ui-monospace, 'JetBrains Mono', 'Menlo', 'Consolas', monospace; /* 基底背景 */ - --bg-a: #f3f4f7; - --bg-b: #fbfbfd; + --bg-a: #dfe6e6; + --bg-b: #f5f5f1; /* 中性光晕,仅保留极淡的层次感 */ - --glow-1: 148 148 158; - --glow-2: 148 148 158; - --glow-3: 148 148 158; + --glow-1: 75 111 109; + --glow-2: 169 119 92; + --glow-3: 100 125 132; /* 毛玻璃面板 */ - --panel-bg: 255 255 255 / 0.42; - --panel-border: 145 145 155 / 0.14; + --panel-bg: 255 255 255 / 0.3; + --panel-border: 255 255 255 / 0.46; --panel-shadow: 0 1px 0 rgb(255 255 255 / 0.75) inset, 0 1px 3px rgb(17 24 39 / 0.06), 0 20px 50px -16px rgb(17 24 39 / 0.1); @@ -39,7 +37,7 @@ /* 文字 */ --accent: #111827; --accent-soft: rgb(17 24 39 / 0.07); - --text-primary: #18181b; + --text-primary: #182322; --text-secondary: #52525b; --text-tertiary: #8e8e93; @@ -56,40 +54,47 @@ 0 1px 3px rgb(17 24 39 / 0.08), 0 4px 12px -4px rgb(17 24 39 / 0.08); } -:root.dark { - color-scheme: dark; +:root[data-theme='clear'] { + --panel-bg: 255 255 255 / 0.14; + --panel-border: 255 255 255 / 0.34; + --chip-bg: 255 255 255 / 0.18; + --bg-a: #c9d5d5; + --bg-b: #eef2ef; +} - --bg-a: #0a0a0c; - --bg-b: #111114; +:root[data-theme='apricot'] { + color-scheme: dark; + --bg-a: #e5c1a4; + --bg-b: #f5e8d7; - --glow-1: 138 138 146; - --glow-2: 138 138 146; - --glow-3: 138 138 146; + --glow-1: 165 105 72; + --glow-2: 119 83 59; + --glow-3: 208 137 86; - --panel-bg: 18 18 22 / 0.52; - --panel-border: 255 255 255 / 0.1; + --panel-bg: 255 247 236 / 0.38; + --panel-border: 255 255 255 / 0.48; --panel-shadow: 0 1px 0 rgb(255 255 255 / 0.04) inset, 0 1px 3px rgb(0 0 0 / 0.45), 0 40px 80px -20px rgb(0 0 0 / 0.55); - --sidebar-active: 255 255 255 / 0.12; + --sidebar-active: 255 255 255 / 0.58; --sidebar-active-shadow: 0 1px 0 rgb(255 255 255 / 0.05) inset, 0 8px 28px -6px rgb(0 0 0 / 0.6); --sidebar-hover: 255 255 255 / 0.07; - --chip-bg: 255 255 255 / 0.06; - --chip-border: 255 255 255 / 0.1; + --chip-bg: 255 247 236 / 0.32; + --chip-border: 124 79 50 / 0.14; - --accent: #f4f4f5; - --accent-soft: rgb(244 244 245 / 0.1); - --text-primary: #f4f4f5; - --text-secondary: #a1a1aa; - --text-tertiary: #6f6f76; + --accent: #5f3825; + --accent-soft: rgb(95 56 37 / 0.1); + --text-primary: #40281d; + --text-secondary: #765644; + --text-tertiary: #a27c65; - --role-user: #d4d4d8; - --role-assistant: #a1a1aa; - --role-tool: #71717a; - --role-system: #52525b; + --role-user: #9b684c; + --role-assistant: #805037; + --role-tool: #bd7d54; + --role-system: #b28e78; --segment-active: 255 255 255 / 0.12; --segment-active-text: #fafafa; @@ -98,6 +103,8 @@ 0 4px 14px -6px rgb(0 0 0 / 0.5); } +:root[data-theme='frosted'] { color-scheme: light; } + html { font-family: var(--font-ui); text-rendering: optimizeLegibility; @@ -118,7 +125,10 @@ body { /* 中性背景,让毛玻璃面板保持透明层次 */ body { - background: linear-gradient(180deg, var(--bg-a), var(--bg-b)); + background: + radial-gradient(circle at 12% 18%, rgb(var(--glow-1) / 0.12), transparent 24rem), + radial-gradient(circle at 86% 82%, rgb(var(--glow-2) / 0.1), transparent 28rem), + linear-gradient(135deg, var(--bg-a), var(--bg-b)); background-attachment: fixed; } @@ -126,12 +136,12 @@ body { .app-shell { position: relative; min-height: 100vh; - padding: 12px 12px 20px; + padding: 18px 14px 28px; } @media (min-width: 1024px) { .app-shell { - padding: 16px 20px 24px; + padding: 28px 32px 42px; } } @@ -147,6 +157,40 @@ body { z-index: 0; } +.particle-field { + position: fixed; + inset: 0; + overflow: hidden; + pointer-events: none; + z-index: 0; +} + +.particle { + position: absolute; + color: rgb(var(--glow-1) / 0.2); + font-family: var(--font-mono); + font-size: 10px; + animation: drift 16s ease-in-out infinite; +} + +.particle--one { left: 8%; top: 20%; animation-delay: -2s; } +.particle--two { left: 18%; top: 76%; animation-duration: 20s; } +.particle--three { left: 35%; top: 10%; animation-delay: -8s; } +.particle--four { left: 48%; top: 84%; animation-duration: 18s; } +.particle--five { left: 62%; top: 26%; animation-delay: -5s; } +.particle--six { left: 73%; top: 72%; animation-duration: 22s; } +.particle--seven { left: 88%; top: 14%; animation-delay: -11s; } +.particle--eight { left: 93%; top: 56%; animation-duration: 19s; } +.particle--nine { left: 4%; top: 52%; animation-delay: -14s; } +.particle--ten { left: 28%; top: 42%; animation-duration: 21s; } +.particle--eleven { left: 79%; top: 44%; animation-delay: -7s; } +.particle--twelve { left: 56%; top: 62%; animation-duration: 17s; } + +@keyframes drift { + 0%, 100% { transform: translate3d(0, 8px, 0); opacity: 0.18; } + 50% { transform: translate3d(12px, -14px, 0); opacity: 0.42; } +} + /* 整体框架:顶栏与工作区收进同一个毛玻璃容器 */ .app-frame { display: flex; @@ -154,11 +198,11 @@ body { position: relative; z-index: 1; width: 100%; - max-width: 1480px; - min-height: calc(100vh - 28px); + max-width: 1540px; + min-height: calc(100vh - 46px); margin: 0 auto; overflow: hidden; - border-radius: 16px; + border-radius: 22px; border: 1px solid rgb(var(--panel-border)); background: rgb(var(--panel-bg)); box-shadow: var(--panel-shadow); @@ -178,11 +222,19 @@ body { align-items: center; justify-content: space-between; gap: 12px; - padding: 10px 14px; + padding: 15px 18px; border-bottom: 1px solid rgb(var(--panel-border)); background: rgb(var(--chip-bg)); } +.brand-kicker { + margin-bottom: 3px; + color: rgb(var(--glow-1) / 0.8); + font-family: var(--font-mono); + font-size: 9px; + letter-spacing: 0.08em; +} + @media (min-width: 1024px) { .header-bar { padding: 12px 18px; @@ -270,6 +322,8 @@ body { box-shadow: var(--segment-active-shadow); } +.theme-switcher button { min-width: 52px; } + /* 等宽字体 */ .mono { font-family: var(--font-mono); @@ -308,12 +362,17 @@ body { /* 消息气泡 */ .msg-bubble { - border-radius: 12px; + border-radius: 15px; border: 1px solid rgb(var(--chip-border)); background: rgb(var(--chip-bg)); backdrop-filter: blur(8px); } +@media (prefers-reduced-motion: reduce) { + .particle { animation: none; } + *, *::before, *::after { scroll-behavior: auto !important; transition-duration: 0.01ms !important; } +} + .msg-bubble--user { border-left: 2px solid var(--role-user); } diff --git a/packages/client/src/types.ts b/packages/client/src/types.ts index 02c4453..8367637 100644 --- a/packages/client/src/types.ts +++ b/packages/client/src/types.ts @@ -1,4 +1,4 @@ -export type Theme = 'light' | 'dark'; +export type Theme = 'clear' | 'frosted' | 'apricot' | 'light' | 'dark'; export type EntryRole = 'user' | 'assistant' | 'tool' | 'system'; diff --git a/tests/client-ui.spec.ts b/tests/client-ui.spec.ts index 9d894f5..98b1669 100644 --- a/tests/client-ui.spec.ts +++ b/tests/client-ui.spec.ts @@ -61,7 +61,9 @@ describe('client HeaderBar', () => { expect(html).toContain('1 个会话'); expect(html).toContain('2 条消息'); expect(html).toContain('1 次工具'); - expect(html).toContain('高级黑'); + expect(html).toContain('透明玻璃'); + expect(html).toContain('毛玻璃'); + expect(html).toContain('杏色毛玻璃'); }); it('统计按多个会话累加', () => { From e8b3b1568cb2ad7a4dd206ce40da29757c52293c Mon Sep 17 00:00:00 2001 From: AlkaidSTART <2595006848@qq.com> Date: Sun, 23 Aug 2026 18:43:55 +0800 Subject: [PATCH 05/10] feat: update connection state handling in HeaderBar and App components - Removed loading and error states from App component rendering. - Added connectionState prop to HeaderBar to display connection status. - Implemented visual indicators for connection state in HeaderBar. - Enhanced global styles for connection state indicators. - Added a test case to verify HeaderBar displays correct state when service is not connected. --- .../client/dist/assets/index-B7QVdr3Y.css | 2 -- packages/client/dist/assets/index-BVFN01-c.js | 9 ----- packages/client/dist/index.html | 4 +-- packages/client/src/App.tsx | 27 +-------------- packages/client/src/components/HeaderBar.tsx | 16 ++++++++- packages/client/src/global.css | 33 ++++++++++++++++++- tests/client-ui.spec.ts | 15 +++++++++ 7 files changed, 65 insertions(+), 41 deletions(-) delete mode 100644 packages/client/dist/assets/index-B7QVdr3Y.css delete mode 100644 packages/client/dist/assets/index-BVFN01-c.js diff --git a/packages/client/dist/assets/index-B7QVdr3Y.css b/packages/client/dist/assets/index-B7QVdr3Y.css deleted file mode 100644 index 90b57dc..0000000 --- a/packages/client/dist/assets/index-B7QVdr3Y.css +++ /dev/null @@ -1,2 +0,0 @@ -/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */ -@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--spacing:.25rem;--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-medium:500;--font-weight-semibold:600;--tracking-wider:.05em;--leading-tight:1.25;--leading-snug:1.375;--leading-relaxed:1.625;--radius-lg:.5rem;--radius-xl:.75rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.relative{position:relative}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.m-0{margin:0}.mx-auto{margin-inline:auto}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-8{margin-top:calc(var(--spacing) * 8)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.ml-auto{margin-left:auto}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.flex{display:flex}.grid{display:grid}.h-4{height:calc(var(--spacing) * 4)}.h-8{height:calc(var(--spacing) * 8)}.h-9{height:calc(var(--spacing) * 9)}.h-full{height:100%}.max-h-40{max-height:calc(var(--spacing) * 40)}.max-h-\[50vh\]{max-height:50vh}.max-h-\[480px\]{max-height:480px}.min-h-0{min-height:0}.min-h-\[60vh\]{min-height:60vh}.min-h-\[120px\]{min-height:120px}.min-h-\[200px\]{min-height:200px}.w-1{width:var(--spacing)}.w-9{width:calc(var(--spacing) * 9)}.w-full{width:100%}.max-w-\[240px\]{max-width:240px}.max-w-\[760px\]{max-width:760px}.min-w-0{min-width:0}.flex-1{flex:1}.shrink-0{flex-shrink:0}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-y-auto{overflow-y:auto}.rounded-full{border-radius:2147483647px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.bg-transparent{background-color:#0000}.object-contain{object-fit:contain}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.\!py-0{padding-block:0!important}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-6{padding-block:calc(var(--spacing) * 6)}.pt-1\.5{padding-top:calc(var(--spacing) * 1.5)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pt-5{padding-top:calc(var(--spacing) * 5)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.text-left{text-align:left}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.\!text-\[10px\]{font-size:10px!important}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-\[13\.5px\]{font-size:13.5px}.text-\[13px\]{font-size:13px}.text-\[15px\]{font-size:15px}.text-\[17px\]{font-size:17px}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.leading-tight{--tw-leading:var(--leading-tight);line-height:var(--leading-tight)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.break-words{overflow-wrap:break-word}.whitespace-pre-wrap{white-space:pre-wrap}.uppercase{text-transform:uppercase}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.outline-none{--tw-outline-style:none;outline-style:none}@media (width>=40rem){.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (width>=64rem){.lg\:max-h-none{max-height:none}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}}:root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--font-ui:"SF Pro Text", "PingFang SC", "Hiragino Sans GB", "Source Han Sans SC", "Microsoft YaHei", sans-serif;--font-mono:"SF Mono", ui-monospace, "JetBrains Mono", "Menlo", "Consolas", monospace;--bg-a:#f3f4f7;--bg-b:#fbfbfd;--glow-1:148 148 158;--glow-2:148 148 158;--glow-3:148 148 158;--panel-bg:255 255 255 / .42;--panel-border:145 145 155 / .14;--panel-shadow:0 1px 0 #ffffffbf inset, 0 1px 3px #1118270f, 0 20px 50px -16px #1118271a;--sidebar-active:255 255 255 / .88;--sidebar-active-shadow:0 1px 3px #11182712, 0 8px 24px -6px #1118271f;--sidebar-hover:255 255 255 / .45;--chip-bg:255 255 255 / .46;--chip-border:145 145 155 / .12;--accent:#111827;--accent-soft:#11182712;--text-primary:#18181b;--text-secondary:#52525b;--text-tertiary:#8e8e93;--role-user:#71717a;--role-assistant:#52525b;--role-tool:#3f3f46;--role-system:#a1a1aa;--segment-active:255 255 255 / .92;--segment-active-text:#18181b;--segment-active-shadow:0 1px 3px #11182714, 0 4px 12px -4px #11182714}:root.dark{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--bg-a:#0a0a0c;--bg-b:#111114;--glow-1:138 138 146;--glow-2:138 138 146;--glow-3:138 138 146;--panel-bg:18 18 22 / .52;--panel-border:255 255 255 / .1;--panel-shadow:0 1px 0 #ffffff0a inset, 0 1px 3px #00000073, 0 40px 80px -20px #0000008c;--sidebar-active:255 255 255 / .12;--sidebar-active-shadow:0 1px 0 #ffffff0d inset, 0 8px 28px -6px #0009;--sidebar-hover:255 255 255 / .07;--chip-bg:255 255 255 / .06;--chip-border:255 255 255 / .1;--accent:#f4f4f5;--accent-soft:#f4f4f51a;--text-primary:#f4f4f5;--text-secondary:#a1a1aa;--text-tertiary:#6f6f76;--role-user:#d4d4d8;--role-assistant:#a1a1aa;--role-tool:#71717a;--role-system:#52525b;--segment-active:255 255 255 / .12;--segment-active-text:#fafafa;--segment-active-shadow:0 1px 0 #ffffff0d inset, 0 1px 3px #00000073, 0 4px 14px -6px #00000080}html{font-family:var(--font-ui);text-rendering:optimizelegibility;-webkit-font-smoothing:antialiased;font-feature-settings:"ss01", "cv11"}body{min-height:100vh;color:var(--text-primary);margin:0}*{scrollbar-width:thin;scrollbar-color:rgb(var(--glow-1) / .2) transparent}body{background:linear-gradient(180deg, var(--bg-a), var(--bg-b));background-attachment:fixed}.app-shell{min-height:100vh;padding:12px 12px 20px;position:relative}@media (width>=1024px){.app-shell{padding:16px 20px 24px}}.app-shell:before{content:"";pointer-events:none;opacity:.35;mix-blend-mode:overlay;z-index:0;background-image:url("data:image/svg+xml;utf8,");position:fixed;inset:0}.app-frame{z-index:1;border:1px solid rgb(var(--panel-border));background:rgb(var(--panel-bg));width:100%;max-width:1480px;min-height:calc(100vh - 28px);box-shadow:var(--panel-shadow);-webkit-backdrop-filter:blur(24px)saturate(180%);border-radius:16px;flex-direction:column;margin:0 auto;display:flex;position:relative;overflow:hidden}@media (width>=1024px){.app-frame{height:calc(100vh - 40px)}}.header-bar{border-bottom:1px solid rgb(var(--panel-border));background:rgb(var(--chip-bg));justify-content:space-between;align-items:center;gap:12px;padding:10px 14px;display:flex}@media (width>=1024px){.header-bar{padding:12px 18px}}.app-workspace{flex:1;grid-template-columns:1fr;min-height:0;display:grid}@media (width>=1024px){.app-workspace{grid-template-columns:300px minmax(0,1fr)}}.sidebar-panel,.main-panel{flex-direction:column;min-height:0;display:flex;position:relative;overflow:hidden}.sidebar-panel{border-bottom:1px solid rgb(var(--panel-border));max-height:50vh}@media (width>=1024px){.sidebar-panel{border-right:1px solid rgb(var(--panel-border));border-bottom:0;max-height:none}}.chip{border:1px solid rgb(var(--chip-border));background:rgb(var(--chip-bg));color:var(--text-secondary);white-space:nowrap;-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-radius:999px;align-items:center;gap:5px;padding:2px 9px;font-size:11px;font-weight:500;display:inline-flex}.segmented{border:1px solid rgb(var(--chip-border));background:rgb(var(--chip-bg));-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-radius:10px;padding:3px;display:inline-flex}.segmented button{color:var(--text-secondary);border-radius:7px;padding:4px 10px;font-size:11px;font-weight:500;transition:all .2s}.segmented button:hover{color:var(--text-primary)}.segmented button[aria-pressed=true]{background:rgb(var(--segment-active));color:var(--segment-active-text);box-shadow:var(--segment-active-shadow)}.mono{font-family:var(--font-mono);font-size:12px;line-height:1.55}::selection{background:rgb(var(--glow-1) / .2)}.role-dot{border-radius:50%;flex-shrink:0;width:8px;height:8px;display:block}.role-dot--user{background:var(--role-user);box-shadow:0 0 6px rgb(var(--glow-1) / .4)}.role-dot--assistant{background:var(--role-assistant);box-shadow:0 0 6px rgb(var(--glow-2) / .4)}.role-dot--tool{background:var(--role-tool);box-shadow:0 0 6px 0 rgb(var(--glow-3) / .35)}.role-dot--system{background:var(--role-system)}.msg-bubble{border:1px solid rgb(var(--chip-border));background:rgb(var(--chip-bg));-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-radius:12px}.msg-bubble--user{border-left:2px solid var(--role-user)}.msg-bubble--assistant{border-left:2px solid var(--role-assistant)}.msg-bubble--tool{border-left:2px solid var(--role-tool)}.search-box{transition:border-color .2s,box-shadow .2s}.search-box:focus-within{box-shadow:0 0 0 3px rgb(var(--glow-1) / .08);border-color:rgb(var(--glow-1) / .35)!important}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false} diff --git a/packages/client/dist/assets/index-BVFN01-c.js b/packages/client/dist/assets/index-BVFN01-c.js deleted file mode 100644 index c9f28f6..0000000 --- a/packages/client/dist/assets/index-BVFN01-c.js +++ /dev/null @@ -1,9 +0,0 @@ -var e=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports);(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var t=e((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.consumer`),s=Symbol.for(`react.context`),c=Symbol.for(`react.forward_ref`),l=Symbol.for(`react.suspense`),u=Symbol.for(`react.memo`),d=Symbol.for(`react.lazy`),f=Symbol.for(`react.activity`),p=Symbol.iterator;function m(e){return typeof e!=`object`||!e?null:(e=p&&e[p]||e[`@@iterator`],typeof e==`function`?e:null)}var h={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},g=Object.assign,_={};function v(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}v.prototype.isReactComponent={},v.prototype.setState=function(e,t){if(typeof e!=`object`&&typeof e!=`function`&&e!=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,e,t,`setState`)},v.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,`forceUpdate`)};function y(){}y.prototype=v.prototype;function b(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}var x=b.prototype=new y;x.constructor=b,g(x,v.prototype),x.isPureReactComponent=!0;var ee=Array.isArray;function S(){}var C={H:null,A:null,T:null,S:null},te=Object.prototype.hasOwnProperty;function ne(e,n,r){var i=r.ref;return{$$typeof:t,type:e,key:n,ref:i===void 0?null:i,props:r}}function re(e,t){return ne(e.type,t,e.props)}function w(e){return typeof e==`object`&&!!e&&e.$$typeof===t}function ie(e){var t={"=":`=0`,":":`=2`};return`$`+e.replace(/[=:]/g,function(e){return t[e]})}var ae=/\/+/g;function oe(e,t){return typeof e==`object`&&e&&e.key!=null?ie(``+e.key):t.toString(36)}function se(e){switch(e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason;default:switch(typeof e.status==`string`?e.then(S,S):(e.status=`pending`,e.then(function(t){e.status===`pending`&&(e.status=`fulfilled`,e.value=t)},function(t){e.status===`pending`&&(e.status=`rejected`,e.reason=t)})),e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason}}throw e}function ce(e,r,i,a,o){var s=typeof e;(s===`undefined`||s===`boolean`)&&(e=null);var c=!1;if(e===null)c=!0;else switch(s){case`bigint`:case`string`:case`number`:c=!0;break;case`object`:switch(e.$$typeof){case t:case n:c=!0;break;case d:return c=e._init,ce(c(e._payload),r,i,a,o)}}if(c)return o=o(e),c=a===``?`.`+oe(e,0):a,ee(o)?(i=``,c!=null&&(i=c.replace(ae,`$&/`)+`/`),ce(o,r,i,``,function(e){return e})):o!=null&&(w(o)&&(o=re(o,i+(o.key==null||e&&e.key===o.key?``:(``+o.key).replace(ae,`$&/`)+`/`)+c)),r.push(o)),1;c=0;var l=a===``?`.`:a+`:`;if(ee(e))for(var u=0;u{n.exports=t()})),r=e((e=>{function t(e,t){var n=e.length;e.push(t);a:for(;0>>1,a=e[r];if(0>>1;ri(c,n))li(u,c)?(e[r]=u,e[l]=n,r=l):(e[r]=c,e[s]=n,r=s);else if(li(u,n))e[r]=u,e[l]=n,r=l;else break a}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return n===0?e.id-t.id:n}if(e.unstable_now=void 0,typeof performance==`object`&&typeof performance.now==`function`){var a=performance;e.unstable_now=function(){return a.now()}}else{var o=Date,s=o.now();e.unstable_now=function(){return o.now()-s}}var c=[],l=[],u=1,d=null,f=3,p=!1,m=!1,h=!1,g=!1,_=typeof setTimeout==`function`?setTimeout:null,v=typeof clearTimeout==`function`?clearTimeout:null,y=typeof setImmediate<`u`?setImmediate:null;function b(e){for(var i=n(l);i!==null;){if(i.callback===null)r(l);else if(i.startTime<=e)r(l),i.sortIndex=i.expirationTime,t(c,i);else break;i=n(l)}}function x(e){if(h=!1,b(e),!m){if(n(c)!==null)m=!0,ee||(ee=!0,w());else{var t=n(l);t!==null&&oe(x,t.startTime-e)}}}var ee=!1,S=-1,C=5,te=-1;function ne(){return g?!0:!(e.unstable_now()-tet&&ne());){var o=d.callback;if(typeof o==`function`){d.callback=null,f=d.priorityLevel;var s=o(d.expirationTime<=t);if(t=e.unstable_now(),typeof s==`function`){d.callback=s,b(t),i=!0;break b}d===n(c)&&r(c),b(t)}else r(c);d=n(c)}if(d!==null)i=!0;else{var u=n(l);u!==null&&oe(x,u.startTime-t),i=!1}}break a}finally{d=null,f=a,p=!1}}}finally{i?w():ee=!1}}}var w;if(typeof y==`function`)w=function(){y(re)};else if(typeof MessageChannel<`u`){var ie=new MessageChannel,ae=ie.port2;ie.port1.onmessage=re,w=function(){ae.postMessage(null)}}else w=function(){_(re,0)};function oe(t,n){S=_(function(){t(e.unstable_now())},n)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(e){e.callback=null},e.unstable_forceFrameRate=function(e){0>e||125o?(r.sortIndex=a,t(l,r),n(c)===null&&r===n(l)&&(h?(v(S),S=-1):h=!0,oe(x,a-o))):(r.sortIndex=s,t(c,r),m||p||(m=!0,ee||(ee=!0,w()))),r},e.unstable_shouldYield=ne,e.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}})),i=e(((e,t)=>{t.exports=r()})),a=e((e=>{var t=n();function r(e){var t=`https://react.dev/errors/`+e;if(1{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=a()})),s=e((e=>{var t=i(),r=n(),a=o();function s(e){var t=`https://react.dev/errors/`+e;if(1pe||(e.current=fe[pe],fe[pe]=null,pe--)}function O(e,t){pe++,fe[pe]=e.current,e.current=t}var he=me(null),ge=me(null),_e=me(null),ve=me(null);function ye(e,t){switch(O(_e,t),O(ge,e),O(he,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Vd(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Vd(t),e=Hd(t,e);else switch(e){case`svg`:e=1;break;case`math`:e=2;break;default:e=0}}D(he),O(he,e)}function be(){D(he),D(ge),D(_e)}function xe(e){e.memoizedState!==null&&O(ve,e);var t=he.current,n=Hd(t,e.type);t!==n&&(O(ge,e),O(he,n))}function Se(e){ge.current===e&&(D(he),D(ge)),ve.current===e&&(D(ve),Qf._currentValue=de)}var Ce,we;function Te(e){if(Ce===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);Ce=t&&t[1]||``,we=-1)`:-1i||c[r]!==l[i]){var u=` -`+c[r].replace(` at new `,` at `);return e.displayName&&u.includes(``)&&(u=u.replace(``,e.displayName)),u}while(1<=r&&0<=i);break}}}finally{Ee=!1,Error.prepareStackTrace=n}return(n=e?e.displayName||e.name:``)?Te(n):``}function Oe(e,t){switch(e.tag){case 26:case 27:case 5:return Te(e.type);case 16:return Te(`Lazy`);case 13:return e.child!==t&&t!==null?Te(`Suspense Fallback`):Te(`Suspense`);case 19:return Te(`SuspenseList`);case 0:case 15:return De(e.type,!1);case 11:return De(e.type.render,!1);case 1:return De(e.type,!0);case 31:return Te(`Activity`);default:return``}}function ke(e){try{var t=``,n=null;do t+=Oe(e,n),n=e,e=e.return;while(e);return t}catch(e){return` -Error generating stack: `+e.message+` -`+e.stack}}var Ae=Object.prototype.hasOwnProperty,je=t.unstable_scheduleCallback,Me=t.unstable_cancelCallback,Ne=t.unstable_shouldYield,Pe=t.unstable_requestPaint,Fe=t.unstable_now,Ie=t.unstable_getCurrentPriorityLevel,Le=t.unstable_ImmediatePriority,Re=t.unstable_UserBlockingPriority,ze=t.unstable_NormalPriority,Be=t.unstable_LowPriority,Ve=t.unstable_IdlePriority,He=t.log,Ue=t.unstable_setDisableYieldValue,We=null,Ge=null;function Ke(e){if(typeof He==`function`&&Ue(e),Ge&&typeof Ge.setStrictMode==`function`)try{Ge.setStrictMode(We,e)}catch{}}var qe=Math.clz32?Math.clz32:Xe,Je=Math.log,Ye=Math.LN2;function Xe(e){return e>>>=0,e===0?32:31-(Je(e)/Ye|0)|0}var Ze=256,Qe=262144,$e=4194304;function et(e){var t=e&42;if(t!==0)return t;switch(e&-e){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 e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function tt(e,t,n){var r=e.pendingLanes;if(r===0)return 0;var i=0,a=e.suspendedLanes,o=e.pingedLanes;e=e.warmLanes;var s=r&134217727;return s===0?(s=r&~a,s===0?o===0?n||(n=r&~e,n!==0&&(i=et(n))):i=et(o):i=et(s)):(r=s&~a,r===0?(o&=s,o===0?n||(n=s&~e,n!==0&&(i=et(n))):i=et(o)):i=et(r)),i===0?0:t!==0&&t!==i&&(t&a)===0&&(a=i&-i,n=t&-t,a>=n||a===32&&n&4194048)?t:i}function nt(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function rt(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+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 t+5e3;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 it(){var e=$e;return $e<<=1,!($e&62914560)&&($e=4194304),e}function at(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function ot(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function st(e,t,n,r,i,a){var o=e.pendingLanes;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=n,e.entangledLanes&=n,e.errorRecoveryDisabledLanes&=n,e.shellSuspendCounter=0;var s=e.entanglements,c=e.expirationTimes,l=e.hiddenUpdates;for(n=o&~n;0`u`||window.document===void 0||window.document.createElement===void 0),yn=!1;if(vn)try{var bn={};Object.defineProperty(bn,"passive",{get:function(){yn=!0}}),window.addEventListener(`test`,bn,bn),window.removeEventListener(`test`,bn,bn)}catch{yn=!1}var xn=null,Sn=null,Cn=null;function wn(){if(Cn)return Cn;var e,t=Sn,n=t.length,r,i=`value`in xn?xn.value:xn.textContent,a=i.length;for(e=0;e=nr),ar=` `,or=!1;function sr(e,t){switch(e){case`keyup`:return er.indexOf(t.keyCode)!==-1;case`keydown`:return t.keyCode!==229;case`keypress`:case`mousedown`:case`focusout`:return!0;default:return!1}}function cr(e){return e=e.detail,typeof e==`object`&&`data`in e?e.data:null}var lr=!1;function ur(e,t){switch(e){case`compositionend`:return cr(t);case`keypress`:return t.which===32?(or=!0,ar):null;case`textInput`:return e=t.data,e===ar&&or?null:e;default:return null}}function dr(e,t){if(lr)return e===`compositionend`||!tr&&sr(e,t)?(e=wn(),Cn=Sn=xn=null,lr=!1,e):null;switch(e){case`paste`:return null;case`keypress`:if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}a:{for(;n;){if(n.nextSibling){n=n.nextSibling;break a}n=n.parentNode}n=void 0}n=Nr(n)}}function Fr(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?Fr(e,t.parentNode):`contains`in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Ir(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=Gt(e.document);t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href==`string`}catch{n=!1}if(n)e=t.contentWindow;else break;t=Gt(e.document)}return t}function Lr(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t===`input`&&(e.type===`text`||e.type===`search`||e.type===`tel`||e.type===`url`||e.type===`password`)||t===`textarea`||e.contentEditable===`true`)}var Rr=vn&&`documentMode`in document&&11>=document.documentMode,zr=null,Br=null,Vr=null,Hr=!1;function Ur(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;Hr||zr==null||zr!==Gt(r)||(r=zr,`selectionStart`in r&&Lr(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),Vr&&Mr(Vr,r)||(Vr=r,r=Ed(Br,`onSelect`),0>=o,i-=o,Fi=1<<32-qe(t)+i|n<h?(g=d,d=null):g=d.sibling;var _=p(i,d,s[h],c);if(_===null){d===null&&(d=g);break}e&&d&&_.alternate===null&&t(i,d),o=a(_,o,h),u===null?l=_:u.sibling=_,u=_,d=g}if(h===s.length)return n(i,d),j&&Li(i,h),l;if(d===null){for(;hg?(_=h,h=null):_=h.sibling;var y=p(i,h,v.value,l);if(y===null){h===null&&(h=_);break}e&&h&&y.alternate===null&&t(i,h),o=a(y,o,g),d===null?u=y:d.sibling=y,d=y,h=_}if(v.done)return n(i,h),j&&Li(i,g),u;if(h===null){for(;!v.done;g++,v=c.next())v=f(i,v.value,l),v!==null&&(o=a(v,o,g),d===null?u=v:d.sibling=v,d=v);return j&&Li(i,g),u}for(h=r(h);!v.done;g++,v=c.next())v=m(h,i,g,v.value,l),v!==null&&(e&&v.alternate!==null&&h.delete(v.key===null?g:v.key),o=a(v,o,g),d===null?u=v:d.sibling=v,d=v);return e&&h.forEach(function(e){return t(i,e)}),j&&Li(i,g),u}function b(e,r,a,c){if(typeof a==`object`&&a&&a.type===y&&a.key===null&&(a=a.props.children),typeof a==`object`&&a){switch(a.$$typeof){case _:a:{for(var l=a.key;r!==null;){if(r.key===l){if(l=a.type,l===y){if(r.tag===7){n(e,r.sibling),c=i(r,a.props.children),c.return=e,e=c;break a}}else if(r.elementType===l||typeof l==`object`&&l&&l.$$typeof===w&&Fa(l)===r.type){n(e,r.sibling),c=i(r,a.props),Ha(c,a),c.return=e,e=c;break a}n(e,r);break}t(e,r),r=r.sibling}a.type===y?(c=Si(a.props.children,e.mode,c,a.key),c.return=e,e=c):(c=xi(a.type,a.key,a.props,null,e.mode,c),Ha(c,a),c.return=e,e=c)}return o(e);case v:a:{for(l=a.key;r!==null;){if(r.key===l){if(r.tag===4&&r.stateNode.containerInfo===a.containerInfo&&r.stateNode.implementation===a.implementation){n(e,r.sibling),c=i(r,a.children||[]),c.return=e,e=c;break a}n(e,r);break}t(e,r),r=r.sibling}c=Ti(a,e.mode,c),c.return=e,e=c}return o(e);case w:return a=Fa(a),b(e,r,a,c)}if(ue(a))return h(e,r,a,c);if(se(a)){if(l=se(a),typeof l!=`function`)throw Error(s(150));return a=l.call(a),g(e,r,a,c)}if(typeof a.then==`function`)return b(e,r,Va(a),c);if(a.$$typeof===S)return b(e,r,ua(e,a),c);Ua(e,a)}return typeof a==`string`&&a!==``||typeof a==`number`||typeof a==`bigint`?(a=``+a,r!==null&&r.tag===6?(n(e,r.sibling),c=i(r,a),c.return=e,e=c):(n(e,r),c=Ci(a,e.mode,c),c.return=e,e=c),o(e)):n(e,r)}return function(e,t,n,r){try{Ba=0;var i=b(e,t,n,r);return za=null,i}catch(t){if(t===ka||t===ja)throw t;var a=_i(29,t,null,e.mode);return a.lanes=r,a.return=e,a}}}var Ga=Wa(!0),Ka=Wa(!1),qa=!1;function Ja(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Ya(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function Xa(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function Za(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,W&2){var i=r.pending;return i===null?t.next=t:(t.next=i.next,i.next=t),r.pending=t,t=mi(e),pi(e,null,n),t}return ui(e,r,t,n),mi(e)}function Qa(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,n&4194048)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,lt(e,n)}}function $a(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var i=null,a=null;if(n=n.firstBaseUpdate,n!==null){do{var o={lane:n.lane,tag:n.tag,payload:n.payload,callback:null,next:null};a===null?i=a=o:a=a.next=o,n=n.next}while(n!==null);a===null?i=a=t:a=a.next=t}else i=a=t;n={baseState:r.baseState,firstBaseUpdate:i,lastBaseUpdate:a,shared:r.shared,callbacks:r.callbacks},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}var eo=!1;function to(){if(eo){var e=ba;if(e!==null)throw e}}function no(e,t,n,r){eo=!1;var i=e.updateQueue;qa=!1;var a=i.firstBaseUpdate,o=i.lastBaseUpdate,s=i.shared.pending;if(s!==null){i.shared.pending=null;var c=s,l=c.next;c.next=null,o===null?a=l:o.next=l,o=c;var u=e.alternate;u!==null&&(u=u.updateQueue,s=u.lastBaseUpdate,s!==o&&(s===null?u.firstBaseUpdate=l:s.next=l,u.lastBaseUpdate=c))}if(a!==null){var d=i.baseState;o=0,u=l=c=null,s=a;do{var f=s.lane&-536870913,p=f!==s.lane;if(p?(q&f)===f:(r&f)===f){f!==0&&f===ya&&(eo=!0),u!==null&&(u=u.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});a:{var m=e,g=s;f=t;var _=n;switch(g.tag){case 1:if(m=g.payload,typeof m==`function`){d=m.call(_,d,f);break a}d=m;break a;case 3:m.flags=m.flags&-65537|128;case 0:if(m=g.payload,f=typeof m==`function`?m.call(_,d,f):m,f==null)break a;d=h({},d,f);break a;case 2:qa=!0}}f=s.callback,f!==null&&(e.flags|=64,p&&(e.flags|=8192),p=i.callbacks,p===null?i.callbacks=[f]:p.push(f))}else p={lane:f,tag:s.tag,payload:s.payload,callback:s.callback,next:null},u===null?(l=u=p,c=d):u=u.next=p,o|=f;if(s=s.next,s===null){if(s=i.shared.pending,s===null)break;p=s,s=p.next,p.next=null,i.lastBaseUpdate=p,i.shared.pending=null}}while(1);u===null&&(c=d),i.baseState=c,i.firstBaseUpdate=l,i.lastBaseUpdate=u,a===null&&(i.shared.lanes=0),Kl|=o,e.lanes=o,e.memoizedState=d}}function ro(e,t){if(typeof e!=`function`)throw Error(s(191,e));e.call(t)}function io(e,t){var n=e.callbacks;if(n!==null)for(e.callbacks=null,e=0;ea?a:8;var o=T.T,s={};T.T=s,zs(e,!1,t,n);try{var c=i(),l=T.S;l!==null&&l(s,c),typeof c==`object`&&c&&typeof c.then==`function`?Rs(e,t,Ca(c,r),pu(e)):Rs(e,t,r,pu(e))}catch(n){Rs(e,t,{then:function(){},status:`rejected`,reason:n},pu())}finally{E.p=a,o!==null&&s.types!==null&&(o.types=s.types),T.T=o}}function Os(){}function ks(e,t,n,r){if(e.tag!==5)throw Error(s(476));var i=As(e).queue;Ds(e,i,t,de,n===null?Os:function(){return js(e),n(r)})}function As(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:de,baseState:de,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Bo,lastRenderedState:de},next:null};var n={};return t.next={memoizedState:n,baseState:n,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Bo,lastRenderedState:n},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function js(e){var t=As(e);t.next===null&&(t=e.alternate.memoizedState),Rs(e,t.next.queue,{},pu())}function Ms(){return la(Qf)}function Ns(){return R().memoizedState}function Ps(){return R().memoizedState}function Fs(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var n=pu();e=Xa(n);var r=Za(t,e,n);r!==null&&(hu(r,t,n),Qa(r,t,n)),t={cache:ha()},e.payload=t;return}t=t.return}}function Is(e,t,n){var r=pu();n={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null},Bs(e)?Vs(t,n):(n=di(e,t,n,r),n!==null&&(hu(n,e,r),Hs(n,t,r)))}function Ls(e,t,n){Rs(e,t,n,pu())}function Rs(e,t,n,r){var i={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null};if(Bs(e))Vs(t,i);else{var a=e.alternate;if(e.lanes===0&&(a===null||a.lanes===0)&&(a=t.lastRenderedReducer,a!==null))try{var o=t.lastRenderedState,s=a(o,n);if(i.hasEagerState=!0,i.eagerState=s,jr(s,o))return ui(e,t,i,0),G===null&&li(),!1}catch{}if(n=di(e,t,i,r),n!==null)return hu(n,e,r),Hs(n,t,r),!0}return!1}function zs(e,t,n,r){if(r={lane:2,revertLane:dd(),gesture:null,action:r,hasEagerState:!1,eagerState:null,next:null},Bs(e)){if(t)throw Error(s(479))}else t=di(e,n,r,2),t!==null&&hu(t,e,2)}function Bs(e){var t=e.alternate;return e===P||t!==null&&t===P}function Vs(e,t){xo=bo=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function Hs(e,t,n){if(n&4194048){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,lt(e,n)}}var Us={readContext:la,use:Ro,useCallback:L,useContext:L,useEffect:L,useImperativeHandle:L,useLayoutEffect:L,useInsertionEffect:L,useMemo:L,useReducer:L,useRef:L,useState:L,useDebugValue:L,useDeferredValue:L,useTransition:L,useSyncExternalStore:L,useId:L,useHostTransitionStatus:L,useFormState:L,useActionState:L,useOptimistic:L,useMemoCache:L,useCacheRefresh:L};Us.useEffectEvent=L;var Ws={readContext:la,use:Ro,useCallback:function(e,t){return Fo().memoizedState=[e,t===void 0?null:t],e},useContext:la,useEffect:ms,useImperativeHandle:function(e,t,n){n=n==null?null:n.concat([e]),fs(4194308,4,bs.bind(null,t,e),n)},useLayoutEffect:function(e,t){return fs(4194308,4,e,t)},useInsertionEffect:function(e,t){fs(4,2,e,t)},useMemo:function(e,t){var n=Fo();t=t===void 0?null:t;var r=e();if(So){Ke(!0);try{e()}finally{Ke(!1)}}return n.memoizedState=[r,t],r},useReducer:function(e,t,n){var r=Fo();if(n!==void 0){var i=n(t);if(So){Ke(!0);try{n(t)}finally{Ke(!1)}}}else i=t;return r.memoizedState=r.baseState=i,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:i},r.queue=e,e=e.dispatch=Is.bind(null,P,e),[r.memoizedState,e]},useRef:function(e){var t=Fo();return e={current:e},t.memoizedState=e},useState:function(e){e=Xo(e);var t=e.queue,n=Ls.bind(null,P,t);return t.dispatch=n,[e.memoizedState,n]},useDebugValue:Ss,useDeferredValue:function(e,t){return Ts(Fo(),e,t)},useTransition:function(){var e=Xo(!1);return e=Ds.bind(null,P,e.queue,!0,!1),Fo().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,n){var r=P,i=Fo();if(j){if(n===void 0)throw Error(s(407));n=n()}else{if(n=t(),G===null)throw Error(s(349));q&127||Go(r,t,n)}i.memoizedState=n;var a={value:n,getSnapshot:t};return i.queue=a,ms(qo.bind(null,r,a,e),[e]),r.flags|=2048,us(9,{destroy:void 0},Ko.bind(null,r,a,n,t),null),n},useId:function(){var e=Fo(),t=G.identifierPrefix;if(j){var n=Ii,r=Fi;n=(r&~(1<<32-qe(r)-1)).toString(32)+n,t=`_`+t+`R_`+n,n=Co++,0<\/script>`,a=a.removeChild(a.firstChild);break;case`select`:a=typeof r.is==`string`?o.createElement(`select`,{is:r.is}):o.createElement(`select`),r.multiple?a.multiple=!0:r.size&&(a.size=r.size);break;default:a=typeof r.is==`string`?o.createElement(i,{is:r.is}):o.createElement(i)}}a[gt]=t,a[_t]=r;a:for(o=t.child;o!==null;){if(o.tag===5||o.tag===6)a.appendChild(o.stateNode);else if(o.tag!==4&&o.tag!==27&&o.child!==null){o.child.return=o,o=o.child;continue}if(o===t)break a;for(;o.sibling===null;){if(o.return===null||o.return===t)break a;o=o.return}o.sibling.return=o.return,o=o.sibling}t.stateNode=a;a:switch(Pd(a,i,r),i){case`button`:case`input`:case`select`:case`textarea`:r=!!r.autoFocus;break a;case`img`:r=!0;break a;default:r=!1}r&&Lc(t)}}return B(t),Rc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,n),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==r&&Lc(t);else{if(typeof r!=`string`&&t.stateNode===null)throw Error(s(166));if(e=_e.current,Yi(t)){if(e=t.stateNode,n=t.memoizedProps,r=null,i=Hi,i!==null)switch(i.tag){case 27:case 5:r=i.memoizedProps}e[gt]=t,e=!!(e.nodeValue===n||r!==null&&!0===r.suppressHydrationWarning||Md(e.nodeValue,n)),e||Ki(t,!0)}else e=Bd(e).createTextNode(r),e[gt]=t,t.stateNode=e}return B(t),null;case 31:if(n=t.memoizedState,e===null||e.memoizedState!==null){if(r=Yi(t),n!==null){if(e===null){if(!r)throw Error(s(318));if(e=t.memoizedState,e=e===null?null:e.dehydrated,!e)throw Error(s(557));e[gt]=t}else Xi(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;B(t),e=!1}else n=Zi(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),e=!0;if(!e)return t.flags&256?(_o(t),t):(_o(t),null);if(t.flags&128)throw Error(s(558))}return B(t),null;case 13:if(r=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(i=Yi(t),r!==null&&r.dehydrated!==null){if(e===null){if(!i)throw Error(s(318));if(i=t.memoizedState,i=i===null?null:i.dehydrated,!i)throw Error(s(317));i[gt]=t}else Xi(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;B(t),i=!1}else i=Zi(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=i),i=!0;if(!i)return t.flags&256?(_o(t),t):(_o(t),null)}return _o(t),t.flags&128?(t.lanes=n,t):(n=r!==null,e=e!==null&&e.memoizedState!==null,n&&(r=t.child,i=null,r.alternate!==null&&r.alternate.memoizedState!==null&&r.alternate.memoizedState.cachePool!==null&&(i=r.alternate.memoizedState.cachePool.pool),a=null,r.memoizedState!==null&&r.memoizedState.cachePool!==null&&(a=r.memoizedState.cachePool.pool),a!==i&&(r.flags|=2048)),n!==e&&n&&(t.child.flags|=8192),Bc(t,t.updateQueue),B(t),null);case 4:return be(),e===null&&Sd(t.stateNode.containerInfo),B(t),null;case 10:return ra(t.type),B(t),null;case 19:if(D(N),r=t.memoizedState,r===null)return B(t),null;if(i=!!(t.flags&128),a=r.rendering,a===null){if(i)Vc(r,!1);else{if(Y!==0||e!==null&&e.flags&128)for(e=t.child;e!==null;){if(a=vo(e),a!==null){for(t.flags|=128,Vc(r,!1),e=a.updateQueue,t.updateQueue=e,Bc(t,e),t.subtreeFlags=0,e=n,n=t.child;n!==null;)bi(n,e),n=n.sibling;return O(N,N.current&1|2),j&&Li(t,r.treeForkCount),t.child}e=e.sibling}r.tail!==null&&Fe()>nu&&(t.flags|=128,i=!0,Vc(r,!1),t.lanes=4194304)}}else{if(!i){if(e=vo(a),e!==null){if(t.flags|=128,i=!0,e=e.updateQueue,t.updateQueue=e,Bc(t,e),Vc(r,!0),r.tail===null&&r.tailMode===`hidden`&&!a.alternate&&!j)return B(t),null}else 2*Fe()-r.renderingStartTime>nu&&n!==536870912&&(t.flags|=128,i=!0,Vc(r,!1),t.lanes=4194304)}r.isBackwards?(a.sibling=t.child,t.child=a):(e=r.last,e===null?t.child=a:e.sibling=a,r.last=a)}return r.tail===null?(B(t),null):(e=r.tail,r.rendering=e,r.tail=e.sibling,r.renderingStartTime=Fe(),e.sibling=null,n=N.current,O(N,i?n&1|2:n&1),j&&Li(t,r.treeForkCount),e);case 22:case 23:return _o(t),lo(),r=t.memoizedState!==null,e===null?r&&(t.flags|=8192):e.memoizedState!==null!==r&&(t.flags|=8192),r?n&536870912&&!(t.flags&128)&&(B(t),t.subtreeFlags&6&&(t.flags|=8192)):B(t),n=t.updateQueue,n!==null&&Bc(t,n.retryQueue),n=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(n=e.memoizedState.cachePool.pool),r=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(r=t.memoizedState.cachePool.pool),r!==n&&(t.flags|=2048),e!==null&&D(Ta),null;case 24:return n=null,e!==null&&(n=e.memoizedState.cache),t.memoizedState.cache!==n&&(t.flags|=2048),ra(M),B(t),null;case 25:return null;case 30:return null}throw Error(s(156,t.tag))}function Uc(e,t){switch(Bi(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return ra(M),be(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return Se(t),null;case 31:if(t.memoizedState!==null){if(_o(t),t.alternate===null)throw Error(s(340));Xi()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(_o(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(s(340));Xi()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return D(N),null;case 4:return be(),null;case 10:return ra(t.type),null;case 22:case 23:return _o(t),lo(),e!==null&&D(Ta),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return ra(M),null;case 25:return null;default:return null}}function Wc(e,t){switch(Bi(t),t.tag){case 3:ra(M),be();break;case 26:case 27:case 5:Se(t);break;case 4:be();break;case 31:t.memoizedState!==null&&_o(t);break;case 13:_o(t);break;case 19:D(N);break;case 10:ra(t.type);break;case 22:case 23:_o(t),lo(),e!==null&&D(Ta);break;case 24:ra(M)}}function Gc(e,t){try{var n=t.updateQueue,r=n===null?null:n.lastEffect;if(r!==null){var i=r.next;n=i;do{if((n.tag&e)===e){r=void 0;var a=n.create,o=n.inst;r=a(),o.destroy=r}n=n.next}while(n!==i)}}catch(e){Z(t,t.return,e)}}function Kc(e,t,n){try{var r=t.updateQueue,i=r===null?null:r.lastEffect;if(i!==null){var a=i.next;r=a;do{if((r.tag&e)===e){var o=r.inst,s=o.destroy;if(s!==void 0){o.destroy=void 0,i=t;var c=n,l=s;try{l()}catch(e){Z(i,c,e)}}}r=r.next}while(r!==a)}}catch(e){Z(t,t.return,e)}}function qc(e){var t=e.updateQueue;if(t!==null){var n=e.stateNode;try{io(t,n)}catch(t){Z(e,e.return,t)}}}function Jc(e,t,n){n.props=Zs(e.type,e.memoizedProps),n.state=e.memoizedState;try{n.componentWillUnmount()}catch(n){Z(e,t,n)}}function Yc(e,t){try{var n=e.ref;if(n!==null){switch(e.tag){case 26:case 27:case 5:var r=e.stateNode;break;case 30:r=e.stateNode;break;default:r=e.stateNode}typeof n==`function`?e.refCleanup=n(r):n.current=r}}catch(n){Z(e,t,n)}}function Xc(e,t){var n=e.ref,r=e.refCleanup;if(n!==null){if(typeof r==`function`)try{r()}catch(n){Z(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof n==`function`)try{n(null)}catch(n){Z(e,t,n)}else n.current=null}}function Zc(e){var t=e.type,n=e.memoizedProps,r=e.stateNode;try{a:switch(t){case`button`:case`input`:case`select`:case`textarea`:n.autoFocus&&r.focus();break a;case`img`:n.src?r.src=n.src:n.srcSet&&(r.srcset=n.srcSet)}}catch(t){Z(e,e.return,t)}}function Qc(e,t,n){try{var r=e.stateNode;Fd(r,e.type,n,t),r[_t]=t}catch(t){Z(e,e.return,t)}}function $c(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&Zd(e.type)||e.tag===4}function el(e){a:for(;;){for(;e.sibling===null;){if(e.return===null||$c(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&Zd(e.type)||e.flags&2||e.child===null||e.tag===4)continue a;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function tl(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?(n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n).insertBefore(e,t):(t=n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n,t.appendChild(e),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=ln));else if(r!==4&&(r===27&&Zd(e.type)&&(n=e.stateNode,t=null),e=e.child,e!==null))for(tl(e,t,n),e=e.sibling;e!==null;)tl(e,t,n),e=e.sibling}function nl(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(r!==4&&(r===27&&Zd(e.type)&&(n=e.stateNode),e=e.child,e!==null))for(nl(e,t,n),e=e.sibling;e!==null;)nl(e,t,n),e=e.sibling}function rl(e){var t=e.stateNode,n=e.memoizedProps;try{for(var r=e.type,i=t.attributes;i.length;)t.removeAttributeNode(i[0]);Pd(t,r,n),t[gt]=e,t[_t]=n}catch(t){Z(e,e.return,t)}}var il=!1,V=!1,al=!1,ol=typeof WeakSet==`function`?WeakSet:Set,H=null;function sl(e,t){if(e=e.containerInfo,Rd=sp,e=Ir(e),Lr(e)){if(`selectionStart`in e)var n={start:e.selectionStart,end:e.selectionEnd};else a:{n=(n=e.ownerDocument)&&n.defaultView||window;var r=n.getSelection&&n.getSelection();if(r&&r.rangeCount!==0){n=r.anchorNode;var i=r.anchorOffset,a=r.focusNode;r=r.focusOffset;try{n.nodeType,a.nodeType}catch{n=null;break a}var o=0,c=-1,l=-1,u=0,d=0,f=e,p=null;b:for(;;){for(var m;f!==n||i!==0&&f.nodeType!==3||(c=o+i),f!==a||r!==0&&f.nodeType!==3||(l=o+r),f.nodeType===3&&(o+=f.nodeValue.length),(m=f.firstChild)!==null;)p=f,f=m;for(;;){if(f===e)break b;if(p===n&&++u===i&&(c=o),p===a&&++d===r&&(l=o),(m=f.nextSibling)!==null)break;f=p,p=f.parentNode}f=m}n=c===-1||l===-1?null:{start:c,end:l}}else n=null}n||={start:0,end:0}}else n=null;for(zd={focusedElem:e,selectionRange:n},sp=!1,H=t;H!==null;)if(t=H,e=t.child,t.subtreeFlags&1028&&e!==null)e.return=t,H=e;else for(;H!==null;){switch(t=H,a=t.alternate,e=t.flags,t.tag){case 0:if(e&4&&(e=t.updateQueue,e=e===null?null:e.events,e!==null))for(n=0;n title`))),Pd(a,r,n),a[gt]=e,k(a),r=a;break a;case`link`:var o=Vf(`link`,`href`,i).get(r+(n.href||``));if(o){for(var c=0;cg&&(o=g,g=h,h=o);var _=Pr(s,h),v=Pr(s,g);if(_&&v&&(p.rangeCount!==1||p.anchorNode!==_.node||p.anchorOffset!==_.offset||p.focusNode!==v.node||p.focusOffset!==v.offset)){var y=d.createRange();y.setStart(_.node,_.offset),p.removeAllRanges(),h>g?(p.addRange(y),p.extend(v.node,v.offset)):(y.setEnd(v.node,v.offset),p.addRange(y))}}}}for(d=[],p=s;p=p.parentNode;)p.nodeType===1&&d.push({element:p,left:p.scrollLeft,top:p.scrollTop});for(typeof s.focus==`function`&&s.focus(),s=0;sn?32:n,T.T=null,n=lu,lu=null;var a=au,o=su;if(X=0,ou=au=null,su=0,W&6)throw Error(s(331));var c=W;if(W|=4,Il(a.current),Ol(a,a.current,o,n),W=c,id(0,!1),Ge&&typeof Ge.onPostCommitFiberRoot==`function`)try{Ge.onPostCommitFiberRoot(We,a)}catch{}return!0}finally{E.p=i,T.T=r,Vu(e,t)}}function Wu(e,t,n){t=Di(n,t),t=rc(e.stateNode,t,2),e=Za(e,t,2),e!==null&&(ot(e,2),rd(e))}function Z(e,t,n){if(e.tag===3)Wu(e,e,n);else for(;t!==null;){if(t.tag===3){Wu(t,e,n);break}if(t.tag===1){var r=t.stateNode;if(typeof t.type.getDerivedStateFromError==`function`||typeof r.componentDidCatch==`function`&&(iu===null||!iu.has(r))){e=Di(n,e),n=ic(2),r=Za(t,n,2),r!==null&&(ac(n,r,t,e),ot(r,2),rd(r));break}}t=t.return}}function Gu(e,t,n){var r=e.pingCache;if(r===null){r=e.pingCache=new Bl;var i=new Set;r.set(t,i)}else i=r.get(t),i===void 0&&(i=new Set,r.set(t,i));i.has(n)||(Wl=!0,i.add(n),e=Ku.bind(null,e,t,n),t.then(e,e))}function Ku(e,t,n){var r=e.pingCache;r!==null&&r.delete(t),e.pingedLanes|=e.suspendedLanes&n,e.warmLanes&=~n,G===e&&(q&n)===n&&(Y===4||Y===3&&(q&62914560)===q&&300>Fe()-eu?!(W&2)&&Su(e,0):Jl|=n,Xl===q&&(Xl=0)),rd(e)}function qu(e,t){t===0&&(t=it()),e=fi(e,t),e!==null&&(ot(e,t),rd(e))}function Ju(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),qu(e,n)}function Yu(e,t){var n=0;switch(e.tag){case 31:case 13:var r=e.stateNode,i=e.memoizedState;i!==null&&(n=i.retryLane);break;case 19:r=e.stateNode;break;case 22:r=e.stateNode._retryCache;break;default:throw Error(s(314))}r!==null&&r.delete(t),qu(e,n)}function Xu(e,t){return je(e,t)}var Zu=null,Qu=null,$u=!1,ed=!1,td=!1,nd=0;function rd(e){e!==Qu&&e.next===null&&(Qu===null?Zu=Qu=e:Qu=Qu.next=e),ed=!0,$u||($u=!0,ud())}function id(e,t){if(!td&&ed){td=!0;do for(var n=!1,r=Zu;r!==null;){if(!t){if(e!==0){var i=r.pendingLanes;if(i===0)var a=0;else{var o=r.suspendedLanes,s=r.pingedLanes;a=(1<<31-qe(42|e)+1)-1,a&=i&~(o&~s),a=a&201326741?a&201326741|1:a?a|2:0}a!==0&&(n=!0,ld(r,a))}else a=q,a=tt(r,r===G?a:0,r.cancelPendingCommit!==null||r.timeoutHandle!==-1),!(a&3)||nt(r,a)||(n=!0,ld(r,a))}r=r.next}while(n);td=!1}}function ad(){od()}function od(){ed=$u=!1;var e=0;nd!==0&&Gd()&&(e=nd);for(var t=Fe(),n=null,r=Zu;r!==null;){var i=r.next,a=sd(r,t);a===0?(r.next=null,n===null?Zu=i:n.next=i,i===null&&(Qu=n)):(n=r,(e!==0||a&3)&&(ed=!0)),r=i}X!==0&&X!==5||id(e,!1),nd!==0&&(nd=0)}function sd(e,t){for(var n=e.suspendedLanes,r=e.pingedLanes,i=e.expirationTimes,a=e.pendingLanes&-62914561;0s)break;var u=c.transferSize,d=c.initiatorType;u&&Id(d)&&(c=c.responseEnd,o+=u*(c`u`?null:document;function xf(e,t,n){var r=bf;if(r&&typeof t==`string`&&t){var i=qt(t);i=`link[rel="`+e+`"][href="`+i+`"]`,typeof n==`string`&&(i+=`[crossorigin="`+n+`"]`),hf.has(i)||(hf.add(i),e={rel:e,crossOrigin:n,href:t},r.querySelector(i)===null&&(t=r.createElement(`link`),Pd(t,`link`,e),k(t),r.head.appendChild(t)))}}function Sf(e){_f.D(e),xf(`dns-prefetch`,e,null)}function Cf(e,t){_f.C(e,t),xf(`preconnect`,e,t)}function wf(e,t,n){_f.L(e,t,n);var r=bf;if(r&&e&&t){var i=`link[rel="preload"][as="`+qt(t)+`"]`;t===`image`&&n&&n.imageSrcSet?(i+=`[imagesrcset="`+qt(n.imageSrcSet)+`"]`,typeof n.imageSizes==`string`&&(i+=`[imagesizes="`+qt(n.imageSizes)+`"]`)):i+=`[href="`+qt(e)+`"]`;var a=i;switch(t){case`style`:a=Af(e);break;case`script`:a=Pf(e)}mf.has(a)||(e=h({rel:`preload`,href:t===`image`&&n&&n.imageSrcSet?void 0:e,as:t},n),mf.set(a,e),r.querySelector(i)!==null||t===`style`&&r.querySelector(jf(a))||t===`script`&&r.querySelector(Ff(a))||(t=r.createElement(`link`),Pd(t,`link`,e),k(t),r.head.appendChild(t)))}}function Tf(e,t){_f.m(e,t);var n=bf;if(n&&e){var r=t&&typeof t.as==`string`?t.as:`script`,i=`link[rel="modulepreload"][as="`+qt(r)+`"][href="`+qt(e)+`"]`,a=i;switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:a=Pf(e)}if(!mf.has(a)&&(e=h({rel:`modulepreload`,href:e},t),mf.set(a,e),n.querySelector(i)===null)){switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:if(n.querySelector(Ff(a)))return}r=n.createElement(`link`),Pd(r,`link`,e),k(r),n.head.appendChild(r)}}}function Ef(e,t,n){_f.S(e,t,n);var r=bf;if(r&&e){var i=Ot(r).hoistableStyles,a=Af(e);t||=`default`;var o=i.get(a);if(!o){var s={loading:0,preload:null};if(o=r.querySelector(jf(a)))s.loading=5;else{e=h({rel:`stylesheet`,href:e,"data-precedence":t},n),(n=mf.get(a))&&Rf(e,n);var c=o=r.createElement(`link`);k(c),Pd(c,`link`,e),c._p=new Promise(function(e,t){c.onload=e,c.onerror=t}),c.addEventListener(`load`,function(){s.loading|=1}),c.addEventListener(`error`,function(){s.loading|=2}),s.loading|=4,Lf(o,t,r)}o={type:`stylesheet`,instance:o,count:1,state:s},i.set(a,o)}}}function Df(e,t){_f.X(e,t);var n=bf;if(n&&e){var r=Ot(n).hoistableScripts,i=Pf(e),a=r.get(i);a||(a=n.querySelector(Ff(i)),a||(e=h({src:e,async:!0},t),(t=mf.get(i))&&zf(e,t),a=n.createElement(`script`),k(a),Pd(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function Of(e,t){_f.M(e,t);var n=bf;if(n&&e){var r=Ot(n).hoistableScripts,i=Pf(e),a=r.get(i);a||(a=n.querySelector(Ff(i)),a||(e=h({src:e,async:!0,type:`module`},t),(t=mf.get(i))&&zf(e,t),a=n.createElement(`script`),k(a),Pd(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function kf(e,t,n,r){var i=(i=_e.current)?gf(i):null;if(!i)throw Error(s(446));switch(e){case`meta`:case`title`:return null;case`style`:return typeof n.precedence==`string`&&typeof n.href==`string`?(t=Af(n.href),n=Ot(i).hoistableStyles,r=n.get(t),r||(r={type:`style`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};case`link`:if(n.rel===`stylesheet`&&typeof n.href==`string`&&typeof n.precedence==`string`){e=Af(n.href);var a=Ot(i).hoistableStyles,o=a.get(e);if(o||(i=i.ownerDocument||i,o={type:`stylesheet`,instance:null,count:0,state:{loading:0,preload:null}},a.set(e,o),(a=i.querySelector(jf(e)))&&!a._p&&(o.instance=a,o.state.loading=5),mf.has(e)||(n={rel:`preload`,as:`style`,href:n.href,crossOrigin:n.crossOrigin,integrity:n.integrity,media:n.media,hrefLang:n.hrefLang,referrerPolicy:n.referrerPolicy},mf.set(e,n),a||Nf(i,e,n,o.state))),t&&r===null)throw Error(s(528,``));return o}if(t&&r!==null)throw Error(s(529,``));return null;case`script`:return t=n.async,n=n.src,typeof n==`string`&&t&&typeof t!=`function`&&typeof t!=`symbol`?(t=Pf(n),n=Ot(i).hoistableScripts,r=n.get(t),r||(r={type:`script`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};default:throw Error(s(444,e))}}function Af(e){return`href="`+qt(e)+`"`}function jf(e){return`link[rel="stylesheet"][`+e+`]`}function Mf(e){return h({},e,{"data-precedence":e.precedence,precedence:null})}function Nf(e,t,n,r){e.querySelector(`link[rel="preload"][as="style"][`+t+`]`)?r.loading=1:(t=e.createElement(`link`),r.preload=t,t.addEventListener(`load`,function(){return r.loading|=1}),t.addEventListener(`error`,function(){return r.loading|=2}),Pd(t,`link`,n),k(t),e.head.appendChild(t))}function Pf(e){return`[src="`+qt(e)+`"]`}function Ff(e){return`script[async]`+e}function If(e,t,n){if(t.count++,t.instance===null)switch(t.type){case`style`:var r=e.querySelector(`style[data-href~="`+qt(n.href)+`"]`);if(r)return t.instance=r,k(r),r;var i=h({},n,{"data-href":n.href,"data-precedence":n.precedence,href:null,precedence:null});return r=(e.ownerDocument||e).createElement(`style`),k(r),Pd(r,`style`,i),Lf(r,n.precedence,e),t.instance=r;case`stylesheet`:i=Af(n.href);var a=e.querySelector(jf(i));if(a)return t.state.loading|=4,t.instance=a,k(a),a;r=Mf(n),(i=mf.get(i))&&Rf(r,i),a=(e.ownerDocument||e).createElement(`link`),k(a);var o=a;return o._p=new Promise(function(e,t){o.onload=e,o.onerror=t}),Pd(a,`link`,r),t.state.loading|=4,Lf(a,n.precedence,e),t.instance=a;case`script`:return a=Pf(n.src),(i=e.querySelector(Ff(a)))?(t.instance=i,k(i),i):(r=n,(i=mf.get(a))&&(r=h({},n),zf(r,i)),e=e.ownerDocument||e,i=e.createElement(`script`),k(i),Pd(i,`link`,r),e.head.appendChild(i),t.instance=i);case`void`:return null;default:throw Error(s(443,t.type))}else t.type===`stylesheet`&&!(t.state.loading&4)&&(r=t.instance,t.state.loading|=4,Lf(r,n.precedence,e));return t.instance}function Lf(e,t,n){for(var r=n.querySelectorAll(`link[rel="stylesheet"][data-precedence],style[data-precedence]`),i=r.length?r[r.length-1]:null,a=i,o=0;o title`):null)}function Uf(e,t,n){if(n===1||t.itemProp!=null)return!1;switch(e){case`meta`:case`title`:return!0;case`style`:if(typeof t.precedence!=`string`||typeof t.href!=`string`||t.href===``)break;return!0;case`link`:if(typeof t.rel!=`string`||typeof t.href!=`string`||t.href===``||t.onLoad||t.onError)break;switch(t.rel){case`stylesheet`:return e=t.disabled,typeof t.precedence==`string`&&e==null;default:return!0}case`script`:if(t.async&&typeof t.async!=`function`&&typeof t.async!=`symbol`&&!t.onLoad&&!t.onError&&t.src&&typeof t.src==`string`)return!0}return!1}function Wf(e){return!(e.type===`stylesheet`&&!(e.state.loading&3))}function Gf(e,t,n,r){if(n.type===`stylesheet`&&(typeof r.media!=`string`||!1!==matchMedia(r.media).matches)&&!(n.state.loading&4)){if(n.instance===null){var i=Af(r.href),a=t.querySelector(jf(i));if(a){t=a._p,typeof t==`object`&&t&&typeof t.then==`function`&&(e.count++,e=Jf.bind(e),t.then(e,e)),n.state.loading|=4,n.instance=a,k(a);return}a=t.ownerDocument||t,r=Mf(r),(i=mf.get(i))&&Rf(r,i),a=a.createElement(`link`),k(a);var o=a;o._p=new Promise(function(e,t){o.onload=e,o.onerror=t}),Pd(a,`link`,r),n.instance=a}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(n,t),(t=n.state.preload)&&!(n.state.loading&3)&&(e.count++,n=Jf.bind(e),t.addEventListener(`load`,n),t.addEventListener(`error`,n))}}var Kf=0;function qf(e,t){return e.stylesheets&&e.count===0&&Xf(e,e.stylesheets),0Kf?50:800)+t);return e.unsuspend=n,function(){e.unsuspend=null,clearTimeout(r),clearTimeout(i)}}:null}function Jf(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Xf(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var Yf=null;function Xf(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,Yf=new Map,t.forEach(Zf,e),Yf=null,Jf.call(e))}function Zf(e,t){if(!(t.state.loading&4)){var n=Yf.get(e);if(n)var r=n.get(null);else{n=new Map,Yf.set(e,n);for(var i=e.querySelectorAll(`link[data-precedence],style[data-precedence]`),a=0;a{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=s()})),l=n(),u=c(),d=e=>{let t=e.role||e.type;return t===`user`||t===`assistant`||t===`tool`||t===`system`?t:`assistant`},f=e=>{if(e.text)return e.text;if(e.payload&&typeof e.payload==`object`&&`content`in e.payload){let t=e.payload.content;if(typeof t==`string`)return t}return``},p=e=>{let t=e.entries.find(e=>d(e)===`user`);if(t){let e=f(t).trim();if(e)return e}let n=e.metadata?.objective;return typeof n==`string`&&n.trim()?n:e.id},m=e=>{let t=new Date(e);return Number.isNaN(t.getTime())?``:new Intl.DateTimeFormat(`zh-CN`,{month:`short`,day:`numeric`,hour:`2-digit`,minute:`2-digit`}).format(t)},h=(e,t)=>{let n=t.trim().toLowerCase();if(!n)return!0;let r=[e.id,e.cwd,p(e)].map(e=>e.toLowerCase());for(let t of e.entries)r.push(f(t).toLowerCase()),t.tool&&r.push(t.tool.toLowerCase());return r.some(e=>e.includes(n))},g=(e,t)=>e.filter(e=>h(e,t)),_=(e,t)=>t===`all`?e:e.filter(e=>d(e)===t),v=``+new URL(`call-code-BBgvhvPd.png`,import.meta.url).href,y=e((e=>{var t=Symbol.for(`react.transitional.element`);function n(e,n,r){var i=null;if(r!==void 0&&(i=``+r),n.key!==void 0&&(i=``+n.key),`key`in n)for(var a in r={},n)a!==`key`&&(r[a]=n[a]);else r=n;return n=r.ref,{$$typeof:t,type:e,key:i,ref:n===void 0?null:n,props:r}}e.jsx=n,e.jsxs=n})),b=e(((e,t)=>{t.exports=y()}))();function x({sessions:e,theme:t,onThemeChange:n}){let r=e.reduce((e,t)=>(e.messages+=t.entries.length,e.tools+=t.entries.filter(e=>d(e)===`tool`).length,e),{messages:0,tools:0});return(0,b.jsxs)(`header`,{className:`header-bar`,children:[(0,b.jsxs)(`div`,{className:`flex min-w-0 items-center gap-3`,children:[(0,b.jsx)(`img`,{src:v,alt:`Call Code`,className:`h-9 w-9 shrink-0 rounded-xl border object-contain`,style:{borderColor:`rgb(var(--chip-border))`,background:`rgb(var(--chip-bg))`}}),(0,b.jsxs)(`div`,{className:`min-w-0`,children:[(0,b.jsx)(`h1`,{className:`truncate text-[17px] font-semibold leading-tight`,style:{color:`var(--text-primary)`},children:`Call Code`}),(0,b.jsxs)(`div`,{className:`mt-0.5 truncate text-[11px]`,style:{color:`var(--text-tertiary)`},children:[e.length,` 个会话 · `,r.messages,` 条消息 · `,r.tools,` `,`次工具`]})]})]}),(0,b.jsx)(`div`,{className:`segmented shrink-0`,role:`tablist`,"aria-label":`主题切换`,children:[`light`,`dark`].map(e=>(0,b.jsx)(`button`,{type:`button`,role:`tab`,"aria-pressed":t===e,onClick:()=>n(e),children:e===`light`?`毛玻璃`:`高级黑`},e))})]})}function ee({sessions:e,activeId:t,query:n,onSelect:r,onQueryChange:i}){return(0,b.jsxs)(`aside`,{className:`sidebar-panel max-h-[50vh] lg:max-h-none`,children:[(0,b.jsx)(`header`,{className:`border-b px-3 py-3`,style:{borderColor:`rgb(var(--panel-border))`},children:(0,b.jsxs)(`div`,{className:`search-box flex h-8 min-w-0 items-center gap-2 rounded-lg border px-2.5`,style:{borderColor:`rgb(var(--chip-border))`,background:`rgb(var(--chip-bg))`},children:[(0,b.jsxs)(`svg`,{width:`13`,height:`13`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,style:{color:`var(--text-tertiary)`},"aria-hidden":`true`,children:[(0,b.jsx)(`circle`,{cx:`11`,cy:`11`,r:`7`}),(0,b.jsx)(`path`,{d:`m20 20-3.5-3.5`})]}),(0,b.jsx)(`input`,{type:`search`,value:n,onChange:e=>i(e.target.value),placeholder:`搜索会话`,"aria-label":`搜索会话`,className:`h-full w-full min-w-0 bg-transparent text-[12px] outline-none`,style:{color:`var(--text-primary)`}})]})}),(0,b.jsxs)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-2 pt-3 pb-3`,children:[e.length===0&&(0,b.jsx)(`div`,{className:`grid min-h-[120px] place-items-center text-[12px]`,style:{color:`var(--text-tertiary)`},children:`暂无会话`}),(0,b.jsx)(`div`,{className:`flex flex-col gap-0.5`,children:e.map(e=>{let n=e.id===t;return(0,b.jsxs)(`button`,{type:`button`,onClick:()=>r(e.id),"aria-current":n?`true`:void 0,className:`group relative flex items-start gap-2.5 rounded-xl px-2.5 py-2 text-left transition-all duration-200`,style:n?{background:`rgb(var(--sidebar-active))`,boxShadow:`var(--sidebar-active-shadow)`}:void 0,onMouseEnter:e=>{n||(e.currentTarget.style.background=`rgb(var(--sidebar-hover))`)},onMouseLeave:e=>{n||(e.currentTarget.style.background=``)},children:[(0,b.jsx)(`span`,{className:`mt-1 h-4 w-1 shrink-0 rounded-full transition-opacity`,style:{background:n?`var(--text-primary)`:`transparent`,opacity:+!!n},"aria-hidden":`true`}),(0,b.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,b.jsx)(`div`,{className:`line-clamp-2 text-[13px] font-medium leading-snug`,style:{color:n?`var(--text-primary)`:`var(--text-secondary)`},children:p(e)}),(0,b.jsxs)(`div`,{className:`mt-1 flex items-center gap-1.5 text-[11px]`,style:{color:`var(--text-tertiary)`},children:[(0,b.jsxs)(`span`,{children:[e.entries.length,` 条`]}),(0,b.jsx)(`span`,{style:{opacity:.4},children:`·`}),(0,b.jsx)(`span`,{className:`truncate`,children:m(e.createdAt)})]})]})]},e.id)})})]})]})}var S={user:{label:`用户`,dotClass:`role-dot role-dot--user`,bubbleClass:`msg-bubble--user`},assistant:{label:`助手`,dotClass:`role-dot role-dot--assistant`,bubbleClass:`msg-bubble--assistant`},tool:{label:`工具`,dotClass:`role-dot role-dot--tool`,bubbleClass:`msg-bubble--tool`},system:{label:`系统`,dotClass:`role-dot role-dot--system`,bubbleClass:``}};function C({entry:e}){let t=d(e),n=S[t],r=f(e),i=t===`tool`||r.length>320;return(0,b.jsxs)(`article`,{className:`flex gap-3`,children:[(0,b.jsx)(`div`,{className:`pt-1.5`,children:(0,b.jsx)(`span`,{className:n.dotClass,"aria-hidden":`true`})}),(0,b.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,b.jsxs)(`div`,{className:`mb-1.5 flex items-center gap-2 text-[11px] font-medium`,style:{color:`var(--text-tertiary)`},children:[(0,b.jsx)(`span`,{style:{color:`var(--role-${t})`},children:n.label}),e.tool?(0,b.jsx)(`span`,{className:`chip !py-0 !text-[10px]`,children:e.tool}):null,(0,b.jsx)(`span`,{className:`ml-auto shrink-0`,children:m(e.timestamp)})]}),i?(0,b.jsx)(`pre`,{className:`msg-bubble ${n.bubbleClass} mono m-0 max-h-[480px] overflow-auto px-3.5 py-2.5 text-[12px]`,style:{color:`var(--text-secondary)`},children:r}):(0,b.jsx)(`div`,{className:`msg-bubble ${n.bubbleClass} whitespace-pre-wrap break-words px-3.5 py-2.5 text-[13.5px] leading-relaxed`,style:{color:`var(--text-primary)`},children:r})]})]})}var te=[{value:`all`,label:`全部`},{value:`user`,label:`用户`},{value:`assistant`,label:`助手`},{value:`tool`,label:`工具`}];function ne({session:e}){let t=[[`消息`,`${e.entries.length}`],[`tokens`,e.stats?.totalTokens?.toLocaleString()??`0`],[`成本`,`$${(e.stats?.costTotal??0).toFixed(3)}`],[`目录`,e.cwd]];return(0,b.jsx)(`div`,{className:`flex flex-wrap items-center gap-1.5`,children:t.map(([e,t])=>(0,b.jsxs)(`span`,{className:`chip max-w-[240px] truncate`,children:[(0,b.jsx)(`span`,{style:{opacity:.6},children:e}),(0,b.jsx)(`span`,{className:`truncate`,children:t})]},e))})}function re({facts:e}){return e.length===0?null:(0,b.jsxs)(`section`,{className:`mt-8`,children:[(0,b.jsx)(`div`,{className:`mb-3 text-[11px] font-medium uppercase tracking-wider`,style:{color:`var(--text-tertiary)`},children:`事实`}),(0,b.jsx)(`div`,{className:`grid gap-2 sm:grid-cols-2 lg:grid-cols-3`,children:e.slice(0,12).map((e,t)=>(0,b.jsxs)(`div`,{className:`msg-bubble px-3 py-2.5`,children:[(0,b.jsx)(`div`,{className:`text-[11px]`,style:{color:`var(--text-tertiary)`},children:e.kind}),(0,b.jsx)(`div`,{className:`mt-0.5 truncate text-[13px]`,style:{color:`var(--text-primary)`},children:e.value||e.key||String(e.seq)})]},`${e.seq}-${t}`))})]})}var w=e=>typeof e==`string`?e:e&&typeof e==`object`?JSON.stringify(e,null,2):String(e??``);function ie({records:e}){return e.length===0?null:(0,b.jsxs)(`section`,{className:`mt-8`,children:[(0,b.jsxs)(`div`,{className:`mb-3 text-[11px] font-medium uppercase tracking-wider`,style:{color:`var(--text-tertiary)`},children:[`运行记录 · 最近 `,Math.min(20,e.length),` 条`]}),(0,b.jsx)(`div`,{className:`flex flex-col gap-1.5`,children:e.slice(-20).reverse().map(e=>(0,b.jsxs)(`div`,{className:`msg-bubble px-3 py-2.5`,children:[(0,b.jsxs)(`div`,{className:`flex items-center justify-between gap-2 text-[11px]`,style:{color:`var(--text-tertiary)`},children:[(0,b.jsxs)(`span`,{className:`truncate`,children:[e.type,e.opKind?` / ${e.opKind}`:``]}),(0,b.jsx)(`span`,{className:`shrink-0`,children:m(e.timestamp)})]}),(0,b.jsx)(`div`,{className:`mt-1.5 max-h-40 overflow-auto whitespace-pre-wrap break-words mono`,style:{color:`var(--text-secondary)`},children:w(e.payload)})]},e.id))})]})}function ae({session:e,filter:t,onFilterChange:n}){let r=e?_(e.entries,t):[];return(0,b.jsxs)(`main`,{className:`main-panel`,children:[(0,b.jsxs)(`header`,{className:`flex flex-col gap-3 px-6 pt-5 pb-4`,children:[(0,b.jsx)(`h2`,{className:`truncate text-[15px] font-semibold leading-snug`,style:{color:`var(--text-primary)`},children:e?p(e):`暂无会话`}),e?(0,b.jsx)(ne,{session:e}):null]}),(0,b.jsx)(`div`,{className:`flex items-center gap-3 border-t px-6 py-2.5`,style:{borderColor:`rgb(var(--panel-border))`},children:(0,b.jsx)(`div`,{className:`segmented`,role:`tablist`,"aria-label":`消息过滤`,children:te.map(e=>(0,b.jsx)(`button`,{type:`button`,role:`tab`,"aria-pressed":t===e.value,onClick:()=>n(e.value),children:e.label},e.value))})}),(0,b.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-6 py-6`,children:(0,b.jsx)(`div`,{className:`mx-auto max-w-[760px]`,children:e?r.length===0?(0,b.jsx)(`div`,{className:`grid min-h-[200px] place-items-center text-[13px]`,style:{color:`var(--text-tertiary)`},children:`没有匹配的消息`}):(0,b.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[r.map(e=>(0,b.jsx)(C,{entry:e},e.id)),e.facts?(0,b.jsx)(re,{facts:e.facts}):null,e.records?(0,b.jsx)(ie,{records:e.records}):null]}):(0,b.jsx)(`div`,{className:`grid min-h-[200px] place-items-center text-[13px]`,style:{color:`var(--text-tertiary)`},children:`暂无会话数据`})})})]})}var oe=`/ws`,se=8e3,ce=5e3,le=e=>{if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.id==`string`&&typeof t.createdAt==`string`&&typeof t.cwd==`string`&&Array.isArray(t.entries)},ue=e=>{if(!e||typeof e!=`object`)return!1;let t=e;return t.schemaVersion===1&&typeof t.exportedAt==`string`&&Array.isArray(t.sessions)&&t.sessions.every(le)},T=e=>{if(!e||typeof e!=`object`)return null;let t=e;return t.type===`sessions.snapshot`&&ue(t.data)?t.data:null},E=e=>{if(e)return e;let t=new URLSearchParams(window.location.search);return(t.get(`ws`)??t.get(`wsUrl`))||`${window.location.protocol===`https:`?`wss:`:`ws:`}//${window.location.host}${oe}`},de=e=>{let{onSnapshot:t,url:n,timeoutMs:r=se,refreshMs:i=ce}=e,a=!1,o=null,s=null,c=null,l=null,u=0,d=!1,f=()=>void 0,p=new Promise(e=>{f=e}),m=e=>{d||(d=!0,f(e))},h=()=>{s&&clearTimeout(s),c&&clearTimeout(c),l&&clearTimeout(l),s=null,c=null,l=null},g=()=>{if(h(),!o)return;let e=o;o=null,e.onopen=null,e.onmessage=null,e.onerror=null,e.onclose=null,e.close()},_=()=>{a||(c=setTimeout(()=>{o?.send(JSON.stringify({type:`sessions.list`})),_()},i))},v=()=>{if(a)return;let e=Math.min(1e3*2**u,15e3);u+=1,l=setTimeout(()=>{l=null,b()},e)},y=()=>{s&&clearTimeout(s),s=setTimeout(()=>{g(),m(null),v()},r)},b=()=>{if(a)return;let e;try{e=new WebSocket(E(n))}catch{v();return}o=e,y(),e.onopen=()=>{u=0,e.send(JSON.stringify({type:`sessions.list`})),_()},e.onmessage=e=>{let n;try{n=JSON.parse(String(e.data))}catch{return}let r=T(n);r&&(y(),t(r),m(r))},e.onerror=()=>{},e.onclose=()=>{o===e&&(g(),m(null),a||v())}};return b(),{ready:p,close(){a=!0,h(),g()}}},fe=`call-code-theme`,pe=()=>localStorage.getItem(fe)===`light`?`light`:`dark`;function me(){let[e,t]=(0,l.useState)(null),[n,r]=(0,l.useState)(`loading`),[i,a]=(0,l.useState)(pe),[o,s]=(0,l.useState)(null),[c,u]=(0,l.useState)(``),[d,f]=(0,l.useState)(`all`);(0,l.useEffect)(()=>{let e=!1,n=de({onSnapshot:n=>{e||(t(n),r(`ready`),s(e=>[new URLSearchParams(window.location.search).get(`session`),e,n.sessions[0]?.id??null].find(e=>e!=null&&n.sessions.some(t=>t.id===e))??null))}});return n.ready.then(t=>{e||r(t?`ready`:`error`)}),()=>{e=!0,n.close()}},[]),(0,l.useEffect)(()=>{document.documentElement.classList.toggle(`dark`,i===`dark`),localStorage.setItem(fe,i)},[i]);let p=(0,l.useMemo)(()=>e?.sessions??[],[e]),m=(0,l.useMemo)(()=>g(p,c),[p,c]),h=(0,l.useMemo)(()=>m.find(e=>e.id===o)??m[0]??null,[m,o]);return n===`loading`?(0,b.jsx)(`div`,{className:`app-shell`,children:(0,b.jsx)(`div`,{className:`grid min-h-[60vh] place-items-center text-sm`,style:{color:`var(--text-tertiary)`},children:`正在读取会话`})}):n===`error`||!e?(0,b.jsx)(`div`,{className:`app-shell`,children:(0,b.jsx)(`div`,{className:`grid min-h-[60vh] place-items-center text-sm`,style:{color:`var(--text-tertiary)`},children:`无法读取会话数据`})}):(0,b.jsx)(`div`,{className:`app-shell`,children:(0,b.jsxs)(`div`,{className:`app-frame`,children:[(0,b.jsx)(x,{sessions:m,theme:i,onThemeChange:a}),(0,b.jsxs)(`div`,{className:`app-workspace`,children:[(0,b.jsx)(ee,{sessions:m,activeId:o,query:c,onSelect:s,onQueryChange:u}),(0,b.jsx)(ae,{session:h,filter:d,onFilterChange:f})]})]})})}var D=document.getElementById(`root`);if(!D)throw Error(`未找到 #root 容器`);(0,u.createRoot)(D).render((0,b.jsx)(l.StrictMode,{children:(0,b.jsx)(me,{})})); \ No newline at end of file diff --git a/packages/client/dist/index.html b/packages/client/dist/index.html index de6e9dc..7959372 100644 --- a/packages/client/dist/index.html +++ b/packages/client/dist/index.html @@ -4,8 +4,8 @@ Call Code History - - + +
diff --git a/packages/client/src/App.tsx b/packages/client/src/App.tsx index e2c52c9..56fb587 100644 --- a/packages/client/src/App.tsx +++ b/packages/client/src/App.tsx @@ -92,32 +92,6 @@ export default function App() { [filteredSessions, activeId], ); - if (loadState === 'loading') { - return ( -
-
- 正在读取会话 -
-
- ); - } - - if (loadState === 'error' || !data) { - return ( -
-
- 无法读取会话数据 -
-
- ); - } - return (
@@ -126,6 +100,7 @@ export default function App() { sessions={filteredSessions} theme={theme} onThemeChange={setTheme} + connectionState={loadState} />
void; + connectionState?: 'loading' | 'ready' | 'error'; } -export function HeaderBar({ sessions, theme, onThemeChange }: HeaderBarProps) { +export function HeaderBar({ + sessions, + theme, + onThemeChange, + connectionState = 'ready', +}: HeaderBarProps) { const count = sessions.reduce( (acc, session) => { acc.messages += session.entries.length; @@ -47,6 +53,14 @@ export function HeaderBar({ sessions, theme, onThemeChange }: HeaderBarProps) { {sessions.length} 个会话 · {count.messages} 条消息 · {count.tools}{' '} 次工具
+
+
diff --git a/packages/client/src/global.css b/packages/client/src/global.css index f4dd065..782b218 100644 --- a/packages/client/src/global.css +++ b/packages/client/src/global.css @@ -167,7 +167,7 @@ body { .particle { position: absolute; - color: rgb(var(--glow-1) / 0.2); + color: rgb(255 255 255 / 0.42); font-family: var(--font-mono); font-size: 10px; animation: drift 16s ease-in-out infinite; @@ -235,6 +235,37 @@ body { letter-spacing: 0.08em; } +.connection-state { + display: flex; + align-items: center; + gap: 5px; + margin-top: 4px; + color: var(--text-tertiary); + font-family: var(--font-mono); + font-size: 9px; +} + +.connection-state > span { + width: 5px; + height: 5px; + border-radius: 999px; + background: var(--role-assistant); + box-shadow: 0 0 0 3px rgb(var(--glow-1) / 0.08); +} + +.connection-state--loading > span { + background: #c28d45; + animation: pulse 1.4s ease-in-out infinite; +} + +.connection-state--error > span { + background: #b66d58; +} + +@keyframes pulse { + 50% { opacity: 0.35; transform: scale(0.75); } +} + @media (min-width: 1024px) { .header-bar { padding: 12px 18px; diff --git a/tests/client-ui.spec.ts b/tests/client-ui.spec.ts index 98b1669..e09e85d 100644 --- a/tests/client-ui.spec.ts +++ b/tests/client-ui.spec.ts @@ -81,4 +81,19 @@ describe('client HeaderBar', () => { expect(html).toContain('2 次工具'); expect(html).toContain('毛玻璃'); }); + + it('服务未连接时仍显示完整界面状态', () => { + const html = renderToStaticMarkup( + React.createElement(HeaderBar, { + sessions: [], + theme: 'frosted', + connectionState: 'error', + onThemeChange: () => undefined, + }), + ); + + expect(html).toContain('Call Code'); + expect(html).toContain('等待会话服务'); + expect(html).toContain('杏色毛玻璃'); + }); }); From 36bbf2d779d84dd1e7dd53aca3613c0e5ba11b3a Mon Sep 17 00:00:00 2001 From: AlkaidSTART <2595006848@qq.com> Date: Sun, 23 Aug 2026 18:46:34 +0800 Subject: [PATCH 06/10] =?UTF-8?q?feat:=20=E9=87=8D=E6=9E=84=E7=BD=91?= =?UTF-8?q?=E9=A1=B5UI=E4=B8=BA=E6=9E=81=E7=AE=80=E9=A3=8E=E6=A0=BC?= =?UTF-8?q?=E5=B9=B6=E5=AE=9E=E7=8E=B0CALL=20CODE=E7=B2=92=E5=AD=90?= =?UTF-8?q?=E5=8A=A8=E7=94=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/client/dist/assets/index-CjSeRC_-.js | 9 + .../client/dist/assets/index-UIvzZf6_.css | 2 + packages/client/dist/index.html | 4 +- packages/client/src/App.tsx | 11 +- packages/client/src/components/HeaderBar.tsx | 48 +-- .../client/src/components/ParticleField.tsx | 203 ++++++++-- packages/client/src/global.css | 348 ++++++------------ packages/client/src/types.ts | 2 +- tests/client-ui.spec.ts | 11 +- 9 files changed, 333 insertions(+), 305 deletions(-) create mode 100644 packages/client/dist/assets/index-CjSeRC_-.js create mode 100644 packages/client/dist/assets/index-UIvzZf6_.css diff --git a/packages/client/dist/assets/index-CjSeRC_-.js b/packages/client/dist/assets/index-CjSeRC_-.js new file mode 100644 index 0000000..f409ccb --- /dev/null +++ b/packages/client/dist/assets/index-CjSeRC_-.js @@ -0,0 +1,9 @@ +var e=(e,t)=>()=>(t||(e((t={exports:{}}).exports,t),e=null),t.exports);(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var t=e((e=>{var t=Symbol.for(`react.transitional.element`),n=Symbol.for(`react.portal`),r=Symbol.for(`react.fragment`),i=Symbol.for(`react.strict_mode`),a=Symbol.for(`react.profiler`),o=Symbol.for(`react.consumer`),s=Symbol.for(`react.context`),c=Symbol.for(`react.forward_ref`),l=Symbol.for(`react.suspense`),u=Symbol.for(`react.memo`),d=Symbol.for(`react.lazy`),f=Symbol.for(`react.activity`),p=Symbol.iterator;function m(e){return typeof e!=`object`||!e?null:(e=p&&e[p]||e[`@@iterator`],typeof e==`function`?e:null)}var h={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},g=Object.assign,_={};function v(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}v.prototype.isReactComponent={},v.prototype.setState=function(e,t){if(typeof e!=`object`&&typeof e!=`function`&&e!=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,e,t,`setState`)},v.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,`forceUpdate`)};function y(){}y.prototype=v.prototype;function b(e,t,n){this.props=e,this.context=t,this.refs=_,this.updater=n||h}var x=b.prototype=new y;x.constructor=b,g(x,v.prototype),x.isPureReactComponent=!0;var ee=Array.isArray;function S(){}var C={H:null,A:null,T:null,S:null},te=Object.prototype.hasOwnProperty;function ne(e,n,r){var i=r.ref;return{$$typeof:t,type:e,key:n,ref:i===void 0?null:i,props:r}}function re(e,t){return ne(e.type,t,e.props)}function w(e){return typeof e==`object`&&!!e&&e.$$typeof===t}function ie(e){var t={"=":`=0`,":":`=2`};return`$`+e.replace(/[=:]/g,function(e){return t[e]})}var ae=/\/+/g;function oe(e,t){return typeof e==`object`&&e&&e.key!=null?ie(``+e.key):t.toString(36)}function se(e){switch(e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason;default:switch(typeof e.status==`string`?e.then(S,S):(e.status=`pending`,e.then(function(t){e.status===`pending`&&(e.status=`fulfilled`,e.value=t)},function(t){e.status===`pending`&&(e.status=`rejected`,e.reason=t)})),e.status){case`fulfilled`:return e.value;case`rejected`:throw e.reason}}throw e}function ce(e,r,i,a,o){var s=typeof e;(s===`undefined`||s===`boolean`)&&(e=null);var c=!1;if(e===null)c=!0;else switch(s){case`bigint`:case`string`:case`number`:c=!0;break;case`object`:switch(e.$$typeof){case t:case n:c=!0;break;case d:return c=e._init,ce(c(e._payload),r,i,a,o)}}if(c)return o=o(e),c=a===``?`.`+oe(e,0):a,ee(o)?(i=``,c!=null&&(i=c.replace(ae,`$&/`)+`/`),ce(o,r,i,``,function(e){return e})):o!=null&&(w(o)&&(o=re(o,i+(o.key==null||e&&e.key===o.key?``:(``+o.key).replace(ae,`$&/`)+`/`)+c)),r.push(o)),1;c=0;var l=a===``?`.`:a+`:`;if(ee(e))for(var u=0;u{n.exports=t()})),r=e((e=>{function t(e,t){var n=e.length;e.push(t);a:for(;0>>1,a=e[r];if(0>>1;ri(c,n))li(u,c)?(e[r]=u,e[l]=n,r=l):(e[r]=c,e[s]=n,r=s);else if(li(u,n))e[r]=u,e[l]=n,r=l;else break a}}return t}function i(e,t){var n=e.sortIndex-t.sortIndex;return n===0?e.id-t.id:n}if(e.unstable_now=void 0,typeof performance==`object`&&typeof performance.now==`function`){var a=performance;e.unstable_now=function(){return a.now()}}else{var o=Date,s=o.now();e.unstable_now=function(){return o.now()-s}}var c=[],l=[],u=1,d=null,f=3,p=!1,m=!1,h=!1,g=!1,_=typeof setTimeout==`function`?setTimeout:null,v=typeof clearTimeout==`function`?clearTimeout:null,y=typeof setImmediate<`u`?setImmediate:null;function b(e){for(var i=n(l);i!==null;){if(i.callback===null)r(l);else if(i.startTime<=e)r(l),i.sortIndex=i.expirationTime,t(c,i);else break;i=n(l)}}function x(e){if(h=!1,b(e),!m){if(n(c)!==null)m=!0,ee||(ee=!0,w());else{var t=n(l);t!==null&&oe(x,t.startTime-e)}}}var ee=!1,S=-1,C=5,te=-1;function ne(){return g?!0:!(e.unstable_now()-tet&&ne());){var o=d.callback;if(typeof o==`function`){d.callback=null,f=d.priorityLevel;var s=o(d.expirationTime<=t);if(t=e.unstable_now(),typeof s==`function`){d.callback=s,b(t),i=!0;break b}d===n(c)&&r(c),b(t)}else r(c);d=n(c)}if(d!==null)i=!0;else{var u=n(l);u!==null&&oe(x,u.startTime-t),i=!1}}break a}finally{d=null,f=a,p=!1}}}finally{i?w():ee=!1}}}var w;if(typeof y==`function`)w=function(){y(re)};else if(typeof MessageChannel<`u`){var ie=new MessageChannel,ae=ie.port2;ie.port1.onmessage=re,w=function(){ae.postMessage(null)}}else w=function(){_(re,0)};function oe(t,n){S=_(function(){t(e.unstable_now())},n)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(e){e.callback=null},e.unstable_forceFrameRate=function(e){0>e||125o?(r.sortIndex=a,t(l,r),n(c)===null&&r===n(l)&&(h?(v(S),S=-1):h=!0,oe(x,a-o))):(r.sortIndex=s,t(c,r),m||p||(m=!0,ee||(ee=!0,w()))),r},e.unstable_shouldYield=ne,e.unstable_wrapCallback=function(e){var t=f;return function(){var n=f;f=t;try{return e.apply(this,arguments)}finally{f=n}}}})),i=e(((e,t)=>{t.exports=r()})),a=e((e=>{var t=n();function r(e){var t=`https://react.dev/errors/`+e;if(1{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=a()})),s=e((e=>{var t=i(),r=n(),a=o();function s(e){var t=`https://react.dev/errors/`+e;if(1pe||(e.current=fe[pe],fe[pe]=null,pe--)}function O(e,t){pe++,fe[pe]=e.current,e.current=t}var he=me(null),ge=me(null),_e=me(null),ve=me(null);function ye(e,t){switch(O(_e,t),O(ge,e),O(he,null),t.nodeType){case 9:case 11:e=(e=t.documentElement)&&(e=e.namespaceURI)?Vd(e):0;break;default:if(e=t.tagName,t=t.namespaceURI)t=Vd(t),e=Hd(t,e);else switch(e){case`svg`:e=1;break;case`math`:e=2;break;default:e=0}}D(he),O(he,e)}function be(){D(he),D(ge),D(_e)}function xe(e){e.memoizedState!==null&&O(ve,e);var t=he.current,n=Hd(t,e.type);t!==n&&(O(ge,e),O(he,n))}function Se(e){ge.current===e&&(D(he),D(ge)),ve.current===e&&(D(ve),Qf._currentValue=de)}var Ce,we;function Te(e){if(Ce===void 0)try{throw Error()}catch(e){var t=e.stack.trim().match(/\n( *(at )?)/);Ce=t&&t[1]||``,we=-1)`:-1i||c[r]!==l[i]){var u=` +`+c[r].replace(` at new `,` at `);return e.displayName&&u.includes(``)&&(u=u.replace(``,e.displayName)),u}while(1<=r&&0<=i);break}}}finally{Ee=!1,Error.prepareStackTrace=n}return(n=e?e.displayName||e.name:``)?Te(n):``}function Oe(e,t){switch(e.tag){case 26:case 27:case 5:return Te(e.type);case 16:return Te(`Lazy`);case 13:return e.child!==t&&t!==null?Te(`Suspense Fallback`):Te(`Suspense`);case 19:return Te(`SuspenseList`);case 0:case 15:return De(e.type,!1);case 11:return De(e.type.render,!1);case 1:return De(e.type,!0);case 31:return Te(`Activity`);default:return``}}function ke(e){try{var t=``,n=null;do t+=Oe(e,n),n=e,e=e.return;while(e);return t}catch(e){return` +Error generating stack: `+e.message+` +`+e.stack}}var Ae=Object.prototype.hasOwnProperty,je=t.unstable_scheduleCallback,Me=t.unstable_cancelCallback,Ne=t.unstable_shouldYield,Pe=t.unstable_requestPaint,Fe=t.unstable_now,Ie=t.unstable_getCurrentPriorityLevel,Le=t.unstable_ImmediatePriority,Re=t.unstable_UserBlockingPriority,ze=t.unstable_NormalPriority,Be=t.unstable_LowPriority,Ve=t.unstable_IdlePriority,He=t.log,Ue=t.unstable_setDisableYieldValue,We=null,Ge=null;function Ke(e){if(typeof He==`function`&&Ue(e),Ge&&typeof Ge.setStrictMode==`function`)try{Ge.setStrictMode(We,e)}catch{}}var qe=Math.clz32?Math.clz32:Xe,Je=Math.log,Ye=Math.LN2;function Xe(e){return e>>>=0,e===0?32:31-(Je(e)/Ye|0)|0}var Ze=256,Qe=262144,$e=4194304;function et(e){var t=e&42;if(t!==0)return t;switch(e&-e){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 e&261888;case 262144:case 524288:case 1048576:case 2097152:return e&3932160;case 4194304:case 8388608:case 16777216:case 33554432:return e&62914560;case 67108864:return 67108864;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 0;default:return e}}function tt(e,t,n){var r=e.pendingLanes;if(r===0)return 0;var i=0,a=e.suspendedLanes,o=e.pingedLanes;e=e.warmLanes;var s=r&134217727;return s===0?(s=r&~a,s===0?o===0?n||(n=r&~e,n!==0&&(i=et(n))):i=et(o):i=et(s)):(r=s&~a,r===0?(o&=s,o===0?n||(n=s&~e,n!==0&&(i=et(n))):i=et(o)):i=et(r)),i===0?0:t!==0&&t!==i&&(t&a)===0&&(a=i&-i,n=t&-t,a>=n||a===32&&n&4194048)?t:i}function nt(e,t){return(e.pendingLanes&~(e.suspendedLanes&~e.pingedLanes)&t)===0}function rt(e,t){switch(e){case 1:case 2:case 4:case 8:case 64:return t+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 t+5e3;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 it(){var e=$e;return $e<<=1,!($e&62914560)&&($e=4194304),e}function at(e){for(var t=[],n=0;31>n;n++)t.push(e);return t}function ot(e,t){e.pendingLanes|=t,t!==268435456&&(e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0)}function st(e,t,n,r,i,a){var o=e.pendingLanes;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=n,e.entangledLanes&=n,e.errorRecoveryDisabledLanes&=n,e.shellSuspendCounter=0;var s=e.entanglements,c=e.expirationTimes,l=e.hiddenUpdates;for(n=o&~n;0`u`||window.document===void 0||window.document.createElement===void 0),yn=!1;if(vn)try{var bn={};Object.defineProperty(bn,"passive",{get:function(){yn=!0}}),window.addEventListener(`test`,bn,bn),window.removeEventListener(`test`,bn,bn)}catch{yn=!1}var xn=null,Sn=null,Cn=null;function wn(){if(Cn)return Cn;var e,t=Sn,n=t.length,r,i=`value`in xn?xn.value:xn.textContent,a=i.length;for(e=0;e=nr),ar=` `,or=!1;function sr(e,t){switch(e){case`keyup`:return er.indexOf(t.keyCode)!==-1;case`keydown`:return t.keyCode!==229;case`keypress`:case`mousedown`:case`focusout`:return!0;default:return!1}}function cr(e){return e=e.detail,typeof e==`object`&&`data`in e?e.data:null}var lr=!1;function ur(e,t){switch(e){case`compositionend`:return cr(t);case`keypress`:return t.which===32?(or=!0,ar):null;case`textInput`:return e=t.data,e===ar&&or?null:e;default:return null}}function dr(e,t){if(lr)return e===`compositionend`||!tr&&sr(e,t)?(e=wn(),Cn=Sn=xn=null,lr=!1,e):null;switch(e){case`paste`:return null;case`keypress`:if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}a:{for(;n;){if(n.nextSibling){n=n.nextSibling;break a}n=n.parentNode}n=void 0}n=Nr(n)}}function Fr(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?Fr(e,t.parentNode):`contains`in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Ir(e){e=e!=null&&e.ownerDocument!=null&&e.ownerDocument.defaultView!=null?e.ownerDocument.defaultView:window;for(var t=Gt(e.document);t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href==`string`}catch{n=!1}if(n)e=t.contentWindow;else break;t=Gt(e.document)}return t}function Lr(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t===`input`&&(e.type===`text`||e.type===`search`||e.type===`tel`||e.type===`url`||e.type===`password`)||t===`textarea`||e.contentEditable===`true`)}var Rr=vn&&`documentMode`in document&&11>=document.documentMode,zr=null,Br=null,Vr=null,Hr=!1;function Ur(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;Hr||zr==null||zr!==Gt(r)||(r=zr,`selectionStart`in r&&Lr(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),Vr&&Mr(Vr,r)||(Vr=r,r=Ed(Br,`onSelect`),0>=o,i-=o,Fi=1<<32-qe(t)+i|n<h?(g=d,d=null):g=d.sibling;var _=p(i,d,s[h],c);if(_===null){d===null&&(d=g);break}e&&d&&_.alternate===null&&t(i,d),o=a(_,o,h),u===null?l=_:u.sibling=_,u=_,d=g}if(h===s.length)return n(i,d),j&&Li(i,h),l;if(d===null){for(;hg?(_=h,h=null):_=h.sibling;var y=p(i,h,v.value,l);if(y===null){h===null&&(h=_);break}e&&h&&y.alternate===null&&t(i,h),o=a(y,o,g),d===null?u=y:d.sibling=y,d=y,h=_}if(v.done)return n(i,h),j&&Li(i,g),u;if(h===null){for(;!v.done;g++,v=c.next())v=f(i,v.value,l),v!==null&&(o=a(v,o,g),d===null?u=v:d.sibling=v,d=v);return j&&Li(i,g),u}for(h=r(h);!v.done;g++,v=c.next())v=m(h,i,g,v.value,l),v!==null&&(e&&v.alternate!==null&&h.delete(v.key===null?g:v.key),o=a(v,o,g),d===null?u=v:d.sibling=v,d=v);return e&&h.forEach(function(e){return t(i,e)}),j&&Li(i,g),u}function b(e,r,a,c){if(typeof a==`object`&&a&&a.type===y&&a.key===null&&(a=a.props.children),typeof a==`object`&&a){switch(a.$$typeof){case _:a:{for(var l=a.key;r!==null;){if(r.key===l){if(l=a.type,l===y){if(r.tag===7){n(e,r.sibling),c=i(r,a.props.children),c.return=e,e=c;break a}}else if(r.elementType===l||typeof l==`object`&&l&&l.$$typeof===w&&Fa(l)===r.type){n(e,r.sibling),c=i(r,a.props),Ha(c,a),c.return=e,e=c;break a}n(e,r);break}t(e,r),r=r.sibling}a.type===y?(c=Si(a.props.children,e.mode,c,a.key),c.return=e,e=c):(c=xi(a.type,a.key,a.props,null,e.mode,c),Ha(c,a),c.return=e,e=c)}return o(e);case v:a:{for(l=a.key;r!==null;){if(r.key===l){if(r.tag===4&&r.stateNode.containerInfo===a.containerInfo&&r.stateNode.implementation===a.implementation){n(e,r.sibling),c=i(r,a.children||[]),c.return=e,e=c;break a}n(e,r);break}t(e,r),r=r.sibling}c=Ti(a,e.mode,c),c.return=e,e=c}return o(e);case w:return a=Fa(a),b(e,r,a,c)}if(ue(a))return h(e,r,a,c);if(se(a)){if(l=se(a),typeof l!=`function`)throw Error(s(150));return a=l.call(a),g(e,r,a,c)}if(typeof a.then==`function`)return b(e,r,Va(a),c);if(a.$$typeof===S)return b(e,r,ua(e,a),c);Ua(e,a)}return typeof a==`string`&&a!==``||typeof a==`number`||typeof a==`bigint`?(a=``+a,r!==null&&r.tag===6?(n(e,r.sibling),c=i(r,a),c.return=e,e=c):(n(e,r),c=Ci(a,e.mode,c),c.return=e,e=c),o(e)):n(e,r)}return function(e,t,n,r){try{Ba=0;var i=b(e,t,n,r);return za=null,i}catch(t){if(t===ka||t===ja)throw t;var a=_i(29,t,null,e.mode);return a.lanes=r,a.return=e,a}}}var Ga=Wa(!0),Ka=Wa(!1),qa=!1;function Ja(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,lanes:0,hiddenCallbacks:null},callbacks:null}}function Ya(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,callbacks:null})}function Xa(e){return{lane:e,tag:0,payload:null,callback:null,next:null}}function Za(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,W&2){var i=r.pending;return i===null?t.next=t:(t.next=i.next,i.next=t),r.pending=t,t=mi(e),pi(e,null,n),t}return ui(e,r,t,n),mi(e)}function Qa(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,n&4194048)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,lt(e,n)}}function $a(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var i=null,a=null;if(n=n.firstBaseUpdate,n!==null){do{var o={lane:n.lane,tag:n.tag,payload:n.payload,callback:null,next:null};a===null?i=a=o:a=a.next=o,n=n.next}while(n!==null);a===null?i=a=t:a=a.next=t}else i=a=t;n={baseState:r.baseState,firstBaseUpdate:i,lastBaseUpdate:a,shared:r.shared,callbacks:r.callbacks},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}var eo=!1;function to(){if(eo){var e=ba;if(e!==null)throw e}}function no(e,t,n,r){eo=!1;var i=e.updateQueue;qa=!1;var a=i.firstBaseUpdate,o=i.lastBaseUpdate,s=i.shared.pending;if(s!==null){i.shared.pending=null;var c=s,l=c.next;c.next=null,o===null?a=l:o.next=l,o=c;var u=e.alternate;u!==null&&(u=u.updateQueue,s=u.lastBaseUpdate,s!==o&&(s===null?u.firstBaseUpdate=l:s.next=l,u.lastBaseUpdate=c))}if(a!==null){var d=i.baseState;o=0,u=l=c=null,s=a;do{var f=s.lane&-536870913,p=f!==s.lane;if(p?(q&f)===f:(r&f)===f){f!==0&&f===ya&&(eo=!0),u!==null&&(u=u.next={lane:0,tag:s.tag,payload:s.payload,callback:null,next:null});a:{var m=e,g=s;f=t;var _=n;switch(g.tag){case 1:if(m=g.payload,typeof m==`function`){d=m.call(_,d,f);break a}d=m;break a;case 3:m.flags=m.flags&-65537|128;case 0:if(m=g.payload,f=typeof m==`function`?m.call(_,d,f):m,f==null)break a;d=h({},d,f);break a;case 2:qa=!0}}f=s.callback,f!==null&&(e.flags|=64,p&&(e.flags|=8192),p=i.callbacks,p===null?i.callbacks=[f]:p.push(f))}else p={lane:f,tag:s.tag,payload:s.payload,callback:s.callback,next:null},u===null?(l=u=p,c=d):u=u.next=p,o|=f;if(s=s.next,s===null){if(s=i.shared.pending,s===null)break;p=s,s=p.next,p.next=null,i.lastBaseUpdate=p,i.shared.pending=null}}while(1);u===null&&(c=d),i.baseState=c,i.firstBaseUpdate=l,i.lastBaseUpdate=u,a===null&&(i.shared.lanes=0),Kl|=o,e.lanes=o,e.memoizedState=d}}function ro(e,t){if(typeof e!=`function`)throw Error(s(191,e));e.call(t)}function io(e,t){var n=e.callbacks;if(n!==null)for(e.callbacks=null,e=0;ea?a:8;var o=T.T,s={};T.T=s,zs(e,!1,t,n);try{var c=i(),l=T.S;l!==null&&l(s,c),typeof c==`object`&&c&&typeof c.then==`function`?Rs(e,t,Ca(c,r),pu(e)):Rs(e,t,r,pu(e))}catch(n){Rs(e,t,{then:function(){},status:`rejected`,reason:n},pu())}finally{E.p=a,o!==null&&s.types!==null&&(o.types=s.types),T.T=o}}function Os(){}function ks(e,t,n,r){if(e.tag!==5)throw Error(s(476));var i=As(e).queue;Ds(e,i,t,de,n===null?Os:function(){return js(e),n(r)})}function As(e){var t=e.memoizedState;if(t!==null)return t;t={memoizedState:de,baseState:de,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Bo,lastRenderedState:de},next:null};var n={};return t.next={memoizedState:n,baseState:n,baseQueue:null,queue:{pending:null,lanes:0,dispatch:null,lastRenderedReducer:Bo,lastRenderedState:n},next:null},e.memoizedState=t,e=e.alternate,e!==null&&(e.memoizedState=t),t}function js(e){var t=As(e);t.next===null&&(t=e.alternate.memoizedState),Rs(e,t.next.queue,{},pu())}function Ms(){return la(Qf)}function Ns(){return R().memoizedState}function Ps(){return R().memoizedState}function Fs(e){for(var t=e.return;t!==null;){switch(t.tag){case 24:case 3:var n=pu();e=Xa(n);var r=Za(t,e,n);r!==null&&(hu(r,t,n),Qa(r,t,n)),t={cache:ha()},e.payload=t;return}t=t.return}}function Is(e,t,n){var r=pu();n={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null},Bs(e)?Vs(t,n):(n=di(e,t,n,r),n!==null&&(hu(n,e,r),Hs(n,t,r)))}function Ls(e,t,n){Rs(e,t,n,pu())}function Rs(e,t,n,r){var i={lane:r,revertLane:0,gesture:null,action:n,hasEagerState:!1,eagerState:null,next:null};if(Bs(e))Vs(t,i);else{var a=e.alternate;if(e.lanes===0&&(a===null||a.lanes===0)&&(a=t.lastRenderedReducer,a!==null))try{var o=t.lastRenderedState,s=a(o,n);if(i.hasEagerState=!0,i.eagerState=s,jr(s,o))return ui(e,t,i,0),G===null&&li(),!1}catch{}if(n=di(e,t,i,r),n!==null)return hu(n,e,r),Hs(n,t,r),!0}return!1}function zs(e,t,n,r){if(r={lane:2,revertLane:dd(),gesture:null,action:r,hasEagerState:!1,eagerState:null,next:null},Bs(e)){if(t)throw Error(s(479))}else t=di(e,n,r,2),t!==null&&hu(t,e,2)}function Bs(e){var t=e.alternate;return e===P||t!==null&&t===P}function Vs(e,t){xo=bo=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function Hs(e,t,n){if(n&4194048){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,lt(e,n)}}var Us={readContext:la,use:Ro,useCallback:L,useContext:L,useEffect:L,useImperativeHandle:L,useLayoutEffect:L,useInsertionEffect:L,useMemo:L,useReducer:L,useRef:L,useState:L,useDebugValue:L,useDeferredValue:L,useTransition:L,useSyncExternalStore:L,useId:L,useHostTransitionStatus:L,useFormState:L,useActionState:L,useOptimistic:L,useMemoCache:L,useCacheRefresh:L};Us.useEffectEvent=L;var Ws={readContext:la,use:Ro,useCallback:function(e,t){return Fo().memoizedState=[e,t===void 0?null:t],e},useContext:la,useEffect:ms,useImperativeHandle:function(e,t,n){n=n==null?null:n.concat([e]),fs(4194308,4,bs.bind(null,t,e),n)},useLayoutEffect:function(e,t){return fs(4194308,4,e,t)},useInsertionEffect:function(e,t){fs(4,2,e,t)},useMemo:function(e,t){var n=Fo();t=t===void 0?null:t;var r=e();if(So){Ke(!0);try{e()}finally{Ke(!1)}}return n.memoizedState=[r,t],r},useReducer:function(e,t,n){var r=Fo();if(n!==void 0){var i=n(t);if(So){Ke(!0);try{n(t)}finally{Ke(!1)}}}else i=t;return r.memoizedState=r.baseState=i,e={pending:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:i},r.queue=e,e=e.dispatch=Is.bind(null,P,e),[r.memoizedState,e]},useRef:function(e){var t=Fo();return e={current:e},t.memoizedState=e},useState:function(e){e=Xo(e);var t=e.queue,n=Ls.bind(null,P,t);return t.dispatch=n,[e.memoizedState,n]},useDebugValue:Ss,useDeferredValue:function(e,t){return Ts(Fo(),e,t)},useTransition:function(){var e=Xo(!1);return e=Ds.bind(null,P,e.queue,!0,!1),Fo().memoizedState=e,[!1,e]},useSyncExternalStore:function(e,t,n){var r=P,i=Fo();if(j){if(n===void 0)throw Error(s(407));n=n()}else{if(n=t(),G===null)throw Error(s(349));q&127||Go(r,t,n)}i.memoizedState=n;var a={value:n,getSnapshot:t};return i.queue=a,ms(qo.bind(null,r,a,e),[e]),r.flags|=2048,us(9,{destroy:void 0},Ko.bind(null,r,a,n,t),null),n},useId:function(){var e=Fo(),t=G.identifierPrefix;if(j){var n=Ii,r=Fi;n=(r&~(1<<32-qe(r)-1)).toString(32)+n,t=`_`+t+`R_`+n,n=Co++,0<\/script>`,a=a.removeChild(a.firstChild);break;case`select`:a=typeof r.is==`string`?o.createElement(`select`,{is:r.is}):o.createElement(`select`),r.multiple?a.multiple=!0:r.size&&(a.size=r.size);break;default:a=typeof r.is==`string`?o.createElement(i,{is:r.is}):o.createElement(i)}}a[gt]=t,a[_t]=r;a:for(o=t.child;o!==null;){if(o.tag===5||o.tag===6)a.appendChild(o.stateNode);else if(o.tag!==4&&o.tag!==27&&o.child!==null){o.child.return=o,o=o.child;continue}if(o===t)break a;for(;o.sibling===null;){if(o.return===null||o.return===t)break a;o=o.return}o.sibling.return=o.return,o=o.sibling}t.stateNode=a;a:switch(Pd(a,i,r),i){case`button`:case`input`:case`select`:case`textarea`:r=!!r.autoFocus;break a;case`img`:r=!0;break a;default:r=!1}r&&Lc(t)}}return B(t),Rc(t,t.type,e===null?null:e.memoizedProps,t.pendingProps,n),null;case 6:if(e&&t.stateNode!=null)e.memoizedProps!==r&&Lc(t);else{if(typeof r!=`string`&&t.stateNode===null)throw Error(s(166));if(e=_e.current,Yi(t)){if(e=t.stateNode,n=t.memoizedProps,r=null,i=Hi,i!==null)switch(i.tag){case 27:case 5:r=i.memoizedProps}e[gt]=t,e=!!(e.nodeValue===n||r!==null&&!0===r.suppressHydrationWarning||Md(e.nodeValue,n)),e||Ki(t,!0)}else e=Bd(e).createTextNode(r),e[gt]=t,t.stateNode=e}return B(t),null;case 31:if(n=t.memoizedState,e===null||e.memoizedState!==null){if(r=Yi(t),n!==null){if(e===null){if(!r)throw Error(s(318));if(e=t.memoizedState,e=e===null?null:e.dehydrated,!e)throw Error(s(557));e[gt]=t}else Xi(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;B(t),e=!1}else n=Zi(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=n),e=!0;if(!e)return t.flags&256?(_o(t),t):(_o(t),null);if(t.flags&128)throw Error(s(558))}return B(t),null;case 13:if(r=t.memoizedState,e===null||e.memoizedState!==null&&e.memoizedState.dehydrated!==null){if(i=Yi(t),r!==null&&r.dehydrated!==null){if(e===null){if(!i)throw Error(s(318));if(i=t.memoizedState,i=i===null?null:i.dehydrated,!i)throw Error(s(317));i[gt]=t}else Xi(),!(t.flags&128)&&(t.memoizedState=null),t.flags|=4;B(t),i=!1}else i=Zi(),e!==null&&e.memoizedState!==null&&(e.memoizedState.hydrationErrors=i),i=!0;if(!i)return t.flags&256?(_o(t),t):(_o(t),null)}return _o(t),t.flags&128?(t.lanes=n,t):(n=r!==null,e=e!==null&&e.memoizedState!==null,n&&(r=t.child,i=null,r.alternate!==null&&r.alternate.memoizedState!==null&&r.alternate.memoizedState.cachePool!==null&&(i=r.alternate.memoizedState.cachePool.pool),a=null,r.memoizedState!==null&&r.memoizedState.cachePool!==null&&(a=r.memoizedState.cachePool.pool),a!==i&&(r.flags|=2048)),n!==e&&n&&(t.child.flags|=8192),Bc(t,t.updateQueue),B(t),null);case 4:return be(),e===null&&Sd(t.stateNode.containerInfo),B(t),null;case 10:return ra(t.type),B(t),null;case 19:if(D(N),r=t.memoizedState,r===null)return B(t),null;if(i=!!(t.flags&128),a=r.rendering,a===null){if(i)Vc(r,!1);else{if(Y!==0||e!==null&&e.flags&128)for(e=t.child;e!==null;){if(a=vo(e),a!==null){for(t.flags|=128,Vc(r,!1),e=a.updateQueue,t.updateQueue=e,Bc(t,e),t.subtreeFlags=0,e=n,n=t.child;n!==null;)bi(n,e),n=n.sibling;return O(N,N.current&1|2),j&&Li(t,r.treeForkCount),t.child}e=e.sibling}r.tail!==null&&Fe()>nu&&(t.flags|=128,i=!0,Vc(r,!1),t.lanes=4194304)}}else{if(!i){if(e=vo(a),e!==null){if(t.flags|=128,i=!0,e=e.updateQueue,t.updateQueue=e,Bc(t,e),Vc(r,!0),r.tail===null&&r.tailMode===`hidden`&&!a.alternate&&!j)return B(t),null}else 2*Fe()-r.renderingStartTime>nu&&n!==536870912&&(t.flags|=128,i=!0,Vc(r,!1),t.lanes=4194304)}r.isBackwards?(a.sibling=t.child,t.child=a):(e=r.last,e===null?t.child=a:e.sibling=a,r.last=a)}return r.tail===null?(B(t),null):(e=r.tail,r.rendering=e,r.tail=e.sibling,r.renderingStartTime=Fe(),e.sibling=null,n=N.current,O(N,i?n&1|2:n&1),j&&Li(t,r.treeForkCount),e);case 22:case 23:return _o(t),lo(),r=t.memoizedState!==null,e===null?r&&(t.flags|=8192):e.memoizedState!==null!==r&&(t.flags|=8192),r?n&536870912&&!(t.flags&128)&&(B(t),t.subtreeFlags&6&&(t.flags|=8192)):B(t),n=t.updateQueue,n!==null&&Bc(t,n.retryQueue),n=null,e!==null&&e.memoizedState!==null&&e.memoizedState.cachePool!==null&&(n=e.memoizedState.cachePool.pool),r=null,t.memoizedState!==null&&t.memoizedState.cachePool!==null&&(r=t.memoizedState.cachePool.pool),r!==n&&(t.flags|=2048),e!==null&&D(Ta),null;case 24:return n=null,e!==null&&(n=e.memoizedState.cache),t.memoizedState.cache!==n&&(t.flags|=2048),ra(M),B(t),null;case 25:return null;case 30:return null}throw Error(s(156,t.tag))}function Uc(e,t){switch(Bi(t),t.tag){case 1:return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return ra(M),be(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 26:case 27:case 5:return Se(t),null;case 31:if(t.memoizedState!==null){if(_o(t),t.alternate===null)throw Error(s(340));Xi()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 13:if(_o(t),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(s(340));Xi()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return D(N),null;case 4:return be(),null;case 10:return ra(t.type),null;case 22:case 23:return _o(t),lo(),e!==null&&D(Ta),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 24:return ra(M),null;case 25:return null;default:return null}}function Wc(e,t){switch(Bi(t),t.tag){case 3:ra(M),be();break;case 26:case 27:case 5:Se(t);break;case 4:be();break;case 31:t.memoizedState!==null&&_o(t);break;case 13:_o(t);break;case 19:D(N);break;case 10:ra(t.type);break;case 22:case 23:_o(t),lo(),e!==null&&D(Ta);break;case 24:ra(M)}}function Gc(e,t){try{var n=t.updateQueue,r=n===null?null:n.lastEffect;if(r!==null){var i=r.next;n=i;do{if((n.tag&e)===e){r=void 0;var a=n.create,o=n.inst;r=a(),o.destroy=r}n=n.next}while(n!==i)}}catch(e){Z(t,t.return,e)}}function Kc(e,t,n){try{var r=t.updateQueue,i=r===null?null:r.lastEffect;if(i!==null){var a=i.next;r=a;do{if((r.tag&e)===e){var o=r.inst,s=o.destroy;if(s!==void 0){o.destroy=void 0,i=t;var c=n,l=s;try{l()}catch(e){Z(i,c,e)}}}r=r.next}while(r!==a)}}catch(e){Z(t,t.return,e)}}function qc(e){var t=e.updateQueue;if(t!==null){var n=e.stateNode;try{io(t,n)}catch(t){Z(e,e.return,t)}}}function Jc(e,t,n){n.props=Zs(e.type,e.memoizedProps),n.state=e.memoizedState;try{n.componentWillUnmount()}catch(n){Z(e,t,n)}}function Yc(e,t){try{var n=e.ref;if(n!==null){switch(e.tag){case 26:case 27:case 5:var r=e.stateNode;break;case 30:r=e.stateNode;break;default:r=e.stateNode}typeof n==`function`?e.refCleanup=n(r):n.current=r}}catch(n){Z(e,t,n)}}function Xc(e,t){var n=e.ref,r=e.refCleanup;if(n!==null){if(typeof r==`function`)try{r()}catch(n){Z(e,t,n)}finally{e.refCleanup=null,e=e.alternate,e!=null&&(e.refCleanup=null)}else if(typeof n==`function`)try{n(null)}catch(n){Z(e,t,n)}else n.current=null}}function Zc(e){var t=e.type,n=e.memoizedProps,r=e.stateNode;try{a:switch(t){case`button`:case`input`:case`select`:case`textarea`:n.autoFocus&&r.focus();break a;case`img`:n.src?r.src=n.src:n.srcSet&&(r.srcset=n.srcSet)}}catch(t){Z(e,e.return,t)}}function Qc(e,t,n){try{var r=e.stateNode;Fd(r,e.type,n,t),r[_t]=t}catch(t){Z(e,e.return,t)}}function $c(e){return e.tag===5||e.tag===3||e.tag===26||e.tag===27&&Zd(e.type)||e.tag===4}function el(e){a:for(;;){for(;e.sibling===null;){if(e.return===null||$c(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.tag===27&&Zd(e.type)||e.flags&2||e.child===null||e.tag===4)continue a;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function tl(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?(n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n).insertBefore(e,t):(t=n.nodeType===9?n.body:n.nodeName===`HTML`?n.ownerDocument.body:n,t.appendChild(e),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=ln));else if(r!==4&&(r===27&&Zd(e.type)&&(n=e.stateNode,t=null),e=e.child,e!==null))for(tl(e,t,n),e=e.sibling;e!==null;)tl(e,t,n),e=e.sibling}function nl(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(r!==4&&(r===27&&Zd(e.type)&&(n=e.stateNode),e=e.child,e!==null))for(nl(e,t,n),e=e.sibling;e!==null;)nl(e,t,n),e=e.sibling}function rl(e){var t=e.stateNode,n=e.memoizedProps;try{for(var r=e.type,i=t.attributes;i.length;)t.removeAttributeNode(i[0]);Pd(t,r,n),t[gt]=e,t[_t]=n}catch(t){Z(e,e.return,t)}}var il=!1,V=!1,al=!1,ol=typeof WeakSet==`function`?WeakSet:Set,H=null;function sl(e,t){if(e=e.containerInfo,Rd=sp,e=Ir(e),Lr(e)){if(`selectionStart`in e)var n={start:e.selectionStart,end:e.selectionEnd};else a:{n=(n=e.ownerDocument)&&n.defaultView||window;var r=n.getSelection&&n.getSelection();if(r&&r.rangeCount!==0){n=r.anchorNode;var i=r.anchorOffset,a=r.focusNode;r=r.focusOffset;try{n.nodeType,a.nodeType}catch{n=null;break a}var o=0,c=-1,l=-1,u=0,d=0,f=e,p=null;b:for(;;){for(var m;f!==n||i!==0&&f.nodeType!==3||(c=o+i),f!==a||r!==0&&f.nodeType!==3||(l=o+r),f.nodeType===3&&(o+=f.nodeValue.length),(m=f.firstChild)!==null;)p=f,f=m;for(;;){if(f===e)break b;if(p===n&&++u===i&&(c=o),p===a&&++d===r&&(l=o),(m=f.nextSibling)!==null)break;f=p,p=f.parentNode}f=m}n=c===-1||l===-1?null:{start:c,end:l}}else n=null}n||={start:0,end:0}}else n=null;for(zd={focusedElem:e,selectionRange:n},sp=!1,H=t;H!==null;)if(t=H,e=t.child,t.subtreeFlags&1028&&e!==null)e.return=t,H=e;else for(;H!==null;){switch(t=H,a=t.alternate,e=t.flags,t.tag){case 0:if(e&4&&(e=t.updateQueue,e=e===null?null:e.events,e!==null))for(n=0;n title`))),Pd(a,r,n),a[gt]=e,k(a),r=a;break a;case`link`:var o=Vf(`link`,`href`,i).get(r+(n.href||``));if(o){for(var c=0;cg&&(o=g,g=h,h=o);var _=Pr(s,h),v=Pr(s,g);if(_&&v&&(p.rangeCount!==1||p.anchorNode!==_.node||p.anchorOffset!==_.offset||p.focusNode!==v.node||p.focusOffset!==v.offset)){var y=d.createRange();y.setStart(_.node,_.offset),p.removeAllRanges(),h>g?(p.addRange(y),p.extend(v.node,v.offset)):(y.setEnd(v.node,v.offset),p.addRange(y))}}}}for(d=[],p=s;p=p.parentNode;)p.nodeType===1&&d.push({element:p,left:p.scrollLeft,top:p.scrollTop});for(typeof s.focus==`function`&&s.focus(),s=0;sn?32:n,T.T=null,n=lu,lu=null;var a=au,o=su;if(X=0,ou=au=null,su=0,W&6)throw Error(s(331));var c=W;if(W|=4,Il(a.current),Ol(a,a.current,o,n),W=c,id(0,!1),Ge&&typeof Ge.onPostCommitFiberRoot==`function`)try{Ge.onPostCommitFiberRoot(We,a)}catch{}return!0}finally{E.p=i,T.T=r,Vu(e,t)}}function Wu(e,t,n){t=Di(n,t),t=rc(e.stateNode,t,2),e=Za(e,t,2),e!==null&&(ot(e,2),rd(e))}function Z(e,t,n){if(e.tag===3)Wu(e,e,n);else for(;t!==null;){if(t.tag===3){Wu(t,e,n);break}if(t.tag===1){var r=t.stateNode;if(typeof t.type.getDerivedStateFromError==`function`||typeof r.componentDidCatch==`function`&&(iu===null||!iu.has(r))){e=Di(n,e),n=ic(2),r=Za(t,n,2),r!==null&&(ac(n,r,t,e),ot(r,2),rd(r));break}}t=t.return}}function Gu(e,t,n){var r=e.pingCache;if(r===null){r=e.pingCache=new Bl;var i=new Set;r.set(t,i)}else i=r.get(t),i===void 0&&(i=new Set,r.set(t,i));i.has(n)||(Wl=!0,i.add(n),e=Ku.bind(null,e,t,n),t.then(e,e))}function Ku(e,t,n){var r=e.pingCache;r!==null&&r.delete(t),e.pingedLanes|=e.suspendedLanes&n,e.warmLanes&=~n,G===e&&(q&n)===n&&(Y===4||Y===3&&(q&62914560)===q&&300>Fe()-eu?!(W&2)&&Su(e,0):Jl|=n,Xl===q&&(Xl=0)),rd(e)}function qu(e,t){t===0&&(t=it()),e=fi(e,t),e!==null&&(ot(e,t),rd(e))}function Ju(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),qu(e,n)}function Yu(e,t){var n=0;switch(e.tag){case 31:case 13:var r=e.stateNode,i=e.memoizedState;i!==null&&(n=i.retryLane);break;case 19:r=e.stateNode;break;case 22:r=e.stateNode._retryCache;break;default:throw Error(s(314))}r!==null&&r.delete(t),qu(e,n)}function Xu(e,t){return je(e,t)}var Zu=null,Qu=null,$u=!1,ed=!1,td=!1,nd=0;function rd(e){e!==Qu&&e.next===null&&(Qu===null?Zu=Qu=e:Qu=Qu.next=e),ed=!0,$u||($u=!0,ud())}function id(e,t){if(!td&&ed){td=!0;do for(var n=!1,r=Zu;r!==null;){if(!t){if(e!==0){var i=r.pendingLanes;if(i===0)var a=0;else{var o=r.suspendedLanes,s=r.pingedLanes;a=(1<<31-qe(42|e)+1)-1,a&=i&~(o&~s),a=a&201326741?a&201326741|1:a?a|2:0}a!==0&&(n=!0,ld(r,a))}else a=q,a=tt(r,r===G?a:0,r.cancelPendingCommit!==null||r.timeoutHandle!==-1),!(a&3)||nt(r,a)||(n=!0,ld(r,a))}r=r.next}while(n);td=!1}}function ad(){od()}function od(){ed=$u=!1;var e=0;nd!==0&&Gd()&&(e=nd);for(var t=Fe(),n=null,r=Zu;r!==null;){var i=r.next,a=sd(r,t);a===0?(r.next=null,n===null?Zu=i:n.next=i,i===null&&(Qu=n)):(n=r,(e!==0||a&3)&&(ed=!0)),r=i}X!==0&&X!==5||id(e,!1),nd!==0&&(nd=0)}function sd(e,t){for(var n=e.suspendedLanes,r=e.pingedLanes,i=e.expirationTimes,a=e.pendingLanes&-62914561;0s)break;var u=c.transferSize,d=c.initiatorType;u&&Id(d)&&(c=c.responseEnd,o+=u*(c`u`?null:document;function xf(e,t,n){var r=bf;if(r&&typeof t==`string`&&t){var i=qt(t);i=`link[rel="`+e+`"][href="`+i+`"]`,typeof n==`string`&&(i+=`[crossorigin="`+n+`"]`),hf.has(i)||(hf.add(i),e={rel:e,crossOrigin:n,href:t},r.querySelector(i)===null&&(t=r.createElement(`link`),Pd(t,`link`,e),k(t),r.head.appendChild(t)))}}function Sf(e){_f.D(e),xf(`dns-prefetch`,e,null)}function Cf(e,t){_f.C(e,t),xf(`preconnect`,e,t)}function wf(e,t,n){_f.L(e,t,n);var r=bf;if(r&&e&&t){var i=`link[rel="preload"][as="`+qt(t)+`"]`;t===`image`&&n&&n.imageSrcSet?(i+=`[imagesrcset="`+qt(n.imageSrcSet)+`"]`,typeof n.imageSizes==`string`&&(i+=`[imagesizes="`+qt(n.imageSizes)+`"]`)):i+=`[href="`+qt(e)+`"]`;var a=i;switch(t){case`style`:a=Af(e);break;case`script`:a=Pf(e)}mf.has(a)||(e=h({rel:`preload`,href:t===`image`&&n&&n.imageSrcSet?void 0:e,as:t},n),mf.set(a,e),r.querySelector(i)!==null||t===`style`&&r.querySelector(jf(a))||t===`script`&&r.querySelector(Ff(a))||(t=r.createElement(`link`),Pd(t,`link`,e),k(t),r.head.appendChild(t)))}}function Tf(e,t){_f.m(e,t);var n=bf;if(n&&e){var r=t&&typeof t.as==`string`?t.as:`script`,i=`link[rel="modulepreload"][as="`+qt(r)+`"][href="`+qt(e)+`"]`,a=i;switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:a=Pf(e)}if(!mf.has(a)&&(e=h({rel:`modulepreload`,href:e},t),mf.set(a,e),n.querySelector(i)===null)){switch(r){case`audioworklet`:case`paintworklet`:case`serviceworker`:case`sharedworker`:case`worker`:case`script`:if(n.querySelector(Ff(a)))return}r=n.createElement(`link`),Pd(r,`link`,e),k(r),n.head.appendChild(r)}}}function Ef(e,t,n){_f.S(e,t,n);var r=bf;if(r&&e){var i=Ot(r).hoistableStyles,a=Af(e);t||=`default`;var o=i.get(a);if(!o){var s={loading:0,preload:null};if(o=r.querySelector(jf(a)))s.loading=5;else{e=h({rel:`stylesheet`,href:e,"data-precedence":t},n),(n=mf.get(a))&&Rf(e,n);var c=o=r.createElement(`link`);k(c),Pd(c,`link`,e),c._p=new Promise(function(e,t){c.onload=e,c.onerror=t}),c.addEventListener(`load`,function(){s.loading|=1}),c.addEventListener(`error`,function(){s.loading|=2}),s.loading|=4,Lf(o,t,r)}o={type:`stylesheet`,instance:o,count:1,state:s},i.set(a,o)}}}function Df(e,t){_f.X(e,t);var n=bf;if(n&&e){var r=Ot(n).hoistableScripts,i=Pf(e),a=r.get(i);a||(a=n.querySelector(Ff(i)),a||(e=h({src:e,async:!0},t),(t=mf.get(i))&&zf(e,t),a=n.createElement(`script`),k(a),Pd(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function Of(e,t){_f.M(e,t);var n=bf;if(n&&e){var r=Ot(n).hoistableScripts,i=Pf(e),a=r.get(i);a||(a=n.querySelector(Ff(i)),a||(e=h({src:e,async:!0,type:`module`},t),(t=mf.get(i))&&zf(e,t),a=n.createElement(`script`),k(a),Pd(a,`link`,e),n.head.appendChild(a)),a={type:`script`,instance:a,count:1,state:null},r.set(i,a))}}function kf(e,t,n,r){var i=(i=_e.current)?gf(i):null;if(!i)throw Error(s(446));switch(e){case`meta`:case`title`:return null;case`style`:return typeof n.precedence==`string`&&typeof n.href==`string`?(t=Af(n.href),n=Ot(i).hoistableStyles,r=n.get(t),r||(r={type:`style`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};case`link`:if(n.rel===`stylesheet`&&typeof n.href==`string`&&typeof n.precedence==`string`){e=Af(n.href);var a=Ot(i).hoistableStyles,o=a.get(e);if(o||(i=i.ownerDocument||i,o={type:`stylesheet`,instance:null,count:0,state:{loading:0,preload:null}},a.set(e,o),(a=i.querySelector(jf(e)))&&!a._p&&(o.instance=a,o.state.loading=5),mf.has(e)||(n={rel:`preload`,as:`style`,href:n.href,crossOrigin:n.crossOrigin,integrity:n.integrity,media:n.media,hrefLang:n.hrefLang,referrerPolicy:n.referrerPolicy},mf.set(e,n),a||Nf(i,e,n,o.state))),t&&r===null)throw Error(s(528,``));return o}if(t&&r!==null)throw Error(s(529,``));return null;case`script`:return t=n.async,n=n.src,typeof n==`string`&&t&&typeof t!=`function`&&typeof t!=`symbol`?(t=Pf(n),n=Ot(i).hoistableScripts,r=n.get(t),r||(r={type:`script`,instance:null,count:0,state:null},n.set(t,r)),r):{type:`void`,instance:null,count:0,state:null};default:throw Error(s(444,e))}}function Af(e){return`href="`+qt(e)+`"`}function jf(e){return`link[rel="stylesheet"][`+e+`]`}function Mf(e){return h({},e,{"data-precedence":e.precedence,precedence:null})}function Nf(e,t,n,r){e.querySelector(`link[rel="preload"][as="style"][`+t+`]`)?r.loading=1:(t=e.createElement(`link`),r.preload=t,t.addEventListener(`load`,function(){return r.loading|=1}),t.addEventListener(`error`,function(){return r.loading|=2}),Pd(t,`link`,n),k(t),e.head.appendChild(t))}function Pf(e){return`[src="`+qt(e)+`"]`}function Ff(e){return`script[async]`+e}function If(e,t,n){if(t.count++,t.instance===null)switch(t.type){case`style`:var r=e.querySelector(`style[data-href~="`+qt(n.href)+`"]`);if(r)return t.instance=r,k(r),r;var i=h({},n,{"data-href":n.href,"data-precedence":n.precedence,href:null,precedence:null});return r=(e.ownerDocument||e).createElement(`style`),k(r),Pd(r,`style`,i),Lf(r,n.precedence,e),t.instance=r;case`stylesheet`:i=Af(n.href);var a=e.querySelector(jf(i));if(a)return t.state.loading|=4,t.instance=a,k(a),a;r=Mf(n),(i=mf.get(i))&&Rf(r,i),a=(e.ownerDocument||e).createElement(`link`),k(a);var o=a;return o._p=new Promise(function(e,t){o.onload=e,o.onerror=t}),Pd(a,`link`,r),t.state.loading|=4,Lf(a,n.precedence,e),t.instance=a;case`script`:return a=Pf(n.src),(i=e.querySelector(Ff(a)))?(t.instance=i,k(i),i):(r=n,(i=mf.get(a))&&(r=h({},n),zf(r,i)),e=e.ownerDocument||e,i=e.createElement(`script`),k(i),Pd(i,`link`,r),e.head.appendChild(i),t.instance=i);case`void`:return null;default:throw Error(s(443,t.type))}else t.type===`stylesheet`&&!(t.state.loading&4)&&(r=t.instance,t.state.loading|=4,Lf(r,n.precedence,e));return t.instance}function Lf(e,t,n){for(var r=n.querySelectorAll(`link[rel="stylesheet"][data-precedence],style[data-precedence]`),i=r.length?r[r.length-1]:null,a=i,o=0;o title`):null)}function Uf(e,t,n){if(n===1||t.itemProp!=null)return!1;switch(e){case`meta`:case`title`:return!0;case`style`:if(typeof t.precedence!=`string`||typeof t.href!=`string`||t.href===``)break;return!0;case`link`:if(typeof t.rel!=`string`||typeof t.href!=`string`||t.href===``||t.onLoad||t.onError)break;switch(t.rel){case`stylesheet`:return e=t.disabled,typeof t.precedence==`string`&&e==null;default:return!0}case`script`:if(t.async&&typeof t.async!=`function`&&typeof t.async!=`symbol`&&!t.onLoad&&!t.onError&&t.src&&typeof t.src==`string`)return!0}return!1}function Wf(e){return!(e.type===`stylesheet`&&!(e.state.loading&3))}function Gf(e,t,n,r){if(n.type===`stylesheet`&&(typeof r.media!=`string`||!1!==matchMedia(r.media).matches)&&!(n.state.loading&4)){if(n.instance===null){var i=Af(r.href),a=t.querySelector(jf(i));if(a){t=a._p,typeof t==`object`&&t&&typeof t.then==`function`&&(e.count++,e=Jf.bind(e),t.then(e,e)),n.state.loading|=4,n.instance=a,k(a);return}a=t.ownerDocument||t,r=Mf(r),(i=mf.get(i))&&Rf(r,i),a=a.createElement(`link`),k(a);var o=a;o._p=new Promise(function(e,t){o.onload=e,o.onerror=t}),Pd(a,`link`,r),n.instance=a}e.stylesheets===null&&(e.stylesheets=new Map),e.stylesheets.set(n,t),(t=n.state.preload)&&!(n.state.loading&3)&&(e.count++,n=Jf.bind(e),t.addEventListener(`load`,n),t.addEventListener(`error`,n))}}var Kf=0;function qf(e,t){return e.stylesheets&&e.count===0&&Xf(e,e.stylesheets),0Kf?50:800)+t);return e.unsuspend=n,function(){e.unsuspend=null,clearTimeout(r),clearTimeout(i)}}:null}function Jf(){if(this.count--,this.count===0&&(this.imgCount===0||!this.waitingForImages)){if(this.stylesheets)Xf(this,this.stylesheets);else if(this.unsuspend){var e=this.unsuspend;this.unsuspend=null,e()}}}var Yf=null;function Xf(e,t){e.stylesheets=null,e.unsuspend!==null&&(e.count++,Yf=new Map,t.forEach(Zf,e),Yf=null,Jf.call(e))}function Zf(e,t){if(!(t.state.loading&4)){var n=Yf.get(e);if(n)var r=n.get(null);else{n=new Map,Yf.set(e,n);for(var i=e.querySelectorAll(`link[data-precedence],style[data-precedence]`),a=0;a{function n(){if(!(typeof __REACT_DEVTOOLS_GLOBAL_HOOK__>`u`||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!=`function`))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(n)}catch(e){console.error(e)}}n(),t.exports=s()})),l=n(),u=c(),d=e=>{let t=e.role||e.type;return t===`user`||t===`assistant`||t===`tool`||t===`system`?t:`assistant`},f=e=>{if(e.text)return e.text;if(e.payload&&typeof e.payload==`object`&&`content`in e.payload){let t=e.payload.content;if(typeof t==`string`)return t}return``},p=e=>{let t=e.entries.find(e=>d(e)===`user`);if(t){let e=f(t).trim();if(e)return e}let n=e.metadata?.objective;return typeof n==`string`&&n.trim()?n:e.id},m=e=>{let t=new Date(e);return Number.isNaN(t.getTime())?``:new Intl.DateTimeFormat(`zh-CN`,{month:`short`,day:`numeric`,hour:`2-digit`,minute:`2-digit`}).format(t)},h=(e,t)=>{let n=t.trim().toLowerCase();if(!n)return!0;let r=[e.id,e.cwd,p(e)].map(e=>e.toLowerCase());for(let t of e.entries)r.push(f(t).toLowerCase()),t.tool&&r.push(t.tool.toLowerCase());return r.some(e=>e.includes(n))},g=(e,t)=>e.filter(e=>h(e,t)),_=(e,t)=>t===`all`?e:e.filter(e=>d(e)===t),v=``+new URL(`call-code-BBgvhvPd.png`,import.meta.url).href,y=e((e=>{var t=Symbol.for(`react.transitional.element`);function n(e,n,r){var i=null;if(r!==void 0&&(i=``+r),n.key!==void 0&&(i=``+n.key),`key`in n)for(var a in r={},n)a!==`key`&&(r[a]=n[a]);else r=n;return n=r.ref,{$$typeof:t,type:e,key:i,ref:n===void 0?null:n,props:r}}e.jsx=n,e.jsxs=n})),b=e(((e,t)=>{t.exports=y()}))();function x({sessions:e,theme:t,onThemeChange:n,connectionState:r=`ready`}){let i=e.reduce((e,t)=>(e.messages+=t.entries.length,e.tools+=t.entries.filter(e=>d(e)===`tool`).length,e),{messages:0,tools:0});return(0,b.jsxs)(`header`,{className:`header-bar`,children:[(0,b.jsxs)(`div`,{className:`flex min-w-0 items-center gap-2.5`,children:[(0,b.jsx)(`img`,{src:v,alt:`Call Code`,className:`h-8 w-8 shrink-0 rounded-lg border object-contain`,style:{borderColor:`var(--chip-border)`,background:`var(--chip-bg)`}}),(0,b.jsxs)(`div`,{className:`min-w-0`,children:[(0,b.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,b.jsx)(`h1`,{className:`truncate text-[15px] font-semibold tracking-tight`,style:{color:`var(--text-primary)`},children:`Call Code`}),(0,b.jsxs)(`div`,{className:`connection-state connection-state--${r}`,children:[(0,b.jsx)(`span`,{"aria-hidden":`true`}),r===`loading`?`连接中`:r===`error`?`等待会话服务`:`实时`]})]}),(0,b.jsxs)(`div`,{className:`truncate text-[11px]`,style:{color:`var(--text-tertiary)`},children:[e.length,` 个会话 · `,i.messages,` 条消息 · `,i.tools,` 次工具`]})]})]}),(0,b.jsx)(`div`,{className:`segmented theme-switcher shrink-0`,role:`tablist`,"aria-label":`主题切换`,children:[`light`,`dark`].map(e=>(0,b.jsx)(`button`,{type:`button`,role:`tab`,"aria-pressed":t===e,onClick:()=>n(e),children:e===`light`?`浅色`:`深色`},e))})]})}function ee({sessions:e,activeId:t,query:n,onSelect:r,onQueryChange:i}){return(0,b.jsxs)(`aside`,{className:`sidebar-panel max-h-[50vh] lg:max-h-none`,children:[(0,b.jsx)(`header`,{className:`border-b px-3 py-3`,style:{borderColor:`rgb(var(--panel-border))`},children:(0,b.jsxs)(`div`,{className:`search-box flex h-8 min-w-0 items-center gap-2 rounded-lg border px-2.5`,style:{borderColor:`rgb(var(--chip-border))`,background:`rgb(var(--chip-bg))`},children:[(0,b.jsxs)(`svg`,{width:`13`,height:`13`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,strokeLinejoin:`round`,style:{color:`var(--text-tertiary)`},"aria-hidden":`true`,children:[(0,b.jsx)(`circle`,{cx:`11`,cy:`11`,r:`7`}),(0,b.jsx)(`path`,{d:`m20 20-3.5-3.5`})]}),(0,b.jsx)(`input`,{type:`search`,value:n,onChange:e=>i(e.target.value),placeholder:`搜索会话`,"aria-label":`搜索会话`,className:`h-full w-full min-w-0 bg-transparent text-[12px] outline-none`,style:{color:`var(--text-primary)`}})]})}),(0,b.jsxs)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-2 pt-3 pb-3`,children:[e.length===0&&(0,b.jsx)(`div`,{className:`grid min-h-[120px] place-items-center text-[12px]`,style:{color:`var(--text-tertiary)`},children:`暂无会话`}),(0,b.jsx)(`div`,{className:`flex flex-col gap-0.5`,children:e.map(e=>{let n=e.id===t;return(0,b.jsxs)(`button`,{type:`button`,onClick:()=>r(e.id),"aria-current":n?`true`:void 0,className:`group relative flex items-start gap-2.5 rounded-xl px-2.5 py-2 text-left transition-all duration-200`,style:n?{background:`rgb(var(--sidebar-active))`,boxShadow:`var(--sidebar-active-shadow)`}:void 0,onMouseEnter:e=>{n||(e.currentTarget.style.background=`rgb(var(--sidebar-hover))`)},onMouseLeave:e=>{n||(e.currentTarget.style.background=``)},children:[(0,b.jsx)(`span`,{className:`mt-1 h-4 w-1 shrink-0 rounded-full transition-opacity`,style:{background:n?`var(--text-primary)`:`transparent`,opacity:+!!n},"aria-hidden":`true`}),(0,b.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,b.jsx)(`div`,{className:`line-clamp-2 text-[13px] font-medium leading-snug`,style:{color:n?`var(--text-primary)`:`var(--text-secondary)`},children:p(e)}),(0,b.jsxs)(`div`,{className:`mt-1 flex items-center gap-1.5 text-[11px]`,style:{color:`var(--text-tertiary)`},children:[(0,b.jsxs)(`span`,{children:[e.entries.length,` 条`]}),(0,b.jsx)(`span`,{style:{opacity:.4},children:`·`}),(0,b.jsx)(`span`,{className:`truncate`,children:m(e.createdAt)})]})]})]},e.id)})})]})]})}var S={user:{label:`用户`,dotClass:`role-dot role-dot--user`,bubbleClass:`msg-bubble--user`},assistant:{label:`助手`,dotClass:`role-dot role-dot--assistant`,bubbleClass:`msg-bubble--assistant`},tool:{label:`工具`,dotClass:`role-dot role-dot--tool`,bubbleClass:`msg-bubble--tool`},system:{label:`系统`,dotClass:`role-dot role-dot--system`,bubbleClass:``}};function C({entry:e}){let t=d(e),n=S[t],r=f(e),i=t===`tool`||r.length>320;return(0,b.jsxs)(`article`,{className:`flex gap-3`,children:[(0,b.jsx)(`div`,{className:`pt-1.5`,children:(0,b.jsx)(`span`,{className:n.dotClass,"aria-hidden":`true`})}),(0,b.jsxs)(`div`,{className:`min-w-0 flex-1`,children:[(0,b.jsxs)(`div`,{className:`mb-1.5 flex items-center gap-2 text-[11px] font-medium`,style:{color:`var(--text-tertiary)`},children:[(0,b.jsx)(`span`,{style:{color:`var(--role-${t})`},children:n.label}),e.tool?(0,b.jsx)(`span`,{className:`chip !py-0 !text-[10px]`,children:e.tool}):null,(0,b.jsx)(`span`,{className:`ml-auto shrink-0`,children:m(e.timestamp)})]}),i?(0,b.jsx)(`pre`,{className:`msg-bubble ${n.bubbleClass} mono m-0 max-h-[480px] overflow-auto px-3.5 py-2.5 text-[12px]`,style:{color:`var(--text-secondary)`},children:r}):(0,b.jsx)(`div`,{className:`msg-bubble ${n.bubbleClass} whitespace-pre-wrap break-words px-3.5 py-2.5 text-[13.5px] leading-relaxed`,style:{color:`var(--text-primary)`},children:r})]})]})}var te=[{value:`all`,label:`全部`},{value:`user`,label:`用户`},{value:`assistant`,label:`助手`},{value:`tool`,label:`工具`}];function ne({session:e}){let t=[[`消息`,`${e.entries.length}`],[`tokens`,e.stats?.totalTokens?.toLocaleString()??`0`],[`成本`,`$${(e.stats?.costTotal??0).toFixed(3)}`],[`目录`,e.cwd]];return(0,b.jsx)(`div`,{className:`flex flex-wrap items-center gap-1.5`,children:t.map(([e,t])=>(0,b.jsxs)(`span`,{className:`chip max-w-[240px] truncate`,children:[(0,b.jsx)(`span`,{style:{opacity:.6},children:e}),(0,b.jsx)(`span`,{className:`truncate`,children:t})]},e))})}function re({facts:e}){return e.length===0?null:(0,b.jsxs)(`section`,{className:`mt-8`,children:[(0,b.jsx)(`div`,{className:`mb-3 text-[11px] font-medium uppercase tracking-wider`,style:{color:`var(--text-tertiary)`},children:`事实`}),(0,b.jsx)(`div`,{className:`grid gap-2 sm:grid-cols-2 lg:grid-cols-3`,children:e.slice(0,12).map((e,t)=>(0,b.jsxs)(`div`,{className:`msg-bubble px-3 py-2.5`,children:[(0,b.jsx)(`div`,{className:`text-[11px]`,style:{color:`var(--text-tertiary)`},children:e.kind}),(0,b.jsx)(`div`,{className:`mt-0.5 truncate text-[13px]`,style:{color:`var(--text-primary)`},children:e.value||e.key||String(e.seq)})]},`${e.seq}-${t}`))})]})}var w=e=>typeof e==`string`?e:e&&typeof e==`object`?JSON.stringify(e,null,2):String(e??``);function ie({records:e}){return e.length===0?null:(0,b.jsxs)(`section`,{className:`mt-8`,children:[(0,b.jsxs)(`div`,{className:`mb-3 text-[11px] font-medium uppercase tracking-wider`,style:{color:`var(--text-tertiary)`},children:[`运行记录 · 最近 `,Math.min(20,e.length),` 条`]}),(0,b.jsx)(`div`,{className:`flex flex-col gap-1.5`,children:e.slice(-20).reverse().map(e=>(0,b.jsxs)(`div`,{className:`msg-bubble px-3 py-2.5`,children:[(0,b.jsxs)(`div`,{className:`flex items-center justify-between gap-2 text-[11px]`,style:{color:`var(--text-tertiary)`},children:[(0,b.jsxs)(`span`,{className:`truncate`,children:[e.type,e.opKind?` / ${e.opKind}`:``]}),(0,b.jsx)(`span`,{className:`shrink-0`,children:m(e.timestamp)})]}),(0,b.jsx)(`div`,{className:`mt-1.5 max-h-40 overflow-auto whitespace-pre-wrap break-words mono`,style:{color:`var(--text-secondary)`},children:w(e.payload)})]},e.id))})]})}function ae({session:e,filter:t,onFilterChange:n}){let r=e?_(e.entries,t):[];return(0,b.jsxs)(`main`,{className:`main-panel`,children:[(0,b.jsxs)(`header`,{className:`flex flex-col gap-3 px-6 pt-5 pb-4`,children:[(0,b.jsx)(`h2`,{className:`truncate text-[15px] font-semibold leading-snug`,style:{color:`var(--text-primary)`},children:e?p(e):`暂无会话`}),e?(0,b.jsx)(ne,{session:e}):null]}),(0,b.jsx)(`div`,{className:`flex items-center gap-3 border-t px-6 py-2.5`,style:{borderColor:`rgb(var(--panel-border))`},children:(0,b.jsx)(`div`,{className:`segmented`,role:`tablist`,"aria-label":`消息过滤`,children:te.map(e=>(0,b.jsx)(`button`,{type:`button`,role:`tab`,"aria-pressed":t===e.value,onClick:()=>n(e.value),children:e.label},e.value))})}),(0,b.jsx)(`div`,{className:`min-h-0 flex-1 overflow-y-auto px-6 py-6`,children:(0,b.jsx)(`div`,{className:`mx-auto max-w-[760px]`,children:e?r.length===0?(0,b.jsx)(`div`,{className:`grid min-h-[200px] place-items-center text-[13px]`,style:{color:`var(--text-tertiary)`},children:`没有匹配的消息`}):(0,b.jsxs)(`div`,{className:`flex flex-col gap-4`,children:[r.map(e=>(0,b.jsx)(C,{entry:e},e.id)),e.facts?(0,b.jsx)(re,{facts:e.facts}):null,e.records?(0,b.jsx)(ie,{records:e.records}):null]}):(0,b.jsx)(`div`,{className:`grid min-h-[200px] place-items-center text-[13px]`,style:{color:`var(--text-tertiary)`},children:`暂无会话数据`})})})]})}var oe=`/ws`,se=8e3,ce=5e3,le=e=>{if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.id==`string`&&typeof t.createdAt==`string`&&typeof t.cwd==`string`&&Array.isArray(t.entries)},ue=e=>{if(!e||typeof e!=`object`)return!1;let t=e;return t.schemaVersion===1&&typeof t.exportedAt==`string`&&Array.isArray(t.sessions)&&t.sessions.every(le)},T=e=>{if(!e||typeof e!=`object`)return null;let t=e;return t.type===`sessions.snapshot`&&ue(t.data)?t.data:null},E=e=>{if(e)return e;let t=new URLSearchParams(window.location.search);return(t.get(`ws`)??t.get(`wsUrl`))||`${window.location.protocol===`https:`?`wss:`:`ws:`}//${window.location.host}${oe}`},de=e=>{let{onSnapshot:t,url:n,timeoutMs:r=se,refreshMs:i=ce}=e,a=!1,o=null,s=null,c=null,l=null,u=0,d=!1,f=()=>void 0,p=new Promise(e=>{f=e}),m=e=>{d||(d=!0,f(e))},h=()=>{s&&clearTimeout(s),c&&clearTimeout(c),l&&clearTimeout(l),s=null,c=null,l=null},g=()=>{if(h(),!o)return;let e=o;o=null,e.onopen=null,e.onmessage=null,e.onerror=null,e.onclose=null,e.close()},_=()=>{a||(c=setTimeout(()=>{o?.send(JSON.stringify({type:`sessions.list`})),_()},i))},v=()=>{if(a)return;let e=Math.min(1e3*2**u,15e3);u+=1,l=setTimeout(()=>{l=null,b()},e)},y=()=>{s&&clearTimeout(s),s=setTimeout(()=>{g(),m(null),v()},r)},b=()=>{if(a)return;let e;try{e=new WebSocket(E(n))}catch{v();return}o=e,y(),e.onopen=()=>{u=0,e.send(JSON.stringify({type:`sessions.list`})),_()},e.onmessage=e=>{let n;try{n=JSON.parse(String(e.data))}catch{return}let r=T(n);r&&(y(),t(r),m(r))},e.onerror=()=>{},e.onclose=()=>{o===e&&(g(),m(null),a||v())}};return b(),{ready:p,close(){a=!0,h(),g()}}};function fe(){let e=(0,l.useRef)(null);return(0,l.useEffect)(()=>{let t=e.current;if(!t)return;let n=t.getContext(`2d`);if(!n)return;let r,i=[],a=t.width=window.innerWidth,o=t.height=window.innerHeight,s={x:-9999,y:-9999,radius:120},c=()=>{let e=document.createElement(`canvas`),t=e.getContext(`2d`);if(!t)return[];e.width=a,e.height=o;let n=Math.min(a/7.5,140);t.font=`900 ${n}px "SF Mono", Monaco, Consolas, monospace`,t.textAlign=`center`,t.textBaseline=`middle`,t.fillStyle=`#ffffff`,t.fillText(`CALL CODE`,a/2,o/2);let r=t.getImageData(0,0,a,o).data,i=[],s=Math.max(Math.floor(n/24),4);for(let e=0;e128&&i.push({x:Math.random()*a,y:Math.random()*o,originX:t,originY:e,vx:0,vy:0,size:Math.random()*1.5+1.2,alpha:Math.random()*.4+.35,baseAlpha:Math.random()*.4+.35,isChar:!0});return i},l=e=>{let t=[];for(let n=0;n{a=t.width=window.innerWidth,o=t.height=window.innerHeight;let e=c(),n=Math.floor(a*o/18e3),r=l(n);i=[...e,...r]};u();let d=()=>u(),f=e=>{s.x=e.clientX,s.y=e.clientY},p=()=>{s.x=-9999,s.y=-9999};window.addEventListener(`resize`,d),window.addEventListener(`mousemove`,f),window.addEventListener(`mouseleave`,p);let m=()=>{n.clearRect(0,0,a,o);let e=document.documentElement.classList.contains(`dark`)||document.documentElement.dataset.theme===`dark`?`255, 255, 255`:`15, 23, 42`;for(let t=0;ta&&(r.x=0),r.y<0&&(r.y=o),r.y>o&&(r.y=0);n.fillStyle=`rgba(${e}, ${r.alpha})`,n.beginPath(),n.arc(r.x,r.y,r.size,0,Math.PI*2),n.fill()}r=requestAnimationFrame(m)};return m(),()=>{window.removeEventListener(`resize`,d),window.removeEventListener(`mousemove`,f),window.removeEventListener(`mouseleave`,p),cancelAnimationFrame(r)}},[]),(0,b.jsx)(`canvas`,{ref:e,className:`particle-canvas`,"aria-hidden":`true`})}var pe=`call-code-theme`,me=()=>localStorage.getItem(pe)===`light`?`light`:`dark`;function D(){let[e,t]=(0,l.useState)(null),[n,r]=(0,l.useState)(`loading`),[i,a]=(0,l.useState)(me),[o,s]=(0,l.useState)(null),[c,u]=(0,l.useState)(``),[d,f]=(0,l.useState)(`all`);(0,l.useEffect)(()=>{let e=!1,n=de({onSnapshot:n=>{e||(t(n),r(`ready`),s(e=>[new URLSearchParams(window.location.search).get(`session`),e,n.sessions[0]?.id??null].find(e=>e!=null&&n.sessions.some(t=>t.id===e))??null))}});return n.ready.then(t=>{e||r(t?`ready`:`error`)}),()=>{e=!0,n.close()}},[]),(0,l.useEffect)(()=>{let e=document.documentElement;e.classList.toggle(`dark`,i===`dark`),e.dataset.theme=i,localStorage.setItem(pe,i)},[i]);let p=(0,l.useMemo)(()=>e?.sessions??[],[e]),m=(0,l.useMemo)(()=>g(p,c),[p,c]),h=(0,l.useMemo)(()=>m.find(e=>e.id===o)??m[0]??null,[m,o]);return(0,b.jsxs)(`div`,{className:`app-shell`,children:[(0,b.jsx)(fe,{}),(0,b.jsxs)(`div`,{className:`app-frame`,children:[(0,b.jsx)(x,{sessions:m,theme:i,onThemeChange:a,connectionState:n}),(0,b.jsxs)(`div`,{className:`app-workspace`,children:[(0,b.jsx)(ee,{sessions:m,activeId:o,query:c,onSelect:s,onQueryChange:u}),(0,b.jsx)(ae,{session:h,filter:d,onFilterChange:f})]})]})]})}var O=document.getElementById(`root`);if(!O)throw Error(`未找到 #root 容器`);(0,u.createRoot)(O).render((0,b.jsx)(l.StrictMode,{children:(0,b.jsx)(D,{})})); \ No newline at end of file diff --git a/packages/client/dist/assets/index-UIvzZf6_.css b/packages/client/dist/assets/index-UIvzZf6_.css new file mode 100644 index 0000000..a29c28e --- /dev/null +++ b/packages/client/dist/assets/index-UIvzZf6_.css @@ -0,0 +1,2 @@ +/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */ +@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial}}}@layer theme{:root,:host{--font-sans:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--spacing:.25rem;--font-weight-medium:500;--font-weight-semibold:600;--tracking-tight:-.025em;--tracking-wider:.05em;--leading-snug:1.375;--leading-relaxed:1.625;--radius-lg:.5rem;--radius-xl:.75rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring:where(:not(iframe)){outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab, currentcolor 50%, transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}}@layer components;@layer utilities{.relative{position:relative}.container{width:100%}@media (width>=40rem){.container{max-width:40rem}}@media (width>=48rem){.container{max-width:48rem}}@media (width>=64rem){.container{max-width:64rem}}@media (width>=80rem){.container{max-width:80rem}}@media (width>=96rem){.container{max-width:96rem}}.m-0{margin:0}.mx-auto{margin-inline:auto}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mt-1{margin-top:var(--spacing)}.mt-1\.5{margin-top:calc(var(--spacing) * 1.5)}.mt-8{margin-top:calc(var(--spacing) * 8)}.mb-1\.5{margin-bottom:calc(var(--spacing) * 1.5)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.ml-auto{margin-left:auto}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.flex{display:flex}.grid{display:grid}.h-4{height:calc(var(--spacing) * 4)}.h-8{height:calc(var(--spacing) * 8)}.h-full{height:100%}.max-h-40{max-height:calc(var(--spacing) * 40)}.max-h-\[50vh\]{max-height:50vh}.max-h-\[480px\]{max-height:480px}.min-h-0{min-height:0}.min-h-\[120px\]{min-height:120px}.min-h-\[200px\]{min-height:200px}.w-1{width:var(--spacing)}.w-8{width:calc(var(--spacing) * 8)}.w-full{width:100%}.max-w-\[240px\]{max-width:240px}.max-w-\[760px\]{max-width:760px}.min-w-0{min-width:0}.flex-1{flex:1}.shrink-0{flex-shrink:0}.resize{resize:both}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.gap-0\.5{gap:calc(var(--spacing) * .5)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-2\.5{gap:calc(var(--spacing) * 2.5)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-y-auto{overflow-y:auto}.rounded-full{border-radius:2147483647px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-xl{border-radius:var(--radius-xl)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.bg-transparent{background-color:#0000}.object-contain{object-fit:contain}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-2\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-3\.5{padding-inline:calc(var(--spacing) * 3.5)}.px-6{padding-inline:calc(var(--spacing) * 6)}.\!py-0{padding-block:0!important}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.py-6{padding-block:calc(var(--spacing) * 6)}.pt-1\.5{padding-top:calc(var(--spacing) * 1.5)}.pt-3{padding-top:calc(var(--spacing) * 3)}.pt-5{padding-top:calc(var(--spacing) * 5)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.pb-4{padding-bottom:calc(var(--spacing) * 4)}.text-left{text-align:left}.\!text-\[10px\]{font-size:10px!important}.text-\[11px\]{font-size:11px}.text-\[12px\]{font-size:12px}.text-\[13\.5px\]{font-size:13.5px}.text-\[13px\]{font-size:13px}.text-\[15px\]{font-size:15px}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.leading-snug{--tw-leading:var(--leading-snug);line-height:var(--leading-snug)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.break-words{overflow-wrap:break-word}.whitespace-pre-wrap{white-space:pre-wrap}.uppercase{text-transform:uppercase}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.outline-none{--tw-outline-style:none;outline-style:none}@media (width>=40rem){.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (width>=64rem){.lg\:max-h-none{max-height:none}.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}}:root{--lightningcss-light:initial;--lightningcss-dark: ;color-scheme:light;--font-ui:-apple-system, BlinkMacSystemFont, "SF Pro Text", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;--font-mono:"SF Mono", ui-monospace, "JetBrains Mono", Menlo, Consolas, monospace;--bg:#fafafa;--panel-bg:#ffffffd9;--panel-border:#00000014;--panel-shadow:0 20px 40px -15px #0000000d;--sidebar-active:#0000000a;--sidebar-hover:#00000005;--chip-bg:#00000008;--chip-border:#0000000f;--text-primary:#111827;--text-secondary:#4b5563;--text-tertiary:#9ca3af;--role-user:#0284c7;--role-assistant:#10b981;--role-tool:#f59e0b;--role-system:#6b7280;--segment-active:#fff;--segment-active-text:#111827;--segment-active-shadow:0 1px 3px #0000001a}:root.dark,:root[data-theme=dark]{--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;--bg:#09090b;--panel-bg:#121214d1;--panel-border:#ffffff1a;--panel-shadow:0 25px 50px -12px #00000080;--sidebar-active:#ffffff14;--sidebar-hover:#ffffff0a;--chip-bg:#ffffff0d;--chip-border:#ffffff14;--text-primary:#f4f4f5;--text-secondary:#a1a1aa;--text-tertiary:#71717a;--role-user:#38bdf8;--role-assistant:#34d399;--role-tool:#fbbf24;--role-system:#9ca3af;--segment-active:#ffffff26;--segment-active-text:#fff;--segment-active-shadow:0 1px 2px #0000004d}html{font-family:var(--font-ui);text-rendering:optimizelegibility;-webkit-font-smoothing:antialiased}body{min-height:100vh;color:var(--text-primary);background:var(--bg);margin:0;overflow-x:hidden}*{scrollbar-width:thin;scrollbar-color:var(--chip-border) transparent}.particle-canvas{pointer-events:none;z-index:0;width:100vw;height:100vh;position:fixed;inset:0}.app-shell{z-index:1;justify-content:center;align-items:center;min-height:100vh;padding:16px;display:flex;position:relative}@media (width>=1024px){.app-shell{padding:24px 32px}}.app-frame{border:1px solid var(--panel-border);background:var(--panel-bg);width:100%;max-width:1440px;height:calc(100vh - 32px);box-shadow:var(--panel-shadow);-webkit-backdrop-filter:blur(20px);border-radius:14px;flex-direction:column;display:flex;position:relative;overflow:hidden}@media (width>=1024px){.app-frame{height:calc(100vh - 48px)}}.header-bar{border-bottom:1px solid var(--panel-border);justify-content:space-between;align-items:center;gap:12px;padding:12px 18px;display:flex}.brand-kicker{color:var(--text-tertiary);font-family:var(--font-mono);letter-spacing:.08em;margin-bottom:2px;font-size:9px}.connection-state{color:var(--text-tertiary);font-family:var(--font-mono);align-items:center;gap:5px;margin-top:3px;font-size:9px;display:flex}.connection-state>span{background:var(--role-assistant);border-radius:50%;width:5px;height:5px}.connection-state--loading>span{background:#f59e0b;animation:1.4s ease-in-out infinite pulse}.connection-state--error>span{background:#ef4444}@keyframes pulse{50%{opacity:.5}}.app-workspace{flex:1;grid-template-columns:1fr;min-height:0;display:grid}@media (width>=1024px){.app-workspace{grid-template-columns:280px minmax(0,1fr)}}.sidebar-panel,.main-panel{flex-direction:column;min-height:0;display:flex;position:relative;overflow:hidden}.sidebar-panel{border-bottom:1px solid var(--panel-border)}@media (width>=1024px){.sidebar-panel{border-right:1px solid var(--panel-border);border-bottom:0}}.chip{border:1px solid var(--chip-border);background:var(--chip-bg);color:var(--text-secondary);white-space:nowrap;border-radius:6px;align-items:center;gap:5px;padding:2px 8px;font-size:11px;display:inline-flex}.segmented{border:1px solid var(--chip-border);background:var(--chip-bg);border-radius:8px;padding:2px;display:inline-flex}.segmented button{color:var(--text-secondary);cursor:pointer;border-radius:6px;padding:4px 10px;font-size:11px;font-weight:500;transition:all .15s}.segmented button:hover{color:var(--text-primary)}.segmented button[aria-pressed=true]{background:var(--segment-active);color:var(--segment-active-text);box-shadow:var(--segment-active-shadow)}.mono{font-family:var(--font-mono);font-size:12px;line-height:1.5}.role-dot{border-radius:50%;flex-shrink:0;width:6px;height:6px;display:block}.role-dot--user{background:var(--role-user)}.role-dot--assistant{background:var(--role-assistant)}.role-dot--tool{background:var(--role-tool)}.role-dot--system{background:var(--role-system)}.msg-bubble{border:1px solid var(--chip-border);background:var(--chip-bg);border-radius:8px}.msg-bubble--user{border-left:2px solid var(--role-user)}.msg-bubble--assistant{border-left:2px solid var(--role-assistant)}.msg-bubble--tool{border-left:2px solid var(--role-tool)}.search-box{transition:border-color .15s}.search-box:focus-within{border-color:var(--text-primary)!important}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false} diff --git a/packages/client/dist/index.html b/packages/client/dist/index.html index 7959372..b8b2d87 100644 --- a/packages/client/dist/index.html +++ b/packages/client/dist/index.html @@ -4,8 +4,8 @@ Call Code History - - + +
diff --git a/packages/client/src/App.tsx b/packages/client/src/App.tsx index 56fb587..6b0ab2e 100644 --- a/packages/client/src/App.tsx +++ b/packages/client/src/App.tsx @@ -11,9 +11,7 @@ const THEME_KEY = 'call-code-theme'; const initialTheme = (): Theme => { const stored = localStorage.getItem(THEME_KEY); - return stored === 'clear' || stored === 'frosted' || stored === 'apricot' - ? stored - : 'frosted'; + return stored === 'light' ? 'light' : 'dark'; }; export default function App() { @@ -73,10 +71,9 @@ export default function App() { useEffect(() => { const root = document.documentElement; - const resolvedTheme = theme === 'light' ? 'frosted' : theme === 'dark' ? 'apricot' : theme; - root.classList.remove('dark'); - root.dataset.theme = resolvedTheme; - localStorage.setItem(THEME_KEY, resolvedTheme); + root.classList.toggle('dark', theme === 'dark'); + root.dataset.theme = theme; + localStorage.setItem(THEME_KEY, theme); }, [theme]); const sessions = useMemo(() => data?.sessions ?? [], [data]); diff --git a/packages/client/src/components/HeaderBar.tsx b/packages/client/src/components/HeaderBar.tsx index 912f3c3..8d08937 100644 --- a/packages/client/src/components/HeaderBar.tsx +++ b/packages/client/src/components/HeaderBar.tsx @@ -28,44 +28,44 @@ export function HeaderBar({ return (
-
+
Call Code
-
LIVE SESSION ARCHIVE
-

- Call Code -

+
+

+ Call Code +

+
+
+
- {sessions.length} 个会话 · {count.messages} 条消息 · {count.tools}{' '} - 次工具 -
-
-
- {(['clear', 'frosted', 'apricot'] as const).map((value) => ( + {(['light', 'dark'] as const).map((value) => ( ))}
diff --git a/packages/client/src/components/ParticleField.tsx b/packages/client/src/components/ParticleField.tsx index 82aedf1..57f56f7 100644 --- a/packages/client/src/components/ParticleField.tsx +++ b/packages/client/src/components/ParticleField.tsx @@ -1,26 +1,187 @@ -const particles = [ - ['call', 'particle--one'], - ['<>', 'particle--two'], - ['code', 'particle--three'], - ['/', 'particle--four'], - ['cc', 'particle--five'], - ['{ }', 'particle--six'], - ['call', 'particle--seven'], - [';', 'particle--eight'], - ['code', 'particle--nine'], - ['//', 'particle--ten'], - ['()', 'particle--eleven'], - ['cc', 'particle--twelve'], -] as const; +import { useEffect, useRef } from 'react'; + +interface Particle { + x: number; + y: number; + originX: number; + originY: number; + vx: number; + vy: number; + size: number; + alpha: number; + baseAlpha: number; + isChar: boolean; +} export function ParticleField() { + const canvasRef = useRef(null); + + useEffect(() => { + const canvas = canvasRef.current; + if (!canvas) return; + + const ctx = canvas.getContext('2d'); + if (!ctx) return; + + let animationFrameId: number; + let particles: Particle[] = []; + let width = (canvas.width = window.innerWidth); + let height = (canvas.height = window.innerHeight); + const mouse = { x: -9999, y: -9999, radius: 120 }; + + const createTextParticles = () => { + const offscreen = document.createElement('canvas'); + const offCtx = offscreen.getContext('2d'); + if (!offCtx) return []; + + offscreen.width = width; + offscreen.height = height; + + const fontSize = Math.min(width / 7.5, 140); + offCtx.font = `900 ${fontSize}px "SF Mono", Monaco, Consolas, monospace`; + offCtx.textAlign = 'center'; + offCtx.textBaseline = 'middle'; + offCtx.fillStyle = '#ffffff'; + offCtx.fillText('CALL CODE', width / 2, height / 2); + + const imageData = offCtx.getImageData(0, 0, width, height); + const data = imageData.data; + const sampled: Particle[] = []; + const step = Math.max(Math.floor(fontSize / 24), 4); + + for (let y = 0; y < height; y += step) { + for (let x = 0; x < width; x += step) { + const index = (y * width + x) * 4; + if (data[index + 3] > 128) { + sampled.push({ + x: Math.random() * width, + y: Math.random() * height, + originX: x, + originY: y, + vx: 0, + vy: 0, + size: Math.random() * 1.5 + 1.2, + alpha: Math.random() * 0.4 + 0.35, + baseAlpha: Math.random() * 0.4 + 0.35, + isChar: true, + }); + } + } + } + return sampled; + }; + + const createAmbientParticles = (count: number): Particle[] => { + const ambient: Particle[] = []; + for (let i = 0; i < count; i++) { + const x = Math.random() * width; + const y = Math.random() * height; + ambient.push({ + x, + y, + originX: x, + originY: y, + vx: (Math.random() - 0.5) * 0.3, + vy: (Math.random() - 0.5) * 0.3, + size: Math.random() * 1.2 + 0.6, + alpha: Math.random() * 0.15 + 0.05, + baseAlpha: Math.random() * 0.15 + 0.05, + isChar: false, + }); + } + return ambient; + }; + + const init = () => { + width = canvas.width = window.innerWidth; + height = canvas.height = window.innerHeight; + const charParticles = createTextParticles(); + const ambientCount = Math.floor((width * height) / 18000); + const ambientParticles = createAmbientParticles(ambientCount); + particles = [...charParticles, ...ambientParticles]; + }; + + init(); + + const onResize = () => init(); + const onMouseMove = (e: MouseEvent) => { + mouse.x = e.clientX; + mouse.y = e.clientY; + }; + const onMouseLeave = () => { + mouse.x = -9999; + mouse.y = -9999; + }; + + window.addEventListener('resize', onResize); + window.addEventListener('mousemove', onMouseMove); + window.addEventListener('mouseleave', onMouseLeave); + + const render = () => { + ctx.clearRect(0, 0, width, height); + + const isDark = + document.documentElement.classList.contains('dark') || + document.documentElement.dataset.theme === 'dark'; + const particleRgb = isDark ? '255, 255, 255' : '15, 23, 42'; + + for (let i = 0; i < particles.length; i++) { + const p = particles[i]; + + if (p.isChar) { + const dx = mouse.x - p.x; + const dy = mouse.y - p.y; + const dist = Math.hypot(dx, dy); + + if (dist < mouse.radius) { + const force = (1 - dist / mouse.radius) * 6; + const angle = Math.atan2(dy, dx); + p.vx -= Math.cos(angle) * force; + p.vy -= Math.sin(angle) * force; + } + + const homeDx = p.originX - p.x; + const homeDy = p.originY - p.y; + p.vx += homeDx * 0.04; + p.vy += homeDy * 0.04; + p.vx *= 0.85; + p.vy *= 0.85; + + p.x += p.vx; + p.y += p.vy; + } else { + p.x += p.vx; + p.y += p.vy; + if (p.x < 0) p.x = width; + if (p.x > width) p.x = 0; + if (p.y < 0) p.y = height; + if (p.y > height) p.y = 0; + } + + ctx.fillStyle = `rgba(${particleRgb}, ${p.alpha})`; + ctx.beginPath(); + ctx.arc(p.x, p.y, p.size, 0, Math.PI * 2); + ctx.fill(); + } + + animationFrameId = requestAnimationFrame(render); + }; + + render(); + + return () => { + window.removeEventListener('resize', onResize); + window.removeEventListener('mousemove', onMouseMove); + window.removeEventListener('mouseleave', onMouseLeave); + cancelAnimationFrame(animationFrameId); + }; + }, []); + return ( - +
diff --git a/packages/client/src/components/MainPanel.tsx b/packages/client/src/components/MainPanel.tsx index 5277646..bcc55ad 100644 --- a/packages/client/src/components/MainPanel.tsx +++ b/packages/client/src/components/MainPanel.tsx @@ -1,26 +1,29 @@ -import type { Filter, WebFact, WebRecord, WebSession } from '../types'; -import { filterEntries, formatTime, getSessionTitle } from '../utils'; -import { MessageItem } from './MessageItem'; +import { useState, type KeyboardEvent } from "react"; +import type { AgentMode, ChatStatusMessage, Filter, WebFact, WebRecord, WebSession } from "../types"; +import { filterEntries, formatTime, getSessionTitle } from "../utils"; +import { MessageItem } from "./MessageItem"; interface MainPanelProps { session: WebSession | null; filter: Filter; onFilterChange: (filter: Filter) => void; + chatStatus: ChatStatusMessage; + onSendMessage: (payload: { input: string; mode: AgentMode }) => boolean; } const filters: Array<{ value: Filter; label: string }> = [ - { value: 'all', label: '全部' }, - { value: 'user', label: '用户' }, - { value: 'assistant', label: '助手' }, - { value: 'tool', label: '工具' }, + { value: "all", label: "全部" }, + { value: "user", label: "用户" }, + { value: "assistant", label: "助手" }, + { value: "tool", label: "工具" }, ]; function StatRow({ session }: { session: WebSession }) { const items = [ - ['消息', `${session.entries.length}`], - ['tokens', session.stats?.totalTokens?.toLocaleString() ?? '0'], - ['成本', `$${(session.stats?.costTotal ?? 0).toFixed(3)}`], - ['目录', session.cwd], + ["消息", `${session.entries.length}`], + ["tokens", session.stats?.totalTokens?.toLocaleString() ?? "0"], + ["成本", `$${(session.stats?.costTotal ?? 0).toFixed(3)}`], + ["目录", session.cwd], ] as const; return ( @@ -44,7 +47,7 @@ function FactGrid({ facts }: { facts: WebFact[] }) {
事实
@@ -53,13 +56,13 @@ function FactGrid({ facts }: { facts: WebFact[] }) {
{fact.kind}
{fact.value || fact.key || String(fact.seq)}
@@ -71,13 +74,13 @@ function FactGrid({ facts }: { facts: WebFact[] }) { } const payloadText = (payload: unknown): string => { - if (typeof payload === 'string') { + if (typeof payload === "string") { return payload; } - if (payload && typeof payload === 'object') { + if (payload && typeof payload === "object") { return JSON.stringify(payload, null, 2); } - return String(payload ?? ''); + return String(payload ?? ""); }; function RecordList({ records }: { records: WebRecord[] }) { @@ -89,7 +92,7 @@ function RecordList({ records }: { records: WebRecord[] }) {
运行记录 · 最近 {Math.min(20, records.length)} 条
@@ -101,17 +104,17 @@ function RecordList({ records }: { records: WebRecord[] }) {
{record.type} - {record.opKind ? ` / ${record.opKind}` : ''} + {record.opKind ? ` / ${record.opKind}` : ""} {formatTime(record.timestamp)}
{payloadText(record.payload)}
@@ -122,26 +125,51 @@ function RecordList({ records }: { records: WebRecord[] }) { ); } -export function MainPanel({ session, filter, onFilterChange }: MainPanelProps) { +export function MainPanel({ + session, + filter, + onFilterChange, + chatStatus, + onSendMessage, +}: MainPanelProps) { + const [input, setInput] = useState(""); + const [mode, setMode] = useState("build"); const entries = session ? filterEntries(session.entries, filter) : []; + const handleSend = () => { + if (!input.trim() || chatStatus.status === "running") { + return; + } + const success = onSendMessage({ input: input.trim(), mode }); + if (success) { + setInput(""); + } + }; + + const handleKeyDown = (e: KeyboardEvent) => { + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + handleSend(); + } + }; + return (
{/* 标题栏 */}

- {session ? getSessionTitle(session) : '暂无会话'} + {session ? getSessionTitle(session) : "暂无会话"}

{session ? : null}
- {/* 过滤器 */} + {/* 过滤器与模式栏 */}
{filters.map((item) => ( @@ -156,6 +184,27 @@ export function MainPanel({ session, filter, onFilterChange }: MainPanelProps) { ))}
+ +
+
+ + +
+
{/* 消息列表 */} @@ -164,14 +213,14 @@ export function MainPanel({ session, filter, onFilterChange }: MainPanelProps) { {!session ? (
- 暂无会话数据 + 暂无会话数据,可在下方直接输入需求启动 Harness
) : entries.length === 0 ? (
没有匹配的消息
@@ -188,6 +237,85 @@ export function MainPanel({ session, filter, onFilterChange }: MainPanelProps) { )}
+ + {/* 底部输入与运行状态栏 */} +
+
+ {chatStatus.status !== "idle" && ( +
+ + + {chatStatus.message || chatStatus.trace || "处理中..."} + +
+ )} + +
+ + [{mode.toUpperCase()}] + + setInput(e.target.value)} + onKeyDown={handleKeyDown} + disabled={chatStatus.status === "running"} + placeholder={ + chatStatus.status === "running" + ? "Harness 正在执行任务中..." + : "输入指令或任务,回车直接调用 Harness CLI..." + } + className="h-8 flex-1 bg-transparent text-[13px] outline-none disabled:opacity-50" + style={{ color: "var(--text-primary)" }} + /> + +
+
+
); } diff --git a/packages/client/src/types.ts b/packages/client/src/types.ts index 02c4453..1ed7b3c 100644 --- a/packages/client/src/types.ts +++ b/packages/client/src/types.ts @@ -1,8 +1,10 @@ -export type Theme = 'light' | 'dark'; +export type AgentMode = "plan" | "build"; -export type EntryRole = 'user' | 'assistant' | 'tool' | 'system'; +export type Theme = "light" | "dark"; -export type Filter = 'all' | EntryRole; +export type EntryRole = "user" | "assistant" | "tool" | "system"; + +export type Filter = "all" | EntryRole; export interface WebEntry { seq: number; @@ -60,3 +62,9 @@ export interface WebExport { exportedAt: string; sessions: WebSession[]; } + +export interface ChatStatusMessage { + status: "idle" | "running" | "success" | "error"; + trace?: string; + message?: string; +} diff --git a/packages/client/src/ws.ts b/packages/client/src/ws.ts index 83a3b0f..3ed1138 100644 --- a/packages/client/src/ws.ts +++ b/packages/client/src/ws.ts @@ -1,32 +1,32 @@ -import type { WebExport, WebSession } from './types'; +import type { AgentMode, ChatStatusMessage, WebExport, WebSession } from "./types"; -const DEFAULT_WS_PATH = '/ws'; +const DEFAULT_WS_PATH = "/ws"; const DEFAULT_TIMEOUT_MS = 8000; const DEFAULT_REFRESH_MS = 5000; const isWebSession = (value: unknown): value is WebSession => { - if (!value || typeof value !== 'object') { + if (!value || typeof value !== "object") { return false; } const session = value as Partial; return ( - typeof session.id === 'string' && - typeof session.createdAt === 'string' && - typeof session.cwd === 'string' && + typeof session.id === "string" && + typeof session.createdAt === "string" && + typeof session.cwd === "string" && Array.isArray(session.entries) ); }; export const isWebExport = (value: unknown): value is WebExport => { - if (!value || typeof value !== 'object') { + if (!value || typeof value !== "object") { return false; } const data = value as Partial; return ( data.schemaVersion === 1 && - typeof data.exportedAt === 'string' && + typeof data.exportedAt === "string" && Array.isArray(data.sessions) && data.sessions.every(isWebSession) ); @@ -34,29 +34,51 @@ export const isWebExport = (value: unknown): value is WebExport => { /** 从服务端消息中提取会话快照,类型不符或结构非法时返回 null。 */ export const parseSnapshotMessage = (value: unknown): WebExport | null => { - if (!value || typeof value !== 'object') { + if (!value || typeof value !== "object") { return null; } const message = value as { type?: unknown; data?: unknown }; - if (message.type !== 'sessions.snapshot') { + if (message.type !== "sessions.snapshot") { return null; } return isWebExport(message.data) ? message.data : null; }; +export const parseChatStatusMessage = (value: unknown): ChatStatusMessage | null => { + if (!value || typeof value !== "object") { + return null; + } + + const message = value as { type?: unknown; status?: unknown; trace?: unknown; message?: unknown }; + if (message.type !== "chat.status") { + return null; + } + + const status = message.status; + if (status !== "idle" && status !== "running" && status !== "success" && status !== "error") { + return null; + } + + return { + status, + trace: typeof message.trace === "string" ? message.trace : undefined, + message: typeof message.message === "string" ? message.message : undefined, + }; +}; + const resolveWsUrl = (override?: string): string => { if (override) { return override; } const params = new URLSearchParams(window.location.search); - const fromQuery = params.get('ws') ?? params.get('wsUrl'); + const fromQuery = params.get("ws") ?? params.get("wsUrl"); if (fromQuery) { return fromQuery; } - const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; + const protocol = window.location.protocol === "https:" ? "wss:" : "ws:"; return `${protocol}//${window.location.host}${DEFAULT_WS_PATH}`; }; @@ -65,22 +87,26 @@ export interface LiveExportOptions { timeoutMs?: number; refreshMs?: number; onSnapshot: (data: WebExport) => void; + onChatStatus?: (status: ChatStatusMessage) => void; } export interface LiveExportConnection { ready: Promise; + sendMessage: (payload: { input: string; mode?: AgentMode }) => boolean; + refresh: () => void; close(): void; } /** * 连接 WebSocket 会话服务:连接成功后立即拉取快照,之后按 refreshMs 周期性刷新。 - * 断开时自动退避重连,close 可彻底关闭。 + * 断开时自动退避重连,支持发送 chat.send 消息触发 harness。 */ export const connectLiveExport = ( options: LiveExportOptions, ): LiveExportConnection => { const { onSnapshot, + onChatStatus, url, timeoutMs = DEFAULT_TIMEOUT_MS, refreshMs = DEFAULT_REFRESH_MS, @@ -142,7 +168,9 @@ export const connectLiveExport = ( return; } refreshTimer = setTimeout(() => { - socket?.send(JSON.stringify({ type: 'sessions.list' })); + if (socket?.readyState === WebSocket.OPEN) { + socket.send(JSON.stringify({ type: "sessions.list" })); + } scheduleRefresh(); }, refreshMs); }; @@ -188,7 +216,7 @@ export const connectLiveExport = ( current.onopen = () => { attempt = 0; - current.send(JSON.stringify({ type: 'sessions.list' })); + current.send(JSON.stringify({ type: "sessions.list" })); scheduleRefresh(); }; @@ -200,6 +228,12 @@ export const connectLiveExport = ( return; } + const chatStatus = parseChatStatusMessage(parsed); + if (chatStatus) { + onChatStatus?.(chatStatus); + return; + } + const data = parseSnapshotMessage(parsed); if (!data) { return; @@ -230,6 +264,24 @@ export const connectLiveExport = ( return { ready, + sendMessage(payload) { + if (!socket || socket.readyState !== WebSocket.OPEN) { + return false; + } + socket.send( + JSON.stringify({ + type: "chat.send", + input: payload.input, + mode: payload.mode ?? "build", + }), + ); + return true; + }, + refresh() { + if (socket && socket.readyState === WebSocket.OPEN) { + socket.send(JSON.stringify({ type: "sessions.list" })); + } + }, close() { closed = true; clearTimers(); diff --git a/tests/client-ui.spec.ts b/tests/client-ui.spec.ts index 0c38420..8b428ff 100644 --- a/tests/client-ui.spec.ts +++ b/tests/client-ui.spec.ts @@ -1,17 +1,18 @@ -import { describe, expect, it, vi } from 'vitest'; -import React from 'react'; -import { renderToStaticMarkup } from 'react-dom/server'; -import { HeaderBar } from '../packages/client/src/components/HeaderBar'; -import type { WebSession } from '../packages/client/src/types'; +import { describe, expect, it, vi } from "vitest"; +import React from "react"; +import { renderToStaticMarkup } from "react-dom/server"; +import { HeaderBar } from "../packages/client/src/components/HeaderBar"; +import { MainPanel } from "../packages/client/src/components/MainPanel"; +import type { WebSession } from "../packages/client/src/types"; -vi.mock('../packages/client/assets/call-code.png', () => ({ - default: 'call-code.png', +vi.mock("../packages/client/assets/call-code.png", () => ({ + default: "call-code.png", })); const makeSession = (overrides: Partial = {}): WebSession => ({ - id: 's1', - createdAt: '2026-08-05T00:00:00.000Z', - cwd: '/tmp/project', + id: "s1", + createdAt: "2026-08-05T00:00:00.000Z", + cwd: "/tmp/project", parentSessionId: null, metadata: {}, stats: { @@ -24,21 +25,22 @@ const makeSession = (overrides: Partial = {}): WebSession => ({ entries: [ { seq: 1, - id: 'e1', + id: "e1", parentId: null, - type: 'user', - role: 'user', - timestamp: '2026-08-05T00:00:00.000Z', - payload: {}, + type: "user", + role: "user", + timestamp: "2026-08-05T00:00:00.000Z", + text: "hello world", + payload: { role: "user", content: "hello world" }, }, { seq: 2, - id: 'e2', + id: "e2", parentId: null, - type: 'tool', - role: 'tool', - timestamp: '2026-08-05T00:00:00.000Z', - tool: 'read_file', + type: "tool", + role: "tool", + timestamp: "2026-08-05T00:00:00.000Z", + tool: "read_file", payload: {}, }, ], @@ -47,52 +49,85 @@ const makeSession = (overrides: Partial = {}): WebSession => ({ ...overrides, }); -describe('client HeaderBar', () => { - it('顶部栏展示产品名、会话统计和主题切换', () => { +describe("client HeaderBar", () => { + it("顶部栏展示产品名、会话统计和主题切换", () => { const html = renderToStaticMarkup( React.createElement(HeaderBar, { sessions: [makeSession()], - theme: 'dark', + theme: "dark", onThemeChange: () => undefined, }), ); - expect(html).toContain('Call Code'); - expect(html).toContain('1 个会话'); - expect(html).toContain('2 条消息'); - expect(html).toContain('1 次工具'); - expect(html).toContain('浅色'); - expect(html).toContain('深色'); + expect(html).toContain("Call Code"); + expect(html).toContain("1 个会话"); + expect(html).toContain("2 条消息"); + expect(html).toContain("1 次工具"); + expect(html).toContain("浅色"); + expect(html).toContain("深色"); }); - it('统计按多个会话累加', () => { - const second = makeSession({ id: 's2' }); + it("统计按多个会话累加", () => { + const second = makeSession({ id: "s2" }); const html = renderToStaticMarkup( React.createElement(HeaderBar, { sessions: [makeSession(), second], - theme: 'light', + theme: "light", onThemeChange: () => undefined, }), ); - expect(html).toContain('2 个会话'); - expect(html).toContain('4 条消息'); - expect(html).toContain('2 次工具'); - expect(html).toContain('浅色'); + expect(html).toContain("2 个会话"); + expect(html).toContain("4 条消息"); + expect(html).toContain("2 次工具"); + expect(html).toContain("浅色"); }); - it('服务未连接时仍显示完整界面状态', () => { + it("服务未连接时仍显示完整界面状态", () => { const html = renderToStaticMarkup( React.createElement(HeaderBar, { sessions: [], - theme: 'light', - connectionState: 'error', + theme: "light", + connectionState: "error", onThemeChange: () => undefined, }), ); - expect(html).toContain('Call Code'); - expect(html).toContain('等待会话服务'); - expect(html).toContain('浅色'); + expect(html).toContain("Call Code"); + expect(html).toContain("等待会话服务"); + expect(html).toContain("浅色"); + }); +}); + +describe("client MainPanel", () => { + it("渲染输入框、模式选择与发送按钮", () => { + const html = renderToStaticMarkup( + React.createElement(MainPanel, { + session: makeSession(), + filter: "all", + onFilterChange: () => undefined, + chatStatus: { status: "idle" }, + onSendMessage: () => true, + }), + ); + + expect(html).toContain("BUILD"); + expect(html).toContain("PLAN"); + expect(html).toContain("发送"); + expect(html).toContain("hello world"); + }); + + it("展示任务运行中的 trace 状态", () => { + const html = renderToStaticMarkup( + React.createElement(MainPanel, { + session: makeSession(), + filter: "all", + onFilterChange: () => undefined, + chatStatus: { status: "running", trace: "正在执行工具调用..." }, + onSendMessage: () => true, + }), + ); + + expect(html).toContain("正在执行工具调用..."); }); }); diff --git a/tests/web-server.spec.ts b/tests/web-server.spec.ts index 724d726..ad24084 100644 --- a/tests/web-server.spec.ts +++ b/tests/web-server.spec.ts @@ -1,20 +1,36 @@ -import { afterEach, describe, expect, it } from 'vitest'; -import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'; -import { tmpdir } from 'node:os'; -import { join } from 'node:path'; -import { WebSocket } from 'ws'; -import { SessionStore } from '../packages/session-sqlite/src/index'; -import type { WebExport } from '../packages/agent-core/src/web/export'; +import { afterEach, describe, expect, it, vi } from "vitest"; +import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { WebSocket } from "ws"; +import { SessionStore } from "../packages/session-sqlite/src/index"; +import type { WebExport } from "../packages/agent-core/src/web/export"; + +vi.mock("../packages/agent-core/src/harness/runtime/run-loop", () => ({ + runLoop: vi.fn(async (task, handlers, options) => { + handlers?.onTrace?.("正在检索本地上下文"); + if (options?.persist && options?.sessionStore) { + const store = options.sessionStore; + store.createSession({ id: task.id, cwd: task.workspace || "/tmp" }); + store.appendEntry(task.id, { + type: "assistant", + payload: { role: "assistant", content: "已处理完毕" }, + }); + } + return "已处理完毕"; + }), +})); + import { startWebServer, type WebServerHandle, -} from '../packages/agent-core/src/web/server'; +} from "../packages/agent-core/src/web/server"; const stores: SessionStore[] = []; const handles: WebServerHandle[] = []; const createServer = async (clientDir?: string) => { - const store = new SessionStore({ dbPath: ':memory:' }); + const store = new SessionStore({ dbPath: ":memory:" }); stores.push(store); const handle = await startWebServer({ store, port: 0, clientDir }); handles.push(handle); @@ -35,39 +51,39 @@ const requestSnapshot = (url: string): Promise => const socket = new WebSocket(url); const timeout = setTimeout(() => { socket.terminate(); - reject(new Error('等待会话快照超时')); + reject(new Error("等待会话快照超时")); }, 3000); - socket.on('open', () => { - socket.send(JSON.stringify({ type: 'sessions.list' })); + socket.on("open", () => { + socket.send(JSON.stringify({ type: "sessions.list" })); }); - socket.on('message', (raw) => { + socket.on("message", (raw) => { const message = JSON.parse(String(raw)) as { type?: string; data?: WebExport; }; - if (message.type === 'sessions.snapshot' && message.data) { + if (message.type === "sessions.snapshot" && message.data) { clearTimeout(timeout); socket.close(); resolve(message.data); } }); - socket.on('error', (error) => { + socket.on("error", (error) => { clearTimeout(timeout); reject(error); }); }); -describe('WebSocket 会话服务', () => { - it('响应 sessions.list 并返回完整会话快照', async () => { +describe("WebSocket 会话服务", () => { + it("响应 sessions.list 并返回完整会话快照", async () => { const { store, handle } = await createServer(); - store.createSession({ cwd: '/tmp/project', id: 's-live' }); - store.appendEntry('s-live', { - id: 'e1', - type: 'user', - payload: { role: 'user', content: 'hello ws' }, + store.createSession({ cwd: "/tmp/project", id: "s-live" }); + store.appendEntry("s-live", { + id: "e1", + type: "user", + payload: { role: "user", content: "hello ws" }, }); - store.updateStats('s-live', { + store.updateStats("s-live", { messageCount: 1, cachedTokens: 0, uncachedTokens: 0, @@ -79,50 +95,106 @@ describe('WebSocket 会话服务', () => { expect(data.schemaVersion).toBe(1); expect(data.sessions).toHaveLength(1); - expect(data.sessions[0].entries[0].text).toBe('hello ws'); + expect(data.sessions[0].entries[0].text).toBe("hello ws"); + }); + + it("响应 chat.send 并触发 harness 执行回传状态与快照", async () => { + const { handle } = await createServer(); + const statuses: unknown[] = []; + let snapshotReceived: WebExport | null = null; + + await new Promise((resolve, reject) => { + const socket = new WebSocket(`ws://127.0.0.1:${handle.port}/ws`); + const timeout = setTimeout(() => { + socket.terminate(); + reject(new Error("等待任务执行超时")); + }, 4000); + + socket.on("open", () => { + socket.send( + JSON.stringify({ + type: "chat.send", + input: "重构页面", + mode: "build", + }), + ); + }); + + socket.on("message", (raw) => { + const message = JSON.parse(String(raw)) as { + type?: string; + status?: string; + data?: WebExport; + }; + if (message.type === "chat.status") { + statuses.push(message); + if (message.status === "success" && snapshotReceived) { + clearTimeout(timeout); + socket.close(); + resolve(); + } + } else if (message.type === "sessions.snapshot" && message.data) { + snapshotReceived = message.data; + if (statuses.some((s: any) => s.status === "success")) { + clearTimeout(timeout); + socket.close(); + resolve(); + } + } + }); + + socket.on("error", (error) => { + clearTimeout(timeout); + reject(error); + }); + }); + + expect(statuses.length).toBeGreaterThanOrEqual(2); + expect(snapshotReceived).not.toBeNull(); + expect((snapshotReceived as unknown as WebExport).sessions.length).toBeGreaterThan(0); }); - it('无法解析的消息返回 error 响应', async () => { + it("无法解析的消息返回 error 响应", async () => { const { handle } = await createServer(); const message = await new Promise((resolve, reject) => { const socket = new WebSocket(`ws://127.0.0.1:${handle.port}/ws`); const timeout = setTimeout(() => { socket.terminate(); - reject(new Error('等待错误响应超时')); + reject(new Error("等待错误响应超时")); }, 3000); - socket.on('open', () => { - socket.send('not json'); + socket.on("open", () => { + socket.send("not json"); }); - socket.on('message', (raw) => { + socket.on("message", (raw) => { clearTimeout(timeout); socket.close(); resolve(JSON.parse(String(raw))); }); - socket.on('error', (error) => { + socket.on("error", (error) => { clearTimeout(timeout); reject(error); }); }); - expect(message).toMatchObject({ type: 'error' }); + expect(message).toMatchObject({ type: "error" }); }); - it('HTTP 服务返回客户端页面并支持 SPA 回退', async () => { - const dir = mkdtempSync(join(tmpdir(), 'call-code-web-client-')); - writeFileSync(join(dir, 'index.html'), '

Call Code Web

'); + it("HTTP 服务返回客户端页面并支持 SPA 回退", async () => { + const dir = mkdtempSync(join(tmpdir(), "call-code-web-client-")); + writeFileSync(join(dir, "index.html"), "

Call Code Web

"); try { const { handle } = await createServer(dir); const home = await fetch(`http://127.0.0.1:${handle.port}/`); expect(home.status).toBe(200); - expect(await home.text()).toContain('Call Code Web'); + expect(await home.text()).toContain("Call Code Web"); const fallback = await fetch( `http://127.0.0.1:${handle.port}/some/route`, ); expect(fallback.status).toBe(200); - expect(await fallback.text()).toContain('Call Code Web'); + expect(await fallback.text()).toContain("Call Code Web"); } finally { rmSync(dir, { recursive: true, force: true }); } From 8a5d5e12bd5e69da8919dc5ae229f99d5442b9aa Mon Sep 17 00:00:00 2001 From: AlkaidSTART <2595006848@qq.com> Date: Sun, 23 Aug 2026 19:20:54 +0800 Subject: [PATCH 08/10] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=20server=20?= =?UTF-8?q?=E5=8C=85=E4=B8=8E=20SDK=20=E5=85=A5=E5=8F=A3=E5=B9=B6=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=20Web=20=E6=9C=8D=E5=8A=A1=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/agent-core/src/index.ts | 45 ++++++++++ packages/server/package.json | 22 +++++ packages/server/src/index.ts | 79 +++++++++++++++++ packages/server/tsconfig.json | 13 +++ source/web-server.ts | 14 +-- tests/server.spec.ts | 148 +++++++++++++++++++++++++++++++ tsconfig.json | 4 + 7 files changed, 315 insertions(+), 10 deletions(-) create mode 100644 packages/agent-core/src/index.ts create mode 100644 packages/server/package.json create mode 100644 packages/server/src/index.ts create mode 100644 packages/server/tsconfig.json create mode 100644 tests/server.spec.ts diff --git a/packages/agent-core/src/index.ts b/packages/agent-core/src/index.ts new file mode 100644 index 0000000..5212f03 --- /dev/null +++ b/packages/agent-core/src/index.ts @@ -0,0 +1,45 @@ +export { agent, type AgentOptions } from './harness/core/agent'; +export { + callLLM, + streamLLM, + llmModel, + type Message as LLMMessage, + type StreamHandlers, +} from './harness/core/llm'; +export { + createTaskState, + type AgentMode, + type TaskState, + type CreateTaskStateOptions, +} from './harness/core/state'; +export { + runLoop, + type RunLoopOptions, +} from './harness/runtime/run-loop'; +export { + executeToolCall, + type ToolExecutionResult, +} from './harness/tools/executor'; +export { tools } from './harness/tools/index'; +export { + buildWebExport, + writeWebExport, + type WebEntry, + type WebRecord, + type WebFact, + type WebSession, + type WebExport, + type WebStore, +} from './web/export'; +export { + parseClientMessage, + type ChatSendPayload, + type WebSocketClientMessage, + type WebSocketServerMessage, +} from './web/protocol'; +export { + startWebServer, + type WebServerOptions, + type WebServerHandle, +} from './web/server'; +export * from './harness/session/index'; diff --git a/packages/server/package.json b/packages/server/package.json new file mode 100644 index 0000000..9fce589 --- /dev/null +++ b/packages/server/package.json @@ -0,0 +1,22 @@ +{ + "name": "@call-code/server", + "version": "0.1.0", + "private": true, + "type": "module", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "scripts": { + "build": "tsc -p tsconfig.json", + "typecheck": "tsc -p tsconfig.json --noEmit" + }, + "dependencies": { + "@call-code/agent-core": "workspace:*", + "@call-code/session-sqlite": "workspace:*", + "ws": "^8.21.3" + }, + "devDependencies": { + "@types/node": "^25.6.0", + "@types/ws": "^8.18.1", + "typescript": "^6.0.3" + } +} diff --git a/packages/server/src/index.ts b/packages/server/src/index.ts new file mode 100644 index 0000000..9cbabff --- /dev/null +++ b/packages/server/src/index.ts @@ -0,0 +1,79 @@ +import { SessionStore, DEFAULT_DB_PATH, type SessionStoreConfig } from '../../session-sqlite/src/index'; +import { + startWebServer, + buildWebExport, + writeWebExport, + type WebServerHandle, + type WebServerOptions, + type WebExport, + type WebStore, +} from '../../agent-core/src/index'; + +export interface ServerConfig { + dbPath?: string; + port?: number; + host?: string; + clientDir?: string; + store?: SessionStore; +} + +export interface ServerInstance { + store: SessionStore; + handle: WebServerHandle; + port: number; + host: string; + close(): Promise; +} + +/** + * 启动 Call Code 统一后端服务:集成 SQLite 会话存储与 WebUI WebSocket / 静态托管服务。 + */ +export const startServer = async ( + config: ServerConfig = {}, +): Promise => { + const dbPath = config.dbPath ?? process.env.SESSION_DB_PATH ?? DEFAULT_DB_PATH; + const store = config.store ?? new SessionStore({ dbPath }); + const ownsStore = !config.store; + + const port = + config.port ?? Number(process.env.CALL_CODE_WEB_PORT ?? 4173); + const host = config.host ?? "127.0.0.1"; + const clientDir = config.clientDir; + + const handle = await startWebServer({ + store, + port, + host, + clientDir, + }); + + return { + store, + handle, + port: handle.port, + host: handle.host, + async close() { + await handle.close(); + if (ownsStore) { + store.close(); + } + }, + }; +}; + +// 重新导出 agent-core 与 session-sqlite 核心能力与类型 +export { + SessionStore, + DEFAULT_DB_PATH, + startWebServer, + buildWebExport, + writeWebExport, +}; +export type { + SessionStoreConfig, + WebServerHandle, + WebServerOptions, + WebExport, + WebStore, +}; +export * from '../../agent-core/src/index'; diff --git a/packages/server/tsconfig.json b/packages/server/tsconfig.json new file mode 100644 index 0000000..93c079a --- /dev/null +++ b/packages/server/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "bundler", + "noEmit": true + }, + "include": [ + "src", + "../agent-core/src", + "../session-sqlite/src" + ] +} diff --git a/source/web-server.ts b/source/web-server.ts index 76de6f9..035d259 100644 --- a/source/web-server.ts +++ b/source/web-server.ts @@ -1,22 +1,16 @@ -import { SessionStore } from '../packages/session-sqlite/src/index'; -import { DEFAULT_DB_PATH } from '../packages/session-sqlite/src/store'; -import { startWebServer } from '@web/server'; +import { startServer } from '@server'; const main = async () => { - const dbPath = process.env.SESSION_DB_PATH ?? DEFAULT_DB_PATH; - const store = new SessionStore({ dbPath }); - const port = Number(process.env.CALL_CODE_WEB_PORT ?? 4173); - const handle = await startWebServer({ store, port }); + const server = await startServer(); const shutdown = async () => { - await handle.close(); - store.close(); + await server.close(); process.exit(0); }; process.on('SIGINT', shutdown); process.on('SIGTERM', shutdown); - console.log(`Web 会话面板已启动: http://127.0.0.1:${handle.port}`); + console.log(`Web 会话面板已启动: http://${server.host}:${server.port}`); }; main().catch((error) => { diff --git a/tests/server.spec.ts b/tests/server.spec.ts new file mode 100644 index 0000000..1ff8e40 --- /dev/null +++ b/tests/server.spec.ts @@ -0,0 +1,148 @@ +import { afterEach, describe, expect, it, vi } from "vitest"; +import { WebSocket } from "ws"; +import { + startServer, + type ServerInstance, + type WebExport, + SessionStore, +} from "../packages/server/src/index"; + +vi.mock("../packages/agent-core/src/harness/runtime/run-loop", () => ({ + runLoop: vi.fn(async (task, handlers, options) => { + handlers?.onTrace?.("正在检索本地上下文"); + if (options?.persist && options?.sessionStore) { + const store = options.sessionStore; + store.createSession({ id: task.id, cwd: task.workspace || "/tmp" }); + store.appendEntry(task.id, { + type: "assistant", + payload: { role: "assistant", content: "已处理完毕" }, + }); + } + return "已处理完毕"; + }), +})); + +const servers: ServerInstance[] = []; + +const createTestServer = async () => { + const store = new SessionStore({ dbPath: ":memory:" }); + const server = await startServer({ store, port: 0 }); + servers.push(server); + return { server, store }; +}; + +afterEach(async () => { + for (const server of servers.splice(0)) { + await server.close(); + } +}); + +const requestSnapshot = (url: string): Promise => + new Promise((resolve, reject) => { + const socket = new WebSocket(url); + const timeout = setTimeout(() => { + socket.terminate(); + reject(new Error("等待会话快照超时")); + }, 3000); + + socket.on("open", () => { + socket.send(JSON.stringify({ type: "sessions.list" })); + }); + socket.on("message", (raw) => { + const message = JSON.parse(String(raw)) as { + type?: string; + data?: WebExport; + }; + if (message.type === "sessions.snapshot" && message.data) { + clearTimeout(timeout); + socket.close(); + resolve(message.data); + } + }); + socket.on("error", (error) => { + clearTimeout(timeout); + reject(error); + }); + }); + +describe("Server SDK 与集成服务", () => { + it("通过 Server SDK 启动服务并响应 sessions.list", async () => { + const { server, store } = await createTestServer(); + store.createSession({ cwd: "/tmp/sdk-test", id: "s-sdk-1" }); + store.appendEntry("s-sdk-1", { + id: "e-sdk-1", + type: "user", + payload: { role: "user", content: "hello server sdk" }, + }); + store.updateStats("s-sdk-1", { + messageCount: 1, + cachedTokens: 0, + uncachedTokens: 0, + totalTokens: 0, + costTotal: 0, + }); + + const data = await requestSnapshot(`ws://${server.host}:${server.port}/ws`); + + expect(data.schemaVersion).toBe(1); + expect(data.sessions).toHaveLength(1); + expect(data.sessions[0].id).toBe("s-sdk-1"); + expect(data.sessions[0].entries[0].text).toBe("hello server sdk"); + }); + + it("通过 Server SDK 接收 chat.send 并触发 Agent 执行", async () => { + const { server } = await createTestServer(); + const statuses: unknown[] = []; + let snapshotReceived: WebExport | null = null; + + await new Promise((resolve, reject) => { + const socket = new WebSocket(`ws://${server.host}:${server.port}/ws`); + const timeout = setTimeout(() => { + socket.terminate(); + reject(new Error("等待任务执行超时")); + }, 4000); + + socket.on("open", () => { + socket.send( + JSON.stringify({ + type: "chat.send", + input: "测试 SDK 调用", + mode: "build", + }), + ); + }); + + socket.on("message", (raw) => { + const message = JSON.parse(String(raw)) as { + type?: string; + status?: string; + data?: WebExport; + }; + if (message.type === "chat.status") { + statuses.push(message); + if (message.status === "success" && snapshotReceived) { + clearTimeout(timeout); + socket.close(); + resolve(); + } + } else if (message.type === "sessions.snapshot" && message.data) { + snapshotReceived = message.data; + if (statuses.some((s: any) => s.status === "success")) { + clearTimeout(timeout); + socket.close(); + resolve(); + } + } + }); + + socket.on("error", (error) => { + clearTimeout(timeout); + reject(error); + }); + }); + + expect(statuses.length).toBeGreaterThanOrEqual(2); + expect(snapshotReceived).not.toBeNull(); + expect((snapshotReceived as unknown as WebExport).sessions.length).toBeGreaterThan(0); + }); +}); diff --git a/tsconfig.json b/tsconfig.json index 4581f75..48f9e53 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,6 +12,9 @@ "skipLibCheck": true, "paths": { + "@server": ["./packages/server/src/index.ts"], + "@server/*": ["./packages/server/src/*"], + "@agent-core": ["./packages/agent-core/src/index.ts"], "@agent-core/*": ["./packages/agent-core/src/*"], "@core/*": ["./packages/agent-core/src/harness/core/*"], "@config/*": ["./packages/agent-core/src/config/*"], @@ -27,6 +30,7 @@ }, "include": [ "packages/agent-core/src/**/*.ts", + "packages/server/src/**/*.ts", "source/**/*.ts", "source/**/*.tsx", "tests/**/*.ts", From d860daeb18519bce74ea690054407f02ea2910bd Mon Sep 17 00:00:00 2001 From: AlkaidSTART <2595006848@qq.com> Date: Sun, 23 Aug 2026 19:46:10 +0800 Subject: [PATCH 09/10] feat: add build script for session-sqlite and server refactor: update import paths to include .js extensions in agent-core package fix: ensure proper type imports in agent-core package chore: update package.json for client to include server dependency feat: implement client-side WebSocket connection for live export functionality --- bun.lock | 17 + package.json | 2 + .../compaction/branch-summarization.ts | 8 +- .../src/harness/compaction/compaction.ts | 6 +- .../src/harness/compaction/index.ts | 6 +- .../src/harness/compaction/utils.ts | 4 +- .../agent-core/src/harness/context/builder.ts | 6 +- .../src/harness/context/context-builder.ts | 2 +- .../src/harness/context/context-summarizer.ts | 2 +- .../src/harness/context/runtime-context.ts | 10 +- .../src/harness/context/task-context.ts | 2 +- packages/agent-core/src/harness/core/agent.ts | 6 +- .../src/harness/memory/memory-retriever.ts | 2 +- .../src/harness/memory/memory-store.ts | 2 +- .../src/harness/memory/memory-writer.ts | 6 +- .../agent-core/src/harness/prompt/modes.ts | 2 +- .../agent-core/src/harness/protocol/index.ts | 10 +- .../agent-core/src/harness/protocol/parser.ts | 2 +- .../agent-core/src/harness/runtime/index.ts | 6 +- .../src/harness/runtime/run-loop.ts | 36 +- .../src/harness/runtime/session-runtime.ts | 14 +- .../src/harness/runtime/tool-runtime.ts | 8 +- .../src/harness/session/activity-query.ts | 4 +- .../agent-core/src/harness/session/history.ts | 6 +- .../agent-core/src/harness/session/index.ts | 10 +- .../src/harness/session/store-registry.ts | 2 +- .../src/harness/session/task-session.ts | 6 +- packages/agent-core/src/harness/tools/bash.ts | 2 +- .../agent-core/src/harness/tools/executor.ts | 10 +- .../src/harness/tools/getEnvironment.ts | 2 +- .../agent-core/src/harness/tools/gitDiff.ts | 2 +- .../agent-core/src/harness/tools/index.ts | 14 +- packages/agent-core/src/harness/tools/ocr.ts | 2 +- .../src/harness/tools/policy/guard.ts | 4 +- .../src/harness/tools/policy/modes.ts | 2 +- .../agent-core/src/harness/tools/readFile.ts | 2 +- .../agent-core/src/harness/tools/search.ts | 2 +- .../agent-core/src/harness/tools/writeFile.ts | 2 +- .../agent-core/src/harness/utils/shell.ts | 2 +- packages/agent-core/src/index.ts | 20 +- packages/agent-core/src/web/export.ts | 2 +- packages/agent-core/src/web/protocol.ts | 4 +- packages/agent-core/src/web/server.ts | 8 +- packages/agent-core/tsconfig.json | 4 +- packages/client/package.json | 1 + packages/client/src/types.ts | 87 +---- packages/client/src/ws.ts | 301 +------------- packages/client/tsconfig.json | 6 +- packages/client/vite.config.ts | 16 + packages/server/package.json | 14 + packages/server/src/client.ts | 369 ++++++++++++++++++ packages/server/src/index.ts | 76 +++- packages/server/tsconfig.json | 17 +- packages/session-sqlite/src/index.ts | 6 +- packages/session-sqlite/src/store.ts | 4 +- packages/session-sqlite/tsconfig.json | 4 +- tests/client-ws.spec.ts | 4 +- tests/server.spec.ts | 19 +- tsconfig.json | 5 + vitest.config.ts | 5 + 60 files changed, 689 insertions(+), 516 deletions(-) create mode 100644 packages/server/src/client.ts diff --git a/bun.lock b/bun.lock index 96d85e4..a79467b 100644 --- a/bun.lock +++ b/bun.lock @@ -43,6 +43,7 @@ "name": "@call-code/client", "version": "0.1.0", "dependencies": { + "@call-code/server": "workspace:*", "react": "^19.2.8", "react-dom": "^19.2.8", }, @@ -56,6 +57,20 @@ "vite": "^8.2.0", }, }, + "packages/server": { + "name": "@call-code/server", + "version": "0.1.0", + "dependencies": { + "@call-code/agent-core": "workspace:*", + "@call-code/session-sqlite": "workspace:*", + "ws": "^8.21.3", + }, + "devDependencies": { + "@types/node": "^25.6.0", + "@types/ws": "^8.18.1", + "typescript": "^6.0.3", + }, + }, "packages/session-sqlite": { "name": "@call-code/session-sqlite", "version": "0.1.0", @@ -75,6 +90,8 @@ "@call-code/client": ["@call-code/client@workspace:packages/client"], + "@call-code/server": ["@call-code/server@workspace:packages/server"], + "@call-code/session-sqlite": ["@call-code/session-sqlite@workspace:packages/session-sqlite"], "@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.28.2", "", { "os": "aix", "cpu": "ppc64" }, "sha512-XExcO+dvLKvVtNTibSTBej1NCAbaGhWn9Ww1ZPx80qsahhPFe/8jgWP0IchNe0F3HwkU7n8ejhH8bjonqht8mQ=="], diff --git a/package.json b/package.json index 638a619..02def43 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,8 @@ "typecheck:client": "tsc -p packages/client/tsconfig.json --noEmit", "test": "vitest run --reporter verbose", "build:agent-core": "tsc -p packages/agent-core/tsconfig.json", + "build:session-sqlite": "tsc -p packages/session-sqlite/tsconfig.json", + "build:server": "bun run build:session-sqlite && bun run build:agent-core && bun run --cwd packages/server build", "export:web": "tsx tests/export-web.ts", "dev:client": "bun run --cwd packages/client dev", "build:client": "bun run --cwd packages/client build", diff --git a/packages/agent-core/src/harness/compaction/branch-summarization.ts b/packages/agent-core/src/harness/compaction/branch-summarization.ts index 74eaefb..1100aa1 100644 --- a/packages/agent-core/src/harness/compaction/branch-summarization.ts +++ b/packages/agent-core/src/harness/compaction/branch-summarization.ts @@ -1,6 +1,6 @@ -import type { ContextMessage } from '../context/context-types'; -import type { EntryLike, SessionStoreLike } from '../session/store-types'; -import type { SummarizeFn } from './compaction'; +import type { ContextMessage } from '../context/context-types.js'; +import type { EntryLike, SessionStoreLike } from '../session/store-types.js'; +import type { SummarizeFn } from './compaction.js'; import { computeFileLists, createFileOps, @@ -9,7 +9,7 @@ import { formatFileOperations, serializeConversation, type FileOperations, -} from './utils'; +} from './utils.js'; export interface BranchSummaryEntryPayload { kind: 'branch_summary'; diff --git a/packages/agent-core/src/harness/compaction/compaction.ts b/packages/agent-core/src/harness/compaction/compaction.ts index 54f71d2..83d7c78 100644 --- a/packages/agent-core/src/harness/compaction/compaction.ts +++ b/packages/agent-core/src/harness/compaction/compaction.ts @@ -1,5 +1,5 @@ -import type { ContextMessage } from '../context/context-types'; -import type { EntryLike, SessionStoreLike } from '../session/store-types'; +import type { ContextMessage } from '../context/context-types.js'; +import type { EntryLike, SessionStoreLike } from '../session/store-types.js'; import { computeFileLists, createFileOps, @@ -9,7 +9,7 @@ import { formatFileOperations, serializeConversation, type FileOperations, -} from './utils'; +} from './utils.js'; export interface CompactionSettings { enabled: boolean; diff --git a/packages/agent-core/src/harness/compaction/index.ts b/packages/agent-core/src/harness/compaction/index.ts index 52d476d..8b73e51 100644 --- a/packages/agent-core/src/harness/compaction/index.ts +++ b/packages/agent-core/src/harness/compaction/index.ts @@ -1,3 +1,3 @@ -export * from './branch-summarization'; -export * from './compaction'; -export * from './utils'; +export * from './branch-summarization.js'; +export * from './compaction.js'; +export * from './utils.js'; diff --git a/packages/agent-core/src/harness/compaction/utils.ts b/packages/agent-core/src/harness/compaction/utils.ts index 64b9948..68ce017 100644 --- a/packages/agent-core/src/harness/compaction/utils.ts +++ b/packages/agent-core/src/harness/compaction/utils.ts @@ -1,5 +1,5 @@ -import type { ContextMessage } from '../context/context-types'; -import type { EntryLike } from '../session/store-types'; +import type { ContextMessage } from '../context/context-types.js'; +import type { EntryLike } from '../session/store-types.js'; /** 摘要阶段累积的文件读写信息,后续追加到摘要里让模型保留文件上下文。 */ export interface FileOperations { diff --git a/packages/agent-core/src/harness/context/builder.ts b/packages/agent-core/src/harness/context/builder.ts index c3ac36f..b5f3f9e 100644 --- a/packages/agent-core/src/harness/context/builder.ts +++ b/packages/agent-core/src/harness/context/builder.ts @@ -1,7 +1,7 @@ -export { ContextBuilder } from './context-builder'; +export { ContextBuilder } from './context-builder.js'; export type { ContextMessage, MessageRole, RuntimeContext, -} from './context-types'; -export { buildRuntimeContext } from './runtime-context'; +} from './context-types.js'; +export { buildRuntimeContext } from './runtime-context.js'; diff --git a/packages/agent-core/src/harness/context/context-builder.ts b/packages/agent-core/src/harness/context/context-builder.ts index f1eb1e7..e4a672e 100644 --- a/packages/agent-core/src/harness/context/context-builder.ts +++ b/packages/agent-core/src/harness/context/context-builder.ts @@ -1,5 +1,5 @@ import { get_encoding, type Tiktoken } from 'tiktoken'; -import type { ContextMessage } from './context-types'; +import type { ContextMessage } from './context-types.js'; export class ContextBuilder { private readonly encoder: Tiktoken; diff --git a/packages/agent-core/src/harness/context/context-summarizer.ts b/packages/agent-core/src/harness/context/context-summarizer.ts index 11c9d84..16da1be 100644 --- a/packages/agent-core/src/harness/context/context-summarizer.ts +++ b/packages/agent-core/src/harness/context/context-summarizer.ts @@ -1,4 +1,4 @@ -import type { ContextMessage } from './context-types'; +import type { ContextMessage } from './context-types.js'; export interface HistorySummary { summary: string; diff --git a/packages/agent-core/src/harness/context/runtime-context.ts b/packages/agent-core/src/harness/context/runtime-context.ts index eb470a6..1730152 100644 --- a/packages/agent-core/src/harness/context/runtime-context.ts +++ b/packages/agent-core/src/harness/context/runtime-context.ts @@ -1,11 +1,11 @@ -import type { TaskState } from '@agent-core/harness/core/state'; -import { createTaskContext } from './task-context'; -import { summarizeHistory } from './context-summarizer'; -import { ContextBuilder } from './context-builder'; +import type { TaskState } from '../core/state.js'; +import { createTaskContext } from './task-context.js'; +import { summarizeHistory } from './context-summarizer.js'; +import { ContextBuilder } from './context-builder.js'; import type { ContextMessage, RuntimeContext, -} from './context-types'; +} from './context-types.js'; export interface BuildRuntimeContextInput { system: string; diff --git a/packages/agent-core/src/harness/context/task-context.ts b/packages/agent-core/src/harness/context/task-context.ts index 0d62d96..066fe35 100644 --- a/packages/agent-core/src/harness/context/task-context.ts +++ b/packages/agent-core/src/harness/context/task-context.ts @@ -1,4 +1,4 @@ -import type { TaskState } from '@agent-core/harness/core/state'; +import type { TaskState } from '../core/state.js'; export interface TaskContext { id: string; diff --git a/packages/agent-core/src/harness/core/agent.ts b/packages/agent-core/src/harness/core/agent.ts index 04fef07..19c67be 100644 --- a/packages/agent-core/src/harness/core/agent.ts +++ b/packages/agent-core/src/harness/core/agent.ts @@ -1,6 +1,6 @@ -import { runLoop } from '@agent-core/harness/runtime/run-loop'; -import type { StreamHandlers } from '@agent-core/harness/core/llm'; -import { createTaskState, type AgentMode } from '@agent-core/harness/core/state'; +import { runLoop } from '../runtime/run-loop.js'; +import type { StreamHandlers } from './llm.js'; +import { createTaskState, type AgentMode } from './state.js'; export interface AgentOptions { mode?: AgentMode; diff --git a/packages/agent-core/src/harness/memory/memory-retriever.ts b/packages/agent-core/src/harness/memory/memory-retriever.ts index 528764b..d2ad9d1 100644 --- a/packages/agent-core/src/harness/memory/memory-retriever.ts +++ b/packages/agent-core/src/harness/memory/memory-retriever.ts @@ -1,4 +1,4 @@ -import { memoryStore } from './memory-store'; +import { memoryStore } from './memory-store.js'; export interface RetrievedMemory { longFacts: string[]; diff --git a/packages/agent-core/src/harness/memory/memory-store.ts b/packages/agent-core/src/harness/memory/memory-store.ts index c1dfe49..68abb8b 100644 --- a/packages/agent-core/src/harness/memory/memory-store.ts +++ b/packages/agent-core/src/harness/memory/memory-store.ts @@ -2,7 +2,7 @@ import { randomUUID } from 'node:crypto'; import type { LongMemoryItem, MemorySnapshot, -} from './memory-schema'; +} from './memory-schema.js'; export class MemoryStore { private readonly longMemory: LongMemoryItem[] = []; diff --git a/packages/agent-core/src/harness/memory/memory-writer.ts b/packages/agent-core/src/harness/memory/memory-writer.ts index afebcfe..49d21be 100644 --- a/packages/agent-core/src/harness/memory/memory-writer.ts +++ b/packages/agent-core/src/harness/memory/memory-writer.ts @@ -1,6 +1,6 @@ -import type { TaskState } from '@core/state'; -import type { ContextMessage } from '../context/context-types'; -import { memoryStore } from './memory-store'; +import type { TaskState } from '../core/state.js'; +import type { ContextMessage } from '../context/context-types.js'; +import { memoryStore } from './memory-store.js'; const countStableMentions = (messages: ContextMessage[], text: string): number => messages.reduce((count, item) => { diff --git a/packages/agent-core/src/harness/prompt/modes.ts b/packages/agent-core/src/harness/prompt/modes.ts index 4605e0b..c7e956c 100644 --- a/packages/agent-core/src/harness/prompt/modes.ts +++ b/packages/agent-core/src/harness/prompt/modes.ts @@ -1,4 +1,4 @@ -import type { AgentMode } from '@agent-core/harness/core/state'; +import type { AgentMode } from '../core/state.js'; const modeSystemPrompts: Record = { plan: ` diff --git a/packages/agent-core/src/harness/protocol/index.ts b/packages/agent-core/src/harness/protocol/index.ts index e00daa1..99b88da 100644 --- a/packages/agent-core/src/harness/protocol/index.ts +++ b/packages/agent-core/src/harness/protocol/index.ts @@ -1,5 +1,5 @@ -export type { ToolCallAction, FinalAction, AgentAction } from '@agent-core/harness/protocol/action'; -export { isToolCallAction, isFinalAction, isAgentAction } from '@agent-core/harness/protocol/action'; -export type { ToolResultObservation } from '@agent-core/harness/protocol/observation'; -export { createToolResultObservation } from '@agent-core/harness/protocol/observation'; -export { parseAgentResponse, shouldContinueLoop, extractFinalText } from '@agent-core/harness/protocol/parser'; +export type { ToolCallAction, FinalAction, AgentAction } from './action.js'; +export { isToolCallAction, isFinalAction, isAgentAction } from './action.js'; +export type { ToolResultObservation } from './observation.js'; +export { createToolResultObservation } from './observation.js'; +export { parseAgentResponse, shouldContinueLoop, extractFinalText } from './parser.js'; diff --git a/packages/agent-core/src/harness/protocol/parser.ts b/packages/agent-core/src/harness/protocol/parser.ts index 0aa37ca..8c984b8 100644 --- a/packages/agent-core/src/harness/protocol/parser.ts +++ b/packages/agent-core/src/harness/protocol/parser.ts @@ -1,4 +1,4 @@ -import { isAgentAction, isFinalAction, isToolCallAction, type AgentAction } from '@agent-core/harness/protocol/action'; +import { isAgentAction, isFinalAction, isToolCallAction, type AgentAction } from './action.js'; export const parseAgentResponse = (response: string): AgentAction | null => { try { diff --git a/packages/agent-core/src/harness/runtime/index.ts b/packages/agent-core/src/harness/runtime/index.ts index 8c269df..381d086 100644 --- a/packages/agent-core/src/harness/runtime/index.ts +++ b/packages/agent-core/src/harness/runtime/index.ts @@ -1,3 +1,3 @@ -export * from './run-loop'; -export * from './session-runtime'; -export * from './tool-runtime'; +export * from './run-loop.js'; +export * from './session-runtime.js'; +export * from './tool-runtime.js'; diff --git a/packages/agent-core/src/harness/runtime/run-loop.ts b/packages/agent-core/src/harness/runtime/run-loop.ts index 8396c5e..4721afd 100644 --- a/packages/agent-core/src/harness/runtime/run-loop.ts +++ b/packages/agent-core/src/harness/runtime/run-loop.ts @@ -1,23 +1,23 @@ -import { callLLM, streamLLM, type StreamHandlers } from '../core/llm'; -import { ContextBuilder } from '../context/context-builder'; -import { buildRuntimeContext } from '../context/runtime-context'; -import type { ContextMessage } from '../context/context-types'; -import { systemPrompt } from '../prompt/system'; -import { toolPrompt } from '../prompt/tool'; -import { getModePrompt } from '../prompt/modes'; -import type { TaskState } from '../core/state'; +import { callLLM, streamLLM, type StreamHandlers } from '../core/llm.js'; +import { ContextBuilder } from '../context/context-builder.js'; +import { buildRuntimeContext } from '../context/runtime-context.js'; +import type { ContextMessage } from '../context/context-types.js'; +import { systemPrompt } from '../prompt/system.js'; +import { toolPrompt } from '../prompt/tool.js'; +import { getModePrompt } from '../prompt/modes.js'; +import type { TaskState } from '../core/state.js'; import { extractFinalText, parseAgentResponse, shouldContinueLoop, -} from '../protocol/parser'; -import { isToolCallAction } from '../protocol/action'; -import { promoteStableFact } from '../memory/memory-writer'; -import { retrieveMemoryForTask } from '../memory/memory-retriever'; -import { getSharedSessionStoreOrNull } from '../session/store-registry'; -import type { SessionStoreLike } from '../session/store-types'; -import { createSessionRuntime } from './session-runtime'; -import { runToolCall } from './tool-runtime'; +} from '../protocol/parser.js'; +import { isToolCallAction } from '../protocol/action.js'; +import { promoteStableFact } from '../memory/memory-writer.js'; +import { retrieveMemoryForTask } from '../memory/memory-retriever.js'; +import { getSharedSessionStoreOrNull } from '../session/store-registry.js'; +import type { SessionStoreLike } from '../session/store-types.js'; +import { createSessionRuntime } from './session-runtime.js'; +import { runToolCall } from './tool-runtime.js'; import { DEFAULT_COMPACTION_SETTINGS, compact, @@ -26,8 +26,8 @@ import { shouldCompact, type CompactionSettings, type SummarizeFn, -} from '../compaction/compaction'; -import { estimateContextTokens } from '../compaction/utils'; +} from '../compaction/compaction.js'; +import { estimateContextTokens } from '../compaction/utils.js'; const contextBuilder = new ContextBuilder(8000); diff --git a/packages/agent-core/src/harness/runtime/session-runtime.ts b/packages/agent-core/src/harness/runtime/session-runtime.ts index baff470..df12da7 100644 --- a/packages/agent-core/src/harness/runtime/session-runtime.ts +++ b/packages/agent-core/src/harness/runtime/session-runtime.ts @@ -1,14 +1,14 @@ -import type { ContextMessage } from '../context/context-types'; -import { persistCompactionEntry, type CompactResult } from '../compaction/compaction'; -import type { TaskState } from '../core/state'; -import type { ToolCallAction } from '../protocol/action'; -import type { SessionStoreLike } from '../session/store-types'; -import { readTaskHistory } from '../session/history'; +import type { ContextMessage } from '../context/context-types.js'; +import { persistCompactionEntry, type CompactResult } from '../compaction/compaction.js'; +import type { TaskState } from '../core/state.js'; +import type { ToolCallAction } from '../protocol/action.js'; +import type { SessionStoreLike } from '../session/store-types.js'; +import { readTaskHistory } from '../session/history.js'; import { appendTaskEntry, appendTaskRecord, ensureTaskSession, -} from '../session/task-session'; +} from '../session/task-session.js'; export interface SessionRuntime { history: ContextMessage[]; diff --git a/packages/agent-core/src/harness/runtime/tool-runtime.ts b/packages/agent-core/src/harness/runtime/tool-runtime.ts index 393c95e..7f62fe1 100644 --- a/packages/agent-core/src/harness/runtime/tool-runtime.ts +++ b/packages/agent-core/src/harness/runtime/tool-runtime.ts @@ -1,7 +1,7 @@ -import type { TaskState } from '../core/state'; -import type { ToolCallAction } from '../protocol/action'; -import { executeToolCall, type ToolExecutionResult } from '../tools/executor'; -import type { SessionRuntime } from './session-runtime'; +import type { TaskState } from '../core/state.js'; +import type { ToolCallAction } from '../protocol/action.js'; +import { executeToolCall, type ToolExecutionResult } from '../tools/executor.js'; +import type { SessionRuntime } from './session-runtime.js'; /** 执行工具并复用会话运行时记录调用与结果。 */ export const runToolCall = async ( diff --git a/packages/agent-core/src/harness/session/activity-query.ts b/packages/agent-core/src/harness/session/activity-query.ts index b63522e..39953ed 100644 --- a/packages/agent-core/src/harness/session/activity-query.ts +++ b/packages/agent-core/src/harness/session/activity-query.ts @@ -1,5 +1,5 @@ -import type { EntryLike, SessionStoreLike } from './store-types'; -import { getSharedSessionStore } from './store-registry'; +import type { EntryLike, SessionStoreLike } from './store-types.js'; +import { getSharedSessionStore } from './store-registry.js'; /** * 活动面板需要的历史条目。 diff --git a/packages/agent-core/src/harness/session/history.ts b/packages/agent-core/src/harness/session/history.ts index faf7cab..5b3d917 100644 --- a/packages/agent-core/src/harness/session/history.ts +++ b/packages/agent-core/src/harness/session/history.ts @@ -1,6 +1,6 @@ -import type { ContextMessage } from '../context/context-types'; -import type { EntryLike, SessionStoreLike } from './store-types'; -import { getSharedSessionStore } from './store-registry'; +import type { ContextMessage } from '../context/context-types.js'; +import type { EntryLike, SessionStoreLike } from './store-types.js'; +import { getSharedSessionStore } from './store-registry.js'; const entryToContextMessage = (entry: EntryLike): ContextMessage | null => { const payload = entry.payload as { content?: unknown; role?: unknown } | null; diff --git a/packages/agent-core/src/harness/session/index.ts b/packages/agent-core/src/harness/session/index.ts index 05dce44..03e7086 100644 --- a/packages/agent-core/src/harness/session/index.ts +++ b/packages/agent-core/src/harness/session/index.ts @@ -1,5 +1,5 @@ -export * from './activity-query'; -export * from './history'; -export * from './store-registry'; -export * from './store-types'; -export * from './task-session'; +export * from './activity-query.js'; +export * from './history.js'; +export * from './store-registry.js'; +export * from './store-types.js'; +export * from './task-session.js'; diff --git a/packages/agent-core/src/harness/session/store-registry.ts b/packages/agent-core/src/harness/session/store-registry.ts index 8562c5a..6e2c507 100644 --- a/packages/agent-core/src/harness/session/store-registry.ts +++ b/packages/agent-core/src/harness/session/store-registry.ts @@ -1,4 +1,4 @@ -import type { SessionStoreLike } from './store-types'; +import type { SessionStoreLike } from './store-types.js'; let sharedStore: SessionStoreLike | null = null; diff --git a/packages/agent-core/src/harness/session/task-session.ts b/packages/agent-core/src/harness/session/task-session.ts index a3efcbb..0b112de 100644 --- a/packages/agent-core/src/harness/session/task-session.ts +++ b/packages/agent-core/src/harness/session/task-session.ts @@ -1,11 +1,11 @@ -import type { TaskState } from '../core/state'; +import type { TaskState } from '../core/state.js'; import type { EntryLike, RecordLike, SessionLike, SessionStoreLike, -} from './store-types'; -import { getSharedSessionStore } from './store-registry'; +} from './store-types.js'; +import { getSharedSessionStore } from './store-registry.js'; /** 默认泳道名称,与 session-sqlite store 保持一致 */ export const DEFAULT_LANE = 'default'; diff --git a/packages/agent-core/src/harness/tools/bash.ts b/packages/agent-core/src/harness/tools/bash.ts index 86d5414..6f5c43d 100644 --- a/packages/agent-core/src/harness/tools/bash.ts +++ b/packages/agent-core/src/harness/tools/bash.ts @@ -1,6 +1,6 @@ import { execFile } from 'node:child_process'; import { promisify } from 'node:util'; -import { resolveUserPath } from './pathUtils'; +import { resolveUserPath } from './pathUtils.js'; const execFileAsync = promisify(execFile); diff --git a/packages/agent-core/src/harness/tools/executor.ts b/packages/agent-core/src/harness/tools/executor.ts index 7be3fff..6fcaf47 100644 --- a/packages/agent-core/src/harness/tools/executor.ts +++ b/packages/agent-core/src/harness/tools/executor.ts @@ -1,8 +1,8 @@ -import { tools } from './'; -import { enforceToolPermission } from './policy/guard'; -import type { AgentMode } from '@agent-core/harness/core/state'; -import type { ToolCallAction } from '@agent-core/harness/protocol/action'; -import { createToolResultObservation } from '@agent-core/harness/protocol/observation'; +import { tools } from './index.js'; +import { enforceToolPermission } from './policy/guard.js'; +import type { AgentMode } from '../core/state.js'; +import type { ToolCallAction } from '../protocol/action.js'; +import { createToolResultObservation } from '../protocol/observation.js'; export interface ToolExecutionResult { content: string; diff --git a/packages/agent-core/src/harness/tools/getEnvironment.ts b/packages/agent-core/src/harness/tools/getEnvironment.ts index a0d9941..2fa897e 100644 --- a/packages/agent-core/src/harness/tools/getEnvironment.ts +++ b/packages/agent-core/src/harness/tools/getEnvironment.ts @@ -1,6 +1,6 @@ import { access } from 'node:fs/promises'; import process from 'node:process'; -import { getKnownLocations } from './pathUtils'; +import { getKnownLocations } from './pathUtils.js'; const exists = async (path: string) => { try { diff --git a/packages/agent-core/src/harness/tools/gitDiff.ts b/packages/agent-core/src/harness/tools/gitDiff.ts index fdaf997..e8437b7 100644 --- a/packages/agent-core/src/harness/tools/gitDiff.ts +++ b/packages/agent-core/src/harness/tools/gitDiff.ts @@ -1,6 +1,6 @@ import { execFile } from 'node:child_process'; import { promisify } from 'node:util'; -import { resolveUserPath } from './pathUtils'; +import { resolveUserPath } from './pathUtils.js'; const execFileAsync = promisify(execFile); diff --git a/packages/agent-core/src/harness/tools/index.ts b/packages/agent-core/src/harness/tools/index.ts index ad63d90..a8bdb12 100644 --- a/packages/agent-core/src/harness/tools/index.ts +++ b/packages/agent-core/src/harness/tools/index.ts @@ -1,10 +1,10 @@ -import { getEnvironmentTool } from './getEnvironment'; -import { bashTool } from './bash'; -import { ocrImageTool } from './ocr'; -import { gitDiffTool } from './gitDiff'; -import { readFileTool } from './readFile'; -import { searchTool } from './search'; -import { writeFileTool } from './writeFile'; +import { getEnvironmentTool } from './getEnvironment.js'; +import { bashTool } from './bash.js'; +import { ocrImageTool } from './ocr.js'; +import { gitDiffTool } from './gitDiff.js'; +import { readFileTool } from './readFile.js'; +import { searchTool } from './search.js'; +import { writeFileTool } from './writeFile.js'; export { bashTool, getEnvironmentTool, diff --git a/packages/agent-core/src/harness/tools/ocr.ts b/packages/agent-core/src/harness/tools/ocr.ts index 074454a..e89d4a6 100644 --- a/packages/agent-core/src/harness/tools/ocr.ts +++ b/packages/agent-core/src/harness/tools/ocr.ts @@ -1,6 +1,6 @@ import { readFile } from 'node:fs/promises'; import Tesseract from 'tesseract.js'; -import { resolveUserPath } from './pathUtils'; +import { resolveUserPath } from './pathUtils.js'; const DEFAULT_LANG = 'eng'; diff --git a/packages/agent-core/src/harness/tools/policy/guard.ts b/packages/agent-core/src/harness/tools/policy/guard.ts index 458f453..512b7bf 100644 --- a/packages/agent-core/src/harness/tools/policy/guard.ts +++ b/packages/agent-core/src/harness/tools/policy/guard.ts @@ -1,5 +1,5 @@ -import type { AgentMode } from '@agent-core/harness/core/state'; -import { modePolicies } from './modes'; +import type { AgentMode } from '../../core/state.js'; +import { modePolicies } from './modes.js'; const toolPermissionByName = (toolName: string, mode: AgentMode): boolean => { const policy = modePolicies[mode]; diff --git a/packages/agent-core/src/harness/tools/policy/modes.ts b/packages/agent-core/src/harness/tools/policy/modes.ts index dc8ee2d..54b9778 100644 --- a/packages/agent-core/src/harness/tools/policy/modes.ts +++ b/packages/agent-core/src/harness/tools/policy/modes.ts @@ -1,4 +1,4 @@ -import type { AgentMode } from '@agent-core/harness/core/state'; +import type { AgentMode } from '../../core/state.js'; export interface ModePolicy { readonly allowBash: boolean; diff --git a/packages/agent-core/src/harness/tools/readFile.ts b/packages/agent-core/src/harness/tools/readFile.ts index 4871e43..72895d5 100644 --- a/packages/agent-core/src/harness/tools/readFile.ts +++ b/packages/agent-core/src/harness/tools/readFile.ts @@ -1,5 +1,5 @@ import { readFile } from 'node:fs/promises'; -import { resolveUserPath } from './pathUtils'; +import { resolveUserPath } from './pathUtils.js'; export const readFileTool = { name: 'read_file', diff --git a/packages/agent-core/src/harness/tools/search.ts b/packages/agent-core/src/harness/tools/search.ts index 535d030..a834477 100644 --- a/packages/agent-core/src/harness/tools/search.ts +++ b/packages/agent-core/src/harness/tools/search.ts @@ -3,7 +3,7 @@ import type { Dirent } from 'node:fs'; import { readdir, readFile, stat } from 'node:fs/promises'; import path from 'node:path'; import { promisify } from 'node:util'; -import { resolveUserPath } from './pathUtils'; +import { resolveUserPath } from './pathUtils.js'; const execFileAsync = promisify(execFile); const DEFAULT_MAX_RESULTS = 100; diff --git a/packages/agent-core/src/harness/tools/writeFile.ts b/packages/agent-core/src/harness/tools/writeFile.ts index 499742f..a7dc46f 100644 --- a/packages/agent-core/src/harness/tools/writeFile.ts +++ b/packages/agent-core/src/harness/tools/writeFile.ts @@ -1,6 +1,6 @@ import { mkdir, writeFile } from 'node:fs/promises'; import pathModule from 'node:path'; -import { resolveUserPath } from './pathUtils'; +import { resolveUserPath } from './pathUtils.js'; export const writeFileTool = { name: 'write_file', diff --git a/packages/agent-core/src/harness/utils/shell.ts b/packages/agent-core/src/harness/utils/shell.ts index b8ea198..5b49c1f 100644 --- a/packages/agent-core/src/harness/utils/shell.ts +++ b/packages/agent-core/src/harness/utils/shell.ts @@ -1,6 +1,6 @@ import { execFile } from 'node:child_process'; import { promisify } from 'node:util'; -import { truncateOutput, type TruncateOptions } from '@agent-core/harness/utils/truncate'; +import { truncateOutput, type TruncateOptions } from './truncate.js'; const execFileAsync = promisify(execFile); export interface ExecShellOptions { diff --git a/packages/agent-core/src/index.ts b/packages/agent-core/src/index.ts index 5212f03..324d173 100644 --- a/packages/agent-core/src/index.ts +++ b/packages/agent-core/src/index.ts @@ -1,26 +1,26 @@ -export { agent, type AgentOptions } from './harness/core/agent'; +export { agent, type AgentOptions } from './harness/core/agent.js'; export { callLLM, streamLLM, llmModel, type Message as LLMMessage, type StreamHandlers, -} from './harness/core/llm'; +} from './harness/core/llm.js'; export { createTaskState, type AgentMode, type TaskState, type CreateTaskStateOptions, -} from './harness/core/state'; +} from './harness/core/state.js'; export { runLoop, type RunLoopOptions, -} from './harness/runtime/run-loop'; +} from './harness/runtime/run-loop.js'; export { executeToolCall, type ToolExecutionResult, -} from './harness/tools/executor'; -export { tools } from './harness/tools/index'; +} from './harness/tools/executor.js'; +export { tools } from './harness/tools/index.js'; export { buildWebExport, writeWebExport, @@ -30,16 +30,16 @@ export { type WebSession, type WebExport, type WebStore, -} from './web/export'; +} from './web/export.js'; export { parseClientMessage, type ChatSendPayload, type WebSocketClientMessage, type WebSocketServerMessage, -} from './web/protocol'; +} from './web/protocol.js'; export { startWebServer, type WebServerOptions, type WebServerHandle, -} from './web/server'; -export * from './harness/session/index'; +} from './web/server.js'; +export * from './harness/session/index.js'; diff --git a/packages/agent-core/src/web/export.ts b/packages/agent-core/src/web/export.ts index ff1f5e2..3cdd95b 100644 --- a/packages/agent-core/src/web/export.ts +++ b/packages/agent-core/src/web/export.ts @@ -4,7 +4,7 @@ import type { EntryLike, SessionStoreLike, SessionStatsLike, -} from '../harness/session/store-types'; +} from '../harness/session/store-types.js'; /** Web 客户端读取的会话快照格式。 */ export interface WebEntry { diff --git a/packages/agent-core/src/web/protocol.ts b/packages/agent-core/src/web/protocol.ts index 7bc377a..d311d0e 100644 --- a/packages/agent-core/src/web/protocol.ts +++ b/packages/agent-core/src/web/protocol.ts @@ -1,5 +1,5 @@ -import type { AgentMode } from "../harness/core/state"; -import type { WebExport } from "./export"; +import type { AgentMode } from "../harness/core/state.js"; +import type { WebExport } from "./export.js"; export type ChatSendPayload = { type: "chat.send"; diff --git a/packages/agent-core/src/web/server.ts b/packages/agent-core/src/web/server.ts index 2c18514..356e972 100644 --- a/packages/agent-core/src/web/server.ts +++ b/packages/agent-core/src/web/server.ts @@ -3,10 +3,10 @@ import { readFile, stat } from "node:fs/promises"; import { extname, join, resolve, sep } from "node:path"; import { fileURLToPath } from "node:url"; import { WebSocket, WebSocketServer } from "ws"; -import { runLoop } from "../harness/runtime/run-loop"; -import { createTaskState } from "../harness/core/state"; -import { buildWebExport, type WebStore } from "./export"; -import { parseClientMessage, type WebSocketServerMessage } from "./protocol"; +import { runLoop } from "../harness/runtime/run-loop.js"; +import { createTaskState } from "../harness/core/state.js"; +import { buildWebExport, type WebStore } from "./export.js"; +import { parseClientMessage, type WebSocketServerMessage } from "./protocol.js"; const DEFAULT_CLIENT_DIR = fileURLToPath( new URL("../../../client/dist", import.meta.url), diff --git a/packages/agent-core/tsconfig.json b/packages/agent-core/tsconfig.json index 1af166c..3b88121 100644 --- a/packages/agent-core/tsconfig.json +++ b/packages/agent-core/tsconfig.json @@ -7,7 +7,9 @@ "moduleResolution": "bundler", "declaration": true, - "composite": true + "composite": true, + "noEmit": false, + "allowImportingTsExtensions": false }, "include": ["src"] } diff --git a/packages/client/package.json b/packages/client/package.json index 03bb50c..86d0d92 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -10,6 +10,7 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { + "@call-code/server": "workspace:*", "react": "^19.2.8", "react-dom": "^19.2.8" }, diff --git a/packages/client/src/types.ts b/packages/client/src/types.ts index 1ed7b3c..4732810 100644 --- a/packages/client/src/types.ts +++ b/packages/client/src/types.ts @@ -1,70 +1,17 @@ -export type AgentMode = "plan" | "build"; - -export type Theme = "light" | "dark"; - -export type EntryRole = "user" | "assistant" | "tool" | "system"; - -export type Filter = "all" | EntryRole; - -export interface WebEntry { - seq: number; - id: string; - parentId: string | null; - type: string; - role: string; - timestamp: string; - text?: string; - tool?: string | null; - tags?: string[]; - payload: unknown; -} - -export interface WebRecord { - seq: number; - id: string; - lane: string; - runId: string | null; - type: string; - opKind: string | null; - timestamp: string; - payload: unknown; -} - -export interface WebFact { - seq: number; - kind: string; - key: string | null; - value: string | null; -} - -export interface WebStats { - messageCount: number; - cachedTokens: number; - uncachedTokens: number; - totalTokens: number; - costTotal: number; -} - -export interface WebSession { - id: string; - createdAt: string; - cwd: string; - parentSessionId: string | null; - metadata: Record; - stats: WebStats; - entries: WebEntry[]; - records?: WebRecord[]; - facts?: WebFact[]; -} - -export interface WebExport { - schemaVersion: 1; - exportedAt: string; - sessions: WebSession[]; -} - -export interface ChatStatusMessage { - status: "idle" | "running" | "success" | "error"; - trace?: string; - message?: string; -} +import type { EntryRole } from '@call-code/server/client'; + +export type { + AgentMode, + EntryRole, + WebEntry, + WebRecord, + WebFact, + WebStats, + WebSession, + WebExport, + ChatStatusMessage, +} from '@call-code/server/client'; + +export type Theme = 'light' | 'dark'; + +export type Filter = 'all' | EntryRole; diff --git a/packages/client/src/ws.ts b/packages/client/src/ws.ts index 3ed1138..0892f6c 100644 --- a/packages/client/src/ws.ts +++ b/packages/client/src/ws.ts @@ -1,291 +1,10 @@ -import type { AgentMode, ChatStatusMessage, WebExport, WebSession } from "./types"; - -const DEFAULT_WS_PATH = "/ws"; -const DEFAULT_TIMEOUT_MS = 8000; -const DEFAULT_REFRESH_MS = 5000; - -const isWebSession = (value: unknown): value is WebSession => { - if (!value || typeof value !== "object") { - return false; - } - - const session = value as Partial; - return ( - typeof session.id === "string" && - typeof session.createdAt === "string" && - typeof session.cwd === "string" && - Array.isArray(session.entries) - ); -}; - -export const isWebExport = (value: unknown): value is WebExport => { - if (!value || typeof value !== "object") { - return false; - } - - const data = value as Partial; - return ( - data.schemaVersion === 1 && - typeof data.exportedAt === "string" && - Array.isArray(data.sessions) && - data.sessions.every(isWebSession) - ); -}; - -/** 从服务端消息中提取会话快照,类型不符或结构非法时返回 null。 */ -export const parseSnapshotMessage = (value: unknown): WebExport | null => { - if (!value || typeof value !== "object") { - return null; - } - - const message = value as { type?: unknown; data?: unknown }; - if (message.type !== "sessions.snapshot") { - return null; - } - return isWebExport(message.data) ? message.data : null; -}; - -export const parseChatStatusMessage = (value: unknown): ChatStatusMessage | null => { - if (!value || typeof value !== "object") { - return null; - } - - const message = value as { type?: unknown; status?: unknown; trace?: unknown; message?: unknown }; - if (message.type !== "chat.status") { - return null; - } - - const status = message.status; - if (status !== "idle" && status !== "running" && status !== "success" && status !== "error") { - return null; - } - - return { - status, - trace: typeof message.trace === "string" ? message.trace : undefined, - message: typeof message.message === "string" ? message.message : undefined, - }; -}; - -const resolveWsUrl = (override?: string): string => { - if (override) { - return override; - } - - const params = new URLSearchParams(window.location.search); - const fromQuery = params.get("ws") ?? params.get("wsUrl"); - if (fromQuery) { - return fromQuery; - } - - const protocol = window.location.protocol === "https:" ? "wss:" : "ws:"; - return `${protocol}//${window.location.host}${DEFAULT_WS_PATH}`; -}; - -export interface LiveExportOptions { - url?: string; - timeoutMs?: number; - refreshMs?: number; - onSnapshot: (data: WebExport) => void; - onChatStatus?: (status: ChatStatusMessage) => void; -} - -export interface LiveExportConnection { - ready: Promise; - sendMessage: (payload: { input: string; mode?: AgentMode }) => boolean; - refresh: () => void; - close(): void; -} - -/** - * 连接 WebSocket 会话服务:连接成功后立即拉取快照,之后按 refreshMs 周期性刷新。 - * 断开时自动退避重连,支持发送 chat.send 消息触发 harness。 - */ -export const connectLiveExport = ( - options: LiveExportOptions, -): LiveExportConnection => { - const { - onSnapshot, - onChatStatus, - url, - timeoutMs = DEFAULT_TIMEOUT_MS, - refreshMs = DEFAULT_REFRESH_MS, - } = options; - - let closed = false; - let socket: WebSocket | null = null; - let failTimer: ReturnType | null = null; - let refreshTimer: ReturnType | null = null; - let retryTimer: ReturnType | null = null; - let attempt = 0; - let readySettled = false; - let resolveReady: (value: WebExport | null) => void = () => undefined; - - const ready = new Promise((resolve) => { - resolveReady = resolve; - }); - - const settleReady = (value: WebExport | null) => { - if (readySettled) { - return; - } - readySettled = true; - resolveReady(value); - }; - - const clearTimers = () => { - if (failTimer) { - clearTimeout(failTimer); - } - if (refreshTimer) { - clearTimeout(refreshTimer); - } - if (retryTimer) { - clearTimeout(retryTimer); - } - failTimer = null; - refreshTimer = null; - retryTimer = null; - }; - - const teardownSocket = () => { - clearTimers(); - if (!socket) { - return; - } - - const current = socket; - socket = null; - current.onopen = null; - current.onmessage = null; - current.onerror = null; - current.onclose = null; - current.close(); - }; - - const scheduleRefresh = () => { - if (closed) { - return; - } - refreshTimer = setTimeout(() => { - if (socket?.readyState === WebSocket.OPEN) { - socket.send(JSON.stringify({ type: "sessions.list" })); - } - scheduleRefresh(); - }, refreshMs); - }; - - const scheduleReconnect = () => { - if (closed) { - return; - } - - const delay = Math.min(1000 * 2 ** attempt, 15000); - attempt += 1; - retryTimer = setTimeout(() => { - retryTimer = null; - openSocket(); - }, delay); - }; - - const armTimeout = () => { - if (failTimer) { - clearTimeout(failTimer); - } - failTimer = setTimeout(() => { - teardownSocket(); - settleReady(null); - scheduleReconnect(); - }, timeoutMs); - }; - - const openSocket = () => { - if (closed) { - return; - } - - let current: WebSocket; - try { - current = new WebSocket(resolveWsUrl(url)); - } catch { - scheduleReconnect(); - return; - } - socket = current; - armTimeout(); - - current.onopen = () => { - attempt = 0; - current.send(JSON.stringify({ type: "sessions.list" })); - scheduleRefresh(); - }; - - current.onmessage = (event) => { - let parsed: unknown; - try { - parsed = JSON.parse(String(event.data)); - } catch { - return; - } - - const chatStatus = parseChatStatusMessage(parsed); - if (chatStatus) { - onChatStatus?.(chatStatus); - return; - } - - const data = parseSnapshotMessage(parsed); - if (!data) { - return; - } - - armTimeout(); - onSnapshot(data); - settleReady(data); - }; - - current.onerror = () => { - // 关闭事件统一负责清理与重连 - }; - - current.onclose = () => { - if (socket !== current) { - return; - } - teardownSocket(); - settleReady(null); - if (!closed) { - scheduleReconnect(); - } - }; - }; - - openSocket(); - - return { - ready, - sendMessage(payload) { - if (!socket || socket.readyState !== WebSocket.OPEN) { - return false; - } - socket.send( - JSON.stringify({ - type: "chat.send", - input: payload.input, - mode: payload.mode ?? "build", - }), - ); - return true; - }, - refresh() { - if (socket && socket.readyState === WebSocket.OPEN) { - socket.send(JSON.stringify({ type: "sessions.list" })); - } - }, - close() { - closed = true; - clearTimers(); - teardownSocket(); - }, - }; -}; +export { + connectLiveExport, + isWebExport, + parseChatStatusMessage, + parseSnapshotMessage, +} from '@call-code/server/client'; +export type { + LiveExportConnection, + LiveExportOptions, +} from '@call-code/server/client'; diff --git a/packages/client/tsconfig.json b/packages/client/tsconfig.json index 6c35f5c..75eeb4d 100644 --- a/packages/client/tsconfig.json +++ b/packages/client/tsconfig.json @@ -16,7 +16,11 @@ "isolatedModules": true, "noEmit": true, "jsx": "react-jsx", - "types": ["vite/client", "node"] + "types": ["vite/client", "node"], + "paths": { + "@call-code/server/client": ["../server/src/client.ts"], + "@call-code/server": ["../server/src/index.ts"] + } }, "include": ["src", "vite.config.ts"] } diff --git a/packages/client/vite.config.ts b/packages/client/vite.config.ts index 5e1099f..5e6c9ae 100644 --- a/packages/client/vite.config.ts +++ b/packages/client/vite.config.ts @@ -7,6 +7,22 @@ export default defineConfig({ root: fileURLToPath(new URL('.', import.meta.url)), plugins: [react(), tailwindcss()], base: './', + resolve: { + alias: [ + { + find: /^@call-code\/server\/client$/, + replacement: fileURLToPath( + new URL('../server/src/client.ts', import.meta.url), + ), + }, + { + find: /^@call-code\/server$/, + replacement: fileURLToPath( + new URL('../server/src/index.ts', import.meta.url), + ), + }, + ], + }, server: { proxy: { // 开发模式下把 WebSocket 请求转发给 web:serve 会话服务 diff --git a/packages/server/package.json b/packages/server/package.json index 9fce589..ae176f1 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -5,6 +5,20 @@ "type": "module", "main": "dist/index.js", "types": "dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + }, + "./client": { + "types": "./dist/client.d.ts", + "import": "./dist/client.js" + } + }, + "files": [ + "dist", + "src/client.ts" + ], "scripts": { "build": "tsc -p tsconfig.json", "typecheck": "tsc -p tsconfig.json --noEmit" diff --git a/packages/server/src/client.ts b/packages/server/src/client.ts new file mode 100644 index 0000000..c8dee28 --- /dev/null +++ b/packages/server/src/client.ts @@ -0,0 +1,369 @@ +export type AgentMode = 'plan' | 'build'; + +export type EntryRole = 'user' | 'assistant' | 'tool' | 'system'; + +export interface WebEntry { + seq: number; + id: string; + parentId: string | null; + type: string; + role: string; + timestamp: string; + text?: string; + tool?: string | null; + tags?: string[]; + payload: unknown; +} + +export interface WebRecord { + seq: number; + id: string; + lane: string; + runId: string | null; + type: string; + opKind: string | null; + timestamp: string; + payload: unknown; +} + +export interface WebFact { + seq: number; + kind: string; + key: string | null; + value: string | null; +} + +export interface WebStats { + messageCount: number; + cachedTokens: number; + uncachedTokens: number; + totalTokens: number; + costTotal: number; +} + +export interface WebSession { + id: string; + createdAt: string; + cwd: string; + parentSessionId: string | null; + metadata: Record; + stats: WebStats; + entries: WebEntry[]; + records?: WebRecord[]; + facts?: WebFact[]; +} + +export interface WebExport { + schemaVersion: 1; + exportedAt: string; + sessions: WebSession[]; +} + +export interface ChatStatusMessage { + status: 'idle' | 'running' | 'success' | 'error'; + trace?: string; + message?: string; +} + +const DEFAULT_WS_PATH = '/ws'; +const DEFAULT_TIMEOUT_MS = 8000; +const DEFAULT_REFRESH_MS = 5000; + +const isWebSession = (value: unknown): value is WebSession => { + if (!value || typeof value !== 'object') { + return false; + } + + const session = value as Partial; + return ( + typeof session.id === 'string' && + typeof session.createdAt === 'string' && + typeof session.cwd === 'string' && + Array.isArray(session.entries) + ); +}; + +export const isWebExport = (value: unknown): value is WebExport => { + if (!value || typeof value !== 'object') { + return false; + } + + const data = value as Partial; + return ( + data.schemaVersion === 1 && + typeof data.exportedAt === 'string' && + Array.isArray(data.sessions) && + data.sessions.every(isWebSession) + ); +}; + +/** 从服务端消息中提取会话快照,类型不符或结构非法时返回 null。 */ +export const parseSnapshotMessage = (value: unknown): WebExport | null => { + if (!value || typeof value !== 'object') { + return null; + } + + const message = value as { type?: unknown; data?: unknown }; + if (message.type !== 'sessions.snapshot') { + return null; + } + return isWebExport(message.data) ? message.data : null; +}; + +export const parseChatStatusMessage = ( + value: unknown, +): ChatStatusMessage | null => { + if (!value || typeof value !== 'object') { + return null; + } + + const message = value as { + type?: unknown; + status?: unknown; + trace?: unknown; + message?: unknown; + }; + if (message.type !== 'chat.status') { + return null; + } + + const status = message.status; + if ( + status !== 'idle' && + status !== 'running' && + status !== 'success' && + status !== 'error' + ) { + return null; + } + + return { + status, + trace: typeof message.trace === 'string' ? message.trace : undefined, + message: + typeof message.message === 'string' ? message.message : undefined, + }; +}; + +const resolveWsUrl = (override?: string): string => { + if (override) { + return override; + } + + const params = new URLSearchParams(window.location.search); + const fromQuery = params.get('ws') ?? params.get('wsUrl'); + if (fromQuery) { + return fromQuery; + } + + const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; + return `${protocol}//${window.location.host}${DEFAULT_WS_PATH}`; +}; + +export interface LiveExportOptions { + url?: string; + timeoutMs?: number; + refreshMs?: number; + onSnapshot: (data: WebExport) => void; + onChatStatus?: (status: ChatStatusMessage) => void; +} + +export interface LiveExportConnection { + ready: Promise; + sendMessage: (payload: { input: string; mode?: AgentMode }) => boolean; + refresh: () => void; + close(): void; +} + +/** + * 连接 Call Code 会话服务:连接成功后立即拉取快照,之后按 refreshMs 周期性刷新。 + * 断开时自动退避重连,支持发送 chat.send 消息触发服务端 Harness。 + */ +export const connectLiveExport = ( + options: LiveExportOptions, +): LiveExportConnection => { + const { + onSnapshot, + onChatStatus, + url, + timeoutMs = DEFAULT_TIMEOUT_MS, + refreshMs = DEFAULT_REFRESH_MS, + } = options; + + let closed = false; + let socket: WebSocket | null = null; + let failTimer: ReturnType | null = null; + let refreshTimer: ReturnType | null = null; + let retryTimer: ReturnType | null = null; + let attempt = 0; + let readySettled = false; + let resolveReady: (value: WebExport | null) => void = () => undefined; + + const ready = new Promise((resolve) => { + resolveReady = resolve; + }); + + const settleReady = (value: WebExport | null) => { + if (readySettled) { + return; + } + readySettled = true; + resolveReady(value); + }; + + const clearTimers = () => { + if (failTimer) { + clearTimeout(failTimer); + } + if (refreshTimer) { + clearTimeout(refreshTimer); + } + if (retryTimer) { + clearTimeout(retryTimer); + } + failTimer = null; + refreshTimer = null; + retryTimer = null; + }; + + const teardownSocket = () => { + clearTimers(); + if (!socket) { + return; + } + + const current = socket; + socket = null; + current.onopen = null; + current.onmessage = null; + current.onerror = null; + current.onclose = null; + current.close(); + }; + + const scheduleRefresh = () => { + if (closed) { + return; + } + refreshTimer = setTimeout(() => { + if (socket?.readyState === WebSocket.OPEN) { + socket.send(JSON.stringify({ type: 'sessions.list' })); + } + scheduleRefresh(); + }, refreshMs); + }; + + const scheduleReconnect = () => { + if (closed) { + return; + } + + const delay = Math.min(1000 * 2 ** attempt, 15000); + attempt += 1; + retryTimer = setTimeout(() => { + retryTimer = null; + openSocket(); + }, delay); + }; + + const armTimeout = () => { + if (failTimer) { + clearTimeout(failTimer); + } + failTimer = setTimeout(() => { + teardownSocket(); + settleReady(null); + scheduleReconnect(); + }, timeoutMs); + }; + + const openSocket = () => { + if (closed) { + return; + } + + let current: WebSocket; + try { + current = new WebSocket(resolveWsUrl(url)); + } catch { + scheduleReconnect(); + return; + } + socket = current; + armTimeout(); + + current.onopen = () => { + attempt = 0; + current.send(JSON.stringify({ type: 'sessions.list' })); + scheduleRefresh(); + }; + + current.onmessage = (event) => { + let parsed: unknown; + try { + parsed = JSON.parse(String(event.data)); + } catch { + return; + } + + const chatStatus = parseChatStatusMessage(parsed); + if (chatStatus) { + onChatStatus?.(chatStatus); + return; + } + + const data = parseSnapshotMessage(parsed); + if (!data) { + return; + } + + armTimeout(); + onSnapshot(data); + settleReady(data); + }; + + current.onerror = () => { + // 关闭事件统一负责清理与重连 + }; + + current.onclose = () => { + if (socket !== current) { + return; + } + teardownSocket(); + settleReady(null); + if (!closed) { + scheduleReconnect(); + } + }; + }; + + openSocket(); + + return { + ready, + sendMessage(payload) { + if (!socket || socket.readyState !== WebSocket.OPEN) { + return false; + } + socket.send( + JSON.stringify({ + type: 'chat.send', + input: payload.input, + mode: payload.mode ?? 'build', + }), + ); + return true; + }, + refresh() { + if (socket && socket.readyState === WebSocket.OPEN) { + socket.send(JSON.stringify({ type: 'sessions.list' })); + } + }, + close() { + closed = true; + clearTimers(); + teardownSocket(); + }, + }; +}; diff --git a/packages/server/src/index.ts b/packages/server/src/index.ts index 9cbabff..3cbc1a6 100644 --- a/packages/server/src/index.ts +++ b/packages/server/src/index.ts @@ -1,13 +1,18 @@ -import { SessionStore, DEFAULT_DB_PATH, type SessionStoreConfig } from '../../session-sqlite/src/index'; +import { SessionStore, DEFAULT_DB_PATH, type SessionStoreConfig } from '@call-code/session-sqlite'; import { startWebServer, buildWebExport, writeWebExport, + createTaskState, + runLoop, type WebServerHandle, type WebServerOptions, type WebExport, type WebStore, -} from '../../agent-core/src/index'; + type AgentMode, + type SessionStoreLike, + type StreamHandlers, +} from '@call-code/agent-core'; export interface ServerConfig { dbPath?: string; @@ -22,9 +27,33 @@ export interface ServerInstance { handle: WebServerHandle; port: number; host: string; + snapshot(): WebExport; + runTask(input: string, options?: Omit): Promise; close(): Promise; } +export interface RunTaskOptions { + mode?: AgentMode; + objective?: string; + constraints?: string[]; + workspace?: string; + sessionStore?: SessionStoreLike; + handlers?: StreamHandlers; +} + +/** 使用显式会话存储执行一次 Agent 任务,供 Server SDK 的调用方直接驱动 agent-core。 */ +export const runTask = async ( + input: string, + options: RunTaskOptions = {}, +): Promise => { + const { sessionStore, handlers, ...taskOptions } = options; + const task = createTaskState(input, taskOptions); + return runLoop(task, handlers, { + persist: sessionStore !== undefined, + sessionStore, + }); +}; + /** * 启动 Call Code 统一后端服务:集成 SQLite 会话存储与 WebUI WebSocket / 静态托管服务。 */ @@ -52,6 +81,12 @@ export const startServer = async ( handle, port: handle.port, host: handle.host, + snapshot() { + return buildWebExport(store); + }, + runTask(input, options = {}) { + return runTask(input, { ...options, sessionStore: store }); + }, async close() { await handle.close(); if (ownsStore) { @@ -61,19 +96,32 @@ export const startServer = async ( }; }; -// 重新导出 agent-core 与 session-sqlite 核心能力与类型 +// 统一对外暴露 agent-core 与 session-sqlite,调用方只需依赖 @call-code/server。 +export * from '@call-code/agent-core'; export { - SessionStore, + SCHEMA_SQL, + DEFAULT_BRANCH, DEFAULT_DB_PATH, - startWebServer, - buildWebExport, - writeWebExport, -}; + DEFAULT_LANE, + SessionStore, +} from '@call-code/session-sqlite'; export type { + BranchEntry, + BranchTip, + CreateSessionInput, + Entry, + EntryInput, + Fact, + GetEntriesOptions, + Lane, + LaneMoveInput, + Lease, + LeafNode, + LeaseAcquireResult, + ListSessionsOptions, + SessionRecord, + RecordInput, + Session, + SessionStats, SessionStoreConfig, - WebServerHandle, - WebServerOptions, - WebExport, - WebStore, -}; -export * from '../../agent-core/src/index'; +} from '@call-code/session-sqlite'; diff --git a/packages/server/tsconfig.json b/packages/server/tsconfig.json index 93c079a..cea6875 100644 --- a/packages/server/tsconfig.json +++ b/packages/server/tsconfig.json @@ -1,13 +1,18 @@ { "extends": "../../tsconfig.json", "compilerOptions": { + "rootDir": "src", + "outDir": "dist", "module": "ESNext", "moduleResolution": "bundler", - "noEmit": true + "declaration": true, + "composite": true, + "noEmit": false, + "allowImportingTsExtensions": false, + "paths": { + "@call-code/agent-core": ["../agent-core/dist/index.d.ts"], + "@call-code/session-sqlite": ["../session-sqlite/dist/index.d.ts"] + } }, - "include": [ - "src", - "../agent-core/src", - "../session-sqlite/src" - ] + "include": ["src"] } diff --git a/packages/session-sqlite/src/index.ts b/packages/session-sqlite/src/index.ts index 7966fd4..06a4d86 100644 --- a/packages/session-sqlite/src/index.ts +++ b/packages/session-sqlite/src/index.ts @@ -1,5 +1,5 @@ // 会话 SQLite 存储的公开入口。 -export { SCHEMA_SQL } from './schema'; +export { SCHEMA_SQL } from './schema.js'; export { DEFAULT_BRANCH, DEFAULT_DB_PATH, @@ -9,7 +9,7 @@ export { type LeaseAcquireResult, type ListSessionsOptions, type SessionStoreConfig, -} from './store'; +} from './store.js'; export type { BranchEntry, BranchTip, @@ -25,4 +25,4 @@ export type { RecordInput, Session, SessionStats, -} from './types'; +} from './types.js'; diff --git a/packages/session-sqlite/src/store.ts b/packages/session-sqlite/src/store.ts index da3b8f0..dffb15b 100644 --- a/packages/session-sqlite/src/store.ts +++ b/packages/session-sqlite/src/store.ts @@ -2,7 +2,7 @@ import { randomUUID } from 'node:crypto'; import { mkdirSync } from 'node:fs'; import { dirname } from 'node:path'; import { DatabaseSync } from 'node:sqlite'; -import { SCHEMA_SQL } from './schema'; +import { SCHEMA_SQL } from './schema.js'; import type { BranchEntry, BranchTip, @@ -18,7 +18,7 @@ import type { RecordInput, Session, SessionStats, -} from './types'; +} from './types.js'; /** 默认数据库文件路径,可用环境变量 SESSION_DB_PATH 覆盖 */ export const DEFAULT_DB_PATH = '.agent-sessions/sessions.db'; diff --git a/packages/session-sqlite/tsconfig.json b/packages/session-sqlite/tsconfig.json index ec8e02f..41cfcc4 100644 --- a/packages/session-sqlite/tsconfig.json +++ b/packages/session-sqlite/tsconfig.json @@ -4,7 +4,9 @@ "rootDir": "src", "outDir": "dist", "declaration": true, - "composite": true + "composite": true, + "noEmit": false, + "allowImportingTsExtensions": false }, "include": ["src"] } diff --git a/tests/client-ws.spec.ts b/tests/client-ws.spec.ts index f4f3ec2..8777a1c 100644 --- a/tests/client-ws.spec.ts +++ b/tests/client-ws.spec.ts @@ -1,10 +1,10 @@ import { afterEach, describe, expect, it } from 'vitest'; import { SessionStore } from '../packages/session-sqlite/src/index'; -import type { WebExport } from '../packages/client/src/types'; +import type { WebExport } from '@call-code/server/client'; import { connectLiveExport, parseSnapshotMessage, -} from '../packages/client/src/ws'; +} from '@call-code/server/client'; import { startWebServer, type WebServerHandle, diff --git a/tests/server.spec.ts b/tests/server.spec.ts index 1ff8e40..3de212e 100644 --- a/tests/server.spec.ts +++ b/tests/server.spec.ts @@ -5,7 +5,7 @@ import { type ServerInstance, type WebExport, SessionStore, -} from "../packages/server/src/index"; +} from "@call-code/server"; vi.mock("../packages/agent-core/src/harness/runtime/run-loop", () => ({ runLoop: vi.fn(async (task, handlers, options) => { @@ -145,4 +145,21 @@ describe("Server SDK 与集成服务", () => { expect(snapshotReceived).not.toBeNull(); expect((snapshotReceived as unknown as WebExport).sessions.length).toBeGreaterThan(0); }); + + it("通过 Server SDK 的 runTask 直接驱动 Agent 并写入会话", async () => { + const { server } = await createTestServer(); + + const result = await server.runTask("SDK runTask 调用", { + mode: "build", + workspace: "/tmp/sdk-run", + }); + + expect(result).toBe("已处理完毕"); + const data = server.snapshot(); + expect(data.sessions).toHaveLength(1); + expect(data.sessions[0].cwd).toBe("/tmp/sdk-run"); + expect( + data.sessions[0].entries.some((entry) => entry.text === "已处理完毕"), + ).toBe(true); + }); }); diff --git a/tsconfig.json b/tsconfig.json index 48f9e53..ba6e3af 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,6 +12,11 @@ "skipLibCheck": true, "paths": { + "@call-code/agent-core": ["./packages/agent-core/src/index.ts"], + "@call-code/agent-core/*": ["./packages/agent-core/src/*"], + "@call-code/session-sqlite": ["./packages/session-sqlite/src/index.ts"], + "@call-code/server": ["./packages/server/src/index.ts"], + "@call-code/server/client": ["./packages/server/src/client.ts"], "@server": ["./packages/server/src/index.ts"], "@server/*": ["./packages/server/src/*"], "@agent-core": ["./packages/agent-core/src/index.ts"], diff --git a/vitest.config.ts b/vitest.config.ts index c88459f..662ccc4 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -12,6 +12,11 @@ export default defineConfig({ exclude: ['**/dist/**', '**/node_modules/**', 'apps/**'], reporters: 'default', alias: [ + { find: /^@call-code\/agent-core$/, replacement: path.resolve(__dirname, './packages/agent-core/src/index.ts') }, + { find: /^@call-code\/agent-core\//, replacement: path.resolve(__dirname, './packages/agent-core/src') + '/' }, + { find: /^@call-code\/session-sqlite$/, replacement: path.resolve(__dirname, './packages/session-sqlite/src/index.ts') }, + { find: /^@call-code\/server\/client$/, replacement: path.resolve(__dirname, './packages/server/src/client.ts') }, + { find: /^@call-code\/server$/, replacement: path.resolve(__dirname, './packages/server/src/index.ts') }, { find: '@agent-core', replacement: path.resolve(__dirname, './packages/agent-core/src') }, { find: '@core', replacement: path.resolve(__dirname, './packages/agent-core/src/harness/core') }, { find: '@config', replacement: path.resolve(__dirname, './packages/agent-core/src/config') }, From b82d29b54574ed0b96053eb313e77d12ffa7f21a Mon Sep 17 00:00:00 2001 From: AlkaidSTART <2595006848@qq.com> Date: Sun, 23 Aug 2026 19:46:15 +0800 Subject: [PATCH 10/10] =?UTF-8?q?feat:=20=E5=88=A0=E9=99=A4=E4=BC=9A?= =?UTF-8?q?=E8=AF=9D=E6=95=B0=E6=8D=AE=E5=BA=93=E6=96=87=E4=BB=B6=E5=B9=B6?= =?UTF-8?q?=E6=9B=B4=E6=96=B0.gitignore=E4=BB=A5=E6=8E=92=E9=99=A4?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .agent-sessions/sessions.db | Bin 143360 -> 0 bytes .gitignore | 5 +++++ 2 files changed, 5 insertions(+) delete mode 100644 .agent-sessions/sessions.db diff --git a/.agent-sessions/sessions.db b/.agent-sessions/sessions.db deleted file mode 100644 index b8c26e4f123ec9721b5ab8b219bf35a609efd578..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 143360 zcmeI(?Qay#8&<6o2RFuukg8gZcL%b< z-Zi`90*b2ZwK3Qw4k$pVfVia(fZAe{x*`D#dDA!jBl@QD?3x!XFDkWCTV37XnRDi8 z*R#8B`XFz=j<7v5=ixV>bIxz(tlQnM^(75m-Ji~kXomWHXmd!CLjR+xp-|{a`nQ$- z*_3SeZ|?{U!XFmN!~|-}-U$@0yLKKQ+A}zuYiX zf2;nP4F~FeB)unX5B-(?`=@+$J=&=Bv`e96Dxn|A9vUWym^Nmlt>aimkEb(1 z530NR>EE8dzE0Ks>grPSGvnq5bIVH?Ru245|bDdwX~0dLEJ$Jt9p=4*XC?OU2)e=_wR$is>zf>uFtG=IVbG1QRbt{C*B@N+9V?4tJ{C=lPz;6vNCI(E!gSf`Lhdrk=oK_ zYN#wTc-FOZ)0FxKqhE^-tdfVED(0nYJQ114rwSL2nYT}wr#__I!W&^TFgU$9jTAn( zW6qr{ES)j0e~;>VR$pLcs=IRHr{?^HES?@q8KuxnL5shsCt^nWpq|RA^epOg z$AK=7r79FK(uOu1SUsN38g!A0_?s^F$UU)9R=T^TT-@)W9~#qBak>fd*rYYWPqeP? zVqdPtCZ!)SSk^3IDGu(f7Fmh5OS!F1@?g`>`z*0jr#Qc{Bv}MiU^zlu^F1VZPGuS4 zaI?(bJ91A2c0Q_Qs0qPIaE{ z%(Dy2AC2=o>F@?-9F^tC!t_liRX$jHyKwf}^6ht4E?--@ch9^yXa0D$nIWWYq5Ry_4pZ33V*1XSy|dFQxR8GP;d)dYCntq~u{}Bco+*)k&@S z^EdCG|7Cu9@xjt`@9uu}%U}H5bEtH|K9r zj4$t|Y2&m+&3H1L|9z0=EK7NNcJ;otC+fe%rdUg)OD^{cFXmNjhxnzbtFfBm&xztP z?LwN^PUJwntUTW#?@)mTQK&iZDQt#W41sCHZ&?-9a6Hi zpZMW~U9Ud46DsBFfsP|1b+qUycz4@kHx!F!bj_eA1wEm7GR|%&)3#IC--Ua6XLR>V zk;zU;RysPQ5Jx_ z+k9G=nbXWLa1X_o9b3;LjMEF|cdt>K><#9_pDf?KM4KG*?m261upI8}DeSxR?aHVf z$_uG z%)a3Z0uX=z1Rwwb2tWV=5P$##AOL|{6~O+#R!0{11px>^00Izz00bZa0SG_<0uXQo zu>W^0@EZgm009U<00Izz00bZa0SG{#Rt2#Cuho&oeL(;M5P$##AOHafKmY;|fB*zs zfiU|O|Nnm%1iwK50uX=z1Rwwb2tWV=5P$##YES@w|F6M8#VtVq0uX=z1Rwwb2tWV= z5P$##iUhF#F9N|K1Rwwb2tWV=5P$##AOHafK%fQ%u>Y^YLB%aW00Izz00bZa0SG_< z0uX=z1d0T(|1Sc;Ap{@*0SG_<0uX=z1Rwwb2tc3)1+f3G!9m3>K>z{}fB*y_009U< z00Izz00fEzu>UUt!65`7009U<00Izz00bZa0SG{#1_iMHufajZEkOVR5P$##AOHaf zKmY;|fB*!F1hD@v0>L2!AOHafKmY;|fB*y_009UY^YLB%aW00Izz00bZa z0SG_<0uX=z1d0T(|1Sc;Ap{@*0SG_<0uX=z1Rwwb2tc3)1+f3G!9m3>K>z{}fB*y_ z009U<00Izz00fEzu>UUt!65`7009U<00Izz00bZa0SG{#1_iMHufajZEkOVR5P$## zAOHafKmY;|fB*!F1hD@v0>L2!AOHafKmY;|fB*y_009UTC9TgS1C9#3Zy+1L*8%VWtcvhso=<=U+4$;6S^u$I!Zv8M8GT({y`b8^OSKAbv#Tc)ohoZ0mP|w@S{{}aMUf`6hBh>; zTLrCeTSU`?JzwpM@&?pxEvo7^q7Fu1A5?es)4x4^eVwZN)zziuXU5GB=9ZT(tSr2* z_U@#LtkvKuyfUk}xOhKz#ymY+xO#)t;&F{DNf?o<8uPtinLBI@4W!LRr48B_=Q_xA40^*kgidPJI#9QdJ(mWsa_ z(^Ez!=@|iWIzE;)(jzo3hy3LpE*Tg9b!Q|?+F_&RFY60iTw)_A`ZkV^>YXZ!?Q)Gq z$45&f_sk|)*-Ihqs}z!mrer#_RU4PvK!xBu^MJ?6hJI2H%St37ooKMuvfsvkv`Iw7 zSGWJ#CtK!DWM$SmTd>o|^Jf?MBDJN<)KFPw@T_a+rYZFeM!yyvSS1fRRm@A*cp@^7 zPZcg4GjE?VPkl(ag*U=xU~qbI8Yz5m$DBJ^SUO`~{~p!#tiHg?RCndXPtExY%eQ8V zst4vJhtFQqGy#j#)I_*dR-S!Un%rlNvz?JCgBw}jLD)CSzDuhPvL~uey2lZE+-L{% zSUf$JGD@MDf);;MPsEJ$K|PgK=~>k0jssmDOI0Xfqz!F2uzEb5HRvK0@i$%Uk$YmJ ztaNuvxwzj$KQyMN;&c<@u}N!$pJ-j(#lBpPO-esvu&i0aQXJe{EwU1AmvUR3u@)y+9pS3qWLP-C zX~%h!adOW6@psK1&N*o(nJAa&oa#K?nP(T4KN{zG(%}uvI4aANh3T74s(i5YcH!)` z<=gM9T)wt)@1A*a&iwIgH&4Fi)M8=r4lPqp23+N3t|%a$$f(`rdne5+6Y5x2&va|_ zUP|dFWpo?q^e}5ONy)>|Mn=ors*_st=WpIW|I7UJ;)A8>-rfD`m%sSA=T!6h`NGey zEPwQi2TL>5;HY+VIIWeJa~h;PZ_eMM7+>B^)5d9un(<^f|N9`#S(ftl?CO1OPt<>j zO|h0pmt5`@Ud*f54)IGr}yIy^8CsfMU106?3>S)nZ@b0$7ZYUPd z=$b)K3VK5EWSrelrfsLNzYF*D&gkx!B9onxtaNlp$G3aazMbu}b-smfcWbSDdj)!C zgLnI4&3KwjVgY+rpnDs^^O`D}(-+MHLt@hFsnMN#k`NQ?a#uO{l7@JpQoop<6gL%}pXTMExu`ja`2Brw-IU6s6a zf8nV{rFU!4M>rm-*bdLZf6z3x5_>MxAuGM~nNF9JarbL+!~IO>Af1mL)U8dtbww>n zkiivLp0uv|-UC^aohr52Nl$`9k%{z^)<->4|7A@8tGxB?Dc_)5r#{(mf5I0e7I&GU zwkAJ~_wwzN=KLIgAEEV1_vvP=l63B@7+&lC*?Fq+ZEbk0%-+x6kvYCZRRSj#e@iI( zJV|bsl~BOyBZsN_p)ySu+w7fzx9Ny zJpHsZ#XlNw%e%jI_-287{$Dy3SQu4Ig}?1X!@|`&^hh;Nzr!A>)qixj>PSnE)AFVb z&vs{|?N4>Zn@21&mZBWU_Kf1nlO>}ZT!js?xau2W-Y6gA+<$&bR$>&xHv?m^M%CJH zrblB|#&N@GuNcm%wSyvKg*&aSMW-q{6Jc&tWTl_Ne4&ak-SD1RLwHoHny{!?!VhCkAW}U6^&j3@8Ji_<2|7#^|5t#V#s0fCCf+tS?OV?`oS0yI_ugu?| z*H-Vow%SE*{Yil@b;`ti>X%RX)*I64mCJAQ*Rm=%x;#SX!6IgF*`BDQ{FzzyQf_@r zNa0nx1OEH%eFf}4VDIaHs^PCw`0JGO7ct+{$a#ClU#HjyJ4c0w_>kw{{I65^-~X@e zBMp>>00bZa0SG_<0uX=z1Rwwb2&_i|?Elx}s3B$uKmY;|fB*y_009U<00Izzz}f_` z|6iLIN<#nw5P$##AOHafKmY;|fB*#6qX72*>v7Z&GXx+20SG_<0uX=z1Rwwb2tZ(M z0@(kr%?qU=009U<00Izz00bZa0SG_<0_#x#`~USgYKR#E5P$##AOHafKmY;|fB*y_ zur>kg|JUY)(hz_E1Rwwb2tWV=5P$##AOL~&D1iO{dK@*x3;_s000Izz00bZa0SG_< z0uWf60QUcD^FnC|KmY;|fB*y_009U<00Izzz|FwCcGz1_30SG_<0uX=z1Rwwb2tZ&x3j9A54`~Dd diff --git a/.gitignore b/.gitignore index 6d05f66..4d7641e 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,8 @@ docs/* !docs/index.html .DS_Store # macOS .agent-sessions/* +packages/client/dist/* +packages/server/dist/* +packages/agent-core/dist/* +sessions.db +packages/session-sqlite/dist/* \ No newline at end of file