Skip to main content

objectiveai_cli/filesystem/tools/
manifest.rs

1use schemars::JsonSchema;
2use serde::{Deserialize, Serialize};
3
4/// Per-OS exec command. Reused from the SDK so the on-disk
5/// `objectiveai.json` shape and the `tools get` wire shape stay
6/// identical.
7pub use objectiveai_sdk::cli::command::tools::get::Exec;
8
9/// Declarative metadata a local tool ships with. The wire shape is
10/// JSON: `<base_dir>/tools/<owner>/<name>/<version>/objectiveai.json`.
11/// The executable command is invoked with that version folder as the
12/// working directory.
13#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
14#[schemars(rename = "filesystem.tools.Manifest")]
15pub struct Manifest {
16    /// One-line description of what the tool does. Surfaced to
17    /// agents that consume the tool.
18    pub description: String,
19
20    /// Version string. Free-form; the host displays whatever's here
21    /// (semver convention recommended but not enforced).
22    pub version: String,
23
24    /// GitHub-style owner (user or org) of the tool's source repo.
25    /// Free-form; tools have no installer, so this is purely
26    /// author-supplied metadata — nothing overrides it the way the
27    /// plugin installer overrides the plugin manifest's owner.
28    pub owner: String,
29
30    /// Per-OS exec command. The current platform's vector is the
31    /// program plus its leading arguments; the caller's `--args` are
32    /// appended and the whole thing runs with CWD = this manifest's
33    /// version folder.
34    pub exec: Exec,
35}
36
37impl Manifest {
38    /// LLM-visible tool name. See
39    /// [`objectiveai_sdk::agent::materialize_tool_name`].
40    pub fn tool_name(&self, name: &str) -> String {
41        objectiveai_sdk::agent::materialize_tool_name(&self.owner, name, &self.version)
42    }
43}
44
45/// A [`Manifest`] enriched with the tool's identifying `name` and the
46/// `source` it was loaded from. Same shape and ordering convention
47/// as `filesystem::plugins::ManifestWithNameAndSource`.
48#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
49#[schemars(rename = "filesystem.tools.ManifestWithNameAndSource")]
50pub struct ManifestWithNameAndSource {
51    /// The tool's identifier — the `<name>` segment of its
52    /// `tools/<owner>/<name>/<version>/` directory.
53    pub name: String,
54    #[serde(flatten)]
55    pub manifest: Manifest,
56    /// Where this manifest came from — typically an absolute
57    /// filesystem path. Free-form string; the host just displays it.
58    pub source: String,
59}
60
61impl ManifestWithNameAndSource {
62    /// LLM-visible tool name. See [`Manifest::tool_name`] — this
63    /// helper supplies the `name` field automatically.
64    pub fn tool_name(&self) -> String {
65        self.manifest.tool_name(&self.name)
66    }
67}
68
69// Typed conversion to the SDK's bare-naked wire shape. Lets
70// `command::tools::{get, list}` leaves yield SDK `ResponseManifest`
71// items without round-tripping through `serde_json::Value`.
72impl From<ManifestWithNameAndSource>
73    for objectiveai_sdk::cli::command::tools::get::ResponseManifest
74{
75    fn from(m: ManifestWithNameAndSource) -> Self {
76        Self {
77            name: m.name,
78            description: m.manifest.description,
79            version: m.manifest.version,
80            owner: m.manifest.owner,
81            exec: m.manifest.exec,
82            source: m.source,
83        }
84    }
85}