Skip to main content

release_smoke/
release_smoke.rs

1//! Mutating smoke: run only with an explicitly supplied disposable CCCC_HOME.
2use cccc_sdk::{CCCCClient, VoiceDocumentLibraryAction as Action};
3use serde_json::{json, Map, Value};
4
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6    let home = std::path::PathBuf::from(
7        std::env::var_os("CCCC_HOME").expect("isolated CCCC_HOME required"),
8    );
9    let client = CCCCClient::discover()?;
10    let call = |op: &str, args: Value| client.call(op, args.as_object().expect("object").clone());
11    let group = call("group_create", json!({"title":"Rust SDK release fixture"}))?;
12    let group_id = group["group"]["group_id"].as_str().expect("group id");
13    call(
14        "group_set_state",
15        json!({"group_id":group_id,"state":"paused"}),
16    )?;
17    let path = "notes/sdk.md";
18    call(
19        "assistant_voice_document_save",
20        json!({"group_id":group_id,"document_path":path,"content":"# SDK fixture"}),
21    )?;
22    let library = client.assistant_voice_document_library_update(
23        group_id,
24        &Action::CreateFolder {
25            name: "Meetings".into(),
26        },
27        None,
28    )?;
29    let folder_id = library.folders[0].folder_id.clone();
30    for action in [
31        Action::RenameFolder {
32            folder_id: folder_id.clone(),
33            name: "Notes".into(),
34        },
35        Action::Rename {
36            document_path: path.into(),
37            name: "Summary".into(),
38        },
39        Action::Move {
40            document_path: path.into(),
41            folder_id: folder_id.clone(),
42        },
43    ] {
44        client.assistant_voice_document_library_update(group_id, &action, None)?;
45    }
46    call(
47        "assistant_voice_document_archive",
48        json!({"group_id":group_id,"document_path":path}),
49    )?;
50    let library = client.assistant_voice_document_library(group_id)?;
51    assert_eq!(library.documents[0]["status"], "archived");
52    let file = home
53        .join("voice-secretary")
54        .join(group_id)
55        .join("documents")
56        .join(path);
57    assert_eq!(std::fs::read_to_string(&file)?, "# SDK fixture");
58    let library = client.assistant_voice_document_library_update(
59        group_id,
60        &Action::Restore {
61            document_path: path.into(),
62        },
63        None,
64    )?;
65    assert_eq!(library.documents[0]["status"], "active");
66    assert_eq!(library.documents[0]["folder_id"], folder_id);
67    client.assistant_voice_document_library_update(
68        group_id,
69        &Action::Move {
70            document_path: path.into(),
71            folder_id: "".into(),
72        },
73        None,
74    )?;
75    let order = vec![format!("folder:{folder_id}"), format!("document:{path}")];
76    let library = client.assistant_voice_document_library_update(
77        group_id,
78        &Action::ReorderRoot {
79            root_order: order.clone(),
80        },
81        None,
82    )?;
83    assert_eq!(library.root_order, order);
84    let library = client.assistant_voice_document_library_update(
85        group_id,
86        &Action::ReorderRoot { root_order: vec![] },
87        None,
88    )?;
89    assert!(library.root_order.is_empty());
90    client.assistant_voice_document_library_update(
91        group_id,
92        &Action::RemoveFolder { folder_id },
93        None,
94    )?;
95    let deleted = client.assistant_voice_document_delete(group_id, path, None)?;
96    assert_eq!(deleted["event"]["data"]["action"], "deleted");
97    assert!(!file.exists());
98    assert!(client
99        .assistant_voice_document_library(group_id)?
100        .documents
101        .is_empty());
102    assert!(client
103        .assistant_voice_document_library_update(
104            group_id,
105            &Action::Restore {
106                document_path: path.into()
107            },
108            None
109        )
110        .is_err());
111
112    // Persist configuration only. No browser/provider starts in this paused Group.
113    for (id, runtime) in [
114        ("chat1", "web_model"),
115        ("chat2", "web_model"),
116        ("bot", "grok_web_model"),
117    ] {
118        let actor = call(
119            "actor_add",
120            json!({"group_id":group_id,"actor_id":id,"runtime":runtime}),
121        )?;
122        assert_eq!(actor["actor"]["runtime"], runtime);
123        assert_eq!(actor["actor"]["runner"], "headless");
124    }
125    let group: Map<String, Value> = client.group_show(group_id)?;
126    assert_eq!(group["group"]["state"], "paused");
127    println!("Installed Rust artifact: Voice library lifecycle and Web Model configuration passed");
128    Ok(())
129}