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

Studio: Add dynamic code block to execute wp-cli commands UI AI assistant #232

Merged
merged 41 commits into from
Jun 19, 2024

Conversation

katinthehatsite
Copy link
Contributor

@katinthehatsite katinthehatsite commented Jun 11, 2024

Related to https://github.com/Automattic/dotcom-forge/issues/7526

Proposed Changes

This PR adds that dynamic code block that allows to execute CLI commands inside that block. It also does the following:

  • if the code block contains more than 1 CLI command, the Run button is disabled
  • the Run button is disabled for code blocks that don't have CLI commands
  • when you execute the CLI command, see the output, navigate to another tab and come back, you can see the results of the output preserved

Testing Instructions

  • Pull the changes from this branch locally
  • Start the app with STUDIO_AI=true npm start
  • Navigate to the Assitant tab
  • Ask the assistant to give you a CLI command to list users
  • Observe that it produces a code block
  • Run the command with Run button
  • Confirm that you see the output being rendered
  • Navigate to a different tab
  • Come back to the AI Assistant
  • Observe that the output of the CLI command is preserved:
Capture d’écran, le 2024-06-13 à 10 26 19
  • Try asking for different CLI commands and checking the output

Pre-merge Checklist

  • Have you checked for TypeScript, React or other console errors?

@katinthehatsite katinthehatsite self-assigned this Jun 11, 2024
@katinthehatsite
Copy link
Contributor Author

A note that I noticed that sometimes CLI output could be strange - for instance, I asked the Chat Assistant to give me CLI commands and it suggested the following but running that command gave strange output that requires action:

Capture d’écran, le 2024-06-12 à 21 49 47

We might need to add a better validation of the commands that we want to run to make sure it does not result into the actionable output like this.

@@ -115,6 +115,7 @@
"hpagent": "1.2.0",
"react-markdown": "^9.0.1",
"semver": "^7.6.0",
"strip-ansi": "^7.1.0",
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 necessary to strip ANSI that comes in the output from CLI - otherwise, the Error and Success messages contain ANSI characters and manually removing them is quite tedious as it is hard to match all of them. I felt like this was appropriate to use

@kozer
Copy link
Contributor

kozer commented Jun 13, 2024

@katinthehatsite nice work!
I left some comments/suggestions.
Other than that it works as expected
image

Note that there are some errors in buildkite/unit-tests that are related to the new library you introduced.

}, 2300 );
}, [ content, id, projectPath, updateMessage ] );

return {
Copy link
Contributor

Choose a reason for hiding this comment

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

[Suggestion]: I find it a bit repetitive. As we call it like this:

	const {
			cliOutput,
			cliStatus,
			cliTime,
			isRunning,
			handleExecute,
			setCliOutput,
			setCliStatus,
			setCliTime,
		} = useExecuteWPCLI( content, projectPath, updateMessage, id );

it is clear enough that this comes from cli.
I suggest to rename them to:

output,
status,
time
setOutput,
setStatus,
setTime

if ( blocks ) {
const block = blocks?.find( ( block ) => block.codeBlockContent === content );
if ( block ) {
setCliOutput( block?.cliOutput ? stripAnsi( block.cliOutput ) : null );
Copy link
Contributor

Choose a reason for hiding this comment

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

[Suggestion] I suggest to change that to setBlock, as this is what those variables actually represent

@katinthehatsite
Copy link
Contributor Author

katinthehatsite commented Jun 13, 2024

Something that still needs to be looked into but documenting it here for the reviewers:

  • when you use Run button and the output appears, the chat scrolls to the bottom of the page. It is because of: that scrolls to the bottom every time an array of messages updates. It would need to be somehow adjusted to scroll through when the messages are added vs. not scroll through when the output is produced (this happens with updateMessage)
  • another thing that the Run button does not go to Run again once the output is generated. This needs to be adjusted as well

@sejas
Copy link
Member

sejas commented Jun 17, 2024

Let's also avoid displaying the Run button if the wp command has some placeholder < >.


export interface Message {
export type Message = {
id?: number;
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 am not 100% sure if this should stay optional or must be mandatory.

@katinthehatsite
Copy link
Contributor Author

katinthehatsite commented Jun 17, 2024

Hi @sejas, since our conversation earlier this morning, I have done the following:

  • Refactored the Run and Run again buttons, reused some of the components that we already have and removed the redundant logic;
  • Fixed the failing unit test;
  • Resolved conflicts with trunk and all the latest changes how now been integrated with trunk
  • Added a check that looks for < and > characters and disables the Run button for these commands

The only other thing I see is that it seems that E2E tests are timing out on Windows 🤔

For the horizontal scroll, I suggest we open a separate issue and handle it in the follow-up. I am not seeing an obvious fix right away and I would prefer to merge the PR asap as it is starting to grow quite large. What do you think?

Let me know what you think of the changes!

Copy link
Member

@sejas sejas left a comment

Choose a reason for hiding this comment

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

Works as expected.
It keeps the result after changing sites and tabs.

@katinthehatsite , great work!

0Hwa8f.mp4

const containsWPCommand = /\bwp\s/.test( content );
const wpCommandCount = ( content.match( /\bwp\s/g ) || [] ).length;
const containsSingleWPCommand = wpCommandCount === 1;
const containsAngleBrackets = /<.*>/.test( content );
Copy link
Member

Choose a reason for hiding this comment

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

We can add more conditions to make this code block only available in a few commands.

Copy link
Contributor

Choose a reason for hiding this comment

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

I noticed that the AI also uses braces {} for argument placeholders. I propose including this symbol in the regular expression. WDYT?

Screenshot 2024-06-26 at 11 50 32

Copy link
Contributor

Choose a reason for hiding this comment

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

I created a PR with improvements in this area.

Copy link
Member

@dcalhoun dcalhoun Jun 26, 2024

Choose a reason for hiding this comment

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

Noting that I have also seen the Assistant exclude wrapping characters altogether for placeholder content, which complicates things a good bit. I suppose the only solution for this case would be adjusting the Assistant prompt in hopes that it avoids this approach or searching for example terms (which is undoubtedly brittle).

Screenshot 2024-06-26 at 09 10 58

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, I haven't encountered that but yes, that definitely complicates the detection of placeholders. As you pointed out, seems the best approach would be to tweak the prompt to ensure it uses the same placeholder to avoid cases like this one.

@sejas sejas merged commit 995de23 into trunk Jun 19, 2024
10 checks passed
@sejas sejas deleted the add/integrate-cli-button-to-execute-in-code-block branch June 19, 2024 14:00
Copy link
Member

@dcalhoun dcalhoun left a comment

Choose a reason for hiding this comment

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

I noted a few issues after pulling these changes. I share them here merely to raise awareness. I'll open a PR addressing them.

@@ -34,6 +40,7 @@ export function CopyTextButton( {
}
setTimeoutId( setTimeout( () => setShowCopied( false ), timeoutConfirmation ) );
}, [ text, timeoutConfirmation, timeoutId ] );
console.log( 'Icon Size:', iconSize );
Copy link
Member

Choose a reason for hiding this comment

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

I suggest we remove this console log. I presume its addition was oversight.

} ) => (
<>
{ messages.map( ( message, index ) => (
<ChatMessage key={ index } id={ `message-${ index }` } isUser={ message.role === 'user' }>
Copy link
Member

@dcalhoun dcalhoun Jun 19, 2024

Choose a reason for hiding this comment

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

It appears the id attribute was removed. The removal introduces a regression where screen readers are no longer able to navigate each message as a group, which was enabled in #248.

I presume this was oversight and likely originates from a merge conflict resolution.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for catching these and adding the PR to fix. Yeah that was a large conflict merge

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants