diff --git a/packages/frontend/editor-ui/src/experiments/readyToRunWorkflowsV2/stores/readyToRunWorkflowsV2.store.ts b/packages/frontend/editor-ui/src/experiments/readyToRunWorkflowsV2/stores/readyToRunWorkflowsV2.store.ts index c186d53c774..c86267402ec 100644 --- a/packages/frontend/editor-ui/src/experiments/readyToRunWorkflowsV2/stores/readyToRunWorkflowsV2.store.ts +++ b/packages/frontend/editor-ui/src/experiments/readyToRunWorkflowsV2/stores/readyToRunWorkflowsV2.store.ts @@ -6,10 +6,12 @@ import { useCredentialsStore } from '@/stores/credentials.store'; import { usePostHog } from '@/stores/posthog.store'; import { useSettingsStore } from '@/stores/settings.store'; import { useUsersStore } from '@/stores/users.store'; +import { useWorkflowsStore } from '@/stores/workflows.store'; import { useI18n } from '@n8n/i18n'; import { STORES } from '@n8n/stores'; import { useLocalStorage } from '@vueuse/core'; -import { OPEN_AI_API_CREDENTIAL_TYPE } from 'n8n-workflow'; +import { OPEN_AI_API_CREDENTIAL_TYPE, deepCopy } from 'n8n-workflow'; +import type { WorkflowDataCreate } from '@n8n/rest-api-client'; import { defineStore } from 'pinia'; import { computed, ref } from 'vue'; import { useRouter, type RouteLocationNormalized } from 'vue-router'; @@ -31,6 +33,7 @@ export const useReadyToRunWorkflowsV2Store = defineStore( const settingsStore = useSettingsStore(); const posthogStore = usePostHog(); const cloudPlanStore = useCloudPlanStore(); + const workflowsStore = useWorkflowsStore(); const isFeatureEnabled = computed(() => { const variant = posthogStore.getVariant(READY_TO_RUN_V2_EXPERIMENT.name); @@ -109,23 +112,50 @@ export const useReadyToRunWorkflowsV2Store = defineStore( } }; - const openAiWorkflow = async (source: 'card' | 'button', parentFolderId?: string) => { + const createAndOpenAiWorkflow = async (source: 'card' | 'button', parentFolderId?: string) => { const variant = getCurrentVariant(); telemetry.track('User opened ready to run AI workflow', { source, variant, }); - const workflow = + const workflowTemplate = variant === READY_TO_RUN_V2_EXPERIMENT.variant2 ? READY_TO_RUN_WORKFLOW_V2 : READY_TO_RUN_WORKFLOW_V1; - await router.push({ - name: VIEWS.TEMPLATE_IMPORT, - params: { id: workflow.meta?.templateId }, - query: { fromJson: 'true', parentFolderId }, - }); + try { + let workflowToCreate: WorkflowDataCreate = { + ...workflowTemplate, + parentFolderId, + }; + + const credentialId = claimedCredentialIdRef.value; + if (credentialId && workflowToCreate.nodes) { + const clonedWorkflow = deepCopy(workflowToCreate); + const openAiNode = clonedWorkflow.nodes?.find((node) => node.name === 'OpenAI Model'); + if (openAiNode) { + openAiNode.credentials ??= {}; + openAiNode.credentials[OPEN_AI_API_CREDENTIAL_TYPE] = { + id: credentialId, + name: '', + }; + } + workflowToCreate = clonedWorkflow; + } + + const createdWorkflow = await workflowsStore.createNewWorkflow(workflowToCreate); + + await router.push({ + name: VIEWS.WORKFLOW, + params: { name: createdWorkflow.id }, + }); + + return createdWorkflow; + } catch (error) { + toast.showError(error, i18n.baseText('generic.error')); + throw error; + } }; const claimCreditsAndOpenWorkflow = async ( @@ -134,7 +164,7 @@ export const useReadyToRunWorkflowsV2Store = defineStore( projectId?: string, ) => { await claimFreeAiCredits(projectId); - await openAiWorkflow(source, parentFolderId); + await createAndOpenAiWorkflow(source, parentFolderId); }; const getCardVisibility = ( @@ -176,7 +206,7 @@ export const useReadyToRunWorkflowsV2Store = defineStore( claimingCredits, userCanClaimOpenAiCredits, claimFreeAiCredits, - openAiWorkflow, + createAndOpenAiWorkflow, claimCreditsAndOpenWorkflow, getCardVisibility, getButtonVisibility, diff --git a/packages/frontend/editor-ui/src/experiments/readyToRunWorkflowsV2/utils/workflowSamples.ts b/packages/frontend/editor-ui/src/experiments/readyToRunWorkflowsV2/utils/workflowSamples.ts deleted file mode 100644 index f2bfd84ae4e..00000000000 --- a/packages/frontend/editor-ui/src/experiments/readyToRunWorkflowsV2/utils/workflowSamples.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { ApplicationError, deepCopy, OPEN_AI_API_CREDENTIAL_TYPE } from 'n8n-workflow'; -import type { WorkflowDataWithTemplateId } from '@/Interface'; -import { isWorkflowDataWithTemplateId } from '@/utils/templates/typeGuards'; -import { READY_TO_RUN_WORKFLOW_V1 } from '../workflows/ai-workflow'; -import { READY_TO_RUN_WORKFLOW_V2 } from '../workflows/ai-workflow-v2'; - -const getWorkflowJson = (json: unknown): WorkflowDataWithTemplateId => { - if (!isWorkflowDataWithTemplateId(json)) { - throw new ApplicationError('Invalid workflow template JSON structure'); - } - - return json; -}; - -/** - * Injects OpenAI credentials into workflow template if available in localStorage - */ -const injectOpenAiCredentialIntoWorkflow = ( - workflow: WorkflowDataWithTemplateId, -): WorkflowDataWithTemplateId => { - const credentialId = localStorage.getItem('N8N_READY_TO_RUN_V2_OPENAI_CREDENTIAL_ID'); - - if (!credentialId) { - return workflow; - } - - const clonedWorkflow = deepCopy(workflow); - - if (clonedWorkflow.nodes) { - const openAiNode = clonedWorkflow.nodes.find((node) => node.name === 'OpenAI Model'); - if (openAiNode) { - openAiNode.credentials ??= {}; - openAiNode.credentials[OPEN_AI_API_CREDENTIAL_TYPE] = { - id: credentialId, - name: '', - }; - } - } - - return clonedWorkflow; -}; - -export const getReadyToRunAIWorkflows = (): WorkflowDataWithTemplateId[] => { - return [ - injectOpenAiCredentialIntoWorkflow(getWorkflowJson(READY_TO_RUN_WORKFLOW_V1)), - injectOpenAiCredentialIntoWorkflow(getWorkflowJson(READY_TO_RUN_WORKFLOW_V2)), - ]; -}; diff --git a/packages/frontend/editor-ui/src/utils/templates/workflowSamples.ts b/packages/frontend/editor-ui/src/utils/templates/workflowSamples.ts index bb0e2329f10..686886a6bd1 100644 --- a/packages/frontend/editor-ui/src/utils/templates/workflowSamples.ts +++ b/packages/frontend/editor-ui/src/utils/templates/workflowSamples.ts @@ -1,8 +1,6 @@ import { ApplicationError, type INodeTypeNameVersion } from 'n8n-workflow'; import type { WorkflowDataWithTemplateId } from '@/Interface'; import { isWorkflowDataWithTemplateId } from '@/utils/templates/typeGuards'; -import { getReadyToRunAIWorkflows } from '@/experiments/readyToRunWorkflowsV2/utils/workflowSamples'; - /* eslint-disable import-x/extensions */ import easyAiStarterJson from '@/utils/templates/samples/easy_ai_starter.json'; import ragStarterJson from '@/utils/templates/samples/rag_starter.json'; @@ -193,7 +191,6 @@ export const getSampleWorkflowByTemplateId = ( const workflows = [ getEasyAiWorkflowJson(), getRagStarterWorkflowJson(), - ...getReadyToRunAIWorkflows(), ...getPrebuiltAgents().map((agent) => agent.template), ...getTutorialTemplates().map((tutorial) => tutorial.template), ];