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.
- mantisdk/__init__.py +22 -0
- mantisdk/adapter/__init__.py +15 -0
- mantisdk/adapter/base.py +94 -0
- mantisdk/adapter/messages.py +270 -0
- mantisdk/adapter/triplet.py +1028 -0
- mantisdk/algorithm/__init__.py +39 -0
- mantisdk/algorithm/apo/__init__.py +5 -0
- mantisdk/algorithm/apo/apo.py +889 -0
- mantisdk/algorithm/apo/prompts/apply_edit_variant01.poml +22 -0
- mantisdk/algorithm/apo/prompts/apply_edit_variant02.poml +18 -0
- mantisdk/algorithm/apo/prompts/text_gradient_variant01.poml +18 -0
- mantisdk/algorithm/apo/prompts/text_gradient_variant02.poml +16 -0
- mantisdk/algorithm/apo/prompts/text_gradient_variant03.poml +107 -0
- mantisdk/algorithm/base.py +162 -0
- mantisdk/algorithm/decorator.py +264 -0
- mantisdk/algorithm/fast.py +250 -0
- mantisdk/algorithm/gepa/__init__.py +59 -0
- mantisdk/algorithm/gepa/adapter.py +459 -0
- mantisdk/algorithm/gepa/gepa.py +364 -0
- mantisdk/algorithm/gepa/lib/__init__.py +18 -0
- mantisdk/algorithm/gepa/lib/adapters/README.md +12 -0
- mantisdk/algorithm/gepa/lib/adapters/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/adapters/anymaths_adapter/README.md +341 -0
- mantisdk/algorithm/gepa/lib/adapters/anymaths_adapter/__init__.py +1 -0
- mantisdk/algorithm/gepa/lib/adapters/anymaths_adapter/anymaths_adapter.py +174 -0
- mantisdk/algorithm/gepa/lib/adapters/anymaths_adapter/requirements.txt +1 -0
- mantisdk/algorithm/gepa/lib/adapters/default_adapter/README.md +0 -0
- mantisdk/algorithm/gepa/lib/adapters/default_adapter/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/adapters/default_adapter/default_adapter.py +209 -0
- mantisdk/algorithm/gepa/lib/adapters/dspy_adapter/README.md +7 -0
- mantisdk/algorithm/gepa/lib/adapters/dspy_adapter/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/adapters/dspy_adapter/dspy_adapter.py +307 -0
- mantisdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/README.md +99 -0
- mantisdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/dspy_program_proposal_signature.py +137 -0
- mantisdk/algorithm/gepa/lib/adapters/dspy_full_program_adapter/full_program_adapter.py +266 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/GEPA_RAG.md +621 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/__init__.py +56 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/evaluation_metrics.py +226 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/generic_rag_adapter.py +496 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/rag_pipeline.py +238 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_store_interface.py +212 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/__init__.py +2 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/chroma_store.py +196 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/lancedb_store.py +422 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/milvus_store.py +409 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/qdrant_store.py +368 -0
- mantisdk/algorithm/gepa/lib/adapters/generic_rag_adapter/vector_stores/weaviate_store.py +418 -0
- mantisdk/algorithm/gepa/lib/adapters/mcp_adapter/README.md +552 -0
- mantisdk/algorithm/gepa/lib/adapters/mcp_adapter/__init__.py +37 -0
- mantisdk/algorithm/gepa/lib/adapters/mcp_adapter/mcp_adapter.py +705 -0
- mantisdk/algorithm/gepa/lib/adapters/mcp_adapter/mcp_client.py +364 -0
- mantisdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/README.md +9 -0
- mantisdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/adapters/terminal_bench_adapter/terminal_bench_adapter.py +217 -0
- mantisdk/algorithm/gepa/lib/api.py +375 -0
- mantisdk/algorithm/gepa/lib/core/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/core/adapter.py +180 -0
- mantisdk/algorithm/gepa/lib/core/data_loader.py +74 -0
- mantisdk/algorithm/gepa/lib/core/engine.py +356 -0
- mantisdk/algorithm/gepa/lib/core/result.py +233 -0
- mantisdk/algorithm/gepa/lib/core/state.py +636 -0
- mantisdk/algorithm/gepa/lib/examples/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/examples/aime.py +24 -0
- mantisdk/algorithm/gepa/lib/examples/anymaths-bench/eval_default.py +111 -0
- mantisdk/algorithm/gepa/lib/examples/anymaths-bench/prompt-templates/instruction_prompt.txt +9 -0
- mantisdk/algorithm/gepa/lib/examples/anymaths-bench/prompt-templates/optimal_prompt.txt +24 -0
- mantisdk/algorithm/gepa/lib/examples/anymaths-bench/train_anymaths.py +177 -0
- mantisdk/algorithm/gepa/lib/examples/dspy_full_program_evolution/arc_agi.ipynb +25705 -0
- mantisdk/algorithm/gepa/lib/examples/dspy_full_program_evolution/example.ipynb +348 -0
- mantisdk/algorithm/gepa/lib/examples/mcp_adapter/__init__.py +4 -0
- mantisdk/algorithm/gepa/lib/examples/mcp_adapter/mcp_optimization_example.py +455 -0
- mantisdk/algorithm/gepa/lib/examples/rag_adapter/RAG_GUIDE.md +613 -0
- mantisdk/algorithm/gepa/lib/examples/rag_adapter/__init__.py +9 -0
- mantisdk/algorithm/gepa/lib/examples/rag_adapter/rag_optimization.py +824 -0
- mantisdk/algorithm/gepa/lib/examples/rag_adapter/requirements-rag.txt +29 -0
- mantisdk/algorithm/gepa/lib/examples/terminal-bench/prompt-templates/instruction_prompt.txt +16 -0
- mantisdk/algorithm/gepa/lib/examples/terminal-bench/prompt-templates/terminus.txt +9 -0
- mantisdk/algorithm/gepa/lib/examples/terminal-bench/train_terminus.py +161 -0
- mantisdk/algorithm/gepa/lib/gepa_utils.py +117 -0
- mantisdk/algorithm/gepa/lib/logging/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/logging/experiment_tracker.py +187 -0
- mantisdk/algorithm/gepa/lib/logging/logger.py +75 -0
- mantisdk/algorithm/gepa/lib/logging/utils.py +103 -0
- mantisdk/algorithm/gepa/lib/proposer/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/proposer/base.py +31 -0
- mantisdk/algorithm/gepa/lib/proposer/merge.py +357 -0
- mantisdk/algorithm/gepa/lib/proposer/reflective_mutation/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/proposer/reflective_mutation/base.py +49 -0
- mantisdk/algorithm/gepa/lib/proposer/reflective_mutation/reflective_mutation.py +176 -0
- mantisdk/algorithm/gepa/lib/py.typed +0 -0
- mantisdk/algorithm/gepa/lib/strategies/__init__.py +0 -0
- mantisdk/algorithm/gepa/lib/strategies/batch_sampler.py +77 -0
- mantisdk/algorithm/gepa/lib/strategies/candidate_selector.py +50 -0
- mantisdk/algorithm/gepa/lib/strategies/component_selector.py +36 -0
- mantisdk/algorithm/gepa/lib/strategies/eval_policy.py +64 -0
- mantisdk/algorithm/gepa/lib/strategies/instruction_proposal.py +127 -0
- mantisdk/algorithm/gepa/lib/utils/__init__.py +10 -0
- mantisdk/algorithm/gepa/lib/utils/stop_condition.py +196 -0
- mantisdk/algorithm/gepa/tracing.py +105 -0
- mantisdk/algorithm/utils.py +177 -0
- mantisdk/algorithm/verl/__init__.py +5 -0
- mantisdk/algorithm/verl/interface.py +202 -0
- mantisdk/cli/__init__.py +56 -0
- mantisdk/cli/prometheus.py +115 -0
- mantisdk/cli/store.py +131 -0
- mantisdk/cli/vllm.py +29 -0
- mantisdk/client.py +408 -0
- mantisdk/config.py +348 -0
- mantisdk/emitter/__init__.py +43 -0
- mantisdk/emitter/annotation.py +370 -0
- mantisdk/emitter/exception.py +54 -0
- mantisdk/emitter/message.py +61 -0
- mantisdk/emitter/object.py +117 -0
- mantisdk/emitter/reward.py +320 -0
- mantisdk/env_var.py +156 -0
- mantisdk/execution/__init__.py +15 -0
- mantisdk/execution/base.py +64 -0
- mantisdk/execution/client_server.py +443 -0
- mantisdk/execution/events.py +69 -0
- mantisdk/execution/inter_process.py +16 -0
- mantisdk/execution/shared_memory.py +282 -0
- mantisdk/instrumentation/__init__.py +119 -0
- mantisdk/instrumentation/agentops.py +314 -0
- mantisdk/instrumentation/agentops_langchain.py +45 -0
- mantisdk/instrumentation/litellm.py +83 -0
- mantisdk/instrumentation/vllm.py +81 -0
- mantisdk/instrumentation/weave.py +500 -0
- mantisdk/litagent/__init__.py +11 -0
- mantisdk/litagent/decorator.py +536 -0
- mantisdk/litagent/litagent.py +252 -0
- mantisdk/llm_proxy.py +1890 -0
- mantisdk/logging.py +370 -0
- mantisdk/reward.py +7 -0
- mantisdk/runner/__init__.py +11 -0
- mantisdk/runner/agent.py +845 -0
- mantisdk/runner/base.py +182 -0
- mantisdk/runner/legacy.py +309 -0
- mantisdk/semconv.py +170 -0
- mantisdk/server.py +401 -0
- mantisdk/store/__init__.py +23 -0
- mantisdk/store/base.py +897 -0
- mantisdk/store/client_server.py +2092 -0
- mantisdk/store/collection/__init__.py +30 -0
- mantisdk/store/collection/base.py +587 -0
- mantisdk/store/collection/memory.py +970 -0
- mantisdk/store/collection/mongo.py +1412 -0
- mantisdk/store/collection_based.py +1823 -0
- mantisdk/store/insight.py +648 -0
- mantisdk/store/listener.py +58 -0
- mantisdk/store/memory.py +396 -0
- mantisdk/store/mongo.py +165 -0
- mantisdk/store/sqlite.py +3 -0
- mantisdk/store/threading.py +357 -0
- mantisdk/store/utils.py +142 -0
- mantisdk/tracer/__init__.py +16 -0
- mantisdk/tracer/agentops.py +242 -0
- mantisdk/tracer/base.py +287 -0
- mantisdk/tracer/dummy.py +106 -0
- mantisdk/tracer/otel.py +555 -0
- mantisdk/tracer/weave.py +677 -0
- mantisdk/trainer/__init__.py +6 -0
- mantisdk/trainer/init_utils.py +263 -0
- mantisdk/trainer/legacy.py +367 -0
- mantisdk/trainer/registry.py +12 -0
- mantisdk/trainer/trainer.py +618 -0
- mantisdk/types/__init__.py +6 -0
- mantisdk/types/core.py +553 -0
- mantisdk/types/resources.py +204 -0
- mantisdk/types/tracer.py +515 -0
- mantisdk/types/tracing.py +218 -0
- mantisdk/utils/__init__.py +1 -0
- mantisdk/utils/id.py +18 -0
- mantisdk/utils/metrics.py +1025 -0
- mantisdk/utils/otel.py +578 -0
- mantisdk/utils/otlp.py +536 -0
- mantisdk/utils/server_launcher.py +1045 -0
- mantisdk/utils/system_snapshot.py +81 -0
- mantisdk/verl/__init__.py +8 -0
- mantisdk/verl/__main__.py +6 -0
- mantisdk/verl/async_server.py +46 -0
- mantisdk/verl/config.yaml +27 -0
- mantisdk/verl/daemon.py +1154 -0
- mantisdk/verl/dataset.py +44 -0
- mantisdk/verl/entrypoint.py +248 -0
- mantisdk/verl/trainer.py +549 -0
- mantisdk-0.1.0.dist-info/METADATA +119 -0
- mantisdk-0.1.0.dist-info/RECORD +190 -0
- mantisdk-0.1.0.dist-info/WHEEL +4 -0
- mantisdk-0.1.0.dist-info/entry_points.txt +2 -0
- mantisdk-0.1.0.dist-info/licenses/LICENSE +19 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
# Copyright (c) Microsoft. All rights reserved.
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
"""Typed representations of tunable resources shared between Mantisdk components."""
|
|
6
|
+
|
|
7
|
+
import inspect
|
|
8
|
+
import logging
|
|
9
|
+
from typing import (
|
|
10
|
+
Annotated,
|
|
11
|
+
Any,
|
|
12
|
+
Dict,
|
|
13
|
+
Literal,
|
|
14
|
+
Optional,
|
|
15
|
+
Union,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
from pydantic import BaseModel, Field
|
|
19
|
+
|
|
20
|
+
from .core import AttemptedRollout
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
__all__ = [
|
|
26
|
+
"Resource",
|
|
27
|
+
"LLM",
|
|
28
|
+
"ProxyLLM",
|
|
29
|
+
"PromptTemplate",
|
|
30
|
+
"ResourceUnion",
|
|
31
|
+
"NamedResources",
|
|
32
|
+
"ResourcesUpdate",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class Resource(BaseModel):
|
|
37
|
+
"""Base class for tunable resources distributed to executors."""
|
|
38
|
+
|
|
39
|
+
resource_type: Any
|
|
40
|
+
"""Alias of the resource type."""
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class LLM(Resource):
|
|
44
|
+
"""Resource that identifies an LLM endpoint and its configuration."""
|
|
45
|
+
|
|
46
|
+
resource_type: Literal["llm"] = "llm"
|
|
47
|
+
endpoint: str
|
|
48
|
+
"""The URL of the LLM API endpoint."""
|
|
49
|
+
model: str
|
|
50
|
+
"""The identifier for the model to be used (e.g., 'gpt-4o')."""
|
|
51
|
+
api_key: Optional[str] = None
|
|
52
|
+
"""Optional secret used to authenticate requests."""
|
|
53
|
+
sampling_parameters: Dict[str, Any] = Field(default_factory=dict)
|
|
54
|
+
"""A dictionary of hyperparameters for model inference, such as temperature, top_p, etc."""
|
|
55
|
+
|
|
56
|
+
def get_base_url(self, *args: Any, **kwargs: Any) -> str:
|
|
57
|
+
"""Return the base URL consumed by OpenAI-compatible clients.
|
|
58
|
+
|
|
59
|
+
Users are encouraged to use `get_base_url(rollout_id, attempt_id)` to get
|
|
60
|
+
the LLM endpoint instead of accessing `.endpoint` directly.
|
|
61
|
+
"""
|
|
62
|
+
return self.endpoint
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class ProxyLLM(LLM):
|
|
66
|
+
"""LLM resource that rewrites endpoints through [`LLMProxy`][mantisdk.LLMProxy].
|
|
67
|
+
|
|
68
|
+
The proxy injects rollout- and attempt-specific routing information into the
|
|
69
|
+
endpoint so that downstream services can attribute requests correctly.
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
resource_type: Literal["proxy_llm"] = "proxy_llm" # type: ignore
|
|
73
|
+
_initialized: bool = False
|
|
74
|
+
|
|
75
|
+
def model_post_init(self, __context: Any) -> None:
|
|
76
|
+
"""Mark initialization as complete after Pydantic finishes setup."""
|
|
77
|
+
super().model_post_init(__context)
|
|
78
|
+
object.__setattr__(self, "_initialized", True)
|
|
79
|
+
|
|
80
|
+
def __getattribute__(self, name: str) -> Any:
|
|
81
|
+
"""Emit a warning when `endpoint` is accessed directly after initialization."""
|
|
82
|
+
# Check if we're accessing endpoint after initialization and not from base_url
|
|
83
|
+
if name == "endpoint":
|
|
84
|
+
try:
|
|
85
|
+
initialized = object.__getattribute__(self, "_initialized")
|
|
86
|
+
except AttributeError:
|
|
87
|
+
initialized = False
|
|
88
|
+
|
|
89
|
+
if initialized:
|
|
90
|
+
# Check the call stack to see if we're being called from base_url
|
|
91
|
+
frame = inspect.currentframe()
|
|
92
|
+
if frame and frame.f_back:
|
|
93
|
+
caller_name = frame.f_back.f_code.co_name
|
|
94
|
+
if caller_name != "get_base_url":
|
|
95
|
+
logger.warning(
|
|
96
|
+
"Accessing 'endpoint' directly on ProxyLLM is discouraged. "
|
|
97
|
+
"Use 'get_base_url(rollout_id, attempt_id)' instead to get the properly formatted endpoint."
|
|
98
|
+
)
|
|
99
|
+
return super().__getattribute__(name)
|
|
100
|
+
|
|
101
|
+
def with_attempted_rollout(self, rollout: AttemptedRollout) -> LLM:
|
|
102
|
+
"""Bake rollout metadata into a concrete [`LLM`][mantisdk.LLM] instance."""
|
|
103
|
+
return LLM(
|
|
104
|
+
endpoint=self.get_base_url(rollout.rollout_id, rollout.attempt.attempt_id),
|
|
105
|
+
model=self.model,
|
|
106
|
+
sampling_parameters=self.sampling_parameters,
|
|
107
|
+
api_key=self.api_key,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
def get_base_url(self, rollout_id: Optional[str], attempt_id: Optional[str]) -> str:
|
|
111
|
+
"""Return the routed endpoint for a specific rollout/attempt pair.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
rollout_id: Identifier of the rollout making the request.
|
|
115
|
+
attempt_id: Identifier of the attempt within that rollout.
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
Fully qualified endpoint including rollout metadata.
|
|
119
|
+
|
|
120
|
+
Raises:
|
|
121
|
+
ValueError: If exactly one of ``rollout_id`` or ``attempt_id`` is provided.
|
|
122
|
+
"""
|
|
123
|
+
if rollout_id is None and attempt_id is None:
|
|
124
|
+
return self.endpoint
|
|
125
|
+
|
|
126
|
+
if not (isinstance(rollout_id, str) and isinstance(attempt_id, str)):
|
|
127
|
+
raise ValueError("rollout_id and attempt_id must be strings or all be empty")
|
|
128
|
+
|
|
129
|
+
prefix = self.endpoint
|
|
130
|
+
if prefix.endswith("/"):
|
|
131
|
+
prefix = prefix[:-1]
|
|
132
|
+
if prefix.endswith("/v1"):
|
|
133
|
+
prefix = prefix[:-3]
|
|
134
|
+
has_v1 = True
|
|
135
|
+
else:
|
|
136
|
+
has_v1 = False
|
|
137
|
+
# Now the prefix should look like "http://localhost:11434"
|
|
138
|
+
|
|
139
|
+
# Append the rollout and attempt id to the prefix
|
|
140
|
+
prefix = prefix + f"/rollout/{rollout_id}/attempt/{attempt_id}"
|
|
141
|
+
if has_v1:
|
|
142
|
+
prefix = prefix + "/v1"
|
|
143
|
+
return prefix
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
class PromptTemplate(Resource):
|
|
147
|
+
"""Resource describing a reusable prompt template."""
|
|
148
|
+
|
|
149
|
+
resource_type: Literal["prompt_template"] = "prompt_template"
|
|
150
|
+
template: str
|
|
151
|
+
"""The template string. The format depends on the engine."""
|
|
152
|
+
engine: Literal["jinja", "f-string", "poml"]
|
|
153
|
+
"""The templating engine to use for rendering the prompt."""
|
|
154
|
+
|
|
155
|
+
def format(self, **kwargs: Any) -> str:
|
|
156
|
+
"""Format the prompt using keyword arguments.
|
|
157
|
+
|
|
158
|
+
!!! warning
|
|
159
|
+
Only the `f-string` engine is supported for now.
|
|
160
|
+
"""
|
|
161
|
+
if self.engine == "f-string":
|
|
162
|
+
return self.template.format(**kwargs)
|
|
163
|
+
else:
|
|
164
|
+
raise NotImplementedError(
|
|
165
|
+
"Formatting prompt templates for non-f-string engines with format() helper is not supported yet."
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
# Use discriminated union for proper deserialization
|
|
170
|
+
# TODO: migrate to use a registry
|
|
171
|
+
ResourceUnion = Annotated[Union[LLM, ProxyLLM, PromptTemplate], Field(discriminator="resource_type")]
|
|
172
|
+
NamedResources = Dict[str, ResourceUnion]
|
|
173
|
+
"""Mapping from resource names to their configured instances.
|
|
174
|
+
|
|
175
|
+
Examples:
|
|
176
|
+
```python
|
|
177
|
+
resources: NamedResources = {
|
|
178
|
+
"main_llm": LLM(
|
|
179
|
+
endpoint="http://localhost:8080",
|
|
180
|
+
model="llama3",
|
|
181
|
+
sampling_parameters={"temperature": 0.7, "max_tokens": 100},
|
|
182
|
+
),
|
|
183
|
+
"system_prompt": PromptTemplate(
|
|
184
|
+
template="You are a helpful assistant.",
|
|
185
|
+
engine="f-string",
|
|
186
|
+
),
|
|
187
|
+
}
|
|
188
|
+
```
|
|
189
|
+
"""
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
class ResourcesUpdate(BaseModel):
|
|
193
|
+
"""Update payload broadcast to clients when resources change."""
|
|
194
|
+
|
|
195
|
+
resources_id: str
|
|
196
|
+
"""Identifier used to version the resources."""
|
|
197
|
+
create_time: float
|
|
198
|
+
"""Timestamp of the creation time of the resources."""
|
|
199
|
+
update_time: float
|
|
200
|
+
"""Timestamp of the last update time of the resources."""
|
|
201
|
+
version: int
|
|
202
|
+
"""Version of the resources."""
|
|
203
|
+
resources: NamedResources
|
|
204
|
+
"""Mapping of resource names to their definitions."""
|