FIX: system persona state leaking between sites (#1304)
System personas leaned on reused classes, this was a problem in a multisite environement cause state, such as "enabled" ended up being reused between sites. New implementation ensures state is pristine between sites in a multisite * more handling for new superclass story * small oversight, display name should be used for display
This commit is contained in:
parent
8b1b6811f4
commit
491dac298f
|
|
@ -226,12 +226,19 @@ class AiPersona < ActiveRecord::Base
|
||||||
|
|
||||||
persona_class = DiscourseAi::Personas::Persona.system_personas_by_id[self.id]
|
persona_class = DiscourseAi::Personas::Persona.system_personas_by_id[self.id]
|
||||||
if persona_class
|
if persona_class
|
||||||
|
return(
|
||||||
|
# we need a new copy so we don't leak information
|
||||||
|
# across sites
|
||||||
|
Class.new(persona_class) do
|
||||||
|
# required for localization
|
||||||
|
define_singleton_method(:to_s) { persona_class.to_s }
|
||||||
instance_attributes.each do |key, value|
|
instance_attributes.each do |key, value|
|
||||||
# description/name are localized
|
# description/name are localized
|
||||||
persona_class.define_singleton_method(key) { value } if key != :description && key != :name
|
define_singleton_method(key) { value } if key != :description && key != :name
|
||||||
end
|
end
|
||||||
persona_class.define_method(:options) { options }
|
define_method(:options) { options }
|
||||||
return persona_class
|
end
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
ai_persona_id = self.id
|
ai_persona_id = self.id
|
||||||
|
|
|
||||||
|
|
@ -459,7 +459,7 @@ module DiscourseAi
|
||||||
post_type: post_type,
|
post_type: post_type,
|
||||||
skip_guardian: true,
|
skip_guardian: true,
|
||||||
custom_fields: {
|
custom_fields: {
|
||||||
DiscourseAi::AiBot::POST_AI_LLM_NAME_FIELD => bot.llm.llm_model.name,
|
DiscourseAi::AiBot::POST_AI_LLM_NAME_FIELD => bot.llm.llm_model.display_name,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -128,7 +128,8 @@ module DiscourseAi
|
||||||
end
|
end
|
||||||
|
|
||||||
def id
|
def id
|
||||||
@ai_persona&.id || self.class.system_personas[self.class]
|
@ai_persona&.id || self.class.system_personas[self.class.superclass] ||
|
||||||
|
self.class.system_personas[self.class]
|
||||||
end
|
end
|
||||||
|
|
||||||
def tools
|
def tools
|
||||||
|
|
|
||||||
|
|
@ -785,7 +785,7 @@ RSpec.describe DiscourseAi::AiBot::Playground do
|
||||||
expect(last_post.user_id).to eq(persona.user_id)
|
expect(last_post.user_id).to eq(persona.user_id)
|
||||||
|
|
||||||
expect(last_post.custom_fields[DiscourseAi::AiBot::POST_AI_LLM_NAME_FIELD]).to eq(
|
expect(last_post.custom_fields[DiscourseAi::AiBot::POST_AI_LLM_NAME_FIELD]).to eq(
|
||||||
gpt_35_turbo.name,
|
gpt_35_turbo.display_name,
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -212,7 +212,7 @@ RSpec.describe DiscourseAi::Personas::Persona do
|
||||||
SiteSetting.ai_google_custom_search_cx = "abc123"
|
SiteSetting.ai_google_custom_search_cx = "abc123"
|
||||||
|
|
||||||
# should be ordered by priority and then alpha
|
# should be ordered by priority and then alpha
|
||||||
expect(DiscourseAi::Personas::Persona.all(user: user)).to eq(
|
expect(DiscourseAi::Personas::Persona.all(user: user).map(&:superclass)).to eq(
|
||||||
[
|
[
|
||||||
DiscourseAi::Personas::General,
|
DiscourseAi::Personas::General,
|
||||||
DiscourseAi::Personas::Artist,
|
DiscourseAi::Personas::Artist,
|
||||||
|
|
@ -226,7 +226,7 @@ RSpec.describe DiscourseAi::Personas::Persona do
|
||||||
)
|
)
|
||||||
|
|
||||||
# it should allow staff access to WebArtifactCreator
|
# it should allow staff access to WebArtifactCreator
|
||||||
expect(DiscourseAi::Personas::Persona.all(user: admin)).to eq(
|
expect(DiscourseAi::Personas::Persona.all(user: admin).map(&:superclass)).to eq(
|
||||||
[
|
[
|
||||||
DiscourseAi::Personas::General,
|
DiscourseAi::Personas::General,
|
||||||
DiscourseAi::Personas::Artist,
|
DiscourseAi::Personas::Artist,
|
||||||
|
|
@ -245,7 +245,7 @@ RSpec.describe DiscourseAi::Personas::Persona do
|
||||||
SiteSetting.ai_google_custom_search_api_key = ""
|
SiteSetting.ai_google_custom_search_api_key = ""
|
||||||
SiteSetting.ai_artifact_security = "disabled"
|
SiteSetting.ai_artifact_security = "disabled"
|
||||||
|
|
||||||
expect(DiscourseAi::Personas::Persona.all(user: admin)).to contain_exactly(
|
expect(DiscourseAi::Personas::Persona.all(user: admin).map(&:superclass)).to contain_exactly(
|
||||||
DiscourseAi::Personas::General,
|
DiscourseAi::Personas::General,
|
||||||
DiscourseAi::Personas::SqlHelper,
|
DiscourseAi::Personas::SqlHelper,
|
||||||
DiscourseAi::Personas::SettingsExplorer,
|
DiscourseAi::Personas::SettingsExplorer,
|
||||||
|
|
@ -258,7 +258,7 @@ RSpec.describe DiscourseAi::Personas::Persona do
|
||||||
DiscourseAi::Personas::Persona.system_personas[DiscourseAi::Personas::General],
|
DiscourseAi::Personas::Persona.system_personas[DiscourseAi::Personas::General],
|
||||||
).update!(enabled: false)
|
).update!(enabled: false)
|
||||||
|
|
||||||
expect(DiscourseAi::Personas::Persona.all(user: user)).to contain_exactly(
|
expect(DiscourseAi::Personas::Persona.all(user: user).map(&:superclass)).to contain_exactly(
|
||||||
DiscourseAi::Personas::SqlHelper,
|
DiscourseAi::Personas::SqlHelper,
|
||||||
DiscourseAi::Personas::SettingsExplorer,
|
DiscourseAi::Personas::SettingsExplorer,
|
||||||
DiscourseAi::Personas::Creative,
|
DiscourseAi::Personas::Creative,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.describe AiPersona, type: :multisite do
|
||||||
|
it "is able to amend settings on system personas on multisite" do
|
||||||
|
persona = AiPersona.find_by(name: "Designer")
|
||||||
|
expect(persona.allow_personal_messages).to eq(true)
|
||||||
|
persona.update!(allow_personal_messages: false)
|
||||||
|
|
||||||
|
instance = persona.class_instance
|
||||||
|
expect(instance.allow_personal_messages).to eq(false)
|
||||||
|
|
||||||
|
test_multisite_connection("second") do
|
||||||
|
persona = AiPersona.find_by(name: "Designer")
|
||||||
|
expect(persona.allow_personal_messages).to eq(true)
|
||||||
|
instance = persona.class_instance
|
||||||
|
expect(instance.name).to eq("Designer")
|
||||||
|
expect(instance.allow_personal_messages).to eq(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
persona = AiPersona.find_by(name: "Designer")
|
||||||
|
instance = persona.class_instance
|
||||||
|
expect(instance.allow_personal_messages).to eq(false)
|
||||||
|
end
|
||||||
|
end
|
||||||
Loading…
Reference in New Issue