[Oncall] Deprecate public workflow run total_cost (#6108)
Some checks failed
Run tests and pre-commit / Frontend Lint and Build (push) Waiting to run
Run tests and pre-commit / Run tests and pre-commit hooks (push) Waiting to run
Publish Fern Docs / run (push) Waiting to run
Auto Create GitHub Release on Version Change / check-version-change (push) Has been cancelled
Build Skyvern SDK and publish to PyPI / check-version-change (push) Has been cancelled
Auto Create GitHub Release on Version Change / create-release (push) Has been cancelled
Build Skyvern SDK and publish to PyPI / run-ci (push) Has been cancelled
Build Skyvern SDK and publish to PyPI / build-sdk (push) Has been cancelled

This commit is contained in:
Marc Kelechava 2026-05-21 17:33:20 -07:00 committed by GitHub
parent 6e098278ec
commit e42716149b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 32 additions and 24 deletions

View file

@ -594,6 +594,8 @@ export type WorkflowRunStatusApiResponse = {
downloaded_file_urls: Array<string> | null;
total_steps: number | null;
total_cost: number | null;
credits_used: number;
cached_credits_used: number;
task_v2: TaskV2 | null;
workflow_title: string | null;
browser_session_id: string | null;
@ -628,6 +630,8 @@ export type WorkflowRunStatusApiResponseWithWorkflow = {
downloaded_file_urls: Array<string> | null;
total_steps: number | null;
total_cost: number | null;
credits_used: number;
cached_credits_used: number;
task_v2: TaskV2 | null;
workflow_title: string | null;
browser_session_id: string | null;

View file

@ -2,7 +2,7 @@ from datetime import datetime
from enum import StrEnum
from typing import Any, List
from pydantic import BaseModel, field_validator
from pydantic import BaseModel, Field, field_validator
from typing_extensions import deprecated
from skyvern.forge.sdk.db.enums import WorkflowRunTriggerType
@ -313,7 +313,13 @@ class WorkflowRunResponseBase(BaseModel):
downloaded_file_urls: list[str] | None = None
outputs: dict[str, Any] | None = None
total_steps: int | None = None
total_cost: float | None = None
total_cost: float | None = Field(
default=None,
deprecated=True,
description="Deprecated. Public workflow-run responses no longer expose cost; use credits_used fields instead.",
)
credits_used: int = 0
cached_credits_used: int = 0
task_v2: TaskV2 | None = None
workflow_title: str | None = None
browser_session_id: str | None = None

View file

@ -5200,27 +5200,12 @@ class WorkflowService:
parameters_with_value = {wfp.key: wfrp.value for wfp, wfrp in workflow_parameter_tuples}
total_steps = None
total_cost = None
if include_step_count or include_cost:
if include_cost:
# step counts and block list are independent — fetch in parallel.
(step_count, completed_step_count), workflow_run_blocks = await asyncio.gather(
app.DATABASE.tasks.get_step_counts_by_task_ids(
task_ids=[task.task_id for task in workflow_run_tasks], organization_id=organization_id
),
app.DATABASE.observer.get_workflow_run_blocks(
workflow_run_id=workflow_run_id, organization_id=organization_id
),
)
text_prompt_blocks = [
block for block in workflow_run_blocks if block.block_type == BlockType.TEXT_PROMPT
]
# This is a temporary cost calculation.
total_cost = 0.05 * (completed_step_count + len(text_prompt_blocks))
else:
step_count, _ = await app.DATABASE.tasks.get_step_counts_by_task_ids(
task_ids=[task.task_id for task in workflow_run_tasks], organization_id=organization_id
)
# `include_cost` is retained as a legacy alias for callers that
# previously received `total_steps` alongside deprecated cost data.
step_count, _ = await app.DATABASE.tasks.get_step_counts_by_task_ids(
task_ids=[task.task_id for task in workflow_run_tasks], organization_id=organization_id
)
total_steps = step_count
return WorkflowRunResponseBase(
@ -5249,7 +5234,9 @@ class WorkflowService:
downloaded_file_urls=downloaded_file_urls,
outputs=outputs,
total_steps=total_steps,
total_cost=total_cost,
total_cost=None,
credits_used=workflow_run.credits_used,
cached_credits_used=workflow_run.cached_credits_used,
workflow_title=workflow.title,
browser_session_id=workflow_run.browser_session_id,
browser_profile_id=workflow_run.browser_profile_id,

View file

@ -158,7 +158,9 @@ def build_sample_workflow_run_payload(run_id: str | None = None) -> dict:
downloaded_file_urls=[],
outputs={"result": "success", "data": "Sample workflow output"},
total_steps=5,
total_cost=0.05,
total_cost=None,
credits_used=5,
cached_credits_used=2,
workflow_title="Sample Workflow",
browser_session_id="pbs_sample_123456",
errors=[],

View file

@ -12,6 +12,7 @@ from datetime import datetime, timezone
from skyvern.forge.sdk.workflow.models.workflow import WorkflowRunResponseBase, WorkflowRunStatus
from skyvern.schemas.runs import RunStatus, RunType, WorkflowRunRequest, WorkflowRunResponse
from skyvern.services.webhook_service import build_sample_workflow_run_payload
def _make_status_response() -> WorkflowRunResponseBase:
@ -113,3 +114,11 @@ def test_webhook_replay_payload_includes_timestamps() -> None:
assert payload_dict["queued_at"] is not None, "queued_at should not be null in webhook replay payload"
assert payload_dict["started_at"] is not None, "started_at should not be null in webhook replay payload"
assert payload_dict["finished_at"] is not None, "finished_at should not be null in webhook replay payload"
def test_sample_workflow_webhook_payload_uses_public_credit_fields() -> None:
payload = build_sample_workflow_run_payload("wr_sample_test")
assert payload["total_cost"] is None
assert payload["credits_used"] == 5
assert payload["cached_credits_used"] == 2