update logic of switch_ptt_and_rt
This commit is contained in:
@@ -475,14 +475,27 @@ export function PhoneSimulator({
|
||||
const handleModeSwitch = async () => {
|
||||
if (!room || !voiceAssistant.agent) return;
|
||||
|
||||
// Determine the target mode (toggle from current state)
|
||||
const targetMode = isPushToTalkMode ? "realtime" : "push_to_talk";
|
||||
|
||||
try {
|
||||
await room.localParticipant.performRpc({
|
||||
const response = await room.localParticipant.performRpc({
|
||||
destinationIdentity: voiceAssistant.agent.identity,
|
||||
method: "switch_ptt_and_rt",
|
||||
payload: "",
|
||||
payload: JSON.stringify({ mode: targetMode }),
|
||||
});
|
||||
// Toggle mode on success
|
||||
setIsPushToTalkMode(prev => !prev);
|
||||
|
||||
// Parse the response to confirm the mode was set
|
||||
try {
|
||||
const responseData = JSON.parse(response);
|
||||
const confirmedMode = responseData.mode;
|
||||
// Update state based on server response
|
||||
setIsPushToTalkMode(confirmedMode === "push_to_talk");
|
||||
} catch (parseError) {
|
||||
// If parsing fails, update state based on what we sent
|
||||
console.warn("Failed to parse mode switch response, using sent mode:", parseError);
|
||||
setIsPushToTalkMode(targetMode === "push_to_talk");
|
||||
}
|
||||
} catch (error: any) {
|
||||
console.error("Failed to switch mode:", error);
|
||||
// Don't show error toast for mode switch failures, just log
|
||||
@@ -502,16 +515,38 @@ export function PhoneSimulator({
|
||||
setInterruptRejected(false);
|
||||
|
||||
try {
|
||||
await room.localParticipant.performRpc({
|
||||
const response = await room.localParticipant.performRpc({
|
||||
destinationIdentity: voiceAssistant.agent.identity,
|
||||
method: "start_turn",
|
||||
payload: "",
|
||||
});
|
||||
setIsPushToTalkActive(true);
|
||||
setInterruptRejected(false);
|
||||
|
||||
// Parse the response to check for success/failure
|
||||
try {
|
||||
const responseData = JSON.parse(response);
|
||||
if (responseData.success === false) {
|
||||
// Interrupt was rejected, show message
|
||||
if (responseData.message === "不能打断") {
|
||||
setInterruptRejected(true);
|
||||
// Clear the rejection message after 3 seconds
|
||||
setTimeout(() => setInterruptRejected(false), 3000);
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.log("Interrupt rejected (cannot interrupt):", responseData.message);
|
||||
}
|
||||
return;
|
||||
}
|
||||
} else if (responseData.success === true) {
|
||||
// Successfully started turn
|
||||
setIsPushToTalkActive(true);
|
||||
setInterruptRejected(false);
|
||||
}
|
||||
} catch (parseError) {
|
||||
// If response is not JSON, assume success (backward compatibility)
|
||||
setIsPushToTalkActive(true);
|
||||
setInterruptRejected(false);
|
||||
}
|
||||
} catch (error: any) {
|
||||
// Prevent error from propagating to React error boundary
|
||||
// by handling all expected errors here
|
||||
// Handle RPC errors (method not found, etc.)
|
||||
setIsPushToTalkActive(false);
|
||||
|
||||
const errorMessage = error?.message || "";
|
||||
@@ -527,45 +562,6 @@ export function PhoneSimulator({
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for "Application error in method handler" - this indicates interrupt failed
|
||||
// This error is raised when session.interrupt() fails in the agent
|
||||
// We handle this gracefully by showing "不允许打断" on the button, so we don't log it as an error
|
||||
if (errorMessage.includes("Application error in method handler") ||
|
||||
errorMessage.includes("Application error") ||
|
||||
errorCode === 13 || // ERROR_INTERNAL (RpcErrorCode.ERROR_INTERNAL)
|
||||
(isAgentSpeaking && errorMessage.includes("interrupt"))) {
|
||||
// Suppress error logging for expected interrupt failures
|
||||
// Only log at debug level to avoid error popups
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.log("Interrupt rejected (expected behavior):", errorMessage);
|
||||
}
|
||||
setInterruptRejected(true);
|
||||
// Clear the rejection message after 3 seconds
|
||||
setTimeout(() => setInterruptRejected(false), 3000);
|
||||
// Explicitly prevent error from propagating
|
||||
error.preventDefault?.();
|
||||
error.stopPropagation?.();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if agent is speaking and the error suggests interruption was rejected
|
||||
if (isAgentSpeaking) {
|
||||
// Check for common rejection indicators
|
||||
if (errorMessage.includes("reject") ||
|
||||
errorMessage.includes("not allowed") ||
|
||||
errorCode === 403 || // Forbidden
|
||||
errorCode === 409) { // Conflict
|
||||
// Suppress error logging for expected rejections
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
console.log("Interrupt rejected:", errorMessage);
|
||||
}
|
||||
setInterruptRejected(true);
|
||||
// Clear the rejection message after 3 seconds
|
||||
setTimeout(() => setInterruptRejected(false), 3000);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Only log and show error for unexpected errors
|
||||
console.error("Unexpected error in push-to-talk:", error);
|
||||
const defaultErrorMessage = "Agent does not support push-to-talk. Make sure your agent has the push-to-talk RPC methods (start_turn, end_turn, cancel_turn) registered.";
|
||||
|
||||
Reference in New Issue
Block a user