@mastra/core
Version:
Mastra is a framework for building AI-powered applications and agents with a modern TypeScript stack.
1 lines • 21.5 kB
Source Map (JSON)
{"version":3,"sources":["../src/background-tasks/workflow.ts"],"names":["z","createStep","createWorkflow","BACKGROUND_TASK_WORKFLOW_ID"],"mappings":"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","file":"workflow-NQFS7R77.cjs","sourcesContent":["import { z } from 'zod';\nimport { InternalSpans } from '../observability';\nimport type { SuspendOptions } from '../workflows';\nimport { createStep, createWorkflow } from '../workflows/evented';\nimport type { BackgroundTaskManager } from './manager';\nimport type { BackgroundTaskStatus } from './types';\nimport { BACKGROUND_TASK_WORKFLOW_ID } from './workflow-id';\n\nexport { BACKGROUND_TASK_WORKFLOW_ID } from './workflow-id';\n\nconst inputSchema = z.object({ taskId: z.string() });\n\nconst attemptOutcomeSchema = z.enum(['success', 'retry', 'cancelled', 'timed_out']);\n\nconst attemptOutputSchema = z.object({\n taskId: z.string(),\n outcome: attemptOutcomeSchema,\n result: z.unknown().optional(),\n error: z.any().optional(),\n});\n\nconst bodyIOSchema = z.object({\n taskId: z.string(),\n done: z.boolean().optional(),\n result: z.unknown().optional(),\n});\n\nconst bodyOutputSchema = z.object({\n taskId: z.string(),\n done: z.boolean(),\n result: z.unknown().optional(),\n});\n\nconst WORKFLOW_STATUS_TO_PERSIST = ['suspended', 'pending', 'paused', 'waiting'];\n\n/**\n * Builds the per-task evented workflow that owns executor + retries.\n *\n * Shape: outer workflow runs an inner `[run-attempt, classify-outcome]`\n * workflow inside a `dountil` loop. `run-attempt` invokes the executor and\n * categorises the outcome; `classify-outcome` persists final state, advances\n * retry bookkeeping, and decides whether the loop is done. The dountil\n * predicate exits on `done === true`.\n *\n * The nested-workflow-as-loop-body path lives in\n * `processWorkflowEnd → processWorkflowLoop` and was fixed in PR #16312.\n * Suspend/resume routes through the runtime's nested-workflow auto-detect\n * (`processWorkflowStepRun` resume branch).\n *\n * Step bodies close over `manager` directly — the bg-tasks layer is the only\n * consumer of the `@internal` private fields.\n */\nexport function buildBackgroundTaskWorkflow(manager: BackgroundTaskManager) {\n const runAttemptStep = createStep({\n id: 'run-attempt',\n inputSchema: bodyIOSchema,\n outputSchema: attemptOutputSchema,\n execute: async ({ inputData, abortSignal: workflowAbortSignal, suspend, resumeData }) => {\n const { taskId } = inputData;\n const storage = await manager.getStorage();\n const task = await storage.getTask(taskId);\n if (!task || task.status === 'cancelled') {\n manager.deregisterTaskContext(taskId);\n return { taskId, outcome: 'cancelled' as const };\n }\n\n // Resolve the executor. Two paths:\n // 1. Per-task `TaskContext` registered on the producer (in-process).\n // Carries closure-captured state (e.g. agent memory hooks) and\n // wins when present.\n // 2. Static executor registered by tool name. Used by remote workers\n // that received the dispatch via PubSub and don't have access to\n // the producer's per-task closure.\n const ctx = manager.taskContexts.get(taskId);\n const executor = ctx?.executor ?? manager.getStaticExecutor(task.toolName);\n if (!executor) {\n const errorInfo = {\n message:\n `No executor registered for tool \"${task.toolName}\". ` +\n `Register the tool on Mastra (so workers can resolve it cross-process) ` +\n `or run the task in the same process as the producer.`,\n };\n await storage.updateTask(taskId, { status: 'failed', error: errorInfo, completedAt: new Date() });\n const failedTask = await storage.getTask(taskId);\n if (failedTask) {\n await manager.runLocalCompletionHooks(failedTask, 'failed', { error: errorInfo });\n await manager.publishLifecycleEvent('task.failed', failedTask);\n }\n manager.deregisterTaskContext(taskId);\n throw new Error(errorInfo.message);\n }\n\n // Throttled progress publisher.\n const progressThrottleMs = manager.config.progressThrottleMs;\n const shouldThrottleProgress =\n typeof progressThrottleMs === 'number' && Number.isFinite(progressThrottleMs) && progressThrottleMs > 0;\n let lastProgressEmitMs: number | undefined;\n const onProgress = async (chunk: any) => {\n if (shouldThrottleProgress) {\n const now = Date.now();\n if (lastProgressEmitMs !== undefined && now - lastProgressEmitMs < progressThrottleMs!) return;\n lastProgressEmitMs = now;\n }\n await manager.publishLifecycleEvent('task.output', { ...task, chunk });\n };\n\n const abortController = new AbortController();\n manager.activeAbortControllers.set(taskId, abortController);\n // Wire the workflow's run-level abort signal into our local controller\n // so `workflow.getRun(taskId).cancel()` propagates to the executor.\n const onWorkflowAbort = () => abortController.abort(new Error('Task cancelled'));\n if (workflowAbortSignal.aborted) {\n abortController.abort(new Error('Task cancelled'));\n } else {\n workflowAbortSignal.addEventListener('abort', onWorkflowAbort, { once: true });\n }\n const timeoutHandle = setTimeout(() => {\n abortController.abort(new Error(`Task timed out after ${task.timeoutMs}ms`));\n }, task.timeoutMs);\n\n // Wrap the workflow runtime's `suspend` so we persist\n // `status: 'suspended'` + `suspendPayload`, fire the per-task\n // suspend hook (so the bg-task's `onResult` updates the agent's\n // message list), and publish the lifecycle event before\n // delegating. The runtime's `suspend` does not throw — it sets a\n // flag the step-executor reads after `execute` returns. We\n // capture the args here and call the runtime's suspend from the\n // step body after the executor returns, so `wrappedSuspend` can\n // safely run all its side effects synchronously inside the\n // tool's call.\n let pendingSuspend: { data?: unknown; suspendOptions?: SuspendOptions } | undefined;\n const wrappedSuspend = async (data?: unknown, suspendOptions?: SuspendOptions) => {\n await storage.updateTask(taskId, {\n status: 'suspended',\n suspendPayload: data,\n suspendedAt: new Date(),\n });\n const suspendedTask = await storage.getTask(taskId);\n if (suspendedTask) {\n // Suspend is non-terminal — DO NOT use `runLocalCompletionHooks`\n // here. That helper deregisters the task context in its `finally`\n // block, which would strand the resume call (the workflow step\n // body re-enters and looks up `manager.taskContexts.get(taskId)`).\n await manager.runLocalSuspendHooks(suspendedTask);\n await manager.publishLifecycleEvent('task.suspended', suspendedTask);\n }\n pendingSuspend = { data, suspendOptions };\n };\n\n try {\n const result = await executor.execute(task.args, {\n abortSignal: abortController.signal,\n onProgress,\n suspend: wrappedSuspend,\n // On resume the runtime populates `resumeData`; undefined on\n // the initial run.\n resumeData,\n });\n\n if (pendingSuspend) {\n return suspend(pendingSuspend.data, pendingSuspend.suspendOptions as SuspendOptions);\n }\n\n return { taskId, outcome: 'success' as const, result };\n } catch (error: any) {\n const currentTask = await storage.getTask(taskId);\n if (!currentTask || (currentTask.status as BackgroundTaskStatus) === 'cancelled') {\n manager.deregisterTaskContext(taskId);\n return { taskId, outcome: 'cancelled' as const };\n }\n\n // Treat any aborted-signal exit as a timeout. The cancel path is\n // already handled by the storage-status check above, so if we reach\n // here with `signal.aborted`, it's the timeout abort. The\n // `AbortError` / message checks are belt-and-braces for executors\n // that throw their own abort error instead of propagating ours.\n if (\n abortController.signal.aborted ||\n error?.name === 'AbortError' ||\n error?.message === 'Task cancelled' ||\n error?.message?.startsWith('Task timed out after ')\n ) {\n return { taskId, outcome: 'timed_out' as const };\n }\n\n return {\n taskId,\n outcome: 'retry' as const,\n error: { message: error?.message ?? 'Unknown error', stack: error?.stack },\n };\n } finally {\n clearTimeout(timeoutHandle);\n workflowAbortSignal.removeEventListener('abort', onWorkflowAbort);\n manager.activeAbortControllers.delete(taskId);\n }\n },\n });\n\n const classifyOutcomeStep = createStep({\n id: 'classify-outcome',\n inputSchema: attemptOutputSchema,\n outputSchema: bodyOutputSchema,\n execute: async ({ inputData }) => {\n const { taskId, outcome, result, error } = inputData;\n const storage = await manager.getStorage();\n const task = await storage.getTask(taskId);\n if (!task) return { taskId, done: true };\n\n if (outcome === 'cancelled') {\n manager.deregisterTaskContext(taskId);\n return { taskId, done: true };\n }\n\n if (outcome === 'timed_out') {\n const status = task.status as string;\n if (status !== 'timed_out' && status !== 'cancelled') {\n await storage.updateTask(taskId, {\n status: 'timed_out',\n error: { message: `Task timed out after ${task.timeoutMs}ms` },\n completedAt: new Date(),\n });\n const timedOutTask = await storage.getTask(taskId);\n if (timedOutTask) await manager.publishLifecycleEvent('task.failed', timedOutTask);\n }\n return { taskId, done: true };\n }\n\n if (outcome === 'success') {\n if ((task.status as BackgroundTaskStatus) === 'cancelled') {\n manager.deregisterTaskContext(taskId);\n return { taskId, done: true };\n }\n await storage.updateTask(taskId, { status: 'completed', result, completedAt: new Date() });\n const completedTask = await storage.getTask(taskId);\n if (completedTask) {\n await manager.runLocalCompletionHooks(completedTask, 'completed', { result });\n await manager.publishLifecycleEvent('task.completed', completedTask);\n }\n return { taskId, done: true, result };\n }\n\n // outcome === 'retry'\n if (task.retryCount < task.maxRetries) {\n await storage.updateTask(taskId, {\n retryCount: task.retryCount + 1,\n error: undefined,\n startedAt: new Date(),\n });\n return { taskId, done: false };\n }\n\n // Retries exhausted: persist failure and throw so the workflow run ends\n // in `failed` rather than completing cleanly. Throw matches the prior\n // single-step behavior — workflow-run history stays accurate.\n const errorInfo = error ?? { message: 'Unknown error' };\n await storage.updateTask(taskId, { status: 'failed', error: errorInfo, completedAt: new Date() });\n const failedTask = await storage.getTask(taskId);\n if (failedTask) {\n await manager.runLocalCompletionHooks(failedTask, 'failed', { error: errorInfo });\n await manager.publishLifecycleEvent('task.failed', failedTask);\n }\n const thrown = new Error(errorInfo.message);\n if (errorInfo.stack) thrown.stack = errorInfo.stack;\n throw thrown;\n },\n });\n\n const attemptBodyWorkflow = createWorkflow({\n id: `${BACKGROUND_TASK_WORKFLOW_ID}__attempt`,\n inputSchema: bodyIOSchema,\n outputSchema: bodyOutputSchema,\n steps: [runAttemptStep, classifyOutcomeStep],\n options: {\n // `dountil` feeds the prior iteration's output back in as input. The\n // body's actual entry point only needs `taskId`, but the loop's\n // feedback shape includes `done`/`result`/etc. Skip validation rather\n // than widen every step's input schema.\n validateInputs: false,\n shouldPersistSnapshot: ({ workflowStatus }) => WORKFLOW_STATUS_TO_PERSIST.includes(workflowStatus),\n // Internal scheduler plumbing — hide workflow spans from exported\n // traces. The task body itself runs as user code and keeps its own\n // spans.\n tracingPolicy: {\n internal: InternalSpans.WORKFLOW,\n },\n },\n })\n .then(runAttemptStep)\n .then(classifyOutcomeStep)\n .commit();\n\n return createWorkflow({\n id: BACKGROUND_TASK_WORKFLOW_ID,\n inputSchema,\n outputSchema: bodyOutputSchema,\n steps: [attemptBodyWorkflow],\n options: {\n shouldPersistSnapshot: ({ workflowStatus }) => WORKFLOW_STATUS_TO_PERSIST.includes(workflowStatus),\n // Internal scheduler plumbing — see the inner workflow comment.\n tracingPolicy: {\n internal: InternalSpans.WORKFLOW,\n },\n },\n })\n .dountil(attemptBodyWorkflow, async ({ inputData }) => inputData?.done === true)\n .commit();\n}\n"]}