Skip to main content

systemprompt_models/artifacts/text/
mod.rs

1//! Text artifact: a titled block of free-form text returned by skills and
2//! tools.
3//!
4//! [`TextArtifact`] is the builder-style producer carrying optional title and
5//! execution metadata.
6//!
7//! Copyright (c) systemprompt.io — Business Source License 1.1.
8//! See <https://systemprompt.io> for licensing details.
9
10use crate::artifacts::metadata::ArtifactProvenance;
11use crate::artifacts::traits::Artifact;
12use crate::artifacts::types::ArtifactType;
13use crate::execution::context::RequestContext;
14use schemars::JsonSchema;
15use serde::{Deserialize, Serialize};
16use serde_json::{Value as JsonValue, json};
17use systemprompt_identifiers::{McpExecutionId, SkillId, SkillName};
18
19fn default_artifact_type() -> String {
20    "text".to_owned()
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
24pub struct TextArtifact {
25    #[serde(rename = "x-artifact-type")]
26    #[serde(default = "default_artifact_type")]
27    pub artifact_type: String,
28    pub content: String,
29    #[serde(skip_serializing_if = "Option::is_none")]
30    pub title: Option<String>,
31    #[serde(skip)]
32    #[schemars(skip)]
33    metadata: ArtifactProvenance,
34}
35
36impl TextArtifact {
37    pub const ARTIFACT_TYPE_STR: &'static str = "text";
38
39    pub fn new(content: impl Into<String>) -> Self {
40        Self {
41            artifact_type: "text".to_owned(),
42            content: content.into(),
43            title: None,
44            metadata: ArtifactProvenance::default(),
45        }
46    }
47
48    pub fn with_request(mut self, ctx: &RequestContext) -> Self {
49        self.metadata.set_request(ctx);
50        self
51    }
52
53    pub fn with_title(mut self, title: impl Into<String>) -> Self {
54        self.title = Some(title.into());
55        self
56    }
57
58    pub fn with_execution_id(mut self, id: McpExecutionId) -> Self {
59        self.metadata.set_execution_id(id);
60        self
61    }
62
63    pub fn with_skill(mut self, skill_id: SkillId, skill_name: SkillName) -> Self {
64        self.metadata.set_skill(skill_id, skill_name);
65        self
66    }
67}
68
69impl Artifact for TextArtifact {
70    fn artifact_type(&self) -> ArtifactType {
71        ArtifactType::Text
72    }
73
74    // JSON: JSON Schema document describing the artifact for the model.
75    fn to_schema(&self) -> JsonValue {
76        json!({
77            "type": "object",
78            "properties": {
79                "content": {
80                    "type": "string",
81                    "description": "Text content"
82                },
83                "title": {
84                    "type": "string",
85                    "description": "Optional title for the text"
86                }
87            },
88            "required": ["content"],
89            "x-artifact-type": "text"
90        })
91    }
92}