meshagent-api 0.24.6__py3-none-any.whl → 0.25.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.
@@ -1,4 +1,4 @@
1
- from pydantic import BaseModel, PositiveInt, ConfigDict, model_validator
1
+ from pydantic import BaseModel, PositiveInt, ConfigDict, Field, model_validator
2
2
  from typing import Optional, Literal
3
3
  from meshagent.api.participant_token import ApiScope
4
4
  from meshagent.api.oauth import OAuthClientConfig
@@ -9,9 +9,18 @@ from yaml.loader import SafeLoader
9
9
 
10
10
 
11
11
  class TokenValue(BaseModel):
12
- identity: str
13
- api: Optional[ApiScope] = None
14
- role: Optional[str] = None
12
+ identity: str = Field(..., description="the name to use in the participant token")
13
+ api: Optional[ApiScope] = Field(
14
+ None,
15
+ description=(
16
+ "the api permissions that should be granted to this token, set to null "
17
+ "or omit to use default permissions"
18
+ ),
19
+ )
20
+ role: Optional[str] = Field(
21
+ None,
22
+ description="a role to use in the participant token, such as user, agent, or tool",
23
+ )
15
24
 
16
25
 
17
26
  class EnvironmentVariable(BaseModel):
@@ -22,28 +31,51 @@ class EnvironmentVariable(BaseModel):
22
31
 
23
32
 
24
33
  class RoomStorageMountSpec(BaseModel):
34
+ """mounts room storage at the specified path using a FUSE mount"""
35
+
25
36
  model_config = ConfigDict(extra="forbid")
26
- path: str
27
- subpath: Optional[str] = None
37
+ path: str = Field(
38
+ ...,
39
+ description="the path within the container for the room's storage to be mounted to",
40
+ )
41
+ subpath: Optional[str] = Field(
42
+ None, description="mount only a portion of the rooms storage"
43
+ )
28
44
  read_only: bool = False
29
45
 
30
46
 
31
47
  class ProjectStorageMountSpec(BaseModel):
48
+ """mounts shared project storage at the specified path using a FUSE mount"""
49
+
32
50
  model_config = ConfigDict(extra="forbid")
33
- path: str
34
- subpath: Optional[str] = None
51
+ path: str = Field(
52
+ ...,
53
+ description="the path within the container for the project storage to be mounted to",
54
+ )
55
+ subpath: Optional[str] = Field(
56
+ None, description="mount only a portion of the project's storage"
57
+ )
35
58
  read_only: bool = True
36
59
 
37
60
 
38
61
  class ImageStorageMountSpec(BaseModel):
62
+ """mounts a the content of a Docker / OCI image at the specified path within the container"""
63
+
39
64
  model_config = ConfigDict(extra="forbid")
40
- image: str
41
- path: str
42
- subpath: Optional[str] = None
65
+ image: str = Field(..., description="the tag of an image that will be mounted")
66
+ path: str = Field(
67
+ ...,
68
+ description="the path within the container for the image volume to be mounted to",
69
+ )
70
+ subpath: Optional[str] = Field(
71
+ None, description="mount only a portion of the image volume"
72
+ )
43
73
  read_only: bool = True
44
74
 
45
75
 
46
76
  class FileStorageMountSpec(BaseModel):
77
+ """mounts a static file into the container at the specified path"""
78
+
47
79
  model_config = ConfigDict(extra="forbid")
48
80
  path: str
49
81
  text: str
@@ -113,13 +145,24 @@ class ServiceMetadata(BaseModel):
113
145
  class ContainerSpec(BaseModel):
114
146
  model_config = ConfigDict(extra="forbid")
115
147
  image: str
148
+
116
149
  command: Optional[str] = None
117
150
  environment: Optional[list[EnvironmentVariable]] = None
118
- secrets: Optional[list[str]] = None
119
- pull_secret: Optional[str] = None
120
- storage: Optional[ContainerMountSpec] = None
151
+ secrets: Optional[list[str]] = Field(
152
+ None,
153
+ description="ids of secrets that contains environment variables for this service to use",
154
+ )
155
+ pull_secret: Optional[str] = Field(
156
+ None,
157
+ description=(
158
+ "the id of a pull secret, can be used to pull private container images"
159
+ ),
160
+ )
161
+ storage: Optional[ContainerMountSpec] = Field(
162
+ None, description="storage mounts that should be provided to this container"
163
+ )
121
164
  api_key: Optional[ServiceApiKeySpec] = None
122
- on_demand: Optional[bool] = None
165
+ on_demand: Optional[bool] = Field(None, description="an on demand service")
123
166
  writable_root_fs: Optional[bool] = None
124
167
 
125
168
 
@@ -133,11 +176,26 @@ class ServiceSpec(BaseModel):
133
176
  version: Literal["v1"]
134
177
  kind: Literal["Service"]
135
178
  id: Optional[str] = None
136
- metadata: ServiceMetadata
137
- agents: Optional[list[AgentSpec]] = None
138
- ports: Optional[list["PortSpec"]] = []
139
- container: Optional[ContainerSpec] = None
140
- external: Optional[ExternalServiceSpec] = None
179
+ metadata: ServiceMetadata = Field(..., description="service metadata")
180
+ agents: Optional[list[AgentSpec]] = Field(
181
+ None, description="a list of agents that will be exposed by this service"
182
+ )
183
+ ports: Optional[list["PortSpec"]] = Field(
184
+ default_factory=list,
185
+ description="a list of ports that are exposed by this service",
186
+ )
187
+ container: Optional[ContainerSpec] = Field(
188
+ None,
189
+ description=(
190
+ "container based services run agents in sandboxed containers inside the room"
191
+ ),
192
+ )
193
+ external: Optional[ExternalServiceSpec] = Field(
194
+ None,
195
+ description=(
196
+ "external services allow discovery of externally hosted agents, mcp servers, and tools"
197
+ ),
198
+ )
141
199
 
142
200
  @model_validator(mode="after")
143
201
  def require_one_of(cls, m):
@@ -152,8 +210,17 @@ class ServiceSpec(BaseModel):
152
210
 
153
211
  class MeshagentEndpointSpec(BaseModel):
154
212
  model_config = ConfigDict(extra="forbid")
155
- identity: str
156
- api: Optional[ApiScope] = None
213
+
214
+ identity: str = Field(
215
+ ...,
216
+ description="the name to use for the participant token provided to this endpoint",
217
+ )
218
+ api: Optional[ApiScope] = Field(
219
+ None,
220
+ description=(
221
+ "customize the permissions available to this endpoint, omit to use default agent permissions"
222
+ ),
223
+ )
157
224
 
158
225
 
159
226
  class AllowedMcpToolFilter(BaseModel):
@@ -175,8 +242,16 @@ class MCPEndpointSpec(BaseModel):
175
242
 
176
243
  class EndpointSpec(BaseModel):
177
244
  model_config = ConfigDict(extra="forbid")
178
- path: str
179
- meshagent: Optional[MeshagentEndpointSpec] = None
245
+ path: str = Field(
246
+ ...,
247
+ description="the path that should receive a webhook call when the service starts",
248
+ )
249
+ meshagent: Optional[MeshagentEndpointSpec] = Field(
250
+ None,
251
+ description=(
252
+ "meshagent endpoints will be automatically notified when the service starts in order to call an agent or tool into the room"
253
+ ),
254
+ )
180
255
  mcp: Optional[MCPEndpointSpec] = None
181
256
 
182
257
 
@@ -184,9 +259,33 @@ class PortSpec(BaseModel):
184
259
  model_config = ConfigDict(extra="forbid")
185
260
  num: Literal["*"] | PositiveInt = "*"
186
261
  type: Optional[Literal["http", "tcp"]] = "http"
187
- endpoints: list[EndpointSpec] = []
188
- liveness: Optional[str] = None
189
- host_port: Optional[PositiveInt] = None
262
+ endpoints: list[EndpointSpec] = Field(
263
+ default_factory=list, description="a list of endpoints exposed under this port"
264
+ )
265
+ liveness: Optional[str] = Field(
266
+ None,
267
+ description=(
268
+ "a path that will accept a HTTP request and should return 200 when the port is live"
269
+ ),
270
+ )
271
+ host_port: Optional[PositiveInt] = Field(
272
+ None,
273
+ description=(
274
+ "expose a host port for this service, allows traffic to be tunneled to the container with port forwarding"
275
+ ),
276
+ )
277
+ published: Optional[bool] = Field(
278
+ None,
279
+ description=(
280
+ "allow traffic to be routed directly to this container from the internet, useful for implementing patterns such as webhooks"
281
+ ),
282
+ )
283
+ public: Optional[bool] = Field(
284
+ None,
285
+ description=(
286
+ "if a port is not public it will require a participant token to be passed as a Bearer token in the Authorization header"
287
+ ),
288
+ )
190
289
 
191
290
 
192
291
  class ServiceTemplateVariable(BaseModel):
meshagent/api/sql.py ADDED
@@ -0,0 +1,223 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Iterable
5
+
6
+ from meshagent.api.room_server_client import (
7
+ BinaryDataType,
8
+ BoolDataType,
9
+ DataTypeUnion,
10
+ DateDataType,
11
+ FloatDataType,
12
+ IntDataType,
13
+ TextDataType,
14
+ TimestampDataType,
15
+ VectorDataType,
16
+ )
17
+
18
+ TABLE_SCHEMA_GRAMMAR = """
19
+ TABLE_SCHEMA := COLUMN_DEF ("," COLUMN_DEF)*
20
+ COLUMN_DEF := IDENTIFIER TYPE_SPEC NULLABILITY?
21
+ TYPE_SPEC := SIMPLE_TYPE | VECTOR_TYPE
22
+ SIMPLE_TYPE := "int" | "bool" | "date" | "timestamp" | "float" | "text" | "binary"
23
+ VECTOR_TYPE := "vector" "(" INT ("," TYPE_SPEC)? ")"
24
+ NULLABILITY := "null" | "not" "null"
25
+ IDENTIFIER := /[A-Za-z_][A-Za-z0-9_]*/
26
+ INT := /[0-9]+/
27
+ """.strip()
28
+
29
+ ALLOWED_DATA_TYPES = (
30
+ "int",
31
+ "bool",
32
+ "date",
33
+ "timestamp",
34
+ "float",
35
+ "text",
36
+ "binary",
37
+ "vector",
38
+ )
39
+
40
+
41
+ @dataclass(frozen=True)
42
+ class _Token:
43
+ kind: str
44
+ value: str
45
+ position: int
46
+
47
+
48
+ class SchemaParseError(ValueError):
49
+ pass
50
+
51
+
52
+ def parse_table_schema(source: str) -> dict[str, DataTypeUnion]:
53
+ tokens = _tokenize(source)
54
+ parser = _SchemaParser(tokens)
55
+ schema = parser.parse_schema()
56
+ parser.ensure_end()
57
+ return schema
58
+
59
+
60
+ class _SchemaParser:
61
+ def __init__(self, tokens: Iterable[_Token]):
62
+ self._tokens = list(tokens)
63
+ self._index = 0
64
+
65
+ def parse_schema(self) -> dict[str, DataTypeUnion]:
66
+ schema: dict[str, DataTypeUnion] = {}
67
+ while True:
68
+ name, data_type = self._parse_column_def()
69
+ if name in schema:
70
+ raise SchemaParseError(f"Duplicate column name: {name}")
71
+ schema[name] = data_type
72
+ if not self._accept("COMMA"):
73
+ break
74
+ return schema
75
+
76
+ def parse_type(self) -> DataTypeUnion:
77
+ token = self._peek()
78
+ if token is None or token.kind != "IDENT":
79
+ raise self._error("Expected data type")
80
+ type_name = token.value.casefold()
81
+ if type_name == "vector":
82
+ self._advance()
83
+ return self._parse_vector_type()
84
+ if type_name not in ALLOWED_DATA_TYPES:
85
+ raise self._error(
86
+ f"Unsupported data type '{token.value}'. Allowed: {', '.join(ALLOWED_DATA_TYPES)}"
87
+ )
88
+ self._advance()
89
+ return _simple_type(type_name)
90
+
91
+ def parse_schema_type(self) -> DataTypeUnion:
92
+ return self.parse_type()
93
+
94
+ def parse_schema_type_with_nullability(self) -> DataTypeUnion:
95
+ data_type = self.parse_schema_type()
96
+ if self._accept("IDENT", "null"):
97
+ data_type.nullable = True
98
+ elif self._accept("IDENT", "not"):
99
+ self._expect("IDENT", "null")
100
+ data_type.nullable = False
101
+ return data_type
102
+
103
+ def ensure_end(self) -> None:
104
+ if self._peek() is not None:
105
+ token = self._peek()
106
+ raise SchemaParseError(
107
+ f"Unexpected token '{token.value}' at position {token.position}"
108
+ )
109
+
110
+ def _parse_column_def(self) -> tuple[str, DataTypeUnion]:
111
+ name_token = self._expect("IDENT")
112
+ data_type = self.parse_schema_type_with_nullability()
113
+ return name_token.value, data_type
114
+
115
+ def _parse_vector_type(self) -> DataTypeUnion:
116
+ self._expect("LPAREN")
117
+ size_token = self._expect("INT")
118
+ size = int(size_token.value)
119
+ if size <= 0:
120
+ raise self._error("Vector size must be a positive integer")
121
+ element_type = FloatDataType()
122
+ if self._accept("COMMA"):
123
+ element_type = self.parse_schema_type()
124
+ self._expect("RPAREN")
125
+ return VectorDataType(size=size, element_type=element_type)
126
+
127
+ def _expect(self, kind: str, value: str | None = None) -> _Token:
128
+ token = self._peek()
129
+ if token is None:
130
+ raise self._error("Unexpected end of input")
131
+ if token.kind != kind or (
132
+ value is not None and token.value.casefold() != value.casefold()
133
+ ):
134
+ expected = f"{kind}{' ' + value if value else ''}"
135
+ raise self._error(f"Expected {expected}")
136
+ self._index += 1
137
+ return token
138
+
139
+ def _accept(self, kind: str, value: str | None = None) -> bool:
140
+ token = self._peek()
141
+ if token is None:
142
+ return False
143
+ if token.kind != kind:
144
+ return False
145
+ if value is not None and token.value.casefold() != value.casefold():
146
+ return False
147
+ self._index += 1
148
+ return True
149
+
150
+ def _peek(self) -> _Token | None:
151
+ if self._index >= len(self._tokens):
152
+ return None
153
+ return self._tokens[self._index]
154
+
155
+ def _advance(self) -> _Token:
156
+ token = self._peek()
157
+ if token is None:
158
+ raise self._error("Unexpected end of input")
159
+ self._index += 1
160
+ return token
161
+
162
+ def _error(self, message: str) -> SchemaParseError:
163
+ token = self._peek()
164
+ if token is None:
165
+ return SchemaParseError(f"{message} at end of input")
166
+ return SchemaParseError(f"{message} at position {token.position}")
167
+
168
+
169
+ def _tokenize(source: str) -> list[_Token]:
170
+ tokens: list[_Token] = []
171
+ idx = 0
172
+ length = len(source)
173
+ while idx < length:
174
+ char = source[idx]
175
+ if char.isspace():
176
+ idx += 1
177
+ continue
178
+ if char == ",":
179
+ tokens.append(_Token("COMMA", char, idx))
180
+ idx += 1
181
+ continue
182
+ if char == "(":
183
+ tokens.append(_Token("LPAREN", char, idx))
184
+ idx += 1
185
+ continue
186
+ if char == ")":
187
+ tokens.append(_Token("RPAREN", char, idx))
188
+ idx += 1
189
+ continue
190
+ if char.isdigit():
191
+ start = idx
192
+ while idx < length and source[idx].isdigit():
193
+ idx += 1
194
+ tokens.append(_Token("INT", source[start:idx], start))
195
+ continue
196
+ if char.isalpha() or char == "_":
197
+ start = idx
198
+ while idx < length and (source[idx].isalnum() or source[idx] == "_"):
199
+ idx += 1
200
+ tokens.append(_Token("IDENT", source[start:idx], start))
201
+ continue
202
+ raise SchemaParseError(f"Unexpected character '{char}' at position {idx}")
203
+ return tokens
204
+
205
+
206
+ def _simple_type(type_name: str) -> DataTypeUnion:
207
+ if type_name == "int":
208
+ return IntDataType()
209
+ if type_name == "bool":
210
+ return BoolDataType()
211
+ if type_name == "date":
212
+ return DateDataType()
213
+ if type_name == "timestamp":
214
+ return TimestampDataType()
215
+ if type_name == "float":
216
+ return FloatDataType()
217
+ if type_name == "text":
218
+ return TextDataType()
219
+ if type_name == "binary":
220
+ return BinaryDataType()
221
+ raise SchemaParseError(
222
+ f"Unsupported data type '{type_name}'. Allowed: {', '.join(ALLOWED_DATA_TYPES)}"
223
+ )
@@ -0,0 +1,38 @@
1
+ import pytest
2
+
3
+ from meshagent.api.room_server_client import (
4
+ FloatDataType,
5
+ IntDataType,
6
+ TextDataType,
7
+ VectorDataType,
8
+ )
9
+ from meshagent.api.sql import SchemaParseError, parse_table_schema
10
+
11
+
12
+ def test_parse_schema_case_insensitive():
13
+ schema = parse_table_schema("names VeCtOr(20) nUlL, test TeXT NoT NuLL, age INT")
14
+
15
+ assert isinstance(schema["names"], VectorDataType)
16
+ assert schema["names"].size == 20
17
+ assert schema["names"].nullable is True
18
+ assert isinstance(schema["names"].element_type, FloatDataType)
19
+
20
+ assert isinstance(schema["test"], TextDataType)
21
+ assert schema["test"].nullable is False
22
+
23
+ assert isinstance(schema["age"], IntDataType)
24
+ assert schema["age"].nullable is None
25
+
26
+
27
+ def test_parse_schema_vector_element_type_case_insensitive():
28
+ schema = parse_table_schema("embedding vector(3, FLOAT)")
29
+ column = schema["embedding"]
30
+
31
+ assert isinstance(column, VectorDataType)
32
+ assert column.size == 3
33
+ assert isinstance(column.element_type, FloatDataType)
34
+
35
+
36
+ def test_parse_schema_duplicate_columns():
37
+ with pytest.raises(SchemaParseError, match="Duplicate column name"):
38
+ parse_table_schema("id int, id text")
meshagent/api/urls.py CHANGED
@@ -8,7 +8,7 @@ def meshagent_base_url(base_url: Optional[str] = None):
8
8
 
9
9
  def websocket_room_url(*, room_name: str, base_url: Optional[str] = None) -> str:
10
10
  if base_url is None:
11
- api_url = os.getenv("MESHAGENT_API_URL")
11
+ api_url = os.getenv("MESHAGENT_ROOM_URL", os.getenv("MESHAGENT_API_URL"))
12
12
  if api_url is None:
13
13
  base_url = "wss://api.meshagent.com"
14
14
  else:
meshagent/api/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.24.6"
1
+ __version__ = "0.25.1"
@@ -4,6 +4,7 @@ import asyncio
4
4
  import logging
5
5
  import urllib
6
6
  from meshagent.api.version import __version__
7
+ from meshagent.api.http import new_client_session
7
8
  from typing import Optional
8
9
 
9
10
  from meshagent.api.protocol import Protocol, ClientProtocol
@@ -12,19 +13,31 @@ logger = logging.getLogger("protocol.websocket")
12
13
 
13
14
 
14
15
  class WebSocketClientProtocol(ClientProtocol):
15
- def __init__(self, *, url: str, token: str, heartbeat: float = 30):
16
+ def __init__(
17
+ self,
18
+ *,
19
+ url: str,
20
+ token: str,
21
+ heartbeat: float = 30,
22
+ session: ClientSession | None = None,
23
+ ):
16
24
  super().__init__(token=token)
17
25
  self._url = url
18
26
  self._heartbeat = heartbeat
27
+ self._session = session
28
+ self._session_external = session is not None
19
29
 
20
30
  @property
21
31
  def url(self):
22
32
  return self._url
23
33
 
24
34
  async def __aenter__(self):
25
- self._session = ClientSession()
35
+ if self._session is None:
36
+ self._session = new_client_session()
37
+ self._session_external = False
26
38
 
27
- await self._session.__aenter__()
39
+ if not self._session_external:
40
+ await self._session.__aenter__()
28
41
 
29
42
  url_parts = urllib.parse.urlparse(self._url)
30
43
  query_dict = urllib.parse.parse_qs(url_parts.query)
@@ -70,7 +83,8 @@ class WebSocketClientProtocol(ClientProtocol):
70
83
  if not self._ws.closed:
71
84
  await self._ws.close()
72
85
  await self._ws_recv_task
73
- await self._session.__aexit__(exc_type, exc, tb)
86
+ if not self._session_external:
87
+ await self._session.__aexit__(exc_type, exc, tb)
74
88
  await self._ws_ctx.__aexit__(exc_type, exc, tb)
75
89
  await super().__aexit__(exc_type, exc, tb)
76
90
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: meshagent-api
3
- Version: 0.24.6
3
+ Version: 0.25.1
4
4
  Summary: Python Server API for Meshagent
5
5
  License-Expression: Apache-2.0
6
6
  Project-URL: Documentation, https://docs.meshagent.com
@@ -10,12 +10,13 @@ Requires-Python: >=3.13
10
10
  Description-Content-Type: text/markdown
11
11
  License-File: LICENSE
12
12
  Requires-Dist: pyjwt~=2.10
13
- Requires-Dist: aiohttp~=3.10
13
+ Requires-Dist: aiohttp[speedups]~=3.13.0
14
14
  Requires-Dist: jsonschema~=4.23
15
15
  Requires-Dist: pycrdt~=0.12.26
16
16
  Requires-Dist: opentelemetry-distro~=0.54b1
17
17
  Requires-Dist: pydantic~=2.11.7
18
18
  Requires-Dist: jinja2~=3.1.6
19
+ Requires-Dist: certifi~=2026.1.4
19
20
  Provides-Extra: all
20
21
  Provides-Extra: sync
21
22
  Provides-Extra: stpyv8
@@ -1,21 +1,22 @@
1
1
  meshagent/api/__init__.py,sha256=kzhnEnzNjm4yUztR4aY78h1mxZxkvXGeWIvxOA2rDxY,2037
2
2
  meshagent/api/chan.py,sha256=PBIfVHj_znsmlZ0zxvmglCrX_4m7zzPLhxWRycfyEgc,4763
3
- meshagent/api/client.py,sha256=Lkjh3KQYWEEd80FQuhwHTbqZlW8INDW7iIC9cwz1WoI,75387
3
+ meshagent/api/client.py,sha256=4aHj3BI6y1UE0jAHPh4m6-X_F4iOe39IwrC2Y-esqFQ,76362
4
4
  meshagent/api/crdt.py,sha256=1d_bjIR8iYfktHBW04dfaaiXWA6ZYCfgfxCmDHXivGk,18580
5
5
  meshagent/api/entrypoint.js,sha256=82XGHgopru9fyzi3V5JFy6YoaV0OmlsczXE9OdHjYgw,85567
6
- meshagent/api/helpers.py,sha256=bwMHDA9PmNZmVTKiMsGef3sQVq3LiyRoi8plJhBxwME,3270
6
+ meshagent/api/helpers.py,sha256=5tU0k1DcWZMcZy2dlA3qJ5Ifs5Au4TEsBontKHa43y4,3365
7
+ meshagent/api/http.py,sha256=gooHy2PIpP4Upnbxn_TZ5D3si6dixsG5piPbFzdGXEI,413
7
8
  meshagent/api/keys.py,sha256=VkRo0tH3uEMgCDnUg7640oDQkruGoE1AItb9g-Jjg9c,2950
8
9
  meshagent/api/messaging.py,sha256=0vCmdxwtki9rHKrON427r2TTbXdyW9iEluQ3fAyjMYU,8844
9
10
  meshagent/api/oauth.py,sha256=ezwtsdM76FWFGIZeUhJ5z02tOTh-ve7djHPe-PuzGVU,460
10
11
  meshagent/api/participant.py,sha256=usyXHK42Swobb76SRNHZrfB3w4h0P8tGmzGRrOJCw-k,341
11
- meshagent/api/participant_token.py,sha256=QZFmWV-5ycSFvqv_uXeNzgPJfuoPpAqa5-XXcXp-_f4,13716
12
+ meshagent/api/participant_token.py,sha256=i5trPgWtCxG380GIMz7xGvYbDiyLsO8jeuztBMmxeEs,13893
12
13
  meshagent/api/participant_token_test.py,sha256=EeMuw47iR1N2mBxVZRAhhiWYtN9BvIT80fAoZAN-VqQ,6998
13
- meshagent/api/port_forward.py,sha256=X2NBvAv6_6Ggs0vWsW6RBI0n_TviSePVM15cW_zQzlE,5050
14
+ meshagent/api/port_forward.py,sha256=WijWKs14kMabW97GjjBXTdB0dg7_mdlCWeNk7KW91e4,5097
14
15
  meshagent/api/protocol.py,sha256=1N82ZQmSTg_XIf5yrjAo3QVEmW9yT29JctWTwzoVDzA,10571
15
16
  meshagent/api/protocol_test.py,sha256=3ETAAAEzuqhFW26xYPxE7Pj1_Us6dHlifgp1W2QiwFs,1428
16
17
  meshagent/api/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
18
  meshagent/api/reasoning_schema.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
- meshagent/api/room_server_client.py,sha256=51dwjpLyxdLRmFNIuh8ud2Qeker8ibvpWMWqq2hdnt8,103727
19
+ meshagent/api/room_server_client.py,sha256=vRpFealzUkRnQsMd8OPc-Rd738hUXJM9ukooHMrjsHM,105259
19
20
  meshagent/api/runtime.py,sha256=H0pcZHefjDBFMZgZMeAW7dKUtYrrrKI7Fb8_vvI7o4s,11355
20
21
  meshagent/api/runtime_test.py,sha256=hQSp2fz2CT94cGg3-yeyFMK5F7jrIXRDoEtn15A5h4k,10807
21
22
  meshagent/api/schema.py,sha256=Y0A1QRk6_hG3zP81Qv7rFO01y2mbNqyvD1sKDyhEJfM,11673
@@ -26,14 +27,16 @@ meshagent/api/schema_test.py,sha256=lYi7AGm5LD8aVMKzGFdN_o219kifb3_laETXAvC7KJI,
26
27
  meshagent/api/schema_util.py,sha256=-vtbWKfolYK0946HAGfD5xYmQ0qHJftcPcMBLPtzs1I,1371
27
28
  meshagent/api/service_template_test.py,sha256=N348oZzlOiLR4GZNTiiLyEXXWq8Btapg6C3oymtVo8g,6145
28
29
  meshagent/api/services.py,sha256=LPJqGuwN0zZgZWIiJqkf6Kh0lyKn9s1z-SEuX2oPw10,11365
30
+ meshagent/api/sql.py,sha256=b3q2xO0yn88S31vha-WZBVEYHUxPcrKR9OcY6dcKXcI,6886
31
+ meshagent/api/sql_test.py,sha256=sDX4vVNRez0EE09J0yPYMuKYJi8dG4eUSE21bBox0sg,1186
29
32
  meshagent/api/token_test.py,sha256=KGa-lDMAsB3QST_6ORCPGSOHPnhm6WSTA4uj4ZYgrPY,3719
30
- meshagent/api/urls.py,sha256=Vxs4Fg4fLfZASmsqAeZtY3u-7vFDx9rH7m7HtQKPg64,712
31
- meshagent/api/version.py,sha256=1LERjg6TTlEZCKHKtH82Ox1j8xI8WMA94hEjeTPs1Io,23
33
+ meshagent/api/urls.py,sha256=g7w-1nzbcRzJVbxp2M8TiT8pz7NLVfSamrEkr0NDiKc,745
34
+ meshagent/api/version.py,sha256=ACu2Z3Q3TFgYpAno_eu9ssJ1QULjNXvjGvyqDSHrQ_o,23
32
35
  meshagent/api/webhooks.py,sha256=6ZKUgc-uXzg6V2DBy-yAvOsb1dXxUVEPTqj36A9w_6Y,8352
33
- meshagent/api/websocket_protocol.py,sha256=I4NYrSnkohpHi7wYbKAwQsgT2HTH_xWmu5_JDRlpeEQ,3760
34
- meshagent/api/specs/service.py,sha256=iobqfBMcg5w4ndyqUzyez9RtPTBYB5oGVZf4wLLVeqE,11615
35
- meshagent_api-0.24.6.dist-info/licenses/LICENSE,sha256=eTt0SPW-sVNdkZe9PS_S8WfCIyLjRXRl7sUBWdlteFg,10254
36
- meshagent_api-0.24.6.dist-info/METADATA,sha256=LJMo9u_WN9MXBQBsquC956TcHh25MfsKd-PVGpKRvOg,4540
37
- meshagent_api-0.24.6.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
38
- meshagent_api-0.24.6.dist-info/top_level.txt,sha256=GlcXnHtRP6m7zlG3Df04M35OsHtNXy_DY09oFwWrH74,10
39
- meshagent_api-0.24.6.dist-info/RECORD,,
36
+ meshagent/api/websocket_protocol.py,sha256=f9IV6goyRvpbOTIsziOd5_aXujikHuSiTSXk2Q0dXTA,4160
37
+ meshagent/api/specs/service.py,sha256=XIBS9MFmG-k8aeY7JV-_IBFtu0TQUADn2418waGyqHc,15398
38
+ meshagent_api-0.25.1.dist-info/licenses/LICENSE,sha256=eTt0SPW-sVNdkZe9PS_S8WfCIyLjRXRl7sUBWdlteFg,10254
39
+ meshagent_api-0.25.1.dist-info/METADATA,sha256=qwHM_KI6GF4R8DC1fgycj4wsj560z45HMy2_g_O0VJA,4585
40
+ meshagent_api-0.25.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
41
+ meshagent_api-0.25.1.dist-info/top_level.txt,sha256=GlcXnHtRP6m7zlG3Df04M35OsHtNXy_DY09oFwWrH74,10
42
+ meshagent_api-0.25.1.dist-info/RECORD,,