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