celesto 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.
- celesto/__init__.py +7 -0
- celesto/a2a.py +127 -0
- celesto/deployment.py +244 -0
- celesto/main.py +34 -0
- celesto/proxy.py +18 -0
- celesto/sdk/__init__.py +44 -0
- celesto/sdk/client.py +672 -0
- celesto/sdk/exceptions.py +143 -0
- celesto/sdk/types.py +117 -0
- celesto-0.0.1.dist-info/METADATA +54 -0
- celesto-0.0.1.dist-info/RECORD +14 -0
- celesto-0.0.1.dist-info/WHEEL +4 -0
- celesto-0.0.1.dist-info/entry_points.txt +2 -0
- celesto-0.0.1.dist-info/licenses/LICENSE +201 -0
celesto/__init__.py
ADDED
celesto/a2a.py
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
from typing import Tuple
|
|
5
|
+
from uuid import uuid4
|
|
6
|
+
|
|
7
|
+
import httpx
|
|
8
|
+
import typer
|
|
9
|
+
from a2a.client import Client, ClientConfig, ClientFactory
|
|
10
|
+
from a2a.types import Message, TextPart
|
|
11
|
+
from rich.console import Console
|
|
12
|
+
|
|
13
|
+
app = typer.Typer()
|
|
14
|
+
console = Console()
|
|
15
|
+
DEFAULT_TIMEOUT_SECONDS = 120.0
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
async def _connect_client(
|
|
19
|
+
agent: str, timeout: float
|
|
20
|
+
) -> Tuple[Client, httpx.AsyncClient]:
|
|
21
|
+
"""
|
|
22
|
+
Connect to the remote agent with a ClientConfig that uses an httpx timeout.
|
|
23
|
+
Returns the client and the httpx.AsyncClient to close after the call completes.
|
|
24
|
+
"""
|
|
25
|
+
http_client = httpx.AsyncClient(timeout=timeout)
|
|
26
|
+
client_config = ClientConfig(httpx_client=http_client)
|
|
27
|
+
|
|
28
|
+
try:
|
|
29
|
+
client = await ClientFactory.connect(agent=agent, client_config=client_config)
|
|
30
|
+
return client, http_client
|
|
31
|
+
except Exception: # noqa: BLE001
|
|
32
|
+
await http_client.aclose()
|
|
33
|
+
raise
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
async def _get_card(agent: str, timeout: float):
|
|
37
|
+
client, http_client = await _connect_client(agent, timeout)
|
|
38
|
+
try:
|
|
39
|
+
card = await client.get_card()
|
|
40
|
+
console.print(card.model_dump(mode="json"))
|
|
41
|
+
finally:
|
|
42
|
+
await http_client.aclose()
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@app.command()
|
|
46
|
+
def get_card(
|
|
47
|
+
agent: str = typer.Option(
|
|
48
|
+
"http://localhost:8000", help="The URL of the agent to connect to"
|
|
49
|
+
),
|
|
50
|
+
timeout: float = typer.Option(
|
|
51
|
+
DEFAULT_TIMEOUT_SECONDS,
|
|
52
|
+
help="Timeout in seconds for connecting to the agent",
|
|
53
|
+
),
|
|
54
|
+
):
|
|
55
|
+
if timeout <= 0:
|
|
56
|
+
raise typer.BadParameter(
|
|
57
|
+
"Timeout must be greater than zero.", param_name="timeout"
|
|
58
|
+
)
|
|
59
|
+
asyncio.run(_get_card(agent, timeout))
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
async def _send_message(agent: str, input: str, timeout: float):
|
|
63
|
+
import sys
|
|
64
|
+
import traceback
|
|
65
|
+
|
|
66
|
+
http_client = None
|
|
67
|
+
try:
|
|
68
|
+
client, http_client = await _connect_client(agent, timeout)
|
|
69
|
+
|
|
70
|
+
message = Message(
|
|
71
|
+
role="user",
|
|
72
|
+
parts=[TextPart(text=input)],
|
|
73
|
+
message_id=str(uuid4()),
|
|
74
|
+
task_id=str(uuid4()),
|
|
75
|
+
context_id=str(uuid4()),
|
|
76
|
+
)
|
|
77
|
+
response_stream = client.send_message(message)
|
|
78
|
+
|
|
79
|
+
async for event in response_stream:
|
|
80
|
+
try:
|
|
81
|
+
if isinstance(event, Message):
|
|
82
|
+
console.print("[bold green]Response:[/bold green]")
|
|
83
|
+
for part in event.parts:
|
|
84
|
+
if hasattr(part.root, "text"):
|
|
85
|
+
console.print(part.root.text)
|
|
86
|
+
else:
|
|
87
|
+
task, update = event
|
|
88
|
+
if update is not None:
|
|
89
|
+
if hasattr(update, "artifact") and update.artifact:
|
|
90
|
+
for part in update.artifact.parts:
|
|
91
|
+
if hasattr(part.root, "text"):
|
|
92
|
+
console.print(part.root.text, end="")
|
|
93
|
+
elif hasattr(update, "status"):
|
|
94
|
+
console.print(
|
|
95
|
+
f"\n[dim]Task status: {update.status.state}[/dim]"
|
|
96
|
+
)
|
|
97
|
+
except Exception as e: # noqa: BLE001
|
|
98
|
+
print(f"\n[ERROR] Failed to process event: {e}", file=sys.stderr)
|
|
99
|
+
print(f"Event type: {type(event)}", file=sys.stderr)
|
|
100
|
+
print(f"Event: {event}", file=sys.stderr)
|
|
101
|
+
traceback.print_exc(file=sys.stderr)
|
|
102
|
+
raise
|
|
103
|
+
except Exception as e: # noqa: BLE001
|
|
104
|
+
print(f"\n[ERROR] Stream failed: {e}", file=sys.stderr)
|
|
105
|
+
traceback.print_exc(file=sys.stderr)
|
|
106
|
+
raise
|
|
107
|
+
finally:
|
|
108
|
+
if http_client is not None:
|
|
109
|
+
await http_client.aclose()
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@app.command()
|
|
113
|
+
def chat(
|
|
114
|
+
agent: str = typer.Option(
|
|
115
|
+
"http://localhost:8000", help="The URL of the agent to connect to"
|
|
116
|
+
),
|
|
117
|
+
message: str = typer.Option(..., help="The message to send to the agent"),
|
|
118
|
+
timeout: float = typer.Option(
|
|
119
|
+
DEFAULT_TIMEOUT_SECONDS,
|
|
120
|
+
help="Timeout in seconds for connecting to the agent",
|
|
121
|
+
),
|
|
122
|
+
):
|
|
123
|
+
if timeout <= 0:
|
|
124
|
+
raise typer.BadParameter(
|
|
125
|
+
"Timeout must be greater than zero.", param_name="timeout"
|
|
126
|
+
)
|
|
127
|
+
asyncio.run(_send_message(agent, message, timeout))
|
celesto/deployment.py
ADDED
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
import typer
|
|
9
|
+
from dotenv.main import DotEnv
|
|
10
|
+
from rich.console import Console
|
|
11
|
+
from typing_extensions import Annotated
|
|
12
|
+
|
|
13
|
+
from .sdk.client import CelestoSDK
|
|
14
|
+
|
|
15
|
+
console = Console()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _get_secrets_from_env_file(
|
|
19
|
+
env_file: Optional[str] = None, secret_name: Optional[str] = None
|
|
20
|
+
) -> Optional[str]:
|
|
21
|
+
if not env_file:
|
|
22
|
+
env_file = ".env"
|
|
23
|
+
if not secret_name:
|
|
24
|
+
secret_name = "CELESTO_API_KEY"
|
|
25
|
+
dotenv_path = Path(env_file)
|
|
26
|
+
dot_env = DotEnv(dotenv_path, verbose=True, encoding="utf-8")
|
|
27
|
+
return dot_env.get(secret_name)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def _get_api_key(
|
|
31
|
+
api_key: Optional[str] = None,
|
|
32
|
+
ignore_env_file: Optional[bool] = False,
|
|
33
|
+
secret_name: Optional[str] = None,
|
|
34
|
+
) -> str:
|
|
35
|
+
"""Get API key from argument or environment variable."""
|
|
36
|
+
if not ignore_env_file:
|
|
37
|
+
final_api_key = api_key or _get_secrets_from_env_file(secret_name=secret_name)
|
|
38
|
+
else:
|
|
39
|
+
final_api_key = api_key
|
|
40
|
+
if not final_api_key:
|
|
41
|
+
console.print("ā [bold red]Error:[/bold red] API key not found.")
|
|
42
|
+
console.print(
|
|
43
|
+
"Please provide it via [bold]--api-key[/bold] or set [bold]CELESTO_API_KEY[/bold] environment variable."
|
|
44
|
+
)
|
|
45
|
+
console.print("\n[bold cyan]To get your API key:[/bold cyan]")
|
|
46
|
+
console.print("1. Log in to https://celesto.ai")
|
|
47
|
+
console.print("2. Navigate to Settings ā Security")
|
|
48
|
+
console.print("3. Copy your API key")
|
|
49
|
+
raise typer.Exit(1)
|
|
50
|
+
return final_api_key
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _resolve_envs(
|
|
54
|
+
folder_path: Path, envs: Optional[str], ignore_env_file: bool
|
|
55
|
+
) -> dict[str, str]:
|
|
56
|
+
"""Build environment dictionary from .env file and CLI overrides."""
|
|
57
|
+
env_dict: dict[str, str] = {}
|
|
58
|
+
if not ignore_env_file:
|
|
59
|
+
env_file_path = folder_path / ".env"
|
|
60
|
+
if env_file_path.exists():
|
|
61
|
+
dotenv = DotEnv(env_file_path, verbose=True, encoding="utf-8")
|
|
62
|
+
for key, value in dotenv.dict().items():
|
|
63
|
+
if value:
|
|
64
|
+
env_dict[key] = value
|
|
65
|
+
|
|
66
|
+
if envs:
|
|
67
|
+
for pair in envs.split(","):
|
|
68
|
+
pair = pair.strip()
|
|
69
|
+
if not pair:
|
|
70
|
+
continue
|
|
71
|
+
if "=" not in pair:
|
|
72
|
+
console.print(
|
|
73
|
+
f"ā [bold red]Error:[/bold red] Invalid env pair: '{pair}'. Expected format: key=value"
|
|
74
|
+
)
|
|
75
|
+
raise typer.Exit(1)
|
|
76
|
+
key, value = pair.split("=", 1)
|
|
77
|
+
env_dict[key.strip()] = value.strip()
|
|
78
|
+
|
|
79
|
+
return env_dict
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def deploy(
|
|
83
|
+
folder: Annotated[
|
|
84
|
+
str,
|
|
85
|
+
typer.Argument(
|
|
86
|
+
...,
|
|
87
|
+
help="Path to the folder containing your agent code",
|
|
88
|
+
default_factory=os.getcwd,
|
|
89
|
+
),
|
|
90
|
+
],
|
|
91
|
+
name: Annotated[
|
|
92
|
+
str,
|
|
93
|
+
typer.Option(
|
|
94
|
+
...,
|
|
95
|
+
"--name",
|
|
96
|
+
"-n",
|
|
97
|
+
help="Name for your deployment",
|
|
98
|
+
default_factory=lambda: f"my-agent-{datetime.now().strftime('%Y%m%d%H%M%S')}",
|
|
99
|
+
),
|
|
100
|
+
],
|
|
101
|
+
description: Optional[str] = typer.Option(
|
|
102
|
+
None, "--description", "-d", help="Description of your agent"
|
|
103
|
+
),
|
|
104
|
+
envs: Optional[str] = typer.Option(
|
|
105
|
+
None,
|
|
106
|
+
"--envs",
|
|
107
|
+
"-e",
|
|
108
|
+
help='Environment variables as comma-separated key=value pairs (e.g., "API_KEY=xyz,DEBUG=true")',
|
|
109
|
+
),
|
|
110
|
+
api_key: Optional[str] = typer.Option(
|
|
111
|
+
None,
|
|
112
|
+
"--api-key",
|
|
113
|
+
"-k",
|
|
114
|
+
help="Celesto API key (or set CELESTO_API_KEY env var)",
|
|
115
|
+
),
|
|
116
|
+
ignore_env_file: Optional[bool] = typer.Option(
|
|
117
|
+
False,
|
|
118
|
+
"--ignore-env-file",
|
|
119
|
+
"-i",
|
|
120
|
+
help="Ignore environment file",
|
|
121
|
+
),
|
|
122
|
+
):
|
|
123
|
+
"""Deploy an agent to the Celesto AI platform.
|
|
124
|
+
|
|
125
|
+
It automatically loads the .env file and injects the environment variables into the deployment. To ignore the .env file, use the --ignore-env-file flag.
|
|
126
|
+
"""
|
|
127
|
+
# Get API key
|
|
128
|
+
final_api_key = _get_api_key(api_key, ignore_env_file, "CELESTO_API_KEY")
|
|
129
|
+
|
|
130
|
+
# Validate folder path
|
|
131
|
+
folder_path = Path(folder).resolve()
|
|
132
|
+
if not folder_path.exists():
|
|
133
|
+
console.print(
|
|
134
|
+
f"ā [bold red]Error:[/bold red] Folder '{folder_path}' does not exist."
|
|
135
|
+
)
|
|
136
|
+
raise typer.Exit(1)
|
|
137
|
+
if not folder_path.is_dir():
|
|
138
|
+
console.print(
|
|
139
|
+
f"ā [bold red]Error:[/bold red] '{folder_path}' is not a directory."
|
|
140
|
+
)
|
|
141
|
+
raise typer.Exit(1)
|
|
142
|
+
|
|
143
|
+
# Parse environment variables
|
|
144
|
+
env_dict = _resolve_envs(folder_path, envs, bool(ignore_env_file))
|
|
145
|
+
|
|
146
|
+
# Deploy
|
|
147
|
+
try:
|
|
148
|
+
console.print(
|
|
149
|
+
f"š [bold cyan]Deploying[/bold cyan] '{name}' from {folder_path}..."
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
client = CelestoSDK(final_api_key)
|
|
153
|
+
result = client.deployment.deploy(
|
|
154
|
+
folder=folder_path, name=name, description=description, envs=env_dict
|
|
155
|
+
)
|
|
156
|
+
console.print("ā
[bold green]Deployment successful![/bold green]")
|
|
157
|
+
|
|
158
|
+
# Show deployment details
|
|
159
|
+
deployment_id = result.get("id")
|
|
160
|
+
deployment_name = result.get("name")
|
|
161
|
+
status = result.get("status")
|
|
162
|
+
console.print(f"\n[bold]Deployment ID:[/bold] {deployment_id}")
|
|
163
|
+
console.print(f"[bold]Status:[/bold] {status}")
|
|
164
|
+
|
|
165
|
+
# Show URL once ready
|
|
166
|
+
if status == "READY":
|
|
167
|
+
if not deployment_name:
|
|
168
|
+
console.print(
|
|
169
|
+
"[yellow]ā ļø Unable to determine app name; deployment URL unavailable.[/yellow]"
|
|
170
|
+
)
|
|
171
|
+
else:
|
|
172
|
+
cloud_url = (
|
|
173
|
+
f"https://api.celesto.ai/v1/deploy/apps/{deployment_name}/chat"
|
|
174
|
+
)
|
|
175
|
+
console.print(f"[bold]URL:[/bold] [link={cloud_url}]{cloud_url}[/link]")
|
|
176
|
+
else:
|
|
177
|
+
console.print(
|
|
178
|
+
"[yellow]ā³ Building... Run 'celesto ls' to check status[/yellow]"
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
except Exception as e: # noqa: BLE001
|
|
182
|
+
console.print(f"ā [bold red]Deployment failed:[/bold red] {e}")
|
|
183
|
+
raise typer.Exit(1) from e
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def list_deployments(
|
|
187
|
+
api_key: Optional[str] = typer.Option(
|
|
188
|
+
None, "--api-key", "-k", help="Celesto API key (or set CELESTO_API_KEY env var)"
|
|
189
|
+
),
|
|
190
|
+
):
|
|
191
|
+
"""List all deployments."""
|
|
192
|
+
from rich.table import Table
|
|
193
|
+
|
|
194
|
+
# Get API key
|
|
195
|
+
final_api_key = _get_api_key(api_key, secret_name="CELESTO_API_KEY")
|
|
196
|
+
|
|
197
|
+
# List deployments
|
|
198
|
+
try:
|
|
199
|
+
client = CelestoSDK(final_api_key)
|
|
200
|
+
deployments = client.deployment.list()
|
|
201
|
+
|
|
202
|
+
if not deployments:
|
|
203
|
+
console.print("š [yellow]No deployments found.[/yellow]")
|
|
204
|
+
return
|
|
205
|
+
|
|
206
|
+
# Create a table
|
|
207
|
+
table = Table(
|
|
208
|
+
title="š Deployments", show_header=True, header_style="bold cyan"
|
|
209
|
+
)
|
|
210
|
+
table.add_column("Name", style="green")
|
|
211
|
+
table.add_column("Status", style="cyan")
|
|
212
|
+
table.add_column("Created At", style="magenta")
|
|
213
|
+
table.add_column("URL", style="blue")
|
|
214
|
+
|
|
215
|
+
for deployment in deployments:
|
|
216
|
+
# Construct the cloud URL
|
|
217
|
+
deployment_name = deployment.get("name")
|
|
218
|
+
status = deployment.get("status")
|
|
219
|
+
if deployment_name and status == "READY":
|
|
220
|
+
cloud_url = (
|
|
221
|
+
f"https://api.celesto.ai/v1/deploy/apps/{deployment_name}/chat"
|
|
222
|
+
)
|
|
223
|
+
elif status == "FAILED":
|
|
224
|
+
cloud_url = "-"
|
|
225
|
+
elif status == "READY":
|
|
226
|
+
cloud_url = "Name unavailable"
|
|
227
|
+
else:
|
|
228
|
+
cloud_url = "Pending"
|
|
229
|
+
|
|
230
|
+
table.add_row(
|
|
231
|
+
deployment.get("name", "N/A"),
|
|
232
|
+
deployment.get("status", "N/A"),
|
|
233
|
+
deployment.get("created_at", "N/A").split("T")[0]
|
|
234
|
+
if deployment.get("created_at")
|
|
235
|
+
else "N/A", # Just date
|
|
236
|
+
cloud_url,
|
|
237
|
+
)
|
|
238
|
+
|
|
239
|
+
console.print(table)
|
|
240
|
+
console.print(f"\nš Total deployments: [bold]{len(deployments)}[/bold]")
|
|
241
|
+
|
|
242
|
+
except Exception as e: # noqa: BLE001
|
|
243
|
+
console.print(f"ā [bold red]Failed to list deployments:[/bold red] {e}")
|
|
244
|
+
raise typer.Exit(1) from e
|
celesto/main.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import typer
|
|
4
|
+
from rich import print
|
|
5
|
+
|
|
6
|
+
from . import a2a, deployment, proxy
|
|
7
|
+
|
|
8
|
+
app = typer.Typer()
|
|
9
|
+
app.add_typer(proxy.app)
|
|
10
|
+
app.add_typer(a2a.app, name="a2a")
|
|
11
|
+
|
|
12
|
+
# Add deployment commands at top level
|
|
13
|
+
app.command("deploy")(deployment.deploy)
|
|
14
|
+
app.command("list")(deployment.list_deployments)
|
|
15
|
+
app.command("ls")(deployment.list_deployments) # Alias for list
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@app.callback(invoke_without_command=True)
|
|
19
|
+
def main(ctx: typer.Context):
|
|
20
|
+
if ctx.invoked_subcommand is None:
|
|
21
|
+
print(
|
|
22
|
+
"""[orange_red1]
|
|
23
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā®
|
|
24
|
+
ā Fastest way to build, prototype and deploy AI Agents. ā
|
|
25
|
+
ā [bold][link=https://celesto.ai]by Celesto AI[/link][/bold] ā
|
|
26
|
+
ā°āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
27
|
+
[range_red1]
|
|
28
|
+
"""
|
|
29
|
+
)
|
|
30
|
+
typer.echo(ctx.get_help())
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
if __name__ == "__main__":
|
|
34
|
+
app()
|
celesto/proxy.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import typer
|
|
4
|
+
|
|
5
|
+
app = typer.Typer(help="Manage MCP proxy connections.")
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@app.command("create-proxy")
|
|
9
|
+
def create_proxy(remote_url: str, name: str | None = None):
|
|
10
|
+
"""Create a proxy to a remote MCP server."""
|
|
11
|
+
try:
|
|
12
|
+
from fastmcp import FastMCP
|
|
13
|
+
|
|
14
|
+
mcp_server = FastMCP.as_proxy(remote_url, name=name)
|
|
15
|
+
mcp_server.run()
|
|
16
|
+
except Exception as exc: # noqa: BLE001
|
|
17
|
+
typer.echo(f"Error creating proxy: {exc}", err=True)
|
|
18
|
+
raise typer.Exit(1) from exc
|
celesto/sdk/__init__.py
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from .client import CelestoSDK
|
|
2
|
+
from .exceptions import (
|
|
3
|
+
CelestoAuthenticationError,
|
|
4
|
+
CelestoError,
|
|
5
|
+
CelestoNetworkError,
|
|
6
|
+
CelestoNotFoundError,
|
|
7
|
+
CelestoRateLimitError,
|
|
8
|
+
CelestoServerError,
|
|
9
|
+
CelestoValidationError,
|
|
10
|
+
)
|
|
11
|
+
from .types import (
|
|
12
|
+
AccessRules,
|
|
13
|
+
ConnectionInfo,
|
|
14
|
+
ConnectionListResponse,
|
|
15
|
+
ConnectionResponse,
|
|
16
|
+
ConnectionStatus,
|
|
17
|
+
DeploymentInfo,
|
|
18
|
+
DeploymentResponse,
|
|
19
|
+
DriveFile,
|
|
20
|
+
DriveFilesResponse,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
__all__ = [
|
|
24
|
+
# Main client
|
|
25
|
+
"CelestoSDK",
|
|
26
|
+
# Exceptions
|
|
27
|
+
"CelestoError",
|
|
28
|
+
"CelestoAuthenticationError",
|
|
29
|
+
"CelestoNotFoundError",
|
|
30
|
+
"CelestoValidationError",
|
|
31
|
+
"CelestoRateLimitError",
|
|
32
|
+
"CelestoServerError",
|
|
33
|
+
"CelestoNetworkError",
|
|
34
|
+
# Types
|
|
35
|
+
"DeploymentInfo",
|
|
36
|
+
"DeploymentResponse",
|
|
37
|
+
"ConnectionStatus",
|
|
38
|
+
"ConnectionResponse",
|
|
39
|
+
"ConnectionInfo",
|
|
40
|
+
"ConnectionListResponse",
|
|
41
|
+
"DriveFile",
|
|
42
|
+
"DriveFilesResponse",
|
|
43
|
+
"AccessRules",
|
|
44
|
+
]
|