mirror of
https://github.com/dograh-hq/dograh.git
synced 2026-06-22 08:38:13 +02:00
feat: add Tuner Integration to Dograh (#311)
* Add tuner integration * bump pipecat version * chore: update pipecat submodule to match upstream and use tuner-pipecat-sdk 0.2.0 Update pipecat submodule from 0.0.109.dev23 to 13e98d0d9 (the exact commit upstream dograh-hq/dograh uses after v1.30.1). This installs pipecat-ai as 1.1.0.post277 via setuptools_scm, satisfying tuner-pipecat-sdk 0.2.0's pipecat-ai>=1.0.0 requirement. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * wire tuner * feat: refactor integrations into self contained packages * chore: simplify ensure_public_access_token * fix: remove NodeSpec and make DTOs the source of truth * feat: send relevant signal to mcp using to_mcp_dict * fix: fix tests * cleanup: remove nango integrations * feat: add agents.md for integrations --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Abhishek Kumar <abhishek@a6k.me>
This commit is contained in:
parent
afa78fe859
commit
5f28c1b2a9
93 changed files with 3388 additions and 3414 deletions
|
|
@ -20,7 +20,7 @@ async def sync_campaign_source(ctx: Dict, campaign_id: int) -> None:
|
|||
Phase 1: Syncs data from configured source to queued_runs table
|
||||
- Campaign state should already be 'syncing'
|
||||
- Determines source type from campaign configuration
|
||||
- Fetches data via appropriate sync service (Google Sheets, HubSpot, etc.)
|
||||
- Fetches data via the appropriate sync service
|
||||
- Creates queued_run entries with unique source_uuid
|
||||
- Updates campaign total_rows
|
||||
- Transitions campaign state to 'running' on success
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
"""Execute integrations (QA analysis, webhooks) after workflow run completion."""
|
||||
|
||||
import random
|
||||
from datetime import UTC, datetime
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
import httpx
|
||||
|
|
@ -14,6 +13,11 @@ from api.constants import BACKEND_API_ENDPOINT
|
|||
from api.db import db_client
|
||||
from api.db.models import WorkflowRunModel
|
||||
from api.enums import OrganizationConfigurationKey
|
||||
from api.services.integrations import (
|
||||
IntegrationCompletionContext,
|
||||
has_completion_handlers,
|
||||
run_completion_handlers,
|
||||
)
|
||||
from api.services.pipecat.tracing_config import register_org_langfuse_credentials
|
||||
from api.services.workflow.dto import (
|
||||
QANodeData,
|
||||
|
|
@ -214,16 +218,20 @@ async def run_integrations_post_workflow_run(_ctx, workflow_run_id: int):
|
|||
nodes = workflow_definition.get("nodes", [])
|
||||
qa_nodes = [n for n in nodes if n.get("type") == "qa"]
|
||||
webhook_nodes = [n for n in nodes if n.get("type") == "webhook"]
|
||||
has_registered_integrations = has_completion_handlers(workflow_definition)
|
||||
|
||||
# Step 4: Generate public access token if webhooks exist or campaign_id is set
|
||||
# Step 4: Generate a public access token for any run that needs post-call work.
|
||||
has_campaign = workflow_run.campaign_id is not None
|
||||
if not webhook_nodes and not qa_nodes and not has_campaign:
|
||||
if (
|
||||
not webhook_nodes
|
||||
and not qa_nodes
|
||||
and not has_registered_integrations
|
||||
and not has_campaign
|
||||
):
|
||||
logger.debug("No integration nodes and no campaign, skipping")
|
||||
return
|
||||
|
||||
public_token = None
|
||||
if webhook_nodes or has_campaign:
|
||||
public_token = await db_client.ensure_public_access_token(workflow_run_id)
|
||||
public_token = await db_client.ensure_public_access_token(workflow_run_id)
|
||||
|
||||
# Step 5: Run QA analysis before webhooks
|
||||
if qa_nodes:
|
||||
|
|
@ -263,17 +271,37 @@ async def run_integrations_post_workflow_run(_ctx, workflow_run_id: int):
|
|||
workflow_run_id
|
||||
)
|
||||
|
||||
# Step 6: Execute webhooks
|
||||
# Step 6: Run registered third-party integrations after uploads are complete
|
||||
integration_results = await run_completion_handlers(
|
||||
context=IntegrationCompletionContext(
|
||||
workflow_run_id=workflow_run_id,
|
||||
workflow_run=workflow_run,
|
||||
workflow_definition=workflow_definition,
|
||||
definition_id=definition_id,
|
||||
organization_id=organization_id,
|
||||
public_token=public_token,
|
||||
)
|
||||
)
|
||||
|
||||
if integration_results:
|
||||
await db_client.update_workflow_run(
|
||||
workflow_run_id, annotations=integration_results
|
||||
)
|
||||
workflow_run, _ = await db_client.get_workflow_run_with_context(
|
||||
workflow_run_id
|
||||
)
|
||||
|
||||
# Step 7: Execute webhooks
|
||||
if not webhook_nodes:
|
||||
logger.debug("No webhook nodes in workflow")
|
||||
return
|
||||
|
||||
logger.info(f"Found {len(webhook_nodes)} webhook nodes to execute")
|
||||
|
||||
# Step 7: Build render context (includes annotations from QA)
|
||||
# Step 8: Build render context (includes annotations from QA and integrations)
|
||||
render_context = _build_render_context(workflow_run, public_token)
|
||||
|
||||
# Step 8: Execute each webhook node
|
||||
# Step 9: Execute each webhook node
|
||||
for node in webhook_nodes:
|
||||
node_id = node.get("id", "unknown")
|
||||
try:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue