mirror of
https://github.com/dograh-hq/dograh.git
synced 2026-06-19 08:28:10 +02:00
feat: persist split user and bot audio
This commit is contained in:
parent
dd3f2e7323
commit
3d1886c450
30 changed files with 1322 additions and 253 deletions
|
|
@ -10,6 +10,7 @@ from api.db.filters import apply_workflow_run_filters, get_workflow_run_order_cl
|
|||
from api.db.models import CampaignModel, QueuedRunModel, WorkflowRunModel
|
||||
from api.schemas.workflow import WorkflowRunResponseSchema
|
||||
from api.services.workflow.run_usage_response import format_public_cost_info
|
||||
from api.utils.recording_artifacts import get_recording_storage_key
|
||||
|
||||
|
||||
class CampaignClient(BaseDBClient):
|
||||
|
|
@ -45,9 +46,11 @@ class CampaignClient(BaseDBClient):
|
|||
source_id=source_id,
|
||||
created_by=user_id,
|
||||
organization_id=organization_id,
|
||||
retry_config=retry_config
|
||||
if retry_config
|
||||
else CampaignModel.retry_config.default.arg,
|
||||
retry_config=(
|
||||
retry_config
|
||||
if retry_config
|
||||
else CampaignModel.retry_config.default.arg
|
||||
),
|
||||
orchestrator_metadata=orchestrator_metadata,
|
||||
telephony_configuration_id=telephony_configuration_id,
|
||||
)
|
||||
|
|
@ -216,6 +219,12 @@ class CampaignClient(BaseDBClient):
|
|||
"is_completed": run.is_completed,
|
||||
"recording_url": run.recording_url,
|
||||
"transcript_url": run.transcript_url,
|
||||
"user_recording_url": get_recording_storage_key(
|
||||
run.extra, "user"
|
||||
),
|
||||
"bot_recording_url": get_recording_storage_key(
|
||||
run.extra, "bot"
|
||||
),
|
||||
"cost_info": format_public_cost_info(
|
||||
run.cost_info, run.usage_info
|
||||
),
|
||||
|
|
@ -270,9 +279,11 @@ class CampaignClient(BaseDBClient):
|
|||
source_id=parent_campaign.source_id,
|
||||
created_by=parent_campaign.created_by,
|
||||
organization_id=parent_campaign.organization_id,
|
||||
retry_config=retry_config
|
||||
if retry_config
|
||||
else CampaignModel.retry_config.default.arg,
|
||||
retry_config=(
|
||||
retry_config
|
||||
if retry_config
|
||||
else CampaignModel.retry_config.default.arg
|
||||
),
|
||||
orchestrator_metadata=child_meta,
|
||||
rate_limit_per_second=parent_campaign.rate_limit_per_second,
|
||||
total_rows=len(queued_runs_data),
|
||||
|
|
@ -338,8 +349,7 @@ class CampaignClient(BaseDBClient):
|
|||
# Retries create new queued_runs with suffixed source_uuids linked via
|
||||
# parent_queued_run_id, so group by the ROOT queued_run using a
|
||||
# recursive walk and pick the latest workflow_run across the tree.
|
||||
sql = text(
|
||||
f"""
|
||||
sql = text(f"""
|
||||
WITH RECURSIVE run_tree AS (
|
||||
SELECT id AS root_id, id AS run_id
|
||||
FROM queued_runs
|
||||
|
|
@ -366,8 +376,7 @@ class CampaignClient(BaseDBClient):
|
|||
JOIN latest_run_per_root lr ON lr.root_id = q0.id
|
||||
WHERE q0.campaign_id = :cid
|
||||
AND ({tag_filter})
|
||||
"""
|
||||
)
|
||||
""")
|
||||
|
||||
async with self.async_session() as session:
|
||||
result = await session.execute(sql, {"cid": campaign_id})
|
||||
|
|
|
|||
|
|
@ -532,6 +532,9 @@ class WorkflowRunModel(Base):
|
|||
is_completed = Column(Boolean, default=False)
|
||||
recording_url = Column(String, nullable=True)
|
||||
transcript_url = Column(String, nullable=True)
|
||||
extra = Column(
|
||||
JSON, nullable=False, default=dict, server_default=text("'{}'::json")
|
||||
)
|
||||
# Store storage backend as string enum (s3, minio)
|
||||
storage_backend = Column(
|
||||
Enum("s3", "minio", name="storage_backend"),
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ from api.db.models import (
|
|||
)
|
||||
from api.enums import OrganizationConfigurationKey
|
||||
from api.schemas.ai_model_configuration import EffectiveAIModelConfiguration
|
||||
from api.utils.recording_artifacts import get_recording_storage_key
|
||||
|
||||
|
||||
class OrganizationUsageClient(BaseDBClient):
|
||||
|
|
@ -226,6 +227,9 @@ class OrganizationUsageClient(BaseDBClient):
|
|||
"call_duration_seconds": int(round(call_duration)),
|
||||
"recording_url": run.recording_url,
|
||||
"transcript_url": run.transcript_url,
|
||||
"user_recording_url": get_recording_storage_key(run.extra, "user"),
|
||||
"bot_recording_url": get_recording_storage_key(run.extra, "bot"),
|
||||
"extra": run.extra,
|
||||
"public_access_token": run.public_access_token,
|
||||
"phone_number": phone_number,
|
||||
"caller_number": caller_number,
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ from api.db.models import (
|
|||
from api.enums import CallType, StorageBackend
|
||||
from api.schemas.workflow import WorkflowRunResponseSchema
|
||||
from api.services.workflow.run_usage_response import format_public_cost_info
|
||||
from api.utils.recording_artifacts import get_recording_storage_key
|
||||
|
||||
|
||||
class WorkflowRunClient(BaseDBClient):
|
||||
|
|
@ -188,13 +189,19 @@ class WorkflowRunClient(BaseDBClient):
|
|||
"workflow_name": run.workflow.name if run.workflow else None,
|
||||
"user_id": run.workflow.user_id if run.workflow else None,
|
||||
"organization_id": organization.id if organization else None,
|
||||
"organization_name": organization.provider_id
|
||||
if organization
|
||||
else None,
|
||||
"organization_name": (
|
||||
organization.provider_id if organization else None
|
||||
),
|
||||
"mode": run.mode,
|
||||
"is_completed": run.is_completed,
|
||||
"recording_url": run.recording_url,
|
||||
"transcript_url": run.transcript_url,
|
||||
"user_recording_url": get_recording_storage_key(
|
||||
run.extra, "user"
|
||||
),
|
||||
"bot_recording_url": get_recording_storage_key(
|
||||
run.extra, "bot"
|
||||
),
|
||||
"usage_info": run.usage_info,
|
||||
"cost_info": run.cost_info,
|
||||
"initial_context": run.initial_context,
|
||||
|
|
@ -313,6 +320,12 @@ class WorkflowRunClient(BaseDBClient):
|
|||
"is_completed": run.is_completed,
|
||||
"recording_url": run.recording_url,
|
||||
"transcript_url": run.transcript_url,
|
||||
"user_recording_url": get_recording_storage_key(
|
||||
run.extra, "user"
|
||||
),
|
||||
"bot_recording_url": get_recording_storage_key(
|
||||
run.extra, "bot"
|
||||
),
|
||||
"cost_info": format_public_cost_info(
|
||||
run.cost_info, run.usage_info
|
||||
),
|
||||
|
|
@ -340,6 +353,7 @@ class WorkflowRunClient(BaseDBClient):
|
|||
logs: dict | None = None,
|
||||
state: str | None = None,
|
||||
annotations: dict | None = None,
|
||||
extra: dict | None = None,
|
||||
) -> WorkflowRunModel:
|
||||
async with self.async_session() as session:
|
||||
# Use SELECT FOR UPDATE to lock the row during the update
|
||||
|
|
@ -374,6 +388,8 @@ class WorkflowRunClient(BaseDBClient):
|
|||
run.logs = {**run.logs, **logs}
|
||||
if annotations:
|
||||
run.annotations = {**run.annotations, **annotations}
|
||||
if extra:
|
||||
run.extra = {**run.extra, **extra}
|
||||
if is_completed:
|
||||
run.is_completed = is_completed
|
||||
if state:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue