mantisdk 0.1.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.

Potentially problematic release.


This version of mantisdk might be problematic. Click here for more details.

Files changed (190) hide show
  1. mantisdk/__init__.py +22 -0
  2. mantisdk/adapter/__init__.py +15 -0
  3. mantisdk/adapter/base.py +94 -0
  4. mantisdk/adapter/messages.py +270 -0
  5. mantisdk/adapter/triplet.py +1028 -0
  6. mantisdk/algorithm/__init__.py +39 -0
  7. mantisdk/algorithm/apo/__init__.py +5 -0
  8. mantisdk/algorithm/apo/apo.py +889 -0
  9. mantisdk/algorithm/apo/prompts/apply_edit_variant01.poml +22 -0
  10. mantisdk/algorithm/apo/prompts/apply_edit_variant02.poml +18 -0
  11. mantisdk/algorithm/apo/prompts/text_gradient_variant01.poml +18 -0
  12. mantisdk/algorithm/apo/prompts/text_gradient_variant02.poml +16 -0
  13. mantisdk/algorithm/apo/prompts/text_gradient_variant03.poml +107 -0
  14. mantisdk/algorithm/base.py +162 -0
  15. mantisdk/algorithm/decorator.py +264 -0
  16. mantisdk/algorithm/fast.py +250 -0
  17. mantisdk/algorithm/gepa/__init__.py +59 -0
  18. mantisdk/algorithm/gepa/adapter.py +459 -0
  19. mantisdk/algorithm/gepa/gepa.py +364 -0
  20. mantisdk/algorithm/gepa/lib/__init__.py +18 -0
  21. mantisdk/algorithm/gepa/lib/adapters/README.md +12 -0
  22. mantisdk/algorithm/gepa/lib/adapters/__init__.py +0 -0
  23. mantisdk/algorithm/gepa/lib/adapters/anymaths_adapter/README.md +341 -0
  24. mantisdk/algorithm/gepa/lib/adapters/anymaths_adapter/__init__.py +1 -0
  25. mantisdk/algorithm/gepa/lib/adapters/anymaths_adapter/anymaths_adapter.py +174 -0
  26. mantisdk/algorithm/gepa/lib/adapters/anymaths_adapter/requirements.txt +1 -0
  27. mantisdk/algorithm/gepa/lib/adapters/default_adapter/README.md +0 -0
  28. mantisdk/algorithm/gepa/lib/adapters/default_adapter/__init__.py +0 -0
  29. mantisdk/algorithm/gepa/lib/adapters/default_adapter/default_adapter.py +209 -0
  30. mantisdk/algorithm/gepa/lib/adapters/dspy_adapter/README.md +7 -0
  31. mantisdk/algorithm/gepa/lib/adapters/dspy_adapter/__init__.py +0 -0
  32. mantisdk/algorithm/gepa/lib/adapters/dspy_adapter/dspy_adapter.py +307 -0
  33. mantisdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/README.md +99 -0
  34. mantisdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/dspy_program_proposal_signature.py +137 -0
  35. mantisdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/full_program_adapter.py +266 -0
  36. mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/GEPA_RAG.md +621 -0
  37. mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/__init__.py +56 -0
  38. mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/evaluation_metrics.py +226 -0
  39. mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/generic_rag_adapter.py +496 -0
  40. mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/rag_pipeline.py +238 -0
  41. mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_store_interface.py +212 -0
  42. mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/__init__.py +2 -0
  43. mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/chroma_store.py +196 -0
  44. mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/lancedb_store.py +422 -0
  45. mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/milvus_store.py +409 -0
  46. mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/qdrant_store.py +368 -0
  47. mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/weaviate_store.py +418 -0
  48. mantisdk/algorithm/gepa/lib/adapters/mcp_adapter/README.md +552 -0
  49. mantisdk/algorithm/gepa/lib/adapters/mcp_adapter/__init__.py +37 -0
  50. mantisdk/algorithm/gepa/lib/adapters/mcp_adapter/mcp_adapter.py +705 -0
  51. mantisdk/algorithm/gepa/lib/adapters/mcp_adapter/mcp_client.py +364 -0
  52. mantisdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/README.md +9 -0
  53. mantisdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/__init__.py +0 -0
  54. mantisdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/terminal_bench_adapter.py +217 -0
  55. mantisdk/algorithm/gepa/lib/api.py +375 -0
  56. mantisdk/algorithm/gepa/lib/core/__init__.py +0 -0
  57. mantisdk/algorithm/gepa/lib/core/adapter.py +180 -0
  58. mantisdk/algorithm/gepa/lib/core/data_loader.py +74 -0
  59. mantisdk/algorithm/gepa/lib/core/engine.py +356 -0
  60. mantisdk/algorithm/gepa/lib/core/result.py +233 -0
  61. mantisdk/algorithm/gepa/lib/core/state.py +636 -0
  62. mantisdk/algorithm/gepa/lib/examples/__init__.py +0 -0
  63. mantisdk/algorithm/gepa/lib/examples/aime.py +24 -0
  64. mantisdk/algorithm/gepa/lib/examples/anymaths-bench/eval_default.py +111 -0
  65. mantisdk/algorithm/gepa/lib/examples/anymaths-bench/prompt-templates/instruction_prompt.txt +9 -0
  66. mantisdk/algorithm/gepa/lib/examples/anymaths-bench/prompt-templates/optimal_prompt.txt +24 -0
  67. mantisdk/algorithm/gepa/lib/examples/anymaths-bench/train_anymaths.py +177 -0
  68. mantisdk/algorithm/gepa/lib/examples/dspy_full_program_evolution/arc_agi.ipynb +25705 -0
  69. mantisdk/algorithm/gepa/lib/examples/dspy_full_program_evolution/example.ipynb +348 -0
  70. mantisdk/algorithm/gepa/lib/examples/mcp_adapter/__init__.py +4 -0
  71. mantisdk/algorithm/gepa/lib/examples/mcp_adapter/mcp_optimization_example.py +455 -0
  72. mantisdk/algorithm/gepa/lib/examples/rag_adapter/RAG_GUIDE.md +613 -0
  73. mantisdk/algorithm/gepa/lib/examples/rag_adapter/__init__.py +9 -0
  74. mantisdk/algorithm/gepa/lib/examples/rag_adapter/rag_optimization.py +824 -0
  75. mantisdk/algorithm/gepa/lib/examples/rag_adapter/requirements-rag.txt +29 -0
  76. mantisdk/algorithm/gepa/lib/examples/terminal-bench/prompt-templates/instruction_prompt.txt +16 -0
  77. mantisdk/algorithm/gepa/lib/examples/terminal-bench/prompt-templates/terminus.txt +9 -0
  78. mantisdk/algorithm/gepa/lib/examples/terminal-bench/train_terminus.py +161 -0
  79. mantisdk/algorithm/gepa/lib/gepa_utils.py +117 -0
  80. mantisdk/algorithm/gepa/lib/logging/__init__.py +0 -0
  81. mantisdk/algorithm/gepa/lib/logging/experiment_tracker.py +187 -0
  82. mantisdk/algorithm/gepa/lib/logging/logger.py +75 -0
  83. mantisdk/algorithm/gepa/lib/logging/utils.py +103 -0
  84. mantisdk/algorithm/gepa/lib/proposer/__init__.py +0 -0
  85. mantisdk/algorithm/gepa/lib/proposer/base.py +31 -0
  86. mantisdk/algorithm/gepa/lib/proposer/merge.py +357 -0
  87. mantisdk/algorithm/gepa/lib/proposer/reflective_mutation/__init__.py +0 -0
  88. mantisdk/algorithm/gepa/lib/proposer/reflective_mutation/base.py +49 -0
  89. mantisdk/algorithm/gepa/lib/proposer/reflective_mutation/reflective_mutation.py +176 -0
  90. mantisdk/algorithm/gepa/lib/py.typed +0 -0
  91. mantisdk/algorithm/gepa/lib/strategies/__init__.py +0 -0
  92. mantisdk/algorithm/gepa/lib/strategies/batch_sampler.py +77 -0
  93. mantisdk/algorithm/gepa/lib/strategies/candidate_selector.py +50 -0
  94. mantisdk/algorithm/gepa/lib/strategies/component_selector.py +36 -0
  95. mantisdk/algorithm/gepa/lib/strategies/eval_policy.py +64 -0
  96. mantisdk/algorithm/gepa/lib/strategies/instruction_proposal.py +127 -0
  97. mantisdk/algorithm/gepa/lib/utils/__init__.py +10 -0
  98. mantisdk/algorithm/gepa/lib/utils/stop_condition.py +196 -0
  99. mantisdk/algorithm/gepa/tracing.py +105 -0
  100. mantisdk/algorithm/utils.py +177 -0
  101. mantisdk/algorithm/verl/__init__.py +5 -0
  102. mantisdk/algorithm/verl/interface.py +202 -0
  103. mantisdk/cli/__init__.py +56 -0
  104. mantisdk/cli/prometheus.py +115 -0
  105. mantisdk/cli/store.py +131 -0
  106. mantisdk/cli/vllm.py +29 -0
  107. mantisdk/client.py +408 -0
  108. mantisdk/config.py +348 -0
  109. mantisdk/emitter/__init__.py +43 -0
  110. mantisdk/emitter/annotation.py +370 -0
  111. mantisdk/emitter/exception.py +54 -0
  112. mantisdk/emitter/message.py +61 -0
  113. mantisdk/emitter/object.py +117 -0
  114. mantisdk/emitter/reward.py +320 -0
  115. mantisdk/env_var.py +156 -0
  116. mantisdk/execution/__init__.py +15 -0
  117. mantisdk/execution/base.py +64 -0
  118. mantisdk/execution/client_server.py +443 -0
  119. mantisdk/execution/events.py +69 -0
  120. mantisdk/execution/inter_process.py +16 -0
  121. mantisdk/execution/shared_memory.py +282 -0
  122. mantisdk/instrumentation/__init__.py +119 -0
  123. mantisdk/instrumentation/agentops.py +314 -0
  124. mantisdk/instrumentation/agentops_langchain.py +45 -0
  125. mantisdk/instrumentation/litellm.py +83 -0
  126. mantisdk/instrumentation/vllm.py +81 -0
  127. mantisdk/instrumentation/weave.py +500 -0
  128. mantisdk/litagent/__init__.py +11 -0
  129. mantisdk/litagent/decorator.py +536 -0
  130. mantisdk/litagent/litagent.py +252 -0
  131. mantisdk/llm_proxy.py +1890 -0
  132. mantisdk/logging.py +370 -0
  133. mantisdk/reward.py +7 -0
  134. mantisdk/runner/__init__.py +11 -0
  135. mantisdk/runner/agent.py +845 -0
  136. mantisdk/runner/base.py +182 -0
  137. mantisdk/runner/legacy.py +309 -0
  138. mantisdk/semconv.py +170 -0
  139. mantisdk/server.py +401 -0
  140. mantisdk/store/__init__.py +23 -0
  141. mantisdk/store/base.py +897 -0
  142. mantisdk/store/client_server.py +2092 -0
  143. mantisdk/store/collection/__init__.py +30 -0
  144. mantisdk/store/collection/base.py +587 -0
  145. mantisdk/store/collection/memory.py +970 -0
  146. mantisdk/store/collection/mongo.py +1412 -0
  147. mantisdk/store/collection_based.py +1823 -0
  148. mantisdk/store/insight.py +648 -0
  149. mantisdk/store/listener.py +58 -0
  150. mantisdk/store/memory.py +396 -0
  151. mantisdk/store/mongo.py +165 -0
  152. mantisdk/store/sqlite.py +3 -0
  153. mantisdk/store/threading.py +357 -0
  154. mantisdk/store/utils.py +142 -0
  155. mantisdk/tracer/__init__.py +16 -0
  156. mantisdk/tracer/agentops.py +242 -0
  157. mantisdk/tracer/base.py +287 -0
  158. mantisdk/tracer/dummy.py +106 -0
  159. mantisdk/tracer/otel.py +555 -0
  160. mantisdk/tracer/weave.py +677 -0
  161. mantisdk/trainer/__init__.py +6 -0
  162. mantisdk/trainer/init_utils.py +263 -0
  163. mantisdk/trainer/legacy.py +367 -0
  164. mantisdk/trainer/registry.py +12 -0
  165. mantisdk/trainer/trainer.py +618 -0
  166. mantisdk/types/__init__.py +6 -0
  167. mantisdk/types/core.py +553 -0
  168. mantisdk/types/resources.py +204 -0
  169. mantisdk/types/tracer.py +515 -0
  170. mantisdk/types/tracing.py +218 -0
  171. mantisdk/utils/__init__.py +1 -0
  172. mantisdk/utils/id.py +18 -0
  173. mantisdk/utils/metrics.py +1025 -0
  174. mantisdk/utils/otel.py +578 -0
  175. mantisdk/utils/otlp.py +536 -0
  176. mantisdk/utils/server_launcher.py +1045 -0
  177. mantisdk/utils/system_snapshot.py +81 -0
  178. mantisdk/verl/__init__.py +8 -0
  179. mantisdk/verl/__main__.py +6 -0
  180. mantisdk/verl/async_server.py +46 -0
  181. mantisdk/verl/config.yaml +27 -0
  182. mantisdk/verl/daemon.py +1154 -0
  183. mantisdk/verl/dataset.py +44 -0
  184. mantisdk/verl/entrypoint.py +248 -0
  185. mantisdk/verl/trainer.py +549 -0
  186. mantisdk-0.1.0.dist-info/METADATA +119 -0
  187. mantisdk-0.1.0.dist-info/RECORD +190 -0
  188. mantisdk-0.1.0.dist-info/WHEEL +4 -0
  189. mantisdk-0.1.0.dist-info/entry_points.txt +2 -0
  190. mantisdk-0.1.0.dist-info/licenses/LICENSE +19 -0
mantisdk/logging.py ADDED
@@ -0,0 +1,370 @@
1
+ # Copyright (c) Microsoft. All rights reserved.
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+ import os
7
+ import platform
8
+ import sys
9
+ import warnings
10
+ from logging.config import dictConfig
11
+ from typing import Any, Dict, Optional
12
+
13
+ from rich.console import Console
14
+
15
+ __all__ = ["setup", "configure_logger", "setup_module"]
16
+
17
+
18
+ def configure_logger(level: int = logging.INFO, name: str = "mantisdk") -> logging.Logger:
19
+ """Create or reset a namespaced logger with a consistent console format.
20
+
21
+ This helper clears any previously attached handlers before binding a single
22
+ `StreamHandler` that writes to standard output. The resulting logger does
23
+ not propagate to the root logger, preventing duplicate log emission when
24
+ applications compose multiple logging configurations.
25
+
26
+ !!! danger
27
+
28
+ This function is deprecated in favor of [`setup_logging`][mantisdk.setup_logging].
29
+
30
+ Args:
31
+ level: Logging level applied both to the logger and the installed
32
+ handler. Defaults to `logging.INFO`.
33
+ name: Dotted path for the logger instance. Defaults to
34
+ `"mantisdk"`.
35
+
36
+ Returns:
37
+ Configured logger instance ready for immediate use.
38
+
39
+ Examples:
40
+ ```python
41
+ from mantisdk import configure_logger
42
+
43
+ logger = configure_logger(level=logging.INFO)
44
+ logger.info("mantisdk is ready!")
45
+ ```
46
+ """
47
+ warnings.warn("This function is deprecated in favor of `setup_logging`.", DeprecationWarning, stacklevel=2)
48
+
49
+ return setup_module(level=level, name=name, console=True, color=True, propagate=False)
50
+
51
+
52
+ DEFAULT_FORMAT = "%(asctime)s [%(levelname)s] (Process-%(process)d %(name)s) %(message)s"
53
+ DATE_FORMAT = "%H:%M:%S"
54
+
55
+
56
+ def _to_level_value(lvl: int | str) -> int:
57
+ if isinstance(lvl, int):
58
+ return lvl
59
+ val = getattr(logging, str(lvl).upper(), None)
60
+ if val is None:
61
+ raise ValueError(f"Invalid log level: {lvl}")
62
+ return val
63
+
64
+
65
+ def _ensure_file_handler(
66
+ logger: logging.Logger,
67
+ filename: str,
68
+ *,
69
+ level: int,
70
+ formatter: Optional[logging.Formatter],
71
+ ) -> None:
72
+ """Attach a FileHandler to `logger` for `filename` if it doesn't already exist."""
73
+ abspath = os.path.abspath(filename)
74
+
75
+ # Avoid duplicates
76
+ for h in logger.handlers:
77
+ if isinstance(h, logging.FileHandler) and getattr(h, "baseFilename", None) == abspath:
78
+ return
79
+
80
+ # Ensure directory exists
81
+ dirname = os.path.dirname(abspath)
82
+ if dirname:
83
+ os.makedirs(dirname, exist_ok=True)
84
+
85
+ fh = logging.FileHandler(abspath, encoding="utf-8")
86
+ fh.setLevel(level)
87
+ if formatter is not None:
88
+ fh.setFormatter(formatter)
89
+ else:
90
+ fh.setFormatter(logging.Formatter(DEFAULT_FORMAT, DATE_FORMAT))
91
+
92
+ logger.addHandler(fh)
93
+
94
+
95
+ def setup(
96
+ level: int | str = "INFO",
97
+ *,
98
+ console: bool = True,
99
+ color: bool | Dict[str, Any] = True,
100
+ propagate: bool = False,
101
+ disable_existing_loggers: bool = False,
102
+ capture_warnings: bool = False,
103
+ submodule_levels: Optional[dict[str, int | str]] = None,
104
+ extra_handlers: Optional[list[logging.Handler]] = None,
105
+ formatter: Optional[logging.Formatter] = None,
106
+ apply_to: Optional[list[str]] = None,
107
+ files: Optional[str | dict[str, str]] = None,
108
+ ) -> None:
109
+ """Configures logging for the `mantisdk` logger hierarchy.
110
+
111
+ This function provides a one-stop setup utility for configuring the
112
+ `mantisdk` root logger and optionally its submodules or external
113
+ loggers. It supports console logging, colored rich output, per-submodule
114
+ log levels, and optional handler/formatter injection.
115
+
116
+ The setup is intentionally isolated: it does not modify the global root
117
+ logger or loggers belonging to other libraries unless explicitly directed
118
+ via `apply_to`.
119
+
120
+ Args:
121
+ level:
122
+ Logging level for the base `mantisdk` logger. Accepts either
123
+ an integer (e.g., `logging.DEBUG`) or a string level name
124
+ (e.g., `"INFO"`). Defaults to `"INFO"`.
125
+ console:
126
+ Whether to attach a console handler to the logger. Defaults to
127
+ `True`.
128
+ color:
129
+ Enables rich-formatted output using `RichHandler` when `True`
130
+ or a configuration dict. If `False`, a plain text formatter is
131
+ used instead. Defaults to `True`.
132
+ propagate:
133
+ Whether `mantisdk` logs should propagate to ancestor
134
+ loggers. Defaults to `False`.
135
+ disable_existing_loggers:
136
+ Passed to `logging.config.dictConfig`. If `True`, disables all
137
+ existing configured loggers before applying this configuration.
138
+ Defaults to `False`.
139
+ capture_warnings:
140
+ If `True`, redirects Python `warnings` emitted via the `warnings`
141
+ module into the logging system. Defaults to `False`.
142
+ submodule_levels:
143
+ Mapping of submodule logger names to logging levels. If a specified
144
+ submodule level is more verbose than the base level, a warning is emitted.
145
+ extra_handlers:
146
+ A list of user-provided handlers to attach to the `mantisdk` logger.
147
+ Handlers are added idempotently; duplicates are not reattached.
148
+ formatter:
149
+ A formatter to apply to any handler under `mantisdk` that does not
150
+ already have one assigned. Useful for customizing output without overwriting
151
+ formatters on custom handlers.
152
+ apply_to:
153
+ A list of additional logger names to configure identically to
154
+ `mantisdk` base logger. Their handlers are replaced with copies of the base
155
+ handlers, and propagation is disabled to avoid duplicate log emission.
156
+ files:
157
+ If a string, attach a FileHandler to the base `mantisdk` logger.
158
+ If a dict, for each `(logger_name, filename)` pair, attach a FileHandler
159
+ directly to that logger.
160
+ Each file handler should use the logger's effective level at creation.
161
+
162
+ Notes:
163
+ * On Windows, this function forces UTF-8 mode in the console to prevent
164
+ issues with rich output or special characters.
165
+ * Submodule loggers can generate records below the handler's emission
166
+ threshold. Whether such records appear depends on both the logger's
167
+ level and the handler's level.
168
+ * `apply_to` loggers inherit the same handlers but do not propagate
169
+ upward, yielding isolated, consistent behavior.
170
+
171
+ Examples:
172
+ Basic setup:
173
+
174
+ >>> setup()
175
+
176
+ Enabling debug mode with no color:
177
+
178
+ >>> setup(level="DEBUG", color=False)
179
+
180
+ Overriding specific submodule levels:
181
+
182
+ >>> setup(submodule_levels={"mantisdk.io": "DEBUG"})
183
+
184
+ Attaching an additional file handler:
185
+
186
+ >>> fh = logging.FileHandler("app.log")
187
+ >>> setup(extra_handlers=[fh])
188
+ """
189
+ # Ensure UTF-8 encoding on Windows consoles
190
+ # Note: This change does not fully represent support for execution under the windows system.
191
+ # It only fixes console printing issues caused by special characters.
192
+ # TODO: More comprehensive Windows support may be needed in the future.
193
+ if platform.system() == "Windows":
194
+ os.environ["PYTHONUTF8"] = "1"
195
+
196
+ base_logger = setup_module(
197
+ level,
198
+ name="mantisdk",
199
+ console=console,
200
+ color=color,
201
+ propagate=propagate,
202
+ disable_existing_loggers=disable_existing_loggers,
203
+ )
204
+
205
+ base_level_value = base_logger.level
206
+
207
+ # Apply user-provided formatter (only to handlers without one,
208
+ # so we don't clobber custom extra_handlers)
209
+ if formatter is not None:
210
+ for h in base_logger.handlers:
211
+ if h.formatter is None:
212
+ h.setFormatter(formatter)
213
+
214
+ # Attach user-provided handler(s) if any, idempotently
215
+ if extra_handlers:
216
+ for h in extra_handlers:
217
+ if h not in base_logger.handlers:
218
+ base_logger.addHandler(h)
219
+
220
+ # Per-submodule levels
221
+ if submodule_levels:
222
+ for name, lvl in submodule_levels.items():
223
+ sub_level = _to_level_value(lvl)
224
+
225
+ # Emit a warning if submodule level is lower (more verbose) than the global/base level
226
+ if sub_level < base_level_value:
227
+ base_logger.warning(
228
+ "Submodule logger '%s' level %s (%s) is more verbose than base "
229
+ "logger level %s (%s). Records below the base level may still be "
230
+ "filtered out by handlers depending on their own levels.",
231
+ name,
232
+ lvl,
233
+ sub_level,
234
+ logging.getLevelName(base_level_value),
235
+ base_level_value,
236
+ )
237
+
238
+ # The logger will *create* records down to the logger's level, but a handler
239
+ # with a higher level will still drop anything below its own threshold.
240
+ # Effective emission is gated by both: record.level >= logger.level AND handler.level.
241
+ logging.getLogger(name).setLevel(lvl)
242
+
243
+ # Attach file handlers if requested
244
+ if files is not None:
245
+ if isinstance(files, str):
246
+ # Single file for the entire `mantisdk` hierarchy.
247
+ _ensure_file_handler(
248
+ logger=base_logger,
249
+ filename=files,
250
+ level=base_level_value,
251
+ formatter=formatter,
252
+ )
253
+ else:
254
+ # Per-logger files
255
+ for logger_name, filename in files.items():
256
+ lg = logging.getLogger(logger_name)
257
+ # Use the logger's *effective* level at creation time
258
+ effective_level = lg.getEffectiveLevel()
259
+ _ensure_file_handler(
260
+ logger=lg,
261
+ filename=filename,
262
+ level=effective_level,
263
+ formatter=formatter,
264
+ )
265
+
266
+ # Optionally apply the same handler setup to other loggers outside this module
267
+ if apply_to:
268
+ for name in apply_to:
269
+ lg = logging.getLogger(name)
270
+ # This removes any existing handlers so we don't duplicate output
271
+ # and ensures these loggers share exactly the same handlers as base_logger.
272
+ lg.handlers.clear()
273
+ for h in base_logger.handlers:
274
+ lg.addHandler(h)
275
+ lg.setLevel(base_logger.level)
276
+ # We've attached handlers directly to these loggers; if propagate
277
+ # stayed True, records would bubble up to ancestor loggers and could be
278
+ # emitted twice (here and on the parent/root). Setting False isolates them.
279
+ lg.propagate = False
280
+
281
+ # Optionally capture warnings
282
+ if capture_warnings:
283
+ logging.captureWarnings(True)
284
+
285
+
286
+ def setup_module(
287
+ level: int | str = "INFO",
288
+ *,
289
+ name: str = "mantisdk",
290
+ console: bool = True,
291
+ color: bool | Dict[str, Any] = True,
292
+ propagate: bool = False,
293
+ disable_existing_loggers: bool = False,
294
+ ) -> logging.Logger:
295
+ """Initializes and returns the base logger for `mantisdk`.
296
+
297
+ This function constructs and applies a `dictConfig` configuration for the
298
+ logger hierarchy rooted at `name`. It supports either rich console
299
+ formatting (via `RichHandler`) or plain text formatting, based on the
300
+ `color` argument.
301
+
302
+ Unlike [`setup_logging`][mantisdk.setup_logging], this function configures only a single logger namespace
303
+ and does not attach extra handlers or submodule levels. It is primarily used
304
+ internally by [`setup_logging`][mantisdk.setup_logging] but is also suitable for direct integration in
305
+ custom logging workflows.
306
+ """
307
+ root_cfg: Dict[str, Any] = {
308
+ "version": 1,
309
+ "disable_existing_loggers": disable_existing_loggers,
310
+ "loggers": {
311
+ name: {
312
+ "handlers": [],
313
+ "level": level,
314
+ "propagate": propagate,
315
+ }
316
+ },
317
+ "handlers": {},
318
+ "formatters": {},
319
+ }
320
+
321
+ # Choose formatter / handler definition
322
+ if color is not False and console:
323
+ # Console must be true to display colored outputs
324
+ if isinstance(color, dict):
325
+ rich_handler_config = color
326
+ else:
327
+ rich_handler_config: Dict[str, Any] = {
328
+ "rich_tracebacks": False,
329
+ "markup": False,
330
+ "show_time": True,
331
+ "show_path": True,
332
+ }
333
+
334
+ if not _has_width():
335
+ # e.g., in a CI environment.
336
+ rich_handler_config["console"] = Console(width=200)
337
+
338
+ root_cfg["handlers"]["console"] = {
339
+ "class": "rich.logging.RichHandler",
340
+ "level": level,
341
+ **rich_handler_config,
342
+ }
343
+ # RichHandler manages its own style; keep formatter None
344
+ else:
345
+ fmt_name = "plain"
346
+ root_cfg["formatters"][fmt_name] = {
347
+ "format": DEFAULT_FORMAT,
348
+ "datefmt": DATE_FORMAT,
349
+ }
350
+
351
+ if console:
352
+ root_cfg["handlers"]["console"] = {
353
+ "class": "logging.StreamHandler",
354
+ "level": level,
355
+ "formatter": fmt_name,
356
+ }
357
+
358
+ # Attach selected handlers to mantisdk
359
+ handler_names = list(root_cfg["handlers"].keys())
360
+ root_cfg["loggers"][name]["handlers"] = handler_names
361
+
362
+ # Apply dictConfig (this resets the logger handlers)
363
+ dictConfig(root_cfg)
364
+
365
+ return logging.getLogger(name)
366
+
367
+
368
+ def _has_width() -> bool:
369
+ """Automatically determine whether the terminal has a width."""
370
+ return sys.stdout.isatty()
mantisdk/reward.py ADDED
@@ -0,0 +1,7 @@
1
+ # Copyright (c) Microsoft. All rights reserved.
2
+
3
+ import warnings
4
+
5
+ from .emitter.reward import * # noqa: F401,F403
6
+
7
+ warnings.warn("mantisdk.reward is deprecated. Please use mantisdk.emitter instead.")
@@ -0,0 +1,11 @@
1
+ # Copyright (c) Microsoft. All rights reserved.
2
+
3
+ from .agent import LitAgentRunner
4
+ from .base import Runner
5
+ from .legacy import LegacyAgentRunner
6
+
7
+ __all__ = [
8
+ "Runner",
9
+ "LegacyAgentRunner",
10
+ "LitAgentRunner",
11
+ ]