From 5ecf28e60cd80d16e531cad3535de0cd73c825fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=89=E9=91=AB=E5=8D=87?= Date: Wed, 24 Jun 2026 15:43:39 +0800 Subject: [PATCH] =?UTF-8?q?feat(y-log/knowledge):=20=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E5=89=8D=E7=BC=80=E6=94=B9=20CM=E5=8A=A9=E6=89=8B-=E5=85=A8?= =?UTF-8?q?=E9=87=8F=20+=20=E5=85=A5=E5=BA=93=20nodeName=20=E6=8C=89?= =?UTF-8?q?=E6=A0=87=E9=A2=98=E5=8E=BB=E6=97=B6=E9=97=B4=E6=88=B3=E4=BF=9D?= =?UTF-8?q?=E6=8C=81=E4=B8=80=E8=87=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Y-Log 上报 optDetail 前缀 B1-CM助手 → CM助手-全量(全量替换 44 个前端文件 + 文档) 2. 知识库入库 nodeName 改为只取 md5(标题).md(去掉时间戳),同一篇 md 每次入库一致,避免重复记录 Co-Authored-By: Claude Opus 4.8 (1M context) --- CLAUDE.md | 2 +- .../settings/account-settings-page.tsx | 2 +- frontend-web/src/core/admin/api.ts | 32 ++++----- frontend-web/src/core/agents/api.ts | 38 +++++----- .../src/core/api/markdown-docx-export.ts | 6 +- frontend-web/src/core/artifacts/api.ts | 2 +- frontend-web/src/core/curator/api.ts | 6 +- frontend-web/src/core/custom-prompts/index.ts | 8 +-- frontend-web/src/core/knowledge/api.ts | 54 +++++++------- frontend-web/src/core/llm-metrics/api.ts | 4 +- frontend-web/src/core/log/y-log.ts | 2 +- frontend-web/src/core/mcp/api.ts | 72 +++++++++---------- frontend-web/src/core/memory/api.ts | 14 ++-- frontend-web/src/core/models/api.ts | 42 +++++------ frontend-web/src/core/note/api.ts | 4 +- frontend-web/src/core/notifications/api.ts | 8 +-- frontend-web/src/core/positions/api.ts | 24 +++---- .../src/core/recommended-questions/api.ts | 10 +-- .../src/core/roundtable-draft-shares/api.ts | 10 +-- frontend-web/src/core/scheduled-tasks/api.ts | 66 ++++++++--------- .../src/core/scheduled-tasks/markdown-docx.ts | 2 +- frontend-web/src/core/studio/api.ts | 16 ++--- frontend-web/src/core/system-settings/api.ts | 34 ++++----- frontend-web/src/core/tags/api.ts | 12 ++-- frontend-web/src/core/thread-shares/api.ts | 10 +-- frontend-web/src/core/threads/hooks.ts | 2 +- frontend-web/src/core/tool-metrics/api.ts | 6 +- .../src/core/user-preferences/index.ts | 2 +- frontend-web/src/core/user-qa/api.ts | 2 +- frontend-web/src/pages/AgentChatPage.tsx | 2 +- frontend-web/src/pages/ChatPage.tsx | 2 +- frontend-web/src/pages/LoginPage.tsx | 2 +- .../src/roundtable-planning/api/chains.ts | 14 ++-- .../api/dashboard-sessions.ts | 4 +- .../src/roundtable-planning/api/drafts.ts | 10 +-- .../roundtable-planning/api/multi-agent.ts | 2 +- .../src/roundtable-planning/api/recommend.ts | 4 +- .../api/roundtable-jobs.ts | 6 +- .../roundtable-planning/api/task-drafts.ts | 12 ++-- .../api/business-mapping.ts | 4 +- .../src/strategy-components/api/light-apps.ts | 10 +-- .../strategy-components/api/menu-overrides.ts | 2 +- .../api/sensitive-words.ts | 4 +- .../api/skill-addresses.ts | 12 ++-- .../strategy-components/api/task-buttons.ts | 2 +- .../app/gateway/routers/knowledge_ingest.py | 24 ++++--- 46 files changed, 307 insertions(+), 301 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index b011329e..db045e54 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -91,7 +91,7 @@ The frontend (`frontend-web/`) is a React 19 + Vite SPA: - **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//{roundtable,agent/:agent_id/chats}` in `StrategyRoutes.tsx` (`` = `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 stay isolated even though they share one taskId; **xdfx** passes a third `actionId` so it filters by `metadata.actionId` too, partitioning chat records per 行动 — `useChatsBase` derives it from `TaskContext.partitionByAction`) + 新建对话; the `…/chats` index (`TaskFxIndexResolver`) opens the latest task thread or 新建. The right `:thread_id` host differs by business: **rwfx** → `TaskFxChat` (`AgentChatPage taskGate`) = full workspace (non-`lite`): 目的树闸门 panel + 清除记录 (placed under 新建对话); **xdfx** → also `TaskFxChat` (same 目的树闸门 query+display, same `purpose_detail_url`) but workspace passed `lite`, **plus its own「清除记录」button** (`ActionClearButton`, under 新建对话) that deletes **by 行动id**: opening its confirm dialog first runs a「行动历史是否存在」pre-check (`fetchActionHistoryExists`; query endpoint `task_deeplink.action_history_url` is **address-TBD** — empty ⇒ unknown, does **not** block the delete; once a definite「无历史」comes back it disables 确认清除), then deletes via the **shared** delete endpoint `task_deeplink.delete_url` (migrated to `dropSixOrSevenData`, used by **both** rwfx + xdfx — Six=6BF/rwfx, Seven=7BF/xdfx): `deleteTaskPurpose(id, {idKind})` sends rwfx `?taskId=` (omits actionId) / xdfx `?actionId=` (omits taskId) — the unused param is **absent from the URL**, not null. `deleteTaskPurpose` + `fetchActionHistoryExists` live in `core/auth/task-purpose.ts`. **3qfx** → `TaskBindChat` (`AgentChatPage taskBind`, `lite`) = 1:N list only, no gate, and 新建对话 **auto-sends** the task opening text (`taskAutoSendText`; gate businesses send it via the gate's 开始问答 instead). **rwfx auto-starts the first Q&A when the 任务目的 query returns empty** (`TaskPurposePanel autoStartWhenEmpty`, threaded from the rwfx `TaskFxChat` only), **but gated by the 3q precheck**: on entering the rwfx workspace `RwfxSqGateProvider` (`task-components/rwfx-sq-gate.tsx`, wraps the workspace, rwfx only) calls `fetchSqReportStatus(taskId)` — `incomplete`(3q 无数据) pops the「3q 未完成,是否前往 3qfx」dialog AND **holds the auto-send**; the question is only sent when the user picks「暂不」(or dismisses — i.e. does NOT go to 3q analysis), while「前往 3qfx」navigates and discards the send. `complete`/`unknown` send immediately (no dialog). The panel's auto-start calls `useRwfxSqGate().gateStart(onStart)` instead of `onStart()`; the manual「开始问答」/覆盖确认 path is unchanged (ungated). This replaced the old standalone `RwfxSqReportGate` (which popped the same dialog but did not gate the auto-send). The 目的树闸门 (`TaskPurposePanel`) defaults **collapsed** and now keeps only 弹框查看 + 开始问答; the former jump buttons (编辑/下一步/3q详情/切换三情/弹框查看) all moved to the **configurable bottom 快捷跳转 bar** (`TaskJumpBar`, red 红底白字 buttons, right-aligned) driven by 按钮管理 — see the 按钮管理 bullet. `TaskPurposeDialog` (exported from `TaskPurposePanel`) backs both the gate zoom and the bottom bar's `purpose`-type button. `chatBasePath` keeps the post-send URL rewrite + new-chat button in the task-management context. Backend config `task_deeplink` (`config.yaml`, surfaced by `GET /api/public/config/task-deeplink`, mirrored in `core/auth/task-deeplink-config.ts`) adds `action_test`/`action_detail_url`/`detail_3q_url` + `mock.action_detail`. Any failure (no consumer URL / fetch error / unmapped goPath / unresolvable action id / no configured agent) silently falls back to the default home. Helpers: `core/auth/task-deeplink.ts`, `core/auth/task-purpose.ts`, `core/auth/task-deeplink-config.ts`, `core/threads/use-task-threads.ts`. - **iframe 嵌入模式 (外部系统用 iframe 套用深链问答/会商)** — 三个**按标签页**开关,全部由深链 URL 参数开启、存进同一份 `sessionStorage` 会话(`embed.session`,键名常量在 `core/embed/embed-session.ts`),跨登录跳转/刷新/页内导航存活,**绝不跨标签污染**同浏览器另开的正常系统页。核心隔离手法:用 `sessionStorage`(按标签页/浏览上下文隔离,iframe 即便同源也有独立一份)而非 `localStorage`(跨标签共享)。开关:(1) **`?embed=1`(可带 `&theme=`)** — 去全局 chrome(`PageLayout` 的 `pageSidebarAllowed && !isEmbedActive()` → 隐藏 Header + PageSidebar)+ 按外部主题色**强制**明/暗:走 next-themes 的 `forcedTheme`(`App.tsx` `AppProviders` 调 `resolveForcedEmbedTheme`,**不写** localStorage `strategy-theme`),离散映射 `dark-blue`/`dark`→深、其余→浅;嵌入侧**绝不**调 `setTheme`/`persistSidebarEnabled`(那俩落 localStorage 跨标签污染,`LoginPage` 据 `readEmbedParam` 跳过)。(2) **`?hideJump=1`** — 隐藏深链底部「快捷跳转」栏 `TaskJumpBar` 的两部分(底部「下一步」等按钮 + 右侧垂直居中悬浮菜单),单智能体问答 + 会商共用该栏,`isJumpBarHidden()` 为真时整条 `return null`。(3) **登录用户隔离** — 嵌入态下鉴权/身份键(`deerflow.auth` token、`userInfo`、`login.*`、`tools_token`、maxkey/userDetail token)全部经 `core/auth/scoped-storage.ts` 的 `authStorage()`(嵌入→sessionStorage / 正常→localStorage)读写,使 iframe 里登录的用户与正常登录用户**完全隔离**、互不覆盖;所有 token 读取都过 `getStoredAuth()`/`getAuthorizationHeaderValue()`(API 客户端 `core/api/*` 全走这俩),改中心函数即让全体调用方自动隔离;跨标签账号变更监听 `AuthSyncWatcher`(`core/auth/sync.tsx`)在嵌入态禁用。嵌入会话在 `main.tsx` 渲染前 `syncEmbedSessionFromCurrentUrl()` 同步启用(早于任何鉴权写入,避免首帧 effect 顺序漏写 localStorage);`AppProviders` 的 effect 再按 SPA 导航同步。`embed=0`/`hideJump=0` 可显式关闭。正常(非嵌入)标签页所有 `isXxx()` 恒 false,行为**零变化**。第三个开关 `?isolate=1`(**独立登录会话**)把同一套**登录用户隔离**单独提供给**普通(带 chrome)标签页**——只切换鉴权存储、不去 chrome / 不强制主题 / 不动跳转栏:`authStorage()` 的条件从「仅嵌入」放宽为 `isEmbedActive() || isIsolatedSession()`,`AuthSyncWatcher` 的跨标签监听对嵌入态**或**独立态都即时忽略(handler 内实时判,运行时开关也即刻生效)。除 URL 参数外,**设置 → 外观 →「登录会话」** 有一个 Switch「独立登录会话(本标签页)」运行时切换(`setIsolatedSession`,`appearance-settings-page.tsx`):**开启时先 `migrateAuthToSession()`**(`scoped-storage.ts`,把 localStorage 的受保护键 `deerflow.auth`/`userInfo`/`userId`/`tools_token` + `login.*` 前缀快照搬进 sessionStorage)再翻标志,故无感不登出;此后本标签页登录态独立——别处登录/换号影响不到它,它换号也影响不到别人,但关掉该标签即结束(需重登)。开启给 toast 提示。 -- **操作日志(Y-Log)上报** — 用户的关键操作(登录登出/查询/查看/增删改/启停/导入导出/问答等)成功后,**前端直连**外部接口 `POST {write_url}`(默认 `https://ch1.b.uat.4.cn/api/y-log/write`)记一条审计日志。核心模块 `src/core/log/`:`y-log.ts`(`writeYLog(params)` + `OptType` 枚举 0/1/3..12;**异步即发即忘、永不 await、永不抛错、失败静默**,自动把完整 url 转相对路径去 ip/host、对象入参/返回自动 `JSON.stringify` + 50k 裁剪、`optResult` 恒 0 只报成功),`y-log-config.ts`(从公开只读 `GET /api/public/config/y-log` 拉 `{enabled, writeUrl}`,模块级缓存 + 去重 + 默认兜底;`App.tsx` `AppProviders` 启动预热 `fetchYLogConfig()`),`y-log-token.ts`(token1 = token 登录的 `?authToken=`,经 [[scoped-storage]] 的 `authStorage*` 存取,嵌入态自动隔离)。**双门控**:仅当①存在 token1(即用 token 登录,`LoginPage` 成功后 `persistYLogToken(authToken)`,登出 `account-settings-page.tsx` 先报后清 token1)且②配置 `enabled && writeUrl` 才上报;否则一律不发。`optDetail` 统一「B1-CM助手-…」(**禁内部框架名**)。埋点**广覆盖**各 API client 的成功路径——原则是「一个用户操作(查看/查询/新增/编辑/删除/启停/导入导出)= 一条日志」,每个 API client 的**单条详情 GET(查看→view 4)/ 列表查询 GET(search 3)/ 新增 POST(create 9)/ 改 PUT·PATCH(edit 5)/ 删 DELETE(delete 6)/ 启停(enabled 11 / disabled 10)/ 导入导出(import 7 / export 8)**都各落一条,仅跳过高频 typeahead/状态轮询/纯 bootstrap config 读。覆盖文件:`strategy-components/api/{sensitive-words,menu-overrides,task-buttons,skill-addresses,light-apps,business-mapping}.ts`、`roundtable-planning/api/{drafts,task-drafts,roundtable-jobs,recommend,chains,multi-agent,dashboard-sessions}.ts`、`core/{agents,scheduled-tasks,knowledge,positions,tags,studio,system-settings,memory,mcp,models,custom-prompts,user-preferences,notifications,recommended-questions,user-qa,curator,admin,thread-shares,roundtable-draft-shares,tool-metrics,llm-metrics,note,artifacts}/api.ts`、`core/api/markdown-docx-export.ts`。**问答(Q&A)改为「一次大模型调用 = 一条日志」**:在共享的 `core/threads/hooks.ts` `useThreadStream` 的 `onLangChainEvent` 里监听 `on_chat_model_end`,每次模型调用结束就上报一条(optType 12,`reqParam` 取本次 input 的最后一条 user 文本 + 模型名,`returnParam` 取本次输出文本)——一个问答轮次里 lead agent / 子代理的**每次** LLM 调用都各记一条,覆盖所有走 `useThreadStream` 的页面(`ChatPage`/`AgentChatPage`/创建智能体/iframe/会商等);`ChatPage`/`AgentChatPage` 的 `onFinish` 仍额外保留一条轮次汇总。后端仅新增公开只读配置:`deerflow/config/y_log_config.py`(`YLogConfig{enabled,write_url}`)挂到 `AppConfig.y_log`,`app/gateway/routers/public_config.py` 加 `GET /api/public/config/y-log`,地址写在 `config.yaml` 的 `y_log` 段(mtime 热重载,前端无需重建);**不做后端代理**。Tests:`tests/test_y_log_config.py`。 +- **操作日志(Y-Log)上报** — 用户的关键操作(登录登出/查询/查看/增删改/启停/导入导出/问答等)成功后,**前端直连**外部接口 `POST {write_url}`(默认 `https://ch1.b.uat.4.cn/api/y-log/write`)记一条审计日志。核心模块 `src/core/log/`:`y-log.ts`(`writeYLog(params)` + `OptType` 枚举 0/1/3..12;**异步即发即忘、永不 await、永不抛错、失败静默**,自动把完整 url 转相对路径去 ip/host、对象入参/返回自动 `JSON.stringify` + 50k 裁剪、`optResult` 恒 0 只报成功),`y-log-config.ts`(从公开只读 `GET /api/public/config/y-log` 拉 `{enabled, writeUrl}`,模块级缓存 + 去重 + 默认兜底;`App.tsx` `AppProviders` 启动预热 `fetchYLogConfig()`),`y-log-token.ts`(token1 = token 登录的 `?authToken=`,经 [[scoped-storage]] 的 `authStorage*` 存取,嵌入态自动隔离)。**双门控**:仅当①存在 token1(即用 token 登录,`LoginPage` 成功后 `persistYLogToken(authToken)`,登出 `account-settings-page.tsx` 先报后清 token1)且②配置 `enabled && writeUrl` 才上报;否则一律不发。`optDetail` 统一「CM助手-全量-…」(**禁内部框架名**)。埋点**广覆盖**各 API client 的成功路径——原则是「一个用户操作(查看/查询/新增/编辑/删除/启停/导入导出)= 一条日志」,每个 API client 的**单条详情 GET(查看→view 4)/ 列表查询 GET(search 3)/ 新增 POST(create 9)/ 改 PUT·PATCH(edit 5)/ 删 DELETE(delete 6)/ 启停(enabled 11 / disabled 10)/ 导入导出(import 7 / export 8)**都各落一条,仅跳过高频 typeahead/状态轮询/纯 bootstrap config 读。覆盖文件:`strategy-components/api/{sensitive-words,menu-overrides,task-buttons,skill-addresses,light-apps,business-mapping}.ts`、`roundtable-planning/api/{drafts,task-drafts,roundtable-jobs,recommend,chains,multi-agent,dashboard-sessions}.ts`、`core/{agents,scheduled-tasks,knowledge,positions,tags,studio,system-settings,memory,mcp,models,custom-prompts,user-preferences,notifications,recommended-questions,user-qa,curator,admin,thread-shares,roundtable-draft-shares,tool-metrics,llm-metrics,note,artifacts}/api.ts`、`core/api/markdown-docx-export.ts`。**问答(Q&A)改为「一次大模型调用 = 一条日志」**:在共享的 `core/threads/hooks.ts` `useThreadStream` 的 `onLangChainEvent` 里监听 `on_chat_model_end`,每次模型调用结束就上报一条(optType 12,`reqParam` 取本次 input 的最后一条 user 文本 + 模型名,`returnParam` 取本次输出文本)——一个问答轮次里 lead agent / 子代理的**每次** LLM 调用都各记一条,覆盖所有走 `useThreadStream` 的页面(`ChatPage`/`AgentChatPage`/创建智能体/iframe/会商等);`ChatPage`/`AgentChatPage` 的 `onFinish` 仍额外保留一条轮次汇总。后端仅新增公开只读配置:`deerflow/config/y_log_config.py`(`YLogConfig{enabled,write_url}`)挂到 `AppConfig.y_log`,`app/gateway/routers/public_config.py` 加 `GET /api/public/config/y-log`,地址写在 `config.yaml` 的 `y_log` 段(mtime 热重载,前端无需重建);**不做后端代理**。Tests:`tests/test_y_log_config.py`。 ### Configuration diff --git a/frontend-web/src/components/workspace/settings/account-settings-page.tsx b/frontend-web/src/components/workspace/settings/account-settings-page.tsx index c8522df2..fccf853e 100644 --- a/frontend-web/src/components/workspace/settings/account-settings-page.tsx +++ b/frontend-web/src/components/workspace/settings/account-settings-page.tsx @@ -45,7 +45,7 @@ export function AccountSettingsPage() { // 操作日志(Y-Log):在清除 token1 之前上报登出(此时 token1 还在),keepalive 保证发出。 writeYLog({ optType: OptType.logout, - optDetail: "B1-CM助手-登出", + optDetail: "CM助手-全量-登出", url: "/api/v1/auth/logout", keepalive: true, }); diff --git a/frontend-web/src/core/admin/api.ts b/frontend-web/src/core/admin/api.ts index 0ab2861c..9a85c2ee 100644 --- a/frontend-web/src/core/admin/api.ts +++ b/frontend-web/src/core/admin/api.ts @@ -177,7 +177,7 @@ export async function listUserThreads(userId: string): Promise { const result = await parse(await apiFetch(url), "Failed to load threads"); writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-管理后台-查询用户会话列表", + optDetail: "CM助手-全量-管理后台-查询用户会话列表", url, reqParam: { userId }, returnParam: { count: result.length }, @@ -193,7 +193,7 @@ export async function listUserThreadMessages( const result = await parse(await apiFetch(url), "Failed to load messages"); writeYLog({ optType: OptType.view, - optDetail: "B1-CM助手-管理后台-查看会话消息", + optDetail: "CM助手-全量-管理后台-查看会话消息", url, reqParam: { userId, threadId }, returnParam: { count: result.length }, @@ -215,7 +215,7 @@ export async function listUserQa( const result = await parse(await apiFetch(url), "Failed to load user Q&A"); writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-管理后台-查询用户问答", + optDetail: "CM助手-全量-管理后台-查询用户问答", url, reqParam: { userId, ...params }, returnParam: { total: result.total, count: result.items.length }, @@ -230,7 +230,7 @@ export async function getUserMemory( const result = await parse(await apiFetch(url), "Failed to load memory"); writeYLog({ optType: OptType.view, - optDetail: "B1-CM助手-管理后台-查看用户记忆", + optDetail: "CM助手-全量-管理后台-查看用户记忆", url, reqParam: { userId }, }); @@ -255,7 +255,7 @@ export async function getUserLeaderboard( const result = await parse(await apiFetch(url), "Failed to load leaderboard"); writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-管理后台-查询用户排行榜", + optDetail: "CM助手-全量-管理后台-查询用户排行榜", url, reqParam: { ...range, limit }, }); @@ -287,7 +287,7 @@ export async function refreshTodayLeaderboard( ); writeYLog({ optType: OptType.other, - optDetail: "B1-CM助手-管理后台-刷新今日排行榜", + optDetail: "CM助手-全量-管理后台-刷新今日排行榜", url, reqParam: { ...range, limit }, }); @@ -309,7 +309,7 @@ export async function getUserAnalytics( const result = await parse(await apiFetch(url), "Failed to load user analytics"); writeYLog({ optType: OptType.view, - optDetail: "B1-CM助手-管理后台-查看用户分析", + optDetail: "CM助手-全量-管理后台-查看用户分析", url, reqParam: { userId, ...range, limit }, }); @@ -335,7 +335,7 @@ export async function generateUserLeaderboardReport( ); writeYLog({ optType: OptType.other, - optDetail: "B1-CM助手-管理后台-生成排行榜报告", + optDetail: "CM助手-全量-管理后台-生成排行榜报告", url, reqParam: { ...range, limit, modelName }, returnParam: { generated_at: result.generated_at, model_name: result.model_name }, @@ -414,7 +414,7 @@ export async function streamUserLeaderboardReport({ } writeYLog({ optType: OptType.other, - optDetail: "B1-CM助手-管理后台-流式生成排行榜报告", + optDetail: "CM助手-全量-管理后台-流式生成排行榜报告", url, reqParam: { ...range, limit, modelName }, }); @@ -436,7 +436,7 @@ export async function addAdminMemoryEntry( ); writeYLog({ optType: OptType.create, - optDetail: "B1-CM助手-管理后台-新增记忆条目", + optDetail: "CM助手-全量-管理后台-新增记忆条目", url, reqParam: { userId, content, agent }, }); @@ -460,7 +460,7 @@ export async function replaceAdminMemoryEntry( ); writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-管理后台-编辑记忆条目", + optDetail: "CM助手-全量-管理后台-编辑记忆条目", url, reqParam: { userId, old_text: oldText, content, agent }, }); @@ -481,7 +481,7 @@ export async function deleteAdminMemoryEntry( ); writeYLog({ optType: OptType.delete, - optDetail: "B1-CM助手-管理后台-删除记忆条目", + optDetail: "CM助手-全量-管理后台-删除记忆条目", url, reqParam: { userId, old_text: oldText, agent }, }); @@ -508,7 +508,7 @@ export async function updateAdminV1Section( ); writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-管理后台-编辑记忆段落", + optDetail: "CM助手-全量-管理后台-编辑记忆段落", url, reqParam: { userId, section_type: sectionType, field, summary, agent }, }); @@ -533,7 +533,7 @@ export async function addAdminV1Fact( ); writeYLog({ optType: OptType.create, - optDetail: "B1-CM助手-管理后台-新增记忆事实", + optDetail: "CM助手-全量-管理后台-新增记忆事实", url, reqParam: { userId, content, category, confidence, agent }, }); @@ -557,7 +557,7 @@ export async function updateAdminV1Fact( ); writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-管理后台-编辑记忆事实", + optDetail: "CM助手-全量-管理后台-编辑记忆事实", url, reqParam: { userId, factId, ...updates, agent }, }); @@ -579,7 +579,7 @@ export async function deleteAdminV1Fact( ); writeYLog({ optType: OptType.delete, - optDetail: "B1-CM助手-管理后台-删除记忆事实", + optDetail: "CM助手-全量-管理后台-删除记忆事实", url, reqParam: { userId, factId, agent }, }); diff --git a/frontend-web/src/core/agents/api.ts b/frontend-web/src/core/agents/api.ts index 86012665..badaaf6f 100644 --- a/frontend-web/src/core/agents/api.ts +++ b/frontend-web/src/core/agents/api.ts @@ -61,7 +61,7 @@ export async function listAgents(params: ListAgentsParams = {}): Promise { const data = (await res.json()) as { agents: Agent[] }; writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-智能体列表", + optDetail: "CM助手-全量-智能体列表", url: `/api/agents?admin=true`, returnParam: data.agents, }); @@ -122,7 +122,7 @@ export async function getAgent(id: string): Promise { const agent = (await res.json()) as Agent; writeYLog({ optType: OptType.view, - optDetail: "B1-CM助手-智能体-查看", + optDetail: "CM助手-全量-智能体-查看", url: `/api/agents/${id}`, reqParam: { id }, returnParam: agent, @@ -143,7 +143,7 @@ export async function createAgent(request: CreateAgentRequest): Promise { const created = (await res.json()) as Agent; writeYLog({ optType: OptType.create, - optDetail: "B1-CM助手-智能体-新建", + optDetail: "CM助手-全量-智能体-新建", url: `/api/agents`, reqParam: request, returnParam: created, @@ -167,7 +167,7 @@ export async function updateAgent( const updated = (await res.json()) as Agent; writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-智能体-修改", + optDetail: "CM助手-全量-智能体-修改", url: `/api/agents/${id}`, reqParam: { id, ...request }, returnParam: updated, @@ -182,7 +182,7 @@ export async function deleteAgent(id: string): Promise { if (!res.ok) throw new Error(`Failed to delete agent: ${res.statusText}`); writeYLog({ optType: OptType.delete, - optDetail: "B1-CM助手-智能体-删除", + optDetail: "CM助手-全量-智能体-删除", url: `/api/agents/${id}`, reqParam: { id }, }); @@ -194,7 +194,7 @@ export async function getAgentSelector(): Promise { const selector = (await res.json()) as AgentSelectorResponse; writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-智能体-选择器", + optDetail: "CM助手-全量-智能体-选择器", url: `/api/agents/selector`, returnParam: selector, }); @@ -211,7 +211,7 @@ export async function favoriteAgent(id: string): Promise { } writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-智能体-收藏", + optDetail: "CM助手-全量-智能体-收藏", url: `/api/agents/${id}/favorite`, reqParam: { id }, }); @@ -227,7 +227,7 @@ export async function unfavoriteAgent(id: string): Promise { } writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-智能体-取消收藏", + optDetail: "CM助手-全量-智能体-取消收藏", url: `/api/agents/${id}/favorite`, reqParam: { id }, }); @@ -243,7 +243,7 @@ export async function pinAgent(id: string): Promise { } writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-智能体-置顶", + optDetail: "CM助手-全量-智能体-置顶", url: `/api/agents/${id}/pin`, reqParam: { id }, }); @@ -259,7 +259,7 @@ export async function unpinAgent(id: string): Promise { } writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-智能体-取消置顶", + optDetail: "CM助手-全量-智能体-取消置顶", url: `/api/agents/${id}/pin`, reqParam: { id }, }); @@ -282,7 +282,7 @@ export async function reorderFeaturedAgents(agentIds: string[]): Promise { } writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-智能体-精选排序", + optDetail: "CM助手-全量-智能体-精选排序", url: `/api/agents/featured/order`, reqParam: { agent_ids: agentIds }, }); @@ -306,7 +306,7 @@ export async function listPrivateAgents(password: string): Promise { const data = (await res.json()) as { agents: Agent[] }; writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-私有广场智能体列表", + optDetail: "CM助手-全量-私有广场智能体列表", url: `/api/agents/private-square/list`, returnParam: data.agents, }); @@ -364,7 +364,7 @@ export async function listPrivateAgentsPaginated( }; writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-私有广场智能体列表", + optDetail: "CM助手-全量-私有广场智能体列表", url: `/api/agents/private-square/list`, reqParam: { ...params, password: undefined }, returnParam: result, @@ -393,7 +393,7 @@ export async function setAgentPrivate( const updated = (await res.json()) as Agent; writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-智能体-设置私有", + optDetail: "CM助手-全量-智能体-设置私有", url: `/api/agents/${id}/private`, reqParam: { id, is_private: isPrivate }, returnParam: updated, @@ -422,7 +422,7 @@ export async function setAgentFeatured( const updated = (await res.json()) as Agent; writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-智能体-设置精选", + optDetail: "CM助手-全量-智能体-设置精选", url: `/api/agents/${id}/featured`, reqParam: { id, order }, returnParam: updated, @@ -455,7 +455,7 @@ export async function adminSyncAgentSkills(): Promise { const result = (await res.json()) as AgentSkillsSyncResult; writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-智能体-同步技能", + optDetail: "CM助手-全量-智能体-同步技能", url: `/api/agents/admin/sync-skills`, returnParam: result, }); @@ -500,7 +500,7 @@ export async function publishArtifactToKnowledge(request: { const result = (await res.json()) as KnowledgeIngestPublishResult; writeYLog({ optType: OptType.export, - optDetail: "B1-CM助手-智能体-产物发布入库", + optDetail: "CM助手-全量-智能体-产物发布入库", url: `/api/knowledge-ingest/publish`, reqParam: request, returnParam: result, diff --git a/frontend-web/src/core/api/markdown-docx-export.ts b/frontend-web/src/core/api/markdown-docx-export.ts index 1225b755..053a1963 100644 --- a/frontend-web/src/core/api/markdown-docx-export.ts +++ b/frontend-web/src/core/api/markdown-docx-export.ts @@ -82,7 +82,7 @@ export async function downloadMarkdownDocxFromBackend(options: { await downloadMarkdownAsDocx(markdown, options.title?.trim() || "document", options.title); writeYLog({ optType: OptType.export, - optDetail: "B1-CM助手-导出-Word", + optDetail: "CM助手-全量-导出-Word", url: `${getBackendBaseURL()}/api/writing/export/docx`, reqParam: { title: options.title?.trim() || undefined }, }); @@ -92,7 +92,7 @@ export async function downloadMarkdownDocxFromBackend(options: { await downloadBlobResponse(response, fallbackFilename); writeYLog({ optType: OptType.export, - optDetail: "B1-CM助手-导出-Word", + optDetail: "CM助手-全量-导出-Word", url: `${getBackendBaseURL()}/api/writing/export/docx`, reqParam: { title: options.title?.trim() || undefined }, }); @@ -101,7 +101,7 @@ export async function downloadMarkdownDocxFromBackend(options: { await downloadMarkdownAsDocx(markdown, options.title?.trim() || "document", options.title); writeYLog({ optType: OptType.export, - optDetail: "B1-CM助手-导出-Word", + optDetail: "CM助手-全量-导出-Word", url: `${getBackendBaseURL()}/api/writing/export/docx`, reqParam: { title: options.title?.trim() || undefined }, }); diff --git a/frontend-web/src/core/artifacts/api.ts b/frontend-web/src/core/artifacts/api.ts index 72c3c1bd..11f55383 100644 --- a/frontend-web/src/core/artifacts/api.ts +++ b/frontend-web/src/core/artifacts/api.ts @@ -40,7 +40,7 @@ export async function updateArtifactContent({ } writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-产物-编辑产物内容", + optDetail: "CM助手-全量-产物-编辑产物内容", url, reqParam: { filepath, threadId }, }); diff --git a/frontend-web/src/core/curator/api.ts b/frontend-web/src/core/curator/api.ts index 5d7f556f..c37e039c 100644 --- a/frontend-web/src/core/curator/api.ts +++ b/frontend-web/src/core/curator/api.ts @@ -37,7 +37,7 @@ export async function updateCuratorConfig( const result = (await response.json()) as CuratorConfig; writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-策展-更新配置", + optDetail: "CM助手-全量-策展-更新配置", url, reqParam: payload, returnParam: result, @@ -57,7 +57,7 @@ export async function runCurator(): Promise { const result = (await response.json()) as RunCuratorResult; writeYLog({ optType: OptType.other, - optDetail: "B1-CM助手-策展-手动触发策展", + optDetail: "CM助手-全量-策展-手动触发策展", url, returnParam: result, }); @@ -70,7 +70,7 @@ export async function getCuratorLogs(): Promise { const result = (await response.json()) as CuratorLogs; writeYLog({ optType: OptType.view, - optDetail: "B1-CM助手-策展-查看运行日志", + optDetail: "CM助手-全量-策展-查看运行日志", url, }); return result; diff --git a/frontend-web/src/core/custom-prompts/index.ts b/frontend-web/src/core/custom-prompts/index.ts index 17d7b2fa..3c9d56b8 100644 --- a/frontend-web/src/core/custom-prompts/index.ts +++ b/frontend-web/src/core/custom-prompts/index.ts @@ -30,7 +30,7 @@ async function listUserPrompts(): Promise { const data = (await res.json()) as { prompts: CustomPrompt[] }; writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-自定义提示词-查询", + optDetail: "CM助手-全量-自定义提示词-查询", url: "/api/user-prompts", returnParam: data.prompts, }); @@ -54,7 +54,7 @@ async function createUserPrompt(input: { const created = (await res.json()) as CustomPrompt; writeYLog({ optType: OptType.create, - optDetail: "B1-CM助手-自定义提示词-新增", + optDetail: "CM助手-全量-自定义提示词-新增", url: "/api/user-prompts", reqParam: input, returnParam: created, @@ -78,7 +78,7 @@ async function updateUserPrompt( const updated = (await res.json()) as CustomPrompt; writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-自定义提示词-编辑", + optDetail: "CM助手-全量-自定义提示词-编辑", url: `/api/user-prompts/${id}`, reqParam: input, returnParam: updated, @@ -96,7 +96,7 @@ async function deleteUserPrompt(id: string): Promise { } writeYLog({ optType: OptType.delete, - optDetail: "B1-CM助手-自定义提示词-删除", + optDetail: "CM助手-全量-自定义提示词-删除", url: `/api/user-prompts/${id}`, reqParam: { id }, }); diff --git a/frontend-web/src/core/knowledge/api.ts b/frontend-web/src/core/knowledge/api.ts index 1e79fa28..ec06cf59 100644 --- a/frontend-web/src/core/knowledge/api.ts +++ b/frontend-web/src/core/knowledge/api.ts @@ -47,7 +47,7 @@ export async function listKnowledgeNotes(params: KnowledgeListParams = {}) { ); writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-知识库-检索", + optDetail: "CM助手-全量-知识库-检索", url: `${baseUrl()}/notes?${qs.toString()}`, reqParam: params, returnParam: result, @@ -61,7 +61,7 @@ export async function getKnowledgeNote(noteId: string) { ); writeYLog({ optType: OptType.view, - optDetail: "B1-CM助手-知识库-查看", + optDetail: "CM助手-全量-知识库-查看", url: `${baseUrl()}/notes/${encodeURIComponent(noteId)}`, reqParam: { noteId }, returnParam: result, @@ -86,7 +86,7 @@ export async function createKnowledgeNote(data: { ); writeYLog({ optType: OptType.create, - optDetail: "B1-CM助手-知识库-新建", + optDetail: "CM助手-全量-知识库-新建", url: `${baseUrl()}/notes`, reqParam: data, returnParam: res.note, @@ -114,7 +114,7 @@ export async function updateKnowledgeNote( ); writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-知识库-修改", + optDetail: "CM助手-全量-知识库-修改", url: `${baseUrl()}/notes/${encodeURIComponent(noteId)}`, reqParam: { noteId, data }, returnParam: result, @@ -131,7 +131,7 @@ export async function deleteKnowledgeNote(noteId: string, hard = false) { ); writeYLog({ optType: OptType.delete, - optDetail: "B1-CM助手-知识库-删除", + optDetail: "CM助手-全量-知识库-删除", url: `${baseUrl()}/notes/${encodeURIComponent(noteId)}${hard ? "?hard=true" : ""}`, reqParam: { noteId, hard }, returnParam: result, @@ -149,7 +149,7 @@ export async function searchKnowledge(query: string, limit = 8) { ); writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-知识库-检索", + optDetail: "CM助手-全量-知识库-检索", url: `${baseUrl()}/search`, reqParam: { query, mode: "keyword", limit }, returnParam: res.items, @@ -171,7 +171,7 @@ export async function ingestThread(threadId: string, payload: IngestThreadPayloa ); writeYLog({ optType: OptType.import, - optDetail: "B1-CM助手-知识库-导入", + optDetail: "CM助手-全量-知识库-导入", url: `${baseUrl()}/ingest/thread/${encodeURIComponent(threadId)}`, reqParam: { threadId, payload }, returnParam: result, @@ -189,7 +189,7 @@ export async function ingestThreadsBatch(payload: BatchIngestPayload = {}) { ); writeYLog({ optType: OptType.import, - optDetail: "B1-CM助手-知识库-导入", + optDetail: "CM助手-全量-知识库-导入", url: `${baseUrl()}/ingest/threads/batch`, reqParam: payload, returnParam: result, @@ -230,7 +230,7 @@ export async function ingestKnowledgeFile( ); writeYLog({ optType: OptType.import, - optDetail: "B1-CM助手-知识库-导入", + optDetail: "CM助手-全量-知识库-导入", url: `${baseUrl()}/ingest/file`, reqParam: { fileName: file.name, ...opts }, returnParam: result, @@ -267,7 +267,7 @@ export async function fetchVaultPage(path: string) { ); writeYLog({ optType: OptType.view, - optDetail: "B1-CM助手-知识库-Vault页面查看", + optDetail: "CM助手-全量-知识库-Vault页面查看", url: `${baseUrl()}/vault-page?path=${encodeURIComponent(path)}`, reqParam: { path }, returnParam: result, @@ -281,7 +281,7 @@ export async function exportKnowledgeGraph() { ); writeYLog({ optType: OptType.export, - optDetail: "B1-CM助手-知识库-导出", + optDetail: "CM助手-全量-知识库-导出", url: `${baseUrl()}/export/graph`, returnParam: result, }); @@ -313,7 +313,7 @@ export async function listNoteVersions(noteId: string) { ); writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-知识库-历史版本列表", + optDetail: "CM助手-全量-知识库-历史版本列表", url: `${baseUrl()}/notes/${encodeURIComponent(noteId)}/versions`, reqParam: { noteId }, returnParam: res.items, @@ -332,7 +332,7 @@ export async function listDuplicates() { ); writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-知识库-重复项列表", + optDetail: "CM助手-全量-知识库-重复项列表", url: `${baseUrl()}/duplicates`, returnParam: res.groups, }); @@ -349,7 +349,7 @@ export async function mergeKnowledgeNotes(primaryId: string, duplicateIds: strin ); writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-知识库-合并", + optDetail: "CM助手-全量-知识库-合并", url: `${baseUrl()}/merge`, reqParam: { primary_id: primaryId, duplicate_ids: duplicateIds }, returnParam: result, @@ -363,7 +363,7 @@ export async function reindexKnowledge() { ); writeYLog({ optType: OptType.other, - optDetail: "B1-CM助手-知识库-重建索引", + optDetail: "CM助手-全量-知识库-重建索引", url: `${baseUrl()}/reindex`, returnParam: result, }); @@ -379,7 +379,7 @@ export async function getKnowledgeGraph() { const result = await parseResponse(await apiFetch(`${baseUrl()}/graph`)); writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-知识库-图谱查看", + optDetail: "CM助手-全量-知识库-图谱查看", url: `${baseUrl()}/graph`, returnParam: result, }); @@ -401,7 +401,7 @@ export async function getGraphBlacklist() { ); writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-知识库-图谱黑名单列表", + optDetail: "CM助手-全量-知识库-图谱黑名单列表", url: `${baseUrl()}/graph/blacklist`, returnParam: res.items, }); @@ -419,7 +419,7 @@ export async function addGraphBlacklist(labels: string[]) { ); writeYLog({ optType: OptType.create, - optDetail: "B1-CM助手-知识库-图谱黑名单新增", + optDetail: "CM助手-全量-知识库-图谱黑名单新增", url: `${baseUrl()}/graph/blacklist`, reqParam: { labels }, returnParam: result, @@ -435,7 +435,7 @@ export async function removeGraphBlacklist(entryId: string) { ); writeYLog({ optType: OptType.delete, - optDetail: "B1-CM助手-知识库-图谱黑名单删除", + optDetail: "CM助手-全量-知识库-图谱黑名单删除", url: `${baseUrl()}/graph/blacklist/${encodeURIComponent(entryId)}`, reqParam: { entryId }, returnParam: result, @@ -451,7 +451,7 @@ export async function listKnowledgeFolders() { ); writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-知识库-目录列表", + optDetail: "CM助手-全量-知识库-目录列表", url: `${baseUrl()}/folders`, returnParam: res.items, }); @@ -468,7 +468,7 @@ export async function createKnowledgeFolder(path: string) { ); writeYLog({ optType: OptType.create, - optDetail: "B1-CM助手-知识库-目录新建", + optDetail: "CM助手-全量-知识库-目录新建", url: `${baseUrl()}/folders`, reqParam: { path }, returnParam: res.folder, @@ -486,7 +486,7 @@ export async function renameKnowledgeFolder(folderId: string, path: string) { ); writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-知识库-目录重命名", + optDetail: "CM助手-全量-知识库-目录重命名", url: `${baseUrl()}/folders/${encodeURIComponent(folderId)}`, reqParam: { folderId, path }, returnParam: res.folder, @@ -503,7 +503,7 @@ export async function deleteKnowledgeFolder(folderId: string, reassignTo?: strin ); writeYLog({ optType: OptType.delete, - optDetail: "B1-CM助手-知识库-目录删除", + optDetail: "CM助手-全量-知识库-目录删除", url: `${baseUrl()}/folders/${encodeURIComponent(folderId)}${qs}`, reqParam: { folderId, reassignTo }, returnParam: result, @@ -523,7 +523,7 @@ export async function listExtractTemplates(scope?: ExtractTemplateScope, enabled ); writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-知识库-抽取模板列表", + optDetail: "CM助手-全量-知识库-抽取模板列表", url: `${baseUrl()}/extract-templates${q ? `?${q}` : ""}`, reqParam: { scope, enabledOnly }, returnParam: res.items, @@ -550,7 +550,7 @@ export async function createExtractTemplate(data: ExtractTemplateInput) { ); writeYLog({ optType: OptType.create, - optDetail: "B1-CM助手-知识库-抽取模板新建", + optDetail: "CM助手-全量-知识库-抽取模板新建", url: `${baseUrl()}/extract-templates`, reqParam: data, returnParam: res.template, @@ -571,7 +571,7 @@ export async function updateExtractTemplate( ); writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-知识库-抽取模板修改", + optDetail: "CM助手-全量-知识库-抽取模板修改", url: `${baseUrl()}/extract-templates/${encodeURIComponent(templateId)}`, reqParam: { templateId, data }, returnParam: res.template, @@ -587,7 +587,7 @@ export async function deleteExtractTemplate(templateId: string) { ); writeYLog({ optType: OptType.delete, - optDetail: "B1-CM助手-知识库-抽取模板删除", + optDetail: "CM助手-全量-知识库-抽取模板删除", url: `${baseUrl()}/extract-templates/${encodeURIComponent(templateId)}`, reqParam: { templateId }, returnParam: result, diff --git a/frontend-web/src/core/llm-metrics/api.ts b/frontend-web/src/core/llm-metrics/api.ts index b3433901..78339f81 100644 --- a/frontend-web/src/core/llm-metrics/api.ts +++ b/frontend-web/src/core/llm-metrics/api.ts @@ -64,7 +64,7 @@ export async function loadLlmMetrics( const result = (await response.json()) as LlmMetricsListResponse; writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-模型指标-查询调用列表", + optDetail: "CM助手-全量-模型指标-查询调用列表", url, reqParam: query, returnParam: { total: result.total, count: result.items.length }, @@ -87,7 +87,7 @@ export async function downloadLlmMetricsExcel( } writeYLog({ optType: OptType.export, - optDetail: "B1-CM助手-模型指标-导出Excel", + optDetail: "CM助手-全量-模型指标-导出Excel", url: requestUrl, reqParam: filters, }); diff --git a/frontend-web/src/core/log/y-log.ts b/frontend-web/src/core/log/y-log.ts index c82ef5d0..c22a91e3 100644 --- a/frontend-web/src/core/log/y-log.ts +++ b/frontend-web/src/core/log/y-log.ts @@ -35,7 +35,7 @@ export enum OptType { export interface WriteYLogParams { /** 操作类型枚举。 */ optType: OptType; - /** 操作详情(简短描述),统一「B1-CM助手-xxx」。 */ + /** 操作详情(简短描述),统一「CM助手-全量-xxx」。 */ optDetail: string; /** 操作命中的接口地址(完整或相对,内部自动转相对,去 ip/host)。 */ url: string; diff --git a/frontend-web/src/core/mcp/api.ts b/frontend-web/src/core/mcp/api.ts index 10c83f02..be3d9527 100644 --- a/frontend-web/src/core/mcp/api.ts +++ b/frontend-web/src/core/mcp/api.ts @@ -1,36 +1,36 @@ -import { getBackendBaseURL } from "@/core/config"; -import { apiFetch } from "@/core/api"; -import { OptType, writeYLog } from "@/core/log/y-log"; - -import type { MCPConfig } from "./types"; - -export async function loadMCPConfig() { - const response = await apiFetch(`${getBackendBaseURL()}/api/mcp/config`); - const data = (await response.json()) as MCPConfig; - writeYLog({ - optType: OptType.view, - optDetail: "B1-CM助手-MCP服务-配置查看", - url: "/api/mcp/config", - returnParam: data, - }); - return data; -} - -export async function updateMCPConfig(config: MCPConfig) { - const response = await apiFetch(`${getBackendBaseURL()}/api/mcp/config`, { - method: "PUT", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(config), - }); - const data = await response.json(); - writeYLog({ - optType: OptType.edit, - optDetail: "B1-CM助手-MCP服务-配置编辑", - url: "/api/mcp/config", - reqParam: config, - returnParam: data, - }); - return data; -} +import { getBackendBaseURL } from "@/core/config"; +import { apiFetch } from "@/core/api"; +import { OptType, writeYLog } from "@/core/log/y-log"; + +import type { MCPConfig } from "./types"; + +export async function loadMCPConfig() { + const response = await apiFetch(`${getBackendBaseURL()}/api/mcp/config`); + const data = (await response.json()) as MCPConfig; + writeYLog({ + optType: OptType.view, + optDetail: "CM助手-全量-MCP服务-配置查看", + url: "/api/mcp/config", + returnParam: data, + }); + return data; +} + +export async function updateMCPConfig(config: MCPConfig) { + const response = await apiFetch(`${getBackendBaseURL()}/api/mcp/config`, { + method: "PUT", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(config), + }); + const data = await response.json(); + writeYLog({ + optType: OptType.edit, + optDetail: "CM助手-全量-MCP服务-配置编辑", + url: "/api/mcp/config", + reqParam: config, + returnParam: data, + }); + return data; +} diff --git a/frontend-web/src/core/memory/api.ts b/frontend-web/src/core/memory/api.ts index 5a759744..8569b666 100644 --- a/frontend-web/src/core/memory/api.ts +++ b/frontend-web/src/core/memory/api.ts @@ -58,7 +58,7 @@ export async function loadMemoryV2(agent?: string): Promise { const data = await readJson(response, "Failed to fetch memory"); writeYLog({ optType: OptType.view, - optDetail: "B1-CM助手-记忆-查看", + optDetail: "CM助手-全量-记忆-查看", url: `/api/memory/v2${agentQuery(agent)}`, reqParam: { agent }, returnParam: data, @@ -82,7 +82,7 @@ export async function addMemoryEntry( const data = await readJson(response, "Failed to add memory entry"); writeYLog({ optType: OptType.create, - optDetail: "B1-CM助手-记忆-新增", + optDetail: "CM助手-全量-记忆-新增", url: `/api/memory/v2/entries${agentQuery(agent)}`, reqParam: { target, content, agent }, returnParam: data, @@ -107,7 +107,7 @@ export async function replaceMemoryEntry( const data = await readJson(response, "Failed to replace memory entry"); writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-记忆-编辑", + optDetail: "CM助手-全量-记忆-编辑", url: `/api/memory/v2/entries${agentQuery(agent)}`, reqParam: { target, old_text: oldText, content, agent }, returnParam: data, @@ -131,7 +131,7 @@ export async function deleteMemoryEntry( const data = await readJson(response, "Failed to delete memory entry"); writeYLog({ optType: OptType.delete, - optDetail: "B1-CM助手-记忆-删除", + optDetail: "CM助手-全量-记忆-删除", url: `/api/memory/v2/entries?${params.toString()}`, reqParam: { target, old_text: oldText, agent }, returnParam: data, @@ -146,7 +146,7 @@ export async function loadMemoryConfig(): Promise { const data = await readJson(response, "Failed to fetch memory config"); writeYLog({ optType: OptType.view, - optDetail: "B1-CM助手-记忆-配置查看", + optDetail: "CM助手-全量-记忆-配置查看", url: "/api/memory/v2/config", returnParam: data, }); @@ -164,7 +164,7 @@ export async function patchMemoryConfig( const data = await readJson(response, "Failed to update memory config"); writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-记忆-配置编辑", + optDetail: "CM助手-全量-记忆-配置编辑", url: "/api/memory/v2/config", reqParam: { overrides }, returnParam: data, @@ -190,7 +190,7 @@ export async function searchMemory( const data = await readJson(response, "Failed to search memory"); writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-记忆-检索", + optDetail: "CM助手-全量-记忆-检索", url: `/api/memory/v2/search${agentQuery(agent)}`, reqParam: { query, mode, agent }, returnParam: data, diff --git a/frontend-web/src/core/models/api.ts b/frontend-web/src/core/models/api.ts index 63ff64a9..766c5467 100644 --- a/frontend-web/src/core/models/api.ts +++ b/frontend-web/src/core/models/api.ts @@ -1,21 +1,21 @@ -import { getBackendBaseURL } from "../config"; -import { apiFetch } from "../api"; -import { OptType, writeYLog } from "../log/y-log"; - -import type { ModelsResponse } from "./types"; - -export async function loadModels(): Promise { - const res = await apiFetch(`${getBackendBaseURL()}/api/models`); - const data = (await res.json()) as Partial; - const result: ModelsResponse = { - models: data.models ?? [], - token_usage: data.token_usage ?? { enabled: false }, - }; - writeYLog({ - optType: OptType.search, - optDetail: "B1-CM助手-模型-查询", - url: "/api/models", - returnParam: result, - }); - return result; -} +import { getBackendBaseURL } from "../config"; +import { apiFetch } from "../api"; +import { OptType, writeYLog } from "../log/y-log"; + +import type { ModelsResponse } from "./types"; + +export async function loadModels(): Promise { + const res = await apiFetch(`${getBackendBaseURL()}/api/models`); + const data = (await res.json()) as Partial; + const result: ModelsResponse = { + models: data.models ?? [], + token_usage: data.token_usage ?? { enabled: false }, + }; + writeYLog({ + optType: OptType.search, + optDetail: "CM助手-全量-模型-查询", + url: "/api/models", + returnParam: result, + }); + return result; +} diff --git a/frontend-web/src/core/note/api.ts b/frontend-web/src/core/note/api.ts index f4a5dbd9..f4a8c66b 100644 --- a/frontend-web/src/core/note/api.ts +++ b/frontend-web/src/core/note/api.ts @@ -80,7 +80,7 @@ export async function createSearchSpace( const result = (await response.json()) as SearchSpace; writeYLog({ optType: OptType.create, - optDetail: "B1-CM助手-笔记-新建笔记空间", + optDetail: "CM助手-全量-笔记-新建笔记空间", url: "/api/v1/searchspaces", reqParam: { name: input.name, description: input.description ?? "" }, returnParam: { id: result.id, name: result.name }, @@ -110,7 +110,7 @@ export async function listSearchSpaces( const list = Array.isArray(data) ? (data as SearchSpace[]) : []; writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-笔记-查询笔记空间列表", + optDetail: "CM助手-全量-笔记-查询笔记空间列表", url: path, reqParam: query, returnParam: { count: list.length }, diff --git a/frontend-web/src/core/notifications/api.ts b/frontend-web/src/core/notifications/api.ts index 19c54190..0b247bee 100644 --- a/frontend-web/src/core/notifications/api.ts +++ b/frontend-web/src/core/notifications/api.ts @@ -27,7 +27,7 @@ export async function listNotifications( const data = (await res.json()) as NotificationListResponse; writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-通知-查询通知列表", + optDetail: "CM助手-全量-通知-查询通知列表", url, reqParam: options, returnParam: { count: data.items.length }, @@ -48,7 +48,7 @@ export async function markNotificationRead(id: string): Promise { if (!res.ok) throw await parseDetail(res, "Failed to mark notification read"); writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-通知-标记已读", + optDetail: "CM助手-全量-通知-标记已读", url, reqParam: { id }, }); @@ -61,7 +61,7 @@ export async function markAllNotificationsRead(): Promise { const data = (await res.json()) as { updated: number }; writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-通知-全部标记已读", + optDetail: "CM助手-全量-通知-全部标记已读", url, returnParam: data, }); @@ -74,7 +74,7 @@ export async function deleteNotification(id: string): Promise { if (!res.ok) throw await parseDetail(res, "Failed to delete notification"); writeYLog({ optType: OptType.delete, - optDetail: "B1-CM助手-通知-删除通知", + optDetail: "CM助手-全量-通知-删除通知", url, reqParam: { id }, }); diff --git a/frontend-web/src/core/positions/api.ts b/frontend-web/src/core/positions/api.ts index f7106191..efe8f62b 100644 --- a/frontend-web/src/core/positions/api.ts +++ b/frontend-web/src/core/positions/api.ts @@ -27,7 +27,7 @@ export async function listPositions(): Promise { const data = (await res.json()) as PositionListResponse; writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-岗位-查询", + optDetail: "CM助手-全量-岗位-查询", url: "/api/positions", returnParam: data.positions, }); @@ -44,7 +44,7 @@ export async function createPosition(input: PositionCreateInput): Promise { if (!res.ok) throw await parseDetail(res, "Failed to delete position"); writeYLog({ optType: OptType.delete, - optDetail: "B1-CM助手-岗位-删除", + optDetail: "CM助手-全量-岗位-删除", url: `/api/positions/${id}`, reqParam: { id }, }); @@ -87,7 +87,7 @@ export async function getTagBindings(positionId: string): Promise { const data = (await res.json()) as TagBindingsResponse; writeYLog({ optType: OptType.view, - optDetail: "B1-CM助手-岗位-标签绑定查看", + optDetail: "CM助手-全量-岗位-标签绑定查看", url: `/api/positions/${positionId}/tag-bindings`, reqParam: { positionId }, returnParam: data.bindings, @@ -105,7 +105,7 @@ export async function setTagBindings(positionId: string, bindings: TagBindings): const data = (await res.json()) as TagBindingsResponse; writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-岗位-标签绑定保存", + optDetail: "CM助手-全量-岗位-标签绑定保存", url: `/api/positions/${positionId}/tag-bindings`, reqParam: { positionId, bindings }, returnParam: data.bindings, @@ -119,7 +119,7 @@ export async function listMembers(positionId: string): Promise const data = (await res.json()) as { members: PositionMember[] }; writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-岗位-成员查询", + optDetail: "CM助手-全量-岗位-成员查询", url: `/api/positions/${positionId}/members`, reqParam: { positionId }, returnParam: data.members, @@ -137,7 +137,7 @@ export async function addMembers(positionId: string, userIds: string[]): Promise const data = (await res.json()) as { members: PositionMember[] }; writeYLog({ optType: OptType.create, - optDetail: "B1-CM助手-岗位-添加成员", + optDetail: "CM助手-全量-岗位-添加成员", url: `/api/positions/${positionId}/members`, reqParam: { positionId, userIds }, returnParam: data.members, @@ -155,7 +155,7 @@ export async function removeMembers(positionId: string, userIds: string[]): Prom const data = (await res.json()) as { members: PositionMember[] }; writeYLog({ optType: OptType.delete, - optDetail: "B1-CM助手-岗位-移除成员", + optDetail: "CM助手-全量-岗位-移除成员", url: `/api/positions/${positionId}/members`, reqParam: { positionId, userIds }, returnParam: data.members, @@ -169,7 +169,7 @@ export async function resyncPosition(positionId: string): Promise { const data = (await res.json()) as { synced: number }; writeYLog({ optType: OptType.other, - optDetail: "B1-CM助手-岗位-同步", + optDetail: "CM助手-全量-岗位-同步", url: `/api/positions/${positionId}/resync`, reqParam: { positionId }, returnParam: data, @@ -190,7 +190,7 @@ export async function listPositionUsers(): Promise { const data = (await res.json()) as { users: PositionUser[] }; writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-岗位-用户查询", + optDetail: "CM助手-全量-岗位-用户查询", url: "/api/positions/users", returnParam: data.users, }); @@ -206,7 +206,7 @@ export async function setUserPosition(userId: string, positionId: string | null) if (!res.ok) throw await parseDetail(res, "Failed to set user position"); writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-岗位-设置用户岗位", + optDetail: "CM助手-全量-岗位-设置用户岗位", url: `/api/positions/users/${userId}`, reqParam: { userId, positionId }, }); diff --git a/frontend-web/src/core/recommended-questions/api.ts b/frontend-web/src/core/recommended-questions/api.ts index d125872a..7943532a 100644 --- a/frontend-web/src/core/recommended-questions/api.ts +++ b/frontend-web/src/core/recommended-questions/api.ts @@ -19,7 +19,7 @@ export async function listRecommendedQuestions(all = false): Promise { if (!res.ok) throw new Error(`Failed to delete question: ${res.statusText}`); writeYLog({ optType: OptType.delete, - optDetail: "B1-CM助手-推荐问题-删除问题", + optDetail: "CM助手-全量-推荐问题-删除问题", url, reqParam: { id }, }); @@ -101,7 +101,7 @@ export async function reorderRecommendedQuestions( const data = (await res.json()) as { questions: RecommendedQuestion[] }; writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-推荐问题-调整排序", + optDetail: "CM助手-全量-推荐问题-调整排序", url, reqParam: { ids }, }); diff --git a/frontend-web/src/core/roundtable-draft-shares/api.ts b/frontend-web/src/core/roundtable-draft-shares/api.ts index cf48e1dc..97e0d4fb 100644 --- a/frontend-web/src/core/roundtable-draft-shares/api.ts +++ b/frontend-web/src/core/roundtable-draft-shares/api.ts @@ -90,7 +90,7 @@ export async function createDraftShare( const result = (await response.json()) as DraftShare; writeYLog({ optType: OptType.create, - optDetail: "B1-CM助手-会商草稿分享-创建分享", + optDetail: "CM助手-全量-会商草稿分享-创建分享", url: baseUrl(), reqParam: { draft_id: draftId, mode }, returnParam: { share_code: result.share_code, mode: result.mode }, @@ -105,7 +105,7 @@ export async function listDraftShares(): Promise { const json = (await response.json()) as { shares: DraftShare[] }; writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-会商草稿分享-查询分享列表", + optDetail: "CM助手-全量-会商草稿分享-查询分享列表", url: baseUrl(), returnParam: { count: json.shares.length }, }); @@ -119,7 +119,7 @@ export async function revokeDraftShare(shareCode: string): Promise { if (!response.ok) throw await parseError(response, "撤销分享失败"); writeYLog({ optType: OptType.delete, - optDetail: "B1-CM助手-会商草稿分享-撤销分享", + optDetail: "CM助手-全量-会商草稿分享-撤销分享", url, reqParam: { shareCode }, }); @@ -133,7 +133,7 @@ export async function previewDraftShare(shareCode: string): Promise(await apiFetch(favoritesUrl())); writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-HTML收藏-列表", + optDetail: "CM助手-全量-HTML收藏-列表", url: `/api/html-page-favorites`, returnParam: result, }); @@ -639,7 +639,7 @@ export async function getHtmlPageFavorite(favoriteId: string) { ); writeYLog({ optType: OptType.view, - optDetail: "B1-CM助手-HTML收藏-查看", + optDetail: "CM助手-全量-HTML收藏-查看", url: `/api/html-page-favorites/${encodeURIComponent(favoriteId)}`, reqParam: { favoriteId }, returnParam: result, @@ -662,7 +662,7 @@ export async function createHtmlPageFavorite(data: { ); writeYLog({ optType: OptType.create, - optDetail: "B1-CM助手-HTML收藏-新建", + optDetail: "CM助手-全量-HTML收藏-新建", url: `/api/html-page-favorites`, reqParam: data, returnParam: result, @@ -678,7 +678,7 @@ export async function deleteHtmlPageFavorite(favoriteId: string) { ); writeYLog({ optType: OptType.delete, - optDetail: "B1-CM助手-HTML收藏-删除", + optDetail: "CM助手-全量-HTML收藏-删除", url: `/api/html-page-favorites/${encodeURIComponent(favoriteId)}`, reqParam: { favoriteId }, returnParam: result, diff --git a/frontend-web/src/core/scheduled-tasks/markdown-docx.ts b/frontend-web/src/core/scheduled-tasks/markdown-docx.ts index 025836c4..48c6676e 100644 --- a/frontend-web/src/core/scheduled-tasks/markdown-docx.ts +++ b/frontend-web/src/core/scheduled-tasks/markdown-docx.ts @@ -488,7 +488,7 @@ export async function downloadMarkdownAsDocx( const blob = await markdownToDocxBlob(markdown, title); writeYLog({ optType: OptType.export, - optDetail: "B1-CM助手-定时任务-导出", + optDetail: "CM助手-全量-定时任务-导出", url: "/scheduled-tasks/export/docx", reqParam: { fileName, title }, }); diff --git a/frontend-web/src/core/studio/api.ts b/frontend-web/src/core/studio/api.ts index d2f31aa6..c1874b3e 100644 --- a/frontend-web/src/core/studio/api.ts +++ b/frontend-web/src/core/studio/api.ts @@ -34,7 +34,7 @@ export async function fetchStudioNotebooks( const notebooks = (await res.json()) as StudioNotebook[]; writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-工作室-空间查询", + optDetail: "CM助手-全量-工作室-空间查询", url: "/api/v1/searchspaces", returnParam: notebooks, }); @@ -62,7 +62,7 @@ export async function createSearchSpace( } writeYLog({ optType: OptType.create, - optDetail: "B1-CM助手-工作室-新建空间", + optDetail: "CM助手-全量-工作室-新建空间", url: "/api/v1/searchspaces", reqParam: { name }, }); @@ -91,7 +91,7 @@ export async function uploadSourceText( if (!res.ok) throw new Error(`上传失败:${res.status}`); writeYLog({ optType: OptType.import, - optDetail: "B1-CM助手-工作室-上传文字来源", + optDetail: "CM助手-全量-工作室-上传文字来源", url: "/api/v1/documents/textupload", reqParam: { search_space_id: notebookId, title: title || "粘贴的文字" }, }); @@ -110,7 +110,7 @@ export async function deleteSearchSpace( if (!res.ok) throw new Error(`删除失败:${res.status}`); writeYLog({ optType: OptType.delete, - optDetail: "B1-CM助手-工作室-删除空间", + optDetail: "CM助手-全量-工作室-删除空间", url: `/api/v1/searchspaces/${id}`, reqParam: { id }, }); @@ -134,7 +134,7 @@ export async function renameSearchSpace( if (!res.ok) throw new Error(`重命名失败:${res.status}`); writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-工作室-重命名空间", + optDetail: "CM助手-全量-工作室-重命名空间", url: `/api/v1/searchspaces/${id}`, reqParam: { id, name }, }); @@ -169,7 +169,7 @@ export async function fetchDocumentByChunk( const doc = (await res.json()) as DocumentWithChunks; writeYLog({ optType: OptType.view, - optDetail: "B1-CM助手-工作室-查看文档", + optDetail: "CM助手-全量-工作室-查看文档", url: `/api/v1/documents/by-chunk/${chunkId}`, reqParam: { chunkId }, returnParam: { id: doc.id, title: doc.title, file_type: doc.file_type }, @@ -199,7 +199,7 @@ export async function uploadSourceFiles( if (!res.ok) throw new Error(`上传失败:${res.status}`); writeYLog({ optType: OptType.import, - optDetail: "B1-CM助手-工作室-上传文件来源", + optDetail: "CM助手-全量-工作室-上传文件来源", url: "/api/v1/documents/fileupload", reqParam: { search_space_id: notebookId, @@ -223,7 +223,7 @@ export async function fetchNotebookSources( const sources = (await res.json()) as SourceItem[]; writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-工作室-来源查询", + optDetail: "CM助手-全量-工作室-来源查询", url: `/api/v1/source/search-space/${notebookId}?limit=100`, reqParam: { notebookId }, returnParam: sources, diff --git a/frontend-web/src/core/system-settings/api.ts b/frontend-web/src/core/system-settings/api.ts index fa78767d..6ca628c2 100644 --- a/frontend-web/src/core/system-settings/api.ts +++ b/frontend-web/src/core/system-settings/api.ts @@ -24,7 +24,7 @@ export async function loadPromptPrefixSettings(): Promise const data = (await response.json()) as PromptPrefixSettings; writeYLog({ optType: OptType.view, - optDetail: "B1-CM助手-系统设置-提示词前缀查看", + optDetail: "CM助手-全量-系统设置-提示词前缀查看", url: "/api/system-settings/prompt-prefix", returnParam: data, }); @@ -51,7 +51,7 @@ export async function updatePromptPrefixSettings( const data = (await response.json()) as PromptPrefixSettings; writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-系统设置-提示词前缀编辑", + optDetail: "CM助手-全量-系统设置-提示词前缀编辑", url: "/api/system-settings/prompt-prefix", reqParam: body, returnParam: data, @@ -105,7 +105,7 @@ export async function loadPrivateSquareStatus(): Promise { const data = (await response.json()) as PrivateSquareStatus; writeYLog({ optType: OptType.view, - optDetail: "B1-CM助手-系统设置-私密广场查看", + optDetail: "CM助手-全量-系统设置-私密广场查看", url: "/api/system-settings/private-square", returnParam: data, }); @@ -138,7 +138,7 @@ export async function loadPublishSquares(): Promise { const data = (await response.json()) as PublishSquaresSettings; writeYLog({ optType: OptType.view, - optDetail: "B1-CM助手-系统设置-发布广场查看", + optDetail: "CM助手-全量-系统设置-发布广场查看", url: "/api/system-settings/publish-squares", returnParam: data, }); @@ -165,7 +165,7 @@ export async function updatePublishSquares( const data = (await response.json()) as PublishSquaresSettings; writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-系统设置-发布广场编辑", + optDetail: "CM助手-全量-系统设置-发布广场编辑", url: "/api/system-settings/publish-squares", reqParam: body, returnParam: data, @@ -203,7 +203,7 @@ export async function loadAppearanceSettings(): Promise { const data = (await response.json()) as AppearanceSettings; writeYLog({ optType: OptType.view, - optDetail: "B1-CM助手-系统设置-外观查看", + optDetail: "CM助手-全量-系统设置-外观查看", url: "/api/system-settings/appearance", returnParam: data, }); @@ -230,7 +230,7 @@ export async function updateAppearanceSettings( const data = (await response.json()) as AppearanceSettings; writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-系统设置-外观编辑", + optDetail: "CM助手-全量-系统设置-外观编辑", url: "/api/system-settings/appearance", reqParam: body, returnParam: data, @@ -250,7 +250,7 @@ export async function loadCitationDisplaySettings(): Promise { const data = (await response.json()) as LeaderboardSettings; writeYLog({ optType: OptType.view, - optDetail: "B1-CM助手-系统设置-排行榜查看", + optDetail: "CM助手-全量-系统设置-排行榜查看", url: "/api/system-settings/leaderboard", returnParam: data, }); @@ -294,7 +294,7 @@ export async function updateLeaderboardSettings( const data = (await response.json()) as LeaderboardSettings; writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-系统设置-排行榜编辑", + optDetail: "CM助手-全量-系统设置-排行榜编辑", url: "/api/system-settings/leaderboard", reqParam: body, returnParam: data, @@ -322,7 +322,7 @@ export async function updateCitationDisplaySettings( const data = (await response.json()) as CitationDisplaySettings; writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-系统设置-引用展示编辑", + optDetail: "CM助手-全量-系统设置-引用展示编辑", url: "/api/system-settings/citation-display", reqParam: body, returnParam: data, @@ -354,7 +354,7 @@ export async function loadSkillCompressionSettings(): Promise { const data = (await response.json()) as LogSystemSettings; writeYLog({ optType: OptType.view, - optDetail: "B1-CM助手-系统设置-日志系统查看", + optDetail: "CM助手-全量-系统设置-日志系统查看", url: "/api/system-settings/log-system", returnParam: data, }); @@ -487,7 +487,7 @@ export async function updatePrivateSquareSettings( const data = (await response.json()) as PrivateSquareStatus; writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-系统设置-私密广场编辑", + optDetail: "CM助手-全量-系统设置-私密广场编辑", url: "/api/system-settings/private-square", // omit `password` (secret) from the logged request params reqParam: { enabled: body.enabled, password_set: body.password != null }, diff --git a/frontend-web/src/core/tags/api.ts b/frontend-web/src/core/tags/api.ts index 42d7d8d7..bf1da254 100644 --- a/frontend-web/src/core/tags/api.ts +++ b/frontend-web/src/core/tags/api.ts @@ -25,7 +25,7 @@ export async function listTags(tagType?: TagType): Promise { const data = (await res.json()) as TagListResponse; writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-标签-查询", + optDetail: "CM助手-全量-标签-查询", url: `/api/tags${query}`, reqParam: { tagType }, returnParam: data.tags, @@ -43,7 +43,7 @@ export async function createTag(input: TagCreateInput): Promise { const created = (await res.json()) as Tag; writeYLog({ optType: OptType.create, - optDetail: "B1-CM助手-标签-新增", + optDetail: "CM助手-全量-标签-新增", url: "/api/tags", reqParam: input, returnParam: created, @@ -61,7 +61,7 @@ export async function updateTag(id: string, input: TagUpdateInput): Promise const updated = (await res.json()) as Tag; writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-标签-编辑", + optDetail: "CM助手-全量-标签-编辑", url: `/api/tags/${id}`, reqParam: input, returnParam: updated, @@ -76,7 +76,7 @@ export async function deleteTag(id: string): Promise { if (!res.ok) throw await parseDetail(res, "Failed to delete tag"); writeYLog({ optType: OptType.delete, - optDetail: "B1-CM助手-标签-删除", + optDetail: "CM助手-全量-标签-删除", url: `/api/tags/${id}`, reqParam: { id }, }); @@ -93,7 +93,7 @@ export async function getResourceTags( const data = (await res.json()) as TagListResponse; writeYLog({ optType: OptType.view, - optDetail: "B1-CM助手-标签-资源标签查看", + optDetail: "CM助手-全量-标签-资源标签查看", url: `/api/tags/assignments/${targetType}/${targetId}`, reqParam: { targetType, targetId }, returnParam: data.tags, @@ -118,7 +118,7 @@ export async function setResourceTags( const data = (await res.json()) as TagListResponse; writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-标签-资源标签设置", + optDetail: "CM助手-全量-标签-资源标签设置", url: `/api/tags/assignments/${targetType}/${targetId}`, reqParam: { targetType, targetId, tagIds }, returnParam: data.tags, diff --git a/frontend-web/src/core/thread-shares/api.ts b/frontend-web/src/core/thread-shares/api.ts index fa6a7517..fb5706c9 100644 --- a/frontend-web/src/core/thread-shares/api.ts +++ b/frontend-web/src/core/thread-shares/api.ts @@ -69,7 +69,7 @@ export async function createShare( const result = (await response.json()) as ThreadShare; writeYLog({ optType: OptType.create, - optDetail: "B1-CM助手-会话分享-创建分享", + optDetail: "CM助手-全量-会话分享-创建分享", url: baseUrl(), reqParam: { thread_id: threadId, mode }, returnParam: { share_code: result.share_code, mode: result.mode }, @@ -84,7 +84,7 @@ export async function listShares(): Promise { const json = (await response.json()) as { shares: ThreadShare[] }; writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-会话分享-查询分享列表", + optDetail: "CM助手-全量-会话分享-查询分享列表", url: baseUrl(), returnParam: { count: json.shares.length }, }); @@ -98,7 +98,7 @@ export async function revokeShare(shareCode: string): Promise { if (!response.ok) throw await parseError(response, "撤销分享失败"); writeYLog({ optType: OptType.delete, - optDetail: "B1-CM助手-会话分享-撤销分享", + optDetail: "CM助手-全量-会话分享-撤销分享", url, reqParam: { shareCode }, }); @@ -112,7 +112,7 @@ export async function previewShare(shareCode: string): Promise { const result = (await response.json()) as SharePreview; writeYLog({ optType: OptType.view, - optDetail: "B1-CM助手-会话分享-预览分享", + optDetail: "CM助手-全量-会话分享-预览分享", url, reqParam: { shareCode }, }); @@ -127,7 +127,7 @@ export async function importShare(shareCode: string): Promise { const result = (await response.json()) as ImportResult; writeYLog({ optType: OptType.import, - optDetail: "B1-CM助手-会话分享-导入分享", + optDetail: "CM助手-全量-会话分享-导入分享", url, reqParam: { shareCode }, returnParam: result, diff --git a/frontend-web/src/core/threads/hooks.ts b/frontend-web/src/core/threads/hooks.ts index 970bd903..9c694496 100644 --- a/frontend-web/src/core/threads/hooks.ts +++ b/frontend-web/src/core/threads/hooks.ts @@ -425,7 +425,7 @@ export function useThreadStream({ const question = lastHumanFromChatModelInput(data.input); writeYLog({ optType: OptType.other, - optDetail: "B1-CM助手-智能问答", + optDetail: "CM助手-全量-智能问答", url: `/api/threads/${threadIdRef.current ?? ""}/runs/stream`, reqParam: { model: event.name ?? "", question }, returnParam: { data: answer }, diff --git a/frontend-web/src/core/tool-metrics/api.ts b/frontend-web/src/core/tool-metrics/api.ts index 457905d6..f2db88f9 100644 --- a/frontend-web/src/core/tool-metrics/api.ts +++ b/frontend-web/src/core/tool-metrics/api.ts @@ -108,7 +108,7 @@ export async function loadToolMetrics( const result = (await response.json()) as ToolMetricsListResponse; writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-工具指标-查询调用列表", + optDetail: "CM助手-全量-工具指标-查询调用列表", url, reqParam: query, returnParam: { total: result.total, count: result.items.length }, @@ -128,7 +128,7 @@ export async function loadToolMetricsSummary( const result = (await response.json()) as ToolMetricsSummary; writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-工具指标-查询汇总统计", + optDetail: "CM助手-全量-工具指标-查询汇总统计", url, reqParam: filters, returnParam: { total: result.total, error_total: result.error_total }, @@ -147,7 +147,7 @@ export async function downloadToolMetricsExcel( } writeYLog({ optType: OptType.export, - optDetail: "B1-CM助手-工具指标-导出Excel", + optDetail: "CM助手-全量-工具指标-导出Excel", url: requestUrl, reqParam: filters, }); diff --git a/frontend-web/src/core/user-preferences/index.ts b/frontend-web/src/core/user-preferences/index.ts index 7a6a4774..41b6688d 100644 --- a/frontend-web/src/core/user-preferences/index.ts +++ b/frontend-web/src/core/user-preferences/index.ts @@ -40,7 +40,7 @@ async function updateUserPreferences( const result = { hide_admin_prompt_prefix: !!data.hide_admin_prompt_prefix }; writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-用户偏好-编辑", + optDetail: "CM助手-全量-用户偏好-编辑", url: "/api/user-preferences", reqParam: input, returnParam: result, diff --git a/frontend-web/src/core/user-qa/api.ts b/frontend-web/src/core/user-qa/api.ts index 754dbd7f..2c0eff76 100644 --- a/frontend-web/src/core/user-qa/api.ts +++ b/frontend-web/src/core/user-qa/api.ts @@ -45,7 +45,7 @@ export async function listMyQa( const result = await parse(await apiFetch(url), "Failed to load my Q&A"); writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-用户问答-查询我的问答", + optDetail: "CM助手-全量-用户问答-查询我的问答", url, reqParam: params, returnParam: { total: result.total, count: result.items.length }, diff --git a/frontend-web/src/pages/AgentChatPage.tsx b/frontend-web/src/pages/AgentChatPage.tsx index e3cfe6c0..ed950343 100644 --- a/frontend-web/src/pages/AgentChatPage.tsx +++ b/frontend-web/src/pages/AgentChatPage.tsx @@ -165,7 +165,7 @@ export default function AgentChatPage({ const lastHuman = [...msgs].reverse().find((m) => (m as { type?: string }).type === "human"); writeYLog({ optType: OptType.other, - optDetail: "B1-CM助手-专家代理问答", + optDetail: "CM助手-全量-专家代理问答", url: `/api/threads/${threadId ?? ""}/runs/stream`, reqParam: { agent_id, question: lastHuman ? textOfMessage(lastHuman) : "" }, returnParam: { data: lastAi ? textOfMessage(lastAi) : "" }, diff --git a/frontend-web/src/pages/ChatPage.tsx b/frontend-web/src/pages/ChatPage.tsx index 44274959..2123a89c 100644 --- a/frontend-web/src/pages/ChatPage.tsx +++ b/frontend-web/src/pages/ChatPage.tsx @@ -195,7 +195,7 @@ export default function ChatPage() { const lastHuman = [...msgs].reverse().find((m) => (m as { type?: string }).type === "human"); writeYLog({ optType: OptType.other, - optDetail: "B1-CM助手-专家代理问答", + optDetail: "CM助手-全量-专家代理问答", url: `/api/threads/${threadId ?? ""}/runs/stream`, reqParam: { agent_id: selectedAgentId, question: lastHuman ? textOfMessage(lastHuman) : "" }, returnParam: { data: lastAi ? textOfMessage(lastAi) : "" }, diff --git a/frontend-web/src/pages/LoginPage.tsx b/frontend-web/src/pages/LoginPage.tsx index 8aa6a45b..d52b5c7e 100644 --- a/frontend-web/src/pages/LoginPage.tsx +++ b/frontend-web/src/pages/LoginPage.tsx @@ -170,7 +170,7 @@ export default function LoginPage() { void fetchYLogConfig(); writeYLog({ optType: OptType.login, - optDetail: 'B1-CM助手-登录', + optDetail: 'CM助手-全量-登录', url: '/api/v1/auth/login/token', reqParam: { username: loginUserName || auth.user_id }, returnParam: { user_id: auth.user_id }, diff --git a/frontend-web/src/roundtable-planning/api/chains.ts b/frontend-web/src/roundtable-planning/api/chains.ts index ae4c3b33..1d8e4819 100644 --- a/frontend-web/src/roundtable-planning/api/chains.ts +++ b/frontend-web/src/roundtable-planning/api/chains.ts @@ -158,7 +158,7 @@ export async function listChains(scope: ChainScope = "mine"): Promise { const chain = toChain(data); writeYLog({ optType: OptType.view, - optDetail: "B1-CM助手-业务链条-查看", + optDetail: "CM助手-全量-业务链条-查看", url: `${BASE()}/${id}`, reqParam: { id }, returnParam: { id: chain.id, title: chain.title }, @@ -197,7 +197,7 @@ export async function createChain(payload: ChainCreatePayload): Promise { } writeYLog({ optType: OptType.delete, - optDetail: "B1-CM助手-业务链条-删除", + optDetail: "CM助手-全量-业务链条-删除", url: `${BASE()}/${id}`, reqParam: { id }, }); diff --git a/frontend-web/src/roundtable-planning/api/dashboard-sessions.ts b/frontend-web/src/roundtable-planning/api/dashboard-sessions.ts index afbbaf48..1a7df37b 100644 --- a/frontend-web/src/roundtable-planning/api/dashboard-sessions.ts +++ b/frontend-web/src/roundtable-planning/api/dashboard-sessions.ts @@ -48,7 +48,7 @@ export async function getDashboardSessionByTask(taskId: string): Promise { const metas = (data.drafts ?? []).map(toMeta); writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-会商-查询草稿", + optDetail: "CM助手-全量-会商-查询草稿", url: BASE(), returnParam: { count: metas.length }, }); @@ -340,7 +340,7 @@ export async function getDraft(id: string): Promise { const record = toRecord(data); writeYLog({ optType: OptType.view, - optDetail: "B1-CM助手-会商-查看草稿", + optDetail: "CM助手-全量-会商-查看草稿", url: `${BASE()}/${id}`, reqParam: { id }, returnParam: { id: record.id, title: record.title }, @@ -358,7 +358,7 @@ export async function createDraft(payload: DraftCreatePayload): Promise { } writeYLog({ optType: OptType.delete, - optDetail: "B1-CM助手-会商-删除草稿", + optDetail: "CM助手-全量-会商-删除草稿", url: `${BASE()}/${id}`, reqParam: { id }, }); diff --git a/frontend-web/src/roundtable-planning/api/multi-agent.ts b/frontend-web/src/roundtable-planning/api/multi-agent.ts index 0c0d2ed2..30aa9f9e 100644 --- a/frontend-web/src/roundtable-planning/api/multi-agent.ts +++ b/frontend-web/src/roundtable-planning/api/multi-agent.ts @@ -934,7 +934,7 @@ export async function listSessionArtifacts( }; writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-会商产物-查询", + optDetail: "CM助手-全量-会商产物-查询", url: `/api/threads/${threadId}/artifacts`, reqParam: { threadId }, returnParam: { count: result.files.length }, diff --git a/frontend-web/src/roundtable-planning/api/recommend.ts b/frontend-web/src/roundtable-planning/api/recommend.ts index e16ad8dd..f0a334aa 100644 --- a/frontend-web/src/roundtable-planning/api/recommend.ts +++ b/frontend-web/src/roundtable-planning/api/recommend.ts @@ -272,7 +272,7 @@ export async function listRecommendHistory(draftId: string): Promise const job = mapJob(await readJson>(res, "start job")); writeYLog({ optType: OptType.other, - optDetail: "B1-CM助手-会商-运行", + optDetail: "CM助手-全量-会商-运行", url: BASE(), reqParam: { draftId: payload.draftId ?? null, taskId: payload.taskId ?? null, model: payload.model }, returnParam: { id: job.id, status: job.status }, @@ -192,7 +192,7 @@ export async function resumeJob(jobId: string, answer: string, taskId?: string | const job = mapJob(await readJson>(res, "resume job")); writeYLog({ optType: OptType.other, - optDetail: "B1-CM助手-会商-回答澄清续跑", + optDetail: "CM助手-全量-会商-回答澄清续跑", url: `${BASE()}/${jobId}/resume`, reqParam: { jobId, taskId: taskId ?? null }, returnParam: { id: job.id, status: job.status }, @@ -206,7 +206,7 @@ export async function cancelJob(jobId: string, taskId?: string | null): Promise< const job = mapJob(await readJson>(res, "cancel job")); writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-会商-取消", + optDetail: "CM助手-全量-会商-取消", url: `${BASE()}/${jobId}/cancel`, reqParam: { jobId, taskId: taskId ?? null }, returnParam: { id: job.id, status: job.status }, diff --git a/frontend-web/src/roundtable-planning/api/task-drafts.ts b/frontend-web/src/roundtable-planning/api/task-drafts.ts index 12963ffc..2d73a0f1 100644 --- a/frontend-web/src/roundtable-planning/api/task-drafts.ts +++ b/frontend-web/src/roundtable-planning/api/task-drafts.ts @@ -37,7 +37,7 @@ export async function listTaskDraftsByTask(taskId: string): Promise const metas = (data.drafts ?? []).map(toMeta); writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-会商任务-查询草稿", + optDetail: "CM助手-全量-会商任务-查询草稿", url: `${BASE()}/by-task/${taskId}`, reqParam: { taskId }, returnParam: { count: metas.length }, @@ -53,7 +53,7 @@ export async function getLatestTaskDraftByTask(taskId: string): Promise { const record = toRecord(data); writeYLog({ optType: OptType.view, - optDetail: "B1-CM助手-会商任务-查看草稿", + optDetail: "CM助手-全量-会商任务-查看草稿", url: `${BASE()}/${id}`, reqParam: { id }, returnParam: { id: record.id, title: record.title }, @@ -88,7 +88,7 @@ export async function createTaskDraft(payload: DraftCreatePayload): Promise { } writeYLog({ optType: OptType.delete, - optDetail: "B1-CM助手-会商任务-删除草稿", + optDetail: "CM助手-全量-会商任务-删除草稿", url: `${BASE()}/${id}`, reqParam: { id }, }); diff --git a/frontend-web/src/strategy-components/api/business-mapping.ts b/frontend-web/src/strategy-components/api/business-mapping.ts index 9f90420e..8b11f05f 100644 --- a/frontend-web/src/strategy-components/api/business-mapping.ts +++ b/frontend-web/src/strategy-components/api/business-mapping.ts @@ -67,7 +67,7 @@ export async function listBusinessMappings(): Promise { const mappings = (data.mappings ?? []).map(toMapping); writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-业务映射-列表", + optDetail: "CM助手-全量-业务映射-列表", url: "/api/business-mapping", returnParam: mappings, }); @@ -94,7 +94,7 @@ export async function updateBusinessMapping( const mapping = toMapping(data); writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-业务映射-修改", + optDetail: "CM助手-全量-业务映射-修改", url: `${BASE()}/${encodeURIComponent(businessCode)}`, reqParam: { businessCode, patch }, returnParam: mapping, diff --git a/frontend-web/src/strategy-components/api/light-apps.ts b/frontend-web/src/strategy-components/api/light-apps.ts index cce7f4bc..77feac85 100644 --- a/frontend-web/src/strategy-components/api/light-apps.ts +++ b/frontend-web/src/strategy-components/api/light-apps.ts @@ -160,7 +160,7 @@ export async function listLightApps(params: ListLightAppsParams = {}): Promise { const app = toApp(await readJson(res, "get light app")); writeYLog({ optType: OptType.view, - optDetail: "B1-CM助手-轻应用-查看", + optDetail: "CM助手-全量-轻应用-查看", url: `${BASE()}/${encodeURIComponent(appId)}`, reqParam: { appId }, returnParam: app, @@ -190,7 +190,7 @@ export async function createLightApp(input: LightAppInput): Promise { const app = toApp(await readJson(res, "create light app")); writeYLog({ optType: OptType.create, - optDetail: "B1-CM助手-轻应用-注册", + optDetail: "CM助手-全量-轻应用-注册", url: BASE(), reqParam: input, returnParam: app, @@ -210,7 +210,7 @@ export async function updateLightApp( const app = toApp(await readJson(res, "update light app")); writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-轻应用-修改", + optDetail: "CM助手-全量-轻应用-修改", url: `${BASE()}/${encodeURIComponent(appId)}`, reqParam: { appId, patch }, returnParam: app, @@ -223,7 +223,7 @@ export async function deleteLightApp(appId: string): Promise { await readJson<{ success: boolean }>(res, "delete light app"); writeYLog({ optType: OptType.delete, - optDetail: "B1-CM助手-轻应用-删除", + optDetail: "CM助手-全量-轻应用-删除", url: `${BASE()}/${encodeURIComponent(appId)}`, reqParam: { appId }, }); diff --git a/frontend-web/src/strategy-components/api/menu-overrides.ts b/frontend-web/src/strategy-components/api/menu-overrides.ts index c904aec1..59db120b 100644 --- a/frontend-web/src/strategy-components/api/menu-overrides.ts +++ b/frontend-web/src/strategy-components/api/menu-overrides.ts @@ -71,7 +71,7 @@ export async function replaceMenuOverrides(overrides: MenuOverride[]): Promise { const words = (data.words ?? []).map(toWord); writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-敏感词管理-列表", + optDetail: "CM助手-全量-敏感词管理-列表", url: "/api/sensitive-words", returnParam: words, }); @@ -92,7 +92,7 @@ export async function replaceSensitiveWords(words: SensitiveWord[]): Promise(res, "扫描")); writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-技能地址管理-扫描", + optDetail: "CM助手-全量-技能地址管理-扫描", url: `${BASE()}/scan${qs ? `?${qs}` : ""}`, reqParam: { kinds, skill }, returnParam: result, @@ -227,7 +227,7 @@ export async function scanAddressesStream( if (!result) throw new Error("扫描未返回结果"); writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-技能地址管理-扫描", + optDetail: "CM助手-全量-技能地址管理-扫描", url: `${BASE()}/scan/stream${qs ? `?${qs}` : ""}`, reqParam: { kinds: opts.kinds, skill: opts.skill }, returnParam: result, @@ -245,7 +245,7 @@ export async function previewReplacements(replacements: Replacement[]): Promise< const result = toPreviewResult(await readJson(res, "预览")); writeYLog({ optType: OptType.view, - optDetail: "B1-CM助手-技能地址管理-预览", + optDetail: "CM助手-全量-技能地址管理-预览", url: `${BASE()}/preview`, reqParam: { replacements }, returnParam: result, @@ -277,7 +277,7 @@ export async function applyReplacementsStream( if (!result) throw new Error("应用未返回结果"); writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-技能地址管理-应用替换", + optDetail: "CM助手-全量-技能地址管理-应用替换", url: `${BASE()}/apply/stream`, reqParam: body, returnParam: result, @@ -297,7 +297,7 @@ export async function listBackups(): Promise { })); writeYLog({ optType: OptType.search, - optDetail: "B1-CM助手-技能地址管理-修改记录", + optDetail: "CM助手-全量-技能地址管理-修改记录", url: `${BASE()}/backups`, returnParam: backups, }); @@ -310,7 +310,7 @@ export async function rollbackBackup(backupId: string): Promise<{ restored: numb const result = { restored: (data.restored_files ?? []).length }; writeYLog({ optType: OptType.edit, - optDetail: "B1-CM助手-技能地址管理-回退", + optDetail: "CM助手-全量-技能地址管理-回退", url: `${BASE()}/rollback/${encodeURIComponent(backupId)}`, reqParam: { backupId }, returnParam: result, diff --git a/frontend-web/src/strategy-components/api/task-buttons.ts b/frontend-web/src/strategy-components/api/task-buttons.ts index 92589a6c..b621a2c8 100644 --- a/frontend-web/src/strategy-components/api/task-buttons.ts +++ b/frontend-web/src/strategy-components/api/task-buttons.ts @@ -95,7 +95,7 @@ export async function replaceTaskButtons(buttons: TaskButton[]): Promise str: - """Build a stable node name as md5(title) + timestamp + .md.""" +def _build_node_name(title: str) -> str: + """Build a stable node name = md5(title) + .md. + + nodeName 只由标题决定(不含时间戳),所以同一篇 md(同标题)每次入库都得到 + 完全相同的 nodeName —— 入库接口据此把重复上传当作同一条记录,而不是每次新增。 + """ title_md5 = hashlib.md5(title.encode("utf-8")).hexdigest() - return f"{title_md5}-{timestamp}.md" + return f"{title_md5}.md" def _resolve_ingest_url() -> str: @@ -132,10 +138,10 @@ async def publish_to_knowledge_base(request: KnowledgeIngestPublishRequest) -> K raise HTTPException(status_code=400, detail=f"智能体 '{request.agent_id}' 未配置入库模板名(template_name),无法发布") now = datetime.now() - # nodeName 是入库记录的唯一标识:md 标题 + 时间戳。两次尝试必须共用同一个 - # nodeName,避免第一次实际已入库时第二次产生重复记录。 - timestamp = now.strftime("%Y%m%d%H%M%S") - node_name = _build_node_name(title, timestamp) + # nodeName 是入库记录的唯一标识:只取 md5(标题),不含时间戳。同一篇 md(同标题) + # 每次入库得到一致的 nodeName —— 既保证两次尝试(名称/标题字段)共用同一个,也 + # 保证重复上传同一篇 md 不会产生多条记录。 + node_name = _build_node_name(title) batch_number = f"md{now.strftime('%Y%m%d')}" ingest_url = _resolve_ingest_url()