"use client"; import { useCallback, useEffect, useState } from "react"; import type { VoicePreview } from "@/hooks/use-voice-preview"; const PHOTO_BUTTON_TOOL = "set_photo_button_visible"; const PHOTO_BUTTON_DEFINITION = { name: PHOTO_BUTTON_TOOL, label: "控制拍照按钮", description: "显示或隐藏客户端的拍照按钮。", parameters: [ { name: "visible", type: "boolean", required: true, description: "是否显示拍照按钮。", }, ], } as const; export function usePhotoCaptureTool(preview: VoicePreview, enabled = true) { const { registerClientTool, sendUserInput, status } = preview; const [visible, setVisible] = useState(false); const [capturing, setCapturing] = useState(false); const [error, setError] = useState(null); useEffect(() => { if (!enabled) return; return registerClientTool( PHOTO_BUTTON_DEFINITION, ({ visible: nextValue }) => { if (typeof nextValue !== "boolean") { throw new Error("visible 参数必须是布尔值"); } setVisible(nextValue); setError(null); return { visible: nextValue }; }, ); }, [enabled, registerClientTool]); useEffect(() => { if (enabled && status === "connected") return; // eslint-disable-next-line react-hooks/set-state-in-effect setVisible(false); setCapturing(false); }, [enabled, status]); const capture = useCallback(async () => { if (capturing || status !== "connected") return; setCapturing(true); setError(null); try { await sendUserInput( [ { type: "input_image", source: { type: "camera_frame", frame: "current" }, }, ], { runImmediately: true, interrupt: true }, ); } catch (captureError) { setError( captureError instanceof Error ? captureError.message : "拍照提交失败", ); } finally { setCapturing(false); } }, [capturing, sendUserInput, status]); return { visible, capturing, error, capture, }; } export type PhotoCaptureTool = ReturnType;