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}