hopx-ai 0.1.15__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 hopx-ai might be problematic. Click here for more details.
- hopx_ai/__init__.py +114 -0
- hopx_ai/_agent_client.py +391 -0
- hopx_ai/_async_agent_client.py +223 -0
- hopx_ai/_async_cache.py +38 -0
- hopx_ai/_async_client.py +230 -0
- hopx_ai/_async_commands.py +58 -0
- hopx_ai/_async_env_vars.py +151 -0
- hopx_ai/_async_files.py +81 -0
- hopx_ai/_async_files_clean.py +489 -0
- hopx_ai/_async_terminal.py +184 -0
- hopx_ai/_client.py +230 -0
- hopx_ai/_generated/__init__.py +22 -0
- hopx_ai/_generated/models.py +502 -0
- hopx_ai/_temp_async_token.py +14 -0
- hopx_ai/_test_env_fix.py +30 -0
- hopx_ai/_utils.py +9 -0
- hopx_ai/_ws_client.py +141 -0
- hopx_ai/async_sandbox.py +763 -0
- hopx_ai/cache.py +97 -0
- hopx_ai/commands.py +174 -0
- hopx_ai/desktop.py +1227 -0
- hopx_ai/env_vars.py +244 -0
- hopx_ai/errors.py +249 -0
- hopx_ai/files.py +489 -0
- hopx_ai/models.py +274 -0
- hopx_ai/models_updated.py +270 -0
- hopx_ai/sandbox.py +1447 -0
- hopx_ai/template/__init__.py +47 -0
- hopx_ai/template/build_flow.py +540 -0
- hopx_ai/template/builder.py +300 -0
- hopx_ai/template/file_hasher.py +81 -0
- hopx_ai/template/ready_checks.py +106 -0
- hopx_ai/template/tar_creator.py +122 -0
- hopx_ai/template/types.py +199 -0
- hopx_ai/terminal.py +164 -0
- hopx_ai-0.1.15.dist-info/METADATA +462 -0
- hopx_ai-0.1.15.dist-info/RECORD +38 -0
- hopx_ai-0.1.15.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"""Async environment variables for sandboxes."""
|
|
2
|
+
|
|
3
|
+
from typing import Dict, Optional
|
|
4
|
+
import logging
|
|
5
|
+
from ._async_agent_client import AsyncAgentHTTPClient
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AsyncEnvironmentVariables:
|
|
11
|
+
"""
|
|
12
|
+
Async environment variable operations.
|
|
13
|
+
|
|
14
|
+
Provides methods for managing environment variables inside the sandbox at runtime.
|
|
15
|
+
|
|
16
|
+
Features:
|
|
17
|
+
- Get all environment variables
|
|
18
|
+
- Set/replace all environment variables
|
|
19
|
+
- Update specific environment variables (merge)
|
|
20
|
+
- Delete individual environment variables
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def __init__(self, sandbox):
|
|
24
|
+
"""Initialize with sandbox reference."""
|
|
25
|
+
self._sandbox = sandbox
|
|
26
|
+
logger.debug("AsyncEnvironmentVariables initialized")
|
|
27
|
+
|
|
28
|
+
async def _get_client(self) -> AsyncAgentHTTPClient:
|
|
29
|
+
"""Get agent client from sandbox."""
|
|
30
|
+
await self._sandbox._ensure_agent_client()
|
|
31
|
+
return self._sandbox._agent_client
|
|
32
|
+
|
|
33
|
+
async def get_all(self, *, timeout: Optional[int] = None) -> Dict[str, str]:
|
|
34
|
+
"""
|
|
35
|
+
Get all environment variables.
|
|
36
|
+
|
|
37
|
+
Args:
|
|
38
|
+
timeout: Request timeout in seconds (overrides default)
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
Dictionary of environment variables
|
|
42
|
+
"""
|
|
43
|
+
logger.debug("Getting all environment variables")
|
|
44
|
+
|
|
45
|
+
client = await self._get_client()
|
|
46
|
+
response = await client.get(
|
|
47
|
+
"/env",
|
|
48
|
+
operation="get environment variables"
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
return response.get("env_vars", {})
|
|
52
|
+
|
|
53
|
+
async def set_all(
|
|
54
|
+
self,
|
|
55
|
+
env_vars: Dict[str, str],
|
|
56
|
+
*,
|
|
57
|
+
timeout: Optional[int] = None
|
|
58
|
+
) -> Dict[str, str]:
|
|
59
|
+
"""
|
|
60
|
+
Set/replace all environment variables.
|
|
61
|
+
|
|
62
|
+
This replaces ALL existing environment variables with the provided ones.
|
|
63
|
+
Use update() if you want to merge instead.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
env_vars: Dictionary of environment variables to set
|
|
67
|
+
timeout: Request timeout in seconds
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
Updated dictionary of all environment variables
|
|
71
|
+
"""
|
|
72
|
+
logger.debug(f"Setting {len(env_vars)} environment variables (replace all)")
|
|
73
|
+
|
|
74
|
+
client = await self._get_client()
|
|
75
|
+
response = await client.put(
|
|
76
|
+
"/env",
|
|
77
|
+
json={"env_vars": env_vars},
|
|
78
|
+
operation="set environment variables"
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
return response.get("env_vars", env_vars)
|
|
82
|
+
|
|
83
|
+
async def update(
|
|
84
|
+
self,
|
|
85
|
+
env_vars: Dict[str, str],
|
|
86
|
+
*,
|
|
87
|
+
timeout: Optional[int] = None
|
|
88
|
+
) -> Dict[str, str]:
|
|
89
|
+
"""
|
|
90
|
+
Update specific environment variables (merge).
|
|
91
|
+
|
|
92
|
+
This merges the provided variables with existing ones.
|
|
93
|
+
Existing variables not specified are preserved.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
env_vars: Dictionary of environment variables to update/add
|
|
97
|
+
timeout: Request timeout in seconds
|
|
98
|
+
|
|
99
|
+
Returns:
|
|
100
|
+
Updated dictionary of all environment variables
|
|
101
|
+
"""
|
|
102
|
+
logger.debug(f"Updating {len(env_vars)} environment variables (merge)")
|
|
103
|
+
|
|
104
|
+
client = await self._get_client()
|
|
105
|
+
response = await client.patch(
|
|
106
|
+
"/env",
|
|
107
|
+
json={"env_vars": env_vars, "merge": True}, # ✅ FIXED: add merge flag
|
|
108
|
+
operation="update environment variables"
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
# Agent returns 204 No Content - get updated vars
|
|
112
|
+
if not response or not response.get("env_vars"):
|
|
113
|
+
return await self.get_all()
|
|
114
|
+
|
|
115
|
+
return response.get("env_vars", {})
|
|
116
|
+
|
|
117
|
+
async def delete(self, name: str, *, timeout: Optional[int] = None) -> None:
|
|
118
|
+
"""
|
|
119
|
+
Delete a specific environment variable.
|
|
120
|
+
|
|
121
|
+
Note: Agent's DELETE /env clears ALL custom variables.
|
|
122
|
+
We work around this by re-setting all vars except the one to delete.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
name: Variable name to delete
|
|
126
|
+
timeout: Request timeout in seconds
|
|
127
|
+
"""
|
|
128
|
+
logger.debug(f"Deleting environment variable: {name}")
|
|
129
|
+
|
|
130
|
+
# Get all current env vars
|
|
131
|
+
current_vars = await self.get_all()
|
|
132
|
+
|
|
133
|
+
# Remove the specified variable
|
|
134
|
+
if name in current_vars:
|
|
135
|
+
del current_vars[name]
|
|
136
|
+
# Re-set all env vars without the deleted one
|
|
137
|
+
await self.set_all(current_vars)
|
|
138
|
+
logger.debug(f"Environment variable {name} deleted")
|
|
139
|
+
else:
|
|
140
|
+
logger.debug(f"Environment variable {name} not found (already deleted)")
|
|
141
|
+
|
|
142
|
+
# Convenience methods (aliases)
|
|
143
|
+
|
|
144
|
+
async def get(self, name: str) -> Optional[str]:
|
|
145
|
+
"""Get a single environment variable value."""
|
|
146
|
+
all_vars = await self.get_all()
|
|
147
|
+
return all_vars.get(name)
|
|
148
|
+
|
|
149
|
+
async def set(self, name: str, value: str) -> None:
|
|
150
|
+
"""Set a single environment variable (convenience method)."""
|
|
151
|
+
await self.update({name: value})
|
hopx_ai/_async_files.py
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""Async file operations for sandboxes."""
|
|
2
|
+
|
|
3
|
+
from typing import Optional, List, Dict, Any, AsyncIterator
|
|
4
|
+
import logging
|
|
5
|
+
from ._async_agent_client import AsyncAgentHTTPClient
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger(__name__)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class AsyncFiles:
|
|
11
|
+
"""Async file operations for sandboxes."""
|
|
12
|
+
|
|
13
|
+
def __init__(self, sandbox):
|
|
14
|
+
"""Initialize with sandbox reference."""
|
|
15
|
+
self._sandbox = sandbox
|
|
16
|
+
logger.debug("AsyncFiles initialized")
|
|
17
|
+
|
|
18
|
+
async def _get_client(self) -> AsyncAgentHTTPClient:
|
|
19
|
+
"""Get agent client from sandbox."""
|
|
20
|
+
await self._sandbox._ensure_agent_client()
|
|
21
|
+
return self._sandbox._agent_client
|
|
22
|
+
|
|
23
|
+
async def write(self, path: str, content: str) -> None:
|
|
24
|
+
"""Write content to file."""
|
|
25
|
+
client = await self._get_client()
|
|
26
|
+
await client.post(
|
|
27
|
+
"/files/write",
|
|
28
|
+
json={"path": path, "content": content},
|
|
29
|
+
operation="write file",
|
|
30
|
+
context={"path": path}
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
async def read(self, path: str) -> str:
|
|
34
|
+
"""Read file content."""
|
|
35
|
+
client = await self._get_client()
|
|
36
|
+
response = await client.get(
|
|
37
|
+
f"/files/read?path={path}",
|
|
38
|
+
operation="read file",
|
|
39
|
+
context={"path": path}
|
|
40
|
+
)
|
|
41
|
+
return response.get("content", "")
|
|
42
|
+
|
|
43
|
+
async def list(self, path: str = "/") -> List[Dict[str, Any]]:
|
|
44
|
+
"""List files in directory."""
|
|
45
|
+
client = await self._get_client()
|
|
46
|
+
response = await client.get(
|
|
47
|
+
f"/files/list?path={path}",
|
|
48
|
+
operation="list files",
|
|
49
|
+
context={"path": path}
|
|
50
|
+
)
|
|
51
|
+
return response.get("files", [])
|
|
52
|
+
|
|
53
|
+
async def exists(self, path: str) -> bool:
|
|
54
|
+
"""Check if file exists."""
|
|
55
|
+
client = await self._get_client()
|
|
56
|
+
response = await client.get(
|
|
57
|
+
f"/files/exists?path={path}",
|
|
58
|
+
operation="check file exists",
|
|
59
|
+
context={"path": path}
|
|
60
|
+
)
|
|
61
|
+
return response.get("exists", False)
|
|
62
|
+
|
|
63
|
+
async def mkdir(self, path: str, parents: bool = True) -> None:
|
|
64
|
+
"""Create directory."""
|
|
65
|
+
client = await self._get_client()
|
|
66
|
+
await client.post(
|
|
67
|
+
"/files/mkdir",
|
|
68
|
+
json={"path": path, "parents": parents},
|
|
69
|
+
operation="create directory",
|
|
70
|
+
context={"path": path}
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
async def remove(self, path: str, recursive: bool = False) -> None:
|
|
74
|
+
"""Remove file or directory."""
|
|
75
|
+
client = await self._get_client()
|
|
76
|
+
await client.post(
|
|
77
|
+
"/files/remove",
|
|
78
|
+
json={"path": path, "recursive": recursive},
|
|
79
|
+
operation="remove file",
|
|
80
|
+
context={"path": path}
|
|
81
|
+
)
|