pipecatcloud 0.0.9__tar.gz → 0.0.11__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 (51) hide show
  1. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11/.github/workflows}/publish-pypi.yml +1 -1
  2. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11/.github/workflows}/publish-test.yml +1 -1
  3. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/.github/workflows/python-publish.yml +0 -37
  4. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/CHANGELOG.md +149 -49
  5. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/PKG-INFO +21 -11
  6. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/README.md +20 -10
  7. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/pyproject.toml +1 -1
  8. pipecatcloud-0.0.11/src/pipecatcloud/__init__.py +39 -0
  9. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud/__main__.py +6 -0
  10. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud/__version__.py +6 -0
  11. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud/_utils/async_utils.py +6 -0
  12. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud/_utils/auth_utils.py +7 -0
  13. pipecatcloud-0.0.11/src/pipecatcloud/_utils/console_utils.py +141 -0
  14. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud/_utils/deploy_utils.py +13 -15
  15. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud/_utils/local_runner.py +6 -5
  16. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud/api.py +42 -15
  17. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud/cli/__init__.py +6 -0
  18. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud/cli/api.py +6 -0
  19. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud/cli/commands/agent.py +172 -148
  20. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud/cli/commands/auth.py +41 -19
  21. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud/cli/commands/deploy.py +85 -77
  22. pipecatcloud-0.0.11/src/pipecatcloud/cli/commands/init.py +124 -0
  23. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud/cli/commands/organizations.py +72 -42
  24. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud/cli/commands/run.py +7 -0
  25. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud/cli/commands/secrets.py +133 -114
  26. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud/cli/config.py +14 -5
  27. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud/cli/entry_point.py +10 -2
  28. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud/config.py +10 -1
  29. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud/exception.py +24 -16
  30. pipecatcloud-0.0.11/src/pipecatcloud/session.py +104 -0
  31. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud.egg-info/PKG-INFO +21 -11
  32. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud.egg-info/SOURCES.txt +0 -2
  33. pipecatcloud-0.0.9/src/pipecatcloud/__init__.py +0 -7
  34. pipecatcloud-0.0.9/src/pipecatcloud/_utils/agent_utils.py +0 -9
  35. pipecatcloud-0.0.9/src/pipecatcloud/_utils/console_utils.py +0 -78
  36. pipecatcloud-0.0.9/src/pipecatcloud/cli/commands/init.py +0 -16
  37. pipecatcloud-0.0.9/src/pipecatcloud/errors.py +0 -11
  38. pipecatcloud-0.0.9/src/pipecatcloud/session.py +0 -59
  39. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/.gitignore +0 -0
  40. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/LICENSE +0 -0
  41. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/dev-requirements.txt +0 -0
  42. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/pipecat-cloud.png +0 -0
  43. {pipecatcloud-0.0.9/.github/workflows → pipecatcloud-0.0.11}/publish-pypi.yml +0 -0
  44. {pipecatcloud-0.0.9/.github/workflows → pipecatcloud-0.0.11}/publish-test.yml +0 -0
  45. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/setup.cfg +0 -0
  46. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud/_utils/__init__.py +0 -0
  47. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud/cli/commands/__init__.py +0 -0
  48. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud.egg-info/dependency_links.txt +0 -0
  49. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud.egg-info/entry_points.txt +0 -0
  50. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud.egg-info/requires.txt +0 -0
  51. {pipecatcloud-0.0.9 → pipecatcloud-0.0.11}/src/pipecatcloud.egg-info/top_level.txt +0 -0
@@ -39,7 +39,7 @@ jobs:
39
39
  - name: Install dependencies
40
40
  run: |
41
41
  python -m pip install --upgrade pip
42
- pip install -r requirements.txt
42
+ pip install -r dev-requirements.txt
43
43
  pip install build twine
44
44
 
45
45
  - name: Build package
@@ -39,7 +39,7 @@ jobs:
39
39
  - name: Install dependencies
40
40
  run: |
41
41
  python -m pip install --upgrade pip
42
- pip install -r requirements.txt
42
+ pip install -r dev-requirements.txt
43
43
  pip install build twine
44
44
 
45
45
  - name: Build package
@@ -38,40 +38,3 @@ jobs:
38
38
  with:
39
39
  name: release-dists
40
40
  path: dist/
41
-
42
- pypi-publish:
43
- runs-on: ubuntu-latest
44
- needs:
45
- - release-build
46
- permissions:
47
- id-token: write
48
- contents: read
49
-
50
- environment:
51
- name: pypi
52
- url: https://pypi.org/p/pipecat-cloud
53
-
54
- steps:
55
- - uses: actions/checkout@v4
56
-
57
- - name: Retrieve release distributions
58
- uses: actions/download-artifact@v4
59
- with:
60
- name: release-dists
61
- path: dist/
62
-
63
- - name: Publish release distributions to PyPI
64
- uses: pypa/gh-action-pypi-publish@release/v1
65
- with:
66
- packages-dir: dist/
67
-
68
- - name: Create GitHub Release
69
- uses: softprops/action-gh-release@v2
70
- with:
71
- tag_name: ${{ github.ref }}
72
- name: Release ${{ github.ref_name }}
73
- draft: false
74
- prerelease: false
75
- files: |
76
- dist/*.tar.gz
77
- dist/*.whl
@@ -5,84 +5,184 @@ 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
+ ## [0.0.11] - 2025-03-04
9
+
10
+ ### Changed
11
+
12
+ - `session.py` now returns the response body from the `start()` method.
13
+
14
+ ### Fixed
15
+
16
+ - Fixed an issue in `session.py` where a bot wouldn't start due to malformed
17
+ `data`.
18
+
19
+ ## [0.0.10] - 2025-03-04
20
+
21
+ ### Added
22
+
23
+ - `init` convenience command will now populate the working directory with files
24
+ from the starter project.
25
+
26
+ - `agent log` allows for optional severity level filtering.
27
+
28
+ ### Changed
29
+
30
+ - `agent status` and `deploy` no longer show superfluous data.
31
+
32
+ - `session.py` now correctly handles errors when starting agents.
33
+
34
+ - `secrets set` no longer prompts twice for confirmation if the secret set does
35
+ not exist.
36
+
37
+ ### Removed
38
+
39
+ - `errors.py` removed as redundant (error message and code returned via API).
40
+
41
+ - `agent_utils.py` removed as redundant (error message and code returned via
42
+ API).
43
+
8
44
  ## [0.0.9] - 2025-02-27
9
45
 
10
46
  ### Added
11
- - `agent status [agent-name]` now shows deployment info and scaling configuration
12
- - `agent sessions [agent-name]` lists active session count for an agent (will list session details in future)
13
- - `agent start [agent-name] -D` now shows the Daily room URL (and token) to join in the terminal output
47
+
48
+ - `agent status [agent-name]` now shows deployment info and scaling
49
+ configuration.
50
+
51
+ - `agent sessions [agent-name]` lists active session count for an agent (will
52
+ list session details in future).
53
+
54
+ - `agent start [agent-name] -D` now shows the Daily room URL (and token) to
55
+ join in the terminal output.
14
56
 
15
57
  ### Changed
16
- - Changed CLI command from `pipecat` to `pipecatcloud` or `pcc`
17
- - `agent delete` prompts the user for confirmation first
18
- - `agent start` now checks the target deployment first to ensure it exists and is in a healthy state
19
- - Changed the information order of `agent status` so the health badge is clearly visible in terminal
20
- - `agent deploy` now defaults to "Y" for the confirmation prompts
58
+
59
+ - Changed CLI command from `pipecat` to `pipecatcloud` or `pcc`.
60
+
61
+ - `agent delete` prompts the user for confirmation first.
62
+
63
+ - `agent start` now checks the target deployment first to ensure it exists and
64
+ is in a healthy state.
65
+
66
+ - Changed the information order of `agent status` so the health badge is
67
+ clearly visible in terminal.
68
+
69
+ - `agent deploy` now defaults to "Y" for the confirmation prompts.
21
70
 
22
71
  ### Fixed
23
- - Fixed lint error with payload data in `agent start`
24
- - Fixed a bug where `pcc-deploy.toml` files were required to be present
25
- - `deploy` command now correctly passes the secret set to the deployment from the `pcc-deploy.toml` file
72
+
73
+ - Fixed lint error with payload data in `agent start`.
74
+
75
+ - Fixed a bug where `pcc-deploy.toml` files were required to be present.
76
+
77
+ - `deploy` command now correctly passes the secret set to the deployment from
78
+ the `pcc-deploy.toml` file.
26
79
 
27
80
  ## [0.0.8] - 2025-02-03
28
81
 
29
82
  ### Added
30
- - `secrets set [set-name] --file` allowing you to create a secret set from .env file
31
- - `agent scale` to modify agent configuration without pushing a new image
32
- - `run` command for running bot.py files locally via FastAPI. This initial implementation is very basic and will be expanded in the future.
33
- - `organizations select` allows passing an `--org / -o` option to bypass prompt
83
+
84
+ - `secrets set [set-name] --file` allowing you to create a secret set from .env
85
+ file.
86
+
87
+ - `agent scale` to modify agent configuration without pushing a new image.
88
+
89
+ - `run` command for running bot.py files locally via FastAPI. This initial
90
+ implementation is very basic and will be expanded in the future.
91
+
92
+ - `organizations select` allows passing an `--org / -o` option to bypass
93
+ prompt.
34
94
 
35
95
  ### Fixed
36
- - All commands use the correct shorthand flag syntax (`-` vs. `--`)
37
- - CLI config extends from module config to avoid loading config TOML with package imports
38
- - `secrets list` now correctly lists all secrets vs. just a single entry
39
- - `deploy` command displays live status to prevent skewed terminal output
40
- - `deploy` command no longer allows pushing images without a tag
41
- - `agent logs` paginate / filter / sort and tidy up display for logs
42
- - `start` command correctly clears the live terminal text
43
- - `pcc-deploy.toml` files now work as intended with `deploy` command
44
- - `deploy` method now passes configuration parameters correctly
45
- - Switching organizations will fully remove any default API tokens from the previously selected organization
96
+
97
+ - All commands use the correct shorthand flag syntax (`-` vs. `--`).
98
+
99
+ - CLI config extends from module config to avoid loading config TOML with
100
+ package imports.
101
+
102
+ - `secrets list` now correctly lists all secrets vs. just a single entry.
103
+
104
+ - `deploy` command displays live status to prevent skewed terminal output.
105
+
106
+ - `deploy` command no longer allows pushing images without a tag.
107
+
108
+ - `agent logs` paginate / filter / sort and tidy up display for logs.
109
+
110
+ - `start` command correctly clears the live terminal text.
111
+
112
+ - `pcc-deploy.toml` files now work as intended with `deploy` command.
113
+
114
+ - `deploy` method now passes configuration parameters correctly.
115
+
116
+ - Switching organizations will fully remove any default API tokens from the
117
+ previously selected organization.
46
118
 
47
119
  ### Changed
48
- - Local config now retains default keys when switching between organizations
49
- - Local config now retains defaukt keys when logging in again
50
- - `deploy` will check passed secret set exists before deployment
51
- - `secrets list` now takes an optional `--sets / -s` parameter that filters by secret sets or image pull secrets
52
- - `organizations keys create` now prompts you to set the newly created key as the default after creation (if active org matches)
53
- - `organizations keys delete` not prompts to confirm if selected key is currently your local config default
54
- - `Agent` module import has been renamed to `Session` to better reflect API
55
120
 
121
+ - Local config now retains default keys when switching between organizations.
122
+
123
+ - Local config now retains defaukt keys when logging in again.
124
+
125
+ - `deploy` will check passed secret set exists before deployment.
126
+
127
+ - `secrets list` now takes an optional `--sets / -s` parameter that filters by
128
+ secret sets or image pull secrets.
129
+
130
+ - `organizations keys create` now prompts you to set the newly created key as
131
+ the default after creation (if active org matches).
132
+
133
+ - `organizations keys delete` not prompts to confirm if selected key is
134
+ currently your local config default.
135
+
136
+ - `Agent` module import has been renamed to `Session` to better reflect API.
56
137
 
57
138
  ## [0.0.7] - 2025-02-01
58
139
 
59
140
  ### Added
60
141
 
61
- - `run` command for running an agent locally. This initial implementation is very basic and will be expanded in the future.
142
+ - `run` command for running an agent locally. This initial implementation is
143
+ very basic and will be expanded in the future.
62
144
 
63
145
  ### Changed
64
146
 
65
- - `start_agent` method no longer requires an organization. If not provided, it will assume the namespace of the API token owner.
66
- - `start` command no longer looks up the agent before starting (health check is handled by the proxy route.)
147
+ - `start_agent` method no longer requires an organization. If not provided, it
148
+ will assume the namespace of the API token owner.
149
+
150
+ - `start` command no longer looks up the agent before starting (health check is
151
+ handled by the proxy route).
67
152
 
68
153
  ## [0.0.6] - 2025-02-01
69
154
 
70
155
  ### Added
71
156
 
72
- - `pipecatcloud.agent` module for working with agents via Python scripts
73
- - `start_agent` method for starting an agent
157
+ - `pipecatcloud.agent` module for working with agents via Python scripts.
158
+
159
+ - `start_agent` method for starting an agent.
74
160
 
75
161
  ### Backlog
76
162
 
77
- - `deploy` make image pull secrets non-optional, but allow for bypassing
78
- - Fix: update docs to assert that the bot method must be async
79
- - Fix: Secrets are not upserting (overriding each time, which may be preferrable?)
80
- - Fix: deployment process needs better output
81
- - `organizations keys create` should ask if you'd like to set the created key as default after creation (if org matches)
82
- - Sense check image parameter of the deploy command (does it have a tag, etc)
83
- - `agent logs` paginate / filter / sort and tidy up display for logs
84
- - Fix: start command should clear the live text
85
- - Secrets from .env method
86
- - Fix: .pcc-deploy.toml should read correctly
87
- - New conveience method to add account associated Daily API Key to a secret set
88
- - Add: concurrency support for agent deployments
163
+ - `deploy` make image pull secrets non-optional, but allow for bypassing.
164
+
165
+ - Fix: update docs to assert that the bot method must be async.
166
+
167
+ - Fix: Secrets are not upserting (overriding each time, which may be.
168
+ preferable?).
169
+
170
+ - Fix: deployment process needs better output.
171
+
172
+ - `organizations keys create` should ask if you'd like to set the created key
173
+ as default after creation (if org matches).
174
+
175
+ - Sense check image parameter of the deploy command (does it have a tag, etc).
176
+
177
+ - `agent logs` paginate / filter / sort and tidy up display for logs.
178
+
179
+ - Fix: start command should clear the live text.
180
+
181
+ - Secrets from .env method.
182
+
183
+ - Fix: .pcc-deploy.toml should read correctly.
184
+
185
+ - New convenience method to add account associated Daily API Key to a secret
186
+ set.
187
+
188
+ - Add: concurrency support for agent deployments.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pipecatcloud
3
- Version: 0.0.9
3
+ Version: 0.0.11
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/
@@ -70,16 +70,26 @@ pcc auth login
70
70
 
71
71
  ### Usage in Python scripts
72
72
 
73
- If want to programmatically start an agent within a Python script, you can use the `pipecatcloud.agent` module.
73
+ If want to programmatically start an agent within a Python script, you can use the `pipecatcloud.session` module.
74
74
 
75
75
  ```python
76
- from pipecatcloud.agent import Agent
77
-
78
- agent = Agent(
79
- agent_name="your-agent-name",
80
- organization="your-organization",
81
- api_key="your-api-key",
82
- )
83
-
84
- await agent.start()
76
+ from pipecatcloud.session import Session
77
+ from pipecatcloud.exception import AgentStartError
78
+ import asyncio
79
+
80
+ async def main():
81
+ session = Session(
82
+ agent_name="your-agent-name",
83
+ api_key="pk_...",
84
+ )
85
+
86
+ try:
87
+ await session.start()
88
+ except AgentStartError as e:
89
+ print(e)
90
+ except Exception as e:
91
+ raise (e)
92
+
93
+ if __name__ == "__main__":
94
+ asyncio.run(main())
85
95
  ```
@@ -50,16 +50,26 @@ pcc auth login
50
50
 
51
51
  ### Usage in Python scripts
52
52
 
53
- If want to programmatically start an agent within a Python script, you can use the `pipecatcloud.agent` module.
53
+ If want to programmatically start an agent within a Python script, you can use the `pipecatcloud.session` module.
54
54
 
55
55
  ```python
56
- from pipecatcloud.agent import Agent
57
-
58
- agent = Agent(
59
- agent_name="your-agent-name",
60
- organization="your-organization",
61
- api_key="your-api-key",
62
- )
63
-
64
- await agent.start()
56
+ from pipecatcloud.session import Session
57
+ from pipecatcloud.exception import AgentStartError
58
+ import asyncio
59
+
60
+ async def main():
61
+ session = Session(
62
+ agent_name="your-agent-name",
63
+ api_key="pk_...",
64
+ )
65
+
66
+ try:
67
+ await session.start()
68
+ except AgentStartError as e:
69
+ print(e)
70
+ except Exception as e:
71
+ raise (e)
72
+
73
+ if __name__ == "__main__":
74
+ asyncio.run(main())
65
75
  ```
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pipecatcloud"
7
- version = "0.0.9"
7
+ version = "0.0.11"
8
8
  requires-python = ">=3.10"
9
9
  description = "Cloud hosting for Pipecat AI applications"
10
10
  license = { text = "BSD 2-Clause License" }
@@ -0,0 +1,39 @@
1
+ #
2
+ # Copyright (c) 2025, Daily
3
+ #
4
+ # SPDX-License-Identifier: BSD 2-Clause License
5
+ #
6
+
7
+ import os
8
+ import sys
9
+
10
+ from loguru import logger
11
+
12
+ from .exception import (
13
+ AgentNotHealthyError,
14
+ AgentStartError,
15
+ AuthError,
16
+ ConfigError,
17
+ ConfigFileError,
18
+ Error,
19
+ InvalidError,
20
+ )
21
+ from .session import Session, SessionParams
22
+
23
+ logger.remove()
24
+ logger.add(sys.stderr, level=str(os.getenv("PCC_LOG_LEVEL", "INFO")))
25
+
26
+
27
+ __all__ = [
28
+ # Session classes
29
+ "Session",
30
+ "SessionParams",
31
+ # Exception classes
32
+ "Error",
33
+ "ConfigFileError",
34
+ "AuthError",
35
+ "InvalidError",
36
+ "ConfigError",
37
+ "AgentNotHealthyError",
38
+ "AgentStartError",
39
+ ]
@@ -1,3 +1,9 @@
1
+ #
2
+ # Copyright (c) 2025, Daily
3
+ #
4
+ # SPDX-License-Identifier: BSD 2-Clause License
5
+ #
6
+
1
7
  from pipecatcloud.cli.entry_point import entrypoint_cli
2
8
 
3
9
 
@@ -1,3 +1,9 @@
1
+ #
2
+ # Copyright (c) 2025, Daily
3
+ #
4
+ # SPDX-License-Identifier: BSD 2-Clause License
5
+ #
6
+
1
7
  from pathlib import Path
2
8
 
3
9
  import toml
@@ -1,3 +1,9 @@
1
+ #
2
+ # Copyright (c) 2025, Daily
3
+ #
4
+ # SPDX-License-Identifier: BSD 2-Clause License
5
+ #
6
+
1
7
  import inspect
2
8
  from typing import (
3
9
  TypeVar,
@@ -1,3 +1,9 @@
1
+ #
2
+ # Copyright (c) 2025, Daily
3
+ #
4
+ # SPDX-License-Identifier: BSD 2-Clause License
5
+ #
6
+
1
7
  import functools
2
8
 
3
9
  from pipecatcloud._utils.console_utils import console
@@ -16,4 +22,5 @@ def requires_login(func):
16
22
  )
17
23
  return
18
24
  return func(*args, **kwargs)
25
+
19
26
  return wrapper
@@ -0,0 +1,141 @@
1
+ #
2
+ # Copyright (c) 2025, Daily
3
+ #
4
+ # SPDX-License-Identifier: BSD 2-Clause License
5
+ #
6
+
7
+ from typing import Optional, Union
8
+
9
+ from rich.console import Console
10
+ from rich.panel import Panel
11
+
12
+ from pipecatcloud.cli import PANEL_TITLE_ERROR, PANEL_TITLE_SUCCESS, PIPECAT_CLI_NAME
13
+
14
+
15
+ class PipecatConsole(Console):
16
+ def success(
17
+ self,
18
+ message,
19
+ title: Optional[str] = None,
20
+ title_extra: Optional[str] = None,
21
+ subtitle: Optional[str] = None,
22
+ ):
23
+ if not title:
24
+ title = f"{PANEL_TITLE_SUCCESS}{f' - {title_extra}' if title_extra is not None else ''}"
25
+
26
+ self.print(
27
+ Panel(
28
+ message,
29
+ title=f"[bold green]{title}[/bold green]",
30
+ subtitle=subtitle,
31
+ title_align="left",
32
+ subtitle_align="left",
33
+ border_style="green",
34
+ )
35
+ )
36
+
37
+ def error(
38
+ self,
39
+ message,
40
+ title: Optional[str] = None,
41
+ title_extra: Optional[str] = None,
42
+ subtitle: Optional[str] = None,
43
+ ):
44
+ if not title:
45
+ title = f"{PANEL_TITLE_ERROR}{f' - {title_extra}' if title_extra is not None else ''}"
46
+
47
+ self.print(
48
+ Panel(
49
+ message,
50
+ title=f"[bold red]{title}[/bold red]",
51
+ subtitle=subtitle,
52
+ title_align="left",
53
+ subtitle_align="left",
54
+ border_style="red",
55
+ )
56
+ )
57
+
58
+ def cancel(self):
59
+ self.print("[yellow]Cancelled by user[/yellow]")
60
+
61
+ def unauthorized(self):
62
+ self.print(
63
+ Panel(
64
+ f"Unauthorized request / invalid user token.\n\nPlease log in again using [bold cyan]{PIPECAT_CLI_NAME} auth login[/bold cyan]",
65
+ title=f"[bold red]{PANEL_TITLE_ERROR} - Unauthorized (401)[/bold red]",
66
+ subtitle="",
67
+ title_align="left",
68
+ subtitle_align="left",
69
+ border_style="red",
70
+ )
71
+ )
72
+
73
+ def api_error(
74
+ self,
75
+ error_code: Optional[Union[str, dict]] = None,
76
+ title: Optional[str] = "API Error",
77
+ hide_subtitle: bool = False,
78
+ ):
79
+ DEFAULT_ERROR_MESSAGE = "Unknown error. Please contact support."
80
+
81
+ if isinstance(error_code, dict):
82
+ error_message = error_code.get("error", DEFAULT_ERROR_MESSAGE)
83
+ code = error_code.get("code")
84
+ else:
85
+ error_message = str(error_code) if error_code else DEFAULT_ERROR_MESSAGE
86
+ code = None
87
+
88
+ if not error_message:
89
+ hide_subtitle = True
90
+
91
+ self.print(
92
+ Panel(
93
+ f"[red]{title}[/red]\n\n" f"[dim]Error message:[/dim]\n{error_message}",
94
+ title=f"[bold red]{PANEL_TITLE_ERROR}{f' - {code}' if code else ''}[/bold red]",
95
+ subtitle=f"[dim]Docs: https://docs.pipecat.daily.co/agents/error-codes#{code}[/dim]"
96
+ if not hide_subtitle and code
97
+ else None,
98
+ title_align="left",
99
+ subtitle_align="left",
100
+ border_style="red",
101
+ )
102
+ )
103
+
104
+
105
+ console = PipecatConsole()
106
+
107
+
108
+ def format_timestamp(timestamp: str) -> str:
109
+ """
110
+ Format a timestamp string to a more readable format.
111
+ Handles timestamps with variable microsecond precision.
112
+
113
+ Args:
114
+ timestamp (str): The timestamp string in ISO format with microseconds (e.g. "2024-01-01T12:34:56.789Z")
115
+
116
+ Returns:
117
+ str: The formatted timestamp string
118
+ """
119
+ from datetime import datetime
120
+
121
+ # First try parsing the timestamp directly
122
+ try:
123
+ return datetime.strptime(timestamp, "%Y-%m-%dT%H:%M:%S.%fZ").strftime("%Y-%m-%d %H:%M:%S")
124
+ except ValueError:
125
+ pass
126
+
127
+ # Handle case where microseconds have higher precision
128
+ try:
129
+ parts = timestamp.split(".")
130
+ if len(parts) == 2 and parts[1].endswith("Z"):
131
+ # Truncate microseconds to 6 digits
132
+ microseconds = parts[1][:-1][:6].ljust(6, "0")
133
+ normalized = f"{parts[0]}.{microseconds}Z"
134
+ return datetime.strptime(normalized, "%Y-%m-%dT%H:%M:%S.%fZ").strftime(
135
+ "%Y-%m-%d %H:%M:%S"
136
+ )
137
+ except (ValueError, IndexError):
138
+ pass
139
+
140
+ # Return original if parsing fails
141
+ return timestamp