vocalize-cli 0.8.0__tar.gz → 0.8.1__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 (44) hide show
  1. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/CHANGELOG.md +9 -0
  2. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/PKG-INFO +1 -1
  3. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/tests/test_cli.py +8 -8
  4. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/tests/test_preprocess.py +8 -0
  5. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/vocalize/__init__.py +1 -1
  6. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/vocalize/preprocess.py +3 -2
  7. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/.env.example +0 -0
  8. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/.github/workflows/ci.yml +0 -0
  9. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/.gitignore +0 -0
  10. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/LICENSE +0 -0
  11. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/README.md +0 -0
  12. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/hooks/claude_stop_hook.py +0 -0
  13. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/hooks/install_hook.py +0 -0
  14. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/hooks/install_quick_action.py +0 -0
  15. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/hooks/quick_actions/Speak Latest Plan.workflow/Contents/Info.plist +0 -0
  16. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/hooks/quick_actions/Speak Latest Plan.workflow/Contents/Resources/document.wflow +0 -0
  17. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/hooks/quick_actions/Speak with Vocalize.workflow/Contents/Info.plist +0 -0
  18. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/hooks/quick_actions/Speak with Vocalize.workflow/Contents/Resources/document.wflow +0 -0
  19. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/hooks/quick_actions/Stop Vocalize.workflow/Contents/Info.plist +0 -0
  20. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/hooks/quick_actions/Stop Vocalize.workflow/Contents/Resources/document.wflow +0 -0
  21. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/hooks/speak_options.py +0 -0
  22. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/hooks/speak_url_gate.py +0 -0
  23. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/pyproject.toml +0 -0
  24. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/tests/conftest.py +0 -0
  25. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/tests/test_audio.py +0 -0
  26. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/tests/test_auth.py +0 -0
  27. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/tests/test_claude_stop_hook.py +0 -0
  28. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/tests/test_clipboard.py +0 -0
  29. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/tests/test_config.py +0 -0
  30. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/tests/test_install_hook.py +0 -0
  31. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/tests/test_install_quick_action.py +0 -0
  32. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/tests/test_speak_options.py +0 -0
  33. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/tests/test_speak_url_gate.py +0 -0
  34. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/tests/test_tts.py +0 -0
  35. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/tests/test_wizard.py +0 -0
  36. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/vocalize/__main__.py +0 -0
  37. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/vocalize/audio.py +0 -0
  38. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/vocalize/auth.py +0 -0
  39. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/vocalize/cli.py +0 -0
  40. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/vocalize/clipboard.py +0 -0
  41. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/vocalize/config.py +0 -0
  42. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/vocalize/exceptions.py +0 -0
  43. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/vocalize/tts.py +0 -0
  44. {vocalize_cli-0.8.0 → vocalize_cli-0.8.1}/vocalize/wizard.py +0 -0
@@ -3,6 +3,15 @@
3
3
  All notable changes to this project are documented here. Format follows
4
4
  [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
5
5
 
6
+ ## 0.8.1 - 2026-09-01
7
+
8
+ ### Fixed
9
+
10
+ - Truncated speech no longer reads the words "dot dot dot truncated" aloud.
11
+ The `... (truncated)` marker was being appended to the text sent to
12
+ ElevenLabs and spoken; it's gone from the audio now. The CLI still prints
13
+ a "Note: input truncated to N characters." line to stderr.
14
+
6
15
  ## 0.8.0 - 2026-08-31
7
16
 
8
17
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: vocalize-cli
3
- Version: 0.8.0
3
+ Version: 0.8.1
4
4
  Summary: A CLI that turns text, markdown, or piped stdin into speech via the ElevenLabs API, with markdown-table-aware preprocessing.
5
5
  Project-URL: Homepage, https://github.com/matthager12-collab/vocalize
6
6
  Project-URL: Repository, https://github.com/matthager12-collab/vocalize
@@ -120,7 +120,7 @@ def test_max_chars_truncates_and_notes(monkeypatch, tmp_path):
120
120
  )
121
121
 
122
122
  assert result.exit_code == 0, result.output
123
- assert len(captured_text[0]) <= 10 + len("... (truncated)")
123
+ assert len(captured_text[0]) <= 10
124
124
  assert "truncated" in result.output
125
125
 
126
126
 
@@ -412,7 +412,7 @@ def test_overflow_truncate_is_the_default(monkeypatch, tmp_path):
412
412
  result, captured = _speak_long(monkeypatch, tmp_path, ["--max-chars", "50"])
413
413
 
414
414
  assert result.exit_code == 0, result.output
415
- assert len(captured[0]) <= 50 + len("... (truncated)")
415
+ assert len(captured[0]) <= 50
416
416
  assert "truncated to 50" in result.output
417
417
 
418
418
 
@@ -425,7 +425,7 @@ def test_overflow_ask_without_a_terminal_degrades_to_truncate(monkeypatch, tmp_p
425
425
  )
426
426
 
427
427
  assert result.exit_code == 0, result.output
428
- assert len(captured[0]) <= 50 + len("... (truncated)")
428
+ assert len(captured[0]) <= 50
429
429
  assert "no terminal to ask on" in result.output
430
430
 
431
431
 
@@ -456,7 +456,7 @@ def test_overflow_ask_truncates_on_a_yes(monkeypatch, tmp_path):
456
456
  )
457
457
 
458
458
  assert result.exit_code == 0, result.output
459
- assert len(captured[0]) <= 50 + len("... (truncated)")
459
+ assert len(captured[0]) <= 50
460
460
 
461
461
 
462
462
  def test_overflow_ask_under_the_cap_never_prompts(monkeypatch, tmp_path):
@@ -478,7 +478,7 @@ def test_default_max_chars_caps_when_nothing_else_is_set(monkeypatch, tmp_path):
478
478
  result, captured = _speak_long(monkeypatch, tmp_path, ["--default-max-chars", "50"])
479
479
 
480
480
  assert result.exit_code == 0, result.output
481
- assert len(captured[0]) <= 50 + len("... (truncated)")
481
+ assert len(captured[0]) <= 50
482
482
  assert "truncated to 50" in result.output
483
483
 
484
484
 
@@ -488,7 +488,7 @@ def test_env_var_beats_default_max_chars(monkeypatch, tmp_path):
488
488
  result, captured = _speak_long(monkeypatch, tmp_path, ["--default-max-chars", "50"])
489
489
 
490
490
  assert result.exit_code == 0, result.output
491
- assert len(captured[0]) <= 80 + len("... (truncated)")
491
+ assert len(captured[0]) <= 80
492
492
  assert "truncated to 80" in result.output
493
493
 
494
494
 
@@ -521,7 +521,7 @@ def test_config_file_overflow_and_max_chars_reach_the_cli(monkeypatch, tmp_path)
521
521
  result, captured = _speak_long(monkeypatch, tmp_path, [])
522
522
 
523
523
  assert result.exit_code == 0, result.output
524
- assert len(captured[0]) <= 60 + len("... (truncated)")
524
+ assert len(captured[0]) <= 60
525
525
  assert "truncated to 60" in result.output
526
526
 
527
527
 
@@ -840,7 +840,7 @@ def test_ask_dialog_truncate_applies_the_cap(monkeypatch, tmp_path):
840
840
  )
841
841
 
842
842
  assert result.exit_code == 0, result.output
843
- assert len(captured[0]) <= 50 + len("... (truncated)")
843
+ assert len(captured[0]) <= 50
844
844
 
845
845
 
846
846
  def test_ask_dialog_cancel_speaks_nothing(monkeypatch, tmp_path):
@@ -107,6 +107,14 @@ def test_truncate_for_budget_cuts_on_word_boundary():
107
107
  assert not text.startswith("one two thre")
108
108
 
109
109
 
110
+ def test_truncate_for_budget_leaves_no_spoken_marker():
111
+ # The result is read aloud; a literal "(truncated)" would be spoken.
112
+ text, truncated = truncate_for_budget("one two three four five", max_chars=13)
113
+ assert truncated is True
114
+ assert "truncated" not in text
115
+ assert "(" not in text
116
+
117
+
110
118
  def test_truncate_for_budget_none_means_unlimited():
111
119
  long_text = "word " * 10000
112
120
  text, truncated = truncate_for_budget(long_text, max_chars=None)
@@ -7,4 +7,4 @@ formatting into something that actually sounds good spoken aloud
7
7
  which is close to useless).
8
8
  """
9
9
 
10
- __version__ = "0.8.0"
10
+ __version__ = "0.8.1"
@@ -191,8 +191,9 @@ def truncate_for_budget(text: str, max_chars: int | None) -> tuple[str, bool]:
191
191
  """
192
192
  if max_chars is None or len(text) <= max_chars:
193
193
  return text, False
194
- cut = text[:max_chars].rsplit(" ", 1)[0]
195
- return cut + "... (truncated)", True
194
+ # No spoken marker: this text is read aloud, and a literal "(truncated)"
195
+ # gets spoken as a word. Callers surface truncation on stderr instead.
196
+ return text[:max_chars].rsplit(" ", 1)[0], True
196
197
 
197
198
 
198
199
  # The eleven_multilingual_v2 model caps a single request at 10,000
File without changes
File without changes
File without changes
File without changes