mirror of
https://github.com/dograh-hq/dograh.git
synced 2026-06-28 08:49:42 +02:00
fix: changes to update pipecat version to 0.0.100 (#122)
* feat: add stt evals * add smart turn as provider * chore: remove deprecations * chore: format files * fix: remove deprecated UserIdleProcessor * fix: remove deprecated TranscriptProcessor * chore: update pipecat submodule * feat: add evals visualisation * fix: trigger llm generation on client connected and pipeline started * chore: update pipecat * chore: update pipecat submodule * Add tests * fix: slow loading of workflow page * chore: update pipecat submodule * Show version after release * Fixes #99 * fix: provider check for websocket connection * Fixes #107 * Fix #96 * chore: fix documentation * fix: cloudonix campaign call error --------- Co-authored-by: Sabiha Khan <sabihak89@gmail.com>
This commit is contained in:
parent
a4367bd83b
commit
911c5ed416
104 changed files with 16919 additions and 597 deletions
|
|
@ -360,6 +360,17 @@ class WorkflowRunModel(Base):
|
|||
campaign = relationship("CampaignModel")
|
||||
queued_run_id = Column(Integer, ForeignKey("queued_runs.id"), nullable=True)
|
||||
queued_run = relationship("QueuedRunModel", foreign_keys=[queued_run_id])
|
||||
public_access_token = Column(String(36), nullable=True)
|
||||
|
||||
# Indexes
|
||||
__table_args__ = (
|
||||
Index(
|
||||
"idx_workflow_runs_public_access_token",
|
||||
"public_access_token",
|
||||
unique=True,
|
||||
postgresql_where=text("public_access_token IS NOT NULL"),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
# LoopTalk Testing Models
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ from typing import Optional
|
|||
|
||||
from sqlalchemy import func
|
||||
from sqlalchemy.future import select
|
||||
from sqlalchemy.orm import selectinload
|
||||
from sqlalchemy.orm import load_only, selectinload
|
||||
|
||||
from api.db.base_client import BaseDBClient
|
||||
from api.db.models import WorkflowDefinitionModel, WorkflowModel, WorkflowRunModel
|
||||
|
|
@ -111,6 +111,70 @@ class WorkflowClient(BaseDBClient):
|
|||
result = await session.execute(query)
|
||||
return result.scalars().all()
|
||||
|
||||
async def get_all_workflows_for_listing(
|
||||
self, organization_id: int = None, status: str = None
|
||||
) -> list[WorkflowModel]:
|
||||
"""Get workflows with only the columns needed for listing.
|
||||
|
||||
This is an optimized version that excludes large JSON columns like
|
||||
workflow_definition, template_context_variables, etc.
|
||||
|
||||
Args:
|
||||
organization_id: Filter by organization ID
|
||||
status: Filter by status (active/archived)
|
||||
|
||||
Returns:
|
||||
List of WorkflowModel with only id, name, status, created_at loaded
|
||||
"""
|
||||
async with self.async_session() as session:
|
||||
query = select(WorkflowModel).options(
|
||||
load_only(
|
||||
WorkflowModel.id,
|
||||
WorkflowModel.name,
|
||||
WorkflowModel.status,
|
||||
WorkflowModel.created_at,
|
||||
)
|
||||
)
|
||||
|
||||
if organization_id:
|
||||
query = query.where(WorkflowModel.organization_id == organization_id)
|
||||
|
||||
if status:
|
||||
query = query.where(WorkflowModel.status == status)
|
||||
|
||||
result = await session.execute(query)
|
||||
return result.scalars().all()
|
||||
|
||||
async def get_workflow_counts(self, organization_id: int = None) -> dict[str, int]:
|
||||
"""Get workflow counts by status.
|
||||
|
||||
Args:
|
||||
organization_id: Filter by organization ID
|
||||
|
||||
Returns:
|
||||
Dict with 'total', 'active', 'archived' counts
|
||||
"""
|
||||
async with self.async_session() as session:
|
||||
query = select(
|
||||
WorkflowModel.status,
|
||||
func.count(WorkflowModel.id).label("count"),
|
||||
)
|
||||
|
||||
if organization_id:
|
||||
query = query.where(WorkflowModel.organization_id == organization_id)
|
||||
|
||||
query = query.group_by(WorkflowModel.status)
|
||||
|
||||
result = await session.execute(query)
|
||||
rows = result.all()
|
||||
|
||||
counts = {"total": 0, "active": 0, "archived": 0}
|
||||
for status, count in rows:
|
||||
counts[status] = count
|
||||
counts["total"] += count
|
||||
|
||||
return counts
|
||||
|
||||
async def get_workflow(
|
||||
self, workflow_id: int, user_id: int = None, organization_id: int = None
|
||||
) -> WorkflowModel | None:
|
||||
|
|
@ -310,3 +374,33 @@ class WorkflowClient(BaseDBClient):
|
|||
)
|
||||
)
|
||||
return result.scalar() or 0
|
||||
|
||||
async def get_workflow_run_counts(self, workflow_ids: list[int]) -> dict[int, int]:
|
||||
"""Get run counts for multiple workflows in a single query.
|
||||
|
||||
Args:
|
||||
workflow_ids: List of workflow IDs to get counts for
|
||||
|
||||
Returns:
|
||||
Dict mapping workflow_id to run count
|
||||
"""
|
||||
if not workflow_ids:
|
||||
return {}
|
||||
|
||||
async with self.async_session() as session:
|
||||
result = await session.execute(
|
||||
select(
|
||||
WorkflowRunModel.workflow_id,
|
||||
func.count(WorkflowRunModel.id).label("run_count"),
|
||||
)
|
||||
.where(WorkflowRunModel.workflow_id.in_(workflow_ids))
|
||||
.group_by(WorkflowRunModel.workflow_id)
|
||||
)
|
||||
rows = result.all()
|
||||
|
||||
# Build dict with counts, defaulting to 0 for workflows with no runs
|
||||
counts = {workflow_id: 0 for workflow_id in workflow_ids}
|
||||
for workflow_id, run_count in rows:
|
||||
counts[workflow_id] = run_count
|
||||
|
||||
return counts
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import uuid
|
||||
from datetime import datetime, timezone
|
||||
from typing import Any, Dict, List, Optional, Tuple
|
||||
|
||||
|
|
@ -414,3 +415,56 @@ class WorkflowRunClient(BaseDBClient):
|
|||
|
||||
organization_id = workflow_run.workflow.user.selected_organization_id
|
||||
return workflow_run, organization_id
|
||||
|
||||
async def ensure_public_access_token(self, workflow_run_id: int) -> Optional[str]:
|
||||
"""Generate a public access token if not exists, return existing if present (idempotent).
|
||||
|
||||
Args:
|
||||
workflow_run_id: The ID of the workflow run
|
||||
|
||||
Returns:
|
||||
The public access token string, or None if workflow run not found
|
||||
"""
|
||||
async with self.async_session() as session:
|
||||
result = await session.execute(
|
||||
select(WorkflowRunModel).where(WorkflowRunModel.id == workflow_run_id)
|
||||
)
|
||||
run = result.scalars().first()
|
||||
if not run:
|
||||
return None
|
||||
|
||||
# Return existing token if present
|
||||
if run.public_access_token:
|
||||
return run.public_access_token
|
||||
|
||||
# Generate and persist new token
|
||||
token = str(uuid.uuid4())
|
||||
run.public_access_token = token
|
||||
|
||||
try:
|
||||
await session.commit()
|
||||
except Exception as e:
|
||||
await session.rollback()
|
||||
raise e
|
||||
await session.refresh(run)
|
||||
|
||||
return run.public_access_token
|
||||
|
||||
async def get_workflow_run_by_public_token(
|
||||
self, token: str
|
||||
) -> Optional[WorkflowRunModel]:
|
||||
"""Lookup workflow run by public access token.
|
||||
|
||||
Args:
|
||||
token: The public access token
|
||||
|
||||
Returns:
|
||||
The WorkflowRunModel if found, None otherwise
|
||||
"""
|
||||
async with self.async_session() as session:
|
||||
result = await session.execute(
|
||||
select(WorkflowRunModel).where(
|
||||
WorkflowRunModel.public_access_token == token
|
||||
)
|
||||
)
|
||||
return result.scalars().first()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue