Merge pull request #22090 from brave/leo_writing_tools
Add more Leo tools in context menu
This commit is contained in:
@@ -101,6 +101,22 @@
|
||||
// AI chat commands.
|
||||
#define IDC_AI_CHAT_CONTEXT_SUMMARIZE_TEXT 56226
|
||||
#define IDC_AI_CHAT_CONTEXT_LEO_TOOLS 56227
|
||||
#define IDC_AI_CHAT_CONTEXT_EXPLAIN 56228
|
||||
#define IDC_AI_CHAT_CONTEXT_PARAPHRASE 56229
|
||||
#define IDC_AI_CHAT_CONTEXT_CREATE_TAGLINE 56230
|
||||
#define IDC_AI_CHAT_CONTEXT_CREATE_SOCIAL_MEDIA_POST 56231
|
||||
#define IDC_AI_CHAT_CONTEXT_CREATE_SOCIAL_MEDIA_COMMENT_SHORT 56232
|
||||
#define IDC_AI_CHAT_CONTEXT_CREATE_SOCIAL_MEDIA_COMMENT_LONG 56233
|
||||
#define IDC_AI_CHAT_CONTEXT_CHANGE_LENGTH 56234
|
||||
#define IDC_AI_CHAT_CONTEXT_IMPROVE 56235
|
||||
#define IDC_AI_CHAT_CONTEXT_SIMPLIFY 56236
|
||||
#define IDC_AI_CHAT_CONTEXT_CHANGE_TONE 56237
|
||||
#define IDC_AI_CHAT_CONTEXT_ACADEMICIZE 56238
|
||||
#define IDC_AI_CHAT_CONTEXT_PROFESSIONALIZE 56239
|
||||
#define IDC_AI_CHAT_CONTEXT_CASUALIZE 56240
|
||||
#define IDC_AI_CHAT_CONTEXT_FUNNY_TONE 56241
|
||||
#define IDC_AI_CHAT_CONTEXT_SHORTEN 56242
|
||||
#define IDC_AI_CHAT_CONTEXT_EXPAND 56243
|
||||
|
||||
// Bookmark commands.
|
||||
#define IDC_TOGGLE_ALL_BOOKMARKS_BUTTON_VISIBILITY 56300
|
||||
|
||||
@@ -224,13 +224,6 @@
|
||||
<message name="IDS_OPEN_MORE_OTHER_DEVICES_SESSIONS" desc="The history sub-menu item to show sessions from other devices">
|
||||
More…
|
||||
</message>
|
||||
<message name="IDS_AI_CHAT_CONTEXT_LEO_TOOLS" desc="The text label of Leo tools submenu in the context menu">
|
||||
Leo tools
|
||||
</message>
|
||||
<message name="IDS_AI_CHAT_CONTEXT_SUMMARIZE_TEXT" desc="The text label of context menu item to summarize selected text">
|
||||
Summarize
|
||||
</message>
|
||||
|
||||
<!-- Widevine -->
|
||||
<message name="IDS_WIDEVINE_PERMISSION_REQUEST_TEXT_FRAGMENT" desc="Text fragment for Widevine permission request. 'Widevine' is the name of a plugin and should not be translated.">
|
||||
Install and run Google Widevine
|
||||
|
||||
@@ -46,7 +46,10 @@
|
||||
#include "brave/browser/ui/sidebar/sidebar_controller.h"
|
||||
#include "brave/components/ai_chat/content/browser/ai_chat_tab_helper.h"
|
||||
#include "brave/components/ai_chat/core/browser/utils.h"
|
||||
#include "brave/components/ai_chat/core/common/features.h"
|
||||
#include "brave/components/ai_chat/core/common/mojom/ai_chat.mojom.h"
|
||||
#include "brave/components/ai_chat/core/common/pref_names.h"
|
||||
#include "components/grit/brave_components_strings.h"
|
||||
#endif
|
||||
|
||||
// Our .h file creates a masquerade for RenderViewContextMenu. Switch
|
||||
@@ -187,11 +190,16 @@ BraveRenderViewContextMenu::BraveRenderViewContextMenu(
|
||||
#endif
|
||||
#if BUILDFLAG(ENABLE_AI_CHAT)
|
||||
,
|
||||
ai_chat_submenu_model_(this)
|
||||
ai_chat_submenu_model_(this),
|
||||
ai_chat_change_tone_submenu_model_(this),
|
||||
ai_chat_change_length_submenu_model_(this),
|
||||
ai_chat_social_media_post_submenu_model_(this)
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
BraveRenderViewContextMenu::~BraveRenderViewContextMenu() = default;
|
||||
|
||||
bool BraveRenderViewContextMenu::IsCommandIdEnabled(int id) const {
|
||||
switch (id) {
|
||||
#if BUILDFLAG(ENABLE_TEXT_RECOGNITION)
|
||||
@@ -229,8 +237,24 @@ bool BraveRenderViewContextMenu::IsCommandIdEnabled(int id) const {
|
||||
return false;
|
||||
#endif
|
||||
#if BUILDFLAG(ENABLE_AI_CHAT)
|
||||
case IDC_AI_CHAT_CONTEXT_LEO_TOOLS:
|
||||
case IDC_AI_CHAT_CONTEXT_SUMMARIZE_TEXT:
|
||||
case IDC_AI_CHAT_CONTEXT_LEO_TOOLS:
|
||||
case IDC_AI_CHAT_CONTEXT_EXPLAIN:
|
||||
case IDC_AI_CHAT_CONTEXT_PARAPHRASE:
|
||||
case IDC_AI_CHAT_CONTEXT_CREATE_TAGLINE:
|
||||
case IDC_AI_CHAT_CONTEXT_CREATE_SOCIAL_MEDIA_COMMENT_SHORT:
|
||||
case IDC_AI_CHAT_CONTEXT_CREATE_SOCIAL_MEDIA_COMMENT_LONG:
|
||||
case IDC_AI_CHAT_CONTEXT_IMPROVE:
|
||||
case IDC_AI_CHAT_CONTEXT_SIMPLIFY:
|
||||
case IDC_AI_CHAT_CONTEXT_CHANGE_TONE:
|
||||
case IDC_AI_CHAT_CONTEXT_ACADEMICIZE:
|
||||
case IDC_AI_CHAT_CONTEXT_PROFESSIONALIZE:
|
||||
case IDC_AI_CHAT_CONTEXT_CASUALIZE:
|
||||
case IDC_AI_CHAT_CONTEXT_FUNNY_TONE:
|
||||
case IDC_AI_CHAT_CONTEXT_SHORTEN:
|
||||
case IDC_AI_CHAT_CONTEXT_EXPAND:
|
||||
case IDC_AI_CHAT_CONTEXT_CHANGE_LENGTH:
|
||||
case IDC_AI_CHAT_CONTEXT_CREATE_SOCIAL_MEDIA_POST:
|
||||
return IsAIChatEnabled();
|
||||
#endif
|
||||
default:
|
||||
@@ -324,6 +348,19 @@ void BraveRenderViewContextMenu::ExecuteCommand(int id, int event_flags) {
|
||||
#endif
|
||||
#if BUILDFLAG(ENABLE_AI_CHAT)
|
||||
case IDC_AI_CHAT_CONTEXT_SUMMARIZE_TEXT:
|
||||
case IDC_AI_CHAT_CONTEXT_EXPLAIN:
|
||||
case IDC_AI_CHAT_CONTEXT_PARAPHRASE:
|
||||
case IDC_AI_CHAT_CONTEXT_CREATE_TAGLINE:
|
||||
case IDC_AI_CHAT_CONTEXT_CREATE_SOCIAL_MEDIA_COMMENT_SHORT:
|
||||
case IDC_AI_CHAT_CONTEXT_CREATE_SOCIAL_MEDIA_COMMENT_LONG:
|
||||
case IDC_AI_CHAT_CONTEXT_IMPROVE:
|
||||
case IDC_AI_CHAT_CONTEXT_SIMPLIFY:
|
||||
case IDC_AI_CHAT_CONTEXT_ACADEMICIZE:
|
||||
case IDC_AI_CHAT_CONTEXT_PROFESSIONALIZE:
|
||||
case IDC_AI_CHAT_CONTEXT_CASUALIZE:
|
||||
case IDC_AI_CHAT_CONTEXT_FUNNY_TONE:
|
||||
case IDC_AI_CHAT_CONTEXT_SHORTEN:
|
||||
case IDC_AI_CHAT_CONTEXT_EXPAND:
|
||||
ExecuteAIChatCommand(id);
|
||||
break;
|
||||
#endif
|
||||
@@ -380,7 +417,63 @@ void BraveRenderViewContextMenu::ExecuteAIChatCommand(int command) {
|
||||
|
||||
switch (command) {
|
||||
case IDC_AI_CHAT_CONTEXT_SUMMARIZE_TEXT:
|
||||
helper->SummarizeSelectedText(base::UTF16ToUTF8(params_.selection_text));
|
||||
helper->SubmitSelectedText(
|
||||
base::UTF16ToUTF8(params_.selection_text),
|
||||
ai_chat::mojom::ActionType::SUMMARIZE_SELECTED_TEXT);
|
||||
break;
|
||||
case IDC_AI_CHAT_CONTEXT_EXPLAIN:
|
||||
helper->SubmitSelectedText(base::UTF16ToUTF8(params_.selection_text),
|
||||
ai_chat::mojom::ActionType::EXPLAIN);
|
||||
break;
|
||||
case IDC_AI_CHAT_CONTEXT_PARAPHRASE:
|
||||
helper->SubmitSelectedText(base::UTF16ToUTF8(params_.selection_text),
|
||||
ai_chat::mojom::ActionType::PARAPHRASE);
|
||||
break;
|
||||
case IDC_AI_CHAT_CONTEXT_CREATE_TAGLINE:
|
||||
helper->SubmitSelectedText(base::UTF16ToUTF8(params_.selection_text),
|
||||
ai_chat::mojom::ActionType::CREATE_TAGLINE);
|
||||
break;
|
||||
case IDC_AI_CHAT_CONTEXT_CREATE_SOCIAL_MEDIA_COMMENT_SHORT:
|
||||
helper->SubmitSelectedText(
|
||||
base::UTF16ToUTF8(params_.selection_text),
|
||||
ai_chat::mojom::ActionType::CREATE_SOCIAL_MEDIA_COMMENT_SHORT);
|
||||
break;
|
||||
case IDC_AI_CHAT_CONTEXT_CREATE_SOCIAL_MEDIA_COMMENT_LONG:
|
||||
helper->SubmitSelectedText(
|
||||
base::UTF16ToUTF8(params_.selection_text),
|
||||
ai_chat::mojom::ActionType::CREATE_SOCIAL_MEDIA_COMMENT_LONG);
|
||||
break;
|
||||
case IDC_AI_CHAT_CONTEXT_IMPROVE:
|
||||
helper->SubmitSelectedText(base::UTF16ToUTF8(params_.selection_text),
|
||||
ai_chat::mojom::ActionType::IMPROVE);
|
||||
break;
|
||||
case IDC_AI_CHAT_CONTEXT_SIMPLIFY:
|
||||
helper->SubmitSelectedText(base::UTF16ToUTF8(params_.selection_text),
|
||||
ai_chat::mojom::ActionType::SIMPLIFY);
|
||||
break;
|
||||
case IDC_AI_CHAT_CONTEXT_ACADEMICIZE:
|
||||
helper->SubmitSelectedText(base::UTF16ToUTF8(params_.selection_text),
|
||||
ai_chat::mojom::ActionType::ACADEMICIZE);
|
||||
break;
|
||||
case IDC_AI_CHAT_CONTEXT_PROFESSIONALIZE:
|
||||
helper->SubmitSelectedText(base::UTF16ToUTF8(params_.selection_text),
|
||||
ai_chat::mojom::ActionType::PROFESSIONALIZE);
|
||||
break;
|
||||
case IDC_AI_CHAT_CONTEXT_CASUALIZE:
|
||||
helper->SubmitSelectedText(base::UTF16ToUTF8(params_.selection_text),
|
||||
ai_chat::mojom::ActionType::CASUALIZE);
|
||||
break;
|
||||
case IDC_AI_CHAT_CONTEXT_FUNNY_TONE:
|
||||
helper->SubmitSelectedText(base::UTF16ToUTF8(params_.selection_text),
|
||||
ai_chat::mojom::ActionType::FUNNY_TONE);
|
||||
break;
|
||||
case IDC_AI_CHAT_CONTEXT_SHORTEN:
|
||||
helper->SubmitSelectedText(base::UTF16ToUTF8(params_.selection_text),
|
||||
ai_chat::mojom::ActionType::SHORTEN);
|
||||
break;
|
||||
case IDC_AI_CHAT_CONTEXT_EXPAND:
|
||||
helper->SubmitSelectedText(base::UTF16ToUTF8(params_.selection_text),
|
||||
ai_chat::mojom::ActionType::EXPAND);
|
||||
break;
|
||||
default:
|
||||
NOTREACHED_NORETURN();
|
||||
@@ -396,8 +489,65 @@ void BraveRenderViewContextMenu::BuildAIChatMenu() {
|
||||
if (!print_index.has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ai_chat_submenu_model_.AddTitleWithStringId(
|
||||
IDS_AI_CHAT_CONTEXT_QUICK_ACTIONS);
|
||||
ai_chat_submenu_model_.AddItemWithStringId(
|
||||
IDC_AI_CHAT_CONTEXT_SUMMARIZE_TEXT, IDS_AI_CHAT_CONTEXT_SUMMARIZE_TEXT);
|
||||
ai_chat_submenu_model_.AddItemWithStringId(IDC_AI_CHAT_CONTEXT_EXPLAIN,
|
||||
IDS_AI_CHAT_CONTEXT_EXPLAIN);
|
||||
ai_chat_submenu_model_.AddItemWithStringId(IDC_AI_CHAT_CONTEXT_PARAPHRASE,
|
||||
IDS_AI_CHAT_CONTEXT_PARAPHRASE);
|
||||
ai_chat_submenu_model_.AddItemWithStringId(IDC_AI_CHAT_CONTEXT_IMPROVE,
|
||||
IDS_AI_CHAT_CONTEXT_IMPROVE);
|
||||
ai_chat_submenu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
|
||||
|
||||
ai_chat_submenu_model_.AddTitleWithStringId(IDS_AI_CHAT_CONTEXT_REWRITE);
|
||||
ai_chat_submenu_model_.AddItemWithStringId(IDC_AI_CHAT_CONTEXT_PARAPHRASE,
|
||||
IDS_AI_CHAT_CONTEXT_PARAPHRASE);
|
||||
ai_chat_submenu_model_.AddItemWithStringId(IDC_AI_CHAT_CONTEXT_IMPROVE,
|
||||
IDS_AI_CHAT_CONTEXT_IMPROVE);
|
||||
ai_chat_submenu_model_.AddItemWithStringId(IDC_AI_CHAT_CONTEXT_SIMPLIFY,
|
||||
IDS_AI_CHAT_CONTEXT_SIMPLIFY);
|
||||
|
||||
ai_chat_change_tone_submenu_model_.AddItemWithStringId(
|
||||
IDC_AI_CHAT_CONTEXT_ACADEMICIZE, IDS_AI_CHAT_CONTEXT_ACADEMICIZE);
|
||||
ai_chat_change_tone_submenu_model_.AddItemWithStringId(
|
||||
IDC_AI_CHAT_CONTEXT_PROFESSIONALIZE, IDS_AI_CHAT_CONTEXT_PROFESSIONALIZE);
|
||||
ai_chat_change_tone_submenu_model_.AddItemWithStringId(
|
||||
IDC_AI_CHAT_CONTEXT_CASUALIZE, IDS_AI_CHAT_CONTEXT_CASUALIZE);
|
||||
ai_chat_change_tone_submenu_model_.AddItemWithStringId(
|
||||
IDC_AI_CHAT_CONTEXT_FUNNY_TONE, IDS_AI_CHAT_CONTEXT_FUNNY_TONE);
|
||||
|
||||
ai_chat_submenu_model_.AddSubMenuWithStringId(
|
||||
IDC_AI_CHAT_CONTEXT_CHANGE_TONE, IDS_AI_CHAT_CONTEXT_CHANGE_TONE,
|
||||
&ai_chat_change_tone_submenu_model_);
|
||||
|
||||
ai_chat_change_length_submenu_model_.AddItemWithStringId(
|
||||
IDC_AI_CHAT_CONTEXT_SHORTEN, IDS_AI_CHAT_CONTEXT_SHORTEN);
|
||||
ai_chat_change_length_submenu_model_.AddItemWithStringId(
|
||||
IDC_AI_CHAT_CONTEXT_EXPAND, IDS_AI_CHAT_CONTEXT_EXPAND);
|
||||
ai_chat_submenu_model_.AddSubMenuWithStringId(
|
||||
IDC_AI_CHAT_CONTEXT_CHANGE_LENGTH, IDS_AI_CHAT_CONTEXT_CHANGE_LENGTH,
|
||||
&ai_chat_change_length_submenu_model_);
|
||||
|
||||
ai_chat_submenu_model_.AddSeparator(ui::NORMAL_SEPARATOR);
|
||||
|
||||
ai_chat_submenu_model_.AddTitleWithStringId(IDS_AI_CHAT_CONTEXT_CREATE);
|
||||
ai_chat_submenu_model_.AddItemWithStringId(
|
||||
IDC_AI_CHAT_CONTEXT_CREATE_TAGLINE, IDS_AI_CHAT_CONTEXT_CREATE_TAGLINE);
|
||||
|
||||
ai_chat_social_media_post_submenu_model_.AddItemWithStringId(
|
||||
IDC_AI_CHAT_CONTEXT_CREATE_SOCIAL_MEDIA_COMMENT_SHORT,
|
||||
IDS_AI_CHAT_CONTEXT_CREATE_SOCIAL_MEDIA_COMMENT_SHORT);
|
||||
ai_chat_social_media_post_submenu_model_.AddItemWithStringId(
|
||||
IDC_AI_CHAT_CONTEXT_CREATE_SOCIAL_MEDIA_COMMENT_LONG,
|
||||
IDS_AI_CHAT_CONTEXT_CREATE_SOCIAL_MEDIA_COMMENT_LONG);
|
||||
ai_chat_submenu_model_.AddSubMenuWithStringId(
|
||||
IDC_AI_CHAT_CONTEXT_CREATE_SOCIAL_MEDIA_POST,
|
||||
IDS_AI_CHAT_CONTEXT_CREATE_SOCIAL_MEDIA_POST,
|
||||
&ai_chat_social_media_post_submenu_model_);
|
||||
|
||||
menu_model_.InsertSubMenuWithStringIdAt(
|
||||
*print_index, IDC_AI_CHAT_CONTEXT_LEO_TOOLS,
|
||||
IDS_AI_CHAT_CONTEXT_LEO_TOOLS, &ai_chat_submenu_model_);
|
||||
|
||||
@@ -37,6 +37,7 @@ class BraveRenderViewContextMenu : public RenderViewContextMenu_Chromium {
|
||||
// NOLINTNEXTLINE(runtime/references)
|
||||
BraveRenderViewContextMenu(content::RenderFrameHost& render_frame_host,
|
||||
const content::ContextMenuParams& params);
|
||||
~BraveRenderViewContextMenu() override;
|
||||
// RenderViewContextMenuBase:
|
||||
bool IsCommandIdEnabled(int command_id) const override;
|
||||
void ExecuteCommand(int id, int event_flags) override;
|
||||
@@ -66,6 +67,9 @@ class BraveRenderViewContextMenu : public RenderViewContextMenu_Chromium {
|
||||
void BuildAIChatMenu();
|
||||
|
||||
ui::SimpleMenuModel ai_chat_submenu_model_;
|
||||
ui::SimpleMenuModel ai_chat_change_tone_submenu_model_;
|
||||
ui::SimpleMenuModel ai_chat_change_length_submenu_model_;
|
||||
ui::SimpleMenuModel ai_chat_social_media_post_submenu_model_;
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(ENABLE_TEXT_RECOGNITION)
|
||||
|
||||
@@ -107,6 +107,27 @@ base::span<const webui::LocalizedString> GetLocalizedStrings() {
|
||||
{"contextToggleLabel", IDS_CHAT_UI_CONTEXT_TOGGLE_LABEL},
|
||||
{"contextToggleTooltipInfo", IDS_CHAT_UI_CONTEXT_TOGGLE_TOOLTIP_INFO},
|
||||
{"subscriptionPolicyInfo", IDS_CHAT_UI_SUBSCRIPTION_POLICY_INFO},
|
||||
{"explainLabel", IDS_AI_CHAT_CONTEXT_EXPLAIN},
|
||||
{"summarizeLabel", IDS_AI_CHAT_CONTEXT_SUMMARIZE_TEXT},
|
||||
{"paraphraseLabel", IDS_AI_CHAT_CONTEXT_PARAPHRASE},
|
||||
{"createCategoryTitle", IDS_AI_CHAT_CONTEXT_CREATE},
|
||||
{"taglineLabel", IDS_AI_CHAT_CONTEXT_CREATE_TAGLINE},
|
||||
{"socialMediaPostLabel", IDS_AI_CHAT_CONTEXT_CREATE_SOCIAL_MEDIA_POST},
|
||||
{"socialMediaShortLabel",
|
||||
IDS_AI_CHAT_CONTEXT_CREATE_SOCIAL_MEDIA_COMMENT_SHORT},
|
||||
{"socialMediaLongLabel",
|
||||
IDS_AI_CHAT_CONTEXT_CREATE_SOCIAL_MEDIA_COMMENT_LONG},
|
||||
{"rewriteCategoryTitle", IDS_AI_CHAT_CONTEXT_REWRITE},
|
||||
{"improveLabel", IDS_AI_CHAT_CONTEXT_IMPROVE},
|
||||
{"simplifyLabel", IDS_AI_CHAT_CONTEXT_SIMPLIFY},
|
||||
{"changeToneLabel", IDS_AI_CHAT_CONTEXT_CHANGE_TONE},
|
||||
{"changeLengthLabel", IDS_AI_CHAT_CONTEXT_CHANGE_LENGTH},
|
||||
{"academicizeLabel", IDS_AI_CHAT_CONTEXT_ACADEMICIZE},
|
||||
{"professionalizeLabel", IDS_AI_CHAT_CONTEXT_PROFESSIONALIZE},
|
||||
{"casualizeLabel", IDS_AI_CHAT_CONTEXT_CASUALIZE},
|
||||
{"funnyToneLabel", IDS_AI_CHAT_CONTEXT_FUNNY_TONE},
|
||||
{"shortenLabel", IDS_AI_CHAT_CONTEXT_SHORTEN},
|
||||
{"expandLabel", IDS_AI_CHAT_CONTEXT_EXPAND},
|
||||
{"sendSiteHostnameLabel", IDS_CHAT_UI_SEND_SITE_HOSTNAME_LABEL}};
|
||||
|
||||
return kLocalizedStrings;
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "base/containers/fixed_flat_set.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/no_destructor.h"
|
||||
#include "base/notreached.h"
|
||||
#include "base/one_shot_event.h"
|
||||
#include "base/ranges/algorithm.h"
|
||||
@@ -50,6 +51,48 @@ bool IsPremiumStatus(mojom::PremiumStatus status) {
|
||||
status == mojom::PremiumStatus::ActiveDisconnected;
|
||||
}
|
||||
|
||||
const base::flat_map<mojom::ActionType, std::string>&
|
||||
GetActionTypeQuestionMap() {
|
||||
static const base::NoDestructor<
|
||||
base::flat_map<mojom::ActionType, std::string>>
|
||||
map({{mojom::ActionType::SUMMARIZE_PAGE,
|
||||
l10n_util::GetStringUTF8(IDS_AI_CHAT_QUESTION_SUMMARIZE_PAGE)},
|
||||
{mojom::ActionType::SUMMARIZE_VIDEO,
|
||||
l10n_util::GetStringUTF8(IDS_AI_CHAT_QUESTION_SUMMARIZE_VIDEO)},
|
||||
{mojom::ActionType::SUMMARIZE_SELECTED_TEXT,
|
||||
l10n_util::GetStringUTF8(
|
||||
IDS_AI_CHAT_QUESTION_SUMMARIZE_SELECTED_TEXT)},
|
||||
{mojom::ActionType::EXPLAIN,
|
||||
l10n_util::GetStringUTF8(IDS_AI_CHAT_QUESTION_EXPLAIN)},
|
||||
{mojom::ActionType::PARAPHRASE,
|
||||
l10n_util::GetStringUTF8(IDS_AI_CHAT_QUESTION_PARAPHRASE)},
|
||||
{mojom::ActionType::CREATE_TAGLINE,
|
||||
l10n_util::GetStringUTF8(IDS_AI_CHAT_QUESTION_CREATE_TAGLINE)},
|
||||
{mojom::ActionType::CREATE_SOCIAL_MEDIA_COMMENT_SHORT,
|
||||
l10n_util::GetStringUTF8(
|
||||
IDS_AI_CHAT_QUESTION_CREATE_SOCIAL_MEDIA_COMMENT_SHORT)},
|
||||
{mojom::ActionType::CREATE_SOCIAL_MEDIA_COMMENT_LONG,
|
||||
l10n_util::GetStringUTF8(
|
||||
IDS_AI_CHAT_QUESTION_CREATE_SOCIAL_MEDIA_COMMENT_LONG)},
|
||||
{mojom::ActionType::IMPROVE,
|
||||
l10n_util::GetStringUTF8(IDS_AI_CHAT_QUESTION_IMPROVE)},
|
||||
{mojom::ActionType::SIMPLIFY,
|
||||
l10n_util::GetStringUTF8(IDS_AI_CHAT_QUESTION_SIMPLIFY)},
|
||||
{mojom::ActionType::PROFESSIONALIZE,
|
||||
l10n_util::GetStringUTF8(IDS_AI_CHAT_QUESTION_PROFESSIONALIZE)},
|
||||
{mojom::ActionType::CASUALIZE,
|
||||
l10n_util::GetStringUTF8(IDS_AI_CHAT_QUESTION_CASUALIZE)},
|
||||
{mojom::ActionType::FUNNY_TONE,
|
||||
l10n_util::GetStringUTF8(IDS_AI_CHAT_QUESTION_FUNNY_TONE)},
|
||||
{mojom::ActionType::ACADEMICIZE,
|
||||
l10n_util::GetStringUTF8(IDS_AI_CHAT_QUESTION_ACADEMICIZE)},
|
||||
{mojom::ActionType::SHORTEN,
|
||||
l10n_util::GetStringUTF8(IDS_AI_CHAT_QUESTION_SHORTEN)},
|
||||
{mojom::ActionType::EXPAND,
|
||||
l10n_util::GetStringUTF8(IDS_AI_CHAT_QUESTION_EXPAND)}});
|
||||
return *map;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ConversationDriver::ConversationDriver(
|
||||
@@ -607,13 +650,15 @@ void ConversationDriver::MaybeUnlinkPageContent() {
|
||||
}
|
||||
}
|
||||
|
||||
void ConversationDriver::SummarizeSelectedText(
|
||||
const std::string& selected_text) {
|
||||
mojom::ConversationTurn turn = {
|
||||
CharacterType::HUMAN, mojom::ActionType::SUMMARIZE_SELECTED_TEXT,
|
||||
ConversationTurnVisibility::VISIBLE,
|
||||
l10n_util::GetStringUTF8(IDS_CHAT_UI_SUMMARIZE_SELECTED_TEXT),
|
||||
selected_text};
|
||||
void ConversationDriver::SubmitSelectedText(const std::string& selected_text,
|
||||
mojom::ActionType action_type) {
|
||||
const auto& action_type_question_map = GetActionTypeQuestionMap();
|
||||
auto iter = action_type_question_map.find(action_type);
|
||||
DCHECK(iter != action_type_question_map.end());
|
||||
|
||||
mojom::ConversationTurn turn = {CharacterType::HUMAN, action_type,
|
||||
ConversationTurnVisibility::VISIBLE,
|
||||
iter->second, selected_text};
|
||||
SubmitHumanConversationEntry(turn);
|
||||
}
|
||||
|
||||
@@ -672,24 +717,22 @@ void ConversationDriver::SubmitHumanConversationEntry(
|
||||
// TODO(petemill): Tokenize the summary question so that we
|
||||
// don't have to do this weird substitution.
|
||||
// TODO(jocelyn): Assigning turn.type below is a workaround for now since
|
||||
// callers of SubmitHumanConversationEntry mojo API currently don't have
|
||||
// callers of SubmitHumanConversationEntry mojo API currently don't have
|
||||
// action_type specified.
|
||||
std::string question_part;
|
||||
if (turn.text == l10n_util::GetStringUTF8(IDS_CHAT_UI_SUMMARIZE_PAGE)) {
|
||||
turn.action_type = mojom::ActionType::SUMMARIZE_PAGE;
|
||||
question_part =
|
||||
l10n_util::GetStringUTF8(IDS_AI_CHAT_QUESTION_SUMMARIZE_PAGE);
|
||||
} else if (turn.text ==
|
||||
l10n_util::GetStringUTF8(IDS_CHAT_UI_SUMMARIZE_VIDEO)) {
|
||||
turn.action_type = mojom::ActionType::SUMMARIZE_VIDEO;
|
||||
question_part =
|
||||
l10n_util::GetStringUTF8(IDS_AI_CHAT_QUESTION_SUMMARIZE_VIDEO);
|
||||
} else if (turn.action_type == mojom::ActionType::SUMMARIZE_SELECTED_TEXT) {
|
||||
question_part =
|
||||
l10n_util::GetStringUTF8(IDS_AI_CHAT_QUESTION_SUMMARIZE_SELECTED_TEXT);
|
||||
} else {
|
||||
turn.action_type = mojom::ActionType::QUERY;
|
||||
question_part = turn.text;
|
||||
std::string question_part = turn.text;
|
||||
if (turn.action_type == mojom::ActionType::UNSPECIFIED) {
|
||||
if (turn.text == l10n_util::GetStringUTF8(IDS_CHAT_UI_SUMMARIZE_PAGE)) {
|
||||
turn.action_type = mojom::ActionType::SUMMARIZE_PAGE;
|
||||
question_part =
|
||||
l10n_util::GetStringUTF8(IDS_AI_CHAT_QUESTION_SUMMARIZE_PAGE);
|
||||
} else if (turn.text ==
|
||||
l10n_util::GetStringUTF8(IDS_CHAT_UI_SUMMARIZE_VIDEO)) {
|
||||
turn.action_type = mojom::ActionType::SUMMARIZE_VIDEO;
|
||||
question_part =
|
||||
l10n_util::GetStringUTF8(IDS_AI_CHAT_QUESTION_SUMMARIZE_VIDEO);
|
||||
} else {
|
||||
turn.action_type = mojom::ActionType::QUERY;
|
||||
}
|
||||
}
|
||||
|
||||
auto history = chat_history_;
|
||||
|
||||
@@ -106,8 +106,8 @@ class ConversationDriver {
|
||||
mojom::SiteInfoPtr BuildSiteInfo();
|
||||
bool HasPendingConversationEntry();
|
||||
|
||||
// Used to summarize the selected text in the page.
|
||||
void SummarizeSelectedText(const std::string& selected_text);
|
||||
void SubmitSelectedText(const std::string& selected_text,
|
||||
mojom::ActionType action_type);
|
||||
|
||||
void RateMessage(bool is_liked,
|
||||
uint32_t turn_id,
|
||||
|
||||
@@ -100,8 +100,6 @@ class ConversationDriverUnitTest : public testing::Test {
|
||||
&url_loader_factory_);
|
||||
auto skus_service_getter = base::BindRepeating(
|
||||
[]() { return mojo::PendingRemote<skus::mojom::SkusService>(); });
|
||||
// set prefs::kDefaultModelKey to llama or claude first, then change model
|
||||
// later
|
||||
conversation_driver_ = std::make_unique<MockConversationDriver>(
|
||||
&prefs_, &local_state_, nullptr, skus_service_getter,
|
||||
shared_url_loader_factory_, "");
|
||||
@@ -119,7 +117,7 @@ class ConversationDriverUnitTest : public testing::Test {
|
||||
std::unique_ptr<MockConversationDriver> conversation_driver_;
|
||||
};
|
||||
|
||||
TEST_F(ConversationDriverUnitTest, SummarizeSelectedText) {
|
||||
TEST_F(ConversationDriverUnitTest, SubmitSelectedText) {
|
||||
bool is_page_content_linked = false;
|
||||
url_loader_factory_.SetInterceptor(
|
||||
base::BindLambdaForTesting([&](const network::ResourceRequest& request) {
|
||||
@@ -158,8 +156,9 @@ TEST_F(ConversationDriverUnitTest, SummarizeSelectedText) {
|
||||
// Fired from OnEngineCompletionComplete.
|
||||
EXPECT_CALL(observer, OnAPIRequestInProgress(false)).Times(1);
|
||||
|
||||
conversation_driver_->SummarizeSelectedText(
|
||||
"<question><excerpt>I have spoken.</excerpt></question>");
|
||||
conversation_driver_->SubmitSelectedText(
|
||||
"<question><excerpt>I have spoken.</excerpt></question>",
|
||||
mojom::ActionType::SUMMARIZE_SELECTED_TEXT);
|
||||
|
||||
task_environment_.RunUntilIdle();
|
||||
testing::Mock::VerifyAndClearExpectations(&observer);
|
||||
@@ -172,10 +171,13 @@ TEST_F(ConversationDriverUnitTest, SummarizeSelectedText) {
|
||||
EXPECT_EQ(
|
||||
history,
|
||||
std::vector<mojom::ConversationTurn>(
|
||||
{mojom::ConversationTurn(mojom::CharacterType::HUMAN,
|
||||
mojom::ActionType::SUMMARIZE_SELECTED_TEXT,
|
||||
mojom::ConversationTurnVisibility::VISIBLE,
|
||||
"Summarize this excerpt", "I have spoken."),
|
||||
{mojom::ConversationTurn(
|
||||
mojom::CharacterType::HUMAN,
|
||||
mojom::ActionType::SUMMARIZE_SELECTED_TEXT,
|
||||
mojom::ConversationTurnVisibility::VISIBLE,
|
||||
l10n_util::GetStringUTF8(
|
||||
IDS_AI_CHAT_QUESTION_SUMMARIZE_SELECTED_TEXT),
|
||||
"I have spoken."),
|
||||
mojom::ConversationTurn(mojom::CharacterType::ASSISTANT,
|
||||
mojom::ActionType::RESPONSE,
|
||||
mojom::ConversationTurnVisibility::VISIBLE,
|
||||
@@ -198,8 +200,9 @@ TEST_F(ConversationDriverUnitTest, SummarizeSelectedText) {
|
||||
// Fired from OnEngineCompletionComplete.
|
||||
EXPECT_CALL(observer, OnAPIRequestInProgress(false)).Times(1);
|
||||
|
||||
conversation_driver_->SummarizeSelectedText(
|
||||
"<question><excerpt>I have spoken again.</excerpt></question>");
|
||||
conversation_driver_->SubmitSelectedText(
|
||||
"<question><excerpt>I have spoken again.</excerpt></question>",
|
||||
mojom::ActionType::SUMMARIZE_SELECTED_TEXT);
|
||||
|
||||
task_environment_.RunUntilIdle();
|
||||
testing::Mock::VerifyAndClearExpectations(&observer);
|
||||
@@ -211,19 +214,24 @@ TEST_F(ConversationDriverUnitTest, SummarizeSelectedText) {
|
||||
EXPECT_EQ(
|
||||
history2,
|
||||
std::vector<mojom::ConversationTurn>(
|
||||
{mojom::ConversationTurn(mojom::CharacterType::HUMAN,
|
||||
mojom::ActionType::SUMMARIZE_SELECTED_TEXT,
|
||||
mojom::ConversationTurnVisibility::VISIBLE,
|
||||
"Summarize this excerpt", "I have spoken."),
|
||||
{mojom::ConversationTurn(
|
||||
mojom::CharacterType::HUMAN,
|
||||
mojom::ActionType::SUMMARIZE_SELECTED_TEXT,
|
||||
mojom::ConversationTurnVisibility::VISIBLE,
|
||||
l10n_util::GetStringUTF8(
|
||||
IDS_AI_CHAT_QUESTION_SUMMARIZE_SELECTED_TEXT),
|
||||
"I have spoken."),
|
||||
mojom::ConversationTurn(mojom::CharacterType::ASSISTANT,
|
||||
mojom::ActionType::RESPONSE,
|
||||
mojom::ConversationTurnVisibility::VISIBLE,
|
||||
"This is the way.", std::nullopt),
|
||||
mojom::ConversationTurn(mojom::CharacterType::HUMAN,
|
||||
mojom::ActionType::SUMMARIZE_SELECTED_TEXT,
|
||||
mojom::ConversationTurnVisibility::VISIBLE,
|
||||
"Summarize this excerpt",
|
||||
"I have spoken again."),
|
||||
mojom::ConversationTurn(
|
||||
mojom::CharacterType::HUMAN,
|
||||
mojom::ActionType::SUMMARIZE_SELECTED_TEXT,
|
||||
mojom::ConversationTurnVisibility::VISIBLE,
|
||||
l10n_util::GetStringUTF8(
|
||||
IDS_AI_CHAT_QUESTION_SUMMARIZE_SELECTED_TEXT),
|
||||
"I have spoken again."),
|
||||
mojom::ConversationTurn(mojom::CharacterType::ASSISTANT,
|
||||
mojom::ActionType::RESPONSE,
|
||||
mojom::ConversationTurnVisibility::VISIBLE,
|
||||
|
||||
@@ -81,13 +81,13 @@ TEST_F(EngineConsumerClaudeUnitTest, TestGenerateAssistantResponse) {
|
||||
"coding-related words and triple backticks along with language keyword "
|
||||
"(```language```) to wrap blocks of code or data.\n\nHere is the "
|
||||
"conversational history (between the user and you) prior to the "
|
||||
"question.\n<history>\n\nH: Which show is this catchphrase "
|
||||
"request.\n<history>\n\nH: Which show is this catchphrase "
|
||||
"from?\nSelected text: I have spoken.\n\nA: The "
|
||||
"Mandalorian.\n</history>\n\nHere is an excerpt of the page content in "
|
||||
"<excerpt> tags:\n<excerpt>\nI'm groot.\n</excerpt>\n\nThe user selects "
|
||||
"this excerpt from the page content.\n\nHere is the user's question "
|
||||
"about the excerpt:\n<question>\nWho?\n</question>\n\nHow do you respond "
|
||||
"to the user's question? Put your response in <response></response> "
|
||||
"this excerpt from the page content.\n\nHere is the user's request "
|
||||
"about the excerpt:\n<request>\nWho?\n</request>\n\nHow do you respond "
|
||||
"to the user's request? Put your response in <response></response> "
|
||||
"tags.\n\nAssistant: <response>\n";
|
||||
|
||||
base::RunLoop run_loop;
|
||||
@@ -129,7 +129,7 @@ TEST_F(EngineConsumerClaudeUnitTest, TestGenerateAssistantResponse) {
|
||||
std::move(callback).Run("");
|
||||
});
|
||||
engine_->GenerateAssistantResponse(
|
||||
false, "12345", "12345", history, "user question", base::DoNothing(),
|
||||
false, "12345", "12345", history, "user request", base::DoNothing(),
|
||||
base::BindLambdaForTesting(
|
||||
[&run_loop2](EngineConsumer::GenerationResult) {
|
||||
run_loop2.Quit();
|
||||
@@ -147,8 +147,8 @@ TEST_F(EngineConsumerClaudeUnitTest, TestGenerateAssistantResponse) {
|
||||
"");
|
||||
base::ReplaceFirstSubstringAfterOffset(
|
||||
&prompt_after_time_and_date, 0u,
|
||||
"Here is the user's question about the excerpt",
|
||||
"Here is the user's question");
|
||||
"Here is the user's request about the excerpt",
|
||||
"Here is the user's request");
|
||||
|
||||
base::RunLoop run_loop3;
|
||||
EXPECT_CALL(*mock_remote_completion_client, QueryPrompt(_, _, _, _))
|
||||
|
||||
@@ -74,12 +74,12 @@ TEST_F(EngineConsumerLlamaUnitTest, TestGenerateAssistantResponse) {
|
||||
"information.\n\nUse unicode symbols for formatting where appropriate. "
|
||||
"Use backticks (`) to wrap inline coding-related words and triple "
|
||||
"backticks along with language keyword (```language```) to wrap blocks "
|
||||
"of code or data.\n<</SYS>>\n\nThis is the text of a web page within "
|
||||
"<page> tags:\n\n<page> This is a page. </page>\n\nWhich show is this "
|
||||
"of code or data.\n<</SYS>>\n\nThis is the text of a web "
|
||||
"page:\n<page>\nThis is a page.\n</page>\n\nWhich show is this "
|
||||
"catchphrase from?\nSelected text: This is the way. [/INST] The "
|
||||
"Mandalorian.</s><s>[INST] This is an excerpt of the page content in "
|
||||
"<excerpt> tags:\n\n<excerpt> I'm groot. </excerpt>\n\nWhat's his name? "
|
||||
"[/INST]";
|
||||
"Mandalorian.</s><s>[INST] This is an excerpt of the page "
|
||||
"content:\n<excerpt>\nI'm groot.\n</excerpt>\n\nWhat's his name? [/INST]";
|
||||
|
||||
base::RunLoop run_loop;
|
||||
EXPECT_CALL(*mock_remote_completion_client, QueryPrompt(_, _, _, _))
|
||||
.WillOnce([&](const std::string& prompt,
|
||||
@@ -99,12 +99,22 @@ TEST_F(EngineConsumerLlamaUnitTest, TestGenerateAssistantResponse) {
|
||||
testing::Mock::VerifyAndClearExpectations(mock_remote_completion_client);
|
||||
|
||||
prompt_after_time_and_date =
|
||||
"\n\nYour name is Leo, a helpful, respectful and honest AI assistant "
|
||||
"created by the company Brave. You will be replying to a user of the "
|
||||
"Brave browser. Always respond in a neutral tone. Be polite and "
|
||||
"courteous. Answer concisely in no more than 50-80 words.\n\nPlease "
|
||||
"ensure that your responses are socially unbiased and positive in "
|
||||
"nature. If a question does not make any sense, or is not factually "
|
||||
"coherent, explain why instead of answering something not correct. If "
|
||||
"you don't know the answer to a question, please don't share false "
|
||||
"information.\n\nUse unicode symbols for formatting where appropriate. "
|
||||
"Use backticks (`) to wrap inline coding-related words and triple "
|
||||
"backticks along with language keyword (```language```) to wrap blocks "
|
||||
"of code or data.\n<</SYS>>\n\nThis is the text of a web page within "
|
||||
"<page> tags:\n\n<page> This is a page. </page>\n\nThis is an excerpt "
|
||||
"of the page content in <excerpt> tags:\n\n<excerpt> I'm groot. "
|
||||
"</excerpt>\n\nWhat's his name? [/INST] ";
|
||||
"of code or data.\n<</SYS>>\n\nThis is the text of a web "
|
||||
"page:\n<page>\nThis is a page.\n</page>\n\nThis is an excerpt of the "
|
||||
"page content:\n<excerpt>\nI'm groot.\n</excerpt>\n\nWhat's his name? "
|
||||
"[/INST] ";
|
||||
|
||||
base::RunLoop run_loop2;
|
||||
EXPECT_CALL(*mock_remote_completion_client, QueryPrompt(_, _, _, _))
|
||||
.WillOnce([&](const std::string& prompt,
|
||||
@@ -133,14 +143,13 @@ TEST_F(EngineConsumerLlamaUnitTest, TestGenerateAssistantResponse) {
|
||||
EngineConsumer::GenerationCompletedCallback callback,
|
||||
EngineConsumer::GenerationDataCallback data_callback) {
|
||||
std::string prompt_segment_with_truncated_page_content =
|
||||
"This is the text of a web page within <page> tags:\n\n<page> 12 "
|
||||
"</page>\n\n";
|
||||
"This is the text of a web page:\n<page>\n12\n</page>\n\n";
|
||||
|
||||
EXPECT_NE(prompt.find(prompt_segment_with_truncated_page_content),
|
||||
std::string::npos);
|
||||
std::string prompt_segment_with_truncated_selected_text =
|
||||
"This is an excerpt of the page content in <excerpt> "
|
||||
"tags:\n\n<excerpt> 12345 </excerpt>\n\n";
|
||||
"This is an excerpt of the page "
|
||||
"content:\n<excerpt>\n12345\n</excerpt>\n\n";
|
||||
EXPECT_NE(prompt.find(prompt_segment_with_truncated_selected_text),
|
||||
std::string::npos);
|
||||
std::move(callback).Run("");
|
||||
|
||||
@@ -86,6 +86,19 @@ enum ActionType {
|
||||
SUMMARIZE_VIDEO,
|
||||
SUMMARIZE_SELECTED_TEXT,
|
||||
QUERY,
|
||||
EXPLAIN,
|
||||
PARAPHRASE,
|
||||
CREATE_TAGLINE,
|
||||
CREATE_SOCIAL_MEDIA_COMMENT_SHORT,
|
||||
CREATE_SOCIAL_MEDIA_COMMENT_LONG,
|
||||
IMPROVE,
|
||||
SIMPLIFY,
|
||||
ACADEMICIZE,
|
||||
PROFESSIONALIZE,
|
||||
CASUALIZE,
|
||||
FUNNY_TONE,
|
||||
SHORTEN,
|
||||
EXPAND,
|
||||
};
|
||||
|
||||
// Represents a single turn in a conversation.
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
/* Copyright (c) 2024 The Brave Authors. All rights reserved.
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import * as React from 'react'
|
||||
import Icon from '@brave/leo/react/icon'
|
||||
import * as mojom from '../../api/page_handler'
|
||||
import styles from './style.module.scss'
|
||||
import { getLocale } from '$web-common/locale'
|
||||
|
||||
interface ActionTypeLabelProps {
|
||||
actionType: mojom.ActionType
|
||||
}
|
||||
|
||||
function getCategoryAndItem(actionType: mojom.ActionType): {
|
||||
category: string | undefined, item: string | undefined
|
||||
} {
|
||||
switch (actionType) {
|
||||
case mojom.ActionType.SUMMARIZE_SELECTED_TEXT:
|
||||
return { category: undefined, item: getLocale('summarizeLabel')}
|
||||
case mojom.ActionType.EXPLAIN:
|
||||
return { category: undefined, item: getLocale('explainLabel')}
|
||||
case mojom.ActionType.CREATE_TAGLINE:
|
||||
return {
|
||||
category: getLocale('createCategoryTitle'),
|
||||
item: getLocale('taglineLabel')
|
||||
}
|
||||
case mojom.ActionType.CREATE_SOCIAL_MEDIA_COMMENT_SHORT:
|
||||
return {
|
||||
category: getLocale('socialMediaPostLabel'),
|
||||
item: getLocale('socialMediaShortLabel')
|
||||
}
|
||||
case mojom.ActionType.CREATE_SOCIAL_MEDIA_COMMENT_LONG:
|
||||
return {
|
||||
category: getLocale('socialMediaPostLabel'),
|
||||
item: getLocale('socialMediaLongLabel')
|
||||
}
|
||||
case mojom.ActionType.PARAPHRASE:
|
||||
return {
|
||||
category: getLocale('rewriteCategoryTitle'),
|
||||
item: getLocale('paraphraseLabel')
|
||||
}
|
||||
case mojom.ActionType.IMPROVE:
|
||||
return {
|
||||
category: getLocale('rewriteCategoryTitle'),
|
||||
item: getLocale('improveLabel')
|
||||
}
|
||||
case mojom.ActionType.SIMPLIFY:
|
||||
return {
|
||||
category: getLocale('rewriteCategoryTitle'),
|
||||
item: getLocale('simplifyLabel')
|
||||
}
|
||||
case mojom.ActionType.ACADEMICIZE:
|
||||
return {
|
||||
category: getLocale('changeToneLabel'),
|
||||
item: getLocale('academicizeLabel')
|
||||
}
|
||||
case mojom.ActionType.PROFESSIONALIZE:
|
||||
return {
|
||||
category: getLocale('changeToneLabel'),
|
||||
item: getLocale('professionalizeLabel')
|
||||
}
|
||||
case mojom.ActionType.CASUALIZE:
|
||||
return {
|
||||
category: getLocale('changeToneLabel'),
|
||||
item: getLocale('casualizeLabel')
|
||||
}
|
||||
case mojom.ActionType.FUNNY_TONE:
|
||||
return {
|
||||
category: getLocale('changeToneLabel'),
|
||||
item: getLocale('funnyToneLabel')
|
||||
}
|
||||
case mojom.ActionType.SHORTEN:
|
||||
return {
|
||||
category: getLocale('changeLengthLabel'),
|
||||
item: getLocale('shortenLabel')
|
||||
}
|
||||
case mojom.ActionType.EXPAND:
|
||||
return {
|
||||
category: getLocale('changeLengthLabel'),
|
||||
item: getLocale('expandLabel')
|
||||
}
|
||||
default:
|
||||
return { category: undefined, item: undefined }
|
||||
}
|
||||
}
|
||||
|
||||
function ActionTypeLabel (props: ActionTypeLabelProps) {
|
||||
const { category, item } = getCategoryAndItem(props.actionType)
|
||||
|
||||
if (category && item) {
|
||||
return (
|
||||
<div className={styles.actionTypeLabel}>
|
||||
<span className={styles.text}>{category}</span>
|
||||
<Icon name='carat-right' />
|
||||
<span className={styles.text}>{item}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={styles.actionTypeLabel}>
|
||||
<span className={styles.text}>{item}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ActionTypeLabel
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) 2024 The Brave Authors. All rights reserved.
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// you can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
.actionTypeLabel {
|
||||
--leo-icon-size: 14px;
|
||||
--leo-icon-color: var(--leo-color-primary-50);
|
||||
display: inline-flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 0px 4px;
|
||||
width: fit-content;
|
||||
height: 20px;
|
||||
background: var(--leo-color-primary-20);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.text {
|
||||
font: var(--leo-font-components-label);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
text-transform: uppercase;
|
||||
color: var(--leo-color-primary-50);
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import ContextMenuAssistant from '../context_menu_assistant'
|
||||
import { getLocale } from '$web-common/locale'
|
||||
import SiteTitle from '../site_title'
|
||||
import Quote from '../quote'
|
||||
import ActionTypeLabel from '../action_type_label'
|
||||
|
||||
const CodeBlock = React.lazy(async () => ({ default: (await import('../code_block')).default.Block }))
|
||||
const CodeInline = React.lazy(async () => ({ default: (await import('../code_block')).default.Inline }))
|
||||
@@ -168,7 +169,10 @@ function ConversationList(props: ConversationListProps) {
|
||||
<div
|
||||
className={styles.message}
|
||||
>
|
||||
{<FormattedTextRenderer text={turn.text} />}
|
||||
{!turn.selectedText &&
|
||||
<FormattedTextRenderer text={turn.text} />}
|
||||
{turn.selectedText &&
|
||||
<ActionTypeLabel actionType={turn.actionType} />}
|
||||
{isLoading && <span className={styles.caret} />}
|
||||
{turn.selectedText && <Quote text={turn.selectedText} />}
|
||||
{showSiteTitle && <div className={styles.siteTitleContainer}><SiteTitle size="default" /></div>}
|
||||
|
||||
@@ -15,25 +15,24 @@
|
||||
|
||||
.text::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 3px;
|
||||
height: 100%;
|
||||
background: var(--leo-color-divider-strong);
|
||||
border-radius: 2px;
|
||||
margin-right: 12px;
|
||||
flex: none;
|
||||
order: 0;
|
||||
align-self: stretch;
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
.text {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 4;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
word-wrap: break-word;
|
||||
position: relative;
|
||||
padding-left: 18px;
|
||||
letter-spacing: -0.1px;
|
||||
color: var(--leo-color-text-secondary);
|
||||
flex: none;
|
||||
order: 1;
|
||||
align-self: stretch;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,21 +25,21 @@ const HISTORY: mojom.ConversationTurn[] = [
|
||||
characterType: mojom.CharacterType.HUMAN,
|
||||
visibility: mojom.ConversationTurnVisibility.VISIBLE,
|
||||
actionType: mojom.ActionType.UNSPECIFIED,
|
||||
selectedText: ''
|
||||
selectedText: undefined
|
||||
},
|
||||
{
|
||||
text: 'Hi, How are you?',
|
||||
characterType: mojom.CharacterType.ASSISTANT,
|
||||
visibility: mojom.ConversationTurnVisibility.VISIBLE,
|
||||
actionType: mojom.ActionType.UNSPECIFIED,
|
||||
selectedText: ''
|
||||
selectedText: undefined
|
||||
},
|
||||
{
|
||||
text: 'What is pointer compression?',
|
||||
characterType: mojom.CharacterType.HUMAN,
|
||||
actionType: mojom.ActionType.QUERY,
|
||||
visibility: mojom.ConversationTurnVisibility.VISIBLE,
|
||||
selectedText: 'Pointer compression is a memory optimization technique where pointers (memory addresses) are stored in a compressed format to save memory.'
|
||||
selectedText: undefined
|
||||
},
|
||||
{
|
||||
text: 'Pointer compression is a memory optimization technique where pointers (memory addresses) are stored in a compressed format to save memory. The basic idea is that since most pointers will be clustered together and point to objects allocated around the same time, you can store a compressed representation of the pointer and decompress it when needed. Some common ways this is done: Store an offset from a base pointer instead of the full pointer value Store increments/decrements from the previous pointer instead of the full value Use pointer tagging to store extra information in the low bits of the pointer Encode groups of pointers together The tradeoff is some extra CPU cost to decompress the pointers, versus saving memory. This technique is most useful in memory constrained environments.',
|
||||
@@ -90,6 +90,20 @@ const HISTORY: mojom.ConversationTurn[] = [
|
||||
visibility: mojom.ConversationTurnVisibility.VISIBLE,
|
||||
selectedText: undefined
|
||||
},
|
||||
{
|
||||
text: 'Shorten this selected text',
|
||||
characterType: mojom.CharacterType.HUMAN,
|
||||
actionType: mojom.ActionType.SHORTEN,
|
||||
visibility: mojom.ConversationTurnVisibility.VISIBLE,
|
||||
selectedText: 'Pointer compression is a memory optimization technique where pointers are stored in a compressed format to save memory.'
|
||||
},
|
||||
{
|
||||
text: 'Pointer compression is a memory optimization technique.',
|
||||
characterType: mojom.CharacterType.ASSISTANT,
|
||||
actionType: mojom.ActionType.UNSPECIFIED,
|
||||
visibility: mojom.ConversationTurnVisibility.VISIBLE,
|
||||
selectedText: undefined
|
||||
}
|
||||
]
|
||||
|
||||
const MODELS: mojom.Model[] = [
|
||||
|
||||
@@ -87,4 +87,7 @@ provideStrings({
|
||||
contextToggleLabel: 'Use page context for response',
|
||||
contextToggleTooltipInfo: 'Toggle on to ask about this page. It\'s content will be sent to Brave Leo along with your messages.',
|
||||
subscriptionPolicyInfo: 'All subscriptions are auto-renewed but can be cancelled at any time before renewal.',
|
||||
summarizeLabel: 'Summarize',
|
||||
changeLengthLabel: 'Change length',
|
||||
shortenLabel: 'Shorten',
|
||||
})
|
||||
|
||||
@@ -18,21 +18,21 @@ Here are some important rules for the interaction:
|
||||
</message>
|
||||
|
||||
<message name="IDS_AI_CHAT_CLAUDE_SYSTEM_MESSAGE_PART2" translateable="false">
|
||||
Here is the user's question:
|
||||
<question>
|
||||
Here is the user's request:
|
||||
<request>
|
||||
<ph name="QUESTION">$1</ph>
|
||||
</question>
|
||||
</request>
|
||||
</message>
|
||||
|
||||
<message name="IDS_AI_CHAT_CLAUDE_SYSTEM_MESSAGE_PART2_WITH_EXCERPT" translateable="false">
|
||||
Here is the user's question about the excerpt:
|
||||
<question>
|
||||
Here is the user's request about the excerpt:
|
||||
<request>
|
||||
<ph name="QUESTION">$1</ph>
|
||||
</question>
|
||||
</request>
|
||||
</message>
|
||||
|
||||
<message name="IDS_AI_CHAT_CLAUDE_SYSTEM_MESSAGE_PART3" translateable="false">
|
||||
How do you respond to the user's question? Put your response in <response></response> tags.</message>
|
||||
How do you respond to the user's request? Put your response in <response></response> tags.</message>
|
||||
|
||||
<message name="IDS_AI_CHAT_CLAUDE_ARTICLE_PROMPT_SEGMENT" translateable="false">Here is the text of a web page in <page> tags:
|
||||
<page>
|
||||
@@ -57,7 +57,7 @@ The user selects this excerpt from the page content.
|
||||
A user is watching this video.</message>
|
||||
|
||||
<message name="IDS_AI_CHAT_CLAUDE_HISTORY_PROMPT_SEGMENT" translateable="false">
|
||||
Here is the conversational history (between the user and you) prior to the question.
|
||||
Here is the conversational history (between the user and you) prior to the request.
|
||||
<history>
|
||||
<ph name="HISTORY">$1</ph>
|
||||
</history></message>
|
||||
@@ -66,8 +66,21 @@ Here is the conversational history (between the user and you) prior to the quest
|
||||
Propose up to 3 very short questions that a reader may ask about the content. Consider intriguing or unusual elements of the content, or structurally important. Separate each suggested question with the character "|". End the question list with a </response> tag.</message>
|
||||
|
||||
<message name="IDS_AI_CHAT_QUESTION_SUMMARIZE_PAGE" translateable="false">Provide a concise list of up to 6 bullets on the most important points of the page.</message>
|
||||
<message name="IDS_AI_CHAT_QUESTION_SUMMARIZE_SELECTED_TEXT" translateable="false">Summarize the excerpt</message>
|
||||
<message name="IDS_AI_CHAT_QUESTION_SUMMARIZE_SELECTED_TEXT" translateable="false">Generate a summary of the excerpt.</message>
|
||||
<message name="IDS_AI_CHAT_QUESTION_SUMMARIZE_VIDEO" translateable="false">Provide a concise list of up to 6 bullets of the most important points of the video.</message>
|
||||
<message name="IDS_AI_CHAT_QUESTION_EXPLAIN" translateable="false">Explain the excerpt in simple terms. Expand on concepts that might not be familiar to the user.</message>
|
||||
<message name="IDS_AI_CHAT_QUESTION_PARAPHRASE" translateable="false">Rewrite the excerpt by paraphrasing. Include only the rewritten version in your response.</message>
|
||||
<message name="IDS_AI_CHAT_QUESTION_CREATE_TAGLINE" translateable="false">Use the excerpt to generate a tagline.</message>
|
||||
<message name="IDS_AI_CHAT_QUESTION_CREATE_SOCIAL_MEDIA_COMMENT_SHORT" translateable="false">Use the excerpt to generate a post that could be used on social platforms like Twitter.</message>
|
||||
<message name="IDS_AI_CHAT_QUESTION_CREATE_SOCIAL_MEDIA_COMMENT_LONG" translateable="false">Use the excerpt to generate a post that could be used on social platforms like Reddit.</message>
|
||||
<message name="IDS_AI_CHAT_QUESTION_IMPROVE" translateable="false">Improve the language of the excerpt. Include only the rewritten version in your response.</message>
|
||||
<message name="IDS_AI_CHAT_QUESTION_SIMPLIFY" translateable="false">Rewrite the excerpt in simpler terms so that it is easier to understand for a general audience. Include only the rewritten version in your response.</message>
|
||||
<message name="IDS_AI_CHAT_QUESTION_ACADEMICIZE" translateable="false">Rewrite the excerpt in an academic tone. Include only the rewritten version in your response.</message>
|
||||
<message name="IDS_AI_CHAT_QUESTION_PROFESSIONALIZE" translateable="false">Rewrite the excerpt in a professional tone. Include only the rewritten version in your response.</message>
|
||||
<message name="IDS_AI_CHAT_QUESTION_CASUALIZE" translateable="false">Rewrite the excerpt in a casual tone. Include only the rewritten version in your response.</message>
|
||||
<message name="IDS_AI_CHAT_QUESTION_FUNNY_TONE" translateable="false">Rewrite the excerpt in a funny tone. Include only the rewritten version in your response.</message>
|
||||
<message name="IDS_AI_CHAT_QUESTION_SHORTEN" translateable="false">Generate a shortened version of the excerpt in paragraph format by removing unnecessary details and refining the language for brevity. Include only the rewritten version in your response.</message>
|
||||
<message name="IDS_AI_CHAT_QUESTION_EXPAND" translateable="false">Generate a lengthened version of the excerpt in paragraph format by expanding on the details provided and adding more descriptive information where applicable. Include only the rewritten version in your response.</message>
|
||||
|
||||
<message name="IDS_AI_CHAT_LLAMA2_SYSTEM_MESSAGE_GENERIC" translateable="false">
|
||||
The current time and date is <ph name="DATE">$1</ph>
|
||||
@@ -83,15 +96,17 @@ Use unicode symbols for formatting where appropriate. Use backticks (`) to wrap
|
||||
Here is your response:</message>
|
||||
|
||||
<message name="IDS_AI_CHAT_LLAMA2_SELECTED_TEXT_PROMPT_SEGMENT" translateable="false">
|
||||
This is an excerpt of the page content in <excerpt> tags:
|
||||
|
||||
<excerpt> <ph name="EXCERPT">$1</ph> </excerpt>
|
||||
This is an excerpt of the page content:
|
||||
<excerpt>
|
||||
<ph name="EXCERPT">$1</ph>
|
||||
</excerpt>
|
||||
</message>
|
||||
|
||||
<message name="IDS_AI_CHAT_LLAMA2_ARTICLE_PROMPT_SEGMENT" translateable="false">
|
||||
This is the text of a web page within <page> tags:
|
||||
|
||||
<page> <ph name="ARTICLE">$1</ph> </page>
|
||||
This is the text of a web page:
|
||||
<page>
|
||||
<ph name="ARTICLE">$1</ph>
|
||||
</page>
|
||||
|
||||
<ph name= "USER_PROMPT">$2</ph>
|
||||
</message>
|
||||
|
||||
@@ -36,9 +36,6 @@
|
||||
<message name="IDS_CHAT_UI_SUMMARIZE_PAGE" desc="Button to summarize the article on the current page">
|
||||
Summarize this page
|
||||
</message>
|
||||
<message name="IDS_CHAT_UI_SUMMARIZE_SELECTED_TEXT" desc="Text for summarizing selected text">
|
||||
Summarize this excerpt
|
||||
</message>
|
||||
<message name="IDS_CHAT_UI_PAGE_CONTENT_WARNING" desc="Description about page content being sent to a remote LLM">
|
||||
Disconnect to stop sending this page content to Leo, and start a new conversation
|
||||
</message>
|
||||
@@ -267,4 +264,70 @@
|
||||
<message name="IDS_CHAT_UI_SEND_SITE_HOSTNAME_LABEL" desc="A checkbox label to opt-in or out for sending current tab's url">
|
||||
Share the hostname of the page you are on (<ph name="HOST_NAME">$1<ex>www.example.com</ex></ph>) to help us make Leo better.
|
||||
</message>
|
||||
<message name="IDS_AI_CHAT_CONTEXT_LEO_TOOLS" desc="The text label of Leo tools submenu in the context menu">
|
||||
Leo tools
|
||||
</message>
|
||||
<message name="IDS_AI_CHAT_CONTEXT_QUICK_ACTIONS" desc="The title of the context menu section for AI quick actions">
|
||||
Quick actions
|
||||
</message>
|
||||
<message name="IDS_AI_CHAT_CONTEXT_CREATE" desc="The title of the context menu section for AI creation tools">
|
||||
Create
|
||||
</message>
|
||||
<message name="IDS_AI_CHAT_CONTEXT_REWRITE" desc="The title of the context menu section for AI rewrite tools">
|
||||
Rewrite
|
||||
</message>
|
||||
<message name="IDS_AI_CHAT_CONTEXT_SUMMARIZE_TEXT" desc="The text label of context menu item to summarize selected text">
|
||||
Summarize
|
||||
</message>
|
||||
<message name="IDS_AI_CHAT_CONTEXT_CREATE_SOCIAL_MEDIA_COMMENT_SHORT" desc="The text label of context menu item to create a short social media post using selected text">
|
||||
Short
|
||||
</message>
|
||||
<message name="IDS_AI_CHAT_CONTEXT_CREATE_SOCIAL_MEDIA_COMMENT_LONG" desc="The text label of context menu item to create a long social media post using selected text">
|
||||
Long
|
||||
</message>
|
||||
<message name="IDS_AI_CHAT_CONTEXT_CREATE_BLOG_POST" desc="The text label of context menu item to create a blog post using selected text">
|
||||
Blog post
|
||||
</message>
|
||||
<message name="IDS_AI_CHAT_CONTEXT_CREATE_TAGLINE" desc="The text label of context menu item to create a tagline using selected text">
|
||||
Tagline
|
||||
</message>
|
||||
<message name="IDS_AI_CHAT_CONTEXT_PARAPHRASE" desc="The text label of context menu item to paraphrase selected text">
|
||||
Paraphrase
|
||||
</message>
|
||||
<message name="IDS_AI_CHAT_CONTEXT_EXPLAIN" desc="The text label of context menu item to explain selected text">
|
||||
Explain
|
||||
</message>
|
||||
<message name="IDS_AI_CHAT_CONTEXT_IMPROVE" desc="The text label of context menu item to improve selected text">
|
||||
Improve
|
||||
</message>
|
||||
<message name="IDS_AI_CHAT_CONTEXT_SIMPLIFY" desc="The text label of context menu item to simplify selected text">
|
||||
Simplify
|
||||
</message>
|
||||
<message name="IDS_AI_CHAT_CONTEXT_CHANGE_TONE" desc="The text label of submenu for changing the tone of selected text">
|
||||
Change tone
|
||||
</message>
|
||||
<message name="IDS_AI_CHAT_CONTEXT_PROFESSIONALIZE" desc="The text label of context menu item to professionalize selected text">
|
||||
Professional
|
||||
</message>
|
||||
<message name="IDS_AI_CHAT_CONTEXT_ACADEMICIZE" desc="The text label of context menu item to academicize selected text">
|
||||
Academic
|
||||
</message>
|
||||
<message name="IDS_AI_CHAT_CONTEXT_CASUALIZE" desc="The text label of context menu item to casualize selected text">
|
||||
Casual
|
||||
</message>
|
||||
<message name="IDS_AI_CHAT_CONTEXT_FUNNY_TONE" desc="The text label of context menu item to rewrite the selected text in a funny tone">
|
||||
Funny
|
||||
</message>
|
||||
<message name="IDS_AI_CHAT_CONTEXT_SHORTEN" desc="The text label of context menu item to shorten selected text">
|
||||
Shorten
|
||||
</message>
|
||||
<message name="IDS_AI_CHAT_CONTEXT_EXPAND" desc="The text label of context menu item to expand selected text">
|
||||
Expand
|
||||
</message>
|
||||
<message name="IDS_AI_CHAT_CONTEXT_CHANGE_LENGTH" desc="The text label of submenu for changing the length of selected text">
|
||||
Change length
|
||||
</message>
|
||||
<message name="IDS_AI_CHAT_CONTEXT_CREATE_SOCIAL_MEDIA_POST" desc="The text label of submenu for creating social media posts using selected text">
|
||||
Social media post
|
||||
</message>
|
||||
</grit-part>
|
||||
|
||||
Reference in New Issue
Block a user