//! Input Augmentation 层 — Mention Resolver trait + 注册表 + 注入段构建 //! //! 核心设计2(plan mighty-wibbling-papert.md): //! - [`MentionResolver`] async trait:把 [`MentionRef`] 投影成 [`Augmentation`], //! 按 provider locality 决定 path 脱敏粒度(Local 全路径 / Remote basename)。 //! - [`ResolverRegistry`]:HashMap> + `resolve_all` //! 按 MentionRef::kind_str 分发,单条失败收集 [`ResolveError`] 不阻断整批注入。 //! - 四 impl(ProjectResolver/TaskResolver/IdeaResolver/SkillResolver)在 [`resolvers`] 模块。 //! //! 新增 mention 类型 = 加一个 impl + 注册一行,主干零改(破解"改 4-5 处"僵化)。 pub mod inject; pub mod registry; pub mod resolvers; pub mod sanitize; pub use inject::build_augmentation_segment; pub use registry::ResolverRegistry; pub use resolvers::build_resolver_registry; use async_trait::async_trait; use df_types::augmentation::{Augmentation, MentionRef, ResolveError}; use crate::commands::ai::augmentation::sanitize::ProviderLocality; /// Mention → Augmentation 的投影 trait。 /// /// 每个 Resolver 处理一种 kind(`project`/`task`/`idea`/`skill`),`kind()` 返回的标签 /// 须与 [`MentionRef::kind_str`] / serde tag 一致。`resolve()` 接收 locality 用于决定 /// path 脱敏粒度(仅 ProjectResolver 用到,其余忽略即可)。 /// /// 单条 resolve 失败应返 [`ResolveError::NotFound`] / [`ResolveError::Skip`], /// 由 [`ResolverRegistry::resolve_all`] 收集进 errors 列表不中断其他 mention。 #[async_trait] pub trait MentionResolver: Send + Sync { /// 返回 Resolver 处理的 kind 标签(与 serde tag 一致):`project`/`task`/`idea`/`skill`。 fn kind(&self) -> &'static str; /// 把单个 [`MentionRef`] 投影成 [`Augmentation`]。 /// /// `loc` 为当前 provider 的 locality,ProjectResolver 据此决定 path 是否脱敏。 /// kind 不匹配返 [`ResolveError::KindMismatch`](防注册表分发错配)。 async fn resolve( &self, rf: &MentionRef, loc: ProviderLocality, ) -> Result; }