/// Content blocks exchanged over the wire.
///|
/// Audience and priority hints attached to content.
pub(all) struct Annotations {
audience : Array[String]?
priority : Double?
} derive(Debug, Eq)
///|
pub impl ToJson for Annotations with fn to_json(self : Annotations) -> Json {
let obj : Map[String, Json] = Map([])
put_opt_array(
obj,
"audience",
self.audience.map(fn(a) { a.map(Json::string) }),
)
if self.priority is Some(p) {
put_opt_double(obj, "priority", p)
}
Json(obj)
}
///|
pub impl FromJson for Annotations with fn from_json(
json : Json,
path : @json.JsonPath,
) -> Annotations raise @json.JsonDecodeError {
let obj = expect_obj(json, path, "Annotations")
{
audience: opt_str_array(obj, path, "audience"),
priority: opt_double(obj, path, "priority"),
}
}
///|
/// The contents of a resource, either inline text or base64-encoded bytes.
pub(all) enum ResourceContents {
Text(uri~ : String, mime_type~ : String?, text~ : String)
Blob(uri~ : String, mime_type~ : String?, blob~ : String)
} derive(Debug, Eq)
///|
pub fn ResourceContents::uri(self : ResourceContents) -> String {
match self {
Text(uri~, ..) => uri
Blob(uri~, ..) => uri
}
}
///|
pub impl ToJson for ResourceContents with fn to_json(self : ResourceContents) -> Json {
let obj : Map[String, Json] = Map([])
match self {
Text(uri~, mime_type~, text~) => {
put_str(obj, "uri", uri)
put_opt_str(obj, "mimeType", mime_type)
put_str(obj, "text", text)
}
Blob(uri~, mime_type~, blob~) => {
put_str(obj, "uri", uri)
put_opt_str(obj, "mimeType", mime_type)
put_str(obj, "blob", blob)
}
}
Json(obj)
}
///|
pub impl FromJson for ResourceContents with fn from_json(
json : Json,
path : @json.JsonPath,
) -> ResourceContents raise @json.JsonDecodeError {
let obj = expect_obj(json, path, "ResourceContents")
let uri = req_str(obj, path, "ResourceContents", "uri")
let mime_type = opt_str(obj, path, "mimeType")
if obj.get("text") is Some(String(text)) {
return Text(uri~, mime_type~, text~)
}
if obj.get("blob") is Some(String(blob)) {
return Blob(uri~, mime_type~, blob~)
}
raise decode_error(path, "ResourceContents: missing text or blob")
}
///|
/// A block of content in a tool result, sampling message or prompt message.
pub(all) enum ContentBlock {
/// Plain text content.
Text(text~ : String, annotations~ : Annotations?, meta~ : Map[String, Json]?)
/// Base64-encoded image content.
Image(
data~ : String,
mime_type~ : String,
annotations~ : Annotations?,
meta~ : Map[String, Json]?
)
/// Base64-encoded audio content.
Audio(
data~ : String,
mime_type~ : String,
annotations~ : Annotations?,
meta~ : Map[String, Json]?
)
/// A link to a resource the client should read separately.
ResourceLink(
uri~ : String,
name~ : String,
title~ : String?,
description~ : String?,
mime_type~ : String?,
size~ : Int32?,
annotations~ : Annotations?,
meta~ : Map[String, Json]?
)
/// A resource embedded directly in the content.
EmbeddedResource(
resource~ : ResourceContents,
annotations~ : Annotations?,
meta~ : Map[String, Json]?
)
} derive(Debug, Eq)
///|
/// Shorthand for a plain text block without annotations.
pub fn text_block(text : String) -> ContentBlock {
Text(text~, annotations=None, meta=None)
}
///|
pub impl ToJson for ContentBlock with fn to_json(self : ContentBlock) -> Json {
let obj : Map[String, Json] = Map([])
fn put_annotations(block_annotations : Annotations?) -> Unit {
put_opt_json(
obj,
"annotations",
block_annotations.map(Annotations::to_json),
)
}
fn put_meta(block_meta : Map[String, Json]?) -> Unit {
put_opt_map(obj, "_meta", block_meta)
}
match self {
Text(text~, annotations~, meta~) => {
put_str(obj, "type", "text")
put_str(obj, "text", text)
put_annotations(annotations)
put_meta(meta)
}
Image(data~, mime_type~, annotations~, meta~) => {
put_str(obj, "type", "image")
put_str(obj, "data", data)
put_str(obj, "mimeType", mime_type)
put_annotations(annotations)
put_meta(meta)
}
Audio(data~, mime_type~, annotations~, meta~) => {
put_str(obj, "type", "audio")
put_str(obj, "data", data)
put_str(obj, "mimeType", mime_type)
put_annotations(annotations)
put_meta(meta)
}
ResourceLink(
uri~,
name~,
title~,
description~,
mime_type~,
size~,
annotations~,
meta~
) => {
put_str(obj, "type", "resource_link")
put_str(obj, "uri", uri)
put_str(obj, "name", name)
put_opt_str(obj, "title", title)
put_opt_str(obj, "description", description)
put_opt_str(obj, "mimeType", mime_type)
put_opt_int(obj, "size", size)
put_annotations(annotations)
put_meta(meta)
}
EmbeddedResource(resource~, annotations~, meta~) => {
put_str(obj, "type", "resource")
put_opt_json(obj, "resource", Some(ResourceContents::to_json(resource)))
put_annotations(annotations)
put_meta(meta)
}
}
Json(obj)
}
///|
pub impl FromJson for ContentBlock with fn from_json(
json : Json,
path : @json.JsonPath,
) -> ContentBlock raise @json.JsonDecodeError {
let obj = expect_obj(json, path, "ContentBlock")
fn annotations() -> Annotations? raise @json.JsonDecodeError {
match obj.get("annotations") {
Some(value) => Some(@json.from_json(value))
None => None
}
}
let block_type = req_str(obj, path, "ContentBlock", "type")
match block_type {
"text" =>
Text(
text=req_str(obj, path, "ContentBlock", "text"),
annotations=annotations(),
meta=opt_obj(obj, path, "_meta"),
)
"image" =>
Image(
data=req_str(obj, path, "ContentBlock", "data"),
mime_type=req_str(obj, path, "ContentBlock", "mimeType"),
annotations=annotations(),
meta=opt_obj(obj, path, "_meta"),
)
"audio" =>
Audio(
data=req_str(obj, path, "ContentBlock", "data"),
mime_type=req_str(obj, path, "ContentBlock", "mimeType"),
annotations=annotations(),
meta=opt_obj(obj, path, "_meta"),
)
"resource_link" =>
ResourceLink(
uri=req_str(obj, path, "ContentBlock", "uri"),
name=req_str(obj, path, "ContentBlock", "name"),
title=opt_str(obj, path, "title"),
description=opt_str(obj, path, "description"),
mime_type=opt_str(obj, path, "mimeType"),
size=opt_int(obj, path, "size"),
annotations=annotations(),
meta=opt_obj(obj, path, "_meta"),
)
"resource" =>
EmbeddedResource(
resource=@json.from_json(obj.get("resource").unwrap_or(Json::null())),
annotations=annotations(),
meta=opt_obj(obj, path, "_meta"),
)
_ => raise decode_error(path, "ContentBlock: unknown type \{block_type}")
}
}
///|
pub extend Annotations with @json.FromJson::{from_json}
///|
pub extend Annotations with Debug::{to_repr}
///|
pub extend Annotations with Eq::{not_equal, equal}
///|
pub extend Annotations with ToJson::{to_json}
///|
pub extend ContentBlock with @json.FromJson::{from_json}
///|
pub extend ContentBlock with Debug::{to_repr}
///|
pub extend ContentBlock with Eq::{not_equal, equal}
///|
pub extend ContentBlock with ToJson::{to_json}
///|
pub extend ResourceContents with @json.FromJson::{from_json}
///|
pub extend ResourceContents with Debug::{to_repr}
///|
pub extend ResourceContents with Eq::{not_equal, equal}
///|
pub extend ResourceContents with ToJson::{to_json}