feat: AIChat 全链路调试日志 + 错误详情展示
load/createSession/loadSession/send 都加了 print 日志: - scope 参数 - 请求成功/失败状态 - 具体错误信息 sessionError 现在显示具体错误原因而非通用"创建对话失败" Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
9d0f426118
commit
99dc2807be
@ -353,7 +353,15 @@ class RagChatService {
|
|||||||
title: nil,
|
title: nil,
|
||||||
forceCreate: forceCreate ? true : nil
|
forceCreate: forceCreate ? true : nil
|
||||||
)
|
)
|
||||||
return try await client.request("/rag-chat/sessions", method: "POST", body: body)
|
print("[RagChat] POST /rag-chat/sessions — scopeType=\(body.scopeType), scopeId=\(body.scopeId ?? "nil"), parentKB=\(body.parentKnowledgeBaseId ?? "nil"), forceCreate=\(forceCreate)")
|
||||||
|
do {
|
||||||
|
let session = try await client.request("/rag-chat/sessions", method: "POST", body: body) as ChatSession
|
||||||
|
print("[RagChat] createSession OK — id=\(session.id), scopeType=\(session.scopeType ?? "nil")")
|
||||||
|
return session
|
||||||
|
} catch {
|
||||||
|
print("[RagChat] createSession FAILED: \(error)")
|
||||||
|
throw error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func listSessions(scopeType: String? = nil, scopeId: String? = nil, parentKnowledgeBaseId: String? = nil) async throws -> [ChatSession] {
|
func listSessions(scopeType: String? = nil, scopeId: String? = nil, parentKnowledgeBaseId: String? = nil) async throws -> [ChatSession] {
|
||||||
|
|||||||
@ -74,12 +74,18 @@ final class AIChatViewModel: ObservableObject {
|
|||||||
createdFrom: "global_ai_entry"
|
createdFrom: "global_ai_entry"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
print("[AIChat] load() entry — scopeType=\(ctx.scopeType.rawValue), scopeId=\(ctx.scopeId ?? "nil"), parentKB=\(ctx.parentKnowledgeBaseId ?? "nil")")
|
||||||
|
|
||||||
do {
|
do {
|
||||||
// open-or-create: backend handles find-or-create logic
|
|
||||||
let session = try await RagChatService.shared.createSession(ctx: ctx)
|
let session = try await RagChatService.shared.createSession(ctx: ctx)
|
||||||
|
print("[AIChat] open-or-create OK — sessionId=\(session.id), isNew=\(session.createdAt == session.updatedAt)")
|
||||||
await loadSession(session.id)
|
await loadSession(session.id)
|
||||||
} catch {
|
} catch {
|
||||||
sessionError = "创建对话失败"
|
print("[AIChat] open-or-create FAILED: \(error)")
|
||||||
|
if let apiErr = error as? APIError {
|
||||||
|
print("[AIChat] APIError detail: \(apiErr)")
|
||||||
|
}
|
||||||
|
sessionError = "创建对话失败: \(error.localizedDescription)"
|
||||||
isCreatingSession = false
|
isCreatingSession = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,7 +95,6 @@ final class AIChatViewModel: ObservableObject {
|
|||||||
messages = []
|
messages = []
|
||||||
isCreatingSession = true
|
isCreatingSession = true
|
||||||
|
|
||||||
// Use entry context if available, otherwise default to global
|
|
||||||
let ctx = entryContext ?? ChatEntryContext(
|
let ctx = entryContext ?? ChatEntryContext(
|
||||||
scopeType: .global,
|
scopeType: .global,
|
||||||
scopeId: nil,
|
scopeId: nil,
|
||||||
@ -98,14 +103,18 @@ final class AIChatViewModel: ObservableObject {
|
|||||||
createdFrom: "global_ai_entry"
|
createdFrom: "global_ai_entry"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
print("[AIChat] createNewSession() — scopeType=\(ctx.scopeType.rawValue), scopeId=\(ctx.scopeId ?? "nil")")
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let session = try await RagChatService.shared.createSession(ctx: ctx, forceCreate: true)
|
let session = try await RagChatService.shared.createSession(ctx: ctx, forceCreate: true)
|
||||||
|
print("[AIChat] forceCreate OK — sessionId=\(session.id)")
|
||||||
sessionId = session.id
|
sessionId = session.id
|
||||||
let scopeLabel = ctx.scopeType != .global ? "「\(ctx.scopeName)」的" : ""
|
let scopeLabel = ctx.scopeType != .global ? "「\(ctx.scopeName)」的" : ""
|
||||||
messages = [AIMessage(role: .ai, content: "你好!我是你的 AI 学习助手,基于\(scopeLabel)内容回答问题。")]
|
messages = [AIMessage(role: .ai, content: "你好!我是你的 AI 学习助手,基于\(scopeLabel)内容回答问题。")]
|
||||||
isCreatingSession = false
|
isCreatingSession = false
|
||||||
} catch {
|
} catch {
|
||||||
sessionError = "创建对话失败"
|
print("[AIChat] forceCreate FAILED: \(error)")
|
||||||
|
sessionError = "创建对话失败: \(error.localizedDescription)"
|
||||||
isCreatingSession = false
|
isCreatingSession = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,6 +122,7 @@ final class AIChatViewModel: ObservableObject {
|
|||||||
func send() {
|
func send() {
|
||||||
guard canSend, let sid = sessionId else { return }
|
guard canSend, let sid = sessionId else { return }
|
||||||
let text = inputText.trimmingCharacters(in: .whitespacesAndNewlines)
|
let text = inputText.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
|
print("[AIChat] send — sessionId=\(sid), text=\(text.prefix(50))")
|
||||||
messages.append(AIMessage(role: .user, content: text))
|
messages.append(AIMessage(role: .user, content: text))
|
||||||
inputText = ""
|
inputText = ""
|
||||||
isSending = true
|
isSending = true
|
||||||
@ -139,10 +149,12 @@ final class AIChatViewModel: ObservableObject {
|
|||||||
messages[idx] = AIMessage(role: .ai, content: reply, thinkingContent: thinking, isStreaming: true, id: placeholderId)
|
messages[idx] = AIMessage(role: .ai, content: reply, thinkingContent: thinking, isStreaming: true, id: placeholderId)
|
||||||
}
|
}
|
||||||
case "error":
|
case "error":
|
||||||
|
print("[AIChat] stream error: \(chunk.content ?? "unknown")")
|
||||||
if let idx = messages.firstIndex(where: { $0.id == placeholderId }) {
|
if let idx = messages.firstIndex(where: { $0.id == placeholderId }) {
|
||||||
messages[idx] = AIMessage(role: .ai, content: "请求失败: \(chunk.content ?? "未知错误")")
|
messages[idx] = AIMessage(role: .ai, content: "请求失败: \(chunk.content ?? "未知错误")")
|
||||||
}
|
}
|
||||||
case "done":
|
case "done":
|
||||||
|
print("[AIChat] stream done — reply=\(reply.count)chars, thinking=\(thinking.count)chars")
|
||||||
if let idx = messages.firstIndex(where: { $0.id == placeholderId }) {
|
if let idx = messages.firstIndex(where: { $0.id == placeholderId }) {
|
||||||
messages[idx] = AIMessage(role: .ai, content: reply, thinkingContent: thinking.isEmpty ? nil : thinking)
|
messages[idx] = AIMessage(role: .ai, content: reply, thinkingContent: thinking.isEmpty ? nil : thinking)
|
||||||
}
|
}
|
||||||
@ -150,6 +162,7 @@ final class AIChatViewModel: ObservableObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
|
print("[AIChat] stream FAILED: \(error)")
|
||||||
if let idx = messages.firstIndex(where: { $0.id == placeholderId }) {
|
if let idx = messages.firstIndex(where: { $0.id == placeholderId }) {
|
||||||
messages[idx] = AIMessage(role: .ai, content: "发送失败: \(error.localizedDescription)")
|
messages[idx] = AIMessage(role: .ai, content: "发送失败: \(error.localizedDescription)")
|
||||||
}
|
}
|
||||||
@ -164,7 +177,9 @@ final class AIChatViewModel: ObservableObject {
|
|||||||
sessionId = id
|
sessionId = id
|
||||||
isCreatingSession = true
|
isCreatingSession = true
|
||||||
do {
|
do {
|
||||||
|
print("[AIChat] loadSession — id=\(id)")
|
||||||
let msgs: [ChatMessage] = try await RagChatService.shared.getMessages(sessionId: id)
|
let msgs: [ChatMessage] = try await RagChatService.shared.getMessages(sessionId: id)
|
||||||
|
print("[AIChat] loadSession OK — \(msgs.count) messages")
|
||||||
|
|
||||||
// Update entryContext from the first message's scope snapshot (if available)
|
// Update entryContext from the first message's scope snapshot (if available)
|
||||||
if let snapshot = msgs.first?.scopeSnapshot,
|
if let snapshot = msgs.first?.scopeSnapshot,
|
||||||
@ -191,7 +206,10 @@ final class AIChatViewModel: ObservableObject {
|
|||||||
AIMessage(role: m.role == "user" ? .user : .ai, content: m.content, citations: m.citations)
|
AIMessage(role: m.role == "user" ? .user : .ai, content: m.content, citations: m.citations)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch { sessionError = "加载对话失败" }
|
} catch {
|
||||||
|
print("[AIChat] loadSession FAILED: \(error)")
|
||||||
|
sessionError = "加载对话失败: \(error.localizedDescription)"
|
||||||
|
}
|
||||||
isCreatingSession = false
|
isCreatingSession = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user