聊天报错

This commit is contained in:
2025-09-21 19:41:49 +08:00
parent 35aa92d78a
commit 274f02b867
7 changed files with 243 additions and 221 deletions
@@ -27,6 +27,8 @@ export class ApiConfig {
private static _instance: ApiConfig; private static _instance: ApiConfig;
private config: AIConfig; private config: AIConfig;
private baseUrl: "https://generativelanguage.googleapis.com";
private constructor() { private constructor() {
this.initConfig(); this.initConfig();
} }
@@ -104,6 +106,9 @@ export class ApiConfig {
public getTimeout() { public getTimeout() {
return this.config.timeout; return this.config.timeout;
} }
public getBaseUrl() {
return this.baseUrl;
}
/** /**
* 验证配置是否有效 * 验证配置是否有效
+21 -4
View File
@@ -1,6 +1,11 @@
// 首先加载 polyfills 以确保兼容性 // 首先加载 polyfills 以确保兼容性
import "../utils/polyfills"; import "../utils/polyfills";
import { GoogleGenAI, HarmBlockThreshold, HarmCategory } from "@google/genai"; import {
Chat,
GoogleGenAI,
HarmBlockThreshold,
HarmCategory,
} from "@google/genai";
import { RoleConfigLoader } from "./RoleConfigLoader"; import { RoleConfigLoader } from "./RoleConfigLoader";
import { ChatHistoryManager } from "../manager/ChatHistoryManager"; import { ChatHistoryManager } from "../manager/ChatHistoryManager";
import { ApiConfig } from "./ApiConfigLoader"; import { ApiConfig } from "./ApiConfigLoader";
@@ -57,8 +62,16 @@ export class ChatAIService {
try { try {
this.ai = new GoogleGenAI({ this.ai = new GoogleGenAI({
apiKey: config.apiKey, apiKey: config.apiKey,
httpOptions: { timeout: ApiConfig.Instance.getTimeout() },
httpOptions: {
timeout: ApiConfig.Instance.getTimeout(),
baseUrl: ApiConfig.Instance.getBaseUrl(),
},
}); });
console.log("-------AI 启动成功-------");
console.log(this.ai);
this.ai.operations;
} catch (error) { } catch (error) {
TipsPanel.show(LanguageUtils.getText("chat_error_code_2001")); TipsPanel.show(LanguageUtils.getText("chat_error_code_2001"));
ErrorHandler.Instance.handleError( ErrorHandler.Instance.handleError(
@@ -88,7 +101,7 @@ export class ChatAIService {
* 创建或获取指定角色的聊天实例 * 创建或获取指定角色的聊天实例
* @param roleId 角色ID * @param roleId 角色ID
*/ */
async createOrGetChat(roleId: number): Promise<any> { async createOrGetChat(roleId: number): Promise<Chat> {
if (!this.chatInstances.has(roleId)) { if (!this.chatInstances.has(roleId)) {
const systemInstruction = RoleConfigLoader.getRoleInstruction(roleId); const systemInstruction = RoleConfigLoader.getRoleInstruction(roleId);
const config = ApiConfig.Instance.getAIConfig(); const config = ApiConfig.Instance.getAIConfig();
@@ -97,7 +110,7 @@ export class ChatAIService {
let savedHistory = await ChatHistoryManager.Instance.loadChatHistory( let savedHistory = await ChatHistoryManager.Instance.loadChatHistory(
roleId roleId
); );
let chat; let chat: Chat;
if (savedHistory && savedHistory.length > 0) { if (savedHistory && savedHistory.length > 0) {
chat = this.ai.chats.create({ chat = this.ai.chats.create({
model: config.model, model: config.model,
@@ -130,6 +143,7 @@ export class ChatAIService {
}, },
history: savedHistory, history: savedHistory,
}); });
console.log(chat);
console.log( console.log(
`Loaded ${savedHistory.length} history messages for role ${roleId}` `Loaded ${savedHistory.length} history messages for role ${roleId}`
); );
@@ -164,6 +178,8 @@ export class ChatAIService {
], ],
}, },
}); });
console.log(chat);
console.log(`Created new chat instance for role ${roleId}`); console.log(`Created new chat instance for role ${roleId}`);
} }
@@ -226,6 +242,7 @@ export class ChatAIService {
try { try {
const chat = await this.createOrGetChat(roleId); const chat = await this.createOrGetChat(roleId);
const response = await chat.sendMessage({ const response = await chat.sendMessage({
message: message.trim(), message: message.trim(),
}); });
@@ -124,6 +124,7 @@ export class GlobalData extends BaseData {
/** 超时时间(微秒) */ /** 超时时间(微秒) */
public getTimeout(): number { public getTimeout(): number {
//return 600000;
return this._timeout; return this._timeout;
} }
+211 -212
View File
@@ -7,237 +7,236 @@
* @version 1.0.0 * @version 1.0.0
*/ */
import LanguageUtils from "../../Main/Common/LanguageUtils";
import { TipsPanel } from "../ui/panels/TipsPanel";
export enum ErrorType { export enum ErrorType {
/** API调用错误 */ /** API调用错误 */
API_ERROR = "API_ERROR", API_ERROR = "API_ERROR",
/** 网络连接错误 */ /** 网络连接错误 */
NETWORK_ERROR = "NETWORK_ERROR", NETWORK_ERROR = "NETWORK_ERROR",
/** 配置错误 */ /** 配置错误 */
CONFIG_ERROR = "CONFIG_ERROR", CONFIG_ERROR = "CONFIG_ERROR",
/** 数据验证错误 */ /** 数据验证错误 */
VALIDATION_ERROR = "VALIDATION_ERROR", VALIDATION_ERROR = "VALIDATION_ERROR",
/** 存储错误 */ /** 存储错误 */
STORAGE_ERROR = "STORAGE_ERROR", STORAGE_ERROR = "STORAGE_ERROR",
/** 未知错误 */ /** 未知错误 */
UNKNOWN_ERROR = "UNKNOWN_ERROR" UNKNOWN_ERROR = "UNKNOWN_ERROR",
} }
export interface ErrorInfo { export interface ErrorInfo {
type: ErrorType; type: ErrorType;
message: string; message: string;
code?: string | number; code?: string | number;
details?: any; details?: any;
timestamp: number; timestamp: number;
stack?: string; stack?: string;
} }
/** /**
* 错误处理管理器 * 错误处理管理器
*/ */
export class ErrorHandler { export class ErrorHandler {
private static _instance: ErrorHandler; private static _instance: ErrorHandler;
private errorLog: ErrorInfo[] = []; private errorLog: ErrorInfo[] = [];
private readonly MAX_LOG_SIZE = 100; private readonly MAX_LOG_SIZE = 100;
/** /**
* 获取ErrorHandler的单例实例 * 获取ErrorHandler的单例实例
*/ */
public static get Instance(): ErrorHandler { public static get Instance(): ErrorHandler {
if (!this._instance) { if (!this._instance) {
this._instance = new ErrorHandler(); this._instance = new ErrorHandler();
} }
return this._instance; return this._instance;
}
private constructor() {}
/**
* 处理错误
*
* @param {Error | string} error - 错误对象或错误消息
* @param {ErrorType} type - 错误类型
* @param {any} details - 错误详情
* @param {boolean} showToUser - 是否向用户显示错误
*/
public handleError(
error: Error | string,
type: ErrorType = ErrorType.UNKNOWN_ERROR,
details?: any,
showToUser: boolean = false
): void {
const errorInfo: ErrorInfo = {
type,
message: typeof error === "string" ? error : error.message,
details,
timestamp: Date.now(),
stack: error instanceof Error ? error.stack : undefined,
};
// 记录到日志
this.logError(errorInfo);
// 输出到控制台
this.logToConsole(errorInfo);
// 如果需要,向用户显示友好的错误信息
if (showToUser) {
this.showUserFriendlyError(errorInfo);
}
}
/**
* 处理API错误
*
* @param {any} error - API错误
* @param {string} apiName - API名称
* @param {any} requestData - 请求数据
*/
public handleApiError(error: any, apiName: string, requestData?: any): void {
const errorMessage = `API调用失败: ${apiName}`;
const details = {
apiName,
requestData,
responseError: error,
};
if (error.status == "FAILED_PRECONDITION") {
//当前用户区域不支持聊天功能
TipsPanel.show(LanguageUtils.getText("chat_error_code_2003"));
} else if (error.message.includes("Fetch is aborted")) {
TipsPanel.show(LanguageUtils.getText("chat_error_code_2004"));
} else {
this.handleError(
new Error(errorMessage),
ErrorType.API_ERROR,
details,
true
);
}
}
/**
* 处理验证错误
*
* @param {string} field - 字段名
* @param {string} message - 错误消息
* @param {any} value - 无效值
*/
public handleValidationError(
field: string,
message: string,
value?: any
): void {
const errorMessage = `数据验证失败: ${field} - ${message}`;
const details = { field, value, validationMessage: message };
this.handleError(
new Error(errorMessage),
ErrorType.VALIDATION_ERROR,
details,
false
);
}
/**
* 处理网络错误
*
* @param {any} error - 网络错误
* @param {string} url - 请求URL
*/
public handleNetworkError(error: any, url?: string): void {
const errorMessage = "网络连接失败,请检查网络设置";
const details = { url, networkError: error };
this.handleError(
new Error(errorMessage),
ErrorType.NETWORK_ERROR,
details,
true
);
}
/**
* 记录错误到内部日志
*/
private logError(errorInfo: ErrorInfo): void {
this.errorLog.push(errorInfo);
// 限制日志大小
if (this.errorLog.length > this.MAX_LOG_SIZE) {
this.errorLog.shift();
}
}
/**
* 输出错误到控制台
*/
private logToConsole(errorInfo: ErrorInfo): void {
const logMessage = `[${errorInfo.type}] ${errorInfo.message}`;
switch (errorInfo.type) {
case ErrorType.API_ERROR:
case ErrorType.NETWORK_ERROR:
console.error(logMessage, errorInfo.details);
break;
case ErrorType.VALIDATION_ERROR:
console.warn(logMessage, errorInfo.details);
break;
default:
console.log(logMessage, errorInfo.details);
} }
private constructor() {} // 如果有堆栈信息,也输出
if (errorInfo.stack) {
/** console.error("Stack trace:", errorInfo.stack);
* 处理错误
*
* @param {Error | string} error - 错误对象或错误消息
* @param {ErrorType} type - 错误类型
* @param {any} details - 错误详情
* @param {boolean} showToUser - 是否向用户显示错误
*/
public handleError(
error: Error | string,
type: ErrorType = ErrorType.UNKNOWN_ERROR,
details?: any,
showToUser: boolean = false
): void {
const errorInfo: ErrorInfo = {
type,
message: typeof error === 'string' ? error : error.message,
details,
timestamp: Date.now(),
stack: error instanceof Error ? error.stack : undefined
};
// 记录到日志
this.logError(errorInfo);
// 输出到控制台
this.logToConsole(errorInfo);
// 如果需要,向用户显示友好的错误信息
if (showToUser) {
this.showUserFriendlyError(errorInfo);
}
} }
}
/** /**
* 处理API错误 * 向用户显示友好的错误信息
* */
* @param {any} error - API错误 private showUserFriendlyError(errorInfo: ErrorInfo): void {
* @param {string} apiName - API名称 let userMessage: string;
* @param {any} requestData - 请求数据
*/
public handleApiError(error: any, apiName: string, requestData?: any): void {
const errorMessage = `API调用失败: ${apiName}`;
const details = {
apiName,
requestData,
responseError: error
};
this.handleError( TipsPanel.show(LanguageUtils.getText("chat_error_code_2005"));
new Error(errorMessage),
ErrorType.API_ERROR,
details,
true
);
}
/** // TODO: 这里应该显示UI提示,比如Toast或对话框
* 处理验证错误 console.log("用户提示:", userMessage);
* }
* @param {string} field - 字段名
* @param {string} message - 错误消息
* @param {any} value - 无效值
*/
public handleValidationError(field: string, message: string, value?: any): void {
const errorMessage = `数据验证失败: ${field} - ${message}`;
const details = { field, value, validationMessage: message };
this.handleError( /**
new Error(errorMessage), * 获取错误日志
ErrorType.VALIDATION_ERROR, */
details, public getErrorLog(): ErrorInfo[] {
false return [...this.errorLog];
); }
}
/** /**
* 处理网络错误 * 清除错误日志
* */
* @param {any} error - 网络错误 public clearErrorLog(): void {
* @param {string} url - 请求URL this.errorLog = [];
*/ console.log("Error log cleared");
public handleNetworkError(error: any, url?: string): void { }
const errorMessage = "网络连接失败,请检查网络设置";
const details = { url, networkError: error };
this.handleError( /**
new Error(errorMessage), * 获取特定类型的错误
ErrorType.NETWORK_ERROR, */
details, public getErrorsByType(type: ErrorType): ErrorInfo[] {
true return this.errorLog.filter((error) => error.type === type);
); }
}
/** /**
* 记录错误到内部日志 * 检查是否有未处理的关键错误
*/ */
private logError(errorInfo: ErrorInfo): void { public hasCriticalErrors(): boolean {
this.errorLog.push(errorInfo); const criticalTypes = [ErrorType.API_ERROR, ErrorType.CONFIG_ERROR];
return this.errorLog.some(
// 限制日志大小 (error) =>
if (this.errorLog.length > this.MAX_LOG_SIZE) { criticalTypes.includes(error.type) &&
this.errorLog.shift(); Date.now() - error.timestamp < 60000 // 1分钟内的错误
} );
} }
/**
* 输出错误到控制台
*/
private logToConsole(errorInfo: ErrorInfo): void {
const logMessage = `[${errorInfo.type}] ${errorInfo.message}`;
switch (errorInfo.type) {
case ErrorType.API_ERROR:
case ErrorType.NETWORK_ERROR:
console.error(logMessage, errorInfo.details);
break;
case ErrorType.VALIDATION_ERROR:
console.warn(logMessage, errorInfo.details);
break;
default:
console.log(logMessage, errorInfo.details);
}
// 如果有堆栈信息,也输出
if (errorInfo.stack) {
console.error("Stack trace:", errorInfo.stack);
}
}
/**
* 向用户显示友好的错误信息
*/
private showUserFriendlyError(errorInfo: ErrorInfo): void {
let userMessage: string;
switch (errorInfo.type) {
case ErrorType.API_ERROR:
userMessage = "AI服务暂时不可用,请稍后再试";
break;
case ErrorType.NETWORK_ERROR:
userMessage = "网络连接失败,请检查网络设置";
break;
case ErrorType.CONFIG_ERROR:
userMessage = "系统配置错误,请联系管理员";
break;
case ErrorType.STORAGE_ERROR:
userMessage = "数据保存失败,请重试";
break;
default:
userMessage = "发生了未知错误,请重试或联系客服";
}
// TODO: 这里应该显示UI提示,比如Toast或对话框
console.log("用户提示:", userMessage);
}
/**
* 获取错误日志
*/
public getErrorLog(): ErrorInfo[] {
return [...this.errorLog];
}
/**
* 清除错误日志
*/
public clearErrorLog(): void {
this.errorLog = [];
console.log("Error log cleared");
}
/**
* 获取特定类型的错误
*/
public getErrorsByType(type: ErrorType): ErrorInfo[] {
return this.errorLog.filter(error => error.type === type);
}
/**
* 检查是否有未处理的关键错误
*/
public hasCriticalErrors(): boolean {
const criticalTypes = [ErrorType.API_ERROR, ErrorType.CONFIG_ERROR];
return this.errorLog.some(error =>
criticalTypes.includes(error.type) &&
(Date.now() - error.timestamp) < 60000 // 1分钟内的错误
);
}
} }
Binary file not shown.