Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Security solution] Assistant package assistant/index.tsx cleanup #190151

Merged
merged 37 commits into from
Aug 21, 2024

Conversation

stephmilovic
Copy link
Contributor

@stephmilovic stephmilovic commented Aug 8, 2024

Summary

Fixes some ugly code in x-pack/packages/kbn-elastic-assistant/impl/assistant/index.tsx.

  • Extracts existing blocks from assistant/index.tsx into components and hooks.
  • Removes duplicate calls to createConversations.
  • Renames variables
  • Eliminates meaningless wrapper functions
  • Removes unused const

The cleanup fixes state side effects and a variety of bugs. See Github comments in code for more details.

To test

  • Cypress tests are coming for basic assistant behavior. As of time of review request, I have the following behaviors covered in Cypress. I will continue to add more Cypress tests until that PR is ready for review

    When no connectors or conversations exist

    • Shows welcome setup when no connectors or conversations exist

    When no conversations exist but connectors do exist, show empty convo

    • When invoked on Al Assistant click, ensure system prompt is selected
    • When invoked from rules page, ensure proper prompt context and user prompt
    • When invoked from alert details, ensure proper prompt context and user prompt
    • Shows empty connector
      callout when a conversation that had a connector no longer does

    Changing conversations

    • Last conversation persists in memory from page to page
    • Properly switches back and forth between conversations
    • Only allows one conversation called "New chat" at a time
  • Manual test steps are a bit vague as root behavior here is not changing. Just a general kicking of the tires

    • start with fresh es and kibana instances, make sure you do not have any preconfigured connectors
    • optionally, run through the scenarios above
    • open new conversation, set up a connector, change conversations, change connectors, update title, send messages, update prompts (system and user)
    • check assistant loading state
    • ensure all conversation behavior still works as it did before

If you find a bug, please check if it exists on main as well.

@stephmilovic stephmilovic added release_note:skip Skip the PR/issue when compiling release notes Team: SecuritySolution Security Solutions Team working on SIEM, Endpoint, Timeline, Resolver, etc. Team:Security Generative AI Security Generative AI v8.16.0 labels Aug 8, 2024
const isWelcomeSetup = useMemo(() => {
// if any conversation has a connector id, we're not in welcome set up
return Object.keys(conversations).some(
(conversation) => conversations[conversation]?.apiConfig?.connectorId != null
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was causing a bug, we also need to check that the connector ID is not empty string.

Before:
welcome-bug

after:
welcome-fix

if (
!isLoadingCurrentUserConversations &&
isFetchedConnectors &&
currentConversation &&
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding this condition skips a flash of the missing connector callout when the current conversation is still loading.

Comment on lines +178 to +182
const setDefaultPromptColor = useCallback((): string => {
const randomColor = getRandomEuiColor();
handleColorChange(randomColor, { hex: randomColor, isValid: true });
return randomColor;
}, [handleColorChange]);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been wanting to do this for a while now, random EuiColors for quick prompt colors:

color.mov

await refetchCurrentUserConversations();
}, [onChatCleared, refetchCurrentUserConversations]);

const handleChatSend = useCallback(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handleChatSend previously existed in assistant/index.tsx. As you can see, it calls handleSendMessage. If you check the old assistant/index.tsx, later on in the components handleChatSend gets assigned to handleSendMessage (handleSendMessage={handleChatSend})


const { isLoading, sendMessage, abortStream } = useSendMessage();
const { clearConversation, removeLastMessage } = useConversation();

const handlePromptChange = (prompt: string) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handlePromptChange was just a wrapper on top of setUserPrompt, so it was eliminated.


// Welcome conversation is a special 'setup' case when no connector exists, mostly extracted to `ConnectorSetup` component,
// but currently a bit of state is littered throughout the assistant component. TODO: clean up/isolate this state
const blockBotConversation = useMemo(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All this block bot stuff is now UpgradeLicenseCallToAction. All of this type of logic (what to show in the body: upgrade cta, welcome setup, empty convo, or messages) is now in assistant_body/index.tsx

);

useEffect(() => {
if (areConnectorsFetched && conversationsLoaded && Object.keys(conversations).length > 0) {
Copy link
Contributor Author

@stephmilovic stephmilovic Aug 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This useEffect has relocated to use_current_conversation/index.tsx and is simplified

}
);

useEffect(() => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this useEffect has been eliminated entirely. Now there is a function, initializeDefaultConversationWithConnector that handles when a default conversation without a connector is initialized with the default connector. If necessary, initializeDefaultConversationWithConnector is called on conversation change/update.

Object.keys(conversations).length > 0,
});

const isInitialLoad = useMemo(() => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This fixes the loading behavior. Notice 3 flashes of incorrect content in the before, and loading indicators in the after.

Before:

loading-bad.mov

After:

load-good.mov

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@spong I'm considering using the AssistantAnimatedIcon for the assistant body loading view, but since it is not available in Eui yet, I cannot get that same bounce effect from EuiLoadingLogo. Which do you prefer?

// proper loading component 
<EuiEmptyPrompt icon={<EuiLoadingLogo logo="logoSecurity" size="xl" />} />

// option with AssistantAnimatedIcon
<EuiEmptyPrompt icon={<AssistantAnimatedIcon />} />
option2.mov

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be best for us to confer with @bojanasan & design here since they're handling all the alignment stuff. This is just on initial load as conversations/prompts and all that get set up, right? If we don't have to gate the full UI with a loader I think that would be best UX (and less jitter), but if not what you showed in option2 above looks good to me.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok i sent this thread to @bojanasan

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re: jitter. Without a loading option, there are 3 views shown before showing the proper view:
Screenshot 2024-08-14 at 8 47 07 AM
Screenshot 2024-08-14 at 8 48 26 AM
Screenshot 2024-08-14 at 8 46 52 AM
Screenshot 2024-08-14 at 8 47 00 AM

With the loading UI, there are 2 views: loading and the proper view. No confusion as to if what you're seeing is correct

Copy link

@bojanasan bojanasan Aug 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stephmilovic I think the loading state with the AI logo works well. I think it looks smoother than the other option, and its nice to use the existing AI icon animation. Thanks for noticing the weird content flashes!

Quick question, it would be great if the body content was centered vertically. Is it off right now because of the browser page height?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah its centered its just that the logo has a lot of padding to do that animation around it. this is also a pretty short browser window

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stephmilovic
Copy link
Contributor Author

@elasticmachine merge upstream

Comment on lines +40 to +41
// Why is this named Title and not Id?
const [conversationTitle, setConversationTitle] = useState<string | undefined>(undefined);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a a good question...probably leftover from before persistence when title was id? I would say go ahead and rename this, let's get as far away from conflating id/title as we can, as that's been problematic/messy as of late.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was this just not being used now? Was searching for usages of ConversationSelector and didn't see any, so maybe this was removed awhile back with the settings overhaul?

I am trying to remember why there ended up being multiple of these, but that escapes me now, so it's good we're down-sizing here 🙂

@spong
Copy link
Member

spong commented Aug 15, 2024

If there's already messages in a pre-defined chat the prompt is not getting pre-populated

No messages:

With previous message:

edit: Confirmed this is also pre-existing on main

@spong
Copy link
Member

spong commented Aug 15, 2024

This might've been pre-existing, but when viewing an attack discovery in the assistant, if the alerts tab is open, the attack discovery prompt context is not available:

CleanShot.2024-08-15.at.16.58.38.mp4

edit: this is pre-existing and reproducible on main

@spong
Copy link
Member

spong commented Aug 15, 2024

When connector privileges are missing we don't have any specific gating and the user can't do anything when trying to add a connector:

CleanShot.2024-08-15.at.17.22.47.mp4

edit: this is partially pre-existing -- we have a badge saying there are missing privileges, but can still see the same UX when trying to add a connector:

Copy link
Member

@spong spong left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checked out, code reviewed, and did a buncha desk testing -- LGTM! 👍

Thank you for all the cleanup here @stephmilovic, you've made a world of difference with this refactor!

Note: I did find a couple small bugs around privileges/pre-defined chats (see comments above) and have verified they were pre-existing. Approving now though as everything else looks good. If you end up fixing them here let me know and I'll re-test and verify.

@kibana-ci
Copy link
Collaborator

💛 Build succeeded, but was flaky

Failed CI Steps

Test Failures

  • [job] [logs] FTR Configs #74 / Visualizations - Group 3 lens app - TSVB Open in Lens Dashboard to TSVB to Lens should convert a by reference TSVB viz to a Lens viz

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
integrationAssistant 540 546 +6
securitySolution 5653 5659 +6
total +12

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
integrationAssistant 937.3KB 936.7KB -679.0B
securitySolution 20.7MB 18.0MB -2.7MB
total -2.7MB

Page load bundle

Size of the bundles that are downloaded on every page load. Target size is below 100kb

id before after diff
securitySolution 86.2KB 86.2KB -8.0B
Unknown metric groups

ESLint disabled line counts

id before after diff
@kbn/elastic-assistant 16 15 -1

Total ESLint disabled count

id before after diff
@kbn/elastic-assistant 17 16 -1

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@stephmilovic stephmilovic merged commit 730f8ea into elastic:main Aug 21, 2024
36 checks passed
@kibanamachine kibanamachine added the backport:skip This commit does not require backporting label Aug 21, 2024
@stephmilovic
Copy link
Contributor Author

💚 All backports created successfully

Status Branch Result
8.15

Note: Successful backport PRs will be merged automatically after passing CI.

Questions ?

Please refer to the Backport tool documentation

stephmilovic added a commit to stephmilovic/kibana that referenced this pull request Aug 27, 2024
…lastic#190151)

(cherry picked from commit 730f8ea)

# Conflicts:
#	x-pack/plugins/translations/translations/fr-FR.json
#	x-pack/plugins/translations/translations/ja-JP.json
#	x-pack/plugins/translations/translations/zh-CN.json
stephmilovic added a commit that referenced this pull request Aug 27, 2024
…eanup (#190151) (#191501)

# Backport

This will backport the following commits from `main` to `8.15`:
- [[Security solution] Assistant package `assistant/index.tsx` cleanup
(#190151)](#190151)

<!--- Backport version: 8.9.8 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Steph
Milovic","email":"stephanie.milovic@elastic.co"},"sourceCommit":{"committedDate":"2024-08-21T14:59:24Z","message":"[Security
solution] Assistant package `assistant/index.tsx` cleanup
(#190151)","sha":"730f8eae87612716877d2ec0b3bdba85c2c535d5","branchLabelMapping":{"^v8.16.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","backport:skip","Team:
SecuritySolution","Team:Security Generative
AI","v8.16.0"],"number":190151,"url":"https://github.com/elastic/kibana/pull/190151","mergeCommit":{"message":"[Security
solution] Assistant package `assistant/index.tsx` cleanup
(#190151)","sha":"730f8eae87612716877d2ec0b3bdba85c2c535d5"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v8.16.0","labelRegex":"^v8.16.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/190151","number":190151,"mergeCommit":{"message":"[Security
solution] Assistant package `assistant/index.tsx` cleanup
(#190151)","sha":"730f8eae87612716877d2ec0b3bdba85c2c535d5"}}]}]
BACKPORT-->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backport:skip This commit does not require backporting release_note:skip Skip the PR/issue when compiling release notes Team:Security Generative AI Security Generative AI Team: SecuritySolution Security Solutions Team working on SIEM, Endpoint, Timeline, Resolver, etc. v8.15.1 v8.16.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants