diff --git a/assets/Scripts/chat18x/core/ApiConfigLoader.ts b/assets/Scripts/chat18x/core/ApiConfigLoader.ts index ee42feaf..29654354 100644 --- a/assets/Scripts/chat18x/core/ApiConfigLoader.ts +++ b/assets/Scripts/chat18x/core/ApiConfigLoader.ts @@ -27,6 +27,8 @@ export class ApiConfig { private static _instance: ApiConfig; private config: AIConfig; + private baseUrl: "https://generativelanguage.googleapis.com"; + private constructor() { this.initConfig(); } @@ -104,6 +106,9 @@ export class ApiConfig { public getTimeout() { return this.config.timeout; } + public getBaseUrl() { + return this.baseUrl; + } /** * 验证配置是否有效 diff --git a/assets/Scripts/chat18x/core/ChatAIService.ts b/assets/Scripts/chat18x/core/ChatAIService.ts index eb9c83b4..de1d2625 100644 --- a/assets/Scripts/chat18x/core/ChatAIService.ts +++ b/assets/Scripts/chat18x/core/ChatAIService.ts @@ -1,6 +1,11 @@ // 首先加载 polyfills 以确保兼容性 import "../utils/polyfills"; -import { GoogleGenAI, HarmBlockThreshold, HarmCategory } from "@google/genai"; +import { + Chat, + GoogleGenAI, + HarmBlockThreshold, + HarmCategory, +} from "@google/genai"; import { RoleConfigLoader } from "./RoleConfigLoader"; import { ChatHistoryManager } from "../manager/ChatHistoryManager"; import { ApiConfig } from "./ApiConfigLoader"; @@ -57,8 +62,16 @@ export class ChatAIService { try { this.ai = new GoogleGenAI({ 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) { TipsPanel.show(LanguageUtils.getText("chat_error_code_2001")); ErrorHandler.Instance.handleError( @@ -88,7 +101,7 @@ export class ChatAIService { * 创建或获取指定角色的聊天实例 * @param roleId 角色ID */ - async createOrGetChat(roleId: number): Promise { + async createOrGetChat(roleId: number): Promise { if (!this.chatInstances.has(roleId)) { const systemInstruction = RoleConfigLoader.getRoleInstruction(roleId); const config = ApiConfig.Instance.getAIConfig(); @@ -97,7 +110,7 @@ export class ChatAIService { let savedHistory = await ChatHistoryManager.Instance.loadChatHistory( roleId ); - let chat; + let chat: Chat; if (savedHistory && savedHistory.length > 0) { chat = this.ai.chats.create({ model: config.model, @@ -130,6 +143,7 @@ export class ChatAIService { }, history: savedHistory, }); + console.log(chat); console.log( `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}`); } @@ -226,6 +242,7 @@ export class ChatAIService { try { const chat = await this.createOrGetChat(roleId); + const response = await chat.sendMessage({ message: message.trim(), }); diff --git a/assets/Scripts/chat18x/data/GlobalData.ts b/assets/Scripts/chat18x/data/GlobalData.ts index 9b9e1d1c..fb8ce2a7 100644 --- a/assets/Scripts/chat18x/data/GlobalData.ts +++ b/assets/Scripts/chat18x/data/GlobalData.ts @@ -124,6 +124,7 @@ export class GlobalData extends BaseData { /** 超时时间(微秒) */ public getTimeout(): number { + //return 600000; return this._timeout; } diff --git a/assets/Scripts/chat18x/network/services/HttpChatService.ts b/assets/Scripts/chat18x/network/services/HttpChatService.ts index ae67fd57..9d5df388 100644 --- a/assets/Scripts/chat18x/network/services/HttpChatService.ts +++ b/assets/Scripts/chat18x/network/services/HttpChatService.ts @@ -6,7 +6,7 @@ import type { IChatService } from "./IChatService"; export class HttpChatService implements IChatService { constructor(private api = ApiClient.I) {} - + // 上报聊天数据 async reqChatMsg(req: proto.cs.ICSChatMsgReq): Promise> { const ep: Endpoint = { diff --git a/assets/Scripts/chat18x/utils/ErrorHandler.ts b/assets/Scripts/chat18x/utils/ErrorHandler.ts index 156b3689..54f78a9b 100644 --- a/assets/Scripts/chat18x/utils/ErrorHandler.ts +++ b/assets/Scripts/chat18x/utils/ErrorHandler.ts @@ -1,243 +1,242 @@ /** * 错误处理工具类 - * + * * 提供统一的错误处理、日志记录和用户友好的错误提示 - * + * * @author AI Chat System * @version 1.0.0 */ +import LanguageUtils from "../../Main/Common/LanguageUtils"; +import { TipsPanel } from "../ui/panels/TipsPanel"; + export enum ErrorType { - /** API调用错误 */ - API_ERROR = "API_ERROR", - /** 网络连接错误 */ - NETWORK_ERROR = "NETWORK_ERROR", - /** 配置错误 */ - CONFIG_ERROR = "CONFIG_ERROR", - /** 数据验证错误 */ - VALIDATION_ERROR = "VALIDATION_ERROR", - /** 存储错误 */ - STORAGE_ERROR = "STORAGE_ERROR", - /** 未知错误 */ - UNKNOWN_ERROR = "UNKNOWN_ERROR" + /** API调用错误 */ + API_ERROR = "API_ERROR", + /** 网络连接错误 */ + NETWORK_ERROR = "NETWORK_ERROR", + /** 配置错误 */ + CONFIG_ERROR = "CONFIG_ERROR", + /** 数据验证错误 */ + VALIDATION_ERROR = "VALIDATION_ERROR", + /** 存储错误 */ + STORAGE_ERROR = "STORAGE_ERROR", + /** 未知错误 */ + UNKNOWN_ERROR = "UNKNOWN_ERROR", } export interface ErrorInfo { - type: ErrorType; - message: string; - code?: string | number; - details?: any; - timestamp: number; - stack?: string; + type: ErrorType; + message: string; + code?: string | number; + details?: any; + timestamp: number; + stack?: string; } /** * 错误处理管理器 */ export class ErrorHandler { - private static _instance: ErrorHandler; - private errorLog: ErrorInfo[] = []; - private readonly MAX_LOG_SIZE = 100; + private static _instance: ErrorHandler; + private errorLog: ErrorInfo[] = []; + private readonly MAX_LOG_SIZE = 100; - /** - * 获取ErrorHandler的单例实例 - */ - public static get Instance(): ErrorHandler { - if (!this._instance) { - this._instance = new ErrorHandler(); - } - return this._instance; + /** + * 获取ErrorHandler的单例实例 + */ + public static get Instance(): ErrorHandler { + if (!this._instance) { + this._instance = new ErrorHandler(); + } + 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() {} - - /** - * 处理错误 - * - * @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); - } + // 如果有堆栈信息,也输出 + if (errorInfo.stack) { + console.error("Stack trace:", errorInfo.stack); } + } - /** - * 处理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 - }; + /** + * 向用户显示友好的错误信息 + */ + private showUserFriendlyError(errorInfo: ErrorInfo): void { + let userMessage: string; - this.handleError( - new Error(errorMessage), - ErrorType.API_ERROR, - details, - true - ); - } + TipsPanel.show(LanguageUtils.getText("chat_error_code_2005")); - /** - * 处理验证错误 - * - * @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 }; + // TODO: 这里应该显示UI提示,比如Toast或对话框 + console.log("用户提示:", userMessage); + } - this.handleError( - new Error(errorMessage), - ErrorType.VALIDATION_ERROR, - details, - false - ); - } + /** + * 获取错误日志 + */ + public getErrorLog(): ErrorInfo[] { + return [...this.errorLog]; + } - /** - * 处理网络错误 - * - * @param {any} error - 网络错误 - * @param {string} url - 请求URL - */ - public handleNetworkError(error: any, url?: string): void { - const errorMessage = "网络连接失败,请检查网络设置"; - const details = { url, networkError: error }; + /** + * 清除错误日志 + */ + public clearErrorLog(): void { + this.errorLog = []; + console.log("Error log cleared"); + } - this.handleError( - new Error(errorMessage), - ErrorType.NETWORK_ERROR, - details, - true - ); - } + /** + * 获取特定类型的错误 + */ + public getErrorsByType(type: ErrorType): ErrorInfo[] { + return this.errorLog.filter((error) => error.type === type); + } - /** - * 记录错误到内部日志 - */ - 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); - } - - // 如果有堆栈信息,也输出 - 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分钟内的错误 - ); - } -} \ No newline at end of file + /** + * 检查是否有未处理的关键错误 + */ + 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分钟内的错误 + ); + } +} diff --git a/assets/bundles/DataTable/tblanguage.bin b/assets/bundles/DataTable/tblanguage.bin index 349e5c65..5d29810c 100644 Binary files a/assets/bundles/DataTable/tblanguage.bin and b/assets/bundles/DataTable/tblanguage.bin differ diff --git a/xchat_cfg b/xchat_cfg index 53e277f1..1f0659bc 160000 --- a/xchat_cfg +++ b/xchat_cfg @@ -1 +1 @@ -Subproject commit 53e277f100f4af0d931654436ac60d3c6b5968ac +Subproject commit 1f0659bc5dfc9dd2b5baa9837faf70279c0d7435