* FEATURE: Less friction for starting a conversation with an AI bot. This PR adds a new header icon as a shortcut to start a conversation with one of our AI Bots. After clicking and selecting one from the dropdown menu, we'll open the composer with some fields already filled (recipients and title). If you leave the title as is, we'll queue a job after five minutes to update it using a bot suggestion. * Update assets/javascripts/initializers/ai-bot-replies.js Co-authored-by: Rafael dos Santos Silva <[email protected]> * Update assets/javascripts/initializers/ai-bot-replies.js Co-authored-by: Rafael dos Santos Silva <[email protected]> --------- Co-authored-by: Rafael dos Santos Silva <[email protected]>
122 lines
3.4 KiB
JavaScript
122 lines
3.4 KiB
JavaScript
import { withPluginApi } from "discourse/lib/plugin-api";
|
|
import { cookAsync } from "discourse/lib/text";
|
|
import { ajax } from "discourse/lib/ajax";
|
|
import { popupAjaxError } from "discourse/lib/ajax-error";
|
|
import loadScript from "discourse/lib/load-script";
|
|
|
|
function isGPTBot(user) {
|
|
return user && [-110, -111, -112].includes(user.id);
|
|
}
|
|
|
|
function attachHeaderIcon(api) {
|
|
const settings = api.container.lookup("service:site-settings");
|
|
|
|
if (settings.ai_helper_add_ai_pm_to_header) {
|
|
api.addToHeaderIcons("ai-bot-header-icon");
|
|
}
|
|
}
|
|
|
|
function initializeAIBotReplies(api) {
|
|
api.addPostMenuButton("cancel-gpt", (post) => {
|
|
if (isGPTBot(post.user)) {
|
|
return {
|
|
icon: "pause",
|
|
action: "cancelStreaming",
|
|
title: "discourse_ai.ai_bot.cancel_streaming",
|
|
className: "btn btn-default cancel-streaming",
|
|
position: "first",
|
|
};
|
|
}
|
|
});
|
|
|
|
api.attachWidgetAction("post", "cancelStreaming", function () {
|
|
ajax(`/discourse-ai/ai-bot/post/${this.model.id}/stop-streaming`, {
|
|
type: "POST",
|
|
})
|
|
.then(() => {
|
|
document
|
|
.querySelector(`#post_${this.model.post_number}`)
|
|
.classList.remove("streaming");
|
|
})
|
|
.catch(popupAjaxError);
|
|
});
|
|
|
|
api.modifyClass("controller:topic", {
|
|
pluginId: "discourse-ai",
|
|
|
|
onAIBotStreamedReply: function (data) {
|
|
const post = this.model.postStream.findLoadedPost(data.post_id);
|
|
|
|
if (post) {
|
|
if (data.raw) {
|
|
cookAsync(data.raw).then((cooked) => {
|
|
post.set("raw", data.raw);
|
|
post.set("cooked", cooked);
|
|
|
|
document
|
|
.querySelector(`#post_${data.post_number}`)
|
|
.classList.add("streaming");
|
|
|
|
const cookedElement = document.createElement("div");
|
|
cookedElement.innerHTML = cooked;
|
|
|
|
let element = document.querySelector(
|
|
`#post_${data.post_number} .cooked`
|
|
);
|
|
|
|
loadScript("/javascripts/diffhtml.min.js").then(() => {
|
|
window.diff.innerHTML(element, cookedElement.innerHTML);
|
|
});
|
|
});
|
|
}
|
|
if (data.done) {
|
|
document
|
|
.querySelector(`#post_${data.post_number}`)
|
|
.classList.remove("streaming");
|
|
}
|
|
}
|
|
},
|
|
subscribe: function () {
|
|
this._super();
|
|
|
|
if (
|
|
this.model.isPrivateMessage &&
|
|
this.model.details.allowed_users &&
|
|
this.model.details.allowed_users.filter(isGPTBot).length >= 1
|
|
) {
|
|
this.messageBus.subscribe(
|
|
`discourse-ai/ai-bot/topic/${this.model.id}`,
|
|
this.onAIBotStreamedReply.bind(this)
|
|
);
|
|
}
|
|
},
|
|
unsubscribe: function () {
|
|
this.messageBus.unsubscribe("discourse-ai/ai-bot/topic/*");
|
|
this._super();
|
|
},
|
|
});
|
|
}
|
|
|
|
export default {
|
|
name: "discourse-ai-bot-replies",
|
|
|
|
initialize(container) {
|
|
const settings = container.lookup("service:site-settings");
|
|
const user = container.lookup("service:current-user");
|
|
const aiBotEnaled =
|
|
settings.discourse_ai_enabled && settings.ai_bot_enabled;
|
|
|
|
const aiBotsAllowedGroups = settings.ai_bot_allowed_groups
|
|
.split("|")
|
|
.map(parseInt);
|
|
const canInteractWithAIBots = user?.groups.some((g) =>
|
|
aiBotsAllowedGroups.includes(g.id)
|
|
);
|
|
|
|
if (aiBotEnaled && canInteractWithAIBots) {
|
|
withPluginApi("1.6.0", attachHeaderIcon);
|
|
withPluginApi("1.6.0", initializeAIBotReplies);
|
|
}
|
|
},
|
|
};
|