Meliputi: - File-level //! doc comment: tujuan file, alur kerja, komponen utama - Function-level /// doc comment: apa, parameter, return, flow, edge cases - Struct/enum/trait /// doc comment: peran, field docs - Tracing logging (tracing::info!/debug!/trace!/warn!/error!) di setiap fungsi - Inline comments untuk variable dan branching logic penting - Seluruh 8 crates di workspace: zesdex-backend, zesdex-cms, zesdex-entities, zesdex-iam, zesdex-infra, zesdex-ipc, zesdex-middleware, zesdex-utils - Build: 0 errors, 242/242 tests passed
184 lines
6.6 KiB
Rust
184 lines
6.6 KiB
Rust
//! Data Transfer Objects (DTOs) for the CMS REST API.
|
|
//!
|
|
//! These types define the wire format accepted and returned by HTTP handlers.
|
|
//! They are intentionally independent of the domain entities so the API
|
|
//! contract can evolve without coupling to the domain model.
|
|
//!
|
|
//! ## DTOs
|
|
//! - `SettingsUpdateRequest` — partial-update body for PUT /settings
|
|
//! - `SettingsResponse` — response body for GET /settings (API keys redacted)
|
|
//! - `MemoryCreateRequest` — request body for POST /memories
|
|
//! - `MemoryResponse` — response body for memory operations
|
|
//! - `ConversationResponse` — response body for GET /conversation
|
|
//!
|
|
//! ## Conventions
|
|
//! - `From<DomainType>` impls convert domain entities → DTO responses
|
|
//! - API key values are **redacted** in responses (only key names exposed)
|
|
//! - Request fields use `Option` to support partial updates
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Settings
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/// Request body for updating settings (partial update — only specified fields
|
|
/// are changed).
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct SettingsUpdateRequest {
|
|
pub internet_mode: Option<String>,
|
|
pub provider: Option<String>,
|
|
pub model: Option<String>,
|
|
pub api_keys: Option<std::collections::HashMap<String, String>>,
|
|
pub max_tokens: Option<Option<u32>>,
|
|
pub temperature: Option<Option<f32>>,
|
|
pub review_max_lessons_per_run: Option<usize>,
|
|
pub adaptive_review_max_skip: Option<u32>,
|
|
pub verify_command: Option<Option<String>>,
|
|
pub verify_timeout_ms: Option<u64>,
|
|
pub workflow_max_concurrency: Option<usize>,
|
|
pub review_enabled: Option<bool>,
|
|
pub session_archive_enabled: Option<bool>,
|
|
pub lsp_auto_provision: Option<bool>,
|
|
pub lsp_languages: Option<Vec<String>>,
|
|
pub hive_mind_node_timeout_ms: Option<u64>,
|
|
}
|
|
|
|
/// Response body for settings.
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct SettingsResponse {
|
|
pub internet_mode: String,
|
|
pub provider: String,
|
|
pub model: String,
|
|
pub api_keys: Vec<String>, // key names only, values redacted
|
|
pub max_tokens: Option<u32>,
|
|
pub temperature: Option<f32>,
|
|
pub review_max_lessons_per_run: usize,
|
|
pub adaptive_review_max_skip: u32,
|
|
pub verify_command: Option<String>,
|
|
pub verify_timeout_ms: u64,
|
|
pub workflow_max_concurrency: usize,
|
|
pub review_enabled: bool,
|
|
pub session_archive_enabled: bool,
|
|
pub lsp_auto_provision: bool,
|
|
pub lsp_languages: Vec<String>,
|
|
pub hive_mind_node_timeout_ms: u64,
|
|
}
|
|
|
|
/// Convert a domain `Settings` entity into its API response representation.
|
|
///
|
|
/// ## Side-effects
|
|
/// - API key **values are redacted** — only key names are exposed.
|
|
impl From<crate::domain::settings::Settings> for SettingsResponse {
|
|
fn from(s: crate::domain::settings::Settings) -> Self {
|
|
Self {
|
|
internet_mode: format!("{:?}", s.internet_mode),
|
|
provider: s.provider,
|
|
model: s.model,
|
|
api_keys: s.api_keys.keys().cloned().collect(),
|
|
max_tokens: s.max_tokens,
|
|
temperature: s.temperature,
|
|
review_max_lessons_per_run: s.review_max_lessons_per_run,
|
|
adaptive_review_max_skip: s.adaptive_review_max_skip,
|
|
verify_command: s.verify_command,
|
|
verify_timeout_ms: s.verify_timeout_ms,
|
|
workflow_max_concurrency: s.workflow_max_concurrency,
|
|
review_enabled: s.flags.review_enabled,
|
|
session_archive_enabled: s.flags.session_archive_enabled,
|
|
lsp_auto_provision: s.flags.lsp_auto_provision,
|
|
lsp_languages: s.lsp_languages,
|
|
hive_mind_node_timeout_ms: s.hive_mind_node_timeout_ms,
|
|
}
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Memory
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/// Request body for creating or updating a memory.
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct MemoryCreateRequest {
|
|
pub name: String,
|
|
pub description: String,
|
|
pub content: String,
|
|
pub kind: Option<String>,
|
|
pub outcome: Option<String>,
|
|
pub lifecycle: Option<String>,
|
|
pub scope: Option<String>,
|
|
pub before_snippet: Option<String>,
|
|
pub after_snippet: Option<String>,
|
|
pub provenances: Option<Vec<String>>,
|
|
}
|
|
|
|
/// Response body for a memory.
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct MemoryResponse {
|
|
pub name: String,
|
|
pub description: String,
|
|
pub content: String,
|
|
pub kind: String,
|
|
pub created_at: i64,
|
|
pub updated_at: i64,
|
|
pub outcome: Option<String>,
|
|
pub lifecycle: String,
|
|
pub scope: Option<String>,
|
|
pub before_snippet: Option<String>,
|
|
pub after_snippet: Option<String>,
|
|
pub provenances: Vec<String>,
|
|
}
|
|
|
|
/// Convert a domain `Memory` entity into its API response representation.
|
|
impl From<crate::domain::memory::Memory> for MemoryResponse {
|
|
fn from(m: crate::domain::memory::Memory) -> Self {
|
|
Self {
|
|
name: m.name,
|
|
description: m.description,
|
|
content: m.content,
|
|
kind: m.kind,
|
|
created_at: m.created_at,
|
|
updated_at: m.updated_at,
|
|
outcome: m.outcome,
|
|
lifecycle: m.lifecycle,
|
|
scope: m.scope,
|
|
before_snippet: m.before_snippet,
|
|
after_snippet: m.after_snippet,
|
|
provenances: m.provenances,
|
|
}
|
|
}
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Conversation
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/// Response body for a conversation.
|
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
|
pub struct ConversationResponse {
|
|
pub session_id: String,
|
|
pub message_count: usize,
|
|
pub model: String,
|
|
pub system_prompt: String,
|
|
pub max_tokens: Option<u32>,
|
|
pub temperature: Option<f32>,
|
|
}
|
|
|
|
/// Convert a domain `Conversation` entity into its API response summary.
|
|
///
|
|
/// ## Note
|
|
/// Only metadata is included (message count, model, system prompt);
|
|
/// individual messages are not returned in this response.
|
|
impl From<crate::domain::conversation::Conversation> for ConversationResponse {
|
|
fn from(c: crate::domain::conversation::Conversation) -> Self {
|
|
let message_count = c.len();
|
|
Self {
|
|
session_id: c.session_id,
|
|
message_count,
|
|
model: c.model,
|
|
system_prompt: c.system_prompt,
|
|
max_tokens: c.max_tokens,
|
|
temperature: c.temperature,
|
|
}
|
|
}
|
|
}
|