From 01bb2f4ab261eb86baa2dcbfa24a5841f7d0ee74 Mon Sep 17 00:00:00 2001 From: Harshit Raizada <112213410+dankgarlic1@users.noreply.github.com> Date: Thu, 18 Jun 2026 14:01:13 +0530 Subject: [PATCH] fix: enforce strict rules for currency value handling by ai chatbot (#21470) opportunity: image fix: image closes #21419 --------- Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com> --- .../zod-schemas/record-properties.zod-schema.ts | 12 +++++++++--- .../zod-schemas/shared-filter-defs.zod-schema.ts | 3 +++ .../zod-schemas/shared-value-defs.zod-schema.ts | 14 +++++++++++++- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/packages/twenty-server/src/engine/core-modules/record-crud/zod-schemas/record-properties.zod-schema.ts b/packages/twenty-server/src/engine/core-modules/record-crud/zod-schemas/record-properties.zod-schema.ts index 859a1f3cee..8ba5588170 100644 --- a/packages/twenty-server/src/engine/core-modules/record-crud/zod-schemas/record-properties.zod-schema.ts +++ b/packages/twenty-server/src/engine/core-modules/record-crud/zod-schemas/record-properties.zod-schema.ts @@ -14,6 +14,8 @@ import { type ObjectMetadataForToolSchema } from 'src/engine/core-modules/record import { AddressValueOptionalSchema, AddressValueSchema, + CurrencyResponseValueOptionalSchema, + CurrencyResponseValueSchema, CurrencyValueOptionalSchema, CurrencyValueSchema, EmailsValueOptionalSchema, @@ -188,9 +190,13 @@ export const generateRecordPropertiesZodSchema = ( } case FieldMetadataType.CURRENCY: { - const baseSchema = field.isNullable - ? CurrencyValueOptionalSchema - : CurrencyValueSchema; + const baseSchema = forResponse + ? field.isNullable + ? CurrencyResponseValueOptionalSchema + : CurrencyResponseValueSchema + : field.isNullable + ? CurrencyValueOptionalSchema + : CurrencyValueSchema; shape[field.name] = field.description ? baseSchema.describe(field.description) diff --git a/packages/twenty-server/src/engine/core-modules/record-crud/zod-schemas/shared-filter-defs.zod-schema.ts b/packages/twenty-server/src/engine/core-modules/record-crud/zod-schemas/shared-filter-defs.zod-schema.ts index 4a0522776b..f87acecb1a 100644 --- a/packages/twenty-server/src/engine/core-modules/record-crud/zod-schemas/shared-filter-defs.zod-schema.ts +++ b/packages/twenty-server/src/engine/core-modules/record-crud/zod-schemas/shared-filter-defs.zod-schema.ts @@ -249,6 +249,9 @@ export const CurrencyFilterSchema = z in: z.array(z.number()).optional().describe('In array'), is: NullCheckEnum.optional(), }) + .describe( + 'Currency amount in micros (1 unit = 1,000,000 micros). Multiply the user-provided amount by 1,000,000 to build this filter.', + ) .optional(), currencyCode: z .object({ diff --git a/packages/twenty-server/src/engine/core-modules/record-crud/zod-schemas/shared-value-defs.zod-schema.ts b/packages/twenty-server/src/engine/core-modules/record-crud/zod-schemas/shared-value-defs.zod-schema.ts index 11e7c1bea9..445ba47bb6 100644 --- a/packages/twenty-server/src/engine/core-modules/record-crud/zod-schemas/shared-value-defs.zod-schema.ts +++ b/packages/twenty-server/src/engine/core-modules/record-crud/zod-schemas/shared-value-defs.zod-schema.ts @@ -17,12 +17,24 @@ export const LinksValueSchema = z.object({ }); export const LinksValueOptionalSchema = LinksValueSchema.optional(); +const CURRENCY_WRITE_DESCRIPTION = + 'Currency amount in micros (1 unit = 1,000,000 micros). Multiply the user-provided amount by 1,000,000 before writing.'; +const CURRENCY_READ_DESCRIPTION = + 'Currency amount in micros (1 unit = 1,000,000 micros). Divide by 1,000,000 to display to users.'; + export const CurrencyValueSchema = z.object({ - amountMicros: z.number().optional(), + amountMicros: z.number().optional().describe(CURRENCY_WRITE_DESCRIPTION), currencyCode: z.string().optional(), }); export const CurrencyValueOptionalSchema = CurrencyValueSchema.optional(); +export const CurrencyResponseValueSchema = z.object({ + amountMicros: z.number().optional().describe(CURRENCY_READ_DESCRIPTION), + currencyCode: z.string().optional(), +}); +export const CurrencyResponseValueOptionalSchema = + CurrencyResponseValueSchema.optional(); + export const FullNameValueSchema = z.object({ firstName: z.string().optional(), lastName: z.string().optional(),