pipecatcloud 0.2.1__tar.gz → 0.2.3__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 (48) hide show
  1. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/CHANGELOG.md +45 -2
  2. {pipecatcloud-0.2.1/src/pipecatcloud.egg-info → pipecatcloud-0.2.3}/PKG-INFO +5 -5
  3. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/pyproject.toml +5 -5
  4. pipecatcloud-0.2.3/pytest.ini +14 -0
  5. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/agent.py +28 -7
  6. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/cli/commands/agent.py +15 -2
  7. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3/src/pipecatcloud.egg-info}/PKG-INFO +5 -5
  8. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud.egg-info/SOURCES.txt +4 -1
  9. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud.egg-info/requires.txt +4 -4
  10. pipecatcloud-0.2.3/tests/__init__.py +1 -0
  11. pipecatcloud-0.2.3/tests/test_agent_sessions.py +70 -0
  12. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/.github/workflows/publish-pypi.yml +0 -0
  13. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/.github/workflows/publish-test.yml +0 -0
  14. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/.github/workflows/python-publish.yml +0 -0
  15. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/.gitignore +0 -0
  16. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/LICENSE +0 -0
  17. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/README.md +0 -0
  18. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/dev-requirements.txt +0 -0
  19. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/pipecat-cloud.png +0 -0
  20. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/setup.cfg +0 -0
  21. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/__init__.py +0 -0
  22. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/__main__.py +0 -0
  23. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/__version__.py +0 -0
  24. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/_utils/__init__.py +0 -0
  25. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/_utils/async_utils.py +0 -0
  26. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/_utils/auth_utils.py +0 -0
  27. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/_utils/console_utils.py +0 -0
  28. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/_utils/deploy_utils.py +0 -0
  29. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/_utils/local_runner.py +0 -0
  30. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/api.py +0 -0
  31. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/cli/__init__.py +0 -0
  32. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/cli/api.py +0 -0
  33. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/cli/commands/__init__.py +0 -0
  34. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/cli/commands/auth.py +0 -0
  35. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/cli/commands/deploy.py +0 -0
  36. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/cli/commands/init.py +0 -0
  37. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/cli/commands/organizations.py +0 -0
  38. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/cli/commands/run.py +0 -0
  39. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/cli/commands/secrets.py +0 -0
  40. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/cli/config.py +0 -0
  41. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/cli/entry_point.py +0 -0
  42. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/config.py +0 -0
  43. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/exception.py +0 -0
  44. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/py.typed +0 -0
  45. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud/session.py +0 -0
  46. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud.egg-info/dependency_links.txt +0 -0
  47. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud.egg-info/entry_points.txt +0 -0
  48. {pipecatcloud-0.2.1 → pipecatcloud-0.2.3}/src/pipecatcloud.egg-info/top_level.txt +0 -0
@@ -5,10 +5,53 @@ All notable changes to **Pipecat Cloud** will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [Unreleased]
8
+ ## [0.2.3] - 2025-08-19
9
9
 
10
+ ### Fixed
11
+
12
+ - Fixed an issue where DailySessionArguments required positional args for
13
+ `handle_sigint`, `handle_sigterm`, and `pipeline_idle_timeout_secs`.
14
+
15
+ ## [0.2.2] - 2025-08-18
16
+
17
+ ### Added
18
+
19
+ - Added `RunnerArguments` as a fallback type in the event that the Pipecat
20
+ development runner is not imported.
21
+
22
+ ### Changed
23
+
24
+ - Updated the `typer` dependency to support a range of versions in order to
25
+ resolve conflicts with other packages. The new range supported is:
26
+ `"typer>=0.15.3,<0.17.0"`.
27
+
28
+ - Relaxed the package requirements for `python-dotenv` and `uvicorn` to make it
29
+ easier to work with Pipecat Cloud. The new supported versions are:
30
+
31
+ - `"python-dotenv>=1.0.1,<2.0.0"`
32
+ - `"uvicorn>=0.32.0,<1.0.0"`
33
+
34
+ - Updated all types to inherit from `RunnerArguments` to align the types with
35
+ the Pipecat development runner types. This adds types:
36
+
37
+ - `handle_sigint`
38
+ - `handle_sigterm`
39
+ - `pipeline_idle_timeout_secs`
40
+
41
+ ### Fixed
42
+
43
+ - Fixed `ZeroDivisionError` in `agent sessions` command when calculating
44
+ metrics for agents with zero sessions.
45
+
46
+ - Fixed `UnboundLocalError` in `agent sessions` command where
47
+ `metric_renderables` was referenced before assignment due to earlier logic
48
+ failures.
49
+
50
+ - `agent sessions` command previously threw `AttributeError` when no agent name
51
+ was provided via command line or `pcc-deploy.toml`, it now exits gracefully
52
+ with a clear error message.
10
53
 
11
- ## [0.2.1] - 2025-08-02
54
+ ## [0.2.1] - 2025-08-02
12
55
 
13
56
  ### Added
14
57
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pipecatcloud
3
- Version: 0.2.1
3
+ Version: 0.2.3
4
4
  Summary: Cloud hosting for Pipecat AI applications
5
5
  License: BSD 2-Clause License
6
6
  Project-URL: Website, https://docs.pipecat.daily.co/
@@ -11,14 +11,14 @@ License-File: LICENSE
11
11
  Requires-Dist: aiohttp<4.0.0,>=3.11.12
12
12
  Requires-Dist: fastapi<0.117.0,>=0.115.6
13
13
  Requires-Dist: loguru~=0.7.3
14
- Requires-Dist: python-dotenv~=1.0.1
15
- Requires-Dist: uvicorn~=0.32.0
16
- Requires-Dist: typer~=0.15.3
14
+ Requires-Dist: python-dotenv<2.0.0,>=1.0.1
15
+ Requires-Dist: uvicorn<1.0.0,>=0.32.0
16
+ Requires-Dist: typer<0.17.0,>=0.15.3
17
17
  Requires-Dist: synchronicity~=0.7.6
18
18
  Requires-Dist: toml~=0.10.2
19
19
  Requires-Dist: questionary~=2.1.0
20
20
  Provides-Extra: pipecat
21
- Requires-Dist: pipecat-ai>=0.0.77; extra == "pipecat"
21
+ Requires-Dist: pipecat-ai>=0.0.79; extra == "pipecat"
22
22
  Dynamic: license-file
23
23
 
24
24
  <h1><div align="center">
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pipecatcloud"
7
- version = "0.2.1"
7
+ version = "0.2.3"
8
8
  requires-python = ">=3.10"
9
9
  description = "Cloud hosting for Pipecat AI applications"
10
10
  license = { text = "BSD 2-Clause License" }
@@ -14,16 +14,16 @@ dependencies = [
14
14
  "aiohttp>=3.11.12,<4.0.0",
15
15
  "fastapi>=0.115.6,<0.117.0",
16
16
  "loguru~=0.7.3",
17
- "python-dotenv~=1.0.1",
18
- "uvicorn~=0.32.0",
19
- "typer~=0.15.3",
17
+ "python-dotenv>=1.0.1,<2.0.0",
18
+ "uvicorn>=0.32.0,<1.0.0",
19
+ "typer>=0.15.3,<0.17.0",
20
20
  "synchronicity~=0.7.6",
21
21
  "toml~=0.10.2",
22
22
  "questionary~=2.1.0"
23
23
  ]
24
24
 
25
25
  [project.optional-dependencies]
26
- pipecat = ["pipecat-ai>=0.0.77"]
26
+ pipecat = ["pipecat-ai>=0.0.79"]
27
27
 
28
28
  [project.scripts]
29
29
  pcc = "pipecatcloud.__main__:main"
@@ -0,0 +1,14 @@
1
+ [tool:pytest]
2
+ # Basic pytest configuration
3
+
4
+ testpaths = tests
5
+ python_files = test_*.py
6
+ # Modern import mode for better import control with src/ layout
7
+ addopts = --import-mode=importlib
8
+
9
+ # Async support for CLI command tests
10
+ asyncio_mode = auto
11
+
12
+ # Markers actually used in tests
13
+ markers =
14
+ asyncio: mark test as async test
@@ -5,7 +5,7 @@
5
5
  #
6
6
 
7
7
  import warnings
8
- from dataclasses import dataclass
8
+ from dataclasses import dataclass, field
9
9
  from typing import Any, Optional
10
10
 
11
11
  from fastapi import WebSocket
@@ -14,6 +14,7 @@ from fastapi import WebSocket
14
14
  try:
15
15
  from pipecat.runner.types import (
16
16
  DailyRunnerArguments,
17
+ RunnerArguments,
17
18
  WebSocketRunnerArguments,
18
19
  )
19
20
 
@@ -23,7 +24,25 @@ except ImportError:
23
24
 
24
25
  # Fallback definitions
25
26
  @dataclass
26
- class DailyRunnerArguments:
27
+ class RunnerArguments:
28
+ """Base class for runner session arguments.
29
+
30
+ .. deprecated:: 0.2.2
31
+ Install pipecatcloud[pipecat] for better compatibility. This class
32
+ will be removed in a future release.
33
+ """
34
+
35
+ handle_sigint: bool = field(init=False)
36
+ handle_sigterm: bool = field(init=False)
37
+ pipeline_idle_timeout_secs: int = field(init=False)
38
+
39
+ def __post_init__(self):
40
+ self.handle_sigint = False
41
+ self.handle_sigterm = False
42
+ self.pipeline_idle_timeout_secs = 300
43
+
44
+ @dataclass
45
+ class DailyRunnerArguments(RunnerArguments):
27
46
  """Fallback Daily runner arguments when pipecat-ai not available.
28
47
 
29
48
  .. deprecated:: 0.2.1
@@ -35,7 +54,7 @@ except ImportError:
35
54
  body: Any
36
55
 
37
56
  @dataclass
38
- class WebSocketRunnerArguments:
57
+ class WebSocketRunnerArguments(RunnerArguments):
39
58
  """Fallback WebSocket runner arguments when pipecat-ai not available.
40
59
 
41
60
  .. deprecated:: 0.2.1
@@ -72,13 +91,13 @@ class SessionArguments:
72
91
 
73
92
 
74
93
  @dataclass
75
- class PipecatSessionArguments(SessionArguments):
94
+ class PipecatSessionArguments(RunnerArguments, SessionArguments):
76
95
  """Standard Pipecat Cloud agent session arguments.
77
96
 
78
- The arguments are received by the bot() entry point.
97
+ Inherits from RunnerArguments for compatibility with pipecat-ai runner.
98
+ When pipecat-ai is not installed, uses a fallback implementation (deprecated).
79
99
 
80
- Parameters:
81
- body (Any): The body of the request.
100
+ For best compatibility, install: pip install pipecatcloud[pipecat]
82
101
  """
83
102
 
84
103
  body: Any
@@ -95,6 +114,7 @@ class DailySessionArguments(DailyRunnerArguments, SessionArguments):
95
114
  """
96
115
 
97
116
  def __post_init__(self):
117
+ DailyRunnerArguments.__post_init__(self)
98
118
  _warn_standalone_usage()
99
119
 
100
120
 
@@ -109,4 +129,5 @@ class WebSocketSessionArguments(WebSocketRunnerArguments, SessionArguments):
109
129
  """
110
130
 
111
131
  def __post_init__(self):
132
+ WebSocketRunnerArguments.__post_init__(self)
112
133
  _warn_standalone_usage()
@@ -220,7 +220,14 @@ async def sessions(
220
220
  ),
221
221
  ):
222
222
  org = organization or config.get("org")
223
- agent_name = agent_name or deploy_config.agent_name
223
+
224
+ # Get agent name from argument or deploy config
225
+ if not agent_name:
226
+ if deploy_config and deploy_config.agent_name:
227
+ agent_name = deploy_config.agent_name
228
+ else:
229
+ console.error("No target agent name provided")
230
+ return typer.Exit(1)
224
231
 
225
232
  with Live(
226
233
  console.status(f"[dim]Looking up agent with name '{agent_name}'[/dim]", spinner="dots")
@@ -257,9 +264,10 @@ async def sessions(
257
264
  bot_start_metrics = calculate_percentiles(bot_start_times)
258
265
  duration_metrics = calculate_percentiles(durations)
259
266
  cold_starts_count = sum(1 for s in sessions_list if s.get("coldStart") is True)
260
- cold_start_percent = cold_starts_count / total_sessions * 100
267
+ metric_renderables = [] # Initialize to empty list for type consistency
261
268
 
262
269
  if duration_metrics and bot_start_metrics and total_sessions > 0:
270
+ cold_start_percent = cold_starts_count / total_sessions * 100
263
271
  metric_renderables = [
264
272
  Panel(
265
273
  f"[bold]Total Sessions:[/bold]\n{total_sessions}\n ",
@@ -289,6 +297,11 @@ async def sessions(
289
297
  table.add_column("Cold Start")
290
298
 
291
299
  for session in data.get("sessions", []):
300
+ # Note: session["sessionId"] is accessed without defensive checks.
301
+ # If the API returns malformed data missing sessionId, the CLI will crash with
302
+ # a KeyError rather than silently skip sessions. This ensures smoke tests and
303
+ # API verification catch breaking changes immediately. We could instead use
304
+ # console.error() and skip the session but its unclear if thats better..
292
305
  if session_id and session["sessionId"] != session_id:
293
306
  continue
294
307
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pipecatcloud
3
- Version: 0.2.1
3
+ Version: 0.2.3
4
4
  Summary: Cloud hosting for Pipecat AI applications
5
5
  License: BSD 2-Clause License
6
6
  Project-URL: Website, https://docs.pipecat.daily.co/
@@ -11,14 +11,14 @@ License-File: LICENSE
11
11
  Requires-Dist: aiohttp<4.0.0,>=3.11.12
12
12
  Requires-Dist: fastapi<0.117.0,>=0.115.6
13
13
  Requires-Dist: loguru~=0.7.3
14
- Requires-Dist: python-dotenv~=1.0.1
15
- Requires-Dist: uvicorn~=0.32.0
16
- Requires-Dist: typer~=0.15.3
14
+ Requires-Dist: python-dotenv<2.0.0,>=1.0.1
15
+ Requires-Dist: uvicorn<1.0.0,>=0.32.0
16
+ Requires-Dist: typer<0.17.0,>=0.15.3
17
17
  Requires-Dist: synchronicity~=0.7.6
18
18
  Requires-Dist: toml~=0.10.2
19
19
  Requires-Dist: questionary~=2.1.0
20
20
  Provides-Extra: pipecat
21
- Requires-Dist: pipecat-ai>=0.0.77; extra == "pipecat"
21
+ Requires-Dist: pipecat-ai>=0.0.79; extra == "pipecat"
22
22
  Dynamic: license-file
23
23
 
24
24
  <h1><div align="center">
@@ -5,6 +5,7 @@ README.md
5
5
  dev-requirements.txt
6
6
  pipecat-cloud.png
7
7
  pyproject.toml
8
+ pytest.ini
8
9
  .github/workflows/publish-pypi.yml
9
10
  .github/workflows/publish-test.yml
10
11
  .github/workflows/python-publish.yml
@@ -40,4 +41,6 @@ src/pipecatcloud/cli/commands/deploy.py
40
41
  src/pipecatcloud/cli/commands/init.py
41
42
  src/pipecatcloud/cli/commands/organizations.py
42
43
  src/pipecatcloud/cli/commands/run.py
43
- src/pipecatcloud/cli/commands/secrets.py
44
+ src/pipecatcloud/cli/commands/secrets.py
45
+ tests/__init__.py
46
+ tests/test_agent_sessions.py
@@ -1,12 +1,12 @@
1
1
  aiohttp<4.0.0,>=3.11.12
2
2
  fastapi<0.117.0,>=0.115.6
3
3
  loguru~=0.7.3
4
- python-dotenv~=1.0.1
5
- uvicorn~=0.32.0
6
- typer~=0.15.3
4
+ python-dotenv<2.0.0,>=1.0.1
5
+ uvicorn<1.0.0,>=0.32.0
6
+ typer<0.17.0,>=0.15.3
7
7
  synchronicity~=0.7.6
8
8
  toml~=0.10.2
9
9
  questionary~=2.1.0
10
10
 
11
11
  [pipecat]
12
- pipecat-ai>=0.0.77
12
+ pipecat-ai>=0.0.79
@@ -0,0 +1 @@
1
+ # Test package for pipecatcloud
@@ -0,0 +1,70 @@
1
+ """
2
+ Unit tests for the 'pcc agent sessions' command.
3
+
4
+ Tests focus on core behaviors and edge cases, not implementation details.
5
+ """
6
+
7
+ import pytest
8
+ from unittest.mock import patch
9
+ import typer
10
+
11
+ # Import the function under test from local source
12
+ from src.pipecatcloud.cli.commands.agent import sessions
13
+
14
+ # Test constants
15
+ TEST_ORG = "test-org"
16
+ TEST_AGENT = "test-agent"
17
+
18
+
19
+ class TestAgentSessionsCommand:
20
+ """Test the 'pcc agent sessions' command behaviors."""
21
+
22
+ @pytest.fixture
23
+ def mock_api(self):
24
+ """Mock the underlying API agent_sessions method."""
25
+ with patch('src.pipecatcloud.cli.commands.agent.API._agent_sessions') as mock_api:
26
+ yield mock_api
27
+
28
+ def test_handles_zero_sessions_without_crash(self, mock_api):
29
+ """Agent with zero sessions should not cause ZeroDivisionError."""
30
+ # Arrange: API returns empty sessions list
31
+ empty_sessions_response = {"sessions": []}
32
+ mock_api.return_value = empty_sessions_response
33
+
34
+ # Act & Assert: Should complete without ZeroDivisionError
35
+ sessions(
36
+ deploy_config=None,
37
+ agent_name=TEST_AGENT,
38
+ session_id=None,
39
+ organization=TEST_ORG
40
+ )
41
+
42
+ def test_handles_api_error_gracefully(self, mock_api):
43
+ """API errors should be handled without crashing."""
44
+ # Arrange: _agent_sessions raises exception (API error)
45
+ mock_api.side_effect = Exception("Agent not found")
46
+
47
+ # Act: Call with API error
48
+ result = sessions(
49
+ deploy_config=None,
50
+ agent_name="nonexistent-agent",
51
+ session_id=None,
52
+ organization=TEST_ORG
53
+ )
54
+
55
+ # Assert: Should return typer.Exit on error
56
+ assert isinstance(result, type(typer.Exit()))
57
+
58
+ def test_handles_missing_agent_name_gracefully(self):
59
+ """Command should exit gracefully when no agent name is provided."""
60
+ # Act: Call with no agent name from either source
61
+ result = sessions(
62
+ deploy_config=None, # No deploy config
63
+ agent_name=None, # No agent name argument
64
+ session_id=None,
65
+ organization=TEST_ORG
66
+ )
67
+
68
+ # Assert: Should return typer.Exit(1) with error message
69
+ assert isinstance(result, type(typer.Exit()))
70
+ assert result.exit_code == 1
File without changes
File without changes
File without changes
File without changes