moss-agent-cli 0.1.0__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.
@@ -0,0 +1,164 @@
1
+ Metadata-Version: 2.4
2
+ Name: moss-agent-cli
3
+ Version: 0.1.0
4
+ Summary: CLI tool for deploying Moss voice agents
5
+ Author-email: Moss Team <support@moss.dev>
6
+ License: MIT
7
+ Requires-Python: >=3.10
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: typer>=0.9.0
10
+ Requires-Dist: rich>=13.0.0
11
+ Requires-Dist: httpx>=0.27.0
12
+ Requires-Dist: python-dotenv>=1.0.0
13
+
14
+ # Moss Agent CLI
15
+
16
+ Command-line tool for deploying voice agents to the Moss platform.
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ pip install moss-agent-cli
22
+ ```
23
+
24
+ Or install from source:
25
+
26
+ ```bash
27
+ cd moss-agent-cli
28
+ pip install -e .
29
+ ```
30
+
31
+ ## Usage
32
+
33
+ ### Deploy Command
34
+
35
+ Deploy your agent to the Moss platform:
36
+
37
+ ```bash
38
+ moss-agent deploy
39
+ ```
40
+
41
+ ### Required Environment Variables
42
+
43
+ Set these environment variables or pass as CLI options:
44
+
45
+ ```bash
46
+ export MOSS_PROJECT_ID="your-project-id"
47
+ export MOSS_PROJECT_KEY="your-project-key"
48
+ export MOSS_VOICE_AGENT_ID="your-voice-agent-id"
49
+ ```
50
+
51
+ Or pass as options:
52
+
53
+ ```bash
54
+ moss-agent deploy \
55
+ --project-id "your-project-id" \
56
+ --project-key "your-project-key" \
57
+ --voice-agent-id "your-voice-agent-id"
58
+ ```
59
+
60
+ ### Agent Structure
61
+
62
+ Your agent directory must contain an entry point file that imports from `moss_voice_agent_manager`:
63
+
64
+ **Simple structure:**
65
+ ```
66
+ my-agent/
67
+ ├── agent.py # Entry point (uses MossAgentSession)
68
+ ├── requirements.txt # Optional: Additional dependencies
69
+ └── tools/ # Optional: Custom tools
70
+ └── my_tools.py
71
+ ```
72
+
73
+ **Or with main.py:**
74
+ ```
75
+ my-agent/
76
+ ├── main.py # Entry point
77
+ ├── requirements.txt
78
+ └── ...
79
+ ```
80
+
81
+ **Or with src structure:**
82
+ ```
83
+ my-agent/
84
+ ├── src/
85
+ │ └── my_agent/
86
+ │ └── main.py # Entry point
87
+ ├── requirements.txt
88
+ └── ...
89
+ ```
90
+
91
+ #### Example agent.py
92
+
93
+ ```python
94
+ from moss_voice_agent_manager import MossAgentSession
95
+
96
+ def get_weather(city: str) -> str:
97
+ """Get weather for a city."""
98
+ return f"Weather in {city} is sunny"
99
+
100
+ session = MossAgentSession(
101
+ function_tools=[get_weather],
102
+ max_tool_steps=10,
103
+ )
104
+
105
+ if __name__ == "__main__":
106
+ session.run()
107
+ ```
108
+
109
+ ## CLI Options
110
+
111
+ ```
112
+ moss-agent deploy [OPTIONS] [DIRECTORY]
113
+
114
+ Arguments:
115
+ DIRECTORY Agent directory to deploy (defaults to current directory)
116
+
117
+ Options:
118
+ --project-id, -p TEXT Moss project ID (or set MOSS_PROJECT_ID env var)
119
+ --project-key, -k TEXT Moss project key (or set MOSS_PROJECT_KEY env var)
120
+ --voice-agent-id, -v TEXT Voice agent ID (or set MOSS_VOICE_AGENT_ID env var)
121
+ --api-url TEXT Moss platform API URL (defaults to production)
122
+ --help Show this message and exit
123
+ ```
124
+
125
+ ## What Gets Deployed
126
+
127
+ When you run `moss-agent deploy`, the CLI:
128
+
129
+ 1. **Validates** your agent structure
130
+ 2. **Packages** your agent directory (excluding .env, __pycache__, .git, etc.)
131
+ 3. **Uploads** the package to Moss platform
132
+ 4. **Deploys** to LiveKit Cloud
133
+
134
+ Your agent code is deployed as-is - no modification or generation.
135
+
136
+ ## Excluded Files
137
+
138
+ The following files/directories are automatically excluded from deployment:
139
+
140
+ - `.env` - Environment variables (secrets)
141
+ - `__pycache__/` - Python cache
142
+ - `.git/` - Git repository
143
+ - `*.pyc` - Compiled Python files
144
+ - `.venv/`, `venv/` - Virtual environments
145
+ - `.DS_Store` - macOS metadata
146
+
147
+ ## Development
148
+
149
+ Install in development mode:
150
+
151
+ ```bash
152
+ cd moss-agent-cli
153
+ pip install -e .
154
+ ```
155
+
156
+ Run the CLI:
157
+
158
+ ```bash
159
+ moss-agent deploy
160
+ ```
161
+
162
+ ## License
163
+
164
+ MIT
@@ -0,0 +1,151 @@
1
+ # Moss Agent CLI
2
+
3
+ Command-line tool for deploying voice agents to the Moss platform.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pip install moss-agent-cli
9
+ ```
10
+
11
+ Or install from source:
12
+
13
+ ```bash
14
+ cd moss-agent-cli
15
+ pip install -e .
16
+ ```
17
+
18
+ ## Usage
19
+
20
+ ### Deploy Command
21
+
22
+ Deploy your agent to the Moss platform:
23
+
24
+ ```bash
25
+ moss-agent deploy
26
+ ```
27
+
28
+ ### Required Environment Variables
29
+
30
+ Set these environment variables or pass as CLI options:
31
+
32
+ ```bash
33
+ export MOSS_PROJECT_ID="your-project-id"
34
+ export MOSS_PROJECT_KEY="your-project-key"
35
+ export MOSS_VOICE_AGENT_ID="your-voice-agent-id"
36
+ ```
37
+
38
+ Or pass as options:
39
+
40
+ ```bash
41
+ moss-agent deploy \
42
+ --project-id "your-project-id" \
43
+ --project-key "your-project-key" \
44
+ --voice-agent-id "your-voice-agent-id"
45
+ ```
46
+
47
+ ### Agent Structure
48
+
49
+ Your agent directory must contain an entry point file that imports from `moss_voice_agent_manager`:
50
+
51
+ **Simple structure:**
52
+ ```
53
+ my-agent/
54
+ ├── agent.py # Entry point (uses MossAgentSession)
55
+ ├── requirements.txt # Optional: Additional dependencies
56
+ └── tools/ # Optional: Custom tools
57
+ └── my_tools.py
58
+ ```
59
+
60
+ **Or with main.py:**
61
+ ```
62
+ my-agent/
63
+ ├── main.py # Entry point
64
+ ├── requirements.txt
65
+ └── ...
66
+ ```
67
+
68
+ **Or with src structure:**
69
+ ```
70
+ my-agent/
71
+ ├── src/
72
+ │ └── my_agent/
73
+ │ └── main.py # Entry point
74
+ ├── requirements.txt
75
+ └── ...
76
+ ```
77
+
78
+ #### Example agent.py
79
+
80
+ ```python
81
+ from moss_voice_agent_manager import MossAgentSession
82
+
83
+ def get_weather(city: str) -> str:
84
+ """Get weather for a city."""
85
+ return f"Weather in {city} is sunny"
86
+
87
+ session = MossAgentSession(
88
+ function_tools=[get_weather],
89
+ max_tool_steps=10,
90
+ )
91
+
92
+ if __name__ == "__main__":
93
+ session.run()
94
+ ```
95
+
96
+ ## CLI Options
97
+
98
+ ```
99
+ moss-agent deploy [OPTIONS] [DIRECTORY]
100
+
101
+ Arguments:
102
+ DIRECTORY Agent directory to deploy (defaults to current directory)
103
+
104
+ Options:
105
+ --project-id, -p TEXT Moss project ID (or set MOSS_PROJECT_ID env var)
106
+ --project-key, -k TEXT Moss project key (or set MOSS_PROJECT_KEY env var)
107
+ --voice-agent-id, -v TEXT Voice agent ID (or set MOSS_VOICE_AGENT_ID env var)
108
+ --api-url TEXT Moss platform API URL (defaults to production)
109
+ --help Show this message and exit
110
+ ```
111
+
112
+ ## What Gets Deployed
113
+
114
+ When you run `moss-agent deploy`, the CLI:
115
+
116
+ 1. **Validates** your agent structure
117
+ 2. **Packages** your agent directory (excluding .env, __pycache__, .git, etc.)
118
+ 3. **Uploads** the package to Moss platform
119
+ 4. **Deploys** to LiveKit Cloud
120
+
121
+ Your agent code is deployed as-is - no modification or generation.
122
+
123
+ ## Excluded Files
124
+
125
+ The following files/directories are automatically excluded from deployment:
126
+
127
+ - `.env` - Environment variables (secrets)
128
+ - `__pycache__/` - Python cache
129
+ - `.git/` - Git repository
130
+ - `*.pyc` - Compiled Python files
131
+ - `.venv/`, `venv/` - Virtual environments
132
+ - `.DS_Store` - macOS metadata
133
+
134
+ ## Development
135
+
136
+ Install in development mode:
137
+
138
+ ```bash
139
+ cd moss-agent-cli
140
+ pip install -e .
141
+ ```
142
+
143
+ Run the CLI:
144
+
145
+ ```bash
146
+ moss-agent deploy
147
+ ```
148
+
149
+ ## License
150
+
151
+ MIT
@@ -0,0 +1,3 @@
1
+ """Moss Agent CLI - Deploy voice agents to Moss platform."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,21 @@
1
+ """Main CLI entry point."""
2
+
3
+ import typer
4
+ from rich.console import Console
5
+
6
+ from .commands.deploy import deploy_command
7
+
8
+ app = typer.Typer(
9
+ name="moss-agent",
10
+ help="Moss Agent CLI - Deploy voice agents to Moss platform",
11
+ add_completion=False,
12
+ )
13
+
14
+ console = Console()
15
+
16
+ # Register commands
17
+ app.command(name="deploy")(deploy_command)
18
+
19
+
20
+ if __name__ == "__main__":
21
+ app()
@@ -0,0 +1 @@
1
+ """CLI commands."""
@@ -0,0 +1,108 @@
1
+ """Deploy command implementation."""
2
+
3
+ import os
4
+ from pathlib import Path
5
+ from typing import Optional
6
+
7
+ import typer
8
+ from dotenv import load_dotenv
9
+ from rich.console import Console
10
+ from rich.progress import Progress, SpinnerColumn, TextColumn
11
+
12
+ from ..core.deployer import deploy_agent_package
13
+
14
+ console = Console()
15
+
16
+ # Load .env file from current directory if it exists
17
+ load_dotenv()
18
+
19
+
20
+ def deploy_command(
21
+ directory: Optional[Path] = typer.Argument(
22
+ None,
23
+ help="Agent directory to deploy (defaults to current directory)",
24
+ ),
25
+ project_id: Optional[str] = typer.Option(
26
+ None,
27
+ "--project-id",
28
+ "-p",
29
+ help="Moss project ID (or set MOSS_PROJECT_ID env var)",
30
+ ),
31
+ project_key: Optional[str] = typer.Option(
32
+ None,
33
+ "--project-key",
34
+ "-k",
35
+ help="Moss project key (or set MOSS_PROJECT_KEY env var)",
36
+ ),
37
+ voice_agent_id: Optional[str] = typer.Option(
38
+ None,
39
+ "--voice-agent-id",
40
+ "-v",
41
+ help="Voice agent ID (or set MOSS_VOICE_AGENT_ID env var)",
42
+ ),
43
+ api_url: Optional[str] = typer.Option(
44
+ None,
45
+ "--api-url",
46
+ help="Moss platform API URL (defaults to production)",
47
+ ),
48
+ ) -> None:
49
+ """Deploy agent to Moss platform."""
50
+
51
+ # Resolve directory
52
+ agent_dir = directory or Path.cwd()
53
+ if not agent_dir.exists():
54
+ console.print(f"[red]Error:[/red] Directory not found: {agent_dir}")
55
+ raise typer.Exit(1)
56
+
57
+ # Load credentials from env or arguments
58
+ project_id = project_id or os.getenv("MOSS_PROJECT_ID")
59
+ project_key = project_key or os.getenv("MOSS_PROJECT_KEY")
60
+ voice_agent_id = voice_agent_id or os.getenv("MOSS_VOICE_AGENT_ID")
61
+ api_url = api_url or os.getenv("MOSS_PLATFORM_API_URL", "https://service.usemoss.dev")
62
+
63
+ # Validate credentials
64
+ if not project_id or not project_key or not voice_agent_id:
65
+ console.print("[red]Error:[/red] Missing required credentials")
66
+ console.print("\nProvide via options or environment variables:")
67
+ console.print(" --project-id / MOSS_PROJECT_ID")
68
+ console.print(" --project-key / MOSS_PROJECT_KEY")
69
+ console.print(" --voice-agent-id / MOSS_VOICE_AGENT_ID")
70
+ raise typer.Exit(1)
71
+
72
+ console.print(f"\n[bold]Deploying agent from:[/bold] {agent_dir}")
73
+ console.print(f"[dim]Project ID:[/dim] {project_id}")
74
+ console.print(f"[dim]Voice Agent ID:[/dim] {voice_agent_id}\n")
75
+
76
+ # Deploy with progress indicator
77
+ with Progress(
78
+ SpinnerColumn(),
79
+ TextColumn("[progress.description]{task.description}"),
80
+ console=console,
81
+ ) as progress:
82
+ task = progress.add_task("Deploying agent...", total=None)
83
+
84
+ try:
85
+ result = deploy_agent_package(
86
+ agent_dir=agent_dir,
87
+ project_id=project_id,
88
+ project_key=project_key,
89
+ voice_agent_id=voice_agent_id,
90
+ api_url=api_url,
91
+ )
92
+
93
+ progress.update(task, completed=True)
94
+
95
+ if result.get("ok"):
96
+ console.print("[green]✓[/green] Deployment successful!")
97
+ if result.get("deployment_url"):
98
+ console.print(f"\n[bold]Deployment URL:[/bold] {result['deployment_url']}")
99
+ else:
100
+ console.print("[red]✗[/red] Deployment failed")
101
+ if result.get("error"):
102
+ console.print(f"\n[red]Error:[/red] {result['error']}")
103
+ raise typer.Exit(1)
104
+
105
+ except Exception as exc:
106
+ progress.update(task, completed=True)
107
+ console.print(f"\n[red]Error:[/red] {exc}")
108
+ raise typer.Exit(1)
@@ -0,0 +1 @@
1
+ """Core CLI logic."""
@@ -0,0 +1,315 @@
1
+ """Agent deployment logic."""
2
+
3
+ import tarfile
4
+ import tempfile
5
+ from pathlib import Path
6
+ from typing import Dict, Any
7
+
8
+ import httpx
9
+
10
+
11
+ def validate_agent_structure(agent_dir: Path) -> None:
12
+ """
13
+ Validate that the agent directory has required files.
14
+
15
+ Args:
16
+ agent_dir: Path to agent directory
17
+
18
+ Raises:
19
+ ValueError: If validation fails
20
+ """
21
+ # Check for either agent.py or main.py (or src/*/main.py pattern)
22
+ agent_py = agent_dir / "agent.py"
23
+ main_py = agent_dir / "main.py"
24
+
25
+ # Also check for src/*/main.py pattern (like src/moss_voice_agent/main.py)
26
+ src_main_files = list(agent_dir.glob("src/*/main.py"))
27
+
28
+ entry_point = None
29
+ if agent_py.exists():
30
+ entry_point = agent_py
31
+ elif main_py.exists():
32
+ entry_point = main_py
33
+ elif src_main_files:
34
+ entry_point = src_main_files[0]
35
+
36
+ if not entry_point:
37
+ raise ValueError(
38
+ "Missing entry point file. Agent directory must contain one of:\n"
39
+ " - agent.py (at root)\n"
40
+ " - main.py (at root)\n"
41
+ " - src/*/main.py (in src subdirectory)"
42
+ )
43
+
44
+ # Check that entry point uses moss_voice_agent_manager
45
+ entry_content = entry_point.read_text()
46
+ if "moss_voice_agent_manager" not in entry_content:
47
+ raise ValueError(
48
+ f"{entry_point.name} must import from moss_voice_agent_manager"
49
+ )
50
+
51
+
52
+ def package_agent(agent_dir: Path) -> Path:
53
+ """
54
+ Package agent directory into a tarball.
55
+
56
+ Args:
57
+ agent_dir: Path to agent directory
58
+
59
+ Returns:
60
+ Path to created tarball
61
+
62
+ Raises:
63
+ ValueError: If packaging fails
64
+ """
65
+ # Create temporary tarball
66
+ temp_dir = Path(tempfile.gettempdir())
67
+ tarball_path = temp_dir / f"agent-{agent_dir.name}.tar.gz"
68
+
69
+ # Files to exclude
70
+ exclude_patterns = {
71
+ ".env",
72
+ "__pycache__",
73
+ ".git",
74
+ "*.pyc",
75
+ ".venv",
76
+ "venv",
77
+ ".DS_Store",
78
+ }
79
+
80
+ def should_exclude(file_path: Path) -> bool:
81
+ """Check if file should be excluded from package."""
82
+ name = file_path.name
83
+ # Check exact matches
84
+ if name in exclude_patterns:
85
+ return True
86
+ # Check pattern matches (*.pyc, etc.)
87
+ for pattern in exclude_patterns:
88
+ if "*" in pattern:
89
+ ext = pattern.replace("*", "")
90
+ if name.endswith(ext):
91
+ return True
92
+ # Check if in excluded directory
93
+ for part in file_path.parts:
94
+ if part in exclude_patterns:
95
+ return True
96
+ return False
97
+
98
+ try:
99
+ with tarfile.open(tarball_path, "w:gz") as tar:
100
+ for item in agent_dir.rglob("*"):
101
+ if item.is_file() and not should_exclude(item):
102
+ arcname = item.relative_to(agent_dir)
103
+ tar.add(item, arcname=arcname)
104
+
105
+ return tarball_path
106
+
107
+ except Exception as exc:
108
+ raise ValueError(f"Failed to package agent: {exc}") from exc
109
+
110
+
111
+ def upload_agent_package(
112
+ tarball_path: Path,
113
+ project_id: str,
114
+ project_key: str,
115
+ voice_agent_id: str,
116
+ api_url: str,
117
+ poll_status: bool = True,
118
+ ) -> Dict[str, Any]:
119
+ """
120
+ Upload agent package to Moss platform.
121
+
122
+ Args:
123
+ tarball_path: Path to agent tarball
124
+ project_id: Moss project ID
125
+ project_key: Moss project key
126
+ voice_agent_id: Voice agent ID
127
+ api_url: API base URL
128
+ poll_status: Whether to poll for deployment status
129
+
130
+ Returns:
131
+ Deployment response
132
+
133
+ Raises:
134
+ httpx.HTTPError: If upload fails
135
+ """
136
+ endpoint = f"{api_url}/api/voice-agent/upload"
137
+ print(f"DEBUG: Uploading to {endpoint}")
138
+
139
+ headers = {
140
+ "X-Project-Id": project_id,
141
+ "X-Project-Key": project_key,
142
+ }
143
+
144
+ with open(tarball_path, "rb") as f:
145
+ files = {
146
+ "agent_package": ("agent.tar.gz", f, "application/gzip")
147
+ }
148
+ data = {
149
+ "voice_agent_id": voice_agent_id,
150
+ }
151
+
152
+ with httpx.Client(timeout=30.0) as client: # Quick upload timeout
153
+ response = client.post(
154
+ endpoint,
155
+ headers=headers,
156
+ files=files,
157
+ data=data,
158
+ )
159
+ response.raise_for_status()
160
+ result = response.json()
161
+
162
+ # If async deployment (202 status), poll for status
163
+ if response.status_code == 202 and poll_status:
164
+ deployment_id = result.get("deployment_id")
165
+ if deployment_id:
166
+ print(f"DEBUG: Polling status for deployment {deployment_id}")
167
+ final_status = poll_deployment_status(
168
+ deployment_id=deployment_id,
169
+ project_id=project_id,
170
+ project_key=project_key,
171
+ api_url=api_url,
172
+ )
173
+ return final_status
174
+
175
+ return result
176
+
177
+
178
+ def poll_deployment_status(
179
+ deployment_id: str,
180
+ project_id: str,
181
+ project_key: str,
182
+ api_url: str,
183
+ max_wait: int = 600, # 10 minutes max
184
+ poll_interval: int = 5, # Check every 5 seconds
185
+ ) -> Dict[str, Any]:
186
+ """
187
+ Poll deployment status until completion.
188
+
189
+ Args:
190
+ deployment_id: Deployment ID to check
191
+ project_id: Moss project ID
192
+ project_key: Moss project key
193
+ api_url: API base URL
194
+ max_wait: Maximum seconds to wait
195
+ poll_interval: Seconds between polls
196
+
197
+ Returns:
198
+ Final deployment status
199
+ """
200
+ import time
201
+
202
+ endpoint = f"{api_url}/api/voice-agent/deployment-status/{deployment_id}"
203
+ headers = {
204
+ "X-Project-Id": project_id,
205
+ "X-Project-Key": project_key,
206
+ }
207
+
208
+ start_time = time.time()
209
+
210
+ with httpx.Client(timeout=10.0) as client:
211
+ while True:
212
+ elapsed = time.time() - start_time
213
+ if elapsed > max_wait:
214
+ return {
215
+ "ok": False,
216
+ "error": f"Deployment timed out after {max_wait} seconds",
217
+ "status": "timeout",
218
+ }
219
+
220
+ try:
221
+ response = client.get(endpoint, headers=headers)
222
+ response.raise_for_status()
223
+ status_data = response.json()
224
+
225
+ status_value = status_data.get("status")
226
+ print(f"DEBUG: Status = {status_value}")
227
+
228
+ if status_value == "completed":
229
+ return {
230
+ "ok": True,
231
+ "deployment_url": status_data.get("deployment_url"),
232
+ "status": "completed",
233
+ }
234
+ elif status_value == "failed":
235
+ return {
236
+ "ok": False,
237
+ "error": status_data.get("error", "Deployment failed"),
238
+ "status": "failed",
239
+ }
240
+
241
+ # Still in progress, wait and retry
242
+ time.sleep(poll_interval)
243
+
244
+ except httpx.HTTPError as exc:
245
+ print(f"DEBUG: Polling error: {exc}")
246
+ time.sleep(poll_interval)
247
+
248
+
249
+ def deploy_agent_package(
250
+ agent_dir: Path,
251
+ project_id: str,
252
+ project_key: str,
253
+ voice_agent_id: str,
254
+ api_url: str,
255
+ ) -> Dict[str, Any]:
256
+ """
257
+ Deploy agent package to Moss platform.
258
+
259
+ Args:
260
+ agent_dir: Path to agent directory
261
+ project_id: Moss project ID
262
+ project_key: Moss project key
263
+ voice_agent_id: Voice agent ID
264
+ api_url: API base URL
265
+
266
+ Returns:
267
+ Deployment response
268
+ """
269
+ print(f"DEBUG: Starting deployment with API URL: {api_url}")
270
+
271
+ # Validate agent structure
272
+ validate_agent_structure(agent_dir)
273
+ print("DEBUG: Validation passed")
274
+
275
+ # Package agent
276
+ tarball_path = package_agent(agent_dir)
277
+ print(f"DEBUG: Packaged to {tarball_path}")
278
+
279
+ try:
280
+ # Upload to platform
281
+ result = upload_agent_package(
282
+ tarball_path=tarball_path,
283
+ project_id=project_id,
284
+ project_key=project_key,
285
+ voice_agent_id=voice_agent_id,
286
+ api_url=api_url,
287
+ )
288
+ return result
289
+
290
+ except httpx.HTTPError as exc:
291
+ print(f"DEBUG: HTTP Error: {exc}")
292
+ print(f"DEBUG: Exception type: {type(exc)}")
293
+ error_msg = str(exc)
294
+ if hasattr(exc, "response") and exc.response is not None:
295
+ print(f"DEBUG: Response status: {exc.response.status_code}")
296
+ print(f"DEBUG: Response text: {exc.response.text[:500]}")
297
+ try:
298
+ error_detail = exc.response.json().get("detail", error_msg)
299
+ error_msg = error_detail
300
+ except Exception as e:
301
+ print(f"DEBUG: Could not parse JSON: {e}")
302
+ pass
303
+ return {"ok": False, "error": error_msg}
304
+
305
+ except Exception as exc:
306
+ print(f"DEBUG: Unexpected error: {exc}")
307
+ print(f"DEBUG: Exception type: {type(exc)}")
308
+ import traceback
309
+ traceback.print_exc()
310
+ return {"ok": False, "error": str(exc)}
311
+
312
+ finally:
313
+ # Clean up tarball
314
+ if tarball_path.exists():
315
+ tarball_path.unlink()
@@ -0,0 +1,164 @@
1
+ Metadata-Version: 2.4
2
+ Name: moss-agent-cli
3
+ Version: 0.1.0
4
+ Summary: CLI tool for deploying Moss voice agents
5
+ Author-email: Moss Team <support@moss.dev>
6
+ License: MIT
7
+ Requires-Python: >=3.10
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: typer>=0.9.0
10
+ Requires-Dist: rich>=13.0.0
11
+ Requires-Dist: httpx>=0.27.0
12
+ Requires-Dist: python-dotenv>=1.0.0
13
+
14
+ # Moss Agent CLI
15
+
16
+ Command-line tool for deploying voice agents to the Moss platform.
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ pip install moss-agent-cli
22
+ ```
23
+
24
+ Or install from source:
25
+
26
+ ```bash
27
+ cd moss-agent-cli
28
+ pip install -e .
29
+ ```
30
+
31
+ ## Usage
32
+
33
+ ### Deploy Command
34
+
35
+ Deploy your agent to the Moss platform:
36
+
37
+ ```bash
38
+ moss-agent deploy
39
+ ```
40
+
41
+ ### Required Environment Variables
42
+
43
+ Set these environment variables or pass as CLI options:
44
+
45
+ ```bash
46
+ export MOSS_PROJECT_ID="your-project-id"
47
+ export MOSS_PROJECT_KEY="your-project-key"
48
+ export MOSS_VOICE_AGENT_ID="your-voice-agent-id"
49
+ ```
50
+
51
+ Or pass as options:
52
+
53
+ ```bash
54
+ moss-agent deploy \
55
+ --project-id "your-project-id" \
56
+ --project-key "your-project-key" \
57
+ --voice-agent-id "your-voice-agent-id"
58
+ ```
59
+
60
+ ### Agent Structure
61
+
62
+ Your agent directory must contain an entry point file that imports from `moss_voice_agent_manager`:
63
+
64
+ **Simple structure:**
65
+ ```
66
+ my-agent/
67
+ ├── agent.py # Entry point (uses MossAgentSession)
68
+ ├── requirements.txt # Optional: Additional dependencies
69
+ └── tools/ # Optional: Custom tools
70
+ └── my_tools.py
71
+ ```
72
+
73
+ **Or with main.py:**
74
+ ```
75
+ my-agent/
76
+ ├── main.py # Entry point
77
+ ├── requirements.txt
78
+ └── ...
79
+ ```
80
+
81
+ **Or with src structure:**
82
+ ```
83
+ my-agent/
84
+ ├── src/
85
+ │ └── my_agent/
86
+ │ └── main.py # Entry point
87
+ ├── requirements.txt
88
+ └── ...
89
+ ```
90
+
91
+ #### Example agent.py
92
+
93
+ ```python
94
+ from moss_voice_agent_manager import MossAgentSession
95
+
96
+ def get_weather(city: str) -> str:
97
+ """Get weather for a city."""
98
+ return f"Weather in {city} is sunny"
99
+
100
+ session = MossAgentSession(
101
+ function_tools=[get_weather],
102
+ max_tool_steps=10,
103
+ )
104
+
105
+ if __name__ == "__main__":
106
+ session.run()
107
+ ```
108
+
109
+ ## CLI Options
110
+
111
+ ```
112
+ moss-agent deploy [OPTIONS] [DIRECTORY]
113
+
114
+ Arguments:
115
+ DIRECTORY Agent directory to deploy (defaults to current directory)
116
+
117
+ Options:
118
+ --project-id, -p TEXT Moss project ID (or set MOSS_PROJECT_ID env var)
119
+ --project-key, -k TEXT Moss project key (or set MOSS_PROJECT_KEY env var)
120
+ --voice-agent-id, -v TEXT Voice agent ID (or set MOSS_VOICE_AGENT_ID env var)
121
+ --api-url TEXT Moss platform API URL (defaults to production)
122
+ --help Show this message and exit
123
+ ```
124
+
125
+ ## What Gets Deployed
126
+
127
+ When you run `moss-agent deploy`, the CLI:
128
+
129
+ 1. **Validates** your agent structure
130
+ 2. **Packages** your agent directory (excluding .env, __pycache__, .git, etc.)
131
+ 3. **Uploads** the package to Moss platform
132
+ 4. **Deploys** to LiveKit Cloud
133
+
134
+ Your agent code is deployed as-is - no modification or generation.
135
+
136
+ ## Excluded Files
137
+
138
+ The following files/directories are automatically excluded from deployment:
139
+
140
+ - `.env` - Environment variables (secrets)
141
+ - `__pycache__/` - Python cache
142
+ - `.git/` - Git repository
143
+ - `*.pyc` - Compiled Python files
144
+ - `.venv/`, `venv/` - Virtual environments
145
+ - `.DS_Store` - macOS metadata
146
+
147
+ ## Development
148
+
149
+ Install in development mode:
150
+
151
+ ```bash
152
+ cd moss-agent-cli
153
+ pip install -e .
154
+ ```
155
+
156
+ Run the CLI:
157
+
158
+ ```bash
159
+ moss-agent deploy
160
+ ```
161
+
162
+ ## License
163
+
164
+ MIT
@@ -0,0 +1,14 @@
1
+ README.md
2
+ pyproject.toml
3
+ moss_agent_cli/__init__.py
4
+ moss_agent_cli/cli.py
5
+ moss_agent_cli.egg-info/PKG-INFO
6
+ moss_agent_cli.egg-info/SOURCES.txt
7
+ moss_agent_cli.egg-info/dependency_links.txt
8
+ moss_agent_cli.egg-info/entry_points.txt
9
+ moss_agent_cli.egg-info/requires.txt
10
+ moss_agent_cli.egg-info/top_level.txt
11
+ moss_agent_cli/commands/__init__.py
12
+ moss_agent_cli/commands/deploy.py
13
+ moss_agent_cli/core/__init__.py
14
+ moss_agent_cli/core/deployer.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ moss-agent = moss_agent_cli.cli:app
@@ -0,0 +1,4 @@
1
+ typer>=0.9.0
2
+ rich>=13.0.0
3
+ httpx>=0.27.0
4
+ python-dotenv>=1.0.0
@@ -0,0 +1 @@
1
+ moss_agent_cli
@@ -0,0 +1,28 @@
1
+ [build-system]
2
+ requires = ["setuptools>=45", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "moss-agent-cli"
7
+ version = "0.1.0"
8
+ description = "CLI tool for deploying Moss voice agents"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = {text = "MIT"}
12
+ authors = [
13
+ {name = "Moss Team", email = "support@moss.dev"}
14
+ ]
15
+ dependencies = [
16
+ "typer>=0.9.0",
17
+ "rich>=13.0.0",
18
+ "httpx>=0.27.0",
19
+ "python-dotenv>=1.0.0",
20
+ ]
21
+
22
+ [project.scripts]
23
+ moss-agent = "moss_agent_cli.cli:app"
24
+
25
+ [tool.setuptools.packages.find]
26
+ where = ["."]
27
+ include = ["moss_agent_cli*"]
28
+ exclude = ["tests*"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+