保证 request_id 会话固定

This commit is contained in:
shunfeng.zhou 2025-04-17 22:45:27 +08:00
parent eae12d45ad
commit ebc8c52368
2 changed files with 92 additions and 6 deletions

View File

@ -370,6 +370,9 @@ function checkAndFixLoadingState() {
if (shouldBeLoading !== chatState.loading) {
log(`[checkAndFixLoadingState] 状态不一致,修复 - 应该loading=${shouldBeLoading}, 当前=${chatState.loading}`);
chatStore.setLoading(shouldBeLoading);
// senderKeya-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();
}
}

View File

@ -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;
}
/**