Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/uipath-openai-agents/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
[project]
name = "uipath-openai-agents"
version = "0.0.9"
version = "0.0.10"
description = "Python SDK that enables developers to build and deploy OpenAI agents to the UiPath Cloud Platform"
readme = "README.md"
requires-python = ">=3.11"
dependencies = [
"aiosqlite>=0.20.0",
"openai>=1.0.0",
"openai-agents>=0.6.5",
"openai-agents>=0.11.1",
"openinference-instrumentation-openai-agents>=1.4.0",
"uipath>=2.10.0, <2.11.0",
"uipath-runtime>=0.9.0, <0.10.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from .factory import UiPathOpenAIAgentRuntimeFactory
from .runtime import UiPathOpenAIAgentRuntime
from .schema import get_agent_schema, get_entrypoints_schema
from .storage import SqliteResumableStorage


def register_runtime_factory() -> None:
Expand All @@ -33,6 +34,7 @@ def create_factory(
"get_agent_schema",
"UiPathOpenAIAgentRuntimeFactory",
"UiPathOpenAIAgentRuntime",
"SqliteResumableStorage",
"get_agent_context_type",
"parse_input_to_context",
]
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
"""Factory for creating OpenAI Agents runtimes from openai_agents.json configuration."""

import asyncio
import os
from typing import Any

from agents import Agent
from agents import Agent, SQLiteSession
from openinference.instrumentation.openai_agents import OpenAIAgentsInstrumentor
from uipath.platform.resume_triggers import (
UiPathResumeTriggerHandler,
)
from uipath.runtime import (
UiPathResumableRuntime,
UiPathRuntimeContext,
UiPathRuntimeFactorySettings,
UiPathRuntimeProtocol,
Expand All @@ -20,6 +25,7 @@
UiPathOpenAIAgentsRuntimeError,
)
from uipath_openai_agents.runtime.runtime import UiPathOpenAIAgentRuntime
from uipath_openai_agents.runtime.storage import SqliteResumableStorage


class UiPathOpenAIAgentRuntimeFactory:
Expand All @@ -41,6 +47,8 @@ def __init__(
self._agent_cache: dict[str, Agent] = {}
self._agent_loaders: dict[str, OpenAiAgentLoader] = {}
self._agent_lock = asyncio.Lock()
self._storage: SqliteResumableStorage | None = None
self._storage_lock = asyncio.Lock()

self._setup_instrumentation()

Expand All @@ -54,6 +62,38 @@ def _load_config(self) -> OpenAiAgentsConfig:
self._config = OpenAiAgentsConfig()
return self._config

def _get_connection_string(self) -> str:
"""Get the SQLite connection string used for resumable state."""
if self.context.state_file_path is not None:
return self.context.state_file_path

if self.context.runtime_dir and self.context.state_file:
path = os.path.join(self.context.runtime_dir, self.context.state_file)
if (
not self.context.resume
and self.context.job_id is None
and not self.context.keep_state_file
):
# If not resuming and no job id, delete previous local state.
if os.path.exists(path):
try:
os.remove(path)
except OSError:
pass
os.makedirs(self.context.runtime_dir, exist_ok=True)
return path

default_path = os.path.join("__uipath", "state.db")
os.makedirs(os.path.dirname(default_path), exist_ok=True)
return default_path

async def _get_storage(self) -> SqliteResumableStorage:
"""Get or create the shared resumable storage instance."""
async with self._storage_lock:
if self._storage is None:
self._storage = SqliteResumableStorage(self._get_connection_string())
return self._storage

async def _load_agent(self, entrypoint: str) -> Agent:
"""
Load an agent for the given entrypoint.
Expand Down Expand Up @@ -185,7 +225,7 @@ async def get_storage(self) -> UiPathRuntimeStorageProtocol | None:
"""
Get the shared storage instance.
"""
return None
return await self._get_storage()

async def get_settings(self) -> UiPathRuntimeFactorySettings | None:
"""
Expand Down Expand Up @@ -213,10 +253,23 @@ async def _create_runtime_instance(
Returns:
Configured runtime instance
"""
return UiPathOpenAIAgentRuntime(
storage = await self._get_storage()
trigger_manager = UiPathResumeTriggerHandler()
session = SQLiteSession(session_id=runtime_id, db_path=storage.db_path)

base_runtime = UiPathOpenAIAgentRuntime(
agent=agent,
runtime_id=runtime_id,
entrypoint=entrypoint,
session=session,
storage=storage,
)

return UiPathResumableRuntime(
delegate=base_runtime,
storage=storage,
trigger_manager=trigger_manager,
runtime_id=runtime_id,
)

async def new_runtime(
Expand Down Expand Up @@ -246,5 +299,9 @@ async def dispose(self) -> None:
for loader in self._agent_loaders.values():
await loader.cleanup()

if self._storage is not None:
await self._storage.close()
self._storage = None

self._agent_loaders.clear()
self._agent_cache.clear()
Loading
Loading