minder-cli 0.2.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.
Files changed (132) hide show
  1. minder/__init__.py +12 -0
  2. minder/api/routers/prompts.py +177 -0
  3. minder/application/__init__.py +1 -0
  4. minder/application/admin/__init__.py +11 -0
  5. minder/application/admin/dto.py +453 -0
  6. minder/application/admin/jobs.py +327 -0
  7. minder/application/admin/use_cases.py +1895 -0
  8. minder/auth/__init__.py +12 -0
  9. minder/auth/context.py +26 -0
  10. minder/auth/middleware.py +70 -0
  11. minder/auth/principal.py +59 -0
  12. minder/auth/rate_limiter.py +89 -0
  13. minder/auth/rbac.py +60 -0
  14. minder/auth/service.py +541 -0
  15. minder/bootstrap/__init__.py +9 -0
  16. minder/bootstrap/providers.py +109 -0
  17. minder/bootstrap/transport.py +807 -0
  18. minder/cache/__init__.py +10 -0
  19. minder/cache/providers.py +140 -0
  20. minder/chunking/__init__.py +4 -0
  21. minder/chunking/code_splitter.py +184 -0
  22. minder/chunking/splitter.py +136 -0
  23. minder/cli.py +1542 -0
  24. minder/config.py +179 -0
  25. minder/continuity.py +363 -0
  26. minder/dev.py +160 -0
  27. minder/embedding/__init__.py +9 -0
  28. minder/embedding/base.py +7 -0
  29. minder/embedding/local.py +65 -0
  30. minder/embedding/openai.py +7 -0
  31. minder/graph/__init__.py +11 -0
  32. minder/graph/edges.py +13 -0
  33. minder/graph/executor.py +127 -0
  34. minder/graph/graph.py +263 -0
  35. minder/graph/nodes/__init__.py +27 -0
  36. minder/graph/nodes/evaluator.py +21 -0
  37. minder/graph/nodes/guard.py +64 -0
  38. minder/graph/nodes/llm.py +59 -0
  39. minder/graph/nodes/planning.py +30 -0
  40. minder/graph/nodes/reasoning.py +87 -0
  41. minder/graph/nodes/reranker.py +141 -0
  42. minder/graph/nodes/retriever.py +86 -0
  43. minder/graph/nodes/verification.py +230 -0
  44. minder/graph/nodes/workflow_planner.py +250 -0
  45. minder/graph/runtime.py +15 -0
  46. minder/graph/state.py +26 -0
  47. minder/llm/__init__.py +5 -0
  48. minder/llm/base.py +14 -0
  49. minder/llm/local.py +381 -0
  50. minder/llm/openai.py +89 -0
  51. minder/models/__init__.py +109 -0
  52. minder/models/base.py +10 -0
  53. minder/models/client.py +137 -0
  54. minder/models/document.py +34 -0
  55. minder/models/error.py +32 -0
  56. minder/models/graph.py +114 -0
  57. minder/models/history.py +32 -0
  58. minder/models/job.py +62 -0
  59. minder/models/prompt.py +41 -0
  60. minder/models/repository.py +62 -0
  61. minder/models/rule.py +68 -0
  62. minder/models/session.py +51 -0
  63. minder/models/skill.py +52 -0
  64. minder/models/user.py +41 -0
  65. minder/models/workflow.py +35 -0
  66. minder/observability/__init__.py +57 -0
  67. minder/observability/audit.py +243 -0
  68. minder/observability/logging.py +253 -0
  69. minder/observability/metrics.py +448 -0
  70. minder/observability/tracing.py +215 -0
  71. minder/presentation/__init__.py +1 -0
  72. minder/presentation/http/__init__.py +1 -0
  73. minder/presentation/http/admin/__init__.py +3 -0
  74. minder/presentation/http/admin/api.py +1309 -0
  75. minder/presentation/http/admin/context.py +94 -0
  76. minder/presentation/http/admin/dashboard.py +111 -0
  77. minder/presentation/http/admin/jobs.py +208 -0
  78. minder/presentation/http/admin/memories.py +185 -0
  79. minder/presentation/http/admin/prompts.py +219 -0
  80. minder/presentation/http/admin/routes.py +127 -0
  81. minder/presentation/http/admin/runtime.py +650 -0
  82. minder/presentation/http/admin/search.py +368 -0
  83. minder/presentation/http/admin/skills.py +230 -0
  84. minder/prompts/__init__.py +646 -0
  85. minder/prompts/formatter.py +142 -0
  86. minder/resources/__init__.py +318 -0
  87. minder/retrieval/__init__.py +5 -0
  88. minder/retrieval/hybrid.py +178 -0
  89. minder/retrieval/mmr.py +116 -0
  90. minder/retrieval/multi_hop.py +115 -0
  91. minder/runtime.py +15 -0
  92. minder/server.py +145 -0
  93. minder/store/__init__.py +64 -0
  94. minder/store/document.py +115 -0
  95. minder/store/error.py +82 -0
  96. minder/store/feedback.py +114 -0
  97. minder/store/graph.py +588 -0
  98. minder/store/history.py +57 -0
  99. minder/store/interfaces.py +512 -0
  100. minder/store/milvus/__init__.py +11 -0
  101. minder/store/milvus/client.py +26 -0
  102. minder/store/milvus/collections.py +15 -0
  103. minder/store/milvus/vector_store.py +232 -0
  104. minder/store/mongodb/__init__.py +11 -0
  105. minder/store/mongodb/client.py +49 -0
  106. minder/store/mongodb/indexes.py +90 -0
  107. minder/store/mongodb/operational_store.py +993 -0
  108. minder/store/relational.py +1087 -0
  109. minder/store/repo_state.py +58 -0
  110. minder/store/rule.py +93 -0
  111. minder/store/vector.py +79 -0
  112. minder/tools/__init__.py +47 -0
  113. minder/tools/auth.py +94 -0
  114. minder/tools/graph.py +839 -0
  115. minder/tools/ingest.py +353 -0
  116. minder/tools/memory.py +381 -0
  117. minder/tools/query.py +307 -0
  118. minder/tools/registry.py +269 -0
  119. minder/tools/repo_scanner.py +1266 -0
  120. minder/tools/search.py +15 -0
  121. minder/tools/session.py +316 -0
  122. minder/tools/skills.py +899 -0
  123. minder/tools/workflow.py +215 -0
  124. minder/transport/__init__.py +4 -0
  125. minder/transport/base.py +286 -0
  126. minder/transport/sse.py +252 -0
  127. minder/transport/stdio.py +29 -0
  128. minder_cli-0.2.0.dist-info/METADATA +318 -0
  129. minder_cli-0.2.0.dist-info/RECORD +132 -0
  130. minder_cli-0.2.0.dist-info/WHEEL +4 -0
  131. minder_cli-0.2.0.dist-info/entry_points.txt +2 -0
  132. minder_cli-0.2.0.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,215 @@
1
+ """OpenTelemetry tracing helpers for Minder.
2
+
3
+ The module uses a graceful-degradation pattern: it tries to import the
4
+ ``opentelemetry`` packages at import time. If they are not installed the
5
+ module falls back to a lightweight no-op implementation so the rest of the
6
+ codebase can import and call ``get_tracer`` / ``trace_async`` / ``start_span``
7
+ unconditionally without a hard dependency on the OTel SDK.
8
+
9
+ Installing the SDK is opt-in:
10
+ uv add opentelemetry-api opentelemetry-sdk
11
+
12
+ The OTLP exporter is also optional:
13
+ uv add opentelemetry-exporter-otlp-proto-grpc
14
+ """
15
+ from __future__ import annotations
16
+
17
+ import functools
18
+ import logging
19
+ from contextlib import asynccontextmanager, contextmanager
20
+ from typing import Any, AsyncIterator, Callable, Iterator, TypeVar
21
+
22
+ _log = logging.getLogger(__name__)
23
+
24
+ F = TypeVar("F", bound=Callable[..., Any])
25
+
26
+ # ---------------------------------------------------------------------------
27
+ # Try to import the real OTel SDK
28
+ # ---------------------------------------------------------------------------
29
+
30
+ try:
31
+ from opentelemetry import trace as _otel_trace # type: ignore[import-not-found,import-untyped]
32
+ from opentelemetry.sdk.resources import Resource # type: ignore[import-not-found,import-untyped]
33
+ from opentelemetry.sdk.trace import TracerProvider # type: ignore[import-not-found,import-untyped]
34
+ from opentelemetry.sdk.trace.export import ( # type: ignore[import-not-found,import-untyped]
35
+ BatchSpanProcessor,
36
+ ConsoleSpanExporter,
37
+ )
38
+
39
+ _OTEL_AVAILABLE = True
40
+ except ImportError: # pragma: no cover – OTel is optional
41
+ _OTEL_AVAILABLE = False
42
+
43
+ # ---------------------------------------------------------------------------
44
+ # Global tracer provider reference
45
+ # ---------------------------------------------------------------------------
46
+
47
+ _provider: Any = None # TracerProvider | None
48
+
49
+
50
+ def _is_configured() -> bool:
51
+ return _provider is not None
52
+
53
+
54
+ # ---------------------------------------------------------------------------
55
+ # Initialisation
56
+ # ---------------------------------------------------------------------------
57
+
58
+
59
+ def configure_tracing(
60
+ service_name: str = "minder",
61
+ service_version: str = "0.1.0",
62
+ *,
63
+ otlp_endpoint: str | None = None,
64
+ console_export: bool = False,
65
+ ) -> None:
66
+ """Initialise the OTel tracer provider.
67
+
68
+ Call once at server startup (from ``bootstrap/providers.py``).
69
+
70
+ Args:
71
+ service_name: OTel ``service.name`` resource attribute.
72
+ service_version: OTel ``service.version`` resource attribute.
73
+ otlp_endpoint: gRPC OTLP collector endpoint, e.g.
74
+ ``"http://otel-collector:4317"``. When *None* and
75
+ *console_export* is *False*, a no-op provider is used.
76
+ console_export: Emit spans to stdout (useful for local debugging).
77
+ """
78
+ global _provider # noqa: PLW0603
79
+
80
+ if not _OTEL_AVAILABLE:
81
+ _log.info(
82
+ "opentelemetry-sdk not installed — tracing disabled. "
83
+ "Run `uv add opentelemetry-api opentelemetry-sdk` to enable."
84
+ )
85
+ return
86
+
87
+ resource = Resource.create(
88
+ {"service.name": service_name, "service.version": service_version}
89
+ )
90
+ provider = TracerProvider(resource=resource)
91
+
92
+ if console_export:
93
+ provider.add_span_processor(BatchSpanProcessor(ConsoleSpanExporter()))
94
+ elif otlp_endpoint:
95
+ try:
96
+ from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import ( # type: ignore[import-not-found,import-untyped]
97
+ OTLPSpanExporter,
98
+ )
99
+
100
+ provider.add_span_processor(
101
+ BatchSpanProcessor(OTLPSpanExporter(endpoint=otlp_endpoint))
102
+ )
103
+ except ImportError:
104
+ _log.warning(
105
+ "opentelemetry-exporter-otlp-proto-grpc not installed; "
106
+ "OTLP tracing export disabled."
107
+ )
108
+
109
+ _otel_trace.set_tracer_provider(provider)
110
+ _provider = provider
111
+ _log.info(
112
+ "OTel tracing configured (service=%s, console=%s, otlp=%s).",
113
+ service_name,
114
+ console_export,
115
+ otlp_endpoint,
116
+ )
117
+
118
+
119
+ # ---------------------------------------------------------------------------
120
+ # No-op span context manager (fallback)
121
+ # ---------------------------------------------------------------------------
122
+
123
+
124
+ class _NoOpSpan:
125
+ """Minimal span interface used when OTel is not available."""
126
+
127
+ def set_attribute(self, key: str, value: Any) -> None: # noqa: ARG002
128
+ pass
129
+
130
+ def record_exception(self, exc: BaseException) -> None: # noqa: ARG002
131
+ pass
132
+
133
+ def set_status(self, *args: Any, **kwargs: Any) -> None:
134
+ pass
135
+
136
+ def __enter__(self) -> "_NoOpSpan":
137
+ return self
138
+
139
+ def __exit__(self, *_: Any) -> None:
140
+ pass
141
+
142
+
143
+ # ---------------------------------------------------------------------------
144
+ # Public helpers
145
+ # ---------------------------------------------------------------------------
146
+
147
+
148
+ def get_tracer(name: str) -> Any:
149
+ """Return an OTel tracer (or a minimal no-op tracer).
150
+
151
+ The returned object supports ``tracer.start_as_current_span(name)`` and
152
+ ``tracer.start_span(name)`` with the standard OTel API surface.
153
+ """
154
+ if _OTEL_AVAILABLE and _is_configured():
155
+ return _otel_trace.get_tracer(name)
156
+ return _NoOpTracer()
157
+
158
+
159
+ class _NoOpTracer:
160
+ """No-op tracer returned when OTel SDK is absent or not configured."""
161
+
162
+ @contextmanager
163
+ def start_as_current_span(self, name: str, **_kwargs: Any) -> Iterator[_NoOpSpan]: # noqa: ARG002
164
+ yield _NoOpSpan()
165
+
166
+ def start_span(self, name: str, **_kwargs: Any) -> _NoOpSpan: # noqa: ARG002
167
+ return _NoOpSpan()
168
+
169
+
170
+ @contextmanager
171
+ def start_span(name: str, tracer_name: str = "minder") -> Iterator[Any]:
172
+ """Context manager that starts a named span (no-op if OTel unavailable)."""
173
+ tracer = get_tracer(tracer_name)
174
+ with tracer.start_as_current_span(name) as span:
175
+ yield span
176
+
177
+
178
+ @asynccontextmanager
179
+ async def async_span(name: str, tracer_name: str = "minder") -> AsyncIterator[Any]:
180
+ """Async context manager that starts a named span."""
181
+ tracer = get_tracer(tracer_name)
182
+ with tracer.start_as_current_span(name) as span:
183
+ yield span
184
+
185
+
186
+ def trace_async(
187
+ span_name: str | None = None,
188
+ tracer_name: str = "minder",
189
+ ) -> Callable[[F], F]:
190
+ """Decorator that wraps an async function in an OTel span.
191
+
192
+ Example::
193
+
194
+ @trace_async("graph.retriever.run")
195
+ async def run(self, state):
196
+ ...
197
+ """
198
+
199
+ def decorator(fn: F) -> F:
200
+ name = span_name or f"{fn.__module__}.{fn.__qualname__}"
201
+
202
+ @functools.wraps(fn)
203
+ async def wrapper(*args: Any, **kwargs: Any) -> Any:
204
+ async with async_span(name, tracer_name=tracer_name) as span:
205
+ try:
206
+ result = await fn(*args, **kwargs)
207
+ return result
208
+ except Exception as exc:
209
+ if hasattr(span, "record_exception"):
210
+ span.record_exception(exc)
211
+ raise
212
+
213
+ return wrapper # type: ignore[return-value]
214
+
215
+ return decorator
@@ -0,0 +1 @@
1
+ __all__: list[str] = []
@@ -0,0 +1 @@
1
+ __all__: list[str] = []
@@ -0,0 +1,3 @@
1
+ from minder.presentation.http.admin.routes import build_http_app, build_http_routes
2
+
3
+ __all__ = ["build_http_app", "build_http_routes"]