Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion newIDE/app/src/AiGeneration/AiRequestChat/ChatMessages.js
Original file line number Diff line number Diff line change
Expand Up @@ -460,9 +460,10 @@ export const ChatMessages = React.memo<Props>(function ChatMessages({
size="small"
style={{
backgroundColor: !isPaused
? getBackgroundColor(theme, 'medium')
? getBackgroundColor(theme, 'light')
: undefined,
borderRadius: 4,
padding: 0,
}}
selected={isPaused}
>
Expand Down
74 changes: 31 additions & 43 deletions newIDE/app/src/AiGeneration/AiRequestChat/FunctionCallRow.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ import {
type EditorFunctionWithoutProject,
type EditorCallbacks,
} from '../../EditorFunctions';
import Link from '../../UI/Link';
import { LineStackLayout, ResponsiveLineStackLayout } from '../../UI/Layout';
import { LineStackLayout } from '../../UI/Layout';
import ChevronArrowRight from '../../UI/CustomSvgIcons/ChevronArrowRight';
import ChevronArrowBottom from '../../UI/CustomSvgIcons/ChevronArrowBottom';
import Paper from '../../UI/Paper';
Expand Down Expand Up @@ -153,50 +152,39 @@ export const FunctionCallRow = React.memo<Props>(function FunctionCallRow({
)}
</span>
</Tooltip>
<ResponsiveLineStackLayout
justifyContent="space-between"
expand
noOverflowParent
<Text
size="body-small"
color="secondary"
style={styles.functionCallText}
>
<LineStackLayout noMargin alignItems="baseline">
<Text
size="body-small"
color="secondary"
style={styles.functionCallText}
>
{text || <Trans>Working...</Trans>}
</Text>
{hasDetailsToShow && (
<Text size="body-small" color="secondary">
<Link
color="inherit"
href={'#'}
onClick={() => setShowDetails(!showDetails)}
>
<span style={{ whiteSpace: 'nowrap', gap: 2 }}>
<Trans>Details</Trans>
{details ? (
<ChevronArrowBottom
fontSize="small"
style={{
verticalAlign: 'middle',
}}
/>
) : (
<ChevronArrowRight
fontSize="small"
style={{
verticalAlign: 'middle',
}}
/>
)}
</span>
</Link>
</Text>
{text || <Trans>Working...</Trans>}
</Text>
</LineStackLayout>
{hasDetailsToShow && (
<div
className={classes.detailsButtonContainer}
onClick={() => setShowDetails(!showDetails)}
role="button"
tabIndex={0}
onKeyDown={e => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
setShowDetails(!showDetails);
}
}}
>
<LineStackLayout noMargin alignItems="center">
{showDetails ? (
<ChevronArrowBottom fontSize="small" />
) : (
<ChevronArrowRight fontSize="small" />
)}
<Text noMargin size="body-small" color="secondary">
<Trans>Details</Trans>
</Text>
</LineStackLayout>
</ResponsiveLineStackLayout>
</LineStackLayout>
</div>
)}
{details && (
<div className={classes.detailsPaperContainer}>
<Paper background="medium" elevation={0} square variant="outlined">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,28 @@
}
}

.detailsButtonContainer {
padding-left: 20px;
user-select: none;
padding-bottom: 4px;
display: flex;
align-items: center;
gap: 4px;
outline: none;
}

.detailsButtonContainer:hover {
opacity: 0.7;
}

.detailsButtonContainer:focus-visible {
outline: 2px solid;
outline-offset: 2px;
border-radius: 4px;
}

.detailsPaperContainer {
transform-origin: top left;
animation: details-paper-appear 0.1s;
padding-left: 20px;
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
}

.header {
cursor: pointer;
user-select: none;
padding: 4px 0;
display: flex;
Expand Down
66 changes: 32 additions & 34 deletions newIDE/app/src/AiGeneration/AiRequestChat/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ const styles = {
},
};

type Props = {
type Props = {|
project: ?gdProject,
i18n: I18nType,
aiRequest: AiRequest | null,
Expand All @@ -77,10 +77,7 @@ type Props = {
mode: 'chat' | 'agent',
aiConfigurationPresetId: string,
|}) => void,
onSendMessage: (options: {|
userMessage: string,
createdSceneNames?: Array<string>,
|}) => Promise<void>,
onSendUserMessage: (userMessage: string) => Promise<void>,
onSendFeedback: (
aiRequestId: string,
messageIndex: number,
Expand Down Expand Up @@ -115,7 +112,7 @@ type Props = {
availableCredits: number,

standAloneForm?: boolean,
};
|};

export type AiRequestChatInterface = {|
resetUserInput: (aiRequestId: string | null) => void,
Expand Down Expand Up @@ -324,7 +321,7 @@ export const AiRequestChat = React.forwardRef<Props, AiRequestChatInterface>(
aiRequestMode,
isSending,
onStartNewAiRequest,
onSendMessage,
onSendUserMessage,
onSendFeedback,
onStartOrOpenChat,
quota,
Expand All @@ -345,9 +342,7 @@ export const AiRequestChat = React.forwardRef<Props, AiRequestChatInterface>(
) => {
const {
aiRequestHistory: { handleNavigateHistory, resetNavigation },
editorFunctionCallResultsStorage,
} = React.useContext(AiRequestContext);
const { getEditorFunctionCallResults } = editorFunctionCallResultsStorage;
const { setAiState } = React.useContext(PreferencesContext);

const [
Expand Down Expand Up @@ -396,16 +391,24 @@ export const AiRequestChat = React.forwardRef<Props, AiRequestChatInterface>(
);
const requiredGameId = (aiRequest && aiRequest.gameId) || null;

// Auto-scroll to bottom when content changes, if user is at the bottom
const scrollToBottom = React.useCallback(() => {
if (scrollViewRef.current) {
scrollViewRef.current.scrollToBottom({ behavior: 'smooth' });
}
}, []);

// Auto-scroll to bottom when content changes, if user is at the bottom.
React.useEffect(
() => {
if (shouldAutoScroll && scrollViewRef.current) {
scrollViewRef.current.scrollToBottom({
behavior: 'smooth',
});
}
if (shouldAutoScroll) scrollToBottom();
},
[aiRequest, editorFunctionCallResults, lastSendError, shouldAutoScroll]
[
scrollToBottom,
aiRequest,
editorFunctionCallResults,
lastSendError,
shouldAutoScroll,
]
);

const onScroll = React.useCallback(
Expand Down Expand Up @@ -487,11 +490,7 @@ export const AiRequestChat = React.forwardRef<Props, AiRequestChatInterface>(
const aiRequestIdToReset: string = aiRequestId || '';
onUserRequestTextChange('', aiRequestIdToReset);

if (scrollViewRef.current) {
scrollViewRef.current.scrollToBottom({
behavior: 'smooth',
});
}
scrollToBottom();
},
}));

Expand Down Expand Up @@ -526,7 +525,7 @@ export const AiRequestChat = React.forwardRef<Props, AiRequestChatInterface>(
aiRequest &&
getFunctionCallsToProcess({
aiRequest: aiRequest,
editorFunctionCallResults: getEditorFunctionCallResults(aiRequest.id),
editorFunctionCallResults,
}).length > 0;
const hasWorkingFunctionCalls =
editorFunctionCallResults &&
Expand All @@ -536,7 +535,7 @@ export const AiRequestChat = React.forwardRef<Props, AiRequestChatInterface>(
const hasUnfinishedResult =
aiRequest &&
getFunctionCallOutputsFromEditorFunctionCallResults(
getEditorFunctionCallResults(aiRequest.id)
editorFunctionCallResults
).hasUnfinishedResult;
const hasWorkToProcess =
hasUnfinishedResult ||
Expand Down Expand Up @@ -622,6 +621,7 @@ export const AiRequestChat = React.forwardRef<Props, AiRequestChatInterface>(
)}
<form
onSubmit={() => {
scrollToBottom();
onStartNewAiRequest({
mode: aiRequestMode,
userRequest: userRequestTextPerAiRequestId[''],
Expand All @@ -643,6 +643,7 @@ export const AiRequestChat = React.forwardRef<Props, AiRequestChatInterface>(
}}
onNavigateHistory={handleNavigateHistory}
onSubmit={() => {
scrollToBottom();
onStartNewAiRequest({
mode: aiRequestMode,
userRequest: userRequestTextPerAiRequestId[''],
Expand Down Expand Up @@ -685,6 +686,7 @@ export const AiRequestChat = React.forwardRef<Props, AiRequestChatInterface>(
!hasReachedLimitAndCannotUseCredits)
}
onClick={() => {
scrollToBottom();
onStartNewAiRequest({
mode: aiRequestMode,
userRequest: userRequestTextPerAiRequestId[''],
Expand Down Expand Up @@ -865,9 +867,7 @@ export const AiRequestChat = React.forwardRef<Props, AiRequestChatInterface>(
<form
onSubmit={() => {
setAutoProcessFunctionCalls(true);
onSendMessage({
userMessage: userRequestTextPerAiRequestId[aiRequestId] || '',
});
onSendUserMessage(userRequestTextPerAiRequestId[aiRequestId] || '');
}}
className={classNames({
// Move the form up when the soft keyboard is open:
Expand Down Expand Up @@ -900,10 +900,9 @@ export const AiRequestChat = React.forwardRef<Props, AiRequestChatInterface>(
maxRows={6}
onSubmit={() => {
setAutoProcessFunctionCalls(true);
onSendMessage({
userMessage:
userRequestTextPerAiRequestId[aiRequestId] || '',
});
onSendUserMessage(
userRequestTextPerAiRequestId[aiRequestId] || ''
);
}}
controls={
<Column>
Expand All @@ -923,10 +922,9 @@ export const AiRequestChat = React.forwardRef<Props, AiRequestChatInterface>(
label={sendButtonLabel}
onClick={() => {
setAutoProcessFunctionCalls(true);
onSendMessage({
userMessage:
userRequestTextPerAiRequestId[aiRequestId] || '',
});
onSendUserMessage(
userRequestTextPerAiRequestId[aiRequestId] || ''
);
}}
/>
</LineStackLayout>
Expand Down
49 changes: 24 additions & 25 deletions newIDE/app/src/AiGeneration/AiRequestContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type EditorFunctionCallResultsStorage = {|
addEditorFunctionCallResults: (
aiRequestId: string,
editorFunctionCallResults: EditorFunctionCallResult[]
) => void,
) => EditorFunctionCallResult[],
clearEditorFunctionCallResults: (aiRequestId: string) => void,
|};

Expand All @@ -44,32 +44,31 @@ const useEditorFunctionCallResultsStorage = (): EditorFunctionCallResultsStorage
aiRequestId: string,
editorFunctionCallResults: EditorFunctionCallResult[]
) => {
const existingEditorFunctionCallResults = (
editorFunctionCallResultsPerRequest[aiRequestId] || []
).filter(existingEditorFunctionCallResult => {
return !editorFunctionCallResults.some(editorFunctionCallResult => {
return (
editorFunctionCallResult.call_id ===
existingEditorFunctionCallResult.call_id
);
});
});

const newEditorFunctionCallResultsPerRequest = {
...editorFunctionCallResultsPerRequest,
[aiRequestId]: [
...existingEditorFunctionCallResults,
...editorFunctionCallResults,
],
};
setEditorFunctionCallResultsPerRequest(
editorFunctionCallResultsPerRequest => {
const existingEditorFunctionCallResults = (
editorFunctionCallResultsPerRequest[aiRequestId] || []
).filter(existingEditorFunctionCallResult => {
return !editorFunctionCallResults.some(
editorFunctionCallResult => {
return (
editorFunctionCallResult.call_id ===
existingEditorFunctionCallResult.call_id
);
}
);
});

return {
...editorFunctionCallResultsPerRequest,
[aiRequestId]: [
...existingEditorFunctionCallResults,
...editorFunctionCallResults,
],
};
}
newEditorFunctionCallResultsPerRequest
);

return newEditorFunctionCallResultsPerRequest[aiRequestId];
},
[]
[editorFunctionCallResultsPerRequest]
),
clearEditorFunctionCallResults: React.useCallback((aiRequestId: string) => {
setEditorFunctionCallResultsPerRequest(
Expand Down Expand Up @@ -435,7 +434,7 @@ export const initialAiRequestContextState: AiRequestContextState = {
},
editorFunctionCallResultsStorage: {
getEditorFunctionCallResults: () => [],
addEditorFunctionCallResults: () => {},
addEditorFunctionCallResults: () => [],
clearEditorFunctionCallResults: () => {},
},
getAiSettings: () => null,
Expand Down
Loading