diff --git a/docs/Agent/SubAgent.md b/docs/Agent/SubAgent.md index 87cd9a6f..739c488a 100644 --- a/docs/Agent/SubAgent.md +++ b/docs/Agent/SubAgent.md @@ -91,7 +91,7 @@ AgentTaskRecord { Invocation 与 task 文件由 `AgentInvocationRepository` 管理,当前文件实现位于: ```text -src-tauri/src/domain/repositories/agent_invocation_repository.rs +src-tauri/crates/tt-ports/src/repositories/agent_invocation_repository.rs src-tauri/src/infrastructure/repositories/file_agent_repository/invocation_store.rs ``` @@ -277,7 +277,7 @@ src-tauri/src/infrastructure/repositories/file_agent_profile_repository/mod.rs Persistence: ```text -src-tauri/src/domain/repositories/agent_invocation_repository.rs +src-tauri/crates/tt-ports/src/repositories/agent_invocation_repository.rs src-tauri/src/infrastructure/repositories/file_agent_repository/invocation_store.rs ``` diff --git a/docs/AgentArchitecture.md b/docs/AgentArchitecture.md index 95c0f873..13e5ecfb 100644 --- a/docs/AgentArchitecture.md +++ b/docs/AgentArchitecture.md @@ -49,7 +49,7 @@ MCP / Tool Direct Call - 应用服务由 `AppState` 管理并在 `composition::build_services()` 装配。见 `src-tauri/src/app.rs`、`src-tauri/src/app/composition.rs`。 - 当前 LLM 请求经过 `ChatCompletionService`,该服务负责 provider 解析、iOS policy、endpoint override policy、payload build、prompt caching 和取消注册。见 `src-tauri/src/application/services/chat_completion_service/mod.rs:32`、`src-tauri/src/application/services/chat_completion_service/mod.rs:302`、`src-tauri/src/application/services/chat_completion_service/mod.rs:358`。 - 当前 LLM API 日志依赖 composition root 中装配的 `LoggingChatCompletionRepository` wrapper;Agent 不得直接调用 `HttpChatCompletionRepository` 绕过日志、secret 或 policy。Responses WebSocket 建连已复用 `HttpClientPool` 的 ChatCompletion WebSocket profile,不应扩散成第二套 LLM 调用链。见 `src-tauri/src/app/composition/repositories.rs`。 -- 当前 chat payload 分片读写由 `ChatService` 和 `ChatRepository` 承担,windowed save/patch 是正式契约。见 `src-tauri/src/application/services/chat_service.rs:495`、`src-tauri/src/application/services/chat_service.rs:563`、`src-tauri/src/domain/repositories/chat_repository.rs:145`、`src-tauri/src/domain/repositories/chat_repository.rs:162`。 +- 当前 chat payload 分片读写由 `ChatService` 和 `ChatRepository` 承担,windowed save/patch 是正式契约。见 `src-tauri/crates/tt-application/src/services/chat_service.rs`、`src-tauri/crates/tt-ports/src/repositories/chat_repository.rs`。 - 前端 Public ABI 的统一入口是 `window.__TAURITAVERN__`,应保持小而稳定。见 `docs/FrontendHostContract.md` 第 3.6 节、`src/tauri/main/bootstrap.js:139`。 - 当前 `Generate()` 支持 dryRun,并在 `GENERATE_AFTER_DATA` 提供生成请求数据。见 `src/script.js:4660`、`src/script.js:5743`。 - 当前 SillyTavern 工具调用会递归回 `Generate()`,并把工具调用结果保存成 `is_system` chat message。这是 Agent 必须摆脱的旧结构。见 `src/script.js:5826`、`src/script.js:5847`、`src/script.js:5959`、`src/scripts/tool-calling.js:868`、`src/scripts/tool-calling.js:887`。 diff --git a/docs/BackendStructure.md b/docs/BackendStructure.md index 33aa2798..104b864a 100644 --- a/docs/BackendStructure.md +++ b/docs/BackendStructure.md @@ -57,10 +57,11 @@ src-tauri/ │ │ ├── composition/ # 仓库/服务/适配器装配子模块 │ │ ├── host/ # Tauri host shell(插件、setup、窗口、资源、shutdown) │ │ ├── startup_profile.rs # 启动期 settings / iOS policy 快照 -│ ├── domain/ # 领域层 -│ │ ├── models/ # 领域模型 -│ │ ├── repositories/ # 仓库接口 -│ │ └── errors.rs # 领域错误 +│ ├── crates/ +│ │ ├── tt-domain/ # 领域模型、领域错误与纯逻辑 +│ │ ├── tt-ports/ # 仓库接口与出站端口 +│ │ ├── tt-contracts/ # 跨 crate DTO / 事件契约 +│ │ └── tt-application/ # 应用服务与用例编排 │ ├── application/ # 应用层 │ │ ├── services/ # 业务服务 │ │ └── dto/ # 数据传输对象 @@ -438,7 +439,7 @@ tauri::Builder::default() #### 3.5.2 分层职责 -- `domain/repositories/chat_repository.rs` +- `crates/tt-ports/src/repositories/chat_repository.rs` - 保留 typed API(`get_chat` / `save` / `search_chats` 等)用于领域操作。 - payload API:path/from-file(大文件,data plane)+ windowed(tail/before/windowed-save,小窗口,control plane)。 - windowed 数据结构:`ChatPayloadCursor` / `ChatPayloadTail` / `ChatPayloadChunk`。 @@ -803,8 +804,8 @@ service 添加新模型时,应遵循以下步骤: -1. 在`domain/models`中定义模型结构 -2. 在`domain/repositories`中定义仓库接口 +1. 在`crates/tt-domain/src/models`中定义模型结构 +2. 在`crates/tt-ports/src/repositories`中定义仓库接口 3. 在`infrastructure/repositories`中实现仓库接口 4. 在`application/services`中创建服务 5. 在`application/dto`中定义数据传输对象 diff --git a/docs/CurrentState/WindowedPayload.md b/docs/CurrentState/WindowedPayload.md index 2982c390..7a98626d 100644 --- a/docs/CurrentState/WindowedPayload.md +++ b/docs/CurrentState/WindowedPayload.md @@ -37,7 +37,7 @@ windowed payload 的底层存储是 JSONL 文件: Rust 侧定义:`ChatPayloadCursor { offset, size, modified_millis }`(序列化为 camelCase)。见: -- `src-tauri/src/domain/repositories/chat_repository.rs` +- `src-tauri/crates/tt-ports/src/repositories/chat_repository.rs` 含义: diff --git a/scripts/check-rust-crate-boundaries.mjs b/scripts/check-rust-crate-boundaries.mjs index d1f705c1..072df218 100644 --- a/scripts/check-rust-crate-boundaries.mjs +++ b/scripts/check-rust-crate-boundaries.mjs @@ -355,6 +355,10 @@ const CRATES = [ ]; const MAIN_CRATE_SOURCE_RULES = [ + sourceRule('main crate domain shim', path.join(REPO_ROOT, 'src-tauri', 'src'), [ + ['domain module declaration', /^\s*(pub\s+)?mod\s+domain\s*;/], + ['domain shim path', /\bcrate::domain::/], + ]), sourceRule('infrastructure', path.join(REPO_ROOT, 'src-tauri', 'src', 'infrastructure'), [ ['application facade', /\bcrate::application::/], ['tt-application crate', /\btt_application::/], diff --git a/src-tauri/src/app/composition.rs b/src-tauri/src/app/composition.rs index 34d529fd..6bc0ccb1 100644 --- a/src-tauri/src/app/composition.rs +++ b/src-tauri/src/app/composition.rs @@ -6,8 +6,8 @@ use std::path::Path; use tauri::AppHandle; -use crate::domain::errors::DomainError; use tt_adapter_storage_core::file_system::DataDirectory; +use tt_domain::errors::DomainError; use super::{AppServices, StartupProfile}; diff --git a/src-tauri/src/app/composition/adapters/cache_reconciler.rs b/src-tauri/src/app/composition/adapters/cache_reconciler.rs index 52f2cd97..e6af3424 100644 --- a/src-tauri/src/app/composition/adapters/cache_reconciler.rs +++ b/src-tauri/src/app/composition/adapters/cache_reconciler.rs @@ -7,7 +7,7 @@ use crate::application::services::chat_service::ChatService; use crate::application::services::group_chat_service::GroupChatService; use crate::application::services::group_service::GroupService; use crate::application::services::secret_service::SecretService; -use crate::domain::errors::DomainError; +use tt_domain::errors::DomainError; use tt_ports::sync::DataChangeReconciler; pub(in crate::app::composition) fn data_change_reconciler( diff --git a/src-tauri/src/app/composition/adapters/tauri_sync.rs b/src-tauri/src/app/composition/adapters/tauri_sync.rs index 19aa7c9d..a6b66130 100644 --- a/src-tauri/src/app/composition/adapters/tauri_sync.rs +++ b/src-tauri/src/app/composition/adapters/tauri_sync.rs @@ -9,12 +9,12 @@ use ttsync_contract::sync::SyncMode; use crate::application::services::lan_sync_service::LanSyncService; use crate::application::services::tt_sync_service::TtSyncService; -use crate::domain::errors::DomainError; -use crate::domain::models::lan_sync::LanSyncPairRequestEvent; use tt_contracts::sync::SyncJobEvent; use tt_contracts::sync_automation::{ SyncAutomationStatus, SyncAutomationTarget, SyncAutomationToastEvent, }; +use tt_domain::errors::DomainError; +use tt_domain::models::lan_sync::LanSyncPairRequestEvent; use tt_ports::lan_sync::{LanPairingApprovalRequest, LanServerErrorReporter, PairingApproval}; use tt_ports::sync::SyncJobEventPublisher; use tt_ports::sync_automation::{ diff --git a/src-tauri/src/app/composition/services/mod.rs b/src-tauri/src/app/composition/services/mod.rs index 8e8c1d52..1090fae8 100644 --- a/src-tauri/src/app/composition/services/mod.rs +++ b/src-tauri/src/app/composition/services/mod.rs @@ -37,10 +37,10 @@ use crate::application::services::update_service::UpdateService; use crate::application::services::user_directory_service::UserDirectoryService; use crate::application::services::user_service::UserService; use crate::application::services::world_info_service::WorldInfoService; -use crate::domain::errors::DomainError; use crate::infrastructure::apis::http_external_import_downloader::HttpExternalImportDownloader; use tt_adapter_http::HttpClientPool; use tt_adapter_storage_core::file_system::DataDirectory; +use tt_domain::errors::DomainError; use super::{adapters, repositories}; diff --git a/src-tauri/src/app/composition/services/sync.rs b/src-tauri/src/app/composition/services/sync.rs index db885ed9..150213e9 100644 --- a/src-tauri/src/app/composition/services/sync.rs +++ b/src-tauri/src/app/composition/services/sync.rs @@ -8,12 +8,12 @@ use crate::application::services::lan_sync_service::{ use crate::application::services::sync_automation_service::SyncAutomationService; use crate::application::services::sync_job_coordinator::SyncJobCoordinator; use crate::application::services::tt_sync_service::TtSyncService; -use crate::domain::ios_policy::IosPolicyActivationReport; use tt_adapter_storage_core::file_system::DataDirectory; use tt_adapter_sync::{ AxumLanServerControl, HttpLanPairingClient, HttpTtPairingClient, InfrastructureSyncJobExecutor, LanPeerStore, LanSyncStore, LocalLanAddressDiscovery, SyncAutomationStore, TtSyncRuntime, }; +use tt_domain::ios_policy::IosPolicyActivationReport; use tt_ports::lan_sync::{LanPeerRepository, LanServerControl, LanSyncSettingsRepository}; use tt_ports::sync::DataChangeReconciler; diff --git a/src-tauri/src/app/contract_tests/mod.rs b/src-tauri/src/app/contract_tests/mod.rs index 6eed9fda..de33f0c4 100644 --- a/src-tauri/src/app/contract_tests/mod.rs +++ b/src-tauri/src/app/contract_tests/mod.rs @@ -38,13 +38,6 @@ use crate::application::services::agent_workspace_lifecycle_service::{ use crate::application::services::character_service::CharacterService; use crate::application::services::llm_connection_service::LlmConnectionService; use crate::application::services::skill_service::SkillService; -use crate::domain::errors::DomainError; -use crate::domain::models::agent::profile::{AgentDelegationPolicy, AgentProfileId}; -use crate::domain::models::agent::{ - AgentChatRef, AgentModelContentPart, AgentModelRequest, AgentRun, AgentRunEventLevel, - AgentRunPresentation, AgentRunStatus, WorkspacePath, -}; -use crate::domain::models::preset::{DefaultPreset, Preset, PresetType}; use crate::infrastructure::persistence::png_utils::{ read_character_data_from_png, write_character_data_to_png, }; @@ -56,6 +49,13 @@ use crate::infrastructure::repositories::file_world_info_repository::FileWorldIn use tt_adapter_storage_core::FileChatRepository; use tt_adapter_storage_core::FileLlmConnectionRepository; use tt_adapter_storage_core::chat_directory_identity::new_shared_chat_alias_store_for_user_dir; +use tt_domain::errors::DomainError; +use tt_domain::models::agent::profile::{AgentDelegationPolicy, AgentProfileId}; +use tt_domain::models::agent::{ + AgentChatRef, AgentModelContentPart, AgentModelRequest, AgentRun, AgentRunEventLevel, + AgentRunPresentation, AgentRunStatus, WorkspacePath, +}; +use tt_domain::models::preset::{DefaultPreset, Preset, PresetType}; use tt_ports::repositories::agent_invocation_repository::AgentInvocationRepository; use tt_ports::repositories::agent_profile_repository::AgentProfileRepository; use tt_ports::repositories::agent_profile_storage_health_repository::AgentProfileStorageHealthRepository; @@ -250,7 +250,7 @@ fn default_agent_responses() -> Vec { async fn resolve_contract_profile( fixture: &AgentRuntimeFixture, -) -> crate::domain::models::agent::profile::ResolvedAgentProfile { +) -> tt_domain::models::agent::profile::ResolvedAgentProfile { let registry = BuiltinAgentToolRegistry::phase2c(); fixture .profile_service @@ -265,7 +265,7 @@ async fn resolve_contract_profile( fn contract_run( id: &str, presentation: AgentRunPresentation, - profile: &crate::domain::models::agent::profile::ResolvedAgentProfile, + profile: &tt_domain::models::agent::profile::ResolvedAgentProfile, ) -> AgentRun { AgentRun { id: id.to_string(), @@ -417,7 +417,7 @@ async fn execute_agent_loop_with_host_resolver( run_id: String, prompt_snapshot: Value, request: ChatCompletionGenerateRequestDto, - profile: crate::domain::models::agent::profile::ResolvedAgentProfile, + profile: tt_domain::models::agent::profile::ResolvedAgentProfile, cancel_receiver: &mut watch::Receiver, resolver: R, ) -> Result<(), ApplicationError> @@ -502,7 +502,7 @@ async fn wait_for_event_field( async fn read_agent_events( repository: &FileAgentRepository, run_id: &str, -) -> Vec { +) -> Vec { repository .read_events( run_id, diff --git a/src-tauri/src/app/dev_observability.rs b/src-tauri/src/app/dev_observability.rs index 6c70bea6..ad251841 100644 --- a/src-tauri/src/app/dev_observability.rs +++ b/src-tauri/src/app/dev_observability.rs @@ -9,13 +9,13 @@ use crate::application::dto::dev_observability_dto::{ BackendLogEntryDto, DevBundleVersionDto, FrontendLogEntrySnapshotDto, LlmApiLogIndexEntryDto, LlmApiLogPreviewDto, LlmApiLogRawDto, LlmApiRawKindDto, }; -use crate::domain::errors::DomainError; use crate::infrastructure::logging::dev_bundle::{DevLogBundleInput, export_dev_log_bundle}; use crate::infrastructure::logging::devtools::{BackendLogEntry, BackendLogStore}; use crate::infrastructure::logging::llm_api_logs::{ LlmApiLogEntryPreview, LlmApiLogEntryRaw, LlmApiLogIndexEntry, LlmApiLogStore, LlmApiRawKind, }; use crate::infrastructure::paths::RuntimePaths; +use tt_domain::errors::DomainError; pub struct DevObservabilityHub { app_handle: AppHandle, diff --git a/src-tauri/src/app/host/setup.rs b/src-tauri/src/app/host/setup.rs index 93a4e706..dbd6a9b4 100644 --- a/src-tauri/src/app/host/setup.rs +++ b/src-tauri/src/app/host/setup.rs @@ -7,11 +7,11 @@ use std::sync::Arc; use crate::app::{BackendReadiness, StartupProfile, spawn_initialization}; -use crate::domain::errors::DomainError; -use crate::domain::ios_policy::IosPolicyScope; use crate::infrastructure::logging::llm_api_logs::LlmApiLogStore; use tauri::Manager; use tt_adapter_http::HttpClientPool; +use tt_domain::errors::DomainError; +use tt_domain::ios_policy::IosPolicyScope; pub(super) fn setup(app: &mut tauri::App) -> Result<(), Box> { let app_handle = app.handle().clone(); diff --git a/src-tauri/src/app/startup_profile.rs b/src-tauri/src/app/startup_profile.rs index 4104f0b4..b553e257 100644 --- a/src-tauri/src/app/startup_profile.rs +++ b/src-tauri/src/app/startup_profile.rs @@ -1,12 +1,12 @@ use std::path::Path; -use crate::domain::errors::DomainError; -use crate::domain::ios_policy::{ - IosPolicyActivationReport, IosPolicyScope, resolve_ios_policy_activation_report, -}; -use crate::domain::models::settings::TauriTavernSettings; use crate::infrastructure::ios_policy_cache::resolve_effective_raw_policy_sync; use tt_adapter_storage_core::FileSettingsRepository; +use tt_domain::errors::DomainError; +use tt_domain::ios_policy::{ + IosPolicyActivationReport, IosPolicyScope, resolve_ios_policy_activation_report, +}; +use tt_domain::models::settings::TauriTavernSettings; #[derive(Debug, Clone)] pub(crate) struct StartupProfile { diff --git a/src-tauri/src/app/state.rs b/src-tauri/src/app/state.rs index 04339d7c..6d0863a4 100644 --- a/src-tauri/src/app/state.rs +++ b/src-tauri/src/app/state.rs @@ -42,9 +42,9 @@ use crate::application::services::update_service::UpdateService; use crate::application::services::user_directory_service::UserDirectoryService; use crate::application::services::user_service::UserService; use crate::application::services::world_info_service::WorldInfoService; -use crate::domain::errors::DomainError; -use crate::domain::ios_policy::IosPolicyActivationReport; use crate::infrastructure::paths::RuntimePaths; +use tt_domain::errors::DomainError; +use tt_domain::ios_policy::IosPolicyActivationReport; use super::{StartupProfile, composition}; diff --git a/src-tauri/src/domain/mod.rs b/src-tauri/src/domain/mod.rs deleted file mode 100644 index ec3d3b6a..00000000 --- a/src-tauri/src/domain/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub(crate) use tt_domain::json_merge; -pub use tt_domain::{errors, ios_policy, text_metrics, text_search}; - -pub mod models; diff --git a/src-tauri/src/domain/models/mod.rs b/src-tauri/src/domain/models/mod.rs deleted file mode 100644 index 9164c267..00000000 --- a/src-tauri/src/domain/models/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub use tt_domain::models::*; diff --git a/src-tauri/src/infrastructure/repositories/file_character_repository/repository.rs b/src-tauri/src/infrastructure/repositories/file_character_repository/repository.rs index ad1141f5..5a153965 100644 --- a/src-tauri/src/infrastructure/repositories/file_character_repository/repository.rs +++ b/src-tauri/src/infrastructure/repositories/file_character_repository/repository.rs @@ -5,11 +5,11 @@ use serde_json::Value; use tokio::fs; use tokio::io::{AsyncBufReadExt, BufReader}; -use crate::domain::json_merge::merge_json_value; use crate::infrastructure::persistence::png_utils::{ process_avatar_image, read_character_data_from_png, write_character_data_to_png, }; use tt_domain::errors::DomainError; +use tt_domain::json_merge::merge_json_value; use tt_domain::models::character::Character; use tt_domain::models::chat::parse_message_timestamp_value; use tt_ports::repositories::character_repository::{ diff --git a/src-tauri/src/infrastructure/repositories/file_skill_repository/read.rs b/src-tauri/src/infrastructure/repositories/file_skill_repository/read.rs index 3bfea55d..1babd6ca 100644 --- a/src-tauri/src/infrastructure/repositories/file_skill_repository/read.rs +++ b/src-tauri/src/infrastructure/repositories/file_skill_repository/read.rs @@ -4,13 +4,13 @@ use std::path::PathBuf; use super::FileSkillRepository; use super::package::{collect_skill_files, sha256_hex}; use super::paths::{normalize_skill_path, validate_skill_name}; -use crate::domain::text_metrics::TextMetrics; -use crate::domain::text_search::PreparedTextSearch; use tt_domain::errors::DomainError; use tt_domain::models::skill::{ DEFAULT_SKILL_READ_FALLBACK_MAX_CHARS, SkillFileKind, SkillFileRef, SkillReadRequest, SkillReadResult, SkillScope, SkillSearchHit, SkillSearchRequest, SkillSearchResult, }; +use tt_domain::text_metrics::TextMetrics; +use tt_domain::text_search::PreparedTextSearch; struct SkillTextFile { scope: SkillScope, diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 2d742698..748d5260 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,6 +1,5 @@ mod app; mod application; -mod domain; mod infrastructure; mod observability_targets; mod platform; diff --git a/src-tauri/src/platform/ios_document_picker.rs b/src-tauri/src/platform/ios_document_picker.rs index eb0b4adf..b4d07b12 100644 --- a/src-tauri/src/platform/ios_document_picker.rs +++ b/src-tauri/src/platform/ios_document_picker.rs @@ -14,8 +14,8 @@ use objc2_uniform_type_identifiers::UTType; use tauri::WebviewWindow; use tokio::sync::oneshot; -use crate::domain::errors::DomainError; use crate::platform::ios_ui::resolve_presenting_view_controller; +use tt_domain::errors::DomainError; const DATA_ARCHIVE_CONTENT_TYPES: &[&str] = &[ "public.zip-archive", diff --git a/src-tauri/src/platform/ios_share_sheet.rs b/src-tauri/src/platform/ios_share_sheet.rs index e2b5d900..2aacca5c 100644 --- a/src-tauri/src/platform/ios_share_sheet.rs +++ b/src-tauri/src/platform/ios_share_sheet.rs @@ -9,8 +9,8 @@ use objc2_ui_kit::{UIActivityType, UIActivityViewController}; use tauri::WebviewWindow; use tokio::sync::oneshot; -use crate::domain::errors::DomainError; use crate::platform::ios_ui::resolve_presenting_view_controller; +use tt_domain::errors::DomainError; #[derive(Debug, Clone)] pub struct ShareResult { diff --git a/src-tauri/src/platform/ios_ui.rs b/src-tauri/src/platform/ios_ui.rs index 63dcb1e2..bb22318f 100644 --- a/src-tauri/src/platform/ios_ui.rs +++ b/src-tauri/src/platform/ios_ui.rs @@ -7,7 +7,7 @@ use objc2::rc::Retained; use objc2::runtime::{AnyClass, AnyObject}; use objc2_foundation::NSArray; -use crate::domain::errors::DomainError; +use tt_domain::errors::DomainError; use objc2_ui_kit::{UIViewController, UIWindow}; diff --git a/src-tauri/src/presentation/commands/agent_commands.rs b/src-tauri/src/presentation/commands/agent_commands.rs index 686d2f8e..df21ef8b 100644 --- a/src-tauri/src/presentation/commands/agent_commands.rs +++ b/src-tauri/src/presentation/commands/agent_commands.rs @@ -25,10 +25,10 @@ use crate::application::dto::agent_dto::{ }; use crate::application::errors::ApplicationError; use crate::application::services::agent_workspace_lifecycle_service::AgentChatWorkspaceTarget; -use crate::domain::models::agent::AgentChatRef; -use crate::domain::models::agent::profile_diagnostic::AgentProfileHealth; use crate::presentation::commands::helpers::{log_command, map_command_error}; use crate::presentation::errors::CommandError; +use tt_domain::models::agent::AgentChatRef; +use tt_domain::models::agent::profile_diagnostic::AgentProfileHealth; use tt_ports::repositories::agent_workspace_lifecycle_repository::AgentPersistentStatePruneRequest; #[tauri::command] diff --git a/src-tauri/src/presentation/commands/asset_commands.rs b/src-tauri/src/presentation/commands/asset_commands.rs index e61ad8df..ced21716 100644 --- a/src-tauri/src/presentation/commands/asset_commands.rs +++ b/src-tauri/src/presentation/commands/asset_commands.rs @@ -4,11 +4,11 @@ use tauri::State; use crate::app::AppState; use crate::application::services::asset_service::AssetDownloadResult; -use crate::domain::models::asset::AssetCatalog; use crate::presentation::commands::helpers::{ ensure_ios_policy_allows, log_command, map_command_error, }; use crate::presentation::errors::CommandError; +use tt_domain::models::asset::AssetCatalog; #[tauri::command] pub async fn get_assets_library( diff --git a/src-tauri/src/presentation/commands/avatar_commands.rs b/src-tauri/src/presentation/commands/avatar_commands.rs index 1a9294aa..6785e57d 100644 --- a/src-tauri/src/presentation/commands/avatar_commands.rs +++ b/src-tauri/src/presentation/commands/avatar_commands.rs @@ -9,11 +9,11 @@ use tauri::State; use tokio::fs; use crate::app::AppState; -use crate::domain::models::avatar::{AvatarUploadResult, CropInfo}; use crate::presentation::commands::helpers::{ log_command, log_user_visible_error, map_command_error, }; use crate::presentation::errors::CommandError; +use tt_domain::models::avatar::{AvatarUploadResult, CropInfo}; const MAX_MOBILE_INLINE_AVATAR_BYTES: u64 = 8 * 1024 * 1024; diff --git a/src-tauri/src/presentation/commands/background_commands.rs b/src-tauri/src/presentation/commands/background_commands.rs index 87201397..a8a8aa55 100644 --- a/src-tauri/src/presentation/commands/background_commands.rs +++ b/src-tauri/src/presentation/commands/background_commands.rs @@ -8,10 +8,10 @@ use tauri::State; use crate::app::AppState; use crate::application::dto::background_dto::{DeleteBackgroundDto, RenameBackgroundDto}; use crate::application::services::host_resource_service::HostResourceService; -use crate::domain::models::background::BackgroundListEntry; -use crate::domain::models::image_metadata::ImageMetadataIndex; use crate::presentation::commands::helpers::{log_command, map_command_error}; use crate::presentation::errors::CommandError; +use tt_domain::models::background::BackgroundListEntry; +use tt_domain::models::image_metadata::ImageMetadataIndex; #[derive(Debug, Clone, Serialize)] pub struct ThumbnailAssetPayload { diff --git a/src-tauri/src/presentation/commands/character_commands.rs b/src-tauri/src/presentation/commands/character_commands.rs index 3cb7e9fc..43f20092 100644 --- a/src-tauri/src/presentation/commands/character_commands.rs +++ b/src-tauri/src/presentation/commands/character_commands.rs @@ -13,9 +13,9 @@ use crate::application::dto::character_dto::{ ResolveCharacterLorebookConflictResultDto, UpdateAvatarDto, UpdateCharacterCardDataDto, UpdateCharacterDto, }; -use crate::domain::models::skill::{SkillScope, SkillScopeRetargetRequest}; use crate::presentation::commands::helpers::{log_command, map_command_error}; use crate::presentation::errors::CommandError; +use tt_domain::models::skill::{SkillScope, SkillScopeRetargetRequest}; const SKILL_SOURCE_KIND_CHARACTER: &str = "character"; diff --git a/src-tauri/src/presentation/commands/chat_completion_commands.rs b/src-tauri/src/presentation/commands/chat_completion_commands.rs index dde2f0ab..56887dec 100644 --- a/src-tauri/src/presentation/commands/chat_completion_commands.rs +++ b/src-tauri/src/presentation/commands/chat_completion_commands.rs @@ -9,9 +9,9 @@ use crate::application::dto::chat_completion_dto::{ ChatCompletionGenerateRequestDto, ChatCompletionStatusRequestDto, }; use crate::application::services::chat_completion_service::ChatCompletionService; -use crate::domain::models::upstream_failure::UpstreamFailure; use crate::presentation::commands::helpers::{log_command, map_command_error}; use crate::presentation::errors::CommandError; +use tt_domain::models::upstream_failure::UpstreamFailure; #[tauri::command] pub async fn get_chat_completions_status( diff --git a/src-tauri/src/presentation/commands/extension_commands.rs b/src-tauri/src/presentation/commands/extension_commands.rs index e944ee6a..accef5ca 100644 --- a/src-tauri/src/presentation/commands/extension_commands.rs +++ b/src-tauri/src/presentation/commands/extension_commands.rs @@ -3,14 +3,14 @@ use std::sync::Arc; use tauri::State; use crate::app::AppState; -use crate::domain::ios_policy::IosPolicyScope; -use crate::domain::models::extension::{ - Extension, ExtensionInstallResult, ExtensionUpdateResult, ExtensionVersion, -}; use crate::presentation::commands::helpers::{ ensure_ios_policy_allows, log_command, map_command_error, }; use crate::presentation::errors::CommandError; +use tt_domain::ios_policy::IosPolicyScope; +use tt_domain::models::extension::{ + Extension, ExtensionInstallResult, ExtensionUpdateResult, ExtensionVersion, +}; #[tauri::command] pub async fn get_extensions( @@ -39,11 +39,11 @@ pub async fn get_extensions( let before = extensions.len(); extensions.retain(|extension| match extension.extension_type { - crate::domain::models::extension::ExtensionType::System => { + tt_domain::models::extension::ExtensionType::System => { system_allowlist.allows(&extension.name) } - crate::domain::models::extension::ExtensionType::Local - | crate::domain::models::extension::ExtensionType::Global => allow_third_party, + tt_domain::models::extension::ExtensionType::Local + | tt_domain::models::extension::ExtensionType::Global => allow_third_party, }); let filtered = before.saturating_sub(extensions.len()); diff --git a/src-tauri/src/presentation/commands/file_commands.rs b/src-tauri/src/presentation/commands/file_commands.rs index 2830e067..287b2688 100644 --- a/src-tauri/src/presentation/commands/file_commands.rs +++ b/src-tauri/src/presentation/commands/file_commands.rs @@ -10,9 +10,9 @@ use tokio::fs; use url::Url; use crate::app::AppState; -use crate::domain::models::filename::sanitize_filename as sanitize_filename_contract; use crate::presentation::commands::helpers::log_command; use crate::presentation::errors::CommandError; +use tt_domain::models::filename::sanitize_filename as sanitize_filename_contract; const UNSAFE_EXTENSIONS: &[&str] = &[ ".php", diff --git a/src-tauri/src/presentation/commands/helpers.rs b/src-tauri/src/presentation/commands/helpers.rs index 0512a9f1..7e639df4 100644 --- a/src-tauri/src/presentation/commands/helpers.rs +++ b/src-tauri/src/presentation/commands/helpers.rs @@ -3,11 +3,11 @@ use std::fmt::Display; use crate::presentation::errors::CommandError; pub fn ensure_ios_policy_allows( - ios_policy: &crate::domain::ios_policy::IosPolicyActivationReport, + ios_policy: &tt_domain::ios_policy::IosPolicyActivationReport, allowed: bool, capability: &'static str, ) -> Result<(), CommandError> { - if ios_policy.scope == crate::domain::ios_policy::IosPolicyScope::Ios && !allowed { + if ios_policy.scope == tt_domain::ios_policy::IosPolicyScope::Ios && !allowed { return Err(CommandError::Unauthorized(format!( "iOS policy disabled capability: {capability}" ))); @@ -67,7 +67,7 @@ pub fn log_user_visible_error(message: impl AsRef) { #[cfg(test)] mod tests { - use crate::domain::errors::GENERATION_CANCELLED_BY_USER_MESSAGE; + use tt_domain::errors::GENERATION_CANCELLED_BY_USER_MESSAGE; use super::*; diff --git a/src-tauri/src/presentation/commands/image_metadata_commands.rs b/src-tauri/src/presentation/commands/image_metadata_commands.rs index 25bb559b..4328e853 100644 --- a/src-tauri/src/presentation/commands/image_metadata_commands.rs +++ b/src-tauri/src/presentation/commands/image_metadata_commands.rs @@ -7,9 +7,9 @@ use crate::application::dto::image_metadata_dto::{ CreateImageMetadataFolderDto, DeleteImageMetadataFolderDto, ImageMetadataFolderAssignmentDto, SetImageMetadataFolderThumbnailsDto, UpdateImageMetadataFolderDto, }; -use crate::domain::models::image_metadata::{BackgroundFoldersPayload, ImageMetadataFolder}; use crate::presentation::commands::helpers::{log_command, map_command_error}; use crate::presentation::errors::CommandError; +use tt_domain::models::image_metadata::{BackgroundFoldersPayload, ImageMetadataFolder}; #[tauri::command] pub async fn get_background_folders( diff --git a/src-tauri/src/presentation/commands/ios_file_bridge_commands.rs b/src-tauri/src/presentation/commands/ios_file_bridge_commands.rs index 9f1989a9..d17cc5ba 100644 --- a/src-tauri/src/presentation/commands/ios_file_bridge_commands.rs +++ b/src-tauri/src/presentation/commands/ios_file_bridge_commands.rs @@ -9,13 +9,13 @@ use tauri::{AppHandle, Manager, State, WebviewWindow}; use crate::app::AppState; use crate::application::host_contract::IOS_EXPORT_STAGING_ROOT_NAME; -use crate::domain::errors::DomainError; use crate::platform::ios_document_picker::{ PickDocumentResult, copy_picked_url_to_path, pick_data_archive, pick_skill_import_archive, }; use crate::platform::ios_share_sheet::share_file; use crate::presentation::commands::helpers::{log_command, map_command_error}; use crate::presentation::errors::CommandError; +use tt_domain::errors::DomainError; const IOS_SKILL_IMPORT_STAGING_ROOT_NAME: &str = "tauritavern-skill-import-staging"; diff --git a/src-tauri/src/presentation/commands/lan_sync_commands.rs b/src-tauri/src/presentation/commands/lan_sync_commands.rs index 254d0d65..a5165e9e 100644 --- a/src-tauri/src/presentation/commands/lan_sync_commands.rs +++ b/src-tauri/src/presentation/commands/lan_sync_commands.rs @@ -6,12 +6,12 @@ use tauri::State; use ttsync_contract::sync::SyncMode; use crate::app::AppState; -use crate::domain::models::lan_sync::{LanSyncPairedDeviceSummary, LanSyncStatus}; use crate::presentation::commands::helpers::{ ensure_ios_policy_allows, log_command, map_command_error, }; use crate::presentation::errors::CommandError; use tt_contracts::sync::{SyncJobReport, SyncOperationOptions}; +use tt_domain::models::lan_sync::{LanSyncPairedDeviceSummary, LanSyncStatus}; fn ensure_lan_sync_allowed(app_state: &AppState) -> Result<(), CommandError> { ensure_ios_policy_allows( @@ -280,9 +280,9 @@ pub async fn lan_sync_clear_sync_mode_override( Ok(()) } -fn generate_qr_svg(text: &str) -> Result { +fn generate_qr_svg(text: &str) -> Result { let code = QrCode::new(text.as_bytes()) - .map_err(|error| crate::domain::errors::DomainError::InternalError(error.to_string()))?; + .map_err(|error| tt_domain::errors::DomainError::InternalError(error.to_string()))?; Ok(code .render::() .min_dimensions(200, 200) diff --git a/src-tauri/src/presentation/commands/preset_commands.rs b/src-tauri/src/presentation/commands/preset_commands.rs index 46505ada..62166af9 100644 --- a/src-tauri/src/presentation/commands/preset_commands.rs +++ b/src-tauri/src/presentation/commands/preset_commands.rs @@ -7,11 +7,11 @@ use crate::application::dto::preset_dto::{ DeleteOpenAIPresetDto, DeleteOpenAIPresetResponseDto, DeletePresetDto, RestorePresetDto, RestorePresetResponseDto, SaveOpenAIPresetDto, SavePresetDto, SavePresetResponseDto, }; -use crate::domain::models::preset::PresetType; use crate::presentation::commands::helpers::{ log_command, log_user_visible_error, map_command_error, }; use crate::presentation::errors::CommandError; +use tt_domain::models::preset::PresetType; const SKILL_SOURCE_KIND_PRESET: &str = "preset"; diff --git a/src-tauri/src/presentation/commands/runtime_paths_commands.rs b/src-tauri/src/presentation/commands/runtime_paths_commands.rs index 4ee8eea5..d2518b96 100644 --- a/src-tauri/src/presentation/commands/runtime_paths_commands.rs +++ b/src-tauri/src/presentation/commands/runtime_paths_commands.rs @@ -64,7 +64,7 @@ fn runtime_paths_dto(info: RuntimePathsInfo) -> RuntimePathsDto { } } -fn map_set_data_root_error(error: crate::domain::errors::DomainError) -> CommandError { +fn map_set_data_root_error(error: tt_domain::errors::DomainError) -> CommandError { let command_error = CommandError::from(error); if matches!(&command_error, CommandError::InternalServerError(_)) { map_command_error("Failed to set data root")(command_error) diff --git a/src-tauri/src/presentation/commands/skill_commands.rs b/src-tauri/src/presentation/commands/skill_commands.rs index edbb8696..1fa255d9 100644 --- a/src-tauri/src/presentation/commands/skill_commands.rs +++ b/src-tauri/src/presentation/commands/skill_commands.rs @@ -6,16 +6,16 @@ use serde::Serialize; use tauri::State; use crate::app::AppState; -use crate::domain::models::skill::{ +use crate::presentation::commands::helpers::{ + ensure_ios_policy_allows, log_command, map_command_error, +}; +use crate::presentation::errors::CommandError; +use tt_domain::models::skill::{ DEFAULT_SKILL_READ_FALLBACK_MAX_CHARS, SkillFileRef, SkillImportInput, SkillImportPreview, SkillIndexEntry, SkillInstallRequest, SkillInstallResult, SkillMoveRequest, SkillReadRequest, SkillReadResult, SkillScope, SkillScopeFilter, SkillScopeRetargetRequest, SkillScopeRetargetResult, SkillWriteRequest, }; -use crate::presentation::commands::helpers::{ - ensure_ios_policy_allows, log_command, map_command_error, -}; -use crate::presentation::errors::CommandError; #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] diff --git a/src-tauri/src/presentation/commands/tt_sync_commands.rs b/src-tauri/src/presentation/commands/tt_sync_commands.rs index 7865e35b..a863a128 100644 --- a/src-tauri/src/presentation/commands/tt_sync_commands.rs +++ b/src-tauri/src/presentation/commands/tt_sync_commands.rs @@ -5,10 +5,10 @@ use tauri::State; use ttsync_contract::sync::SyncMode; use crate::app::AppState; -use crate::domain::models::tt_sync::TtSyncPairedServer; use crate::presentation::commands::helpers::{log_command, map_command_error}; use crate::presentation::errors::CommandError; use tt_contracts::sync::{SyncJobReport, SyncOperationOptions}; +use tt_domain::models::tt_sync::TtSyncPairedServer; #[derive(Debug, Clone, Serialize)] pub struct TtSyncPermissionsDto { diff --git a/src-tauri/src/presentation/commands/update_commands.rs b/src-tauri/src/presentation/commands/update_commands.rs index 62784050..c8ed4afd 100644 --- a/src-tauri/src/presentation/commands/update_commands.rs +++ b/src-tauri/src/presentation/commands/update_commands.rs @@ -3,11 +3,11 @@ use std::sync::Arc; use tauri::State; use crate::app::AppState; -use crate::domain::models::update::UpdateCheckResult; use crate::presentation::commands::helpers::{ ensure_ios_policy_allows, log_command, map_command_error, }; use crate::presentation::errors::CommandError; +use tt_domain::models::update::UpdateCheckResult; #[tauri::command] pub async fn check_for_update( diff --git a/src-tauri/src/presentation/errors.rs b/src-tauri/src/presentation/errors.rs index 1a525a00..a922ff8f 100644 --- a/src-tauri/src/presentation/errors.rs +++ b/src-tauri/src/presentation/errors.rs @@ -1,8 +1,8 @@ use crate::application::errors::ApplicationError; -use crate::domain::errors::DomainError; -use crate::domain::models::upstream_failure::UpstreamFailure; use serde::Serialize; use thiserror::Error; +use tt_domain::errors::DomainError; +use tt_domain::models::upstream_failure::UpstreamFailure; #[derive(Error, Debug, Serialize)] pub enum CommandError { @@ -82,7 +82,7 @@ impl CommandError { #[cfg(test)] mod tests { - use crate::domain::errors::GENERATION_CANCELLED_BY_USER_MESSAGE; + use tt_domain::errors::GENERATION_CANCELLED_BY_USER_MESSAGE; use super::*; diff --git a/tests/event-abi-contract.test.mjs b/tests/event-abi-contract.test.mjs index 843aeb8d..6247a993 100644 --- a/tests/event-abi-contract.test.mjs +++ b/tests/event-abi-contract.test.mjs @@ -83,8 +83,8 @@ test('chat rename events use backend-committed normalized file names', async () readFile(path.join(REPO_ROOT, 'src/tauri/main/routes/chat-routes.js'), 'utf8'), readFile(path.join(REPO_ROOT, 'src-tauri/src/presentation/commands/chat_commands.rs'), 'utf8'), readFile(path.join(REPO_ROOT, 'src-tauri/src/presentation/commands/group_chat_commands.rs'), 'utf8'), - readFile(path.join(REPO_ROOT, 'src-tauri/src/application/services/chat_service.rs'), 'utf8'), - readFile(path.join(REPO_ROOT, 'src-tauri/src/application/services/group_chat_service.rs'), 'utf8'), + readFile(path.join(REPO_ROOT, 'src-tauri/crates/tt-application/src/services/chat_service.rs'), 'utf8'), + readFile(path.join(REPO_ROOT, 'src-tauri/crates/tt-application/src/services/group_chat_service.rs'), 'utf8'), ]); assert.match(route, /const sanitizedFileName = await context\.safeInvoke\('rename_group_chat'/); diff --git a/tests/minimax-provider-contract.test.mjs b/tests/minimax-provider-contract.test.mjs index c77ec169..038a607d 100644 --- a/tests/minimax-provider-contract.test.mjs +++ b/tests/minimax-provider-contract.test.mjs @@ -6,8 +6,8 @@ const openaiSource = await readFile(new URL('../src/scripts/openai.js', import.m const secretsSource = await readFile(new URL('../src/scripts/secrets.js', import.meta.url), 'utf8'); const aiRoutesSource = await readFile(new URL('../src/tauri/main/routes/ai-routes.js', import.meta.url), 'utf8'); const rustSource = await readFile(new URL('../src-tauri/crates/tt-domain/src/models/chat_completion_source.rs', import.meta.url), 'utf8'); -const rustConfigSource = await readFile(new URL('../src-tauri/src/application/services/chat_completion_service/config.rs', import.meta.url), 'utf8'); -const rustPayloadSource = await readFile(new URL('../src-tauri/src/application/services/chat_completion_service/payload/minimax.rs', import.meta.url), 'utf8'); +const rustConfigSource = await readFile(new URL('../src-tauri/crates/tt-application/src/services/chat_completion_service/config.rs', import.meta.url), 'utf8'); +const rustPayloadSource = await readFile(new URL('../src-tauri/crates/tt-application/src/services/chat_completion_service/payload/minimax.rs', import.meta.url), 'utf8'); const rustRepositorySource = await readRustSources(new URL('../src-tauri/crates/tt-adapter-provider-http/src/http_chat_completion_repository/', import.meta.url)); const rossAscendsSource = await readFile(new URL('../src/scripts/RossAscends-mods.js', import.meta.url), 'utf8'); diff --git a/tests/prompt-assembly-decoupling-contract.test.mjs b/tests/prompt-assembly-decoupling-contract.test.mjs index b39612d4..5228c525 100644 --- a/tests/prompt-assembly-decoupling-contract.test.mjs +++ b/tests/prompt-assembly-decoupling-contract.test.mjs @@ -11,7 +11,7 @@ function readProjectFile(relativePath) { } test('connectionRef prompt assembly overlays model binding instead of validating preset source', async () => { - const source = await readProjectFile('src-tauri/src/application/services/prompt_assembly_service.rs'); + const source = await readProjectFile('src-tauri/crates/tt-application/src/services/prompt_assembly_service.rs'); assert.match(source, /apply_model_binding_to_prompt_settings/); assert.match(source, /"deepseek"\s*=>\s*Ok\("deepseek_model"\)/); @@ -20,7 +20,7 @@ test('connectionRef prompt assembly overlays model binding instead of validating }); test('currentPromptSnapshot prompt assembly overlays frozen current model connection', async () => { - const source = await readProjectFile('src-tauri/src/application/services/prompt_assembly_service.rs'); + const source = await readProjectFile('src-tauri/crates/tt-application/src/services/prompt_assembly_service.rs'); const frontendSource = await readProjectFile('src/scripts/tauritavern/agent/frozen-run-input-snapshot.js'); const agentApiSource = await readProjectFile('src/tauri/main/api/agent-prompt-assembly-run.js'); @@ -35,7 +35,7 @@ test('currentPromptSnapshot prompt assembly overlays frozen current model connec }); test('requiresConfiguration prompt assembly fails fast before frontend broker handoff', async () => { - const source = await readProjectFile('src-tauri/src/application/services/prompt_assembly_service.rs'); + const source = await readProjectFile('src-tauri/crates/tt-application/src/services/prompt_assembly_service.rs'); const guardIndex = source.indexOf('ensure_profile_model_configured(&profile)?;'); const brokerIndex = source.indexOf('AgentPromptAssemblyModeDto::FrontendPromptAssembly'); diff --git a/tests/regex-native-backend-contract.test.mjs b/tests/regex-native-backend-contract.test.mjs index 4075c21b..9aaa4a93 100644 --- a/tests/regex-native-backend-contract.test.mjs +++ b/tests/regex-native-backend-contract.test.mjs @@ -16,7 +16,7 @@ test('native regex batching shares the same runnable-script gate as sync regex e }); test('native regex DTO remains an execution payload, not SillyTavern extension state', async () => { - const source = await readFile(path.join(REPO_ROOT, 'src-tauri', 'src', 'application', 'dto', 'native_regex_dto.rs'), 'utf8'); + const source = await readFile(path.join(REPO_ROOT, 'src-tauri', 'crates', 'tt-application', 'src', 'dto', 'native_regex_dto.rs'), 'utf8'); assert.doesNotMatch(source, /\bpub\s+disabled\b/); }); diff --git a/tests/stable-diffusion-upstream-contract.test.mjs b/tests/stable-diffusion-upstream-contract.test.mjs index bc440cd4..d25d69d7 100644 --- a/tests/stable-diffusion-upstream-contract.test.mjs +++ b/tests/stable-diffusion-upstream-contract.test.mjs @@ -49,7 +49,7 @@ test('Stable Diffusion backend request uses explicit credentials instead of prov 'utf8', ); const serviceSource = await readFile( - path.join(REPO_ROOT, 'src-tauri', 'src', 'application', 'services', 'stable_diffusion_service.rs'), + path.join(REPO_ROOT, 'src-tauri', 'crates', 'tt-application', 'src', 'services', 'stable_diffusion_service.rs'), 'utf8', ); diff --git a/tests/tauritavern-sync-vue-contract.test.mjs b/tests/tauritavern-sync-vue-contract.test.mjs index 0ba9726a..82b9fe10 100644 --- a/tests/tauritavern-sync-vue-contract.test.mjs +++ b/tests/tauritavern-sync-vue-contract.test.mjs @@ -255,7 +255,7 @@ test('TauriTavern Sync automation status events refresh status only while toasts test('TauriTavern Sync automation success toasts include next run time', async () => { const listeners = await readRepoFile('src/scripts/tauri/setting/setting-panel/sync-listeners.js'); - const service = await readRepoFile('src-tauri/src/application/services/sync_automation_service.rs'); + const service = await readRepoFile('src-tauri/crates/tt-application/src/services/sync_automation_service.rs'); const model = await readRepoFile('src-tauri/crates/tt-contracts/src/sync_automation.rs'); const zhCn = await readRepoFile('src/locales/zh-cn.json'); const zhTw = await readRepoFile('src/locales/zh-tw.json');