mobileops-managed-agent 0.3.2__tar.gz → 0.4.1__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.
- {mobileops_managed_agent-0.3.2/src/mobileops_managed_agent.egg-info → mobileops_managed_agent-0.4.1}/PKG-INFO +7 -1
- {mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/README.md +6 -0
- {mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/pyproject.toml +1 -1
- {mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/src/mobileops_managed_agent/__init__.py +2 -0
- {mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/src/mobileops_managed_agent/auth.py +2 -1
- {mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/src/mobileops_managed_agent/client.py +3 -0
- mobileops_managed_agent-0.4.1/src/mobileops_managed_agent/run_timing.py +65 -0
- mobileops_managed_agent-0.4.1/src/mobileops_managed_agent/stream_policy.py +33 -0
- {mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1/src/mobileops_managed_agent.egg-info}/PKG-INFO +7 -1
- {mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/src/mobileops_managed_agent.egg-info/SOURCES.txt +2 -0
- {mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/MANIFEST.in +0 -0
- {mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/setup.cfg +0 -0
- {mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/src/mobileops_managed_agent/artifacts.py +0 -0
- {mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/src/mobileops_managed_agent/assistant_model.py +0 -0
- {mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/src/mobileops_managed_agent/assistants.py +0 -0
- {mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/src/mobileops_managed_agent/capabilities.py +0 -0
- {mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/src/mobileops_managed_agent/credential_vault.py +0 -0
- {mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/src/mobileops_managed_agent/files.py +0 -0
- {mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/src/mobileops_managed_agent/model_retry.py +0 -0
- {mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/src/mobileops_managed_agent/resources.py +0 -0
- {mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/src/mobileops_managed_agent/response_schema.py +0 -0
- {mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/src/mobileops_managed_agent/sandbox_profile.py +0 -0
- {mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/src/mobileops_managed_agent/sandbox_profiles.py +0 -0
- {mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/src/mobileops_managed_agent/tool_permissions.py +0 -0
- {mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/src/mobileops_managed_agent/vaults.py +0 -0
- {mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/src/mobileops_managed_agent.egg-info/dependency_links.txt +0 -0
- {mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/src/mobileops_managed_agent.egg-info/requires.txt +0 -0
- {mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/src/mobileops_managed_agent.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mobileops-managed-agent
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: Server-side SDK for the MobileOPS Managed Agent API.
|
|
5
5
|
Project-URL: Homepage, https://github.com/InnoMindX/deepagent/tree/main/managed-agent-sdk/python
|
|
6
6
|
Project-URL: Repository, https://github.com/InnoMindX/deepagent
|
|
@@ -76,3 +76,9 @@ await client.files.list(thread["thread_id"], "/workspace")
|
|
|
76
76
|
```
|
|
77
77
|
|
|
78
78
|
Keep MobileOPS Managed Agent API keys in server-side code only.
|
|
79
|
+
|
|
80
|
+
## Streaming in 0.4.0
|
|
81
|
+
|
|
82
|
+
Run streaming defaults to `messages-tuple`, `updates`, and `custom`. Explicit
|
|
83
|
+
`values` subscriptions raise `ValueError` before network access. Fetch full state
|
|
84
|
+
once with `client.agent.threads.get_state(thread_id)` after the stream ends.
|
|
@@ -60,3 +60,9 @@ await client.files.list(thread["thread_id"], "/workspace")
|
|
|
60
60
|
```
|
|
61
61
|
|
|
62
62
|
Keep MobileOPS Managed Agent API keys in server-side code only.
|
|
63
|
+
|
|
64
|
+
## Streaming in 0.4.0
|
|
65
|
+
|
|
66
|
+
Run streaming defaults to `messages-tuple`, `updates`, and `custom`. Explicit
|
|
67
|
+
`values` subscriptions raise `ValueError` before network access. Fetch full state
|
|
68
|
+
once with `client.agent.threads.get_state(thread_id)` after the stream ends.
|
|
@@ -67,6 +67,7 @@ from .vaults import (
|
|
|
67
67
|
__all__ = [
|
|
68
68
|
"ModelRetryEvent",
|
|
69
69
|
"ModelRetryTracker",
|
|
70
|
+
"human_run_duration_ms",
|
|
70
71
|
"MobileOpsArtifactsClient",
|
|
71
72
|
"MobileOpsStorageClient",
|
|
72
73
|
"Artifact",
|
|
@@ -135,3 +136,4 @@ from .artifacts import (
|
|
|
135
136
|
)
|
|
136
137
|
|
|
137
138
|
from .model_retry import ModelRetryEvent, ModelRetryTracker
|
|
139
|
+
from .run_timing import human_run_duration_ms
|
{mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/src/mobileops_managed_agent/auth.py
RENAMED
|
@@ -10,9 +10,10 @@ def build_headers(
|
|
|
10
10
|
safe_headers = {
|
|
11
11
|
name: value
|
|
12
12
|
for name, value in dict(headers or {}).items()
|
|
13
|
-
if name.lower()
|
|
13
|
+
if name.lower() not in {"authorization", "x-mobileops-sdk"}
|
|
14
14
|
}
|
|
15
15
|
return {
|
|
16
16
|
**safe_headers,
|
|
17
|
+
"X-MobileOps-SDK": "python",
|
|
17
18
|
"Authorization": f"Bearer {api_key}",
|
|
18
19
|
}
|
|
@@ -6,6 +6,7 @@ from typing import Any
|
|
|
6
6
|
import httpx
|
|
7
7
|
|
|
8
8
|
from .auth import build_headers
|
|
9
|
+
from .stream_policy import RunsClient
|
|
9
10
|
from .files import MobileOpsFilesClient
|
|
10
11
|
from .assistants import MobileOpsAssistantsClient
|
|
11
12
|
from .resources import MobileOpsResourcesClient
|
|
@@ -21,6 +22,8 @@ class MobileOpsAgentClient:
|
|
|
21
22
|
|
|
22
23
|
def __init__(self, native: Any) -> None:
|
|
23
24
|
self._native = native
|
|
25
|
+
if getattr(native, "runs", None) is not None:
|
|
26
|
+
self.runs = RunsClient(native.runs)
|
|
24
27
|
native_assistants = getattr(native, "assistants", None)
|
|
25
28
|
if native_assistants is not None:
|
|
26
29
|
self.assistants = MobileOpsAssistantsClient(native_assistants)
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""Read turn duration from timestamps stamped on the current human message."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from datetime import datetime, timezone
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
RUN_STARTED_AT = "run_started_at"
|
|
9
|
+
RUN_ENDED_AT = "run_ended_at"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _kwargs(message: Any) -> dict[str, Any]:
|
|
13
|
+
if isinstance(message, dict):
|
|
14
|
+
raw = message.get("additional_kwargs")
|
|
15
|
+
else:
|
|
16
|
+
raw = getattr(message, "additional_kwargs", None)
|
|
17
|
+
return raw if isinstance(raw, dict) else {}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _kind(message: Any) -> str:
|
|
21
|
+
if isinstance(message, dict):
|
|
22
|
+
value = message.get("type") or message.get("role")
|
|
23
|
+
else:
|
|
24
|
+
value = getattr(message, "type", None) or getattr(message, "role", None)
|
|
25
|
+
return str(value or "")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _parse_ms(value: str) -> int | None:
|
|
29
|
+
text = value[:-1] + "+00:00" if value.endswith("Z") else value
|
|
30
|
+
try:
|
|
31
|
+
parsed = datetime.fromisoformat(text)
|
|
32
|
+
except ValueError:
|
|
33
|
+
return None
|
|
34
|
+
if parsed.tzinfo is None:
|
|
35
|
+
parsed = parsed.replace(tzinfo=timezone.utc)
|
|
36
|
+
return int(parsed.timestamp() * 1000)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def human_run_duration_ms(message: Any, now_ms: int | None = None) -> int | None:
|
|
40
|
+
"""Milliseconds for this human turn. Uses now while still running."""
|
|
41
|
+
if message is None:
|
|
42
|
+
return None
|
|
43
|
+
kind = _kind(message)
|
|
44
|
+
if kind and kind not in {"human", "user"}:
|
|
45
|
+
return None
|
|
46
|
+
kwargs = _kwargs(message)
|
|
47
|
+
started = kwargs.get(RUN_STARTED_AT)
|
|
48
|
+
if not isinstance(started, str) or not started:
|
|
49
|
+
return None
|
|
50
|
+
started_ms = _parse_ms(started)
|
|
51
|
+
if started_ms is None:
|
|
52
|
+
return None
|
|
53
|
+
ended = kwargs.get(RUN_ENDED_AT)
|
|
54
|
+
if isinstance(ended, str) and ended:
|
|
55
|
+
ended_ms = _parse_ms(ended)
|
|
56
|
+
else:
|
|
57
|
+
ended_ms = (
|
|
58
|
+
now_ms
|
|
59
|
+
if now_ms is not None
|
|
60
|
+
else int(datetime.now(timezone.utc).timestamp() * 1000)
|
|
61
|
+
)
|
|
62
|
+
if ended_ms is None:
|
|
63
|
+
return None
|
|
64
|
+
duration = ended_ms - started_ms
|
|
65
|
+
return duration if duration >= 0 else None
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""MobileOPS event modes; full state remains available through get_state."""
|
|
2
|
+
DEFAULT_MODES = ("messages-tuple", "updates", "custom")
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def normalize_stream_mode(mode):
|
|
6
|
+
if mode is None or mode == [] or mode == ():
|
|
7
|
+
return list(DEFAULT_MODES)
|
|
8
|
+
if "values" in ([mode] if isinstance(mode, str) else mode):
|
|
9
|
+
raise ValueError("MobileOPS does not support the values stream mode. Use messages, updates and custom; call get_state() after streaming.")
|
|
10
|
+
return mode
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class RunsClient:
|
|
14
|
+
def __init__(self, native):
|
|
15
|
+
self._native = native
|
|
16
|
+
|
|
17
|
+
def __getattr__(self, name):
|
|
18
|
+
method = getattr(self._native, name)
|
|
19
|
+
if name == "create_batch":
|
|
20
|
+
def batch(payloads, **kwargs):
|
|
21
|
+
prepared = []
|
|
22
|
+
for payload in payloads:
|
|
23
|
+
mode = normalize_stream_mode(payload.get("stream_mode"))
|
|
24
|
+
prepared.append({**payload, "stream_mode": mode})
|
|
25
|
+
return method(prepared, **kwargs)
|
|
26
|
+
return batch
|
|
27
|
+
if name not in {"stream", "create", "join_stream"}:
|
|
28
|
+
return method
|
|
29
|
+
|
|
30
|
+
def call(*args, **kwargs):
|
|
31
|
+
modes = normalize_stream_mode(kwargs.get("stream_mode"))
|
|
32
|
+
return method(*args, **{**kwargs, "stream_mode": modes})
|
|
33
|
+
return call
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mobileops-managed-agent
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.1
|
|
4
4
|
Summary: Server-side SDK for the MobileOPS Managed Agent API.
|
|
5
5
|
Project-URL: Homepage, https://github.com/InnoMindX/deepagent/tree/main/managed-agent-sdk/python
|
|
6
6
|
Project-URL: Repository, https://github.com/InnoMindX/deepagent
|
|
@@ -76,3 +76,9 @@ await client.files.list(thread["thread_id"], "/workspace")
|
|
|
76
76
|
```
|
|
77
77
|
|
|
78
78
|
Keep MobileOPS Managed Agent API keys in server-side code only.
|
|
79
|
+
|
|
80
|
+
## Streaming in 0.4.0
|
|
81
|
+
|
|
82
|
+
Run streaming defaults to `messages-tuple`, `updates`, and `custom`. Explicit
|
|
83
|
+
`values` subscriptions raise `ValueError` before network access. Fetch full state
|
|
84
|
+
once with `client.agent.threads.get_state(thread_id)` after the stream ends.
|
|
@@ -13,8 +13,10 @@ src/mobileops_managed_agent/files.py
|
|
|
13
13
|
src/mobileops_managed_agent/model_retry.py
|
|
14
14
|
src/mobileops_managed_agent/resources.py
|
|
15
15
|
src/mobileops_managed_agent/response_schema.py
|
|
16
|
+
src/mobileops_managed_agent/run_timing.py
|
|
16
17
|
src/mobileops_managed_agent/sandbox_profile.py
|
|
17
18
|
src/mobileops_managed_agent/sandbox_profiles.py
|
|
19
|
+
src/mobileops_managed_agent/stream_policy.py
|
|
18
20
|
src/mobileops_managed_agent/tool_permissions.py
|
|
19
21
|
src/mobileops_managed_agent/vaults.py
|
|
20
22
|
src/mobileops_managed_agent.egg-info/PKG-INFO
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{mobileops_managed_agent-0.3.2 → mobileops_managed_agent-0.4.1}/src/mobileops_managed_agent/files.py
RENAMED
|
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
|