diff --git a/crates/goose-server/src/routes/session_events.rs b/crates/goose-server/src/routes/session_events.rs index 0d3221e15f..a0492642d3 100644 --- a/crates/goose-server/src/routes/session_events.rs +++ b/crates/goose-server/src/routes/session_events.rs @@ -35,8 +35,6 @@ pub struct SessionReplyRequest { pub user_message: Message, #[serde(default)] pub override_conversation: Option>, - pub recipe_name: Option, - pub recipe_version: Option, } #[derive(Debug, Serialize, utoipa::ToSchema)] @@ -287,7 +285,7 @@ pub async fn session_reply( } // Validate session exists before allocating a bus/registering work - state + let session_data = state .session_manager() .get_session(&session_id, false) .await @@ -302,17 +300,12 @@ pub async fn session_reply( "Session started" ); - if let Some(recipe_name) = request.recipe_name.clone() { + if let Some(ref recipe) = session_data.recipe { if state.mark_recipe_run_if_absent(&session_id).await { - let recipe_version = request - .recipe_version - .clone() - .unwrap_or_else(|| "unknown".to_string()); - tracing::info!( monotonic_counter.goose.recipe_runs = 1, - recipe_name = %recipe_name, - recipe_version = %recipe_version, + recipe_name = %recipe.title, + recipe_version = %recipe.version, session_type = "app", interface = "ui", "Recipe execution started" diff --git a/crates/goose/src/scheduler.rs b/crates/goose/src/scheduler.rs index 9c6793c646..b43a5fdbdb 100644 --- a/crates/goose/src/scheduler.rs +++ b/crates/goose/src/scheduler.rs @@ -839,8 +839,31 @@ async fn execute_job( } drop(jobs_guard); - #[cfg(feature = "telemetry")] let start_time = std::time::Instant::now(); + + let recipe_display_name = recipe_path + .file_name() + .and_then(|name| name.to_str()) + .unwrap_or(&job.id); + let recipe_version = recipe.version.clone(); + + tracing::info!( + monotonic_counter.goose.session_starts = 1, + session_type = "schedule", + interface = "scheduler", + interactive = false, + "Scheduled session started" + ); + + tracing::info!( + monotonic_counter.goose.recipe_runs = 1, + recipe_name = %recipe_display_name, + recipe_version = %recipe_version, + session_type = "schedule", + interface = "scheduler", + "Recipe execution started" + ); + #[cfg(feature = "telemetry")] tokio::spawn(async move { let mut props = HashMap::new(); @@ -884,6 +907,7 @@ async fn execute_job( use futures::StreamExt; let mut stream = std::pin::pin!(stream); + let mut stream_error = false; while let Some(message_result) = stream.next().await { tokio::task::yield_now().await; @@ -897,6 +921,7 @@ async fn execute_job( Ok(_) => {} Err(e) => { tracing::error!("Error in agent stream: {}", e); + stream_error = true; break; } } @@ -911,6 +936,45 @@ async fn execute_job( .apply() .await?; + { + let session_duration = start_time.elapsed(); + let exit_type = if stream_error { "error" } else { "normal" }; + let (total_tokens, message_count) = agent + .config + .session_manager + .get_session(&session.id, false) + .await + .map(|s| (s.total_tokens.unwrap_or(0), s.message_count)) + .unwrap_or((0, 0)); + + tracing::info!( + monotonic_counter.goose.session_completions = 1, + session_type = "schedule", + interface = "scheduler", + exit_type, + duration_ms = session_duration.as_millis() as u64, + total_tokens, + message_count, + "Session completed" + ); + + tracing::info!( + monotonic_counter.goose.session_duration_ms = session_duration.as_millis() as u64, + session_type = "schedule", + interface = "scheduler", + "Session duration" + ); + + if total_tokens > 0 { + tracing::info!( + monotonic_counter.goose.session_tokens = total_tokens, + session_type = "schedule", + interface = "scheduler", + "Session tokens" + ); + } + } + #[cfg(feature = "telemetry")] { let duration_secs = start_time.elapsed().as_secs(); diff --git a/ui/desktop/openapi.json b/ui/desktop/openapi.json index a684adaae4..3498c0ddbc 100644 --- a/ui/desktop/openapi.json +++ b/ui/desktop/openapi.json @@ -7944,14 +7944,6 @@ }, "nullable": true }, - "recipe_name": { - "type": "string", - "nullable": true - }, - "recipe_version": { - "type": "string", - "nullable": true - }, "request_id": { "type": "string", "description": "Client-generated UUIDv7 identifying this request." diff --git a/ui/desktop/src/api/types.gen.ts b/ui/desktop/src/api/types.gen.ts index e8c281dc49..6747db7dc9 100644 --- a/ui/desktop/src/api/types.gen.ts +++ b/ui/desktop/src/api/types.gen.ts @@ -1295,8 +1295,6 @@ export type SessionListResponse = { export type SessionReplyRequest = { override_conversation?: Array | null; - recipe_name?: string | null; - recipe_version?: string | null; /** * Client-generated UUIDv7 identifying this request. */ diff --git a/ui/desktop/src/hooks/useChatStream.ts b/ui/desktop/src/hooks/useChatStream.ts index 0121eaf5f8..e2eb68b3fc 100644 --- a/ui/desktop/src/hooks/useChatStream.ts +++ b/ui/desktop/src/hooks/useChatStream.ts @@ -583,8 +583,6 @@ export function useChatStream({ userMessage: Message, currentMessages: Message[], overrideConversation?: Message[], - recipeName?: string, - recipeVersion?: string, ) => { const requestId = uuidv7(); const abortController = new AbortController(); @@ -624,8 +622,6 @@ export function useChatStream({ request_id: requestId, user_message: userMessage, override_conversation: overrideConversation, - recipe_name: recipeName, - recipe_version: recipeVersion, }, signal: abortController.signal, throwOnError: true,