bear-utils 0.0.1__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 (107) hide show
  1. bear_utils/__init__.py +51 -0
  2. bear_utils/__main__.py +14 -0
  3. bear_utils/_internal/__init__.py +0 -0
  4. bear_utils/_internal/_version.py +1 -0
  5. bear_utils/_internal/cli.py +119 -0
  6. bear_utils/_internal/debug.py +174 -0
  7. bear_utils/ai/__init__.py +30 -0
  8. bear_utils/ai/ai_helpers/__init__.py +136 -0
  9. bear_utils/ai/ai_helpers/_common.py +19 -0
  10. bear_utils/ai/ai_helpers/_config.py +24 -0
  11. bear_utils/ai/ai_helpers/_parsers.py +194 -0
  12. bear_utils/ai/ai_helpers/_types.py +15 -0
  13. bear_utils/cache/__init__.py +131 -0
  14. bear_utils/cli/__init__.py +22 -0
  15. bear_utils/cli/_args.py +12 -0
  16. bear_utils/cli/_get_version.py +207 -0
  17. bear_utils/cli/commands.py +105 -0
  18. bear_utils/cli/prompt_helpers.py +186 -0
  19. bear_utils/cli/shell/__init__.py +1 -0
  20. bear_utils/cli/shell/_base_command.py +81 -0
  21. bear_utils/cli/shell/_base_shell.py +430 -0
  22. bear_utils/cli/shell/_common.py +19 -0
  23. bear_utils/cli/typer_bridge.py +90 -0
  24. bear_utils/config/__init__.py +13 -0
  25. bear_utils/config/config_manager.py +229 -0
  26. bear_utils/config/dir_manager.py +69 -0
  27. bear_utils/config/settings_manager.py +179 -0
  28. bear_utils/constants/__init__.py +90 -0
  29. bear_utils/constants/_exceptions.py +8 -0
  30. bear_utils/constants/_exit_code.py +60 -0
  31. bear_utils/constants/_http_status_code.py +37 -0
  32. bear_utils/constants/_lazy_typing.py +15 -0
  33. bear_utils/constants/_meta.py +196 -0
  34. bear_utils/constants/date_related.py +25 -0
  35. bear_utils/constants/time_related.py +24 -0
  36. bear_utils/database/__init__.py +8 -0
  37. bear_utils/database/_db_manager.py +98 -0
  38. bear_utils/events/__init__.py +18 -0
  39. bear_utils/events/events_class.py +52 -0
  40. bear_utils/events/events_module.py +74 -0
  41. bear_utils/extras/__init__.py +28 -0
  42. bear_utils/extras/_async_helpers.py +67 -0
  43. bear_utils/extras/_tools.py +185 -0
  44. bear_utils/extras/_zapper.py +399 -0
  45. bear_utils/extras/platform_utils.py +57 -0
  46. bear_utils/extras/responses/__init__.py +5 -0
  47. bear_utils/extras/responses/function_response.py +451 -0
  48. bear_utils/extras/wrappers/__init__.py +1 -0
  49. bear_utils/extras/wrappers/add_methods.py +100 -0
  50. bear_utils/extras/wrappers/string_io.py +46 -0
  51. bear_utils/files/__init__.py +6 -0
  52. bear_utils/files/file_handlers/__init__.py +5 -0
  53. bear_utils/files/file_handlers/_base_file_handler.py +107 -0
  54. bear_utils/files/file_handlers/file_handler_factory.py +280 -0
  55. bear_utils/files/file_handlers/json_file_handler.py +71 -0
  56. bear_utils/files/file_handlers/log_file_handler.py +40 -0
  57. bear_utils/files/file_handlers/toml_file_handler.py +76 -0
  58. bear_utils/files/file_handlers/txt_file_handler.py +76 -0
  59. bear_utils/files/file_handlers/yaml_file_handler.py +64 -0
  60. bear_utils/files/ignore_parser.py +293 -0
  61. bear_utils/graphics/__init__.py +6 -0
  62. bear_utils/graphics/bear_gradient.py +145 -0
  63. bear_utils/graphics/font/__init__.py +13 -0
  64. bear_utils/graphics/font/_raw_block_letters.py +463 -0
  65. bear_utils/graphics/font/_theme.py +31 -0
  66. bear_utils/graphics/font/_utils.py +220 -0
  67. bear_utils/graphics/font/block_font.py +192 -0
  68. bear_utils/graphics/font/glitch_font.py +63 -0
  69. bear_utils/graphics/image_helpers.py +45 -0
  70. bear_utils/gui/__init__.py +8 -0
  71. bear_utils/gui/gui_tools/__init__.py +10 -0
  72. bear_utils/gui/gui_tools/_settings.py +36 -0
  73. bear_utils/gui/gui_tools/_types.py +12 -0
  74. bear_utils/gui/gui_tools/qt_app.py +150 -0
  75. bear_utils/gui/gui_tools/qt_color_picker.py +130 -0
  76. bear_utils/gui/gui_tools/qt_file_handler.py +130 -0
  77. bear_utils/gui/gui_tools/qt_input_dialog.py +303 -0
  78. bear_utils/logger_manager/__init__.py +109 -0
  79. bear_utils/logger_manager/_common.py +63 -0
  80. bear_utils/logger_manager/_console_junk.py +135 -0
  81. bear_utils/logger_manager/_log_level.py +50 -0
  82. bear_utils/logger_manager/_styles.py +95 -0
  83. bear_utils/logger_manager/logger_protocol.py +42 -0
  84. bear_utils/logger_manager/loggers/__init__.py +1 -0
  85. bear_utils/logger_manager/loggers/_console.py +223 -0
  86. bear_utils/logger_manager/loggers/_level_sin.py +61 -0
  87. bear_utils/logger_manager/loggers/_logger.py +19 -0
  88. bear_utils/logger_manager/loggers/base_logger.py +244 -0
  89. bear_utils/logger_manager/loggers/base_logger.pyi +51 -0
  90. bear_utils/logger_manager/loggers/basic_logger/__init__.py +5 -0
  91. bear_utils/logger_manager/loggers/basic_logger/logger.py +80 -0
  92. bear_utils/logger_manager/loggers/basic_logger/logger.pyi +19 -0
  93. bear_utils/logger_manager/loggers/buffer_logger.py +57 -0
  94. bear_utils/logger_manager/loggers/console_logger.py +278 -0
  95. bear_utils/logger_manager/loggers/console_logger.pyi +50 -0
  96. bear_utils/logger_manager/loggers/fastapi_logger.py +333 -0
  97. bear_utils/logger_manager/loggers/file_logger.py +151 -0
  98. bear_utils/logger_manager/loggers/simple_logger.py +98 -0
  99. bear_utils/logger_manager/loggers/sub_logger.py +105 -0
  100. bear_utils/logger_manager/loggers/sub_logger.pyi +23 -0
  101. bear_utils/monitoring/__init__.py +13 -0
  102. bear_utils/monitoring/_common.py +28 -0
  103. bear_utils/monitoring/host_monitor.py +346 -0
  104. bear_utils/time/__init__.py +59 -0
  105. bear_utils-0.0.1.dist-info/METADATA +305 -0
  106. bear_utils-0.0.1.dist-info/RECORD +107 -0
  107. bear_utils-0.0.1.dist-info/WHEEL +4 -0
bear_utils/__init__.py ADDED
@@ -0,0 +1,51 @@
1
+ """A module for Bear Utils, providing various utilities and tools."""
2
+
3
+ from bear_utils.cache import CacheWrapper, cache, cache_factory
4
+ from bear_utils.config.settings_manager import SettingsManager, get_settings_manager
5
+ from bear_utils.constants import DEVNULL, STDERR, STDOUT, ExitCode, HTTPStatusCode
6
+ from bear_utils.database import DatabaseManager
7
+ from bear_utils.events import Events
8
+ from bear_utils.extras.responses import FunctionResponse
9
+ from bear_utils.files.file_handlers.file_handler_factory import FileHandlerFactory
10
+ from bear_utils.logger_manager import BaseLogger, BufferLogger, ConsoleLogger, FileLogger, LoggingClient, LoggingServer
11
+ from bear_utils.logger_manager._common import VERBOSE_CONSOLE_FORMAT
12
+ from bear_utils.logger_manager._styles import VERBOSE
13
+ from bear_utils.time import (
14
+ DATE_FORMAT,
15
+ DATE_TIME_FORMAT,
16
+ EpochTimestamp,
17
+ TimeTools,
18
+ convert_to_milliseconds,
19
+ seconds_to_time,
20
+ )
21
+
22
+ __all__ = [
23
+ "DATE_FORMAT",
24
+ "DATE_TIME_FORMAT",
25
+ "DEVNULL",
26
+ "STDERR",
27
+ "STDOUT",
28
+ "VERBOSE",
29
+ "VERBOSE_CONSOLE_FORMAT",
30
+ "BaseLogger",
31
+ "BufferLogger",
32
+ "CacheWrapper",
33
+ "ConsoleLogger",
34
+ "DatabaseManager",
35
+ "EpochTimestamp",
36
+ "Events",
37
+ "ExitCode",
38
+ "FileHandlerFactory",
39
+ "FileLogger",
40
+ "FunctionResponse",
41
+ "HTTPStatusCode",
42
+ "LoggingClient",
43
+ "LoggingServer",
44
+ "SettingsManager",
45
+ "TimeTools",
46
+ "cache",
47
+ "cache_factory",
48
+ "convert_to_milliseconds",
49
+ "get_settings_manager",
50
+ "seconds_to_time",
51
+ ]
bear_utils/__main__.py ADDED
@@ -0,0 +1,14 @@
1
+ """Entry-point module, in case you use `python -m bear_utils`.
2
+
3
+ Why does this file exist, and why `__main__`? For more info, read:
4
+
5
+ - https://www.python.org/dev/peps/pep-0338/
6
+ - https://docs.python.org/3/using/cmdline.html#cmdoption-m
7
+ """
8
+
9
+ import sys
10
+
11
+ from bear_utils._internal.cli import main
12
+
13
+ if __name__ == "__main__":
14
+ sys.exit(main(sys.argv[1:]))
File without changes
@@ -0,0 +1 @@
1
+ version = "0.0.1"
@@ -0,0 +1,119 @@
1
+ # Why does this file exist, and why not put this in `__main__`?
2
+ #
3
+ # You might be tempted to import things from `__main__` later,
4
+ # but that will cause problems: the code will get executed twice:
5
+ #
6
+ # - When you run `python -m bear_utils` python will execute
7
+ # `__main__.py` as a script. That means there won't be any
8
+ # `bear_utils.__main__` in `sys.modules`.
9
+ # - When you import `__main__` it will get executed again (as a module) because
10
+ # there's no `bear_utils.__main__` in `sys.modules`.
11
+ from __future__ import annotations
12
+
13
+ from argparse import Action, ArgumentParser, Namespace
14
+ import sys
15
+ from typing import Any
16
+
17
+ from bear_utils._internal import debug
18
+ from bear_utils._internal._version import version as _version
19
+ from bear_utils.cli._get_version import VALID_BUMP_TYPES, cli_bump
20
+ from bear_utils.constants import STDERR, ExitCode
21
+
22
+
23
+ class _DebugInfo(Action):
24
+ def __init__(self, nargs: int | str | None = 0, **kwargs: Any) -> None:
25
+ super().__init__(nargs=nargs, **kwargs)
26
+
27
+ def __call__(self, *_: Any, **__: Any) -> None:
28
+ debug._print_debug_info()
29
+ sys.exit(ExitCode.SUCCESS)
30
+
31
+
32
+ class _About(Action):
33
+ def __init__(self, nargs: int | str | None = 0, **kwargs: Any) -> None:
34
+ super().__init__(nargs=nargs, **kwargs)
35
+
36
+ def __call__(self, *_: Any, **__: Any) -> None:
37
+ print(debug._get_package_info())
38
+ sys.exit(ExitCode.SUCCESS)
39
+
40
+
41
+ class _Version(Action):
42
+ def __init__(self, nargs: int | str | None = 0, **kwargs: Any) -> None:
43
+ super().__init__(nargs=nargs, **kwargs)
44
+
45
+ def __call__(self, *_: Any, **__: Any) -> None:
46
+ version: str = f"{debug._get_name()} v{_version}"
47
+ print(version)
48
+ sys.exit(ExitCode.SUCCESS)
49
+
50
+
51
+ def get_version() -> ExitCode:
52
+ """CLI command to get the version of the package."""
53
+ print(_version)
54
+ return ExitCode.SUCCESS
55
+
56
+
57
+ def bump_version(args: list[str] | None = None) -> ExitCode:
58
+ """CLI command to bump the version of the package."""
59
+ parser = ArgumentParser(description="Bump the version of the package.")
60
+ parser.add_argument(
61
+ "bump_type",
62
+ type=str,
63
+ choices=VALID_BUMP_TYPES,
64
+ help=f"Type of version bump: {', '.join(VALID_BUMP_TYPES)}",
65
+ )
66
+ _args: Namespace = parser.parse_args(args or sys.argv[1:])
67
+ return cli_bump([_args.bump_type, debug.__PACKAGE_NAME__, _version])
68
+
69
+
70
+ def get_parser() -> ArgumentParser:
71
+ name = debug._get_name()
72
+ parser = ArgumentParser(description=name.capitalize(), prog=name, exit_on_error=False)
73
+ parser.add_argument("-V", "--version", action=_Version, help="Print the version of the package")
74
+ subparser = parser.add_subparsers(dest="command", required=False, help="Available commands")
75
+ subparser.add_parser("get-version", help="Get the current version of the package")
76
+ bump = subparser.add_parser("bump-version", help="Bump the version of the package")
77
+ bump.add_argument("bump_type", type=str, choices=VALID_BUMP_TYPES, help="major, minor, or patch")
78
+ parser.add_argument("--about", action=_About, help="Print information about the package")
79
+ parser.add_argument("--debug_info", action=_DebugInfo, help="Print debug information")
80
+ return parser
81
+
82
+
83
+ def main(args: list[str] | None = None) -> ExitCode:
84
+ """Main entry point for the CLI.
85
+
86
+ This function is called when the CLI is executed. It can be used to
87
+ initialize the CLI, parse arguments, and execute commands.
88
+
89
+ Args:
90
+ args (list[str] | None): A list of command-line arguments. If None, uses sys.argv[1:].
91
+
92
+ Returns:
93
+ int: Exit code of the CLI execution. 0 for success, non-zero for failure.
94
+ """
95
+ if args is None:
96
+ args = sys.argv[1:]
97
+ try:
98
+ parser: ArgumentParser = get_parser()
99
+ opts: Namespace = parser.parse_args(args)
100
+ command: str | None = opts.command
101
+ if command is None:
102
+ parser.print_help()
103
+ return ExitCode.SUCCESS
104
+ if command == "get-version":
105
+ return get_version()
106
+ if command == "bump-version":
107
+ if not hasattr(opts, "bump_type"):
108
+ print("Error: 'bump-version' command requires a 'bump_type' argument.", STDERR)
109
+ return ExitCode.FAILURE
110
+ bump_type: str = opts.bump_type
111
+ return bump_version([bump_type])
112
+ except Exception as e:
113
+ print(f"Error initializing CLI: {e}", STDERR)
114
+ return ExitCode.FAILURE
115
+ return ExitCode.SUCCESS
116
+
117
+
118
+ if __name__ == "__main__":
119
+ main()
@@ -0,0 +1,174 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass, field
4
+ import importlib.metadata
5
+ from importlib.metadata import PackageNotFoundError, metadata, version
6
+ import os
7
+ import platform
8
+ import sys
9
+
10
+ from bear_utils._internal._version import version as _version
11
+ from bear_utils.cli._get_version import Version
12
+
13
+ __PACKAGE_NAME__ = "bear-utils"
14
+
15
+
16
+ @dataclass
17
+ class _Package:
18
+ """Dataclass to store package information."""
19
+
20
+ name: str = __PACKAGE_NAME__
21
+ """Package name."""
22
+ version: str = _version
23
+ """Package version."""
24
+ _version: Version = field(default_factory=lambda: Version.from_string(_version))
25
+ description: str = "No description available."
26
+ """Package description."""
27
+
28
+ def __post_init__(self) -> None:
29
+ """Post-initialization to ensure version is a string."""
30
+ if not isinstance(self.version, str) or "0.0.0" in self.version:
31
+ self.version = version(self.name) if self.name else "0.0.0"
32
+ if not self.description:
33
+ try:
34
+ self.description = metadata(self.name)["Summary"]
35
+ except PackageNotFoundError:
36
+ self.description = "No description available."
37
+
38
+ def __str__(self) -> str:
39
+ """String representation of the package information."""
40
+ return f"{self.name} v{self.version}: {self.description}"
41
+
42
+
43
+ @dataclass
44
+ class _Variable:
45
+ """Dataclass describing an environment variable."""
46
+
47
+ name: str
48
+ """Variable name."""
49
+ value: str
50
+ """Variable value."""
51
+
52
+
53
+ @dataclass
54
+ class _Environment:
55
+ """Dataclass to store environment information."""
56
+
57
+ interpreter_name: str
58
+ """Python interpreter name."""
59
+ interpreter_version: str
60
+ """Python interpreter version."""
61
+ interpreter_path: str
62
+ """Path to Python executable."""
63
+ platform: str
64
+ """Operating System."""
65
+ packages: list[_Package]
66
+ """Installed packages."""
67
+ variables: list[_Variable]
68
+ """Environment variables."""
69
+
70
+
71
+ def _interpreter_name_version() -> tuple[str, str]:
72
+ if hasattr(sys, "implementation"):
73
+ impl = sys.implementation.version
74
+ version = f"{impl.major}.{impl.minor}.{impl.micro}"
75
+ kind = impl.releaselevel
76
+ if kind != "final":
77
+ version += kind[0] + str(impl.serial)
78
+ return sys.implementation.name, version
79
+ return "", "0.0.0"
80
+
81
+
82
+ def _get_package_info(dist: str = __PACKAGE_NAME__) -> _Package:
83
+ try:
84
+ return _Package(
85
+ name=dist,
86
+ version=_version or version(dist),
87
+ description=metadata(dist)["Summary"],
88
+ )
89
+ except PackageNotFoundError:
90
+ return _Package(name=dist)
91
+
92
+
93
+ def _get_name(dist: str = __PACKAGE_NAME__) -> str:
94
+ """Get name of the given distribution.
95
+
96
+ Parameters:
97
+ dist: A distribution name.
98
+
99
+ Returns:
100
+ A package name.
101
+ """
102
+ return _get_package_info(dist).name
103
+
104
+
105
+ def _get_version(dist: str = __PACKAGE_NAME__) -> str:
106
+ """Get version of the given distribution.
107
+
108
+ Parameters:
109
+ dist: A distribution name.
110
+
111
+ Returns:
112
+ A version number.
113
+ """
114
+ return _get_package_info(dist).version
115
+
116
+
117
+ def _get_description(dist: str = __PACKAGE_NAME__) -> str:
118
+ """Get description of the given distribution.
119
+
120
+ Parameters:
121
+ dist: A distribution name.
122
+
123
+ Returns:
124
+ A description string.
125
+ """
126
+ return _get_package_info(dist).description
127
+
128
+
129
+ def _get_debug_info() -> _Environment:
130
+ """Get debug/environment information.
131
+
132
+ Returns:
133
+ Environment information.
134
+ """
135
+ py_name, py_version = _interpreter_name_version()
136
+ packages: list[str] = [__PACKAGE_NAME__]
137
+ variables: list[str] = [
138
+ "PYTHONPATH",
139
+ *[var for var in os.environ if var.startswith(__PACKAGE_NAME__.replace("-", "_"))],
140
+ ]
141
+ return _Environment(
142
+ interpreter_name=py_name,
143
+ interpreter_version=py_version,
144
+ interpreter_path=sys.executable,
145
+ platform=platform.platform(),
146
+ variables=[_Variable(var, val) for var in variables if (val := os.getenv(var))],
147
+ packages=[_Package(pkg, _get_version(pkg)) for pkg in packages],
148
+ )
149
+
150
+
151
+ def get_installed_packages() -> list[_Package]:
152
+ """Get all installed packages in current environment"""
153
+ packages = []
154
+ for dist in importlib.metadata.distributions():
155
+ packages.append({"name": dist.metadata["Name"], "version": dist.version})
156
+ return packages
157
+
158
+
159
+ def _print_debug_info() -> None:
160
+ """Print debug/environment information."""
161
+ info: _Environment = _get_debug_info()
162
+ print(f"- __System__: {info.platform}")
163
+ print(f"- __Python__: {info.interpreter_name} {info.interpreter_version} ({info.interpreter_path})")
164
+ print("- __Environment variables__:")
165
+ for var in info.variables:
166
+ print(f" - `{var.name}`: `{var.value}`")
167
+ print("- __Installed packages__:")
168
+ for pkg in info.packages:
169
+ print(f" - `{pkg.name}` v{pkg.version}")
170
+
171
+
172
+ if __name__ == "__main__":
173
+ # _print_debug_info()
174
+ print(_get_package_info())
@@ -0,0 +1,30 @@
1
+ """AI Helpers Module for Bear Utils."""
2
+
3
+ from .ai_helpers._common import (
4
+ GPT_4_1,
5
+ GPT_4_1_MINI,
6
+ GPT_4_1_NANO,
7
+ PRODUCTION_MODE,
8
+ TESTING_MODE,
9
+ AIModel,
10
+ EnvironmentMode,
11
+ )
12
+ from .ai_helpers._config import AIEndpointConfig
13
+ from .ai_helpers._parsers import CommandResponseParser, PassthroughResponseParser, ResponseParser, TypedResponseParser
14
+ from .ai_helpers._types import ResponseParser as BaseResponseParser
15
+
16
+ __all__ = [
17
+ "GPT_4_1",
18
+ "GPT_4_1_MINI",
19
+ "GPT_4_1_NANO",
20
+ "PRODUCTION_MODE",
21
+ "TESTING_MODE",
22
+ "AIEndpointConfig",
23
+ "AIModel",
24
+ "BaseResponseParser",
25
+ "CommandResponseParser",
26
+ "EnvironmentMode",
27
+ "PassthroughResponseParser",
28
+ "ResponseParser",
29
+ "TypedResponseParser",
30
+ ]
@@ -0,0 +1,136 @@
1
+ """This module provides helper functions to create AI endpoints with various response parsing strategies."""
2
+
3
+ from collections.abc import Callable
4
+ from typing import Any, cast
5
+
6
+ from rich.markdown import Markdown
7
+
8
+ from bear_utils.logger_manager import BaseLogger
9
+
10
+ from ._common import GPT_4_1_NANO, PRODUCTION_MODE, TESTING_MODE, AIModel, EnvironmentMode
11
+ from ._config import AIEndpointConfig
12
+ from ._parsers import JSONResponseParser, ModularAIEndpoint, PassthroughResponseParser, TypedResponseParser
13
+
14
+
15
+ def create_typed_endpoint[T_Response](
16
+ response_type: type[T_Response],
17
+ project_name: str,
18
+ prompt: str,
19
+ testing_url: str,
20
+ production_url: str,
21
+ logger: BaseLogger,
22
+ transformers: dict[str, Callable] | None = None,
23
+ environment: EnvironmentMode = PRODUCTION_MODE,
24
+ chat_model: AIModel = GPT_4_1_NANO,
25
+ **kwargs,
26
+ ) -> ModularAIEndpoint[T_Response]:
27
+ """Create an endpoint with strict TypedDict response typing."""
28
+ config = AIEndpointConfig(
29
+ project_name=project_name,
30
+ prompt=prompt,
31
+ testing_url=testing_url,
32
+ production_url=production_url,
33
+ environment=environment,
34
+ chat_model=chat_model,
35
+ **kwargs,
36
+ )
37
+ parser: TypedResponseParser[type[T_Response]] = TypedResponseParser(
38
+ default_response=response_type,
39
+ response_transformers=transformers,
40
+ )
41
+ return cast("ModularAIEndpoint[T_Response]", ModularAIEndpoint(config, logger, parser))
42
+
43
+
44
+ def create_command_endpoint[T_Response](
45
+ default_response: T_Response,
46
+ project_name: str,
47
+ prompt: str,
48
+ testing_url: str,
49
+ production_url: str,
50
+ logger: BaseLogger,
51
+ environment: EnvironmentMode = EnvironmentMode.PRODUCTION,
52
+ chat_model: AIModel = GPT_4_1_NANO,
53
+ **kwargs,
54
+ ) -> ModularAIEndpoint[T_Response]:
55
+ """Create an endpoint that returns a command response with Markdown formatting."""
56
+ config = AIEndpointConfig(
57
+ project_name=project_name,
58
+ prompt=prompt,
59
+ testing_url=testing_url,
60
+ production_url=production_url,
61
+ environment=environment,
62
+ chat_model=chat_model,
63
+ **kwargs,
64
+ )
65
+
66
+ parser: TypedResponseParser[T_Response] = TypedResponseParser(
67
+ default_response=default_response,
68
+ response_transformers={"response": lambda x: Markdown(str(x))},
69
+ )
70
+ return ModularAIEndpoint(config=config, logger=logger, response_parser=parser)
71
+
72
+
73
+ def create_flexible_endpoint(
74
+ project_name: str,
75
+ prompt: str,
76
+ testing_url: str,
77
+ production_url: str,
78
+ logger: BaseLogger,
79
+ required_fields: list | None = None,
80
+ transformers: dict[str, Callable] | None = None,
81
+ append_json: bool = True,
82
+ environment: EnvironmentMode = PRODUCTION_MODE,
83
+ chat_model: AIModel = GPT_4_1_NANO,
84
+ **kwargs,
85
+ ) -> ModularAIEndpoint[dict[str, Any]]:
86
+ """Create an endpoint with flexible JSON parsing."""
87
+ config = AIEndpointConfig(
88
+ project_name=project_name,
89
+ prompt=prompt,
90
+ testing_url=testing_url,
91
+ production_url=production_url,
92
+ append_json_suffix=append_json,
93
+ environment=environment,
94
+ chat_model=chat_model,
95
+ **kwargs,
96
+ )
97
+ parser = JSONResponseParser(required_fields=required_fields, response_transformers=transformers)
98
+ return ModularAIEndpoint(config=config, logger=logger, response_parser=parser)
99
+
100
+
101
+ def create_simple_endpoint(
102
+ project_name: str,
103
+ prompt: str,
104
+ testing_url: str,
105
+ production_url: str,
106
+ logger: BaseLogger,
107
+ environment: EnvironmentMode = PRODUCTION_MODE,
108
+ chat_model: AIModel = GPT_4_1_NANO,
109
+ **kwargs,
110
+ ) -> ModularAIEndpoint[dict[str, Any]]:
111
+ """Create an endpoint that returns raw output without JSON parsing."""
112
+ config = AIEndpointConfig(
113
+ project_name=project_name,
114
+ prompt=prompt,
115
+ testing_url=testing_url,
116
+ production_url=production_url,
117
+ append_json_suffix=False,
118
+ environment=environment,
119
+ chat_model=chat_model,
120
+ **kwargs,
121
+ )
122
+ parser = PassthroughResponseParser()
123
+ return ModularAIEndpoint(config, logger, parser)
124
+
125
+
126
+ __all__: list[str] = [
127
+ "PRODUCTION_MODE",
128
+ "TESTING_MODE",
129
+ "AIEndpointConfig",
130
+ "EnvironmentMode",
131
+ "ModularAIEndpoint",
132
+ "create_command_endpoint",
133
+ "create_flexible_endpoint",
134
+ "create_simple_endpoint",
135
+ "create_typed_endpoint",
136
+ ]
@@ -0,0 +1,19 @@
1
+ from enum import Enum, StrEnum
2
+
3
+
4
+ class EnvironmentMode(Enum):
5
+ TESTING = "testing"
6
+ PRODUCTION = "production"
7
+
8
+
9
+ class AIModel(StrEnum):
10
+ GPT_4_1_NANO = "gpt-4.1-nano"
11
+ GPT_4_1_MINI = "gpt-4.1-mini"
12
+ GPT_4_1 = "gpt-4.1"
13
+
14
+
15
+ GPT_4_1_NANO = AIModel.GPT_4_1_NANO
16
+ GPT_4_1_MINI = AIModel.GPT_4_1_MINI
17
+ GPT_4_1 = AIModel.GPT_4_1
18
+ TESTING_MODE = EnvironmentMode.TESTING
19
+ PRODUCTION_MODE = EnvironmentMode.PRODUCTION
@@ -0,0 +1,24 @@
1
+ from dataclasses import dataclass
2
+
3
+ from ._common import GPT_4_1_NANO, PRODUCTION_MODE, AIModel, EnvironmentMode
4
+
5
+
6
+ @dataclass
7
+ class AIEndpointConfig:
8
+ """Configuration for AI endpoint communication."""
9
+
10
+ project_name: str
11
+ bearer_token: str
12
+ prompt: str
13
+ testing_url: str
14
+ production_url: str
15
+ connection_timeout: int = 20
16
+ append_json_suffix: bool = True
17
+ json_suffix: str = " \nEnsure to output your response as json as specified in the prompt"
18
+ chat_model: AIModel | str = GPT_4_1_NANO
19
+ environment: EnvironmentMode = PRODUCTION_MODE
20
+
21
+ @property
22
+ def url(self) -> str:
23
+ """Get the appropriate URL based on environment."""
24
+ return self.testing_url if self.environment == EnvironmentMode.TESTING else self.production_url