xenfra-sdk 0.1.7__tar.gz → 0.1.9__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.
Files changed (31) hide show
  1. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/PKG-INFO +1 -1
  2. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/pyproject.toml +1 -1
  3. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/engine.py +1 -1
  4. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/resources/deployments.py +33 -6
  5. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/README.md +0 -0
  6. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/__init__.py +0 -0
  7. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/cli/__init__.py +0 -0
  8. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/cli/main.py +0 -0
  9. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/client.py +0 -0
  10. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/client_with_hooks.py +0 -0
  11. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/config.py +0 -0
  12. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/db/__init__.py +0 -0
  13. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/db/models.py +0 -0
  14. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/db/session.py +0 -0
  15. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/dependencies.py +0 -0
  16. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/dockerizer.py +0 -0
  17. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/exceptions.py +0 -0
  18. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/mcp_client.py +0 -0
  19. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/models.py +0 -0
  20. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/patterns.json +0 -0
  21. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/privacy.py +0 -0
  22. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/recipes.py +0 -0
  23. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/resources/__init__.py +0 -0
  24. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/resources/base.py +0 -0
  25. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/resources/intelligence.py +0 -0
  26. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/resources/projects.py +0 -0
  27. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/security.py +0 -0
  28. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/templates/Dockerfile.j2 +0 -0
  29. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/templates/cloud-init.sh.j2 +0 -0
  30. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/templates/docker-compose.yml.j2 +0 -0
  31. {xenfra_sdk-0.1.7 → xenfra_sdk-0.1.9}/src/xenfra_sdk/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: xenfra-sdk
3
- Version: 0.1.7
3
+ Version: 0.1.9
4
4
  Summary: Xenfra SDK: Core engine and utilities for the Xenfra platform.
5
5
  Author: xenfra-cloud
6
6
  Author-email: xenfra-cloud <xenfracloud@gmail.com>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "xenfra-sdk"
3
- version = "0.1.7"
3
+ version = "0.1.9"
4
4
  description = "Xenfra SDK: Core engine and utilities for the Xenfra platform."
5
5
  readme = "README.md"
6
6
  authors = [
@@ -324,7 +324,7 @@ class InfraEngine:
324
324
  raise DeploymentError("Could not establish SSH connection.", stage="Polling")
325
325
 
326
326
  with conn:
327
- for i in range(30): # 5-minute timeout for cloud-init
327
+ for i in range(120): # 20-minute timeout for cloud-init (installing Docker, Caddy, etc.)
328
328
  if conn.run("test -f /root/setup_complete", warn=True).ok:
329
329
  logger(" - Cloud-init setup complete.")
330
330
  break
@@ -133,6 +133,7 @@ class DeploymentsManager(BaseManager):
133
133
  try:
134
134
  # Use httpx to stream the SSE response
135
135
  import httpx
136
+ import os
136
137
 
137
138
  headers = {
138
139
  "Authorization": f"Bearer {self._client._token}",
@@ -140,7 +141,19 @@ class DeploymentsManager(BaseManager):
140
141
  "Content-Type": "application/json",
141
142
  }
142
143
 
143
- url = f"{self._client.api_url}/deployments/stream"
144
+ # Use streaming API URL if available (bypasses Cloudflare timeout)
145
+ # Otherwise fall back to regular API URL
146
+ streaming_api_url = os.getenv("XENFRA_STREAMING_API_URL")
147
+ if streaming_api_url:
148
+ base_url = streaming_api_url
149
+ elif self._client.api_url == "https://api.xenfra.tech":
150
+ # Production: use non-proxied streaming subdomain
151
+ base_url = "https://stream.xenfra.tech"
152
+ else:
153
+ # Local/dev: use regular API URL
154
+ base_url = self._client.api_url
155
+
156
+ url = f"{base_url}/deployments/stream"
144
157
 
145
158
  with httpx.stream(
146
159
  "POST",
@@ -169,7 +182,13 @@ class DeploymentsManager(BaseManager):
169
182
  )
170
183
 
171
184
  # Parse SSE events
185
+ current_event = None # Initialize before loop
172
186
  for line in response.iter_lines():
187
+ # No need to explicitly decode if iter_lines is used on a decoded response,
188
+ # but if it returns bytes, we decode it.
189
+ if isinstance(line, bytes):
190
+ line = line.decode('utf-8', errors='ignore')
191
+
173
192
  line = line.strip()
174
193
  if not line:
175
194
  continue
@@ -179,17 +198,25 @@ class DeploymentsManager(BaseManager):
179
198
  current_event = line[6:].strip()
180
199
  elif line.startswith("data:"):
181
200
  data = line[5:].strip()
201
+
202
+ # Get event type (default to "message" if no event line was sent)
203
+ event_type = current_event if current_event is not None else "message"
204
+
205
+ # Skip keep-alive events (used to prevent proxy timeouts)
206
+ if event_type == "keep-alive":
207
+ current_event = None
208
+ continue
209
+
182
210
  try:
183
211
  # Try to parse as JSON
184
212
  data_parsed = json.loads(data)
185
- yield {"event": current_event if 'current_event' in locals() else "message", "data": data_parsed}
213
+ yield {"event": event_type, "data": data_parsed}
186
214
  except json.JSONDecodeError:
187
215
  # If not JSON, yield as plain text
188
- yield {"event": current_event if 'current_event' in locals() else "message", "data": data}
216
+ yield {"event": event_type, "data": data}
189
217
 
190
- # Reset current_event
191
- if 'current_event' in locals():
192
- del current_event
218
+ # Reset current_event after yielding
219
+ current_event = None
193
220
 
194
221
  except httpx.HTTPError as e:
195
222
  raise XenfraError(f"HTTP error during streaming deployment: {e}")
File without changes