Skip to main content

feagi_agent/sdk/sensory/text/
encoder.rs

1//! Text encoder implementation.
2
3use crate::core::SdkError;
4use crate::sdk::base::TopologyCache;
5use crate::sdk::sensory::text::config::TextEncoderConfig;
6use crate::sdk::sensory::traits::SensoryEncoder;
7use crate::sdk::types::{
8    CorticalChannelCount, CorticalChannelIndex, CorticalUnitIndex, FrameChangeHandling,
9    MiscDataDimensions, SensorDeviceCache, WrappedIOData,
10};
11use feagi_sensorimotor::data_types::encode_token_id_to_misc_data;
12
13/// Text encoder backed by a sensor cache.
14pub struct TextEncoder {
15    config: TextEncoderConfig,
16    cache: SensorDeviceCache,
17    cortical_ids: Vec<crate::sdk::types::CorticalID>,
18    depth: u32,
19}
20
21impl TextEncoder {
22    /// Create a new text encoder and register device definitions.
23    pub async fn new(
24        config: TextEncoderConfig,
25        topology_cache: &TopologyCache,
26    ) -> Result<Self, SdkError> {
27        let cortical_id = config.cortical_id();
28        let topology = topology_cache.get_topology(&cortical_id).await?;
29        let depth = topology.depth;
30
31        let unit = CorticalUnitIndex::from(config.cortical_unit_id);
32        let channel_count = CorticalChannelCount::new(topology.channels)
33            .map_err(|e| SdkError::Other(format!("Invalid text channel count: {e}")))?;
34        let dimensions = MiscDataDimensions::new(1, 1, depth)
35            .map_err(|e| SdkError::Other(format!("Invalid text dimensions: {e}")))?;
36
37        let mut cache = SensorDeviceCache::new();
38        cache
39            .text_english_input_register(
40                unit,
41                channel_count,
42                FrameChangeHandling::Absolute,
43                dimensions,
44            )
45            .map_err(|e| SdkError::Other(format!("Text register failed: {e}")))?;
46
47        Ok(Self {
48            config,
49            cache,
50            cortical_ids: vec![cortical_id],
51            depth,
52        })
53    }
54
55    /// Return the Z depth (bitplanes) used for token encoding.
56    pub fn depth(&self) -> u32 {
57        self.depth
58    }
59}
60
61impl SensoryEncoder for TextEncoder {
62    type Input = u32;
63
64    fn encode(&mut self, input: &Self::Input) -> Result<Vec<u8>, SdkError> {
65        let misc = encode_token_id_to_misc_data(*input, self.depth)
66            .map_err(|e| SdkError::Other(format!("Text encode failed: {e}")))?;
67
68        self.cache
69            .text_english_input_write(
70                CorticalUnitIndex::from(self.config.cortical_unit_id),
71                CorticalChannelIndex::from(0u32),
72                WrappedIOData::MiscData(misc),
73            )
74            .map_err(|e| SdkError::Other(format!("Text cache write failed: {e}")))?;
75
76        self.cache
77            .encode_all_sensors_to_neurons(std::time::Instant::now())
78            .map_err(|e| SdkError::Other(format!("Text sensor encode failed: {e}")))?;
79        self.cache
80            .encode_neurons_to_bytes()
81            .map_err(|e| SdkError::Other(format!("Text byte encode failed: {e}")))?;
82
83        Ok(self
84            .cache
85            .get_feagi_byte_container()
86            .get_byte_ref()
87            .to_vec())
88    }
89
90    fn cortical_ids(&self) -> &[crate::sdk::types::CorticalID] {
91        &self.cortical_ids
92    }
93}