Skip to main content

vtcode_threads/
lib.rs

1#![allow(missing_docs, clippy::expect_used, dead_code, reason = "Extracted identifiers")]
2//! Thread identifiers extracted from `vtcode-core`.
3//!
4//! `ThreadId` and `SubmissionId` live here so downstream crates (`vtcode-acp`
5//! and `vtcode-core`) can depend on identifiers without pulling the 303k
6//! `vtcode-core` monolith. `vtcode-core` re-exports these for compatibility.
7
8use serde::{Deserialize, Serialize};
9use uuid::Uuid;
10use vtcode_macros::StringNewtype;
11
12/// Unique identifier for a thread in the runtime.
13#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, StringNewtype)]
14pub struct ThreadId(String);
15
16/// Unique identifier for a submission within a thread turn.
17#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, StringNewtype)]
18pub struct SubmissionId(String);
19
20impl SubmissionId {
21    /// Generate a new submission identifier with a `sub-` prefix.
22    pub fn generate() -> Self {
23        Self(format!("sub-{}", Uuid::new_v4()))
24    }
25}
26
27impl Default for SubmissionId {
28    fn default() -> Self {
29        Self::generate()
30    }
31}
32
33#[cfg(test)]
34mod tests {
35    use super::*;
36
37    #[test]
38    fn submission_id_generate_has_prefix() {
39        let id = SubmissionId::generate();
40        assert!(id.as_ref().starts_with("sub-"), "generated id must have sub- prefix");
41        assert_eq!(id.len(), 36 + 4, "uuid v4 36 plus sub-");
42    }
43
44    #[test]
45    fn thread_id_string_newtype_roundtrip() {
46        let id = ThreadId::new("thread-abc");
47        assert_eq!(id.as_ref(), "thread-abc");
48        let back: ThreadId = serde_json::from_str(&serde_json::to_string(&id).unwrap()).unwrap();
49        assert_eq!(back, id);
50    }
51}