1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
//! Download-consent helpers for the local Parakeet backend.
//!
//! The transcribe pipeline NEVER downloads the model on its own
//! (`model::ensure_present` only checks; it never fetches). Instead,
//! each entry surface — the `transcribe` CLI, `dictate --toggle`, the
//! `--pick` picker — is responsible for obtaining explicit user
//! consent and then calling [`model::download_model`].
//!
//! This module holds the shared, surface-agnostic pieces:
//!
//! * [`resolve`] — turn a [`Config`] into the Parakeet model
//! directory + variant + a presence flag, so a surface can decide
//! whether a consent prompt is even needed.
//! * [`ensure_with_cli_consent`] — the terminal/CLI consent flow
//! (interactive y/n on a TTY; a clear stderr log + proceed when
//! non-interactive, since *selecting Parakeet is the consent* for
//! unattended callers).
//!
//! The GTK picker drives its own dialog-based consent (it cannot
//! block on stdin) and the toggle overlay drives a progress badge;
//! both call [`model::download_model`] directly after consent, reusing
//! [`resolve`] for the presence decision.
use PathBuf;
use crate;
use crateTalkError;
use model;
/// Resolved Parakeet model location + whether it is already present.
/// Resolve the Parakeet model directory + variant from config and
/// report whether the model is already present on disk.
///
/// Uses defaults when no `providers.parakeet:` block exists (the
/// backend is zero-config). Returns an error only when the model
/// directory cannot be resolved at all (e.g. no home directory).
/// Ensure the Parakeet model is present, asking for consent on the
/// terminal when it is not.
///
/// Behaviour when the model is absent:
///
/// * **Interactive (stdin is a TTY):** prints a `[y/N]` prompt to
/// stderr and reads the answer. Anything other than `y`/`yes`
/// aborts with a [`TalkError::Config`] (no download).
/// * **Non-interactive (piped / no TTY):** logs a clear message to
/// stderr and proceeds with the download — for unattended callers
/// *selecting Parakeet is itself the consent* (user-confirmed
/// policy). This keeps scripts/cron working without a hung prompt.
///
/// A no-op (returns `Ok`) when the model is already present.
///
/// Delegates the interactive `[y/N]` prompt / non-interactive
/// proceed-with-log mechanics to the shared
/// [`crate::model_fetch::ensure_with_cli_consent`], passing the
/// parakeet INT8 [`ModelSpec`](crate::model_fetch::ModelSpec). This
/// is behaviour-preserving: the prompt copy is templated from the
/// spec's `display_name` / `approx_size`, and the download still runs
/// through [`model::download_model`]'s atomic + concurrency path.
pub async