feat(backend): modèle unifié streaming/progress/events provider-agnostic + pont app-tauri — foundation #156 (QA verte)
This commit is contained in:
@ -17,6 +17,7 @@ use application::{
|
||||
ListProjectsOutput, LiveSessionKind, LiveSessionSnapshot, OpenProjectOutput, ProjectWorkState,
|
||||
StopLiveAgentOutput, TicketWorkSource, TicketWorkStatus, TurnPage, TurnSource, TurnView,
|
||||
};
|
||||
use domain::ports::{ReplyProgress, ReplyProgressKind, ReplyProgressSource, ReplyProgressStage};
|
||||
use domain::{
|
||||
AgentBusyState, PageCursor, PageDirection, Project, ProjectId, ProjectSystemPermissions,
|
||||
ResolvedAgentSystemPermissions, SystemPermissionSet, TurnRole,
|
||||
@ -3046,6 +3047,119 @@ impl From<domain::ChatAttachment> for ChatAttachmentDto {
|
||||
}
|
||||
}
|
||||
|
||||
/// DTO source of a canonical non-terminal reply progress event.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum ReplyProgressSourceDto {
|
||||
/// Native provider event.
|
||||
ProviderNative,
|
||||
/// Local IdeA observability event.
|
||||
IdeaLocal,
|
||||
}
|
||||
|
||||
impl From<ReplyProgressSource> for ReplyProgressSourceDto {
|
||||
fn from(value: ReplyProgressSource) -> Self {
|
||||
match value {
|
||||
ReplyProgressSource::ProviderNative => Self::ProviderNative,
|
||||
ReplyProgressSource::IdeaLocal => Self::IdeaLocal,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// DTO kind of a canonical non-terminal reply progress event.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum ReplyProgressKindDto {
|
||||
/// Turn lifecycle/progress.
|
||||
Turn,
|
||||
/// Assistant message/progress.
|
||||
Message,
|
||||
/// Provider tool activity.
|
||||
Tool,
|
||||
/// IdeA MCP/tool activity.
|
||||
Mcp,
|
||||
/// Unclassified event.
|
||||
Other,
|
||||
}
|
||||
|
||||
impl From<ReplyProgressKind> for ReplyProgressKindDto {
|
||||
fn from(value: ReplyProgressKind) -> Self {
|
||||
match value {
|
||||
ReplyProgressKind::Turn => Self::Turn,
|
||||
ReplyProgressKind::Message => Self::Message,
|
||||
ReplyProgressKind::Tool => Self::Tool,
|
||||
ReplyProgressKind::Mcp => Self::Mcp,
|
||||
ReplyProgressKind::Other => Self::Other,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// DTO stage of a canonical non-terminal reply progress event.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub enum ReplyProgressStageDto {
|
||||
/// Activity started.
|
||||
Started,
|
||||
/// Incremental update.
|
||||
Delta,
|
||||
/// Activity completed.
|
||||
Completed,
|
||||
/// Informational point event.
|
||||
Info,
|
||||
}
|
||||
|
||||
impl From<ReplyProgressStage> for ReplyProgressStageDto {
|
||||
fn from(value: ReplyProgressStage) -> Self {
|
||||
match value {
|
||||
ReplyProgressStage::Started => Self::Started,
|
||||
ReplyProgressStage::Delta => Self::Delta,
|
||||
ReplyProgressStage::Completed => Self::Completed,
|
||||
ReplyProgressStage::Info => Self::Info,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Canonical, provider-agnostic non-terminal progress/event DTO.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ReplyProgressDto {
|
||||
/// Event source.
|
||||
pub source: ReplyProgressSourceDto,
|
||||
/// Canonical event family.
|
||||
pub kind: ReplyProgressKindDto,
|
||||
/// Canonical stage.
|
||||
pub stage: ReplyProgressStageDto,
|
||||
/// Short display label.
|
||||
pub label: String,
|
||||
/// Optional display excerpt.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub text: Option<String>,
|
||||
/// Optional provider identity.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub provider: Option<String>,
|
||||
/// Optional native provider event name.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub native_event: Option<String>,
|
||||
/// Optional tool/MCP name.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub tool_name: Option<String>,
|
||||
}
|
||||
|
||||
impl From<ReplyProgress> for ReplyProgressDto {
|
||||
fn from(value: ReplyProgress) -> Self {
|
||||
Self {
|
||||
source: value.source.into(),
|
||||
kind: value.kind.into(),
|
||||
stage: value.stage.into(),
|
||||
label: value.label,
|
||||
text: value.text,
|
||||
provider: value.provider,
|
||||
native_event: value.native_event,
|
||||
tool_name: value.tool_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// One incremental chunk of a structured agent reply, streamed over the chat
|
||||
/// session's adapter-owned channel. The serialised wire twin of a
|
||||
/// [`domain::ports::ReplyEvent`]: the `agent_send` pump maps each turn event to
|
||||
@ -3077,6 +3191,12 @@ pub enum ReplyChunk {
|
||||
/// The human-readable activity label.
|
||||
label: String,
|
||||
},
|
||||
/// Canonical non-terminal progress/event emitted before `Final`.
|
||||
#[serde(rename_all = "camelCase")]
|
||||
Progress {
|
||||
/// Canonical event payload.
|
||||
progress: ReplyProgressDto,
|
||||
},
|
||||
/// The deterministic end-of-turn chunk carrying the aggregated final content.
|
||||
#[serde(rename_all = "camelCase")]
|
||||
Final {
|
||||
|
||||
Reference in New Issue
Block a user