37 lines
1.3 KiB
TypeScript
37 lines
1.3 KiB
TypeScript
import { useSessionStore } from "../store/sessionStore";
|
|
import { resolve } from "../widgets";
|
|
import { postResponse } from "../api/sessions";
|
|
import type { UiResponse } from "../api/types";
|
|
|
|
export function WidgetHost({ sessionId }: { sessionId: string | null }) {
|
|
const pending = useSessionStore((s) => s.pendingWidget);
|
|
const clearPending = useSessionStore((s) => s.clearPending);
|
|
const pushToast = useSessionStore((s) => s.pushToast);
|
|
const setLastUserEntry = useSessionStore((s) => s.setLastUserEntry);
|
|
if (!pending) return null;
|
|
const Renderer = resolve(pending.widget);
|
|
const onRespond = async (r: UiResponse) => {
|
|
if (sessionId) {
|
|
try {
|
|
await postResponse(sessionId, r);
|
|
} catch (err) {
|
|
// Surface feedback and keep the widget pending so the user can retry.
|
|
pushToast({
|
|
level: "error",
|
|
text:
|
|
err instanceof Error
|
|
? `Failed to send response: ${err.message}`
|
|
: "Failed to send response.",
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
setLastUserEntry({
|
|
kind: "choice",
|
|
text: r.text ?? r.choices?.join(", ") ?? r.decision?.type ?? r.control ?? "(choice)",
|
|
});
|
|
clearPending();
|
|
};
|
|
return <Renderer descriptor={pending} onRespond={onRespond} />;
|
|
}
|