fix(web): 放宽会话详情 REST 超时

This commit is contained in:
lyon
2026-06-17 08:11:27 +08:00
parent 0147987f1e
commit 165290c180
2 changed files with 30 additions and 21 deletions
+12 -2
View File
@@ -3,18 +3,23 @@ import type { ApiResult, ConversationRecord, WorkspaceRecord } from "@/types";
export interface ConversationListOptions {
includeConversationId?: string | null;
timeoutMs?: number | null;
}
export interface ConversationDetailOptions {
projectId?: string | null;
timeoutMs?: number | null;
}
const CONVERSATION_LIST_TIMEOUT_MS = 30_000;
const CONVERSATION_DETAIL_TIMEOUT_MS = 45_000;
export const workbenchAPI = {
workspace: (projectId: string): Promise<ApiResult<{ workspace?: WorkspaceRecord }>> => fetchJson(`/v1/workbench/workspace?projectId=${encodeURIComponent(projectId)}`, { timeoutMs: 8000, timeoutName: "workspace" }),
updateWorkspace: (workspaceId: string, payload: Record<string, unknown>): Promise<ApiResult<{ workspace?: WorkspaceRecord }>> => fetchJson(`/v1/workbench/workspace/${encodeURIComponent(workspaceId)}`, { method: "PATCH", body: JSON.stringify(payload), timeoutMs: 8000, timeoutName: "workspace update" }),
selectConversation: (workspaceId: string, payload: Record<string, unknown>): Promise<ApiResult<{ workspace?: WorkspaceRecord }>> => fetchJson(`/v1/workbench/workspace/${encodeURIComponent(workspaceId)}/select-conversation`, { method: "POST", body: JSON.stringify(payload), timeoutMs: 8000, timeoutName: "select conversation" }),
conversations: (projectId: string, options: ConversationListOptions = {}): Promise<ApiResult<{ conversations?: ConversationRecord[] }>> => fetchJson(conversationListPath(projectId, options), { timeoutMs: 8000, timeoutName: "conversations" }),
conversation: (conversationId: string, options: ConversationDetailOptions = {}): Promise<ApiResult<{ conversation?: ConversationRecord }>> => fetchJson(conversationDetailPath(conversationId, options), { timeoutMs: 8000, timeoutName: "conversation" }),
conversations: (projectId: string, options: ConversationListOptions = {}): Promise<ApiResult<{ conversations?: ConversationRecord[] }>> => fetchJson(conversationListPath(projectId, options), { timeoutMs: requestTimeoutMs(options.timeoutMs, CONVERSATION_LIST_TIMEOUT_MS), timeoutName: "conversations" }),
conversation: (conversationId: string, options: ConversationDetailOptions = {}): Promise<ApiResult<{ conversation?: ConversationRecord }>> => fetchJson(conversationDetailPath(conversationId, options), { timeoutMs: requestTimeoutMs(options.timeoutMs, CONVERSATION_DETAIL_TIMEOUT_MS), timeoutName: "conversation" }),
deleteConversation: (conversationId: string, payload: Record<string, unknown>): Promise<ApiResult<{ workspace?: WorkspaceRecord }>> => fetchJson(`/v1/agent/conversations/${encodeURIComponent(conversationId)}`, { method: "DELETE", body: JSON.stringify(payload), timeoutMs: 8000, timeoutName: "delete conversation" }),
saveConversation: (conversationId: string, payload: Record<string, unknown>): Promise<ApiResult<{ ok?: boolean }>> => fetchJson(`/v1/agent/conversations/${encodeURIComponent(conversationId)}`, { method: "PUT", body: JSON.stringify(payload), timeoutMs: 8000, timeoutName: "save conversation" })
};
@@ -33,3 +38,8 @@ function conversationListPath(projectId: string, options: ConversationListOption
if (includeConversationId) params.set("includeConversationId", includeConversationId);
return `/v1/agent/conversations?${params.toString()}`;
}
function requestTimeoutMs(value: number | null | undefined, fallback: number): number {
const timeout = Number(value);
return Number.isFinite(timeout) && timeout > 0 ? Math.trunc(timeout) : fallback;
}
+18 -19
View File
@@ -74,26 +74,9 @@ export const useWorkbenchStore = defineStore("workbench", () => {
projectId.value = nextProjectId;
const routeConversationId = normalizeWorkbenchConversationId(options.conversationId);
const selectedConversationId = routeConversationId ?? selectedConversationIdFromWorkspace(nextWorkspace);
const [conversationsResult, selectedConversationResult] = await Promise.all([
api.workbench.conversations(nextProjectId, { includeConversationId: selectedConversationId }),
selectedConversationId ? api.workbench.conversation(selectedConversationId, { projectId: nextProjectId }) : Promise.resolve(null)
]);
loading.value = false;
const conversationsPromise = api.workbench.conversations(nextProjectId, { includeConversationId: selectedConversationId });
const selectedConversationResult = selectedConversationId ? await api.workbench.conversation(selectedConversationId, { projectId: nextProjectId }) : null;
const selectedConversation = selectedConversationResult?.ok ? selectedConversationResult.data?.conversation ?? null : null;
let nextConversations = conversations.value;
if (conversationsResult.ok) {
nextConversations = stableConversationList(conversations.value, conversationsResult.data?.conversations, selectedConversationId, selectedConversation);
conversations.value = nextConversations;
conversationsReady.value = true;
void refreshSessionStatusAuthority(nextConversations);
} else {
if (selectedConversation) {
nextConversations = mergeConversationIntoList(nextConversations, selectedConversation);
conversations.value = nextConversations;
}
conversationsReady.value = conversations.value.length > 0;
error.value = conversations.value.length > 0 ? null : conversationsResult.error ?? "session list unavailable";
}
if (selectedConversationId && selectedConversationResult && !selectedConversationResult.ok) error.value = selectedConversationResult.error ?? "conversation unavailable";
const workspaceSnapshot = selectedConversation
? workspaceWithSelectedConversation(nextWorkspace, selectedConversation, conversationProjectId(selectedConversation, nextProjectId))
@@ -110,6 +93,22 @@ export const useWorkbenchStore = defineStore("workbench", () => {
void hydrateTraceEvents(messages.value);
reattachRestoredActiveTrace();
}
loading.value = false;
const conversationsResult = await conversationsPromise;
let nextConversations = conversations.value;
if (conversationsResult.ok) {
nextConversations = stableConversationList(conversations.value, conversationsResult.data?.conversations, selectedConversationId, selectedConversation);
conversations.value = nextConversations;
conversationsReady.value = true;
void refreshSessionStatusAuthority(nextConversations);
} else {
if (selectedConversation) {
nextConversations = mergeConversationIntoList(nextConversations, selectedConversation);
conversations.value = nextConversations;
}
conversationsReady.value = conversations.value.length > 0;
error.value = conversations.value.length > 0 ? null : conversationsResult.error ?? "session list unavailable";
}
await refreshProviderOptions();
}