diff --git a/db/migrate/20250714104358_add_response_guidelines_and_guardrails_to_captain_assistants.rb b/db/migrate/20250714104358_add_response_guidelines_and_guardrails_to_captain_assistants.rb new file mode 100644 index 000000000..3c048b8f7 --- /dev/null +++ b/db/migrate/20250714104358_add_response_guidelines_and_guardrails_to_captain_assistants.rb @@ -0,0 +1,6 @@ +class AddResponseGuidelinesAndGuardrailsToCaptainAssistants < ActiveRecord::Migration[7.1] + def change + add_column :captain_assistants, :response_guidelines, :jsonb, default: [] + add_column :captain_assistants, :guardrails, :jsonb, default: [] + end +end diff --git a/db/schema.rb b/db/schema.rb index 837eb58bd..1806ab23f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2025_07_10_145708) do +ActiveRecord::Schema[7.1].define(version: 2025_07_14_104358) do # These extensions should be enabled to support this database enable_extension "pg_stat_statements" enable_extension "pg_trgm" @@ -277,6 +277,8 @@ ActiveRecord::Schema[7.1].define(version: 2025_07_10_145708) do t.datetime "created_at", null: false t.datetime "updated_at", null: false t.jsonb "config", default: {}, null: false + t.jsonb "response_guidelines", default: [] + t.jsonb "guardrails", default: [] t.index ["account_id"], name: "index_captain_assistants_on_account_id" end diff --git a/enterprise/app/controllers/api/v1/accounts/captain/assistants_controller.rb b/enterprise/app/controllers/api/v1/accounts/captain/assistants_controller.rb index ec8e8e653..37890fade 100644 --- a/enterprise/app/controllers/api/v1/accounts/captain/assistants_controller.rb +++ b/enterprise/app/controllers/api/v1/accounts/captain/assistants_controller.rb @@ -43,12 +43,18 @@ class Api::V1::Accounts::Captain::AssistantsController < Api::V1::Accounts::Base end def assistant_params - params.require(:assistant).permit(:name, :description, - config: [ - :product_name, :feature_faq, :feature_memory, - :welcome_message, :handoff_message, :resolution_message, - :instructions, :temperature - ]) + permitted = params.require(:assistant).permit(:name, :description, + config: [ + :product_name, :feature_faq, :feature_memory, + :welcome_message, :handoff_message, :resolution_message, + :instructions, :temperature + ]) + + # Handle array parameters separately to allow partial updates + permitted[:response_guidelines] = params[:assistant][:response_guidelines] if params[:assistant][:response_guidelines].present? + permitted[:guardrails] = params[:assistant][:guardrails] if params[:assistant][:guardrails].present? + + permitted end def playground_params diff --git a/enterprise/app/models/captain/assistant.rb b/enterprise/app/models/captain/assistant.rb index 8f1227231..4ce4c4afd 100644 --- a/enterprise/app/models/captain/assistant.rb +++ b/enterprise/app/models/captain/assistant.rb @@ -2,13 +2,15 @@ # # Table name: captain_assistants # -# id :bigint not null, primary key -# config :jsonb not null -# description :string -# name :string not null -# created_at :datetime not null -# updated_at :datetime not null -# account_id :bigint not null +# id :bigint not null, primary key +# config :jsonb not null +# description :string +# guardrails :jsonb +# name :string not null +# response_guidelines :jsonb +# created_at :datetime not null +# updated_at :datetime not null +# account_id :bigint not null # # Indexes # diff --git a/enterprise/app/views/api/v1/models/captain/_assistant.json.jbuilder b/enterprise/app/views/api/v1/models/captain/_assistant.json.jbuilder index 80008423c..d597ed220 100644 --- a/enterprise/app/views/api/v1/models/captain/_assistant.json.jbuilder +++ b/enterprise/app/views/api/v1/models/captain/_assistant.json.jbuilder @@ -2,6 +2,8 @@ json.account_id resource.account_id json.config resource.config json.created_at resource.created_at.to_i json.description resource.description +json.guardrails resource.guardrails json.id resource.id json.name resource.name +json.response_guidelines resource.response_guidelines json.updated_at resource.updated_at.to_i diff --git a/spec/enterprise/controllers/api/v1/accounts/captain/assistants_controller_spec.rb b/spec/enterprise/controllers/api/v1/accounts/captain/assistants_controller_spec.rb index 80be6f30f..b6418c8ec 100644 --- a/spec/enterprise/controllers/api/v1/accounts/captain/assistants_controller_spec.rb +++ b/spec/enterprise/controllers/api/v1/accounts/captain/assistants_controller_spec.rb @@ -62,7 +62,9 @@ RSpec.describe 'Api::V1::Accounts::Captain::Assistants', type: :request do { assistant: { name: 'New Assistant', - description: 'Assistant Description' + description: 'Assistant Description', + response_guidelines: ['Be helpful', 'Be concise'], + guardrails: ['No harmful content', 'Stay on topic'] } } end @@ -96,6 +98,8 @@ RSpec.describe 'Api::V1::Accounts::Captain::Assistants', type: :request do end.to change(Captain::Assistant, :count).by(1) expect(json_response[:name]).to eq('New Assistant') + expect(json_response[:response_guidelines]).to eq(['Be helpful', 'Be concise']) + expect(json_response[:guardrails]).to eq(['No harmful content', 'Stay on topic']) expect(response).to have_http_status(:success) end end @@ -106,7 +110,9 @@ RSpec.describe 'Api::V1::Accounts::Captain::Assistants', type: :request do let(:update_attributes) do { assistant: { - name: 'Updated Assistant' + name: 'Updated Assistant', + response_guidelines: ['Updated guideline'], + guardrails: ['Updated guardrail'] } } end @@ -139,6 +145,38 @@ RSpec.describe 'Api::V1::Accounts::Captain::Assistants', type: :request do expect(response).to have_http_status(:success) expect(json_response[:name]).to eq('Updated Assistant') + expect(json_response[:response_guidelines]).to eq(['Updated guideline']) + expect(json_response[:guardrails]).to eq(['Updated guardrail']) + end + + it 'updates only response_guidelines when only that is provided' do + assistant.update!(response_guidelines: ['Original guideline'], guardrails: ['Original guardrail']) + original_name = assistant.name + + patch "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}", + params: { assistant: { response_guidelines: ['New guideline only'] } }, + headers: admin.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + expect(json_response[:name]).to eq(original_name) + expect(json_response[:response_guidelines]).to eq(['New guideline only']) + expect(json_response[:guardrails]).to eq(['Original guardrail']) + end + + it 'updates only guardrails when only that is provided' do + assistant.update!(response_guidelines: ['Original guideline'], guardrails: ['Original guardrail']) + original_name = assistant.name + + patch "/api/v1/accounts/#{account.id}/captain/assistants/#{assistant.id}", + params: { assistant: { guardrails: ['New guardrail only'] } }, + headers: admin.create_new_auth_token, + as: :json + + expect(response).to have_http_status(:success) + expect(json_response[:name]).to eq(original_name) + expect(json_response[:response_guidelines]).to eq(['Original guideline']) + expect(json_response[:guardrails]).to eq(['New guardrail only']) end end end