openai-sdk-helpers 0.0.7__py3-none-any.whl → 0.0.9__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.
Files changed (63) hide show
  1. openai_sdk_helpers/__init__.py +85 -10
  2. openai_sdk_helpers/agent/__init__.py +8 -4
  3. openai_sdk_helpers/agent/base.py +81 -46
  4. openai_sdk_helpers/agent/config.py +6 -4
  5. openai_sdk_helpers/agent/{project_manager.py → coordination.py} +29 -45
  6. openai_sdk_helpers/agent/prompt_utils.py +7 -1
  7. openai_sdk_helpers/agent/runner.py +67 -141
  8. openai_sdk_helpers/agent/search/__init__.py +33 -0
  9. openai_sdk_helpers/agent/search/base.py +297 -0
  10. openai_sdk_helpers/agent/{vector_search.py → search/vector.py} +89 -157
  11. openai_sdk_helpers/agent/{web_search.py → search/web.py} +82 -162
  12. openai_sdk_helpers/agent/summarizer.py +29 -8
  13. openai_sdk_helpers/agent/translator.py +40 -13
  14. openai_sdk_helpers/agent/validation.py +32 -8
  15. openai_sdk_helpers/async_utils.py +132 -0
  16. openai_sdk_helpers/config.py +74 -36
  17. openai_sdk_helpers/context_manager.py +241 -0
  18. openai_sdk_helpers/enums/__init__.py +9 -1
  19. openai_sdk_helpers/enums/base.py +67 -8
  20. openai_sdk_helpers/environment.py +33 -6
  21. openai_sdk_helpers/errors.py +133 -0
  22. openai_sdk_helpers/logging_config.py +105 -0
  23. openai_sdk_helpers/prompt/__init__.py +10 -71
  24. openai_sdk_helpers/prompt/base.py +172 -0
  25. openai_sdk_helpers/response/__init__.py +37 -5
  26. openai_sdk_helpers/response/base.py +427 -189
  27. openai_sdk_helpers/response/config.py +176 -0
  28. openai_sdk_helpers/response/messages.py +104 -40
  29. openai_sdk_helpers/response/runner.py +79 -35
  30. openai_sdk_helpers/response/tool_call.py +75 -12
  31. openai_sdk_helpers/response/vector_store.py +29 -16
  32. openai_sdk_helpers/retry.py +175 -0
  33. openai_sdk_helpers/streamlit_app/__init__.py +30 -0
  34. openai_sdk_helpers/streamlit_app/app.py +345 -0
  35. openai_sdk_helpers/streamlit_app/config.py +502 -0
  36. openai_sdk_helpers/streamlit_app/streamlit_web_search.py +68 -0
  37. openai_sdk_helpers/structure/__init__.py +69 -3
  38. openai_sdk_helpers/structure/agent_blueprint.py +82 -19
  39. openai_sdk_helpers/structure/base.py +245 -91
  40. openai_sdk_helpers/structure/plan/__init__.py +15 -1
  41. openai_sdk_helpers/structure/plan/enum.py +41 -5
  42. openai_sdk_helpers/structure/plan/plan.py +101 -45
  43. openai_sdk_helpers/structure/plan/task.py +38 -6
  44. openai_sdk_helpers/structure/prompt.py +21 -2
  45. openai_sdk_helpers/structure/responses.py +52 -11
  46. openai_sdk_helpers/structure/summary.py +55 -7
  47. openai_sdk_helpers/structure/validation.py +34 -6
  48. openai_sdk_helpers/structure/vector_search.py +132 -18
  49. openai_sdk_helpers/structure/web_search.py +128 -12
  50. openai_sdk_helpers/types.py +57 -0
  51. openai_sdk_helpers/utils/__init__.py +32 -1
  52. openai_sdk_helpers/utils/core.py +200 -32
  53. openai_sdk_helpers/validation.py +302 -0
  54. openai_sdk_helpers/vector_storage/__init__.py +21 -1
  55. openai_sdk_helpers/vector_storage/cleanup.py +25 -13
  56. openai_sdk_helpers/vector_storage/storage.py +124 -66
  57. openai_sdk_helpers/vector_storage/types.py +20 -19
  58. openai_sdk_helpers-0.0.9.dist-info/METADATA +550 -0
  59. openai_sdk_helpers-0.0.9.dist-info/RECORD +66 -0
  60. openai_sdk_helpers-0.0.7.dist-info/METADATA +0 -193
  61. openai_sdk_helpers-0.0.7.dist-info/RECORD +0 -51
  62. {openai_sdk_helpers-0.0.7.dist-info → openai_sdk_helpers-0.0.9.dist-info}/WHEEL +0 -0
  63. {openai_sdk_helpers-0.0.7.dist-info → openai_sdk_helpers-0.0.9.dist-info}/licenses/LICENSE +0 -0
@@ -2,15 +2,59 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from .structure import *
5
+ from .async_utils import run_coroutine_thread_safe, run_coroutine_with_fallback
6
+ from .context_manager import (
7
+ AsyncManagedResource,
8
+ ManagedResource,
9
+ async_context,
10
+ ensure_closed,
11
+ ensure_closed_async,
12
+ )
13
+ from .errors import (
14
+ OpenAISDKError,
15
+ ConfigurationError,
16
+ PromptNotFoundError,
17
+ AgentExecutionError,
18
+ VectorStorageError,
19
+ ToolExecutionError,
20
+ ResponseGenerationError,
21
+ InputValidationError,
22
+ AsyncExecutionError,
23
+ ResourceCleanupError,
24
+ )
25
+ from .logging_config import LoggerFactory
26
+ from .retry import with_exponential_backoff
27
+ from .validation import (
28
+ validate_choice,
29
+ validate_dict_mapping,
30
+ validate_list_items,
31
+ validate_max_length,
32
+ validate_non_empty_string,
33
+ validate_safe_path,
34
+ validate_url_format,
35
+ )
36
+ from .structure import (
37
+ BaseStructure,
38
+ SchemaOptions,
39
+ PlanStructure,
40
+ TaskStructure,
41
+ WebSearchStructure,
42
+ VectorSearchStructure,
43
+ PromptStructure,
44
+ spec_field,
45
+ SummaryStructure,
46
+ ExtendedSummaryStructure,
47
+ ValidationResultStructure,
48
+ AgentBlueprint,
49
+ )
6
50
  from .prompt import PromptRenderer
7
51
  from .config import OpenAISettings
8
- from .vector_storage import *
52
+ from .vector_storage import VectorStorage, VectorStorageFileInfo, VectorStorageFileStats
9
53
  from .agent import (
10
54
  AgentBase,
11
55
  AgentConfig,
12
56
  AgentEnum,
13
- ProjectManager,
57
+ CoordinatorAgent,
14
58
  SummarizerAgent,
15
59
  TranslatorAgent,
16
60
  ValidatorAgent,
@@ -18,13 +62,47 @@ from .agent import (
18
62
  WebAgentSearch,
19
63
  )
20
64
  from .response import (
21
- ResponseBase,
65
+ BaseResponse,
22
66
  ResponseMessage,
23
67
  ResponseMessages,
24
68
  ResponseToolCall,
69
+ attach_vector_store,
25
70
  )
26
71
 
27
72
  __all__ = [
73
+ # Async utilities
74
+ "run_coroutine_thread_safe",
75
+ "run_coroutine_with_fallback",
76
+ # Error classes
77
+ "OpenAISDKError",
78
+ "ConfigurationError",
79
+ "PromptNotFoundError",
80
+ "AgentExecutionError",
81
+ "VectorStorageError",
82
+ "ToolExecutionError",
83
+ "ResponseGenerationError",
84
+ "InputValidationError",
85
+ "AsyncExecutionError",
86
+ "ResourceCleanupError",
87
+ # Logging
88
+ "LoggerFactory",
89
+ # Retry utilities
90
+ "with_exponential_backoff",
91
+ # Context managers
92
+ "ManagedResource",
93
+ "AsyncManagedResource",
94
+ "ensure_closed",
95
+ "ensure_closed_async",
96
+ "async_context",
97
+ # Validation
98
+ "validate_non_empty_string",
99
+ "validate_max_length",
100
+ "validate_url_format",
101
+ "validate_dict_mapping",
102
+ "validate_list_items",
103
+ "validate_choice",
104
+ "validate_safe_path",
105
+ # Main structure classes
28
106
  "BaseStructure",
29
107
  "SchemaOptions",
30
108
  "spec_field",
@@ -33,10 +111,6 @@ __all__ = [
33
111
  "VectorStorage",
34
112
  "VectorStorageFileInfo",
35
113
  "VectorStorageFileStats",
36
- "assistant_tool_definition",
37
- "assistant_format",
38
- "response_tool_definition",
39
- "response_format",
40
114
  "SummaryStructure",
41
115
  "PromptStructure",
42
116
  "AgentBlueprint",
@@ -45,7 +119,7 @@ __all__ = [
45
119
  "AgentEnum",
46
120
  "AgentBase",
47
121
  "AgentConfig",
48
- "ProjectManager",
122
+ "CoordinatorAgent",
49
123
  "SummarizerAgent",
50
124
  "TranslatorAgent",
51
125
  "ValidatorAgent",
@@ -55,8 +129,9 @@ __all__ = [
55
129
  "WebSearchStructure",
56
130
  "VectorSearchStructure",
57
131
  "ValidationResultStructure",
58
- "ResponseBase",
132
+ "BaseResponse",
59
133
  "ResponseMessage",
60
134
  "ResponseMessages",
61
135
  "ResponseToolCall",
136
+ "attach_vector_store",
62
137
  ]
@@ -5,24 +5,28 @@ from __future__ import annotations
5
5
  from .base import AgentBase
6
6
  from .config import AgentConfig
7
7
  from ..structure.plan.enum import AgentEnum
8
- from .project_manager import ProjectManager
8
+ from .coordination import CoordinatorAgent
9
9
  from .runner import run_sync, run_async, run_streamed
10
+ from .search.base import SearchPlanner, SearchToolAgent, SearchWriter
10
11
  from .summarizer import SummarizerAgent
11
12
  from .translator import TranslatorAgent
12
13
  from .validation import ValidatorAgent
13
14
  from .utils import run_coroutine_agent_sync
14
- from .vector_search import VectorSearch
15
- from .web_search import WebAgentSearch
15
+ from .search.vector import VectorSearch
16
+ from .search.web import WebAgentSearch
16
17
 
17
18
  __all__ = [
18
19
  "AgentBase",
19
20
  "AgentConfig",
20
21
  "AgentEnum",
21
- "ProjectManager",
22
+ "CoordinatorAgent",
22
23
  "run_sync",
23
24
  "run_async",
24
25
  "run_streamed",
25
26
  "run_coroutine_agent_sync",
27
+ "SearchPlanner",
28
+ "SearchToolAgent",
29
+ "SearchWriter",
26
30
  "SummarizerAgent",
27
31
  "TranslatorAgent",
28
32
  "ValidatorAgent",
@@ -2,16 +2,15 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- import asyncio
6
- import threading
7
5
  from pathlib import Path
8
6
  from typing import Any, Dict, Optional, Protocol
9
7
 
10
- from agents import Agent, Runner, RunResult, RunResultStreaming
8
+ from agents import Agent, RunResult, RunResultStreaming, Runner
11
9
  from agents.run_context import RunContextWrapper
12
10
  from agents.tool import FunctionTool
13
11
  from jinja2 import Template
14
- from .runner import run_sync, run_streamed, run_async
12
+
13
+ from .runner import run_async, run_streamed, run_sync
15
14
 
16
15
 
17
16
  class AgentConfigLike(Protocol):
@@ -30,6 +29,41 @@ class AgentConfigLike(Protocol):
30
29
  class AgentBase:
31
30
  """Factory for creating and configuring specialized agents.
32
31
 
32
+ ``AgentBase`` provides the foundation for building OpenAI agents with support
33
+ for Jinja2 prompt templates, custom tools, and both synchronous and
34
+ asynchronous execution modes. All specialized agents in this package extend
35
+ this base class.
36
+
37
+ Examples
38
+ --------
39
+ Create a basic agent from configuration:
40
+
41
+ >>> from openai_sdk_helpers.agent import AgentBase, AgentConfig
42
+ >>> config = AgentConfig(
43
+ ... name="my_agent",
44
+ ... description="A custom agent",
45
+ ... model="gpt-4o-mini"
46
+ ... )
47
+ >>> agent = AgentBase(config=config, default_model="gpt-4o-mini")
48
+ >>> result = agent.run_sync("What is 2+2?")
49
+
50
+ Use absolute path to template:
51
+
52
+ >>> config = AgentConfig(
53
+ ... name="my_agent",
54
+ ... template_path="/absolute/path/to/template.jinja",
55
+ ... model="gpt-4o-mini"
56
+ ... )
57
+ >>> agent = AgentBase(config=config, default_model="gpt-4o-mini")
58
+
59
+ Use async execution:
60
+
61
+ >>> import asyncio
62
+ >>> async def main():
63
+ ... result = await agent.run_async("Explain quantum physics")
64
+ ... return result
65
+ >>> asyncio.run(main())
66
+
33
67
  Methods
34
68
  -------
35
69
  from_config(config, run_context_wrapper)
@@ -59,23 +93,21 @@ class AgentBase:
59
93
  prompt_dir: Optional[Path] = None,
60
94
  default_model: Optional[str] = None,
61
95
  ) -> None:
62
- """Initialize the ``AgentBase`` using a configuration object.
96
+ """Initialize the AgentBase using a configuration object.
63
97
 
64
98
  Parameters
65
99
  ----------
66
- config
100
+ config : AgentConfigLike
67
101
  Configuration describing this agent.
68
- run_context_wrapper
102
+ run_context_wrapper : RunContextWrapper or None, default=None
69
103
  Optional wrapper providing runtime context for prompt rendering.
70
- Default ``None``.
71
- prompt_dir
72
- Optional directory holding prompt templates.
73
- default_model
104
+ prompt_dir : Path or None, default=None
105
+ Optional directory holding prompt templates. Used when
106
+ ``config.template_path`` is not provided or is relative. If
107
+ ``config.template_path`` is an absolute path, this parameter is
108
+ ignored.
109
+ default_model : str or None, default=None
74
110
  Optional fallback model identifier if the config does not supply one.
75
-
76
- Returns
77
- -------
78
- None
79
111
  """
80
112
  name = config.name
81
113
  description = config.description or ""
@@ -117,18 +149,21 @@ class AgentBase:
117
149
  run_context_wrapper: Optional[RunContextWrapper[Dict[str, Any]]] = None,
118
150
  prompt_dir: Optional[Path] = None,
119
151
  default_model: Optional[str] = None,
120
- ) -> "AgentBase":
121
- """Create a :class:`AgentBase` instance from configuration.
152
+ ) -> AgentBase:
153
+ """Create an AgentBase instance from configuration.
122
154
 
123
155
  Parameters
124
156
  ----------
125
- config
157
+ config : AgentConfigLike
126
158
  Configuration describing the agent.
127
- run_context_wrapper
128
- Optional wrapper providing runtime context. Default ``None``.
129
- prompt_dir
130
- Optional directory holding prompt templates.
131
- default_model
159
+ run_context_wrapper : RunContextWrapper or None, default=None
160
+ Optional wrapper providing runtime context.
161
+ prompt_dir : Path or None, default=None
162
+ Optional directory holding prompt templates. Used when
163
+ ``config.template_path`` is not provided or is relative. If
164
+ ``config.template_path`` is an absolute path, this parameter is
165
+ ignored.
166
+ default_model : str or None, default=None
132
167
  Optional fallback model identifier.
133
168
 
134
169
  Returns
@@ -144,7 +179,7 @@ class AgentBase:
144
179
  )
145
180
 
146
181
  def _build_prompt_from_jinja(self) -> str:
147
- """Return the rendered instructions prompt for this agent.
182
+ """Render the instructions prompt for this agent.
148
183
 
149
184
  Returns
150
185
  -------
@@ -162,9 +197,9 @@ class AgentBase:
162
197
 
163
198
  Parameters
164
199
  ----------
165
- run_context_wrapper
200
+ run_context_wrapper : RunContextWrapper or None, default=None
166
201
  Wrapper whose ``context`` dictionary is used to render the Jinja
167
- template. Default ``None``.
202
+ template.
168
203
 
169
204
  Returns
170
205
  -------
@@ -184,11 +219,11 @@ class AgentBase:
184
219
 
185
220
  Parameters
186
221
  ----------
187
- run_context_wrapper
222
+ run_context_wrapper : RunContextWrapper
188
223
  Wrapper around the current run context whose ``context`` dictionary
189
224
  is used to render the Jinja template.
190
- _
191
- Underlying :class:`agents.Agent` instance (ignored).
225
+ _ : Agent
226
+ Underlying Agent instance (ignored).
192
227
 
193
228
  Returns
194
229
  -------
@@ -207,7 +242,7 @@ class AgentBase:
207
242
  """
208
243
  agent_config: Dict[str, Any] = {
209
244
  "name": self.agent_name,
210
- "instructions": self._build_prompt_from_jinja(),
245
+ "instructions": self._build_prompt_from_jinja() or ".",
211
246
  "model": self.model,
212
247
  }
213
248
  if self._output_type:
@@ -229,12 +264,12 @@ class AgentBase:
229
264
 
230
265
  Parameters
231
266
  ----------
232
- input
267
+ input : str
233
268
  Prompt or query for the agent.
234
- context
235
- Optional dictionary passed to the agent. Default ``None``.
236
- output_type
237
- Optional type used to cast the final output. Default ``None``.
269
+ context : dict or None, default=None
270
+ Optional dictionary passed to the agent.
271
+ output_type : type or None, default=None
272
+ Optional type used to cast the final output.
238
273
 
239
274
  Returns
240
275
  -------
@@ -260,12 +295,12 @@ class AgentBase:
260
295
 
261
296
  Parameters
262
297
  ----------
263
- input
298
+ input : str
264
299
  Prompt or query for the agent.
265
- context
266
- Optional dictionary passed to the agent. Default ``None``.
267
- output_type
268
- Optional type used to cast the final output. Default ``None``.
300
+ context : dict or None, default=None
301
+ Optional dictionary passed to the agent.
302
+ output_type : type or None, default=None
303
+ Optional type used to cast the final output.
269
304
 
270
305
  Returns
271
306
  -------
@@ -285,16 +320,16 @@ class AgentBase:
285
320
  context: Optional[Dict[str, Any]] = None,
286
321
  output_type: Optional[Any] = None,
287
322
  ) -> RunResultStreaming:
288
- """Return a streaming result for the agent execution.
323
+ """Stream the agent execution results.
289
324
 
290
325
  Parameters
291
326
  ----------
292
- input
327
+ input : str
293
328
  Prompt or query for the agent.
294
- context
295
- Optional dictionary passed to the agent. Default ``None``.
296
- output_type
297
- Optional type used to cast the final output. Default ``None``.
329
+ context : dict or None, default=None
330
+ Optional dictionary passed to the agent.
331
+ output_type : type or None, default=None
332
+ Optional type used to cast the final output.
298
333
 
299
334
  Returns
300
335
  -------
@@ -11,12 +11,12 @@ from ..structure import BaseStructure
11
11
 
12
12
 
13
13
  class AgentConfig(BaseStructure):
14
- """Configuration required to build a :class:`AgentBase`.
14
+ """Configuration required to build an AgentBase.
15
15
 
16
16
  Methods
17
17
  -------
18
18
  print()
19
- Return a human readable representation of the configuration.
19
+ Return a human-readable representation of the configuration.
20
20
  """
21
21
 
22
22
  model_config = ConfigDict(arbitrary_types_allowed=True)
@@ -29,7 +29,9 @@ class AgentConfig(BaseStructure):
29
29
  default=None, title="Model", description="Model identifier to use"
30
30
  )
31
31
  template_path: Optional[str] = Field(
32
- default=None, title="Template Path", description="Path to the Jinja template"
32
+ default=None,
33
+ title="Template Path",
34
+ description="Path to the Jinja template (absolute or relative to prompt_dir)",
33
35
  )
34
36
  input_type: Optional[Type[BaseModel]] = Field(
35
37
  default=None,
@@ -51,7 +53,7 @@ class AgentConfig(BaseStructure):
51
53
  )
52
54
 
53
55
  def print(self) -> str:
54
- """Return a human readable representation.
56
+ """Return a human-readable representation.
55
57
 
56
58
  Returns
57
59
  -------
@@ -24,7 +24,7 @@ ExecutePlanFn = Callable[[PlanStructure], List[str]]
24
24
  SummarizeFn = Callable[[List[str]], str]
25
25
 
26
26
 
27
- class ProjectManager(AgentBase, JSONSerializable):
27
+ class CoordinatorAgent(AgentBase, JSONSerializable):
28
28
  """Coordinate agent plans while persisting project state and outputs.
29
29
 
30
30
  Methods
@@ -54,7 +54,7 @@ class ProjectManager(AgentBase, JSONSerializable):
54
54
  execute_plan_fn: ExecutePlanFn,
55
55
  summarize_fn: SummarizeFn,
56
56
  module_data_path: Path,
57
- module_name: str,
57
+ name: str,
58
58
  config: Optional[AgentConfig] = None,
59
59
  prompt_dir: Optional[Path] = None,
60
60
  default_model: Optional[str] = None,
@@ -63,32 +63,28 @@ class ProjectManager(AgentBase, JSONSerializable):
63
63
 
64
64
  Parameters
65
65
  ----------
66
- prompt_fn
66
+ prompt_fn : PromptFn
67
67
  Callable that generates a prompt brief from the input string.
68
- build_plan_fn
68
+ build_plan_fn : BuildPlanFn
69
69
  Callable that generates a plan from the prompt brief.
70
- execute_plan_fn
70
+ execute_plan_fn : ExecutePlanFn
71
71
  Callable that executes a plan and returns results.
72
- summarize_fn
72
+ summarize_fn : SummarizeFn
73
73
  Callable that summarizes a list of result strings.
74
- module_data_path
74
+ module_data_path : Path
75
75
  Base path for persisting project artifacts.
76
- module_name
76
+ name : str
77
77
  Name of the parent module for data organization.
78
- config
78
+ config : AgentConfig or None, default=None
79
79
  Optional agent configuration describing prompts and metadata.
80
- prompt_dir
80
+ prompt_dir : Path or None, default=None
81
81
  Optional directory holding prompt templates.
82
- default_model
82
+ default_model : str or None, default=None
83
83
  Optional fallback model identifier.
84
-
85
- Returns
86
- -------
87
- None
88
84
  """
89
85
  if config is None:
90
86
  config = AgentConfig(
91
- name="project_manager",
87
+ name="coordinator_agent",
92
88
  description="Coordinates agents for planning and summarization.",
93
89
  )
94
90
  super().__init__(
@@ -99,7 +95,7 @@ class ProjectManager(AgentBase, JSONSerializable):
99
95
  self._execute_plan_fn = execute_plan_fn
100
96
  self._summarize_fn = summarize_fn
101
97
  self._module_data_path = Path(module_data_path)
102
- self._module_name = module_name
98
+ self._name = name
103
99
 
104
100
  self.prompt: Optional[str] = None
105
101
  self.brief: Optional[PromptStructure] = None
@@ -109,16 +105,12 @@ class ProjectManager(AgentBase, JSONSerializable):
109
105
  self.end_date: Optional[datetime] = None
110
106
 
111
107
  def build_prompt(self, prompt: str) -> None:
112
- """Return a concise brief for the project.
108
+ """Generate a concise brief for the project.
113
109
 
114
110
  Parameters
115
111
  ----------
116
112
  prompt : str
117
113
  The core request or goal for the project.
118
-
119
- Returns
120
- -------
121
- None
122
114
  """
123
115
  log("build_prompt", level=logging.INFO)
124
116
  self.start_date = datetime.now(timezone.utc)
@@ -133,10 +125,6 @@ class ProjectManager(AgentBase, JSONSerializable):
133
125
  ------
134
126
  ValueError
135
127
  If called before :meth:`build_prompt`.
136
-
137
- Returns
138
- -------
139
- None
140
128
  """
141
129
  log("build_plan", level=logging.INFO)
142
130
  if not self.brief:
@@ -148,7 +136,7 @@ class ProjectManager(AgentBase, JSONSerializable):
148
136
  self.save()
149
137
 
150
138
  def execute_plan(self) -> List[str]:
151
- """Run each task, updating status, timestamps, and recorded results.
139
+ """Execute each task, updating status, timestamps, and recorded results.
152
140
 
153
141
  Returns
154
142
  -------
@@ -169,9 +157,9 @@ class ProjectManager(AgentBase, JSONSerializable):
169
157
 
170
158
  Parameters
171
159
  ----------
172
- results : list[str], optional
173
- List of string outputs gathered from task execution. Defaults to
174
- ``None``, which uses the stored plan task results if available.
160
+ results : list[str] or None, default=None
161
+ List of string outputs gathered from task execution. When ``None``,
162
+ uses the stored plan task results if available.
175
163
 
176
164
  Returns
177
165
  -------
@@ -202,10 +190,6 @@ class ProjectManager(AgentBase, JSONSerializable):
202
190
  ----------
203
191
  prompt : str
204
192
  The request or question to analyze and summarize.
205
-
206
- Returns
207
- -------
208
- None
209
193
  """
210
194
  self.build_prompt(prompt)
211
195
  self.build_plan()
@@ -224,7 +208,7 @@ class ProjectManager(AgentBase, JSONSerializable):
224
208
  if not self.start_date:
225
209
  self.start_date = datetime.now(timezone.utc)
226
210
  start_date_str = self.start_date.strftime(DATETIME_FMT)
227
- return self._module_data_path / self._module_name / f"{start_date_str}.json"
211
+ return self._module_data_path / self._name / f"{start_date_str}.json"
228
212
 
229
213
  def save(self) -> Path:
230
214
  """Persist the current project state to disk.
@@ -259,7 +243,7 @@ class ProjectManager(AgentBase, JSONSerializable):
259
243
  Any
260
244
  Raw output from the underlying callable.
261
245
  """
262
- task_type = ProjectManager._normalize_task_type(task.task_type)
246
+ task_type = CoordinatorAgent._normalize_task_type(task.task_type)
263
247
  prompt_with_context = task.prompt
264
248
  if aggregated_context and task_type not in {"WebAgentSearch", "VectorSearch"}:
265
249
  context_block = "\n".join(aggregated_context)
@@ -284,7 +268,7 @@ class ProjectManager(AgentBase, JSONSerializable):
284
268
  level=logging.ERROR,
285
269
  )
286
270
  return f"Task error: {exc}"
287
- return ProjectManager._resolve_result(output)
271
+ return CoordinatorAgent._resolve_result(output)
288
272
 
289
273
  @staticmethod
290
274
  def _run_task_in_thread(
@@ -312,7 +296,7 @@ class ProjectManager(AgentBase, JSONSerializable):
312
296
 
313
297
  def _runner() -> None:
314
298
  try:
315
- result_container["result"] = ProjectManager._run_task(
299
+ result_container["result"] = CoordinatorAgent._run_task(
316
300
  task,
317
301
  agent_callable=agent_callable,
318
302
  aggregated_context=aggregated_context,
@@ -363,14 +347,14 @@ class ProjectManager(AgentBase, JSONSerializable):
363
347
  "await the task instead."
364
348
  )
365
349
  return asyncio.run_coroutine_threadsafe(
366
- ProjectManager._await_wrapper(result), owning_loop
350
+ CoordinatorAgent._await_wrapper(result), owning_loop
367
351
  ).result()
368
352
 
369
353
  awaitable: asyncio.Future[Any] | asyncio.Task[Any] | Any = result
370
354
  coroutine = (
371
355
  awaitable
372
356
  if inspect.iscoroutine(awaitable)
373
- else ProjectManager._await_wrapper(awaitable)
357
+ else CoordinatorAgent._await_wrapper(awaitable)
374
358
  )
375
359
 
376
360
  try:
@@ -394,7 +378,7 @@ class ProjectManager(AgentBase, JSONSerializable):
394
378
 
395
379
  @staticmethod
396
380
  async def _await_wrapper(awaitable: Any) -> Any:
397
- """Await a generic awaitable and return its result.
381
+ """Resolve an awaitable and return its result.
398
382
 
399
383
  Parameters
400
384
  ----------
@@ -459,8 +443,8 @@ class ProjectManager(AgentBase, JSONSerializable):
459
443
  timestamp = datetime.now(timezone.utc).strftime("%Y%m%d_%H%M%S")
460
444
  self._run_directory = (
461
445
  self._module_data_path
462
- / Path(self._module_name)
463
- / "project_manager"
446
+ / Path(self._name)
447
+ / "coordinator_agent"
464
448
  / timestamp
465
449
  )
466
450
  self._run_directory.mkdir(parents=True, exist_ok=True)
@@ -480,7 +464,7 @@ class ProjectManager(AgentBase, JSONSerializable):
480
464
  str
481
465
  Lowercase label safe for filesystem usage.
482
466
  """
483
- task_type = ProjectManager._normalize_task_type(task.task_type)
467
+ task_type = CoordinatorAgent._normalize_task_type(task.task_type)
484
468
  base = (task_type or "task").replace(" ", "_").lower()
485
469
  return f"{base}_{task_type}"
486
470
 
@@ -508,4 +492,4 @@ class ProjectManager(AgentBase, JSONSerializable):
508
492
  return str(task_type)
509
493
 
510
494
 
511
- __all__ = ["ProjectManager"]
495
+ __all__ = ["CoordinatorAgent"]
@@ -1,4 +1,10 @@
1
- """Shared helpers for locating bundled prompt templates."""
1
+ """Shared helpers for locating bundled prompt templates.
2
+
3
+ Attributes
4
+ ----------
5
+ DEFAULT_PROMPT_DIR : Path
6
+ Default directory containing bundled prompt templates.
7
+ """
2
8
 
3
9
  from __future__ import annotations
4
10