v2.3.2-coder-answer-endpoint: fix ask_user_input submit in CoderPane
The CoderPane runs its own inference runner and broker on the boocoder service. The AskUserInputCard was calling /api/chats/:id/answer_user_input on the main BooChat server, which has a different inference runner — the answer was accepted but the next turn was enqueued on the wrong runner, so nothing happened. Fix: register the same answer_user_input endpoint on the boocoder, and add an apiPrefix prop to AskUserInputCard so the CoderPane routes through /api/coder/chats/:id/answer_user_input. BooChat's MessageList continues to use the default (no prefix) path. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
import { useMemo, useState } from 'react';
|
||||
import { Check } from 'lucide-react';
|
||||
import { toast } from 'sonner';
|
||||
import { api } from '@/api/client';
|
||||
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import type {
|
||||
@@ -22,6 +21,7 @@ interface Props {
|
||||
toolCall: ToolCall;
|
||||
toolResult: ToolResult | null;
|
||||
chatId: string;
|
||||
apiPrefix?: string;
|
||||
}
|
||||
|
||||
function parseQuestions(raw: unknown): AskUserQuestion[] {
|
||||
@@ -63,7 +63,7 @@ function parseAnswerSet(raw: unknown): AskUserAnswerSet | null {
|
||||
return { answers };
|
||||
}
|
||||
|
||||
export function AskUserInputCard({ toolCall, toolResult, chatId }: Props) {
|
||||
export function AskUserInputCard({ toolCall, toolResult, chatId, apiPrefix = '' }: Props) {
|
||||
const questions = useMemo(() => parseQuestions(toolCall.args), [toolCall.args]);
|
||||
|
||||
if (questions.length === 0) {
|
||||
@@ -74,9 +74,6 @@ export function AskUserInputCard({ toolCall, toolResult, chatId }: Props) {
|
||||
);
|
||||
}
|
||||
|
||||
// Tool result with a non-null output means the answer is already submitted.
|
||||
// The pending sentinel uses output=null, so this branch only triggers after
|
||||
// the real WS tool_result frame lands.
|
||||
const answered = toolResult && toolResult.output !== null;
|
||||
if (answered) {
|
||||
const answerSet = parseAnswerSet(toolResult!.output);
|
||||
@@ -84,7 +81,7 @@ export function AskUserInputCard({ toolCall, toolResult, chatId }: Props) {
|
||||
}
|
||||
|
||||
return (
|
||||
<PendingView questions={questions} toolCallId={toolCall.id} chatId={chatId} />
|
||||
<PendingView questions={questions} toolCallId={toolCall.id} chatId={chatId} apiPrefix={apiPrefix} />
|
||||
);
|
||||
}
|
||||
|
||||
@@ -92,10 +89,12 @@ function PendingView({
|
||||
questions,
|
||||
toolCallId,
|
||||
chatId,
|
||||
apiPrefix = '',
|
||||
}: {
|
||||
questions: AskUserQuestion[];
|
||||
toolCallId: string;
|
||||
chatId: string;
|
||||
apiPrefix?: string;
|
||||
}) {
|
||||
// Per-question selections + free text. Selections are option arrays so the
|
||||
// multi_select case is uniform; single_select just constrains to length 1.
|
||||
@@ -133,9 +132,16 @@ function PendingView({
|
||||
if (submitting) return;
|
||||
setSubmitting(true);
|
||||
try {
|
||||
await api.chats.answerUserInput(chatId, toolCallId, answers);
|
||||
// Card stays mounted; the incoming WS tool_result frame will flip it
|
||||
// into AnsweredView via the parent prop change.
|
||||
const url = `${apiPrefix}/api/chats/${chatId}/answer_user_input`;
|
||||
const res = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ tool_call_id: toolCallId, answers }),
|
||||
});
|
||||
if (!res.ok) {
|
||||
const body = await res.json().catch(() => ({})) as { error?: string; detail?: string };
|
||||
throw new Error(body.detail ?? body.error ?? `HTTP ${res.status}`);
|
||||
}
|
||||
} catch (err) {
|
||||
toast.error(err instanceof Error ? err.message : 'submit failed');
|
||||
setSubmitting(false);
|
||||
|
||||
@@ -230,6 +230,7 @@ export function CoderMessageList({ messages, chatId, footer }: Props) {
|
||||
toolCall={item.run.call}
|
||||
toolResult={item.run.result}
|
||||
chatId={chatId}
|
||||
apiPrefix="/api/coder"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user