pipecatcloud 0.2.19__tar.gz → 0.2.20__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 (60) hide show
  1. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/CHANGELOG.md +9 -0
  2. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/PKG-INFO +1 -1
  3. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/cli/commands/auth.py +69 -32
  4. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/cli/config.py +20 -0
  5. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud.egg-info/PKG-INFO +1 -1
  6. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/.github/workflows/format.yml +0 -0
  7. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/.github/workflows/publish-pypi.yml +0 -0
  8. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/.github/workflows/publish-test.yml +0 -0
  9. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/.github/workflows/tests.yml +0 -0
  10. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/.gitignore +0 -0
  11. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/.pre-commit-config.yaml +0 -0
  12. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/LICENSE +0 -0
  13. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/README.md +0 -0
  14. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/pipecat-cloud.png +0 -0
  15. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/pyproject.toml +0 -0
  16. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/pytest.ini +0 -0
  17. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/scripts/fix-ruff.sh +0 -0
  18. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/scripts/pre-commit.sh +0 -0
  19. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/setup.cfg +0 -0
  20. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/__init__.py +0 -0
  21. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/__main__.py +0 -0
  22. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/__version__.py +0 -0
  23. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/_utils/__init__.py +0 -0
  24. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/_utils/async_utils.py +0 -0
  25. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/_utils/auth_utils.py +0 -0
  26. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/_utils/console_utils.py +0 -0
  27. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/_utils/deploy_utils.py +0 -0
  28. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/_utils/regions.py +0 -0
  29. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/agent.py +0 -0
  30. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/api.py +0 -0
  31. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/cli/__init__.py +0 -0
  32. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/cli/api.py +0 -0
  33. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/cli/commands/__init__.py +0 -0
  34. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/cli/commands/agent.py +0 -0
  35. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/cli/commands/deploy.py +0 -0
  36. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/cli/commands/docker.py +0 -0
  37. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/cli/commands/organizations.py +0 -0
  38. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/cli/commands/regions.py +0 -0
  39. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/cli/commands/secrets.py +0 -0
  40. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/cli/entry_point.py +0 -0
  41. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/config.py +0 -0
  42. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/constants.py +0 -0
  43. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/exception.py +0 -0
  44. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/py.typed +0 -0
  45. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/session.py +0 -0
  46. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud/smallwebrtc/session_manager.py +0 -0
  47. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud.egg-info/SOURCES.txt +0 -0
  48. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud.egg-info/dependency_links.txt +0 -0
  49. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud.egg-info/entry_points.txt +0 -0
  50. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud.egg-info/requires.txt +0 -0
  51. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/src/pipecatcloud.egg-info/top_level.txt +0 -0
  52. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/tests/__init__.py +0 -0
  53. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/tests/test_agent_sessions.py +0 -0
  54. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/tests/test_agent_stop.py +0 -0
  55. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/tests/test_api_client.py +0 -0
  56. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/tests/test_docker_commands.py +0 -0
  57. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/tests/test_krisp_viva.py +0 -0
  58. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/tests/test_managed_keys.py +0 -0
  59. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/tests/test_regions.py +0 -0
  60. {pipecatcloud-0.2.19 → pipecatcloud-0.2.20}/uv.lock +0 -0
@@ -5,6 +5,15 @@ 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.2.20] - 2026-02-11
9
+
10
+ ### Fixed
11
+
12
+ - Fixed `auth login --headless` to be fully non-interactive by using plain text
13
+ output instead of Rich terminal widgets, enabling use in environments like
14
+ Claude Code and CI/CD pipelines.
15
+
16
+
8
17
  ## [0.2.19] - 2026-01-27
9
18
 
10
19
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pipecatcloud
3
- Version: 0.2.19
3
+ Version: 0.2.20
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/
@@ -161,17 +161,22 @@ async def login(
161
161
  return
162
162
 
163
163
  # Display the authentication URL and code
164
- console.print(
165
- Panel(
166
- "[bold]To authenticate with Pipecat Cloud:[/bold]\n\n"
167
- "Visit this URL:\n"
168
- f"[blue][link={web_url}]{web_url}[/link][/blue]\n\n"
169
- "Then enter this code:\n"
170
- f"[cyan bold]{code}[/cyan bold]",
171
- title="[bold]Authentication Required[/bold]",
172
- border_style="blue",
164
+ if headless:
165
+ print("\nTo authenticate with Pipecat Cloud:\n", flush=True)
166
+ print(f" Visit this URL: {web_url}", flush=True)
167
+ print(f" Then enter this code: {code}\n", flush=True)
168
+ else:
169
+ console.print(
170
+ Panel(
171
+ "[bold]To authenticate with Pipecat Cloud:[/bold]\n\n"
172
+ "Visit this URL:\n"
173
+ f"[blue][link={web_url}]{web_url}[/link][/blue]\n\n"
174
+ "Then enter this code:\n"
175
+ f"[cyan bold]{code}[/cyan bold]",
176
+ title="[bold]Authentication Required[/bold]",
177
+ border_style="blue",
178
+ )
173
179
  )
174
- )
175
180
 
176
181
  # Prompt user to open the browser (unless in headless mode)
177
182
  if not headless:
@@ -185,44 +190,76 @@ async def login(
185
190
  return typer.Exit()
186
191
  _open_url(web_url)
187
192
 
188
- with Live(
189
- console.status(
190
- "[dim]Waiting for authentication to complete...[/dim]", spinner="dots"
191
- ),
192
- transient=True,
193
- ) as live:
193
+ if headless:
194
+ print("Waiting for authentication to complete...", flush=True)
194
195
  for attempt in itertools.count():
195
196
  result = await auth_flow.finish()
196
197
  if result is not None:
197
198
  break
198
- live.update(
199
- console.status(
200
- f"[dim]Waiting for authentication to complete... (attempt {attempt + 1})[/dim]"
201
- )
202
- )
203
199
  if result is None:
204
- live.stop()
205
- console.error("Authentication failed")
200
+ print("Error: Authentication failed", flush=True)
206
201
  return typer.Exit()
207
202
 
208
- live.update(console.status("[dim]Obtaining account data[/dim]", spinner="dots"))
203
+ print("Obtaining account data...", flush=True)
209
204
  try:
210
205
  account_name, account_name_verbose = await _get_account_org(result, active_org)
211
- live.stop()
212
206
  logger.debug(f"Setting namespace to {account_name_verbose} ({account_name})")
213
207
  if account_name is None:
214
208
  raise
215
209
  except Exception:
216
- live.stop()
217
- console.error(
218
- "Account has no associated namespace. Have you completed the onboarding process? Please first sign in via the web dashboard."
210
+ print(
211
+ "Error: Account has no associated namespace. "
212
+ "Have you completed the onboarding process? "
213
+ "Please first sign in via the web dashboard.",
214
+ flush=True,
219
215
  )
220
216
  return typer.Exit()
221
217
 
222
- console.success(
223
- "Web authentication finished successfully!\n"
224
- f"[dim]Account details stored to [magenta]{user_config_path}[/magenta][/dim]"
225
- )
218
+ print("Web authentication finished successfully!", flush=True)
219
+ print(f"Account details stored to {user_config_path}", flush=True)
220
+ else:
221
+ with Live(
222
+ console.status(
223
+ "[dim]Waiting for authentication to complete...[/dim]", spinner="dots"
224
+ ),
225
+ transient=True,
226
+ ) as live:
227
+ for attempt in itertools.count():
228
+ result = await auth_flow.finish()
229
+ if result is not None:
230
+ break
231
+ live.update(
232
+ console.status(
233
+ f"[dim]Waiting for authentication to complete... (attempt {attempt + 1})[/dim]"
234
+ )
235
+ )
236
+ if result is None:
237
+ live.stop()
238
+ console.error("Authentication failed")
239
+ return typer.Exit()
240
+
241
+ live.update(console.status("[dim]Obtaining account data[/dim]", spinner="dots"))
242
+ try:
243
+ account_name, account_name_verbose = await _get_account_org(
244
+ result, active_org
245
+ )
246
+ live.stop()
247
+ logger.debug(
248
+ f"Setting namespace to {account_name_verbose} ({account_name})"
249
+ )
250
+ if account_name is None:
251
+ raise
252
+ except Exception:
253
+ live.stop()
254
+ console.error(
255
+ "Account has no associated namespace. Have you completed the onboarding process? Please first sign in via the web dashboard."
256
+ )
257
+ return typer.Exit()
258
+
259
+ console.success(
260
+ "Web authentication finished successfully!\n"
261
+ f"[dim]Account details stored to [magenta]{user_config_path}[/magenta][/dim]"
262
+ )
226
263
 
227
264
  except Exception as e:
228
265
  logger.debug(e)
@@ -5,6 +5,8 @@
5
5
  #
6
6
 
7
7
  import os
8
+ import stat
9
+ import warnings
8
10
  from typing import Optional
9
11
 
10
12
  import toml
@@ -47,6 +49,18 @@ def _read_user_config():
47
49
 
48
50
  if not all(isinstance(e, dict) for e in org_sections.values()):
49
51
  config_problem = "Pipecat Cloud config file is not valid TOML. Organization sections must be dictionaries. Please log out and log back in."
52
+
53
+ # Warn if credentials file is readable by group or others (Unix only).
54
+ if os.name != "nt":
55
+ file_mode = os.stat(user_config_path).st_mode
56
+ if file_mode & (stat.S_IRWXG | stat.S_IRWXO):
57
+ warnings.warn(
58
+ f"Credentials file '{user_config_path}' has overly permissive "
59
+ f"permissions ({stat.filemode(file_mode)}). Other users on this "
60
+ f"system may be able to read your token. Run "
61
+ f"'chmod 600 {user_config_path}' to fix, or login again to repair automatically.",
62
+ stacklevel=2,
63
+ )
50
64
  if config_problem:
51
65
  raise ConfigError(config_problem)
52
66
 
@@ -63,6 +77,12 @@ def _write_user_config(new_config):
63
77
  with open(user_config_path, "w") as f:
64
78
  toml.dump(new_config, f)
65
79
 
80
+ # Restrict permissions so only the file owner can access credentials.
81
+ # On Windows os.chmod is limited but home directories are already
82
+ # protected by ACLs, so this is effectively a Unix-only hardening.
83
+ os.chmod(dir_path, stat.S_IRWXU) # 0o700
84
+ os.chmod(user_config_path, stat.S_IRUSR | stat.S_IWUSR) # 0o600
85
+
66
86
 
67
87
  def remove_user_config():
68
88
  os.remove(user_config_path)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pipecatcloud
3
- Version: 0.2.19
3
+ Version: 0.2.20
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/
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes