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//! Copyright (c) systemprompt.io — Business Source License 1.1.
11//! See <https://systemprompt.io> for licensing details.
12
13use serde::Deserialize;
14
15use crate::bridge::ids::{LibraryArtifactId, PluginId};
16
17const fn default_true() -> bool {
18    true
19}
20
21fn default_artifact_version() -> String {
22    "1".to_owned()
23}
24
25pub const ARTIFACT_CONFIG_FILENAME: &str = "config.yaml";
26pub const DEFAULT_ARTIFACT_CONTENT_FILE: &str = "content.html";
27
28#[derive(Debug, Clone, Deserialize)]
29pub struct DiskArtifactConfig {
30    pub id: LibraryArtifactId,
31    pub name: String,
32    pub description: String,
33    #[serde(default = "default_artifact_version")]
34    pub version: String,
35    pub plugin_id: PluginId,
36    #[serde(default)]
37    pub mcp_tools: Vec<String>,
38    #[serde(default = "default_true")]
39    pub enabled: bool,
40    #[serde(default)]
41    pub starred: bool,
42    #[serde(default)]
43    pub file: String,
44}
45
46impl DiskArtifactConfig {
47    pub fn content_file(&self) -> &str {
48        if self.file.is_empty() {
49            DEFAULT_ARTIFACT_CONTENT_FILE
50        } else {
51            &self.file
52        }
53    }
54}