114 lines
4.7 KiB
Rust
114 lines
4.7 KiB
Rust
use galaxyui::{AppContext, SingletonEntity};
|
|
use serde::Serialize;
|
|
|
|
use super::conversation::AIConversationId;
|
|
use super::{
|
|
AIAgentCitation, AIAgentExchangeId, EntrypointType, PassiveSuggestionTriggerType,
|
|
ServerOutputId,
|
|
};
|
|
use crate::ai::llms::LLMId;
|
|
use crate::server::telemetry::AgentModeCitation as CitationForTelemetry;
|
|
use crate::CloudModel;
|
|
|
|
pub trait ForTelemetry {
|
|
type Output;
|
|
|
|
fn for_telemetry(&self, ctx: &AppContext) -> Option<Self::Output>;
|
|
}
|
|
|
|
impl ForTelemetry for AIAgentCitation {
|
|
type Output = CitationForTelemetry;
|
|
|
|
fn for_telemetry(&self, ctx: &AppContext) -> Option<Self::Output> {
|
|
match self {
|
|
Self::WarpDriveObject { uid } => {
|
|
CloudModel::as_ref(ctx).get_by_uid(uid).map(|object| {
|
|
CitationForTelemetry::WarpDriveObject {
|
|
object_type: object.object_type(),
|
|
uid: object.uid(),
|
|
}
|
|
})
|
|
}
|
|
Self::WarpDocumentation { path } => {
|
|
Some(CitationForTelemetry::WarpDocs { page: path.clone() })
|
|
}
|
|
Self::WebPage { url } => Some(CitationForTelemetry::WebPage { url: url.clone() }),
|
|
Self::AgentMemory {
|
|
memory_store_id,
|
|
memory_id,
|
|
..
|
|
} => Some(CitationForTelemetry::AgentMemory {
|
|
memory_store_id: memory_store_id.clone(),
|
|
memory_id: memory_id.clone(),
|
|
}),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl EntrypointType {
|
|
pub fn entrypoint(&self) -> String {
|
|
match self {
|
|
Self::PromptSuggestion {
|
|
is_static,
|
|
is_coding,
|
|
} => match (is_static, is_coding) {
|
|
(true, true) => "PROMPT_SUGGESTION.CODING_STATIC".to_string(),
|
|
(true, false) => "PROMPT_SUGGESTION.STATIC".to_string(),
|
|
(false, true) => "PROMPT_SUGGESTION.CODING".to_string(),
|
|
(false, false) => "PROMPT_SUGGESTION.SIMPLE".to_string(),
|
|
},
|
|
Self::ZeroStateAgentModePromptSuggestion => {
|
|
"ZERO_STATE_AGENT_MODE_PROMPT_SUGGESTION".to_string()
|
|
}
|
|
Self::InitProjectRules => "INIT_PROJECT_RULES".to_string(),
|
|
Self::UserInitiated => "USER_INITIATED".to_string(),
|
|
Self::AgentInitiated => "AGENT_INITIATED".to_string(),
|
|
Self::TriggerPassiveSuggestion { trigger } => {
|
|
let trigger_name = match trigger {
|
|
Some(PassiveSuggestionTriggerType::FilesChanged) => "FILES_CHANGED",
|
|
Some(PassiveSuggestionTriggerType::CommandRun) => "COMMAND_RUN",
|
|
Some(PassiveSuggestionTriggerType::ShellCommandCompleted) => {
|
|
"SHELL_COMMAND_COMPLETED"
|
|
}
|
|
Some(PassiveSuggestionTriggerType::AgentResponseCompleted) => {
|
|
"AGENT_RESPONSE_COMPLETED"
|
|
}
|
|
None => "NONE",
|
|
};
|
|
format!("TRIGGER_SUGGEST_PROMPT.{trigger_name}")
|
|
}
|
|
Self::CloneRepository => "CLONE_REPOSITORY".to_string(),
|
|
Self::SharedSession => "SHARED_SESSION".to_string(),
|
|
Self::ResumeConversation => "RESUME_CONVERSATION".to_string(),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Default, Debug, Serialize)]
|
|
pub struct AIIdentifiers {
|
|
/// Useful for joining to client-side telemetry.
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub client_conversation_id: Option<AIConversationId>,
|
|
/// A stable ID to relate failures for the same underlying request.
|
|
#[serde(rename = "exchange_id", skip_serializing_if = "Option::is_none")]
|
|
pub client_exchange_id: Option<AIAgentExchangeId>,
|
|
/// Unique ID for this output coming from the AI API. Generated by the server. Only passed in
|
|
/// the initial response chunk.
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub server_output_id: Option<ServerOutputId>,
|
|
/// The conversation ID included in the response chunk.
|
|
///
|
|
/// Once this is set, it is never updated. That shouldn't be an issue because the conversation
|
|
/// ID is only expected to be passed in the initial response chunk.
|
|
///
|
|
/// Note that this conversation ID is server-scoped; it is _not_ related to the
|
|
/// `AIConversationId`, which is entirely a client-side abstraction.
|
|
///
|
|
/// This is mainly used for server-side logging and analytics.
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub server_conversation_id: Option<String>,
|
|
/// The ID of the model actually used to generate the output. This may differ from the requested model.
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub model_id: Option<LLMId>,
|
|
}
|