Skip to content
Draft
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
5 changes: 5 additions & 0 deletions src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,9 @@
/** The transaction IDs to be highlighted when opening the Expenses search route page */
TRANSACTION_IDS_HIGHLIGHT_ON_SEARCH_ROUTE: 'transactionIdsHighlightOnSearchRoute',

/** Virtual employees configured for a workspace, keyed by policyID */
VIRTUAL_EMPLOYEES: 'virtualEmployees',

/** Collection Keys */
COLLECTION: {
DOMAIN: 'domain_',
Expand Down Expand Up @@ -777,6 +780,8 @@
* Key format: passkey_${userId}
*/
PASSKEY_CREDENTIALS: 'passkeyCredentials_',
VIRTUAL_EMPLOYEES: 'virtualEmployees_',
VIRTUAL_EMPLOYEE_ACTIONS: 'virtualEmployeeActions_',
},

/** List of Form ids */
Expand Down Expand Up @@ -1455,7 +1460,7 @@
type MissingOnyxKeysError = `Error: Types don't match, OnyxKey type is missing: ${Exclude<AllOnyxKeys, OnyxKey>}`;
/** If this type errors, it means that the `OnyxKey` type is missing some keys. */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
type AssertOnyxKeys = AssertTypesEqual<AllOnyxKeys, OnyxKey, MissingOnyxKeysError>;

Check failure on line 1463 in src/ONYXKEYS.ts

View workflow job for this annotation

GitHub Actions / typecheck

Type 'OnyxKey' does not satisfy the constraint '"Error: Types don't match, OnyxKey type is missing: virtualEmployees" | "Error: Types don't match, OnyxKey type is missing: virtualEmployees_" | "Error: Types don't match, OnyxKey type is missing: virtualEmployeeActions_"'.

export default ONYXKEYS;
export type {
Expand Down
9 changes: 9 additions & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2636,6 +2636,15 @@ const ROUTES = {
route: 'workspaces/:policyID/travel/missing-personal-details',
getRoute: (policyID: string) => `workspaces/${policyID}/travel/missing-personal-details` as const,
},
WORKSPACE_VIRTUAL_EMPLOYEES: {
route: 'workspace/:policyID/virtual-employees',
getRoute: (policyID: string) => `workspace/${policyID}/virtual-employees` as const,
},
WORKSPACE_VIRTUAL_EMPLOYEES_EDIT: {
route: 'workspace/:policyID/virtual-employees/:virtualEmployeeID',
getRoute: (policyID: string, virtualEmployeeID: string) =>
`workspace/${policyID}/virtual-employees/${virtualEmployeeID}` as const,
},
WORKSPACE_CREATE_DISTANCE_RATE: {
route: 'workspaces/:policyID/distance-rates/new',
getRoute: (policyID: string, transactionID?: string, reportID?: string) =>
Expand Down
2 changes: 2 additions & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -807,6 +807,8 @@ const SCREENS = {
PER_DIEM_EDIT_CURRENCY: 'Per_Diem_Edit_Currency',
TIME_TRACKING: 'Time_Tracking',
TIME_TRACKING_DEFAULT_RATE: 'Time_Tracking_Default_Rate',
VIRTUAL_EMPLOYEES: 'Workspace_VirtualEmployees',
VIRTUAL_EMPLOYEES_EDIT: 'Workspace_VirtualEmployees_Edit',
},

EDIT_REQUEST: {
Expand Down
64 changes: 64 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5339,6 +5339,70 @@ const translations = {
defaultHourlyRate: 'Default hourly rate',
},
},
virtualEmployees: {
title: 'Virtual employees',
addNew: 'Add virtual employee',
createTitle: 'Create virtual employee',
editTitle: 'Edit virtual employee',
emptyStateTitle: 'No virtual employees yet',
emptyStateDescription: 'Create AI-powered virtual employees to automate expense management tasks in your workspace.',
displayNameLabel: 'Name',
displayNamePlaceholder: 'e.g. AP Specialist, Spend Analyst...',
systemPromptLabel: 'Instructions',
systemPromptPlaceholder:
'Example: You are an AP specialist for Acme Corp. When a report is submitted, check that every Amazon expense has a business purpose in the comment. If not, message the submitter and ask them to add one.',
systemPromptHint: 'Be specific about what to check and when to act. The more detail, the better.',
unnamedEmployee: 'Unnamed employee',
virtualEmployeeLabel: 'Virtual Employee',
previewPlaceholder: 'Start typing instructions to preview how your virtual employee will behave\u2026',
capabilitiesSection: 'Capabilities',
capabilitiesSectionHint: 'Choose what actions this virtual employee is allowed to perform.',
eventsSection: 'Triggers',
eventsSectionHint: 'Choose which workspace events will activate this virtual employee.',
statusPaused: 'Paused',
noCapabilities: 'No capabilities',
capabilityCount: ({count}: {count: number}) => (count === 1 ? '1 capability' : `${count} capabilities`),
triggerCount: ({count}: {count: number}) => (count === 1 ? '1 trigger' : `${count} triggers`),
create: 'Create',
capabilities: {
readTransactions: 'Read transactions',
readTransactionsDescription: 'View expense details, amounts, merchants, and receipts.',
readReports: 'Read reports',
readReportsDescription: 'View expense report summaries and status.',
editTransactions: 'Edit transactions',
editTransactionsDescription: 'Update comments, categories, and tags on expenses.',
sendMessages: 'Send messages',
sendMessagesDescription: 'Post comments in report chats and open direct messages.',
approveReports: 'Approve reports',
approveReportsDescription: 'Approve expense reports when configured as an approver in the workspace workflow.',
rejectReports: 'Reject or hold reports',
rejectReportsDescription: 'Return reports to the submitter or place them on hold with a reason.',
dismissViolations: 'Dismiss violations',
dismissViolationsDescription: 'Dismiss policy violations on expenses.',
readPolicy: 'Read policy rules',
readPolicyDescription: 'View workspace spending limits, categories, and approval settings.',
},
events: {
transactionCreated: 'New expense created',
transactionCreatedDescription: 'Fires when any expense is added to the workspace.',
transactionModified: 'Expense modified',
transactionModifiedDescription: 'Fires when an expense field (amount, merchant, category, etc.) is changed.',
receiptScanned: 'Receipt scanned',
receiptScannedDescription: 'Fires when SmartScan finishes reading a receipt.',
reportSubmitted: 'Report submitted',
reportSubmittedDescription: 'Fires when a member submits an expense report for approval.',
reportApproved: 'Report approved',
reportApprovedDescription: 'Fires when an expense report is approved.',
chatMention: 'Mentioned in chat',
chatMentionDescription: 'Fires when this virtual employee is @mentioned in any workspace chat.',
chatMessage: 'Any chat message',
chatMessageDescription: 'Fires on every message in chats where this virtual employee participates. Use with care — high volume.',
},
errors: {
displayNameRequired: 'Display name is required.',
systemPromptMinLength: ({minLength}: {minLength: number}) => `System prompt must be at least ${minLength} characters.`,
},
},
reports: {
reportsCustomTitleExamples: 'Examples:',
customReportNamesSubtitle: `<muted-text>Customize report titles using our <a href="${CONST.CUSTOM_REPORT_NAME_HELP_URL}">extensive formulas</a>.</muted-text>`,
Expand Down
43 changes: 43 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5187,6 +5187,49 @@
defaultHourlyRate: 'Tarifa por hora predeterminada',
},
},
virtualEmployees: {
title: 'Empleados virtuales',
addNew: 'Agregar empleado virtual',
createTitle: 'Crear empleado virtual',
editTitle: 'Editar empleado virtual',
emptyStateTitle: 'No hay empleados virtuales',
emptyStateDescription: 'Crea empleados virtuales con IA para automatizar tareas de gestión de gastos en tu espacio de trabajo.',
displayNameLabel: 'Nombre para mostrar',
systemPromptLabel: 'Prompt del sistema',
systemPromptHint: 'Describe el rol y comportamiento de este empleado virtual. Mínimo 20 caracteres.',
unnamedEmployee: 'Empleado sin nombre',
virtualEmployeeLabel: 'Empleado Virtual',
previewPlaceholder: 'Escribe instrucciones para previsualizar el comportamiento de tu empleado virtual\u2026',
capabilitiesSection: 'Capacidades',
eventsSection: 'Suscripciones a eventos',
noCapabilities: 'Sin capacidades',
capabilityCount: ({count}: {count: number}) => (count === 1 ? '1 capacidad' : `${count} capacidades`),
triggerCount: ({count}: {count: number}) => (count === 1 ? '1 activador' : `${count} activadores`),
create: 'Crear',
capabilities: {

Check failure on line 5209 in src/languages/es.ts

View workflow job for this annotation

GitHub Actions / typecheck

Type '{ readTransactions: string; editTransactions: string; sendMessages: string; approveReports: string; rejectReports: string; dismissViolations: string; readPolicy: string; readReports: string; }' is missing the following properties from type 'TranslationDeepObject<{ readTransactions: string; readTransactionsDescription: string; readReports: string; readReportsDescription: string; editTransactions: string; editTransactionsDescription: string; ... 9 more ...; readPolicyDescription: string; }>': readTransactionsDescription, readReportsDescription, editTransactionsDescription, sendMessagesDescription, and 4 more.
readTransactions: 'Leer transacciones',
editTransactions: 'Editar transacciones',
sendMessages: 'Enviar mensajes',
approveReports: 'Aprobar informes',
rejectReports: 'Rechazar informes',
dismissViolations: 'Descartar violaciones',
readPolicy: 'Leer política',
readReports: 'Leer informes',
},
events: {

Check failure on line 5219 in src/languages/es.ts

View workflow job for this annotation

GitHub Actions / typecheck

Type '{ transactionCreated: string; transactionModified: string; receiptScanned: string; reportSubmitted: string; reportApproved: string; chatMention: string; chatMessage: string; }' is missing the following properties from type 'TranslationDeepObject<{ transactionCreated: string; transactionCreatedDescription: string; transactionModified: string; transactionModifiedDescription: string; receiptScanned: string; receiptScannedDescription: string; ... 7 more ...; chatMessageDescription: string; }>': transactionCreatedDescription, transactionModifiedDescription, receiptScannedDescription, reportSubmittedDescription, and 3 more.
transactionCreated: 'Transacción creada',
transactionModified: 'Transacción modificada',
receiptScanned: 'Recibo escaneado',
reportSubmitted: 'Informe enviado',
reportApproved: 'Informe aprobado',
chatMention: 'Mención en chat',
chatMessage: 'Mensaje de chat',
},
errors: {
displayNameRequired: 'El nombre para mostrar es obligatorio.',
systemPromptMinLength: ({minLength}: {minLength: number}) => `El prompt del sistema debe tener al menos ${minLength} caracteres.`,
},
},
reports: {
reportsCustomTitleExamples: 'Ejemplos:',
customReportNamesSubtitle: `<muted-text>Personaliza los títulos de los informes usando nuestras <a href="${CONST.CUSTOM_REPORT_NAME_HELP_URL}">amplias fórmulas</a>.</muted-text>`,
Expand Down
9 changes: 9 additions & 0 deletions src/libs/API/parameters/CreateVirtualEmployeeParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
type CreateVirtualEmployeeParams = {
policyID: string;
displayName: string;
systemPrompt: string;
capabilities: string;
eventSubs: string;
};

export default CreateVirtualEmployeeParams;
6 changes: 6 additions & 0 deletions src/libs/API/parameters/DeleteVirtualEmployeeParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
type DeleteVirtualEmployeeParams = {
policyID: string;
vaAccountID: number;
};

export default DeleteVirtualEmployeeParams;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
type OpenWorkspaceVirtualEmployeesPageParams = {
policyID: string;
};

export default OpenWorkspaceVirtualEmployeesPageParams;
10 changes: 10 additions & 0 deletions src/libs/API/parameters/UpdateVirtualEmployeeParams.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
type UpdateVirtualEmployeeParams = {
policyID: string;
vaAccountID: number;
displayName: string;
systemPrompt: string;
capabilities: string;
eventSubs: string;
};

export default UpdateVirtualEmployeeParams;
4 changes: 4 additions & 0 deletions src/libs/API/parameters/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -489,3 +489,7 @@ export type {default as ToggleTwoFactorAuthRequiredForDomainParams} from './Togg
export type {default as DeleteVacationDelegateParams} from './DeleteVacationDelegateParams';
export type {default as SetTwoFactorAuthExemptEmailForDomainParams} from './SetTwoFactorAuthExemptEmailForDomainParams';
export type {default as ResetDomainMemberTwoFactorAuthParams} from './ResetDomainMemberTwoFactorAuthParams';
export type {default as CreateVirtualEmployeeParams} from './CreateVirtualEmployeeParams';
export type {default as UpdateVirtualEmployeeParams} from './UpdateVirtualEmployeeParams';
export type {default as DeleteVirtualEmployeeParams} from './DeleteVirtualEmployeeParams';
export type {default as OpenWorkspaceVirtualEmployeesPageParams} from './OpenWorkspaceVirtualEmployeesPageParams';
8 changes: 8 additions & 0 deletions src/libs/API/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,9 @@ const WRITE_COMMANDS = {
TOGGLE_TWO_FACTOR_AUTH_REQUIRED_FOR_DOMAIN: 'ToggleTwoFactorAuthRequiredForDomain',
SET_TWO_FACTOR_AUTH_EXEMPT_EMAIL_FOR_DOMAIN: 'SetTwoFactorAuthExemptEmailForDomain',
RESET_DOMAIN_MEMBER_TWO_FACTOR_AUTH: 'ResetDomainMemberTwoFactorAuth',
CREATE_VIRTUAL_EMPLOYEE: 'CreateVirtualEmployee',
UPDATE_VIRTUAL_EMPLOYEE: 'UpdateVirtualEmployee',
DELETE_VIRTUAL_EMPLOYEE: 'DeleteVirtualEmployee',
} as const;

type WriteCommand = ValueOf<typeof WRITE_COMMANDS>;
Expand Down Expand Up @@ -1139,6 +1142,9 @@ type WriteCommandParameters = {
[WRITE_COMMANDS.TOGGLE_TWO_FACTOR_AUTH_REQUIRED_FOR_DOMAIN]: Parameters.ToggleTwoFactorAuthRequiredForDomainParams;
[WRITE_COMMANDS.SET_TWO_FACTOR_AUTH_EXEMPT_EMAIL_FOR_DOMAIN]: Parameters.SetTwoFactorAuthExemptEmailForDomainParams;
[WRITE_COMMANDS.RESET_DOMAIN_MEMBER_TWO_FACTOR_AUTH]: Parameters.ResetDomainMemberTwoFactorAuthParams;
[WRITE_COMMANDS.CREATE_VIRTUAL_EMPLOYEE]: Parameters.CreateVirtualEmployeeParams;
[WRITE_COMMANDS.UPDATE_VIRTUAL_EMPLOYEE]: Parameters.UpdateVirtualEmployeeParams;
[WRITE_COMMANDS.DELETE_VIRTUAL_EMPLOYEE]: Parameters.DeleteVirtualEmployeeParams;
};

const READ_COMMANDS = {
Expand Down Expand Up @@ -1225,6 +1231,7 @@ const READ_COMMANDS = {
GET_SAML_SETTINGS: 'GetSAMLSettings',
GET_DUPLICATE_TRANSACTION_DETAILS: 'GetDuplicateTransactionDetails',
GET_TRANSACTIONS_MATCHING_CODING_RULE: 'GetTransactionsMatchingCodingRule',
OPEN_WORKSPACE_VIRTUAL_EMPLOYEES_PAGE: 'OpenWorkspaceVirtualEmployeesPage',
} as const;

type ReadCommand = ValueOf<typeof READ_COMMANDS>;
Expand Down Expand Up @@ -1313,6 +1320,7 @@ type ReadCommandParameters = {
[READ_COMMANDS.OPEN_DOMAIN_INITIAL_PAGE]: Parameters.DomainParams;
[READ_COMMANDS.GET_DUPLICATE_TRANSACTION_DETAILS]: Parameters.GetDuplicateTransactionDetailsParams;
[READ_COMMANDS.GET_TRANSACTIONS_MATCHING_CODING_RULE]: Parameters.GetTransactionsMatchingCodingRuleParams;
[READ_COMMANDS.OPEN_WORKSPACE_VIRTUAL_EMPLOYEES_PAGE]: Parameters.OpenWorkspaceVirtualEmployeesPageParams;
};

const SIDE_EFFECT_REQUEST_COMMANDS = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ const CENTRAL_PANE_WORKSPACE_SCREENS = {
[SCREENS.WORKSPACE.TRAVEL]: () => require<ReactComponentModule>('../../../../pages/workspace/travel/PolicyTravelPage').default,
[SCREENS.WORKSPACE.RULES]: () => require<ReactComponentModule>('../../../../pages/workspace/rules/PolicyRulesPage').default,
[SCREENS.WORKSPACE.TIME_TRACKING]: () => require<ReactComponentModule>('../../../../pages/workspace/timeTracking/WorkspaceTimeTrackingPage').default,
[SCREENS.WORKSPACE.VIRTUAL_EMPLOYEES]: () => require<ReactComponentModule>('../../../../pages/workspace/virtualEmployees/WorkspaceVirtualEmployeesPage').default,
[SCREENS.WORKSPACE.VIRTUAL_EMPLOYEES_EDIT]: () => require<ReactComponentModule>('../../../../pages/workspace/virtualEmployees/WorkspaceVirtualEmployeePage').default,
} satisfies Screens;

const Split = createSplitNavigator<WorkspaceSplitNavigatorParamList>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ const WORKSPACE_TO_RHP: Partial<Record<keyof WorkspaceSplitNavigatorParamList, s
],
[SCREENS.WORKSPACE.TIME_TRACKING]: [SCREENS.WORKSPACE.TIME_TRACKING_DEFAULT_RATE],
[SCREENS.WORKSPACE.MORE_FEATURES]: [],
[SCREENS.WORKSPACE.VIRTUAL_EMPLOYEES]: [SCREENS.WORKSPACE.VIRTUAL_EMPLOYEES_EDIT],
};

export default WORKSPACE_TO_RHP;
6 changes: 6 additions & 0 deletions src/libs/Navigation/linkingConfig/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2212,6 +2212,12 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
[SCREENS.WORKSPACE.TIME_TRACKING]: {
path: ROUTES.WORKSPACE_TIME_TRACKING.route,
},
[SCREENS.WORKSPACE.VIRTUAL_EMPLOYEES]: {
path: ROUTES.WORKSPACE_VIRTUAL_EMPLOYEES.route,
},
[SCREENS.WORKSPACE.VIRTUAL_EMPLOYEES_EDIT]: {
path: ROUTES.WORKSPACE_VIRTUAL_EMPLOYEES_EDIT.route,
},
},
},

Expand Down
7 changes: 7 additions & 0 deletions src/libs/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2721,6 +2721,13 @@ type WorkspaceSplitNavigatorParamList = {
[SCREENS.WORKSPACE.TIME_TRACKING]: {
policyID: string;
};
[SCREENS.WORKSPACE.VIRTUAL_EMPLOYEES]: {
policyID: string;
};
[SCREENS.WORKSPACE.VIRTUAL_EMPLOYEES_EDIT]: {
policyID: string;
virtualEmployeeID: string;
};
};

type DomainSplitNavigatorParamList = {
Expand Down
Loading
Loading