Fix answer endpoint to avoid duplicate DB updates

This commit is contained in:
Jared Miller 2026-01-28 13:20:47 -05:00
parent 091979390a
commit 1827baaf39
Signed by: shmup
GPG key ID: 22B5C6D66A38B06C
2 changed files with 33 additions and 56 deletions

View file

@ -157,22 +157,43 @@ const server = Bun.serve<SessionData>({
} }
const answer = body.response as AnswerResponse; const answer = body.response as AnswerResponse;
let inputData: string;
// Handle each response type // Get WebSocket connection
const ws = sessionWebSockets.get(prompt.session_id);
if (!ws) {
return new Response("Session WebSocket not found", { status: 404 });
}
// Determine response value for DB and broadcast
let responseValue: string;
if (answer.type === "option") { if (answer.type === "option") {
inputData = `${answer.value}\n`; responseValue = answer.value;
} else if (answer.type === "text") { } else if (answer.type === "text") {
inputData = `${answer.value}\n`; responseValue = "custom";
} else if (answer.type === "tab_instructions") { } else if (answer.type === "tab_instructions") {
// Execute key sequence for tab instructions with delays: responseValue = `tab:${answer.selected_option}`;
// 1. Navigate to selected_option (up/down arrows) } else {
// 2. Wait 100ms return new Response("Invalid response type", { status: 400 });
// 3. Send Tab key }
// 4. Wait 100ms
// 5. Write instruction text
// 6. Send Enter key
// Mark as responded in DB (once)
respondToPrompt(promptId, responseValue);
// Broadcast to dashboards (once)
broadcastSSE({
type: "prompt_response",
prompt_id: promptId,
response: responseValue,
});
// Handle WebSocket input based on type
if (answer.type === "option" || answer.type === "text") {
// Synchronous send for simple responses
const inputData = `${answer.value}\n`;
const message: ServerMessage = { type: "input", data: inputData };
ws.send(JSON.stringify(message));
} else if (answer.type === "tab_instructions") {
// Async execution for tab instructions
const promptData = prompt.prompt_json; const promptData = prompt.prompt_json;
if (!promptData || promptData.prompt_type !== "permission") { if (!promptData || promptData.prompt_type !== "permission") {
return new Response( return new Response(
@ -184,22 +205,6 @@ const server = Bun.serve<SessionData>({
const currentOption = promptData.selected_option; const currentOption = promptData.selected_option;
const targetOption = answer.selected_option; const targetOption = answer.selected_option;
// Mark as responded in DB first
respondToPrompt(promptId, `tab:${answer.selected_option}`);
// Broadcast to dashboards
broadcastSSE({
type: "prompt_response",
prompt_id: promptId,
response: answer.selected_option === 1 ? "approve" : "reject",
});
// Get WebSocket for async execution
const ws = sessionWebSockets.get(prompt.session_id);
if (!ws) {
return new Response("Session WebSocket not found", { status: 404 });
}
// Execute key sequence asynchronously with delays // Execute key sequence asynchronously with delays
(async () => { (async () => {
const sendInput = (data: string) => { const sendInput = (data: string) => {
@ -224,36 +229,8 @@ const server = Bun.serve<SessionData>({
})().catch((err) => { })().catch((err) => {
console.error("Error executing tab instruction sequence:", err); console.error("Error executing tab instruction sequence:", err);
}); });
// Return immediately (async execution continues in background)
return Response.json({ success: true });
} else {
return new Response("Invalid response type", { status: 400 });
} }
// Mark as responded in DB
respondToPrompt(
promptId,
answer.type === "option" ? answer.value : "custom",
);
// Notify CLI via WebSocket
const ws = sessionWebSockets.get(prompt.session_id);
if (ws) {
const message: ServerMessage = { type: "input", data: inputData };
ws.send(JSON.stringify(message));
}
// Broadcast to dashboards
broadcastSSE({
type: "prompt_response",
prompt_id: promptId,
response:
answer.type === "option" && answer.value === "1"
? "approve"
: "reject",
});
return Response.json({ success: true }); return Response.json({ success: true });
} }

View file

@ -118,5 +118,5 @@ export type SSEEvent =
| { | {
type: "prompt_response"; type: "prompt_response";
prompt_id: number; prompt_id: number;
response: "approve" | "reject"; response: string;
}; };