meshagent-api 0.41.2__tar.gz → 0.41.5__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.
- {meshagent_api-0.41.2/meshagent_api.egg-info → meshagent_api-0.41.5}/PKG-INFO +1 -1
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/client.py +42 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/client_test.py +62 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/room_server_client.py +8 -1
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/specs/service.py +20 -0
- meshagent_api-0.41.5/meshagent/api/version.py +1 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5/meshagent_api.egg-info}/PKG-INFO +1 -1
- meshagent_api-0.41.2/meshagent/api/version.py +0 -1
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/LICENSE +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/MANIFEST.in +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/README.md +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/__init__.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/agent_content.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/aiohttp_redaction.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/chan.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/crdt.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/dataset_schema.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/entrypoint.js +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/error_codes.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/helpers.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/http.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/image_runtime.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/keys.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/managed_agents.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/managed_agents_test.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/messaging.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/messaging_test.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/oauth.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/oauth_scopes.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/oauth_scopes_test.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/participant.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/participant_token.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/participant_token_test.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/port_forward.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/port_forward_test.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/protocol.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/protocol_test.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/py.typed +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/reasoning_schema.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/registry_auth.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/room_ports.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/room_server_client_test.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/runtime.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/runtime_test.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/schema.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/schema_document.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/schema_document_test.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/schema_registry.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/schema_test.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/schema_util.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/service_spec_test.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/service_template_test.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/services.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/sql.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/sql_test.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/token_test.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/urls.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/webhooks.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/websocket_protocol.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent/api/websocket_protocol_test.py +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent_api.egg-info/SOURCES.txt +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent_api.egg-info/dependency_links.txt +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent_api.egg-info/requires.txt +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/meshagent_api.egg-info/top_level.txt +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/pyproject.toml +0 -0
- {meshagent_api-0.41.2 → meshagent_api-0.41.5}/setup.cfg +0 -0
|
@@ -2,6 +2,7 @@ import aiohttp
|
|
|
2
2
|
import base64
|
|
3
3
|
import json
|
|
4
4
|
import re
|
|
5
|
+
from urllib.parse import quote
|
|
5
6
|
from typing import Any, Dict, List, Optional, Literal, TypeVar
|
|
6
7
|
from pydantic import (
|
|
7
8
|
BaseModel,
|
|
@@ -2700,6 +2701,26 @@ class Meshagent:
|
|
|
2700
2701
|
except ValidationError as exc:
|
|
2701
2702
|
raise RoomException(f"Invalid service payload: {exc}") from exc
|
|
2702
2703
|
|
|
2704
|
+
async def get_service_by_name(
|
|
2705
|
+
self, *, project_id: str, service_name: str
|
|
2706
|
+
) -> ServiceSpec:
|
|
2707
|
+
"""
|
|
2708
|
+
GET /accounts/projects/{project_id}/services/by-name/{service_name}
|
|
2709
|
+
Returns a `Service` instance.
|
|
2710
|
+
"""
|
|
2711
|
+
service_name_path = quote(service_name, safe="")
|
|
2712
|
+
url = (
|
|
2713
|
+
f"{self.base_url}/accounts/projects/{project_id}"
|
|
2714
|
+
f"/services/by-name/{service_name_path}"
|
|
2715
|
+
)
|
|
2716
|
+
async with self._session.get(url, headers=self._get_headers()) as resp:
|
|
2717
|
+
await self._raise_for_status(resp)
|
|
2718
|
+
raw = await resp.text()
|
|
2719
|
+
try:
|
|
2720
|
+
return ServiceSpec.model_validate_json(raw)
|
|
2721
|
+
except ValidationError as exc:
|
|
2722
|
+
raise RoomException(f"Invalid service payload: {exc}") from exc
|
|
2723
|
+
|
|
2703
2724
|
async def list_services(self, *, project_id: str) -> List[ServiceSpec]:
|
|
2704
2725
|
"""
|
|
2705
2726
|
GET /accounts/projects/{project_id}/services
|
|
@@ -2858,6 +2879,27 @@ class Meshagent:
|
|
|
2858
2879
|
except ValidationError as exc:
|
|
2859
2880
|
raise RoomException(f"Invalid service payload: {exc}") from exc
|
|
2860
2881
|
|
|
2882
|
+
async def get_room_service_by_name(
|
|
2883
|
+
self, *, project_id: str, room_name: str, service_name: str
|
|
2884
|
+
) -> ServiceSpec:
|
|
2885
|
+
"""
|
|
2886
|
+
GET /accounts/projects/{project_id}/rooms/{room_name}/services/by-name/{service_name}
|
|
2887
|
+
Returns a `Service` instance.
|
|
2888
|
+
"""
|
|
2889
|
+
room_name_path = quote(room_name, safe="")
|
|
2890
|
+
service_name_path = quote(service_name, safe="")
|
|
2891
|
+
url = (
|
|
2892
|
+
f"{self.base_url}/accounts/projects/{project_id}/rooms/{room_name_path}"
|
|
2893
|
+
f"/services/by-name/{service_name_path}"
|
|
2894
|
+
)
|
|
2895
|
+
async with self._session.get(url, headers=self._get_headers()) as resp:
|
|
2896
|
+
await self._raise_for_status(resp)
|
|
2897
|
+
raw = await resp.text()
|
|
2898
|
+
try:
|
|
2899
|
+
return ServiceSpec.model_validate_json(raw)
|
|
2900
|
+
except ValidationError as exc:
|
|
2901
|
+
raise RoomException(f"Invalid service payload: {exc}") from exc
|
|
2902
|
+
|
|
2861
2903
|
async def list_room_services(
|
|
2862
2904
|
self, *, project_id: str, room_name: str
|
|
2863
2905
|
) -> List[ServiceSpec]:
|
|
@@ -253,6 +253,68 @@ async def test_create_room_service_omits_client_supplied_id():
|
|
|
253
253
|
]
|
|
254
254
|
|
|
255
255
|
|
|
256
|
+
@pytest.mark.asyncio
|
|
257
|
+
async def test_get_service_by_name_uses_by_name_endpoint():
|
|
258
|
+
session = _FakeSession(
|
|
259
|
+
[
|
|
260
|
+
_FakeResponse(
|
|
261
|
+
status=200,
|
|
262
|
+
payload={
|
|
263
|
+
"version": "v1",
|
|
264
|
+
"kind": "Service",
|
|
265
|
+
"id": "svc_123",
|
|
266
|
+
"metadata": {"name": "worker"},
|
|
267
|
+
},
|
|
268
|
+
)
|
|
269
|
+
]
|
|
270
|
+
)
|
|
271
|
+
client = Meshagent(base_url="http://example.test", token="token", session=session)
|
|
272
|
+
|
|
273
|
+
service = await client.get_service_by_name(
|
|
274
|
+
project_id="proj_123", service_name="worker/service"
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
assert service.id == "svc_123"
|
|
278
|
+
assert session.calls == [
|
|
279
|
+
(
|
|
280
|
+
"get",
|
|
281
|
+
"http://example.test/accounts/projects/proj_123/services/by-name/worker%2Fservice",
|
|
282
|
+
None,
|
|
283
|
+
)
|
|
284
|
+
]
|
|
285
|
+
|
|
286
|
+
|
|
287
|
+
@pytest.mark.asyncio
|
|
288
|
+
async def test_get_room_service_by_name_uses_by_name_endpoint():
|
|
289
|
+
session = _FakeSession(
|
|
290
|
+
[
|
|
291
|
+
_FakeResponse(
|
|
292
|
+
status=200,
|
|
293
|
+
payload={
|
|
294
|
+
"version": "v1",
|
|
295
|
+
"kind": "Service",
|
|
296
|
+
"id": "svc_123",
|
|
297
|
+
"metadata": {"name": "worker"},
|
|
298
|
+
},
|
|
299
|
+
)
|
|
300
|
+
]
|
|
301
|
+
)
|
|
302
|
+
client = Meshagent(base_url="http://example.test", token="token", session=session)
|
|
303
|
+
|
|
304
|
+
service = await client.get_room_service_by_name(
|
|
305
|
+
project_id="proj_123", room_name="room 1", service_name="worker/service"
|
|
306
|
+
)
|
|
307
|
+
|
|
308
|
+
assert service.id == "svc_123"
|
|
309
|
+
assert session.calls == [
|
|
310
|
+
(
|
|
311
|
+
"get",
|
|
312
|
+
"http://example.test/accounts/projects/proj_123/rooms/room%201/services/by-name/worker%2Fservice",
|
|
313
|
+
None,
|
|
314
|
+
)
|
|
315
|
+
]
|
|
316
|
+
|
|
317
|
+
|
|
256
318
|
@pytest.mark.asyncio
|
|
257
319
|
async def test_update_scheduled_task_replaces_spec():
|
|
258
320
|
session = _FakeSession([_FakeResponse(status=200, payload={})])
|
|
@@ -13,7 +13,11 @@ from meshagent.api.protocol import (
|
|
|
13
13
|
ProtocolCloseKind,
|
|
14
14
|
ProtocolReconnectUnsupportedError,
|
|
15
15
|
)
|
|
16
|
-
from meshagent.api.specs.service import
|
|
16
|
+
from meshagent.api.specs.service import (
|
|
17
|
+
ContainerMountSpec,
|
|
18
|
+
ContainerTemplate,
|
|
19
|
+
ServiceSpec,
|
|
20
|
+
)
|
|
17
21
|
from meshagent.api.websocket_protocol import WebSocketClientProtocol
|
|
18
22
|
from meshagent.api.participant_token import ApiScope
|
|
19
23
|
from pydantic import (
|
|
@@ -7612,6 +7616,7 @@ class _RunRequest(BaseModel):
|
|
|
7612
7616
|
name: Optional[str] = None
|
|
7613
7617
|
annotations: Optional[Dict[str, str]] = None
|
|
7614
7618
|
mounts: Optional[ContainerMountSpec] = None
|
|
7619
|
+
template: Optional[ContainerTemplate] = "none"
|
|
7615
7620
|
writable_root_fs: Optional[bool] = None
|
|
7616
7621
|
private: Optional[bool] = None
|
|
7617
7622
|
|
|
@@ -8217,6 +8222,7 @@ class ContainersClient:
|
|
|
8217
8222
|
credentials: List[DockerSecret] | None = None,
|
|
8218
8223
|
name: Optional[str] = None,
|
|
8219
8224
|
mounts: Optional[ContainerMountSpec] = None,
|
|
8225
|
+
template: Optional[ContainerTemplate] = "none",
|
|
8220
8226
|
writable_root_fs: Optional[bool] = None,
|
|
8221
8227
|
private: Optional[bool] = None,
|
|
8222
8228
|
) -> str:
|
|
@@ -8242,6 +8248,7 @@ class ContainersClient:
|
|
|
8242
8248
|
"mounts": mounts.model_dump(mode="json", exclude_none=True)
|
|
8243
8249
|
if mounts is not None
|
|
8244
8250
|
else None,
|
|
8251
|
+
"template": template,
|
|
8245
8252
|
"writable_root_fs": writable_root_fs,
|
|
8246
8253
|
"private": private,
|
|
8247
8254
|
},
|
|
@@ -18,6 +18,7 @@ import json
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
MIN_SCHEDULED_TASK_INTERVAL_SECONDS = 15 * 60
|
|
21
|
+
ContainerTemplate = Literal["agent", "none"]
|
|
21
22
|
_SCHEDULE_INTERVAL_RE = re.compile(
|
|
22
23
|
r"^\s*(?P<count>\d+)\s+(?P<unit>second|seconds|minute|minutes|hour|hours|day|days)\s*$",
|
|
23
24
|
re.IGNORECASE,
|
|
@@ -339,6 +340,15 @@ class ServiceMetadata(BaseModel):
|
|
|
339
340
|
class ContainerSpec(BaseModel):
|
|
340
341
|
model_config = ConfigDict(extra="forbid")
|
|
341
342
|
image: str
|
|
343
|
+
template: Optional[ContainerTemplate] = Field(
|
|
344
|
+
"agent",
|
|
345
|
+
description=(
|
|
346
|
+
"container defaults to apply. 'agent' mounts room storage at /data "
|
|
347
|
+
"and injects MeshAgent/OpenAI/Anthropic proxy environment variables "
|
|
348
|
+
"with a token that has default agent permissions unless manually "
|
|
349
|
+
"overridden. 'none' applies no defaults."
|
|
350
|
+
),
|
|
351
|
+
)
|
|
342
352
|
|
|
343
353
|
command: Optional[str] = None
|
|
344
354
|
working_dir: Optional[str] = None
|
|
@@ -717,6 +727,15 @@ class ContainerTemplateSpec(BaseModel):
|
|
|
717
727
|
model_config = ConfigDict(extra="forbid")
|
|
718
728
|
environment: Optional[list[TemplateEnvironmentVariable]] = None
|
|
719
729
|
image: Optional[str] = None
|
|
730
|
+
template: Optional[ContainerTemplate] = Field(
|
|
731
|
+
"agent",
|
|
732
|
+
description=(
|
|
733
|
+
"container defaults to apply. 'agent' mounts room storage at /data "
|
|
734
|
+
"and injects MeshAgent/OpenAI/Anthropic proxy environment variables "
|
|
735
|
+
"with a token that has default agent permissions unless manually "
|
|
736
|
+
"overridden. 'none' applies no defaults."
|
|
737
|
+
),
|
|
738
|
+
)
|
|
720
739
|
command: Optional[str] = None
|
|
721
740
|
working_dir: Optional[str] = None
|
|
722
741
|
storage: Optional[ServiceTemplateContainerMountSpec] = None
|
|
@@ -816,6 +835,7 @@ class ServiceTemplateSpec(BaseModel):
|
|
|
816
835
|
command=self.container.command,
|
|
817
836
|
working_dir=self.container.working_dir,
|
|
818
837
|
image=self.container.image,
|
|
838
|
+
template=self.container.template,
|
|
819
839
|
environment=env,
|
|
820
840
|
storage=ContainerMountSpec(
|
|
821
841
|
room=self.container.storage.room,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.41.5"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.41.2"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|