Skip to main content

objectiveai_sdk/cli/command/laboratories/config/addresses/add/
mod.rs

1//! `laboratories config addresses add` — async handler stub.
2
3use crate::cli::command::CommandRequest;
4
5#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
6#[schemars(rename = "cli.command.laboratories.config.addresses.add.Request")]
7pub struct Request {
8    pub path_type: Path,
9    #[serde(flatten)]
10    pub base: crate::cli::command::RequestBase,
11    pub scope: crate::cli::command::SetScope,
12    /// The daemon `http://` address the laboratory host should connect to.
13    pub key: String,
14    /// The signature to present at that address. Empty ⇒ dial
15    /// unauthenticated (the address's daemon must be open). Always
16    /// sent explicitly — NO serde default: empty-string schema
17    /// defaults are banned (the json-schema builder asserts it), and
18    /// the CLI fills `""` itself when `--value` is omitted.
19    pub value: String,
20}
21
22#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize, schemars::JsonSchema)]
23#[schemars(rename = "cli.command.laboratories.config.addresses.add.Path")]
24pub enum Path {
25    #[serde(rename = "laboratories/config/addresses/add")]
26    LaboratoriesConfigAddressesAdd,
27}
28
29impl CommandRequest for Request {
30    fn request_base(&self) -> &crate::cli::command::RequestBase {
31        &self.base
32    }
33
34    fn request_base_mut(&mut self) -> Option<&mut crate::cli::command::RequestBase> {
35        Some(&mut self.base)
36    }
37}
38
39pub type Response = crate::cli::command::Ok;
40
41#[derive(clap::Args)]
42#[command(group(clap::ArgGroup::new("key_required").required(true).args(["key"])))]
43pub struct Args {
44    /// Mutate the global config layer.
45    #[arg(long)]
46    pub global: bool,
47    /// Mutate the state config layer.
48    #[arg(long)]
49    pub state: bool,
50    #[command(flatten)]
51    pub base: crate::cli::command::RequestBaseArgs,
52    /// Entry key (a daemon `http://` address).
53    #[arg(long)]
54    pub key: Option<String>,
55    /// Entry value (the signature to present at that address).
56    /// Omitted ⇒ dial unauthenticated.
57    #[arg(long)]
58    pub value: Option<String>,
59}
60
61#[derive(clap::Args)]
62#[command(args_conflicts_with_subcommands = true)]
63pub struct Command {
64    #[command(flatten)]
65    pub args: Args,
66    #[command(subcommand)]
67    pub schema: Option<Schema>,
68}
69
70#[derive(clap::Subcommand)]
71pub enum Schema {
72    /// Emit the JSON Schema for this leaf's `Request` type and exit.
73    RequestSchema(request_schema::Args),
74    /// Emit the JSON Schema for this leaf's `Response` type and exit.
75    ResponseSchema(response_schema::Args),
76}
77
78impl TryFrom<Args> for Request {
79    type Error = crate::cli::command::FromArgsError;
80    fn try_from(args: Args) -> Result<Self, Self::Error> {
81        let scope = match (args.global, args.state) {
82            (true, false) => crate::cli::command::SetScope::Global,
83            (false, true) => crate::cli::command::SetScope::State,
84            _ => {
85                return Err(crate::cli::command::FromArgsError {
86                    field: "scope",
87                    source: crate::cli::command::FromArgsErrorSource::Plain(
88                        "exactly one of --global, --state is required".to_string(),
89                    ),
90                });
91            }
92        };
93        Ok(Self {
94            base: args.base.into(), path_type: Path::LaboratoriesConfigAddressesAdd,
95            scope,
96            key: args.key.ok_or_else(|| {
97                crate::cli::command::FromArgsError::path_parse(
98                    "key",
99                    "--key is required".to_string(),
100                )
101            })?,
102            // Optional: an address without a signature dials
103            // unauthenticated.
104            value: args.value.unwrap_or_default(),
105        })
106    }
107}
108
109#[cfg(feature = "cli-executor")]
110pub async fn execute<E: crate::cli::command::CommandExecutor>(
111    executor: &E,
112    request: Request,
113
114        agent_arguments: Option<&crate::cli::command::AgentArguments>,
115    ) -> Result<Response, E::Error> {
116    executor.execute_one(request, agent_arguments).await
117}
118
119pub mod request_schema;
120
121pub mod response_schema;
122
123#[cfg(feature = "cli-executor")]
124pub async fn execute_transform<E: crate::cli::command::CommandExecutor>(
125    executor: &E,
126    request: Request,
127    _transform: crate::cli::command::Transform,
128
129        agent_arguments: Option<&crate::cli::command::AgentArguments>,
130    ) -> Result<serde_json::Value, E::Error> {
131    let resp: Response = executor.execute_one(request, agent_arguments).await?;
132    Ok(serde_json::to_value(resp).expect("Response serializes"))
133}
134
135/// One `/listen` broadcast run of `laboratories config addresses add`: the actual
136/// [`Request`], the producer's
137/// [`AgentArguments`](crate::cli::command::AgentArguments), and the
138/// unary response future. See [`crate::cli::broadcast_listener`].
139#[cfg(feature = "cli-listener")]
140pub struct ListenerExecution {
141    pub request: Request,
142    pub agent_arguments: crate::cli::command::AgentArguments,
143    pub response: crate::cli::broadcast_listener::UnaryResponse<Response>,
144}