diff --git a/browser/ui/webui/ai_chat/ai_chat_ui_page_handler.cc b/browser/ui/webui/ai_chat/ai_chat_ui_page_handler.cc index 505df5a78a74..a6ce4cbfc680 100644 --- a/browser/ui/webui/ai_chat/ai_chat_ui_page_handler.cc +++ b/browser/ui/webui/ai_chat/ai_chat_ui_page_handler.cc @@ -273,10 +273,9 @@ void AIChatUIPageHandler::BindParentUIFrameFromChildFrame( void AIChatUIPageHandler::GetFaviconImageDataForAssociatedContent( GetFaviconImageDataCallback callback, - mojom::SiteInfoPtr content_info, + mojom::AssociatedContentPtr content_info, bool should_send_page_contents) { - if (!content_info->is_content_association_possible || - !content_info->url.has_value() || !content_info->url->is_valid()) { + if (!content_info || !content_info->url.is_valid()) { std::move(callback).Run(std::nullopt); return; } @@ -297,7 +296,7 @@ void AIChatUIPageHandler::GetFaviconImageDataForAssociatedContent( }; favicon_service_->GetRawFaviconForPageURL( - content_info->url.value(), icon_types, kDesiredFaviconSizePixels, true, + content_info->url, icon_types, kDesiredFaviconSizePixels, true, base::BindOnce(on_favicon_available, std::move(callback)), &favicon_task_tracker_); } diff --git a/browser/ui/webui/ai_chat/ai_chat_ui_page_handler.h b/browser/ui/webui/ai_chat/ai_chat_ui_page_handler.h index a8fa5d418829..e695b8e5a3b6 100644 --- a/browser/ui/webui/ai_chat/ai_chat_ui_page_handler.h +++ b/browser/ui/webui/ai_chat/ai_chat_ui_page_handler.h @@ -90,7 +90,7 @@ class AIChatUIPageHandler : public mojom::AIChatUIHandler, void GetFaviconImageDataForAssociatedContent( GetFaviconImageDataCallback callback, - mojom::SiteInfoPtr content_info, + mojom::AssociatedContentPtr content_info, bool should_send_page_contents); raw_ptr active_chat_tab_helper_ = nullptr; diff --git a/components/ai_chat/core/browser/ai_chat_database.cc b/components/ai_chat/core/browser/ai_chat_database.cc index dbe97c31c9da..3dd30f10caf4 100644 --- a/components/ai_chat/core/browser/ai_chat_database.cc +++ b/components/ai_chat/core/browser/ai_chat_database.cc @@ -194,14 +194,12 @@ std::vector AIChatDatabase::GetAllConversations() { conversation->updated_time = statement.ColumnTime(index++); conversation->has_content = true; - conversation->associated_content = mojom::SiteInfo::New(); - if (statement.GetColumnType(index) != sql::ColumnType::kNull) { DVLOG(1) << __func__ << " got associated content"; - + conversation->associated_content = mojom::AssociatedContent::New(); conversation->associated_content->uuid = statement.ColumnString(index++); conversation->associated_content->title = - DecryptOptionalColumnToString(statement, index++); + DecryptOptionalColumnToString(statement, index++).value_or(""); auto url_raw = DecryptOptionalColumnToString(statement, index++); if (url_raw.has_value()) { conversation->associated_content->url = GURL(url_raw.value()); @@ -212,9 +210,6 @@ std::vector AIChatDatabase::GetAllConversations() { statement.ColumnInt(index++); conversation->associated_content->is_content_refined = statement.ColumnBool(index++); - conversation->associated_content->is_content_association_possible = true; - } else { - conversation->associated_content->is_content_association_possible = false; } } @@ -426,10 +421,10 @@ bool AIChatDatabase::AddConversation(mojom::ConversationPtr conversation, return false; } - if (conversation->associated_content->is_content_association_possible) { + if (conversation->associated_content) { DVLOG(2) << "Adding associated content for conversation " << conversation->uuid << " with url " - << conversation->associated_content->url->spec(); + << conversation->associated_content->url.spec(); if (!AddOrUpdateAssociatedContent( conversation->uuid, std::move(conversation->associated_content), contents)) { @@ -452,7 +447,7 @@ bool AIChatDatabase::AddConversation(mojom::ConversationPtr conversation, bool AIChatDatabase::AddOrUpdateAssociatedContent( std::string_view conversation_uuid, - mojom::SiteInfoPtr associated_content, + mojom::AssociatedContentPtr associated_content, std::optional contents) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!LazyInit()) { @@ -461,7 +456,7 @@ bool AIChatDatabase::AddOrUpdateAssociatedContent( // TODO(petemill): handle multiple associated content per conversation CHECK(!conversation_uuid.empty()); - CHECK(associated_content->uuid.has_value()); + CHECK(associated_content); // Check if we already have persisted this content static constexpr char kSelectExistingAssociatedContentId[] = @@ -471,13 +466,12 @@ bool AIChatDatabase::AddOrUpdateAssociatedContent( SQL_FROM_HERE, kSelectExistingAssociatedContentId)); CHECK(select_statement.is_valid()); select_statement.BindString(0, conversation_uuid); - select_statement.BindString(1, associated_content->uuid.value()); + select_statement.BindString(1, associated_content->uuid); sql::Statement statement; if (select_statement.Step()) { DVLOG(4) << "Updating associated content for conversation " - << conversation_uuid << " with id " - << associated_content->uuid.value(); + << conversation_uuid << " with id " << associated_content->uuid; static constexpr char kUpdateAssociatedContentQuery[] = "UPDATE associated_content" " SET title = ?," @@ -502,13 +496,13 @@ bool AIChatDatabase::AddOrUpdateAssociatedContent( int index = 0; BindAndEncryptOptionalString(statement, index++, associated_content->title); BindAndEncryptOptionalString(statement, index++, - associated_content->url->spec()); + associated_content->url.spec()); statement.BindInt(index++, base::to_underlying(associated_content->content_type)); BindAndEncryptOptionalString(statement, index++, contents); statement.BindInt(index++, associated_content->content_used_percentage); statement.BindBool(index++, associated_content->is_content_refined); - statement.BindString(index++, associated_content->uuid.value()); + statement.BindString(index++, associated_content->uuid); statement.BindString(index, conversation_uuid); if (!statement.Run()) { @@ -1016,9 +1010,8 @@ bool AIChatDatabase::CreateSchema() { "title BLOB," // Encrypted url string "url BLOB," - // Stores SiteInfo.IsVideo. Future-proofed for multiple content types - // 0 for regular content - // 1 for video. + // Stores AssociatedContent.IsVideo. Future-proofed for multiple content + // types 0 for regular content 1 for video. "content_type INTEGER NOT NULL," // Encrypted string value of the content, so that conversations can be // continued. diff --git a/components/ai_chat/core/browser/ai_chat_database.h b/components/ai_chat/core/browser/ai_chat_database.h index 96b3cac36f41..b1dedf9136ce 100644 --- a/components/ai_chat/core/browser/ai_chat_database.h +++ b/components/ai_chat/core/browser/ai_chat_database.h @@ -50,9 +50,10 @@ class AIChatDatabase { mojom::ConversationTurnPtr first_entry); // Update any properties of associated content metadata or full-text content - bool AddOrUpdateAssociatedContent(std::string_view conversation_uuid, - mojom::SiteInfoPtr associated_content, - std::optional content); + bool AddOrUpdateAssociatedContent( + std::string_view conversation_uuid, + mojom::AssociatedContentPtr associated_content, + std::optional content); // Adds a new conversation entry to the conversation with the provided UUID bool AddConversationEntry( diff --git a/components/ai_chat/core/browser/ai_chat_database_unittest.cc b/components/ai_chat/core/browser/ai_chat_database_unittest.cc index 88a3b4582528..203d62023ca7 100644 --- a/components/ai_chat/core/browser/ai_chat_database_unittest.cc +++ b/components/ai_chat/core/browser/ai_chat_database_unittest.cc @@ -126,14 +126,11 @@ TEST_P(AIChatDatabaseTest, AddAndGetConversationAndEntries) { // recent entry. const GURL page_url = GURL("https://example.com/page"); const std::string expected_contents = "Page contents"; - mojom::SiteInfoPtr associated_content = - has_content - ? mojom::SiteInfo::New( - content_uuid, mojom::ContentType::PageContent, "page title", - page_url.host(), page_url, 62, true, true) - : mojom::SiteInfo::New( - std::nullopt, mojom::ContentType::PageContent, std::nullopt, - std::nullopt, std::nullopt, 0, false, false); + mojom::AssociatedContentPtr associated_content = + has_content ? mojom::AssociatedContent::New( + content_uuid, mojom::ContentType::PageContent, + "page title", page_url, 62, true) + : nullptr; const mojom::ConversationPtr metadata = mojom::Conversation::New(uuid, "title", now - base::Hours(2), true, std::nullopt, std::move(associated_content)); @@ -265,10 +262,7 @@ TEST_P(AIChatDatabaseTest, UpdateConversationTitle) { base::StrCat({"for_conversation_title_", initial_title}); const std::string updated_title = "updated title"; mojom::ConversationPtr metadata = mojom::Conversation::New( - uuid, initial_title, base::Time::Now(), true, std::nullopt, - mojom::SiteInfo::New(std::nullopt, mojom::ContentType::PageContent, - std::nullopt, std::nullopt, std::nullopt, 0, false, - false)); + uuid, initial_title, base::Time::Now(), true, std::nullopt, nullptr); // Persist the first entry (and get the response ready) const auto history = CreateSampleChatHistory(1u); @@ -298,9 +292,9 @@ TEST_P(AIChatDatabaseTest, AddOrUpdateAssociatedContent) { const GURL page_url = GURL("https://example.com/page"); mojom::ConversationPtr metadata = mojom::Conversation::New( uuid, "title", base::Time::Now() - base::Hours(2), true, std::nullopt, - mojom::SiteInfo::New(content_uuid, mojom::ContentType::PageContent, - "page title", page_url.host(), page_url, 62, true, - true)); + mojom::AssociatedContent::New(content_uuid, + mojom::ContentType::PageContent, + "page title", page_url, 62, true)); auto history = CreateSampleChatHistory(1u); @@ -329,7 +323,7 @@ TEST_P(AIChatDatabaseTest, AddOrUpdateAssociatedContent) { result = db_->GetConversationData(uuid); EXPECT_EQ(result->associated_content.size(), 1u); EXPECT_EQ(result->associated_content[0]->content_uuid, - metadata->associated_content->uuid.value()); + metadata->associated_content->uuid); EXPECT_EQ(result->associated_content[0]->content, expected_contents); conversations = db_->GetAllConversations(); EXPECT_EQ(conversations.size(), 1u); @@ -341,9 +335,7 @@ TEST_P(AIChatDatabaseTest, DeleteAllData) { const GURL page_url = GURL("https://example.com/page"); mojom::ConversationPtr metadata = mojom::Conversation::New( uuid, "title", base::Time::Now() - base::Hours(2), true, std::nullopt, - mojom::SiteInfo::New(std::nullopt, mojom::ContentType::PageContent, - std::nullopt, std::nullopt, std::nullopt, 0, false, - false)); + nullptr); auto history = CreateSampleChatHistory(1u); @@ -380,14 +372,14 @@ TEST_P(AIChatDatabaseTest, DeleteAssociatedWebContent) { // are persisted. mojom::ConversationPtr metadata_first = mojom::Conversation::New( "first", "title", base::Time::Now() - base::Hours(2), true, std::nullopt, - mojom::SiteInfo::New("first-content", mojom::ContentType::PageContent, - "page title", page_url.host(), page_url, 62, true, - true)); + mojom::AssociatedContent::New("first-content", + mojom::ContentType::PageContent, + "page title", page_url, 62, true)); mojom::ConversationPtr metadata_second = mojom::Conversation::New( "second", "title", base::Time::Now() - base::Hours(1), true, "model-2", - mojom::SiteInfo::New("second-content", mojom::ContentType::PageContent, - "page title", page_url.host(), page_url, 62, true, - true)); + mojom::AssociatedContent::New("second-content", + mojom::ContentType::PageContent, + "page title", page_url, 62, true)); auto history_first = CreateSampleChatHistory(1u, -2); auto history_second = CreateSampleChatHistory(1u, -1); @@ -427,8 +419,8 @@ TEST_P(AIChatDatabaseTest, DeleteAssociatedWebContent) { conversations = db_->GetAllConversations(); EXPECT_EQ(conversations.size(), 2u); ExpectConversationEquals(FROM_HERE, conversations[0], metadata_first); - metadata_second->associated_content->url = std::nullopt; - metadata_second->associated_content->title = std::nullopt; + metadata_second->associated_content->url = GURL(); + metadata_second->associated_content->title = ""; ExpectConversationEquals(FROM_HERE, conversations[1], metadata_second); archive_result = db_->GetConversationData("second"); @@ -540,12 +532,8 @@ TEST_P(AIChatDatabaseMigrationTest, MigrationToVCurrent) { // ConversationEntry table changed, check it persists correctly auto now = base::Time::Now(); const std::string uuid = "migrationtest"; - mojom::SiteInfoPtr associated_content = mojom::SiteInfo::New( - std::nullopt, mojom::ContentType::PageContent, std::nullopt, - std::nullopt, std::nullopt, 0, false, false); - const mojom::ConversationPtr metadata = - mojom::Conversation::New(uuid, "title", now - base::Hours(2), true, - std::nullopt, std::move(associated_content)); + const mojom::ConversationPtr metadata = mojom::Conversation::New( + uuid, "title", now - base::Hours(2), true, std::nullopt, nullptr); // Persist the first entry (and get the response ready) auto history = CreateSampleChatHistory(1u); diff --git a/components/ai_chat/core/browser/ai_chat_service.cc b/components/ai_chat/core/browser/ai_chat_service.cc index b4d449e50d90..3dd9c70b97de 100644 --- a/components/ai_chat/core/browser/ai_chat_service.cc +++ b/components/ai_chat/core/browser/ai_chat_service.cc @@ -157,10 +157,7 @@ ConversationHandler* AIChatService::CreateConversation() { // Create the conversation metadata { mojom::ConversationPtr conversation = mojom::Conversation::New( - conversation_uuid, "", base::Time::Now(), false, std::nullopt, - mojom::SiteInfo::New(base::Uuid::GenerateRandomV4().AsLowercaseString(), - mojom::ContentType::PageContent, std::nullopt, - std::nullopt, std::nullopt, 0, false, false)); + conversation_uuid, "", base::Time::Now(), false, std::nullopt, nullptr); conversations_.insert_or_assign(conversation_uuid, std::move(conversation)); } mojom::Conversation* conversation = @@ -745,7 +742,7 @@ void AIChatService::HandleFirstEntry( DVLOG(1) << __func__ << " Conversation " << conversation->uuid << " being persisted for first time."; CHECK(entry->uuid.has_value()); - CHECK(conversation->associated_content->uuid.has_value()); + // We can persist the conversation metadata for the first time as well as the // entry. if (ai_chat_db_) { @@ -780,7 +777,7 @@ void AIChatService::HandleNewEntry( conversation->model_key, std::nullopt); if (associated_content_value.has_value() && - conversation->associated_content->is_content_association_possible) { + conversation->associated_content) { ai_chat_db_ .AsyncCall( base::IgnoreResult(&AIChatDatabase::AddOrUpdateAssociatedContent)) diff --git a/components/ai_chat/core/browser/ai_chat_service_unittest.cc b/components/ai_chat/core/browser/ai_chat_service_unittest.cc index 60e464b31d4d..d2bab71bb902 100644 --- a/components/ai_chat/core/browser/ai_chat_service_unittest.cc +++ b/components/ai_chat/core/browser/ai_chat_service_unittest.cc @@ -113,7 +113,6 @@ class MockConversationHandlerClient : public mojom::ConversationUI { conversation_ui_receiver_.reset(); } - MOCK_METHOD(void, OnConversationHistoryUpdate, (), (override)); MOCK_METHOD(void, OnAPIRequestInProgress, (bool), (override)); @@ -133,7 +132,7 @@ class MockConversationHandlerClient : public mojom::ConversationUI { MOCK_METHOD(void, OnAssociatedContentInfoChanged, - (const mojom::SiteInfoPtr, bool), + (const mojom::AssociatedContentPtr, bool), (override)); MOCK_METHOD(void, OnFaviconImageDataChanged, (), (override)); @@ -496,10 +495,10 @@ TEST_P(AIChatServiceUnitTest, GetOrCreateConversationHandlerForContent) { base::RunLoop run_loop; conversation_with_content->GetAssociatedContentInfo( base::BindLambdaForTesting( - [&](mojom::SiteInfoPtr site_info, bool should_send_page_contents) { - EXPECT_TRUE(site_info->is_content_association_possible); - EXPECT_TRUE(site_info->url.has_value()); - EXPECT_EQ(site_info->url.value(), GURL("https://example.com")); + [&](mojom::AssociatedContentPtr associated_content, + bool should_send_page_contents) { + EXPECT_TRUE(associated_content); + EXPECT_EQ(associated_content->url, GURL("https://example.com")); run_loop.Quit(); })); run_loop.Run(); @@ -558,10 +557,10 @@ TEST_P(AIChatServiceUnitTest, base::RunLoop run_loop; conversation_with_content->GetAssociatedContentInfo( base::BindLambdaForTesting( - [&](mojom::SiteInfoPtr site_info, bool should_send_page_contents) { + [&](mojom::AssociatedContentPtr associated_content, + bool should_send_page_contents) { EXPECT_FALSE(should_send_page_contents); - EXPECT_FALSE(site_info->is_content_association_possible); - EXPECT_FALSE(site_info->url.has_value()); + EXPECT_FALSE(associated_content); run_loop.Quit(); })); run_loop.Run(); @@ -814,13 +813,12 @@ TEST_P(AIChatServiceUnitTest, DeleteAssociatedWebContent) { // Verify associated are initially correct base::RunLoop run_loop; data[i].conversation_handler->GetAssociatedContentInfo( - base::BindLambdaForTesting([&](mojom::SiteInfoPtr site_info, + base::BindLambdaForTesting([&](mojom::AssociatedContentPtr site_info, bool should_send_page_contents) { SCOPED_TRACE(testing::Message() << "data index: " << i); - EXPECT_TRUE(site_info->is_content_association_possible); - EXPECT_TRUE(site_info->url.has_value()); - EXPECT_EQ(site_info->url.value(), content_url); - EXPECT_EQ(site_info->title.value(), base::UTF16ToUTF8(page_title)); + ASSERT_TRUE(site_info); + EXPECT_EQ(site_info->url, content_url); + EXPECT_EQ(site_info->title, base::UTF16ToUTF8(page_title)); run_loop.Quit(); })); run_loop.Run(); @@ -849,18 +847,16 @@ TEST_P(AIChatServiceUnitTest, DeleteAssociatedWebContent) { for (int i = 0; i < 3; i++) { base::RunLoop run_loop; data[i].conversation_handler->GetAssociatedContentInfo( - base::BindLambdaForTesting([&](mojom::SiteInfoPtr site_info, + base::BindLambdaForTesting([&](mojom::AssociatedContentPtr site_info, bool should_send_page_contents) { SCOPED_TRACE(testing::Message() << "data index: " << i); - EXPECT_TRUE(site_info->is_content_association_possible); - EXPECT_TRUE(site_info->url.has_value()); - EXPECT_TRUE(site_info->title.has_value()); + ASSERT_TRUE(site_info); if (i == 1) { - EXPECT_TRUE(site_info->url->is_empty()); - EXPECT_TRUE(site_info->title->empty()); + EXPECT_TRUE(site_info->url.is_empty()); + EXPECT_TRUE(site_info->title.empty()); } else { - EXPECT_EQ(site_info->url.value(), content_url); - EXPECT_EQ(site_info->title.value(), base::UTF16ToUTF8(page_title)); + EXPECT_EQ(site_info->url, content_url); + EXPECT_EQ(site_info->title, base::UTF16ToUTF8(page_title)); } run_loop.Quit(); })); diff --git a/components/ai_chat/core/browser/conversation_handler.cc b/components/ai_chat/core/browser/conversation_handler.cc index a74530bbd762..d797d92e663d 100644 --- a/components/ai_chat/core/browser/conversation_handler.cc +++ b/components/ai_chat/core/browser/conversation_handler.cc @@ -229,9 +229,9 @@ ConversationHandler::ConversationHandler( mojom::ConversationArchivePtr conversation_data = std::move(initial_state.value()); if (!conversation_data->associated_content.empty()) { - CHECK(metadata_->associated_content->uuid.has_value()); + CHECK(metadata_->associated_content); CHECK_EQ(conversation_data->associated_content[0]->content_uuid, - metadata_->associated_content->uuid.value()); + metadata_->associated_content->uuid); bool is_video = (metadata_->associated_content->content_type == mojom::ContentType::VideoTranscript); SetArchiveContent(conversation_data->associated_content[0]->content, @@ -289,14 +289,20 @@ void ConversationHandler::BindUntrustedConversationUI( } void ConversationHandler::OnConversationMetadataUpdated() { - // Pass the updated data to archive content if (archive_content_) { - archive_content_->SetMetadata( - metadata_->associated_content->url.value_or(GURL()), - base::UTF8ToUTF16(metadata_->associated_content->title.value_or("")), - metadata_->associated_content->content_type == - mojom::ContentType::VideoTranscript); + if (metadata_->associated_content) { + // Pass the updated data to archive content + archive_content_->SetMetadata( + metadata_->associated_content->url, + base::UTF8ToUTF16(metadata_->associated_content->title), + metadata_->associated_content->content_type == + mojom::ContentType::VideoTranscript); + } else { + // TODO: Confirm with @petemill if this is the correct behavior + archive_content_->SetMetadata(GURL(), u"", false); + } } + // Notify UI. If we have live content then the metadata will be updated // again from that live data. OnAssociatedContentInfoChanged(); @@ -411,8 +417,7 @@ void ConversationHandler::OnAssociatedContentDestroyed( : -1; DisassociateContentDelegate(); if (!chat_history_.empty() && should_send_page_contents_ && - metadata_->associated_content && - metadata_->associated_content->is_content_association_possible) { + metadata_->associated_content) { // Get the latest version of article text and // associated_content_info_ if this chat has history and was connected to // the associated conversation, then store the content so the conversation @@ -428,13 +433,13 @@ void ConversationHandler::OnAssociatedContentDestroyed( void ConversationHandler::SetArchiveContent(std::string text_content, bool is_video) { + CHECK(metadata_->associated_content); + // Construct a "content archive" implementation of AssociatedContentDelegate // with a duplicate of the article text. auto archive_content = std::make_unique( - metadata_->associated_content->url.value_or(GURL()), - std::move(text_content), - base::UTF8ToUTF16(metadata_->associated_content->title.value_or("")), - is_video); + metadata_->associated_content->url, std::move(text_content), + base::UTF8ToUTF16(metadata_->associated_content->title), is_video); associated_content_delegate_ = archive_content->GetWeakPtr(); archive_content_ = std::move(archive_content); should_send_page_contents_ = features::IsPageContextEnabledInitially(); @@ -518,8 +523,9 @@ void ConversationHandler::GetState(GetStateCallback callback) { mojom::ConversationStatePtr state = mojom::ConversationState::New( metadata_->uuid, is_request_in_progress_, std::move(models_copy), model_key, std::move(suggestions), suggestion_generation_status_, - metadata_->associated_content->Clone(), should_send_page_contents_, - current_error_); + metadata_->associated_content ? metadata_->associated_content->Clone() + : nullptr, + should_send_page_contents_, current_error_); std::move(callback).Run(std::move(state)); } @@ -968,7 +974,9 @@ void ConversationHandler::DisassociateContentDelegate() { void ConversationHandler::GetAssociatedContentInfo( GetAssociatedContentInfoCallback callback) { BuildAssociatedContentInfo(); - std::move(callback).Run(metadata_->associated_content->Clone(), + std::move(callback).Run(metadata_->associated_content + ? metadata_->associated_content->Clone() + : nullptr, should_send_page_contents_); } @@ -1429,9 +1437,11 @@ void ConversationHandler::OnGeneratePageContentComplete( is_content_different_ = is_content_different_ || contents_text != previous_content; - metadata_->associated_content->content_type = - is_video ? mojom::ContentType::VideoTranscript - : mojom::ContentType::PageContent; + if (metadata_->associated_content) { + metadata_->associated_content->content_type = + is_video ? mojom::ContentType::VideoTranscript + : mojom::ContentType::PageContent; + } std::move(callback).Run(contents_text, is_video, invalidation_token); @@ -1671,20 +1681,25 @@ bool ConversationHandler::IsContentAssociationPossible() { void ConversationHandler::BuildAssociatedContentInfo() { // Only modify associated content metadata here if (associated_content_delegate_) { + // Note: We don't create a new AssociatedContent object here unless one + // doesn't exist. If we generate one with a new UUID the deserializer + // breaks. + if (!metadata_->associated_content) { + metadata_->associated_content = mojom::AssociatedContent::New(); + metadata_->associated_content->uuid = + base::Uuid::GenerateRandomV4().AsLowercaseString(); + LOG(ERROR) << "Created new AssociatedContent " + << metadata_->associated_content->uuid; + } metadata_->associated_content->title = base::UTF16ToUTF8(associated_content_delegate_->GetTitle()); const GURL url = associated_content_delegate_->GetURL(); - metadata_->associated_content->hostname = url.host(); metadata_->associated_content->url = url; metadata_->associated_content->content_used_percentage = GetContentUsedPercentage(); metadata_->associated_content->is_content_refined = is_content_refined_; - metadata_->associated_content->is_content_association_possible = true; } else { - metadata_->associated_content->title = std::nullopt; - metadata_->associated_content->hostname = std::nullopt; - metadata_->associated_content->url = std::nullopt; - metadata_->associated_content->is_content_association_possible = false; + metadata_->associated_content = nullptr; } } @@ -1699,7 +1714,7 @@ ConversationHandler::GetStateForConversationEntries() { entries_state->is_content_refined = is_content_refined_; entries_state->is_leo_model = is_leo_model; entries_state->content_used_percentage = - metadata_->associated_content->is_content_association_possible + metadata_->associated_content ? std::make_optional( metadata_->associated_content->content_used_percentage) : std::nullopt; @@ -1716,7 +1731,9 @@ void ConversationHandler::OnAssociatedContentInfoChanged() { BuildAssociatedContentInfo(); for (auto& client : conversation_ui_handlers_) { client->OnAssociatedContentInfoChanged( - metadata_->associated_content->Clone(), should_send_page_contents_); + metadata_->associated_content ? metadata_->associated_content->Clone() + : nullptr, + should_send_page_contents_); } OnStateForConversationEntriesChanged(); } diff --git a/components/ai_chat/core/browser/conversation_handler_unittest.cc b/components/ai_chat/core/browser/conversation_handler_unittest.cc index 8766416f8993..64faac51260b 100644 --- a/components/ai_chat/core/browser/conversation_handler_unittest.cc +++ b/components/ai_chat/core/browser/conversation_handler_unittest.cc @@ -38,7 +38,6 @@ #include "brave/components/ai_chat/core/browser/types.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-shared.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" @@ -109,7 +108,7 @@ class MockConversationHandlerClient : public mojom::ConversationUI { MOCK_METHOD(void, OnAssociatedContentInfoChanged, - (const mojom::SiteInfoPtr, bool), + (const mojom::AssociatedContentPtr, bool), (override)); MOCK_METHOD(void, OnFaviconImageDataChanged, (), (override)); @@ -207,12 +206,8 @@ class ConversationHandlerUnitTest : public testing::Test { os_crypt_.get(), shared_url_loader_factory_, "", temp_directory_.GetPath()); - mojom::SiteInfoPtr non_content = mojom::SiteInfo::New( - std::nullopt, mojom::ContentType::PageContent, std::nullopt, - std::nullopt, std::nullopt, 0, false, false); - conversation_ = - mojom::Conversation::New("uuid", "title", base::Time::Now(), false, - std::nullopt, std::move(non_content)); + conversation_ = mojom::Conversation::New("uuid", "title", base::Time::Now(), + false, std::nullopt, nullptr); conversation_handler_ = std::make_unique( conversation_.get(), ai_chat_service_.get(), model_service_.get(), @@ -375,8 +370,7 @@ TEST_F(ConversationHandlerUnitTest, GetState) { should_send_content ? mojom::SuggestionGenerationStatus::CanGenerate : mojom::SuggestionGenerationStatus::None); - EXPECT_TRUE( - state->associated_content_info->is_content_association_possible); + EXPECT_TRUE(state->associated_content); EXPECT_EQ(state->should_send_content, should_send_content); EXPECT_EQ(state->error, mojom::APIError::None); run_loop.Quit(); @@ -410,13 +404,15 @@ TEST_F(ConversationHandlerUnitTest, SubmitSelectedText) { EXPECT_FALSE(conversation_handler_->HasAnyHistory()); // Test without page contents. - conversation_handler_->GetAssociatedContentInfo(base::BindLambdaForTesting( - [&](mojom::SiteInfoPtr site_info, bool should_send_page_contents) { + conversation_handler_->GetAssociatedContentInfo( + base::BindLambdaForTesting([&](mojom::AssociatedContentPtr site_info, + bool should_send_page_contents) { EXPECT_TRUE(should_send_page_contents); })); conversation_handler_->SetShouldSendPageContents(false); - conversation_handler_->GetAssociatedContentInfo(base::BindLambdaForTesting( - [&](mojom::SiteInfoPtr site_info, bool should_send_page_contents) { + conversation_handler_->GetAssociatedContentInfo( + base::BindLambdaForTesting([&](mojom::AssociatedContentPtr site_info, + bool should_send_page_contents) { EXPECT_FALSE(should_send_page_contents); })); @@ -448,12 +444,13 @@ TEST_F(ConversationHandlerUnitTest, SubmitSelectedText) { testing::Mock::VerifyAndClearExpectations(associated_content_.get()); // article_text_ and suggestions_ should be cleared when page content is // unlinked. - conversation_handler_->GetAssociatedContentInfo(base::BindLambdaForTesting( - [&](mojom::SiteInfoPtr site_info, bool should_send_page_contents) { + conversation_handler_->GetAssociatedContentInfo( + base::BindLambdaForTesting([&](mojom::AssociatedContentPtr site_info, + bool should_send_page_contents) { EXPECT_FALSE(should_send_page_contents); // We should not have any relationship to associated content // once conversation history is committed. - EXPECT_FALSE(site_info->is_content_association_possible); + EXPECT_FALSE(site_info); })); EXPECT_TRUE(conversation_handler_->GetSuggestedQuestionsForTest().empty()); @@ -506,11 +503,12 @@ TEST_F(ConversationHandlerUnitTest, SubmitSelectedText_WithAssociatedContent) { EXPECT_CALL(*associated_content_, GetContent) .WillOnce(base::test::RunOnceCallback<0>(page_content, false, "")); conversation_handler_->SetShouldSendPageContents(true); - conversation_handler_->GetAssociatedContentInfo(base::BindLambdaForTesting( - [&](mojom::SiteInfoPtr site_info, bool should_send_page_contents) { + conversation_handler_->GetAssociatedContentInfo( + base::BindLambdaForTesting([&](mojom::AssociatedContentPtr site_info, + bool should_send_page_contents) { EXPECT_TRUE(should_send_page_contents); - EXPECT_TRUE(site_info->is_content_association_possible); - EXPECT_EQ(site_info->url->spec(), "https://www.brave.com/"); + ASSERT_TRUE(site_info); + EXPECT_EQ(site_info->url, GURL("https://www.brave.com/")); })); NiceMock client(conversation_handler_.get()); @@ -533,11 +531,12 @@ TEST_F(ConversationHandlerUnitTest, SubmitSelectedText_WithAssociatedContent) { testing::Mock::VerifyAndClearExpectations(&client); // associated info should be unchanged - conversation_handler_->GetAssociatedContentInfo(base::BindLambdaForTesting( - [&](mojom::SiteInfoPtr site_info, bool should_send_page_contents) { + conversation_handler_->GetAssociatedContentInfo( + base::BindLambdaForTesting([&](mojom::AssociatedContentPtr site_info, + bool should_send_page_contents) { EXPECT_TRUE(should_send_page_contents); - EXPECT_TRUE(site_info->is_content_association_possible); - EXPECT_EQ(site_info->url->spec(), "https://www.brave.com/"); + ASSERT_TRUE(site_info); + EXPECT_EQ(site_info->url, GURL("https://www.brave.com/")); })); // Should not be any LLM-generated suggested questions yet because they @@ -944,8 +943,9 @@ TEST_F(ConversationHandlerUnitTest, // History update notification once for each entry EXPECT_CALL(client, OnConversationHistoryUpdate()).Times(2); - conversation_handler_->GetAssociatedContentInfo(base::BindLambdaForTesting( - [&](mojom::SiteInfoPtr site_info, bool should_send_page_contents) { + conversation_handler_->GetAssociatedContentInfo( + base::BindLambdaForTesting([&](mojom::AssociatedContentPtr site_info, + bool should_send_page_contents) { EXPECT_TRUE(should_send_page_contents); })); @@ -1005,8 +1005,9 @@ TEST_F(ConversationHandlerUnitTest, NiceMock client(conversation_handler_.get()); EXPECT_CALL(client, OnConversationHistoryUpdate()).Times(4); EXPECT_TRUE(conversation_handler_->IsAnyClientConnected()); - conversation_handler_->GetAssociatedContentInfo(base::BindLambdaForTesting( - [&](mojom::SiteInfoPtr site_info, bool should_send_page_contents) { + conversation_handler_->GetAssociatedContentInfo( + base::BindLambdaForTesting([&](mojom::AssociatedContentPtr site_info, + bool should_send_page_contents) { EXPECT_TRUE(should_send_page_contents); })); @@ -1201,8 +1202,9 @@ TEST_F(ConversationHandlerUnitTest, // Connecting a client will trigger content staging. NiceMock client(conversation_handler_.get()); EXPECT_TRUE(conversation_handler_->IsAnyClientConnected()); - conversation_handler_->GetAssociatedContentInfo(base::BindLambdaForTesting( - [&](mojom::SiteInfoPtr site_info, bool should_send_page_contents) { + conversation_handler_->GetAssociatedContentInfo( + base::BindLambdaForTesting([&](mojom::AssociatedContentPtr site_info, + bool should_send_page_contents) { EXPECT_TRUE(should_send_page_contents); })); @@ -1219,9 +1221,10 @@ TEST_F(ConversationHandlerUnitTest, // use page content. SetAssociatedContentStagedEntries(/*empty=*/false); conversation_handler_->SetShouldSendPageContents(false); - conversation_handler_->GetAssociatedContentInfo(base::BindLambdaForTesting( - [&](mojom::SiteInfoPtr site_info, bool should_send_page_contents) { - EXPECT_TRUE(site_info->is_content_association_possible); + conversation_handler_->GetAssociatedContentInfo( + base::BindLambdaForTesting([&](mojom::AssociatedContentPtr site_info, + bool should_send_page_contents) { + EXPECT_TRUE(site_info); EXPECT_FALSE(should_send_page_contents); })); @@ -1241,9 +1244,8 @@ TEST_F(ConversationHandlerUnitTest_NoAssociatedContent, MaybeFetchOrClearSearchQuerySummary) { // Ensure nothing gets staged when there's no associated content. conversation_handler_->GetAssociatedContentInfo(base::BindLambdaForTesting( - [&](mojom::SiteInfoPtr site_info, bool should_send_page_contents) { - EXPECT_FALSE(site_info->is_content_association_possible); - })); + [&](mojom::AssociatedContentPtr site_info, + bool should_send_page_contents) { EXPECT_FALSE(site_info); })); // Client connecting would trigger content staging NiceMock client(conversation_handler_.get()); EXPECT_CALL(client, OnConversationHistoryUpdate()).Times(0); @@ -1379,8 +1381,9 @@ TEST_F(ConversationHandlerUnitTest, SubmitSuggestion) { TEST_F(ConversationHandlerUnitTest, GenerateQuestions_DisableSendPageContent) { conversation_handler_->SetShouldSendPageContents(false); - conversation_handler_->GetAssociatedContentInfo(base::BindLambdaForTesting( - [&](mojom::SiteInfoPtr site_info, bool should_send_page_contents) { + conversation_handler_->GetAssociatedContentInfo( + base::BindLambdaForTesting([&](mojom::AssociatedContentPtr site_info, + bool should_send_page_contents) { EXPECT_FALSE(should_send_page_contents); })); EXPECT_CALL(*associated_content_, GetURL).Times(0); diff --git a/components/ai_chat/core/browser/test_utils.cc b/components/ai_chat/core/browser/test_utils.cc index c7b1ced131e7..94887a9f8172 100644 --- a/components/ai_chat/core/browser/test_utils.cc +++ b/components/ai_chat/core/browser/test_utils.cc @@ -73,8 +73,8 @@ void ExpectConversationEquals(base::Location location, } void ExpectAssociatedContentEquals(base::Location location, - const mojom::SiteInfoPtr& a, - const mojom::SiteInfoPtr& b) { + const mojom::AssociatedContentPtr& a, + const mojom::AssociatedContentPtr& b) { SCOPED_TRACE(testing::Message() << location.ToString()); if (!a || !b) { EXPECT_EQ(a, b); // Both should be null or neither @@ -86,8 +86,6 @@ void ExpectAssociatedContentEquals(base::Location location, EXPECT_EQ(a->content_type, b->content_type); EXPECT_EQ(a->content_used_percentage, b->content_used_percentage); EXPECT_EQ(a->is_content_refined, b->is_content_refined); - EXPECT_EQ(a->is_content_association_possible, - b->is_content_association_possible); } void ExpectConversationHistoryEquals( diff --git a/components/ai_chat/core/browser/test_utils.h b/components/ai_chat/core/browser/test_utils.h index a56716508e91..984c0fb9999a 100644 --- a/components/ai_chat/core/browser/test_utils.h +++ b/components/ai_chat/core/browser/test_utils.h @@ -19,8 +19,8 @@ void ExpectConversationEquals(base::Location location, const mojom::ConversationPtr& b); void ExpectAssociatedContentEquals(base::Location location, - const mojom::SiteInfoPtr& a, - const mojom::SiteInfoPtr& b); + const mojom::AssociatedContentPtr& a, + const mojom::AssociatedContentPtr& b); void ExpectConversationEntryEquals(base::Location location, const mojom::ConversationTurnPtr& a, diff --git a/components/ai_chat/core/common/mojom/ai_chat.mojom b/components/ai_chat/core/common/mojom/ai_chat.mojom index 7b6769d375bd..9ab214aa31c9 100644 --- a/components/ai_chat/core/common/mojom/ai_chat.mojom +++ b/components/ai_chat/core/common/mojom/ai_chat.mojom @@ -74,29 +74,20 @@ enum ContentType { VideoTranscript, }; -// A piece of content associated with a conversation. -// TODO(petemill): Rename to AssociatedContent and have hostname/url/title be -// part of a detail property (which would have different structure possibilities -// depending on content type. -struct SiteInfo { - string? uuid; +// Represents the content that is associated with a conversation. +struct AssociatedContent { + string uuid; + ContentType content_type; - // Web page specific fields, if available and allowed - string? title; - string? hostname; - url.mojom.Url? url; + string title; + url.mojom.Url url; // Percentage of the content that has been utilized by remote LLM (0-100) int32 content_used_percentage; + // Indicates content has been refined through extracting most relevant parts // from long page content bool is_content_refined; - - // Indicates if the URL scheme is of a type that allows for - // content association. - // TODO(petemill): SiteInfo should just not exist if content-associated is - // not possible. - bool is_content_association_possible; }; struct Conversation { @@ -110,7 +101,7 @@ struct Conversation { // Model key, if different than default string? model_key; - SiteInfo associated_content; + AssociatedContent? associated_content; }; struct ContentArchive { @@ -413,7 +404,7 @@ struct ConversationState { string current_model_key; array suggested_questions; SuggestionGenerationStatus suggestion_status; - SiteInfo associated_content_info; + AssociatedContent? associated_content; bool should_send_content; APIError error; // TODO(petemill): include conversation history, once @@ -467,11 +458,11 @@ interface ConversationHandler { // the assistant. SubmitSuggestion(string suggestion); - // Get associated page information. If there is none then |site_info| will be - // |null|. If the reason for that is it's still being fetched, then + // Get associated page information. If there is none then |associated_content| + // will be |null|. If the reason for that is it's still being fetched, then // |is_fetching| will be |true|. GetAssociatedContentInfo() => ( - SiteInfo associated_content_info, bool should_send_content); + AssociatedContent? associated_content, bool should_send_content); SetShouldSendPageContents(bool should_send); @@ -537,10 +528,10 @@ interface ConversationUI { // Browser window. OnSuggestedQuestionsChanged( array questions, SuggestionGenerationStatus status); - // Associated page information has changed. If there is none then |site_info| + // Associated page information has changed. If there is none then |associated_content| // will be |null|. If the reason for that is it's still being fetched, then // |is_fetching| will be |true|. - OnAssociatedContentInfoChanged(SiteInfo info, bool should_send_page_contents); + OnAssociatedContentInfoChanged(AssociatedContent? associated_content, bool should_send_page_contents); OnFaviconImageDataChanged(); OnConversationDeleted(); }; diff --git a/components/ai_chat/resources/page/components/feedback_form/index.tsx b/components/ai_chat/resources/page/components/feedback_form/index.tsx index 3e578cad09f8..ecb8e5e0ed21 100644 --- a/components/ai_chat/resources/page/components/feedback_form/index.tsx +++ b/components/ai_chat/resources/page/components/feedback_form/index.tsx @@ -84,13 +84,13 @@ function FeedbackForm() { /> - {conversationContext.associatedContentInfo?.hostname && ( + {conversationContext.associatedContentInfo && (
diff --git a/components/ai_chat/resources/page/components/main/index.tsx b/components/ai_chat/resources/page/components/main/index.tsx index 973117915d3f..0715ad9872cb 100644 --- a/components/ai_chat/resources/page/components/main/index.tsx +++ b/components/ai_chat/resources/page/components/main/index.tsx @@ -72,7 +72,7 @@ function Main() { !conversationContext.apiHasError && // Don't show premium prompt and errors (rate limit error has its own premium prompt suggestion) !shouldShowStorageNotice && // Don't show premium prompt and storage notice aiChatContext.canShowPremiumPrompt && - conversationContext.associatedContentInfo === null && // SiteInfo request has finished and this is a standalone conversation + conversationContext.associatedContentInfo === null && // AssociatedContent request has finished and this is a standalone conversation !aiChatContext.isPremiumUser @@ -82,7 +82,7 @@ function Main() { const showContextToggle = (conversationContext.conversationHistory.length === 0 || isLastTurnBraveSearchSERPSummary) && - conversationContext.associatedContentInfo?.isContentAssociationPossible + !!conversationContext.associatedContentInfo let currentErrorElement = null @@ -253,7 +253,7 @@ function Main() { <> - {conversationContext.associatedContentInfo?.isContentAssociationPossible && conversationContext.shouldSendPageContents && ( + {conversationContext.associatedContentInfo && conversationContext.shouldSendPageContents && (
diff --git a/components/ai_chat/resources/page/components/welcome_guide/index.tsx b/components/ai_chat/resources/page/components/welcome_guide/index.tsx index 78e47a5a25a3..7c903f87468a 100644 --- a/components/ai_chat/resources/page/components/welcome_guide/index.tsx +++ b/components/ai_chat/resources/page/components/welcome_guide/index.tsx @@ -26,7 +26,7 @@ function WelcomeGuide() {

{getLocale('welcomeGuideSiteHelpCardTitle')}

- {conversationContext.associatedContentInfo?.isContentAssociationPossible && + {conversationContext.associatedContentInfo && conversationContext.shouldSendPageContents ? ( <>

{getLocale('welcomeGuideSiteHelpCardDescWithAction')}

diff --git a/components/ai_chat/resources/page/state/conversation_context.tsx b/components/ai_chat/resources/page/state/conversation_context.tsx index d6d81be07b41..0dcd2c4f7042 100644 --- a/components/ai_chat/resources/page/state/conversation_context.tsx +++ b/components/ai_chat/resources/page/state/conversation_context.tsx @@ -25,7 +25,7 @@ export interface CharCountContext { export type ConversationContext = SendFeedbackState & CharCountContext & { conversationUuid?: string conversationHistory: Mojom.ConversationTurn[] - associatedContentInfo?: Mojom.SiteInfo + associatedContentInfo?: Mojom.AssociatedContent allModels: Mojom.Model[] currentModel?: Mojom.Model suggestedQuestions: string[] @@ -201,7 +201,7 @@ export function ConversationContextProvider(props: React.PropsWithChildren) { currentModelKey, suggestedQuestions, suggestionStatus, - associatedContentInfo, + associatedContent, shouldSendContent, error } } = await conversationHandler.getState() @@ -211,7 +211,7 @@ export function ConversationContextProvider(props: React.PropsWithChildren) { ...getModelContext(currentModelKey, models), suggestedQuestions, suggestionStatus, - associatedContentInfo, + associatedContentInfo: associatedContent, shouldSendPageContents: shouldSendContent, currentError: error }) @@ -260,7 +260,7 @@ export function ConversationContextProvider(props: React.PropsWithChildren) { id = callbackRouter.onAssociatedContentInfoChanged.addListener( ( - associatedContentInfo: Mojom.SiteInfo, + associatedContentInfo: Mojom.AssociatedContent, shouldSendPageContents: boolean ) => { setPartialContext({ diff --git a/components/ai_chat/resources/page/stories/components_panel.tsx b/components/ai_chat/resources/page/stories/components_panel.tsx index 0f1466bbbf28..90d95bb7f75d 100644 --- a/components/ai_chat/resources/page/stories/components_panel.tsx +++ b/components/ai_chat/resources/page/stories/components_panel.tsx @@ -76,24 +76,13 @@ function getPageContentRefineEvent(): Mojom.ConversationEntryEvent { } } -const associatedContentNone: Mojom.SiteInfo = { - uuid: undefined, - contentType: Mojom.ContentType.PageContent, - isContentAssociationPossible: false, - contentUsedPercentage: 0, - isContentRefined: false, - title: undefined, - hostname: undefined, - url: undefined, -} - const CONVERSATIONS: Mojom.Conversation[] = [ { title: 'Star Trek Poem', uuid: '1', hasContent: true, updatedTime: { internalValue: BigInt('13278618001000000') }, - associatedContent: associatedContentNone, + associatedContent: undefined, modelKey: undefined, }, { @@ -101,7 +90,7 @@ const CONVERSATIONS: Mojom.Conversation[] = [ uuid: '2', hasContent: true, updatedTime: { internalValue: BigInt('13278618001000001') }, - associatedContent: associatedContentNone, + associatedContent: undefined, modelKey: undefined, }, { @@ -109,7 +98,7 @@ const CONVERSATIONS: Mojom.Conversation[] = [ uuid: '3', hasContent: true, updatedTime: { internalValue: BigInt('13278618001000002') }, - associatedContent: associatedContentNone, + associatedContent: undefined, modelKey: undefined, } ] @@ -388,13 +377,11 @@ const SAMPLE_QUESTIONS = [ 'Why did google executives disregard this character in the company?' ] -const SITE_INFO: Mojom.SiteInfo = { - uuid: undefined, +const ASSOCIATED_CONTENT: Mojom.AssociatedContent = { + uuid: 'uuid', contentType: Mojom.ContentType.PageContent, title: 'Tiny Tweaks to Neurons Can Rewire Animal Motion', contentUsedPercentage: 40, - isContentAssociationPossible: true, - hostname: 'www.example.com', url: { url: 'https://www.example.com/a' }, isContentRefined: false, } @@ -409,7 +396,7 @@ type CustomArgs = { deletingConversationId: string | null visibleConversationListCount: number hasSuggestedQuestions: boolean - hasSiteInfo: boolean + hasAssociatedContent: boolean isFeedbackFormVisible: boolean isStorageNoticeDismissed: boolean canShowPremiumPrompt: boolean @@ -435,7 +422,7 @@ const args: CustomArgs = { hasConversation: true, visibleConversationListCount: CONVERSATIONS.length, hasSuggestedQuestions: true, - hasSiteInfo: true, + hasAssociatedContent: true, editingConversationId: null, deletingConversationId: null, isFeedbackFormVisible: false, @@ -505,10 +492,10 @@ function StoryContext(props: React.PropsWithChildren<{args: CustomArgs, setArgs: const options = { args: props.args } const { setArgs } = props - const siteInfo = options.args.hasSiteInfo ? SITE_INFO : new Mojom.SiteInfo() + const associatedContent = options.args.hasAssociatedContent ? ASSOCIATED_CONTENT : new Mojom.AssociatedContent() const suggestedQuestions = options.args.hasSuggestedQuestions ? SAMPLE_QUESTIONS - : siteInfo + : associatedContent ? [SAMPLE_QUESTIONS[0]] : [] @@ -578,7 +565,7 @@ function StoryContext(props: React.PropsWithChildren<{args: CustomArgs, setArgs: const conversationContext: ConversationContext = { conversationUuid: CONVERSATIONS[1].uuid, conversationHistory: options.args.hasConversation ? HISTORY : [], - associatedContentInfo: siteInfo, + associatedContentInfo: associatedContent, allModels: MODELS, currentModel, suggestedQuestions, @@ -590,7 +577,7 @@ function StoryContext(props: React.PropsWithChildren<{args: CustomArgs, setArgs: shouldDisableUserInput: false, shouldShowLongPageWarning: options.args.shouldShowLongPageWarning, shouldShowLongConversationInfo: options.args.shouldShowLongConversationInfo, - shouldSendPageContents: siteInfo?.isContentAssociationPossible, + shouldSendPageContents: !!associatedContent, inputText, actionList: ACTIONS_LIST, selectedActionType: undefined, diff --git a/ios/brave-ios/Sources/AIChat/ModelView/AIChatViewModel.swift b/ios/brave-ios/Sources/AIChat/ModelView/AIChatViewModel.swift index 2bf12e63a463..eefb6bf7dbba 100644 --- a/ios/brave-ios/Sources/AIChat/ModelView/AIChatViewModel.swift +++ b/ios/brave-ios/Sources/AIChat/ModelView/AIChatViewModel.swift @@ -27,7 +27,7 @@ public class AIChatViewModel: NSObject, ObservableObject { private let braveTalkScript: AIChatBraveTalkJavascript? var querySubmited: String? - @Published var siteInfo: AiChat.SiteInfo? + @Published var siteInfo: AiChat.AssociatedContent? @Published var _shouldSendPageContents: Bool = true @Published var _canShowPremiumPrompt: Bool = false @Published var premiumStatus: AiChat.PremiumStatus = .inactive @@ -194,7 +194,7 @@ public class AIChatViewModel: NSObject, ObservableObject { self.requestInProgress = state.isRequestInProgress self.suggestedQuestions = state.suggestedQuestions self.suggestionsStatus = state.suggestionStatus - self.siteInfo = state.associatedContentInfo + self.siteInfo = state.associatedContent self._shouldSendPageContents = state.shouldSendContent self.apiError = state.error self.models = state.allModels @@ -327,7 +327,7 @@ extension AIChatViewModel: AIChatDelegate { } public func onPageHasContent( - _ siteInfo: AiChat.SiteInfo, + _ siteInfo: AiChat.AssociatedContent, shouldSendContent shouldSendPageContents: Bool ) { self.siteInfo = siteInfo diff --git a/ios/browser/api/ai_chat/ai_chat_delegate.h b/ios/browser/api/ai_chat/ai_chat_delegate.h index fbc2569c150b..cc0f49e317f5 100644 --- a/ios/browser/api/ai_chat/ai_chat_delegate.h +++ b/ios/browser/api/ai_chat/ai_chat_delegate.h @@ -26,7 +26,7 @@ OBJC_EXPORT modelList:(NSArray*)modelList; - (void)onSuggestedQuestionsChanged:(NSArray*)questions status:(AiChatSuggestionGenerationStatus)status; -- (void)onPageHasContent:(AiChatSiteInfo*)siteInfo +- (void)onPageHasContent:(AiChatAssociatedContent*)siteInfo shouldSendContent:(bool)shouldSendContent; - (void)onServiceStateChanged:(AiChatServiceState*)state; @end diff --git a/ios/browser/api/ai_chat/conversation_client.h b/ios/browser/api/ai_chat/conversation_client.h index 7ec3051dc317..7967e577d8e5 100644 --- a/ios/browser/api/ai_chat/conversation_client.h +++ b/ios/browser/api/ai_chat/conversation_client.h @@ -43,8 +43,9 @@ class ConversationClient : public mojom::ConversationUI, void OnSuggestedQuestionsChanged( const std::vector& questions, mojom::SuggestionGenerationStatus status) override; - void OnAssociatedContentInfoChanged(const mojom::SiteInfoPtr site_info, - bool should_send_content) override; + void OnAssociatedContentInfoChanged( + const mojom::AssociatedContentPtr site_info, + bool should_send_content) override; void OnFaviconImageDataChanged() override; void OnConversationDeleted() override; diff --git a/ios/browser/api/ai_chat/conversation_client.mm b/ios/browser/api/ai_chat/conversation_client.mm index d51bfdb2bb1a..f234097c2aca 100644 --- a/ios/browser/api/ai_chat/conversation_client.mm +++ b/ios/browser/api/ai_chat/conversation_client.mm @@ -69,10 +69,10 @@ } void ConversationClient::OnAssociatedContentInfoChanged( - const mojom::SiteInfoPtr site_info, + const mojom::AssociatedContentPtr site_info, bool should_send_content) { - [bridge_ onPageHasContent:[[AiChatSiteInfo alloc] - initWithSiteInfoPtr:site_info->Clone()] + [bridge_ onPageHasContent:[[AiChatAssociatedContent alloc] + initWithAssociatedContentPtr:site_info->Clone()] shouldSendContent:should_send_content]; }