cloudcruise 0.0.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.
@@ -0,0 +1,114 @@
1
+ from .cloudcruise import CloudCruise, CloudCruiseParams
2
+
3
+ from .vault.types import (
4
+ VaultEntry,
5
+ GetVaultEntriesFilters,
6
+ ProxyConfig,
7
+ VaultPostPutHeadersInBody,
8
+ )
9
+
10
+ from .workflows.types import (
11
+ Workflow,
12
+ WorkflowInputSchema,
13
+ WorkflowMetadata,
14
+ InputValidationError,
15
+ )
16
+
17
+ from .runs.types import (
18
+ EventType,
19
+ DryRun,
20
+ Metadata,
21
+ RunSpecificWebhook,
22
+ PayloadWebhook,
23
+ StartRunRequest,
24
+ StartRunResponse,
25
+ UserInteractionData,
26
+ VideoUrl,
27
+ FileUrl,
28
+ ScreenshotUrl,
29
+ RunError,
30
+ RunResult,
31
+ WebhookEvent,
32
+ WebhookReplayResponse,
33
+ RunHandle,
34
+ RunStreamOptions,
35
+ SseEventName,
36
+ SseMessage,
37
+ RunEventEnvelope,
38
+ # Event payload types
39
+ ExecutionQueuedPayload,
40
+ ExecutionStartPayload,
41
+ ExecutionStepPayload,
42
+ InteractionWaitingPayload,
43
+ InteractionFinishedPayload,
44
+ AgentErrorAnalysisPayload,
45
+ ExecutionRequeuedPayload,
46
+ EndRunPayload,
47
+ EndRunError,
48
+ ExecutionStoppedEarlyPayload,
49
+ FileUploadedPayload,
50
+ ScreenshotUploadedPayload,
51
+ EventWebhookMessage,
52
+ RunEventMessage,
53
+ )
54
+
55
+ from .webhook.types import WebhookPayload, WebhookVerificationOptions, VerificationError, WebhookMessage
56
+ from ._default import get_client as client
57
+
58
+ __all__ = [
59
+ "CloudCruise",
60
+ "CloudCruiseParams",
61
+ # Default client helper
62
+ "client",
63
+ # Vault Types
64
+ "VaultEntry",
65
+ "GetVaultEntriesFilters",
66
+ "ProxyConfig",
67
+ "VaultPostPutHeadersInBody",
68
+ # Workflow Types
69
+ "Workflow",
70
+ "WorkflowInputSchema",
71
+ "WorkflowMetadata",
72
+ "InputValidationError",
73
+ # Run Types
74
+ "EventType",
75
+ "DryRun",
76
+ "Metadata",
77
+ "RunSpecificWebhook",
78
+ "PayloadWebhook",
79
+ "StartRunRequest",
80
+ "StartRunResponse",
81
+ "UserInteractionData",
82
+ "VideoUrl",
83
+ "FileUrl",
84
+ "ScreenshotUrl",
85
+ "RunError",
86
+ "RunResult",
87
+ "WebhookEvent",
88
+ "WebhookReplayResponse",
89
+ "RunHandle",
90
+ "RunStreamOptions",
91
+ "SseEventName",
92
+ "SseMessage",
93
+ "RunEventEnvelope",
94
+ # Event Payload Types
95
+ "ExecutionQueuedPayload",
96
+ "ExecutionStartPayload",
97
+ "ExecutionStepPayload",
98
+ "InteractionWaitingPayload",
99
+ "InteractionFinishedPayload",
100
+ "AgentErrorAnalysisPayload",
101
+ "ExecutionRequeuedPayload",
102
+ "EndRunPayload",
103
+ "EndRunError",
104
+ "ExecutionStoppedEarlyPayload",
105
+ "FileUploadedPayload",
106
+ "ScreenshotUploadedPayload",
107
+ "EventWebhookMessage",
108
+ "RunEventMessage",
109
+ # Webhook Types
110
+ "WebhookPayload",
111
+ "WebhookVerificationOptions",
112
+ "VerificationError",
113
+ "WebhookMessage",
114
+ ]
@@ -0,0 +1,31 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Optional
4
+
5
+ from .cloudcruise import CloudCruise, CloudCruiseParams
6
+
7
+ _default_client: Optional[CloudCruise] = None
8
+
9
+
10
+ def get_client(
11
+ params: Optional[CloudCruiseParams] = None,
12
+ *,
13
+ api_key: Optional[str] = None,
14
+ encryption_key: Optional[str] = None,
15
+ base_url: Optional[str] = None,
16
+ ) -> CloudCruise:
17
+ """Return the shared default CloudCruise client.
18
+
19
+ You can configure it by passing a CloudCruiseParams instance or via
20
+ keyword args (api_key, encryption_key, base_url). Passing any params or
21
+ keyword args replaces the cached client.
22
+ """
23
+ global _default_client
24
+
25
+ effective_params = params
26
+ if effective_params is None and (api_key is not None or encryption_key is not None or base_url is not None):
27
+ effective_params = CloudCruiseParams(api_key=api_key, encryption_key=encryption_key, base_url=base_url)
28
+
29
+ if effective_params is not None or _default_client is None:
30
+ _default_client = CloudCruise(effective_params)
31
+ return _default_client
@@ -0,0 +1,96 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from typing import Any, Optional
5
+ import json
6
+ import requests
7
+
8
+ from .utils.env import get_env
9
+ from .vault.client import VaultClient
10
+ from .workflows.client import WorkflowsClient
11
+ from .runs.client import RunsClient
12
+ from .webhook.client import WebhookClient
13
+ from .utils.connection_manager import ConnectionManager
14
+
15
+ @dataclass
16
+ class CloudCruiseParams:
17
+ api_key: Optional[str] = None
18
+ base_url: Optional[str] = None
19
+ encryption_key: Optional[str] = None
20
+
21
+
22
+ class CloudCruise:
23
+ """
24
+ CloudCruise Python SDK
25
+ Official client library for the CloudCruise Platform
26
+ """
27
+
28
+ # Expose typed attributes for IDE autocomplete
29
+ vault: VaultClient
30
+ workflows: WorkflowsClient
31
+ runs: RunsClient
32
+ webhook: WebhookClient
33
+
34
+ def __init__(self, params: Optional[CloudCruiseParams] = None) -> None:
35
+ params = params or CloudCruiseParams()
36
+ api_key = params.api_key or get_env("CLOUDCRUISE_API_KEY")
37
+ base_url = params.base_url or get_env("CLOUDCRUISE_BASE_URL") or "https://api.cloudcruise.com"
38
+ encryption_key = params.encryption_key or get_env("CLOUDCRUISE_ENCRYPTION_KEY")
39
+
40
+ if not api_key:
41
+ raise ValueError("Missing apiKey. Provide via params.api_key or CLOUDCRUISE_API_KEY env var.")
42
+ if not encryption_key:
43
+ raise ValueError(
44
+ "Missing encryptionKey. Provide via params.encryption_key or CLOUDCRUISE_ENCRYPTION_KEY env var."
45
+ )
46
+
47
+ self._api_key = api_key
48
+ self._base_url = base_url.rstrip("/")
49
+ self._encryption_key = encryption_key
50
+
51
+ # Initialize namespace clients
52
+ self._connection_manager = ConnectionManager(self._base_url, self._api_key)
53
+ self.vault = VaultClient(self._make_request, self._encryption_key)
54
+ self.workflows = WorkflowsClient(self._make_request)
55
+ self.runs = RunsClient(self._connection_manager, self._make_request, self.workflows)
56
+ self.webhook = WebhookClient()
57
+
58
+ def _make_request(self, method: str, path: str, body: Optional[Any] = None) -> Any:
59
+ """
60
+ Makes an HTTP request to the CloudCruise API
61
+ Automatically adds the cc-key header for authentication
62
+ """
63
+ url = f"{self._base_url}{path}"
64
+ headers = {
65
+ "cc-key": self._api_key,
66
+ }
67
+ try:
68
+ # Only send Content-Type when we have a JSON body
69
+ if body is not None:
70
+ headers["Content-Type"] = "application/json"
71
+
72
+ resp = requests.request(
73
+ method=method,
74
+ url=url,
75
+ headers=headers,
76
+ data=(json.dumps(body) if body is not None else None),
77
+ timeout=60,
78
+ )
79
+ if not resp.ok:
80
+ error_text = resp.text
81
+ error_message = f"HTTP {resp.status_code}: {resp.reason}"
82
+ try:
83
+ error_json = resp.json()
84
+ error_message = error_json.get("message") or error_json.get("error") or error_message
85
+ except Exception:
86
+ pass
87
+ raise RuntimeError(error_message)
88
+
89
+ ctype = resp.headers.get("content-type", "")
90
+ if "application/json" in ctype:
91
+ return resp.json()
92
+
93
+ else:
94
+ return resp.text
95
+ except Exception as e:
96
+ raise e
@@ -0,0 +1,43 @@
1
+ from __future__ import annotations
2
+
3
+ from .types import (
4
+ ExecutionQueuedPayload,
5
+ ExecutionStartPayload,
6
+ ExecutionStepPayload,
7
+ InteractionWaitingPayload,
8
+ InteractionFinishedPayload,
9
+ InteractionFinishedPayloadVariant1,
10
+ InteractionFinishedPayloadVariant2,
11
+ AgentErrorAnalysisPayload,
12
+ ExecutionRequeuedPayload,
13
+ EndRunPayload,
14
+ EndRunError,
15
+ ExecutionStoppedEarlyPayload,
16
+ FileUploadedPayload,
17
+ ScreenshotUploadedPayload,
18
+ WebhookMessage,
19
+ RunEventMessage,
20
+ RunEventMessageData,
21
+ )
22
+
23
+ __all__ = [
24
+ # Event payload types
25
+ "ExecutionQueuedPayload",
26
+ "ExecutionStartPayload",
27
+ "ExecutionStepPayload",
28
+ "InteractionWaitingPayload",
29
+ "InteractionFinishedPayload",
30
+ "InteractionFinishedPayloadVariant1",
31
+ "InteractionFinishedPayloadVariant2",
32
+ "AgentErrorAnalysisPayload",
33
+ "ExecutionRequeuedPayload",
34
+ "EndRunPayload",
35
+ "EndRunError",
36
+ "ExecutionStoppedEarlyPayload",
37
+ "FileUploadedPayload",
38
+ "ScreenshotUploadedPayload",
39
+ # Generic message types
40
+ "WebhookMessage",
41
+ "RunEventMessage",
42
+ "RunEventMessageData",
43
+ ]
@@ -0,0 +1,151 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Any, Dict, Generic, List, Literal, TypeVar, TypedDict, Union
4
+
5
+ # Re-use EventType from runs.types to avoid circular imports
6
+ # We'll import it later after updating runs/types.py
7
+
8
+ # Event Payload TypedDicts
9
+ class ExecutionQueuedPayload(TypedDict):
10
+ session_id: str
11
+ workflow_id: str
12
+
13
+
14
+ class ExecutionStartPayload(TypedDict, total=False):
15
+ session_id: str
16
+ workflow_id: str
17
+ live_view_url: str # optional
18
+
19
+
20
+ class ExecutionStepPayload(TypedDict):
21
+ session_id: str
22
+ workflow_id: str
23
+ current_step: str
24
+ next_step: str
25
+
26
+
27
+ class InteractionWaitingPayload(TypedDict):
28
+ session_id: str
29
+ workflow_id: str
30
+ current_step: str
31
+ missing_properties: List[str]
32
+ expected_json_schema_datamodel: Dict[str, Any]
33
+ message: str
34
+
35
+
36
+ # InteractionFinishedPayload has two possible shapes
37
+ class InteractionFinishedPayloadVariant1(TypedDict):
38
+ session_id: str
39
+ workflow_id: str
40
+ current_step: str
41
+ missing_properties: List[str] # empty list in this variant
42
+ expected_json_schema_datamodel: Dict[str, Any]
43
+ message: str
44
+
45
+
46
+ class InteractionFinishedPayloadVariant2(TypedDict, total=False):
47
+ session_id: str
48
+ workflow_id: str
49
+ provided_input: Any
50
+ message: str # optional
51
+ expected_json_schema_datamodel: Dict[str, Any]
52
+
53
+
54
+ InteractionFinishedPayload = Union[
55
+ InteractionFinishedPayloadVariant1,
56
+ InteractionFinishedPayloadVariant2
57
+ ]
58
+
59
+
60
+ class AgentErrorAnalysisPayload(TypedDict, total=False):
61
+ analysis_step_name: str
62
+ ai_analysis: str # optional
63
+ root_cause_analysis: str # optional
64
+ error_category: str # optional
65
+
66
+
67
+ class ExecutionRequeuedPayload(TypedDict, total=False):
68
+ session_id: str
69
+ workflow_id: str
70
+ retry_attempt: int
71
+ max_retries: int # optional
72
+ next_execution_time: str
73
+ delay_ms: int
74
+
75
+
76
+ class EndRunError(TypedDict, total=False):
77
+ message: str
78
+ error_id: str
79
+ full_url: str # optional
80
+ created_at: str
81
+ error_code: str # optional
82
+ action_type: str # optional
83
+ action_display_name: str # optional
84
+ llm_error_category: str # optional
85
+
86
+
87
+ class EndRunPayload(TypedDict, total=False):
88
+ session_id: str
89
+ workflow_id: str
90
+ data: Any
91
+ input_variables: Dict[str, Any]
92
+ errors: List[EndRunError]
93
+ status: Literal["execution.success", "execution.failed", "execution.stopped"]
94
+ encrypted_variables: Union[List[str], None]
95
+ file_urls: Union[List[Any], None]
96
+
97
+
98
+ class ExecutionStoppedEarlyPayload(TypedDict):
99
+ message: str
100
+ error_code: str
101
+ session_id: str
102
+
103
+
104
+ class FileUploadedPayload(TypedDict):
105
+ signed_file_url: str
106
+ file_name: str
107
+ timestamp: str
108
+ signed_file_url_expires: str
109
+ metadata: Dict[str, Any]
110
+ session_id: str
111
+
112
+
113
+ class ScreenshotUploadedPayload(TypedDict):
114
+ screenshot_id: str
115
+ signed_screenshot_url: str
116
+ node_display_name: str
117
+ node_id: str
118
+ timestamp: str
119
+ signed_screenshot_url_expires: str
120
+ error_screenshot: bool
121
+ retry_index: int
122
+ full_length_screenshot: bool
123
+ session_id: str
124
+
125
+
126
+ # Type variable for generic webhook messages
127
+ E = TypeVar('E', bound=str)
128
+
129
+
130
+ # Generic Webhook Message type
131
+ class WebhookMessage(TypedDict, Generic[E], total=False):
132
+ event: E
133
+ timestamp: int
134
+ expires_at: int
135
+ payload: Any # Will be typed more specifically with EventPayloadMap
136
+ metadata: Dict[str, Any] # optional
137
+
138
+
139
+ # Generic SSE Run Event Message type
140
+ class RunEventMessageData(TypedDict, Generic[E]):
141
+ event: E
142
+ payload: Any
143
+ timestamp: int
144
+ expires_at: int
145
+
146
+
147
+ class RunEventMessage(TypedDict, Generic[E]):
148
+ event: Literal["run.event"]
149
+ data: RunEventMessageData[E]
150
+ timestamp: str
151
+ expires_at: str
cloudcruise/py.typed ADDED
File without changes
@@ -0,0 +1,64 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Optional
4
+
5
+ from .types import * # re-export types for convenience
6
+
7
+ def _client():
8
+ # Lazy import to avoid circular imports during package initialization
9
+ from .._default import get_client as _get_client
10
+ return _get_client()
11
+
12
+ __all__ = [
13
+ "EventType",
14
+ "DryRun",
15
+ "Metadata",
16
+ "RunSpecificWebhook",
17
+ "PayloadWebhook",
18
+ "StartRunRequest",
19
+ "StartRunResponse",
20
+ "UserInteractionData",
21
+ "VideoUrl",
22
+ "FileUrl",
23
+ "ScreenshotUrl",
24
+ "RunError",
25
+ "RunResult",
26
+ "WebhookEvent",
27
+ "WebhookReplayResponse",
28
+ "RunHandle",
29
+ "RunStreamOptions",
30
+ "SseEventName",
31
+ "SseMessage",
32
+ "RunEventEnvelope",
33
+ # Convenience APIs
34
+ "start",
35
+ "subscribe_to_session",
36
+ "submit_user_interaction",
37
+ "get_results",
38
+ "interrupt",
39
+ "replay_webhooks",
40
+ ]
41
+
42
+
43
+ def start(request: StartRunRequest, options: Optional[RunStreamOptions] = None) -> RunHandle:
44
+ return _client().runs.start(request, options)
45
+
46
+
47
+ def subscribe_to_session(session_id: str, options: Optional[RunStreamOptions] = None) -> RunHandle:
48
+ return _client().runs.subscribe_to_session(session_id, options)
49
+
50
+
51
+ def submit_user_interaction(session_id: str, data: UserInteractionData) -> None:
52
+ return _client().runs.submit_user_interaction(session_id, data)
53
+
54
+
55
+ def get_results(session_id: str) -> RunResult:
56
+ return _client().runs.get_results(session_id)
57
+
58
+
59
+ def interrupt(session_id: str) -> None:
60
+ return _client().runs.interrupt(session_id)
61
+
62
+
63
+ def replay_webhooks(session_id: str) -> WebhookReplayResponse:
64
+ return _client().runs.replay_webhooks(session_id)