DEV: Add compatibility with the Glimmer Post Stream (#1230)

This commit is contained in:
Sérgio Saquetim 2025-04-29 23:55:54 -03:00 committed by GitHub
parent 09a6841480
commit ede65c971f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 250 additions and 211 deletions

View File

@ -1,3 +1,4 @@
< 3.5.0.beta3-dev: 09a68414804a1447f52e5d60691ba59742cda9ec
< 3.5.0.beta2-dev: de8624416a15b3d8e7ad350b083cc1420451ccec < 3.5.0.beta2-dev: de8624416a15b3d8e7ad350b083cc1420451ccec
< 3.5.0.beta1-dev: bdef136080074a993e7c4f5ca562edc31a8ba756 < 3.5.0.beta1-dev: bdef136080074a993e7c4f5ca562edc31a8ba756
< 3.4.0.beta4-dev: a53719ab8eb071459f215227421b3ea4987e5f87 < 3.4.0.beta4-dev: a53719ab8eb071459f215227421b3ea4987e5f87

View File

@ -0,0 +1,14 @@
import Component from "@glimmer/component";
import { isGPTBot } from "../../lib/ai-bot-helper";
export default class AiPersonaFlair extends Component {
static shouldRender(args) {
return isGPTBot(args.post.user);
}
<template>
<span class="persona-flair">
{{@outletArgs.post.topic.ai_persona_name}}
</span>
</template>
}

View File

@ -1,11 +1,29 @@
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error"; import { popupAjaxError } from "discourse/lib/ajax-error";
import { getOwnerWithFallback } from "discourse/lib/get-owner";
import Composer from "discourse/models/composer"; import Composer from "discourse/models/composer";
import { i18n } from "discourse-i18n"; import { i18n } from "discourse-i18n";
import ShareFullTopicModal from "../components/modal/share-full-topic-modal"; import ShareFullTopicModal from "../components/modal/share-full-topic-modal";
const MAX_PERSONA_USER_ID = -1200; const MAX_PERSONA_USER_ID = -1200;
let enabledChatBotIds;
export function isGPTBot(user) {
if (!user) {
return;
}
if (!enabledChatBotIds) {
const currentUser = getOwnerWithFallback(this).lookup(
"service:current-user"
);
enabledChatBotIds = currentUser.ai_enabled_chat_bots.map((bot) => bot.id);
}
return enabledChatBotIds.includes(user.id);
}
export function isPostFromAiBot(post, currentUser) { export function isPostFromAiBot(post, currentUser) {
return ( return (
post.user_id <= MAX_PERSONA_USER_ID || post.user_id <= MAX_PERSONA_USER_ID ||

View File

@ -1,20 +1,20 @@
import { hbs } from "ember-cli-htmlbars"; import { hbs } from "ember-cli-htmlbars";
import { withSilencedDeprecations } from "discourse/lib/deprecated";
import { withPluginApi } from "discourse/lib/plugin-api"; import { withPluginApi } from "discourse/lib/plugin-api";
import { registerWidgetShim } from "discourse/widgets/render-glimmer"; import { registerWidgetShim } from "discourse/widgets/render-glimmer";
import AiBotHeaderIcon from "../discourse/components/ai-bot-header-icon"; import AiBotHeaderIcon from "../discourse/components/ai-bot-header-icon";
import AiPersonaFlair from "../discourse/components/post/ai-persona-flair";
import AiCancelStreamingButton from "../discourse/components/post-menu/ai-cancel-streaming-button"; import AiCancelStreamingButton from "../discourse/components/post-menu/ai-cancel-streaming-button";
import AiDebugButton from "../discourse/components/post-menu/ai-debug-button"; import AiDebugButton from "../discourse/components/post-menu/ai-debug-button";
import AiShareButton from "../discourse/components/post-menu/ai-share-button"; import AiShareButton from "../discourse/components/post-menu/ai-share-button";
import { showShareConversationModal } from "../discourse/lib/ai-bot-helper"; import {
isGPTBot,
showShareConversationModal,
} from "../discourse/lib/ai-bot-helper";
import { streamPostText } from "../discourse/lib/ai-streamer/progress-handlers"; import { streamPostText } from "../discourse/lib/ai-streamer/progress-handlers";
let enabledChatBotIds = [];
let allowDebug = false; let allowDebug = false;
function isGPTBot(user) {
return user && enabledChatBotIds.includes(user.id);
}
function attachHeaderIcon(api) { function attachHeaderIcon(api) {
api.headerIcons.add("ai", AiBotHeaderIcon); api.headerIcons.add("ai", AiBotHeaderIcon);
} }
@ -53,28 +53,28 @@ function initializeAIBotReplies(api) {
} }
function initializePersonaDecorator(api) { function initializePersonaDecorator(api) {
let topicController = null; api.renderAfterWrapperOutlet("post-meta-data-poster-name", AiPersonaFlair);
withSilencedDeprecations("discourse.post-stream-widget-overrides", () =>
initializeWidgetPersonaDecorator(api)
);
}
function initializeWidgetPersonaDecorator(api) {
api.decorateWidget(`poster-name:after`, (dec) => { api.decorateWidget(`poster-name:after`, (dec) => {
if (!isGPTBot(dec.attrs.user)) { if (!isGPTBot(dec.attrs.user)) {
return; return;
} }
// this is hacky and will need to change
// trouble is we need to get the model for the topic
// and it is not available in the decorator
// long term this will not be a problem once we remove widgets and
// have a saner structure for our model
topicController =
topicController || api.container.lookup("controller:topic");
return dec.widget.attach("persona-flair", { return dec.widget.attach("persona-flair", {
topicController, personaName: dec.model?.topic?.ai_persona_name,
}); });
}); });
registerWidgetShim( registerWidgetShim(
"persona-flair", "persona-flair",
"span.persona-flair", "span.persona-flair",
hbs`{{@data.topicController.model.ai_persona_name}}` hbs`{{@data.personaName}}`
); );
} }
@ -159,16 +159,16 @@ export default {
const user = container.lookup("service:current-user"); const user = container.lookup("service:current-user");
if (user?.ai_enabled_chat_bots) { if (user?.ai_enabled_chat_bots) {
enabledChatBotIds = user.ai_enabled_chat_bots.map((bot) => bot.id);
allowDebug = user.can_debug_ai_bot_conversations; allowDebug = user.can_debug_ai_bot_conversations;
withPluginApi("1.6.0", attachHeaderIcon);
withPluginApi("1.34.0", initializeAIBotReplies); withPluginApi((api) => {
withPluginApi("1.6.0", initializePersonaDecorator); attachHeaderIcon(api);
withPluginApi("1.34.0", (api) => initializeDebugButton(api, container)); initializeAIBotReplies(api);
withPluginApi("1.34.0", (api) => initializeShareButton(api, container)); initializePersonaDecorator(api);
withPluginApi("1.22.0", (api) => initializeDebugButton(api, container);
initializeShareTopicButton(api, container) initializeShareButton(api, container);
); initializeShareTopicButton(api, container);
});
} }
}, },
}; };

View File

@ -105,6 +105,10 @@ RSpec.describe "AI Bot - Homepage", type: :system do
sign_in(user) sign_in(user)
end end
%w[enabled disabled].each do |value|
before { SiteSetting.glimmer_post_stream_mode = value }
context "when glimmer_post_stream_mode=#{value}" do
context "when `ai_enable_experimental_bot_ux` is enabled" do context "when `ai_enable_experimental_bot_ux` is enabled" do
it "renders landing page on bot click" do it "renders landing page on bot click" do
visit "/" visit "/"
@ -332,3 +336,5 @@ RSpec.describe "AI Bot - Homepage", type: :system do
end end
end end
end end
end
end