|
1 | 1 | from functools import wraps
|
2 | 2 | import inspect
|
| 3 | +import sys |
| 4 | +import azure.functions as func |
3 | 5 | from agents.run import set_default_agent_runner
|
4 | 6 | from azure.durable_functions.models.DurableOrchestrationContext import DurableOrchestrationContext
|
5 | 7 | from durable_openai_runner import DurableOpenAIRunner
|
6 | 8 | from yield_exception import YieldException
|
7 | 9 | from durable_ai_agent_context import DurableAIAgentContext
|
8 | 10 | import event_loop
|
| 11 | +from model_activity import create_invoke_model_activity |
| 12 | + |
| 13 | + |
| 14 | +# Global registry to track which apps have been set up |
| 15 | +_registered_apps = set() |
| 16 | + |
| 17 | + |
| 18 | +def _setup_durable_openai_agent(app: func.FunctionApp): |
| 19 | + """ |
| 20 | + Set up the Durable OpenAI Agent framework for the given FunctionApp. |
| 21 | + This is automatically called when using the framework decorators. |
| 22 | + """ |
| 23 | + app_id = id(app) |
| 24 | + if app_id not in _registered_apps: |
| 25 | + create_invoke_model_activity(app) |
| 26 | + _registered_apps.add(app_id) |
| 27 | + |
| 28 | + |
| 29 | +def _find_function_app_in_module(module): |
| 30 | + """ |
| 31 | + Find a FunctionApp instance in the given module. |
| 32 | + Returns the first FunctionApp instance found, or None if none found. |
| 33 | + """ |
| 34 | + if not hasattr(module, '__dict__'): |
| 35 | + return None |
| 36 | + |
| 37 | + for name, obj in module.__dict__.items(): |
| 38 | + if isinstance(obj, func.FunctionApp): |
| 39 | + return obj |
| 40 | + return None |
| 41 | + |
| 42 | + |
| 43 | +def _auto_setup_durable_openai_agent(decorated_func): |
| 44 | + """ |
| 45 | + Automatically detect and setup the FunctionApp for Durable OpenAI Agents. |
| 46 | + This finds the FunctionApp in the same module as the decorated function. |
| 47 | + """ |
| 48 | + try: |
| 49 | + # Get the module where the decorated function is defined |
| 50 | + func_module = sys.modules.get(decorated_func.__module__) |
| 51 | + if func_module is None: |
| 52 | + return |
| 53 | + |
| 54 | + # Find the FunctionApp instance in that module |
| 55 | + app = _find_function_app_in_module(func_module) |
| 56 | + if app is not None: |
| 57 | + _setup_durable_openai_agent(app) |
| 58 | + except Exception: |
| 59 | + # Silently fail if auto-setup doesn't work |
| 60 | + # The user can still manually call create_invoke_model_activity if needed |
| 61 | + pass |
9 | 62 |
|
10 | 63 |
|
11 | 64 | def durable_openai_agent_orchestrator(func):
|
| 65 | + # Auto-setup: Find and configure the FunctionApp when decorator is applied |
| 66 | + _auto_setup_durable_openai_agent(func) |
| 67 | + |
12 | 68 | @wraps(func)
|
13 | 69 | def wrapper(durable_orchestration_context: DurableOrchestrationContext):
|
14 | 70 | event_loop.ensure_event_loop()
|
|
0 commit comments