fix: 收敛 workbench 会话选择权威
This commit is contained in:
@@ -90,6 +90,12 @@ async function handleRequest(request: IncomingMessage, response: ServerResponse)
|
||||
if (/^\/v1\/workbench\/workspace\/[^/]+\/select-conversation$/u.test(path) && method === "POST") {
|
||||
const body = await readJson(request);
|
||||
state.selectRequests.push(redactRequestBody(body));
|
||||
if (state.scenarioId === "server-authoritative-create" && body.create === true) {
|
||||
const conversationId = "cnv_server_created";
|
||||
if (!conversationById(conversationId)) state.conversations.unshift(createConversationFromSelect({ ...body, sessionId: "ses_server_created", threadId: null }, conversationId));
|
||||
state.selectedConversationId = conversationId;
|
||||
return json(response, 200, { workspace: workspacePayload() });
|
||||
}
|
||||
const conversationId = String(body.conversationId ?? "");
|
||||
if (conversationId && !conversationById(conversationId) && body.create === true) state.conversations.unshift(createConversationFromSelect(body, conversationId));
|
||||
if (conversationId && conversationById(conversationId)) state.selectedConversationId = conversationId;
|
||||
@@ -112,7 +118,10 @@ async function handleRequest(request: IncomingMessage, response: ServerResponse)
|
||||
}
|
||||
const conversationMatch = path.match(/^\/v1\/agent\/conversations\/([^/]+)$/u);
|
||||
if (conversationMatch && method === "GET") {
|
||||
const conversation = conversationById(decodeURIComponent(conversationMatch[1] ?? ""));
|
||||
const conversationId = decodeURIComponent(conversationMatch[1] ?? "");
|
||||
if (state.scenarioId === "session-switch-detail-404-isolated" && conversationId === "cnv_stale_404") return json(response, 404, { ok: false, status: 404, error: { code: "conversation_not_found" } });
|
||||
if (state.scenarioId === "completed-replay-detail-404" && conversationId === "cnv_completed") return json(response, 404, { ok: false, status: 404, error: { code: "conversation_replay_unavailable" } });
|
||||
const conversation = conversationById(conversationId);
|
||||
if (conversation && conversationProjectMismatch(conversation, url)) return json(response, 404, { ok: false, status: 404, error: { code: "conversation_project_mismatch" } });
|
||||
return conversation ? json(response, 200, { conversation }) : json(response, 404, { ok: false, status: 404, error: { code: "conversation_not_found" } });
|
||||
}
|
||||
@@ -124,6 +133,7 @@ async function handleRequest(request: IncomingMessage, response: ServerResponse)
|
||||
const turnMatch = path.match(/^\/v1\/agent\/turns\/([^/]+)$/u);
|
||||
if (turnMatch && method === "GET") {
|
||||
const traceId = decodeURIComponent(turnMatch[1] ?? "");
|
||||
if (state.scenarioId === "completed-replay-detail-404" && traceId === "trc_completed") return json(response, 404, { ok: false, status: 404, error: { code: "turn_replay_unavailable" } });
|
||||
if (traceId === state.staleNestedTraceId) return json(response, 502, { ok: false, status: 502, error: { code: "upstream_unavailable", message: "stale trace is unavailable" } });
|
||||
if (traceProjectMismatch(traceId, url)) return json(response, 404, { ok: false, status: 404, error: { code: "trace_project_mismatch" } });
|
||||
return json(response, 200, turnPayload(traceId));
|
||||
@@ -132,6 +142,7 @@ async function handleRequest(request: IncomingMessage, response: ServerResponse)
|
||||
const traceMatch = path.match(/^\/v1\/agent\/traces\/([^/]+)$/u);
|
||||
if (traceMatch && method === "GET") {
|
||||
const traceId = decodeURIComponent(traceMatch[1] ?? "");
|
||||
if (state.scenarioId === "completed-replay-detail-404" && traceId === "trc_completed") return json(response, 404, { ok: false, status: 404, error: { code: "trace_replay_unavailable" } });
|
||||
if (traceId === state.staleNestedTraceId) return json(response, 502, { ok: false, status: 502, error: { code: "upstream_unavailable", message: "stale trace is unavailable" } });
|
||||
if (traceProjectMismatch(traceId, url)) return json(response, 404, { ok: false, status: 404, error: { code: "trace_project_mismatch" } });
|
||||
return json(response, 200, tracePayload(traceId, url));
|
||||
@@ -156,6 +167,10 @@ function createScenarioState(scenarioId: string): ScenarioState {
|
||||
conversations.push(crossProjectConversation());
|
||||
traces.trc_cross_project = crossProjectTrace();
|
||||
}
|
||||
if (id === "session-switch-detail-404-isolated") {
|
||||
conversations.unshift(staleDetailConversation());
|
||||
conversations.push(emptyConversation());
|
||||
}
|
||||
if (id === "terminal-empty-trace") {
|
||||
conversations.push(terminalEmptyTraceConversation());
|
||||
traces.trc_terminal_empty = terminalEmptyTrace();
|
||||
@@ -163,6 +178,8 @@ function createScenarioState(scenarioId: string): ScenarioState {
|
||||
if (id === "session-switch-empty-reload") conversations.push(emptyConversation());
|
||||
const selectedConversationId = id === "deep-link" || id === "stale-nested-trace"
|
||||
? "cnv_failed"
|
||||
: id === "session-switch-detail-404-isolated" || id === "completed-replay-detail-404"
|
||||
? "cnv_completed"
|
||||
: id === "terminal-turn-stale-session-active"
|
||||
? "cnv_completed"
|
||||
: id === "terminal-empty-trace"
|
||||
@@ -316,6 +333,23 @@ function terminalEmptyTrace(): JsonRecord {
|
||||
return { traceId: "trc_terminal_empty", status: "completed", conversationId: "cnv_terminal_empty", sessionId: "ses_terminal_empty", threadId: "thr_terminal_empty", events: [], eventCount: 0, fullTraceLoaded: true, hasMore: false, finalResponse: { text: "终态空 Trace 已完成。" } };
|
||||
}
|
||||
|
||||
function staleDetailConversation(): ConversationRecord {
|
||||
const now = new Date().toISOString();
|
||||
return {
|
||||
conversationId: "cnv_stale_404",
|
||||
projectId: state?.projectId ?? capture.scenario.projectId,
|
||||
sessionId: "ses_stale_404",
|
||||
threadId: "thr_stale_404",
|
||||
status: "active",
|
||||
startedAt: now,
|
||||
updatedAt: now,
|
||||
messageCount: 0,
|
||||
firstUserMessagePreview: "已失效的列表项",
|
||||
session: { sessionId: "ses_stale_404", threadId: "thr_stale_404", status: "active" },
|
||||
messages: []
|
||||
};
|
||||
}
|
||||
|
||||
function emptyConversation(): ConversationRecord {
|
||||
const now = new Date().toISOString();
|
||||
return { conversationId: "cnv_empty", projectId: state?.projectId ?? capture.scenario.projectId, sessionId: "ses_empty", threadId: "thr_empty", status: "active", startedAt: now, updatedAt: now, messageCount: 0, firstUserMessagePreview: "空白会话", session: { sessionId: "ses_empty", threadId: "thr_empty", status: "active" }, messages: [] };
|
||||
|
||||
Reference in New Issue
Block a user