construct-labs-crm-env 0.1.1__tar.gz → 0.1.2__tar.gz
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.
- construct_labs_crm_env-0.1.2/.gitignore +23 -0
- {construct_labs_crm_env-0.1.1 → construct_labs_crm_env-0.1.2}/PKG-INFO +2 -1
- {construct_labs_crm_env-0.1.1 → construct_labs_crm_env-0.1.2}/pyproject.toml +3 -2
- {construct_labs_crm_env-0.1.1 → construct_labs_crm_env-0.1.2}/src/construct_labs_crm_env/client.py +3 -2
- {construct_labs_crm_env-0.1.1 → construct_labs_crm_env-0.1.2}/src/construct_labs_crm_env/models.py +1 -2
- construct_labs_crm_env-0.1.1/.gitignore +0 -24
- construct_labs_crm_env-0.1.1/src/construct_labs_crm_env/_vendored/LICENSE.openenv +0 -28
- construct_labs_crm_env-0.1.1/src/construct_labs_crm_env/_vendored/__init__.py +0 -14
- construct_labs_crm_env-0.1.1/src/construct_labs_crm_env/_vendored/_client.py +0 -216
- construct_labs_crm_env-0.1.1/src/construct_labs_crm_env/_vendored/_types.py +0 -82
- {construct_labs_crm_env-0.1.1 → construct_labs_crm_env-0.1.2}/LICENSE +0 -0
- {construct_labs_crm_env-0.1.1 → construct_labs_crm_env-0.1.2}/README.md +0 -0
- {construct_labs_crm_env-0.1.1 → construct_labs_crm_env-0.1.2}/src/construct_labs_crm_env/__init__.py +0 -0
- {construct_labs_crm_env-0.1.1 → construct_labs_crm_env-0.1.2}/src/construct_labs_crm_env/protocol.py +0 -0
- {construct_labs_crm_env-0.1.1 → construct_labs_crm_env-0.1.2}/src/construct_labs_crm_env/py.typed +0 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
.venv/
|
|
6
|
+
|
|
7
|
+
# Testing
|
|
8
|
+
.pytest_cache/
|
|
9
|
+
.coverage
|
|
10
|
+
htmlcov/
|
|
11
|
+
|
|
12
|
+
# Linting
|
|
13
|
+
.ruff_cache/
|
|
14
|
+
.mypy_cache/
|
|
15
|
+
|
|
16
|
+
# Build
|
|
17
|
+
dist/
|
|
18
|
+
build/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
|
|
21
|
+
# IDE
|
|
22
|
+
.idea/
|
|
23
|
+
.vscode/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: construct-labs-crm-env
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: CRM Agent Environment SDK by Construct Labs - Train RL agents to interact with CRM systems
|
|
5
5
|
Project-URL: Homepage, https://construct-labs.com
|
|
6
6
|
Author-email: Construct Labs GmbH <hello@construct-labs.com>
|
|
@@ -19,6 +19,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
19
19
|
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
20
20
|
Classifier: Typing :: Typed
|
|
21
21
|
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: openenv-core>=0.2.0
|
|
22
23
|
Requires-Dist: pydantic>=2.0.0
|
|
23
24
|
Requires-Dist: websockets>=12.0
|
|
24
25
|
Provides-Extra: dev
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "construct-labs-crm-env"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.2"
|
|
8
8
|
description = "CRM Agent Environment SDK by Construct Labs - Train RL agents to interact with CRM systems"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "Proprietary" }
|
|
@@ -34,6 +34,7 @@ classifiers = [
|
|
|
34
34
|
"Typing :: Typed",
|
|
35
35
|
]
|
|
36
36
|
dependencies = [
|
|
37
|
+
"openenv-core>=0.2.0",
|
|
37
38
|
"pydantic>=2.0.0",
|
|
38
39
|
"websockets>=12.0",
|
|
39
40
|
]
|
|
@@ -88,7 +89,7 @@ warn_unused_ignores = true
|
|
|
88
89
|
disallow_untyped_defs = true
|
|
89
90
|
|
|
90
91
|
[[tool.mypy.overrides]]
|
|
91
|
-
module = ["websockets.*"]
|
|
92
|
+
module = ["websockets.*", "openenv.*"]
|
|
92
93
|
ignore_missing_imports = true
|
|
93
94
|
|
|
94
95
|
[tool.pytest.ini_options]
|
{construct_labs_crm_env-0.1.1 → construct_labs_crm_env-0.1.2}/src/construct_labs_crm_env/client.py
RENAMED
|
@@ -24,9 +24,10 @@ import json
|
|
|
24
24
|
import os
|
|
25
25
|
from typing import Any, cast
|
|
26
26
|
|
|
27
|
+
from openenv.core import EnvClient
|
|
28
|
+
from openenv.core.client_types import StepResult
|
|
27
29
|
from websockets.sync.client import connect as ws_connect
|
|
28
30
|
|
|
29
|
-
from ._vendored import EnvClient, StepResult
|
|
30
31
|
from .models import (
|
|
31
32
|
CRMActionType,
|
|
32
33
|
CrmAgentAction,
|
|
@@ -104,7 +105,7 @@ class CrmAgentEnv(EnvClient[CrmAgentAction, CrmAgentObservation, CrmAgentState])
|
|
|
104
105
|
raise ValueError(
|
|
105
106
|
"API key is required. Pass api_key parameter or set "
|
|
106
107
|
"CRM_AGENT_API_KEY environment variable. "
|
|
107
|
-
"Get your API key
|
|
108
|
+
"Get your API key by contacting hello@construct-labs.com"
|
|
108
109
|
)
|
|
109
110
|
|
|
110
111
|
self._api_key = resolved_api_key
|
{construct_labs_crm_env-0.1.1 → construct_labs_crm_env-0.1.2}/src/construct_labs_crm_env/models.py
RENAMED
|
@@ -9,10 +9,9 @@ from __future__ import annotations
|
|
|
9
9
|
from enum import Enum
|
|
10
10
|
from typing import Any
|
|
11
11
|
|
|
12
|
+
from openenv.core import Action, Observation, State
|
|
12
13
|
from pydantic import ConfigDict, Field
|
|
13
14
|
|
|
14
|
-
from ._vendored import Action, Observation, State
|
|
15
|
-
|
|
16
15
|
|
|
17
16
|
class CRMActionType(str, Enum):
|
|
18
17
|
"""Types of actions available in the CRM environment.
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
# React
|
|
3
|
-
node_modules/
|
|
4
|
-
dist/
|
|
5
|
-
build/
|
|
6
|
-
.next/
|
|
7
|
-
out/
|
|
8
|
-
.cache/
|
|
9
|
-
.eslintcache
|
|
10
|
-
npm-debug.log*
|
|
11
|
-
yarn-debug.log*
|
|
12
|
-
yarn-error.log*
|
|
13
|
-
pnpm-debug.log*
|
|
14
|
-
.npm-cache/
|
|
15
|
-
|
|
16
|
-
# Python
|
|
17
|
-
.venv/
|
|
18
|
-
__pycache__/
|
|
19
|
-
|
|
20
|
-
# macOS
|
|
21
|
-
.DS_Store
|
|
22
|
-
|
|
23
|
-
launch.json
|
|
24
|
-
.env
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
BSD 3-Clause License
|
|
2
|
-
|
|
3
|
-
(c) Meta Platforms, Inc. and affiliates.
|
|
4
|
-
|
|
5
|
-
Redistribution and use in source and binary forms, with or without modification,
|
|
6
|
-
are permitted provided that the following conditions are met:
|
|
7
|
-
|
|
8
|
-
1. Redistributions of source code must retain the above copyright notice,this list
|
|
9
|
-
of conditions and the following disclaimer.
|
|
10
|
-
|
|
11
|
-
2. Redistributions in binary form must reproduce the above copyright notice, this
|
|
12
|
-
list of conditions and the following disclaimer in the documentation
|
|
13
|
-
and/or other materials provided with the distribution.
|
|
14
|
-
|
|
15
|
-
3. Neither the name of the copyright holder nor the names of its contributors may
|
|
16
|
-
be used to endorse or promote products derived from this software without specific
|
|
17
|
-
prior written permission.
|
|
18
|
-
|
|
19
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
|
20
|
-
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
21
|
-
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
22
|
-
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
23
|
-
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
|
24
|
-
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
|
25
|
-
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
26
|
-
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
|
27
|
-
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
28
|
-
DAMAGE.
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
# All rights reserved.
|
|
3
|
-
#
|
|
4
|
-
# This source code is licensed under the BSD-3-Clause license.
|
|
5
|
-
# See LICENSE.openenv in this directory for the full license text.
|
|
6
|
-
#
|
|
7
|
-
# This module contains vendored code from the OpenEnv project:
|
|
8
|
-
# https://github.com/meta-pytorch/OpenEnv
|
|
9
|
-
"""Vendored OpenEnv core components."""
|
|
10
|
-
|
|
11
|
-
from ._client import EnvClient
|
|
12
|
-
from ._types import Action, Observation, State, StepResult
|
|
13
|
-
|
|
14
|
-
__all__ = ["Action", "EnvClient", "Observation", "State", "StepResult"]
|
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
# All rights reserved.
|
|
3
|
-
#
|
|
4
|
-
# This source code is licensed under the BSD-3-Clause license.
|
|
5
|
-
# See LICENSE.openenv in this directory for the full license text.
|
|
6
|
-
"""WebSocket-based environment client from OpenEnv."""
|
|
7
|
-
|
|
8
|
-
from __future__ import annotations
|
|
9
|
-
|
|
10
|
-
import json
|
|
11
|
-
import os
|
|
12
|
-
from abc import ABC, abstractmethod
|
|
13
|
-
from typing import TYPE_CHECKING, Any, Generic, TypeVar
|
|
14
|
-
|
|
15
|
-
from ._types import StateT, StepResult
|
|
16
|
-
|
|
17
|
-
if TYPE_CHECKING:
|
|
18
|
-
from websockets.sync.client import ClientConnection
|
|
19
|
-
|
|
20
|
-
from websockets.sync.client import connect as ws_connect
|
|
21
|
-
|
|
22
|
-
ActT = TypeVar("ActT")
|
|
23
|
-
ObsT = TypeVar("ObsT")
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def _convert_to_ws_url(url: str) -> str:
|
|
27
|
-
"""Convert an HTTP/HTTPS URL to a WS/WSS URL."""
|
|
28
|
-
ws_url = url.rstrip("/")
|
|
29
|
-
if ws_url.startswith("http://"):
|
|
30
|
-
ws_url = "ws://" + ws_url[7:]
|
|
31
|
-
elif ws_url.startswith("https://"):
|
|
32
|
-
ws_url = "wss://" + ws_url[8:]
|
|
33
|
-
elif not ws_url.startswith("ws://") and not ws_url.startswith("wss://"):
|
|
34
|
-
ws_url = "ws://" + ws_url
|
|
35
|
-
return ws_url
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
class EnvClient(ABC, Generic[ActT, ObsT, StateT]):
|
|
39
|
-
"""WebSocket client for environment interactions.
|
|
40
|
-
|
|
41
|
-
Maintains a persistent connection to an environment server for efficient
|
|
42
|
-
multi-step interactions without HTTP overhead.
|
|
43
|
-
|
|
44
|
-
Example:
|
|
45
|
-
>>> with MyEnvClient(base_url="ws://localhost:8000") as env:
|
|
46
|
-
... result = env.reset(seed=42)
|
|
47
|
-
... while not result.done:
|
|
48
|
-
... action = agent.predict(result.observation)
|
|
49
|
-
... result = env.step(action)
|
|
50
|
-
"""
|
|
51
|
-
|
|
52
|
-
def __init__(
|
|
53
|
-
self,
|
|
54
|
-
base_url: str,
|
|
55
|
-
connect_timeout_s: float = 10.0,
|
|
56
|
-
message_timeout_s: float = 60.0,
|
|
57
|
-
):
|
|
58
|
-
"""Initialize environment client.
|
|
59
|
-
|
|
60
|
-
Args:
|
|
61
|
-
base_url: Server URL (http://, https://, ws://, or wss://).
|
|
62
|
-
connect_timeout_s: Timeout for establishing connection.
|
|
63
|
-
message_timeout_s: Timeout for receiving responses.
|
|
64
|
-
"""
|
|
65
|
-
ws_url = _convert_to_ws_url(base_url)
|
|
66
|
-
self._ws_url = f"{ws_url}/ws"
|
|
67
|
-
self._connect_timeout = connect_timeout_s
|
|
68
|
-
self._message_timeout = message_timeout_s
|
|
69
|
-
self._ws: ClientConnection | None = None
|
|
70
|
-
|
|
71
|
-
def connect(self) -> EnvClient[ActT, ObsT, StateT]:
|
|
72
|
-
"""Establish WebSocket connection.
|
|
73
|
-
|
|
74
|
-
Returns:
|
|
75
|
-
self for method chaining.
|
|
76
|
-
|
|
77
|
-
Raises:
|
|
78
|
-
ConnectionError: If connection fails.
|
|
79
|
-
"""
|
|
80
|
-
if self._ws is not None:
|
|
81
|
-
return self
|
|
82
|
-
|
|
83
|
-
# Bypass proxy for localhost
|
|
84
|
-
ws_url_lower = self._ws_url.lower()
|
|
85
|
-
is_localhost = "localhost" in ws_url_lower or "127.0.0.1" in ws_url_lower
|
|
86
|
-
|
|
87
|
-
old_no_proxy = os.environ.get("NO_PROXY")
|
|
88
|
-
if is_localhost:
|
|
89
|
-
current_no_proxy = old_no_proxy or ""
|
|
90
|
-
if "localhost" not in current_no_proxy.lower():
|
|
91
|
-
os.environ["NO_PROXY"] = (
|
|
92
|
-
f"{current_no_proxy},localhost,127.0.0.1"
|
|
93
|
-
if current_no_proxy
|
|
94
|
-
else "localhost,127.0.0.1"
|
|
95
|
-
)
|
|
96
|
-
|
|
97
|
-
try:
|
|
98
|
-
self._ws = ws_connect(
|
|
99
|
-
self._ws_url,
|
|
100
|
-
open_timeout=self._connect_timeout,
|
|
101
|
-
)
|
|
102
|
-
except Exception as e:
|
|
103
|
-
raise ConnectionError(f"Failed to connect to {self._ws_url}: {e}") from e
|
|
104
|
-
finally:
|
|
105
|
-
if is_localhost:
|
|
106
|
-
if old_no_proxy is None:
|
|
107
|
-
os.environ.pop("NO_PROXY", None)
|
|
108
|
-
else:
|
|
109
|
-
os.environ["NO_PROXY"] = old_no_proxy
|
|
110
|
-
|
|
111
|
-
return self
|
|
112
|
-
|
|
113
|
-
def disconnect(self) -> None:
|
|
114
|
-
"""Close the WebSocket connection."""
|
|
115
|
-
if self._ws is not None:
|
|
116
|
-
try:
|
|
117
|
-
self._send({"type": "close"})
|
|
118
|
-
except Exception:
|
|
119
|
-
pass
|
|
120
|
-
try:
|
|
121
|
-
self._ws.close()
|
|
122
|
-
except Exception:
|
|
123
|
-
pass
|
|
124
|
-
self._ws = None
|
|
125
|
-
|
|
126
|
-
def _ensure_connected(self) -> None:
|
|
127
|
-
"""Ensure connection is established."""
|
|
128
|
-
if self._ws is None:
|
|
129
|
-
self.connect()
|
|
130
|
-
|
|
131
|
-
def _send(self, message: dict[str, Any]) -> None:
|
|
132
|
-
"""Send a message over WebSocket."""
|
|
133
|
-
self._ensure_connected()
|
|
134
|
-
assert self._ws is not None
|
|
135
|
-
self._ws.send(json.dumps(message))
|
|
136
|
-
|
|
137
|
-
def _receive(self) -> dict[str, Any]:
|
|
138
|
-
"""Receive and parse a message."""
|
|
139
|
-
assert self._ws is not None
|
|
140
|
-
raw = self._ws.recv(timeout=self._message_timeout)
|
|
141
|
-
return json.loads(raw)
|
|
142
|
-
|
|
143
|
-
def _send_and_receive(self, message: dict[str, Any]) -> dict[str, Any]:
|
|
144
|
-
"""Send a message and wait for response."""
|
|
145
|
-
self._send(message)
|
|
146
|
-
response = self._receive()
|
|
147
|
-
|
|
148
|
-
if response.get("type") == "error":
|
|
149
|
-
error_data = response.get("data", {})
|
|
150
|
-
raise RuntimeError(
|
|
151
|
-
f"Server error: {error_data.get('message', 'Unknown error')} "
|
|
152
|
-
f"(code: {error_data.get('code', 'UNKNOWN')})"
|
|
153
|
-
)
|
|
154
|
-
|
|
155
|
-
return response
|
|
156
|
-
|
|
157
|
-
@abstractmethod
|
|
158
|
-
def _step_payload(self, action: ActT) -> dict[str, Any]:
|
|
159
|
-
"""Convert action to JSON payload for the server."""
|
|
160
|
-
raise NotImplementedError
|
|
161
|
-
|
|
162
|
-
@abstractmethod
|
|
163
|
-
def _parse_result(self, payload: dict[str, Any]) -> StepResult[ObsT]:
|
|
164
|
-
"""Convert server response to StepResult."""
|
|
165
|
-
raise NotImplementedError
|
|
166
|
-
|
|
167
|
-
@abstractmethod
|
|
168
|
-
def _parse_state(self, payload: dict[str, Any]) -> StateT:
|
|
169
|
-
"""Convert server response to State object."""
|
|
170
|
-
raise NotImplementedError
|
|
171
|
-
|
|
172
|
-
def reset(self, **kwargs: Any) -> StepResult[ObsT]:
|
|
173
|
-
"""Reset the environment.
|
|
174
|
-
|
|
175
|
-
Args:
|
|
176
|
-
**kwargs: Parameters for reset (e.g., seed, episode_id).
|
|
177
|
-
|
|
178
|
-
Returns:
|
|
179
|
-
StepResult with initial observation.
|
|
180
|
-
"""
|
|
181
|
-
message = {"type": "reset", "data": kwargs}
|
|
182
|
-
response = self._send_and_receive(message)
|
|
183
|
-
return self._parse_result(response.get("data", {}))
|
|
184
|
-
|
|
185
|
-
def step(self, action: ActT, **kwargs: Any) -> StepResult[ObsT]:
|
|
186
|
-
"""Execute an action.
|
|
187
|
-
|
|
188
|
-
Args:
|
|
189
|
-
action: The action to execute.
|
|
190
|
-
**kwargs: Additional parameters.
|
|
191
|
-
|
|
192
|
-
Returns:
|
|
193
|
-
StepResult with observation, reward, and done status.
|
|
194
|
-
"""
|
|
195
|
-
message = {"type": "step", "data": self._step_payload(action)}
|
|
196
|
-
response = self._send_and_receive(message)
|
|
197
|
-
return self._parse_result(response.get("data", {}))
|
|
198
|
-
|
|
199
|
-
def state(self) -> StateT:
|
|
200
|
-
"""Get current environment state."""
|
|
201
|
-
message = {"type": "state"}
|
|
202
|
-
response = self._send_and_receive(message)
|
|
203
|
-
return self._parse_state(response.get("data", {}))
|
|
204
|
-
|
|
205
|
-
def close(self) -> None:
|
|
206
|
-
"""Close connection and clean up resources."""
|
|
207
|
-
self.disconnect()
|
|
208
|
-
|
|
209
|
-
def __enter__(self) -> EnvClient[ActT, ObsT, StateT]:
|
|
210
|
-
"""Enter context manager."""
|
|
211
|
-
self.connect()
|
|
212
|
-
return self
|
|
213
|
-
|
|
214
|
-
def __exit__(self, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
|
|
215
|
-
"""Exit context manager."""
|
|
216
|
-
self.close()
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
-
# All rights reserved.
|
|
3
|
-
#
|
|
4
|
-
# This source code is licensed under the BSD-3-Clause license.
|
|
5
|
-
# See LICENSE.openenv in this directory for the full license text.
|
|
6
|
-
"""Type definitions from OpenEnv."""
|
|
7
|
-
|
|
8
|
-
from __future__ import annotations
|
|
9
|
-
|
|
10
|
-
from dataclasses import dataclass
|
|
11
|
-
from typing import Any, Generic, TypeVar
|
|
12
|
-
|
|
13
|
-
from pydantic import BaseModel, ConfigDict, Field
|
|
14
|
-
|
|
15
|
-
ObsT = TypeVar("ObsT")
|
|
16
|
-
StateT = TypeVar("StateT")
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
@dataclass
|
|
20
|
-
class StepResult(Generic[ObsT]):
|
|
21
|
-
"""Result of one environment step.
|
|
22
|
-
|
|
23
|
-
Attributes:
|
|
24
|
-
observation: The environment's observation after the action.
|
|
25
|
-
reward: Scalar reward for this step.
|
|
26
|
-
done: Whether the episode is finished.
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
|
-
observation: ObsT
|
|
30
|
-
reward: float | None = None
|
|
31
|
-
done: bool = False
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
class Action(BaseModel):
|
|
35
|
-
"""Base class for environment actions."""
|
|
36
|
-
|
|
37
|
-
model_config = ConfigDict(
|
|
38
|
-
extra="forbid",
|
|
39
|
-
validate_assignment=True,
|
|
40
|
-
arbitrary_types_allowed=True,
|
|
41
|
-
)
|
|
42
|
-
|
|
43
|
-
metadata: dict[str, Any] = Field(
|
|
44
|
-
default_factory=dict, description="Additional metadata for the action"
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
class Observation(BaseModel):
|
|
49
|
-
"""Base class for environment observations."""
|
|
50
|
-
|
|
51
|
-
model_config = ConfigDict(
|
|
52
|
-
extra="forbid",
|
|
53
|
-
validate_assignment=True,
|
|
54
|
-
arbitrary_types_allowed=True,
|
|
55
|
-
)
|
|
56
|
-
|
|
57
|
-
done: bool = Field(default=False, description="Whether the episode has terminated")
|
|
58
|
-
reward: bool | int | float | None = Field(
|
|
59
|
-
default=None, description="Reward signal from the last action"
|
|
60
|
-
)
|
|
61
|
-
metadata: dict[str, Any] = Field(
|
|
62
|
-
default_factory=dict, description="Additional metadata for the observation"
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
class State(BaseModel):
|
|
67
|
-
"""Base class for environment state."""
|
|
68
|
-
|
|
69
|
-
model_config = ConfigDict(
|
|
70
|
-
extra="allow",
|
|
71
|
-
validate_assignment=True,
|
|
72
|
-
arbitrary_types_allowed=True,
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
episode_id: str | None = Field(
|
|
76
|
-
default=None, description="Unique identifier for the current episode"
|
|
77
|
-
)
|
|
78
|
-
step_count: int = Field(
|
|
79
|
-
default=0,
|
|
80
|
-
ge=0,
|
|
81
|
-
description="Number of steps taken in the current episode",
|
|
82
|
-
)
|
|
File without changes
|
|
File without changes
|
{construct_labs_crm_env-0.1.1 → construct_labs_crm_env-0.1.2}/src/construct_labs_crm_env/__init__.py
RENAMED
|
File without changes
|
{construct_labs_crm_env-0.1.1 → construct_labs_crm_env-0.1.2}/src/construct_labs_crm_env/protocol.py
RENAMED
|
File without changes
|
{construct_labs_crm_env-0.1.1 → construct_labs_crm_env-0.1.2}/src/construct_labs_crm_env/py.typed
RENAMED
|
File without changes
|