Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion crates/goose-server/src/openapi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use goose::conversation::Conversation;
use goose::model::ModelConfig;
use goose::permission::permission_confirmation::PrincipalType;
use goose::providers::base::{ConfigKey, ModelInfo, ProviderMetadata, ProviderType};
use goose::session::{Session, SessionInsights, SessionType};
use goose::session::{Session, SessionInsights, SessionType, SystemInfo};
use rmcp::model::{
Annotations, Content, EmbeddedResource, Icon, ImageContent, JsonObject, RawAudioContent,
RawEmbeddedResource, RawImageContent, RawResource, RawTextContent, ResourceContents, Role,
Expand Down Expand Up @@ -327,6 +327,7 @@ derive_utoipa!(Icon as IconSchema);
#[openapi(
paths(
super::routes::status::status,
super::routes::status::system_info,
super::routes::status::diagnostics,
super::routes::mcp_ui_proxy::mcp_ui_proxy,
super::routes::config_management::backup_config,
Expand Down Expand Up @@ -483,6 +484,7 @@ derive_utoipa!(Icon as IconSchema);
Session,
SessionInsights,
SessionType,
SystemInfo,
Conversation,
IconSchema,
goose::session::extension_data::ExtensionData,
Expand Down
14 changes: 12 additions & 2 deletions crates/goose-server/src/routes/status.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use axum::body::Body;
use axum::http::HeaderValue;
use axum::response::IntoResponse;
use axum::{extract::Path, http::StatusCode, routing::get, Router};
use goose::session::generate_diagnostics;
use axum::{extract::Path, http::StatusCode, routing::get, Json, Router};
use goose::session::{generate_diagnostics, get_system_info, SystemInfo};

#[utoipa::path(get, path = "/status",
responses(
Expand All @@ -13,6 +13,15 @@ async fn status() -> String {
"ok".to_string()
}

#[utoipa::path(get, path = "/system_info",
responses(
(status = 200, description = "System information", body = SystemInfo),
)
)]
async fn system_info() -> Json<SystemInfo> {
Json(get_system_info())
}

#[utoipa::path(get, path = "/diagnostics/{session_id}",
responses(
(status = 200, description = "Diagnostics zip file", content_type = "application/zip", body = Vec<u8>),
Expand Down Expand Up @@ -42,5 +51,6 @@ async fn diagnostics(Path(session_id): Path<String>) -> impl IntoResponse {
pub fn routes() -> Router {
Router::new()
.route("/status", get(status))
.route("/system_info", get(system_info))
.route("/diagnostics/{session_id}", get(diagnostics))
}
77 changes: 64 additions & 13 deletions crates/goose/src/session/diagnostics.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,81 @@
use crate::config::base::Config;
use crate::config::extensions::get_enabled_extensions;
use crate::config::paths::Paths;
use crate::providers::utils::LOGS_TO_KEEP;
use crate::session::SessionManager;
use serde::{Deserialize, Serialize};
use std::fs::{self};
use std::io::Cursor;
use std::io::Write;
use utoipa::ToSchema;
use zip::write::FileOptions;
use zip::ZipWriter;

#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct SystemInfo {
pub app_version: String,
pub os: String,
pub os_version: String,
pub architecture: String,
pub provider: Option<String>,
pub model: Option<String>,
pub enabled_extensions: Vec<String>,
}

impl SystemInfo {
pub fn collect() -> Self {
let config = Config::global();
let provider = config.get_goose_provider().ok();
let model = config.get_goose_model().ok();
let enabled_extensions = get_enabled_extensions()
.into_iter()
.map(|ext| ext.name().to_string())
.collect();

Self {
app_version: env!("CARGO_PKG_VERSION").to_string(),
os: std::env::consts::OS.to_string(),
os_version: sys_info::os_release().unwrap_or_else(|_| "unknown".to_string()),
architecture: std::env::consts::ARCH.to_string(),
provider,
model,
enabled_extensions,
}
}

pub fn to_text(&self) -> String {
format!(
"App Version: {}\n\
OS: {}\n\
OS Version: {}\n\
Architecture: {}\n\
Provider: {}\n\
Model: {}\n\
Enabled Extensions: {}\n\
Timestamp: {}\n",
self.app_version,
self.os,
self.os_version,
self.architecture,
self.provider.as_deref().unwrap_or("unknown"),
self.model.as_deref().unwrap_or("unknown"),
self.enabled_extensions.join(", "),
chrono::Utc::now().to_rfc3339()
)
}
}

pub fn get_system_info() -> SystemInfo {
SystemInfo::collect()
}

pub async fn generate_diagnostics(session_id: &str) -> anyhow::Result<Vec<u8>> {
let logs_dir = Paths::in_state_dir("logs");
let config_dir = Paths::config_dir();
let config_path = config_dir.join("config.yaml");
let data_dir = Paths::data_dir();

let system_info = format!(
"App Version: {}\n\
OS: {}\n\
OS Version: {}\n\
Architecture: {}\n\
Timestamp: {}\n",
env!("CARGO_PKG_VERSION"),
std::env::consts::OS,
sys_info::os_release().unwrap_or_else(|_| "unknown".to_string()),
std::env::consts::ARCH,
chrono::Utc::now().to_rfc3339()
);
let system_info = SystemInfo::collect();

let mut buffer = Vec::new();
{
Expand Down Expand Up @@ -55,7 +106,7 @@ pub async fn generate_diagnostics(session_id: &str) -> anyhow::Result<Vec<u8>> {
}

zip.start_file("system.txt", options)?;
zip.write_all(system_info.as_bytes())?;
zip.write_all(system_info.to_text().as_bytes())?;

let schedule_json = data_dir.join("schedule.json");
if schedule_json.exists() {
Expand Down
2 changes: 1 addition & 1 deletion crates/goose/src/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ pub mod extension_data;
mod legacy;
pub mod session_manager;

pub use diagnostics::generate_diagnostics;
pub use diagnostics::{generate_diagnostics, get_system_info, SystemInfo};
pub use extension_data::{EnabledExtensionsState, ExtensionData, ExtensionState, TodoState};
pub use session_manager::{Session, SessionInsights, SessionManager, SessionType};
58 changes: 58 additions & 0 deletions ui/desktop/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -2531,6 +2531,26 @@
}
}
},
"/system_info": {
"get": {
"tags": [
"super::routes::status"
],
"operationId": "system_info",
"responses": {
"200": {
"description": "System information",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/SystemInfo"
}
}
}
}
}
}
},
"/telemetry/event": {
"post": {
"tags": [
Expand Down Expand Up @@ -5711,6 +5731,44 @@
"propertyName": "type"
}
},
"SystemInfo": {
"type": "object",
"required": [
"app_version",
"os",
"os_version",
"architecture",
"enabled_extensions"
],
"properties": {
"app_version": {
"type": "string"
},
"architecture": {
"type": "string"
},
"enabled_extensions": {
"type": "array",
"items": {
"type": "string"
}
},
"model": {
"type": "string",
"nullable": true
},
"os": {
"type": "string"
},
"os_version": {
"type": "string"
},
"provider": {
"type": "string",
"nullable": true
}
}
},
"SystemNotificationContent": {
"type": "object",
"required": [
Expand Down
4 changes: 3 additions & 1 deletion ui/desktop/src/api/sdk.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import type { Client, Options as Options2, TDataShape } from './client';
import { client } from './client.gen';
import type { AddExtensionData, AddExtensionErrors, AddExtensionResponses, AgentAddExtensionData, AgentAddExtensionErrors, AgentAddExtensionResponses, AgentRemoveExtensionData, AgentRemoveExtensionErrors, AgentRemoveExtensionResponses, BackupConfigData, BackupConfigErrors, BackupConfigResponses, CallToolData, CallToolErrors, CallToolResponses, CheckProviderData, ConfirmToolActionData, ConfirmToolActionErrors, ConfirmToolActionResponses, CreateCustomProviderData, CreateCustomProviderErrors, CreateCustomProviderResponses, CreateRecipeData, CreateRecipeErrors, CreateRecipeResponses, CreateScheduleData, CreateScheduleErrors, CreateScheduleResponses, DecodeRecipeData, DecodeRecipeErrors, DecodeRecipeResponses, DeleteRecipeData, DeleteRecipeErrors, DeleteRecipeResponses, DeleteScheduleData, DeleteScheduleErrors, DeleteScheduleResponses, DeleteSessionData, DeleteSessionErrors, DeleteSessionResponses, DetectProviderData, DetectProviderErrors, DetectProviderResponses, DiagnosticsData, DiagnosticsErrors, DiagnosticsResponses, EditMessageData, EditMessageErrors, EditMessageResponses, EncodeRecipeData, EncodeRecipeErrors, EncodeRecipeResponses, ExportSessionData, ExportSessionErrors, ExportSessionResponses, GetCustomProviderData, GetCustomProviderErrors, GetCustomProviderResponses, GetExtensionsData, GetExtensionsErrors, GetExtensionsResponses, GetPricingData, GetPricingResponses, GetProviderModelsData, GetProviderModelsErrors, GetProviderModelsResponses, GetSessionData, GetSessionErrors, GetSessionExtensionsData, GetSessionExtensionsErrors, GetSessionExtensionsResponses, GetSessionInsightsData, GetSessionInsightsErrors, GetSessionInsightsResponses, GetSessionResponses, GetSlashCommandsData, GetSlashCommandsResponses, GetToolsData, GetToolsErrors, GetToolsResponses, GetTunnelStatusData, GetTunnelStatusResponses, ImportSessionData, ImportSessionErrors, ImportSessionResponses, InitConfigData, InitConfigErrors, InitConfigResponses, InspectRunningJobData, InspectRunningJobErrors, InspectRunningJobResponses, KillRunningJobData, KillRunningJobResponses, ListRecipesData, ListRecipesErrors, ListRecipesResponses, ListSchedulesData, ListSchedulesErrors, ListSchedulesResponses, ListSessionsData, ListSessionsErrors, ListSessionsResponses, McpUiProxyData, McpUiProxyErrors, McpUiProxyResponses, ParseRecipeData, ParseRecipeErrors, ParseRecipeResponses, PauseScheduleData, PauseScheduleErrors, PauseScheduleResponses, ProvidersData, ProvidersResponses, ReadAllConfigData, ReadAllConfigResponses, ReadConfigData, ReadConfigErrors, ReadConfigResponses, ReadResourceData, ReadResourceErrors, ReadResourceResponses, RecipeToYamlData, RecipeToYamlErrors, RecipeToYamlResponses, RecoverConfigData, RecoverConfigErrors, RecoverConfigResponses, RemoveConfigData, RemoveConfigErrors, RemoveConfigResponses, RemoveCustomProviderData, RemoveCustomProviderErrors, RemoveCustomProviderResponses, RemoveExtensionData, RemoveExtensionErrors, RemoveExtensionResponses, ReplyData, ReplyErrors, ReplyResponses, RestartAgentData, RestartAgentErrors, RestartAgentResponses, ResumeAgentData, ResumeAgentErrors, ResumeAgentResponses, RunNowHandlerData, RunNowHandlerErrors, RunNowHandlerResponses, SaveRecipeData, SaveRecipeErrors, SaveRecipeResponses, ScanRecipeData, ScanRecipeResponses, ScheduleRecipeData, ScheduleRecipeErrors, ScheduleRecipeResponses, SendTelemetryEventData, SendTelemetryEventResponses, SessionsHandlerData, SessionsHandlerErrors, SessionsHandlerResponses, SetConfigProviderData, SetRecipeSlashCommandData, SetRecipeSlashCommandErrors, SetRecipeSlashCommandResponses, StartAgentData, StartAgentErrors, StartAgentResponses, StartOpenrouterSetupData, StartOpenrouterSetupResponses, StartTetrateSetupData, StartTetrateSetupResponses, StartTunnelData, StartTunnelErrors, StartTunnelResponses, StatusData, StatusResponses, StopTunnelData, StopTunnelErrors, StopTunnelResponses, UnpauseScheduleData, UnpauseScheduleErrors, UnpauseScheduleResponses, UpdateAgentProviderData, UpdateAgentProviderErrors, UpdateAgentProviderResponses, UpdateCustomProviderData, UpdateCustomProviderErrors, UpdateCustomProviderResponses, UpdateFromSessionData, UpdateFromSessionErrors, UpdateFromSessionResponses, UpdateScheduleData, UpdateScheduleErrors, UpdateScheduleResponses, UpdateSessionNameData, UpdateSessionNameErrors, UpdateSessionNameResponses, UpdateSessionUserRecipeValuesData, UpdateSessionUserRecipeValuesErrors, UpdateSessionUserRecipeValuesResponses, UpdateWorkingDirData, UpdateWorkingDirErrors, UpdateWorkingDirResponses, UpsertConfigData, UpsertConfigErrors, UpsertConfigResponses, UpsertPermissionsData, UpsertPermissionsErrors, UpsertPermissionsResponses, ValidateConfigData, ValidateConfigErrors, ValidateConfigResponses } from './types.gen';
import type { AddExtensionData, AddExtensionErrors, AddExtensionResponses, AgentAddExtensionData, AgentAddExtensionErrors, AgentAddExtensionResponses, AgentRemoveExtensionData, AgentRemoveExtensionErrors, AgentRemoveExtensionResponses, BackupConfigData, BackupConfigErrors, BackupConfigResponses, CallToolData, CallToolErrors, CallToolResponses, CheckProviderData, ConfirmToolActionData, ConfirmToolActionErrors, ConfirmToolActionResponses, CreateCustomProviderData, CreateCustomProviderErrors, CreateCustomProviderResponses, CreateRecipeData, CreateRecipeErrors, CreateRecipeResponses, CreateScheduleData, CreateScheduleErrors, CreateScheduleResponses, DecodeRecipeData, DecodeRecipeErrors, DecodeRecipeResponses, DeleteRecipeData, DeleteRecipeErrors, DeleteRecipeResponses, DeleteScheduleData, DeleteScheduleErrors, DeleteScheduleResponses, DeleteSessionData, DeleteSessionErrors, DeleteSessionResponses, DetectProviderData, DetectProviderErrors, DetectProviderResponses, DiagnosticsData, DiagnosticsErrors, DiagnosticsResponses, EditMessageData, EditMessageErrors, EditMessageResponses, EncodeRecipeData, EncodeRecipeErrors, EncodeRecipeResponses, ExportSessionData, ExportSessionErrors, ExportSessionResponses, GetCustomProviderData, GetCustomProviderErrors, GetCustomProviderResponses, GetExtensionsData, GetExtensionsErrors, GetExtensionsResponses, GetPricingData, GetPricingResponses, GetProviderModelsData, GetProviderModelsErrors, GetProviderModelsResponses, GetSessionData, GetSessionErrors, GetSessionExtensionsData, GetSessionExtensionsErrors, GetSessionExtensionsResponses, GetSessionInsightsData, GetSessionInsightsErrors, GetSessionInsightsResponses, GetSessionResponses, GetSlashCommandsData, GetSlashCommandsResponses, GetToolsData, GetToolsErrors, GetToolsResponses, GetTunnelStatusData, GetTunnelStatusResponses, ImportSessionData, ImportSessionErrors, ImportSessionResponses, InitConfigData, InitConfigErrors, InitConfigResponses, InspectRunningJobData, InspectRunningJobErrors, InspectRunningJobResponses, KillRunningJobData, KillRunningJobResponses, ListRecipesData, ListRecipesErrors, ListRecipesResponses, ListSchedulesData, ListSchedulesErrors, ListSchedulesResponses, ListSessionsData, ListSessionsErrors, ListSessionsResponses, McpUiProxyData, McpUiProxyErrors, McpUiProxyResponses, ParseRecipeData, ParseRecipeErrors, ParseRecipeResponses, PauseScheduleData, PauseScheduleErrors, PauseScheduleResponses, ProvidersData, ProvidersResponses, ReadAllConfigData, ReadAllConfigResponses, ReadConfigData, ReadConfigErrors, ReadConfigResponses, ReadResourceData, ReadResourceErrors, ReadResourceResponses, RecipeToYamlData, RecipeToYamlErrors, RecipeToYamlResponses, RecoverConfigData, RecoverConfigErrors, RecoverConfigResponses, RemoveConfigData, RemoveConfigErrors, RemoveConfigResponses, RemoveCustomProviderData, RemoveCustomProviderErrors, RemoveCustomProviderResponses, RemoveExtensionData, RemoveExtensionErrors, RemoveExtensionResponses, ReplyData, ReplyErrors, ReplyResponses, RestartAgentData, RestartAgentErrors, RestartAgentResponses, ResumeAgentData, ResumeAgentErrors, ResumeAgentResponses, RunNowHandlerData, RunNowHandlerErrors, RunNowHandlerResponses, SaveRecipeData, SaveRecipeErrors, SaveRecipeResponses, ScanRecipeData, ScanRecipeResponses, ScheduleRecipeData, ScheduleRecipeErrors, ScheduleRecipeResponses, SendTelemetryEventData, SendTelemetryEventResponses, SessionsHandlerData, SessionsHandlerErrors, SessionsHandlerResponses, SetConfigProviderData, SetRecipeSlashCommandData, SetRecipeSlashCommandErrors, SetRecipeSlashCommandResponses, StartAgentData, StartAgentErrors, StartAgentResponses, StartOpenrouterSetupData, StartOpenrouterSetupResponses, StartTetrateSetupData, StartTetrateSetupResponses, StartTunnelData, StartTunnelErrors, StartTunnelResponses, StatusData, StatusResponses, StopTunnelData, StopTunnelErrors, StopTunnelResponses, SystemInfoData, SystemInfoResponses, UnpauseScheduleData, UnpauseScheduleErrors, UnpauseScheduleResponses, UpdateAgentProviderData, UpdateAgentProviderErrors, UpdateAgentProviderResponses, UpdateCustomProviderData, UpdateCustomProviderErrors, UpdateCustomProviderResponses, UpdateFromSessionData, UpdateFromSessionErrors, UpdateFromSessionResponses, UpdateScheduleData, UpdateScheduleErrors, UpdateScheduleResponses, UpdateSessionNameData, UpdateSessionNameErrors, UpdateSessionNameResponses, UpdateSessionUserRecipeValuesData, UpdateSessionUserRecipeValuesErrors, UpdateSessionUserRecipeValuesResponses, UpdateWorkingDirData, UpdateWorkingDirErrors, UpdateWorkingDirResponses, UpsertConfigData, UpsertConfigErrors, UpsertConfigResponses, UpsertPermissionsData, UpsertPermissionsErrors, UpsertPermissionsResponses, ValidateConfigData, ValidateConfigErrors, ValidateConfigResponses } from './types.gen';

export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = Options2<TData, ThrowOnError> & {
/**
Expand Down Expand Up @@ -435,6 +435,8 @@ export const updateSessionUserRecipeValues = <ThrowOnError extends boolean = fal

export const status = <ThrowOnError extends boolean = false>(options?: Options<StatusData, ThrowOnError>) => (options?.client ?? client).get<StatusResponses, unknown, ThrowOnError>({ url: '/status', ...options });

export const systemInfo = <ThrowOnError extends boolean = false>(options?: Options<SystemInfoData, ThrowOnError>) => (options?.client ?? client).get<SystemInfoResponses, unknown, ThrowOnError>({ url: '/system_info', ...options });

export const sendTelemetryEvent = <ThrowOnError extends boolean = false>(options: Options<SendTelemetryEventData, ThrowOnError>) => (options.client ?? client).post<SendTelemetryEventResponses, unknown, ThrowOnError>({
url: '/telemetry/event',
...options,
Expand Down
26 changes: 26 additions & 0 deletions ui/desktop/src/api/types.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -988,6 +988,16 @@ export type SuccessCheck = {
type: 'Shell';
};

export type SystemInfo = {
app_version: string;
architecture: string;
enabled_extensions: Array<string>;
model?: string | null;
os: string;
os_version: string;
provider?: string | null;
};

export type SystemNotificationContent = {
msg: string;
notificationType: SystemNotificationType;
Expand Down Expand Up @@ -3137,6 +3147,22 @@ export type StatusResponses = {

export type StatusResponse = StatusResponses[keyof StatusResponses];

export type SystemInfoData = {
body?: never;
path?: never;
query?: never;
url: '/system_info';
};

export type SystemInfoResponses = {
/**
* System information
*/
200: SystemInfo;
};

export type SystemInfoResponse = SystemInfoResponses[keyof SystemInfoResponses];

export type SendTelemetryEventData = {
body: TelemetryEventRequest;
path?: never;
Expand Down
2 changes: 1 addition & 1 deletion ui/desktop/src/components/ChatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { DroppedFile, useFileDrop } from '../hooks/useFileDrop';
import { Recipe } from '../recipe';
import MessageQueue from './MessageQueue';
import { detectInterruption } from '../utils/interruptionDetector';
import { DiagnosticsModal } from './ui/DownloadDiagnostics';
import { DiagnosticsModal } from './ui/Diagnostics';
import { getSession, Message } from '../api';
import CreateRecipeFromSessionModal from './recipes/CreateRecipeFromSessionModal';
import CreateEditRecipeModal from './recipes/CreateEditRecipeModal';
Expand Down
Loading
Loading