Fix workflow forward task immediate disconnection issue

Fixed critical bug where forward tasks in workflows would immediately disconnect calls instead of forwarding them properly.

Changes:
- Fixed append_twiml_element function to properly handle Dial elements with child Number elements
- Enhanced create_forward_twiml to extract numbers from nested data structures
- Added comprehensive error handling for missing forward numbers
- Added detailed logging throughout workflow execution for debugging
- Set default timeout of 30 seconds for forward operations

The issue was caused by the Dial element being converted to string which lost all child Number elements, resulting in an empty dial that would immediately disconnect.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-09-18 16:27:51 -07:00
parent 345ef43740
commit 90cb03acfd
4 changed files with 287 additions and 20 deletions

View File

@@ -390,7 +390,8 @@ class TWP_Admin {
<?php endif; ?>
</select>
<button type="button" class="button" onclick="loadElevenLabsVoices()">Load Voices</button>
<p class="description">Default voice for text-to-speech. Click "Load Voices" after entering your API key.</p>
<button type="button" class="button" onclick="refreshElevenLabsVoices()" title="Refresh voices from ElevenLabs">🔄 Refresh</button>
<p class="description">Default voice for text-to-speech. Click "Load Voices" after entering your API key, or "Refresh" to get updated voices.</p>
<?php if (WP_DEBUG): ?>
<p class="description"><small>Debug: Current saved voice ID = "<?php echo esc_html(get_option('twp_elevenlabs_voice_id', 'empty')); ?>"</small></p>
<?php endif; ?>
@@ -1066,6 +1067,70 @@ class TWP_Admin {
xhr.send('action=twp_get_elevenlabs_voices&nonce=' + '<?php echo wp_create_nonce('twp_ajax_nonce'); ?>');
}
function refreshElevenLabsVoices() {
var select = document.getElementById('elevenlabs-voice-select');
var button = event.target;
var currentValue = select.getAttribute('data-current') || select.value;
console.log('Refreshing voices, current value:', currentValue);
button.textContent = 'Refreshing...';
button.disabled = true;
var xhr = new XMLHttpRequest();
xhr.open('POST', ajaxurl);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.onload = function() {
button.textContent = '🔄 Refresh';
button.disabled = false;
try {
var response = JSON.parse(xhr.responseText);
if (response.success) {
var options = '<option value="">Select a voice...</option>';
if (Array.isArray(response.data)) {
response.data.forEach(function(voice) {
var selected = voice.voice_id === currentValue ? ' selected' : '';
var category = voice.category === 'cloned' ? ' (Cloned)' : (voice.category === 'premade' ? ' (Premade)' : '');
options += '<option value="' + voice.voice_id + '"' + selected + '>' + voice.name + category + '</option>';
});
}
select.innerHTML = options;
select.setAttribute('data-current', currentValue);
// Re-add preview buttons
addVoicePreviewButtons(select, response.data);
// Show success message
var statusMsg = document.createElement('div');
statusMsg.style.color = 'green';
statusMsg.style.fontSize = '12px';
statusMsg.style.marginTop = '5px';
statusMsg.textContent = 'Voices refreshed successfully! Found ' + response.data.length + ' voices.';
button.parentNode.appendChild(statusMsg);
setTimeout(function() {
if (statusMsg.parentNode) {
statusMsg.parentNode.removeChild(statusMsg);
}
}, 3000);
} else {
alert('Error refreshing voices: ' + (response.data || 'Unknown error'));
}
} catch (e) {
console.error('Refresh voices error:', e);
alert('Failed to refresh voices. Please try again.');
}
};
xhr.send('action=twp_refresh_elevenlabs_voices&nonce=' + '<?php echo wp_create_nonce('twp_ajax_nonce'); ?>');
}
function addVoicePreviewButtons(select, voices) {
// Remove existing preview container
var existingPreview = document.getElementById('voice-preview-container');
@@ -4786,6 +4851,36 @@ class TWP_Admin {
}
}
/**
* AJAX handler for refreshing ElevenLabs voices (clears cache)
*/
public function ajax_refresh_elevenlabs_voices() {
check_ajax_referer('twp_ajax_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_die('Unauthorized');
}
// Clear the cached voices
delete_transient('twp_elevenlabs_voices');
// Now fetch fresh voices
$elevenlabs = new TWP_ElevenLabs_API();
$result = $elevenlabs->get_voices(); // This will fetch from API and re-cache
if ($result['success']) {
wp_send_json_success($result['data']['voices']);
} else {
$error_message = 'Failed to refresh voices';
if (is_string($result['error'])) {
$error_message = $result['error'];
} elseif (is_array($result['error']) && isset($result['error']['detail'])) {
$error_message = $result['error']['detail'];
}
wp_send_json_error($error_message);
}
}
/**
* AJAX handler for getting ElevenLabs models
*/