Skip to main content

systemprompt_models/services/
artifacts.rs

1//! Cowork library-artifact on-disk descriptor.
2//!
3//! [`DiskArtifactConfig`] is the `services/artifacts/<id>/config.yaml` shape
4//! the marketplace loader projects into a signed
5//! [`crate::bridge::manifest::ArtifactEntry`]. The HTML body lives in a sibling
6//! file (default `content.html`) referenced by [`DiskArtifactConfig::file`].
7//! These are Cowork-native library documents, not the in-chat MCP artifacts in
8//! [`crate::artifacts`].
9//!
10//! An artifact declares no owning plugin: selection is driven the other way,
11//! by each plugin's `artifacts` [`crate::services::PluginComponentRef`], so one
12//! artifact can ship with several plugins.
13//!
14//! Copyright (c) systemprompt.io — Business Source License 1.1.
15//! See <https://systemprompt.io> for licensing details.
16
17use serde::Deserialize;
18
19use crate::bridge::ids::LibraryArtifactId;
20
21const fn default_true() -> bool {
22    true
23}
24
25fn default_artifact_version() -> String {
26    "1".to_owned()
27}
28
29pub const ARTIFACT_CONFIG_FILENAME: &str = "config.yaml";
30pub const DEFAULT_ARTIFACT_CONTENT_FILE: &str = "content.html";
31
32#[derive(Debug, Clone, Deserialize)]
33pub struct DiskArtifactConfig {
34    pub id: LibraryArtifactId,
35    pub name: String,
36    pub description: String,
37    #[serde(default = "default_artifact_version")]
38    pub version: String,
39    #[serde(default)]
40    pub mcp_tools: Vec<String>,
41    #[serde(default = "default_true")]
42    pub enabled: bool,
43    #[serde(default)]
44    pub starred: bool,
45    #[serde(default)]
46    pub file: String,
47}
48
49impl DiskArtifactConfig {
50    pub fn content_file(&self) -> &str {
51        if self.file.is_empty() {
52            DEFAULT_ARTIFACT_CONTENT_FILE
53        } else {
54            &self.file
55        }
56    }
57}