use super::helpers::parse_csv_items;
use crate::domain::{
ContextBundle, MemoryScope, OutputFormat, RouteInput, TargetTool, WakeupPacket, WakeupProfile,
};
use crate::lifecycle_service::{LifecycleAction, LifecycleWorkbenchSnapshot};
use crate::lifecycle_store::{
LedgerEntry, ProposeMemoryRequest, RecordMemoryRequest, TransitionMetadata,
};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::path::PathBuf;
use ts_rs::TS;
#[derive(Debug, Clone, Serialize, PartialEq, Eq, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopRouteRequest {
#[ts(type = "string")]
pub config_path: PathBuf,
#[ts(type = "string | null")]
pub vault_root_override: Option<PathBuf>,
#[ts(type = "string")]
pub cwd: PathBuf,
pub task: String,
pub files: Vec<String>,
pub target: TargetTool,
pub format: OutputFormat,
}
#[derive(Debug, Clone, Serialize, PartialEq, Eq, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopWakeupRequest {
#[ts(type = "string")]
pub config_path: PathBuf,
#[ts(type = "string | null")]
pub vault_root_override: Option<PathBuf>,
#[ts(type = "string")]
pub cwd: PathBuf,
pub task: String,
pub files: Vec<String>,
pub target: TargetTool,
pub profile: WakeupProfile,
}
#[derive(Debug, Clone, Serialize, PartialEq, Eq, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopPromptOptimizeRequest {
#[ts(type = "string")]
pub config_path: PathBuf,
#[ts(type = "string | null")]
pub vault_root_override: Option<PathBuf>,
#[ts(type = "string")]
pub cwd: PathBuf,
pub task: String,
pub files: Vec<String>,
pub target: TargetTool,
pub profile: WakeupProfile,
pub provider: Option<String>,
pub session_id: Option<String>,
}
#[derive(Debug, Clone, Serialize, PartialEq, Eq, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopWorkbenchRequest {
#[ts(type = "string")]
pub config_path: PathBuf,
pub daemon: Option<DesktopDaemonRequest>,
}
#[derive(Debug, Clone, Serialize, PartialEq, Eq, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopRecordLookupRequest {
#[ts(type = "string")]
pub config_path: PathBuf,
pub record_id: String,
pub daemon: Option<DesktopDaemonRequest>,
}
#[derive(Debug, Clone, Serialize, PartialEq, Eq, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopSessionBrowserRequest {
#[ts(type = "string")]
pub config_path: PathBuf,
pub page: usize,
pub per_page: usize,
pub provider: Option<String>,
}
#[derive(Debug, Clone, Serialize, PartialEq, Eq, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopSessionDetailRequest {
#[ts(type = "string")]
pub config_path: PathBuf,
pub session_id: String,
pub message_offset: Option<usize>,
pub message_limit: Option<usize>,
}
#[derive(Debug, Clone, Serialize, PartialEq, Eq, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopSessionActionRequest {
#[ts(type = "string")]
pub config_path: PathBuf,
pub session_id: String,
}
#[derive(Debug, Clone, Serialize, PartialEq, Eq, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopStatusRequest {
#[ts(type = "string")]
pub config_path: PathBuf,
#[ts(type = "string | null")]
pub vault_root_override: Option<PathBuf>,
#[ts(type = "string")]
pub cwd: PathBuf,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopWikiLintRequest {
#[ts(type = "string")]
pub config_path: PathBuf,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopWikiIndexRequest {
#[ts(type = "string")]
pub config_path: PathBuf,
#[serde(default)]
pub project_id: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopImportSessionRequest {
#[ts(type = "string")]
pub config_path: PathBuf,
pub provider: String,
pub session_id: String,
#[serde(default)]
pub apply: bool,
#[serde(default)]
pub actor: Option<String>,
}
pub type DesktopImportSessionResponse = crate::memory_importer::ImportSessionResponse;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopMemoryDraftRequest {
#[ts(type = "string")]
pub config_path: PathBuf,
pub title: String,
pub summary: String,
pub memory_type: String,
pub scope: MemoryScope,
pub source_ref: String,
pub project_id: Option<String>,
pub user_id: Option<String>,
pub sensitivity: Option<String>,
pub metadata: DesktopMetadataDto,
#[serde(default)]
pub entities: Vec<String>,
#[serde(default)]
pub tags: Vec<String>,
#[serde(default)]
pub triggers: Vec<String>,
#[serde(default)]
pub related_files: Vec<String>,
#[serde(default)]
pub related_records: Vec<String>,
#[serde(default)]
pub supersedes: Option<String>,
#[serde(default)]
pub applies_to: Vec<String>,
#[serde(default)]
pub valid_until: Option<String>,
}
#[derive(Debug, Clone, Serialize, PartialEq, Eq, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopMemoryActionRequest {
#[ts(type = "string")]
pub config_path: PathBuf,
pub record_id: String,
pub action: DesktopLifecycleActionDto,
pub metadata: DesktopMetadataDto,
}
#[derive(Debug, Clone, Serialize, PartialEq, Eq, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopDaemonRequest {
pub enabled: bool,
#[ts(type = "string | null")]
pub daemon_bin: Option<PathBuf>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopMetadataDto {
pub actor: Option<String>,
pub reason: Option<String>,
pub evidence_refs: Vec<String>,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, ts_rs::TS)]
#[serde(rename_all = "snake_case")]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub enum DesktopLifecycleActionDto {
Accept,
Promote,
Archive,
}
#[derive(Debug, Clone, Serialize, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopContextResponse {
pub rendered: String,
pub explain: String,
pub used_format: OutputFormat,
#[ts(type = "string")]
pub used_vault_root: PathBuf,
pub bundle: ContextBundle,
}
#[derive(Debug, Clone, Serialize, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopWakeupResponse {
#[ts(type = "string")]
pub used_vault_root: PathBuf,
pub bundle: ContextBundle,
pub packet: WakeupPacket,
}
pub type DesktopPromptOptimizeResponse = crate::memory_gateway::PromptOptimizeResponse;
#[derive(Debug, Clone, Serialize, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopWorkbenchResponse {
pub snapshot: LifecycleWorkbenchSnapshot,
#[ts(type = "unknown")]
pub payload: Value,
}
#[derive(Debug, Clone, Serialize, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopRecordResponse {
pub record: LedgerEntry,
#[ts(type = "unknown")]
pub payload: Value,
pub rendered: String,
pub available_actions: Vec<DesktopLifecycleActionDto>,
}
#[derive(Debug, Clone, Serialize, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopHistoryResponse {
pub record_id: String,
pub history: Vec<LedgerEntry>,
#[ts(type = "unknown")]
pub payload: Value,
pub rendered: String,
}
#[derive(Debug, Clone, Serialize, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopWriteResponse {
pub entry: LedgerEntry,
#[ts(type = "unknown")]
pub payload: Value,
}
#[derive(Debug, Clone, Serialize, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopSessionItem {
pub provider: String,
pub session_id: String,
pub title: String,
pub summary: Option<String>,
pub prompt_preview: Option<String>,
pub cwd: Option<String>,
pub source_path: Option<String>,
pub project_path: Option<String>,
pub updated_at: String,
pub record_count: usize,
pub pending_review_count: usize,
pub wakeup_ready_count: usize,
pub titles: Vec<String>,
pub memory_types: Vec<String>,
}
#[derive(Debug, Clone, Serialize, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopSessionBrowserResponse {
pub sessions: Vec<DesktopSessionItem>,
pub page: usize,
pub per_page: usize,
pub total: usize,
pub has_more: bool,
}
#[derive(Debug, Clone, Serialize, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopSessionMessage {
pub role: String,
pub timestamp: String,
pub content: String,
pub truncated: bool,
}
#[derive(Debug, Clone, Serialize, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopSessionDetailResponse {
pub session: DesktopSessionItem,
pub records: Vec<LedgerEntry>,
pub messages: Vec<DesktopSessionMessage>,
pub total_messages: usize,
pub showing_recent_messages: usize,
pub has_more_messages: bool,
pub latest_user_message: Option<String>,
}
#[derive(Debug, Clone, Serialize, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopSessionActionResponse {
pub session_id: String,
pub provider: String,
pub command: Option<String>,
pub message: String,
}
#[derive(Debug, Clone, Serialize, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopWikiLintResponse {
#[ts(type = "string")]
pub used_vault_root: PathBuf,
pub report: crate::wiki_lint::LintReport,
pub markdown: String,
}
#[derive(Debug, Clone, Serialize, TS)]
#[ts(export, export_to = "../frontend/src/lib/types/generated/")]
pub struct DesktopWikiIndexResponse {
#[ts(type = "string")]
pub used_vault_root: PathBuf,
pub markdown: Option<String>,
}
impl DesktopRouteRequest {
pub(super) fn to_route_input(&self) -> RouteInput {
RouteInput {
task: self.task.clone(),
cwd: self.cwd.clone(),
files: self.files.clone(),
target: self.target,
format: self.format,
}
}
}
impl DesktopWakeupRequest {
pub(super) fn to_route_input(&self) -> RouteInput {
RouteInput {
task: self.task.clone(),
cwd: self.cwd.clone(),
files: self.files.clone(),
target: self.target,
format: OutputFormat::Json,
}
}
}
impl DesktopPromptOptimizeRequest {
pub(super) fn to_route_input(&self) -> RouteInput {
RouteInput {
task: self.task.clone(),
cwd: self.cwd.clone(),
files: self.files.clone(),
target: self.target,
format: OutputFormat::Prompt,
}
}
}
impl DesktopMemoryDraftRequest {
pub(super) fn to_record_request(&self) -> RecordMemoryRequest {
RecordMemoryRequest {
title: self.title.clone(),
summary: self.summary.clone(),
memory_type: self.memory_type.clone(),
scope: self.scope,
source_ref: self.source_ref.clone(),
project_id: self.project_id.clone(),
user_id: self.user_id.clone(),
sensitivity: self.sensitivity.clone(),
metadata: self.metadata.clone().into_transition_metadata(),
entities: self.entities.clone(),
tags: self.tags.clone(),
triggers: self.triggers.clone(),
related_files: self.related_files.clone(),
related_records: self.related_records.clone(),
supersedes: self.supersedes.clone(),
applies_to: self.applies_to.clone(),
valid_until: self.valid_until.clone(),
}
}
pub(super) fn to_propose_request(&self) -> ProposeMemoryRequest {
ProposeMemoryRequest {
title: self.title.clone(),
summary: self.summary.clone(),
memory_type: self.memory_type.clone(),
scope: self.scope,
source_ref: self.source_ref.clone(),
project_id: self.project_id.clone(),
user_id: self.user_id.clone(),
sensitivity: self.sensitivity.clone(),
metadata: self.metadata.clone().into_transition_metadata(),
entities: self.entities.clone(),
tags: self.tags.clone(),
triggers: self.triggers.clone(),
related_files: self.related_files.clone(),
related_records: self.related_records.clone(),
supersedes: self.supersedes.clone(),
applies_to: self.applies_to.clone(),
valid_until: self.valid_until.clone(),
}
}
}
impl DesktopMetadataDto {
pub fn from_evidence_csv(value: &str) -> Self {
Self {
actor: None,
reason: None,
evidence_refs: parse_csv_items(value),
}
}
pub(super) fn into_transition_metadata(self) -> TransitionMetadata {
TransitionMetadata {
actor: self.actor,
reason: self.reason,
evidence_refs: self.evidence_refs,
}
}
}
impl DesktopLifecycleActionDto {
pub(super) fn from_lifecycle_action(action: LifecycleAction) -> Self {
match action {
LifecycleAction::Accept => Self::Accept,
LifecycleAction::PromoteToCanonical => Self::Promote,
LifecycleAction::Archive => Self::Archive,
}
}
pub(super) fn into_lifecycle_action(self) -> LifecycleAction {
match self {
Self::Accept => LifecycleAction::Accept,
Self::Promote => LifecycleAction::PromoteToCanonical,
Self::Archive => LifecycleAction::Archive,
}
}
}