Workflow Copilot: backend side of the first version (#4401)
This commit is contained in:
committed by
GitHub
parent
1e314ce149
commit
e3dd75d7c1
@@ -47,6 +47,8 @@ from skyvern.forge.sdk.db.models import (
|
||||
TaskV2Model,
|
||||
ThoughtModel,
|
||||
TOTPCodeModel,
|
||||
WorkflowCopilotChatMessageModel,
|
||||
WorkflowCopilotChatModel,
|
||||
WorkflowModel,
|
||||
WorkflowParameterModel,
|
||||
WorkflowRunBlockModel,
|
||||
@@ -72,6 +74,7 @@ from skyvern.forge.sdk.db.utils import (
|
||||
convert_to_task,
|
||||
convert_to_task_v2,
|
||||
convert_to_workflow,
|
||||
convert_to_workflow_copilot_chat_message,
|
||||
convert_to_workflow_parameter,
|
||||
convert_to_workflow_run,
|
||||
convert_to_workflow_run_block,
|
||||
@@ -100,6 +103,11 @@ from skyvern.forge.sdk.schemas.task_generations import TaskGeneration
|
||||
from skyvern.forge.sdk.schemas.task_v2 import TaskV2, TaskV2Status, Thought, ThoughtType
|
||||
from skyvern.forge.sdk.schemas.tasks import OrderBy, SortDirection, Task, TaskStatus
|
||||
from skyvern.forge.sdk.schemas.totp_codes import OTPType, TOTPCode
|
||||
from skyvern.forge.sdk.schemas.workflow_copilot import (
|
||||
WorkflowCopilotChat,
|
||||
WorkflowCopilotChatMessage,
|
||||
WorkflowCopilotChatSender,
|
||||
)
|
||||
from skyvern.forge.sdk.schemas.workflow_runs import WorkflowRunBlock
|
||||
from skyvern.forge.sdk.workflow.models.parameter import (
|
||||
AWSSecretParameter,
|
||||
@@ -3640,6 +3648,91 @@ class AgentDB(BaseAlchemyDB):
|
||||
await session.refresh(new_ai_suggestion)
|
||||
return AISuggestion.model_validate(new_ai_suggestion)
|
||||
|
||||
async def create_workflow_copilot_chat(
|
||||
self,
|
||||
organization_id: str,
|
||||
workflow_permanent_id: str,
|
||||
) -> WorkflowCopilotChat:
|
||||
async with self.Session() as session:
|
||||
new_chat = WorkflowCopilotChatModel(
|
||||
organization_id=organization_id,
|
||||
workflow_permanent_id=workflow_permanent_id,
|
||||
)
|
||||
session.add(new_chat)
|
||||
await session.commit()
|
||||
await session.refresh(new_chat)
|
||||
return WorkflowCopilotChat.model_validate(new_chat)
|
||||
|
||||
async def create_workflow_copilot_chat_message(
|
||||
self,
|
||||
organization_id: str,
|
||||
workflow_copilot_chat_id: str,
|
||||
sender: WorkflowCopilotChatSender,
|
||||
content: str,
|
||||
global_llm_context: str | None = None,
|
||||
) -> WorkflowCopilotChatMessage:
|
||||
async with self.Session() as session:
|
||||
new_message = WorkflowCopilotChatMessageModel(
|
||||
workflow_copilot_chat_id=workflow_copilot_chat_id,
|
||||
organization_id=organization_id,
|
||||
sender=sender,
|
||||
content=content,
|
||||
global_llm_context=global_llm_context,
|
||||
)
|
||||
session.add(new_message)
|
||||
await session.commit()
|
||||
await session.refresh(new_message)
|
||||
return convert_to_workflow_copilot_chat_message(new_message, self.debug_enabled)
|
||||
|
||||
async def get_workflow_copilot_chat_messages(
|
||||
self,
|
||||
workflow_copilot_chat_id: str,
|
||||
) -> list[WorkflowCopilotChatMessage]:
|
||||
async with self.Session() as session:
|
||||
query = (
|
||||
select(WorkflowCopilotChatMessageModel)
|
||||
.filter(WorkflowCopilotChatMessageModel.workflow_copilot_chat_id == workflow_copilot_chat_id)
|
||||
.order_by(WorkflowCopilotChatMessageModel.workflow_copilot_chat_message_id.asc())
|
||||
)
|
||||
messages = (await session.scalars(query)).all()
|
||||
return [convert_to_workflow_copilot_chat_message(message, self.debug_enabled) for message in messages]
|
||||
|
||||
async def get_workflow_copilot_chat_by_id(
|
||||
self,
|
||||
organization_id: str,
|
||||
workflow_copilot_chat_id: str,
|
||||
) -> WorkflowCopilotChat | None:
|
||||
async with self.Session() as session:
|
||||
query = (
|
||||
select(WorkflowCopilotChatModel)
|
||||
.filter(WorkflowCopilotChatModel.organization_id == organization_id)
|
||||
.filter(WorkflowCopilotChatModel.workflow_copilot_chat_id == workflow_copilot_chat_id)
|
||||
.order_by(WorkflowCopilotChatModel.created_at.desc())
|
||||
.limit(1)
|
||||
)
|
||||
chat = (await session.scalars(query)).first()
|
||||
if not chat:
|
||||
return None
|
||||
return WorkflowCopilotChat.model_validate(chat)
|
||||
|
||||
async def get_latest_workflow_copilot_chat(
|
||||
self,
|
||||
organization_id: str,
|
||||
workflow_permanent_id: str,
|
||||
) -> WorkflowCopilotChat | None:
|
||||
async with self.Session() as session:
|
||||
query = (
|
||||
select(WorkflowCopilotChatModel)
|
||||
.filter(WorkflowCopilotChatModel.organization_id == organization_id)
|
||||
.filter(WorkflowCopilotChatModel.workflow_permanent_id == workflow_permanent_id)
|
||||
.order_by(WorkflowCopilotChatModel.created_at.desc())
|
||||
.limit(1)
|
||||
)
|
||||
chat = (await session.scalars(query)).first()
|
||||
if not chat:
|
||||
return None
|
||||
return WorkflowCopilotChat.model_validate(chat)
|
||||
|
||||
async def get_task_generation_by_prompt_hash(
|
||||
self,
|
||||
user_prompt_hash: str,
|
||||
|
||||
@@ -69,6 +69,8 @@ WORKFLOW_RUN_PREFIX = "wr"
|
||||
WORKFLOW_SCRIPT_PREFIX = "ws"
|
||||
WORKFLOW_TEMPLATE_PREFIX = "wt"
|
||||
ORGANIZATION_BILLING_PREFIX = "ob"
|
||||
WORKFLOW_COPILOT_CHAT_PREFIX = "wcc"
|
||||
WORKFLOW_COPILOT_CHAT_MESSAGE_PREFIX = "wccm"
|
||||
|
||||
|
||||
def generate_workflow_id() -> str:
|
||||
@@ -266,6 +268,16 @@ def generate_billing_id() -> str:
|
||||
return f"{ORGANIZATION_BILLING_PREFIX}_{int_id}"
|
||||
|
||||
|
||||
def generate_workflow_copilot_chat_id() -> str:
|
||||
int_id = generate_id()
|
||||
return f"{WORKFLOW_COPILOT_CHAT_PREFIX}_{int_id}"
|
||||
|
||||
|
||||
def generate_workflow_copilot_chat_message_id() -> str:
|
||||
int_id = generate_id()
|
||||
return f"{WORKFLOW_COPILOT_CHAT_MESSAGE_PREFIX}_{int_id}"
|
||||
|
||||
|
||||
############# Helper functions below ##############
|
||||
def generate_id() -> int:
|
||||
"""
|
||||
|
||||
@@ -51,6 +51,8 @@ from skyvern.forge.sdk.db.id import (
|
||||
generate_task_v2_id,
|
||||
generate_thought_id,
|
||||
generate_totp_code_id,
|
||||
generate_workflow_copilot_chat_id,
|
||||
generate_workflow_copilot_chat_message_id,
|
||||
generate_workflow_id,
|
||||
generate_workflow_parameter_id,
|
||||
generate_workflow_permanent_id,
|
||||
@@ -1081,3 +1083,40 @@ class ScriptBlockModel(Base):
|
||||
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
|
||||
modified_at = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow, nullable=False)
|
||||
deleted_at = Column(DateTime, nullable=True)
|
||||
|
||||
|
||||
class WorkflowCopilotChatModel(Base):
|
||||
__tablename__ = "workflow_copilot_chats"
|
||||
|
||||
workflow_copilot_chat_id = Column(String, primary_key=True, default=generate_workflow_copilot_chat_id)
|
||||
organization_id = Column(String, nullable=False)
|
||||
workflow_permanent_id = Column(String, nullable=False, index=True)
|
||||
|
||||
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
|
||||
modified_at = Column(
|
||||
DateTime,
|
||||
default=datetime.datetime.utcnow,
|
||||
onupdate=datetime.datetime.utcnow,
|
||||
nullable=False,
|
||||
)
|
||||
|
||||
|
||||
class WorkflowCopilotChatMessageModel(Base):
|
||||
__tablename__ = "workflow_copilot_chat_messages"
|
||||
|
||||
workflow_copilot_chat_message_id = Column(
|
||||
String, primary_key=True, default=generate_workflow_copilot_chat_message_id
|
||||
)
|
||||
workflow_copilot_chat_id = Column(String, nullable=False, index=True)
|
||||
organization_id = Column(String, nullable=False)
|
||||
sender = Column(String, nullable=False)
|
||||
content = Column(UnicodeText, nullable=False)
|
||||
global_llm_context = Column(UnicodeText, nullable=True)
|
||||
|
||||
created_at = Column(DateTime, default=datetime.datetime.utcnow, nullable=False)
|
||||
modified_at = Column(
|
||||
DateTime,
|
||||
default=datetime.datetime.utcnow,
|
||||
onupdate=datetime.datetime.utcnow,
|
||||
nullable=False,
|
||||
)
|
||||
|
||||
@@ -21,6 +21,7 @@ from skyvern.forge.sdk.db.models import (
|
||||
StepModel,
|
||||
TaskModel,
|
||||
TaskV2Model,
|
||||
WorkflowCopilotChatMessageModel,
|
||||
WorkflowModel,
|
||||
WorkflowParameterModel,
|
||||
WorkflowRunBlockModel,
|
||||
@@ -39,6 +40,7 @@ from skyvern.forge.sdk.schemas.organizations import (
|
||||
)
|
||||
from skyvern.forge.sdk.schemas.task_v2 import TaskV2
|
||||
from skyvern.forge.sdk.schemas.tasks import Task, TaskStatus
|
||||
from skyvern.forge.sdk.schemas.workflow_copilot import WorkflowCopilotChatMessage as WorkflowCopilotChatMessageSchema
|
||||
from skyvern.forge.sdk.schemas.workflow_runs import WorkflowRunBlock
|
||||
from skyvern.forge.sdk.workflow.models.parameter import (
|
||||
AWSSecretParameter,
|
||||
@@ -217,6 +219,17 @@ def convert_to_task_v2(task_v2_model: TaskV2Model, debug_enabled: bool = False)
|
||||
return TaskV2.model_validate(task_v2_data)
|
||||
|
||||
|
||||
def convert_to_workflow_copilot_chat_message(
|
||||
message_model: WorkflowCopilotChatMessageModel, debug_enabled: bool = False
|
||||
) -> WorkflowCopilotChatMessageSchema:
|
||||
if debug_enabled:
|
||||
LOG.debug(
|
||||
"Converting WorkflowCopilotChatMessage to WorkflowCopilotChatMessageSchema",
|
||||
workflow_copilot_chat_message_id=message_model.workflow_copilot_chat_message_id,
|
||||
)
|
||||
return WorkflowCopilotChatMessageSchema.model_validate(message_model)
|
||||
|
||||
|
||||
def convert_to_step(step_model: StepModel, debug_enabled: bool = False) -> Step:
|
||||
if debug_enabled:
|
||||
LOG.debug("Converting StepModel to Step", step_id=step_model.step_id)
|
||||
|
||||
Reference in New Issue
Block a user