Infer record pickers for record-typed logic function workflow inputs (#21494)
## Context Logic functions can declare workflow inputs typed as records or arrays of records (e.g. the People Data Labs enrichment functions), but the workflow builder rendered those as a plain text input with a variable picker, which is not usable. ## What this does - Adds an `objectUniversalIdentifier` link on input schema properties, so a record-typed input is tied to a workspace object. - The SDK build infers it from a `TwentyRecord<'objectUniversalIdentifier'>` marker type in the handler signature, reading the object's universal identifier straight from the source; explicit input schemas can still set the field directly. - The workflow builder renders these inputs as a single record picker or a record multi-select with the variable picker on the right. Selected records are stored as record ids; `TwentyRecord<UID>` is a branded `string`, so the handler signature reflects that it receives ids (a bound variable resolves to whatever the referenced step produced). - The multi-select collapses overflowing chips into a `+N` badge (reusing `ExpandableList`) and its variable picker offers both record objects and fields. - Updates the People Data Labs enrichment inputs as the reference implementation. <img width="802" height="824" alt="CleanShot 2026-06-12 at 16 54 10@2x" src="https://github.com/user-attachments/assets/a0896d74-0aab-49bd-a173-14c578a2e533" /> <!-- This is an auto-generated description by cubic. --> <a href="https://cubic.dev/pr/twentyhq/twenty/pull/21494?utm_source=github" target="_blank" rel="noopener noreferrer" data-no-image-dialog="true"><picture><source media="(prefers-color-scheme: dark)" srcset="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"><source media="(prefers-color-scheme: light)" srcset="https://www.cubic.dev/buttons/review-in-cubic-light.svg"><img alt="Review in cubic" src="https://www.cubic.dev/buttons/review-in-cubic-dark.svg"></picture></a> <!-- End of auto-generated description by cubic. -->
This commit is contained in:
+16
-6
@@ -1,7 +1,10 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { DEFAULT_TOOL_INPUT_SCHEMA } from 'twenty-shared/logic-function';
|
||||
import {
|
||||
buildToolInputJsonSchema,
|
||||
DEFAULT_TOOL_INPUT_SCHEMA,
|
||||
} from 'twenty-shared/logic-function';
|
||||
|
||||
import { type GenerateDescriptorOptions } from 'src/engine/core-modules/tool-provider/interfaces/generate-descriptor-options.type';
|
||||
import { type ToolProvider } from 'src/engine/core-modules/tool-provider/interfaces/tool-provider.interface';
|
||||
@@ -46,14 +49,18 @@ export class LogicFunctionToolProvider implements ToolProvider {
|
||||
): Promise<(ToolIndexEntry | ToolDescriptor)[]> {
|
||||
const includeSchemas = options?.includeSchemas ?? true;
|
||||
|
||||
const { flatLogicFunctionMaps } =
|
||||
const { flatLogicFunctionMaps, flatObjectMetadataMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId: context.workspaceId,
|
||||
flatMapsKeys: ['flatLogicFunctionMaps'],
|
||||
flatMapsKeys: ['flatLogicFunctionMaps', 'flatObjectMetadataMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const resolveObjectLabel = (objectUniversalIdentifier: string) =>
|
||||
flatObjectMetadataMaps.byUniversalIdentifier[objectUniversalIdentifier]
|
||||
?.labelSingular;
|
||||
|
||||
const logicFunctionsWithSchema = Object.values(
|
||||
flatLogicFunctionMaps.byUniversalIdentifier,
|
||||
).filter(
|
||||
@@ -83,9 +90,12 @@ export class LogicFunctionToolProvider implements ToolProvider {
|
||||
if (includeSchemas) {
|
||||
descriptors.push({
|
||||
...base,
|
||||
inputSchema:
|
||||
(logicFunction.toolTriggerSettings?.inputSchema as object) ??
|
||||
DEFAULT_TOOL_INPUT_SCHEMA,
|
||||
inputSchema: isDefined(logicFunction.toolTriggerSettings?.inputSchema)
|
||||
? (buildToolInputJsonSchema(
|
||||
logicFunction.toolTriggerSettings.inputSchema,
|
||||
resolveObjectLabel,
|
||||
) as object)
|
||||
: DEFAULT_TOOL_INPUT_SCHEMA,
|
||||
});
|
||||
} else {
|
||||
descriptors.push(base);
|
||||
|
||||
Reference in New Issue
Block a user