agent-cli 0.63.0__py3-none-any.whl → 0.64.0__py3-none-any.whl

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,50 @@
1
+ #!/usr/bin/env python3
2
+ """Check that plugin skill files are in sync with source files."""
3
+
4
+ import sys
5
+ from pathlib import Path
6
+
7
+ SYNC_PAIRS = [
8
+ # Plugin marketplace distribution
9
+ ("agent_cli/dev/skill/SKILL.md", ".claude-plugin/skills/agent-cli-dev/SKILL.md"),
10
+ ("agent_cli/dev/skill/examples.md", ".claude-plugin/skills/agent-cli-dev/examples.md"),
11
+ # Project-local skill (for Claude Code working on this repo)
12
+ ("agent_cli/dev/skill/SKILL.md", ".claude/skills/agent-cli-dev/SKILL.md"),
13
+ ("agent_cli/dev/skill/examples.md", ".claude/skills/agent-cli-dev/examples.md"),
14
+ ]
15
+
16
+
17
+ def main() -> int:
18
+ """Check that plugin skill files match source files."""
19
+ root = Path(__file__).parent.parent
20
+ out_of_sync = []
21
+
22
+ for source, target in SYNC_PAIRS:
23
+ source_path = root / source
24
+ target_path = root / target
25
+
26
+ if not source_path.exists():
27
+ print(f"Source not found: {source}")
28
+ continue
29
+
30
+ if not target_path.exists():
31
+ out_of_sync.append((source, target, "target missing"))
32
+ continue
33
+
34
+ if source_path.read_text() != target_path.read_text():
35
+ out_of_sync.append((source, target, "content differs"))
36
+
37
+ if out_of_sync:
38
+ print("Plugin skill files are out of sync:")
39
+ for source, target, reason in out_of_sync:
40
+ print(f" {source} -> {target} ({reason})")
41
+ print("\nRun:")
42
+ print(" cp agent_cli/dev/skill/*.md .claude-plugin/skills/agent-cli-dev/")
43
+ print(" cp agent_cli/dev/skill/*.md .claude/skills/agent-cli-dev/")
44
+ return 1
45
+
46
+ return 0
47
+
48
+
49
+ if __name__ == "__main__":
50
+ sys.exit(main())
@@ -2,19 +2,18 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- import io
6
5
  import logging
7
- import wave
8
6
  from functools import partial
9
7
  from typing import TYPE_CHECKING
10
8
 
11
9
  from wyoming.asr import Transcribe, Transcript
12
- from wyoming.audio import AudioChunk, AudioStop
10
+ from wyoming.audio import AudioChunk, AudioChunkConverter, AudioStop
13
11
  from wyoming.info import AsrModel, AsrProgram, Attribution, Describe, Info
14
12
  from wyoming.server import AsyncEventHandler, AsyncServer
15
13
 
16
- from agent_cli.server.common import setup_wav_file
14
+ from agent_cli import constants
17
15
  from agent_cli.server.whisper.languages import WHISPER_LANGUAGE_CODES
16
+ from agent_cli.services import pcm_to_wav
18
17
 
19
18
  if TYPE_CHECKING:
20
19
  from wyoming.event import Event
@@ -49,8 +48,12 @@ class WyomingWhisperHandler(AsyncEventHandler):
49
48
  """
50
49
  super().__init__(*args, **kwargs)
51
50
  self._registry = registry
52
- self._audio_buffer: io.BytesIO | None = None
53
- self._wav_file: wave.Wave_write | None = None
51
+ self._audio_bytes: bytes = b""
52
+ self._audio_converter = AudioChunkConverter(
53
+ rate=constants.AUDIO_RATE,
54
+ width=constants.AUDIO_FORMAT_WIDTH,
55
+ channels=constants.AUDIO_CHANNELS,
56
+ )
54
57
  self._language: str | None = None
55
58
  self._initial_prompt: str | None = None
56
59
 
@@ -80,39 +83,31 @@ class WyomingWhisperHandler(AsyncEventHandler):
80
83
 
81
84
  async def _handle_audio_chunk(self, event: Event) -> bool:
82
85
  """Handle an audio chunk event."""
83
- chunk = AudioChunk.from_event(event)
84
-
85
- if self._wav_file is None:
86
+ if not self._audio_bytes:
86
87
  logger.debug("AudioChunk begin")
87
- self._audio_buffer = io.BytesIO()
88
- self._wav_file = wave.open(self._audio_buffer, "wb") # noqa: SIM115
89
- setup_wav_file(
90
- self._wav_file,
91
- rate=chunk.rate,
92
- channels=chunk.channels,
93
- sample_width=chunk.width,
94
- )
95
88
 
96
- self._wav_file.writeframes(chunk.audio)
89
+ chunk = AudioChunk.from_event(event)
90
+ chunk = self._audio_converter.convert(chunk)
91
+ self._audio_bytes += chunk.audio
97
92
  return True
98
93
 
99
94
  async def _handle_audio_stop(self) -> bool:
100
95
  """Handle audio stop event - transcribe the collected audio."""
101
96
  logger.debug("AudioStop")
102
97
 
103
- if self._wav_file is None or self._audio_buffer is None:
98
+ if not self._audio_bytes:
104
99
  logger.warning("AudioStop received but no audio data")
105
100
  await self.write_event(Transcript(text="").event())
106
101
  return False
107
102
 
108
- # Close WAV file
109
- self._wav_file.close()
110
- self._wav_file = None
111
-
112
- # Get audio data
113
- self._audio_buffer.seek(0)
114
- audio_data = self._audio_buffer.read()
115
- self._audio_buffer = None
103
+ # Wrap PCM in WAV format for the backend
104
+ audio_data = pcm_to_wav(
105
+ self._audio_bytes,
106
+ sample_rate=constants.AUDIO_RATE,
107
+ sample_width=constants.AUDIO_FORMAT_WIDTH,
108
+ channels=constants.AUDIO_CHANNELS,
109
+ )
110
+ self._audio_bytes = b""
116
111
 
117
112
  # Transcribe
118
113
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-cli
3
- Version: 0.63.0
3
+ Version: 0.64.0
4
4
  Summary: A suite of AI-powered command-line tools for text correction, audio transcription, and voice assistance.
5
5
  Project-URL: Homepage, https://github.com/basnijholt/agent-cli
6
6
  Author-email: Bas Nijholt <bas@nijho.lt>
@@ -109,6 +109,7 @@ agent_cli/rag/client.py,sha256=mFiZ4yjI75Vsehie6alsV1My50uIsp-G07Qz6SaNrZw,8913
109
109
  agent_cli/rag/engine.py,sha256=XySDer0fNTsEUjbUby5yf7JqB7uCE7tw2A6tYJixHnI,9800
110
110
  agent_cli/rag/models.py,sha256=uECWoeBChlkAK7uTM-pUnPGaaMO4EYJ3pJcAf8uh1vI,1043
111
111
  agent_cli/scripts/__init__.py,sha256=QvI1gnTagN85mmKDy2IRw96MEU9DKRWKkhSKSBshGVY,78
112
+ agent_cli/scripts/check_plugin_skill_sync.py,sha256=abuiSjvj34mazYeKOG-Mw6y14uN_1Ie8dkcCs_M_RF0,1656
112
113
  agent_cli/scripts/run-openwakeword.sh,sha256=jXZ3hegiL5TINFttvOPnnfDWuIR6x8Mv_pAEWij7Z08,446
113
114
  agent_cli/scripts/run-piper-windows.ps1,sha256=jpy4-3NxCoBpT3mnNbmCCSGbahjbv34KozlQ3lCDpV4,1134
114
115
  agent_cli/scripts/run-piper.sh,sha256=MAI1yTnmcn3z-t7UWwK5oSvpr9KNgh6Z2h7ns_dbYNc,877
@@ -161,7 +162,7 @@ agent_cli/server/whisper/api.py,sha256=_2z04tUfuQ6QnKMaZnikb5Ji7LbtCfKYs42MG6v-Q
161
162
  agent_cli/server/whisper/languages.py,sha256=Tv3qsIOSQQLxw-v5Wy41jSS6uHG_YBiG-T2uJVVt3u0,2686
162
163
  agent_cli/server/whisper/model_manager.py,sha256=LI92mkueu8o8m6AhzlUaaIWygnZucJa295-j7ymx7Ss,4925
163
164
  agent_cli/server/whisper/model_registry.py,sha256=qoRkB0ex6aRtUlsUN5BGik-oIZlwJbVHGQKaCbf_yVg,789
164
- agent_cli/server/whisper/wyoming_handler.py,sha256=bX0nYeSKFuyccVyNj0034QNuWJvAS1r7XMopiFK72X4,6712
165
+ agent_cli/server/whisper/wyoming_handler.py,sha256=HjN565YfDHeVfaGjQfoy9xjCZPx_TvYvjRYgbKn3aOI,6634
165
166
  agent_cli/server/whisper/backends/__init__.py,sha256=DfgyigwMLKiSfaRzZ1TTeV7fa9HWSmT1UJnJa-6el7k,2338
166
167
  agent_cli/server/whisper/backends/base.py,sha256=gQi5EyMCFS464mKXGIKbh1vgtBm99eNkf93SCIYRYg0,2597
167
168
  agent_cli/server/whisper/backends/faster_whisper.py,sha256=-BogM_-_rhlXKUZuW1qUN8zw2gD0ut1bJozPDP19knA,6717
@@ -172,8 +173,8 @@ agent_cli/services/asr.py,sha256=V6SV-USnMhK-0aE-pneiktU4HpmLqenmMb-jZ-_74zU,169
172
173
  agent_cli/services/llm.py,sha256=Kwdo6pbMYI9oykF-RBe1iaL3KsYrNWTLdRSioewmsGQ,7199
173
174
  agent_cli/services/tts.py,sha256=exKo-55_670mx8dQOzVSZkv6aWYLv04SVmBcjOlD458,14772
174
175
  agent_cli/services/wake_word.py,sha256=j6Z8rsGq_vAdRevy9fkXIgLZd9UWfrIsefmTreNmM0c,4575
175
- agent_cli-0.63.0.dist-info/METADATA,sha256=h6K2iJsMSndMhIyJyLa2pPtRmTmZeZvrpbTqsQuqYsA,151909
176
- agent_cli-0.63.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
177
- agent_cli-0.63.0.dist-info/entry_points.txt,sha256=FUv-fB2atLsPUk_RT4zqnZl1coz4_XHFwRALOKOF38s,97
178
- agent_cli-0.63.0.dist-info/licenses/LICENSE,sha256=majJU6S9kC8R8bW39NVBHyv32Dq50FL6TDxECG2WVts,1068
179
- agent_cli-0.63.0.dist-info/RECORD,,
176
+ agent_cli-0.64.0.dist-info/METADATA,sha256=WqgllIIkSkpdrweYCTidamE3s_F0eCLPLknMCM6Bj48,151909
177
+ agent_cli-0.64.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
178
+ agent_cli-0.64.0.dist-info/entry_points.txt,sha256=FUv-fB2atLsPUk_RT4zqnZl1coz4_XHFwRALOKOF38s,97
179
+ agent_cli-0.64.0.dist-info/licenses/LICENSE,sha256=majJU6S9kC8R8bW39NVBHyv32Dq50FL6TDxECG2WVts,1068
180
+ agent_cli-0.64.0.dist-info/RECORD,,