diff --git a/alembic/versions/2025_09_29_1900-ac9d96ea0501_add_run_with_to_workflows_table_and_.py b/alembic/versions/2025_09_29_1900-ac9d96ea0501_add_run_with_to_workflows_table_and_.py new file mode 100644 index 00000000..c954d047 --- /dev/null +++ b/alembic/versions/2025_09_29_1900-ac9d96ea0501_add_run_with_to_workflows_table_and_.py @@ -0,0 +1,33 @@ +"""add run_with to workflows table and observer_cruises table + +Revision ID: ac9d96ea0501 +Revises: e0ccabc005af +Create Date: 2025-09-29 19:00:39.108889+00:00 + +""" + +from typing import Sequence, Union + +import sqlalchemy as sa + +from alembic import op + +# revision identifiers, used by Alembic. +revision: str = "ac9d96ea0501" +down_revision: Union[str, None] = "e0ccabc005af" +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.add_column("observer_cruises", sa.Column("run_with", sa.String(), nullable=True)) + op.add_column("workflows", sa.Column("run_with", sa.String(), nullable=True)) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column("workflows", "run_with") + op.drop_column("observer_cruises", "run_with") + # ### end Alembic commands ### diff --git a/skyvern/forge/sdk/db/client.py b/skyvern/forge/sdk/db/client.py index c7bc98d7..7c59c6eb 100644 --- a/skyvern/forge/sdk/db/client.py +++ b/skyvern/forge/sdk/db/client.py @@ -1396,7 +1396,7 @@ class AgentDB: version: int | None = None, is_saved_task: bool = False, status: WorkflowStatus = WorkflowStatus.published, - generate_script: bool = False, + run_with: str | None = None, ai_fallback: bool = False, cache_key: str | None = None, run_sequentially: bool = False, @@ -1418,7 +1418,7 @@ class AgentDB: model=model, is_saved_task=is_saved_task, status=status, - generate_script=generate_script, + run_with=run_with, ai_fallback=ai_fallback, cache_key=cache_key, run_sequentially=run_sequentially, @@ -1625,7 +1625,7 @@ class AgentDB: description: str | None = None, workflow_definition: dict[str, Any] | None = None, version: int | None = None, - generate_script: bool | None = None, + run_with: str | None = None, cache_key: str | None = None, ) -> Workflow: try: @@ -1644,8 +1644,8 @@ class AgentDB: workflow.workflow_definition = workflow_definition if version is not None: workflow.version = version - if generate_script is not None: - workflow.generate_script = generate_script + if run_with is not None: + workflow.run_with = run_with if cache_key is not None: workflow.cache_key = cache_key await session.commit() @@ -2795,7 +2795,7 @@ class AgentDB: max_screenshot_scrolling_times: int | None = None, extra_http_headers: dict[str, str] | None = None, browser_address: str | None = None, - generate_script: bool = False, + run_with: str | None = None, ) -> TaskV2: async with self.Session() as session: new_task_v2 = TaskV2Model( @@ -2815,7 +2815,7 @@ class AgentDB: max_screenshot_scrolling_times=max_screenshot_scrolling_times, extra_http_headers=extra_http_headers, browser_address=browser_address, - generate_script=generate_script, + run_with=run_with, ) session.add(new_task_v2) await session.commit() diff --git a/skyvern/forge/sdk/db/models.py b/skyvern/forge/sdk/db/models.py index 64b5854c..ae5d04e0 100644 --- a/skyvern/forge/sdk/db/models.py +++ b/skyvern/forge/sdk/db/models.py @@ -245,6 +245,7 @@ class WorkflowModel(Base): model = Column(JSON, nullable=True) status = Column(String, nullable=False, default="published") generate_script = Column(Boolean, default=False, nullable=False) + run_with = Column(String, nullable=True) # 'agent' or 'code' ai_fallback = Column(Boolean, default=False, nullable=False) cache_key = Column(String, nullable=True) run_sequentially = Column(Boolean, nullable=True) @@ -704,7 +705,8 @@ class TaskV2Model(Base): max_screenshot_scrolling_times = Column(Integer, nullable=True) extra_http_headers = Column(JSON, nullable=True) browser_address = Column(String, nullable=True) - generate_script = Column(Boolean, nullable=False, default=False) + generate_script = Column(Boolean, default=False, nullable=False) + run_with = Column(String, nullable=True) # 'agent' or 'code' queued_at = Column(DateTime, nullable=True) started_at = Column(DateTime, nullable=True) diff --git a/skyvern/forge/sdk/db/utils.py b/skyvern/forge/sdk/db/utils.py index 7500eadb..0e78a171 100644 --- a/skyvern/forge/sdk/db/utils.py +++ b/skyvern/forge/sdk/db/utils.py @@ -280,7 +280,7 @@ def convert_to_workflow(workflow_model: WorkflowModel, debug_enabled: bool = Fal deleted_at=workflow_model.deleted_at, status=WorkflowStatus(workflow_model.status), extra_http_headers=workflow_model.extra_http_headers, - generate_script=workflow_model.generate_script, + run_with=workflow_model.run_with, ai_fallback=workflow_model.ai_fallback, cache_key=workflow_model.cache_key, run_sequentially=workflow_model.run_sequentially, diff --git a/skyvern/forge/sdk/routes/agent_protocol.py b/skyvern/forge/sdk/routes/agent_protocol.py index 65386c55..376140f4 100644 --- a/skyvern/forge/sdk/routes/agent_protocol.py +++ b/skyvern/forge/sdk/routes/agent_protocol.py @@ -567,7 +567,7 @@ async def create_workflow_from_prompt( extra_http_headers=data.extra_http_headers, max_iterations=x_max_iterations_override, max_steps=x_max_steps_override, - generate_script=data.generate_script, + run_with=data.run_with, ai_fallback=data.ai_fallback, ) except Exception as e: diff --git a/skyvern/forge/sdk/schemas/task_v2.py b/skyvern/forge/sdk/schemas/task_v2.py index d162929f..a10e48d7 100644 --- a/skyvern/forge/sdk/schemas/task_v2.py +++ b/skyvern/forge/sdk/schemas/task_v2.py @@ -52,7 +52,7 @@ class TaskV2(BaseModel): max_screenshot_scrolls: int | None = Field(default=None, alias="max_screenshot_scrolling_times") extra_http_headers: dict[str, str] | None = None browser_address: str | None = None - generate_script: bool = False + run_with: str | None = None created_at: datetime modified_at: datetime @@ -156,7 +156,7 @@ class TaskV2Request(BaseModel): max_screenshot_scrolls: int | None = None extra_http_headers: dict[str, str] | None = None browser_address: str | None = None - generate_script: bool = False + run_with: str | None = None ai_fallback: bool = False @field_validator("url", "webhook_callback_url", "totp_verification_url") diff --git a/skyvern/forge/sdk/workflow/models/workflow.py b/skyvern/forge/sdk/workflow/models/workflow.py index 762fa074..a4ba0382 100644 --- a/skyvern/forge/sdk/workflow/models/workflow.py +++ b/skyvern/forge/sdk/workflow/models/workflow.py @@ -77,7 +77,7 @@ class Workflow(BaseModel): status: WorkflowStatus = WorkflowStatus.published max_screenshot_scrolls: int | None = None extra_http_headers: dict[str, str] | None = None - generate_script: bool = False + run_with: str | None = None ai_fallback: bool = False cache_key: str | None = None run_sequentially: bool | None = None diff --git a/skyvern/forge/sdk/workflow/service.py b/skyvern/forge/sdk/workflow/service.py index fb185fde..345bfda8 100644 --- a/skyvern/forge/sdk/workflow/service.py +++ b/skyvern/forge/sdk/workflow/service.py @@ -635,7 +635,7 @@ class WorkflowService: is_saved_task: bool = False, status: WorkflowStatus = WorkflowStatus.published, extra_http_headers: dict[str, str] | None = None, - generate_script: bool = False, + run_with: str | None = None, cache_key: str | None = None, ai_fallback: bool | None = None, run_sequentially: bool = False, @@ -658,7 +658,7 @@ class WorkflowService: is_saved_task=is_saved_task, status=status, extra_http_headers=extra_http_headers, - generate_script=generate_script, + run_with=run_with, cache_key=cache_key, ai_fallback=False if ai_fallback is None else ai_fallback, run_sequentially=run_sequentially, @@ -677,7 +677,7 @@ class WorkflowService: extra_http_headers: dict[str, str] | None = None, max_iterations: int | None = None, max_steps: int | None = None, - generate_script: bool = True, + run_with: str | None = None, ai_fallback: bool = True, ) -> Workflow: metadata_prompt = prompt_engine.load_prompt( @@ -720,7 +720,7 @@ class WorkflowService: totp_identifier=totp_identifier, max_screenshot_scrolling_times=max_screenshot_scrolling_times, extra_http_headers=extra_http_headers, - generate_script=generate_script, + run_with=run_with, ai_fallback=ai_fallback, ) @@ -1776,7 +1776,7 @@ class WorkflowService: version=existing_version + 1, is_saved_task=request.is_saved_task, status=request.status, - generate_script=request.generate_script, + run_with=request.run_with, cache_key=request.cache_key, ai_fallback=request.ai_fallback, run_sequentially=request.run_sequentially, @@ -1798,7 +1798,7 @@ class WorkflowService: extra_http_headers=request.extra_http_headers, is_saved_task=request.is_saved_task, status=request.status, - generate_script=request.generate_script, + run_with=request.run_with, cache_key=request.cache_key, ai_fallback=request.ai_fallback, run_sequentially=request.run_sequentially, @@ -2417,7 +2417,7 @@ class WorkflowService: proxy_location: ProxyLocation | None = None, max_screenshot_scrolling_times: int | None = None, extra_http_headers: dict[str, str] | None = None, - generate_script: bool = False, + run_with: str | None = None, status: WorkflowStatus = WorkflowStatus.published, ) -> Workflow: """ @@ -2434,7 +2434,7 @@ class WorkflowService: status=status, max_screenshot_scrolls=max_screenshot_scrolling_times, extra_http_headers=extra_http_headers, - generate_script=generate_script, + run_with=run_with, ) return await app.WORKFLOW_SERVICE.create_workflow_from_request( organization=organization, @@ -2600,8 +2600,6 @@ class WorkflowService: ) -> bool: if workflow_run.run_with == "code": return True - if workflow_run.run_with == "agent": - return False - if workflow.generate_script: + if workflow.run_with == "code": return True return False diff --git a/skyvern/schemas/workflows.py b/skyvern/schemas/workflows.py index 8fe93d2b..f63c396f 100644 --- a/skyvern/schemas/workflows.py +++ b/skyvern/schemas/workflows.py @@ -514,7 +514,7 @@ class WorkflowCreateYAMLRequest(BaseModel): max_screenshot_scrolls: int | None = None extra_http_headers: dict[str, str] | None = None status: WorkflowStatus = WorkflowStatus.published - generate_script: bool = False + run_with: str | None = None ai_fallback: bool = False cache_key: str | None = None run_sequentially: bool = False diff --git a/skyvern/services/task_v2_service.py b/skyvern/services/task_v2_service.py index bc7d5f72..b8bf2a51 100644 --- a/skyvern/services/task_v2_service.py +++ b/skyvern/services/task_v2_service.py @@ -154,7 +154,7 @@ async def initialize_task_v2( totp_identifier: str | None = None, totp_verification_url: str | None = None, webhook_callback_url: str | None = None, - publish_workflow: bool = False, + publish_workflow: bool = True, parent_workflow_run_id: str | None = None, extracted_information_schema: dict | list | str | None = None, error_code_mapping: dict | None = None, @@ -164,11 +164,8 @@ async def initialize_task_v2( browser_session_id: str | None = None, extra_http_headers: dict[str, str] | None = None, browser_address: str | None = None, - generate_script: bool = False, + run_with: str | None = None, ) -> TaskV2: - if generate_script: - publish_workflow = True - task_v2 = await app.DATABASE.create_task_v2( prompt=user_prompt, organization_id=organization.organization_id, @@ -182,7 +179,7 @@ async def initialize_task_v2( max_screenshot_scrolling_times=max_screenshot_scrolling_times, extra_http_headers=extra_http_headers, browser_address=browser_address, - generate_script=generate_script, + run_with=run_with, ) # set task_v2_id in context context = skyvern_context.current() @@ -229,7 +226,7 @@ async def initialize_task_v2( status=workflow_status, max_screenshot_scrolling_times=max_screenshot_scrolling_times, extra_http_headers=extra_http_headers, - generate_script=generate_script, + run_with=run_with, ) workflow_run = await app.WORKFLOW_SERVICE.setup_workflow_run( request_id=None, @@ -901,7 +898,7 @@ async def run_task_v2_helper( context=context, screenshots=completion_screenshots, ) - if task_v2.generate_script: + if task_v2.run_with == "code": # TODO(jdo): not sure about this one... await app.WORKFLOW_SERVICE.generate_script_if_needed( workflow=workflow, workflow_run=workflow_run,