agent-tk 0.4.0

`agent-tk` (`agent toolkit/tasks-knowledge`) is a crate for the development of autonomous agents using Rust, with an emphasis on tasks and knowledge based agents. This project is part of the [auKsys](http://auksys.org) project.
Documentation
//! This module defines an tk agent.

use log::info;
use yaaral::TaskInterface as _;

use crate::prelude::*;

use delegation::Task;
use module::Module;

//     _                    _   ____        _
//    / \   __ _  ___ _ __ | |_|  _ \  __ _| |_ __ _
//   / _ \ / _` |/ _ \ '_ \| __| | | |/ _` | __/ _` |
//  / ___ | (_| |  __/ | | | |_| |_| | (_| | || (_| |
// /_/   \_\__, |\___|_| |_|\__|____/ \__,_|\__\__,_|
//         |___/

/// Data of an agent
#[derive(Clone)]
pub struct AgentData
{
  /// Uri of the agent
  pub agent_uri: String,
  /// Runtime for async (selected as a feature)
  pub async_runtime: crate::Runtime,
  /// Interface to the knowledge base of the agent
  pub knowledge_base: Box<dyn knowledge_base::KnowledgeBase>,
  /// Internal copy of the states of the agent
  pub states: states::SharedStates,
  /// Capabilities of the agent
  pub capabilities: definitions::agent::capabilities::Capabilities,
  /// Geographic projection
  pub projection: projection::Projection,
}

ccutils::assert_impl_all!(AgentData: Sync, Send);

//                           _
//     /\                   | |
//    /  \   __ _  ___ _ __ | |_
//   / /\ \ / _` |/ _ \ '_ \| __|
//  / ____ \ (_| |  __/ | | | |_
// /_/    \_\__, |\___|_| |_|\__|
//           __/ |
//          |___/

/// This class represent a TK agent
pub struct Agent
{
  agent_data: AgentData,
  delegation_interface:
    module::ModuleInterface<delegation::InputMessage, delegation::OutputMessage>,
}

impl Agent
{
  /// Create a new agent with the given knowlege base and transport for the delegation
  pub fn new<TTransport, TDecision, TExecution>(
    agent_data: AgentData,
    transport_options: TTransport::Options,
    decision_options: TDecision::Options,
    executor_options: TExecution::Options,
  ) -> Result<Self>
  where
    TTransport: delegation::transport::Module,
    TDecision: decision::Module,
    TExecution: execution::Module,
  {
    let transport_interfaces = TTransport::prepare_interfaces(200);
    let delegation_interfaces = delegation::Module::prepare_interfaces(200);
    let decision_interfaces = TDecision::prepare_interfaces(200);
    let executor_interfaces = TExecution::prepare_interfaces(200);

    let transport_interface = transport_interfaces.0.clone();
    let execution_interface = executor_interfaces.0.clone();
    let delegation_interface = delegation_interfaces.0.clone();
    let decision_interface = decision_interfaces.0.clone();

    // transport_interface.input_sender().

    let transport_module = TTransport::start(
      agent_data.to_owned(),
      transport_interfaces,
      delegation_interfaces.0.clone(),
      transport_options,
    )?;
    let delegation_module = delegation::Module::start(
      agent_data.to_owned(),
      delegation_interfaces,
      transport_interface,
      decision_interface,
    );
    let decision_module = TDecision::start(
      agent_data.to_owned(),
      decision_interfaces,
      execution_interface,
      decision_options,
    );
    let execution_module =
      TExecution::start(agent_data.to_owned(), executor_interfaces, executor_options);
    agent_data
      .async_runtime
      .spawn_task(transport_module)
      .map_spawn_error()?
      .detach();
    agent_data
      .async_runtime
      .spawn_task(delegation_module)
      .map_spawn_error()?
      .detach();
    agent_data
      .async_runtime
      .spawn_task(decision_module)
      .map_spawn_error()?
      .detach();
    agent_data
      .async_runtime
      .spawn_task(execution_module)
      .map_spawn_error()?
      .detach();
    Ok(Self {
      agent_data,
      delegation_interface,
    })
  }
  /// Return a reference to the projection used by this agent
  pub fn projection_ref(&self) -> &crate::projection::Projection
  {
    &self.agent_data.projection
  }
  /// Return a reference to the states of this agent
  pub fn states_ref(&self) -> &crate::states::SharedStates
  {
    &self.agent_data.states
  }
  /// Return a reference to the capabilities of this agent
  pub fn capabilities_ref(&self) -> &definitions::agent::capabilities::Capabilities
  {
    &self.agent_data.capabilities
  }
  /// Start the delegation of a task by this agent
  pub fn delegate_task<'b>(
    &self,
    task: definitions::task::Task,
  ) -> impl std::future::Future<Output = Result<()>> + 'b
  {
    log::info!("Start delegation of task {:?}", task.task_id());
    let agent_data = self.agent_data.clone();
    let delegation_input_sender = self.delegation_interface.input_sender();
    let mut delegation_output_recv = self.delegation_interface.output_receiver();
    async move {
      let task_uuid = task.task_id();
      delegation_input_sender
        .broadcast(delegation::InputMessage::create_start_delegation(
          agent_data.agent_uri.to_owned(),
          task,
          None,
        ))
        .await?;
      while let Ok(msg) = delegation_output_recv.recv().await
      {
        match msg
        {
          delegation::OutputMessage::Status { uuid, status } =>
          {
            if uuid == task_uuid
            {
              info!("Delegation {:?} received status {:?}", uuid, status);
            }
          }
        }
      }
      Ok(())
    }
  }
}