deepctl-cmd-ffprobe 0.0.2__tar.gz → 0.0.4__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deepctl-cmd-ffprobe
3
- Version: 0.0.2
3
+ Version: 0.0.4
4
4
  Summary: FFprobe configuration command for deepctl
5
5
  Author-email: Deepgram <devrel@deepgram.com>
6
6
  Maintainer-email: Deepgram <devrel@deepgram.com>
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "deepctl-cmd-ffprobe"
7
- version = "0.0.2" # x-release-please-version
7
+ version = "0.0.4" # x-release-please-version
8
8
  description = "FFprobe configuration command for deepctl"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -3,20 +3,43 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import os
6
- import shutil
7
6
  import subprocess
8
7
  from typing import Any
9
8
 
10
- from deepctl_core import AuthManager, BaseCommand, BaseResult, Config, DeepgramClient
9
+ from deepctl_core import (
10
+ AuthManager,
11
+ BaseCommand,
12
+ BaseResult,
13
+ CodedErrorResult,
14
+ Config,
15
+ DeepgramClient,
16
+ get_console,
17
+ get_output_format,
18
+ get_status_console,
19
+ is_ai_agent,
20
+ )
21
+ from deepctl_core import messages as msg
22
+ from deepctl_core.output import print_error, print_hint
23
+ from deepctl_core.tools import find_executable
11
24
  from deepctl_shared_utils import (
12
25
  get_ffprobe_path,
13
26
  print_ffprobe_install_instructions,
14
27
  )
15
- from rich.console import Console
16
28
 
17
29
  from .models import FfprobeResult
18
30
 
19
- console = Console()
31
+ # Two channels, deliberately (#104):
32
+ # console -> stdout, the human rendering of the FfprobeResult.
33
+ # Written only in default (human) output mode, so
34
+ # `dg -o json ffprobe | jq` sees the payload alone.
35
+ # status_console -> stderr, always: errors and install instructions.
36
+ console = get_console()
37
+ status_console = get_status_console()
38
+
39
+
40
+ def _human_output() -> bool:
41
+ """True when stdout is for a person, not a parser."""
42
+ return get_output_format() == "default"
20
43
 
21
44
 
22
45
  class FfprobeCommand(BaseCommand):
@@ -68,13 +91,15 @@ class FfprobeCommand(BaseCommand):
68
91
  auth_manager: AuthManager,
69
92
  client: DeepgramClient,
70
93
  **kwargs: Any,
71
- ) -> BaseResult:
94
+ ) -> BaseResult | CodedErrorResult:
72
95
  """Handle ffprobe command."""
73
96
  path = kwargs.get("path")
74
97
  reset = kwargs.get("reset", False)
75
98
 
76
99
  if path and reset:
77
- console.print("[red]Error:[/red] Cannot use --path and --reset together")
100
+ status_console.print(
101
+ "[red]Error:[/red] Cannot use --path and --reset together"
102
+ )
78
103
  return BaseResult(
79
104
  status="error",
80
105
  message="Cannot use --path and --reset together",
@@ -84,6 +109,17 @@ class FfprobeCommand(BaseCommand):
84
109
  return self._handle_reset(config)
85
110
 
86
111
  if path:
112
+ # A stored tool path is run by later commands: an AI agent
113
+ # session never sets it. Scripts and CI without an agent marker
114
+ # still can.
115
+ if is_ai_agent():
116
+ print_error(msg.E_TOOL_PATH_AGENT)
117
+ print_hint(msg.E_PERSON_ONLY_AGENT_HINT)
118
+ return CodedErrorResult(
119
+ error=msg.E_TOOL_PATH_AGENT,
120
+ code=msg.CODE_CONFIRMATION_REQUIRED,
121
+ hint=msg.E_PERSON_ONLY_AGENT_HINT,
122
+ )
87
123
  return self._handle_set_path(config, path)
88
124
 
89
125
  return self._handle_status(config)
@@ -92,21 +128,23 @@ class FfprobeCommand(BaseCommand):
92
128
  """Store a custom ffprobe path."""
93
129
  # Validate the path
94
130
  if not os.path.isfile(path):
95
- console.print(f"[red]Error:[/red] File not found: {path}")
131
+ status_console.print(f"[red]Error:[/red] File not found: {path}")
96
132
  return BaseResult(status="error", message=f"File not found: {path}")
97
133
 
98
134
  if not os.access(path, os.X_OK):
99
- console.print(f"[red]Error:[/red] File is not executable: {path}")
135
+ status_console.print(f"[red]Error:[/red] File is not executable: {path}")
100
136
  return BaseResult(status="error", message=f"File is not executable: {path}")
101
137
 
102
- # Store in config
138
+ # Store in config. Only absolute paths are used, so resolve it now.
139
+ path = os.path.abspath(path)
103
140
  config._config.tools.ffprobe_path = path
104
141
  config.save()
105
142
 
106
143
  version = self._get_version(path)
107
- console.print(f"[green]✓[/green] ffprobe path stored: {path}")
108
- if version:
109
- console.print(f" Version: {version}")
144
+ if _human_output():
145
+ console.print(f"[green]✓[/green] ffprobe path stored: {path}")
146
+ if version:
147
+ console.print(f" Version: {version}")
110
148
 
111
149
  return FfprobeResult(
112
150
  status="success",
@@ -121,14 +159,14 @@ class FfprobeCommand(BaseCommand):
121
159
  config._config.tools.ffprobe_path = None
122
160
  config.save()
123
161
 
124
- console.print("[green]✓[/green] Stored ffprobe path cleared")
125
-
126
162
  # Show auto-detected path
127
- auto_path = shutil.which("ffprobe")
128
- if auto_path:
129
- console.print(f" Auto-detected: {auto_path}")
130
- else:
131
- console.print(" [yellow]ffprobe not found in PATH[/yellow]")
163
+ auto_path = find_executable("ffprobe")
164
+ if _human_output():
165
+ console.print("[green]✓[/green] Stored ffprobe path cleared")
166
+ if auto_path:
167
+ console.print(f" Auto-detected: {auto_path}")
168
+ else:
169
+ console.print(" [yellow]ffprobe not found in PATH[/yellow]")
132
170
 
133
171
  return FfprobeResult(
134
172
  status="success",
@@ -140,20 +178,22 @@ class FfprobeCommand(BaseCommand):
140
178
  def _handle_status(self, config: Config) -> BaseResult:
141
179
  """Show ffprobe status."""
142
180
  stored_path = config.get("tools.ffprobe_path")
143
- auto_path = shutil.which("ffprobe")
181
+ auto_path = find_executable("ffprobe")
144
182
  effective_path = get_ffprobe_path(config)
145
183
 
146
- if stored_path:
147
- console.print(f" Stored path: {stored_path}")
148
- if auto_path:
149
- console.print(f" Auto-detected: {auto_path}")
184
+ if _human_output():
185
+ if stored_path:
186
+ console.print(f" Stored path: {stored_path}")
187
+ if auto_path:
188
+ console.print(f" Auto-detected: {auto_path}")
150
189
 
151
190
  if effective_path:
152
191
  version = self._get_version(effective_path)
153
- console.print(f" Active path: [green]{effective_path}[/green]")
154
- if version:
155
- console.print(f" Version: {version}")
156
- console.print("\n[green]✓[/green] ffprobe is available")
192
+ if _human_output():
193
+ console.print(f" Active path: [green]{effective_path}[/green]")
194
+ if version:
195
+ console.print(f" Version: {version}")
196
+ console.print("\n[green]✓[/green] ffprobe is available")
157
197
 
158
198
  return FfprobeResult(
159
199
  status="success",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: deepctl-cmd-ffprobe
3
- Version: 0.0.2
3
+ Version: 0.0.4
4
4
  Summary: FFprobe configuration command for deepctl
5
5
  Author-email: Deepgram <devrel@deepgram.com>
6
6
  Maintainer-email: Deepgram <devrel@deepgram.com>