openai-sdk-helpers 0.2.0__py3-none-any.whl → 0.3.0__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.
@@ -0,0 +1,183 @@
1
+ """Base registry class for managing configuration instances."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import warnings
6
+ from pathlib import Path
7
+ from typing import Generic, TypeVar
8
+
9
+ from .path_utils import ensure_directory
10
+
11
+ T = TypeVar("T")
12
+
13
+
14
+ class BaseRegistry(Generic[T]):
15
+ """Base registry for managing configuration instances.
16
+
17
+ Provides centralized storage and retrieval of configurations,
18
+ enabling reusable specs across the application. Configurations
19
+ are stored by name and can be retrieved or listed as needed.
20
+
21
+ Type Parameters
22
+ ---------------
23
+ T
24
+ The configuration type this registry manages.
25
+
26
+ Methods
27
+ -------
28
+ register(config)
29
+ Add a configuration to the registry.
30
+ get(name)
31
+ Retrieve a configuration by name.
32
+ list_names()
33
+ Return all registered configuration names.
34
+ clear()
35
+ Remove all registered configurations.
36
+ save_to_directory(path)
37
+ Export all registered configurations to JSON files.
38
+ load_from_directory(path)
39
+ Load configurations from JSON files in a directory.
40
+ """
41
+
42
+ def __init__(self) -> None:
43
+ """Initialize an empty registry."""
44
+ self._configs: dict[str, T] = {}
45
+
46
+ def register(self, config: T) -> None:
47
+ """Add a configuration to the registry.
48
+
49
+ Parameters
50
+ ----------
51
+ config : T
52
+ Configuration to register. Must have a 'name' attribute.
53
+
54
+ Raises
55
+ ------
56
+ ValueError
57
+ If a configuration with the same name is already registered.
58
+ """
59
+ name = getattr(config, "name")
60
+ if name in self._configs:
61
+ raise ValueError(
62
+ f"Configuration '{name}' is already registered. "
63
+ "Use a unique name or clear the registry first."
64
+ )
65
+ self._configs[name] = config
66
+
67
+ def get(self, name: str) -> T:
68
+ """Retrieve a configuration by name.
69
+
70
+ Parameters
71
+ ----------
72
+ name : str
73
+ Configuration name to look up.
74
+
75
+ Returns
76
+ -------
77
+ T
78
+ The registered configuration.
79
+
80
+ Raises
81
+ ------
82
+ KeyError
83
+ If no configuration with the given name exists.
84
+ """
85
+ if name not in self._configs:
86
+ raise KeyError(
87
+ f"No configuration named '{name}' found. "
88
+ f"Available: {list(self._configs.keys())}"
89
+ )
90
+ return self._configs[name]
91
+
92
+ def list_names(self) -> list[str]:
93
+ """Return all registered configuration names.
94
+
95
+ Returns
96
+ -------
97
+ list[str]
98
+ Sorted list of configuration names.
99
+ """
100
+ return sorted(self._configs.keys())
101
+
102
+ def clear(self) -> None:
103
+ """Remove all registered configurations."""
104
+ self._configs.clear()
105
+
106
+ def save_to_directory(self, path: Path | str) -> None:
107
+ """Export all registered configurations to JSON files in a directory.
108
+
109
+ Serializes each registered configuration to an individual JSON file
110
+ named after the configuration. Creates the directory if it does not exist.
111
+
112
+ Parameters
113
+ ----------
114
+ path : Path or str
115
+ Directory path where JSON files will be saved. Will be created if
116
+ it does not already exist.
117
+
118
+ Raises
119
+ ------
120
+ OSError
121
+ If the directory cannot be created or files cannot be written.
122
+ """
123
+ dir_path = ensure_directory(Path(path))
124
+ config_names = self.list_names()
125
+
126
+ if not config_names:
127
+ return
128
+
129
+ for config_name in config_names:
130
+ config = self.get(config_name)
131
+ filename = f"{config_name}.json"
132
+ filepath = dir_path / filename
133
+ # Call to_json_file on the config
134
+ getattr(config, "to_json_file")(filepath)
135
+
136
+ def load_from_directory(self, path: Path | str, *, config_class: type[T]) -> int:
137
+ """Load all configurations from JSON files in a directory.
138
+
139
+ Scans the directory for JSON files and attempts to load each as a
140
+ configuration. Successfully loaded configurations are registered.
141
+ If a file fails to load, a warning is issued and processing continues
142
+ with the remaining files.
143
+
144
+ Parameters
145
+ ----------
146
+ path : Path or str
147
+ Directory path containing JSON configuration files.
148
+ config_class : type[T]
149
+ The configuration class to use for deserialization.
150
+
151
+ Returns
152
+ -------
153
+ int
154
+ Number of configurations successfully loaded and registered.
155
+
156
+ Raises
157
+ ------
158
+ FileNotFoundError
159
+ If the directory does not exist.
160
+ NotADirectoryError
161
+ If the path is not a directory.
162
+ """
163
+ dir_path = Path(path)
164
+ if not dir_path.exists():
165
+ raise FileNotFoundError(f"Directory not found: {dir_path}")
166
+
167
+ if not dir_path.is_dir():
168
+ raise NotADirectoryError(f"Path is not a directory: {dir_path}")
169
+
170
+ count = 0
171
+ for json_file in sorted(dir_path.glob("*.json")):
172
+ try:
173
+ config = getattr(config_class, "from_json_file")(json_file)
174
+ self.register(config)
175
+ count += 1
176
+ except Exception as exc:
177
+ # Log warning but continue processing other files
178
+ warnings.warn(
179
+ f"Failed to load configuration from {json_file}: {exc}",
180
+ stacklevel=2,
181
+ )
182
+
183
+ return count
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openai-sdk-helpers
3
- Version: 0.2.0
3
+ Version: 0.3.0
4
4
  Summary: Composable helpers for OpenAI SDK agents, prompts, and storage
5
5
  Author: openai-sdk-helpers maintainers
6
6
  License: MIT
@@ -1,4 +1,4 @@
1
- openai_sdk_helpers/__init__.py,sha256=rsCoQ2yB8jJmWZxbXeXTf0dPcyWJIzghCS_CVPkBWKg,4626
1
+ openai_sdk_helpers/__init__.py,sha256=uqVd5iDoSo5_jlL9xX8sVRpZZhmc4isna7cr6RTP2Gc,4640
2
2
  openai_sdk_helpers/cli.py,sha256=J62XKPkGgYzYHKHfnkFy53Dp4rvBXf9cPEl1hrev3ZU,7400
3
3
  openai_sdk_helpers/config.py,sha256=pjBzjYM9Fs4DQqwio387lBt_4IwWKct_VNZBSe-bMqg,10972
4
4
  openai_sdk_helpers/context_manager.py,sha256=QqlrtenwKoz2krY0IzuToKdTX1HptUYtIEylxieybgY,6633
@@ -11,20 +11,20 @@ openai_sdk_helpers/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
11
  openai_sdk_helpers/retry.py,sha256=J10oQYphfzDXm3BnLoXwxk7PAhN93TC2LQOv0VDGOwI,6533
12
12
  openai_sdk_helpers/tools.py,sha256=C2xl0euovFyrDVh0qf1pEyuaicmrTmoZcJu9CxCKqic,9534
13
13
  openai_sdk_helpers/types.py,sha256=xzldCRfwCZ3rZl18IBmfgA-PVdoZKSWNrlSIhirumSo,1451
14
- openai_sdk_helpers/agent/__init__.py,sha256=giowU8jke0z0h7FFUG9V6Vssja8AYwvJMQbiMb3s64k,960
15
- openai_sdk_helpers/agent/base.py,sha256=8ZkW57vL8_fYzuLr6f9kMvBChYq5lN5vQ8MMJtcWD9s,11784
16
- openai_sdk_helpers/agent/config.py,sha256=htqy5bcrJeMf3rIpRdL9CKlYwyQI4po420rcgR3i8XI,1971
17
- openai_sdk_helpers/agent/coordination.py,sha256=mAIEjWJ7xnagKssLCrOEn1oOp-XoqYpQOdRlZpUyw90,16610
14
+ openai_sdk_helpers/agent/__init__.py,sha256=Dst1jjP5a-iLItis0B-RMMYiHB_yw_2ZusU38u7YQyE,1086
15
+ openai_sdk_helpers/agent/base.py,sha256=RotgsaCXVfxhrEE_7fyiR3ekhGunecTdwJ6p8lAyEM8,17348
16
+ openai_sdk_helpers/agent/config.py,sha256=dY76c5Tqn_MYe7huN_1HIDQCVkerEJwqaFGvPaXF8kQ,13773
17
+ openai_sdk_helpers/agent/coordination.py,sha256=rxUWhdgdEvPOrab6CbQIquzpOZDsIVXgFLNJEe_nVaY,16720
18
18
  openai_sdk_helpers/agent/prompt_utils.py,sha256=-1M66tqQxh9wWCFg6X-K7cCcqauca3yA04ZjvOpN3bA,337
19
- openai_sdk_helpers/agent/runner.py,sha256=1_azIWx1Bcy7RRlEbizTD0LXBdYgof_tYMpDUcnJJuM,4164
20
- openai_sdk_helpers/agent/summarizer.py,sha256=fH8AnYK_68ERf2U7mv0nwXL8KyhrluE-TDY_M5TCdD0,3266
21
- openai_sdk_helpers/agent/translator.py,sha256=GhUuwFTBecgOO9pMQ41VPvK9mTub5DXJ_7BIS9Xp7bs,5082
19
+ openai_sdk_helpers/agent/runner.py,sha256=w7gBFEuYGn7aKPpf9KNULboNY3pM2yLcoRcl_w80Wr4,4662
20
+ openai_sdk_helpers/agent/summarizer.py,sha256=gmQlzhL4DaSzItlqLMfqFC4Xns0imPG3OIaIzjDVDrQ,3327
21
+ openai_sdk_helpers/agent/translator.py,sha256=PbwfC6sbLkaU4bHwY5LdBqn5gMzYzKazZwJwk5nDLSo,5143
22
22
  openai_sdk_helpers/agent/utils.py,sha256=DTD5foCqGYfXf13F2bZMYIQROl7SbDSy5GDPGi0Zl-0,1089
23
- openai_sdk_helpers/agent/validation.py,sha256=JIYVhBTTs0tTxYyzYgY3BHC-9psyzE3LLQDZDqpg13M,4191
23
+ openai_sdk_helpers/agent/validation.py,sha256=uQBi1irE7sX2B_tvkpTpOX97Yz9oVdCXXIUTCyhM37o,4252
24
24
  openai_sdk_helpers/agent/search/__init__.py,sha256=xqosfzH4HcBs9IFZks9msG_694rS5q6Ea4_qNeRQRmU,798
25
- openai_sdk_helpers/agent/search/base.py,sha256=EP4WCIC-IItToTFVRVpg1pj1PC5QtqheIiK1l087yRg,8613
26
- openai_sdk_helpers/agent/search/vector.py,sha256=xMWhuRQENdWfLN1NTBzEjMfq1WsaGS6yn70-Xq9oFj4,13622
27
- openai_sdk_helpers/agent/search/web.py,sha256=8le4xnZ3nllySqWb7rZaOq44ZR8q67c_WiE57ncmL90,10014
25
+ openai_sdk_helpers/agent/search/base.py,sha256=lSfh7kMphmGRLrmBzDLprs_Owm7tL9moYbKhkU1tZ0M,8704
26
+ openai_sdk_helpers/agent/search/vector.py,sha256=bkd6OJT0FSioWaVgp1ZOLaHYV33HNrOyfCSCkFbhBtk,13833
27
+ openai_sdk_helpers/agent/search/web.py,sha256=81qPBmwj7HnMqJW0g3f_9_OoPOiVlKAy-gEUM92WROk,10225
28
28
  openai_sdk_helpers/enums/__init__.py,sha256=aFf79C4JBeLC3kMlJfSpehyjx5uNCtW6eK5rD6ZFfhM,322
29
29
  openai_sdk_helpers/enums/base.py,sha256=cNllDtzcgI0_eZYXxFko14yhxwicX6xbeDfz9gFE3qo,2753
30
30
  openai_sdk_helpers/prompt/__init__.py,sha256=MOqgKwG9KLqKudoKRlUfLxiSmdOi2aD6hNrWDFqLHkk,418
@@ -33,8 +33,8 @@ openai_sdk_helpers/prompt/summarizer.jinja,sha256=jliSetWDISbql1EkWi1RB8-L_BXUg8
33
33
  openai_sdk_helpers/prompt/translator.jinja,sha256=SZhW8ipEzM-9IA4wyS_r2wIMTAclWrilmk1s46njoL0,291
34
34
  openai_sdk_helpers/prompt/validator.jinja,sha256=6t8q_IdxFd3mVBGX6SFKNOert1Wo3YpTOji2SNEbbtE,547
35
35
  openai_sdk_helpers/response/__init__.py,sha256=td-HTSPLtl1d5AkUFZ0rrUBUfsacM_CGtZQNj1_GWB8,1886
36
- openai_sdk_helpers/response/base.py,sha256=Y77LbnNB50-CG_KPYxM6XU0lIj9pYvAQt7FzekeHhF4,30176
37
- openai_sdk_helpers/response/config.py,sha256=pZgjh5GOb4juy1Afnyn28QS3yIArByU2MAJIc1_i3WM,13237
36
+ openai_sdk_helpers/response/base.py,sha256=oX2uIjRDVEOSJVp3_WkJrBI6a2DPVaEBiKSrRj-oD-4,32869
37
+ openai_sdk_helpers/response/config.py,sha256=bbl1kCvOhAS1vIoN60c-gNRavXZHO1kY_RqYztPqN30,9150
38
38
  openai_sdk_helpers/response/files.py,sha256=ANCoedNHXmpTXSaaGUvesAGq2DIUXT7SKZDCIJlXOv8,13226
39
39
  openai_sdk_helpers/response/messages.py,sha256=AbxLy2Q3sDHFLhhhoKfCcrRVlA8M7Ts9SuYx0PODi54,10061
40
40
  openai_sdk_helpers/response/runner.py,sha256=Rf13cQGsR7sN9gA81Y5th1tfH2DCCAwQ6RMs3bVgjnk,4269
@@ -64,16 +64,18 @@ openai_sdk_helpers/utils/async_utils.py,sha256=9KbPEVfi6IXdbwkTUE0h5DleK8TI7I6P_
64
64
  openai_sdk_helpers/utils/coercion.py,sha256=Pq1u7tAbD7kTZ84lK-7Fb9CyYKKKQt4fypG5BlSI6oQ,3774
65
65
  openai_sdk_helpers/utils/deprecation.py,sha256=VF0VDDegawYhsu5f-vE6dop9ob-jv8egxsm0KsPvP9E,4753
66
66
  openai_sdk_helpers/utils/encoding.py,sha256=oDtlNGZ5p-edXiHW76REs-0-8NXkQNReKJdj6sHLkt8,4615
67
- openai_sdk_helpers/utils/json_utils.py,sha256=Z-9AugR0CbNMLXcaJk1IJ-SwGNdo_d0a3r6MqP8rbYs,7089
67
+ openai_sdk_helpers/utils/instructions.py,sha256=trbjxjxv2otQR9VmBsPFk1_CJj8nA85Sgtj_5QmQOKI,942
68
+ openai_sdk_helpers/utils/json_utils.py,sha256=g8x497URz0bNYHgdcYM_3kNzj9QKsN5xionH1yh5nMk,7674
68
69
  openai_sdk_helpers/utils/output_validation.py,sha256=O9Adt-fxL5DtnMd1GuZ9E2YxX3yj4uzSZuBNKVH2GkI,12152
69
70
  openai_sdk_helpers/utils/path_utils.py,sha256=qGGDpuDnY5EODOACzH23MYECQOE2rKhrQ3sbDvefwEg,1307
71
+ openai_sdk_helpers/utils/registry.py,sha256=qezdmsCRokrV9snXNyUG2rJ-jBG-UCCkp7-rRBE9LFY,5565
70
72
  openai_sdk_helpers/utils/validation.py,sha256=ZjnZNOy5AoFlszRxarNol6YZwfgw6LnwPtkCekZmwAU,7826
71
73
  openai_sdk_helpers/vector_storage/__init__.py,sha256=L5LxO09puh9_yBB9IDTvc1CvVkARVkHqYY1KX3inB4c,975
72
74
  openai_sdk_helpers/vector_storage/cleanup.py,sha256=ImWIE-9lli-odD8qIARvmeaa0y8ZD4pYYP-kT0O3178,3552
73
75
  openai_sdk_helpers/vector_storage/storage.py,sha256=1juu3Qq6hy33afvVfQeI5A35fQzIPjVZumZ-aP_MxhU,23305
74
76
  openai_sdk_helpers/vector_storage/types.py,sha256=jTCcOYMeOpZWvcse0z4T3MVs-RBOPC-fqWTBeQrgafU,1639
75
- openai_sdk_helpers-0.2.0.dist-info/METADATA,sha256=4uIwpDW0oqwdAqsf5uhb_GmutPvrlek0pbO6G4zYVXU,23557
76
- openai_sdk_helpers-0.2.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
77
- openai_sdk_helpers-0.2.0.dist-info/entry_points.txt,sha256=gEOD1ZeXe8d2OP-KzUlG-b_9D9yUZTCt-GFW3EDbIIY,63
78
- openai_sdk_helpers-0.2.0.dist-info/licenses/LICENSE,sha256=CUhc1NrE50bs45tcXF7OcTQBKEvkUuLqeOHgrWQ5jaA,1067
79
- openai_sdk_helpers-0.2.0.dist-info/RECORD,,
77
+ openai_sdk_helpers-0.3.0.dist-info/METADATA,sha256=7KeZYCdLQTmtvQj0mZVWzimqkA0hNzU9RNnN_25z2CY,23557
78
+ openai_sdk_helpers-0.3.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
79
+ openai_sdk_helpers-0.3.0.dist-info/entry_points.txt,sha256=gEOD1ZeXe8d2OP-KzUlG-b_9D9yUZTCt-GFW3EDbIIY,63
80
+ openai_sdk_helpers-0.3.0.dist-info/licenses/LICENSE,sha256=CUhc1NrE50bs45tcXF7OcTQBKEvkUuLqeOHgrWQ5jaA,1067
81
+ openai_sdk_helpers-0.3.0.dist-info/RECORD,,