refactor: unify kubernetes_ table prefix, merge CI/CD models, LLM session support

- Rename container_clusters → kubernetes_clusters, container_topology_layouts → kubernetes_topology_layouts
- LLM: add session_id to chat history for multi-turn conversation support
- CI/CD: add pipeline_id, deploy_type, artifact_url, k8s_cluster_id to AppRelease
- Cleanup: remove deprecated playbook handler, simplify automation models
- Database: optimize auto-migrate model list
- Frontend: AIOps assistant improvements, api.ts updates
This commit is contained in:
attacker committed 2026-06-19 15:01:54 +00:00
1 parent 9365c1e9db
commit 732974d152
14 files changed
+121 -474

No files matched your search

@@ -157,6 +157,8 @@ export function AIOpsAssistant() {
const [config, setConfig] = useState<LLMConfigData>(defaultConfig);
const [configReady, setConfigReady] = useState(false); // 已配置且启用
const [contextLoading, setContextLoading] = useState<string | null>(null); // 快捷操作拉取平台数据中
// 会话 ID:前端生成 UUID,用于隔离多轮对话 // Logan.Li
const [sessionId, setSessionId] = useState(() => crypto.randomUUID());
const messagesEndRef = useRef<HTMLDivElement>(null);
// 滚动到底部 // Logan.Li
@@ -174,10 +176,10 @@ export function AIOpsAssistant() {
}
};
// 加载历史对话(按用户隔离,刷新后仍可见) // Logan.Li
// 加载历史对话(按 session 隔离) // Logan.Li
const loadHistory = async () => {
try {
const res = await aiApi.getHistory();
const res = await aiApi.getHistory(sessionId);
const items: ChatHistoryItem[] = (res as any)?.list || [];
setMessages(
items.map((m) => ({
@@ -275,7 +277,7 @@ export function AIOpsAssistant() {
m.id === assistantId ? { ...m, content: m.content + delta } : m,
),
);
}, controller.signal);
}, controller.signal, sessionId);
} catch (e) {
// 用户主动中止:保留已生成的部分内容,不当作错误 // Logan.Li
if (controller.signal.aborted) {
@@ -340,13 +342,15 @@ export function AIOpsAssistant() {
await sendMessage(fullPrompt);
};
// 新对话(清空本地 + 后端持久化历史) // Logan.Li
// 新对话(生成新 session_id,清空本地 + 后端持久化历史) // Logan.Li
const handleNewChat = async () => {
try {
await aiApi.clearHistory();
} catch {
// 清除失败不阻塞本地清空
}
const newSid = crypto.randomUUID();
setSessionId(newSid);
setMessages([]);
setInput('');
toast.success('已开始新对话');
+11 -6
View File
@@ -892,6 +892,7 @@ export interface ChatResult {
export interface ChatHistoryItem {
id: number;
user_id: number;
session_id: string;
role: 'user' | 'assistant';
content: string;
model?: string;
@@ -905,15 +906,16 @@ export const aiApi = {
saveConfig: (data: LLMConfigData) => http.put<LLMConfigData>('/aiops/llm-config', data),
// 测试 LLM 连接(发送 ping)
testConnection: () => http.post('/aiops/llm-config/test'),
// AI 对话(messages 含历史 + 当前用户消息)
chat: (messages: { role: 'user' | 'assistant'; content: string }[]) =>
http.post<ChatResult>('/aiops/chat', { messages }),
// AI 对话(messages 含历史 + 当前用户消息,session_id 区分多轮对话)
chat: (messages: { role: 'user' | 'assistant'; content: string }[], sessionId?: string) =>
http.post<ChatResult>('/aiops/chat', { messages, session_id: sessionId || '' }),
// AI 流式对话(SSE)。逐块回调 onChunk,返回完整内容。错误抛出 Error。
// 使用裸 fetch 绕过 http.ts(后者会 await json() 一次性消费) // Logan.Li
chatStream: async (
messages: { role: 'user' | 'assistant'; content: string }[],
onChunk: (delta: string) => void,
signal?: AbortSignal,
sessionId?: string,
): Promise<string> => {
const token = useUserStore.getState().token;
const res = await fetch('/api/v1/aiops/chat/stream', {
@@ -922,7 +924,7 @@ export const aiApi = {
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}),
},
body: JSON.stringify({ messages }),
body: JSON.stringify({ messages, session_id: sessionId || '' }),
signal,
});
if (res.status === 401) {
@@ -980,8 +982,11 @@ export const aiApi = {
}
return fullContent;
},
// 获取当前用户对话历史(按时间正序,最近 100 条)
getHistory: () => http.get<{ list: ChatHistoryItem[]; total: number }>('/aiops/chat-history'),
// 获取当前用户对话历史(按 session_id 过滤,默认最新 session)
getHistory: (sessionId?: string) => {
const params = sessionId ? `?session_id=${encodeURIComponent(sessionId)}` : '';
return http.get<{ list: ChatHistoryItem[]; total: number }>(`/aiops/chat-history${params}`);
},
// 清空当前用户对话历史
clearHistory: () => http.delete('/aiops/chat-history'),
};