82 lines
2.1 KiB
TypeScript
82 lines
2.1 KiB
TypeScript
"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<string | null>(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<typeof usePhotoCaptureTool>;
|