openai-sdk-helpers 0.0.2__py3-none-any.whl → 0.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- openai_sdk_helpers/prompt/summarizer.jinja +7 -0
- openai_sdk_helpers/prompt/translator.jinja +7 -0
- openai_sdk_helpers/prompt/validator.jinja +7 -0
- openai_sdk_helpers/py.typed +0 -0
- {openai_sdk_helpers-0.0.2.dist-info → openai_sdk_helpers-0.0.3.dist-info}/METADATA +57 -4
- openai_sdk_helpers-0.0.3.dist-info/RECORD +8 -0
- openai_sdk_helpers/__init__.py +0 -34
- openai_sdk_helpers/agent/__init__.py +0 -23
- openai_sdk_helpers/agent/base.py +0 -432
- openai_sdk_helpers/agent/config.py +0 -66
- openai_sdk_helpers/agent/project_manager.py +0 -416
- openai_sdk_helpers/agent/runner.py +0 -117
- openai_sdk_helpers/agent/utils.py +0 -47
- openai_sdk_helpers/agent/vector_search.py +0 -418
- openai_sdk_helpers/agent/web_search.py +0 -404
- openai_sdk_helpers/config.py +0 -141
- openai_sdk_helpers/enums/__init__.py +0 -7
- openai_sdk_helpers/enums/base.py +0 -17
- openai_sdk_helpers/environment.py +0 -27
- openai_sdk_helpers/prompt/__init__.py +0 -77
- openai_sdk_helpers/response/__init__.py +0 -16
- openai_sdk_helpers/response/base.py +0 -477
- openai_sdk_helpers/response/messages.py +0 -211
- openai_sdk_helpers/response/runner.py +0 -42
- openai_sdk_helpers/response/tool_call.py +0 -70
- openai_sdk_helpers/structure/__init__.py +0 -57
- openai_sdk_helpers/structure/base.py +0 -591
- openai_sdk_helpers/structure/plan/__init__.py +0 -13
- openai_sdk_helpers/structure/plan/enum.py +0 -48
- openai_sdk_helpers/structure/plan/plan.py +0 -104
- openai_sdk_helpers/structure/plan/task.py +0 -122
- openai_sdk_helpers/structure/prompt.py +0 -24
- openai_sdk_helpers/structure/responses.py +0 -148
- openai_sdk_helpers/structure/summary.py +0 -65
- openai_sdk_helpers/structure/vector_search.py +0 -82
- openai_sdk_helpers/structure/web_search.py +0 -46
- openai_sdk_helpers/utils/__init__.py +0 -13
- openai_sdk_helpers/utils/core.py +0 -208
- openai_sdk_helpers/vector_storage/__init__.py +0 -15
- openai_sdk_helpers/vector_storage/cleanup.py +0 -91
- openai_sdk_helpers/vector_storage/storage.py +0 -501
- openai_sdk_helpers/vector_storage/types.py +0 -58
- openai_sdk_helpers-0.0.2.dist-info/RECORD +0 -40
- {openai_sdk_helpers-0.0.2.dist-info → openai_sdk_helpers-0.0.3.dist-info}/WHEEL +0 -0
- {openai_sdk_helpers-0.0.2.dist-info → openai_sdk_helpers-0.0.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,416 +0,0 @@
|
|
|
1
|
-
"""Generic project manager for coordinating agent plans."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import asyncio
|
|
6
|
-
import inspect
|
|
7
|
-
import logging
|
|
8
|
-
import threading
|
|
9
|
-
from datetime import datetime
|
|
10
|
-
from pathlib import Path
|
|
11
|
-
from typing import Any, Callable, Dict, List, Optional
|
|
12
|
-
|
|
13
|
-
from ..structure import AgentEnum, AgentTaskStructure, PlanStructure, PromptStructure
|
|
14
|
-
from ..environment import DATETIME_FMT
|
|
15
|
-
from ..utils import JSONSerializable, log
|
|
16
|
-
from .base import BaseAgent
|
|
17
|
-
from .config import AgentConfig
|
|
18
|
-
|
|
19
|
-
BuildBriefFn = Callable[[str], PromptStructure]
|
|
20
|
-
BuildPlanFn = Callable[[str], PlanStructure]
|
|
21
|
-
ExecutePlanFn = Callable[[PlanStructure], List[str]]
|
|
22
|
-
SummarizeFn = Callable[[List[str]], str]
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
class ProjectManager(BaseAgent, JSONSerializable):
|
|
26
|
-
"""Coordinate agent plans while persisting project state and outputs.
|
|
27
|
-
|
|
28
|
-
Methods
|
|
29
|
-
-------
|
|
30
|
-
build_instructions(prompt)
|
|
31
|
-
Summarize the prompt into a concise brief.
|
|
32
|
-
build_plan()
|
|
33
|
-
Create a list of ``AgentTaskStructure`` entries for the project.
|
|
34
|
-
execute_plan()
|
|
35
|
-
Run each task sequentially while tracking status and timing.
|
|
36
|
-
summarize_plan(results)
|
|
37
|
-
Summarize a collection of result strings.
|
|
38
|
-
to_dict()
|
|
39
|
-
Return a JSON-serializable snapshot of stored project data.
|
|
40
|
-
save()
|
|
41
|
-
Persist the stored project data to a JSON file.
|
|
42
|
-
"""
|
|
43
|
-
|
|
44
|
-
def __init__(
|
|
45
|
-
self,
|
|
46
|
-
build_brief_fn: BuildBriefFn,
|
|
47
|
-
build_plan_fn: BuildPlanFn,
|
|
48
|
-
execute_plan_fn: ExecutePlanFn,
|
|
49
|
-
summarize_fn: SummarizeFn,
|
|
50
|
-
module_data_path: Path,
|
|
51
|
-
module_name: str,
|
|
52
|
-
config: Optional[AgentConfig] = None,
|
|
53
|
-
prompt_dir: Optional[Path] = None,
|
|
54
|
-
default_model: Optional[str] = None,
|
|
55
|
-
) -> None:
|
|
56
|
-
"""Initialize the project manager with injected workflow helpers.
|
|
57
|
-
|
|
58
|
-
Parameters
|
|
59
|
-
----------
|
|
60
|
-
build_brief_fn
|
|
61
|
-
Callable that generates a prompt brief from the input string.
|
|
62
|
-
build_plan_fn
|
|
63
|
-
Callable that generates a plan from the prompt brief.
|
|
64
|
-
execute_plan_fn
|
|
65
|
-
Callable that executes a plan and returns results.
|
|
66
|
-
summarize_fn
|
|
67
|
-
Callable that summarizes a list of result strings.
|
|
68
|
-
module_data_path
|
|
69
|
-
Base path for persisting project artifacts.
|
|
70
|
-
module_name
|
|
71
|
-
Name of the parent module for data organization.
|
|
72
|
-
config
|
|
73
|
-
Optional agent configuration describing prompts and metadata.
|
|
74
|
-
prompt_dir
|
|
75
|
-
Optional directory holding prompt templates.
|
|
76
|
-
default_model
|
|
77
|
-
Optional fallback model identifier.
|
|
78
|
-
|
|
79
|
-
Returns
|
|
80
|
-
-------
|
|
81
|
-
None
|
|
82
|
-
"""
|
|
83
|
-
if config is None:
|
|
84
|
-
config = AgentConfig(
|
|
85
|
-
name="project_manager",
|
|
86
|
-
description="Coordinates agents for planning and summarization.",
|
|
87
|
-
)
|
|
88
|
-
super().__init__(
|
|
89
|
-
config=config, prompt_dir=prompt_dir, default_model=default_model
|
|
90
|
-
)
|
|
91
|
-
self._build_brief_fn = build_brief_fn
|
|
92
|
-
self._build_plan_fn = build_plan_fn
|
|
93
|
-
self._execute_plan_fn = execute_plan_fn
|
|
94
|
-
self._summarize_fn = summarize_fn
|
|
95
|
-
self._module_data_path = Path(module_data_path)
|
|
96
|
-
self._module_name = module_name
|
|
97
|
-
|
|
98
|
-
self.prompt: Optional[str] = None
|
|
99
|
-
self.brief: Optional[PromptStructure] = None
|
|
100
|
-
self.plan: PlanStructure = PlanStructure()
|
|
101
|
-
self.summary: Optional[str] = None
|
|
102
|
-
self.start_date: Optional[datetime] = None
|
|
103
|
-
self.end_date: Optional[datetime] = None
|
|
104
|
-
|
|
105
|
-
def build_instructions(self, prompt: str) -> None:
|
|
106
|
-
"""Return a concise brief for the project.
|
|
107
|
-
|
|
108
|
-
Parameters
|
|
109
|
-
----------
|
|
110
|
-
prompt : str
|
|
111
|
-
The core request or goal for the project.
|
|
112
|
-
|
|
113
|
-
Returns
|
|
114
|
-
-------
|
|
115
|
-
None
|
|
116
|
-
"""
|
|
117
|
-
log("build_instructions", level=logging.INFO)
|
|
118
|
-
self.start_date = datetime.utcnow()
|
|
119
|
-
self.prompt = prompt
|
|
120
|
-
self.brief = self._build_brief_fn(prompt)
|
|
121
|
-
self.save()
|
|
122
|
-
|
|
123
|
-
def build_plan(self) -> None:
|
|
124
|
-
"""Generate and store a structured plan based on the current brief.
|
|
125
|
-
|
|
126
|
-
Raises
|
|
127
|
-
------
|
|
128
|
-
ValueError
|
|
129
|
-
If called before :meth:`build_instructions`.
|
|
130
|
-
|
|
131
|
-
Returns
|
|
132
|
-
-------
|
|
133
|
-
None
|
|
134
|
-
"""
|
|
135
|
-
log("build_plan", level=logging.INFO)
|
|
136
|
-
if not self.brief:
|
|
137
|
-
raise ValueError("Brief is required before building a plan.")
|
|
138
|
-
|
|
139
|
-
plan = self._build_plan_fn(self.brief.prompt)
|
|
140
|
-
if isinstance(plan, PlanStructure):
|
|
141
|
-
self.plan = plan
|
|
142
|
-
self.save()
|
|
143
|
-
|
|
144
|
-
def execute_plan(self) -> List[str]:
|
|
145
|
-
"""Run each task, updating status, timestamps, and recorded results.
|
|
146
|
-
|
|
147
|
-
Returns
|
|
148
|
-
-------
|
|
149
|
-
list[str]
|
|
150
|
-
Flattened list of results from all executed tasks.
|
|
151
|
-
"""
|
|
152
|
-
log("execute_plan", level=logging.INFO)
|
|
153
|
-
if not self.plan:
|
|
154
|
-
log("No tasks to execute.", level=logging.WARNING)
|
|
155
|
-
return []
|
|
156
|
-
|
|
157
|
-
compiled_results = self._execute_plan_fn(self.plan)
|
|
158
|
-
self.save()
|
|
159
|
-
return compiled_results
|
|
160
|
-
|
|
161
|
-
def summarize_plan(self, results: Optional[List[str]] = None) -> str:
|
|
162
|
-
"""Summarize a collection of task outputs.
|
|
163
|
-
|
|
164
|
-
Parameters
|
|
165
|
-
----------
|
|
166
|
-
results : list[str], optional
|
|
167
|
-
List of string outputs gathered from task execution. Defaults to
|
|
168
|
-
``None``, which uses the stored plan task results if available.
|
|
169
|
-
|
|
170
|
-
Returns
|
|
171
|
-
-------
|
|
172
|
-
str
|
|
173
|
-
Concise summary derived from the provided results.
|
|
174
|
-
"""
|
|
175
|
-
log("summarize_plan", level=logging.INFO)
|
|
176
|
-
|
|
177
|
-
if results is None:
|
|
178
|
-
results = []
|
|
179
|
-
if self.plan and self.plan.tasks:
|
|
180
|
-
for task in self.plan.tasks:
|
|
181
|
-
results.extend(task.results or [])
|
|
182
|
-
|
|
183
|
-
if not results:
|
|
184
|
-
self.summary = ""
|
|
185
|
-
return self.summary
|
|
186
|
-
|
|
187
|
-
self.summary = self._summarize_fn(results)
|
|
188
|
-
self.end_date = datetime.utcnow()
|
|
189
|
-
self.save()
|
|
190
|
-
return self.summary
|
|
191
|
-
|
|
192
|
-
def run_plan(self, prompt: str) -> None:
|
|
193
|
-
"""Execute the full workflow for the provided prompt.
|
|
194
|
-
|
|
195
|
-
Parameters
|
|
196
|
-
----------
|
|
197
|
-
prompt : str
|
|
198
|
-
The request or question to analyze and summarize.
|
|
199
|
-
|
|
200
|
-
Returns
|
|
201
|
-
-------
|
|
202
|
-
None
|
|
203
|
-
"""
|
|
204
|
-
self.build_instructions(prompt)
|
|
205
|
-
self.build_plan()
|
|
206
|
-
results = self.execute_plan()
|
|
207
|
-
self.summarize_plan(results)
|
|
208
|
-
|
|
209
|
-
@property
|
|
210
|
-
def file_path(self) -> Path:
|
|
211
|
-
"""Return the path where the project snapshot will be stored.
|
|
212
|
-
|
|
213
|
-
Returns
|
|
214
|
-
-------
|
|
215
|
-
Path
|
|
216
|
-
Location of the JSON artifact for the current run.
|
|
217
|
-
"""
|
|
218
|
-
if not self.start_date:
|
|
219
|
-
self.start_date = datetime.utcnow()
|
|
220
|
-
start_date_str = self.start_date.strftime(DATETIME_FMT)
|
|
221
|
-
return self._module_data_path / self._module_name / f"{start_date_str}.json"
|
|
222
|
-
|
|
223
|
-
def save(self) -> Path:
|
|
224
|
-
"""Persist the current project state to disk.
|
|
225
|
-
|
|
226
|
-
Returns
|
|
227
|
-
-------
|
|
228
|
-
Path
|
|
229
|
-
Path to the saved JSON artifact.
|
|
230
|
-
"""
|
|
231
|
-
self.to_json_file(self.file_path)
|
|
232
|
-
return self.file_path
|
|
233
|
-
|
|
234
|
-
@staticmethod
|
|
235
|
-
def _run_task(
|
|
236
|
-
task: AgentTaskStructure,
|
|
237
|
-
agent_callable: Callable[..., Any],
|
|
238
|
-
aggregated_context: List[str],
|
|
239
|
-
) -> Any:
|
|
240
|
-
"""Execute a single task and return the raw result.
|
|
241
|
-
|
|
242
|
-
Parameters
|
|
243
|
-
----------
|
|
244
|
-
task : AgentTaskStructure
|
|
245
|
-
Task definition containing the callable and inputs.
|
|
246
|
-
aggregated_context : list[str]
|
|
247
|
-
Context combined from the task and prior task outputs.
|
|
248
|
-
|
|
249
|
-
Returns
|
|
250
|
-
-------
|
|
251
|
-
Any
|
|
252
|
-
Raw output from the underlying callable.
|
|
253
|
-
"""
|
|
254
|
-
task_type = ProjectManager._normalize_task_type(task.task_type)
|
|
255
|
-
prompt_with_context = task.prompt
|
|
256
|
-
if aggregated_context and task_type not in {"WebAgentSearch", "VectorSearch"}:
|
|
257
|
-
context_block = "\n".join(aggregated_context)
|
|
258
|
-
prompt_with_context = f"{task.prompt}\n\nContext:\n{context_block}"
|
|
259
|
-
|
|
260
|
-
try:
|
|
261
|
-
if task_type == "summarizer":
|
|
262
|
-
summary_chunks: List[str] = [task.prompt] + aggregated_context
|
|
263
|
-
output = agent_callable(summary_chunks)
|
|
264
|
-
elif task_type in {"WebAgentSearch", "VectorSearch"}:
|
|
265
|
-
output = agent_callable(task.prompt)
|
|
266
|
-
else:
|
|
267
|
-
output = agent_callable(
|
|
268
|
-
prompt_with_context,
|
|
269
|
-
context=aggregated_context,
|
|
270
|
-
)
|
|
271
|
-
except TypeError:
|
|
272
|
-
output = agent_callable(prompt_with_context)
|
|
273
|
-
except Exception as exc: # pragma: no cover - defensive guard
|
|
274
|
-
log(
|
|
275
|
-
f"Task '{task.task_type}' encountered an error: {exc}",
|
|
276
|
-
level=logging.ERROR,
|
|
277
|
-
)
|
|
278
|
-
return f"Task error: {exc}"
|
|
279
|
-
return ProjectManager._resolve_result(output)
|
|
280
|
-
|
|
281
|
-
@staticmethod
|
|
282
|
-
def _run_task_in_thread(
|
|
283
|
-
task: AgentTaskStructure,
|
|
284
|
-
agent_callable: Callable[..., Any],
|
|
285
|
-
aggregated_context: List[str],
|
|
286
|
-
) -> Any:
|
|
287
|
-
"""Execute a task in a background thread to avoid event-loop conflicts."""
|
|
288
|
-
result_container: Dict[str, Any] = {"result": None, "error": None}
|
|
289
|
-
|
|
290
|
-
def _runner() -> None:
|
|
291
|
-
try:
|
|
292
|
-
result_container["result"] = ProjectManager._run_task(
|
|
293
|
-
task,
|
|
294
|
-
agent_callable=agent_callable,
|
|
295
|
-
aggregated_context=aggregated_context,
|
|
296
|
-
)
|
|
297
|
-
except Exception as exc: # pragma: no cover - defensive guard
|
|
298
|
-
result_container["error"] = exc
|
|
299
|
-
|
|
300
|
-
thread = threading.Thread(target=_runner)
|
|
301
|
-
thread.start()
|
|
302
|
-
thread.join()
|
|
303
|
-
if result_container["error"] is not None:
|
|
304
|
-
raise result_container["error"]
|
|
305
|
-
return result_container["result"]
|
|
306
|
-
|
|
307
|
-
@staticmethod
|
|
308
|
-
def _resolve_result(result: Any) -> Any:
|
|
309
|
-
"""Return awaited results when the callable is asynchronous.
|
|
310
|
-
|
|
311
|
-
Parameters
|
|
312
|
-
----------
|
|
313
|
-
result : Any
|
|
314
|
-
Potentially awaitable output from a task callable.
|
|
315
|
-
|
|
316
|
-
Returns
|
|
317
|
-
-------
|
|
318
|
-
Any
|
|
319
|
-
Resolved output, awaited when necessary.
|
|
320
|
-
"""
|
|
321
|
-
if not inspect.isawaitable(result):
|
|
322
|
-
return result
|
|
323
|
-
|
|
324
|
-
awaitable: asyncio.Future[Any] | asyncio.Task[Any] | Any = result
|
|
325
|
-
coroutine = (
|
|
326
|
-
awaitable
|
|
327
|
-
if inspect.iscoroutine(awaitable)
|
|
328
|
-
else ProjectManager._await_wrapper(awaitable)
|
|
329
|
-
)
|
|
330
|
-
|
|
331
|
-
try:
|
|
332
|
-
loop = asyncio.get_running_loop()
|
|
333
|
-
except RuntimeError:
|
|
334
|
-
return asyncio.run(coroutine)
|
|
335
|
-
|
|
336
|
-
if loop.is_running():
|
|
337
|
-
resolved_result: Any = None
|
|
338
|
-
|
|
339
|
-
def _run_in_thread() -> None:
|
|
340
|
-
nonlocal resolved_result
|
|
341
|
-
resolved_result = asyncio.run(coroutine)
|
|
342
|
-
|
|
343
|
-
thread = threading.Thread(target=_run_in_thread, daemon=True)
|
|
344
|
-
thread.start()
|
|
345
|
-
thread.join()
|
|
346
|
-
return resolved_result
|
|
347
|
-
|
|
348
|
-
return loop.run_until_complete(coroutine)
|
|
349
|
-
|
|
350
|
-
@staticmethod
|
|
351
|
-
async def _await_wrapper(awaitable: Any) -> Any:
|
|
352
|
-
"""Await a generic awaitable and return its result."""
|
|
353
|
-
return await awaitable
|
|
354
|
-
|
|
355
|
-
@staticmethod
|
|
356
|
-
def _normalize_results(result: Any) -> List[str]:
|
|
357
|
-
"""Convert agent outputs into a list of strings.
|
|
358
|
-
|
|
359
|
-
Parameters
|
|
360
|
-
----------
|
|
361
|
-
result : Any
|
|
362
|
-
Raw output from a task execution.
|
|
363
|
-
|
|
364
|
-
Returns
|
|
365
|
-
-------
|
|
366
|
-
list[str]
|
|
367
|
-
Normalized string values representing the output.
|
|
368
|
-
"""
|
|
369
|
-
if result is None:
|
|
370
|
-
return []
|
|
371
|
-
if isinstance(result, list):
|
|
372
|
-
return [str(item) for item in result]
|
|
373
|
-
return [str(result)]
|
|
374
|
-
|
|
375
|
-
def _persist_task_results(self, task: AgentTaskStructure) -> Path:
|
|
376
|
-
"""Write task context and results to disk for future analysis."""
|
|
377
|
-
run_dir = self._get_run_directory()
|
|
378
|
-
task_label = self._task_label(task)
|
|
379
|
-
file_path = run_dir / f"{task_label}.json"
|
|
380
|
-
task.to_json_file(str(file_path))
|
|
381
|
-
return file_path
|
|
382
|
-
|
|
383
|
-
def _get_run_directory(self) -> Path:
|
|
384
|
-
"""Return (and create) the directory used to persist task artifacts."""
|
|
385
|
-
if not hasattr(self, "_run_directory"):
|
|
386
|
-
timestamp = datetime.utcnow().strftime("%Y%m%d_%H%M%S")
|
|
387
|
-
self._run_directory = (
|
|
388
|
-
self._module_data_path
|
|
389
|
-
/ Path(self._module_name)
|
|
390
|
-
/ "project_manager"
|
|
391
|
-
/ timestamp
|
|
392
|
-
)
|
|
393
|
-
self._run_directory.mkdir(parents=True, exist_ok=True)
|
|
394
|
-
return self._run_directory
|
|
395
|
-
|
|
396
|
-
@staticmethod
|
|
397
|
-
def _task_label(task: AgentTaskStructure) -> str:
|
|
398
|
-
"""Generate a filesystem-safe label for the task."""
|
|
399
|
-
task_type = ProjectManager._normalize_task_type(task.task_type)
|
|
400
|
-
base = (task_type or "task").replace(" ", "_").lower()
|
|
401
|
-
return f"{base}_{task_type}"
|
|
402
|
-
|
|
403
|
-
@staticmethod
|
|
404
|
-
def _normalize_task_type(task_type: AgentEnum | str) -> str:
|
|
405
|
-
"""Return the normalized task type string."""
|
|
406
|
-
if isinstance(task_type, AgentEnum):
|
|
407
|
-
return task_type.value
|
|
408
|
-
if task_type in AgentEnum.__members__:
|
|
409
|
-
return AgentEnum.__members__[task_type].value
|
|
410
|
-
try:
|
|
411
|
-
return AgentEnum(task_type).value
|
|
412
|
-
except ValueError:
|
|
413
|
-
return str(task_type)
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
__all__ = ["ProjectManager"]
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
"""Convenience wrappers for running OpenAI agents.
|
|
2
|
-
|
|
3
|
-
These helpers provide a narrow surface around the lower-level functions in
|
|
4
|
-
``openai-sdk-helpers.agent.base`` so that callers can execute agents with consistent
|
|
5
|
-
signatures whether they need asynchronous, synchronous, or streamed results.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from __future__ import annotations
|
|
9
|
-
|
|
10
|
-
from typing import Any, Dict, Optional
|
|
11
|
-
|
|
12
|
-
from agents import Agent, RunResult, RunResultStreaming
|
|
13
|
-
|
|
14
|
-
from .base import _run_agent, _run_agent_streamed, _run_agent_sync
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
async def run(
|
|
18
|
-
agent: Agent,
|
|
19
|
-
agent_input: str,
|
|
20
|
-
agent_context: Optional[Dict[str, Any]] = None,
|
|
21
|
-
output_type: Optional[Any] = None,
|
|
22
|
-
) -> Any:
|
|
23
|
-
"""Run an ``Agent`` asynchronously.
|
|
24
|
-
|
|
25
|
-
Parameters
|
|
26
|
-
----------
|
|
27
|
-
agent
|
|
28
|
-
Configured agent instance to execute.
|
|
29
|
-
agent_input
|
|
30
|
-
Prompt or query string for the agent.
|
|
31
|
-
agent_context
|
|
32
|
-
Optional context dictionary passed to the agent. Default ``None``.
|
|
33
|
-
output_type
|
|
34
|
-
Optional type used to cast the final output. Default ``None``.
|
|
35
|
-
|
|
36
|
-
Returns
|
|
37
|
-
-------
|
|
38
|
-
Any
|
|
39
|
-
Agent response, optionally converted to ``output_type``.
|
|
40
|
-
"""
|
|
41
|
-
return await _run_agent(
|
|
42
|
-
agent=agent,
|
|
43
|
-
agent_input=agent_input,
|
|
44
|
-
agent_context=agent_context,
|
|
45
|
-
output_type=output_type,
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def run_sync(
|
|
50
|
-
agent: Agent,
|
|
51
|
-
agent_input: str,
|
|
52
|
-
agent_context: Optional[Dict[str, Any]] = None,
|
|
53
|
-
output_type: Optional[Any] = None,
|
|
54
|
-
) -> Any:
|
|
55
|
-
"""Run an ``Agent`` synchronously.
|
|
56
|
-
|
|
57
|
-
Parameters
|
|
58
|
-
----------
|
|
59
|
-
agent
|
|
60
|
-
Configured agent instance to execute.
|
|
61
|
-
agent_input
|
|
62
|
-
Prompt or query string for the agent.
|
|
63
|
-
agent_context
|
|
64
|
-
Optional context dictionary passed to the agent. Default ``None``.
|
|
65
|
-
output_type
|
|
66
|
-
Optional type used to cast the final output. Default ``None``.
|
|
67
|
-
|
|
68
|
-
Returns
|
|
69
|
-
-------
|
|
70
|
-
Any
|
|
71
|
-
Agent response, optionally converted to ``output_type``.
|
|
72
|
-
"""
|
|
73
|
-
result: RunResult = _run_agent_sync(
|
|
74
|
-
agent=agent,
|
|
75
|
-
agent_input=agent_input,
|
|
76
|
-
agent_context=agent_context,
|
|
77
|
-
)
|
|
78
|
-
if output_type:
|
|
79
|
-
return result.final_output_as(output_type)
|
|
80
|
-
return result
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
def run_streamed(
|
|
84
|
-
agent: Agent,
|
|
85
|
-
agent_input: str,
|
|
86
|
-
agent_context: Optional[Dict[str, Any]] = None,
|
|
87
|
-
output_type: Optional[Any] = None,
|
|
88
|
-
) -> RunResultStreaming:
|
|
89
|
-
"""Run an ``Agent`` and return a streaming result.
|
|
90
|
-
|
|
91
|
-
Parameters
|
|
92
|
-
----------
|
|
93
|
-
agent
|
|
94
|
-
Configured agent instance to execute.
|
|
95
|
-
agent_input
|
|
96
|
-
Prompt or query string for the agent.
|
|
97
|
-
agent_context
|
|
98
|
-
Optional context dictionary passed to the agent. Default ``None``.
|
|
99
|
-
output_type
|
|
100
|
-
Optional type used to cast the final output. Default ``None``.
|
|
101
|
-
|
|
102
|
-
Returns
|
|
103
|
-
-------
|
|
104
|
-
RunResultStreaming
|
|
105
|
-
Streaming output wrapper from the agent execution.
|
|
106
|
-
"""
|
|
107
|
-
result = _run_agent_streamed(
|
|
108
|
-
agent=agent,
|
|
109
|
-
agent_input=agent_input,
|
|
110
|
-
context=agent_context,
|
|
111
|
-
)
|
|
112
|
-
if output_type:
|
|
113
|
-
return result.final_output_as(output_type)
|
|
114
|
-
return result
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
__all__ = ["run", "run_sync", "run_streamed"]
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
"""Utility helpers for synchronous interaction with async agents."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import asyncio
|
|
6
|
-
import threading
|
|
7
|
-
from typing import Any, Coroutine, TypeVar
|
|
8
|
-
|
|
9
|
-
T = TypeVar("T")
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def run_coro_sync(coro: Coroutine[Any, Any, T]) -> T:
|
|
13
|
-
"""Run a coroutine from synchronous code.
|
|
14
|
-
|
|
15
|
-
Parameters
|
|
16
|
-
----------
|
|
17
|
-
coro : Coroutine[Any, Any, T]
|
|
18
|
-
Coroutine to execute.
|
|
19
|
-
|
|
20
|
-
Returns
|
|
21
|
-
-------
|
|
22
|
-
T
|
|
23
|
-
Result returned by the coroutine.
|
|
24
|
-
"""
|
|
25
|
-
try:
|
|
26
|
-
loop = asyncio.get_running_loop()
|
|
27
|
-
except RuntimeError:
|
|
28
|
-
return asyncio.run(coro)
|
|
29
|
-
|
|
30
|
-
if loop.is_running():
|
|
31
|
-
result: T | None = None
|
|
32
|
-
|
|
33
|
-
def _thread_runner() -> None:
|
|
34
|
-
nonlocal result
|
|
35
|
-
result = asyncio.run(coro)
|
|
36
|
-
|
|
37
|
-
thread = threading.Thread(target=_thread_runner, daemon=True)
|
|
38
|
-
thread.start()
|
|
39
|
-
thread.join()
|
|
40
|
-
if result is None:
|
|
41
|
-
raise RuntimeError("Coroutine execution did not return a result.")
|
|
42
|
-
return result
|
|
43
|
-
|
|
44
|
-
return loop.run_until_complete(coro)
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
__all__ = ["run_coro_sync"]
|