chore: add #[non_exhaustive] and mutation methods to improve compatibility (#715)
* chore: add #[non_exhaustive] to reduce backwards-incompatible changes going forward * fix: remove ProtocolVersion import * fix: add a few more with_ mutator methods --------- Co-authored-by: Alex Hancock <alexhancock@block.xyz>
This commit is contained in:
parent
79834b6211
commit
f63718d202
8 changed files with 1568 additions and 1110 deletions
|
|
@ -11,6 +11,7 @@ use super::{
|
|||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[non_exhaustive]
|
||||
pub struct Annotations {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub audience: Option<Vec<Role>>,
|
||||
|
|
|
|||
|
|
@ -243,6 +243,7 @@ pub struct SamplingCapability {
|
|||
/// ```
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[non_exhaustive]
|
||||
pub struct ClientCapabilities {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub experimental: Option<ExperimentalCapabilities>,
|
||||
|
|
@ -280,6 +281,7 @@ pub struct ClientCapabilities {
|
|||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Default)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[non_exhaustive]
|
||||
pub struct ServerCapabilities {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub experimental: Option<ExperimentalCapabilities>,
|
||||
|
|
|
|||
|
|
@ -38,6 +38,17 @@ pub struct RawEmbeddedResource {
|
|||
pub meta: Option<super::Meta>,
|
||||
pub resource: ResourceContents,
|
||||
}
|
||||
|
||||
impl RawEmbeddedResource {
|
||||
/// Create a new RawEmbeddedResource.
|
||||
pub fn new(resource: ResourceContents) -> Self {
|
||||
Self {
|
||||
meta: None,
|
||||
resource,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type EmbeddedResource = Annotated<RawEmbeddedResource>;
|
||||
|
||||
impl EmbeddedResource {
|
||||
|
|
@ -63,6 +74,7 @@ pub type AudioContent = Annotated<RawAudioContent>;
|
|||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[non_exhaustive]
|
||||
pub struct ToolUseContent {
|
||||
/// Unique identifier for this tool call
|
||||
pub id: String,
|
||||
|
|
@ -79,6 +91,7 @@ pub struct ToolUseContent {
|
|||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[non_exhaustive]
|
||||
pub struct ToolResultContent {
|
||||
/// Optional metadata
|
||||
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ pub enum StringFormat {
|
|||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[non_exhaustive]
|
||||
pub struct StringSchema {
|
||||
/// Type discriminator
|
||||
#[serde(rename = "type")]
|
||||
|
|
@ -237,6 +238,7 @@ impl StringSchema {
|
|||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[non_exhaustive]
|
||||
pub struct NumberSchema {
|
||||
/// Type discriminator
|
||||
#[serde(rename = "type")]
|
||||
|
|
@ -444,6 +446,7 @@ impl IntegerSchema {
|
|||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[non_exhaustive]
|
||||
pub struct BooleanSchema {
|
||||
/// Type discriminator
|
||||
#[serde(rename = "type")]
|
||||
|
|
@ -513,6 +516,16 @@ pub struct ConstTitle {
|
|||
pub title: String,
|
||||
}
|
||||
|
||||
impl ConstTitle {
|
||||
/// Create a new ConstTitle.
|
||||
pub fn new(const_: impl Into<String>, title: impl Into<String>) -> Self {
|
||||
Self {
|
||||
const_: const_.into(),
|
||||
title: title.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Legacy enum schema, keep for backward compatibility
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
|
|
@ -533,6 +546,7 @@ pub struct LegacyEnumSchema {
|
|||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[non_exhaustive]
|
||||
pub struct UntitledSingleSelectEnumSchema {
|
||||
#[serde(rename = "type")]
|
||||
pub type_: StringTypeConst,
|
||||
|
|
@ -550,6 +564,7 @@ pub struct UntitledSingleSelectEnumSchema {
|
|||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[non_exhaustive]
|
||||
pub struct TitledSingleSelectEnumSchema {
|
||||
#[serde(rename = "type")]
|
||||
pub type_: StringTypeConst,
|
||||
|
|
@ -563,6 +578,19 @@ pub struct TitledSingleSelectEnumSchema {
|
|||
pub default: Option<String>,
|
||||
}
|
||||
|
||||
impl TitledSingleSelectEnumSchema {
|
||||
/// Create a new TitledSingleSelectEnumSchema.
|
||||
pub fn new(one_of: Vec<ConstTitle>) -> Self {
|
||||
Self {
|
||||
type_: StringTypeConst,
|
||||
title: None,
|
||||
description: None,
|
||||
one_of,
|
||||
default: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Combined single-select
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
|
|
@ -592,10 +620,18 @@ pub struct TitledItems {
|
|||
pub any_of: Vec<ConstTitle>,
|
||||
}
|
||||
|
||||
impl TitledItems {
|
||||
/// Create a new TitledItems.
|
||||
pub fn new(any_of: Vec<ConstTitle>) -> Self {
|
||||
Self { any_of }
|
||||
}
|
||||
}
|
||||
|
||||
/// Multi-select untitled options
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[non_exhaustive]
|
||||
pub struct UntitledMultiSelectEnumSchema {
|
||||
#[serde(rename = "type")]
|
||||
pub type_: ArrayTypeConst,
|
||||
|
|
@ -616,6 +652,7 @@ pub struct UntitledMultiSelectEnumSchema {
|
|||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[non_exhaustive]
|
||||
pub struct TitledMultiSelectEnumSchema {
|
||||
#[serde(rename = "type")]
|
||||
pub type_: ArrayTypeConst,
|
||||
|
|
@ -632,6 +669,51 @@ pub struct TitledMultiSelectEnumSchema {
|
|||
pub default: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
impl TitledMultiSelectEnumSchema {
|
||||
/// Create a new TitledMultiSelectEnumSchema.
|
||||
pub fn new(items: TitledItems) -> Self {
|
||||
Self {
|
||||
type_: ArrayTypeConst,
|
||||
title: None,
|
||||
description: None,
|
||||
min_items: None,
|
||||
max_items: None,
|
||||
items,
|
||||
default: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the title.
|
||||
pub fn with_title(mut self, title: impl Into<Cow<'static, str>>) -> Self {
|
||||
self.title = Some(title.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the description.
|
||||
pub fn with_description(mut self, description: impl Into<Cow<'static, str>>) -> Self {
|
||||
self.description = Some(description.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the minimum number of items.
|
||||
pub fn with_min_items(mut self, min_items: u64) -> Self {
|
||||
self.min_items = Some(min_items);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the maximum number of items.
|
||||
pub fn with_max_items(mut self, max_items: u64) -> Self {
|
||||
self.max_items = Some(max_items);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the default values.
|
||||
pub fn with_default(mut self, default: Vec<String>) -> Self {
|
||||
self.default = Some(default);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Multi-select enum options
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
|
|
|
|||
|
|
@ -7,9 +7,10 @@ use super::{
|
|||
};
|
||||
|
||||
/// A prompt that can be used to generate text from a model
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[non_exhaustive]
|
||||
pub struct Prompt {
|
||||
/// The name of the prompt
|
||||
pub name: String,
|
||||
|
|
@ -49,11 +50,46 @@ impl Prompt {
|
|||
meta: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new prompt from raw fields (used by the macro)
|
||||
pub fn from_raw(
|
||||
name: impl Into<String>,
|
||||
description: Option<impl Into<String>>,
|
||||
arguments: Option<Vec<PromptArgument>>,
|
||||
) -> Self {
|
||||
Prompt {
|
||||
name: name.into(),
|
||||
title: None,
|
||||
description: description.map(Into::into),
|
||||
arguments,
|
||||
icons: None,
|
||||
meta: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the human-readable title
|
||||
pub fn with_title(mut self, title: Option<String>) -> Self {
|
||||
self.title = title;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the icons
|
||||
pub fn with_icons(mut self, icons: Option<Vec<Icon>>) -> Self {
|
||||
self.icons = icons;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the metadata
|
||||
pub fn with_meta(mut self, meta: Option<Meta>) -> Self {
|
||||
self.meta = meta;
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a prompt argument that can be passed to customize the prompt
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[non_exhaustive]
|
||||
pub struct PromptArgument {
|
||||
/// The name of the argument
|
||||
pub name: String,
|
||||
|
|
@ -68,6 +104,36 @@ pub struct PromptArgument {
|
|||
pub required: Option<bool>,
|
||||
}
|
||||
|
||||
impl PromptArgument {
|
||||
/// Create a new prompt argument
|
||||
pub fn new<N: Into<String>>(name: N) -> Self {
|
||||
PromptArgument {
|
||||
name: name.into(),
|
||||
title: None,
|
||||
description: None,
|
||||
required: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the title
|
||||
pub fn with_title<T: Into<String>>(mut self, title: T) -> Self {
|
||||
self.title = Some(title.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the description
|
||||
pub fn with_description<D: Into<String>>(mut self, description: D) -> Self {
|
||||
self.description = Some(description.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the required flag
|
||||
pub fn with_required(mut self, required: bool) -> Self {
|
||||
self.required = Some(required);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the role of a message sender in a prompt conversation
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
|
|
@ -112,6 +178,7 @@ impl PromptMessageContent {
|
|||
/// A message in a prompt conversation
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[non_exhaustive]
|
||||
pub struct PromptMessage {
|
||||
/// The role of the message sender
|
||||
pub role: PromptMessageRole,
|
||||
|
|
@ -120,6 +187,11 @@ pub struct PromptMessage {
|
|||
}
|
||||
|
||||
impl PromptMessage {
|
||||
/// Create a new prompt message with the given role and content
|
||||
pub fn new(role: PromptMessageRole, content: PromptMessageContent) -> Self {
|
||||
Self { role, content }
|
||||
}
|
||||
|
||||
/// Create a new text message with the given role and text content
|
||||
pub fn new_text<S: Into<String>>(role: PromptMessageRole, text: S) -> Self {
|
||||
Self {
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ pub enum ResourceContents {
|
|||
}
|
||||
|
||||
impl ResourceContents {
|
||||
/// Create text resource contents.
|
||||
pub fn text(text: impl Into<String>, uri: impl Into<String>) -> Self {
|
||||
Self::TextResourceContents {
|
||||
uri: uri.into(),
|
||||
|
|
@ -88,6 +89,34 @@ impl ResourceContents {
|
|||
meta: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create blob resource contents.
|
||||
pub fn blob(blob: impl Into<String>, uri: impl Into<String>) -> Self {
|
||||
Self::BlobResourceContents {
|
||||
uri: uri.into(),
|
||||
mime_type: None,
|
||||
blob: blob.into(),
|
||||
meta: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the MIME type on this resource contents.
|
||||
pub fn with_mime_type(mut self, mime_type: impl Into<String>) -> Self {
|
||||
match &mut self {
|
||||
Self::TextResourceContents { mime_type: mt, .. } => *mt = Some(mime_type.into()),
|
||||
Self::BlobResourceContents { mime_type: mt, .. } => *mt = Some(mime_type.into()),
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the metadata on this resource contents.
|
||||
pub fn with_meta(mut self, meta: Meta) -> Self {
|
||||
match &mut self {
|
||||
Self::TextResourceContents { meta: m, .. } => *m = Some(meta),
|
||||
Self::BlobResourceContents { meta: m, .. } => *m = Some(meta),
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RawResource {
|
||||
|
|
@ -104,6 +133,80 @@ impl RawResource {
|
|||
meta: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the human-readable title.
|
||||
pub fn with_title(mut self, title: impl Into<String>) -> Self {
|
||||
self.title = Some(title.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the description.
|
||||
pub fn with_description(mut self, description: impl Into<String>) -> Self {
|
||||
self.description = Some(description.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the MIME type.
|
||||
pub fn with_mime_type(mut self, mime_type: impl Into<String>) -> Self {
|
||||
self.mime_type = Some(mime_type.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the size in bytes.
|
||||
pub fn with_size(mut self, size: u32) -> Self {
|
||||
self.size = Some(size);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the icons.
|
||||
pub fn with_icons(mut self, icons: Vec<Icon>) -> Self {
|
||||
self.icons = Some(icons);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the metadata.
|
||||
pub fn with_meta(mut self, meta: Meta) -> Self {
|
||||
self.meta = Some(meta);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl RawResourceTemplate {
|
||||
/// Creates a new RawResourceTemplate with a URI template and name.
|
||||
pub fn new(uri_template: impl Into<String>, name: impl Into<String>) -> Self {
|
||||
Self {
|
||||
uri_template: uri_template.into(),
|
||||
name: name.into(),
|
||||
title: None,
|
||||
description: None,
|
||||
mime_type: None,
|
||||
icons: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the human-readable title.
|
||||
pub fn with_title(mut self, title: impl Into<String>) -> Self {
|
||||
self.title = Some(title.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the description.
|
||||
pub fn with_description(mut self, description: impl Into<String>) -> Self {
|
||||
self.description = Some(description.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the MIME type.
|
||||
pub fn with_mime_type(mut self, mime_type: impl Into<String>) -> Self {
|
||||
self.mime_type = Some(mime_type.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the icons.
|
||||
pub fn with_icons(mut self, icons: Vec<Icon>) -> Self {
|
||||
self.icons = Some(icons);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ pub enum TaskStatus {
|
|||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[non_exhaustive]
|
||||
pub struct Task {
|
||||
/// Unique task identifier generated by the receiver.
|
||||
pub task_id: String,
|
||||
|
|
@ -48,14 +49,60 @@ pub struct Task {
|
|||
pub poll_interval: Option<u64>,
|
||||
}
|
||||
|
||||
impl Task {
|
||||
/// Create a new Task with required fields.
|
||||
pub fn new(
|
||||
task_id: String,
|
||||
status: TaskStatus,
|
||||
created_at: String,
|
||||
last_updated_at: String,
|
||||
) -> Self {
|
||||
Self {
|
||||
task_id,
|
||||
status,
|
||||
status_message: None,
|
||||
created_at,
|
||||
last_updated_at,
|
||||
ttl: None,
|
||||
poll_interval: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the status message.
|
||||
pub fn with_status_message(mut self, status_message: impl Into<String>) -> Self {
|
||||
self.status_message = Some(status_message.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the TTL in milliseconds. `None` means unlimited retention.
|
||||
pub fn with_ttl(mut self, ttl: u64) -> Self {
|
||||
self.ttl = Some(ttl);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the poll interval in milliseconds.
|
||||
pub fn with_poll_interval(mut self, poll_interval: u64) -> Self {
|
||||
self.poll_interval = Some(poll_interval);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Wrapper returned by task-augmented requests (CreateTaskResult in SEP-1686).
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[non_exhaustive]
|
||||
pub struct CreateTaskResult {
|
||||
pub task: Task,
|
||||
}
|
||||
|
||||
impl CreateTaskResult {
|
||||
/// Create a new CreateTaskResult.
|
||||
pub fn new(task: Task) -> Self {
|
||||
Self { task }
|
||||
}
|
||||
}
|
||||
|
||||
/// Response to a `tasks/get` request.
|
||||
///
|
||||
/// Per spec, `GetTaskResult = allOf[Result, Task]` — the Task fields are
|
||||
|
|
@ -78,8 +125,16 @@ pub struct GetTaskResult {
|
|||
/// serialized as a JSON value.
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[non_exhaustive]
|
||||
pub struct GetTaskPayloadResult(pub Value);
|
||||
|
||||
impl GetTaskPayloadResult {
|
||||
/// Create a new GetTaskPayloadResult with the given value.
|
||||
pub fn new(value: Value) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
/// Response to a `tasks/cancel` request.
|
||||
///
|
||||
/// Per spec, `CancelTaskResult = allOf[Result, Task]` — same shape as `GetTaskResult`.
|
||||
|
|
@ -104,3 +159,14 @@ pub struct TaskList {
|
|||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub total: Option<u64>,
|
||||
}
|
||||
|
||||
impl TaskList {
|
||||
/// Create a new TaskList.
|
||||
pub fn new(tasks: Vec<Task>) -> Self {
|
||||
Self {
|
||||
tasks,
|
||||
next_cursor: None,
|
||||
total: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,9 +10,10 @@ use serde_json::Value;
|
|||
use super::{Icon, JsonObject, Meta};
|
||||
|
||||
/// A tool that can be used by a model.
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[non_exhaustive]
|
||||
pub struct Tool {
|
||||
/// The name of the tool
|
||||
pub name: Cow<'static, str>,
|
||||
|
|
@ -67,6 +68,7 @@ pub enum TaskSupport {
|
|||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[non_exhaustive]
|
||||
pub struct ToolExecution {
|
||||
/// Indicates whether this tool supports task-based invocation.
|
||||
///
|
||||
|
|
@ -83,6 +85,11 @@ impl ToolExecution {
|
|||
Self::default()
|
||||
}
|
||||
|
||||
/// Create a ToolExecution from raw optional fields.
|
||||
pub fn from_raw(task_support: Option<TaskSupport>) -> Self {
|
||||
Self { task_support }
|
||||
}
|
||||
|
||||
/// Set the task support mode.
|
||||
pub fn with_task_support(mut self, task_support: TaskSupport) -> Self {
|
||||
self.task_support = Some(task_support);
|
||||
|
|
@ -101,6 +108,7 @@ impl ToolExecution {
|
|||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
|
||||
#[non_exhaustive]
|
||||
pub struct ToolAnnotations {
|
||||
/// A human-readable title for the tool.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
|
|
@ -145,6 +153,24 @@ impl ToolAnnotations {
|
|||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Create a new ToolAnnotations with all fields specified
|
||||
pub fn from_raw(
|
||||
title: Option<String>,
|
||||
read_only_hint: Option<bool>,
|
||||
destructive_hint: Option<bool>,
|
||||
idempotent_hint: Option<bool>,
|
||||
open_world_hint: Option<bool>,
|
||||
) -> Self {
|
||||
ToolAnnotations {
|
||||
title,
|
||||
read_only_hint,
|
||||
destructive_hint,
|
||||
idempotent_hint,
|
||||
open_world_hint,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_title<T>(title: T) -> Self
|
||||
where
|
||||
T: Into<String>,
|
||||
|
|
@ -211,6 +237,59 @@ impl Tool {
|
|||
}
|
||||
}
|
||||
|
||||
/// Create a new tool with just a name and input schema (no description)
|
||||
pub fn new_with_raw<N, S>(
|
||||
name: N,
|
||||
description: Option<Cow<'static, str>>,
|
||||
input_schema: S,
|
||||
) -> Self
|
||||
where
|
||||
N: Into<Cow<'static, str>>,
|
||||
S: Into<Arc<JsonObject>>,
|
||||
{
|
||||
Tool {
|
||||
name: name.into(),
|
||||
title: None,
|
||||
description,
|
||||
input_schema: input_schema.into(),
|
||||
output_schema: None,
|
||||
annotations: None,
|
||||
execution: None,
|
||||
icons: None,
|
||||
meta: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the human-readable title
|
||||
pub fn with_title(mut self, title: Option<String>) -> Self {
|
||||
self.title = title;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the output schema from a raw value
|
||||
pub fn with_raw_output_schema(mut self, output_schema: Option<Arc<JsonObject>>) -> Self {
|
||||
self.output_schema = output_schema;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the annotations
|
||||
pub fn with_annotations(mut self, annotations: Option<ToolAnnotations>) -> Self {
|
||||
self.annotations = annotations;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the icons
|
||||
pub fn with_icons(mut self, icons: Option<Vec<Icon>>) -> Self {
|
||||
self.icons = icons;
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the metadata
|
||||
pub fn with_meta(mut self, meta: Option<Meta>) -> Self {
|
||||
self.meta = meta;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn annotate(self, annotations: ToolAnnotations) -> Self {
|
||||
Tool {
|
||||
annotations: Some(annotations),
|
||||
|
|
@ -219,11 +298,9 @@ impl Tool {
|
|||
}
|
||||
|
||||
/// Set the execution configuration for this tool.
|
||||
pub fn with_execution(self, execution: ToolExecution) -> Self {
|
||||
Tool {
|
||||
execution: Some(execution),
|
||||
..self
|
||||
}
|
||||
pub fn with_execution(mut self, execution: Option<ToolExecution>) -> Self {
|
||||
self.execution = execution;
|
||||
self
|
||||
}
|
||||
|
||||
/// Returns the task support mode for this tool.
|
||||
|
|
|
|||
Loading…
Reference in a new issue