Compare commits

..
Author SHA1 Message Date
gozeros 1c933a8f19 sync snapshot from LAN repo (source tjlnew @ 9774c311) 2026-11-05 11:02:38 +08:00
1572 changed files with 15845 additions and 194879 deletions

No files matched your search

-39
View File
@@ -71,7 +71,6 @@ offline-backend-20260512/backend/.deer-flow/data/*.db-*
offline-backend-20260512/backend/.deer-flow/*
offline-backend-20260512/backend/.env
offline-backend-20260512/backend/.env.local
offline-backend-20260512/backend/.extensions_config.json.lock
offline-backend-20260512/start_backend.sh
offline-backend-20260512/stop_backend.sh
offline-backend-20260512/check_backend.sh
@@ -89,32 +88,12 @@ skills/
hermes-agent-main/
.gitignore
offline-backend-20260512/backend/tests/*
!offline-backend-20260512/backend/tests/test_large_file_safety.py
# Seeder-owned Agent Skills are product source; keep them out of the broad
# runtime `skills/` ignore above.
!offline-backend-20260512/backend/app/gateway/routers/_*_seed_assets/skills/
!offline-backend-20260512/backend/app/gateway/routers/_*_seed_assets/skills/**
# Keep startup seed completeness and task-report conversion regressions versioned.
!offline-backend-20260512/backend/tests/test_seed_assets.py
!offline-backend-20260512/backend/tests/test_task_report_convert.py
!offline-backend-20260512/backend/tests/test_migration_compatibility.py
# Keep project-scoped cross-conversation memory regressions versioned.
!offline-backend-20260512/backend/tests/test_analysis_project_memory.py
!offline-backend-20260512/backend/tests/test_analysis_project_memory_integration.py
!offline-backend-20260512/backend/tests/test_analysis_project_memory_runtime.py
!offline-backend-20260512/backend/tests/test_analysis_project_memory_store.py
# Keep answer-level feedback persistence, scoring, resolver, and migration regressions versioned.
!offline-backend-20260512/backend/tests/test_answer_feedback.py
# Keep wx common-agent category configuration regressions versioned.
!offline-backend-20260512/backend/tests/test_wx_common_agents.py
# Keep the built-in public-document seed regressions versioned.
!offline-backend-20260512/backend/tests/test_gongwen_agent_seed.py
!offline-backend-20260512/backend/tests/test_gongwen_documents.py
# Keep the openGauss URL/dialect/schema compatibility regression coverage versioned.
!offline-backend-20260512/backend/tests/test_gauss_database.py
!offline-backend-20260512/backend/tests/test_llmwiki_weknora.py
!offline-backend-20260512/backend/tests/test_llmwiki_knowledge_management.py
!offline-backend-20260512/backend/tests/test_llmwiki_advanced_retrieval.py
!offline-backend-20260512/backend/tests/test_knowledge_live_embedding.py
!offline-backend-20260512/backend/tests/test_health_auth_bypass.py
# Keep formal Word OOXML and embedded-font regression coverage versioned.
@@ -138,26 +117,17 @@ offline-backend-20260512/backend/tests/*
!offline-backend-20260512/backend/tests/test_llmwiki_local_index_repository.py
!offline-backend-20260512/backend/tests/test_llmwiki_vector_search.py
!offline-backend-20260512/backend/tests/test_llmwiki_wiki_sync.py
!offline-backend-20260512/backend/tests/test_llmwiki_incremental_sync_contract.py
!offline-backend-20260512/backend/tests/test_llmwiki_encoder_runtime.py
!offline-backend-20260512/backend/tests/test_external_llmwiki_search.py
!offline-backend-20260512/backend/tests/test_llmwiki_wiki_retrieval.py
!offline-backend-20260512/backend/tests/test_public_llmwiki_embed.py
# Keep assistant-source snapshot publication atomic across re-import jobs.
!offline-backend-20260512/backend/tests/test_assistant_snapshot_pointer_contract.py
# Deep-research reliability regression coverage.
!offline-backend-20260512/backend/tests/test_deep_research_persistence.py
!offline-backend-20260512/backend/tests/test_deep_research_event_sink.py
!offline-backend-20260512/backend/tests/test_deep_research_executor_reliability.py
!offline-backend-20260512/backend/tests/test_deep_research_start_job.py
!offline-backend-20260512/backend/tests/test_summarization_human_message.py
!offline-backend-20260512/backend/tests/test_llmwiki_title_ranking.py
!offline-backend-20260512/backend/tests/test_menu_overrides.py
!offline-backend-20260512/backend/tests/test_compact_menu_overrides.py
# Keep database-backed upload-policy, enforcement and bounded-preview regressions versioned.
!offline-backend-20260512/backend/tests/test_upload_policy.py
!offline-backend-20260512/backend/tests/test_uploads_policy_enforcement.py
!offline-backend-20260512/backend/tests/test_artifact_preview.py
# Independent enterprise-research persistence, HTTP and race regressions.
!offline-backend-20260512/backend/tests/test_enterprise_research_tasks.py
# Position-roundtable per-turn write/present cap (weak-model duplicate artifacts).
@@ -218,19 +188,10 @@ docs/backups
# Frontend skills components must be tracked (excluded from the broad skills/ ignore above)
!frontend-web/src/components/workspace/skills/
# Built-in analysis mind-map skill is product source, not a per-user runtime skill.
!offline-backend-20260512/backend/skills/
offline-backend-20260512/backend/skills/*
!offline-backend-20260512/backend/skills/public/
offline-backend-20260512/backend/skills/public/*
!offline-backend-20260512/backend/skills/public/analysis-mindmap/
!offline-backend-20260512/backend/skills/public/analysis-mindmap/SKILL.md
# uv lockfile (not tracked per project preference)
offline-backend-20260512/backend/uv.lock
!offline-backend-20260512/backend/tests/test_wiki_package_roundtrip.py
!offline-backend-20260512/backend/tests/test_llmwiki_incremental_sync_scheduler.py
# Local-only scratch directory (not committed)
0622/
+2 -4
View File
@@ -90,18 +90,16 @@ The frontend (`frontend-web/`) is a React 19 + Vite SPA:
- **Pages**: `ChatPage` (thread chat), `AgentChatPage` (custom agent chat), `AgentsPage`/`NewAgentPage` (agent management), `ScheduledTasksPage`/`ScheduledTaskRunDetailPage` (scheduled tasks), `LightAppManagementPage`/`LightAppListPage`/`LightAppIframeView` (轻应用中心 — register/list/embed mini-apps)
- **AI 写作·对话版(对话驱动写作台)**: a **parallel new entry** beside the classic AI-writing page (classic page/routes untouched) — route `/page/canvas/ai-writing-chat`, sidebar 「问答管理 → 课题研究(对话版)」. Page `open-canvas/pages/AIWritingChatPage.tsx` reuses the engine (`AIWritingContext` + `useStream` + `AIWritingDraftPanel`); **idle keeps the classic setup layout** (`WritingSetupChat` + collapsible form) and switches to the chat workbench once writing starts; left panel `components/ai-writing-chat/WritingChatPanel.tsx` = **unified chronological feed** (`ChatFlowTimeline.tsx`, chat bubbles anchor-interleaved into the progress timeline so triggered events render below the user's message) + button-only intervention cards (`ChatInterventionCards.tsx`, inline textareas removed) + bottom unified smart composer. Intent resolution: frontend fast path + `POST /api/ai-writing/sessions/{id}/intent` → `deerflow/agents/ai_writing/intent_router.py` (per-pause action whitelist, high-cost confidence gates, payload cleaning); supports QA bypass, clarify follow-ups, control intents, and material-stage auto re-search + pending-intent resume. Tests `tests/test_ai_writing_intent.py`; plan doc `frontend-web/docs/ai-writing-对话驱动写作台-实现方案.md`.
- **轻应用中心 (Light App Center)**: a sibling of 任务管理 in the sidebar with two pages — 应用管理 (admin registers `window_open` or `iframe` mini-apps with a route-param builder: login params resolved from `localStorage.userInfo`, theme params literal) and 应用列表 (card grid of `window_open` apps, `window.open` launch). `iframe` apps are mounted under a chosen parent menu (XK/PG/TY/综合管理) and **dynamically injected into the sidebar** by `core/page-layout/use-sidebar-menu.ts` (`useSidebarMenuItems`), opening in the `LightAppIframeView` host. Client + React Query hooks in `strategy-components/api/light-apps.ts`; URL builder/constants in `strategy-components/lib/light-app.ts`. Backend: `/api/light-apps` (global/shared, admin-gated writes).
- **菜单管理 (Menu Management, admin defaults + personal layouts)**: `MenuManagementPage` (`pages/MenuManagementPage.tsx`) is available from「设置和更多」and the global Header account dropdown. Administrators edit the shared default menu; ordinary users edit only their own full/compact menu snapshot. For users with a saved snapshot, known node ids keep the personal `label`/`disabled`/`parentId`/`sortOrder` (or compact placement/order), while administrator defaults for node ids absent from that snapshot flow through—so newly-added code menus and iframe light apps follow the current default without overwriting older personal choices. Temporarily absent dynamic nodes are preserved when an unrelated personal edit is saved;「恢复默认」deletes only that user's snapshot. The static tree (`core/page-layout/sidebar-menu.ts`) remains the source of icons/routes and administrator defaults remain sparse per-node deltas. Merge/snapshot helpers live in `core/page-layout/menu-overrides.ts` and `compact-menu-overrides.ts`; full-menu writes carry the complete effective parent hierarchy for cycle/strict three-level validation while persisting only the sparse admin delta or full personal snapshot. Backend `/api/menu-overrides` uses `menu_overrides` (default) + `user_menu_override_configs` (per-user snapshot); `/api/compact-menu-overrides` uses `compact_menu_overrides` (type `A` / `B` defaults) + `user_compact_menu_override_configs` (per-user/type snapshots). Each website selects its compact type via `runtime-config.js` `VITE_COMPACT_MENU_TYPE`; `CompactToolbox` renders `toolbox` items.
- **菜单管理 (Menu Management, admin-only)**: an **overlay** over the static sidebar menu — `MenuManagementPage` (`pages/MenuManagementPage.tsx`, route `/page/strategy/admin/menu-management`, opened from the admin-only 「菜单管理」 item in the **bottom-left settings dropdown** of `components/page-sidebar.tsx`). Admins rename / 停用·启用 / reorder (↑↓ or @dnd-kit drag) / re-parent (horizontal drag **or** the edit dialog's 「移动到」parent selector) any node across 一级/二级/三级, **including injected iframe light-app nodes** (`light-app-<appId>`). The static tree (`core/page-layout/sidebar-menu.ts`) stays the source of icons/routes; only per-node deltas (`label`/`disabled`/`parentId`/`sortOrder`) persist to the backend. Merge logic in `core/page-layout/menu-overrides.ts` (`applyMenuOverrides`, applied in `use-sidebar-menu.ts` after light-app injection, before role filter; disabling a node hides its whole subtree) — strict **3-level cap** (`wouldExceedDepth`). Client `strategy-components/api/menu-overrides.ts`. Backend: `/api/menu-overrides` (global/shared; open read, admin atomic replace-all). **简介模式** uses a separate overlay: every compact workspace menu item can be placed in `sidebar`(左侧菜单)、`settings`(设置和更多)or `toolbox`(右侧工具箱); `CompactToolbox` (`components/workspace/compact-toolbox.tsx`, mounted by `PageRoutes.tsx`) opens only when the square right-edge trigger is clicked, then slides a compact, content-height right-side drawer over a backdrop above global dropdowns; configured items render top-to-bottom as centered square cards with a large icon above the label while the effective layout is compact. `/api/compact-menu-overrides` stores two independent sets (type `A` / `B`); each website picks one via `runtime-config.js` `VITE_COMPACT_MENU_TYPE`.
- **舆情分析智能体(前端虚拟智能体)**: 智能体管理页新增「舆情分析」类型 tab,固定一张虚拟智能体卡片(名称/简介可编辑,存 localStorage)。对话页 `pages/SentimentAgentChatPage.tsx`(路由 `agents/sentiment-analysis/chats/:thread_id`)复用普通问答布局 + `MessageList`,**输入框只有发送按钮**;问答经 Gateway `POST /api/sentiment-agent/stream` 转发外部 AG-UI 网关(不经过 LangGraph),会话仅存 sessionStorage。接口地址 + Basic Auth 在 `runtime-config.js` 配置(`VITE_SENTIMENT_AGENT_API_URL` / `_AUTH_USERNAME` / `_AUTH_PASSWORD`)并随请求传给后台;后台按传入地址转发、关闭 TLS 校验,失败时把完整错误回传。核心模块 `src/core/sentiment-agent/`。
- **简洁模式用户引导 (Compact-mode onboarding tour)**: 简洁模式(外观设置的「全量/简洁」= compact,无全局导航栏 + 页面侧边栏)新增 TDesign React `Guide` 组件驱动的分步引导。组件 `components/workspace/compact-mode-guide.tsx`(挂在 `ChatPage`):9 步 —— 欢迎弹窗(dialog 模式)→ 左侧功能导航 → 聊天记录 → 设置和更多 → 换肤 → 界面模式(切回全量)→ 常用提示词栏 → 提示词管理弹窗 → 输入框;高亮目标由各组件上的 `data-compact-guide` 标记定位(`workspace-nav-chat-list` / `recent-chat-list` / `workspace-nav-menu` / `appearance-controls` / `custom-prompt-menu.tsx` 的 `CustomPromptBar`(提示词栏,仅新对话落地态渲染)与其 `ManagePromptsDialog`(`prompt-dialog` 锚点)/ ChatPage 输入框容器),**启动时按目标是否存在过滤步骤**(如新用户无聊天记录、侧栏收起时自动剔除该步 —— Guide 对缺失元素会抛错,不能盲传)。**提示词管理弹窗步骤是动态目标**:弹窗平时不渲染,引导切到该步前先广播 `PROMPT_DIALOG_GUIDE_EVENT`(`custom-prompt-menu.tsx` 导出)让 `CustomPromptBar` 打开 `ManagePromptsDialog` 并**接管**(`owner: true` 期间 ESC/点遮罩不关闭,防止高亮目标消失导致 Guide 报错),轮询锚点真正挂载后才切步;离开该步 / 跳过 / 完成 / 中途卸载时以 `owner: false` 收回弹窗,4 秒打不开则跳过该步防卡死。**TDesign Guide × Radix 模态互操作**:Radix 模态弹窗打开时会把 `body` 置 `pointer-events:none`(滚动锁定),Guide 直接挂在 body 下的遮罩/高亮/弹层会一并继承失活(引导按钮点不动),`styles/tdesign-theme.css` 末尾对 `.t-guide__overlay/__highlight/__popup/__wrapper` 显式 `pointer-events:auto` 兜底。触发:① 自动 —— 简洁模式新对话落地页自动演示,直到用户显式点「完成」或「跳过」才写 localStorage `deerflow.compact-guide-finished` 记忆(浏览器级);**中途刷新/离开不记忆,下次进入还会再演示**。② 手动 —— 「设置和更多」下拉新增「界面使用引导」(该下拉仅存在于简洁模式工作区侧栏 footer):已在问答页时广播 `compact-guide:start` 窗口事件直接启动,否则写 sessionStorage 请求并导航 `/chats/new` 由挂载的引导消费(消费在定时器真正启动时才执行,规避 StrictMode effect 双跑吞请求)。`eligible` 排除 embed=1 / hideChrome=1 / chats_iframe / FORCE_COLLAPSED_SIDEBAR(无界)等同样无全局 chrome 的特殊环境;启动延迟 800ms 等侧栏宽度过渡稳定后再测量高亮框。
- **智能体使用引导 (Agent onboarding tour, 三段式)**: 智能体「浏览管理 → 创建与配置 → 发起问答」全流程分步引导,组件 `components/workspace/agents/agent-guide.tsx`(同一 TDesign `Guide` 封装模式,与简洁模式引导共享记忆语义:**仅显式点「完成/跳过」才写 localStorage** `deerflow.agent-guide.<stage>.finished`,中途刷新/离开不记忆)。**自动演示仅 create / chat 两段**(进智能体列表页不弹引导,点「创建智能体」进入新建页时才自动演示;list 段的 `AgentGuide` 传 `autoStart={false}`,只能由头部「使用引导」按钮手动触发)。三段各自挂载、各自记忆:① `list`(`agent-gallery.tsx`,/page/workspace/agents)——分区 Tabs、搜索排序、智能体卡片操作、右上「创建智能体」按钮;**完成/跳过就地结束(不跳转创建页,与 create 段无联动)**,最后一步仅提示进入创建页后会有配置引导;② `create`(`NewAgentPage.tsx`,/page/workspace/agents/new)——左侧对话式创建输入区、基本信息、运行模型+入库模板名、知识空间、SOUL.md、技能穿梭框、保存按钮(9 步);③ `chat`(`AgentChatPage.tsx`,agents/:id/chats)——左栏切换与历史、常用问题 chips、输入框(落地态/会话态两个挂点同一 `chat-input` 标记)、右侧详情面板;`eligible` 限定普通智能体对话页(`showAgentList && !isEmbedded && !taskCtxOn`,即排除通用问答原地嵌入与任务深链工作区),三段共用 `isAgentGuideEnvironment()` 排除 embed/hideChrome/无界环境。高亮锚点 `data-agent-guide`:列表页 `tabs`/`search`/`agent-card`(卡片+列表两种布局的根元素)/`new-agent-btn`,创建页 `create-chat-input`/`create-basic`/`create-model`/`create-knowledge`/`create-soul`/`create-skills`/`create-save-btn`,对话页 `chat-sidebar`/`chat-questions`/`chat-input`/`chat-detail`;同样**启动时按目标存在性过滤步骤**(新用户无卡片/无预设问题时自动剔除)。手动重放:三个页面头部各有「使用引导」按钮(列表页创建按钮左侧、创建页 header 右侧、对话页 header),广播 `agent-guide:start:<stage>` 窗口事件强制重放(忽略已看过记忆)。
- **敏感词管理 (Sensitive Word Management)**: configures the **展示层脱敏映射** (原始词 → 替换词). **Gated on the username `lqq`** (not the admin role) — `getAccountDisplayName().toLowerCase() === "lqq"` (username = email `@` prefix, else `user_id`, same as the profile page); the dropdown entry, the route guard, and the page-level guard all use this check. `src/lib/desensitize.ts` ships a frozen seed map `SEED_DESENSITIZE_MAP` (the deployment seed) plus a live mutable `DESENSITIZE_MAP` (initialized from the seed so `desensitize()` works before any fetch). `DesensitizeWordsLoader` (mounted in `App.tsx` `AppProviders`) fetches `/api/sensitive-words` on startup and, if non-empty, calls `replaceDesensitizeMap(...)` to make the backend config the source of truth (empty/failed → keep seed). Page `SensitiveWordsPage.tsx` (route `/page/strategy/admin/sensitive-words`, opened from the 「敏感词管理」 item in the **bottom-left settings dropdown** of `components/page-sidebar.tsx`, present in **both** full + collapsed sidebar modes) lists/adds/edits/启停/deletes words and saves the **whole set atomically** (replace-all); a 「导入种子词」 button merges any missing `SEED_DESENSITIZE_MAP` entries into the editor. Client + hooks in `strategy-components/api/sensitive-words.ts` (`wordsToMap` folds enabled rows into the runtime map). Backend: `/api/sensitive-words` (global/shared; open read, write allowed for admin **or** the `lqq` account), mirroring 菜单管理's store shape. **侧边栏 + 导航栏 menu labels are desensitized** at the data source: `useSidebarMenuItems`/`useActiveThirdLevel` (`core/page-layout/use-sidebar-menu.ts`) map every node's `label` through a desensitizer built **directly from the `/api/sensitive-words` query** (`makeDesensitizer(wordsToMap(words))`, falling back to the global seed `desensitize` while empty) — this sidesteps the `replaceDesensitizeMap` effect-timing race. Only `label` is rewritten; `path`/`id`/`icon` are untouched so routing/highlight are unaffected. All nav surfaces (`page-sidebar.tsx`, `page-sidebar-dark.tsx`, `page-sidebar-v1.tsx`, `strategy-components/Header.tsx`, `PageRoutes.tsx`) consume this hook and are covered; `MenuManagementPage` uses the raw tree so admins still edit real labels.
- **技能上下线 (Skill Availability, owner/admin)**: the global `Skill.enabled` flag is the online/offline switch. Taking a skill offline persists `skills.<name>.enabled=false` in `extensions_config.json` but does **not** delete its directory or remove it from existing agent/workflow configurations; the row remains visible and bringing it online restores those references. Administrators may toggle every skill from 「技能管理」; ordinary users may toggle only their own non-built-in `custom` skills from 「技能 → 技能列表 → 我的」. Offline skills must be absent from every model-facing skill catalogue (`lead` prompt, `search_skills`, `skill_list`, `skill_view`, subagents, AI writing/deep research/roundtable and Workflow run-start validation), from agent skill pickers, and from direct sandbox access: `read_file`/`ls`/`glob`/`grep`/`bash` reject offline, unknown, root-wide and category-wide `/mnt/skills` paths. The backend mutation is `PUT /api/skills/{name}`, authorizes either an administrator or the persisted owner of the target custom skill, patches the raw document so MCP placeholders and unrelated extension fields survive, uses atomic replacement when supported plus a Docker single-file-bind fallback, and refreshes the skill prompt cache. Launchers keep the runtime extensions file in a writable persisted directory. Existing agent/strategy-agent references stay visible as 「已下线」 and may be removed but not newly selected.
- **技能地址管理 (Skill Address Management, admin-only)**: 扫描运行中的技能(`skills/{public,custom}` 下所有 `.md`/`.py`)里的 **http(s) URL 与 IP/IP:端口**,按唯一地址聚合全部出现位置(跨 .md/.py),支持**批量替换**(如把 UAT 地址一次性改成生产)。主体抽成可复用组件 `SkillAddressesPanel`(`pages/SkillAddressesPage.tsx` 导出,默认导出 `SkillAddressesPage` 仍保留旧路由 `/page/strategy/admin/skill-addresses` 作直链回退),**作为「技能地址管理」标签页嵌入管理员「技能管理」页 `pages/AdminSkillsPage.tsx`**(该页加 Tabs:「技能列表」+「技能地址管理」;入口在「设置和更多」下拉的「技能管理」`workspace-nav-menu.tsx` → `/page/workspace/admin/skills`,不再单列于 `components/page-sidebar.tsx` 左下角设置下拉):打开自动扫描并带**进度条**(扫描逐技能 / 应用逐文件 X/N,应对 150+ 技能),URL/IP 类型过滤 + 搜索 + 「片段批量套用」(如所有 `uat.4.cn` → `prod.4.cn`)、每地址「替换为」输入框(可展开看 `file:line` 片段)、内联**预览**、**应用**、**多关键词检索**(空格分隔全部命中),以及**修改记录**面板——每次应用生成一条记录(显示时间/改了哪些地址 from→to/文件数/处数),可**针对单次记录回退**(二次确认)。client + NDJSON 流式解析在 `strategy-components/api/skill-addresses.ts`。后端 `/api/skill-addresses`(**仅管理员**):所有文件 IO 走 `asyncio.to_thread` 不阻塞事件循环;`GET /scan`(+`/scan/stream`)、`POST /preview`、`POST /apply`(+`/apply/stream`)、`GET /backups`、`POST /rollback/{id}`;**子串安全替换**(基于 token span,不会误伤子串)、`expected_total` 乐观锁(409)、写前自动磁盘备份到 `{skills_root}/.address-edits/`(同时写一份 `{id}.manifest.json` 记录本次替换明细,供修改记录展示)、应用后刷新技能系统提示缓存。纯引擎 `deerflow/skills/address_scan.py`,router `app/gateway/routers/skill_addresses.py`,tests `tests/test_skill_addresses.py`。范围仅运行中技能,不动 `deploy/minimal/skills/`。
- **按钮管理 (Task Button Management, admin-only)**: configures the **可配置跳转按钮** rendered in the left task panel of the task deep-link workspaces (rwfx / 3qfx / xdfx, see `TaskFxWorkspace`). Each button = `{business, label, linkType, target, appendTaskId, idParam, idKind, enabled, sortOrder}`; `linkType` is `url` (外链 `window.open`, optional append of `?{idParam}={id}` — **`idParam` is the editable query-param name**, e.g. `id`/`task_id`), `business` (内部切换到另一业务, reuses `resolveTaskDeeplinkTarget`, always task id), or `purpose` (弹出当前任务的「任务目的」表格 via the shared `TaskPurposeDialog`, no target — configurable for any page incl. xdfx). **`host`(宿主路由)** asks the embedding parent to navigate: `runTaskButton` sends `window.parent.postMessage({ type:'HOST_NAVIGATE', path, queryParams:{ [idParam]: Number(taskId) } }, hostOrigin)` — `target` is the host route, `appendTaskId`/`idParam` become numeric `queryParams` (task id, or action id when `idKind:"action"` — same selector as url buttons, xdfx only), origin from `runtime-config.js` `VITE_HOST_NAVIGATE_ORIGIN` (else ancestorOrigins/referrer; never `*`). **`idKind` (`task`/`action`) only matters for xdfx**: its deep-link `?taskId=` is an 行动id and the 任务id is resolved at login (`fetchTaskIdFromAction`) — `TaskContext` now also stashes the raw `actionId`, so a url **or host** button can append either (default `task`). Page `TaskButtonsPage.tsx` (route `/page/strategy/admin/task-buttons`, **admin-gated**, entry「按钮管理」in the bottom-left settings dropdown of `components/page-sidebar.tsx`, both full + collapsed modes) has per-business tabs, edits name/type/target/启停/排序/增删, saves the **whole set atomically** (replace-all), plus 「导入默认」 to merge code-seed defaults. **Seed/fallback** (like 敏感词管理): only when the whole table is empty (fresh deploy, never saved) do the workspace + page fall back to `defaultTaskButtons(cfg)` — rwfx's url buttons (编辑/下一步/3q详情) built from the **live** `/api/public/config/task-deeplink` plus cross-business switch buttons for **all three** businesses (each switches to the other two — rwfx→三情/行动, 3qfx→任务/行动, xdfx→任务/三情). Once saved, the store is the sole source of truth. The old hardcoded jump buttons were migrated out: `TaskFxWorkspace` no longer hardcodes 切换到三情分析, `TaskActionsPanel` keeps only the non-jump 清除记录, and `TaskPurposePanel` dropped its 3q详情 button (now configurable) **and defaults the 目的树 table to collapsed** (chevron toggle). Helpers `core/auth/task-buttons.ts` (`TaskButton`, `defaultTaskButtons`, `resolveTaskButtons`, `buttonsForBusiness`, `runTaskButton`), client+hooks `strategy-components/api/task-buttons.ts`. Backend: `/api/task-buttons` (global/shared; open read, admin replace-all), store `deerflow.persistence.task_buttons` (table `task_buttons`, auto-created by `create_all`), wired `app.state.task_button_store`. Tests: `tests/test_task_buttons.py`.
- **State**: TanStack Query for server state, context providers (`SubtasksProvider`, `ArtifactsProvider`, `PromptInputProvider`) scoped to `WorkspaceRoutes`
- **LLM streaming**: `@langchain/langgraph-sdk` streams messages from the backend via SSE
- **UI**: Radix UI primitives + TailwindCSS v3 + shadcn-style components in `src/components/ui/`
- **麒麟 Chromium ~80 兼容 (Kylin legacy Chrome)**: Tailwind 自 v4 降级到 v3(v4 的 `@layer` 需要 Chrome 99+,麒麟系统自带 Chromium 80 多整站裸奔)。要点:① `tailwind.config.ts` —— 语义色走六套主题(`:root/.dark/.lightblue/.lightgreen/.iceblue/.lightyellow`)维护的 `--legacy-*-rgb` 通道变量,透明度修饰符(`bg-primary/10`)用 `rgb(var()/<alpha-value>)` 原生支持;border/input/sidebar-border/ring 用 `--*-alpha` 变量还原 v4 color-mix 叠乘语义;`xs/sm` 刻度(shadow/blur/rounded)与裸 `ring`(1px+currentColor)按 v4 值覆盖,类名零改动;streamdown 运行时拼类名的白名单在 `safelist`;v4 独有工具类(outline-hidden/text-shadow-sm/field-sizing-*)以插件手写兜底。② `darkMode: "class"` 输出 `:is(.dark *)`,由 `scripts/postcss-dark-descendant.mjs` 在 postcss 阶段改写为 `.dark X` 后代形式(v3.4 的 `["selector", ...]` 堆叠变体会生成非法选择器、无 darkMode 配置会退化成媒体查询,均不可用)。③ 手写 CSS 禁用 `:is()`(复杂参数 lightningcss 无法安全降级,globals/roundtable/intent 已全部展开为逗号选择器);`:has()`(105+)按渐进增强放行,唯一功能性依赖(input-group 焦点/校验环)在 globals.css 有 `@supports not selector(:has(*))` 回退。④ vite `build.target` + lightningcss targets = chrome80(转译 `:is()`/逻辑属性/媒体 range 语法、厂商前缀);`src/polyfills.ts`(core-js 精选 API)在 main.tsx 首位引入。⑤ 构建后跑 `pnpm check:legacy-css` 防回归(产物不得含 @layer/@property/:is()/未守护 color-mix)。
- **UI**: Radix UI primitives + TailwindCSS v4 + shadcn-style components in `src/components/ui/`
- **Shims**: `src/shims/` provides `next/link` and `next/navigation` polyfills (original code was Next.js)
- **Login URL params** (`LoginPage.tsx`, frontend-only — the backend never sees these): besides the auth params (`ticket`/`userId`/`env`/`theme`/`yUserId`/`token`/`access_token`/`authToken`/`password`), the page supports a **task deep-link** via `?taskId=&goPath=`. After login it calls the consumer API `GET {VITE_AIPI_CONSUMER_URL}/taskAnalyseSearch/cop-task-detail?taskId=` (header `Authorization: Bearer admin`, auto-injected by `utils/request.ts`), stashes the full `data` (`id/overview/taskDirection/taskName/taskContent`) into `sessionStorage["login.copTaskDetail"]`, then routes by `goPath`: base codes `3qfx`/`rwfx`/`xdfx` → that business's configured **single agent** Q&A inside a **任务工作区** (resolved via `/api/business-mapping`; `resolveTaskDeeplinkTarget` calls `persistTaskContext({taskId, agentId, openingText})` and navigates to the `…/chats` **index**, which opens the latest task conversation or 新建 — a 1:N task↔对话 workspace, NOT `pendingAgentMessage`); the `-A` suffix (`3qfx-A`/…) → **multi-agent roundtable** with `roundtablePrefill.businessCode` so the page auto-selects the configured 业务链条. **xdfx's deep-link `?taskId=` is actually an 行动id, not a 任务id** — `resolveDeeplinkTaskId(goPath, rawId)` (called in `LoginPage` before everything) detects `xdfx`/`xdfx-A` and resolves it via `GET {action_detail_url}/{actionId}` → `data.taskId` (`fetchTaskIdFromAction`; `action_test`+`mock.action_detail` for offline testing); the resolved 任务id then drives `cop-task-detail`, the purpose tree, and the 1:N binding (other businesses pass the id through unchanged). **xdfx additionally partitions its chat records by 行动id (action_id), NOT by task_id**: `resolveTaskDeeplinkTarget` sets `partitionByAction:true` + keeps the raw action_id as `TaskContext.actionId`, so new threads are tagged `metadata.{taskId,actionId}` (taskId kept only to preserve the backend「任务深链对话全局共享」semantics, which keys off `metadata.taskId`) and the conversation list filters by `actionId` (+`agent_id`) — different actions of the same task get separate lists. xdfx's first-question opening text also appends `行动id(action_id)为…` (see `buildOpeningText` / `taskThreadMetadata`). goPath→businessCode: `3qfx`→`3Q`, `rwfx`→`6BF`, `xdfx`→`7BF`. The roundtable target also threads the URL `taskId` into `roundtablePrefill.taskId` (`resolveTaskDeeplinkTarget(goPath, detail, taskId)`), which turns on two taskId-scoped behaviors: (1) **separate, unpartitioned per-task storage** — taskId 会商聊天记录 live in their **own** store/table (`roundtable_task_drafts`), keyed **only by `task_id`** (one taskId = many records, shared across users, **no user 分权** at all; `created_by` is audit-only), kept entirely out of the per-user personal store (`roundtable_drafts`, now strictly per-user) so the two never mix. Backend router `/api/roundtable-task-drafts` (`GET /by-task/{id}` + `/by-task/{id}/latest`, `POST`, `GET/PUT/DELETE /{id}` — all user-agnostic); frontend client `roundtable-planning/api/task-drafts.ts`, and `useDraftPersistence`/`useRoundtableDrafts` route **all** CRUD to it when a `taskId` is present (else the personal `drafts.ts`). The matching **background jobs** are shared by task too: `roundtable_jobs.task_id` marks a task job; reads/dedup/stream/resume/cancel pass `?task_id=` so any user opening the task sees the same running 研讨 (progress/flowchart), and the executor writes the final report back to the task-draft store. Existing rows are moved over by `scripts/migrate_roundtable_task_drafts.py` (migration `20260618_01`). The history dropdown filters to the task and 新建 keeps the binding; (2) **Step-3 auto structured output** — after the `roundtable-summary` agent writes the Markdown report it automatically runs a second round emitting a `flow-json` flowchart (`useStep3Summary` `autoFlow`+`chainLevels`), whose hierarchy follows the business chain's stage goals (任务 → 目的 → 行为体 → …; coordinatorPrompt-specified hierarchy wins) and whose nodes never carry 阶段编号/阶段名 (the prior bug). **Both targets render embedded under the 任务管理 layout** — nested routes under `task-management/<business-path>/{roundtable,agent/:agent_id/chats}` in `StrategyRoutes.tsx` (`<business-path>` = `plan-task-sentiment` / `plan-task/plan-task-fx` / `plan-task/plan-task-action`, matching the COH中任务 menu paths in `sidebar-menu.ts`) so the global sidebar keeps 任务管理 → COH中任务 → the matching business highlighted. **All three single-agent businesses share `TaskFxWorkspace`** (`task-components/TaskFxWorkspace.tsx`): left = a「当前任务」card (`readCopTaskDetail()` 任务名称 + 简介, desensitized, 留存 above 新建对话) + per-task 1:N conversation list (`useTaskThreads(taskId, agentId, actionId?)` — filtered by **both** `metadata.taskId` AND `metadata.agent_id` so the three businesses' conversations staLine truncated
- **agentfx 任务深链(新系统 iframe 嵌入的智能体问答,3qfx 单智能体 lite 模式的独立复制)**: goPath=`agentfx`(`${loginBase}?password=…&taskId=…&goPath=agentfx&embed=1&hideJump=1&theme=dark-blue`)。与 3qfx 的差异:①任务详情不走外部 consumer,改调**本系统 Gateway** `GET {backend}/taskAnalyseSearch/cop-task-detail?taskId=`(`apiFetch` 带刚登录的 DeerFlow 态;任务数据来自 TaskCOP 任务表,与任务列表/报告导入同一份);②**固定使用内置智能体** `agentfx-analyst`(不走业务映射);③路由 `task-management/plan-task-agentfx/agent/:agent_id/chats`,页面为独立复制的 `AgentFxWorkspace.tsx`(`AgentFxWorkspace`/`AgentFxIndexResolver`/`AgentFxChat` —— 左「当前任务」卡 + 1:N 对话列表 + 新建对话,`AgentChatPage taskBind` 自动发开场白;无 TaskJumpBar/清除记录/闸门/xdfx 行动卡)。模块 `core/auth/agentfx-deeplink.ts`(`isAgentfxGoPath`/`fetchAgentfxTaskDetail`/`resolveAgentfxDeeplinkTarget`);任务详情整包仍存共享键 `login.copTaskDetail`(按标签页隔离),`AgentChatPage` 的 taskBind 自恢复对 agentfx 生效。`LoginPage` 在既有深链分支前用 `isAgentfxGoPath` 分流。**内置「任务研判报告助手」**:后端 seeder `app/gateway/routers/_agentfx_seed.py` + `_agentfx_seed_assets/`(config.yaml + SOUL.md,目录存在不覆盖;app.py lifespan 在 `_sync_legacy_agents` 之前调用,自动进 agents 表 user_id IS NULL)——SOUL 规定工作流「搜集信息(`web_search`,**首步不可跳过**)→ 每次检索 JSON 原样落盘 `/mnt/user-data/workspace/hits/qN.json` → **一条命令** `task-report-build`(group `all`)技能函数转换成 14 类 `task-reports.json`(模型禁止手写该 JSON;分页技能 `task-report-{enemy,our,env,judge}` 仅用于事后补跑单页;五者都是共享引擎 `task-report-lib/convert_lib.py` 的瘦 CLI,`resolve_hit_files` 对虚拟绝对路径读空的情况自动回退到相对写法并在 `warnings` 里列出尝试过的路径,免得智能体自己写脚本排查)→ `write_file` 生成 `/mnt/user-data/outputs/report.md` → 聊天总结 → 引导入库」,硬性约束:categoryType 逐字用 14 个全称(禁缩写自造如「DQ关键事件」)、JSON 直接写汉字禁 `\uXXXX` 转义、每类必须有实质内容不许空数组/纯占位、文件一律用 `/mnt/user-data/...` 虚拟路径(防宿主路径泄漏进 tool args)。**检索依赖 `config.yaml tools.web_search`(DDG,enabled 已开;内网需换 configurable_search 时改回并填 endpoint)**。任务工作区输入框在 `taskCtxOn` 时隐藏「写作/记忆/参考文献」(InputBox `hideContextTools` prop)与「知识空间」(不传 knowledgeSelector);消息流里 write_file 文件卡片只显示文件名(`artifactDisplayName` 收敛宿主/虚拟路径)。**入库两条路径**:(a) **前端协助卡** —— `AgentChatPage`(taskBind 且非 taskGate)检测线程 artifacts 出现 `task-reports.json`(按文件名后缀匹配,兼容本地沙箱记录的宿主路径)且流式结束时,向 displayThread 尾部注入 `additional_kwargs.task_report_import_approval` 虚拟 ai 消息(`core/messages/utils.ts` 分组 `assistant:task-report-import` + `MessageList` 的 `taskReportImportSlot` 插槽渲染 `TaskReportImportCard`),点「开始入库」前端校验(`strategy-components/lib/agentfx-report-schema.ts`,14 类 + contentJson 合法 JSON + **\u 转义归一化还原为汉字**,与技能脚本同规则)后 `importTaskReport`(`strategy-components/api/task-reports.ts`)POST 导入接口整体替换;任务已有详情**不抑制**卡片(入库即整体替换,卡片文案说明覆盖语义),导入成功按 thread 记 sessionStorage(刷新不重复询问)、「暂不入库」为会话内记忆;(b) **入库技能** `task-report-import`(seeder 一并复制到 `skills/public/`,public 类技能 extensions_config 缺省即启用)—— 用户聊天里说「入库」时智能体按 SKILL.md 用 bash 跑 `scripts/task_report_import.py`(纯标准库:同样的校验规则 + 转义归一化;**默认关闭 SSL 证书校验** `ssl._create_unverified_context` + 忽略代理,适配内网自签证书;鉴权 `--token`/env `AGENTFX_IMPORT_TOKEN`→`DEERFLOW_AUTH_TOKEN`→`TOOLS_TOKEN` 优先,缺省经公共端点 `POST /api/parallel-agents/auth/token` 以 `agentfx-import` 用户现签 token——内网既有鉴权旁路;gateway 地址 env `AGENTFX_GATEWAY_URL` 或 `http://127.0.0.1:{DEER_FLOW_GATEWAY_PORT}`);`--strict` 可要求 14 类齐全,默认允许部分导入并在 stdout JSON 的 `missing_categories` 里列缺。入库成功后任务 TaskCOP 状态自动置 25(已完成分析)。**入库成功通知宿主**(iframe 嵌入场景):两条路径成功后都会 `window.top.postMessage({source: "magent-web", type: "Line truncated
+2 -4
View File
@@ -82,7 +82,7 @@ The frontend (`frontend-web/`) is a React 19 + Vite SPA:
- **Routing**: React Router v7; top-level routes in `src/pages/PageRoutes.tsx`, workspace sub-routes in `src/pages/WorkspaceRoutes.tsx`
- **Pages**: `ChatPage` (thread chat), `AgentChatPage` (custom agent chat), `AgentsPage`/`NewAgentPage` (agent management), `ScheduledTasksPage`/`ScheduledTaskRunDetailPage` (scheduled tasks), `LightAppManagementPage`/`LightAppListPage`/`LightAppIframeView` (轻应用中心 — register/list/embed mini-apps)
- **普通问答地图可视化**: shared `MarkdownContent` recognizes only dedicated `map-json` fences and otherwise preserves the legacy Markdown/Streamdown path byte-for-byte. `components/workspace/visualizations/` validates the bounded map contract with Zod, lazy-loads MapLibre, and provides loading/error/text fallbacks so malformed or unreachable maps never blank the message. The lead-agent prompt emits `map-json` only when the user explicitly asks for a map; flowcharts and other graphics continue through the existing Markdown/Mermaid path. The raster tile template comes from the single post-build setting `runtime-config.js` → `VITE_MAP_TILE_URL` (Google by default); replace it with the intranet `{z}/{x}/{y}` endpoint for disconnected deployments.
- **HTML 成品离线绘图运行时**: 新生成的 `.html` 源码直接引用 Gateway `/api/public/html-runtime/` 下的浏览器版 `g6.min.js`、`echarts.min.js`、`leaflet.js/css` 和 `deerflow-runtime.js`;文件随后台源码存放于 `vendor/html-runtime/`,不再依赖前端 Vite/node_modules 产物或公网 CDN。`config.yaml -> html_runtime.base_url` 是写入新 HTML 的浏览器可访问绝对地址,`html_runtime.map_tile_url` 是初始化脚本读取的瓦片模板。用户上传的栅格图若要作为页面背景,使用同一 Gateway 源下的签名地址 `/api/public/html-images/{token}` 写入 `background-image`。流程图使用 `data-df-flow` + G6(不用 Mermaid),图表使用 `data-df-chart`,地图使用 Leaflet `data-df-map`。普通问答保持独立:消息列表 `map-json` 继续由前端原逻辑渲染,普通流程图/图表仍走 Markdown/Mermaid。
- **HTML 成品离线绘图运行时**: 新生成的 `.html` 源码直接引用 Gateway `/api/public/html-runtime/` 下的浏览器版 `g6.min.js`、`echarts.min.js`、`leaflet.js/css` 和 `deerflow-runtime.js`;文件随后台源码存放于 `vendor/html-runtime/`,不再依赖前端 Vite/node_modules 产物或公网 CDN。`config.yaml -> html_runtime.base_url` 是写入新 HTML 的浏览器可访问绝对地址,`html_runtime.map_tile_url` 是初始化脚本读取的瓦片模板。流程图使用 `data-df-flow` + G6(不用 Mermaid),图表使用 `data-df-chart`,地图使用 Leaflet `data-df-map`。普通问答保持独立:消息列表 `map-json` 继续由前端原逻辑渲染,普通流程图/图表仍走 Markdown/Mermaid。
- **定时任务「JSON → HTML 模板填充」(模板数据转换器)**: a third scheduled-task execution mode. In the create/edit dialog (`ScheduledTasksPage.tsx`), selecting the built-in agent **「模板数据转换器」** (`execution_agent_name === "template-json-builder"`, `TEMPLATE_BUILDER_AGENT_ID`) reveals a 「HTML模板」 select (`useHtmlTemplates` → `GET /api/scheduled-tasks/html-templates`) + a **.json 上传** button (reads the file's text into the prompt box) and **hides** the 必须生成 HTML/Markdown switches (this mode always outputs HTML). The chosen template persists as `execution_context.template_config.template_id` (`TemplateFillConfig` in `core/scheduled-tasks/types.ts`). At run time the backend converts the source JSON (the task prompt) into that template's `DATA` structure, validates (retry-on-fail), fills the template, and stores an HTML page previewable via the existing run-detail HTML preview. The source can be **pure JSON, plain text, or text-with-embedded-JSON** — the backend pre-extracts any embedded JSON and the agent's `SOUL.md` maps it (or the plain text's semantics) to the template's schema skeleton. **Chat-page debug entry (only this agent's `AgentChatPage`)**: when `agent_id === "template-json-builder"`, the chat header shows a 「页面模板」 select + a 「渲染预览」 button — after a normal Q&A run, the button takes the **latest AI reply**, POSTs it to `POST /api/scheduled-tasks/template-fill/render` (`renderTemplateFill`), and pops a dialog rendering the filled HTML in a `sandbox="allow-scripts"` iframe plus the structure-validation status/errors/gaps — for debugging the agent's conversion effect without creating a scheduled task. Gated strictly on the agent id, so other agents' chat pages are untouched. See the backend CLAUDE.md「Template-fill mode」for the engine (`deerflow/runtime/scheduler/template_fill.py`), agent seed, dispatch, and the render API.
- **AI 写作·对话版(对话驱动写作台)**: a **parallel new entry** beside the classic AI-writing page (classic page/routes untouched) — route `/page/canvas/ai-writing-chat` (`OpenCanvasRoutes.tsx`), sidebar 「问答管理 → 课题研究(对话版)」. Page `open-canvas/pages/AIWritingChatPage.tsx` fully **reuses the engine** (`AIWritingContext` state machine + LangGraph `useStream`, `AIWritingHistoryProvider`, right-side `AIWritingDraftPanel`) but replaces the presentation: left = `components/ai-writing-chat/WritingChatPanel.tsx` (timeline + **button-only intervention cards** `ChatInterventionCards.tsx` — the five pause cards copied from `InterventionCard.tsx` with all inline textareas removed, confirm/action buttons kept — plus a bottom **unified smart composer**). Free text goes through two-level intent resolution (`open-canvas/api/ai-writing-intent.ts`): deterministic short-phrase fast path (确认/继续/重新搜索/重写大纲…; high-cost actions never fast-pathed) then `POST /api/ai-writing/sessions/{id}/intent` — the backend reads the graph checkpoint (authoritative pause point from the pending interrupt) and routes via `deerflow/agents/ai_writing/intent_router.py` (LLM + strict per-pause action whitelist aligned to the graph's real resume actions, confidence gates: finalize/force_finalize/覆盖式 re_search need ≥0.85 else clarify, payload key-whitelist cleaning). Results map to `submitIntervention`/control (暂停/继续/后台挂起)/QA bypass (`answer` rendered as a chat bubble, never touches graph state)/clarify (amber follow-up bubble with multi-turn context). **Two-state layout**: idle (未开始写作) renders the **classic setup experience unchanged** — `WritingSetupChat` + collapsible `AIWritingPanel` form under `WritingFormProvider` (same as `AIWritingPage`'s idle branch); once writing starts (or history view opens) it switches to the chat workbench. **Unified chronological feed** (`ChatFlowTimeline.tsx`): intent-layer chat bubbles are interleaved INTO the progress-event timeline by anchor (= `progressEvents.length` at message creation), so events triggered by a user message render **below** it (Google-AI-Studio-style single stream, not timeline-above/chat-below); composer-driven interventions suppress the duplicate 「我的要求」card (`suppressedRequirementIndices`). **素材不足自动续跑** only at `material_confirm` (the only pause the graph supports re-search from): needResearch caches the payload as a pending intent, submits `re_search + userQuery`, and auto-submits the pending intent when the new material-confirm pause arrives (cancellable pill). Stage chips + per-stage placeholder + 「当前交互对象」status badge. Backend tests `tests/test_ai_writing_intent.py`. Plan doc: `frontend-web/docs/ai-writing-对话驱动写作台-实现方案.md`.
- **策略优选**: route `/page/strategy/qa/strategy-selection`, sidebar 「问答管理 → 策略优选」. The standalone `src/strategy-selection/` workbench has two horizontal split stages: Step 1 keeps intent-understanding conversation cards on the left and an editable task draft plus angle selection on the right; Step 2 keeps multiplexed parallel strategy cards and automatic judging on the left while the right stays dedicated to the selected-strategy basket and final Markdown synthesis. It consumes the existing `POST /api/parallel-agents/run/stream` protocol, isolates output by stable agent id, supports expanded per-agent dialogs, user selection, Markdown editing/copy/download, and shared server-side DOCX export. A clearly marked neutral Taiwan-Strait risk-management demo is loaded by default for offline UI acceptance. Administrators can edit the SOUL and skills of the nine built-in functional agents through the page dialog; the backend seeds `strategy-selection-{intent,angle-*,judge,solution}` only when their directories are missing, preserving later admin changes. Pure parsing/SSE tests live in `src/strategy-selection/lib.test.ts`; backend seed tests live in `tests/test_strategy_selection_seed.py`.
@@ -93,9 +93,7 @@ The frontend (`frontend-web/`) is a React 19 + Vite SPA:
- **技能地址管理 (Skill Address Management, admin-only)**: 扫描运行中的技能(`skills/{public,custom}` 下所有 `.md`/`.py`)里的 **http(s) URL 与 IP/IP:端口**,按唯一地址聚合全部出现位置(跨 .md/.py),支持**批量替换**(如把 UAT 地址一次性改成生产)。主体抽成可复用组件 `SkillAddressesPanel`(`pages/SkillAddressesPage.tsx` 导出,默认导出 `SkillAddressesPage` 仍保留旧路由 `/page/strategy/admin/skill-addresses` 作直链回退),**作为「技能地址管理」标签页嵌入管理员「技能管理」页 `pages/AdminSkillsPage.tsx`**(该页加 Tabs:「技能列表」+「技能地址管理」;入口在「设置和更多」下拉的「技能管理」`workspace-nav-menu.tsx` → `/page/workspace/admin/skills`,不再单列于 `components/page-sidebar.tsx` 左下角设置下拉):打开自动扫描并带**进度条**(扫描逐技能 / 应用逐文件 X/N,应对 150+ 技能),URL/IP 类型过滤 + 搜索 + 「片段批量套用」(如所有 `uat.4.cn` → `prod.4.cn`)、每地址「替换为」输入框(可展开看 `file:line` 片段)、内联**预览**、**应用**、**多关键词检索**(空格分隔全部命中),以及**修改记录**面板——每次应用生成一条记录(显示时间/改了哪些地址 from→to/文件数/处数),可**针对单次记录回退**(二次确认)。client + NDJSON 流式解析在 `strategy-components/api/skill-addresses.ts`。后端 `/api/skill-addresses`(**仅管理员**):所有文件 IO 走 `asyncio.to_thread` 不阻塞事件循环;`GET /scan`(+`/scan/stream`)、`POST /preview`、`POST /apply`(+`/apply/stream`)、`GET /backups`、`POST /rollback/{id}`;**子串安全替换**(基于 token span,不会误伤子串)、`expected_total` 乐观锁(409)、写前自动磁盘备份到 `{skills_root}/.address-edits/`(同时写一份 `{id}.manifest.json` 记录本次替换明细,供修改记录展示)、应用后刷新技能系统提示缓存。纯引擎 `deerflow/skills/address_scan.py`,router `app/gateway/routers/skill_addresses.py`,tests `tests/test_skill_addresses.py`。范围仅运行中技能,不动 `deploy/minimal/skills/`。
- **按钮管理 (Task Button Management, admin-only)**: configures the **可配置跳转按钮** rendered in the left task panel of the task deep-link workspaces (rwfx / 3qfx / xdfx, see `TaskFxWorkspace`). Each button = `{business, label, linkType, target, appendTaskId, idParam, idKind, openMode, loginParams, appendAuth, authTokenParam, authNameParam, enabled, sortOrder}`; `linkType` is `url` (外链 `window.open`, optional append of `?{idParam}={id}` — **`idParam` is the editable query-param name**, e.g. `id`/`task_id`), `business` (内部切换到另一业务, reuses `resolveTaskDeeplinkTarget`, always task id), or `purpose` (弹出当前任务的「任务目的」表格 via the shared `TaskPurposeDialog`, no target — configurable for any page incl. xdfx). **`host`(宿主路由)** asks the embedding parent to navigate: `runTaskButton` sends `window.parent.postMessage({ type:'HOST_NAVIGATE', path, queryParams:{ [idParam]: Number(taskId) } }, hostOrigin)` — `target` is the host route (e.g. `/task/item-aiceh/step-analysis-audience`), `appendTaskId`/`idParam` become numeric `queryParams` (task id only), origin from `runtime-config.js` `VITE_HOST_NAVIGATE_ORIGIN` (else ancestorOrigins/referrer; never `*`). Independent-tab clicks toast and do nothing. **`url` buttons support two independent, coexisting login-append mechanisms**: (1) **`loginParams` (追加登录参数, like 应用管理/Light App Center)** — a list of `{key, source, customValue}` resolved at click time: `runTaskButton` reads `userInfo` (via `readUserInfo` from `strategy-components/lib/light-app`, embed-isolated through `authStorage`) and appends `?{key}={value}` for each (`source` = a userInfo field such as `accessToken`/`yUserId`, or `other` → literal `customValue`); empty list = nothing appended. Reuses `LOGIN_SOURCE_OPTIONS` from light-app; stored as JSON column `task_buttons.login_params_json` (`PortableJSON`, migration `20260625_01`). (2) **`appendAuth` (追加登录态)** — appends `?{authTokenParam}={token1}&{authNameParam}={username}` (default param names `token`/`username`) so the跳转目标外部系统 can identify the current user — e.g. `…/action/sentiment?token=<JWT>&username=lizhaoxing`. **Gated on token login**: `token1` = the `?authToken=` used by token-exchange login; `username` = the raw login name the backend resolved from `getTokenInfo`. Both are stashed at login by `persistLoginCredentials` into `login.token1`/`login.username` (`core/auth/login-credentials.ts`, scoped via [[scoped-storage]] so嵌入/独立会话隔离 + 随独立会话迁移). Only token login writes them → a non-token-login session has no `token1`, so `runTaskButton` silently skips the auth append (the jump still works, just without those two params). The frontend reads `username` straight from the new `UsernameLoginResponse.username` field (the stored email local-part is lossy — lowercased/normalized — so not used), **not** by decoding the JWT. Stored as columns `task_buttons.{append_auth, auth_token_param, auth_name_param}` (migration `20260625_02`). The admin page renders both editors for `url` buttons (loginParams 虚线框 + 追加登录态 switch). **`idKind` (`task`/`action`) only matters for xdfx**: its deep-link `?taskId=` is an 行动id and the 任务id is resolved at login (`fetchTaskIdFromAction`) — `TaskContext` now also stashes the raw `actionId`, so a url button can append either (default `task`). Page `TaskButtonsPage.tsx` (route `/page/strategy/admin/task-buttons`, **admin-gated**, entry「按钮管理」in the bottom-left settings dropdown of `components/page-sidebar.tsx`, both full + collapsed modes) has per-business tabs, edits name/type/target/启停/排序/增删, saves the **whole set atomically** (replace-all), plus 「导入默认」 to merge code-seed defaults. **Seed/fallback** (like 敏感词管理): only when the whole table is empty (fresh deploy, never saved) do the workspace + page fall back to `defaultTaskButtons(cfg)` — rwfx's url buttons (编辑/上一步/下一步/3q详情) built from the **live** `/api/public/config/task-deeplink` plus cross-business switch buttons for **all three** businesses (each switches to the other two — rwfx→三情/行动, 3qfx→任务/行动, xdfx→任务/三情). Once saved, the store is the sole source of truth. **Bottom 快捷跳转 bar groups by prev/next**: `TaskJumpBar` renders only「上一步/下一步」-type buttons in the bottom bar — a `prev` group (id 含 `prev` 或文案「上一步」, 描边次要样式 + ←图标) rendered **左侧**, then a `next` group (id 含 `next` 或文案「下一步」, 实心主色) on the **右侧** (container `justify-end`); everything else goes to the right-edge floating menu. The default 上一步 button (`rwfx-prev`, `url`, target = `DASHBOARD_AGENT_ROUTE` `/page/strategy/dashboard-agent`, `appendTaskId` + `idParam=taskId` → `?taskId=任务id`, `openMode=self`) 默认指向**应用内**「大屏绘制」Line truncated
- **实时并发监控 (Concurrency / System-Pressure Monitor, admin-only)**: a live panel mounted at the **top of the admin 排行榜 page** (`components/workspace/admin/concurrency-monitor.tsx` `ConcurrencyMonitorPanel`, rendered in `pages/AdminUserLeaderboardPage.tsx`) showing **当前并发的大模型调用数 + 列表(用户/智能体/类型/已运行时长)**, each row with a 「停止」button (and a 「全部停止」) that **truly aborts** that run's in-flight model stream via `RunManager.cancel` (`POST /api/admin/active-runs/{run_id}/cancel`) — to relieve pressure when 使用人数过多. Two line charts (minute/hour toggle): **并发量折线图** (peak/avg, `GET /api/admin/active-runs/concurrency`, fed by a lightweight background sampler into `concurrency_samples`) and **大模型出字速度折线图** (tokens/sec, `GET /api/admin/active-runs/token-speed`, aggregated from `llm_call_metrics`) so a dip pinpoints where the bottleneck is. A **「后台采样」Switch** (`system_settings.json → concurrency_monitor.enabled`, **default off / opt-in**, `GET|PUT /api/admin/active-runs/settings`) turns the background sampling on/off **at runtime, no restart** (the live concurrency count + 「停止」 work even while sampling is off — only the 并发量 history chart needs it on); everything is designed to **never impact production** (one tiny INSERT/15s, retention-purged, best-effort). Client/hooks: `core/admin/active-runs.ts` + `core/admin/hooks.ts` (`useActiveRuns`/`useConcurrencySeries`/`useTokenSpeedSeries`/`useCancel*`/`useMonitorSettings`). See the backend CLAUDE.md「Admin Concurrency Monitor」.
- **会话冲突与模型工具流恢复**: when a user submits a new question while the previous turn is still streaming, the backend's `RunManager.create_or_reject` rejects with HTTP 409 (`services.py` returns the Chinese detail「当前对话还在生成回答…」). `core/threads/hooks.ts` detects the conflict and routes it through `confirmOrRejoin`. Run-creation SSE responses expose `Content-Location` plus the SDK `Location` reconnect endpoint; `core/api/api-client.ts` records the last consumed event id, so an in-page rejoin resumes after that cursor instead of replaying tool arguments from `-1`. `write_file` argument updates carried by `messages-tuple` count as business activity. A known active run is probed only after 90 seconds without a business frame; the watchdog hides `lg:stream`, stops only the old browser reader, and rejoins without cancelling the backend run. Clean EOF, transport errors, 409 and watchdog recovery share one single-flight Promise to prevent duplicate joins/finalization. The backend `PatchedChatOpenAI` separately normalizes confirmed cumulative argument snapshots and bounded compatible response shapes while preserving standard deltas; its content-free diagnostics never log prompts, arguments or file bodies.
- **React #185 与流式刷新保护**: every direct LangGraph `useStream` surface (main/agent chat, AI writing, Canvas and Studio notebook) uses shared `STREAM_RENDER_BATCHING = true`. The installed SDK implements numeric `throttle: 16` as a trailing debounce, which can indefinitely postpone UI updates during a continuous fast stream; `true` retains asynchronous next-task batching without requiring 16ms silence. `stream-error-classification.ts` detects `Maximum update depth exceeded` / production `#185` through bounded, cycle-safe wrappers. Main chat filters the SDK's stored error and duplicate submit rejection; `react-ui-error.ts` gives each send at most one automatic UI recovery, then pauses rejoin without cancelling the server run. Token activity must not reset that budget. The top-level `ReactUiErrorBoundary` catches only this render/commit error, shows a static friendly reload panel, and never automatically remounts the failing tree. Other errors are not swallowed. Shared toasts are deduplicated for 30 seconds; diagnostics retain error type, recovery phase, thread/run identifiers and component stack but never message/tool content. Real SDK SSE replay covers partial reasoning and write_file Markdown before generation ends; the browser boundary check triggers a real production React layout-effect loop and requires manual reload to recover. These safeguards do not prove the unknown production component loop is fixed.
- **流式游标作用域**: resumable cursors belong to the current SDK message accumulator, not a module-global map. `createStreamAPIClient` isolates same-reader recovery; newly mounted chats and real thread switches must replay the retained prefix instead of borrowing another reader's consumed position. Clearing replaces the cursor map so late old-reader events cannot pollute the new scope. The shared `getAPIClient` does not rewrite replay-from-start cursors. `stream-cursor-replay.test.ts` uses the real SDK to protect against both duplicate tool arguments on reconnect and missing prefixes on reopening.
- **会话冲突 409 中文化**: when a user submits a new question while the previous turn is still streaming, the backend's `RunManager.create_or_reject` rejects with HTTP 409 (`services.py` now returns a **Chinese** detail「当前对话还在生成回答…」). `core/threads/hooks.ts` `onError` detects the conflict (`isActiveRunConflictError`: 409 / "already has an active run" / the Chinese text). A premature SSE close (SDK treats it as success and restores the send button while the backend run is still occupying the thread) is recovered by `confirmOrRejoin`: hold the stop button, `joinStream` the live run, and on 409 auto-reconnect instead of a fake AI bubble. `sse_consumer` no longer ends a resumable (`on_disconnect=continue`) stream on a false-positive `is_disconnected()`.
- **State**: TanStack Query for server state, context providers (`SubtasksProvider`, `ArtifactsProvider`, `PromptInputProvider`) scoped to `WorkspaceRoutes`
- **LLM streaming**: `@langchain/langgraph-sdk` streams messages from the backend via SSE
- **UI**: Radix UI primitives + TailwindCSS v4 + shadcn-style components in `src/components/ui/`
@@ -1,188 +0,0 @@
# 报告协作工作台 — 交互重设计方案(v2)
> 日期:2026-09-07
> 状态:**待确认**(确认后按 §7 分期实施)
> 取代:现行「规则澄清 + 三张模板方案卡 + 画布为主」的交互
> 原则:回到最初设计 —— **协调者智能体全程与用户对话的主线**
---
## 1. 设计目标与总体形态
用户视角只有一条主线:**和一个规划师智能体对话 → 它摸清意图并规划工作流 → 确认后执行、过程在流程图上可见 → 随时插话干预、指定智能体重跑 → 最终成稿、继续对话式修改**。
```
┌─────────────────────────────────────────────────────────┐
│ 阶段1 计划模式 阶段2/3 执行+干预 阶段4 成稿 │
│ ┌───────────┐ ┌───────────┐ ┌──────────┐ │
│ │ 规划师对话 │ 确认 │ 聊天时间线 │ 审稿过 │ 对话改稿 │ │
│ │ 需求摘要卡 │ ─────→ │ +成员Tab │ ─────→ │ 版本/diff│ │
│ │ 工作流卡 │ 冻结 │ +流程图动画│ 报告卡 │ 上游重跑 │ │
│ └───────────┘ └───────────┘ └──────────┘ │
│ ↑ 回到计划模式(replan)随时可触发 ↑ │
└─────────────────────────────────────────────────────────┘
```
与现行的核心差异:
| 维度 | 现行(做偏的) | v2 |
|------|----------------|-----|
| 需求澄清 | 规则模板问句秒回 | 规划师智能体(LLM)领域化提问 |
| 工作流来源 | 3 张确定性模板 | LLM 按意图生成自定义 DAG,对话迭代修改 |
| 执行展示 | 画布为主、聊天为辅 | **聊天时间线为主**(成员 Tab 切换保留),**执行状态在流程图上动画呈现** |
| 干预 | 命令确认卡体系 | 输入框常开 → 协调者智能体分类;支持**指定智能体重跑** |
| 报告修改 | 改写候选(纯文字层) | 意图分流:润色走改写;**事实性问题触发上游节点重跑** |
---
## 2. 阶段 1:计划模式 — 需求梳理与工作流规划
### 2.1 计划模式状态
- 用户发出第一条需求消息起进入**计划模式**,Header 显示徽章「📋 计划模式」,输入框提示语切换为「梳理需求中,你可以随时补充或纠正…」。
- 计划模式在**工作流确认冻结**时结束;执行期大改可通过 replan 回到计划模式(见 §5.4)。
### 2.2 规划师对话(LLM,替换现行规则路由)
- 必须调用独立内置智能体 `report-collaboration-intent` 的真实 LangGraph thread,并原样消费 `messages-tuple` SSE;禁止用 `ainvoke()` 等待完整 JSON 后再包装成一话。
- 流式正文、思考内容和工具步骤直接进入工作台现有 `MessageList`,与普通智能体问答采用同一套步骤条 / Reasoning 展示。
- 模型:`report_collaboration.planner_model`(回退 `coordinator_model` → 默认模型,复用现有 model_resolver 冻结机制)。
- 提问是领域化的:写市场分析就问「关注整车还是供应链 / 要不要竞品对比 / 给谁看 / 篇幅」,而非固定模板问句。
- 澄清轮次上限沿用 `max_clarification_rounds`;用户随时可以说「直接开始」按默认假设推进。
### 2.3 需求摘要卡
信息足够后,规划师在对话中输出一张**结构化需求摘要卡**(业务卡插槽渲染):主题 / 目的 / 读者 / 角度清单 / 篇幅与重点 / 默认假设。用户逐项看,可在对话里继续改(「读者改成投资人」→ 卡片更新出新版)。
### 2.4 工作流生成与迭代
- 规划师判断意图信息足够后,立即按已确认意图自动生成**一份**工作流方案(不是三选一),不再要求用户额外点击“确认意图/生成方案”;方案以工作流卡(成员构成、各节点使命、预计时长/成本)+ 右侧流程图预览呈现。
- 生成约束(保证可执行):**节点类型受词表约束** — `research / verify / analyze / write / review`;自由的是结构(几条线、并行还是串行、核验深度)与每个节点的使命/角度/工具。
- 对话式修改:「把价格策略单独拆一条线」「加一个政策风险分析」→ 规划师修订后出新版工作流卡(带变更说明),再确认。
- 「开始执行」→ 冻结需求 + 工作流(含模型/预算快照,沿用现有 freeze 机制)。
---
## 3. 阶段 2:执行 — 过程在流程图上可见
### 3.1 流程图动画规格(执行状态的可视化主载体)
节点状态 → 样式(`ReportFlowCanvas` / `ReportFlowNode`,状态源 `selectNodeStatusMap`,事件源 `node.status.changed` SSE):
| 状态 | 节点样式 | 连入边 |
|------|----------|--------|
| planned / queued | 灰色常态 | 静态 |
| **running** | 主色描边 + **呼吸脉冲动画**(ring)+ 角标 spinner | **流动动画**(@xyflow 内置 `animated: true` 的 dash 流动) |
| **completed** | 绿色 + ✓ 角标,常驻 | 恢复静态实线 |
| failed | 红色 + 错误角标 | 红色虚线 |
| awaiting_input | 橙色 + ?角标 | 橙色静态 |
| interrupted / superseded | 半透明降级 | 灰 |
- 语义:**边流动 = 数据正在流入该节点**(该节点执行中);节点完成即停动画换完成样式。
- 实现成本:@xyflow 原生支持 animated 边与自定义节点 className,纯 CSS 补呼吸动画即可,无需新依赖。
### 3.2 聊天区(保留现有 Tab 切换)
- 并行成员沿用 **AgentStageSelector Tab 切换**(维持现状,不改交错时间线)。
- 每个 Tab 内是该成员的完整流式输出:思考、工具调用卡、检索过程、正文 —— 与普通智能体问答同观感(message-adapter 已具备映射能力)。
- 协调者播报(「研究线 A 完成,核心发现 X,开始交叉核验」)进入总时间线 Tab。
---
## 4. 阶段 3:干预 — 对话即干预 + 指定重跑
### 4.1 输入框常开,协调者智能体分流
执行期输入框永远可用,所有输入先到协调者(LLM 分类,规则高精度直判兜底——复用 RC-BE-014 IntentRouter 骨架,把「规则优先」反转为「LLM 优先 + 规则快路径」):
| 用户意图 | 协调者行为 | 生效时机 |
|----------|-----------|----------|
| 提问(「查到什么了?」) | 直接回答 | 立即,不打断 |
| 修正方向(「重点看下沉市场」) | 小改:在安全点注入 overlay,并回复说明 | 下个安全点 |
| **指定重跑**(见 §4.2) | 出确认卡 → 重开节点 attempt | 确认后 |
| 大改(砍线/加线) | 提议 replan → 回计划模式 | 用户确认 |
| 停止 | 直接取消 | 立即 |
### 4.2 指定智能体重跑(新增核心交互)
**场景**:用户发现某节点传给下游的信息不对(如研究线 B 的结论有误)。
两个入口,同一后端动作:
1. **对话**:「研究线 B 的结果不对,重新查,重点看价格战」→ 协调者解析出 `node_id` + 新指令;
2. **画布**:点节点 → 抽屉(NodeInspectorDrawer)加「↻ 重新执行」按钮。
**级联规则**(复用并补全 ledger 的 targeted rework):
```
重跑节点 N(attempt+1,带用户新指令作为 mission overlay)
→ N 完成 → 所有直接/间接依赖 N 产物的下游节点标记 superseded
→ 按 DAG 依赖序逐波重跑(边动画重新流动,用户全程可见)
→ 受影响章节重新生成
```
- 确认卡必须展示**影响面**:「将级联重跑 核验B / 分析 / 写作 共 3 个节点,预计 +8 分钟」。
- 成本保护:级联重跑计入 run 预算(现有 budget 机制),预算不足时明确报因。
---
## 5. 阶段 4:报告成稿与对话式修改
### 5.1 成稿
审稿通过 → 报告卡出现在时间线(点开 ReportPreviewDialog 全文),协调者播报总结(各线核心发现 → 结论如何形成)。
### 5.2 修改意图分流(协调者 LLM 判定)
| 用户说 | 判定 | 动作 |
|--------|------|------|
| 「把第二章结论写得更笃定」 | 文字润色 | 改写候选(现有 rewrite API)→ 对比预览 → apply → 新版本 |
| 「这个数据不对 / 重新收集一下」 | **事实性问题** | 定位来源节点 → **触发该节点重跑(可带新角度)→ 级联 §4.2 → 受影响章节重生成 → 新版本** |
| 「再从供应链角度补一节」 | 结构性新增 | replan:回计划模式改工作流(只增不删已完成部分) |
| 「恢复到上一版」 | 版本回退 | 现有 restore API |
- 版本链:每次 apply / restore / 级联重跑产出均产生新 head,历史完整保留(现有机制)。
- 修改对话里协调者必须先**复述理解**(「你是想让研究线 B 换个角度重查,然后重写第三章,对吗?」)再执行,避免误触发昂贵的级联。
---
## 6. 工程改造清单
### 6.1 保留(本次联调已验证)
- 持久化 13 张表 + durable SSE + `after_seq` 断线续传;幂等键 / 乐观锁 / 预算框架。
- MessageList 复用链路(message-adapter → LangGraph Message → 业务卡插槽)。
- AgentStageSelector Tab、commands 安全点骨架(RC-BE-014)、报告版本三件套(RC-BE-015)、前端 hooks/reducer/selectors 主体。
- 「清空历史」「生成候选方案」等本次新增入口。
### 6.2 后端重做 / 新建
| 项 | 说明 |
|----|------|
| 规划师智能体 | LLM 多轮澄清(替换 `requirement/intent_router.py` 规则路由)+ 需求摘要结构化 + **工作流 LLM 生成**(受 §2.4 词表约束,替换 `planning/controller.py` 三模板)+ 对话式工作流修订 |
| 协调者智能体升级 | 干预分类 LLM 优先;修改意图分流(§5.2);执行前复述确认 |
| 指定重跑 + 级联 | ledger targeted rework 补全级联 superseded/重跑波次;确认卡带影响面计算 |
| AgentScope 适配器修复 | `count_tokens` 协议缺失(上下文压缩必崩);attempt 耗尽终态化(防僵尸 run) |
| 事件补齐 | 边流动所需的节点状态事件已有;补「级联影响预告」事件 |
### 6.3 前端重做 / 新建
| 项 | 说明 |
|----|------|
| 计划模式 UI | Header 徽章、composer 提示切换、需求摘要卡、工作流卡(替换现三张模板卡) |
| 流程图动画 | running 节点呼吸动画 + 入边 `animated`、completed ✓ 样式、级联重跑时边动画重流(§3.1) |
| 节点抽屉 | 加「重新执行」按钮 → 确认卡 |
| 干预交互 | 执行期输入框常开;意图确认卡(含影响面);修改对话复述确认 |
| 布局 | 聊天为主、画布为辅的默认比例微调(不动整体两栏结构) |
---
## 7. 实施分期
| 期 | 内容 | 验收 |
|----|------|------|
| **P0 地基** | AgentScope `count_tokens` 修复;attempt 耗尽终态化;级联重跑的 ledger 补全 | 执行阶段不崩、无僵尸 run、单节点重跑级联正确(后端测试) |
| **P1 计划模式 + 执行可视化** | 规划师 LLM 对话、需求摘要卡、工作流 LLM 生成与迭代、计划模式 UI、流程图动画 | 从新会话到确认工作流全程对话完成;执行时动画正确随状态流转 |
| **P2 干预 + 成稿修改** | 协调者 LLM 分类、指定重跑(两入口 + 影响面确认卡)、报告修改意图分流、上游级联重跑 | 四类干预各自走通;「数据不对→重跑→新章节→新版本」全链路 |
每期结束跑 RC 全量测试(当前基线 233 通过)+ 前端 26 单测,不引入对其他模块的影响。
@@ -229,27 +229,23 @@ sequenceDiagram
```http
POST /api/report-collaboration/sessions
POST /api/intent/init
POST /api/intent/stream
POST /api/report-collaboration/sessions/{sessionId}/intent-turns
POST /api/report-collaboration/sessions/{sessionId}/messages
Content-Type: application/json
{ "text": "请写一份…", "target_node_id": null, "agent_run_id": null }
```
- 报告页面固定调用内置 `report-collaboration-intent` 智能体;`/api/intent/stream` 原样透传 LangGraph `messages-tuple`,不是等待模型完成后包装响应。
- 正文 token、provider reasoning 和工具调用步骤实时写入当前 `MessageList` 气泡;终态后 `/intent-turns` 只负责持久化镜像与状态交接,不再调用模型识别意图。
- 旧 `/sessions/{sessionId}/messages` 在 `empty/clarifying` 阶段返回 `409 USE_STREAMING_INTENT`,防止退回阻塞式 `ainvoke` 路径。
- `useReportCollaborationSession.send()`:当 `session.status` 不是 `running` / `awaiting_input` / `reviewing` 时走 `sendMessage`。
- 会话状态:`empty` → `clarifying` → `planning` → `proposal_ready`。
- 澄清问题以 `CollaborationMessage` 进入时间线;业务卡通过 `MessageList` 的 `businessCardSlot` 渲染(`additional_kwargs.report_collaboration_card`)。
- 意图智能体输出 `INTENT_READY` 后,`POST /intent-turns` 自动创建并完成 `plan_request`;前端无需再展示“确认意图”或“生成候选方案”按钮。
### 5.3 阶段 2:候选方案
```http
# 正常路径:由最后一轮 POST /messages 自动触发规划
POST /api/report-collaboration/sessions/{sessionId}/plan-requests
POST /api/report-collaboration/sessions/{sessionId}/plans/{planId}/select
```
- `POST /plan-requests` 仅保留给“重新生成”与兼容调用,不是首次规划的必经步骤。
- 规划师尚未判定 `ready` 时直接调用该兼容接口会返回 `422 REQUIREMENT_NOT_READY`,防止跳过意图确认。
- **预览方案**(`previewPlanId`):纯前端,不调 API。
- **采用方案**:`select` 写 `selected_plan_id`,**不**创建 run。
- 409:方案 revision 过期 → 前端 `refreshSnapshot`,提示用户重选。
@@ -1,354 +0,0 @@
# 技能并发与流式修复:配置、前端包与验收说明
日期:2026-09-27。
本说明对应本次提交的修改,包含模型流式兼容与恢复、React #185 错误处理和已完成的最小技能示例,
以及可选的技能视图复用、版本缓存、模型计时日志队列和 Gateway 线程池扩容。
部署前通过 `git log -1` 核对代码提交;仅修改配置或替换旧包不能确认已部署本次修复。
## 1. 先确认需要更新什么
- **后台代码也要更新**:四个新开关需要新版后台读取。只换前端 dist 或只把字段写进旧版 config.yaml 不会实现后台优化。
- **前端**:使用本说明末尾的 ZIP,里面是完整 `dist/`,不是源码或 node_modules。
- **默认不启用优化**:仓库两份 config.yaml 的四个新开关均为 `false`。只有主动改为 `true` 才启用对应项。
- 开启线程池开关后可将上限调整为 100,但不提高模型服务商配额、不启用多 worker。
## 2. .env 需要修改哪些项
后台启动所使用的 `.env` 保持或修改为:
```dotenv
# Gateway 进程数,不是线程池大小;当前内存流/运行管理器必须单进程。
GATEWAY_WORKERS=1
# 默认就是 0;显式写 0 可防止误用不安全的多进程覆盖开关。
DEERFLOW_ALLOW_UNSAFE_MULTIWORKER=0
# Gateway asyncio 线程池上限;还必须打开下一节的 asyncio_thread_pool_enabled。
DEER_FLOW_ASYNCIO_THREAD_POOL_SIZE=100
```
适用于已更新的 `scripts/start_backend-online.sh` 和 `offline-backend-20260512/start_backend.sh`。
若通过自定义服务直接运行 Uvicorn,也应确认实际命令是单 worker;仅修改 .env 不会改变硬编码的启动命令。
启动环境中已导出的同名变量可能覆盖 .env,需一并核对。
前面三个技能/日志优化没有独立环境变量,它们配置在下一节的 `config.yaml`。
线程池上限变量现已真正接入;修改 .env 后必须重新启动后台,Docker 应通过现有启动脚本重新创建容器,
单纯 `docker restart` 不会更新容器创建时注入的环境变量。
其余模型地址、密钥、数据库连接等保留服务器原值,不用本机 .env 覆盖生产文件。
### 100 个线程与环境变量优先级
`GATEWAY_WORKERS=100` **不是**把工具线程池调成 100,而是启动 100 个进程,当前部署不要这样设置。
`DEER_FLOW_ASYNCIO_THREAD_POOL_SIZE=100` **已经实现**,兼容别名 `DEERFLOW_IO_THREADS=100`,
两者任选其一即可。开启线程池开关后,按以下顺序取第一个非空值:
1. `DEER_FLOW_ASYNCIO_THREAD_POOL_SIZE`(正式变量)
2. `DEERFLOW_IO_THREADS`(兼容别名)
3. `config.yaml` 的 `runtime_performance.asyncio_thread_pool_size`(默认 100)
有效范围为整数 **1..1024**。选中环境变量的值非法时启动失败并提示,不会静默退回默认小线程池。
开关关闭时不读取环境变量来改变线程池,保留 Python 原默认。已有正式变量时,修改别名不会覆盖它。
线程按需创建,100 是上限,不会预先常驻启动 100 个线程。
## 3. config.yaml 新增配置
在实际加载的 `config.yaml` **顶层**新增一段,不能缩进到 `models`、`sandbox` 或 `skills` 内,
也不要重复定义两个 `runtime_performance`:
```yaml
runtime_performance:
# 一次工具调用内只获取一次已验证技能视图,默认 false。
skill_view_reuse_enabled: false
# 版本未变时复用技能视图,默认 false。
skill_view_cache_enabled: false
# 模型计时日志使用独立队列,不争抢耗时工具线程,默认 false。
model_timing_nonblocking_enabled: false
# 是否覆盖 Gateway asyncio 默认线程池,默认 false。
asyncio_thread_pool_enabled: false
asyncio_thread_pool_size: 100
```
如决定启用本次四项优化并将线程池上限设为 100,改为:
```yaml
runtime_performance:
skill_view_reuse_enabled: true
skill_view_cache_enabled: true
model_timing_nonblocking_enabled: true
asyncio_thread_pool_enabled: true
asyncio_thread_pool_size: 100
```
四个开关独立生效,可以单独开关。关闭/省略对应项时,对应的性能优化走原实现。
这四项不控制模型协议兼容修复或前端错误处理;全部关闭不等于回退所有代码。
为了让已有模型实例和所有后台进程配置一致,修改后重启后台;回退也是改回 `false` 后重启。
### 确认没有改错配置文件
- 已设置 `DEER_FLOW_CONFIG_PATH` 时,以它指向的文件为准;Docker 内该值必须是容器内可访问路径。
- 本仓库包含 `offline-backend-20260512/config.yaml` 和 `offline-backend-20260512/backend/config.yaml`;
两份都已补齐默认关闭的示例,但服务器要修改的是启动时实际加载/挂载的那一份。
- 启动日志 `Loaded AppConfig from ...` 可确认路径,`RUNTIME_PERFORMANCE` 可确认实际开关值。
## 4. 开启后做了什么,没做什么
### 单次调用复用
同一次 `read_file`、`ls`、`glob`、`grep`、`bash` 等工具执行期间,技能检查、沙箱初始化、
路径替换和输出脱敏共用一份已验证视图;退出调用后清理作用域,下一次调用重新验证。
不会把一个问答最初的技能启停状态一直沿用到结束。
### 技能版本缓存
每次核对启停 JSON 内容、已知源/目标文件和目录的元数据及标记。
版本一致时不重新发现/解析全部技能、不复制文件、不持有全局刷新锁。
新增、编辑、删除、启停及支持文件变化触发重建,并保留跨进程锁合并并发刷新。
没有采用会延迟下线的 TTL 缓存;下一次工具调用能发现下线或无效配置并拒绝访问。
已经开始执行的工具不因此被强行中断。
缓存仅用于标准 `LocalSkillStorage`,自定义存储实现/子类保守回到原刷新路径。
热路径仍有 O(文件数) 元数据校验,慢磁盘/网络挂载仍可能耗时;这不是“所有文件操作零开销”,
也没有把受锁保护的重建变成无锁写入。
### 模型计时日志
仅轻量计时/入队在回调中执行,日志 I/O 由独立线程消费,不占工具共享线程池或事件循环。
队列上限 4096 条;日志端长期阻塞时会丢弃诊断并在恢复后汇总告警,不无限积压或阻塞模型输出。
退出时最多等待 0.5 秒尽力刷新,异常退出可能丢失尾部日志。
这是 `ModelTimingCallback` 的优化,不会改变其他回调(如 RunJournal、可选追踪插件)、
子智能体调度池、数据库池或模型上游的连接/速率限制。不能据此保证 100 个会话同时生成。
### Gateway 工具线程池
开启 `asyncio_thread_pool_enabled` 后,在后台启动时、LangGraph 初始化之前设置当前
Gateway 事件循环的默认执行器。同步工具、该循环的 `asyncio.to_thread` 等可使用最多 100 个槽位。
关闭时完全不替换默认执行器;退出时由拥有该事件循环的服务运行器清理。
这不是 AnyIO 的同步 HTTP 路由线程池,也不改变子智能体专用池或独立事件循环的默认池。
线程池扩大只能减少可并行 I/O 的排队,不能让同一把技能锁同时被多人持有,也不会增加模型端的生成配额。
## 5. 日志检查
确认加载日志类似:
```text
RUNTIME_PERFORMANCE skill_view_reuse_enabled=True skill_view_cache_enabled=True model_timing_nonblocking_enabled=True asyncio_thread_pool_enabled=True asyncio_thread_pool_size=100
```
线程池最终是否生效,以另一条启动日志为准(进程 id 随实际启动变化):
```text
GATEWAY_ASYNCIO_EXECUTOR enabled=true max_workers=100 source=DEER_FLOW_ASYNCIO_THREAD_POOL_SIZE pid=12345
```
如果仍显示 `enabled=false max_workers=python_default`,说明线程池开关没打开或改错了配置文件,
不是已经调整到 100。改环境变量后若日志仍取旧值,检查是否重建了 Docker 容器及实际 env-file。
查看以下日志:
| 日志 | 用途 |
| --- | --- |
| `GATEWAY_ASYNCIO_EXECUTOR` | 实际线程池开关、最终上限、配置来源和进程 id;关闭时显示使用 Python 默认,不虚报 100 |
| `SKILL_VIEW_CACHE status=refreshed` | 发生重建;包含 `lock_wait_ms`、`refresh_ms`、`total_ms` 和条目数 |
| `SKILL_VIEW_CACHE status=joined` | 等待期间其他线程/进程已完成重建,本次直接复用 |
| `SKILL_VIEW_CACHE status=hit` | 缓存命中;正常命中为 DEBUG,超过 500ms 的慢命中为 INFO |
| `SKILL_VIEW_CACHE status=failed` | 刷新失败,旧能力不可继续使用,需要排查配置/磁盘 |
| `LLM_CONNECT_START/OK`、`LLM_REQUEST_DONE/FAILED` | 模型调用生命周期、首块和总耗时 |
| `LLM_CALL_RETRY/FAILED`、`OPENAI_TOOL_STREAM_SUMMARY` | 模型重试/兼容处理诊断 |
| `LLM_TIMING_LOG_DROPPED` | 日志队列曾满;检查日志磁盘/采集端速度 |
如需查看正常缓存命中,可短时设置顶层 `log_level: debug`;排查后恢复 `info`。
首块耗时不等于纯网络连接等待,仍包括上游排队、模型处理等阶段。单次 curl 成功也不能证明并发容量足够。
本次日志不记录技能正文、模型正文或 API 密钥。
## 6. 前端替换与回退
1. 先备份服务器当前前端目录和 `runtime-config.js`,并备份实际后台 .env/config.yaml。
2. 校验下载 ZIP 的 SHA-256 与本说明记录一致,再解压到一个新的发布目录。
3. ZIP 包含 `dist/`;Web 根目录应指向其内部,确保根下直接能找到 `index.html`,不要误放成 `dist/dist/`。
4. **保留/恢复服务器自己的 `runtime-config.js`**。核对生产后台地址、认证和嵌入参数;不要把构建机默认值当生产配置。
也不要覆盖生产 .env 的密钥与数据库配置。恢复 runtime-config 后其单文件哈希自然与原包不同。
5. 更新后台代码并按需设置四个开关,使用现有部署方式重启后台,再切换前端发布目录。
6. 刷新浏览器缓存后检查普通问答、智能体问答、技能示例、读取技能、生成文件以及离开后重新打开正在生成的会话。
7. 如需回退性能优化,后台关闭相应开关并重启,无需删除技能文件或技能缓存目录。
如需回退模型协议或前端修复,须恢复对应的已备份代码/前端发布目录,单独关闭性能开关不够。
正式 Linux AMD64 离线镜像/发版仍通过独立的 `knowledge-base-bj/deerflow-offline-deployment`
仓库流程执行;本次前端 ZIP 不是完整后台离线镜像。
## 7. 本地验证结果与限制
### 后台
- 提交前最终专项:技能/线程池/日志/启动配置及技能老回归 **166 项通过**;模型适配、错误分类、
诊断失败保护、SSE 响应头、会话计时与真实 transport **123 项通过**(两组不重叠,共 289 项)。
对应修改模块与测试 Ruff 通过,harness 未增加对 app 的反向依赖。后续没有执行生产模型并发压测。
- 本次技能复用/缓存/配置、日志回调与相关技能目录、大文件安全专项:**79 项通过**;
又补充 1 项开关关闭/重新开启的回退测试,通过缓存文件全部 13 项回归,合计 **80 项**。
- 模型工具参数流/推理流、错误恢复、SSE 传输和启动 worker 校验另 **76 项通过**;相关专项共 **156 项通过**。
- 后续新增线程池接入与配置专项 **45 项通过**(与前述配置测试有重叠,不相加充当独立总数):
覆盖默认关闭、两个环境变量优先级/别名、非法值拒启、启动顺序,以及实际 **24 / 100 个本地阻塞任务同时执行**、
退出后线程全部清理;新模块和相关测试 Ruff 检查通过。另一次联合技能/日志/启动配置回归 **88 项通过**。
该测试只验证本地线程池,不是 100 路模型压测。
- 线程池接入后再次尝试后台全量测试(首次失败即停止):**604 通过、2 跳过、1 失败**,
仍停在修改前已复现的 `test_llm_metrics.py::test_middleware_records_success_with_speed`,不是全量通过。
- 冷启动 8 线程并发只构建一次;真实第二进程复用持久化清单、不再发现技能。
- 下线/无效配置、源文件变更、同长保留 mtime 编辑、目标篡改、Windows junction 保护均有回归覆盖。
- 真实 LangChain 异步模型测试证明:默认工具线程池占满且日志处理器阻塞时,启用计时日志优化仍可开始、输出 token 并结束;未调用真实模型服务。
- 修改后尝试全量测试,设置失败 5 项停止:**871 通过、2 跳过、5 失败**,并非全量通过。
失败包括 `test_llm_metrics.py` 的 3 项记录时序断言、既有 Wiki `auto_sync` 配置与测试预期不一致、
`test_model_management.py` 的 thinking 参数预期不一致。首项在本轮修改前即已复现;
本轮没有修改指标中间件、模型工厂或 Wiki auto_sync 设置,不为过测试擅改这些业务配置。
- 本次针对 #185/MD 的追加回归:模型真实 SDK 回放、工具参数、思考字段、日志、配置、线程池、
错误中间件和传输联合 **145 项通过**。其中新增 SDK 回放 19 项,覆盖 8 种写文件形态,
确认 JSON 尚未闭合时部分 MD 已传出、最终工具名称和参数正确;没有连接线上模型。
### 合成性能对比
Windows 11 / Python 3.12.13,本机临时目录:150 个技能、450 个文件,各模式预热一次后串行 10 次。
旧刷新平均约 **3133ms**,缓存命中平均约 **806ms**(本次约 3.89 倍);
`load_skills` 从 10 次降为 0 次。临时数据已清理。
这不是生产 Linux 性能结论,也不是多人访问模型的承载压测。
### 前端与交付包
- 提交前最终前端专项 **60 项通过**(原 57 项,加同 reader 续接/新页面重播与迟到事件隔离 2 项、
最小技能示例 1 项);真实生产 React 浏览器错误边界测试再次通过。
- 最终全量类型检查仍有既有 **75 个诊断**,本次变更文件无新增诊断;记录在
`.runtime/frontend-final-typecheck-20260927.log`。不要把构建成功等同全量类型检查通过。
- 前端本次流式恢复、React #185 分类、技能示例、流式预览及相关权限等 **32 项专项通过**;
修正新增测试文件一处 `.ts` 导入导致的 TS5097 后,相关 16 项再次通过。
- 最新追加前端专项 **57 项通过**,含真实 SDK SSE → 文件参数 → MD 预览;旧 16ms 设置在连续流中
没有通知刷新,修复后在 JSON 尚未闭合时持续更新。真实 Chrome + 生产 React 中用循环 layoutEffect
触发 #185,验证静态友好兜底、无自动重挂、点击重新载入后恢复。
- 最新 `pnpm build` **通过**:Vite 13,853 个模块,8 分 49 秒;存在大于 500KB 的 chunk 提醒,不是构建失败。
构建日志 `.runtime/frontend-final-build-20260927.log`;本次修复重新打开会话的游标边界后已重新打包。
- 前一版临时 localhost 静态 HTTP 烟测 **通过**:入口 HTML 及引用的主 JS/CSS/runtime 等 5 个资源均 200,
响应字节 SHA-256 与磁盘一致,没有缺失资源;烟测服务已关闭。
- 最新 ZIP 中 **886 个文件**均逐文件比对大小和 SHA-256,与本次 dist 一致;入口/CSS 的 99 个本地资源引用全部存在。包内无 `.env`,
入口为 `dist/index.html`,包含 `dist/runtime-config.js`。
- 全量 `pnpm typecheck` **未通过**:复测还有 **75 个诊断、涉及 29 个本次未修改文件**,
包括现有 nextra / `@codemirror/state` 依赖、旧测试及 legacy QA 类型问题;
本次新增测试文件的 TS5097 已修正并复测,本次前端变更文件无类型诊断。
完整本地日志为 `.runtime/qa/frontend-delivery-typecheck-20260927.log`;
不能把生产构建通过表述成整个项目类型检查通过。
追加修复后本次产品变更文件无全量类型诊断,新增测试及依赖专项 TypeScript 检查为 0 诊断。
- 附加 legacy Chrome CSS 检查 **未通过**,报三个本轮未修改文件
`legacy-html-preview.test.ts`、`legacy-html-preview.ts`、`SolutionProjectLanding.tsx` 中的现代颜色函数字样;
没有报本次 dist CSS 缺失回退,也不能据此宣称完成旧浏览器端到端兼容验收。
交付 ZIP(仓库根目录):
```text
deerflow-frontend-dist-20260927-master-final.zip
```
- ZIP 大小:35,869,210 字节(约 34.2 MiB)。
- 此包替代 `deerflow-frontend-dist-20260927-191207-185-stream-fix.zip` 及更早版本;旧包保留,但不包含最终的游标作用域修复。
- 解压后文件总大小:66,347,693 字节。
- ZIP SHA-256:
```text
7E4C1525BDEB686161FFF5AED12D36087407BBF4F472B87E78CA04DADD1DF371
```
Linux 可用 `sha256sum deerflow-frontend-dist-20260927-master-final.zip`;
Windows 可用 `Get-FileHash -Algorithm SHA256 .\deerflow-frontend-dist-20260927-master-final.zip`。
未连接生产环境进行真实多人模型问答端到端验收,不能宣称所有线上卡顿已被实测消除。
## 8. 关于 20 人同时使用
当前不能承诺 20 人同时问答一定流畅。本次验证了本地代码路径和构建产物,并没有验证你的两台服务器、
上游模型地址/API key 配额、数据库/磁盘及实际技能耗时在 20 路负载下的容量。
部署新版后台、明确开启所需开关后,先在测试环境按 5 → 10 → 20 个独立会话逐级测试:
1. 纯聊天和包含技能读取/写文件的问答分开测试,保持提示长度和输出规模接近真实业务。
2. 每级记录成功/失败/超时数、首字和总耗时的分位数,以及技能 `lock_wait_ms/total_ms`。
3. 同步查看模型端 429/503、排队数量/首 token 延迟,以及应用 CPU、内存、磁盘和数据库等待。
4. 若上游只能并行处理少量请求,应用扩线程无法增加上游容量;应控制并发或扩容模型服务。
20 个在线用户、20 条运行中的问答和 20 个正在模型端生成的请求不是同一指标。
## 9. #185 与 MD 流式追加修复
用户已确认思考模式正常;本节针对仍出现的 #185 和 MD 预览卡住。
- 四个直接流入口统一使用 `STREAM_RENDER_BATCHING=true`,避免安装版本 SDK 的数字 16ms
尾部防抖不断推迟 UI 刷新;保留异步批处理,不改成每个片段同步强制渲染。
- #185 流错误不会再按模型异常直接显示原始错误串;同一轮最多一次自动恢复,重复失败暂停重连,
不主动取消后台任务,不循环重新发送问题。友好提示 30 秒去重。
- 真正渲染/commit 阶段的 #185 由页面错误边界接住,进入静态提示,只能手动重新载入;
不吞其他错误。控制台 `react_ui_render_error` 保留组件堆栈,帮助定位未知的线上循环组件。
- 恢复游标与当前页面的消息累积器绑定:同一页面断线续接不重复拼接工具参数,离开后重新打开或
切换会话则完整重播,不能复用全局旧游标跳过正文前缀;旧 reader 的迟到事件也不污染新页面。
- 后端兼容重复工具名称,避免 `write_filewrite_file` 使工具路由和预览识别失效;
`OPENAI_TOOL_STREAM_SUMMARY repeated_tool_names` 可确认是否命中。也修复了空 `error:{}` 被误判失败。
- 诊断日志写入失败不会覆盖真实模型异常、取消或成功结果。错误脱敏后仍在内存中识别上下文超限,
并识别 `invalid_api_key` 等结构化认证错误,防止本应修剪上下文或停止重试的请求反复排队。
- **实时预览和物理落盘不同**:模型还在生成参数时展示虚拟 MD 内容;参数完整、工具校验通过后,
`write_file` 才正式写沙箱文件。此次不把未完成的 JSON 直接写进最终文件。
本地已经复现并修复上述具体缺陷,但没有线上原始流/组件堆栈,不能保证它们解释全部生产故障。
## 10. `threads` 创建慢:数据库路由与阶段耗时
`POST /api/threads` 会先查/写应用数据库的 `threads_meta`,再调用检查点存储写入空 checkpoint;
它不需要请求模型,也不会在创建时遍历所有旧问答。
当前仓库部署模板是 `database.backend: mysql`,同时 `checkpointer.type: postgres`、
`checkpointer.use_postgres: false`。如果服务器保持这些值且没有 `DEER_FLOW_USE_PG_CHECKPOINTER`
覆盖,实际是 **MySQL 元数据 + SQLite 检查点**,清理 PostgreSQL 不会加速这条链路。
本地开发配置则是 SQLite。线上以实际加载的配置和环境覆盖为准,不凭数据库连接串是否存在判断。
新建/搜索接口新增 `GATEWAY_OPERATION_TIMING` 日志和 `Server-Timing` 响应头,
浏览器 Network 的响应头也能看到,不必先拿服务器日志:
- `metadata_lookup` / `metadata_create`:应用元数据查询/写入。
- `checkpoint_create`:检查点创建,包含 saver 锁/连接池等待和数据库写入,不能等同为纯 SQL 时间。
- `metadata_search`:会话列表的元数据查询。
- `handler_total`:进入处理函数后的耗时;**不含进入函数前的事件循环/鉴权/代理排队**。
模型图构建仍保持原来的任务上下文。新增 `AGENT_BUILD_TIMING`:超过 500ms 以 WARNING 记录,
正常为 DEBUG。已在本地复现同步慢工厂阻塞同事件循环的其他请求,但不能直接裸搬到线程:
延迟工具注册上下文需回传,MCP 初始化存在跨事件循环约束。此处目前是定位日志,不是已经消除阻塞。
本机安装的 SQLite saver 和 PostgreSQL saver 都存在实例级串行锁;后者使用连接池也不代表
同一个 saver 自动并行处理所有检查点。扩大 asyncio 线程池不解除此锁。
尚未取得线上分阶段耗时,因此不能承诺新建 10 秒已经根治,也不能承诺归档即可解决。
新增计时与真实 SQLite 锁测试、已有分析项目/浏览器内部创建入口联合 **43 项通过**,
其中计时专项 14 项;这是本地回归,不是线上延迟验收。
## 11. 30 天已结束会话的 PostgreSQL 归档 SQL
归档脚本单独交付,不进入本源码仓库,也不在启动时执行。使用 `pg_checkpoint_archive.sql` 搬移,
`pg_checkpoint_restore.sql` 按提交批次恢复;两者需与 `pg_checkpoint_common.sql` 放在同一目录。
应用数据库在 MySQL / PostgreSQL 的候选只读导出分别为
`mysql_checkpoint_candidates.sql` / `pg_checkpoint_candidates.sql`。
按用户确认,候选仅包括 30 天未更新、所有运行已结束的会话,排除正在运行、待处理和等待用户输入的会话。
PG 检查点没有应用会话终态字段,因此不能只按 `checkpoint.ts` 猜测,必须先从应用元数据导出候选 ID。
脚本仅在确认实际启用 PG、全部写入服务已停、备份可恢复及双读回退关闭后允许提交。
默认是预览/回滚;提交时三张原始表的全部 namespace 一起搬入新归档 schema,逐行校验后才删源行,
恢复时不覆盖同 ID 的新数据,归档副本保留。不删除沙箱文件。
**范围与风险**:这是 PG 检查点冷归档,不是完整应用归档。它不搬 MySQL `threads_meta/runs`,
因此旧会话列表入口可能仍在,但归档正文需要恢复后才能读取/续聊。归档到同一库的新表也不保证减少总磁盘占用。
SQL 的验证记录与具体执行命令见单独交付包的 README;部署前仍须在生产备份恢复的隔离副本演练。
不要跳过预检直接在生产提交。如果线上仍为 SQLite,这组 PG SQL 不适用。
独立包 `deerflow-db-archive-20260927.zip` 含 SQL、README 和复验测试,不含数据库数据、连接凭据或数据库二进制。
已在 PostgreSQL 16.15 + 安装的 LangGraph checkpoint 3.1.2 原始建表结构上通过 13 项真实执行和 14 项静态检查;
未执行真实 MySQL 候选导出,详见独立包 README。ZIP 共 9 个文件、20,983 字节,SHA-256:
```text
E90A189DA7D7032527EED7CEC9B51DE1A30FB6D48B4382CE06AF1C287B670F59
```
-3
View File
@@ -59,9 +59,6 @@
# 简介模式左侧菜单类型:与菜单管理页「简介模式」的类型 A / B 对应。两套网页分别填 A 或 B。
# 不填或留空时按类型 A,继续使用原来的简介菜单数据。
# VITE_COMPACT_MENU_TYPE=A
# 问答页「极速」模式:true=在模式菜单显示并直连大模型;false 或未设=隐藏。
# 部署后优先改 dist/runtime-config.js 的 VITE_TURBO_MODE_VISIBLE,刷新即可。
# VITE_TURBO_MODE_VISIBLE=false
# VITE_GITHUB_OAUTH_TOKEN=
# --- 官方 DeerFlow 风格页面入口(仅 Vite,不引入 Next.js)---
+7 -28
View File
@@ -1,34 +1,23 @@
# 我的项目
# 项目空间
入口:全量与简洁导航中的「我的项目」,路由 `/page/strategy/qa/projects`。旧地址 `/page/workspace/projects` 仅保留兼容跳转,不再展示独立入口或旧页面。
入口:全量与简洁导航中的「项目空间」,路由 `/page/workspace/projects`。
## 使用流程
1. 新建项目,选择普通问答、策略优选或方案生成。三类项目独立保存和展示,方案生成不会复用或标记策略优选项目。
1. 新建项目,填写名称,在问答、策略智能、方案生成中选择一种模式。
2. 选择项目默认智能体,填写目标、约束等项目说明。新建项目对话时仍可换用另一个可访问的智能体。
3. 创建后进入项目工作区。普通问答项目可包含多条独立问答;方案项目可包含多条方案记录。最近对话根据 `analysis_project_mode` 回到普通问答分组或方案项目。
3. 创建后进入嵌入式问答工作区,左侧保留普通聊天记录;项目对话也会出现在聊天记录中并返回所属项目。
4. 方案生成可从「工作流配置 · 报告结构」选择、启停、编辑、删除结构,选择后自动填充项目报告结构配置;也可直接编辑大纲及固定/弹性约束。
5. 策略智能项目保存默认 Strategy Lens;每轮依次进行问题重构、各 Lens 独立分析、策略辩论和方案生成,并分为「意图理解」「多视角策略分析」「完整策略方案」三栏。右栏以文档形式给出执行摘要、目标原则、分阶段行动、资源配置、风险应对、评估复盘、形成依据与备选策略切换条件;原始对话和引用仍可切换查看。
6. 策略智能对话底部提供改变约束、增删视角、重新推演和挑战当前策略快捷动作;项目主页面可直接添加或删除 Lens。
模式在创建后不可修改,前后端都不提供修改入口。项目、对话归属和智能体访问权限在服务端校验;方案结构及每条对话所选智能体也以服务端配置为准。
## 普通问答跨会话记忆
- 仅普通问答项目显示「跨会话项目记忆」。它只受项目自身开关控制,与系统「问答记忆」总开关相互独立;成功完成的会话会在后台整理,状态包括等待沉淀、整理中、已就绪和异常。
- 新会话提问时会召回同一账号、同一项目中其他会话的事实、决策、约束、偏好、术语与未决事项。不会读取其他项目或其他账号,也不会混用普通聊天/智能体的通用记忆。
- 项目设置和问答页头部均可打开「项目记忆」面板,查看精简快照、条目可信度/重要度和来源对话;支持手工新增、编辑、固定、删除、清空以及从当前项目历史对话重建。项目暂停后仍可清空已有数据,但不能重建。
- 编辑、删除或清空原对话时,服务端先让对应记忆失效,再修改消息;重建期间不注入旧快照。固定或手工条目在重建时保留,自动条目按来源 checkpoint 时间判断新旧,较早会话不会因后台任务晚完成而覆盖新的纠正。
- 交互问答在首包前使用有界关键词召回,避免等待远程向量编码;后台整理仍可写入向量供显式或离线检索使用,编码不可用不影响跨会话记忆。输入提示块有条数与 token 上限,历史内容只作为非指令资料,当前消息优先。
## 代码与运行
- `src/pages/AnalysisProjectsPage.tsx`:普通问答与方案项目的新建、设置、历史和工作台布局。
- `src/strategy-selection/StrategyProjectsPage.tsx`:「我的项目」三类项目列表及创建入口。
- `src/pages/AnalysisProjectsPage.tsx`:项目列表、新建、设置、Lens 配置、历史与工作台布局。
- `src/pages/analysis-projects/ProjectConversation.tsx`:现有聊天、研究进度、方案画布的项目级组合。
- `src/core/analysis-projects/api.ts`:Gateway 项目 API 与按账号隔离的缓存。
- `src/pages/analysis-projects/ProjectMemoryPanel.tsx`:项目记忆状态、快照、来源和管理操作。
- `src/core/analysis-projects/memory-status.ts`:总开关/项目开关、状态和按钮可用性映射。
- 后端:`/api/analysis-projects`,对话仍通过现有 `/api/threads/{thread_id}/runs/*` 流式接口发送;服务端从不可变归属读取项目配置。
启动新版 Gateway 后自动创建项目表。生产持久化依赖已配置的数据库;memory 模式中的项目随服务重启丢失。前端沿用仓库的 Vite 开发与构建命令。
@@ -43,14 +32,6 @@ python -m pytest tests/test_analysis_projects.py tests/test_deep_research_report
涵盖内存与 SQLite 存储、跨用户隔离、禁止修改模式、运行时覆盖伪造模式与知识库、更新配置、对话归属与失败清理、固定方案模板及知识库资料进入研究管线。
跨会话记忆专项:
```shell
python -m pytest tests/test_analysis_project_memory.py tests/test_analysis_project_memory_store.py tests/test_analysis_project_memory_runtime.py tests/test_analysis_project_memory_integration.py tests/test_analysis_projects.py -q
```
前端专项:`node --experimental-strip-types --test src/core/analysis-projects/memory-status.test.ts`,并执行 `pnpm build`。
部署前还需使用实际知识库和模型验证三类问答、流式断线续接及方案后续修改。接口模拟与单元测试不能替代真实模型联调。
## 2026-09-14 我的项目与知识库验收修复
@@ -59,11 +40,9 @@ python -m pytest tests/test_analysis_project_memory.py tests/test_analysis_proje
- 简洁模式的「我的项目」列表、策略工作台和普通问答项目恢复工作区功能导航;窄屏提供展开菜单按钮。
- 普通问答先创建具名项目,再在项目内创建多个对话。列表读取 `/api/analysis-projects` 的 `qa` 项目,不再读取、标记或自动归入全局普通聊天。
- 项目设置更新保留既有知识库绑定。旧「项目空间」入口已移除并跳转「我的项目」;普通问答路由为 `qa/projects/groups/*`,方案生成路由为 `qa/projects/solutions/*`。
- 项目设置更新保留既有知识库绑定。原「项目空间」与官方入口继续可用;我的项目下问答路由为 `qa/projects/groups/*`。
- 策略生成卡片统一先显示思考/执行过程,再显示正文;评判、方案及展开视图沿用相同顺序。
- 策略优选工作台拆为三步:意图与任务定义、策略生成与智能评判、综合方案生成。第二步不重复展示问答记录,突出当前任务并扩大策略回答、评判正文;第三步将生成过程默认收起并为方案正文保留固定可视空间,集中完成方案生成、Markdown 编辑、项目保存以及 Markdown/Word 直接下载。保存后的项目卡也提供 Markdown/Word 下载;`?module=solution` 直接进入第三步,历史方案即使任务已修改仍可查看下载。
- 资料库把已完成的策略优选综合方案作为独立「策略生成」来源展示,并标注具体策略项目名称;条目可回到策略项目第三步,也可直接下载 Markdown/Word。普通策略项目线程生成的文件沿用原文件下载链路并显示同类来源标识。
- 方案生成使用独立项目和固定报告结构,通过 `deep_research_report` 直接生成并打开方案画布;策略优选项目不再出现在方案生成分类中。
- 完成评判但尚未勾选策略的项目可以从方案列表进入,在工作台选择后生成;已保存方案在任务修改后仍可打开。旧列表请求不再覆盖新请求状态。
- 知识库管理页读取上游最新目录,避免远端删除后命中旧缓存;检索调用仍共享短期目录缓存。
- 普通用户访问尚未初始化的助手知识库时显示明确空态及刷新按钮。
@@ -1,977 +0,0 @@
# 多智能体会商功能与接口梳理
## 1. 文档范围与入口
本文梳理的是常规「多智能体会商 / 圆桌规划」页面 `RoundtablePlanningPage` 的完整三步流程:
1. 任务意图理解
2. 多智能体研讨
3. 方案结果展示
主入口为 `/page/workspace/qa/multi-agent-roundtable`。它也可由任务深链 `3qfx-A`、`rwfx-A`、`xdfx-A` 打开,分别挂载在任务管理下的三情、任务、行动业务路由中;另有 `#/embed/roundtable` 嵌入入口。
任务深链会预填任务名称、任务目标、业务编码和任务 ID,并自动选择对应业务链:
| 深链 | 业务编码 | 嵌入路由 |
| --- | --- | --- |
| `3qfx-A` | `3Q` | `/page/strategy/task-management/plan-task-sentiment/roundtable` |
| `rwfx-A` | `6BF` | `/page/strategy/task-management/plan-task/plan-task-fx/roundtable` |
| `xdfx-A` | `7BF` | `/page/strategy/task-management/plan-task/plan-task-action/roundtable` |
> 本文不展开独立的阵位会商,以及仅展示报告的 8BF 变体。8BF 复用了部分组件,但其第三步为 `report-only`,不属于常规三步会商主路径。
## 2. 公共机制
### 2.1 会商记录与保存
功能:
- 保存任务意图、研讨过程、会商结论、第三步报告及当前已完成步骤。
- 支持新建会商、历史记录切换、重命名、删除和从已有记录继续。
- 普通入口按当前用户隔离;任务深链按任务共享,进入同一任务的用户看到同一批会商和后台任务。
- 更新使用乐观锁;版本不一致时后端返回 `409`,前端应以服务端最新记录为准后再处理。
接口:
| 场景 | 接口 | 调用方式与参数 |
| --- | --- | --- |
| 普通会商列表 | `GET /api/roundtable-drafts` | 无请求体,按当前用户返回。 |
| 新建普通会商 | `POST /api/roundtable-drafts` | JSON:`{ id?, title, furthest_step, step1, step2, step3 }`。 |
| 读取/更新/删除普通会商 | `GET/PUT/DELETE /api/roundtable-drafts/{draftId}` | `PUT` 传需更新字段及 `expected_version`。 |
| 任务会商列表 | `GET /api/roundtable-task-drafts/by-task/{taskId}` | `taskId` 为任务 ID。 |
| 读取最新任务会商 | `GET /api/roundtable-task-drafts/by-task/{taskId}/latest` | 用于任务进入后恢复最近一次会商。 |
| 新建任务会商 | `POST /api/roundtable-task-drafts` | JSON:`{ id?, task_id, title, furthest_step, step1, step2, step3 }`。 |
| 读取/更新/删除任务会商 | `GET/PUT/DELETE /api/roundtable-task-drafts/{draftId}` | `PUT` 为局部更新并携带 `expected_version`。 |
参数说明:
- `step1`、`step2`、`step3` 保存的是各步骤可恢复的完整页面状态,而不是单一文本。
- `furthest_step` 记录用户历史上到达的最远步骤,用于恢复导航可用性。
- `xdfx-A` 的页面记录和后台任务分区使用 URL 原始行动 ID;任务正文及任务详情仍使用解析后的实际任务 ID。
### 2.2 流式调用与附件
功能:
- 大模型回复、意图澄清、推荐、研讨、报告和流程图均通过 SSE 增量返回。
- 用户可停止当前流;前端按事件逐段追加正文、思考、工具调用、澄清卡片和错误信息。
- 有文件时先上传到对应线程,再将后端返回的虚拟路径传给后续流式接口。
附件接口:
```http
POST /api/threads/{threadId}/uploads
Content-Type: multipart/form-data
files: <file> # 可重复,支持多文件
```
响应中的 `{ filename, size, virtual_path }` 应转换后传入流式请求:
```json
{
"files": [
{
"filename": "任务材料.docx",
"size": 10240,
"path": "/mnt/user-data/uploads/任务材料.docx",
"status": "uploaded"
}
]
}
```
所有 JSON 接口经前端 `apiFetch` 调用,自动携带当前登录态;流式接口使用 `ReadableStream` 解析 SSE。
---
# 第一步:任务意图理解
## 1. 功能
第一步将用户的自然语言任务转成可供多个智能体研讨的结构化意图,并确定后续参会智能体来源。
- 创建内置「任务意图理解」智能体会话,接收任务描述、补充材料和多轮追问。
- 流式展示智能体回复、思考过程和工具型澄清问题。
- 澄清卡支持单选、多选、自定义填写、跳过和继续追问;同一轮可返回多张澄清卡。
- 意图完成后生成可编辑的结构化摘要:目标(`objective`)、约束(`constraints`)、可选假设(`assumptions`)。
- 支持手工修改意图摘要后再进入下一步。
- 智能体选择有两条路径:
- **智能体推荐**:依据意图,在可用智能体候选池中推荐参会人及理由。
- **业务链条**:选择已配置的业务链条,带入席位、阶段、阶段目标、协调人提示词和席位模型策略。
- 任务深链模式自动加载任务卡片、预填任务上下文并自动选择业务链;普通模式在“选择参会智能体”弹窗中手工选择“我的”或“公共”业务链。
步骤流转:
```text
输入任务 / 上传材料
↓
意图智能体澄清(可多轮)
↓
结构化意图完成并可编辑
↓
智能体推荐 或 选择业务链
↓
进入第二步
```
### 1.1 业务链功能与两个弹窗
业务链是可命名、可复用、可保存的“智能体编排模板”,不是单纯的智能体名单。一条链定义了谁参会、谁先后执行、哪些席位并行、每阶段应产出什么,以及协调人如何派发和汇总。
第一步中有两个职责不同的业务链入口:
| 入口 | 弹窗/页面 | 作用 | 是否直接开始研讨 |
| --- | --- | --- | --- |
| 页面顶栏“业务链条” | BusinessChainListDialog | 浏览、筛选、启停、发布、进入配置页编辑业务链。 | 否,它是管理入口。 |
| 意图完成后点击“选择参会智能体 / 进入研讨” | RecommendAgentsDialog 的“业务链条”页签,内部为 BusinessChainPicker | 从可用链中选择一条,校验席位后把编排结果带入第二步。 | 是,确认“进入研讨”后开始第二步。 |
#### A. 选择参会智能体弹窗中的“业务链条”页签
功能:
- 弹窗有“智能体推荐”和“业务链条”两个页签;切换到业务链条后不会调用推荐模型,而是读取已保存的链条。
- 可在“我的 / 公共”之间筛选:
- **我的**:当前用户创建的业务链。
- **公共**:已发布、所有账号都可查看和选用的业务链。
- 每张链条卡展示链条名称、描述、席位数和席位编排流:
- 线性链用“智能体 A → 智能体 B → 智能体 C”表示顺序。
- 同一阶段有多个席位时显示“并行 N”分组;阶段之间仍用箭头表示串行依赖。
- 实时智能体名称优先于链条保存时的名称快照;已删除智能体会置灰并提示。
- 仅启用的链条可进入选择列表;选中链条后,至少保留 **2 个仍存在的可用席位** 才能点击“进入研讨”。
- 如果链条配置了默认执行模式,弹窗顶部的执行模式会自动带入该值,用户仍可临时改为:
- flash:快速,不开启思考。
- thinking:思考,低推理强度。
- pro:专业问答,思考 + 中等推理强度。
- ultra:多智能体问答,思考 + 高推理强度,并允许席位调用子代理。
- 如果链条含有有效分层、阶段目标或协调人提示词,选择后按 dag 编排;否则按 chain 线性编排。
- DAG 链在弹窗底部额外选择执行方式:
- **快速 · 双列禁写**:同阶段席位并行,主区双列展示,并行席位不写文件。
- **沙箱 · 单列可写**:同阶段仍并行,但主区单列展示,允许文件产出,右侧沙箱随当前席位切换。
- “配置链条”按钮跳转到业务链编辑页;没有链条时也会显示“去配置业务链条”引导。
确认后传给第二步的运行结果可概括为:
~~~json
{
"agents": [
{
"agent_id": "agent-001",
"name": "态势专家",
"model": "该席位模型覆盖,可为空",
"seat_skill_directive": true,
"human_validation": false,
"seatMode": "该席位推理深度覆盖,可为空"
}
],
"mode": "chain | dag",
"chain": {
"id": "chain-id",
"title": "任务综合研判链"
},
"plan": {
"stages": "仅 dag 时携带的分层执行计划"
},
"dagExecMode": "fast | sandbox",
"seatMode": "本次会商的链条级执行模式",
"gatherFirst": true
}
~~~
其中,席位数组的顺序就是线性链执行顺序;DAG 时按阶段展平。单席位的 seatMode、模型覆盖、技能识别强化和人工校验会一并继承到第二步。
#### B. 顶部“业务链条”管理弹窗
功能:
- 顶栏点击“业务链条”打开,定位为“浏览和管理”,不直接选择参会人。
- 支持按 **我的 / 公共 / 全部(仅管理员)** 筛选,再按 **全部状态 / 启用 / 停用** 过滤。
- 每张卡片展示:
- 名称、描述、席位数量;
- 公共、待审核、已停用等状态;
- 配置人和最后修改时间;
- 智能体编排流:同 Stage 的席位用“并行 N”分组,Stage 之间以箭头连接。
- 本人链条或管理员可在卡片上:
- 启用 / 停用;
- 发布为公共、取消发布;
- 草稿链提交审核,审核中可撤回;
- 点击“设置”跳转到该链条的编辑页。
- 新建和编辑页面包含:
- **基本信息**:标题、描述、默认执行模式、研讨前并行取数开关、总控提示词。
- **链条编排**:从候选智能体池拖拽到 Stage;可新建、删除、上下移动 Stage,移动/拆分/合并席位。
- **阶段目标**:每个 Stage 可填写目标,并可使用 AI 优化;阶段目标会指导协调人该阶段产出什么、如何承接前一阶段结果。
- **总控提示词**:说明协调人如何派发、汇总、收口,支持 Markdown 和 AI 优化。
- **席位级配置**:模型覆盖、推理深度覆盖、会商技能识别强化、人工校验;岗位协同专用入口还可配置岗位归属和产物位置。
- **编排预览**:以流程图检查“同层并行、层间串行”的最终结构。
两个业务链弹窗的页面结构:
~~~text
顶部“业务链条”管理弹窗
┌ 标题和说明 ───────────────────────────────────────────────────────────┐
│ 筛选:我的 / 公共 / 全部(管理员) | 全部状态 / 启用 / 停用 │
├ 业务链卡片列表 ───────────────────────────────────────────────────────┤
│ 名称、席位数、公共/待审核/停用状态、配置人、更新时间、说明 │
│ 智能体 A → [并行:智能体 B、智能体 C] → 智能体 D │
│ 操作:启停 / 发布或撤回 / 设置 │
├───────────────────────────────────────────────────────────────────────┤
│ 底部:配置(新建或跳转到业务链编辑页) │
└───────────────────────────────────────────────────────────────────────┘
“选择参会智能体”弹窗的业务链页签
┌ 顶部:智能体推荐 | 业务链条 | 本次执行模式(快速/思考/专业/多智能体)┐
│ 筛选:我的 / 公共 │
├ 链条选择卡片 ─────────────────────────────────────────────────────────┤
│ 名称、描述、席位数、线性/分层编排、已删除席位告警 │
├───────────────────────────────────────────────────────────────────────┤
│ DAG 链:快速·双列禁写 | 沙箱·单列可写 │
│ 底部:配置链条 | 取消 | 进入研讨 │
└───────────────────────────────────────────────────────────────────────┘
~~~
## 2. 接口、调用时机与传参
### 2.1 初始化意图会话
```http
POST /api/intent/init
Content-Type: application/json
```
```json
{
"model": "模型标识,可选,使用页面当前模型",
"task_context": {
"task_id": "任务深链时的任务 ID",
"task_name": "任务名称",
"task_goal": "任务目标",
"business_code": "3Q | 6BF | 7BF"
},
"intent_agent_id": "roundtable-intent"
}
```
说明:
- 普通会商一般省略 `task_context`,`intent_agent_id` 也可省略并由后端使用内置 `roundtable-intent`。
- 返回 `{ status, agent_id, thread_id }`;后续上传与流式对话都使用此 `thread_id`。
### 2.2 发送任务或回答澄清问题
```http
POST /api/intent/stream
Accept: text/event-stream
```
```json
{
"thread_id": "意图会话线程 ID",
"message": "用户任务描述,或对澄清问题的答案",
"model": "页面当前模型,可选",
"intent_agent_id": "roundtable-intent",
"task_context": {
"task_id": "任务 ID",
"task_name": "任务名称",
"task_goal": "任务目标",
"business_code": "业务编码"
},
"client_turn_id": "前端生成的幂等 ID",
"files": [
{
"filename": "材料.pdf",
"size": 10240,
"path": "/mnt/user-data/uploads/材料.pdf",
"status": "uploaded"
}
]
}
```
主要 SSE 完成帧字段:
```json
{
"status": "asking | clarification | done | error",
"content": "本轮可见回答",
"summary": {
"objective": "任务目标",
"constraints": ["约束 1"],
"assumptions": ["可选假设"]
},
"question": "单个澄清问题",
"clarifications": ["多个澄清问题"],
"clarification_type": "single | multiple | text",
"clarification_context": {},
"options": ["选项 A", "选项 B"],
"allow_custom": true,
"allow_multiple": false,
"error_detail": "失败原因"
}
```
调用要点:
- `client_turn_id` 用于避免重试或网络抖动造成同一用户轮次重复执行。
- 用户选项、填写的自定义答案、点击“继续/跳过”后,仍通过本接口的 `message` 继续同一 `thread_id`。
- 上传接口必须先于本接口调用;流式接口只传上传成功后的虚拟路径。
### 2.3 获取候选智能体和执行推荐
```http
GET /api/agents
```
前端从返回列表中排除内置工具型智能体,将可参会的候选人整理成:
```json
{
"agent_id": "agent-001",
"name": "态势研判专家",
"description": "负责态势信息研判"
}
```
```http
POST /api/recommend/stream
Accept: text/event-stream
```
```json
{
"intent": {
"objective": "形成处置建议",
"constraints": ["时限 24 小时"],
"assumptions": ["数据可访问"]
},
"candidates": [
{
"agent_id": "agent-001",
"name": "态势研判专家",
"description": "负责态势信息研判"
}
],
"model": "页面当前模型"
}
```
推荐完成帧可得到:
```json
{
"status": "done",
"content": "推荐过程说明",
"picks": [
{
"agent_id": "agent-001",
"reason": "与任务目标的匹配理由"
}
]
}
```
普通会商会额外保存推荐记录,便于恢复和审计:
| 接口 | 参数 |
| --- | --- |
| `GET /api/roundtable-drafts/{draftId}/recommendations` | 无请求体,读取该草稿的推荐历史。 |
| `POST /api/roundtable-drafts/{draftId}/recommendations` | `{ objective, status, model?, rationale?, picks, candidates }`。 |
### 2.4 读取、选择和管理业务链
| 接口 | 调用方式与参数 |
| --- | --- |
| `GET /api/roundtable-chains?scope=public\|mine\|pending\|all` | 获取业务链列表;入口页通常读取公开链。 |
| `GET /api/roundtable-chains/{id}` | 获取某条业务链完整定义。 |
| `POST /api/roundtable-chains` | 新建业务链。 |
| `PUT /api/roundtable-chains/{id}` | 更新业务链。 |
| `DELETE /api/roundtable-chains/{id}` | 删除业务链。 |
| `POST /api/roundtable-chains/optimize-prompt` | 使用模型优化总控提示词或阶段目标。 |
读取与弹窗行为:
- “选择参会智能体”弹窗调用 GET /api/roundtable-chains(我的)或 GET /api/roundtable-chains?scope=public(公共),并同时调用 GET /api/agents 校验每个席位是否仍存在。
- 顶部管理弹窗在管理员身份下还可调用 scope=all;scope=pending 用于待审核链的管理场景。非管理员请求 all/pending 时后端会退化为当前用户范围。
- 启用状态为 false 的链条仍可在管理弹窗查看,但不会出现在“选择参会智能体”弹窗中。
创建或更新业务链的核心参数示例:
```json
{
"title": "任务综合研判链",
"description": "先收集信息,再由专家研讨",
"seats": [
{
"agent_id": "agent-001",
"name": "态势专家",
"description": "分析外部态势",
"model": "模型标识",
"seat_skill_directive": true,
"human_validation": true,
"seat_mode": "flash"
}
],
"stages": [["agent-001", "agent-002"], ["agent-003"]],
"stage_goals": ["平行收集信息", "汇总形成判断"],
"coordinator_prompt": "协调人需要按风险、机会、建议汇总",
"seat_mode": "flash",
"gather_first": true
}
```
其中:
- 链条创建时前端使用驼峰字段 stageGoals、coordinatorPrompt、seatMode、gatherFirst;请求发送前映射为接口字段 stage_goals、coordinator_prompt、seat_mode、gather_first。更新时传 null 可清除分层、阶段目标、总控提示词或默认执行模式。
- `stages` 表示 DAG 分层:同层可并行,不同层按顺序执行。
- `seat_mode` / 席位 `seat_mode` 可取 `flash`、`thinking`、`pro`、`ultra`。
- model 为空时,该席位跟随第二步页面的全局模型;有值时仅覆盖该席位。
- seat_skill_directive: true 会在该席位运行时强化其技能识别和使用指令;它与智能体自身同名开关任一开启即可生效。
- `human_validation: true` 表示该席位输出后需要人工确认才可继续。
- `gather_first: true` 表示先让全部席位平行收集信息,再进入正式研讨。
发布、审核和启停均通过更新接口发送局部字段:
| 操作 | PUT /api/roundtable-chains/{id} 请求体 |
| --- | --- |
| 启用 / 停用 | { "enabled": true } / { "enabled": false } |
| 直接发布 / 取消发布 | { "is_public": true } / { "is_public": false } |
| 提交审核 / 撤回审核 | { "pending_review": true } / { "pending_review": false } |
| 管理员审核发布 | { "is_public": true, "pending_review": false } |
提示词优化接口的请求示例:
~~~json
{
"prompt_text": "当前总控提示词或阶段目标原文",
"kind": "coordinator | stage_goal",
"context": "链条标题、各阶段席位及已有阶段目标组成的上下文",
"model_name": "可选模型标识"
}
~~~
返回:
~~~json
{
"optimized": "可直接回填到总控提示词或阶段目标编辑框的文本"
}
~~~
## 3. 页面结构
```text
┌──────────────────────────────── 页面顶部 ────────────────────────────────┐
│ 三步导航:①任务意图理解 ②多智能体研讨 ③方案结果展示 │
│ 业务链 / 新建或重新分析 / 保存草稿 / 历史记录 / 模型选择 / 设置 │
└───────────────────────────────────────────────────────────────────────┘
┌──────────── 左侧入口栏 ───────────┬──────────── 中间工作区 ────────────┬──── 右侧摘要栏 ────┐
│ 任务卡(仅任务深链) │ Step1 对话面板 │ 当前模型选择 │
│ 业务链列表与展开关系 │ - 意图智能体消息 │ 结构化意图摘要 │
│ 会商/分析历史记录 │ - 思考、工具、澄清卡 │ - 目标 │
│ │ - 输入框、附件、发送/停止/继续 │ - 约束 │
│ │ │ - 假设,均可编辑 │
└───────────────────────────────────┴────────────────────────────────────┴────────────────────┘
```
任务深链还会显示任务目的入口和底部 `TaskJumpBar` 快捷跳转栏;任务模式隐藏手工选择业务链的入口,以深链业务编码自动选择链条。
---
# 第二步:多智能体研讨
## 1. 功能
第二步以第一步意图和选定智能体/业务链为输入,创建协调人与多个席位智能体,进行可观察、可干预、可恢复的会商。
- 为每位参会智能体和协调人创建独立线程。
- 支持三种编排模式:
- **推荐模式(recommend)**:协调人自由决定调度哪些推荐智能体。
- **链条模式(chain)**:按业务链指定的席位顺序执行。
- **DAG 模式(dag)**:同阶段并行、跨阶段串行;可传入阶段目标和协调人提示词。
- DAG 支持 `fast` 与 `sandbox` 执行视图。快速模式会限制并行席位写文件;沙箱模式可产出和预览文件。
- 可选“先收集后研讨”:全部席位先并行收集资料,再将有效交付共享给正式研讨。
- 协调人可继续派发、发起人工澄清,或在不再派发时形成共识。
- 用户可暂停/继续本地编排,回答协调人的澄清问题,向协调人追加文字或附件。
- 席位可配置人工验证点;达到验证点后需人工确认。
- 支持打开角色画像抽屉,在下一次运行前调整单席位模型和运行策略。
- 实时展示角色状态、对话、思考、工具调用、阶段流图、并行席位、文件产物和人工参与记录。
- 每次重新推荐或选择链条都会创建独立“研讨运行快照”;历史运行互不覆盖,可在左侧切换查看。
- 支持将长时间会商转入后台任务。后台任务可被同一任务的其他用户看到、跟踪、继续回答或接管。
步骤门槛:
- 只有第一步的 `intentReady` 为真时,第二步可进入。
- 协调人形成共识(`hasConsensus`)后,第三步才可进入。
## 2. 接口、调用时机与传参
### 2.1 初始化所有参会线程
```http
POST /api/multi-agent/init
Accept: text/event-stream
```
```json
{
"agent_names": ["agent-001", "agent-002"],
"main_agent_name": "coordinator",
"model": "页面当前模型,可选"
}
```
说明:
- `agent_names` 为选中的席位智能体标识。
- `main_agent_name` 为协调人标识。
- SSE 依次返回席位就绪、协调人就绪和初始化完成事件,最终得到线程映射:
```json
{
"thread_ids": {
"agent-001": "席位线程 ID",
"agent-002": "席位线程 ID",
"coordinator": "协调人线程 ID"
}
}
```
### 2.2 驱动协调人和席位研讨
```http
POST /api/multi-agent/run/stream
Accept: text/event-stream
```
基础请求:
```json
{
"agent_type": "leader | special",
"agent_name": "coordinator 或席位 agent ID",
"display_name": "页面展示名称",
"d_agent_thread_id": {
"coordinator": "协调人线程 ID",
"agent-001": "席位线程 ID"
},
"new_message": "给协调人或席位的本轮提示词",
"model": "模型标识",
"business_code": "3Q | 6BF | 7BF",
"files": []
}
```
关键参数:
| 参数 | 适用对象 | 用途 |
| --- | --- | --- |
| `agent_type: "leader"` | 协调人 | 由协调人分析现状、派发席位或形成共识。 |
| `agent_type: "special"` | 席位、总结/报告等专用智能体 | 执行专业分析、总结或文件生成。 |
| `d_agent_thread_id` | 全部 | 是“智能体 ID → 线程 ID”的映射,不是单一线程 ID。 |
| `thinking_enabled?` | 席位 | 是否启用思考。 |
| `reasoning_effort?` | 席位 | 推理强度。 |
| `subagent_enabled?` | 席位 | 是否允许席位再调用子智能体。 |
| `seat_skill_directive?` | 席位 | 席位特定的技能使用指令。 |
| `parallel_no_file?` | 并行席位 | 快速并行时限制文件写入。 |
| `peer_deliveries?` | 后续席位/协调人 | 传递前序席位可见交付物。 |
| `synthesis_mode?` | 协调人 | 指示汇总类执行。 |
| `suppress_pre_broadcast?` | 协调人 | 控制汇总前广播。 |
| `skill_stop_names?` | 全部 | 指定需要拦截/停止的技能名称。 |
流式完成后前端重点读取:
```json
{
"dispatched": ["agent-001"],
"content": "可见回答或结论",
"agentName": "本次完成者",
"modelUsed": "实际使用模型",
"clarification": {
"question": "需要用户回答的问题",
"options": ["选项 A"]
},
"invalidDelivery": false
}
```
编排规则:
- 协调人先运行并决定需调度的席位。
- 每个席位完成后,将其“可见回答”作为交付物回传,思考内容不作为席位交付。
- 链条模式按链定义的顺序运行;DAG 模式同层并行、阶段间串行。
- 协调人返回不再派发且无待答澄清时,前端将结果标记为共识。
### 2.3 产物查看与下载
| 接口 | 调用方式 |
| --- | --- |
| `GET /api/threads/{threadId}/artifacts` | 查询指定协调人或席位线程的文件产物。 |
| `GET /api/threads/{threadId}/artifacts/{path}` | 预览或下载文件;下载时前端附加 `?download=true`。 |
### 2.4 后台会商任务
开始后台任务:
```http
POST /api/roundtable-jobs
Content-Type: application/json
```
```json
{
"requestId": "前端请求 ID",
"draftId": "会商草稿 ID",
"taskId": "任务深链时的任务 ID",
"intent": {
"objective": "任务目标",
"constraints": ["约束"],
"assumptions": ["假设"]
},
"agents": [
{
"agentId": "agent-001",
"name": "态势专家"
}
],
"model": "当前模型",
"orchestrationMode": "recommend | chain | dag",
"chain": {
"id": "chain-id",
"title": "业务链名称"
},
"orchestrationPlan": {},
"seedMessage": "首次给协调人的提示",
"threadIds": {
"coordinator": "线程 ID",
"agent-001": "线程 ID"
},
"coordinatorName": "协调人名称",
"seat_skill_directives": {
"agent-001": true
},
"seat_modes": {
"agent-001": "thinking"
},
"gather_first": true,
"business_code": "3Q",
"thinking_enabled": true,
"reasoning_effort": "medium",
"subagent_enabled": false
}
```
后台任务接口:
| 接口 | 调用方式与参数 |
| --- | --- |
| `GET /api/roundtable-jobs?draft_id={draftId}&task_id={taskId}` | 获取草稿/任务关联的后台任务列表。任务模式需带 `task_id`。 |
| `GET /api/roundtable-jobs/{jobId}?task_id={taskId}` | 获取任务快照。 |
| `GET /api/roundtable-jobs/{jobId}/stream?task_id={taskId}` | SSE 跟踪后台任务完整进度。 |
| `POST /api/roundtable-jobs/{jobId}/resume?task_id={taskId}` | JSON:`{ answer }`,用于回答后台任务等待的人工问题。 |
| `POST /api/roundtable-jobs/{jobId}/cancel?task_id={taskId}` | 取消后台任务;前台接管时也会先结束后台执行。 |
状态和阶段:
| 分类 | 枚举 |
| --- | --- |
| 任务状态 | `queued`、`running`、`awaiting_input`、`done`、`error`、`cancelled` |
| 执行阶段 | `initializing`、`leader_thinking`、`dispatching`、`consensus`、`summary_writing`、`report_drawing`、`report_done` |
## 3. 页面结构
```text
┌──────────────────────────────── 页面顶部 ────────────────────────────────┐
│ 三步导航 / 会商记录 / 模型选择 │
└───────────────────────────────────────────────────────────────────────┘
┌──────────── 可收起左栏 ───────────┬──────────── 中间研讨区 ─────────────┬──── 右侧沙箱区 ────┐
│ 意图摘要 │ 顶部:模型、暂停/继续、转后台 │ Step2SandboxLayout │
│ 角色列表与席位筛选 │ DAG 流程缩略图、并行席位切换 │ 文件/网页预览 │
│ 人工参与/验证状态 │ 对话时间线:协调人、席位、工具、思考 │ 产物查看和下载 │
│ 多次研讨运行快照切换 │ 澄清问题卡、人工确认卡 │ 打开时左栏自动收起 │
│ 任务概览(任务深链) │ 底部:追加消息、附件、发送 │ │
└───────────────────────────────────┴─────────────────────────────────────┴────────────────────┘
```
页面展示规则:
- 角色卡显示席位状态、当前轮次、模型和是否等待人工确认。
- 对话区可按角色筛选,思考内容默认折叠,工具调用和交付物以步骤卡展示。
- DAG 研讨可打开流程面板观察阶段、依赖和并行关系。
- 打开沙箱/产物预览后,优先保证产物可读区域,左侧栏自动收起。
---
# 第三步:方案结果展示
## 1. 功能
第三步基于第一步意图、第二步席位交付和协调人共识,生成可阅读、可修改、可下载、可继续加工的最终方案。
- 首次进入常规会商第三步时,启动三个相互独立的产出流:
- **方案总结报告**:生成 Markdown 方案,是默认主界面。
- **经典可视化报告**:生成 HTML 风格报告/仪表盘。
- **结构化仪表盘**:生成 `report-json`,由前端 `DashboardApp` 渲染。
- 三条流以约 0 / 300 / 600 ms 错峰启动,减少瞬间请求峰值,但互不等待。
- 已保存草稿再次打开时优先恢复既有结果,不重复生成;切换到新会商运行时会终止旧运行的活跃流。
- Markdown 报告完成后,常规模式自动调用流程图提取,生成 `flow-json` 结构化流程图。
- 用户可对报告提问、要求重写、修改流程图、重新生成流程图或报告。
- 任务深链可根据业务链层次和业务编码生成任务 → 目的 → 行为体等结构;行动业务会使用行动名称作为根节点。
- 若任务和技能条件满足,可选择“现在导入 / 稍后导入 / 不再导入”,把报告和流程结构交给 `roundtable-structure` 进行任务结构化入库。
- 左侧汇集协调人共识、各席位交付和文件;右侧可预览 Markdown、流程图及沙箱产物。
- 支持下载会商文档和智能体产物。任务模式还可将选定产物提交到任务交付接口。
## 2. 接口、调用时机与传参
### 2.1 初始化第三步专用智能体
| 目标 | 接口 | 返回 |
| --- | --- | --- |
| Markdown 方案总结 | `POST /api/multi-agent/summary/init` | `{ agent_name, thread_id }` |
| 经典可视化报告 | `POST /api/multi-agent/report/init` | `{ agent_name, thread_id }` |
| 结构化仪表盘 | `POST /api/multi-agent/dashboard/init` | `{ agent_name, thread_id }` |
| 任务结构化入库 | `POST /api/multi-agent/structure/init` | `{ agent_name, thread_id }` |
初始化请求体均为:
```json
{}
```
各专用智能体初始化后,均继续通过统一接口 `POST /api/multi-agent/run/stream` 运行。
### 2.2 生成或修改 Markdown 方案总结
```json
{
"agent_type": "special",
"agent_name": "roundtable-summary",
"display_name": "方案总结报告",
"d_agent_thread_id": {
"roundtable-summary": "总结线程 ID"
},
"new_message": "包含结构化意图、席位交付、协调人共识、链条提示词的生成或修改指令",
"model": "当前模型",
"business_code": "3Q",
"files": []
}
```
功能覆盖:
- 首次生成 Markdown 报告。
- 在报告下方继续问答或下达修改指令。
- 支持暂停、继续、重新生成和生成后下载 Docx。
- 上述问答与修改沿用同一总结线程,保证上下文连续。
### 2.3 生成经典报告和仪表盘
经典报告请求使用 `roundtable-report`:
```json
{
"agent_type": "special",
"agent_name": "roundtable-report",
"d_agent_thread_id": {
"roundtable-report": "报告线程 ID"
},
"new_message": "包含意图、席位交付、共识、主题模式、修订要求和已有 HTML 的提示词",
"model": "当前模型"
}
```
结构化仪表盘请求使用 `roundtable-dashboard`:
```json
{
"agent_type": "special",
"agent_name": "roundtable-dashboard",
"d_agent_thread_id": {
"roundtable-dashboard": "仪表盘线程 ID"
},
"new_message": "包含意图、席位交付、共识,或对已有仪表盘的修订要求",
"model": "当前模型"
}
```
前端依据返回的 HTML 或 `report-json` 分别渲染经典报告和 `DashboardApp`,并提供全屏、在新窗口打开、继续优化以及切回经典报告的操作。
### 2.4 自动提取和修改流程图
```http
POST /api/flow-extract/stream
Accept: text/event-stream
```
```json
{
"report_md": "Markdown 完整报告",
"seat_deliveries": [
{
"sender": "态势专家",
"content": "席位可见交付"
}
],
"chain_levels": [["信息收集"], ["研判决策"]],
"coordinator_prompt": "协调人对结构层次的要求",
"business_code": "3Q",
"root_label": "任务根节点名称",
"model": "当前模型",
"current_graph": {
"nodes": [],
"edges": []
},
"instruction": "用户对当前流程图的修改要求"
}
```
参数使用规则:
- 首次自动提取可不传 `current_graph` 和 `instruction`。
- 修改现有图时传当前图和用户要求。
- 任务模式的 `chain_levels` 由业务链阶段目标推导;若 `coordinator_prompt` 明确规定层次,则优先使用该要求。
流中包含提取增量、校验过程、模型切换和最终图数据,最终形成前端 `FlowGraphPanel` 使用的 `flow-json`。
### 2.5 判断用户在第三步的意图
| 接口 | 请求体 | 返回用途 |
| --- | --- | --- |
| `POST /api/flow-extract/intent` | `{ message, has_report, has_flow, can_ingest, model? }` | 分类为 `regenerate_report`、`modify_flow`、`regenerate_flow`、`ingest`、`qa`、`unclear`,决定继续调用哪一条流。 |
| `POST /api/flow-extract/ingest-intent` | `{ message, model? }` | 在已提示导入或稍后导入时,判断 `start_ingest`、`add_data`、`other`、`unclear`。 |
### 2.6 任务结构化入库
先检查是否可入库:
```http
POST /api/flow-extract/ingest-eligibility
```
```json
{
"task_id": "任务 ID",
"business_code": "3Q",
"chain_name": "业务链名称",
"coordinator_prompt": "协调人提示词",
"report_title": "报告标题",
"model": "当前模型"
}
```
返回:
```json
{
"can_ingest": true,
"skill": "命中的入库技能",
"reason": "是否可入库的原因"
}
```
符合条件且用户确认后,初始化 `roundtable-structure` 线程,并调用统一研讨流:
```json
{
"agent_type": "special",
"agent_name": "roundtable-structure",
"d_agent_thread_id": {
"roundtable-structure": "结构化入库线程 ID"
},
"new_message": "包含 taskId、业务编码/链条/技能提示、最新 Markdown 报告、flow-json 和用户补充说明的指令",
"model": "当前模型",
"business_code": "3Q"
}
```
注意:前端不会直接调用某个入库技能,而是交给 `roundtable-structure` 智能体在具备完整报告和流程图上下文后执行。
### 2.7 任务交付物提交
任务深链启用交付配置时,第三步可以查询和更新任务产物提交状态。
| 接口 | 调用方式与参数 |
| --- | --- |
| `GET /api/roundtable/tasks/{taskId}/artifacts?submitted=true\|false` | 获取任务已提交或待提交产物。 |
| `PUT /api/roundtable/tasks/{taskId}/artifacts/submission` | 更新某个产物的提交状态。 |
```json
{
"taskId": "任务 ID",
"submitted": true,
"registerOnly": false,
"submissionId": "已有提交记录 ID,可选",
"taskDeliveryId": "外部交付 ID,可选",
"expectedVersion": 3,
"artifact": {
"sessionId": "会商会话 ID",
"threadId": "产物所属线程 ID",
"nodeKey": "流程节点标识,可选",
"sourceKey": "来源标识",
"path": "/mnt/user-data/outputs/report.md",
"name": "会商报告.md",
"mimeType": "text/markdown",
"revision": 1
}
}
```
## 3. 页面结构
默认的“方案总结”视图:
```text
┌──────────────────────────────── 页面顶部 ────────────────────────────────┐
│ 步骤导航 / 报告标题 / 模型 / 总结报告、流程图、最终方案等视图切换 │
└───────────────────────────────────────────────────────────────────────┘
┌──────────── 可收起左栏 ───────────┬──────────── 中间主内容 ─────────────┬──── 右侧结果区 ────┐
│ 协调人共识 │ Markdown 总结报告对话流 │ Markdown 预览 │
│ 各席位交付 │ 报告问答、修改、重生成入口 │ 或 FlowGraphPanel │
│ 各线程文件/产物 │ 输入框与附件 │ 文件/沙箱预览 │
│ │ │ │
└───────────────────────────────────┴─────────────────────────────────────┴────────────────────┘
```
其他结果视图:
| 视图 | 中央区域 | 右侧/扩展区域 |
| --- | --- | --- |
| 最终方案 | 汇总后的静态方案和文件清单 | 可查看来源与下载产物。 |
| 经典可视化报告 | 报告生成对话、修订指令 | HTML/沙箱预览,支持全屏和下载。 |
| 结构化仪表盘 | 仪表盘优化对话 | `DashboardApp` 或 HTML 视图,可新窗口打开。 |
| 流程图 | 报告问答和流程图修改指令 | `FlowGraphPanel` 显示节点、关系和层级。 |
常规第三步会隐藏外层研讨左导航,以扩大结果阅读区域;任务深链保留任务环境相关的交付与跳转能力。
## 4. 三步数据衔接
```text
第一步
结构化意图 + 已选智能体/业务链 + 意图线程
│
▼
第二步
席位线程 + 协调人线程 + 对话/交付 + 共识 + 研讨运行快照
│
▼
第三步
Markdown 报告 + HTML 报告 + report-json 仪表盘 + flow-json 流程图 + 任务入库/交付
```
关键约束:
- 第一步未形成有效意图,不能开始第二步。
- 第二步未形成协调人共识,不能进入第三步。
- 第三步的所有产出都应绑定对应的第二步研讨运行快照,避免新一轮会商覆盖历史结果。
- 后端发生模型降级/切换时,前端应保留已收到的流内容并显示实际使用模型或切换提示。
## 5. 主要前端模块索引
| 范围 | 主要文件/目录 |
| --- | --- |
| 页面编排 | `src/roundtable-planning/pages/RoundtablePlanningPage.tsx` |
| 第一步 | `components/Step1Panel.tsx`、`hooks/useStep1Intent.ts`、`api/intent.ts` |
| 推荐与业务链 | `api/recommend.ts`、`components/RecommendAgentsDialog.tsx`、`api/chains.ts` |
| 第二步 | `components/Step2Panel.tsx`、`components/Step2SandboxLayout.tsx`、`hooks/useStep2Orchestration.ts` |
| 多智能体与后台任务 API | `api/multi-agent.ts`、`api/roundtable-jobs.ts` |
| 第三步 | `components/Step3Panel.tsx`、`components/HighFidelityReport.tsx`、`hooks/useStep3Summary.ts`、`hooks/useStep3Report.ts`、`hooks/useStep3Dashboard.ts` |
| 流程图与任务入库 | `api/flow-extract.ts`、`api/ingest.ts` |
| 草稿持久化 | `api/drafts.ts`、`api/task-drafts.ts`、相关草稿 hooks |
@@ -1,49 +0,0 @@
# 麒麟系统 Chromium ~80 真机回归清单
> 背景:Tailwind v4 依赖 `@layer`(Chrome 99+)/`@property`(85+)/`color-mix`、`oklch`(111+),麒麟系统自带的 Chromium 80 多浏览器上整站样式失效。本分支(`feat/tailwind-v3-legacy-chrome`)完成 v4→v3 降级迁移,产物结构性指标已全部达标(详见提交 1607c7fe / 40b02520 / e54abcc6)。本文档供真机验收使用。
## 一、测试准备
1. 在麒麟机器的浏览器地址栏输入 `chrome://version`,记录完整版本号(重点关注是否 ≥84 —— 低于 84 时 flex `gap` 不支持,各处间距会塌陷,需单独反馈)。
2. 部署本分支 `pnpm build` 产物(或开发机 `pnpm preview` 后用麒麟机器访问)。
3. 先跑一次 `pnpm check:legacy-css`(开发机),确认绿色再发版。
## 二、页面巡检(明/暗两套主题各过一遍)
| 页面 | 路径 | 重点检查点 |
|---|---|---|
| 登录/落地页 | `/` | 布局完整、文字阴影(hero 标题)、无裸奔样式 |
| 问答首页 | `/chats/new` | 整体配色、输入框焦点环(回退为内层 outline)、常用提示词栏 |
| 对话流 | 任意会话 | Markdown 渲染(标题/列表/表格/代码块/引用——streamdown 白名单类)、气泡圆角、流式输出 |
| 智能体 | `/page/workspace/agents` 及详情 | 卡片、Tabs、新建页表单、技能穿梭框 |
| 圆桌会商 | roundtable 页 | 左侧步骤条、消息气泡、流程图面板、暗色兜底配色 |
| 任务深链 | `?taskId=&goPath=3qfx/rwfx/xdfx` | 左侧任务卡、目的树、快捷跳转栏(按钮管理配置项) |
| 轻应用/菜单管理/敏感词 | 各管理页 | Tabs、表格、弹窗 |
| 简洁模式 | 外观设置切换 | 无全局导航栏布局、右侧工具箱、引导高亮框 |
| 换肤 | 浅红/暗色/浅蓝/绿/冰蓝/浅黄 | 六套主题各自的 primary/ring 颜色、半透明档(primary/10 等) |
| 大屏(dashboard-agent) | 战情大屏页 | 时间线、图表、暗色文字覆盖 |
| iframe 嵌入 | `?embed=1&theme=dark-blue` | 去全局 chrome、强制主题生效 |
## 三、已知降级点(预期行为,非 bug)
1. **`:has()` 渐进增强**(Chrome <105 不生效):按钮内含图标时内边距略宽、alert 带图标时首列宽度、item 带描述时对齐微差 —— 视觉细节,不影响功能。
2. **input-group 焦点环回退**:聊天输入框的焦点指示从「整框 3px 环」回退为「内层输入控件 2px outline」;校验态从整框环回退为内层红色阴影 —— 仍有明确指示。
3. **`:where()` 圆桌字号缩放**(Chrome <88 不生效):设置页调字号时圆桌页面小字号文本不跟随缩放,基础字号正常。
4. **textarea 自增高**:`field-sizing` 需要 Chrome 123+,旧浏览器走原生 `rows` 行为(已有多行默认值)。
5. **prefers-color-scheme 单块**:产物中 1 处 lightningcss 内部标记(`--lightningcss-light/dark`),无影响。
## 四、重点风险项(出现问题按此排查)
- **整页无样式** → 确认产物是本分支构建(旧 v4 产物在 80 上必然裸奔);查 `@layer`。
- **暗色主题失效** → 查产物 `.dark .dark\:` 前缀选择器是否存在(`pnpm check:legacy-css` 会拦)。
- **弹层错位(下拉/气泡/选择器)** → radix 弹层依赖 `origin-[var(--radix-...)]`,确认类已生成。
- **控制台语法错误/白屏** → JS 侧:确认构建 `target: chrome80` 且 `polyfills.ts` 在 main chunk 首位;记录报错栈反馈。
- **mermaid 流程图 / 地图(maplibre)**:重型库在 80 上的运行时差异,出现异常截图 + 控制台报错反馈,单独处理。
## 五、发版前自检(开发机)
```bash
pnpm build # 构建绿
pnpm check:legacy-css # 产物守卫:@layer/@property/:is() 为 0,color-mix 全部守护
pnpm typecheck # 58 个存量错误 = master 基线(迁移零新增)
```
+5 -11
View File
@@ -12,12 +12,11 @@
"preview": "vite preview",
"typecheck": "tsc --noEmit",
"test:input-mode": "node --experimental-strip-types --test src/components/workspace/input-mode.test.ts",
"test:answer-feedback": "node --experimental-strip-types --test src/components/workspace/agents/agent-feedback-visibility.test.ts src/components/workspace/messages/answer-feedback-eligibility.test.ts src/strategy-components/api/answer-feedback-batching.test.ts",
"test:retrieval-debug": "node --experimental-strip-types --test src/core/llmwiki/retrieval-debug.test.ts",
"test:html-preview": "pnpm exec esbuild src/core/utils/legacy-html-preview.test.ts --bundle --platform=node --format=esm --outfile=.runtime/unit-tests/legacy-html-preview.test.mjs && node --test .runtime/unit-tests/legacy-html-preview.test.mjs",
"test:visualizations": "node --experimental-strip-types --test src/components/workspace/visualizations/visualization-spec.test.ts",
"test:report-collaboration": "npx esbuild src/report-collaboration/tests/event-reducer.test.ts --bundle --platform=node --format=esm --outfile=.runtime/unit-tests/event-reducer.test.mjs && npx esbuild src/report-collaboration/tests/message-adapter.test.ts --bundle --platform=node --format=esm --outfile=.runtime/unit-tests/message-adapter.test.mjs && node --test .runtime/unit-tests/event-reducer.test.mjs .runtime/unit-tests/message-adapter.test.mjs",
"check:legacy-css": "node scripts/check-legacy-css.mjs"
"check:chrome109-css": "node scripts/check-chrome109-css.mjs",
"check:legacy-chrome-css": "node scripts/check-chrome109-css.mjs"
},
"dependencies": {
"@codemirror/lang-css": "^6.3.1",
@@ -71,7 +70,6 @@
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"codemirror": "^6.0.2",
"core-js": "3.45.1",
"date-fns": "^4.1.0",
"dayjs": "^1.11.21",
"dnd-kit": "^0.0.2",
@@ -85,7 +83,6 @@
"leaflet": "^1.9.4",
"lucide-react": "^0.562.0",
"maplibre-gl": "^6.9.0",
"marked": "16.4.2",
"mermaid": "^11.15.0",
"motion": "^12.26.2",
"nanoid": "^5.1.6",
@@ -114,17 +111,17 @@
"zod": "^3.24.2"
},
"devDependencies": {
"@tailwindcss/postcss": "^4.0.15",
"@types/file-saver": "^2.0.7",
"@types/gsap": "^3.0.0",
"@types/node": "^20.14.10",
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0",
"@vitejs/plugin-react": "^5.0.4",
"autoprefixer": "^10.4.20",
"lightningcss": "^1.30.2",
"postcss": "^8.5.3",
"tailwindcss": "^3.4.17",
"tailwindcss-animate": "^1.0.7",
"tailwindcss": "^4.0.15",
"tw-animate-css": "^1.4.0",
"typescript": "^5.8.2",
"vite": "^6.0.0",
"vite-plugin-source-identifier": "^1.1.2"
@@ -132,8 +129,5 @@
"overrides": {
"@radix-ui/react-slot": "1.3.3"
},
"browserslist": [
"Chrome >= 80"
],
"packageManager": "pnpm@10.26.2"
}
+8 -9
View File
@@ -1,12 +1,11 @@
import tailwindcss from "tailwindcss";
import darkDescendant from "./scripts/postcss-dark-descendant.mjs";
import autoprefixer from "autoprefixer";
import tailwindcss from "@tailwindcss/postcss";
import legacyColorFallback from "./scripts/postcss-legacy-color-fallback.mjs";
import lightningCssLegacyChrome from "./scripts/postcss-lightningcss-chrome109.mjs";
// Tailwind v3:透明度修饰符(bg-primary/10 等)由 tailwind.config.ts 里的
// --legacy-*-rgb 通道变量直接实现,不再需要 v4 时代的 color-mix 回退插件;
// dark-descendant 把暗色变体的 :is(.dark *) 改写为 Chrome 80 可读的后代形式;
// dev 环境面向开发者的现代 Chrome,产物侧的旧浏览器降级(:is()/逻辑属性/
// 媒体查询 range 语法/厂商前缀)由 vite 的 lightningcss targets 负责。
export default {
plugins: [tailwindcss, darkDescendant, autoprefixer],
plugins: [
tailwindcss(),
legacyColorFallback(),
lightningCssLegacyChrome(),
],
};
@@ -1,10 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 52 52">
<defs>
<linearGradient id="ap-add" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox">
<stop offset="0" stop-color="#f5222d"/>
<stop offset="1" stop-color="#a8071a"/>
</linearGradient>
</defs>
<rect width="52" height="52" rx="8" fill="#ffcfd1"/>
<path fill="url(#ap-add)" d="M26 14a2 2 0 0 1 2 2v8h8a2 2 0 1 1 0 4h-8v8a2 2 0 1 1-4 0v-8h-8a2 2 0 1 1 0-4h8v-8a2 2 0 0 1 2-2z"/>
</svg>

Before

Width:  |  Height:  |  Size: 503 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="52" height="52" viewBox="0 0 52 52"><defs><style>.a{fill:#ffcfd1;}.b{fill:url(#a);}</style><linearGradient id="a" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#f5222d"/><stop offset="1" stop-color="#a8071a"/></linearGradient></defs><g transform="translate(0 -116.002)"><rect class="a" width="52" height="52" rx="8" transform="translate(0 116.002)"/><g transform="translate(2.236 118.236)"><path class="b" d="M9204.336-22218.762a6.4,6.4,0,0,1-2.489-.691,6.242,6.242,0,0,1-2-1.615,6.363,6.363,0,0,1-1.206-2.283,6.357,6.357,0,0,1-.246-1.863c-.047-.033-.094-.066-.139-.1a6.4,6.4,0,0,1-2.272-3.4,6.418,6.418,0,0,1,.268-4.076,6.336,6.336,0,0,1,1.233-1.912,6.383,6.383,0,0,1-.4-1.973,6.41,6.41,0,0,1,.53-2.809,6.441,6.441,0,0,1,1.7-2.289,6.424,6.424,0,0,1,1.751-1.057,4.969,4.969,0,0,1,.343-1.289,4.965,4.965,0,0,1,1.334-1.859,5.038,5.038,0,0,1,2.016-1.082,5.037,5.037,0,0,1,2.289-.074,5.024,5.024,0,0,1,2.089.943,4.947,4.947,0,0,1,.871.861,5.147,5.147,0,0,1,.876-.861,5,5,0,0,1,2.083-.943,5.035,5.035,0,0,1,2.289.074,5.06,5.06,0,0,1,2.021,1.082,5.031,5.031,0,0,1,1.334,1.859,5.008,5.008,0,0,1,.343,1.289,6.424,6.424,0,0,1,1.751,1.057,6.441,6.441,0,0,1,1.7,2.289,6.405,6.405,0,0,1,.524,2.809,6.434,6.434,0,0,1-.4,1.973,6.315,6.315,0,0,1,1.234,1.912,6.418,6.418,0,0,1,.268,4.076,6.4,6.4,0,0,1-2.272,3.4l-.143.105a6.214,6.214,0,0,1-.248,1.859,6.26,6.26,0,0,1-1.2,2.283,6.271,6.271,0,0,1-2.01,1.615,6.354,6.354,0,0,1-2.485.691c-.14.006-.278.012-.418.012a6.213,6.213,0,0,1-2.139-.375,6.394,6.394,0,0,1-2.2-1.34,6.4,6.4,0,0,1-.915-1.066,6.415,6.415,0,0,1-.91,1.066,6.427,6.427,0,0,1-2.206,1.34,6.283,6.283,0,0,1-2.143.377C9204.609-22218.748,9204.473-22218.752,9204.336-22218.762Zm6.768-6.342a4.232,4.232,0,0,0,.346,1.652,4.123,4.123,0,0,0,.972,1.379,4.116,4.116,0,0,0,1.44.877,4.062,4.062,0,0,0,1.67.234,4.159,4.159,0,0,0,1.63-.447,4.159,4.159,0,0,0,1.313-1.061,4.227,4.227,0,0,0,.787-1.49c.02-.07.037-.139.054-.209a6.32,6.32,0,0,1-1.422.164,1.1,1.1,0,0,1-1.1-1.1,1.1,1.1,0,0,1,1.1-1.1,4.178,4.178,0,0,0,2.529-.859,4.138,4.138,0,0,0,1.485-2.221,4.216,4.216,0,0,0-.173-2.67,4.2,4.2,0,0,0-1.765-2.01,1.1,1.1,0,0,1-.4-1.5,1.1,1.1,0,0,1,1.063-.543,4.16,4.16,0,0,0,.1-.758,4.249,4.249,0,0,0-.346-1.838,4.156,4.156,0,0,0-1.117-1.5,4.078,4.078,0,0,0-.569-.408,4.928,4.928,0,0,1-.385.838,1.1,1.1,0,0,1-.955.553,1.08,1.08,0,0,1-.547-.15,1.093,1.093,0,0,1-.4-1.5,2.906,2.906,0,0,0,.374-1.229,1.022,1.022,0,0,1,.006-.145,2.841,2.841,0,0,0-.218-1.133,2.836,2.836,0,0,0-.754-1.051,2.794,2.794,0,0,0-1.139-.607,2.8,2.8,0,0,0-1.29-.045,2.782,2.782,0,0,0-1.173.535,2.84,2.84,0,0,0-.82.994,2.912,2.912,0,0,0-.3,1.262v5.254a4.426,4.426,0,0,0,.877,2.625,4.4,4.4,0,0,0,2.277,1.58,1.1,1.1,0,0,1,.748,1.361,1.1,1.1,0,0,1-1.367.748,6.6,6.6,0,0,1-2.535-1.41v6.928Zm-10.352,1.145a4.119,4.119,0,0,0,.787,1.49,4.148,4.148,0,0,0,1.313,1.061,4.105,4.105,0,0,0,1.624.447,4.076,4.076,0,0,0,1.676-.234,4.125,4.125,0,0,0,1.44-.877,4.208,4.208,0,0,0,.972-1.379,4.226,4.226,0,0,0,.34-1.652v-6.924a6.628,6.628,0,0,1-2.534,1.406,1.117,1.117,0,0,1-.308.045,1.1,1.1,0,0,1-1.055-.793,1.093,1.093,0,0,1,.748-1.361,4.393,4.393,0,0,0,2.272-1.58,4.354,4.354,0,0,0,.876-2.625v-5.254a2.906,2.906,0,0,0-.29-1.262,2.84,2.84,0,0,0-.82-.994,2.778,2.778,0,0,0-1.179-.535,2.8,2.8,0,0,0-1.29.045,2.832,2.832,0,0,0-1.139.607,2.821,2.821,0,0,0-.748,1.051,2.819,2.819,0,0,0-.212,1.271,2.821,2.821,0,0,0,.374,1.234,1.1,1.1,0,0,1-.4,1.5,1.1,1.1,0,0,1-1.5-.4,5.009,5.009,0,0,1-.386-.838,4.127,4.127,0,0,0-.568.408,4.156,4.156,0,0,0-1.117,1.5,4.249,4.249,0,0,0-.346,1.838,4.246,4.246,0,0,0,.1.758,1.106,1.106,0,0,1,1.064.543,1.1,1.1,0,0,1-.4,1.5,4.2,4.2,0,0,0-1.765,2.01,4.216,4.216,0,0,0-.173,2.67,4.138,4.138,0,0,0,1.485,2.221,4.178,4.178,0,0,0,2.529.859,1.1,1.1,0,0,1,1.1,1.1,1.1,1.1,0,0,1-1.1,1.1,6.32,6.32,0,0,1-1.422-.164C9200.714-22224.1,9200.732-22224.029,9200.752-22223.959Z" transform="translate(-9186.242 22256.754)"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 3.9 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="52" height="52" viewBox="0 0 52 52"><defs><style>.a{fill:#ffcfd1;}.b{opacity:0;}.b,.c{fill:url(#a);}</style><linearGradient id="a" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#f5222d"/><stop offset="1" stop-color="#a8071a"/></linearGradient></defs><g transform="translate(0 -116.002)"><rect class="a" width="52" height="52" rx="8" transform="translate(0 116.002)"/><g transform="translate(18559 4825)"><rect class="b" width="42" height="42" transform="translate(-18554 -4704)"/><path class="c" d="M-9736.837-26950.139a1.008,1.008,0,0,1-.542-.889v-3.371h-.752a4.506,4.506,0,0,1-4.5-4.5v-2.629c-1.89-.08-3.366-2-3.366-4.367s1.477-4.287,3.366-4.369v-2.633a4.5,4.5,0,0,1,4.5-4.5h15.658v.129a3.676,3.676,0,0,0,.494,1.869h-16.152a2.5,2.5,0,0,0-2.5,2.5v14a2.5,2.5,0,0,0,2.5,2.5h1.741a1.006,1.006,0,0,1,1.009,1v2.432l4.544-3.244a.97.97,0,0,1,.576-.189h13.124a2.5,2.5,0,0,0,2.506-2.5v-9.441a3.524,3.524,0,0,0,1.118.189h.033a3.634,3.634,0,0,0,2.764-1.293,4.793,4.793,0,0,1,1.456,3.549,5.014,5.014,0,0,1-.982,3.041,3.23,3.23,0,0,1-2.391,1.334v2.621a4.507,4.507,0,0,1-4.5,4.5h-12.806l-5.858,4.184a1.021,1.021,0,0,1-.582.191A1.007,1.007,0,0,1-9736.837-26950.139Zm1.334-10.389a1.876,1.876,0,0,1-1.876-1.877v-7.869a1.876,1.876,0,0,1,1.876-1.877h15.739a1.876,1.876,0,0,1,1.876,1.877v7.869a1.876,1.876,0,0,1-1.876,1.877Zm10.931-5.811a1.752,1.752,0,0,0,1.754,1.746,1.751,1.751,0,0,0,1.747-1.746,1.754,1.754,0,0,0-1.747-1.756A1.755,1.755,0,0,0-9724.572-26966.338Zm-9.617,0a1.752,1.752,0,0,0,1.748,1.746,1.751,1.751,0,0,0,1.747-1.746,1.755,1.755,0,0,0-1.747-1.756A1.755,1.755,0,0,0-9734.189-26966.338Zm20.1-5.277-.453-1.551a4.433,4.433,0,0,0-2.946-3.006l-1.537-.467a.649.649,0,0,1-.447-.611.524.524,0,0,1,.021-.148.616.616,0,0,1,.217-.346.624.624,0,0,1,.217-.115l.284-.088,1.232-.365a4.417,4.417,0,0,0,2.96-3.02l.46-1.551a.625.625,0,0,1,.42-.434v.006a.538.538,0,0,1,.183-.033.574.574,0,0,1,.292.08.581.581,0,0,1,.3.381l.46,1.557a4.422,4.422,0,0,0,2.96,3.014l1.171.346.346.107a.647.647,0,0,1,.454.609.641.641,0,0,1-.447.611l-1.537.467a4.434,4.434,0,0,0-2.946,3.006l-.453,1.551a.631.631,0,0,1-.6.461A.636.636,0,0,1-9714.089-26971.615Zm-4.571-7.34-.183-.623a2.7,2.7,0,0,0-1.829-1.83l-.623-.189a.29.29,0,0,1-.2-.277.284.284,0,0,1,.2-.277l.61-.184a2.7,2.7,0,0,0,1.842-1.842l.183-.615a.32.32,0,0,1,.2-.2.327.327,0,0,1,.224.027.275.275,0,0,1,.143.17l.183.615a2.713,2.713,0,0,0,1.842,1.842l.609.184a.289.289,0,0,1,.21.277.3.3,0,0,1-.21.277l-.257.076-.366.113a2.725,2.725,0,0,0-1.828,1.83l-.183.623a.293.293,0,0,1-.278.2A.3.3,0,0,1-9718.66-26978.955Z" transform="translate(-8805.37 22282.029)"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

-1
View File
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1920" height="1080" viewBox="0 0 1920 1080"><defs><style>.a{fill:url(#a);}</style><pattern id="a" preserveAspectRatio="xMidYMid slice" width="100%" height="100%" viewBox="0 0 3840 2160"><image width="3840" height="2160" xlink:href="data:image/png;base64,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 truncated

Before

Width:  |  Height:  |  Size: 1.7 MiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="582" height="667" viewBox="0 0 582 667"><image width="582" height="667" xlink:href="data:image/png;base64,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 truncated

Before

Width:  |  Height:  |  Size: 664 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="139" height="765" viewBox="0 0 139 765"><defs><style>.a{fill:url(#a);}</style><pattern id="a" width="1" height="1" patternTransform="matrix(-1, 0, 0, 1, 278, 0)" viewBox="0 0 139 765"><image preserveAspectRatio="xMidYMid slice" width="139" height="765" xlink:href="data:image/png;base64,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 truncated

Before

Width:  |  Height:  |  Size: 51 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="139" height="765" viewBox="0 0 139 765"><defs><style>.a{fill:url(#a);}</style><pattern id="a" preserveAspectRatio="xMidYMid slice" width="100%" height="100%" viewBox="0 0 278 1530"><image width="278" height="1530" xlink:href="data:image/png;base64,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 truncated

Before

Width:  |  Height:  |  Size: 51 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="273" height="323" viewBox="0 0 273 323"><image width="273" height="323" xlink:href="data:image/png;base64,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 truncated

Before

Width:  |  Height:  |  Size: 193 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="727" height="727" viewBox="0 0 727 727"><defs><style>.a{fill:url(#a);}.b{fill:url(#d);}.c,.d,.f{fill:none;}.c{stroke:rgba(32,194,255,0);stroke-width:8px;}.d{stroke:rgba(255,173,32,0.15);stroke-width:5px;stroke-dasharray:7 5;}.e{stroke:none;}.g{filter:url(#e);}.h{filter:url(#b);}</style><linearGradient id="a" x1="0.761" y1="0.205" x2="0.284" y2="0.581" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#ffd2ab"/><stop offset="1" stop-color="#ff7855"/></linearGradient><filter id="b" x="88.068" y="60.324" width="217.004" height="181.59" filterUnits="userSpaceOnUse"><feOffset input="SourceAlpha"/><feGaussianBlur stdDeviation="7.5" result="c"/><feFlood flood-color="#ff941a" flood-opacity="0.4"/><feComposite operator="in" in2="c"/><feComposite in="SourceGraphic"/></filter><linearGradient id="d" x1="0.237" y1="0.761" x2="0.718" y2="0.394" xlink:href="#a"/><filter id="e" x="424.041" y="484.359" width="215.309" height="181.689" filterUnits="userSpaceOnUse"><feOffset input="SourceAlpha"/><feGaussianBlur stdDeviation="7.5" result="f"/><feFlood flood-color="#ff941a" flood-opacity="0.4"/><feComposite operator="in" in2="f"/><feComposite in="SourceGraphic"/></filter></defs><g transform="translate(4 4)"><g transform="translate(-126.998 -127.002)"><g class="h" transform="matrix(1, 0, 0, 1, 123, 123)"><path class="a" d="M18115.566-21172.494q4.919-8.443,10.389-16.543a294.531,294.531,0,0,1,35.713-43.289,294.545,294.545,0,0,1,43.293-35.717,292.5,292.5,0,0,1,49.682-26.969,290.614,290.614,0,0,1,31.271-11.162l1.656,5.506a288.092,288.092,0,0,0-166.973,131.084Z" transform="translate(-18005 21389)"/></g><g class="g" transform="matrix(1, 0, 0, 1, 123, 123)"><path class="b" d="M18451.539-20750.967a288.209,288.209,0,0,0,165.279-131.172l5.029,2.92q-5.1,8.815-10.8,17.258a294.659,294.659,0,0,1-35.717,43.287,294.647,294.647,0,0,1-43.293,35.717,292.2,292.2,0,0,1-49.686,26.971,291.1,291.1,0,0,1-29.178,10.537Z" transform="translate(-18005 21389)"/></g><circle class="c" cx="359.5" cy="359.5" r="359.5" transform="translate(126.998 127.002)"/></g><g class="d" transform="translate(98 98)"><circle class="e" cx="261.5" cy="261.5" r="261.5"/><circle class="f" cx="261.5" cy="261.5" r="259"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="727" height="727" viewBox="0 0 727 727"><defs><style>.a{fill:url(#a);}.b{fill:url(#d);}.c,.d,.f{fill:none;}.c{stroke:rgba(32,194,255,0);stroke-width:8px;}.d{stroke:rgba(255,173,32,0.15);stroke-width:5px;stroke-dasharray:7 5;}.e{stroke:none;}.g{filter:url(#e);}.h{filter:url(#b);}</style><linearGradient id="a" x1="0.761" y1="0.205" x2="0.284" y2="0.581" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#ffd2ab"/><stop offset="1" stop-color="#ff7855"/></linearGradient><filter id="b" x="88.068" y="60.324" width="217.004" height="181.59" filterUnits="userSpaceOnUse"><feOffset input="SourceAlpha"/><feGaussianBlur stdDeviation="7.5" result="c"/><feFlood flood-color="#ff941a" flood-opacity="0.4"/><feComposite operator="in" in2="c"/><feComposite in="SourceGraphic"/></filter><linearGradient id="d" x1="0.237" y1="0.761" x2="0.718" y2="0.394" xlink:href="#a"/><filter id="e" x="424.041" y="484.359" width="215.309" height="181.689" filterUnits="userSpaceOnUse"><feOffset input="SourceAlpha"/><feGaussianBlur stdDeviation="7.5" result="f"/><feFlood flood-color="#ff941a" flood-opacity="0.4"/><feComposite operator="in" in2="f"/><feComposite in="SourceGraphic"/></filter></defs><g transform="translate(4 4)"><g transform="translate(-126.998 -127.002)"><g class="h" transform="matrix(1, 0, 0, 1, 123, 123)"><path class="a" d="M18115.566-21172.494q4.919-8.443,10.389-16.543a294.531,294.531,0,0,1,35.713-43.289,294.545,294.545,0,0,1,43.293-35.717,292.5,292.5,0,0,1,49.682-26.969,290.614,290.614,0,0,1,31.271-11.162l1.656,5.506a288.092,288.092,0,0,0-166.973,131.084Z" transform="translate(-18005 21389)"/></g><g class="g" transform="matrix(1, 0, 0, 1, 123, 123)"><path class="b" d="M18451.539-20750.967a288.209,288.209,0,0,0,165.279-131.172l5.029,2.92q-5.1,8.815-10.8,17.258a294.659,294.659,0,0,1-35.717,43.287,294.647,294.647,0,0,1-43.293,35.717,292.2,292.2,0,0,1-49.686,26.971,291.1,291.1,0,0,1-29.178,10.537Z" transform="translate(-18005 21389)"/></g><circle class="c" cx="359.5" cy="359.5" r="359.5" transform="translate(126.998 127.002)"/></g><g class="d" transform="translate(98 98)"><circle class="e" cx="261.5" cy="261.5" r="261.5"/><circle class="f" cx="261.5" cy="261.5" r="259"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="458" height="113.588" viewBox="0 0 458 113.588"><defs><style>.a{opacity:0.78;}.b{fill:url(#a);}.c{fill:#fff;}.d{filter:url(#d);}.e{filter:url(#b);}</style><linearGradient id="a" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff9c1"/></linearGradient><filter id="b" x="104.221" y="19.443" width="226.559" height="61.289" filterUnits="userSpaceOnUse"><feOffset dy="1" input="SourceAlpha"/><feGaussianBlur stdDeviation="5.5" result="c"/><feFlood flood-color="#fe0" flood-opacity="0.71"/><feComposite operator="in" in2="c"/><feComposite in="SourceGraphic"/></filter><filter id="d" x="104.221" y="19.443" width="226.559" height="61.289" filterUnits="userSpaceOnUse"><feOffset input="SourceAlpha"/><feGaussianBlur stdDeviation="2" result="e"/><feFlood flood-color="#fff" result="f"/><feComposite operator="out" in="SourceGraphic" in2="e"/><feComposite operator="in" in="f"/><feComposite operator="in" in2="SourceGraphic"/></filter></defs><g transform="translate(-731 -564.412)"><image class="a" width="458" height="113.588" transform="translate(731 564.412)" xlink:href="data:image/png;base64,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 truncated

Before

Width:  |  Height:  |  Size: 625 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="68" viewBox="0 0 68 68"><defs><style>.a{opacity:0;fill:url(#a);}.b{fill:url(#b);}</style><linearGradient id="a" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#f3212c"/><stop offset="1" stop-color="#aa071a"/></linearGradient><linearGradient id="b" x1="0.405" x2="1" xlink:href="#a"/></defs><g transform="translate(14482.893 -23044.904)"><rect class="a" width="68" height="68" transform="translate(-14482.893 23044.904)"/><path class="b" d="M110.023,105.37H98.2a1.721,1.721,0,0,1-1.716-1.716v-1.918h10.189a1.721,1.721,0,0,0,1.716-1.716V72.8a1.721,1.721,0,0,0-1.716-1.716H98.2V67.437A3.444,3.444,0,0,0,94.76,64H87.83a3.444,3.444,0,0,0-3.437,3.437v3.652H75.625A1.721,1.721,0,0,0,73.91,72.8v27.21a1.721,1.721,0,0,0,1.716,1.716h10.49v1.918a1.721,1.721,0,0,1-1.716,1.716H72.3a1.721,1.721,0,0,0-1.716,1.716v10.1A1.721,1.721,0,0,0,72.3,118.9h37.724a1.721,1.721,0,0,0,1.716-1.716v-10.1A1.726,1.726,0,0,0,110.023,105.37Zm-8.406-19.1a3.437,3.437,0,1,1-3.437-3.437A3.436,3.436,0,0,1,101.616,86.266ZM87.83,67.437h6.924v3.646H87.83ZM81.121,86.266A3.437,3.437,0,1,1,84.558,89.7,3.436,3.436,0,0,1,81.121,86.266Zm32.48-7.089V93.355a1.716,1.716,0,0,1-3.431,0V79.177a1.716,1.716,0,0,1,3.431,0Zm5.122,3.548v6.881a1.716,1.716,0,0,1-3.431,0V82.724a1.716,1.716,0,0,1,3.431,0ZM70.644,95.07a1.717,1.717,0,0,1-1.716-1.716V79.177a1.716,1.716,0,0,1,3.431,0V93.355A1.713,1.713,0,0,1,70.644,95.07ZM67.231,82.724v6.881a1.716,1.716,0,1,1-3.431,0V82.724a1.716,1.716,0,0,1,3.431,0Zm0,0" transform="translate(-14540.154 22987.455)"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="188" height="241" viewBox="0 0 188 241"><defs><style>.a{fill:url(#a);}.b{fill:#fff;opacity:0.47;}</style><pattern id="a" preserveAspectRatio="xMidYMid slice" width="100%" height="100%" viewBox="0 0 376 482"><image width="376" height="482" xlink:href="data:image/png;base64,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 truncated

Before

Width:  |  Height:  |  Size: 68 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="68" viewBox="0 0 68 68"><defs><style>.a{fill:#fff;stroke:#707070;stroke-width:3.75px;opacity:0;}.b{fill:url(#a);}.c{stroke:none;}.d{fill:none;}</style><linearGradient id="a" x1="0.431" x2="1" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#f3212c"/><stop offset="1" stop-color="#aa071a"/></linearGradient></defs><g transform="translate(-71.077 -67.746)"><g class="a" transform="translate(71.077 67.746)"><rect class="c" width="68" height="68"/><rect class="d" x="1.875" y="1.875" width="64.25" height="64.25"/></g><path class="b" d="M114.406,106.791a7.707,7.707,0,0,0-4.354,1.353L98.7,99.937a13.3,13.3,0,0,0,1.742-6.583c0-.421-.03-.842-.06-1.263L112,85.207a4.687,4.687,0,1,0-1.952-2.345L99.691,88.995a13.678,13.678,0,0,0-6.1-7.365l2.072-10.341c.15,0,.3.03.451.03a4.66,4.66,0,1,0-4.655-4.659,4.727,4.727,0,0,0,1.412,3.367l-2.1,10.462A13.479,13.479,0,0,0,80.05,81.87l-6.4-5.712A6.129,6.129,0,1,0,71.7,78.443L77.677,83.7a13.456,13.456,0,0,0,.691,19.991l-5.316,5.622a5.948,5.948,0,0,0-3.394-1.022,6.163,6.163,0,1,0,6.156,6.162,6.343,6.343,0,0,0-.721-2.916l5.826-6.193a13.464,13.464,0,0,0,16.1-2.946l11.022,7.966a7.77,7.77,0,0,0-1.2,4.118,7.658,7.658,0,1,0,15.316,0A7.817,7.817,0,0,0,114.406,106.791Zm0,0" transform="translate(13 9.671)"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

@@ -1,13 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="68" viewBox="0 0 68 68">
<defs>
<linearGradient id="ap-idea" x1="0.405" x2="1" y2="1" gradientUnits="objectBoundingBox">
<stop offset="0" stop-color="#f3212c"/>
<stop offset="1" stop-color="#aa071a"/>
</linearGradient>
</defs>
<g fill="url(#ap-idea)" transform="translate(12 10)">
<path d="M22 2.2A12.8 12.8 0 0 0 9.2 15c0 5.1 2.9 9.5 7.1 11.6v3.8a2.4 2.4 0 0 0 2.4 2.4h6.6a2.4 2.4 0 0 0 2.4-2.4v-3.8A12.8 12.8 0 0 0 34.8 15 12.8 12.8 0 0 0 22 2.2Zm3.3 26.8h-6.6v-2.1h6.6Zm-3.3-26.8A10.4 10.4 0 0 1 32.4 15a10.4 10.4 0 0 1-6.3 9.5 2.4 2.4 0 0 0-1.3 2.1v.3h-5.6v-.3a2.4 2.4 0 0 0-1.3-2.1A10.4 10.4 0 0 1 11.6 15 10.4 10.4 0 0 1 22 2.2Z"/>
<path d="M17.6 39.2a2 2 0 0 0 2 2h4.8a2 2 0 0 0 2-2v-1.4h-8.8Zm-1.8-3.8h12.4a1.6 1.6 0 1 0 0-3.2H15.8a1.6 1.6 0 1 0 0 3.2Z"/>
<path d="M8.4 22.6a1.6 1.6 0 0 0 0-3.2H3.8a1.6 1.6 0 1 0 0 3.2Zm31.8 0a1.6 1.6 0 0 0 0-3.2h-4.6a1.6 1.6 0 1 0 0 3.2ZM7.2 10.8a1.6 1.6 0 0 0 2.3-2.3L6.2 5.3A1.6 1.6 0 0 0 4 7.6Zm29.3-2.3a1.6 1.6 0 0 0 2.3 2.3l3.2-3.2A1.6 1.6 0 1 0 39.7 5.3Z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="68" viewBox="0 0 68 68"><defs><style>.a{fill:#fff;opacity:0;}.b{fill:url(#a);}</style><linearGradient id="a" x1="0.405" x2="1" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#f3212c"/><stop offset="1" stop-color="#aa071a"/></linearGradient></defs><g transform="translate(14482.893 -23044.904)"><rect class="a" width="68" height="68" transform="translate(-14482.893 23044.904)"/><path class="b" d="M43.013,57.336h-.255l-.074,0a14.064,14.064,0,0,1-8.911-3.467,6.216,6.216,0,0,1,6.1-5.029h6.278a6.218,6.218,0,0,1,6.1,5.03A14.073,14.073,0,0,1,43.6,57.324h-.009l-.067,0H43.5l-.063,0h-.424ZM30.159,54.9H8.5a1.717,1.717,0,0,1-1.715-1.716v-10.1A1.717,1.717,0,0,1,8.5,41.363H20.6a1.717,1.717,0,0,0,1.716-1.715V37.73H11.824a1.717,1.717,0,0,1-1.716-1.715V8.8a1.718,1.718,0,0,1,1.716-1.716h8.768V3.437A3.44,3.44,0,0,1,24.029,0h6.93A3.441,3.441,0,0,1,34.4,3.437V7.089H42.87A1.718,1.718,0,0,1,44.586,8.8V26.022c-.515-.046-1.044-.07-1.574-.07A17.327,17.327,0,0,0,30.157,54.9Zm4.219-36.07a3.437,3.437,0,1,0,3.438,3.437A3.441,3.441,0,0,0,34.378,18.828Zm-13.619,0A3.437,3.437,0,1,0,24.2,22.265,3.441,3.441,0,0,0,20.758,18.828ZM24.029,3.437V7.083h6.924V3.437Zm7.256,47.59v0a14.059,14.059,0,1,1,23.456,0,9.508,9.508,0,0,0-8.589-5.455H44.686a7.193,7.193,0,1,0-3.347,0H39.873a9.5,9.5,0,0,0-8.587,5.457ZM43.013,42.5a3.923,3.923,0,1,1,3.923-3.924A3.928,3.928,0,0,1,43.013,42.5ZM6.844,31.07a1.717,1.717,0,0,1-1.716-1.715V15.176a1.715,1.715,0,1,1,3.431,0V29.355A1.717,1.717,0,0,1,6.844,31.07ZM49.8,27.327h0a17.187,17.187,0,0,0-3.429-1.051v-11.1a1.715,1.715,0,1,1,3.431,0v12.15Zm3.406-.007a1.717,1.717,0,0,1-1.715-1.715V18.724a1.715,1.715,0,0,1,3.431,0v6.881A1.717,1.717,0,0,1,53.206,27.32Zm-51.491,0A1.717,1.717,0,0,1,0,25.605V18.724a1.715,1.715,0,0,1,3.431,0v6.881A1.717,1.717,0,0,1,1.715,27.32Z" transform="translate(-14477.664 23050.15)"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

@@ -1,14 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="68" viewBox="0 0 68 68">
<defs>
<linearGradient id="ap-task" x1="0.405" x2="1" y2="1" gradientUnits="objectBoundingBox">
<stop offset="0" stop-color="#f3212c"/>
<stop offset="1" stop-color="#aa071a"/>
</linearGradient>
</defs>
<g fill="url(#ap-task)" transform="translate(14 12)">
<path d="M28.4 2.2H15.6A3.4 3.4 0 0 0 12.2 5.6v2.8H8.6A3.4 3.4 0 0 0 5.2 11.8v28.8A3.4 3.4 0 0 0 8.6 44h22.8a3.4 3.4 0 0 0 3.4-3.4V11.8a3.4 3.4 0 0 0-3.4-3.4h-3.6V5.6A3.4 3.4 0 0 0 28.4 2.2Zm-12.8 3.4h12.8v2.8H15.6Zm19.2 35.8H8.6V11.8h3.6v2.2a1.6 1.6 0 0 0 1.6 1.6h12.8a1.6 1.6 0 0 0 1.6-1.6v-2.2h3.6Z"/>
<rect x="11.4" y="24.2" width="3.6" height="11.6" rx="1.2"/>
<rect x="18.2" y="20.4" width="3.6" height="15.4" rx="1.2"/>
<rect x="25" y="27.2" width="3.6" height="8.6" rx="1.2"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 924 B

+3 -8
View File
@@ -40,7 +40,7 @@ window.__CM_RUNTIME_CONFIG__ = {
// Canvas/AI 写作独立 LangGraph 地址:为空时前端会回退使用 VITE_LANGGRAPH_BASE_URL。
VITE_CANVAS_LANGGRAPH_BASE_URL: "",
// 地图瓦片地址模板:仅供普通问答消息列表中的交互地图使用。
// 地图瓦片地址模板:普通问答地图和生成的 HTML 网页地图共同使用。
// 后续接入内网瓦片服务时,只需替换此项并保留 {z}/{x}/{y} 占位符。
VITE_MAP_TILE_URL: "http://119.254.86.251:8023/tiles/{z}/{x}/{y}.png?v=zh-z14-13",
@@ -98,10 +98,10 @@ window.__CM_RUNTIME_CONFIG__ = {
VITE_AIPI_MOPECHAT_URL: "https://ch1.b.uat.4.cn/likun_b1_mope",
// 工作室/空间后端接口:空间列表、空间详情、素材上传等使用。
VITE_AIPI_BACKENP_URL: "https://knowledgetoolserver.b.uat.4.cn",
VITE_AIPI_BACKENP_URL: "http://47.88.25.99:8000",
// 工作室/空间后端别名:兼容旧配置命名,通常与 VITE_AIPI_BACKENP_URL 保持一致。
VITE_NOTEBOOK_API_BASE_URL: "https://knowledgetoolserver.b.uat.4.cn",
VITE_NOTEBOOK_API_BASE_URL: "http://47.88.25.99:8000",
// 工作室/空间前端地址:用于 auth/callback、新建对话等跳转。
VITE_AIPI_FRONTEND_URL: "http://47.88.25.99:3000",
@@ -155,11 +155,6 @@ window.__CM_RUNTIME_CONFIG__ = {
// GitHub OAuth Token;不使用 GitHub 相关能力时留空。
VITE_GITHUB_OAUTH_TOKEN: "",
// 是否在问答输入框「模式」菜单显示「极速」:"true" 显示,"false" 隐藏。
// 默认关闭。开启后可直连大模型流式问答,不走智能体工具与技能。
// 部署后改 dist/runtime-config.js 再刷新页面即可,无需重新打包。
VITE_TURBO_MODE_VISIBLE: "true",
// 是否在智能体管理页显示「舆情分析」类型:"true" 显示,"false" 隐藏。
// 关闭后,该智能体的专用对话地址也会自动跳回智能体管理页。
VITE_SENTIMENT_AGENT_VISIBLE: "true",
@@ -0,0 +1,119 @@
import fs from "node:fs";
import path from "node:path";
import postcss from "postcss";
const unsupportedColor = /(?:color-mix|oklch|oklab|lab|lch)\(/i;
const assetsDir = path.resolve("dist/assets");
if (!fs.existsSync(assetsDir)) {
throw new Error("dist/assets 不存在,请先运行 pnpm build");
}
const cssFiles = fs
.readdirSync(assetsDir)
.filter((file) => file.endsWith(".css"));
if (cssFiles.length === 0) {
throw new Error("dist/assets 中没有 CSS 构建产物");
}
const failures = [];
let modernDeclarations = 0;
const requiredLegacyFallbacks = [
{
file: "src/components/ui/textarea.tsx",
pattern: /rows=\{rows\s*\?\?\s*3\}/,
description: "Textarea needs a native rows fallback",
},
{
file: "src/components/ai-elements/prompt-input.tsx",
pattern: /<InputGroup className="h-auto min-h-16">/,
description: "Prompt textarea must not rely on :has() for its parent height",
},
{
file: "src/core/utils/mermaid.ts",
pattern: /htmlLabels:\s*false[\s\S]*secure:\s*\[[\s\S]*"htmlLabels"/,
description: "Sandbox flowcharts must use native SVG labels in legacy browsers",
},
{
file: "src/core/utils/legacy-html-preview.ts",
pattern: /export function downlevelModernColors[\s\S]*function injectLegacyChartShim/,
description: "Generated HTML charts must downlevel modern CSS colors for Chrome 109",
},
];
for (const file of cssFiles) {
const root = postcss.parse(
fs.readFileSync(path.join(assetsDir, file), "utf8"),
{ from: file },
);
root.walkDecls((declaration) => {
if (!unsupportedColor.test(declaration.value)) return;
modernDeclarations += 1;
let ancestor = declaration.parent;
while (ancestor) {
if (
ancestor.type === "atrule" &&
ancestor.name === "supports" &&
unsupportedColor.test(ancestor.params)
) {
return;
}
ancestor = ancestor.parent;
}
let previous = declaration.prev();
while (previous?.type === "comment") previous = previous.prev();
const hasSafeFallback =
!declaration.prop.startsWith("--") &&
previous?.type === "decl" &&
previous.prop === declaration.prop &&
!unsupportedColor.test(previous.value);
if (!hasSafeFallback) {
failures.push(
`${file}:${declaration.source?.start?.line ?? "?"} ${declaration.prop}: ${declaration.value}`,
);
}
});
}
function walk(directory) {
return fs.readdirSync(directory, { withFileTypes: true }).flatMap((entry) => {
const fullPath = path.join(directory, entry.name);
return entry.isDirectory() ? walk(fullPath) : [fullPath];
});
}
for (const file of walk(path.resolve("src"))) {
if (!/\.[jt]sx?$/.test(file)) continue;
const source = fs.readFileSync(file, "utf8");
if (unsupportedColor.test(source)) {
failures.push(
`${path.relative(process.cwd(), file)} contains a runtime-only modern color function`,
);
}
}
for (const fallback of requiredLegacyFallbacks) {
const source = fs.readFileSync(path.resolve(fallback.file), "utf8");
if (!fallback.pattern.test(source)) {
failures.push(`${fallback.file}: ${fallback.description}`);
}
}
if (failures.length > 0) {
console.error("Legacy Chrome CSS compatibility check failed:\n");
console.error(failures.slice(0, 50).join("\n"));
if (failures.length > 50) {
console.error(`... and ${failures.length - 50} more`);
}
process.exit(1);
}
console.log(
`Legacy Chrome (100+) CSS compatibility check passed (${modernDeclarations} guarded modern declarations).`,
);
-72
View File
@@ -1,72 +0,0 @@
import fs from "node:fs";
import path from "node:path";
import postcss from "postcss";
/**
* 旧浏览器(麒麟 Chromium ~80)CSS 产物守卫:构建后运行,防止回归。
* 迁移后的结构性保证(见 tailwind.config.ts / postcss.config.js):
* - Tailwind v3 输出无 @layer(Chrome 99+)与 @property(Chrome 85+);
* - dark: 变体经 postcss-dark-descendant 改写为 .dark 后代形式,全库 :is( 为 0;
* - 媒体查询 range 语法(Chrome 104+)由 lightningcss 按 target 转译;
* - 手写 CSS 不使用 :is()(复杂参数无法安全降级,源头展开为逗号选择器);
* - color-mix()/oklch() 仅允许出现在 @supports 守护内或带前置回退声明。
* :has()(Chrome 105+)与 :where()(Chrome 88+)按渐进增强放行,不在检查范围。
*/
const unsupportedColor = /(?:color-mix|oklch|oklab|lab|lch)\(/i;
const assetsDir = path.resolve("dist/assets");
if (!fs.existsSync(assetsDir)) {
throw new Error("dist/assets 不存在,请先运行 pnpm build");
}
const cssFiles = fs.readdirSync(assetsDir).filter((f) => f.endsWith(".css"));
if (cssFiles.length === 0) throw new Error("dist/assets 中没有 CSS 构建产物");
const failures = [];
const hardTokens = [
[/@layer\b/, "@layer(Chrome 99+)"],
[/@property\b/, "@property(Chrome 85+)"],
[/:is\(/, ":is()(Chrome 88+)"],
[/\(width\s*>=|\(width\s*<=|\(height\s*>=/, "媒体查询 range 语法(Chrome 104+)"],
];
let guardedColors = 0;
for (const file of cssFiles) {
const raw = fs.readFileSync(path.join(assetsDir, file), "utf8");
for (const [re, label] of hardTokens) {
const hits = raw.match(new RegExp(re.source, "g")) || [];
if (hits.length > 0) failures.push(`${file}: ${hits.length} 处 ${label}`);
}
const root = postcss.parse(raw, { from: file });
root.walkDecls((decl) => {
if (!unsupportedColor.test(decl.value)) return;
guardedColors += 1;
let anc = decl.parent;
while (anc) {
if (anc.type === "atrule" && anc.name === "supports" && unsupportedColor.test(anc.params)) return;
anc = anc.parent;
}
let prev = decl.prev();
while (prev?.type === "comment") prev = prev.prev();
const hasFallback =
!decl.prop.startsWith("--") &&
prev?.type === "decl" &&
prev.prop === decl.prop &&
!unsupportedColor.test(prev.value);
if (!hasFallback) {
failures.push(`${file}: 未守护的现代颜色 ${decl.prop}: ${decl.value.slice(0, 60)}`);
}
});
}
if (failures.length > 0) {
console.error("旧浏览器 CSS 兼容检查失败:\n");
console.error(failures.slice(0, 50).join("\n"));
if (failures.length > 50) console.error(`... 及另外 ${failures.length - 50} 处`);
process.exit(1);
}
console.log(
`旧浏览器(麒麟 Chromium ~80)CSS 兼容检查通过(${guardedColors} 处守护的现代颜色声明)。`,
);
@@ -1,39 +0,0 @@
import { spawnSync } from "node:child_process";
import { mkdirSync, mkdtempSync } from "node:fs";
import { createRequire } from "node:module";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath, pathToFileURL } from "node:url";
const require = createRequire(import.meta.url);
const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const { build } = await import(pathToFileURL(require.resolve("esbuild", {
paths: [dirname(require.resolve("vite"))],
})).href);
const output = join(root, ".runtime", "ui-boundary-check");
mkdirSync(output, { recursive: true });
await build({
absWorkingDir: root,
entryPoints: ["src/components/react-ui-error-boundary.browser-check.tsx"],
bundle: true,
platform: "browser",
format: "iife",
define: { "process.env.NODE_ENV": JSON.stringify("production") },
outfile: join(output, "check.js"),
});
const browser = process.env.CHROME_PATH || (process.platform === "win32"
? "C:/Program Files/Google/Chrome/Application/chrome.exe"
: "/usr/bin/chromium");
const response = spawnSync(browser, [
"--headless=new", "--disable-gpu", "--disable-background-networking", "--no-first-run",
`--user-data-dir=${mkdtempSync(join(output, "browser-profile-"))}`,
"--virtual-time-budget=3000", "--dump-dom",
pathToFileURL(join(root, "scripts", "react-ui-error-boundary-check.html")).href,
], { encoding: "utf8", windowsHide: true, timeout: 30_000 });
if (response.error) throw response.error;
const payload = response.stdout?.match(/<pre id="boundary-check-result">([^<]+)<\/pre>/)?.[1];
if (!payload || response.status !== 0) {
throw new Error(`Browser check did not finish: exit=${response.status}; ${response.stderr?.slice(-500)}`);
}
const result = JSON.parse(payload);
if (result.passed !== true) throw new Error(`Browser check failed: ${payload}`);
console.log("React production boundary browser check:", result);
@@ -1,31 +0,0 @@
/**
* 把 Tailwind v3.4 class 模式暗色变体输出的 `X:is(.dark *)` 机械改写为
* `.dark X` 后代选择器,供麒麟 Chromium ~80 使用(无 :is())。
*
* - 特异性不变:`:is(.dark *)` 取最高参数 = (0,1,0),剥离后前置 `.dark `
* 同样 +(0,1,0),两种形式均为 (0,2,0),级联行为一致。
* - `.dark` 挂在 <html> 上、是全局祖先,前置到组合器最左侧语义等价
* (group-hover:dark:* 等组合下同样成立)。
* - 堆叠变体(dark:marker:* 等)生成的 `X *:is(.dark *)::marker` 会被
* 改写为 `.dark X *::marker`,保持合法。
*/
const TOKEN = ":is(.dark *)";
export default function darkDescendant() {
return {
postcssPlugin: "postcss-dark-descendant",
Rule(rule) {
if (!rule.selector.includes(TOKEN)) return;
rule.selector = rule.selector
.split(",")
.map((sel) => {
const trimmed = sel.trim();
if (!trimmed.includes(TOKEN)) return trimmed;
return ".dark " + trimmed.split(TOKEN).join("");
})
.join(", ");
},
};
}
darkDescendant.postcss = true;
@@ -0,0 +1,70 @@
/**
* Tailwind 4 gracefully falls back from color-mix() to the base semantic
* color, but that turns utilities such as bg-primary/5 into an opaque fill on
* Chrome 109. Replace that fallback with an sRGB-channel based alpha color.
* The modern color-mix() declaration remains in its @supports block.
*/
const LEGACY_RGB_TOKENS = new Set([
"accent",
"background",
"border",
"brand-200",
"card",
"destructive",
"foreground",
"input",
"muted",
"muted-foreground",
"primary",
"primary-foreground",
"ring",
"secondary",
"sidebar-accent",
"sidebar-border",
"sidebar-foreground",
"workspace-brand",
]);
const TRANSPARENT_MIX_RE =
/color-mix\(\s*in\s+[\w-]+\s*,\s*var\(--([\w-]+)\)\s+([\d.]+)%\s*,\s*transparent\s*\)/i;
function legacyAlphaColor(value) {
const match = value.match(TRANSPARENT_MIX_RE);
if (!match || !LEGACY_RGB_TOKENS.has(match[1])) return null;
const [, token, percentage] = match;
return `rgb(var(--legacy-${token}-rgb) / ${percentage}%)`;
}
export default function legacyColorFallback() {
return {
postcssPlugin: "postcss-legacy-color-fallback",
OnceExit(root) {
root.walkAtRules("supports", (atRule) => {
if (!atRule.params.includes("color-mix")) return;
atRule.walkDecls((modernDeclaration) => {
const fallbackValue = legacyAlphaColor(modernDeclaration.value);
if (!fallbackValue) return;
// Tailwind emits the old-browser declaration immediately before
// the nested @supports block, in the same utility/variant rule.
let fallbackDeclaration = atRule.prev();
while (fallbackDeclaration?.type === "comment") {
fallbackDeclaration = fallbackDeclaration.prev();
}
if (
fallbackDeclaration?.type === "decl" &&
fallbackDeclaration.prop === modernDeclaration.prop
) {
fallbackDeclaration.value = fallbackValue;
}
});
});
},
};
}
legacyColorFallback.postcss = true;
@@ -0,0 +1,33 @@
import postcss from "postcss";
import { transform } from "lightningcss";
const LEGACY_CHROME = 100 << 16;
/**
* Keep Vite's PostCSS pipeline (required by Tailwind 4), then compile the
* resulting CSS to Chrome 100-compatible syntax for both dev and production.
*/
export default function lightningCssLegacyChrome() {
return {
postcssPlugin: "postcss-lightningcss-legacy-chrome",
OnceExit(root, { result }) {
const filename = root.source?.input.file ?? result.opts.from ?? "style.css";
const output = transform({
filename,
code: Buffer.from(root.toString()),
targets: { chrome: LEGACY_CHROME },
minify: false,
});
const compiled = postcss.parse(output.code.toString(), { from: filename });
root.removeAll();
root.append(compiled.nodes);
for (const warning of output.warnings) {
result.warn(warning.message, { plugin: "lightningcss" });
}
},
};
}
lightningCssLegacyChrome.postcss = true;
@@ -1,8 +0,0 @@
<!doctype html>
<html lang="zh-CN">
<head><meta charset="utf-8"><title>Offline React UI boundary check</title></head>
<body>
<div id="root"></div>
<script src="../.runtime/ui-boundary-check/check.js"></script>
</body>
</html>
@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="53" height="53" viewBox="0 0 53 53"><defs><style>.a{fill:#fddadc;stroke:#f86c73;stroke-dasharray:4;}.b{fill:#fff;opacity:0;}.c{fill:url(#a);}</style><linearGradient id="a" x2="1" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#f5222d"/><stop offset="1" stop-color="#a8071a"/></linearGradient></defs><g transform="translate(0.5 -109.5)"><rect class="a" width="52" height="52" rx="8" transform="translate(0 110)"/><g transform="translate(6.5 116.5)"><rect class="b" width="39" height="39"/><path class="c" d="M20.72,28.846a8.938,8.938,0,0,1-7.044-14.437c.01-.014.02-.025.029-.037s.026-.035.04-.051l.02-.025.017-.02.012-.014c.01-.012.021-.023.03-.037l.015-.018a.179.179,0,0,0,.021-.025l.011-.012a.139.139,0,0,1,.011-.012l.064-.078.026-.031A.221.221,0,0,0,14,14.021a8.936,8.936,0,0,1,12.315-1.082c.093.072.181.146.279.234,0,0,0,0,.008.006.023.021.048.041.07.063a.393.393,0,0,1,.037.033c.015.012.028.025.041.037l.016.016a.055.055,0,0,1,.013.01l.014.012.014.012a.043.043,0,0,0,.008.01l0,0a8.964,8.964,0,0,1,2.719,5.055l0,.014c0,.031.01.061.015.09l0,.016,0,.016c0,.021.007.045.011.066l0,.018v0a.04.04,0,0,1,0,.01l0,.016,0,.018,0,.016c0,.018,0,.035.006.053a.171.171,0,0,1,0,.031c.011.078.02.158.026.238l.008.07v.018c0,.016,0,.029,0,.045a.106.106,0,0,0,0,.018.108.108,0,0,1,0,.018.28.28,0,0,0,0,.035l0,.051v.006c0,.021,0,.045,0,.064s0,.02,0,.029a.064.064,0,0,1,0,.014v.014c0,.021,0,.041,0,.063v.014c0,.01,0,.02,0,.029v.018c0,.025,0,.049,0,.074s0,.033,0,.049a.131.131,0,0,0,0,.02V19.7c0,.016,0,.027,0,.043v.041c0,.041,0,.082,0,.123A8.947,8.947,0,0,1,20.72,28.846Zm-3.574-9.953a1.016,1.016,0,0,0,0,2.031H19.7v2.563a1.016,1.016,0,0,0,2.031,0V20.924h2.563a1.016,1.016,0,0,0,0-2.031H21.73V16.334a1.016,1.016,0,0,0-2.031,0v2.559Zm-6.872,9.547H2.726A2.731,2.731,0,0,1,0,25.709V18.166a2.728,2.728,0,0,1,2.726-2.725h7.548a2.736,2.736,0,0,1,1.336.35A10.015,10.015,0,0,0,12.954,26.2,2.727,2.727,0,0,1,10.273,28.439ZM2.726,17.877a.292.292,0,0,0-.289.289v7.543A.293.293,0,0,0,2.726,26h7.548a.292.292,0,0,0,.289-.295V18.166a.292.292,0,0,0-.289-.289ZM10.273,13H2.726A2.731,2.731,0,0,1,0,10.273V2.73A2.731,2.731,0,0,1,2.726,0h7.548A2.731,2.731,0,0,1,13,2.73v7.543A2.731,2.731,0,0,1,10.273,13Zm17.09-.559v0a9.929,9.929,0,0,0-3.091-1.881H25.71A.288.288,0,0,0,26,10.273V2.73a.288.288,0,0,0-.288-.289H18.166a.286.286,0,0,0-.289.289v7.543c0,.014,0,.027,0,.049a9.841,9.841,0,0,0-2.246.979,2.737,2.737,0,0,1-.2-1.027V2.73A2.734,2.734,0,0,1,18.166,0H25.71a2.733,2.733,0,0,1,2.729,2.73v7.543a2.709,2.709,0,0,1-1.075,2.17Z" transform="translate(5.281 5.278)"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

@@ -1,10 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="52" height="52" viewBox="0 0 52 52">
<defs>
<linearGradient id="ap-add" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox">
<stop offset="0" stop-color="#f5222d"/>
<stop offset="1" stop-color="#a8071a"/>
</linearGradient>
</defs>
<rect width="52" height="52" rx="8" fill="#ffcfd1"/>
<path fill="url(#ap-add)" d="M26 14a2 2 0 0 1 2 2v8h8a2 2 0 1 1 0 4h-8v8a2 2 0 1 1-4 0v-8h-8a2 2 0 1 1 0-4h8v-8a2 2 0 0 1 2-2z"/>
</svg>

Before

Width:  |  Height:  |  Size: 503 B

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="52" height="52" viewBox="0 0 52 52"><defs><style>.a{fill:#ffcfd1;}.b{fill:url(#a);}</style><linearGradient id="a" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#f5222d"/><stop offset="1" stop-color="#a8071a"/></linearGradient></defs><g transform="translate(0 -116.002)"><rect class="a" width="52" height="52" rx="8" transform="translate(0 116.002)"/><g transform="translate(2.236 118.236)"><path class="b" d="M9204.336-22218.762a6.4,6.4,0,0,1-2.489-.691,6.242,6.242,0,0,1-2-1.615,6.363,6.363,0,0,1-1.206-2.283,6.357,6.357,0,0,1-.246-1.863c-.047-.033-.094-.066-.139-.1a6.4,6.4,0,0,1-2.272-3.4,6.418,6.418,0,0,1,.268-4.076,6.336,6.336,0,0,1,1.233-1.912,6.383,6.383,0,0,1-.4-1.973,6.41,6.41,0,0,1,.53-2.809,6.441,6.441,0,0,1,1.7-2.289,6.424,6.424,0,0,1,1.751-1.057,4.969,4.969,0,0,1,.343-1.289,4.965,4.965,0,0,1,1.334-1.859,5.038,5.038,0,0,1,2.016-1.082,5.037,5.037,0,0,1,2.289-.074,5.024,5.024,0,0,1,2.089.943,4.947,4.947,0,0,1,.871.861,5.147,5.147,0,0,1,.876-.861,5,5,0,0,1,2.083-.943,5.035,5.035,0,0,1,2.289.074,5.06,5.06,0,0,1,2.021,1.082,5.031,5.031,0,0,1,1.334,1.859,5.008,5.008,0,0,1,.343,1.289,6.424,6.424,0,0,1,1.751,1.057,6.441,6.441,0,0,1,1.7,2.289,6.405,6.405,0,0,1,.524,2.809,6.434,6.434,0,0,1-.4,1.973,6.315,6.315,0,0,1,1.234,1.912,6.418,6.418,0,0,1,.268,4.076,6.4,6.4,0,0,1-2.272,3.4l-.143.105a6.214,6.214,0,0,1-.248,1.859,6.26,6.26,0,0,1-1.2,2.283,6.271,6.271,0,0,1-2.01,1.615,6.354,6.354,0,0,1-2.485.691c-.14.006-.278.012-.418.012a6.213,6.213,0,0,1-2.139-.375,6.394,6.394,0,0,1-2.2-1.34,6.4,6.4,0,0,1-.915-1.066,6.415,6.415,0,0,1-.91,1.066,6.427,6.427,0,0,1-2.206,1.34,6.283,6.283,0,0,1-2.143.377C9204.609-22218.748,9204.473-22218.752,9204.336-22218.762Zm6.768-6.342a4.232,4.232,0,0,0,.346,1.652,4.123,4.123,0,0,0,.972,1.379,4.116,4.116,0,0,0,1.44.877,4.062,4.062,0,0,0,1.67.234,4.159,4.159,0,0,0,1.63-.447,4.159,4.159,0,0,0,1.313-1.061,4.227,4.227,0,0,0,.787-1.49c.02-.07.037-.139.054-.209a6.32,6.32,0,0,1-1.422.164,1.1,1.1,0,0,1-1.1-1.1,1.1,1.1,0,0,1,1.1-1.1,4.178,4.178,0,0,0,2.529-.859,4.138,4.138,0,0,0,1.485-2.221,4.216,4.216,0,0,0-.173-2.67,4.2,4.2,0,0,0-1.765-2.01,1.1,1.1,0,0,1-.4-1.5,1.1,1.1,0,0,1,1.063-.543,4.16,4.16,0,0,0,.1-.758,4.249,4.249,0,0,0-.346-1.838,4.156,4.156,0,0,0-1.117-1.5,4.078,4.078,0,0,0-.569-.408,4.928,4.928,0,0,1-.385.838,1.1,1.1,0,0,1-.955.553,1.08,1.08,0,0,1-.547-.15,1.093,1.093,0,0,1-.4-1.5,2.906,2.906,0,0,0,.374-1.229,1.022,1.022,0,0,1,.006-.145,2.841,2.841,0,0,0-.218-1.133,2.836,2.836,0,0,0-.754-1.051,2.794,2.794,0,0,0-1.139-.607,2.8,2.8,0,0,0-1.29-.045,2.782,2.782,0,0,0-1.173.535,2.84,2.84,0,0,0-.82.994,2.912,2.912,0,0,0-.3,1.262v5.254a4.426,4.426,0,0,0,.877,2.625,4.4,4.4,0,0,0,2.277,1.58,1.1,1.1,0,0,1,.748,1.361,1.1,1.1,0,0,1-1.367.748,6.6,6.6,0,0,1-2.535-1.41v6.928Zm-10.352,1.145a4.119,4.119,0,0,0,.787,1.49,4.148,4.148,0,0,0,1.313,1.061,4.105,4.105,0,0,0,1.624.447,4.076,4.076,0,0,0,1.676-.234,4.125,4.125,0,0,0,1.44-.877,4.208,4.208,0,0,0,.972-1.379,4.226,4.226,0,0,0,.34-1.652v-6.924a6.628,6.628,0,0,1-2.534,1.406,1.117,1.117,0,0,1-.308.045,1.1,1.1,0,0,1-1.055-.793,1.093,1.093,0,0,1,.748-1.361,4.393,4.393,0,0,0,2.272-1.58,4.354,4.354,0,0,0,.876-2.625v-5.254a2.906,2.906,0,0,0-.29-1.262,2.84,2.84,0,0,0-.82-.994,2.778,2.778,0,0,0-1.179-.535,2.8,2.8,0,0,0-1.29.045,2.832,2.832,0,0,0-1.139.607,2.821,2.821,0,0,0-.748,1.051,2.819,2.819,0,0,0-.212,1.271,2.821,2.821,0,0,0,.374,1.234,1.1,1.1,0,0,1-.4,1.5,1.1,1.1,0,0,1-1.5-.4,5.009,5.009,0,0,1-.386-.838,4.127,4.127,0,0,0-.568.408,4.156,4.156,0,0,0-1.117,1.5,4.249,4.249,0,0,0-.346,1.838,4.246,4.246,0,0,0,.1.758,1.106,1.106,0,0,1,1.064.543,1.1,1.1,0,0,1-.4,1.5,4.2,4.2,0,0,0-1.765,2.01,4.216,4.216,0,0,0-.173,2.67,4.138,4.138,0,0,0,1.485,2.221,4.178,4.178,0,0,0,2.529.859,1.1,1.1,0,0,1,1.1,1.1,1.1,1.1,0,0,1-1.1,1.1,6.32,6.32,0,0,1-1.422-.164C9200.714-22224.1,9200.732-22224.029,9200.752-22223.959Z" transform="translate(-9186.242 22256.754)"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 3.9 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="52" height="52" viewBox="0 0 52 52"><defs><style>.a{fill:#ffcfd1;}.b{opacity:0;}.b,.c{fill:url(#a);}</style><linearGradient id="a" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#f5222d"/><stop offset="1" stop-color="#a8071a"/></linearGradient></defs><g transform="translate(0 -116.002)"><rect class="a" width="52" height="52" rx="8" transform="translate(0 116.002)"/><g transform="translate(18559 4825)"><rect class="b" width="42" height="42" transform="translate(-18554 -4704)"/><path class="c" d="M-9736.837-26950.139a1.008,1.008,0,0,1-.542-.889v-3.371h-.752a4.506,4.506,0,0,1-4.5-4.5v-2.629c-1.89-.08-3.366-2-3.366-4.367s1.477-4.287,3.366-4.369v-2.633a4.5,4.5,0,0,1,4.5-4.5h15.658v.129a3.676,3.676,0,0,0,.494,1.869h-16.152a2.5,2.5,0,0,0-2.5,2.5v14a2.5,2.5,0,0,0,2.5,2.5h1.741a1.006,1.006,0,0,1,1.009,1v2.432l4.544-3.244a.97.97,0,0,1,.576-.189h13.124a2.5,2.5,0,0,0,2.506-2.5v-9.441a3.524,3.524,0,0,0,1.118.189h.033a3.634,3.634,0,0,0,2.764-1.293,4.793,4.793,0,0,1,1.456,3.549,5.014,5.014,0,0,1-.982,3.041,3.23,3.23,0,0,1-2.391,1.334v2.621a4.507,4.507,0,0,1-4.5,4.5h-12.806l-5.858,4.184a1.021,1.021,0,0,1-.582.191A1.007,1.007,0,0,1-9736.837-26950.139Zm1.334-10.389a1.876,1.876,0,0,1-1.876-1.877v-7.869a1.876,1.876,0,0,1,1.876-1.877h15.739a1.876,1.876,0,0,1,1.876,1.877v7.869a1.876,1.876,0,0,1-1.876,1.877Zm10.931-5.811a1.752,1.752,0,0,0,1.754,1.746,1.751,1.751,0,0,0,1.747-1.746,1.754,1.754,0,0,0-1.747-1.756A1.755,1.755,0,0,0-9724.572-26966.338Zm-9.617,0a1.752,1.752,0,0,0,1.748,1.746,1.751,1.751,0,0,0,1.747-1.746,1.755,1.755,0,0,0-1.747-1.756A1.755,1.755,0,0,0-9734.189-26966.338Zm20.1-5.277-.453-1.551a4.433,4.433,0,0,0-2.946-3.006l-1.537-.467a.649.649,0,0,1-.447-.611.524.524,0,0,1,.021-.148.616.616,0,0,1,.217-.346.624.624,0,0,1,.217-.115l.284-.088,1.232-.365a4.417,4.417,0,0,0,2.96-3.02l.46-1.551a.625.625,0,0,1,.42-.434v.006a.538.538,0,0,1,.183-.033.574.574,0,0,1,.292.08.581.581,0,0,1,.3.381l.46,1.557a4.422,4.422,0,0,0,2.96,3.014l1.171.346.346.107a.647.647,0,0,1,.454.609.641.641,0,0,1-.447.611l-1.537.467a4.434,4.434,0,0,0-2.946,3.006l-.453,1.551a.631.631,0,0,1-.6.461A.636.636,0,0,1-9714.089-26971.615Zm-4.571-7.34-.183-.623a2.7,2.7,0,0,0-1.829-1.83l-.623-.189a.29.29,0,0,1-.2-.277.284.284,0,0,1,.2-.277l.61-.184a2.7,2.7,0,0,0,1.842-1.842l.183-.615a.32.32,0,0,1,.2-.2.327.327,0,0,1,.224.027.275.275,0,0,1,.143.17l.183.615a2.713,2.713,0,0,0,1.842,1.842l.609.184a.289.289,0,0,1,.21.277.3.3,0,0,1-.21.277l-.257.076-.366.113a2.725,2.725,0,0,0-1.828,1.83l-.183.623a.293.293,0,0,1-.278.2A.3.3,0,0,1-9718.66-26978.955Z" transform="translate(-8805.37 22282.029)"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="52" height="52" viewBox="0 0 52 52"><defs><style>.a{fill:#ffcfd1;}.b{fill:#fff;opacity:0;}.c{fill:url(#a);}</style><linearGradient id="a" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#f5222d"/><stop offset="1" stop-color="#a8071a"/></linearGradient></defs><g transform="translate(0 -116.002)"><rect class="a" width="52" height="52" rx="8" transform="translate(0 116.002)"/><g transform="translate(18558 4829)"><rect class="b" width="42" height="42" transform="translate(-18553 -4708)"/><path class="c" d="M-9520.252-26774.373h-17.5a8.261,8.261,0,0,1-8.248-8.254v-8.746a8.261,8.261,0,0,1,8.248-8.256h7.75v-2.582a2.5,2.5,0,0,1-1.5-2.287,2.506,2.506,0,0,1,2.5-2.5,2.5,2.5,0,0,1,2.5,2.5,2.515,2.515,0,0,1-1.5,2.293v2.576h2.752a1.254,1.254,0,0,1,1.251,1.252,1.254,1.254,0,0,1-1.251,1.252h-12.5a5.758,5.758,0,0,0-5.752,5.752v8.746a5.758,5.758,0,0,0,5.752,5.752h17.5a5.758,5.758,0,0,0,5.752-5.752v-5.746a1.252,1.252,0,0,1,1.251-1.25,1.252,1.252,0,0,1,1.252,1.25v5.746A8.264,8.264,0,0,1-9520.252-26774.373Zm-2.624-6.25h-12.251a5.506,5.506,0,0,1-5.5-5.5,5.5,5.5,0,0,1,5.5-5.5h12.251a5.507,5.507,0,0,1,5.5,5.5A5.509,5.509,0,0,1-9522.876-26780.623Zm-.989-7.812a.992.992,0,0,0-.706.291l-1.312,1.313a1,1,0,0,0-.289.707.985.985,0,0,0,.289.705l1.313,1.313a1,1,0,0,0,.706.3,1,1,0,0,0,.706-.3.988.988,0,0,0,.293-.707.987.987,0,0,0-.293-.705l-.605-.605.605-.605a.988.988,0,0,0,.293-.707.988.988,0,0,0-.293-.707A.988.988,0,0,0-9523.865-26788.436Zm-10.388.561a1.751,1.751,0,0,0-1.749,1.75,1.75,1.75,0,0,0,1.749,1.748,1.75,1.75,0,0,0,1.749-1.748A1.751,1.751,0,0,0-9534.253-26787.875Zm19.262-3.531a.587.587,0,0,1-.552-.4l-1.5-4.568-4.555-1.447a.593.593,0,0,1-.4-.551.577.577,0,0,1,.4-.553l4.5-1.514,1.419-4.5a.59.59,0,0,1,.557-.412.609.609,0,0,1,.17.027.569.569,0,0,1,.377.377l1.5,4.568,4.7,1.668a.579.579,0,0,1,.384.559.59.59,0,0,1-.417.545l-4.6,1.293-1.426,4.5A.572.572,0,0,1-9514.991-26791.406Z" transform="translate(-9002.999 22102.623)"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1920" height="1080" viewBox="0 0 1920 1080"><defs><style>.a{fill:url(#a);}</style><pattern id="a" preserveAspectRatio="xMidYMid slice" width="100%" height="100%" viewBox="0 0 3840 2160"><image width="3840" height="2160" xlink:href="data:image/png;base64,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 truncated

Before

Width:  |  Height:  |  Size: 1.7 MiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="53" height="53" viewBox="0 0 53 53"><defs><style>.a{fill:#d4e9ff;stroke:#55a6fe;stroke-dasharray:4;}.b{fill:#fff;opacity:0;}.c{fill:url(#a);}</style><linearGradient id="a" x2="1" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#0077fb"/><stop offset="1" stop-color="#004bb5"/></linearGradient></defs><g transform="translate(0.5 -109.5)"><rect class="a" width="52" height="52" rx="8" transform="translate(0 110)"/><g transform="translate(6.5 116.5)"><rect class="b" width="39" height="39"/><path class="c" d="M20.72,28.846a8.938,8.938,0,0,1-7.044-14.437c.01-.014.02-.025.029-.037s.026-.035.04-.051l.02-.025.017-.02.012-.014c.01-.012.021-.023.03-.037l.015-.018a.179.179,0,0,0,.021-.025l.011-.012a.139.139,0,0,1,.011-.012l.064-.078.026-.031A.221.221,0,0,0,14,14.021a8.936,8.936,0,0,1,12.315-1.082c.093.072.181.146.279.234,0,0,0,0,.008.006.023.021.048.041.07.063a.393.393,0,0,1,.037.033c.015.012.028.025.041.037l.016.016a.055.055,0,0,1,.013.01l.014.012.014.012a.043.043,0,0,0,.008.01l0,0a8.964,8.964,0,0,1,2.719,5.055l0,.014c0,.031.01.061.015.09l0,.016,0,.016c0,.021.007.045.011.066l0,.018v0a.04.04,0,0,1,0,.01l0,.016,0,.018,0,.016c0,.018,0,.035.006.053a.171.171,0,0,1,0,.031c.011.078.02.158.026.238l.008.07v.018c0,.016,0,.029,0,.045a.106.106,0,0,0,0,.018.108.108,0,0,1,0,.018.28.28,0,0,0,0,.035l0,.051v.006c0,.021,0,.045,0,.064s0,.02,0,.029a.064.064,0,0,1,0,.014v.014c0,.021,0,.041,0,.063v.014c0,.01,0,.02,0,.029v.018c0,.025,0,.049,0,.074s0,.033,0,.049a.131.131,0,0,0,0,.02V19.7c0,.016,0,.027,0,.043v.041c0,.041,0,.082,0,.123A8.947,8.947,0,0,1,20.72,28.846Zm-3.574-9.953a1.016,1.016,0,0,0,0,2.031H19.7v2.563a1.016,1.016,0,0,0,2.031,0V20.924h2.563a1.016,1.016,0,0,0,0-2.031H21.73V16.334a1.016,1.016,0,0,0-2.031,0v2.559Zm-6.872,9.547H2.726A2.731,2.731,0,0,1,0,25.709V18.166a2.728,2.728,0,0,1,2.726-2.725h7.548a2.736,2.736,0,0,1,1.336.35A10.015,10.015,0,0,0,12.954,26.2,2.727,2.727,0,0,1,10.273,28.439ZM2.726,17.877a.292.292,0,0,0-.289.289v7.543A.293.293,0,0,0,2.726,26h7.548a.292.292,0,0,0,.289-.295V18.166a.292.292,0,0,0-.289-.289ZM10.273,13H2.726A2.731,2.731,0,0,1,0,10.273V2.73A2.731,2.731,0,0,1,2.726,0h7.548A2.731,2.731,0,0,1,13,2.73v7.543A2.731,2.731,0,0,1,10.273,13Zm17.09-.559v0a9.929,9.929,0,0,0-3.091-1.881H25.71A.288.288,0,0,0,26,10.273V2.73a.288.288,0,0,0-.288-.289H18.166a.286.286,0,0,0-.289.289v7.543c0,.014,0,.027,0,.049a9.841,9.841,0,0,0-2.246.979,2.737,2.737,0,0,1-.2-1.027V2.73A2.734,2.734,0,0,1,18.166,0H25.71a2.733,2.733,0,0,1,2.729,2.73v7.543a2.709,2.709,0,0,1-1.075,2.17Z" transform="translate(5.281 5.278)"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.6 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="52" height="52" viewBox="0 0 52 52"><defs><style>.a{fill:#aad2ff;}.b{fill:url(#a);}</style><linearGradient id="a" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#0077fb"/><stop offset="1" stop-color="#004bb5"/></linearGradient></defs><g transform="translate(0 -116.002)"><rect class="a" width="52" height="52" rx="8" transform="translate(0 116.002)"/><g transform="translate(2.236 118.236)"><path class="b" d="M9204.336-22218.762a6.4,6.4,0,0,1-2.489-.691,6.242,6.242,0,0,1-2-1.615,6.363,6.363,0,0,1-1.206-2.283,6.357,6.357,0,0,1-.246-1.863c-.047-.033-.094-.066-.139-.1a6.4,6.4,0,0,1-2.272-3.4,6.418,6.418,0,0,1,.268-4.076,6.336,6.336,0,0,1,1.233-1.912,6.383,6.383,0,0,1-.4-1.973,6.41,6.41,0,0,1,.53-2.809,6.441,6.441,0,0,1,1.7-2.289,6.424,6.424,0,0,1,1.751-1.057,4.969,4.969,0,0,1,.343-1.289,4.965,4.965,0,0,1,1.334-1.859,5.038,5.038,0,0,1,2.016-1.082,5.037,5.037,0,0,1,2.289-.074,5.024,5.024,0,0,1,2.089.943,4.947,4.947,0,0,1,.871.861,5.147,5.147,0,0,1,.876-.861,5,5,0,0,1,2.083-.943,5.035,5.035,0,0,1,2.289.074,5.06,5.06,0,0,1,2.021,1.082,5.031,5.031,0,0,1,1.334,1.859,5.008,5.008,0,0,1,.343,1.289,6.424,6.424,0,0,1,1.751,1.057,6.441,6.441,0,0,1,1.7,2.289,6.405,6.405,0,0,1,.524,2.809,6.434,6.434,0,0,1-.4,1.973,6.315,6.315,0,0,1,1.234,1.912,6.418,6.418,0,0,1,.268,4.076,6.4,6.4,0,0,1-2.272,3.4l-.143.105a6.214,6.214,0,0,1-.248,1.859,6.26,6.26,0,0,1-1.2,2.283,6.271,6.271,0,0,1-2.01,1.615,6.354,6.354,0,0,1-2.485.691c-.14.006-.278.012-.418.012a6.213,6.213,0,0,1-2.139-.375,6.394,6.394,0,0,1-2.2-1.34,6.4,6.4,0,0,1-.915-1.066,6.415,6.415,0,0,1-.91,1.066,6.427,6.427,0,0,1-2.206,1.34,6.283,6.283,0,0,1-2.143.377C9204.609-22218.748,9204.473-22218.752,9204.336-22218.762Zm6.768-6.342a4.232,4.232,0,0,0,.346,1.652,4.123,4.123,0,0,0,.972,1.379,4.116,4.116,0,0,0,1.44.877,4.062,4.062,0,0,0,1.67.234,4.159,4.159,0,0,0,1.63-.447,4.159,4.159,0,0,0,1.313-1.061,4.227,4.227,0,0,0,.787-1.49c.02-.07.037-.139.054-.209a6.32,6.32,0,0,1-1.422.164,1.1,1.1,0,0,1-1.1-1.1,1.1,1.1,0,0,1,1.1-1.1,4.178,4.178,0,0,0,2.529-.859,4.138,4.138,0,0,0,1.485-2.221,4.216,4.216,0,0,0-.173-2.67,4.2,4.2,0,0,0-1.765-2.01,1.1,1.1,0,0,1-.4-1.5,1.1,1.1,0,0,1,1.063-.543,4.16,4.16,0,0,0,.1-.758,4.249,4.249,0,0,0-.346-1.838,4.156,4.156,0,0,0-1.117-1.5,4.078,4.078,0,0,0-.569-.408,4.928,4.928,0,0,1-.385.838,1.1,1.1,0,0,1-.955.553,1.08,1.08,0,0,1-.547-.15,1.093,1.093,0,0,1-.4-1.5,2.906,2.906,0,0,0,.374-1.229,1.022,1.022,0,0,1,.006-.145,2.841,2.841,0,0,0-.218-1.133,2.836,2.836,0,0,0-.754-1.051,2.794,2.794,0,0,0-1.139-.607,2.8,2.8,0,0,0-1.29-.045,2.782,2.782,0,0,0-1.173.535,2.84,2.84,0,0,0-.82.994,2.912,2.912,0,0,0-.3,1.262v5.254a4.426,4.426,0,0,0,.877,2.625,4.4,4.4,0,0,0,2.277,1.58,1.1,1.1,0,0,1,.748,1.361,1.1,1.1,0,0,1-1.367.748,6.6,6.6,0,0,1-2.535-1.41v6.928Zm-10.352,1.145a4.119,4.119,0,0,0,.787,1.49,4.148,4.148,0,0,0,1.313,1.061,4.105,4.105,0,0,0,1.624.447,4.076,4.076,0,0,0,1.676-.234,4.125,4.125,0,0,0,1.44-.877,4.208,4.208,0,0,0,.972-1.379,4.226,4.226,0,0,0,.34-1.652v-6.924a6.628,6.628,0,0,1-2.534,1.406,1.117,1.117,0,0,1-.308.045,1.1,1.1,0,0,1-1.055-.793,1.093,1.093,0,0,1,.748-1.361,4.393,4.393,0,0,0,2.272-1.58,4.354,4.354,0,0,0,.876-2.625v-5.254a2.906,2.906,0,0,0-.29-1.262,2.84,2.84,0,0,0-.82-.994,2.778,2.778,0,0,0-1.179-.535,2.8,2.8,0,0,0-1.29.045,2.832,2.832,0,0,0-1.139.607,2.821,2.821,0,0,0-.748,1.051,2.819,2.819,0,0,0-.212,1.271,2.821,2.821,0,0,0,.374,1.234,1.1,1.1,0,0,1-.4,1.5,1.1,1.1,0,0,1-1.5-.4,5.009,5.009,0,0,1-.386-.838,4.127,4.127,0,0,0-.568.408,4.156,4.156,0,0,0-1.117,1.5,4.249,4.249,0,0,0-.346,1.838,4.246,4.246,0,0,0,.1.758,1.106,1.106,0,0,1,1.064.543,1.1,1.1,0,0,1-.4,1.5,4.2,4.2,0,0,0-1.765,2.01,4.216,4.216,0,0,0-.173,2.67,4.138,4.138,0,0,0,1.485,2.221,4.178,4.178,0,0,0,2.529.859,1.1,1.1,0,0,1,1.1,1.1,1.1,1.1,0,0,1-1.1,1.1,6.32,6.32,0,0,1-1.422-.164C9200.714-22224.1,9200.732-22224.029,9200.752-22223.959Z" transform="translate(-9186.242 22256.754)"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 3.9 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="52" height="52" viewBox="0 0 52 52"><defs><style>.a{fill:#aad2ff;}.b{opacity:0;}.b,.c{fill:url(#a);}</style><linearGradient id="a" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#0077fb"/><stop offset="1" stop-color="#004bb5"/></linearGradient></defs><g transform="translate(0 -116.002)"><rect class="a" width="52" height="52" rx="8" transform="translate(0 116.002)"/><g transform="translate(18559 4825)"><rect class="b" width="42" height="42" transform="translate(-18554 -4704)"/><path class="c" d="M-9736.837-26950.139a1.008,1.008,0,0,1-.542-.889v-3.371h-.752a4.506,4.506,0,0,1-4.5-4.5v-2.629c-1.89-.08-3.366-2-3.366-4.367s1.477-4.287,3.366-4.369v-2.633a4.5,4.5,0,0,1,4.5-4.5h15.658v.129a3.676,3.676,0,0,0,.494,1.869h-16.152a2.5,2.5,0,0,0-2.5,2.5v14a2.5,2.5,0,0,0,2.5,2.5h1.741a1.006,1.006,0,0,1,1.009,1v2.432l4.544-3.244a.97.97,0,0,1,.576-.189h13.124a2.5,2.5,0,0,0,2.506-2.5v-9.441a3.524,3.524,0,0,0,1.118.189h.033a3.634,3.634,0,0,0,2.764-1.293,4.793,4.793,0,0,1,1.456,3.549,5.014,5.014,0,0,1-.982,3.041,3.23,3.23,0,0,1-2.391,1.334v2.621a4.507,4.507,0,0,1-4.5,4.5h-12.806l-5.858,4.184a1.021,1.021,0,0,1-.582.191A1.007,1.007,0,0,1-9736.837-26950.139Zm1.334-10.389a1.876,1.876,0,0,1-1.876-1.877v-7.869a1.876,1.876,0,0,1,1.876-1.877h15.739a1.876,1.876,0,0,1,1.876,1.877v7.869a1.876,1.876,0,0,1-1.876,1.877Zm10.931-5.811a1.752,1.752,0,0,0,1.754,1.746,1.751,1.751,0,0,0,1.747-1.746,1.754,1.754,0,0,0-1.747-1.756A1.755,1.755,0,0,0-9724.572-26966.338Zm-9.617,0a1.752,1.752,0,0,0,1.748,1.746,1.751,1.751,0,0,0,1.747-1.746,1.755,1.755,0,0,0-1.747-1.756A1.755,1.755,0,0,0-9734.189-26966.338Zm20.1-5.277-.453-1.551a4.433,4.433,0,0,0-2.946-3.006l-1.537-.467a.649.649,0,0,1-.447-.611.524.524,0,0,1,.021-.148.616.616,0,0,1,.217-.346.624.624,0,0,1,.217-.115l.284-.088,1.232-.365a4.417,4.417,0,0,0,2.96-3.02l.46-1.551a.625.625,0,0,1,.42-.434v.006a.538.538,0,0,1,.183-.033.574.574,0,0,1,.292.08.581.581,0,0,1,.3.381l.46,1.557a4.422,4.422,0,0,0,2.96,3.014l1.171.346.346.107a.647.647,0,0,1,.454.609.641.641,0,0,1-.447.611l-1.537.467a4.434,4.434,0,0,0-2.946,3.006l-.453,1.551a.631.631,0,0,1-.6.461A.636.636,0,0,1-9714.089-26971.615Zm-4.571-7.34-.183-.623a2.7,2.7,0,0,0-1.829-1.83l-.623-.189a.29.29,0,0,1-.2-.277.284.284,0,0,1,.2-.277l.61-.184a2.7,2.7,0,0,0,1.842-1.842l.183-.615a.32.32,0,0,1,.2-.2.327.327,0,0,1,.224.027.275.275,0,0,1,.143.17l.183.615a2.713,2.713,0,0,0,1.842,1.842l.609.184a.289.289,0,0,1,.21.277.3.3,0,0,1-.21.277l-.257.076-.366.113a2.725,2.725,0,0,0-1.828,1.83l-.183.623a.293.293,0,0,1-.278.2A.3.3,0,0,1-9718.66-26978.955Z" transform="translate(-8805.37 22282.029)"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="52" height="52" viewBox="0 0 52 52"><defs><style>.a{fill:#aad2ff;}.b{fill:#fff;opacity:0;}.c{fill:url(#a);}</style><linearGradient id="a" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#0077fb"/><stop offset="1" stop-color="#004bb5"/></linearGradient></defs><g transform="translate(0 -116.002)"><rect class="a" width="52" height="52" rx="8" transform="translate(0 116.002)"/><g transform="translate(18558 4829)"><rect class="b" width="42" height="42" transform="translate(-18553 -4708)"/><path class="c" d="M-9520.252-26774.373h-17.5a8.261,8.261,0,0,1-8.248-8.254v-8.746a8.261,8.261,0,0,1,8.248-8.256h7.75v-2.582a2.5,2.5,0,0,1-1.5-2.287,2.506,2.506,0,0,1,2.5-2.5,2.5,2.5,0,0,1,2.5,2.5,2.515,2.515,0,0,1-1.5,2.293v2.576h2.752a1.254,1.254,0,0,1,1.251,1.252,1.254,1.254,0,0,1-1.251,1.252h-12.5a5.758,5.758,0,0,0-5.752,5.752v8.746a5.758,5.758,0,0,0,5.752,5.752h17.5a5.758,5.758,0,0,0,5.752-5.752v-5.746a1.252,1.252,0,0,1,1.251-1.25,1.252,1.252,0,0,1,1.252,1.25v5.746A8.264,8.264,0,0,1-9520.252-26774.373Zm-2.624-6.25h-12.251a5.506,5.506,0,0,1-5.5-5.5,5.5,5.5,0,0,1,5.5-5.5h12.251a5.507,5.507,0,0,1,5.5,5.5A5.509,5.509,0,0,1-9522.876-26780.623Zm-.989-7.812a.992.992,0,0,0-.706.291l-1.312,1.313a1,1,0,0,0-.289.707.985.985,0,0,0,.289.705l1.313,1.313a1,1,0,0,0,.706.3,1,1,0,0,0,.706-.3.988.988,0,0,0,.293-.707.987.987,0,0,0-.293-.705l-.605-.605.605-.605a.988.988,0,0,0,.293-.707.988.988,0,0,0-.293-.707A.988.988,0,0,0-9523.865-26788.436Zm-10.388.561a1.751,1.751,0,0,0-1.749,1.75,1.75,1.75,0,0,0,1.749,1.748,1.75,1.75,0,0,0,1.749-1.748A1.751,1.751,0,0,0-9534.253-26787.875Zm19.262-3.531a.587.587,0,0,1-.552-.4l-1.5-4.568-4.555-1.447a.593.593,0,0,1-.4-.551.577.577,0,0,1,.4-.553l4.5-1.514,1.419-4.5a.59.59,0,0,1,.557-.412.609.609,0,0,1,.17.027.569.569,0,0,1,.377.377l1.5,4.568,4.7,1.668a.579.579,0,0,1,.384.559.59.59,0,0,1-.417.545l-4.6,1.293-1.426,4.5A.572.572,0,0,1-9514.991-26791.406Z" transform="translate(-9002.999 22102.623)"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.0 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1920" height="1080" viewBox="0 0 1920 1080"><image width="1920" height="1080" xlink:href="data:image/png;base64,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 truncated

Before

Width:  |  Height:  |  Size: 1.9 MiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="582" height="667" viewBox="0 0 582 667"><image width="582" height="667" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABIwAAAU2CAYAAAD3cC0IAAAgAElEQVR4nOy9B5fkynWteSKQWb6qze2+XuSltxIpihLlpTdv3F+eWWtmzfN6eiKfSFG0IkWK5LXty1cmImadiBPAQWQgE1VdWVXZtXcvNNIiAaQpxId99jGnU08QdNNlzrt+537CtS725qzfNW3gTd+vy9aN2/5X/A257Z+3gTIyWXW5b7LZ49eJaIOItoloU66vyVxPG4Xb1tXjeaqIaEREY7k+ktcYyfWxPKaSy2O5byS35W+3V+s6Us+3PbvFEVFNRBMimsrzfc9ya3nMVB4/kdvS80/lvrTMM7XcdP1MHleaTgq3pccfE9GheoxT66ov9036MdAcvfI76IZt4G3/QF7b9r/kC9/0921p63fOBd/2zze0GhrhfYIgCIIgSGQUeNHwJZ8qBXPyaU1A0aaCQuMMBK0V4NBadr0PBlkFe/J1yW+bB4z6IFGf3ABgVCtgNM1uO8uAUQkqaWh0VoBI+W0JRJ0INDpWr5NPdQa18mmiJoxjIAiCIAgCMIIgCIKgWy4jcGdHXEE83yKiXZmnaVsAUAJB6XK6f1OBHg2RrHLx6HnfZT3XcKfKrtsrNowtAkzzjqkSUNIOn7rgBKoLc31b6X5XAD9nAo+OZDoWqKTB0lE27cv1A3ErHcjjAI8gCIIg6JYKwAiCIAiCXh1VCtqU5qPMQTRWpWMJGKXpPMAoOYqgssw1HHNpMKSB0ZGa62lfQNFhBowOM/dRPp3R7LzG5wCCIAiCVl/IMIJWQsgwGiZkGK2mkGF0tXpFN49hzR0i2pNpV+Y7cvuO3LatwNCuAj+6nGusMoL6ytF02Rd086XL0frK0s6ycro0T6BpXyBSciAlwPRcbtPzFzIdv2qfDWQYXa1u+ygFGUbLETKMIGi44DCCIAiCoJupPNOn7/KWAkPnBUa3ndfeFlXKfXYR+QsAo+dy/1FPNtNJls80ve1vEgRBEATdNAEYQRAEQdDNUoI892V+V+DPPTW/o8DQtgJKfaVouiQNriDovDIKRtYDStI0IErlbgkiPVXzZ+r6k1fVlQRBEARBqyoAIwiCIAi6GlUCdTZ7WsmnPKA7A4DRnnIOrYJm2rn7GNbM15ysf7o9f2x+X7qlc79Xj1PP6ZXvPn+RjDEL3VhGzY3Jb1PPN214d+c58rzufSaGbZtuCHj+/KtUcittnOM1tfNoHjB6LtOxch6dKkfSqZojJwmCIAiClixkGEErIWQYDRMyjFZTyDC6Wl3D5lkBPA+I6DWZ35PLd+XyPQFE26oV/XpWiqbb04+vdScuVuoCNnWplbyPHb28XPfpum+6h9Wd21VXMYFLroFMERfVGjx53zzGy3JoDhBKXck0oCpJA5x5XdmMECIrj7cmBz2mbfMvt1kNgYx0hjOm0ynOpOvNPHWek+u2my1107+9EwWATrOStHQ9BW4/U0DpmQAlvvxYpkcCoNyA1700IcPoanXbRynIMFqOkGEEQcMFhxEEQRAEvZwS3NkoTJvKDbQIGN27IQN+pyavQIzrgBbftoT3LXzRYCgAowwQ1T4DQ9njvcxr9XppuU63oU+v79v18ep+t8hBpCAULQBGpOBOn5IDKQEgK9dNgkICkFr4ZGaAUYBEJoEiAUg0C4yCwycDSCP9+OY19fLb19f3JbCl75u3nS+r8UDYORkIjJ4JNDqZM50tcXsgCIIg6JUWHEbQSggOo2GCw2g1BYfR1eoSN29TIM8DcQfp+WsypfKxzQJM0uVoyxykDxEDmtAVy/vOvPY+QJ9Jut0loONjxy2eO309OYME4OQlZhoEqcfpcjN9P/WWm8Xnkde3qcctOLqRZy8sX9MlZTTv46NK0HSZWSo/S0uYX7bWQpu2bK19XgdAZSVsllpAlYDSyMqc1NxKlztjaGyIxgKexnJ/mjOAGt+AvKu6pyQtTcdSwvYsA0lPZM7XPxHQdHoZKwSH0dXqto9S4DBajuAwgqDhAjCCVkIARsMEYLSaAjC6Wp1j84zKFUpuoTRtCxzKQVEOjO5ew6C7Jl3C5Rt3UJ1dD/MEelKIsYvXNTCKt0v7dedngZHX89kSod4yrnl3Dnj+ZT/nMnSRg6r5WUuLH9e53YgLicGPKQGjCIhGUso2A4qsXJeJwVKVldAlV1K83TT3VVfgUCppKtBoHjBK7qQjgUyladB7B2B0tbrtoxQAo+UIwAiChgvACFoJARgNE4DRagrA6Go1cPMYEr0u0xtE9FBdf111KttQIdYbKrx644pBEf8xPxMn0KkAn7MAeRyd+ugMCnNy4XYGQ5OsRMx1SrrS5W5JWusYykvC2sfnynd5yatTeltmbjML7h+yjCVpyMGUn7nQc3/xttKl0vNk786UpZnmutHwR5xJ7fVuBlNTAmcNjS1DJENrDJWMoXUTgdK6gKY1AU9rpu3Kd5W/JrVyHZWcSClw+2OZPhKo9KFc/0SA0lwBGF2tbvsoBcBoOQIwgqDhAjCCVkIARsMEYLSaAjC6WqnN21JTchKtSwnZ3QXA6M4VrHTK5IlQxzc5P7WfDY2eeGlr7nycszNIAFIASc3tLriF0v1T3z1mLcKdgaDmtn+Vb5oWOpLmuJea6yZCplDCZiMQGhsbytnWEkBiUGTbeXAnGWoAUpPB1MlpMi2MWhAofpl6vgAY6Uyk5EI6VM4kAKMr1m0fpQAYLUcARhA0XABG0EoIwGiYAIxWUwBGVysT4RCXi71FRG/K/HW5/JqUle1mJWh6WrZzyAnwYUfQGc8dwyAX5z5Op45vd6EcZyJAKZWDdR1Bbai0I1WSprKGtNp3v20Db0r3mzn3QTdC+p3NM538zGVfuK19V0M2Uh6UbXQod+tQam4XIDS2NjiQ2JG0LqBpjSytW74eHUlrJgKntSsoaasF/hwJGEowiC/vq9K2jwQkfaCmxz4+7tUVgNGNEoDRcgRgBEHDBWAErYQAjIYJwGg1BWC0FNnMQbQluUPbJkKhh3OA0c4S1ys5hqa+zQJquoT5NjtoQhEUnSpwdOYEIPF1BkbsFspygzoAZ4Ez6LZ/9aDzqehC6nEphctNnpINzqN1AUMMitZMe50B0ro4ldYkjHvUuJFM40gaZY6kZWl/DjB65ON9h8p5pKcrbfG/FAEY3SgBGC1HAEYQNFwARtBKCMBomACMVlMARpeuHQFAb0k52dty+W3VuSwHSclBdOGt73ui/JVlqMO5KgyATpynE+/opAFCPjqGFDDS5Wd15hRKoMmpdvP5apS6epW6ckHQUJW61rUf876uc7H0TAdlNyVqRJ0ytQSIAjAKgInhUgRM62RpU24LWWEmlo9WC753F5VXziMNhA6lbI1L2d6Xcrb3BS59IIDpYKU/UQBGN0oARssRgBEEDReAEbQSAjAaJgCj1RSA0YW1KXBoW6YdKSV7IA6itwvA6N7LlJSVdo1kAOVt5YNzSLqHnUnZWHIKnSRoxMCIXLicSs+mqu28Lv/qK/267V8faDVULHfzs7eHkG4bM5PWAiCytCGla5tGgFFwJkVglBxJlQJQleoKN+r5zr6Maum6lgOj9yUH6RNxKSUX0oHMj1funboBuu2jFACj5QjACIKGC8AIWgkBGA0TgNFqCsDo3BoLFHqHiN4lot8TGPSuamW/qZxD2yrQ+lJk2gM9BkHH3tOxi46hExIQxNeljCx2J2sdQlMNlMgryBSdGukPc/IImdwVZOASglZLqXxNO5Dy7KQ4N00nt6oDglogNKI2I2kUYJINTqQNKW0Lc8uAydKmZJaNzOUPzk6V6+hYzZ9KSdvvZPqNmj8J5aY3WQBGN0oARssRgBEEDReAEbQSAjAaJgCj1RSAUa8q5RzSLqLXpOSsBIzuXuSF5pS1OIqun6mAnalv52fSyv5YlZgF95DvAqMzAUKmAHwoh0EQBKWvX2c+A5wYKIU8JAFGkovEJWx8edPa4EbapOhQSk6kUZaJlPKSSt//i8hL2dpvxXWkgdEjmQ4LDqT6RrztAEY3SgBGyxGAEQQNF4ARtBICMBomAKPVFIBRUdsCgRIUSvPU4n43g0jb0mHppZQ2XbqInTbuoVhGdiylZMlNlJxD08wpNPU6zNp3BoImyxdCrhAEzaqUl6Rzktq2/8qB1JSjtUDIynwcXEdc3taWtm0JZApQSTq4Wbq8QdxZBoQOZEot/XMH0vviWLpeARjdKAEYLUcARhA0XABG0EoIwGiYAIxWU7ccGBmBPztqfldKzkrA6HUpLzv3i+QSt8JUQR92DfGcW9qzKyg5ho4kmDrAo7p1E010dzK4hiDo2tTnRmq6tYkTaaNKkCiCo+hEogCNNqTF/1hcSCNK8+hCmvkuX/AI+lCgUQkYsfvouYClfTW/uoN1AKMbJQCj5QjACIKGC8AIWgkBGA0TgNFq6hYDoy1xDH2aiD4l8wSH7mcOoi2Zv9TamdaewLDnSGAQO4aOHF93dFLzbTGceqodQ7okjeJct7KHawiCrkdlNxI1nqQYpm06bfpHKQNJZSUxFFqrDG1J0PaWtbQlYGnLUJjGl5SF5AUGHSnn0ZFkHCWI9G8y/VrCta8mNBvA6EYJwGg5AjCCoOECMIJWQgBGwwRgtJq6JcBIdzFLE8OiNwvA6E3qyRQ5zyo3sEe5hzgnxKVOZTF76Ig8HblYdnbknJSfRUjUdCorhEzf9o8tBK2iOk4knYlkIugdhfDs2MKfS9Y2Kc63QtlaDNReoxYwjaQb27iUg3SBI2wn7fl/mwGj1LJ/P5suv4QNwOhGCcBoOQIwgqDhAjCCVkILine truncated

Before

Width:  |  Height:  |  Size: 608 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="139" height="765" viewBox="0 0 139 765"><defs><style>.a{fill:url(#a);}</style><pattern id="a" width="1" height="1" patternTransform="matrix(-1, 0, 0, 1, 278, 0)" viewBox="0 0 139 765"><image preserveAspectRatio="none" width="139" height="765" xlink:href="data:image/png;base64,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 truncated

Before

Width:  |  Height:  |  Size: 50 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="139" height="765" viewBox="0 0 139 765"><image width="139" height="765" xlink:href="data:image/png;base64,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 truncated

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="727" height="727" viewBox="0 0 727 727"><defs><style>.a{fill:url(#a);}.b{fill:url(#d);}.c,.d,.f{fill:none;}.c{stroke:rgba(32,194,255,0);stroke-width:8px;}.d{stroke:rgba(32,194,255,0.15);stroke-width:5px;stroke-dasharray:7 5;}.e{stroke:none;}.g{filter:url(#e);}.h{filter:url(#b);}</style><linearGradient id="a" x1="0.351" y1="0.016" x2="0.065" y2="0.243" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#1ec6fe"/><stop offset="1" stop-color="#3279ff"/></linearGradient><filter id="b" x="88.068" y="60.324" width="217.004" height="181.59" filterUnits="userSpaceOnUse"><feOffset input="SourceAlpha"/><feGaussianBlur stdDeviation="7.5" result="c"/><feFlood flood-color="#1a9cff" flood-opacity="0.8"/><feComposite operator="in" in2="c"/><feComposite in="SourceGraphic"/></filter><linearGradient id="d" x1="0.025" y1="0.971" x2="0.971" y2="0.034" xlink:href="#a"/><filter id="e" x="424.041" y="484.359" width="215.309" height="181.689" filterUnits="userSpaceOnUse"><feOffset input="SourceAlpha"/><feGaussianBlur stdDeviation="7.5" result="f"/><feFlood flood-color="#1a9cff" flood-opacity="0.8"/><feComposite operator="in" in2="f"/><feComposite in="SourceGraphic"/></filter></defs><g transform="translate(4 4)"><g transform="translate(-126.998 -127.002)"><g class="h" transform="matrix(1, 0, 0, 1, 123, 123)"><path class="a" d="M18115.566-21172.494q4.919-8.443,10.389-16.543a294.531,294.531,0,0,1,35.713-43.289,294.545,294.545,0,0,1,43.293-35.717,292.5,292.5,0,0,1,49.682-26.969,290.614,290.614,0,0,1,31.271-11.162l1.656,5.506a288.092,288.092,0,0,0-166.973,131.084Z" transform="translate(-18005 21389)"/></g><g class="g" transform="matrix(1, 0, 0, 1, 123, 123)"><path class="b" d="M18451.539-20750.967a288.209,288.209,0,0,0,165.279-131.172l5.029,2.92q-5.1,8.815-10.8,17.258a294.659,294.659,0,0,1-35.717,43.287,294.647,294.647,0,0,1-43.293,35.717,292.2,292.2,0,0,1-49.686,26.971,291.1,291.1,0,0,1-29.178,10.537Z" transform="translate(-18005 21389)"/></g><circle class="c" cx="359.5" cy="359.5" r="359.5" transform="translate(126.998 127.002)"/></g><g class="d" transform="translate(98 98)"><circle class="e" cx="261.5" cy="261.5" r="261.5"/><circle class="f" cx="261.5" cy="261.5" r="259"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="458" height="113.588" viewBox="0 0 458 113.588"><defs><style>.a{fill:url(#a);}.b{fill:#fff;}.c{filter:url(#d);}.d{filter:url(#b);}</style><linearGradient id="a" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#f0feff"/><stop offset="1" stop-color="#c1e6ff"/></linearGradient><filter id="b" x="111.721" y="26.943" width="211.559" height="46.289" filterUnits="userSpaceOnUse"><feOffset dy="1" input="SourceAlpha"/><feGaussianBlur stdDeviation="3" result="c"/><feFlood flood-color="#00ffa2" flood-opacity="0.322"/><feComposite operator="in" in2="c"/><feComposite in="SourceGraphic"/></filter><filter id="d" x="111.721" y="26.943" width="211.559" height="46.289" filterUnits="userSpaceOnUse"><feOffset input="SourceAlpha"/><feGaussianBlur stdDeviation="2" result="e"/><feFlood flood-color="#fff" result="f"/><feComposite operator="out" in="SourceGraphic" in2="e"/><feComposite operator="in" in="f"/><feComposite operator="in" in2="SourceGraphic"/></filter></defs><g transform="translate(-731 -564.412)"><image width="458" height="113.588" transform="translate(731 564.412)" xlink:href="data:image/png;base64,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 truncated

Before

Width:  |  Height:  |  Size: 813 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="68" viewBox="0 0 68 68"><defs><style>.a{fill:#fff;opacity:0;}.b{fill:url(#a);}</style><linearGradient id="a" x1="0.405" x2="1" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#2bbaff"/><stop offset="0.498" stop-color="#1a8cfd"/><stop offset="1" stop-color="#006aef"/></linearGradient></defs><g transform="translate(14482.893 -23044.904)"><rect class="a" width="68" height="68" transform="translate(-14482.893 23044.904)"/><path class="b" d="M110.023,105.37H98.2a1.721,1.721,0,0,1-1.716-1.716v-1.918h10.189a1.721,1.721,0,0,0,1.716-1.716V72.8a1.721,1.721,0,0,0-1.716-1.716H98.2V67.437A3.444,3.444,0,0,0,94.76,64H87.83a3.444,3.444,0,0,0-3.437,3.437v3.652H75.625A1.721,1.721,0,0,0,73.91,72.8v27.21a1.721,1.721,0,0,0,1.716,1.716h10.49v1.918a1.721,1.721,0,0,1-1.716,1.716H72.3a1.721,1.721,0,0,0-1.716,1.716v10.1A1.721,1.721,0,0,0,72.3,118.9h37.724a1.721,1.721,0,0,0,1.716-1.716v-10.1A1.726,1.726,0,0,0,110.023,105.37Zm-8.406-19.1a3.437,3.437,0,1,1-3.437-3.437A3.436,3.436,0,0,1,101.616,86.266ZM87.83,67.437h6.924v3.646H87.83ZM81.121,86.266A3.437,3.437,0,1,1,84.558,89.7,3.436,3.436,0,0,1,81.121,86.266Zm32.48-7.089V93.355a1.716,1.716,0,0,1-3.431,0V79.177a1.716,1.716,0,0,1,3.431,0Zm5.122,3.548v6.881a1.716,1.716,0,0,1-3.431,0V82.724a1.716,1.716,0,0,1,3.431,0ZM70.644,95.07a1.717,1.717,0,0,1-1.716-1.716V79.177a1.716,1.716,0,0,1,3.431,0V93.355A1.713,1.713,0,0,1,70.644,95.07ZM67.231,82.724v6.881a1.716,1.716,0,1,1-3.431,0V82.724a1.716,1.716,0,0,1,3.431,0Zm0,0" transform="translate(-14540.154 22987.455)"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

@@ -1,48 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="188" height="241" viewBox="0 0 188 241" fill="none">
<defs>
<radialGradient id="surface" cx="0" cy="0" r="1" gradientTransform="translate(63 27) rotate(61) scale(148 156)" gradientUnits="userSpaceOnUse">
<stop stop-color="#FFFFFF"/>
<stop offset=".2" stop-color="#FAFDFF"/>
<stop offset=".48" stop-color="#E4F2FF"/>
<stop offset=".72" stop-color="#A7D4FF"/>
<stop offset="1" stop-color="#3C9AF4"/>
</radialGradient>
<radialGradient id="inner-blue" cx="0" cy="0" r="1" gradientTransform="translate(94 101) rotate(90) scale(68 84)" gradientUnits="userSpaceOnUse">
<stop stop-color="#68B6FF" stop-opacity=".58"/>
<stop offset="1" stop-color="#1688F7" stop-opacity="0"/>
</radialGradient>
<linearGradient id="lower-blue" x1="94" y1="103" x2="94" y2="165" gradientUnits="userSpaceOnUse">
<stop stop-color="#4EA7FA" stop-opacity="0"/>
<stop offset="1" stop-color="#188AF4" stop-opacity=".72"/>
</linearGradient>
<linearGradient id="edge" x1="38" y1="10" x2="151" y2="160" gradientUnits="userSpaceOnUse">
<stop stop-color="#FFFFFF" stop-opacity=".98"/>
<stop offset=".52" stop-color="#FFFFFF" stop-opacity=".86"/>
<stop offset="1" stop-color="#C6E8FF" stop-opacity=".9"/>
</linearGradient>
<filter id="glow" x="-13" y="-13" width="214" height="214" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feGaussianBlur stdDeviation="4.8"/>
</filter>
<filter id="shadow" x="18" y="162" width="152" height="49" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feGaussianBlur stdDeviation="7"/>
</filter>
<clipPath id="clip">
<circle cx="94" cy="82" r="81"/>
</clipPath>
</defs>
<ellipse cx="94" cy="188" rx="65" ry="9" fill="#147BD2" fill-opacity=".23" filter="url(#shadow)"/>
<circle cx="94" cy="82" r="82" fill="#5EBAFF" fill-opacity=".2" filter="url(#glow)"/>
<circle cx="94" cy="82" r="81" fill="url(#surface)"/>
<g clip-path="url(#clip)">
<ellipse cx="94" cy="106" rx="80" ry="61" fill="url(#inner-blue)"/>
<ellipse cx="94" cy="143" rx="91" ry="38" fill="url(#lower-blue)"/>
<ellipse cx="94" cy="151" rx="76" ry="14" fill="#FFFFFF" fill-opacity=".11"/>
<path d="M20 145C47 157 141 157 168 145" stroke="#FFFFFF" stroke-opacity=".28" stroke-width="1.2"/>
<path d="M31 160C55 168 133 168 157 160" stroke="#7CC4FF" stroke-opacity=".35" stroke-width="1.1"/>
<path d="M22 64C27 37 49 16 77 9" stroke="#FFFFFF" stroke-opacity=".42" stroke-width="8" stroke-linecap="round" filter="url(#glow)"/>
</g>
<circle cx="94" cy="82" r="81" stroke="url(#edge)" stroke-width="2"/>
<circle cx="94" cy="82" r="76" stroke="#FFFFFF" stroke-opacity=".24"/>
<path d="M19 70C24 39 49 13 81 5" stroke="#FFFFFF" stroke-opacity=".88" stroke-width="2" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.8 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="68" viewBox="0 0 68 68"><defs><style>.a{fill:#fff;stroke:#707070;stroke-width:3.75px;opacity:0;}.b{fill:url(#a);}.c{stroke:none;}.d{fill:none;}</style><linearGradient id="a" x1="0.431" x2="1" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#2bbaff"/><stop offset="0.498" stop-color="#1a8cfd"/><stop offset="1" stop-color="#006aef"/></linearGradient></defs><g transform="translate(-71.077 -67.746)"><g class="a" transform="translate(71.077 67.746)"><rect class="c" width="68" height="68"/><rect class="d" x="1.875" y="1.875" width="64.25" height="64.25"/></g><path class="b" d="M114.406,106.791a7.707,7.707,0,0,0-4.354,1.353L98.7,99.937a13.3,13.3,0,0,0,1.742-6.583c0-.421-.03-.842-.06-1.263L112,85.207a4.687,4.687,0,1,0-1.952-2.345L99.691,88.995a13.678,13.678,0,0,0-6.1-7.365l2.072-10.341c.15,0,.3.03.451.03a4.66,4.66,0,1,0-4.655-4.659,4.727,4.727,0,0,0,1.412,3.367l-2.1,10.462A13.479,13.479,0,0,0,80.05,81.87l-6.4-5.712A6.129,6.129,0,1,0,71.7,78.443L77.677,83.7a13.456,13.456,0,0,0,.691,19.991l-5.316,5.622a5.948,5.948,0,0,0-3.394-1.022,6.163,6.163,0,1,0,6.156,6.162,6.343,6.343,0,0,0-.721-2.916l5.826-6.193a13.464,13.464,0,0,0,16.1-2.946l11.022,7.966a7.77,7.77,0,0,0-1.2,4.118,7.658,7.658,0,1,0,15.316,0A7.817,7.817,0,0,0,114.406,106.791Zm0,0" transform="translate(13 9.671)"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="68" viewBox="0 0 68 68"><defs><style>.a{fill:#fff;opacity:0;}.b{fill:url(#a);}</style><linearGradient id="a" x1="0.337" x2="1" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#2bbaff"/><stop offset="0.498" stop-color="#1a8cfd"/><stop offset="1" stop-color="#006aef"/></linearGradient></defs><g transform="translate(-204.426 -230.797)"><rect class="a" width="68" height="68" transform="translate(204.426 230.797)"/><g transform="translate(209.658 232.191)"><path class="b" d="M25.52,64.045c-1.725-.852-8.6-4.486-10.846-5.656-2.309-1.207-3.3-1.01-5.09.146L6.346,60.67,0,46.383s6.887-3.254,10.033-4.508C15,39.885,17.273,41.6,20.115,43.4c1.209.762,5.131,3.664,5.131,3.664a17.886,17.886,0,0,0,7.783,2.316c5.928,0,6.975.344,6.975,2.266,0,2.113-3.859,2.266-3.883,2.266H26.605c-3.236,0-7.766-1.893-7.766-1.893s3.846,4.156,7.766,4.156h9.547c2.105-.047,6.1-1.047,6.1-4.537,0-4.529-4.066-4.529-9.219-4.529a5.2,5.2,0,0,1-1.127-.145c.2-.1.4-.207.639-.35.9-.523,2.145-1.27,3.535-2.158,3.67-2.3,5.555-2.592,7.387-.152a5.718,5.718,0,0,1,4.248-1.678c1.551,0,2.865,1.039,2.494,2.719,3.975-2.377,5.936-1.42,6.809-.266,1.156,1.527.373,3.109-2.143,4.926C53.244,51.17,37.809,61.543,35.635,62.82c-1.732,1-3.326,2.395-5.8,2.395A9.825,9.825,0,0,1,25.52,64.045ZM22.51,39.5l-.229-.865a.706.706,0,0,1,.129-.607.688.688,0,0,1,.557-.275H35.734a.689.689,0,0,1,.547.275.7.7,0,0,1,.121.607l-.219.865a7.065,7.065,0,0,1-13.674,0Zm6.84,2.486a4.265,4.265,0,0,0,3.178-1.424H26.174A4.239,4.239,0,0,0,29.35,41.982Zm-6.285-5.07a.885.885,0,1,1,0-1.77H35.658a.885.885,0,0,1-.008,1.77Zm-.189-2.637a.7.7,0,0,1-.707-.7V31.021a.565.565,0,0,0-.244-.461,13.168,13.168,0,1,1,14.844,0,.563.563,0,0,0-.242.461v2.547a.7.7,0,0,1-.7.707Zm8.672-8.785a6.207,6.207,0,0,0,2.455-.3c.547-.258.721-.676.721-1.572V14.719H33.059v8.887c0,.219-.1.281-.334.3-.234,0-1.033,0-1.732-.039A6.217,6.217,0,0,1,31.547,25.49Zm-6.18-2.166c0,1.535.463,1.967,1.969,1.967h1.7c1.285,0,1.717-.516,1.877-2.174a4.544,4.544,0,0,1-1.443-.607c-.062,1.141-.145,1.361-.586,1.361H27.557c-.494,0-.578-.055-.578-.562V20.117h1.475a3.131,3.131,0,0,1-.213,1.223.374.374,0,0,1-.334.131,6.154,6.154,0,0,1-.836-.047,3.419,3.419,0,0,1,.41,1.4,8.144,8.144,0,0,0,1.3-.045,1.284,1.284,0,0,0,.844-.455c.281-.35.395-1.223.465-3.107l.016-.2.744-.707v4.154h1.619V15.793H30.848V18.17a28.18,28.18,0,0,0-2.326-2.758c.084-.158.152-.328.221-.486l-1.535-.479a9.09,9.09,0,0,1-3.215,3.9,7.919,7.919,0,0,1,1.2,1.27l.174-.129Zm.906-4.643a11.211,11.211,0,0,0,1.465-1.855c.518.609,1.049,1.27,1.469,1.855Zm17.676-2.123a1.606,1.606,0,0,1,1.186-1.943l2.363-.578a1.608,1.608,0,0,1,.76,3.125l-2.369.576a1.629,1.629,0,0,1-.383.047A1.611,1.611,0,0,1,43.949,16.559ZM12.631,17.631,10.389,16.7a1.608,1.608,0,0,1,1.23-2.971l2.242.941a1.6,1.6,0,1,1-1.23,2.963Zm4.088-9.514L15.328,6.125a1.605,1.605,0,0,1,2.637-1.832l1.391,1.99a1.6,1.6,0,0,1-.4,2.234,1.58,1.58,0,0,1-.916.289A1.6,1.6,0,0,1,16.719,8.117Zm22.709.32a1.614,1.614,0,0,1-.273-2.252l1.488-1.914A1.6,1.6,0,1,1,43.174,6.24L41.686,8.16a1.626,1.626,0,0,1-2.258.277ZM27.746,4.043V1.6a1.607,1.607,0,0,1,3.215,0V4.043a1.607,1.607,0,0,1-3.215,0Z" transform="translate(0 0)"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 3.2 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="68" viewBox="0 0 68 68"><defs><style>.a{fill:#fff;opacity:0;}.b{fill:url(#a);}</style><linearGradient id="a" x1="0.405" x2="1" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#2bbaff"/><stop offset="0.498" stop-color="#1a8cfd"/><stop offset="1" stop-color="#006aef"/></linearGradient></defs><g transform="translate(14482.893 -23044.904)"><rect class="a" width="68" height="68" transform="translate(-14482.893 23044.904)"/><path class="b" d="M43.013,57.336h-.255l-.074,0a14.064,14.064,0,0,1-8.911-3.467,6.216,6.216,0,0,1,6.1-5.029h6.278a6.218,6.218,0,0,1,6.1,5.03A14.073,14.073,0,0,1,43.6,57.324h-.009l-.067,0H43.5l-.063,0h-.424ZM30.159,54.9H8.5a1.717,1.717,0,0,1-1.715-1.716v-10.1A1.717,1.717,0,0,1,8.5,41.363H20.6a1.717,1.717,0,0,0,1.716-1.715V37.73H11.824a1.717,1.717,0,0,1-1.716-1.715V8.8a1.718,1.718,0,0,1,1.716-1.716h8.768V3.437A3.44,3.44,0,0,1,24.029,0h6.93A3.441,3.441,0,0,1,34.4,3.437V7.089H42.87A1.718,1.718,0,0,1,44.586,8.8V26.022c-.515-.046-1.044-.07-1.574-.07A17.327,17.327,0,0,0,30.157,54.9Zm4.219-36.07a3.437,3.437,0,1,0,3.438,3.437A3.441,3.441,0,0,0,34.378,18.828Zm-13.619,0A3.437,3.437,0,1,0,24.2,22.265,3.441,3.441,0,0,0,20.758,18.828ZM24.029,3.437V7.083h6.924V3.437Zm7.256,47.59v0a14.059,14.059,0,1,1,23.456,0,9.508,9.508,0,0,0-8.589-5.455H44.686a7.193,7.193,0,1,0-3.347,0H39.873a9.5,9.5,0,0,0-8.587,5.457ZM43.013,42.5a3.923,3.923,0,1,1,3.923-3.924A3.928,3.928,0,0,1,43.013,42.5ZM6.844,31.07a1.717,1.717,0,0,1-1.716-1.715V15.176a1.715,1.715,0,1,1,3.431,0V29.355A1.717,1.717,0,0,1,6.844,31.07ZM49.8,27.327h0a17.187,17.187,0,0,0-3.429-1.051v-11.1a1.715,1.715,0,1,1,3.431,0v12.15Zm3.406-.007a1.717,1.717,0,0,1-1.715-1.715V18.724a1.715,1.715,0,0,1,3.431,0v6.881A1.717,1.717,0,0,1,53.206,27.32Zm-51.491,0A1.717,1.717,0,0,1,0,25.605V18.724a1.715,1.715,0,0,1,3.431,0v6.881A1.717,1.717,0,0,1,1.715,27.32Z" transform="translate(-14477.664 23050.15)"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="68" viewBox="0 0 68 68"><defs><style>.a{fill:#fff;stroke:#707070;stroke-width:3.75px;opacity:0;}.b{fill:url(#a);}.c{stroke:none;}.d{fill:none;}</style><linearGradient id="a" x1="0.414" x2="1" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#2bbaff"/><stop offset="0.498" stop-color="#1a8cfd"/><stop offset="1" stop-color="#006aef"/></linearGradient></defs><g transform="translate(-2.29 3.525)"><g class="a" transform="translate(2.29 -3.525)"><rect class="c" width="68" height="68"/><rect class="d" x="1.875" y="1.875" width="64.25" height="64.25"/></g><path class="b" d="M36.066,58.469a15.431,15.431,0,0,1,0-21.866,15.011,15.011,0,0,1,3.577-2.662,2.018,2.018,0,0,1,1.878,3.571,11.53,11.53,0,0,0-2.6,1.947A11.446,11.446,0,0,0,55.132,55.622a11.938,11.938,0,0,0,1.878-2.462A2.02,2.02,0,1,1,60.5,55.2,15.711,15.711,0,0,1,58,58.469a15.533,15.533,0,0,1-21.929,0Zm-5.87-.994H5.225A5.225,5.225,0,0,1,0,52.263V13.925A5.226,5.226,0,0,1,5.225,8.712H53.769A5.226,5.226,0,0,1,59,13.925V32.117A19.526,19.526,0,0,0,30.2,57.474v0ZM21.753,18.77l-8.5,7.4a2.531,2.531,0,0,0-.239,3.565,2.536,2.536,0,0,0,3.568.239l6.835-5.958L28.446,28.4a2.52,2.52,0,0,0,3.351-.015L42.282,19a2.508,2.508,0,0,0,.191-3.557,2.529,2.529,0,0,0-3.567-.192L30.085,23.14l-5-4.369a2.544,2.544,0,0,0-3.335,0ZM47.03,49.554a2.017,2.017,0,0,1-2.022-2.017V34.091a2.021,2.021,0,0,1,2.022-2.017A15.485,15.485,0,0,1,62.537,47.537a2.018,2.018,0,0,1-2.024,2.017Zm2.025-4.034h9.258a11.471,11.471,0,0,0-9.258-9.229ZM7.53,5.051a2.521,2.521,0,1,1,0-5.043H50.681a2.521,2.521,0,1,1,0,5.043Z" transform="translate(6.296 0.013)"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="582" height="667" viewBox="0 0 582 667"><image width="582" height="667" xlink:href="data:image/png;base64,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 truncated

Before

Width:  |  Height:  |  Size: 664 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="53" height="53" viewBox="0 0 53 53"><defs><style>.a{fill:rgba(0,121,254,0.3);stroke:rgba(0,121,254,0.5);}.b{fill:url(#a);}</style><linearGradient id="a" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#92eeff"/><stop offset="1" stop-color="#00c7ff"/></linearGradient></defs><g transform="translate(0.5 -115.502)"><rect class="a" width="52" height="52" rx="8" transform="translate(0 116.002)"/><g transform="translate(2.236 118.236)"><path class="b" d="M9204.336-22218.762a6.4,6.4,0,0,1-2.489-.691,6.242,6.242,0,0,1-2-1.615,6.363,6.363,0,0,1-1.206-2.283,6.357,6.357,0,0,1-.246-1.863c-.047-.033-.094-.066-.139-.1a6.4,6.4,0,0,1-2.272-3.4,6.418,6.418,0,0,1,.268-4.076,6.336,6.336,0,0,1,1.233-1.912,6.383,6.383,0,0,1-.4-1.973,6.41,6.41,0,0,1,.53-2.809,6.441,6.441,0,0,1,1.7-2.289,6.424,6.424,0,0,1,1.751-1.057,4.969,4.969,0,0,1,.343-1.289,4.965,4.965,0,0,1,1.334-1.859,5.038,5.038,0,0,1,2.016-1.082,5.037,5.037,0,0,1,2.289-.074,5.024,5.024,0,0,1,2.089.943,4.947,4.947,0,0,1,.871.861,5.147,5.147,0,0,1,.876-.861,5,5,0,0,1,2.083-.943,5.035,5.035,0,0,1,2.289.074,5.06,5.06,0,0,1,2.021,1.082,5.031,5.031,0,0,1,1.334,1.859,5.008,5.008,0,0,1,.343,1.289,6.424,6.424,0,0,1,1.751,1.057,6.441,6.441,0,0,1,1.7,2.289,6.405,6.405,0,0,1,.524,2.809,6.434,6.434,0,0,1-.4,1.973,6.315,6.315,0,0,1,1.234,1.912,6.418,6.418,0,0,1,.268,4.076,6.4,6.4,0,0,1-2.272,3.4l-.143.105a6.214,6.214,0,0,1-.248,1.859,6.26,6.26,0,0,1-1.2,2.283,6.271,6.271,0,0,1-2.01,1.615,6.354,6.354,0,0,1-2.485.691c-.14.006-.278.012-.418.012a6.213,6.213,0,0,1-2.139-.375,6.394,6.394,0,0,1-2.2-1.34,6.4,6.4,0,0,1-.915-1.066,6.415,6.415,0,0,1-.91,1.066,6.427,6.427,0,0,1-2.206,1.34,6.283,6.283,0,0,1-2.143.377C9204.609-22218.748,9204.473-22218.752,9204.336-22218.762Zm6.768-6.342a4.232,4.232,0,0,0,.346,1.652,4.123,4.123,0,0,0,.972,1.379,4.116,4.116,0,0,0,1.44.877,4.062,4.062,0,0,0,1.67.234,4.159,4.159,0,0,0,1.63-.447,4.159,4.159,0,0,0,1.313-1.061,4.227,4.227,0,0,0,.787-1.49c.02-.07.037-.139.054-.209a6.32,6.32,0,0,1-1.422.164,1.1,1.1,0,0,1-1.1-1.1,1.1,1.1,0,0,1,1.1-1.1,4.178,4.178,0,0,0,2.529-.859,4.138,4.138,0,0,0,1.485-2.221,4.216,4.216,0,0,0-.173-2.67,4.2,4.2,0,0,0-1.765-2.01,1.1,1.1,0,0,1-.4-1.5,1.1,1.1,0,0,1,1.063-.543,4.16,4.16,0,0,0,.1-.758,4.249,4.249,0,0,0-.346-1.838,4.156,4.156,0,0,0-1.117-1.5,4.078,4.078,0,0,0-.569-.408,4.928,4.928,0,0,1-.385.838,1.1,1.1,0,0,1-.955.553,1.08,1.08,0,0,1-.547-.15,1.093,1.093,0,0,1-.4-1.5,2.906,2.906,0,0,0,.374-1.229,1.022,1.022,0,0,1,.006-.145,2.841,2.841,0,0,0-.218-1.133,2.836,2.836,0,0,0-.754-1.051,2.794,2.794,0,0,0-1.139-.607,2.8,2.8,0,0,0-1.29-.045,2.782,2.782,0,0,0-1.173.535,2.84,2.84,0,0,0-.82.994,2.912,2.912,0,0,0-.3,1.262v5.254a4.426,4.426,0,0,0,.877,2.625,4.4,4.4,0,0,0,2.277,1.58,1.1,1.1,0,0,1,.748,1.361,1.1,1.1,0,0,1-1.367.748,6.6,6.6,0,0,1-2.535-1.41v6.928Zm-10.352,1.145a4.119,4.119,0,0,0,.787,1.49,4.148,4.148,0,0,0,1.313,1.061,4.105,4.105,0,0,0,1.624.447,4.076,4.076,0,0,0,1.676-.234,4.125,4.125,0,0,0,1.44-.877,4.208,4.208,0,0,0,.972-1.379,4.226,4.226,0,0,0,.34-1.652v-6.924a6.628,6.628,0,0,1-2.534,1.406,1.117,1.117,0,0,1-.308.045,1.1,1.1,0,0,1-1.055-.793,1.093,1.093,0,0,1,.748-1.361,4.393,4.393,0,0,0,2.272-1.58,4.354,4.354,0,0,0,.876-2.625v-5.254a2.906,2.906,0,0,0-.29-1.262,2.84,2.84,0,0,0-.82-.994,2.778,2.778,0,0,0-1.179-.535,2.8,2.8,0,0,0-1.29.045,2.832,2.832,0,0,0-1.139.607,2.821,2.821,0,0,0-.748,1.051,2.819,2.819,0,0,0-.212,1.271,2.821,2.821,0,0,0,.374,1.234,1.1,1.1,0,0,1-.4,1.5,1.1,1.1,0,0,1-1.5-.4,5.009,5.009,0,0,1-.386-.838,4.127,4.127,0,0,0-.568.408,4.156,4.156,0,0,0-1.117,1.5,4.249,4.249,0,0,0-.346,1.838,4.246,4.246,0,0,0,.1.758,1.106,1.106,0,0,1,1.064.543,1.1,1.1,0,0,1-.4,1.5,4.2,4.2,0,0,0-1.765,2.01,4.216,4.216,0,0,0-.173,2.67,4.138,4.138,0,0,0,1.485,2.221,4.178,4.178,0,0,0,2.529.859,1.1,1.1,0,0,1,1.1,1.1,1.1,1.1,0,0,1-1.1,1.1,6.32,6.32,0,0,1-1.422-.164C9200.714-22224.1,9200.732-22224.029,9200.752-22223.959Z" transform="translate(-9186.242 22256.754)"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 4.0 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="53" height="53" viewBox="0 0 53 53"><defs><style>.a{fill:rgba(0,121,254,0.3);stroke:rgba(0,121,254,0.5);}.b{opacity:0;}.b,.c{fill:url(#a);}</style><linearGradient id="a" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#92eeff"/><stop offset="1" stop-color="#00c7ff"/></linearGradient></defs><g transform="translate(0.5 -115.502)"><rect class="a" width="52" height="52" rx="8" transform="translate(0 116.002)"/><g transform="translate(18559 4825)"><rect class="b" width="42" height="42" transform="translate(-18554 -4704)"/><path class="c" d="M-9736.837-26950.139a1.008,1.008,0,0,1-.542-.889v-3.371h-.752a4.506,4.506,0,0,1-4.5-4.5v-2.629c-1.89-.08-3.366-2-3.366-4.367s1.477-4.287,3.366-4.369v-2.633a4.5,4.5,0,0,1,4.5-4.5h15.658v.129a3.676,3.676,0,0,0,.494,1.869h-16.152a2.5,2.5,0,0,0-2.5,2.5v14a2.5,2.5,0,0,0,2.5,2.5h1.741a1.006,1.006,0,0,1,1.009,1v2.432l4.544-3.244a.97.97,0,0,1,.576-.189h13.124a2.5,2.5,0,0,0,2.506-2.5v-9.441a3.524,3.524,0,0,0,1.118.189h.033a3.634,3.634,0,0,0,2.764-1.293,4.793,4.793,0,0,1,1.456,3.549,5.014,5.014,0,0,1-.982,3.041,3.23,3.23,0,0,1-2.391,1.334v2.621a4.507,4.507,0,0,1-4.5,4.5h-12.806l-5.858,4.184a1.021,1.021,0,0,1-.582.191A1.007,1.007,0,0,1-9736.837-26950.139Zm1.334-10.389a1.876,1.876,0,0,1-1.876-1.877v-7.869a1.876,1.876,0,0,1,1.876-1.877h15.739a1.876,1.876,0,0,1,1.876,1.877v7.869a1.876,1.876,0,0,1-1.876,1.877Zm10.931-5.811a1.752,1.752,0,0,0,1.754,1.746,1.751,1.751,0,0,0,1.747-1.746,1.754,1.754,0,0,0-1.747-1.756A1.755,1.755,0,0,0-9724.572-26966.338Zm-9.617,0a1.752,1.752,0,0,0,1.748,1.746,1.751,1.751,0,0,0,1.747-1.746,1.755,1.755,0,0,0-1.747-1.756A1.755,1.755,0,0,0-9734.189-26966.338Zm20.1-5.277-.453-1.551a4.433,4.433,0,0,0-2.946-3.006l-1.537-.467a.649.649,0,0,1-.447-.611.524.524,0,0,1,.021-.148.616.616,0,0,1,.217-.346.624.624,0,0,1,.217-.115l.284-.088,1.232-.365a4.417,4.417,0,0,0,2.96-3.02l.46-1.551a.625.625,0,0,1,.42-.434v.006a.538.538,0,0,1,.183-.033.574.574,0,0,1,.292.08.581.581,0,0,1,.3.381l.46,1.557a4.422,4.422,0,0,0,2.96,3.014l1.171.346.346.107a.647.647,0,0,1,.454.609.641.641,0,0,1-.447.611l-1.537.467a4.434,4.434,0,0,0-2.946,3.006l-.453,1.551a.631.631,0,0,1-.6.461A.636.636,0,0,1-9714.089-26971.615Zm-4.571-7.34-.183-.623a2.7,2.7,0,0,0-1.829-1.83l-.623-.189a.29.29,0,0,1-.2-.277.284.284,0,0,1,.2-.277l.61-.184a2.7,2.7,0,0,0,1.842-1.842l.183-.615a.32.32,0,0,1,.2-.2.327.327,0,0,1,.224.027.275.275,0,0,1,.143.17l.183.615a2.713,2.713,0,0,0,1.842,1.842l.609.184a.289.289,0,0,1,.21.277.3.3,0,0,1-.21.277l-.257.076-.366.113a2.725,2.725,0,0,0-1.828,1.83l-.183.623a.293.293,0,0,1-.278.2A.3.3,0,0,1-9718.66-26978.955Z" transform="translate(-8805.37 22282.029)"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="53" height="53" viewBox="0 0 53 53"><defs><style>.a{fill:rgba(0,121,254,0.3);stroke:rgba(0,121,254,0.5);}.b{fill:#fff;opacity:0;}.c{fill:url(#a);}</style><linearGradient id="a" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#92eeff"/><stop offset="1" stop-color="#00c7ff"/></linearGradient></defs><g transform="translate(0.5 -115.502)"><rect class="a" width="52" height="52" rx="8" transform="translate(0 116.002)"/><g transform="translate(18558 4829)"><rect class="b" width="42" height="42" transform="translate(-18553 -4708)"/><path class="c" d="M-9520.252-26774.373h-17.5a8.261,8.261,0,0,1-8.248-8.254v-8.746a8.261,8.261,0,0,1,8.248-8.256h7.75v-2.582a2.5,2.5,0,0,1-1.5-2.287,2.506,2.506,0,0,1,2.5-2.5,2.5,2.5,0,0,1,2.5,2.5,2.515,2.515,0,0,1-1.5,2.293v2.576h2.752a1.254,1.254,0,0,1,1.251,1.252,1.254,1.254,0,0,1-1.251,1.252h-12.5a5.758,5.758,0,0,0-5.752,5.752v8.746a5.758,5.758,0,0,0,5.752,5.752h17.5a5.758,5.758,0,0,0,5.752-5.752v-5.746a1.252,1.252,0,0,1,1.251-1.25,1.252,1.252,0,0,1,1.252,1.25v5.746A8.264,8.264,0,0,1-9520.252-26774.373Zm-2.624-6.25h-12.251a5.506,5.506,0,0,1-5.5-5.5,5.5,5.5,0,0,1,5.5-5.5h12.251a5.507,5.507,0,0,1,5.5,5.5A5.509,5.509,0,0,1-9522.876-26780.623Zm-.989-7.812a.992.992,0,0,0-.706.291l-1.312,1.313a1,1,0,0,0-.289.707.985.985,0,0,0,.289.705l1.313,1.313a1,1,0,0,0,.706.3,1,1,0,0,0,.706-.3.988.988,0,0,0,.293-.707.987.987,0,0,0-.293-.705l-.605-.605.605-.605a.988.988,0,0,0,.293-.707.988.988,0,0,0-.293-.707A.988.988,0,0,0-9523.865-26788.436Zm-10.388.561a1.751,1.751,0,0,0-1.749,1.75,1.75,1.75,0,0,0,1.749,1.748,1.75,1.75,0,0,0,1.749-1.748A1.751,1.751,0,0,0-9534.253-26787.875Zm19.262-3.531a.587.587,0,0,1-.552-.4l-1.5-4.568-4.555-1.447a.593.593,0,0,1-.4-.551.577.577,0,0,1,.4-.553l4.5-1.514,1.419-4.5a.59.59,0,0,1,.557-.412.609.609,0,0,1,.17.027.569.569,0,0,1,.377.377l1.5,4.568,4.7,1.668a.579.579,0,0,1,.384.559.59.59,0,0,1-.417.545l-4.6,1.293-1.426,4.5A.572.572,0,0,1-9514.991-26791.406Z" transform="translate(-9002.999 22102.623)"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1920" height="1080" viewBox="0 0 1920 1080"><defs><style>.a{fill:url(#a);}</style><pattern id="a" preserveAspectRatio="xMidYMid slice" width="100%" height="100%" viewBox="0 0 3840 2160"><image width="3840" height="2160" xlink:href="data:image/png;base64,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 truncated

Before

Width:  |  Height:  |  Size: 4.3 MiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="582" height="667" viewBox="0 0 582 667"><defs><style>.a{fill:#fff;opacity:0;}.b{fill:url(#a);}</style><pattern id="a" preserveAspectRatio="xMidYMid slice" width="100%" height="100%" viewBox="0 0 1164 1312"><image width="1164" height="1312" xlink:href="data:image/png;base64,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 truncated

Before

Width:  |  Height:  |  Size: 968 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="139" height="765" viewBox="0 0 139 765"><defs><style>.a{fill:url(#a);}</style><pattern id="a" width="1" height="1" patternTransform="matrix(-1, 0, 0, 1, 278, 0)" viewBox="0 0 139 765"><image preserveAspectRatio="xMidYMid slice" width="139" height="765" xlink:href="data:image/png;base64,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 truncated

Before

Width:  |  Height:  |  Size: 53 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="139" height="765" viewBox="0 0 139 765"><defs><style>.a{fill:url(#a);}</style><pattern id="a" preserveAspectRatio="xMidYMid slice" width="100%" height="100%" viewBox="0 0 278 1530"><image width="278" height="1530" xlink:href="data:image/png;base64,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 truncated

Before

Width:  |  Height:  |  Size: 53 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="68" viewBox="0 0 68 68"><defs><style>.a{fill:#fff;opacity:0;}.b{fill:url(#a);}</style><linearGradient id="a" x1="0.405" x2="1" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#a6cfff"/></linearGradient></defs><g transform="translate(14482.893 -23044.904)"><rect class="a" width="68" height="68" transform="translate(-14482.893 23044.904)"/><path class="b" d="M110.023,105.37H98.2a1.721,1.721,0,0,1-1.716-1.716v-1.918h10.189a1.721,1.721,0,0,0,1.716-1.716V72.8a1.721,1.721,0,0,0-1.716-1.716H98.2V67.437A3.444,3.444,0,0,0,94.76,64H87.83a3.444,3.444,0,0,0-3.437,3.437v3.652H75.625A1.721,1.721,0,0,0,73.91,72.8v27.21a1.721,1.721,0,0,0,1.716,1.716h10.49v1.918a1.721,1.721,0,0,1-1.716,1.716H72.3a1.721,1.721,0,0,0-1.716,1.716v10.1A1.721,1.721,0,0,0,72.3,118.9h37.724a1.721,1.721,0,0,0,1.716-1.716v-10.1A1.726,1.726,0,0,0,110.023,105.37Zm-8.406-19.1a3.437,3.437,0,1,1-3.437-3.437A3.436,3.436,0,0,1,101.616,86.266ZM87.83,67.437h6.924v3.646H87.83ZM81.121,86.266A3.437,3.437,0,1,1,84.558,89.7,3.436,3.436,0,0,1,81.121,86.266Zm32.48-7.089V93.355a1.716,1.716,0,0,1-3.431,0V79.177a1.716,1.716,0,0,1,3.431,0Zm5.122,3.548v6.881a1.716,1.716,0,0,1-3.431,0V82.724a1.716,1.716,0,0,1,3.431,0ZM70.644,95.07a1.717,1.717,0,0,1-1.716-1.716V79.177a1.716,1.716,0,0,1,3.431,0V93.355A1.713,1.713,0,0,1,70.644,95.07ZM67.231,82.724v6.881a1.716,1.716,0,1,1-3.431,0V82.724a1.716,1.716,0,0,1,3.431,0Zm0,0" transform="translate(-14540.154 22987.455)"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.5 KiB

@@ -1,47 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="188" height="241" viewBox="0 0 188 241" fill="none">
<defs>
<radialGradient id="surface" cx="0" cy="0" r="1" gradientTransform="translate(60 30) rotate(60) scale(150 158)" gradientUnits="userSpaceOnUse">
<stop stop-color="#46B6FF"/>
<stop offset=".24" stop-color="#1A83DE"/>
<stop offset=".6" stop-color="#075FBC"/>
<stop offset="1" stop-color="#003675"/>
</radialGradient>
<radialGradient id="inner-light" cx="0" cy="0" r="1" gradientTransform="translate(94 82) rotate(90) scale(79 84)" gradientUnits="userSpaceOnUse">
<stop stop-color="#0876DC" stop-opacity=".42"/>
<stop offset="1" stop-color="#001F55" stop-opacity="0"/>
</radialGradient>
<linearGradient id="lower-depth" x1="94" y1="118" x2="94" y2="165" gradientUnits="userSpaceOnUse">
<stop stop-color="#005DBB" stop-opacity="0"/>
<stop offset="1" stop-color="#002A68" stop-opacity=".58"/>
</linearGradient>
<linearGradient id="edge" x1="36" y1="12" x2="152" y2="160" gradientUnits="userSpaceOnUse">
<stop stop-color="#FFFFFF" stop-opacity=".98"/>
<stop offset=".48" stop-color="#B6EAFF" stop-opacity=".78"/>
<stop offset="1" stop-color="#48BBFF" stop-opacity=".72"/>
</linearGradient>
<filter id="glow" x="-12" y="-12" width="212" height="212" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feGaussianBlur stdDeviation="4.5"/>
</filter>
<filter id="shadow" x="22" y="163" width="144" height="48" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feGaussianBlur stdDeviation="6.5"/>
</filter>
<clipPath id="clip">
<circle cx="94" cy="82" r="81"/>
</clipPath>
</defs>
<ellipse cx="94" cy="188" rx="61" ry="9" fill="#00112F" fill-opacity=".58" filter="url(#shadow)"/>
<circle cx="94" cy="82" r="82" fill="#139DFF" fill-opacity=".22" filter="url(#glow)"/>
<circle cx="94" cy="82" r="81" fill="url(#surface)"/>
<g clip-path="url(#clip)">
<circle cx="94" cy="82" r="79" fill="url(#inner-light)"/>
<ellipse cx="94" cy="142" rx="89" ry="38" fill="url(#lower-depth)"/>
<ellipse cx="94" cy="150" rx="78" ry="15" fill="#55B9FF" fill-opacity=".13"/>
<path d="M19 145C46 157 142 157 169 145" stroke="#BCEAFF" stroke-opacity=".24" stroke-width="1.2"/>
<path d="M30 160C54 169 134 169 158 160" stroke="#1599F7" stroke-opacity=".28" stroke-width="1.2"/>
<path d="M24 62C29 36 49 17 76 11" stroke="#D8F4FF" stroke-opacity=".3" stroke-width="9" stroke-linecap="round" filter="url(#glow)"/>
</g>
<circle cx="94" cy="82" r="81" stroke="url(#edge)" stroke-width="2"/>
<circle cx="94" cy="82" r="76" stroke="#27B2FF" stroke-opacity=".28"/>
<path d="M19 69C24 38 49 12 82 4" stroke="#FFFFFF" stroke-opacity=".88" stroke-width="2" stroke-linecap="round"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.8 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="68" viewBox="0 0 68 68"><defs><style>.a{fill:#fff;stroke:#707070;stroke-width:3.75px;opacity:0;}.b{fill:url(#a);}.c{stroke:none;}.d{fill:none;}</style><linearGradient id="a" x1="0.431" x2="1" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#a6cfff"/></linearGradient></defs><g transform="translate(-71.077 -67.746)"><g class="a" transform="translate(71.077 67.746)"><rect class="c" width="68" height="68"/><rect class="d" x="1.875" y="1.875" width="64.25" height="64.25"/></g><path class="b" d="M114.406,106.791a7.707,7.707,0,0,0-4.354,1.353L98.7,99.937a13.3,13.3,0,0,0,1.742-6.583c0-.421-.03-.842-.06-1.263L112,85.207a4.687,4.687,0,1,0-1.952-2.345L99.691,88.995a13.678,13.678,0,0,0-6.1-7.365l2.072-10.341c.15,0,.3.03.451.03a4.66,4.66,0,1,0-4.655-4.659,4.727,4.727,0,0,0,1.412,3.367l-2.1,10.462A13.479,13.479,0,0,0,80.05,81.87l-6.4-5.712A6.129,6.129,0,1,0,71.7,78.443L77.677,83.7a13.456,13.456,0,0,0,.691,19.991l-5.316,5.622a5.948,5.948,0,0,0-3.394-1.022,6.163,6.163,0,1,0,6.156,6.162,6.343,6.343,0,0,0-.721-2.916l5.826-6.193a13.464,13.464,0,0,0,16.1-2.946l11.022,7.966a7.77,7.77,0,0,0-1.2,4.118,7.658,7.658,0,1,0,15.316,0A7.817,7.817,0,0,0,114.406,106.791Zm0,0" transform="translate(13 9.671)"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="68" viewBox="0 0 68 68"><defs><style>.a{fill:#fff;opacity:0;}.b{fill:url(#a);}</style><linearGradient id="a" x1="0.337" x2="1" y2="1.007" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#a6cfff"/></linearGradient></defs><g transform="translate(-204.426 -230.797)"><rect class="a" width="68" height="68" transform="translate(204.426 230.797)"/><g transform="translate(209.658 232.191)"><path class="b" d="M25.52,64.045c-1.725-.852-8.6-4.486-10.846-5.656-2.309-1.207-3.3-1.01-5.09.146L6.346,60.67,0,46.383s6.887-3.254,10.033-4.508C15,39.885,17.273,41.6,20.115,43.4c1.209.762,5.131,3.664,5.131,3.664a17.886,17.886,0,0,0,7.783,2.316c5.928,0,6.975.344,6.975,2.266,0,2.113-3.859,2.266-3.883,2.266H26.605c-3.236,0-7.766-1.893-7.766-1.893s3.846,4.156,7.766,4.156h9.547c2.105-.047,6.1-1.047,6.1-4.537,0-4.529-4.066-4.529-9.219-4.529a5.2,5.2,0,0,1-1.127-.145c.2-.1.4-.207.639-.35.9-.523,2.145-1.27,3.535-2.158,3.67-2.3,5.555-2.592,7.387-.152a5.718,5.718,0,0,1,4.248-1.678c1.551,0,2.865,1.039,2.494,2.719,3.975-2.377,5.936-1.42,6.809-.266,1.156,1.527.373,3.109-2.143,4.926C53.244,51.17,37.809,61.543,35.635,62.82c-1.732,1-3.326,2.395-5.8,2.395A9.825,9.825,0,0,1,25.52,64.045ZM22.51,39.5l-.229-.865a.706.706,0,0,1,.129-.607.688.688,0,0,1,.557-.275H35.734a.689.689,0,0,1,.547.275.7.7,0,0,1,.121.607l-.219.865a7.065,7.065,0,0,1-13.674,0Zm6.84,2.486a4.265,4.265,0,0,0,3.178-1.424H26.174A4.239,4.239,0,0,0,29.35,41.982Zm-6.285-5.07a.885.885,0,1,1,0-1.77H35.658a.885.885,0,0,1-.008,1.77Zm-.189-2.637a.7.7,0,0,1-.707-.7V31.021a.565.565,0,0,0-.244-.461,13.168,13.168,0,1,1,14.844,0,.563.563,0,0,0-.242.461v2.547a.7.7,0,0,1-.7.707Zm8.672-8.785a6.207,6.207,0,0,0,2.455-.3c.547-.258.721-.676.721-1.572V14.719H33.059v8.887c0,.219-.1.281-.334.3-.234,0-1.033,0-1.732-.039A6.217,6.217,0,0,1,31.547,25.49Zm-6.18-2.166c0,1.535.463,1.967,1.969,1.967h1.7c1.285,0,1.717-.516,1.877-2.174a4.544,4.544,0,0,1-1.443-.607c-.062,1.141-.145,1.361-.586,1.361H27.557c-.494,0-.578-.055-.578-.562V20.117h1.475a3.131,3.131,0,0,1-.213,1.223.374.374,0,0,1-.334.131,6.154,6.154,0,0,1-.836-.047,3.419,3.419,0,0,1,.41,1.4,8.144,8.144,0,0,0,1.3-.045,1.284,1.284,0,0,0,.844-.455c.281-.35.395-1.223.465-3.107l.016-.2.744-.707v4.154h1.619V15.793H30.848V18.17a28.18,28.18,0,0,0-2.326-2.758c.084-.158.152-.328.221-.486l-1.535-.479a9.09,9.09,0,0,1-3.215,3.9,7.919,7.919,0,0,1,1.2,1.27l.174-.129Zm.906-4.643a11.211,11.211,0,0,0,1.465-1.855c.518.609,1.049,1.27,1.469,1.855Zm17.676-2.123a1.606,1.606,0,0,1,1.186-1.943l2.363-.578a1.608,1.608,0,0,1,.76,3.125l-2.369.576a1.629,1.629,0,0,1-.383.047A1.611,1.611,0,0,1,43.949,16.559ZM12.631,17.631,10.389,16.7a1.608,1.608,0,0,1,1.23-2.971l2.242.941a1.6,1.6,0,1,1-1.23,2.963Zm4.088-9.514L15.328,6.125a1.605,1.605,0,0,1,2.637-1.832l1.391,1.99a1.6,1.6,0,0,1-.4,2.234,1.58,1.58,0,0,1-.916.289A1.6,1.6,0,0,1,16.719,8.117Zm22.709.32a1.614,1.614,0,0,1-.273-2.252l1.488-1.914A1.6,1.6,0,1,1,43.174,6.24L41.686,8.16a1.626,1.626,0,0,1-2.258.277ZM27.746,4.043V1.6a1.607,1.607,0,0,1,3.215,0V4.043a1.607,1.607,0,0,1-3.215,0Z" transform="translate(0 0)"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 3.1 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="68" viewBox="0 0 68 68"><defs><style>.a{fill:#fff;opacity:0;}.b{fill:url(#a);}</style><linearGradient id="a" x1="0.405" x2="1" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#a6cfff"/></linearGradient></defs><g transform="translate(14482.893 -23044.904)"><rect class="a" width="68" height="68" transform="translate(-14482.893 23044.904)"/><path class="b" d="M43.013,57.336h-.255l-.074,0a14.064,14.064,0,0,1-8.911-3.467,6.216,6.216,0,0,1,6.1-5.029h6.278a6.218,6.218,0,0,1,6.1,5.03A14.073,14.073,0,0,1,43.6,57.324h-.009l-.067,0H43.5l-.063,0h-.424ZM30.159,54.9H8.5a1.717,1.717,0,0,1-1.715-1.716v-10.1A1.717,1.717,0,0,1,8.5,41.363H20.6a1.717,1.717,0,0,0,1.716-1.715V37.73H11.824a1.717,1.717,0,0,1-1.716-1.715V8.8a1.718,1.718,0,0,1,1.716-1.716h8.768V3.437A3.44,3.44,0,0,1,24.029,0h6.93A3.441,3.441,0,0,1,34.4,3.437V7.089H42.87A1.718,1.718,0,0,1,44.586,8.8V26.022c-.515-.046-1.044-.07-1.574-.07A17.327,17.327,0,0,0,30.157,54.9Zm4.219-36.07a3.437,3.437,0,1,0,3.438,3.437A3.441,3.441,0,0,0,34.378,18.828Zm-13.619,0A3.437,3.437,0,1,0,24.2,22.265,3.441,3.441,0,0,0,20.758,18.828ZM24.029,3.437V7.083h6.924V3.437Zm7.256,47.59v0a14.059,14.059,0,1,1,23.456,0,9.508,9.508,0,0,0-8.589-5.455H44.686a7.193,7.193,0,1,0-3.347,0H39.873a9.5,9.5,0,0,0-8.587,5.457ZM43.013,42.5a3.923,3.923,0,1,1,3.923-3.924A3.928,3.928,0,0,1,43.013,42.5ZM6.844,31.07a1.717,1.717,0,0,1-1.716-1.715V15.176a1.715,1.715,0,1,1,3.431,0V29.355A1.717,1.717,0,0,1,6.844,31.07ZM49.8,27.327h0a17.187,17.187,0,0,0-3.429-1.051v-11.1a1.715,1.715,0,1,1,3.431,0v12.15Zm3.406-.007a1.717,1.717,0,0,1-1.715-1.715V18.724a1.715,1.715,0,0,1,3.431,0v6.881A1.717,1.717,0,0,1,53.206,27.32Zm-51.491,0A1.717,1.717,0,0,1,0,25.605V18.724a1.715,1.715,0,0,1,3.431,0v6.881A1.717,1.717,0,0,1,1.715,27.32Z" transform="translate(-14477.664 23050.15)"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="68" viewBox="0 0 68 68"><defs><style>.a{fill:#fff;stroke:#707070;stroke-width:3.75px;opacity:0;}.b{fill:url(#a);}.c{stroke:none;}.d{fill:none;}</style><linearGradient id="a" x1="0.207" x2="0.793" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#a6cfff"/></linearGradient></defs><g transform="translate(-2.29 3.525)"><g class="a" transform="translate(2.29 -3.525)"><rect class="c" width="68" height="68"/><rect class="d" x="1.875" y="1.875" width="64.25" height="64.25"/></g><path class="b" d="M36.066,58.469a15.431,15.431,0,0,1,0-21.866,15.011,15.011,0,0,1,3.577-2.662,2.018,2.018,0,0,1,1.878,3.571,11.53,11.53,0,0,0-2.6,1.947A11.446,11.446,0,0,0,55.132,55.622a11.938,11.938,0,0,0,1.878-2.462A2.02,2.02,0,1,1,60.5,55.2,15.711,15.711,0,0,1,58,58.469a15.533,15.533,0,0,1-21.929,0Zm-5.87-.994H5.225A5.225,5.225,0,0,1,0,52.263V13.925A5.226,5.226,0,0,1,5.225,8.712H53.769A5.226,5.226,0,0,1,59,13.925V32.117A19.526,19.526,0,0,0,30.2,57.474v0ZM21.753,18.77l-8.5,7.4a2.531,2.531,0,0,0-.239,3.565,2.536,2.536,0,0,0,3.568.239l6.835-5.958L28.446,28.4a2.52,2.52,0,0,0,3.351-.015L42.282,19a2.508,2.508,0,0,0,.191-3.557,2.529,2.529,0,0,0-3.567-.192L30.085,23.14l-5-4.369a2.544,2.544,0,0,0-3.335,0ZM47.03,49.554a2.017,2.017,0,0,1-2.022-2.017V34.091a2.021,2.021,0,0,1,2.022-2.017A15.485,15.485,0,0,1,62.537,47.537a2.018,2.018,0,0,1-2.024,2.017Zm2.025-4.034h9.258a11.471,11.471,0,0,0-9.258-9.229ZM7.53,5.051a2.521,2.521,0,1,1,0-5.043H50.681a2.521,2.521,0,1,1,0,5.043Z" transform="translate(6.296 0.013)"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="139" height="765" viewBox="0 0 139 765"><defs><style>.a{fill:url(#a);}</style><pattern id="a" width="1" height="1" patternTransform="matrix(-1, 0, 0, 1, 278, 0)" viewBox="0 0 139 765"><image preserveAspectRatio="xMidYMid slice" width="139" height="765" xlink:href="data:image/png;base64,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 truncated

Before

Width:  |  Height:  |  Size: 51 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="139" height="765" viewBox="0 0 139 765"><defs><style>.a{fill:url(#a);}</style><pattern id="a" preserveAspectRatio="xMidYMid slice" width="100%" height="100%" viewBox="0 0 278 1530"><image width="278" height="1530" xlink:href="data:image/png;base64,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 truncated

Before

Width:  |  Height:  |  Size: 51 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="54.923" height="54.898" viewBox="0 0 54.923 54.898"><defs><style>.a{fill:url(#a);}</style><linearGradient id="a" x1="0.405" x2="1" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#f3212c"/><stop offset="1" stop-color="#aa071a"/></linearGradient></defs><path class="a" d="M110.023,105.37H98.2a1.721,1.721,0,0,1-1.716-1.716v-1.918h10.189a1.721,1.721,0,0,0,1.716-1.716V72.8a1.721,1.721,0,0,0-1.716-1.716H98.2V67.437A3.444,3.444,0,0,0,94.76,64H87.83a3.444,3.444,0,0,0-3.437,3.437v3.652H75.625A1.721,1.721,0,0,0,73.91,72.8v27.21a1.721,1.721,0,0,0,1.716,1.716h10.49v1.918a1.721,1.721,0,0,1-1.716,1.716H72.3a1.721,1.721,0,0,0-1.716,1.716v10.1A1.721,1.721,0,0,0,72.3,118.9h37.724a1.721,1.721,0,0,0,1.716-1.716v-10.1A1.726,1.726,0,0,0,110.023,105.37Zm-8.406-19.1a3.437,3.437,0,1,1-3.437-3.437A3.436,3.436,0,0,1,101.616,86.266ZM87.83,67.437h6.924v3.646H87.83ZM81.121,86.266A3.437,3.437,0,1,1,84.558,89.7,3.436,3.436,0,0,1,81.121,86.266Zm32.48-7.089V93.355a1.716,1.716,0,0,1-3.431,0V79.177a1.716,1.716,0,0,1,3.431,0Zm5.122,3.548v6.881a1.716,1.716,0,0,1-3.431,0V82.724a1.716,1.716,0,0,1,3.431,0ZM70.644,95.07a1.717,1.717,0,0,1-1.716-1.716V79.177a1.716,1.716,0,0,1,3.431,0V93.355A1.713,1.713,0,0,1,70.644,95.07ZM67.231,82.724v6.881a1.716,1.716,0,1,1-3.431,0V82.724a1.716,1.716,0,0,1,3.431,0Zm0,0" transform="translate(-63.8 -64)"/></svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="68" viewBox="0 0 68 68"><defs><style>.a{fill:#fff;stroke:#707070;stroke-width:3.75px;opacity:0;}.b{fill:url(#a);}.c{stroke:none;}.d{fill:none;}</style><linearGradient id="a" x1="0.431" x2="1" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#f3212c"/><stop offset="1" stop-color="#aa071a"/></linearGradient></defs><g transform="translate(-71.077 -67.746)"><g class="a" transform="translate(71.077 67.746)"><rect class="c" width="68" height="68"/><rect class="d" x="1.875" y="1.875" width="64.25" height="64.25"/></g><path class="b" d="M114.406,106.791a7.707,7.707,0,0,0-4.354,1.353L98.7,99.937a13.3,13.3,0,0,0,1.742-6.583c0-.421-.03-.842-.06-1.263L112,85.207a4.687,4.687,0,1,0-1.952-2.345L99.691,88.995a13.678,13.678,0,0,0-6.1-7.365l2.072-10.341c.15,0,.3.03.451.03a4.66,4.66,0,1,0-4.655-4.659,4.727,4.727,0,0,0,1.412,3.367l-2.1,10.462A13.479,13.479,0,0,0,80.05,81.87l-6.4-5.712A6.129,6.129,0,1,0,71.7,78.443L77.677,83.7a13.456,13.456,0,0,0,.691,19.991l-5.316,5.622a5.948,5.948,0,0,0-3.394-1.022,6.163,6.163,0,1,0,6.156,6.162,6.343,6.343,0,0,0-.721-2.916l5.826-6.193a13.464,13.464,0,0,0,16.1-2.946l11.022,7.966a7.77,7.77,0,0,0-1.2,4.118,7.658,7.658,0,1,0,15.316,0A7.817,7.817,0,0,0,114.406,106.791Zm0,0" transform="translate(13 9.671)"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="68" viewBox="0 0 68 68"><defs><style>.a{opacity:0;fill:url(#a);}.b{fill:url(#b);}</style><linearGradient id="a" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#f3212c"/><stop offset="1" stop-color="#aa071a"/></linearGradient><linearGradient id="b" x1="0.337" x2="1" xlink:href="#a"/></defs><g transform="translate(-204.426 -230.797)"><rect class="a" width="68" height="68" transform="translate(204.426 230.797)"/><g transform="translate(209.658 232.191)"><path class="b" d="M25.52,64.045c-1.725-.852-8.6-4.486-10.846-5.656-2.309-1.207-3.3-1.01-5.09.146L6.346,60.67,0,46.383s6.887-3.254,10.033-4.508C15,39.885,17.273,41.6,20.115,43.4c1.209.762,5.131,3.664,5.131,3.664a17.886,17.886,0,0,0,7.783,2.316c5.928,0,6.975.344,6.975,2.266,0,2.113-3.859,2.266-3.883,2.266H26.605c-3.236,0-7.766-1.893-7.766-1.893s3.846,4.156,7.766,4.156h9.547c2.105-.047,6.1-1.047,6.1-4.537,0-4.529-4.066-4.529-9.219-4.529a5.2,5.2,0,0,1-1.127-.145c.2-.1.4-.207.639-.35.9-.523,2.145-1.27,3.535-2.158,3.67-2.3,5.555-2.592,7.387-.152a5.718,5.718,0,0,1,4.248-1.678c1.551,0,2.865,1.039,2.494,2.719,3.975-2.377,5.936-1.42,6.809-.266,1.156,1.527.373,3.109-2.143,4.926C53.244,51.17,37.809,61.543,35.635,62.82c-1.732,1-3.326,2.395-5.8,2.395A9.825,9.825,0,0,1,25.52,64.045ZM22.51,39.5l-.229-.865a.706.706,0,0,1,.129-.607.688.688,0,0,1,.557-.275H35.734a.689.689,0,0,1,.547.275.7.7,0,0,1,.121.607l-.219.865a7.065,7.065,0,0,1-13.674,0Zm6.84,2.486a4.265,4.265,0,0,0,3.178-1.424H26.174A4.239,4.239,0,0,0,29.35,41.982Zm-6.285-5.07a.885.885,0,1,1,0-1.77H35.658a.885.885,0,0,1-.008,1.77Zm-.189-2.637a.7.7,0,0,1-.707-.7V31.021a.565.565,0,0,0-.244-.461,13.168,13.168,0,1,1,14.844,0,.563.563,0,0,0-.242.461v2.547a.7.7,0,0,1-.7.707Zm8.672-8.785a6.207,6.207,0,0,0,2.455-.3c.547-.258.721-.676.721-1.572V14.719H33.059v8.887c0,.219-.1.281-.334.3-.234,0-1.033,0-1.732-.039A6.217,6.217,0,0,1,31.547,25.49Zm-6.18-2.166c0,1.535.463,1.967,1.969,1.967h1.7c1.285,0,1.717-.516,1.877-2.174a4.544,4.544,0,0,1-1.443-.607c-.062,1.141-.145,1.361-.586,1.361H27.557c-.494,0-.578-.055-.578-.562V20.117h1.475a3.131,3.131,0,0,1-.213,1.223.374.374,0,0,1-.334.131,6.154,6.154,0,0,1-.836-.047,3.419,3.419,0,0,1,.41,1.4,8.144,8.144,0,0,0,1.3-.045,1.284,1.284,0,0,0,.844-.455c.281-.35.395-1.223.465-3.107l.016-.2.744-.707v4.154h1.619V15.793H30.848V18.17a28.18,28.18,0,0,0-2.326-2.758c.084-.158.152-.328.221-.486l-1.535-.479a9.09,9.09,0,0,1-3.215,3.9,7.919,7.919,0,0,1,1.2,1.27l.174-.129Zm.906-4.643a11.211,11.211,0,0,0,1.465-1.855c.518.609,1.049,1.27,1.469,1.855Zm17.676-2.123a1.606,1.606,0,0,1,1.186-1.943l2.363-.578a1.608,1.608,0,0,1,.76,3.125l-2.369.576a1.629,1.629,0,0,1-.383.047A1.611,1.611,0,0,1,43.949,16.559ZM12.631,17.631,10.389,16.7a1.608,1.608,0,0,1,1.23-2.971l2.242.941a1.6,1.6,0,1,1-1.23,2.963Zm4.088-9.514L15.328,6.125a1.605,1.605,0,0,1,2.637-1.832l1.391,1.99a1.6,1.6,0,0,1-.4,2.234,1.58,1.58,0,0,1-.916.289A1.6,1.6,0,0,1,16.719,8.117Zm22.709.32a1.614,1.614,0,0,1-.273-2.252l1.488-1.914A1.6,1.6,0,1,1,43.174,6.24L41.686,8.16a1.626,1.626,0,0,1-2.258.277ZM27.746,4.043V1.6a1.607,1.607,0,0,1,3.215,0V4.043a1.607,1.607,0,0,1-3.215,0Z" transform="translate(0 0)"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 3.2 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="68" viewBox="0 0 68 68"><defs><style>.a{fill:#fff;opacity:0;}.b{fill:url(#a);}</style><linearGradient id="a" x1="0.405" x2="1" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#f3212c"/><stop offset="1" stop-color="#aa071a"/></linearGradient></defs><g transform="translate(14482.893 -23044.904)"><rect class="a" width="68" height="68" transform="translate(-14482.893 23044.904)"/><path class="b" d="M43.013,57.336h-.255l-.074,0a14.064,14.064,0,0,1-8.911-3.467,6.216,6.216,0,0,1,6.1-5.029h6.278a6.218,6.218,0,0,1,6.1,5.03A14.073,14.073,0,0,1,43.6,57.324h-.009l-.067,0H43.5l-.063,0h-.424ZM30.159,54.9H8.5a1.717,1.717,0,0,1-1.715-1.716v-10.1A1.717,1.717,0,0,1,8.5,41.363H20.6a1.717,1.717,0,0,0,1.716-1.715V37.73H11.824a1.717,1.717,0,0,1-1.716-1.715V8.8a1.718,1.718,0,0,1,1.716-1.716h8.768V3.437A3.44,3.44,0,0,1,24.029,0h6.93A3.441,3.441,0,0,1,34.4,3.437V7.089H42.87A1.718,1.718,0,0,1,44.586,8.8V26.022c-.515-.046-1.044-.07-1.574-.07A17.327,17.327,0,0,0,30.157,54.9Zm4.219-36.07a3.437,3.437,0,1,0,3.438,3.437A3.441,3.441,0,0,0,34.378,18.828Zm-13.619,0A3.437,3.437,0,1,0,24.2,22.265,3.441,3.441,0,0,0,20.758,18.828ZM24.029,3.437V7.083h6.924V3.437Zm7.256,47.59v0a14.059,14.059,0,1,1,23.456,0,9.508,9.508,0,0,0-8.589-5.455H44.686a7.193,7.193,0,1,0-3.347,0H39.873a9.5,9.5,0,0,0-8.587,5.457ZM43.013,42.5a3.923,3.923,0,1,1,3.923-3.924A3.928,3.928,0,0,1,43.013,42.5ZM6.844,31.07a1.717,1.717,0,0,1-1.716-1.715V15.176a1.715,1.715,0,1,1,3.431,0V29.355A1.717,1.717,0,0,1,6.844,31.07ZM49.8,27.327h0a17.187,17.187,0,0,0-3.429-1.051v-11.1a1.715,1.715,0,1,1,3.431,0v12.15Zm3.406-.007a1.717,1.717,0,0,1-1.715-1.715V18.724a1.715,1.715,0,0,1,3.431,0v6.881A1.717,1.717,0,0,1,53.206,27.32Zm-51.491,0A1.717,1.717,0,0,1,0,25.605V18.724a1.715,1.715,0,0,1,3.431,0v6.881A1.717,1.717,0,0,1,1.715,27.32Z" transform="translate(-14477.664 23050.15)"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="68" viewBox="0 0 68 68"><defs><style>.a{stroke:#707070;stroke-width:3.75px;opacity:0;fill:url(#a);}.b{fill:url(#b);}.c{stroke:none;}.d{fill:none;}</style><linearGradient id="a" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#f3212c"/><stop offset="1" stop-color="#aa071a"/></linearGradient><linearGradient id="b" x1="0.414" x2="1" xlink:href="#a"/></defs><g transform="translate(-2.29 3.525)"><g class="a" transform="translate(2.29 -3.525)"><rect class="c" width="68" height="68"/><rect class="d" x="1.875" y="1.875" width="64.25" height="64.25"/></g><path class="b" d="M36.066,58.469a15.431,15.431,0,0,1,0-21.866,15.011,15.011,0,0,1,3.577-2.662,2.018,2.018,0,0,1,1.878,3.571,11.53,11.53,0,0,0-2.6,1.947A11.446,11.446,0,0,0,55.132,55.622a11.938,11.938,0,0,0,1.878-2.462A2.02,2.02,0,1,1,60.5,55.2,15.711,15.711,0,0,1,58,58.469a15.533,15.533,0,0,1-21.929,0Zm-5.87-.994H5.225A5.225,5.225,0,0,1,0,52.263V13.925A5.226,5.226,0,0,1,5.225,8.712H53.769A5.226,5.226,0,0,1,59,13.925V32.117A19.526,19.526,0,0,0,30.2,57.474v0ZM21.753,18.77l-8.5,7.4a2.531,2.531,0,0,0-.239,3.565,2.536,2.536,0,0,0,3.568.239l6.835-5.958L28.446,28.4a2.52,2.52,0,0,0,3.351-.015L42.282,19a2.508,2.508,0,0,0,.191-3.557,2.529,2.529,0,0,0-3.567-.192L30.085,23.14l-5-4.369a2.544,2.544,0,0,0-3.335,0ZM47.03,49.554a2.017,2.017,0,0,1-2.022-2.017V34.091a2.021,2.021,0,0,1,2.022-2.017A15.485,15.485,0,0,1,62.537,47.537a2.018,2.018,0,0,1-2.024,2.017Zm2.025-4.034h9.258a11.471,11.471,0,0,0-9.258-9.229ZM7.53,5.051a2.521,2.521,0,1,1,0-5.043H50.681a2.521,2.521,0,1,1,0,5.043Z" transform="translate(6.296 0.013)"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="273" height="323" viewBox="0 0 273 323"><image width="273" height="323" xlink:href="data:image/png;base64,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 truncated

Before

Width:  |  Height:  |  Size: 193 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="727" height="727" viewBox="0 0 727 727"><defs><style>.a{fill:url(#a);}.b{fill:url(#d);}.c,.d,.f{fill:none;}.c{stroke:rgba(32,194,255,0);stroke-width:8px;}.d{stroke:rgba(255,173,32,0.15);stroke-width:5px;stroke-dasharray:7 5;}.e{stroke:none;}.g{filter:url(#e);}.h{filter:url(#b);}</style><linearGradient id="a" x1="0.761" y1="0.205" x2="0.284" y2="0.581" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#ffd2ab"/><stop offset="1" stop-color="#ff7855"/></linearGradient><filter id="b" x="88.068" y="60.324" width="217.004" height="181.59" filterUnits="userSpaceOnUse"><feOffset input="SourceAlpha"/><feGaussianBlur stdDeviation="7.5" result="c"/><feFlood flood-color="#ff941a" flood-opacity="0.4"/><feComposite operator="in" in2="c"/><feComposite in="SourceGraphic"/></filter><linearGradient id="d" x1="0.237" y1="0.761" x2="0.718" y2="0.394" xlink:href="#a"/><filter id="e" x="424.041" y="484.359" width="215.309" height="181.689" filterUnits="userSpaceOnUse"><feOffset input="SourceAlpha"/><feGaussianBlur stdDeviation="7.5" result="f"/><feFlood flood-color="#ff941a" flood-opacity="0.4"/><feComposite operator="in" in2="f"/><feComposite in="SourceGraphic"/></filter></defs><g transform="translate(4 4)"><g transform="translate(-126.998 -127.002)"><g class="h" transform="matrix(1, 0, 0, 1, 123, 123)"><path class="a" d="M18115.566-21172.494q4.919-8.443,10.389-16.543a294.531,294.531,0,0,1,35.713-43.289,294.545,294.545,0,0,1,43.293-35.717,292.5,292.5,0,0,1,49.682-26.969,290.614,290.614,0,0,1,31.271-11.162l1.656,5.506a288.092,288.092,0,0,0-166.973,131.084Z" transform="translate(-18005 21389)"/></g><g class="g" transform="matrix(1, 0, 0, 1, 123, 123)"><path class="b" d="M18451.539-20750.967a288.209,288.209,0,0,0,165.279-131.172l5.029,2.92q-5.1,8.815-10.8,17.258a294.659,294.659,0,0,1-35.717,43.287,294.647,294.647,0,0,1-43.293,35.717,292.2,292.2,0,0,1-49.686,26.971,291.1,291.1,0,0,1-29.178,10.537Z" transform="translate(-18005 21389)"/></g><circle class="c" cx="359.5" cy="359.5" r="359.5" transform="translate(126.998 127.002)"/></g><g class="d" transform="translate(98 98)"><circle class="e" cx="261.5" cy="261.5" r="261.5"/><circle class="f" cx="261.5" cy="261.5" r="259"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="727" height="727" viewBox="0 0 727 727"><defs><style>.a{fill:url(#a);}.b{fill:url(#d);}.c,.d,.f{fill:none;}.c{stroke:rgba(32,194,255,0);stroke-width:8px;}.d{stroke:rgba(255,173,32,0.15);stroke-width:5px;stroke-dasharray:7 5;}.e{stroke:none;}.g{filter:url(#e);}.h{filter:url(#b);}</style><linearGradient id="a" x1="0.761" y1="0.205" x2="0.284" y2="0.581" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#ffd2ab"/><stop offset="1" stop-color="#ff7855"/></linearGradient><filter id="b" x="88.068" y="60.324" width="217.004" height="181.59" filterUnits="userSpaceOnUse"><feOffset input="SourceAlpha"/><feGaussianBlur stdDeviation="7.5" result="c"/><feFlood flood-color="#ff941a" flood-opacity="0.4"/><feComposite operator="in" in2="c"/><feComposite in="SourceGraphic"/></filter><linearGradient id="d" x1="0.237" y1="0.761" x2="0.718" y2="0.394" xlink:href="#a"/><filter id="e" x="424.041" y="484.359" width="215.309" height="181.689" filterUnits="userSpaceOnUse"><feOffset input="SourceAlpha"/><feGaussianBlur stdDeviation="7.5" result="f"/><feFlood flood-color="#ff941a" flood-opacity="0.4"/><feComposite operator="in" in2="f"/><feComposite in="SourceGraphic"/></filter></defs><g transform="translate(4 4)"><g transform="translate(-126.998 -127.002)"><g class="h" transform="matrix(1, 0, 0, 1, 123, 123)"><path class="a" d="M18115.566-21172.494q4.919-8.443,10.389-16.543a294.531,294.531,0,0,1,35.713-43.289,294.545,294.545,0,0,1,43.293-35.717,292.5,292.5,0,0,1,49.682-26.969,290.614,290.614,0,0,1,31.271-11.162l1.656,5.506a288.092,288.092,0,0,0-166.973,131.084Z" transform="translate(-18005 21389)"/></g><g class="g" transform="matrix(1, 0, 0, 1, 123, 123)"><path class="b" d="M18451.539-20750.967a288.209,288.209,0,0,0,165.279-131.172l5.029,2.92q-5.1,8.815-10.8,17.258a294.659,294.659,0,0,1-35.717,43.287,294.647,294.647,0,0,1-43.293,35.717,292.2,292.2,0,0,1-49.686,26.971,291.1,291.1,0,0,1-29.178,10.537Z" transform="translate(-18005 21389)"/></g><circle class="c" cx="359.5" cy="359.5" r="359.5" transform="translate(126.998 127.002)"/></g><g class="d" transform="translate(98 98)"><circle class="e" cx="261.5" cy="261.5" r="261.5"/><circle class="f" cx="261.5" cy="261.5" r="259"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="458" height="113.588" viewBox="0 0 458 113.588"><defs><style>.a{opacity:0.78;}.b{fill:url(#a);}.c{fill:#fff;}.d{filter:url(#d);}.e{filter:url(#b);}</style><linearGradient id="a" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff9c1"/></linearGradient><filter id="b" x="104.221" y="19.443" width="226.559" height="61.289" filterUnits="userSpaceOnUse"><feOffset dy="1" input="SourceAlpha"/><feGaussianBlur stdDeviation="5.5" result="c"/><feFlood flood-color="#fe0" flood-opacity="0.71"/><feComposite operator="in" in2="c"/><feComposite in="SourceGraphic"/></filter><filter id="d" x="104.221" y="19.443" width="226.559" height="61.289" filterUnits="userSpaceOnUse"><feOffset input="SourceAlpha"/><feGaussianBlur stdDeviation="2" result="e"/><feFlood flood-color="#fff" result="f"/><feComposite operator="out" in="SourceGraphic" in2="e"/><feComposite operator="in" in="f"/><feComposite operator="in" in2="SourceGraphic"/></filter></defs><g transform="translate(-731 -564.412)"><image class="a" width="458" height="113.588" transform="translate(731 564.412)" xlink:href="data:image/png;base64,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 truncated

Before

Width:  |  Height:  |  Size: 625 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="68" viewBox="0 0 68 68"><defs><style>.a{opacity:0;fill:url(#a);}.b{fill:url(#b);}</style><linearGradient id="a" x1="0.5" x2="0.5" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#f3212c"/><stop offset="1" stop-color="#aa071a"/></linearGradient><linearGradient id="b" x1="0.405" x2="1" xlink:href="#a"/></defs><g transform="translate(14482.893 -23044.904)"><rect class="a" width="68" height="68" transform="translate(-14482.893 23044.904)"/><path class="b" d="M110.023,105.37H98.2a1.721,1.721,0,0,1-1.716-1.716v-1.918h10.189a1.721,1.721,0,0,0,1.716-1.716V72.8a1.721,1.721,0,0,0-1.716-1.716H98.2V67.437A3.444,3.444,0,0,0,94.76,64H87.83a3.444,3.444,0,0,0-3.437,3.437v3.652H75.625A1.721,1.721,0,0,0,73.91,72.8v27.21a1.721,1.721,0,0,0,1.716,1.716h10.49v1.918a1.721,1.721,0,0,1-1.716,1.716H72.3a1.721,1.721,0,0,0-1.716,1.716v10.1A1.721,1.721,0,0,0,72.3,118.9h37.724a1.721,1.721,0,0,0,1.716-1.716v-10.1A1.726,1.726,0,0,0,110.023,105.37Zm-8.406-19.1a3.437,3.437,0,1,1-3.437-3.437A3.436,3.436,0,0,1,101.616,86.266ZM87.83,67.437h6.924v3.646H87.83ZM81.121,86.266A3.437,3.437,0,1,1,84.558,89.7,3.436,3.436,0,0,1,81.121,86.266Zm32.48-7.089V93.355a1.716,1.716,0,0,1-3.431,0V79.177a1.716,1.716,0,0,1,3.431,0Zm5.122,3.548v6.881a1.716,1.716,0,0,1-3.431,0V82.724a1.716,1.716,0,0,1,3.431,0ZM70.644,95.07a1.717,1.717,0,0,1-1.716-1.716V79.177a1.716,1.716,0,0,1,3.431,0V93.355A1.713,1.713,0,0,1,70.644,95.07ZM67.231,82.724v6.881a1.716,1.716,0,1,1-3.431,0V82.724a1.716,1.716,0,0,1,3.431,0Zm0,0" transform="translate(-14540.154 22987.455)"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="188" height="241" viewBox="0 0 188 241"><defs><style>.a{fill:url(#a);}.b{fill:#fff;opacity:0.47;}</style><pattern id="a" preserveAspectRatio="xMidYMid slice" width="100%" height="100%" viewBox="0 0 376 482"><image width="376" height="482" xlink:href="data:image/png;base64,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 truncated

Before

Width:  |  Height:  |  Size: 68 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="68" viewBox="0 0 68 68"><defs><style>.a{fill:#fff;stroke:#707070;stroke-width:3.75px;opacity:0;}.b{fill:url(#a);}.c{stroke:none;}.d{fill:none;}</style><linearGradient id="a" x1="0.431" x2="1" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#f3212c"/><stop offset="1" stop-color="#aa071a"/></linearGradient></defs><g transform="translate(-71.077 -67.746)"><g class="a" transform="translate(71.077 67.746)"><rect class="c" width="68" height="68"/><rect class="d" x="1.875" y="1.875" width="64.25" height="64.25"/></g><path class="b" d="M114.406,106.791a7.707,7.707,0,0,0-4.354,1.353L98.7,99.937a13.3,13.3,0,0,0,1.742-6.583c0-.421-.03-.842-.06-1.263L112,85.207a4.687,4.687,0,1,0-1.952-2.345L99.691,88.995a13.678,13.678,0,0,0-6.1-7.365l2.072-10.341c.15,0,.3.03.451.03a4.66,4.66,0,1,0-4.655-4.659,4.727,4.727,0,0,0,1.412,3.367l-2.1,10.462A13.479,13.479,0,0,0,80.05,81.87l-6.4-5.712A6.129,6.129,0,1,0,71.7,78.443L77.677,83.7a13.456,13.456,0,0,0,.691,19.991l-5.316,5.622a5.948,5.948,0,0,0-3.394-1.022,6.163,6.163,0,1,0,6.156,6.162,6.343,6.343,0,0,0-.721-2.916l5.826-6.193a13.464,13.464,0,0,0,16.1-2.946l11.022,7.966a7.77,7.77,0,0,0-1.2,4.118,7.658,7.658,0,1,0,15.316,0A7.817,7.817,0,0,0,114.406,106.791Zm0,0" transform="translate(13 9.671)"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.3 KiB

@@ -1,13 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="68" viewBox="0 0 68 68">
<defs>
<linearGradient id="ap-idea" x1="0.405" x2="1" y2="1" gradientUnits="objectBoundingBox">
<stop offset="0" stop-color="#f3212c"/>
<stop offset="1" stop-color="#aa071a"/>
</linearGradient>
</defs>
<g fill="url(#ap-idea)" transform="translate(12 10)">
<path d="M22 2.2A12.8 12.8 0 0 0 9.2 15c0 5.1 2.9 9.5 7.1 11.6v3.8a2.4 2.4 0 0 0 2.4 2.4h6.6a2.4 2.4 0 0 0 2.4-2.4v-3.8A12.8 12.8 0 0 0 34.8 15 12.8 12.8 0 0 0 22 2.2Zm3.3 26.8h-6.6v-2.1h6.6Zm-3.3-26.8A10.4 10.4 0 0 1 32.4 15a10.4 10.4 0 0 1-6.3 9.5 2.4 2.4 0 0 0-1.3 2.1v.3h-5.6v-.3a2.4 2.4 0 0 0-1.3-2.1A10.4 10.4 0 0 1 11.6 15 10.4 10.4 0 0 1 22 2.2Z"/>
<path d="M17.6 39.2a2 2 0 0 0 2 2h4.8a2 2 0 0 0 2-2v-1.4h-8.8Zm-1.8-3.8h12.4a1.6 1.6 0 1 0 0-3.2H15.8a1.6 1.6 0 1 0 0 3.2Z"/>
<path d="M8.4 22.6a1.6 1.6 0 0 0 0-3.2H3.8a1.6 1.6 0 1 0 0 3.2Zm31.8 0a1.6 1.6 0 0 0 0-3.2h-4.6a1.6 1.6 0 1 0 0 3.2ZM7.2 10.8a1.6 1.6 0 0 0 2.3-2.3L6.2 5.3A1.6 1.6 0 0 0 4 7.6Zm29.3-2.3a1.6 1.6 0 0 0 2.3 2.3l3.2-3.2A1.6 1.6 0 1 0 39.7 5.3Z"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="68" viewBox="0 0 68 68"><defs><style>.a{fill:#fff;opacity:0;}.b{fill:url(#a);}</style><linearGradient id="a" x1="0.405" x2="1" y2="1" gradientUnits="objectBoundingBox"><stop offset="0" stop-color="#f3212c"/><stop offset="1" stop-color="#aa071a"/></linearGradient></defs><g transform="translate(14482.893 -23044.904)"><rect class="a" width="68" height="68" transform="translate(-14482.893 23044.904)"/><path class="b" d="M43.013,57.336h-.255l-.074,0a14.064,14.064,0,0,1-8.911-3.467,6.216,6.216,0,0,1,6.1-5.029h6.278a6.218,6.218,0,0,1,6.1,5.03A14.073,14.073,0,0,1,43.6,57.324h-.009l-.067,0H43.5l-.063,0h-.424ZM30.159,54.9H8.5a1.717,1.717,0,0,1-1.715-1.716v-10.1A1.717,1.717,0,0,1,8.5,41.363H20.6a1.717,1.717,0,0,0,1.716-1.715V37.73H11.824a1.717,1.717,0,0,1-1.716-1.715V8.8a1.718,1.718,0,0,1,1.716-1.716h8.768V3.437A3.44,3.44,0,0,1,24.029,0h6.93A3.441,3.441,0,0,1,34.4,3.437V7.089H42.87A1.718,1.718,0,0,1,44.586,8.8V26.022c-.515-.046-1.044-.07-1.574-.07A17.327,17.327,0,0,0,30.157,54.9Zm4.219-36.07a3.437,3.437,0,1,0,3.438,3.437A3.441,3.441,0,0,0,34.378,18.828Zm-13.619,0A3.437,3.437,0,1,0,24.2,22.265,3.441,3.441,0,0,0,20.758,18.828ZM24.029,3.437V7.083h6.924V3.437Zm7.256,47.59v0a14.059,14.059,0,1,1,23.456,0,9.508,9.508,0,0,0-8.589-5.455H44.686a7.193,7.193,0,1,0-3.347,0H39.873a9.5,9.5,0,0,0-8.587,5.457ZM43.013,42.5a3.923,3.923,0,1,1,3.923-3.924A3.928,3.928,0,0,1,43.013,42.5ZM6.844,31.07a1.717,1.717,0,0,1-1.716-1.715V15.176a1.715,1.715,0,1,1,3.431,0V29.355A1.717,1.717,0,0,1,6.844,31.07ZM49.8,27.327h0a17.187,17.187,0,0,0-3.429-1.051v-11.1a1.715,1.715,0,1,1,3.431,0v12.15Zm3.406-.007a1.717,1.717,0,0,1-1.715-1.715V18.724a1.715,1.715,0,0,1,3.431,0v6.881A1.717,1.717,0,0,1,53.206,27.32Zm-51.491,0A1.717,1.717,0,0,1,0,25.605V18.724a1.715,1.715,0,0,1,3.431,0v6.881A1.717,1.717,0,0,1,1.715,27.32Z" transform="translate(-14477.664 23050.15)"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

@@ -1,14 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="68" height="68" viewBox="0 0 68 68">
<defs>
<linearGradient id="ap-task" x1="0.405" x2="1" y2="1" gradientUnits="objectBoundingBox">
<stop offset="0" stop-color="#f3212c"/>
<stop offset="1" stop-color="#aa071a"/>
</linearGradient>
</defs>
<g fill="url(#ap-task)" transform="translate(14 12)">
<path d="M28.4 2.2H15.6A3.4 3.4 0 0 0 12.2 5.6v2.8H8.6A3.4 3.4 0 0 0 5.2 11.8v28.8A3.4 3.4 0 0 0 8.6 44h22.8a3.4 3.4 0 0 0 3.4-3.4V11.8a3.4 3.4 0 0 0-3.4-3.4h-3.6V5.6A3.4 3.4 0 0 0 28.4 2.2Zm-12.8 3.4h12.8v2.8H15.6Zm19.2 35.8H8.6V11.8h3.6v2.2a1.6 1.6 0 0 0 1.6 1.6h12.8a1.6 1.6 0 0 0 1.6-1.6v-2.2h3.6Z"/>
<rect x="11.4" y="24.2" width="3.6" height="11.6" rx="1.2"/>
<rect x="18.2" y="20.4" width="3.6" height="15.4" rx="1.2"/>
<rect x="25" y="27.2" width="3.6" height="8.6" rx="1.2"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 924 B

@@ -18,9 +18,7 @@ import {
} from "lucide-react";
import type { ComponentProps, HTMLAttributes, ReactElement } from "react";
import { createContext, memo, useContext, useEffect, useState } from "react";
import type { StreamdownProps } from "streamdown";
import { SafeStreamdown } from "@/core/streamdown";
import { Streamdown } from "streamdown";
export type MessageProps = HTMLAttributes<HTMLDivElement> & {
from: UIMessage["role"];
@@ -304,11 +302,11 @@ export const MessageBranchPage = ({
);
};
export type MessageResponseProps = StreamdownProps;
export type MessageResponseProps = ComponentProps<typeof Streamdown>;
export const MessageResponse = memo(
({ className, ...props }: MessageResponseProps) => (
<SafeStreamdown
<Streamdown
className={cn(
"size-full [&>*:first-child]:mt-0 [&>*:last-child]:mb-0",
className,
@@ -34,13 +34,8 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import type { PromptInputFilePart, UploadPolicy } from "@/core/uploads";
import {
DEFAULT_UPLOAD_POLICY,
splitUnsupportedUploadFiles,
useUploadPolicy,
validateChatUploadFiles,
} from "@/core/uploads";
import type { PromptInputFilePart } from "@/core/uploads";
import { splitUnsupportedUploadFiles } from "@/core/uploads";
import { isIMEComposing } from "@/lib/ime";
import { cn } from "@/lib/utils";
import type { ChatStatus } from "ai";
@@ -148,94 +143,73 @@ const useOptionalProviderAttachments = () =>
useContext(ProviderAttachmentsContext);
const usePromptInputValidation = () => useContext(PromptInputValidationContext);
export type PromptInputProviderProps = PropsWithChildren<{
initialInput?: string;
uploadPolicy?: UploadPolicy;
}>;
export type PromptInputProviderProps = PropsWithChildren<{
initialInput?: string;
}>;
/**
* Optional global provider that lifts PromptInput state outside of PromptInput.
* If you don't use it, PromptInput stays fully self-managed.
*/
export function PromptInputProvider({
initialInput: initialTextInput = "",
uploadPolicy,
children,
}: PromptInputProviderProps) {
const { data: fetchedUploadPolicy } = useUploadPolicy();
const effectiveUploadPolicy =
uploadPolicy ?? fetchedUploadPolicy ?? DEFAULT_UPLOAD_POLICY;
// ----- textInput state
export function PromptInputProvider({
initialInput: initialTextInput = "",
children,
}: PromptInputProviderProps) {
// ----- textInput state
const [textInput, setTextInput] = useState(initialTextInput);
const clearInput = useCallback(() => setTextInput(""), []);
// ----- attachments state (global when wrapped)
const [attachmentFiles, setAttachmentFiles] = useState<
(PromptInputFilePart & { id: string })[]
>([]);
const attachmentsRef = useRef(attachmentFiles);
const fileInputRef = useRef<HTMLInputElement | null>(null);
const openRef = useRef<() => void>(() => {});
const add = useCallback((files: File[] | FileList) => {
const incoming = Array.from(files);
>([]);
const fileInputRef = useRef<HTMLInputElement | null>(null);
const openRef = useRef<() => void>(() => {});
const add = useCallback((files: File[] | FileList) => {
const incoming = Array.from(files);
if (incoming.length === 0) {
return;
}
const current = attachmentsRef.current;
const existing = current.map((item) => ({
name: item.filename ?? "attachment",
size: item.file?.size ?? 0,
type: item.mediaType ?? "",
}));
const validation = validateChatUploadFiles(
incoming,
existing,
effectiveUploadPolicy,
);
for (const message of new Set(
validation.issues.map((issue) => issue.message),
)) {
toast.error(message);
}
if (validation.accepted.length === 0) return;
const next = current.concat(
validation.accepted.map((file) => ({
id: nanoid(),
type: "file" as const,
url: URL.createObjectURL(file),
mediaType: file.type,
filename: file.name,
file,
})),
);
attachmentsRef.current = next;
setAttachmentFiles(next);
}, [effectiveUploadPolicy]);
const remove = useCallback((id: string) => {
const current = attachmentsRef.current;
const found = current.find((f) => f.id === id);
if (found?.url) URL.revokeObjectURL(found.url);
const next = current.filter((f) => f.id !== id);
attachmentsRef.current = next;
setAttachmentFiles(next);
}, []);
const clear = useCallback(() => {
for (const f of attachmentsRef.current) {
if (f.url) {
URL.revokeObjectURL(f.url);
}
}
attachmentsRef.current = [];
setAttachmentFiles([]);
}, []);
// Keep a ref to attachments for cleanup on unmount (avoids stale closure)
attachmentsRef.current = attachmentFiles;
return;
}
setAttachmentFiles((prev) =>
prev.concat(
incoming.map((file) => ({
id: nanoid(),
type: "file" as const,
url: URL.createObjectURL(file),
mediaType: file.type,
filename: file.name,
file,
})),
),
);
}, []);
const remove = useCallback((id: string) => {
setAttachmentFiles((prev) => {
const found = prev.find((f) => f.id === id);
if (found?.url) {
URL.revokeObjectURL(found.url);
}
return prev.filter((f) => f.id !== id);
});
}, []);
const clear = useCallback(() => {
setAttachmentFiles((prev) => {
for (const f of prev) {
if (f.url) {
URL.revokeObjectURL(f.url);
}
}
return [];
});
}, []);
// Keep a ref to attachments for cleanup on unmount (avoids stale closure)
const attachmentsRef = useRef(attachmentFiles);
attachmentsRef.current = attachmentFiles;
// Cleanup blob URLs on unmount to prevent memory leaks
useEffect(() => {
@@ -483,17 +457,10 @@ export type PromptInputProps = Omit<
// Render a hidden input with given name and keep it in sync for native form posts. Default false.
syncHiddenInput?: boolean;
// Minimal constraints
maxFiles?: number;
maxFileSize?: number; // bytes
uploadPolicy?: UploadPolicy;
onError?: (err: {
code:
| "max_files"
| "max_file_size"
| "max_total_size"
| "unsupported_type"
| "accept"
| "unsupported_package";
maxFiles?: number;
maxFileSize?: number; // bytes
onError?: (err: {
code: "max_files" | "max_file_size" | "accept" | "unsupported_package";
message: string;
}) => void;
onSubmit: (
@@ -509,25 +476,14 @@ export const PromptInput = ({
multiple,
globalDrop,
syncHiddenInput,
maxFiles,
maxFileSize,
uploadPolicy,
maxFiles,
maxFileSize,
onError,
onSubmit,
children,
...props
}: PromptInputProps) => {
const { data: fetchedUploadPolicy } = useUploadPolicy();
const effectiveUploadPolicy =
uploadPolicy ?? fetchedUploadPolicy ?? DEFAULT_UPLOAD_POLICY;
const policyAccept = useMemo(
() =>
Object.values(effectiveUploadPolicy.groups)
.flatMap((group) => group.extensions)
.join(","),
[effectiveUploadPolicy],
);
// Try to use a provider controller if present
}: PromptInputProps) => {
// Try to use a provider controller if present
const controller = useOptionalPromptInputController();
const usingProvider = !!controller;
@@ -560,11 +516,8 @@ export const PromptInput = ({
.map((s) => s.trim())
.filter(Boolean);
return patterns.some((pattern) => {
if (pattern.startsWith(".")) {
return f.name.toLowerCase().endsWith(pattern.toLowerCase());
}
if (pattern.endsWith("/*")) {
return patterns.some((pattern) => {
if (pattern.endsWith("/*")) {
const prefix = pattern.slice(0, -1); // e.g: image/* -> image/
return f.type.startsWith(prefix);
}
@@ -574,72 +527,57 @@ export const PromptInput = ({
[accept],
);
const addLocal = useCallback(
(fileList: File[] | FileList) => {
const incoming = Array.from(fileList);
const accepted = incoming.filter((f) => matchesAccept(f));
if (accepted.length < incoming.length) {
const error = {
code: "accept",
message: "部分文件不符合当前输入框允许的格式。",
} as const;
onError?.(error);
if (!onError) toast.error(error.message);
}
const localPolicy: UploadPolicy = {
...effectiveUploadPolicy,
max_files_per_message:
typeof maxFiles === "number"
? Math.min(effectiveUploadPolicy.max_files_per_message, maxFiles)
: effectiveUploadPolicy.max_files_per_message,
groups: Object.fromEntries(
Object.entries(effectiveUploadPolicy.groups).map(([key, group]) => [
key,
{
...group,
max_bytes:
typeof maxFileSize === "number"
? Math.min(group.max_bytes, maxFileSize)
: group.max_bytes,
},
]),
) as UploadPolicy["groups"],
};
const existing = items.map((item) => ({
name: item.filename ?? "attachment",
size: item.file?.size ?? 0,
type: item.mediaType ?? "",
}));
const validation = validateChatUploadFiles(
accepted,
existing,
localPolicy,
);
for (const issue of Array.from(
new Map(
validation.issues.map((item) => [item.message, item]),
).values(),
)) {
onError?.({ code: issue.code, message: issue.message });
if (!onError) toast.error(issue.message);
}
if (validation.accepted.length === 0) return;
setItems((prev) =>
prev.concat(
validation.accepted.map((file) => ({
id: nanoid(),
type: "file" as const,
url: URL.createObjectURL(file),
mediaType: file.type,
filename: file.name,
file,
})),
),
);
},
[effectiveUploadPolicy, items, matchesAccept, maxFiles, maxFileSize, onError],
);
const addLocal = useCallback(
(fileList: File[] | FileList) => {
const incoming = Array.from(fileList);
const accepted = incoming.filter((f) => matchesAccept(f));
if (incoming.length && accepted.length === 0) {
onError?.({
code: "accept",
message: "No files match the accepted types.",
});
return;
}
const withinSize = (f: File) =>
maxFileSize ? f.size <= maxFileSize : true;
const sized = accepted.filter(withinSize);
if (accepted.length > 0 && sized.length === 0) {
onError?.({
code: "max_file_size",
message: "All files exceed the maximum size.",
});
return;
}
setItems((prev) => {
const capacity =
typeof maxFiles === "number"
? Math.max(0, maxFiles - prev.length)
: undefined;
const capped =
typeof capacity === "number" ? sized.slice(0, capacity) : sized;
if (typeof capacity === "number" && sized.length > capacity) {
onError?.({
code: "max_files",
message: "Too many files. Some were not added.",
});
}
const next: (PromptInputFilePart & { id: string })[] = [];
for (const file of capped) {
next.push({
id: nanoid(),
type: "file",
url: URL.createObjectURL(file),
mediaType: file.type,
filename: file.name,
file,
});
}
return prev.concat(next);
});
},
[matchesAccept, maxFiles, maxFileSize, onError],
);
const removeLocal = useCallback(
(id: string) =>
@@ -894,7 +832,7 @@ export const PromptInput = ({
const inner = (
<PromptInputValidationContext.Provider value={sanitizeIncomingFiles}>
<input
accept={accept ?? policyAccept}
accept={accept}
aria-label="Upload files"
className="hidden"
multiple={multiple}
@@ -912,9 +850,7 @@ export const PromptInput = ({
{/* Do not rely on InputGroup's :has(textarea) selector here: Chrome
versions before 105 ignore :has(), retain h-9, and clip the whole
multi-line composer to a single row. */}
<InputGroup className="prompt-input-group h-auto min-h-16 flex-col items-stretch">
{children}
</InputGroup>
<InputGroup className="h-auto min-h-16">{children}</InputGroup>
</form>
</PromptInputValidationContext.Provider>
);
@@ -934,11 +870,7 @@ export const PromptInputBody = ({
className,
...props
}: PromptInputBodyProps) => (
<div
data-slot="prompt-input-body"
className={cn("contents", className)}
{...props}
/>
<div className={cn("contents", className)} {...props} />
);
export type PromptInputTextareaProps = ComponentProps<
@@ -1214,9 +1146,9 @@ export const PromptInputSubmit = ({
<InputGroupButton
aria-label="Submit"
className={cn(
"transition-all duration-300",
status === "streaming" &&
"streaming-stop-button bg-primary/10 text-primary border-primary/25 hover:bg-primary/14",
"transition-all duration-300",
status === "streaming" &&
"animate-breathe-stop bg-primary/10 text-primary border-primary/25 shadow-[0_0_0_0_rgba(217,33,33,0.25)] hover:bg-primary/14",
className,
)}
size={size}
Loaded 100 of 1572 files, more files were not shown because too many files have changed in this diff. Show more