+5
-2
@@ -310,7 +310,7 @@ describe('WorkflowVersionStepOperationsWorkspaceService', () => {
|
||||
runtime: LogicFunctionRuntime.NODE22,
|
||||
timeoutSeconds: 30,
|
||||
sourceHandlerPath: 'src/index.ts',
|
||||
builtHandlerPath: 'index.mjs',
|
||||
builtHandlerPath: 'src/index.mjs',
|
||||
handlerName: 'main',
|
||||
checksum: null,
|
||||
toolInputSchema: null,
|
||||
@@ -321,6 +321,7 @@ describe('WorkflowVersionStepOperationsWorkspaceService', () => {
|
||||
cronTriggerSettings: null,
|
||||
databaseEventTriggerSettings: null,
|
||||
httpRouteTriggerSettings: null,
|
||||
isBuildUpToDate: false,
|
||||
};
|
||||
|
||||
logicFunctionMetadataService.createOne.mockResolvedValue(
|
||||
@@ -394,6 +395,7 @@ describe('WorkflowVersionStepOperationsWorkspaceService', () => {
|
||||
cronTriggerSettings: null,
|
||||
databaseEventTriggerSettings: null,
|
||||
httpRouteTriggerSettings: null,
|
||||
isBuildUpToDate: true,
|
||||
};
|
||||
|
||||
const mockNewFlatLogicFunction: FlatLogicFunction = {
|
||||
@@ -407,7 +409,7 @@ describe('WorkflowVersionStepOperationsWorkspaceService', () => {
|
||||
runtime: LogicFunctionRuntime.NODE22,
|
||||
timeoutSeconds: 30,
|
||||
sourceHandlerPath: 'src/index.ts',
|
||||
builtHandlerPath: 'index.mjs',
|
||||
builtHandlerPath: 'src/index.mjs',
|
||||
handlerName: 'main',
|
||||
checksum: null,
|
||||
toolInputSchema: null,
|
||||
@@ -418,6 +420,7 @@ describe('WorkflowVersionStepOperationsWorkspaceService', () => {
|
||||
cronTriggerSettings: null,
|
||||
databaseEventTriggerSettings: null,
|
||||
httpRouteTriggerSettings: null,
|
||||
isBuildUpToDate: false,
|
||||
};
|
||||
|
||||
const emptyMaps = createEmptyAllFlatEntityMaps();
|
||||
|
||||
+11
-90
@@ -14,30 +14,25 @@ import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/
|
||||
import { LogicFunctionMetadataService } from 'src/engine/metadata-modules/logic-function/services/logic-function-metadata.service';
|
||||
import { type FlatLogicFunction } from 'src/engine/metadata-modules/logic-function/types/flat-logic-function.type';
|
||||
import { findFlatLogicFunctionOrThrow } from 'src/engine/metadata-modules/logic-function/utils/find-flat-logic-function-or-throw.util';
|
||||
import { fromCreateLogicFunctionInputToFlatLogicFunction } from 'src/engine/metadata-modules/logic-function/utils/from-create-logic-function-input-to-flat-logic-function.util';
|
||||
import { fromCreateLogicFunctionInputToFlatLogicFunction } from 'src/engine/metadata-modules/logic-function/utils/from-create-logic-function-from-source-input-to-flat-logic-function.util';
|
||||
import {
|
||||
WorkflowActionType,
|
||||
type WorkflowAction,
|
||||
} from 'src/modules/workflow/workflow-executor/workflow-actions/types/workflow-action.type';
|
||||
import { LogicFunctionResourceService } from 'src/engine/core-modules/logic-function/logic-function-resource/logic-function-resource.service';
|
||||
import { SEED_LOGIC_FUNCTION_INPUT_SCHEMA } from 'src/engine/core-modules/logic-function/logic-function-resource/constants/seed-logic-function-input-schema';
|
||||
import type { JsonbProperty } from 'src/engine/workspace-manager/workspace-migration/universal-flat-entity/types/jsonb-property.type';
|
||||
|
||||
const WORKFLOW_BASE_FOLDER_PREFIX = 'workflow';
|
||||
import { LogicFunctionFromSourceService } from 'src/engine/metadata-modules/logic-function/services/logic-function-from-source.service';
|
||||
|
||||
@Injectable()
|
||||
export class CodeStepBuildService {
|
||||
constructor(
|
||||
private readonly workspaceManyOrAllFlatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
private readonly logicFunctionMetadataService: LogicFunctionMetadataService,
|
||||
private readonly logicFunctionFromSourceService: LogicFunctionFromSourceService,
|
||||
private readonly applicationService: ApplicationService,
|
||||
private readonly logicFunctionResourceService: LogicFunctionResourceService,
|
||||
) {}
|
||||
|
||||
private getSourceSubfolderForCodeStep(logicFunctionId: string) {
|
||||
return `${WORKFLOW_BASE_FOLDER_PREFIX}/${logicFunctionId}`;
|
||||
}
|
||||
|
||||
async createCodeStepLogicFunction({
|
||||
logicFunctionId,
|
||||
workspaceId,
|
||||
@@ -45,33 +40,13 @@ export class CodeStepBuildService {
|
||||
logicFunctionId: string;
|
||||
workspaceId: string;
|
||||
}) {
|
||||
const { workspaceCustomFlatApplication } =
|
||||
await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow(
|
||||
{
|
||||
workspaceId,
|
||||
},
|
||||
);
|
||||
const { sourceHandlerPath, builtHandlerPath, handlerName, checksum } =
|
||||
await this.logicFunctionResourceService.seedSourceFiles({
|
||||
sourceSubfolder: this.getSourceSubfolderForCodeStep(logicFunctionId),
|
||||
workspaceId,
|
||||
applicationUniversalIdentifier:
|
||||
workspaceCustomFlatApplication.universalIdentifier,
|
||||
});
|
||||
|
||||
return await this.logicFunctionMetadataService.createOne({
|
||||
return await this.logicFunctionFromSourceService.createOne({
|
||||
input: {
|
||||
id: logicFunctionId,
|
||||
name: 'A Logic Function Code Workflow Step',
|
||||
name: 'A Code Step',
|
||||
description: '',
|
||||
sourceHandlerPath,
|
||||
builtHandlerPath,
|
||||
handlerName,
|
||||
checksum,
|
||||
toolInputSchema: SEED_LOGIC_FUNCTION_INPUT_SCHEMA,
|
||||
},
|
||||
workspaceId,
|
||||
ownerFlatApplication: workspaceCustomFlatApplication,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -114,7 +89,6 @@ export class CodeStepBuildService {
|
||||
existingLogicFunction.id,
|
||||
newId,
|
||||
);
|
||||
|
||||
const toBuiltHandlerPath = builtHandlerPath.replace(
|
||||
existingLogicFunction.id,
|
||||
newId,
|
||||
@@ -122,9 +96,9 @@ export class CodeStepBuildService {
|
||||
|
||||
await this.logicFunctionResourceService.copyResources({
|
||||
fromSourceHandlerPath: sourceHandlerPath,
|
||||
fromBuiltHandlerPath: builtHandlerPath,
|
||||
toSourceHandlerPath,
|
||||
toBuiltHandlerPath,
|
||||
fromBuiltHandlerPath: builtHandlerPath,
|
||||
toBuiltHandlerPath: toBuiltHandlerPath,
|
||||
workspaceId,
|
||||
applicationUniversalIdentifier,
|
||||
});
|
||||
@@ -136,8 +110,8 @@ export class CodeStepBuildService {
|
||||
id: newId,
|
||||
universalIdentifier: newUniversalIdentifier,
|
||||
description: existingLogicFunction.description ?? undefined,
|
||||
builtHandlerPath: toBuiltHandlerPath,
|
||||
sourceHandlerPath: toSourceHandlerPath,
|
||||
builtHandlerPath: toBuiltHandlerPath,
|
||||
toolInputSchema: existingLogicFunction.toolInputSchema ?? {},
|
||||
checksum: existingLogicFunction.checksum ?? '[default-checksum]', // TODO: checksum should never be null, update column in logicFunction entity to set it non nullable
|
||||
cronTriggerSettings: existingLogicFunction.cronTriggerSettings as
|
||||
@@ -230,7 +204,7 @@ export class CodeStepBuildService {
|
||||
if (
|
||||
!isDefined(flatLogicFunction) ||
|
||||
flatLogicFunction.deletedAt ||
|
||||
!this.isWorkflowCodeStepLogicFunction(flatLogicFunction)
|
||||
flatLogicFunction.isBuildUpToDate
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
@@ -246,63 +220,10 @@ export class CodeStepBuildService {
|
||||
continue;
|
||||
}
|
||||
|
||||
const { checksum } =
|
||||
await this.logicFunctionResourceService.buildFromSource({
|
||||
sourceHandlerPath: flatLogicFunction.sourceHandlerPath,
|
||||
builtHandlerPath: flatLogicFunction.builtHandlerPath,
|
||||
workspaceId,
|
||||
applicationUniversalIdentifier,
|
||||
});
|
||||
|
||||
await this.logicFunctionMetadataService.updateChecksum({
|
||||
id: flatLogicFunction.id,
|
||||
checksum,
|
||||
await this.logicFunctionFromSourceService.buildOneFromSource({
|
||||
workspaceId,
|
||||
id: logicFunctionId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
isWorkflowCodeStepLogicFunction(
|
||||
flatLogicFunction: FlatLogicFunction,
|
||||
): boolean {
|
||||
return (
|
||||
flatLogicFunction.sourceHandlerPath.startsWith(
|
||||
`${WORKFLOW_BASE_FOLDER_PREFIX}/`,
|
||||
) ||
|
||||
flatLogicFunction.builtHandlerPath.startsWith(
|
||||
`${WORKFLOW_BASE_FOLDER_PREFIX}/`,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
async getFlatLogicFunctionForCodeStepOrNull({
|
||||
logicFunctionId,
|
||||
workspaceId,
|
||||
}: {
|
||||
logicFunctionId: string;
|
||||
workspaceId: string;
|
||||
}): Promise<FlatLogicFunction | null> {
|
||||
const { flatLogicFunctionMaps } =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatLogicFunctionMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
const flatLogicFunction = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: logicFunctionId,
|
||||
flatEntityMaps: flatLogicFunctionMaps,
|
||||
});
|
||||
|
||||
if (
|
||||
!isDefined(flatLogicFunction) ||
|
||||
flatLogicFunction.deletedAt ||
|
||||
!this.isWorkflowCodeStepLogicFunction(flatLogicFunction)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return flatLogicFunction;
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -3,8 +3,8 @@ import { Injectable } from '@nestjs/common';
|
||||
import { type ToolSet } from 'ai';
|
||||
|
||||
import { RecordPositionService } from 'src/engine/core-modules/record-position/services/record-position.service';
|
||||
import { LogicFunctionFromSourceService } from 'src/engine/metadata-modules/logic-function/services/logic-function-from-source.service';
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import { LogicFunctionService } from 'src/engine/metadata-modules/logic-function/services/logic-function.service';
|
||||
import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import { type RolePermissionConfig } from 'src/engine/twenty-orm/types/role-permission-config';
|
||||
import { WorkflowSchemaWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-schema/workflow-schema.workspace-service';
|
||||
@@ -43,7 +43,7 @@ export class WorkflowToolWorkspaceService {
|
||||
workflowSchemaService: WorkflowSchemaWorkspaceService,
|
||||
globalWorkspaceOrmManager: GlobalWorkspaceOrmManager,
|
||||
recordPositionService: RecordPositionService,
|
||||
logicFunctionService: LogicFunctionService,
|
||||
logicFunctionFromSourceService: LogicFunctionFromSourceService,
|
||||
flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService,
|
||||
) {
|
||||
this.deps = {
|
||||
@@ -55,7 +55,7 @@ export class WorkflowToolWorkspaceService {
|
||||
workflowSchemaService,
|
||||
globalWorkspaceOrmManager,
|
||||
recordPositionService,
|
||||
logicFunctionService,
|
||||
logicFunctionFromSourceService,
|
||||
flatEntityMapsCacheService,
|
||||
};
|
||||
}
|
||||
|
||||
+8
-19
@@ -13,24 +13,14 @@ const updateLogicFunctionSourceSchema = z.object({
|
||||
'The ID of the logic function to update (from the code step settings.input.logicFunctionId)',
|
||||
),
|
||||
code: z
|
||||
.object({
|
||||
src: z
|
||||
.object({
|
||||
'index.ts': z
|
||||
.string()
|
||||
.describe(
|
||||
'The TypeScript source code for the logic function. Must export a main function.',
|
||||
),
|
||||
})
|
||||
.describe('Source folder containing the index.ts file'),
|
||||
})
|
||||
.string()
|
||||
.describe(
|
||||
'The source code structure. Use { src: { "index.ts": "your code here" } }',
|
||||
'The TypeScript source code for the logic function. Must export a main function.',
|
||||
),
|
||||
});
|
||||
|
||||
export const createUpdateLogicFunctionSourceTool = (
|
||||
deps: Pick<WorkflowToolDependencies, 'logicFunctionService'>,
|
||||
deps: Pick<WorkflowToolDependencies, 'logicFunctionFromSourceService'>,
|
||||
context: WorkflowToolContext,
|
||||
) => ({
|
||||
name: 'update_logic_function_source' as const,
|
||||
@@ -55,17 +45,16 @@ export const main = async (params: { url: string }) => {
|
||||
|
||||
To find the logicFunctionId, look at the code step's settings.input.logicFunctionId field.`,
|
||||
inputSchema: updateLogicFunctionSourceSchema,
|
||||
execute: async (parameters: {
|
||||
logicFunctionId: string;
|
||||
code: { src: { 'index.ts': string } };
|
||||
}) => {
|
||||
execute: async (parameters: { logicFunctionId: string; code: string }) => {
|
||||
try {
|
||||
const { logicFunctionId, code } = parameters;
|
||||
const { workspaceId } = context;
|
||||
|
||||
await deps.logicFunctionService.updateLogicFunctionSource({
|
||||
await deps.logicFunctionFromSourceService.updateOne({
|
||||
id: logicFunctionId,
|
||||
code,
|
||||
update: {
|
||||
sourceHandlerCode: code,
|
||||
},
|
||||
workspaceId,
|
||||
});
|
||||
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
import type { RecordPositionService } from 'src/engine/core-modules/record-position/services/record-position.service';
|
||||
import type { LogicFunctionFromSourceService } from 'src/engine/metadata-modules/logic-function/services/logic-function-from-source.service';
|
||||
import type { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service';
|
||||
import type { LogicFunctionService } from 'src/engine/metadata-modules/logic-function/services/logic-function.service';
|
||||
import type { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager';
|
||||
import type { WorkflowSchemaWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-schema/workflow-schema.workspace-service';
|
||||
import type { WorkflowVersionEdgeWorkspaceService } from 'src/modules/workflow/workflow-builder/workflow-version-edge/workflow-version-edge.workspace-service';
|
||||
@@ -18,7 +18,7 @@ export type WorkflowToolDependencies = {
|
||||
workflowSchemaService: WorkflowSchemaWorkspaceService;
|
||||
globalWorkspaceOrmManager: GlobalWorkspaceOrmManager;
|
||||
recordPositionService: RecordPositionService;
|
||||
logicFunctionService: LogicFunctionService;
|
||||
logicFunctionFromSourceService: LogicFunctionFromSourceService;
|
||||
flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user