feat(y-log): 操作日志上报(前端直连 + 后端公开只读下发地址)
- 后端新增 y_log 公开只读配置:YLogConfig + AppConfig.y_log + GET /api/public/config/y-log,地址写在 config.yaml(mtime 热重载) - 前端核心 src/core/log/:writeYLog(双门控/异步即发即忘/永不抛错/ 去ip-host/对象序列化裁剪/optResult恒0)+ 配置加载 + token1 隔离存取 - 登录(token)持久化 token1 并报登录、登出先报后清;启动预热配置 - 各 API client 成功路径埋点:敏感词/菜单/按钮/技能地址/轻应用、 会商草稿+任务草稿+后台任务、智能体/定时任务/知识库、Word导出, 以及问答完成钩子(ChatPage/AgentChatPage onFinish) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
dd942cdd60
commit
d2be3b206d
26 files changed
+808
-40
No files matched your search
@@ -30,6 +30,7 @@ import { useNotification } from "@/core/notification/hooks";
|
||||
import { saveLastAgentId, useThreadSettings } from "@/core/settings";
|
||||
import { stopThreadRun, useThreadStream } from "@/core/threads/hooks";
|
||||
import { textOfMessage } from "@/core/threads/utils";
|
||||
import { OptType, writeYLog } from "@/core/log/y-log";
|
||||
import { env } from "@/env";
|
||||
import { readTaskContext, taskThreadMetadata } from "@/core/auth/task-purpose";
|
||||
import { TaskPurposePanel } from "@/strategy-components/components/task-components/TaskPurposePanel";
|
||||
@@ -157,6 +158,21 @@ export default function AgentChatPage({
|
||||
);
|
||||
},
|
||||
onFinish: (state) => {
|
||||
// 操作日志(Y-Log):专家代理问答完成(成功)后,用最终汇总文本上报一条。
|
||||
try {
|
||||
const msgs = state.messages ?? [];
|
||||
const lastAi = [...msgs].reverse().find((m) => (m as { type?: string }).type === "ai");
|
||||
const lastHuman = [...msgs].reverse().find((m) => (m as { type?: string }).type === "human");
|
||||
writeYLog({
|
||||
optType: OptType.other,
|
||||
optDetail: "B1-CM助手-专家代理问答",
|
||||
url: `/api/threads/${threadId ?? ""}/runs/stream`,
|
||||
reqParam: { agent_id, question: lastHuman ? textOfMessage(lastHuman) : "" },
|
||||
returnParam: { data: lastAi ? textOfMessage(lastAi) : "" },
|
||||
});
|
||||
} catch {
|
||||
/* 上报绝不影响问答 */
|
||||
}
|
||||
if (document.hidden || !document.hasFocus()) {
|
||||
let body = "Conversation finished";
|
||||
const lastMessage = state.messages[state.messages.length - 1];
|
||||
|
||||
@@ -49,6 +49,7 @@ import { useThreadStream } from "@/core/threads/hooks";
|
||||
import { useLayoutMode } from "@/core/system-settings/hooks";
|
||||
import { useRouteBase } from "@/core/route-base";
|
||||
import { textOfMessage } from "@/core/threads/utils";
|
||||
import { OptType, writeYLog } from "@/core/log/y-log";
|
||||
import { env } from "@/env";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
@@ -183,6 +184,21 @@ export default function ChatPage() {
|
||||
);
|
||||
},
|
||||
onFinish: (state) => {
|
||||
// 操作日志(Y-Log):问答完成(成功)后,用最终汇总文本上报一条。
|
||||
try {
|
||||
const msgs = state.messages ?? [];
|
||||
const lastAi = [...msgs].reverse().find((m) => (m as { type?: string }).type === "ai");
|
||||
const lastHuman = [...msgs].reverse().find((m) => (m as { type?: string }).type === "human");
|
||||
writeYLog({
|
||||
optType: OptType.other,
|
||||
optDetail: "B1-CM助手-专家代理问答",
|
||||
url: `/api/threads/${threadId ?? ""}/runs/stream`,
|
||||
reqParam: { agent_id: selectedAgentId, question: lastHuman ? textOfMessage(lastHuman) : "" },
|
||||
returnParam: { data: lastAi ? textOfMessage(lastAi) : "" },
|
||||
});
|
||||
} catch {
|
||||
/* 上报绝不影响问答 */
|
||||
}
|
||||
if (document.hidden || !document.hasFocus()) {
|
||||
let body = "Conversation finished";
|
||||
const lastMessage = state.messages.at(-1);
|
||||
|
||||
@@ -31,6 +31,9 @@ import {
|
||||
isSidebarEnabledFromSearch,
|
||||
persistSidebarEnabled,
|
||||
} from '@/core/page-layout/sidebar-enabled';
|
||||
import { fetchYLogConfig } from '@/core/log/y-log-config';
|
||||
import { persistYLogToken } from '@/core/log/y-log-token';
|
||||
import { OptType, writeYLog } from '@/core/log/y-log';
|
||||
|
||||
const DEFAULT_USERNAME = 'guest';
|
||||
const IFRAME_LOGIN_SOURCE = 'iframe';
|
||||
@@ -160,6 +163,19 @@ export default function LoginPage() {
|
||||
return;
|
||||
}
|
||||
setStoredAuth(auth);
|
||||
// 操作日志(Y-Log):只有 token 登录(存在 token1=authToken)才上报。
|
||||
// 持久化 token1(走 authStorage,嵌入态自动隔离)+ 预热上报配置 + 上报登录。
|
||||
if (authToken) {
|
||||
persistYLogToken(authToken);
|
||||
void fetchYLogConfig();
|
||||
writeYLog({
|
||||
optType: OptType.login,
|
||||
optDetail: 'B1-CM助手-登录',
|
||||
url: '/api/v1/auth/login/token',
|
||||
reqParam: { username: loginUserName || auth.user_id },
|
||||
returnParam: { user_id: auth.user_id },
|
||||
});
|
||||
}
|
||||
// 标准登录把用户名写入 userInfo,供顶栏用户区显示(已有则不覆盖)
|
||||
setStoredUserName(loginUserName);
|
||||
// 内网透传的 access_token 合并进 userInfo(在 loginByYUserId 覆盖之后),
|
||||
|
||||
Reference in new issue
Block a user