保证 request_id 会话固定
This commit is contained in:
parent
eae12d45ad
commit
ebc8c52368
@ -370,6 +370,9 @@ function checkAndFixLoadingState() {
|
||||
if (shouldBeLoading !== chatState.loading) {
|
||||
log(`[checkAndFixLoadingState] 状态不一致,修复 - 应该loading=${shouldBeLoading}, 当前=${chatState.loading}`);
|
||||
chatStore.setLoading(shouldBeLoading);
|
||||
|
||||
// 强制更新senderKey,确保a-x-sender组件重新渲染
|
||||
chatState.senderKey = Date.now();
|
||||
}
|
||||
|
||||
// 更新本地状态,只在需要时更新
|
||||
@ -381,8 +384,8 @@ function checkAndFixLoadingState() {
|
||||
lastLoadingState.value = shouldBeLoading;
|
||||
lastPendingState.value = hasPendingMessage;
|
||||
|
||||
// 仅在需要时更新senderKey
|
||||
if (shouldBeLoading !== actualLoadingState.value || Date.now() - chatState.senderKey > 5000) {
|
||||
// 仅在需要时更新senderKey (此条件可能不再需要,但保留为了防止其他情况)
|
||||
if (shouldBeLoading !== actualLoadingState.value) {
|
||||
chatState.senderKey = Date.now();
|
||||
}
|
||||
}
|
||||
|
@ -41,18 +41,24 @@ try {
|
||||
|
||||
// 添加常量定义
|
||||
const REQUEST_TIMEOUT = 5000; // 请求超时时间(毫秒)
|
||||
const LOCAL_STORAGE_REQUEST_ID_KEY = 'vscode_ai_chat_request_id'; // 保存requestId的localStorage键名
|
||||
|
||||
// WebSocket服务- 浏览器环境下实现
|
||||
export class WebSocketService {
|
||||
private socket: WebSocket | null = null;
|
||||
private backoffTime = 1000;
|
||||
private nextRequestId = 1;
|
||||
// 使用静态变量确保在同一个会话中所有的WebSocketService实例共享同一个requestId序列
|
||||
private static _nextRequestId = 1;
|
||||
private requestHandlers: Map<number, (response: any) => void> = new Map();
|
||||
private reconnectAttempts = 0;
|
||||
private reconnectTimer: NodeJS.Timeout | null = null;
|
||||
private readonly MAX_RECONNECT_ATTEMPTS = 5;
|
||||
private readonly RECONNECT_DELAY = 2000;
|
||||
private isReconnecting = false;
|
||||
private _hasLoggedRequestId = false; // 用于跟踪是否已记录过requestId
|
||||
|
||||
// 内存存储,用于在localStorage不可用时的备用
|
||||
private static memoryStorage: Record<string, string> = {};
|
||||
|
||||
public isConnected = false;
|
||||
public isLoading = false;
|
||||
@ -62,7 +68,77 @@ export class WebSocketService {
|
||||
public messages: ChatMessage[] = []; // 聊天消息历史
|
||||
private eventListeners: Map<string, Array<(data?: any) => void>> = new Map();
|
||||
|
||||
constructor(private apiUrl: string, private apiKey: string, private logger: (message: string) => void = console.log) {}
|
||||
/**
|
||||
* 安全地获取存储值,优先使用localStorage,失败时使用内存存储
|
||||
* @param key 存储键
|
||||
* @returns 存储的值或null
|
||||
*/
|
||||
private safeGetItem(key: string): string | null {
|
||||
try {
|
||||
// 首先尝试从localStorage获取
|
||||
if (typeof localStorage !== 'undefined') {
|
||||
return localStorage.getItem(key);
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger(`无法从localStorage读取数据: ${error}`);
|
||||
}
|
||||
|
||||
// 回退到内存存储
|
||||
return WebSocketService.memoryStorage[key] || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 安全地设置存储值,优先使用localStorage,失败时使用内存存储
|
||||
* @param key 存储键
|
||||
* @param value 要存储的值
|
||||
*/
|
||||
private safeSetItem(key: string, value: string): void {
|
||||
try {
|
||||
// 首先尝试存储到localStorage
|
||||
if (typeof localStorage !== 'undefined') {
|
||||
localStorage.setItem(key, value);
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
this.logger(`无法写入数据到localStorage: ${error}`);
|
||||
}
|
||||
|
||||
// 回退到内存存储
|
||||
WebSocketService.memoryStorage[key] = value;
|
||||
}
|
||||
|
||||
constructor(private apiUrl: string, private apiKey: string, private logger: (message: string) => void = console.log) {
|
||||
// 仅在类的静态变量_nextRequestId还是初始值时才从存储中恢复
|
||||
if (WebSocketService._nextRequestId === 1) {
|
||||
// 从存储中恢复requestId,确保在同一VSCode会话中保持一致
|
||||
const savedRequestId = this.safeGetItem(LOCAL_STORAGE_REQUEST_ID_KEY);
|
||||
|
||||
if (savedRequestId) {
|
||||
const parsedId = parseInt(savedRequestId, 10);
|
||||
if (!isNaN(parsedId) && parsedId > 0) {
|
||||
WebSocketService._nextRequestId = parsedId;
|
||||
this.logger(`从存储中恢复requestId: ${WebSocketService._nextRequestId}`);
|
||||
} else {
|
||||
// 如果存储的值无效,生成一个新的随机ID并保存
|
||||
// 使用时间戳作为基础,确保唯一性
|
||||
const timestamp = Date.now();
|
||||
WebSocketService._nextRequestId = timestamp % 100000000 + Math.floor(Math.random() * 10000);
|
||||
this.safeSetItem(LOCAL_STORAGE_REQUEST_ID_KEY, WebSocketService._nextRequestId.toString());
|
||||
this.logger(`创建新的随机requestId: ${WebSocketService._nextRequestId} (基于时间戳)`);
|
||||
}
|
||||
} else {
|
||||
// 首次运行,创建新的随机ID
|
||||
// 使用时间戳作为基础,确保唯一性
|
||||
const timestamp = Date.now();
|
||||
WebSocketService._nextRequestId = timestamp % 100000000 + Math.floor(Math.random() * 10000);
|
||||
this.safeSetItem(LOCAL_STORAGE_REQUEST_ID_KEY, WebSocketService._nextRequestId.toString());
|
||||
this.logger(`创建新的随机requestId: ${WebSocketService._nextRequestId} (基于时间戳)`);
|
||||
}
|
||||
} else {
|
||||
// 静态变量已初始化,记录当前值
|
||||
this.logger(`使用已初始化的会话requestId: ${WebSocketService._nextRequestId}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接到WebSocket服务
|
||||
@ -500,10 +576,17 @@ export class WebSocketService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成唯一的请求ID
|
||||
* 生成唯一的请求ID - 在同一会话内保持不变,确保所有请求使用相同的ID
|
||||
*/
|
||||
private generateRequestId(): number {
|
||||
return this.nextRequestId++;
|
||||
// 不再自增,每次返回相同的请求ID
|
||||
// 仅在初始请求时记录日志,避免日志过多
|
||||
if (!this._hasLoggedRequestId) {
|
||||
this.logger(`使用固定请求ID: ${WebSocketService._nextRequestId} (会话中保持一致)`);
|
||||
this._hasLoggedRequestId = true;
|
||||
}
|
||||
|
||||
return WebSocketService._nextRequestId;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user