mirror of
https://github.com/dograh-hq/dograh.git
synced 2026-07-25 12:01:04 +02:00
chore: incorporate review comments
This commit is contained in:
parent
e486920db2
commit
fdc181e75d
11 changed files with 215 additions and 152 deletions
70
api/services/workflow/configuration_policy.py
Normal file
70
api/services/workflow/configuration_policy.py
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
"""Workflow-configuration policies shared by workflow update surfaces."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from copy import deepcopy
|
||||
from typing import Any
|
||||
|
||||
from api.db import db_client
|
||||
from api.services.organization_preferences import external_pbx_integrations_enabled
|
||||
|
||||
|
||||
class WorkflowConfigurationNotFoundError(LookupError):
|
||||
"""Raised when configuration policy cannot resolve the target workflow."""
|
||||
|
||||
|
||||
class ExternalPBXConfigurationDisabledError(PermissionError):
|
||||
"""Raised when a disabled organization changes external-PBX mappings."""
|
||||
|
||||
|
||||
async def apply_external_pbx_mapping_policy(
|
||||
workflow_configurations: dict[str, Any] | None,
|
||||
*,
|
||||
workflow_id: int,
|
||||
organization_id: int,
|
||||
) -> dict[str, Any] | None:
|
||||
"""Preserve hidden mappings and reject edits while external PBX is disabled.
|
||||
|
||||
Workflow configuration updates replace the stored configuration document. When
|
||||
the External PBX UI is hidden, its field mappings are absent from the request,
|
||||
so they must be copied from the active draft or published definition before the
|
||||
update is persisted.
|
||||
"""
|
||||
if workflow_configurations is None or await external_pbx_integrations_enabled(
|
||||
organization_id
|
||||
):
|
||||
return workflow_configurations
|
||||
|
||||
workflow = await db_client.get_workflow(
|
||||
workflow_id, organization_id=organization_id
|
||||
)
|
||||
if workflow is None:
|
||||
raise WorkflowConfigurationNotFoundError(
|
||||
f"Workflow with id {workflow_id} not found"
|
||||
)
|
||||
|
||||
draft = await db_client.get_draft_version(workflow_id)
|
||||
stored_configurations = (
|
||||
draft.workflow_configurations
|
||||
if draft
|
||||
else workflow.released_definition.workflow_configurations
|
||||
)
|
||||
stored_mappings = (stored_configurations or {}).get(
|
||||
"external_pbx_field_mappings", []
|
||||
)
|
||||
incoming_mappings = workflow_configurations.get(
|
||||
"external_pbx_field_mappings", stored_mappings
|
||||
)
|
||||
|
||||
if incoming_mappings != stored_mappings:
|
||||
raise ExternalPBXConfigurationDisabledError(
|
||||
"External PBX integrations are disabled for this organization. "
|
||||
"Enable them in Platform Settings before changing field mappings."
|
||||
)
|
||||
|
||||
if not stored_mappings:
|
||||
return workflow_configurations
|
||||
|
||||
prepared_configurations = dict(workflow_configurations)
|
||||
prepared_configurations["external_pbx_field_mappings"] = deepcopy(stored_mappings)
|
||||
return prepared_configurations
|
||||
|
|
@ -626,18 +626,6 @@ class CustomToolManager:
|
|||
is_dynamic_transfer = config.get(
|
||||
"destination_source", "static"
|
||||
) == "dynamic" and isinstance(resolver, dict)
|
||||
resolver_phase_muted = False
|
||||
|
||||
def clear_transfer_setup_mute_state() -> None:
|
||||
nonlocal resolver_phase_muted
|
||||
if resolver_phase_muted:
|
||||
self._engine.set_mute_pipeline(False)
|
||||
resolver_phase_muted = False
|
||||
self._engine._queued_speech_mute_state = "idle"
|
||||
|
||||
if is_dynamic_transfer:
|
||||
self._engine.set_mute_pipeline(True)
|
||||
resolver_phase_muted = True
|
||||
|
||||
if is_dynamic_transfer and resolver.get("wait_message"):
|
||||
await self._engine.task.queue_frame(
|
||||
|
|
@ -647,7 +635,6 @@ class CustomToolManager:
|
|||
persist_to_logs=True,
|
||||
)
|
||||
)
|
||||
self._engine._queued_speech_mute_state = "waiting"
|
||||
|
||||
try:
|
||||
resolved_transfer = await resolve_transfer_config(
|
||||
|
|
@ -662,7 +649,6 @@ class CustomToolManager:
|
|||
destination = resolved_transfer.destination
|
||||
timeout_seconds = resolved_transfer.timeout_seconds
|
||||
except TransferResolutionError as e:
|
||||
clear_transfer_setup_mute_state()
|
||||
validation_error_result = {
|
||||
"status": "failed",
|
||||
"message": "I'm sorry, but I couldn't find a valid destination for this transfer.",
|
||||
|
|
@ -678,7 +664,6 @@ class CustomToolManager:
|
|||
resolved_transfer.source == "context_mapping"
|
||||
and not external_pbx_call
|
||||
):
|
||||
clear_transfer_setup_mute_state()
|
||||
await self._handle_transfer_result(
|
||||
{
|
||||
"status": "failed",
|
||||
|
|
@ -702,7 +687,6 @@ class CustomToolManager:
|
|||
"action": "transfer_failed",
|
||||
"reason": "no_destination",
|
||||
}
|
||||
clear_transfer_setup_mute_state()
|
||||
await self._handle_transfer_result(
|
||||
validation_error_result, function_call_params, properties
|
||||
)
|
||||
|
|
@ -720,11 +704,8 @@ class CustomToolManager:
|
|||
persist_to_logs=True,
|
||||
)
|
||||
)
|
||||
self._engine._queued_speech_mute_state = "waiting"
|
||||
else:
|
||||
played = await self._play_config_message(config)
|
||||
if played:
|
||||
self._engine._queued_speech_mute_state = "waiting"
|
||||
await self._play_config_message(config)
|
||||
|
||||
if external_pbx_call:
|
||||
workflow_configurations = (
|
||||
|
|
@ -742,7 +723,6 @@ class CustomToolManager:
|
|||
field_updates=field_updates,
|
||||
)
|
||||
if external_result is not None:
|
||||
clear_transfer_setup_mute_state()
|
||||
if external_result.get("status") == "success":
|
||||
self._engine._gathered_context[
|
||||
"external_pbx_transferred"
|
||||
|
|
@ -779,7 +759,6 @@ class CustomToolManager:
|
|||
"action": "transfer_failed",
|
||||
"reason": "provider_does_not_support_transfer",
|
||||
}
|
||||
clear_transfer_setup_mute_state()
|
||||
await self._handle_transfer_result(
|
||||
validation_error_result, function_call_params, properties
|
||||
)
|
||||
|
|
@ -830,7 +809,6 @@ class CustomToolManager:
|
|||
except Exception as e:
|
||||
logger.error(f"Transfer provider failed: {e}")
|
||||
self._engine.set_mute_pipeline(False)
|
||||
self._engine._queued_speech_mute_state = "idle"
|
||||
await call_transfer_manager.remove_transfer_context(transfer_id)
|
||||
provider_error_result = {
|
||||
"status": "failed",
|
||||
|
|
@ -930,7 +908,6 @@ class CustomToolManager:
|
|||
f"Transfer call tool '{function_name}' execution failed: {e}"
|
||||
)
|
||||
self._engine.set_mute_pipeline(False)
|
||||
self._engine._queued_speech_mute_state = "idle"
|
||||
|
||||
# Handle generic exception with user-friendly message
|
||||
exception_result = {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue