From e3ccb42f58466686dc3459b662ee82eb5366be21 Mon Sep 17 00:00:00 2001 From: Nicolas Bonet Date: Mon, 4 May 2026 12:51:55 -0500 Subject: [PATCH 01/24] feat: add new agent creation functionality and related UI components --- src/CONST/index.ts | 3 + src/ONYXKEYS.ts | 3 + src/ROUTES.ts | 1 + src/SCREENS.ts | 1 + src/components/AvatarButtonWithIcon.tsx | 6 +- src/languages/de.ts | 7 ++ src/languages/en.ts | 7 ++ src/languages/es.ts | 7 ++ src/languages/fr.ts | 7 ++ src/languages/it.ts | 7 ++ src/languages/ja.ts | 7 ++ src/languages/nl.ts | 7 ++ src/languages/pl.ts | 7 ++ src/languages/pt-BR.ts | 7 ++ src/languages/zh-hans.ts | 7 ++ src/libs/API/parameters/CreateAgentParams.ts | 6 + src/libs/API/parameters/index.ts | 1 + src/libs/API/types.ts | 2 + .../ModalStackNavigators/index.tsx | 1 + .../RELATIONS/SETTINGS_TO_RHP.ts | 1 + src/libs/Navigation/linkingConfig/config.ts | 4 + src/libs/Navigation/types.ts | 1 + src/libs/actions/Agent.ts | 65 +++++++++- src/pages/settings/Agents/AgentsPage.tsx | 3 +- src/pages/settings/Agents/NewAgentPage.tsx | 119 ++++++++++++++++++ src/styles/index.ts | 5 + src/types/form/NewAgentForm.ts | 20 +++ src/types/form/index.ts | 1 + 28 files changed, 307 insertions(+), 6 deletions(-) create mode 100644 src/libs/API/parameters/CreateAgentParams.ts create mode 100644 src/pages/settings/Agents/NewAgentPage.tsx create mode 100644 src/types/form/NewAgentForm.ts diff --git a/src/CONST/index.ts b/src/CONST/index.ts index 002848e4747c..342f3495725a 100644 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -9539,6 +9539,9 @@ const CONST = { SIGN_OUT: 'SettingsGeneral-SignOut', GO_TO_CLASSIC: 'SettingsGeneral-GoToExpensifyClassic', }, + NEW_AGENT_PAGE: { + AVATAR: 'NewAgentPage-Avatar', + }, SETTINGS_PROFILE: { AVATAR: 'SettingsProfile-Avatar', DISPLAY_NAME: 'SettingsProfile-DisplayName', diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index 6e7d9dc72238..a26213692cf9 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -1107,6 +1107,8 @@ const ONYXKEYS = { ADD_WORK_EMAIL_FORM_DRAFT: 'addWorkEmailFormDraft', EDIT_DOMAIN_GROUP_NAME_FORM: 'editDomainGroupNameForm', EDIT_DOMAIN_GROUP_NAME_FORM_DRAFT: 'editDomainGroupNameFormDraft', + NEW_AGENT_FORM: 'newAgentForm', + NEW_AGENT_FORM_DRAFT: 'newAgentFormDraft', }, DERIVED: { REPORT_ATTRIBUTES: 'reportAttributes', @@ -1252,6 +1254,7 @@ type OnyxFormValuesMapping = { [ONYXKEYS.FORMS.ADD_DOMAIN_MEMBER_FORM]: FormTypes.AddDomainMemberForm; [ONYXKEYS.FORMS.ADD_WORK_EMAIL_FORM]: FormTypes.AddWorkEmailForm; [ONYXKEYS.FORMS.EDIT_DOMAIN_GROUP_NAME_FORM]: FormTypes.DomainGroupEditNameForm; + [ONYXKEYS.FORMS.NEW_AGENT_FORM]: FormTypes.NewAgentForm; }; type OnyxFormDraftValuesMapping = { diff --git a/src/ROUTES.ts b/src/ROUTES.ts index e0c6d437a70f..f5f749cf05ca 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -870,6 +870,7 @@ const ROUTES = { SETTINGS_WALLET_TRAVEL_CVV: 'settings/wallet/travel-cvv', SETTINGS_WALLET_TRAVEL_CVV_VERIFY_ACCOUNT: `settings/wallet/travel-cvv/${VERIFY_ACCOUNT}`, SETTINGS_AGENTS: 'settings/agents', + SETTINGS_AGENTS_NEW: 'settings/agents/new', SETTINGS_RULES: 'settings/rules', SETTINGS_RULES_ADD: { route: 'settings/rules/new/:field?/:index?', diff --git a/src/SCREENS.ts b/src/SCREENS.ts index a7d812a73f59..b3159016f6f3 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -172,6 +172,7 @@ const SCREENS = { AGENTS: { ROOT: 'Settings_Agents', + NEW: 'Settings_Agents_New', }, RULES: { diff --git a/src/components/AvatarButtonWithIcon.tsx b/src/components/AvatarButtonWithIcon.tsx index cc17434816f9..824e48e58278 100644 --- a/src/components/AvatarButtonWithIcon.tsx +++ b/src/components/AvatarButtonWithIcon.tsx @@ -42,6 +42,9 @@ type AvatarButtonWithIconProps = WithSentryLabel & { /** Additional style props for the edit icon */ editIconStyle?: StyleProp; + /** Fill color for the edit icon */ + editIconFill?: string; + /** A default avatar component to display when there is no source */ DefaultAvatar?: () => React.ReactNode; @@ -74,6 +77,7 @@ function AvatarButtonWithIcon({ DefaultAvatar = () => null, disabledStyle, editIconStyle, + editIconFill, pendingAction, text, onPress, @@ -131,7 +135,7 @@ function AvatarButtonWithIcon({ src={editIcon ?? expensifyIcons.Pencil} width={variables.iconSizeSmall} height={variables.iconSizeSmall} - fill={theme.icon} + fill={editIconFill ?? theme.icon} /> )} diff --git a/src/languages/de.ts b/src/languages/de.ts index 99fc0b2e4460..b6ef586b708f 100644 --- a/src/languages/de.ts +++ b/src/languages/de.ts @@ -2726,6 +2726,13 @@ ${amount} für ${merchant} – ${date}`, newAgent: 'Neue:r Agent:in', emptyAgents: {title: 'Keine Agenten erstellt', subtitle: 'Hör auf, Dinge manuell zu erledigen. Weise stattdessen eine:n Agent:in an und spare dir eine Menge Zeit.'}, }, + newAgentPage: { + title: 'Neuer Agent', + agentName: 'Agentenname', + instructions: 'Benutzerdefinierte Anweisungen schreiben', + createAgent: 'Agent erstellen', + switchAvatar: 'Avatar wechseln', + }, expenseRulesPage: { title: 'Ausgabenregeln', findRule: 'Regel finden', diff --git a/src/languages/en.ts b/src/languages/en.ts index ba38d8931813..3d188457fcdb 100644 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -2783,6 +2783,13 @@ const translations = { subtitle: 'Stop manually doing stuff. Instruct an agent instead and save yourself lots of time.', }, }, + newAgentPage: { + title: 'New agent', + agentName: 'Agent name', + instructions: 'Write custom instructions', + createAgent: 'Create agent', + switchAvatar: 'Switch avatar', + }, expenseRulesPage: { title: 'Expense rules', subtitle: 'These rules will apply to your expenses.', diff --git a/src/languages/es.ts b/src/languages/es.ts index 745b29b85a84..3f3f9c5a5514 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -2618,6 +2618,13 @@ ${amount} para ${merchant} - ${date}`, subtitle: 'Deja de hacer las cosas manualmente. En su lugar, instruye a un agente y ahorra mucho tiempo.', }, }, + newAgentPage: { + title: 'Nuevo agente', + agentName: 'Nombre del agente', + instructions: 'Escribe instrucciones personalizadas', + createAgent: 'Crear agente', + switchAvatar: 'Cambiar avatar', + }, expenseRulesPage: { title: 'Reglas de gastos', subtitle: 'Estas reglas se aplicarán a tus gastos.', diff --git a/src/languages/fr.ts b/src/languages/fr.ts index 2d3c7d1dbbc7..c3ffff785022 100644 --- a/src/languages/fr.ts +++ b/src/languages/fr.ts @@ -2732,6 +2732,13 @@ ${amount} pour ${merchant} - ${date}`, newAgent: 'Nouvel agent', emptyAgents: {title: 'Aucun agent créé', subtitle: 'Arrêtez de faire les choses manuellement. Donnez plutôt des instructions à un agent et gagnez beaucoup de temps.'}, }, + newAgentPage: { + title: 'Nouvel agent', + agentName: "Nom de l'agent", + instructions: 'Rédiger des instructions personnalisées', + createAgent: 'Créer un agent', + switchAvatar: "Changer l'avatar", + }, expenseRulesPage: { title: 'Règles de dépenses', findRule: 'Rechercher une règle', diff --git a/src/languages/it.ts b/src/languages/it.ts index 06bbc1f28549..4b721d49ce41 100644 --- a/src/languages/it.ts +++ b/src/languages/it.ts @@ -2722,6 +2722,13 @@ ${amount} per ${merchant} - ${date}`, newAgent: 'Nuovo agente', emptyAgents: {title: 'Nessun agente creato', subtitle: 'Smetti di fare le cose manualmente. Dai istruzioni a un agente e risparmia un sacco di tempo.'}, }, + newAgentPage: { + title: 'Nuovo agente', + agentName: "Nome dell'agente", + instructions: 'Scrivi istruzioni personalizzate', + createAgent: 'Crea agente', + switchAvatar: "Cambia l'avatar", + }, expenseRulesPage: { title: 'Regole spese', findRule: 'Trova regola', diff --git a/src/languages/ja.ts b/src/languages/ja.ts index ac5a03f90794..411b3f318531 100644 --- a/src/languages/ja.ts +++ b/src/languages/ja.ts @@ -2695,6 +2695,13 @@ ${date} の ${merchant} への ${amount}`, newAgent: '新しいエージェント', emptyAgents: {title: 'エージェントは作成されていません', subtitle: '手作業はやめて、代わりにエージェントに指示を出して、時間を大幅に節約しましょう。'}, }, + newAgentPage: { + title: '新しいエージェント', + agentName: 'エージェント名', + instructions: 'カスタム指示を書く', + createAgent: 'エージェントを作成', + switchAvatar: 'アバターを変更', + }, expenseRulesPage: { title: '経費ルール', findRule: 'ルールを検索', diff --git a/src/languages/nl.ts b/src/languages/nl.ts index 5cbb18b520ad..035d7d820cf6 100644 --- a/src/languages/nl.ts +++ b/src/languages/nl.ts @@ -2719,6 +2719,13 @@ ${amount} voor ${merchant} - ${date}`, newAgent: 'Nieuwe medewerker', emptyAgents: {title: 'Geen agents aangemaakt', subtitle: 'Stop met dingen handmatig doen. Geef in plaats daarvan een opdracht aan een agent en bespaar jezelf veel tijd.'}, }, + newAgentPage: { + title: 'Nieuwe agent', + agentName: 'Agentnaam', + instructions: 'Schrijf aangepaste instructies', + createAgent: 'Agent aanmaken', + switchAvatar: 'Avatar wijzigen', + }, expenseRulesPage: { title: 'Declaratieregels', findRule: 'Regel zoeken', diff --git a/src/languages/pl.ts b/src/languages/pl.ts index c5288fd5c935..545254903910 100644 --- a/src/languages/pl.ts +++ b/src/languages/pl.ts @@ -2713,6 +2713,13 @@ ${amount} dla ${merchant} - ${date}`, newAgent: 'Nowy agent', emptyAgents: {title: 'Nie utworzono agentów', subtitle: 'Przestań robić wszystko ręcznie. Zamiast tego wydaj polecenia agentowi i zaoszczędź mnóstwo czasu.'}, }, + newAgentPage: { + title: 'Nowy agent', + agentName: 'Nazwa agenta', + instructions: 'Napisz niestandardowe instrukcje', + createAgent: 'Utwórz agenta', + switchAvatar: 'Zmień avatar', + }, expenseRulesPage: { title: 'Reguły wydatków', findRule: 'Znajdź regułę', diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts index 7dc9be735efe..0a235bf8b108 100644 --- a/src/languages/pt-BR.ts +++ b/src/languages/pt-BR.ts @@ -2713,6 +2713,13 @@ ${amount} para ${merchant} - ${date}`, newAgent: 'Novo agente', emptyAgents: {title: 'Nenhum agente criado', subtitle: 'Pare de fazer tudo manualmente. Instrua um agente e economize muito tempo.'}, }, + newAgentPage: { + title: 'Novo agente', + agentName: 'Nome do agente', + instructions: 'Escrever instruções personalizadas', + createAgent: 'Criar agente', + switchAvatar: 'Trocar avatar', + }, expenseRulesPage: { title: 'Regras de despesas', findRule: 'Encontrar regra', diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts index 391e1db13561..0d2a3d8b42cf 100644 --- a/src/languages/zh-hans.ts +++ b/src/languages/zh-hans.ts @@ -2645,6 +2645,13 @@ ${amount},商户:${merchant} - 日期:${date}`, newAgent: '新代理人', emptyAgents: {title: '尚未创建代理', subtitle: '别再手动处理这些事情了。交给智能代理去执行,为自己节省大量时间。'}, }, + newAgentPage: { + title: '新代理', + agentName: '代理名称', + instructions: '编写自定义指令', + createAgent: '创建代理', + switchAvatar: '切换头像', + }, expenseRulesPage: { title: '报销规则', findRule: '查找规则', diff --git a/src/libs/API/parameters/CreateAgentParams.ts b/src/libs/API/parameters/CreateAgentParams.ts new file mode 100644 index 000000000000..291417171e5c --- /dev/null +++ b/src/libs/API/parameters/CreateAgentParams.ts @@ -0,0 +1,6 @@ +type CreateAgentParams = { + agentName: string; + prompt: string; +}; + +export default CreateAgentParams; diff --git a/src/libs/API/parameters/index.ts b/src/libs/API/parameters/index.ts index 2f83fe5583d5..819c40ade1b9 100644 --- a/src/libs/API/parameters/index.ts +++ b/src/libs/API/parameters/index.ts @@ -521,3 +521,4 @@ export type {default as InitiateBankAccountUnlockParams} from './InitiateBankAcc export type {default as UpdateDomainSecurityGroupParams} from './UpdateDomainSecurityGroupParams'; export type {default as SetDefaultDomainSecurityGroupParams} from './SetDefaultDomainSecurityGroupParams'; export type {default as DeleteDomainSecurityGroupParams} from './DeleteDomainSecurityGroupParams'; +export type {default as CreateAgentParams} from './CreateAgentParams'; diff --git a/src/libs/API/types.ts b/src/libs/API/types.ts index 30f580fb0648..ecbdce188127 100644 --- a/src/libs/API/types.ts +++ b/src/libs/API/types.ts @@ -586,6 +586,7 @@ const WRITE_COMMANDS = { UPDATE_DOMAIN_SECURITY_GROUP: 'UpdateDomainSecurityGroupForNewDot', SET_DEFAULT_DOMAIN_SECURITY_GROUP: 'SetDefaultDomainSecurityGroup', DELETE_DOMAIN_SECURITY_GROUP: 'DeleteDomainSecurityGroup', + CREATE_AGENT: 'CreateAgent', } as const; type WriteCommand = ValueOf; @@ -1189,6 +1190,7 @@ type WriteCommandParameters = { [WRITE_COMMANDS.UPDATE_DOMAIN_SECURITY_GROUP]: Parameters.UpdateDomainSecurityGroupParams; [WRITE_COMMANDS.SET_DEFAULT_DOMAIN_SECURITY_GROUP]: Parameters.SetDefaultDomainSecurityGroupParams; [WRITE_COMMANDS.DELETE_DOMAIN_SECURITY_GROUP]: Parameters.DeleteDomainSecurityGroupParams; + [WRITE_COMMANDS.CREATE_AGENT]: Parameters.CreateAgentParams; }; const READ_COMMANDS = { diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index b10ec42b3f04..1d3986b95f11 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -466,6 +466,7 @@ const SettingsModalStackNavigator = createModalStackNavigator('../../../../pages/settings/Wallet/InternationalDepositAccount/CountrySelectionVerifyAccountPage').default, [SCREENS.SETTINGS.BANK_ACCOUNT_PURPOSE]: () => require('../../../../pages/settings/Wallet/BankAccountPurposePage').default, [SCREENS.SETTINGS.RULES.ROOT]: () => require('../../../../pages/settings/Rules/ExpenseRulesPage').default, + [SCREENS.SETTINGS.AGENTS.NEW]: () => require('../../../../pages/settings/Agents/NewAgentPage').default, [SCREENS.SETTINGS.RULES.ADD]: () => require('../../../../pages/settings/Rules/AddRulePage').default, [SCREENS.SETTINGS.RULES.ADD_MERCHANT]: () => require('../../../../pages/settings/Rules/Fields/AddMerchantPage').default, [SCREENS.SETTINGS.RULES.ADD_RENAME_MERCHANT]: () => require('../../../../pages/settings/Rules/Fields/AddRenameMerchantPage').default, diff --git a/src/libs/Navigation/linkingConfig/RELATIONS/SETTINGS_TO_RHP.ts b/src/libs/Navigation/linkingConfig/RELATIONS/SETTINGS_TO_RHP.ts index 0abe30ed3b2d..525076617897 100755 --- a/src/libs/Navigation/linkingConfig/RELATIONS/SETTINGS_TO_RHP.ts +++ b/src/libs/Navigation/linkingConfig/RELATIONS/SETTINGS_TO_RHP.ts @@ -70,6 +70,7 @@ const SETTINGS_TO_RHP: Partial['config'] = { path: ROUTES.SETTINGS_BANK_ACCOUNT_PURPOSE, exact: true, }, + [SCREENS.SETTINGS.AGENTS.NEW]: { + path: ROUTES.SETTINGS_AGENTS_NEW, + exact: true, + }, [SCREENS.SETTINGS.RULES.ADD]: { path: ROUTES.SETTINGS_RULES_ADD.route, exact: true, diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 29e26555278a..881341e03815 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -256,6 +256,7 @@ type SettingsNavigatorParamList = { }; [SCREENS.SETTINGS.BANK_ACCOUNT_PURPOSE]: undefined; [SCREENS.SETTINGS.ADD_BANK_ACCOUNT_SELECT_COUNTRY_VERIFY_ACCOUNT]: undefined; + [SCREENS.SETTINGS.AGENTS.NEW]: undefined; [SCREENS.SETTINGS.RULES.ADD]: undefined; [SCREENS.SETTINGS.RULES.ADD_MERCHANT]: undefined; [SCREENS.SETTINGS.RULES.ADD_RENAME_MERCHANT]: undefined; diff --git a/src/libs/actions/Agent.ts b/src/libs/actions/Agent.ts index 19e601b172bf..a2ea93a617e8 100644 --- a/src/libs/actions/Agent.ts +++ b/src/libs/actions/Agent.ts @@ -1,9 +1,66 @@ -import {read} from '@libs/API'; -import {READ_COMMANDS} from '@libs/API/types'; +import Onyx from 'react-native-onyx'; +import {read, write} from '@libs/API'; +import {READ_COMMANDS, WRITE_COMMANDS} from '@libs/API/types'; +import ONYXKEYS from '@src/ONYXKEYS'; +import type {AnyOnyxUpdate} from '@src/types/onyx/Request'; function openAgentsPage() { read(READ_COMMANDS.OPEN_AGENTS_PAGE, null); } -// eslint-disable-next-line import/prefer-default-export -export {openAgentsPage}; +function createAgent(agentName: string, prompt: string) { + const optimisticAccountID = -Math.round(Math.random() * 1000000); + + const optimisticData: AnyOnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + value: { + [optimisticAccountID]: { + accountID: optimisticAccountID, + displayName: agentName, + isOptimisticPersonalDetail: true, + }, + }, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT}${optimisticAccountID}`, + value: {prompt}, + }, + ]; + + const successData: AnyOnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + value: { + [optimisticAccountID]: null, + }, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT}${optimisticAccountID}`, + value: null, + }, + ]; + + const failureData: AnyOnyxUpdate[] = [ + { + onyxMethod: Onyx.METHOD.MERGE, + key: ONYXKEYS.PERSONAL_DETAILS_LIST, + value: { + [optimisticAccountID]: null, + }, + }, + { + onyxMethod: Onyx.METHOD.SET, + key: `${ONYXKEYS.COLLECTION.SHARED_NVP_AGENT_PROMPT}${optimisticAccountID}`, + value: null, + }, + ]; + + write(WRITE_COMMANDS.CREATE_AGENT, {agentName, prompt}, {optimisticData, successData, failureData}); +} + +export {openAgentsPage, createAgent}; diff --git a/src/pages/settings/Agents/AgentsPage.tsx b/src/pages/settings/Agents/AgentsPage.tsx index 74e1d6de0e72..474b455a3b90 100644 --- a/src/pages/settings/Agents/AgentsPage.tsx +++ b/src/pages/settings/Agents/AgentsPage.tsx @@ -19,6 +19,7 @@ import NotFoundPage from '@pages/ErrorPage/NotFoundPage'; import {openAgentsPage} from '@userActions/Agent'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; +import ROUTES from '@src/ROUTES'; import AgentsListRow from './AgentsListRow'; type AgentItem = { @@ -79,7 +80,7 @@ function AgentsPage() { success icon={icons.Plus} text={translate('agentsPage.newAgent')} - onPress={() => {}} + onPress={() => Navigation.navigate(ROUTES.SETTINGS_AGENTS_NEW)} /> ); diff --git a/src/pages/settings/Agents/NewAgentPage.tsx b/src/pages/settings/Agents/NewAgentPage.tsx new file mode 100644 index 000000000000..34f526f44aa1 --- /dev/null +++ b/src/pages/settings/Agents/NewAgentPage.tsx @@ -0,0 +1,119 @@ +import React from 'react'; +import {View} from 'react-native'; +import AvatarButtonWithIcon from '@components/AvatarButtonWithIcon'; +import FormProvider from '@components/Form/FormProvider'; +import InputWrapper from '@components/Form/InputWrapper'; +import type {FormOnyxValues} from '@components/Form/types'; +import HeaderWithBackButton from '@components/HeaderWithBackButton'; +import {usePersonalDetails} from '@components/OnyxListItemProvider'; +import ScreenWrapper from '@components/ScreenWrapper'; +import TextInput from '@components/TextInput'; +import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset'; +import useLocalize from '@hooks/useLocalize'; +import useOnyx from '@hooks/useOnyx'; +import useTheme from '@hooks/useTheme'; +import useThemeStyles from '@hooks/useThemeStyles'; +import Navigation from '@libs/Navigation/Navigation'; +import {createAgent} from '@userActions/Agent'; +import CONST from '@src/CONST'; +import ONYXKEYS from '@src/ONYXKEYS'; +import INPUT_IDS from '@src/types/form/NewAgentForm'; +import type {Errors} from '@src/types/onyx/OnyxCommon'; + +function NewAgentPage() { + const {translate} = useLocalize(); + const styles = useThemeStyles(); + const theme = useTheme(); + const illustrations = useMemoizedLazyIllustrations(['AiBot']); + const expensifyIcons = useMemoizedLazyExpensifyIcons(['Sync']); + const personalDetailsList = usePersonalDetails(); + const [session] = useOnyx(ONYXKEYS.SESSION); + + const currentUserDisplayName = personalDetailsList?.[session?.accountID ?? CONST.DEFAULT_NUMBER_ID]?.displayName ?? ''; + const defaultAgentName = `${currentUserDisplayName}'s Agent`; + + const avatarStyle = [styles.avatarXLarge, styles.alignSelfCenter]; + + const validate = (values: FormOnyxValues): Errors => { + const errors: Errors = {}; + if (!values[INPUT_IDS.AGENT_NAME].trim()) { + errors[INPUT_IDS.AGENT_NAME] = translate('common.error.fieldRequired'); + } + if (!values[INPUT_IDS.INSTRUCTIONS].trim()) { + errors[INPUT_IDS.INSTRUCTIONS] = translate('common.error.fieldRequired'); + } + return errors; + }; + + const handleSubmit = (values: FormOnyxValues) => { + createAgent(values[INPUT_IDS.AGENT_NAME].trim(), values[INPUT_IDS.INSTRUCTIONS].trim()); + Navigation.goBack(); + }; + + return ( + + Navigation.goBack()} + /> + + + {}} + size={CONST.AVATAR_SIZE.X_LARGE} + avatarStyle={avatarStyle} + editIcon={expensifyIcons.Sync} + editIconStyle={styles.smallEditIconAgent} + editIconFill={theme.textLight} + sentryLabel={CONST.SENTRY_LABEL.NEW_AGENT_PAGE.AVATAR} + /> + + + + + + + + + + ); +} + +NewAgentPage.displayName = 'NewAgentPage'; + +export default NewAgentPage; diff --git a/src/styles/index.ts b/src/styles/index.ts index 74ec3a78ef42..e514443df58e 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -3289,6 +3289,11 @@ const staticStyles = (theme: ThemeColors) => borderColor: theme.appBG, }, + smallEditIconAgent: { + backgroundColor: theme.icon, + borderWidth: 0, + }, + smallAvatarEditIcon: { position: 'absolute', right: -8, diff --git a/src/types/form/NewAgentForm.ts b/src/types/form/NewAgentForm.ts new file mode 100644 index 000000000000..b1fbce61139e --- /dev/null +++ b/src/types/form/NewAgentForm.ts @@ -0,0 +1,20 @@ +import type {ValueOf} from 'type-fest'; +import type Form from './Form'; + +const INPUT_IDS = { + AGENT_NAME: 'agentName', + INSTRUCTIONS: 'instructions', +} as const; + +type InputID = ValueOf; + +type NewAgentForm = Form< + InputID, + { + [INPUT_IDS.AGENT_NAME]: string; + [INPUT_IDS.INSTRUCTIONS]: string; + } +>; + +export type {NewAgentForm}; +export default INPUT_IDS; diff --git a/src/types/form/index.ts b/src/types/form/index.ts index 58ef8b698fb7..8d9570b52970 100644 --- a/src/types/form/index.ts +++ b/src/types/form/index.ts @@ -123,3 +123,4 @@ export type {DomainGroupEditNameForm} from './DomainGroupEditNameForm'; export type {WorkspaceTimeTrackingDefaultRateForm} from './WorkspaceTimeTrackingDefaultRateForm'; export type {EditExpensifyCardLimitTypeForm} from './EditExpensifyCardLimitTypeForm'; export type {AddWorkEmailForm} from './AddWorkEmailForm'; +export type {NewAgentForm} from './NewAgentForm'; From 41ea5bb5eba0c5811d44d407468c0b8424f83aac Mon Sep 17 00:00:00 2001 From: Nicolas Bonet Date: Mon, 4 May 2026 13:05:19 -0500 Subject: [PATCH 02/24] feat: rename and refactor agent creation components and routes --- src/CONST/index.ts | 4 +- src/ONYXKEYS.ts | 6 +-- src/ROUTES.ts | 2 +- src/SCREENS.ts | 2 +- src/languages/de.ts | 4 +- src/languages/en.ts | 4 +- src/languages/es.ts | 4 +- src/languages/fr.ts | 4 +- src/languages/it.ts | 4 +- src/languages/ja.ts | 4 +- src/languages/nl.ts | 4 +- src/languages/pl.ts | 4 +- src/languages/pt-BR.ts | 4 +- src/languages/zh-hans.ts | 4 +- src/libs/API/parameters/CreateAgentParams.ts | 3 +- .../ModalStackNavigators/index.tsx | 2 +- .../RELATIONS/SETTINGS_TO_RHP.ts | 2 +- src/libs/Navigation/linkingConfig/config.ts | 4 +- src/libs/Navigation/types.ts | 2 +- src/libs/actions/Agent.ts | 6 +-- .../{NewAgentPage.tsx => AddAgentPage.tsx} | 46 +++++++++---------- src/pages/settings/Agents/AgentsListRow.tsx | 44 +++++++++++++++++- src/pages/settings/Agents/AgentsPage.tsx | 2 +- .../form/{NewAgentForm.ts => AddAgentForm.ts} | 12 ++--- src/types/form/index.ts | 2 +- 25 files changed, 121 insertions(+), 58 deletions(-) rename src/pages/settings/Agents/{NewAgentPage.tsx => AddAgentPage.tsx} (75%) rename src/types/form/{NewAgentForm.ts => AddAgentForm.ts} (50%) diff --git a/src/CONST/index.ts b/src/CONST/index.ts index 342f3495725a..fae5916c7d7c 100644 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -9539,8 +9539,8 @@ const CONST = { SIGN_OUT: 'SettingsGeneral-SignOut', GO_TO_CLASSIC: 'SettingsGeneral-GoToExpensifyClassic', }, - NEW_AGENT_PAGE: { - AVATAR: 'NewAgentPage-Avatar', + ADD_AGENT_PAGE: { + AVATAR: 'AddAgentPage-Avatar', }, SETTINGS_PROFILE: { AVATAR: 'SettingsProfile-Avatar', diff --git a/src/ONYXKEYS.ts b/src/ONYXKEYS.ts index a26213692cf9..d56f664119d6 100755 --- a/src/ONYXKEYS.ts +++ b/src/ONYXKEYS.ts @@ -1107,8 +1107,8 @@ const ONYXKEYS = { ADD_WORK_EMAIL_FORM_DRAFT: 'addWorkEmailFormDraft', EDIT_DOMAIN_GROUP_NAME_FORM: 'editDomainGroupNameForm', EDIT_DOMAIN_GROUP_NAME_FORM_DRAFT: 'editDomainGroupNameFormDraft', - NEW_AGENT_FORM: 'newAgentForm', - NEW_AGENT_FORM_DRAFT: 'newAgentFormDraft', + ADD_AGENT_FORM: 'addAgentForm', + ADD_AGENT_FORM_DRAFT: 'addAgentFormDraft', }, DERIVED: { REPORT_ATTRIBUTES: 'reportAttributes', @@ -1254,7 +1254,7 @@ type OnyxFormValuesMapping = { [ONYXKEYS.FORMS.ADD_DOMAIN_MEMBER_FORM]: FormTypes.AddDomainMemberForm; [ONYXKEYS.FORMS.ADD_WORK_EMAIL_FORM]: FormTypes.AddWorkEmailForm; [ONYXKEYS.FORMS.EDIT_DOMAIN_GROUP_NAME_FORM]: FormTypes.DomainGroupEditNameForm; - [ONYXKEYS.FORMS.NEW_AGENT_FORM]: FormTypes.NewAgentForm; + [ONYXKEYS.FORMS.ADD_AGENT_FORM]: FormTypes.AddAgentForm; }; type OnyxFormDraftValuesMapping = { diff --git a/src/ROUTES.ts b/src/ROUTES.ts index f5f749cf05ca..97ebe8ebdaf1 100644 --- a/src/ROUTES.ts +++ b/src/ROUTES.ts @@ -870,7 +870,7 @@ const ROUTES = { SETTINGS_WALLET_TRAVEL_CVV: 'settings/wallet/travel-cvv', SETTINGS_WALLET_TRAVEL_CVV_VERIFY_ACCOUNT: `settings/wallet/travel-cvv/${VERIFY_ACCOUNT}`, SETTINGS_AGENTS: 'settings/agents', - SETTINGS_AGENTS_NEW: 'settings/agents/new', + SETTINGS_AGENTS_ADD: 'settings/agents/new', SETTINGS_RULES: 'settings/rules', SETTINGS_RULES_ADD: { route: 'settings/rules/new/:field?/:index?', diff --git a/src/SCREENS.ts b/src/SCREENS.ts index b3159016f6f3..5938bd77f006 100644 --- a/src/SCREENS.ts +++ b/src/SCREENS.ts @@ -172,7 +172,7 @@ const SCREENS = { AGENTS: { ROOT: 'Settings_Agents', - NEW: 'Settings_Agents_New', + ADD: 'Settings_Agents_Add', }, RULES: { diff --git a/src/languages/de.ts b/src/languages/de.ts index b6ef586b708f..8cabf55d7bdb 100644 --- a/src/languages/de.ts +++ b/src/languages/de.ts @@ -2724,9 +2724,11 @@ ${amount} für ${merchant} – ${date}`, title: 'Agenten', subtitle: 'Erstelle Agents, die deinen Workflow übernehmen. Spare dir die manuelle Arbeit und gewinne stundenweise Zeit im Alltag zurück.', newAgent: 'Neue:r Agent:in', + chat: 'Chat', + copilot: 'Co-pilot', emptyAgents: {title: 'Keine Agenten erstellt', subtitle: 'Hör auf, Dinge manuell zu erledigen. Weise stattdessen eine:n Agent:in an und spare dir eine Menge Zeit.'}, }, - newAgentPage: { + addAgentPage: { title: 'Neuer Agent', agentName: 'Agentenname', instructions: 'Benutzerdefinierte Anweisungen schreiben', diff --git a/src/languages/en.ts b/src/languages/en.ts index 3d188457fcdb..b0ab312c54cf 100644 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -2778,12 +2778,14 @@ const translations = { title: 'Agents', subtitle: 'Create agents to handle your workflow. Skip the manual work and get hours back in your day.', newAgent: 'New agent', + chat: 'Chat', + copilot: 'Co-pilot', emptyAgents: { title: 'No agents created', subtitle: 'Stop manually doing stuff. Instruct an agent instead and save yourself lots of time.', }, }, - newAgentPage: { + addAgentPage: { title: 'New agent', agentName: 'Agent name', instructions: 'Write custom instructions', diff --git a/src/languages/es.ts b/src/languages/es.ts index 3f3f9c5a5514..6967014a8650 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -2613,12 +2613,14 @@ ${amount} para ${merchant} - ${date}`, title: 'Agentes', subtitle: 'Automatiza tareas con agentes personalizados.', newAgent: 'Nuevo agente', + chat: 'Chat', + copilot: 'Co-pilot', emptyAgents: { title: 'No se han creado agentes.', subtitle: 'Deja de hacer las cosas manualmente. En su lugar, instruye a un agente y ahorra mucho tiempo.', }, }, - newAgentPage: { + addAgentPage: { title: 'Nuevo agente', agentName: 'Nombre del agente', instructions: 'Escribe instrucciones personalizadas', diff --git a/src/languages/fr.ts b/src/languages/fr.ts index c3ffff785022..24dfa251c5e4 100644 --- a/src/languages/fr.ts +++ b/src/languages/fr.ts @@ -2730,9 +2730,11 @@ ${amount} pour ${merchant} - ${date}`, title: 'Agents', subtitle: 'Créez des agents pour gérer votre flux de travail. Évitez le travail manuel et gagnez des heures dans votre journée.', newAgent: 'Nouvel agent', + chat: 'Chat', + copilot: 'Co-pilot', emptyAgents: {title: 'Aucun agent créé', subtitle: 'Arrêtez de faire les choses manuellement. Donnez plutôt des instructions à un agent et gagnez beaucoup de temps.'}, }, - newAgentPage: { + addAgentPage: { title: 'Nouvel agent', agentName: "Nom de l'agent", instructions: 'Rédiger des instructions personnalisées', diff --git a/src/languages/it.ts b/src/languages/it.ts index 4b721d49ce41..b5058aa2ad58 100644 --- a/src/languages/it.ts +++ b/src/languages/it.ts @@ -2720,9 +2720,11 @@ ${amount} per ${merchant} - ${date}`, title: 'Agenti', subtitle: 'Crea agenti per gestire il tuo flusso di lavoro. Elimina il lavoro manuale e recupera ore della tua giornata.', newAgent: 'Nuovo agente', + chat: 'Chat', + copilot: 'Co-pilot', emptyAgents: {title: 'Nessun agente creato', subtitle: 'Smetti di fare le cose manualmente. Dai istruzioni a un agente e risparmia un sacco di tempo.'}, }, - newAgentPage: { + addAgentPage: { title: 'Nuovo agente', agentName: "Nome dell'agente", instructions: 'Scrivi istruzioni personalizzate', diff --git a/src/languages/ja.ts b/src/languages/ja.ts index 411b3f318531..5e289443755e 100644 --- a/src/languages/ja.ts +++ b/src/languages/ja.ts @@ -2693,9 +2693,11 @@ ${date} の ${merchant} への ${amount}`, title: '担当者', subtitle: 'ワークフローを処理するエージェントを作成しましょう。手作業を省いて、1日の時間を何時間も取り戻せます。', newAgent: '新しいエージェント', + chat: 'Chat', + copilot: 'Co-pilot', emptyAgents: {title: 'エージェントは作成されていません', subtitle: '手作業はやめて、代わりにエージェントに指示を出して、時間を大幅に節約しましょう。'}, }, - newAgentPage: { + addAgentPage: { title: '新しいエージェント', agentName: 'エージェント名', instructions: 'カスタム指示を書く', diff --git a/src/languages/nl.ts b/src/languages/nl.ts index 035d7d820cf6..baf4784d6a9a 100644 --- a/src/languages/nl.ts +++ b/src/languages/nl.ts @@ -2717,9 +2717,11 @@ ${amount} voor ${merchant} - ${date}`, title: 'Agenten', subtitle: 'Maak agents aan om je workflow af te handelen. Sla het handmatige werk over en krijg uren van je dag terug.', newAgent: 'Nieuwe medewerker', + chat: 'Chat', + copilot: 'Co-pilot', emptyAgents: {title: 'Geen agents aangemaakt', subtitle: 'Stop met dingen handmatig doen. Geef in plaats daarvan een opdracht aan een agent en bespaar jezelf veel tijd.'}, }, - newAgentPage: { + addAgentPage: { title: 'Nieuwe agent', agentName: 'Agentnaam', instructions: 'Schrijf aangepaste instructies', diff --git a/src/languages/pl.ts b/src/languages/pl.ts index 545254903910..f5b6f213aa6a 100644 --- a/src/languages/pl.ts +++ b/src/languages/pl.ts @@ -2711,9 +2711,11 @@ ${amount} dla ${merchant} - ${date}`, title: 'Agenci', subtitle: 'Twórz agentów do obsługi swojego przepływu pracy. Pomiń ręczną pracę i odzyskaj godziny w ciągu dnia.', newAgent: 'Nowy agent', + chat: 'Chat', + copilot: 'Co-pilot', emptyAgents: {title: 'Nie utworzono agentów', subtitle: 'Przestań robić wszystko ręcznie. Zamiast tego wydaj polecenia agentowi i zaoszczędź mnóstwo czasu.'}, }, - newAgentPage: { + addAgentPage: { title: 'Nowy agent', agentName: 'Nazwa agenta', instructions: 'Napisz niestandardowe instrukcje', diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts index 0a235bf8b108..f56451882581 100644 --- a/src/languages/pt-BR.ts +++ b/src/languages/pt-BR.ts @@ -2711,9 +2711,11 @@ ${amount} para ${merchant} - ${date}`, title: 'Agentes', subtitle: 'Crie agentes para gerenciar seu fluxo de trabalho. Pule o trabalho manual e ganhe horas de volta no seu dia.', newAgent: 'Novo agente', + chat: 'Chat', + copilot: 'Co-pilot', emptyAgents: {title: 'Nenhum agente criado', subtitle: 'Pare de fazer tudo manualmente. Instrua um agente e economize muito tempo.'}, }, - newAgentPage: { + addAgentPage: { title: 'Novo agente', agentName: 'Nome do agente', instructions: 'Escrever instruções personalizadas', diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts index 0d2a3d8b42cf..cece6727ce01 100644 --- a/src/languages/zh-hans.ts +++ b/src/languages/zh-hans.ts @@ -2643,9 +2643,11 @@ ${amount},商户:${merchant} - 日期:${date}`, title: '代理人', subtitle: '通过自定义智能体自动化处理任务。', newAgent: '新代理人', + chat: 'Chat', + copilot: 'Co-pilot', emptyAgents: {title: '尚未创建代理', subtitle: '别再手动处理这些事情了。交给智能代理去执行,为自己节省大量时间。'}, }, - newAgentPage: { + addAgentPage: { title: '新代理', agentName: '代理名称', instructions: '编写自定义指令', diff --git a/src/libs/API/parameters/CreateAgentParams.ts b/src/libs/API/parameters/CreateAgentParams.ts index 291417171e5c..e06ada32618e 100644 --- a/src/libs/API/parameters/CreateAgentParams.ts +++ b/src/libs/API/parameters/CreateAgentParams.ts @@ -1,5 +1,6 @@ type CreateAgentParams = { - agentName: string; + firstName?: string; + customExpensifyAvatarID?: string; prompt: string; }; diff --git a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx index 1d3986b95f11..b104468662c2 100644 --- a/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx +++ b/src/libs/Navigation/AppNavigator/ModalStackNavigators/index.tsx @@ -466,7 +466,7 @@ const SettingsModalStackNavigator = createModalStackNavigator('../../../../pages/settings/Wallet/InternationalDepositAccount/CountrySelectionVerifyAccountPage').default, [SCREENS.SETTINGS.BANK_ACCOUNT_PURPOSE]: () => require('../../../../pages/settings/Wallet/BankAccountPurposePage').default, [SCREENS.SETTINGS.RULES.ROOT]: () => require('../../../../pages/settings/Rules/ExpenseRulesPage').default, - [SCREENS.SETTINGS.AGENTS.NEW]: () => require('../../../../pages/settings/Agents/NewAgentPage').default, + [SCREENS.SETTINGS.AGENTS.ADD]: () => require('../../../../pages/settings/Agents/AddAgentPage').default, [SCREENS.SETTINGS.RULES.ADD]: () => require('../../../../pages/settings/Rules/AddRulePage').default, [SCREENS.SETTINGS.RULES.ADD_MERCHANT]: () => require('../../../../pages/settings/Rules/Fields/AddMerchantPage').default, [SCREENS.SETTINGS.RULES.ADD_RENAME_MERCHANT]: () => require('../../../../pages/settings/Rules/Fields/AddRenameMerchantPage').default, diff --git a/src/libs/Navigation/linkingConfig/RELATIONS/SETTINGS_TO_RHP.ts b/src/libs/Navigation/linkingConfig/RELATIONS/SETTINGS_TO_RHP.ts index 525076617897..763dc052e74b 100755 --- a/src/libs/Navigation/linkingConfig/RELATIONS/SETTINGS_TO_RHP.ts +++ b/src/libs/Navigation/linkingConfig/RELATIONS/SETTINGS_TO_RHP.ts @@ -70,7 +70,7 @@ const SETTINGS_TO_RHP: Partial['config'] = { path: ROUTES.SETTINGS_BANK_ACCOUNT_PURPOSE, exact: true, }, - [SCREENS.SETTINGS.AGENTS.NEW]: { - path: ROUTES.SETTINGS_AGENTS_NEW, + [SCREENS.SETTINGS.AGENTS.ADD]: { + path: ROUTES.SETTINGS_AGENTS_ADD, exact: true, }, [SCREENS.SETTINGS.RULES.ADD]: { diff --git a/src/libs/Navigation/types.ts b/src/libs/Navigation/types.ts index 881341e03815..1c15e66269c8 100644 --- a/src/libs/Navigation/types.ts +++ b/src/libs/Navigation/types.ts @@ -256,7 +256,7 @@ type SettingsNavigatorParamList = { }; [SCREENS.SETTINGS.BANK_ACCOUNT_PURPOSE]: undefined; [SCREENS.SETTINGS.ADD_BANK_ACCOUNT_SELECT_COUNTRY_VERIFY_ACCOUNT]: undefined; - [SCREENS.SETTINGS.AGENTS.NEW]: undefined; + [SCREENS.SETTINGS.AGENTS.ADD]: undefined; [SCREENS.SETTINGS.RULES.ADD]: undefined; [SCREENS.SETTINGS.RULES.ADD_MERCHANT]: undefined; [SCREENS.SETTINGS.RULES.ADD_RENAME_MERCHANT]: undefined; diff --git a/src/libs/actions/Agent.ts b/src/libs/actions/Agent.ts index a2ea93a617e8..0b2144342a8a 100644 --- a/src/libs/actions/Agent.ts +++ b/src/libs/actions/Agent.ts @@ -8,7 +8,7 @@ function openAgentsPage() { read(READ_COMMANDS.OPEN_AGENTS_PAGE, null); } -function createAgent(agentName: string, prompt: string) { +function createAgent(firstName: string, prompt: string) { const optimisticAccountID = -Math.round(Math.random() * 1000000); const optimisticData: AnyOnyxUpdate[] = [ @@ -18,7 +18,7 @@ function createAgent(agentName: string, prompt: string) { value: { [optimisticAccountID]: { accountID: optimisticAccountID, - displayName: agentName, + displayName: firstName, isOptimisticPersonalDetail: true, }, }, @@ -60,7 +60,7 @@ function createAgent(agentName: string, prompt: string) { }, ]; - write(WRITE_COMMANDS.CREATE_AGENT, {agentName, prompt}, {optimisticData, successData, failureData}); + write(WRITE_COMMANDS.CREATE_AGENT, {firstName, prompt}, {optimisticData, successData, failureData}); } export {openAgentsPage, createAgent}; diff --git a/src/pages/settings/Agents/NewAgentPage.tsx b/src/pages/settings/Agents/AddAgentPage.tsx similarity index 75% rename from src/pages/settings/Agents/NewAgentPage.tsx rename to src/pages/settings/Agents/AddAgentPage.tsx index 34f526f44aa1..b9ce14c2cb72 100644 --- a/src/pages/settings/Agents/NewAgentPage.tsx +++ b/src/pages/settings/Agents/AddAgentPage.tsx @@ -17,10 +17,10 @@ import Navigation from '@libs/Navigation/Navigation'; import {createAgent} from '@userActions/Agent'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; -import INPUT_IDS from '@src/types/form/NewAgentForm'; +import INPUT_IDS from '@src/types/form/AddAgentForm'; import type {Errors} from '@src/types/onyx/OnyxCommon'; -function NewAgentPage() { +function AddAgentPage() { const {translate} = useLocalize(); const styles = useThemeStyles(); const theme = useTheme(); @@ -34,37 +34,37 @@ function NewAgentPage() { const avatarStyle = [styles.avatarXLarge, styles.alignSelfCenter]; - const validate = (values: FormOnyxValues): Errors => { + const validate = (values: FormOnyxValues): Errors => { const errors: Errors = {}; - if (!values[INPUT_IDS.AGENT_NAME].trim()) { - errors[INPUT_IDS.AGENT_NAME] = translate('common.error.fieldRequired'); + if (!values[INPUT_IDS.FIRST_NAME].trim()) { + errors[INPUT_IDS.FIRST_NAME] = translate('common.error.fieldRequired'); } - if (!values[INPUT_IDS.INSTRUCTIONS].trim()) { - errors[INPUT_IDS.INSTRUCTIONS] = translate('common.error.fieldRequired'); + if (!values[INPUT_IDS.PROMPT].trim()) { + errors[INPUT_IDS.PROMPT] = translate('common.error.fieldRequired'); } return errors; }; - const handleSubmit = (values: FormOnyxValues) => { - createAgent(values[INPUT_IDS.AGENT_NAME].trim(), values[INPUT_IDS.INSTRUCTIONS].trim()); + const handleSubmit = (values: FormOnyxValues) => { + createAgent(values[INPUT_IDS.FIRST_NAME].trim(), values[INPUT_IDS.PROMPT].trim()); Navigation.goBack(); }; return ( Navigation.goBack()} /> {}} size={CONST.AVATAR_SIZE.X_LARGE} @@ -80,15 +80,15 @@ function NewAgentPage() { editIcon={expensifyIcons.Sync} editIconStyle={styles.smallEditIconAgent} editIconFill={theme.textLight} - sentryLabel={CONST.SENTRY_LABEL.NEW_AGENT_PAGE.AVATAR} + sentryLabel={CONST.SENTRY_LABEL.ADD_AGENT_PAGE.AVATAR} /> { + navigateToAndOpenReportWithAccountIDs([accountID], currentUserAccountID, introSelected, isSelfTourViewed, betas); + }; + + const handleCopilot = () => { + connect({ + email: login, + delegatedAccess: account?.delegatedAccess, + credentials, + session, + activePolicyID, + }); + }; return ( @@ -44,7 +75,18 @@ function AgentsListRow({accountID, displayName, login}: AgentsListRowProps) { {login} - {/* Action buttons are deferred to R1.3 per phased rollout plan */} + +