Skip to main content

sim/runtime/glasses/proofs/
voice.rs

1use sim_kernel::{Cx, Expr, Result};
2use sim_lib_intent::intent_kind_of;
3use sim_lib_stream_device::ModeledSource;
4use sim_lib_stream_xr::ModeledHaloMicSource;
5use sim_lib_view_device::{ConsentReceipt, EdgeId};
6use sim_lib_view_spatial::{AsrSite, XrMicChunkRef, glasses_mic_grant, voice_intent_via_site};
7use sim_value::build;
8
9use crate::runtime::glasses::modeled_asr_site_symbol;
10
11/// Result of the consent-gated modeled ASR site proof.
12#[derive(Clone, Debug, PartialEq, Eq)]
13pub struct VoiceSiteProof {
14    /// Whether the modeled ASR runtime is registered as a site export.
15    pub site_exported: bool,
16    /// Whether the visible microphone receipt is bound to this session.
17    pub session_bound: bool,
18    /// Whether ASR receives audio by reference rather than inline bytes.
19    pub by_reference: bool,
20    /// Intent kind returned by the site.
21    pub intent_kind: String,
22}
23
24impl VoiceSiteProof {
25    /// Encodes the proof as expression data for cookbook recipes.
26    pub fn to_expr(&self) -> Expr {
27        build::map(vec![
28            ("kind", build::qsym("glasses/sdk", "voice-site-proof")),
29            ("site-exported", Expr::Bool(self.site_exported)),
30            ("session-bound", Expr::Bool(self.session_bound)),
31            ("by-reference", Expr::Bool(self.by_reference)),
32            ("intent-kind", build::text(&self.intent_kind)),
33        ])
34    }
35}
36
37/// Turns a canned microphone chunk reference into an Intent through `Export::Site`.
38pub fn prove_voice_site(cx: &mut Cx) -> Result<VoiceSiteProof> {
39    let source_chunk = ModeledHaloMicSource.at(42);
40    let chunk = XrMicChunkRef::new(
41        source_chunk.store_key().clone(),
42        source_chunk.seq(),
43        16_000,
44        1,
45        u64::from(source_chunk.ms()) * 32,
46    )?;
47    let site_value = cx
48        .registry()
49        .site_by_symbol(&modeled_asr_site_symbol())
50        .cloned()
51        .ok_or_else(|| {
52            sim_kernel::Error::HostError("modeled glasses ASR site missing".to_owned())
53        })?;
54    let fabric = site_value.object().as_eval_fabric().ok_or_else(|| {
55        sim_kernel::Error::HostError("modeled glasses ASR export is not a fabric".to_owned())
56    })?;
57    let site = AsrSite::local(fabric);
58    let session = EdgeId::named("sdk-glasses-voice");
59    let receipt = ConsentReceipt::new(
60        vec![glasses_mic_grant()],
61        1_000,
62        Vec::new(),
63        session.clone(),
64        42,
65    );
66    let intent = voice_intent_via_site(cx, &chunk, Some(&site), &receipt, &session)?;
67    let kind = intent_kind_of(&intent)
68        .map(|kind| kind.name.to_string())
69        .unwrap_or_default();
70
71    Ok(VoiceSiteProof {
72        site_exported: true,
73        session_bound: receipt.session == session,
74        by_reference: matches!(
75            sim_value::access::field(&chunk.to_expr(), "ref"),
76            Some(Expr::Symbol(_))
77        ),
78        intent_kind: kind,
79    })
80}