make chat creation explicit
This commit is contained in:
parent
366fde13ce
commit
11cd84fdaa
|
|
@ -27,7 +27,7 @@ import { fixTestPrompt } from '@web/components/prompts';
|
||||||
import type { GitCommitInfo } from '@testIsomorphic/types';
|
import type { GitCommitInfo } from '@testIsomorphic/types';
|
||||||
import { AIConversation } from './aiConversation';
|
import { AIConversation } from './aiConversation';
|
||||||
import { ToolbarButton } from '@web/components/toolbarButton';
|
import { ToolbarButton } from '@web/components/toolbarButton';
|
||||||
import { useLLMChat, useLLMConversation } from './llm';
|
import { useIsLLMAvailable, useLLMChat, useLLMConversation } from './llm';
|
||||||
import { useAsyncMemo } from '@web/uiUtils';
|
import { useAsyncMemo } from '@web/uiUtils';
|
||||||
|
|
||||||
const GitCommitInfoContext = React.createContext<GitCommitInfo | undefined>(undefined);
|
const GitCommitInfoContext = React.createContext<GitCommitInfo | undefined>(undefined);
|
||||||
|
|
@ -99,7 +99,7 @@ export function useErrorsTabModel(model: modelUtil.MultiTraceModel | undefined):
|
||||||
|
|
||||||
function Error({ message, error, errorId, sdkLanguage, pageSnapshot, revealInSource }: { message: string, error: ErrorDescription, errorId: string, sdkLanguage: Language, pageSnapshot?: string, revealInSource: (error: ErrorDescription) => void }) {
|
function Error({ message, error, errorId, sdkLanguage, pageSnapshot, revealInSource }: { message: string, error: ErrorDescription, errorId: string, sdkLanguage: Language, pageSnapshot?: string, revealInSource: (error: ErrorDescription) => void }) {
|
||||||
const [showLLM, setShowLLM] = React.useState(false);
|
const [showLLM, setShowLLM] = React.useState(false);
|
||||||
const llmAvailable = !!useLLMChat();
|
const llmAvailable = useIsLLMAvailable();
|
||||||
const gitCommitInfo = useGitCommitInfo();
|
const gitCommitInfo = useGitCommitInfo();
|
||||||
const diff = gitCommitInfo?.['pull.diff'] ?? gitCommitInfo?.['revision.diff'];
|
const diff = gitCommitInfo?.['pull.diff'] ?? gitCommitInfo?.['revision.diff'];
|
||||||
|
|
||||||
|
|
@ -127,7 +127,7 @@ function Error({ message, error, errorId, sdkLanguage, pageSnapshot, revealInSou
|
||||||
</div>}
|
</div>}
|
||||||
<span style={{ position: 'absolute', right: '5px' }}>
|
<span style={{ position: 'absolute', right: '5px' }}>
|
||||||
{llmAvailable
|
{llmAvailable
|
||||||
? <ToolbarButton onClick={() => setShowLLM(v => !v)} style={{ width: '96px', justifyContent: 'center' }} title='Fix with AI' className='copy-to-clipboard-text-button'>{showLLM ? 'Hide AI' : 'Fix with AI'}</ToolbarButton>
|
? <FixWithAIButton conversationId={errorId} onChange={setShowLLM} value={showLLM} />
|
||||||
: <CopyPromptButton error={message} pageSnapshot={pageSnapshot} diff={diff} />}
|
: <CopyPromptButton error={message} pageSnapshot={pageSnapshot} diff={diff} />}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -138,6 +138,29 @@ function Error({ message, error, errorId, sdkLanguage, pageSnapshot, revealInSou
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function FixWithAIButton({ conversationId, value, onChange }: { conversationId: string, value: boolean, onChange: React.Dispatch<React.SetStateAction<boolean>> }) {
|
||||||
|
const chat = useLLMChat();
|
||||||
|
|
||||||
|
return <ToolbarButton
|
||||||
|
onClick={() => {
|
||||||
|
if (!chat.getConversation(conversationId)) {
|
||||||
|
chat.startConversation(conversationId, [
|
||||||
|
`My Playwright test failed. What's going wrong?`,
|
||||||
|
`Please give me a suggestion how to fix it, and then explain what went wrong. Be very concise and apply Playwright best practices.`,
|
||||||
|
`Don't include many headings in your output. Make sure what you're saying is correct, and take into account whether there might be a bug in the app.`
|
||||||
|
].join('\n'));
|
||||||
|
}
|
||||||
|
|
||||||
|
onChange(v => !v);
|
||||||
|
}}
|
||||||
|
style={{ width: '96px', justifyContent: 'center' }}
|
||||||
|
title='Fix with AI'
|
||||||
|
className='copy-to-clipboard-text-button'
|
||||||
|
>
|
||||||
|
{value ? 'Hide AI' : 'Fix with AI'}
|
||||||
|
</ToolbarButton>;
|
||||||
|
}
|
||||||
|
|
||||||
export const ErrorsTab: React.FunctionComponent<{
|
export const ErrorsTab: React.FunctionComponent<{
|
||||||
errorsModel: ErrorsTabModel,
|
errorsModel: ErrorsTabModel,
|
||||||
actions: modelUtil.ActionTraceEventInContext[],
|
actions: modelUtil.ActionTraceEventInContext[],
|
||||||
|
|
@ -159,14 +182,7 @@ export const ErrorsTab: React.FunctionComponent<{
|
||||||
};
|
};
|
||||||
|
|
||||||
export function AIErrorConversation({ conversationId, error, pageSnapshot, diff }: { conversationId: string, error: string, pageSnapshot?: string, diff?: string }) {
|
export function AIErrorConversation({ conversationId, error, pageSnapshot, diff }: { conversationId: string, error: string, pageSnapshot?: string, diff?: string }) {
|
||||||
const [history, conversation] = useLLMConversation(
|
const [history, conversation] = useLLMConversation(conversationId);
|
||||||
conversationId,
|
|
||||||
[
|
|
||||||
`My Playwright test failed. What's going wrong?`,
|
|
||||||
`Please give me a suggestion how to fix it, and then explain what went wrong. Be very concise and apply Playwright best practices.`,
|
|
||||||
`Don't include many headings in your output. Make sure what you're saying is correct, and take into account whether there might be a bug in the app.`
|
|
||||||
].join('\n')
|
|
||||||
);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
let content = `Here's the error: ${error}`;
|
let content = `Here's the error: ${error}`;
|
||||||
|
|
|
||||||
|
|
@ -170,12 +170,14 @@ class LLMChat {
|
||||||
|
|
||||||
constructor(readonly api: LLM) {}
|
constructor(readonly api: LLM) {}
|
||||||
|
|
||||||
getConversation(id: string, systemPrompt: string) {
|
getConversation(id: string) {
|
||||||
if (!this.conversations.has(id)) {
|
return this.conversations.get(id);
|
||||||
const conversation = new Conversation(this, systemPrompt);
|
}
|
||||||
this.conversations.set(id, conversation); // TODO: cleanup
|
|
||||||
}
|
startConversation(id: string, systemPrompt: string) {
|
||||||
return this.conversations.get(id)!;
|
const conversation = new Conversation(this, systemPrompt);
|
||||||
|
this.conversations.set(id, conversation); // TODO: cleanup
|
||||||
|
return conversation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -237,18 +239,25 @@ export function LLMProvider({ children }: React.PropsWithChildren<{}>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function useLLMChat() {
|
export function useLLMChat() {
|
||||||
return React.useContext(llmContext);
|
const chat = React.useContext(llmContext);
|
||||||
}
|
|
||||||
|
|
||||||
export function useLLMConversation(id: string, systemPrompt: string) {
|
|
||||||
const chat = useLLMChat();
|
|
||||||
if (!chat)
|
if (!chat)
|
||||||
throw new Error('No LLM chat available, make sure theres a LLMProvider above');
|
throw new Error('No LLM chat available, make sure theres a LLMProvider above');
|
||||||
const conversation = React.useMemo(() => chat.getConversation(id, systemPrompt), [chat, id]); // eslint-disable-line react-hooks/exhaustive-deps
|
return chat;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useIsLLMAvailable() {
|
||||||
|
return !!React.useContext(llmContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useLLMConversation(id: string) {
|
||||||
|
const chat = useLLMChat();
|
||||||
|
const conversation = React.useMemo(() => chat.getConversation(id), [chat, id]);
|
||||||
|
if (!conversation)
|
||||||
|
throw new Error('No conversation found for id: ' + id);
|
||||||
const [history, setHistory] = React.useState(conversation.history);
|
const [history, setHistory] = React.useState(conversation.history);
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
function update() {
|
function update() {
|
||||||
setHistory([...conversation.history]);
|
setHistory([...conversation!.history]);
|
||||||
}
|
}
|
||||||
update();
|
update();
|
||||||
const subscription = conversation.onChange.event(update);
|
const subscription = conversation.onChange.event(update);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue