///|
/// Optional annotations attached to content blocks.
pub(all) struct Annotations {
audience : ProtocolNullable[Array[Role]]
last_modified : ProtocolNullable[String]
priority : ProtocolNullable[Double]
meta : ProtocolNullable[Json]
} derive(Eq, Debug)
///|
/// Text provided to or from an LLM.
pub(all) struct TextContent {
annotations : ProtocolNullable[Annotations]
text : String
meta : ProtocolNullable[Json]
} derive(Eq, Debug)
///|
/// An image provided to or from an LLM.
pub(all) struct ImageContent {
annotations : ProtocolNullable[Annotations]
data : String
mime_type : String
uri : ProtocolNullable[String]
meta : ProtocolNullable[Json]
} derive(Eq, Debug)
///|
/// Audio provided to or from an LLM.
pub(all) struct AudioContent {
annotations : ProtocolNullable[Annotations]
data : String
mime_type : String
meta : ProtocolNullable[Json]
} derive(Eq, Debug)
///|
/// A resource that the server can read.
pub(all) struct ResourceLink {
annotations : ProtocolNullable[Annotations]
description : ProtocolNullable[String]
mime_type : ProtocolNullable[String]
name : String
size : ProtocolNullable[Int64]
title : ProtocolNullable[String]
uri : String
meta : ProtocolNullable[Json]
} derive(Eq, Debug)
///|
/// Text-based resource contents embedded directly in a message.
pub(all) struct TextResourceContents {
mime_type : ProtocolNullable[String]
text : String
uri : String
meta : ProtocolNullable[Json]
} derive(Eq, Debug)
///|
/// Binary resource contents embedded directly in a message.
pub(all) struct BlobResourceContents {
blob : String
mime_type : ProtocolNullable[String]
uri : String
meta : ProtocolNullable[Json]
} derive(Eq, Debug)
///|
/// The two resource payloads accepted by an embedded resource.
pub(all) enum EmbeddedResourceResource {
Text(TextResourceContents)
Blob(BlobResourceContents)
} derive(Eq, Debug)
///|
/// Complete resource contents embedded directly in a message.
pub(all) struct EmbeddedResource {
annotations : ProtocolNullable[Annotations]
resource : EmbeddedResourceResource
meta : ProtocolNullable[Json]
} derive(Eq, Debug)
///|
/// The five stable ACP content block variants.
pub(all) enum ContentBlock {
Text(TextContent)
Image(ImageContent)
Audio(AudioContent)
ResourceLink(ResourceLink)
Resource(EmbeddedResource)
} derive(Eq, Debug)
///|
/// A standard content wrapper.
pub(all) struct Content {
content : ContentBlock
meta : ProtocolNullable[Json]
} derive(Eq, Debug)
///|
/// One streamed content item.
pub(all) struct ContentChunk {
content : ContentBlock
message_id : ProtocolNullable[MessageId]
meta : ProtocolNullable[Json]
} derive(Eq, Debug)
///|
fn decode_role_array(
value : Json,
path~ : String,
) -> Array[Role] raise ProtocolDecodeError {
let values = protocol_require_array(value, path~)
let roles : Array[Role] = []
for index, value in values {
roles.push(
protocol_decode_role(value, path=path + "[" + index.to_string() + "]"),
)
}
roles
}
///|
fn encode_role_array(values : Array[Role]) -> Json {
Json::array(values.map(value => protocol_encode_role(value)))
}
///|
fn decode_nullable_annotations(
fields : Map[String, Json],
path~ : String,
) -> ProtocolNullable[Annotations] raise ProtocolDecodeError {
match protocol_field(fields, "annotations") {
Omitted => Omitted
Null => Null
Value(value) =>
Value(annotations_from_json(value, path=path + ".annotations"))
}
}
///|
fn put_nullable_annotations(
fields : Map[String, Json],
value : ProtocolNullable[Annotations],
) -> Unit raise ProtocolDecodeError {
match value {
Omitted => ()
Null => fields["annotations"] = Json::null()
Value(value) => fields["annotations"] = annotations_to_json(value)
}
}
///|
fn decode_finite_number(
value : Json,
path~ : String,
) -> Double raise ProtocolDecodeError {
let number = protocol_decode_number(value, path~)
if number.is_nan() || number.is_inf() {
raise InvalidField(path~, reason="number must be finite")
}
number
}
///|
fn encode_finite_number(
value : Double,
path~ : String,
) -> Json raise ProtocolDecodeError {
if value.is_nan() || value.is_inf() {
raise InvalidField(path~, reason="number must be finite")
}
Json::number(value)
}
///|
fn decode_annotations_fields(
fields : Map[String, Json],
path~ : String,
) -> Annotations raise ProtocolDecodeError {
protocol_reject_unknown(
fields,
["audience", "lastModified", "priority", "_meta"],
prefix=path,
)
let audience : ProtocolNullable[Array[Role]] = match
protocol_field(fields, "audience") {
Omitted => Omitted
Null => Null
Value(value) => Value(decode_role_array(value, path=path + ".audience"))
}
let last_modified = protocol_nullable_string(
fields,
"lastModified",
path=path + ".lastModified",
)
let priority : ProtocolNullable[Double] = match
protocol_field(fields, "priority") {
Omitted => Omitted
Null => Null
Value(value) => Value(decode_finite_number(value, path=path + ".priority"))
}
let meta = protocol_meta(fields, path=path + "._meta")
{ audience, last_modified, priority, meta }
}
///|
/// Decode annotations from a JSON value.
pub fn annotations_from_json(
value : Json,
path? : String = "annotations",
) -> Annotations raise ProtocolDecodeError {
let fields = protocol_require_object(value, path~)
decode_annotations_fields(fields, path~)
}
///|
/// Encode annotations as a JSON object.
pub fn annotations_to_json(
value : Annotations,
) -> Json raise ProtocolDecodeError {
let fields : Map[String, Json] = Map([])
match value.audience {
Omitted => ()
Null => fields["audience"] = Json::null()
Value(audience) => fields["audience"] = encode_role_array(audience)
}
match value.last_modified {
Omitted => ()
Null => fields["lastModified"] = Json::null()
Value(last_modified) => fields["lastModified"] = Json::string(last_modified)
}
match value.priority {
Omitted => ()
Null => fields["priority"] = Json::null()
Value(priority) =>
fields["priority"] = encode_finite_number(priority, path="priority")
}
protocol_put_meta(fields, value.meta)
Json::object(fields)
}
///|
fn decode_text_content_fields(
fields : Map[String, Json],
path~ : String,
with_type : Bool,
) -> TextContent raise ProtocolDecodeError {
let allowed = if with_type {
["type", "annotations", "text", "_meta"]
} else {
["annotations", "text", "_meta"]
}
protocol_reject_unknown(fields, allowed, prefix=path)
let annotations = decode_nullable_annotations(fields, path~)
let text = protocol_required_string(fields, "text", path=path + ".text")
let meta = protocol_meta(fields, path=path + "._meta")
{ annotations, text, meta }
}
///|
/// Decode text content from a JSON value.
pub fn text_content_from_json(
value : Json,
path? : String = "text",
) -> TextContent raise ProtocolDecodeError {
let fields = protocol_require_object(value, path~)
decode_text_content_fields(fields, path~, false)
}
///|
/// Encode text content as a JSON object.
pub fn text_content_to_json(
value : TextContent,
) -> Json raise ProtocolDecodeError {
let fields : Map[String, Json] = Map([])
put_nullable_annotations(fields, value.annotations)
fields["text"] = Json::string(value.text)
protocol_put_meta(fields, value.meta)
Json::object(fields)
}
///|
fn decode_image_content_fields(
fields : Map[String, Json],
path~ : String,
with_type : Bool,
) -> ImageContent raise ProtocolDecodeError {
let allowed = if with_type {
["type", "annotations", "data", "mimeType", "uri", "_meta"]
} else {
["annotations", "data", "mimeType", "uri", "_meta"]
}
protocol_reject_unknown(fields, allowed, prefix=path)
let annotations = decode_nullable_annotations(fields, path~)
let data = protocol_required_string(fields, "data", path=path + ".data")
let data = protocol_validate_base64(data, field_path=path + ".data")
let mime_type = protocol_required_string(
fields,
"mimeType",
path=path + ".mimeType",
)
let uri = protocol_nullable_string(fields, "uri", path=path + ".uri")
let meta = protocol_meta(fields, path=path + "._meta")
{ annotations, data, mime_type, uri, meta }
}
///|
/// Decode image content from a JSON value.
pub fn image_content_from_json(
value : Json,
path? : String = "image",
) -> ImageContent raise ProtocolDecodeError {
let fields = protocol_require_object(value, path~)
decode_image_content_fields(fields, path~, false)
}
///|
/// Encode image content as a JSON object.
pub fn image_content_to_json(
value : ImageContent,
) -> Json raise ProtocolDecodeError {
let fields : Map[String, Json] = Map([])
put_nullable_annotations(fields, value.annotations)
fields["data"] = Json::string(
protocol_validate_base64(value.data, field_path="data"),
)
fields["mimeType"] = Json::string(value.mime_type)
protocol_put_nullable(fields, "uri", value.uri, value => Json::string(value))
protocol_put_meta(fields, value.meta)
Json::object(fields)
}
///|
fn decode_audio_content_fields(
fields : Map[String, Json],
path~ : String,
with_type : Bool,
) -> AudioContent raise ProtocolDecodeError {
let allowed = if with_type {
["type", "annotations", "data", "mimeType", "_meta"]
} else {
["annotations", "data", "mimeType", "_meta"]
}
protocol_reject_unknown(fields, allowed, prefix=path)
let annotations = decode_nullable_annotations(fields, path~)
let data = protocol_required_string(fields, "data", path=path + ".data")
let data = protocol_validate_base64(data, field_path=path + ".data")
let mime_type = protocol_required_string(
fields,
"mimeType",
path=path + ".mimeType",
)
let meta = protocol_meta(fields, path=path + "._meta")
{ annotations, data, mime_type, meta }
}
///|
/// Decode audio content from a JSON value.
pub fn audio_content_from_json(
value : Json,
path? : String = "audio",
) -> AudioContent raise ProtocolDecodeError {
let fields = protocol_require_object(value, path~)
decode_audio_content_fields(fields, path~, false)
}
///|
/// Encode audio content as a JSON object.
pub fn audio_content_to_json(
value : AudioContent,
) -> Json raise ProtocolDecodeError {
let fields : Map[String, Json] = Map([])
put_nullable_annotations(fields, value.annotations)
fields["data"] = Json::string(
protocol_validate_base64(value.data, field_path="data"),
)
fields["mimeType"] = Json::string(value.mime_type)
protocol_put_meta(fields, value.meta)
Json::object(fields)
}
///|
fn decode_resource_link_fields(
fields : Map[String, Json],
path~ : String,
with_type : Bool,
) -> ResourceLink raise ProtocolDecodeError {
let allowed = if with_type {
[
"type", "annotations", "description", "mimeType", "name", "size", "title",
"uri", "_meta",
]
} else {
[
"annotations", "description", "mimeType", "name", "size", "title", "uri", "_meta",
]
}
protocol_reject_unknown(fields, allowed, prefix=path)
let annotations = decode_nullable_annotations(fields, path~)
let description = protocol_nullable_string(
fields,
"description",
path=path + ".description",
)
let mime_type = protocol_nullable_string(
fields,
"mimeType",
path=path + ".mimeType",
)
let name = protocol_required_string(fields, "name", path=path + ".name")
let size : ProtocolNullable[Int64] = match protocol_field(fields, "size") {
Omitted => Omitted
Null => Null
Value(value) => Value(protocol_decode_int64(value, path=path + ".size"))
}
let title = protocol_nullable_string(fields, "title", path=path + ".title")
let uri = protocol_required_string(fields, "uri", path=path + ".uri")
let meta = protocol_meta(fields, path=path + "._meta")
{ annotations, description, mime_type, name, size, title, uri, meta }
}
///|
/// Decode a resource link from a JSON value.
pub fn resource_link_from_json(
value : Json,
path? : String = "resource_link",
) -> ResourceLink raise ProtocolDecodeError {
let fields = protocol_require_object(value, path~)
decode_resource_link_fields(fields, path~, false)
}
///|
/// Encode a resource link as a JSON object.
pub fn resource_link_to_json(
value : ResourceLink,
) -> Json raise ProtocolDecodeError {
let fields : Map[String, Json] = Map([])
put_nullable_annotations(fields, value.annotations)
protocol_put_nullable(fields, "description", value.description, value => {
Json::string(value)
})
protocol_put_nullable(fields, "mimeType", value.mime_type, value => {
Json::string(value)
})
fields["name"] = Json::string(value.name)
match value.size {
Omitted => ()
Null => fields["size"] = Json::null()
Value(size) => fields["size"] = size.to_json()
}
protocol_put_nullable(fields, "title", value.title, value => {
Json::string(value)
})
fields["uri"] = Json::string(value.uri)
protocol_put_meta(fields, value.meta)
Json::object(fields)
}
///|
fn decode_text_resource_contents_fields(
fields : Map[String, Json],
path~ : String,
) -> TextResourceContents raise ProtocolDecodeError {
protocol_reject_unknown(
fields,
["mimeType", "text", "uri", "_meta"],
prefix=path,
)
let mime_type = protocol_nullable_string(
fields,
"mimeType",
path=path + ".mimeType",
)
let text = protocol_required_string(fields, "text", path=path + ".text")
let uri = protocol_required_string(fields, "uri", path=path + ".uri")
let meta = protocol_meta(fields, path=path + "._meta")
{ mime_type, text, uri, meta }
}
///|
/// Decode text resource contents from a JSON value.
pub fn text_resource_contents_from_json(
value : Json,
path? : String = "resource",
) -> TextResourceContents raise ProtocolDecodeError {
let fields = protocol_require_object(value, path~)
decode_text_resource_contents_fields(fields, path~)
}
///|
/// Encode text resource contents as a JSON object.
pub fn text_resource_contents_to_json(
value : TextResourceContents,
) -> Json raise ProtocolDecodeError {
let fields : Map[String, Json] = Map([])
protocol_put_nullable(fields, "mimeType", value.mime_type, value => {
Json::string(value)
})
fields["text"] = Json::string(value.text)
fields["uri"] = Json::string(value.uri)
protocol_put_meta(fields, value.meta)
Json::object(fields)
}
///|
fn decode_blob_resource_contents_fields(
fields : Map[String, Json],
path~ : String,
) -> BlobResourceContents raise ProtocolDecodeError {
protocol_reject_unknown(
fields,
["blob", "mimeType", "uri", "_meta"],
prefix=path,
)
let blob = protocol_required_string(fields, "blob", path=path + ".blob")
let blob = protocol_validate_base64(blob, field_path=path + ".blob")
let mime_type = protocol_nullable_string(
fields,
"mimeType",
path=path + ".mimeType",
)
let uri = protocol_required_string(fields, "uri", path=path + ".uri")
let meta = protocol_meta(fields, path=path + "._meta")
{ blob, mime_type, uri, meta }
}
///|
/// Decode binary resource contents from a JSON value.
pub fn blob_resource_contents_from_json(
value : Json,
path? : String = "resource",
) -> BlobResourceContents raise ProtocolDecodeError {
let fields = protocol_require_object(value, path~)
decode_blob_resource_contents_fields(fields, path~)
}
///|
/// Encode binary resource contents as a JSON object.
pub fn blob_resource_contents_to_json(
value : BlobResourceContents,
) -> Json raise ProtocolDecodeError {
let fields : Map[String, Json] = Map([])
fields["blob"] = Json::string(
protocol_validate_base64(value.blob, field_path="blob"),
)
protocol_put_nullable(fields, "mimeType", value.mime_type, value => {
Json::string(value)
})
fields["uri"] = Json::string(value.uri)
protocol_put_meta(fields, value.meta)
Json::object(fields)
}
///|
/// Decode an embedded resource payload from a JSON value.
pub fn embedded_resource_resource_from_json(
value : Json,
path? : String = "resource",
) -> EmbeddedResourceResource raise ProtocolDecodeError {
let fields = protocol_require_object(value, path~)
let has_text = fields.contains("text")
let has_blob = fields.contains("blob")
if has_text && has_blob {
raise InvalidField(
path~,
reason="resource payload cannot contain both text and blob",
)
}
if has_text {
Text(decode_text_resource_contents_fields(fields, path~))
} else if has_blob {
Blob(decode_blob_resource_contents_fields(fields, path~))
} else {
raise InvalidField(
path~,
reason="resource payload must contain text or blob",
)
}
}
///|
/// Encode an embedded resource payload as a JSON object.
pub fn embedded_resource_resource_to_json(
value : EmbeddedResourceResource,
) -> Json raise ProtocolDecodeError {
match value {
Text(value) => text_resource_contents_to_json(value)
Blob(value) => blob_resource_contents_to_json(value)
}
}
///|
fn decode_embedded_resource_fields(
fields : Map[String, Json],
path~ : String,
with_type : Bool,
) -> EmbeddedResource raise ProtocolDecodeError {
let allowed = if with_type {
["type", "annotations", "resource", "_meta"]
} else {
["annotations", "resource", "_meta"]
}
protocol_reject_unknown(fields, allowed, prefix=path)
let annotations = decode_nullable_annotations(fields, path~)
let resource = match fields.get("resource") {
Some(value) =>
embedded_resource_resource_from_json(value, path=path + ".resource")
None => raise MissingField(path=path + ".resource")
}
let meta = protocol_meta(fields, path=path + "._meta")
{ annotations, resource, meta }
}
///|
/// Decode an embedded resource from a JSON value.
pub fn embedded_resource_from_json(
value : Json,
path? : String = "resource",
) -> EmbeddedResource raise ProtocolDecodeError {
let fields = protocol_require_object(value, path~)
decode_embedded_resource_fields(fields, path~, false)
}
///|
/// Encode an embedded resource as a JSON object.
pub fn embedded_resource_to_json(
value : EmbeddedResource,
) -> Json raise ProtocolDecodeError {
let fields : Map[String, Json] = Map([])
put_nullable_annotations(fields, value.annotations)
fields["resource"] = embedded_resource_resource_to_json(value.resource)
protocol_put_meta(fields, value.meta)
Json::object(fields)
}
///|
fn add_content_discriminator(value : Json, kind : String) -> Json {
match value {
Object(fields) => {
fields["type"] = Json::string(kind)
Json::object(fields)
}
_ => value
}
}
///|
/// Encode one of the five stable ACP content block variants.
pub fn content_block_to_json(
value : ContentBlock,
) -> Json raise ProtocolDecodeError {
match value {
Text(value) =>
add_content_discriminator(text_content_to_json(value), "text")
Image(value) =>
add_content_discriminator(image_content_to_json(value), "image")
Audio(value) =>
add_content_discriminator(audio_content_to_json(value), "audio")
ResourceLink(value) =>
add_content_discriminator(resource_link_to_json(value), "resource_link")
Resource(value) =>
add_content_discriminator(embedded_resource_to_json(value), "resource")
}
}
///|
fn content_block_from_fields(
fields : Map[String, Json],
path~ : String,
) -> ContentBlock raise ProtocolDecodeError {
let kind = protocol_required_string(fields, "type", path=path + ".type")
match kind {
"text" => Text(decode_text_content_fields(fields, path~, true))
"image" => Image(decode_image_content_fields(fields, path~, true))
"audio" => Audio(decode_audio_content_fields(fields, path~, true))
"resource_link" =>
ResourceLink(decode_resource_link_fields(fields, path~, true))
"resource" => Resource(decode_embedded_resource_fields(fields, path~, true))
_ => raise InvalidDiscriminator(path=path + ".type", value=kind)
}
}
///|
/// Decode one of the five stable ACP content block variants.
pub fn content_block_from_json(
value : Json,
path? : String = "content",
) -> ContentBlock raise ProtocolDecodeError {
let fields = protocol_require_object(value, path~)
content_block_from_fields(fields, path~)
}
///|
/// Decode a standard content wrapper.
fn content_from_fields(
fields : Map[String, Json],
path~ : String,
with_type : Bool,
) -> Content raise ProtocolDecodeError {
let allowed = if with_type {
["type", "content", "_meta"]
} else {
["content", "_meta"]
}
protocol_reject_unknown(fields, allowed, prefix=path)
let content = match fields.get("content") {
Some(value) => content_block_from_json(value, path=path + ".content")
None => raise MissingField(path=path + ".content")
}
let meta = protocol_meta(fields, path=path + "._meta")
{ content, meta }
}
///|
pub fn content_from_json(
value : Json,
path? : String = "content",
) -> Content raise ProtocolDecodeError {
let fields = protocol_require_object(value, path~)
content_from_fields(fields, path~, false)
}
///|
/// Encode a standard content wrapper.
pub fn content_to_json(value : Content) -> Json raise ProtocolDecodeError {
let fields : Map[String, Json] = Map([])
fields["content"] = content_block_to_json(value.content)
protocol_put_meta(fields, value.meta)
Json::object(fields)
}
///|
/// Decode a streamed content item.
fn content_chunk_from_fields(
fields : Map[String, Json],
path~ : String,
with_session_update : Bool,
) -> ContentChunk raise ProtocolDecodeError {
let allowed = if with_session_update {
["sessionUpdate", "content", "messageId", "_meta"]
} else {
["content", "messageId", "_meta"]
}
protocol_reject_unknown(fields, allowed, prefix=path)
let content = match fields.get("content") {
Some(value) => content_block_from_json(value, path=path + ".content")
None => raise MissingField(path=path + ".content")
}
let message_id = protocol_nullable_string(
fields,
"messageId",
path=path + ".messageId",
)
let meta = protocol_meta(fields, path=path + "._meta")
{ content, message_id, meta }
}
///|
pub fn content_chunk_from_json(
value : Json,
path? : String = "contentChunk",
) -> ContentChunk raise ProtocolDecodeError {
let fields = protocol_require_object(value, path~)
content_chunk_from_fields(fields, path~, false)
}
///|
/// Encode a streamed content item.
pub fn content_chunk_to_json(
value : ContentChunk,
) -> Json raise ProtocolDecodeError {
let fields : Map[String, Json] = Map([])
fields["content"] = content_block_to_json(value.content)
protocol_put_nullable(fields, "messageId", value.message_id, value => {
Json::string(value)
})
protocol_put_meta(fields, value.meta)
Json::object(fields)
}