supervoxtral 0.1.4__py3-none-any.whl → 0.1.5__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: supervoxtral
3
- Version: 0.1.4
3
+ Version: 0.1.5
4
4
  Summary: CLI/GUI audio recorder and transcription client using Mistral Voxtral (chat with audio and transcription).
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -4,15 +4,15 @@ svx/core/__init__.py,sha256=mhzXuIXo3kUzjWme0Bxhe4TQZQELlyEiG_89LUAPC7M,2856
4
4
  svx/core/audio.py,sha256=r0m5T1uzdsJ1j9YXgQ5clv15dvMwZBp_bk2aLpjnrkc,7684
5
5
  svx/core/clipboard.py,sha256=IFtiN2SnYKQIu0WXx0hCK8syvDXanBpm1Jr2a8X7y9s,3692
6
6
  svx/core/config.py,sha256=e2tTGjjPcUYFctB28Ha90G-W44mF_0eWey1zpSyZkBo,16095
7
- svx/core/pipeline.py,sha256=nqvCgK5Pbyx18mfACrN_mIDt546Bh7fKA6MF4XG1hxM,10637
8
- svx/core/prompt.py,sha256=yO8UbpFg7n1IT7wFjSQ7NUTbrqxuwPhdnxkTH4Iu7XU,5967
7
+ svx/core/pipeline.py,sha256=AjNTzx8eFyWjI4VQYgKGELdo4soWUJZCn3861yIE5i0,10728
8
+ svx/core/prompt.py,sha256=VAHBSL0UESrkbalT6s7SaMc9IQ0OJFKBFO1bEmXnRrI,7172
9
9
  svx/core/storage.py,sha256=5_xKYEpvDhaixRxmSTBlyX_jt8ssjHwHzX9VodcrtJw,3213
10
10
  svx/providers/__init__.py,sha256=SzlSWpZSUIptbSrAnGfi0d0NX4hYTpT0ObWpYyskDdA,2634
11
11
  svx/providers/base.py,sha256=YoiI8KWVRGISh7dx9XXPr1Q1a7ZDu8vfeJFlPbcKr20,2695
12
12
  svx/providers/mistral.py,sha256=vrBatNZg0zGNkJ5Qfnfz6ZwP6QtBgIt9sT_w59zkSO0,6636
13
- svx/ui/qt_app.py,sha256=6LOMeMjkMmYylu6H_prDRmPDsL0s4PVMZqfbflByCMs,18808
14
- supervoxtral-0.1.4.dist-info/METADATA,sha256=0w_i5geOKu8F9x7eviNboDNt-PTy6FS3WHe3cCx4eHg,753
15
- supervoxtral-0.1.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
16
- supervoxtral-0.1.4.dist-info/entry_points.txt,sha256=phJhRy3VkYHC6AR_tUB5CypHzG0ePRR9sB13HWE1vEg,36
17
- supervoxtral-0.1.4.dist-info/licenses/LICENSE,sha256=fCEBKmC4i-1WZAwoKjKWegfDd8qNsG8ECB7JyqoswyQ,1064
18
- supervoxtral-0.1.4.dist-info/RECORD,,
13
+ svx/ui/qt_app.py,sha256=yww_sH0zFI2HEQTRFcR1LW0N4duFqlW-HDo6SWelkWo,19975
14
+ supervoxtral-0.1.5.dist-info/METADATA,sha256=Nq09MVEhqC5mjfVQCNaL2LL4HSgaQB-aQdJTp0-7Gk4,753
15
+ supervoxtral-0.1.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
16
+ supervoxtral-0.1.5.dist-info/entry_points.txt,sha256=phJhRy3VkYHC6AR_tUB5CypHzG0ePRR9sB13HWE1vEg,36
17
+ supervoxtral-0.1.5.dist-info/licenses/LICENSE,sha256=fCEBKmC4i-1WZAwoKjKWegfDd8qNsG8ECB7JyqoswyQ,1064
18
+ supervoxtral-0.1.5.dist-info/RECORD,,
svx/core/pipeline.py CHANGED
@@ -180,6 +180,8 @@ class RecordingPipeline:
180
180
  else:
181
181
  self._status("Transcribe mode activated: no prompt used.")
182
182
 
183
+ logging.debug(f"Applied prompt: {final_user_prompt or 'None (transcribe mode)'}")
184
+
183
185
  paths: dict[str, Path | None] = {"wav": wav_path}
184
186
 
185
187
  # Convert if needed
svx/core/prompt.py CHANGED
@@ -12,6 +12,7 @@ Intended to be small and dependency-light so it can be imported broadly.
12
12
  from __future__ import annotations
13
13
 
14
14
  import logging
15
+ from collections.abc import Callable
15
16
  from pathlib import Path
16
17
 
17
18
  from .config import USER_PROMPT_DIR, Config, PromptEntry
@@ -121,22 +122,45 @@ def resolve_user_prompt(
121
122
  return ""
122
123
 
123
124
  key = key or "default"
124
- suppliers = [
125
- lambda: _strip(inline),
126
- lambda: _read(file),
127
- lambda: _from_user_cfg(key),
128
- _from_user_prompt_dir,
125
+
126
+ # Suppliers annotated with a name for tracing which one returned the prompt.
127
+ named_suppliers: list[tuple[str, Callable[[], str]]] = [
128
+ ("inline", lambda: _strip(inline)),
129
+ ("file", lambda: _read(file)),
130
+ (f"prompt_config[{key}]", lambda: _from_user_cfg(key)),
131
+ ("user_prompt_dir/user.md", _from_user_prompt_dir),
129
132
  ]
130
133
 
131
- for supplier in suppliers:
134
+ for name, supplier in named_suppliers:
132
135
  try:
133
136
  val = supplier()
134
137
  if val:
138
+ # Log which supplier provided the prompt and a short snippet for debugging.
139
+ try:
140
+ if len(val) > 200:
141
+ snippet = val[:200] + "..."
142
+ else:
143
+ snippet = val
144
+ logging.info(
145
+ "resolve_user_prompt: supplier '%s' provided prompt snippet: %s",
146
+ name,
147
+ snippet,
148
+ )
149
+ except Exception:
150
+ # Ensure logging failures do not change behavior.
151
+ logging.info(
152
+ "resolve_user_prompt: supplier '%s' provided a prompt "
153
+ "(snippet unavailable)",
154
+ name,
155
+ )
135
156
  return val
136
157
  except Exception as e:
137
- logging.debug("Prompt supplier failed: %s", e)
158
+ logging.debug("Prompt supplier '%s' failed: %s", name, e)
138
159
 
139
- return "What's in this audio?"
160
+ # Final fallback
161
+ fallback = "What's in this audio?"
162
+ logging.info("resolve_user_prompt: no supplier provided a prompt, using fallback: %s", fallback)
163
+ return fallback
140
164
 
141
165
 
142
166
  def init_user_prompt_file(force: bool = False) -> Path:
svx/ui/qt_app.py CHANGED
@@ -273,10 +273,39 @@ class RecorderWorker(QObject):
273
273
  self.canceled.emit()
274
274
  return
275
275
  self.status.emit("Processing in progress...")
276
+ # Wait for user to select mode in the GUI
276
277
  while self.mode is None:
277
278
  time.sleep(0.05)
279
+
280
+ # Log the selected mode/key for debugging prompt application
281
+ try:
282
+ logging.info("RecorderWorker: selected mode/key: %s", self.mode)
283
+ except Exception:
284
+ # ensure failures in logging don't break the worker
285
+ pass
286
+
278
287
  transcribe_mode = self.mode == "transcribe"
279
- user_prompt = None if transcribe_mode else self._resolve_user_prompt(self.mode)
288
+ if transcribe_mode:
289
+ user_prompt = None
290
+ else:
291
+ # Resolve the user prompt for the selected key and log a short snippet
292
+ user_prompt = self._resolve_user_prompt(self.mode)
293
+ try:
294
+ if user_prompt:
295
+ snippet = (
296
+ user_prompt[:200] + "..." if len(user_prompt) > 200 else user_prompt
297
+ )
298
+ else:
299
+ snippet = "<EMPTY>"
300
+ logging.info(
301
+ "RecorderWorker: resolved prompt snippet for key '%s': %s",
302
+ self.mode,
303
+ snippet,
304
+ )
305
+ except Exception:
306
+ # avoid breaking the flow on logging errors
307
+ pass
308
+
280
309
  result = pipeline.process(wav_path, duration, transcribe_mode, user_prompt)
281
310
  keep_audio = self.save_all or self.cfg.defaults.keep_audio_files
282
311
  pipeline.clean(wav_path, result["paths"], keep_audio)
@@ -383,13 +412,15 @@ class RecorderWindow(QWidget):
383
412
  button_layout.addStretch()
384
413
  self._transcribe_btn = QPushButton("Transcribe")
385
414
  self._transcribe_btn.setToolTip("Stop and transcribe without prompt")
386
- self._transcribe_btn.clicked.connect(lambda: self._on_mode_selected("transcribe"))
415
+ self._transcribe_btn.clicked.connect(
416
+ lambda checked=False, m="transcribe": self._on_mode_selected(m)
417
+ )
387
418
  button_layout.addWidget(self._transcribe_btn)
388
419
  self._prompt_buttons: dict[str, QPushButton] = {}
389
420
  for key in self.prompt_keys:
390
421
  btn = QPushButton(key.capitalize())
391
422
  btn.setToolTip(f"Stop and transcribe with '{key}' prompt")
392
- btn.clicked.connect(lambda k=key: self._on_mode_selected(k))
423
+ btn.clicked.connect(lambda checked=False, k=key: self._on_mode_selected(k))
393
424
  self._prompt_buttons[key] = btn
394
425
  button_layout.addWidget(btn)
395
426
  self._cancel_btn = QPushButton("Cancel")