Skip to main content

lean_ctx/
models.rs

1use serde::{Deserialize, Serialize};
2use serde_json::{Map, Value};
3
4#[derive(Debug, Clone, Default, Serialize, Deserialize)]
5pub struct RepositoryFingerprint {
6    pub remote_url: Option<String>,
7    pub host: Option<String>,
8    pub owner: Option<String>,
9    pub repo_name: Option<String>,
10    pub default_branch: Option<String>,
11}
12
13#[derive(Debug, Clone, Serialize, Deserialize)]
14pub struct CheckoutBinding {
15    pub project_id: String,
16    pub local_root: Option<String>,
17    pub branch: Option<String>,
18    pub last_commit: Option<String>,
19    pub client_label: Option<String>,
20    pub last_sync: Option<String>,
21}
22
23impl Default for CheckoutBinding {
24    fn default() -> Self {
25        Self {
26            project_id: "pending".to_string(),
27            local_root: None,
28            branch: None,
29            last_commit: None,
30            client_label: None,
31            last_sync: None,
32        }
33    }
34}
35
36#[derive(Debug, Clone, Serialize, Deserialize)]
37pub struct ProjectResolutionRequest {
38    pub fingerprint: RepositoryFingerprint,
39    pub suggested_slug: Option<String>,
40    #[serde(rename = "checkout_binding", alias = "workspace_binding")]
41    pub checkout_binding: Option<CheckoutBinding>,
42    pub project_metadata: Option<ProjectMetadataEnvelope>,
43}
44
45#[derive(Debug, Clone, Serialize, Deserialize)]
46pub struct ProjectRecord {
47    pub project_id: String,
48    pub slug: String,
49    pub fingerprint: Option<RepositoryFingerprint>,
50    pub created_at: String,
51    pub updated_at: String,
52}
53
54#[derive(Debug, Clone, Serialize, Deserialize)]
55pub struct ProjectResolutionResponse {
56    pub project: ProjectRecord,
57    #[serde(rename = "checkout_bound", alias = "workspace_bound")]
58    pub checkout_bound: bool,
59}
60
61#[derive(Debug, Clone, Serialize, Deserialize)]
62pub struct ToolDefinition {
63    pub name: String,
64    pub description: String,
65    #[serde(rename = "inputSchema")]
66    pub input_schema: Value,
67}
68
69#[derive(Debug, Clone, Serialize, Deserialize)]
70pub struct ToolListResponse {
71    pub tools: Vec<ToolDefinition>,
72    pub total: usize,
73}
74
75#[derive(Debug, Clone, Serialize, Deserialize)]
76pub struct ToolCallRequest {
77    pub name: String,
78    pub arguments: Map<String, Value>,
79    pub project_id: Option<String>,
80    pub project_slug: Option<String>,
81    pub repository_fingerprint: Option<RepositoryFingerprint>,
82    #[serde(rename = "checkout_binding", alias = "workspace_binding")]
83    pub checkout_binding: Option<CheckoutBinding>,
84    pub project_metadata: Option<ProjectMetadataEnvelope>,
85}
86
87#[derive(Debug, Clone, Serialize, Deserialize)]
88pub struct ToolCallResponse {
89    pub result: Value,
90}
91
92#[derive(Debug, Clone, Serialize, Deserialize)]
93pub struct ServerConnection {
94    pub endpoint: String,
95    pub token: String,
96}
97
98#[derive(Debug, Clone, Serialize, Deserialize)]
99pub struct ProjectMetadataEnvelope {
100    pub schema_version: u32,
101    pub summary: ProjectMetadataSummary,
102}
103
104#[derive(Debug, Clone, Serialize, Deserialize)]
105pub struct ProjectMetadataSummary {
106    pub total_file_count: u64,
107    pub source_file_count: u64,
108    pub markers: Vec<String>,
109    pub languages: Vec<ProjectLanguageStat>,
110}
111
112#[derive(Debug, Clone, Serialize, Deserialize)]
113pub struct ProjectLanguageStat {
114    pub language: String,
115    pub file_count: u64,
116}
117
118#[derive(Debug, Clone)]
119pub struct ProjectContext {
120    pub project_slug: String,
121    pub project_root: String,
122    pub fingerprint: RepositoryFingerprint,
123    pub checkout_binding: CheckoutBinding,
124    pub project_metadata: Option<ProjectMetadataEnvelope>,
125}
126
127pub type RepositoryContext = ProjectContext;
128pub type WorkspaceBinding = CheckoutBinding;
129/// Request payload for POST /v1/telemetry/ingest.
130/// Only token counts and metadata — no raw file content or shell output.
131#[derive(Debug, Clone, Serialize, Deserialize)]
132pub struct TelemetryIngestRequest {
133    pub tool_name: String,
134    pub tokens_original: i64,
135    pub tokens_saved: i64,
136    pub duration_ms: i64,
137    #[serde(skip_serializing_if = "Option::is_none")]
138    pub mode: Option<String>,
139    #[serde(skip_serializing_if = "Option::is_none")]
140    pub repository_fingerprint: Option<RepositoryFingerprint>,
141    #[serde(skip_serializing_if = "Option::is_none")]
142    pub checkout_binding: Option<CheckoutBinding>,
143    #[serde(skip_serializing_if = "Option::is_none")]
144    pub project_slug: Option<String>,
145}