175 lines
4.9 KiB
JavaScript
175 lines
4.9 KiB
JavaScript
import { hbs } from "ember-cli-htmlbars";
|
|
import { withSilencedDeprecations } from "discourse/lib/deprecated";
|
|
import { withPluginApi } from "discourse/lib/plugin-api";
|
|
import { registerWidgetShim } from "discourse/widgets/render-glimmer";
|
|
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 AiDebugButton from "../discourse/components/post-menu/ai-debug-button";
|
|
import AiShareButton from "../discourse/components/post-menu/ai-share-button";
|
|
import {
|
|
isGPTBot,
|
|
showShareConversationModal,
|
|
} from "../discourse/lib/ai-bot-helper";
|
|
import { streamPostText } from "../discourse/lib/ai-streamer/progress-handlers";
|
|
|
|
let allowDebug = false;
|
|
|
|
function attachHeaderIcon(api) {
|
|
api.headerIcons.add("ai", AiBotHeaderIcon);
|
|
}
|
|
|
|
function initializeAIBotReplies(api) {
|
|
initializePauseButton(api);
|
|
|
|
api.modifyClass("controller:topic", {
|
|
pluginId: "discourse-ai",
|
|
|
|
onAIBotStreamedReply: function (data) {
|
|
streamPostText(this.model.postStream, data);
|
|
},
|
|
subscribe: function () {
|
|
this._super();
|
|
|
|
if (
|
|
this.model.isPrivateMessage &&
|
|
this.model.details.allowed_users &&
|
|
this.model.details.allowed_users.filter(isGPTBot).length >= 1
|
|
) {
|
|
// we attempt to recover the last message in the bus
|
|
// so we subscribe at -2
|
|
this.messageBus.subscribe(
|
|
`discourse-ai/ai-bot/topic/${this.model.id}`,
|
|
this.onAIBotStreamedReply.bind(this),
|
|
-2
|
|
);
|
|
}
|
|
},
|
|
unsubscribe: function () {
|
|
this.messageBus.unsubscribe("discourse-ai/ai-bot/topic/*");
|
|
this._super();
|
|
},
|
|
});
|
|
}
|
|
|
|
function initializePersonaDecorator(api) {
|
|
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) => {
|
|
if (!isGPTBot(dec.attrs.user)) {
|
|
return;
|
|
}
|
|
|
|
return dec.widget.attach("persona-flair", {
|
|
personaName: dec.model?.topic?.ai_persona_name,
|
|
});
|
|
});
|
|
|
|
registerWidgetShim(
|
|
"persona-flair",
|
|
"span.persona-flair",
|
|
hbs`{{@data.personaName}}`
|
|
);
|
|
}
|
|
|
|
function initializePauseButton(api) {
|
|
api.registerValueTransformer(
|
|
"post-menu-buttons",
|
|
({ value: dag, context: { post, firstButtonKey } }) => {
|
|
if (isGPTBot(post.user)) {
|
|
dag.add("ai-cancel-gpt", AiCancelStreamingButton, {
|
|
before: firstButtonKey,
|
|
after: ["ai-share", "ai-debug"],
|
|
});
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
function initializeDebugButton(api) {
|
|
const currentUser = api.getCurrentUser();
|
|
if (!currentUser || !currentUser.ai_enabled_chat_bots || !allowDebug) {
|
|
return;
|
|
}
|
|
|
|
api.registerValueTransformer(
|
|
"post-menu-buttons",
|
|
({ value: dag, context: { post, firstButtonKey } }) => {
|
|
if (post.topic?.archetype === "private_message") {
|
|
dag.add("ai-debug", AiDebugButton, {
|
|
before: firstButtonKey,
|
|
after: "ai-share",
|
|
});
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
function initializeShareButton(api) {
|
|
const currentUser = api.getCurrentUser();
|
|
if (!currentUser || !currentUser.ai_enabled_chat_bots) {
|
|
return;
|
|
}
|
|
|
|
api.registerValueTransformer(
|
|
"post-menu-buttons",
|
|
({ value: dag, context: { post, firstButtonKey } }) => {
|
|
if (post.topic?.archetype === "private_message") {
|
|
dag.add("ai-share", AiShareButton, {
|
|
before: firstButtonKey,
|
|
});
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
function initializeShareTopicButton(api) {
|
|
const modal = api.container.lookup("service:modal");
|
|
const currentUser = api.container.lookup("service:current-user");
|
|
|
|
api.registerTopicFooterButton({
|
|
id: "share-ai-conversation",
|
|
icon: "share-nodes",
|
|
label: "discourse_ai.ai_bot.share_ai_conversation.name",
|
|
title: "discourse_ai.ai_bot.share_ai_conversation.title",
|
|
action() {
|
|
showShareConversationModal(modal, this.topic.id);
|
|
},
|
|
classNames: ["share-ai-conversation-button"],
|
|
dependentKeys: ["topic.ai_persona_name"],
|
|
displayed() {
|
|
return (
|
|
currentUser?.can_share_ai_bot_conversations &&
|
|
this.topic.ai_persona_name
|
|
);
|
|
},
|
|
});
|
|
}
|
|
|
|
export default {
|
|
name: "discourse-ai-bot-replies",
|
|
|
|
initialize(container) {
|
|
const user = container.lookup("service:current-user");
|
|
|
|
if (user?.ai_enabled_chat_bots) {
|
|
allowDebug = user.can_debug_ai_bot_conversations;
|
|
|
|
withPluginApi((api) => {
|
|
attachHeaderIcon(api);
|
|
initializeAIBotReplies(api);
|
|
initializePersonaDecorator(api);
|
|
initializeDebugButton(api, container);
|
|
initializeShareButton(api, container);
|
|
initializeShareTopicButton(api, container);
|
|
});
|
|
}
|
|
},
|
|
};
|