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
2 changes: 2 additions & 0 deletions crates/goose-server/src/openapi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ impl<'__s> ToSchema<'__s> for AnnotatedSchema {
super::routes::context::manage_context,
super::routes::session::list_sessions,
super::routes::session::get_session_history,
super::routes::session::update_session_recipe_parameters,
super::routes::schedule::create_schedule,
super::routes::schedule::list_schedules,
super::routes::schedule::delete_schedule,
Expand Down Expand Up @@ -420,6 +421,7 @@ impl<'__s> ToSchema<'__s> for AnnotatedSchema {
super::routes::context::ContextManageResponse,
super::routes::session::SessionListResponse,
super::routes::session::SessionHistoryResponse,
super::routes::session::UpdateSessionRecipeParametersRequest,
Message,
MessageContent,
MessageMetadata,
Expand Down
1 change: 1 addition & 0 deletions crates/goose-server/src/routes/agent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ async fn start_agent(
accumulated_output_tokens: Some(0),
extension_data: Default::default(),
recipe: payload.recipe,
recipe_parameters: None,
};

let session_path = match session::get_path(session::Identifier::Name(session_id.clone())) {
Expand Down
51 changes: 51 additions & 0 deletions crates/goose-server/src/routes/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ pub struct UpdateSessionMetadataRequest {
description: String,
}

#[derive(Deserialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct UpdateSessionRecipeParametersRequest {
/// Recipe parameter values entered by the user
recipe_parameters: HashMap<String, String>,
}

const MAX_DESCRIPTION_LENGTH: usize = 200;

#[derive(Serialize, ToSchema, Debug)]
Expand Down Expand Up @@ -300,6 +307,46 @@ async fn update_session_metadata(
Ok(StatusCode::OK)
}

#[utoipa::path(
put,
path = "/sessions/{session_id}/recipe_parameters",
request_body = UpdateSessionRecipeParametersRequest,
params(
("session_id" = String, Path, description = "Unique identifier for the session")
),
responses(
(status = 200, description = "Session recipe parameters updated successfully"),
(status = 401, description = "Unauthorized - Invalid or missing API key"),
(status = 404, description = "Session not found"),
(status = 500, description = "Internal server error")
),
security(
("api_key" = [])
),
tag = "Session Management"
)]
// Update session recipe parameters
async fn update_session_recipe_parameters(
Path(session_id): Path<String>,
Json(request): Json<UpdateSessionRecipeParametersRequest>,
) -> Result<StatusCode, StatusCode> {
let session_path = session::get_path(session::Identifier::Name(session_id.clone()))
.map_err(|_| StatusCode::BAD_REQUEST)?;

// Read current metadata
let mut metadata = session::read_metadata(&session_path).map_err(|_| StatusCode::NOT_FOUND)?;

// Update recipe parameters
metadata.recipe_parameters = Some(request.recipe_parameters);

// Save updated metadata
session::update_metadata(&session_path, &metadata)
.await
.map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?;

Ok(StatusCode::OK)
}

#[utoipa::path(
delete,
path = "/sessions/{session_id}/delete",
Expand Down Expand Up @@ -347,6 +394,10 @@ pub fn routes(state: Arc<AppState>) -> Router {
"/sessions/{session_id}/metadata",
put(update_session_metadata),
)
.route(
"/sessions/{session_id}/recipe_parameters",
put(update_session_recipe_parameters),
)
.with_state(state)
}

Expand Down
1 change: 1 addition & 0 deletions crates/goose/src/scheduler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1300,6 +1300,7 @@ async fn run_scheduled_job_internal(
accumulated_output_tokens: None,
extension_data: crate::session::ExtensionData::new(),
recipe: None,
recipe_parameters: None,
};
if let Err(e_fb) = crate::session::storage::save_messages_with_metadata(
&session_file_path,
Expand Down
5 changes: 5 additions & 0 deletions crates/goose/src/session/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ pub struct SessionMetadata {
pub extension_data: ExtensionData,

pub recipe: Option<Recipe>,
/// Recipe parameter values entered by the user
pub recipe_parameters: Option<std::collections::HashMap<String, String>>,
}

// Custom deserializer to handle old sessions without working_dir
Expand All @@ -95,6 +97,7 @@ impl<'de> Deserialize<'de> for SessionMetadata {
#[serde(default)]
extension_data: ExtensionData,
recipe: Option<Recipe>,
recipe_parameters: Option<std::collections::HashMap<String, String>>,
}

let helper = Helper::deserialize(deserializer)?;
Expand All @@ -118,6 +121,7 @@ impl<'de> Deserialize<'de> for SessionMetadata {
working_dir,
extension_data: helper.extension_data,
recipe: helper.recipe,
recipe_parameters: helper.recipe_parameters,
})
}
}
Expand All @@ -144,6 +148,7 @@ impl SessionMetadata {
accumulated_output_tokens: None,
extension_data: ExtensionData::new(),
recipe: None,
recipe_parameters: None,
}
}
}
Expand Down
71 changes: 71 additions & 0 deletions ui/desktop/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -1545,6 +1545,54 @@
]
}
},
"/sessions/{session_id}/recipe_parameters": {
"put": {
"tags": [
"Session Management"
],
"operationId": "update_session_recipe_parameters",
"parameters": [
{
"name": "session_id",
"in": "path",
"description": "Unique identifier for the session",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/UpdateSessionRecipeParametersRequest"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "Session recipe parameters updated successfully"
},
"401": {
"description": "Unauthorized - Invalid or missing API key"
},
"404": {
"description": "Session not found"
},
"500": {
"description": "Internal server error"
}
},
"security": [
{
"api_key": []
}
]
}
},
"/status": {
"get": {
"tags": [
Expand Down Expand Up @@ -3606,6 +3654,14 @@
],
"nullable": true
},
"recipe_parameters": {
"type": "object",
"description": "Recipe parameter values entered by the user",
"additionalProperties": {
"type": "string"
},
"nullable": true
},
"schedule_id": {
"type": "string",
"description": "ID of the schedule that triggered this session, if any",
Expand Down Expand Up @@ -4007,6 +4063,21 @@
}
}
},
"UpdateSessionRecipeParametersRequest": {
"type": "object",
"required": [
"recipeParameters"
],
"properties": {
"recipeParameters": {
"type": "object",
"description": "Recipe parameter values entered by the user",
"additionalProperties": {
"type": "string"
}
}
}
},
"UpsertConfigQuery": {
"type": "object",
"required": [
Expand Down
13 changes: 12 additions & 1 deletion ui/desktop/src/api/sdk.gen.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// This file is auto-generated by @hey-api/openapi-ts

import type { Options as ClientOptions, TDataShape, Client } from './client';
import type { AddSubRecipesData, AddSubRecipesResponses, AddSubRecipesErrors, ExtendPromptData, ExtendPromptResponses, ExtendPromptErrors, ResumeAgentData, ResumeAgentResponses, ResumeAgentErrors, UpdateSessionConfigData, UpdateSessionConfigResponses, UpdateSessionConfigErrors, StartAgentData, StartAgentResponses, StartAgentErrors, GetToolsData, GetToolsResponses, GetToolsErrors, UpdateAgentProviderData, UpdateAgentProviderResponses, UpdateAgentProviderErrors, UpdateRouterToolSelectorData, UpdateRouterToolSelectorResponses, UpdateRouterToolSelectorErrors, ReadAllConfigData, ReadAllConfigResponses, BackupConfigData, BackupConfigResponses, BackupConfigErrors, CreateCustomProviderData, CreateCustomProviderResponses, CreateCustomProviderErrors, RemoveCustomProviderData, RemoveCustomProviderResponses, RemoveCustomProviderErrors, GetExtensionsData, GetExtensionsResponses, GetExtensionsErrors, AddExtensionData, AddExtensionResponses, AddExtensionErrors, RemoveExtensionData, RemoveExtensionResponses, RemoveExtensionErrors, InitConfigData, InitConfigResponses, InitConfigErrors, UpsertPermissionsData, UpsertPermissionsResponses, UpsertPermissionsErrors, ProvidersData, ProvidersResponses, GetProviderModelsData, GetProviderModelsResponses, GetProviderModelsErrors, ReadConfigData, ReadConfigResponses, ReadConfigErrors, RecoverConfigData, RecoverConfigResponses, RecoverConfigErrors, RemoveConfigData, RemoveConfigResponses, RemoveConfigErrors, UpsertConfigData, UpsertConfigResponses, UpsertConfigErrors, ValidateConfigData, ValidateConfigResponses, ValidateConfigErrors, ConfirmPermissionData, ConfirmPermissionResponses, ConfirmPermissionErrors, ManageContextData, ManageContextResponses, ManageContextErrors, StartOpenrouterSetupData, StartOpenrouterSetupResponses, StartTetrateSetupData, StartTetrateSetupResponses, CreateRecipeData, CreateRecipeResponses, CreateRecipeErrors, DecodeRecipeData, DecodeRecipeResponses, DecodeRecipeErrors, DeleteRecipeData, DeleteRecipeResponses, DeleteRecipeErrors, EncodeRecipeData, EncodeRecipeResponses, EncodeRecipeErrors, ListRecipesData, ListRecipesResponses, ListRecipesErrors, ScanRecipeData, ScanRecipeResponses, CreateScheduleData, CreateScheduleResponses, CreateScheduleErrors, DeleteScheduleData, DeleteScheduleResponses, DeleteScheduleErrors, ListSchedulesData, ListSchedulesResponses, ListSchedulesErrors, UpdateScheduleData, UpdateScheduleResponses, UpdateScheduleErrors, InspectRunningJobData, InspectRunningJobResponses, InspectRunningJobErrors, KillRunningJobData, KillRunningJobResponses, PauseScheduleData, PauseScheduleResponses, PauseScheduleErrors, RunNowHandlerData, RunNowHandlerResponses, RunNowHandlerErrors, SessionsHandlerData, SessionsHandlerResponses, SessionsHandlerErrors, UnpauseScheduleData, UnpauseScheduleResponses, UnpauseScheduleErrors, ListSessionsData, ListSessionsResponses, ListSessionsErrors, GetSessionHistoryData, GetSessionHistoryResponses, GetSessionHistoryErrors, StatusData, StatusResponses } from './types.gen';
import type { AddSubRecipesData, AddSubRecipesResponses, AddSubRecipesErrors, ExtendPromptData, ExtendPromptResponses, ExtendPromptErrors, ResumeAgentData, ResumeAgentResponses, ResumeAgentErrors, UpdateSessionConfigData, UpdateSessionConfigResponses, UpdateSessionConfigErrors, StartAgentData, StartAgentResponses, StartAgentErrors, GetToolsData, GetToolsResponses, GetToolsErrors, UpdateAgentProviderData, UpdateAgentProviderResponses, UpdateAgentProviderErrors, UpdateRouterToolSelectorData, UpdateRouterToolSelectorResponses, UpdateRouterToolSelectorErrors, ReadAllConfigData, ReadAllConfigResponses, BackupConfigData, BackupConfigResponses, BackupConfigErrors, CreateCustomProviderData, CreateCustomProviderResponses, CreateCustomProviderErrors, RemoveCustomProviderData, RemoveCustomProviderResponses, RemoveCustomProviderErrors, GetExtensionsData, GetExtensionsResponses, GetExtensionsErrors, AddExtensionData, AddExtensionResponses, AddExtensionErrors, RemoveExtensionData, RemoveExtensionResponses, RemoveExtensionErrors, InitConfigData, InitConfigResponses, InitConfigErrors, UpsertPermissionsData, UpsertPermissionsResponses, UpsertPermissionsErrors, ProvidersData, ProvidersResponses, GetProviderModelsData, GetProviderModelsResponses, GetProviderModelsErrors, ReadConfigData, ReadConfigResponses, ReadConfigErrors, RecoverConfigData, RecoverConfigResponses, RecoverConfigErrors, RemoveConfigData, RemoveConfigResponses, RemoveConfigErrors, UpsertConfigData, UpsertConfigResponses, UpsertConfigErrors, ValidateConfigData, ValidateConfigResponses, ValidateConfigErrors, ConfirmPermissionData, ConfirmPermissionResponses, ConfirmPermissionErrors, ManageContextData, ManageContextResponses, ManageContextErrors, StartOpenrouterSetupData, StartOpenrouterSetupResponses, StartTetrateSetupData, StartTetrateSetupResponses, CreateRecipeData, CreateRecipeResponses, CreateRecipeErrors, DecodeRecipeData, DecodeRecipeResponses, DecodeRecipeErrors, DeleteRecipeData, DeleteRecipeResponses, DeleteRecipeErrors, EncodeRecipeData, EncodeRecipeResponses, EncodeRecipeErrors, ListRecipesData, ListRecipesResponses, ListRecipesErrors, ScanRecipeData, ScanRecipeResponses, CreateScheduleData, CreateScheduleResponses, CreateScheduleErrors, DeleteScheduleData, DeleteScheduleResponses, DeleteScheduleErrors, ListSchedulesData, ListSchedulesResponses, ListSchedulesErrors, UpdateScheduleData, UpdateScheduleResponses, UpdateScheduleErrors, InspectRunningJobData, InspectRunningJobResponses, InspectRunningJobErrors, KillRunningJobData, KillRunningJobResponses, PauseScheduleData, PauseScheduleResponses, PauseScheduleErrors, RunNowHandlerData, RunNowHandlerResponses, RunNowHandlerErrors, SessionsHandlerData, SessionsHandlerResponses, SessionsHandlerErrors, UnpauseScheduleData, UnpauseScheduleResponses, UnpauseScheduleErrors, ListSessionsData, ListSessionsResponses, ListSessionsErrors, GetSessionHistoryData, GetSessionHistoryResponses, GetSessionHistoryErrors, UpdateSessionRecipeParametersData, UpdateSessionRecipeParametersResponses, UpdateSessionRecipeParametersErrors, StatusData, StatusResponses } from './types.gen';
import { client as _heyApiClient } from './client.gen';

export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = ClientOptions<TData, ThrowOnError> & {
Expand Down Expand Up @@ -431,6 +431,17 @@ export const getSessionHistory = <ThrowOnError extends boolean = false>(options:
});
};

export const updateSessionRecipeParameters = <ThrowOnError extends boolean = false>(options: Options<UpdateSessionRecipeParametersData, ThrowOnError>) => {
return (options.client ?? _heyApiClient).put<UpdateSessionRecipeParametersResponses, UpdateSessionRecipeParametersErrors, ThrowOnError>({
url: '/sessions/{session_id}/recipe_parameters',
...options,
headers: {
'Content-Type': 'application/json',
...options.headers
}
});
};

export const status = <ThrowOnError extends boolean = false>(options?: Options<StatusData, ThrowOnError>) => {
return (options?.client ?? _heyApiClient).get<StatusResponses, unknown, ThrowOnError>({
url: '/status',
Expand Down
49 changes: 49 additions & 0 deletions ui/desktop/src/api/types.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,12 @@ export type SessionMetadata = {
*/
output_tokens?: number | null;
recipe?: Recipe | null;
/**
* Recipe parameter values entered by the user
*/
recipe_parameters?: {
[key: string]: string;
} | null;
/**
* ID of the schedule that triggered this session, if any
*/
Expand Down Expand Up @@ -926,6 +932,15 @@ export type UpdateScheduleRequest = {
cron: string;
};

export type UpdateSessionRecipeParametersRequest = {
/**
* Recipe parameter values entered by the user
*/
recipeParameters: {
[key: string]: string;
};
};

export type UpsertConfigQuery = {
is_secret: boolean;
key: string;
Expand Down Expand Up @@ -2176,6 +2191,40 @@ export type GetSessionHistoryResponses = {

export type GetSessionHistoryResponse = GetSessionHistoryResponses[keyof GetSessionHistoryResponses];

export type UpdateSessionRecipeParametersData = {
body: UpdateSessionRecipeParametersRequest;
path: {
/**
* Unique identifier for the session
*/
session_id: string;
};
query?: never;
url: '/sessions/{session_id}/recipe_parameters';
};

export type UpdateSessionRecipeParametersErrors = {
/**
* Unauthorized - Invalid or missing API key
*/
401: unknown;
/**
* Session not found
*/
404: unknown;
/**
* Internal server error
*/
500: unknown;
};

export type UpdateSessionRecipeParametersResponses = {
/**
* Session recipe parameters updated successfully
*/
200: unknown;
};

export type StatusData = {
body?: never;
path?: never;
Expand Down
Loading