{"version":3,"file":"background-tasks-lifNqs9M.cjs","names":["#mastra","#doInit","#ensureExecutionWorkersStarted","z"],"sources":["../src/background-tasks/workflow-id.ts","../src/background-tasks/manager.ts","../src/background-tasks/create.ts","../src/background-tasks/resolve-config.ts","../src/background-tasks/schema-injection.ts","../src/background-tasks/system-prompt.ts"],"sourcesContent":["/**\n * Workflow id used by the bg-task workflow registered on Mastra.\n * Double-underscore prefix marks it as internal — same convention as\n * `__batch-scoring-traces`.\n *\n * Lives in its own file (separate from `./workflow`) so `manager.ts` can\n * reference the id without statically pulling in `../workflows/evented`,\n * which would create a circular import via `agent → background-tasks →\n * workflow → evented → workflows/index → agent`.\n */\nexport const BACKGROUND_TASK_WORKFLOW_ID = '__background-task';\n","import { randomUUID } from 'node:crypto';\nimport type { Mastra } from '..';\nimport type { PubSub } from '../events/pubsub';\nimport type { Event, EventCallback } from '../events/types';\nimport type {\n  BackgroundTask,\n  BackgroundTaskManagerConfig,\n  BackgroundTaskStatus,\n  EnqueueResult,\n  TaskContext,\n  TaskFilter,\n  TaskPayload,\n  TaskListResult,\n  ToolExecutor,\n  BackgroundTaskEvent,\n} from './types';\nimport { BACKGROUND_TASK_WORKFLOW_ID } from './workflow-id';\n\nconst TOPIC_DISPATCH = 'background-tasks';\nconst TOPIC_RESULT = 'background-tasks-result';\nconst WORKER_GROUP = 'background-task-workers';\n\nexport class BackgroundTaskManager {\n  private pubsub!: PubSub;\n  config: Required<\n    Pick<BackgroundTaskManagerConfig, 'globalConcurrency' | 'perAgentConcurrency' | 'backpressure' | 'defaultTimeoutMs'>\n  > &\n    BackgroundTaskManagerConfig;\n\n  #mastra?: Mastra;\n\n  // Per-task contexts — keyed by task ID, holds closures from the caller's stream.\n  /** @internal — read by the workflow-engine step bodies in workflow.ts */\n  taskContexts: Map<string, TaskContext> = new Map();\n\n  // Static executors keyed by tool name. Populated by `Mastra` for every\n  // registered tool, and by `BackgroundTaskWorker.#wireStaticTools` on\n  // standalone worker processes. Used as the fallback for cross-process\n  // dispatch where the producer's per-task closure (taskContexts) is not\n  // visible — a remote worker resolves the tool by name instead.\n  private staticExecutors: Map<string, ToolExecutor> = new Map();\n\n  // Track active AbortControllers for running tasks (for cancellation + timeout)\n  /** @internal — read by the workflow-engine step bodies in workflow.ts */\n  activeAbortControllers: Map<string, AbortController> = new Map();\n\n  // Pubsub callbacks (kept for unsubscribe)\n  private workerCallback?: EventCallback;\n  private resultCallback?: EventCallback;\n\n  private shuttingDown = false;\n\n  // Cleanup interval handle\n  private cleanupInterval?: ReturnType<typeof setInterval>;\n\n  // Tracks the in-flight `init(pubsub)` so consumers can await readiness.\n  // Mastra fires init as fire-and-forget in `#ensureBackgroundTaskManager`,\n  // so without this any caller that hits `enqueue`/`resume`/`cancel`\n  // before init completes races against worker subscription + workflow\n  // registration. Public methods that depend on init await this promise\n  // before doing work.\n  private initPromise?: Promise<void>;\n\n  constructor(config: BackgroundTaskManagerConfig = { enabled: false }) {\n    this.config = {\n      globalConcurrency: config.globalConcurrency ?? 10,\n      perAgentConcurrency: config.perAgentConcurrency ?? 5,\n      backpressure: config.backpressure ?? 'queue',\n      defaultTimeoutMs: config.defaultTimeoutMs ?? 300_000,\n      ...config,\n    };\n  }\n\n  __registerMastra(mastra: Mastra) {\n    this.#mastra = mastra;\n  }\n\n  async getStorage() {\n    const storage = this.#mastra?.getStorage();\n    if (!storage) {\n      throw new Error('Storage is not initialized');\n    }\n    const bgStore = await storage.getStore('backgroundTasks');\n    if (!bgStore) {\n      throw new Error('Background tasks storage is not available');\n    }\n    return bgStore;\n  }\n\n  async init(pubsub: PubSub): Promise<void> {\n    if (this.initPromise) return this.initPromise;\n    this.initPromise = this.#doInit(pubsub);\n    return this.initPromise;\n  }\n\n  async #doInit(pubsub: PubSub): Promise<void> {\n    this.pubsub = pubsub;\n\n    const isProducerOnly = this.config.mode === 'producer';\n\n    // Result listener: fan-out so all processes receive results.\n    // Both producer and worker modes need this — the producer uses it\n    // to receive completion/failure notifications for dispatched tasks.\n    this.resultCallback = async (event: Event, ack?: () => Promise<void>) => {\n      if (event.type === 'task.completed' || event.type === 'task.failed') {\n        await this.handleResult(event);\n      }\n      await ack?.();\n    };\n\n    if (!isProducerOnly) {\n      // Worker: subscribes with group so only one worker processes each task.\n      this.workerCallback = async (event: Event, ack?: () => Promise<void>) => {\n        if (event.type === 'task.dispatch' || event.type === 'task.restart') {\n          await this.handleDispatch(event);\n        } else if (event.type === 'task.resume') {\n          await this.handleResume(event);\n        } else if (event.type === 'task.cancel') {\n          this.handleCancel(event);\n        }\n        await ack?.();\n      };\n\n      // Register the workflow BEFORE subscribing the worker so that any\n      // dispatch event the worker picks up can immediately resolve the\n      // workflow on Mastra. Reversing this order races: a publish that\n      // arrives between `subscribe(TOPIC_DISPATCH)` and the workflow\n      // registration triggers `__getInternalWorkflow` to throw\n      // `Workflow with id __background-task not found`, the task stays at\n      // `running` forever, and the dispatch is silently dropped.\n      if (this.#mastra) {\n        // Dynamic import breaks the static cycle:\n        // agent → background-tasks → manager → workflow → workflows/evented →\n        // workflows/index → agent. Static import works at runtime but during\n        // module evaluation in test environments the cycle leaves `Workflow`\n        // undefined when `evented/workflow.ts` evaluates its `class extends`.\n        const { buildBackgroundTaskWorkflow } = await import('./workflow');\n        const workflow = buildBackgroundTaskWorkflow(this);\n        if (!this.#mastra.__hasInternalWorkflow(BACKGROUND_TASK_WORKFLOW_ID)) {\n          // The `__background-task` workflow is typed against `EventedEngineType`\n          // and a concrete input/output schema, while `__registerInternalWorkflow`\n          // accepts the looser default `Workflow` shape. The cast is purely a\n          // type-level bridge — the runtime value is a real Workflow.\n          this.#mastra.__registerInternalWorkflow(\n            workflow as unknown as Parameters<Mastra['__registerInternalWorkflow']>[0],\n          );\n        }\n      }\n\n      await this.pubsub.subscribe(TOPIC_DISPATCH, this.workerCallback, { group: WORKER_GROUP });\n    }\n\n    await this.pubsub.subscribe(TOPIC_RESULT, this.resultCallback);\n\n    if (!isProducerOnly) {\n      // Recover stale tasks from a previous process — only workers should\n      // attempt recovery since they own execution.\n      await this.recoverStaleTasks();\n    }\n\n    // Start periodic cleanup if configured\n    const cleanupConfig = this.config.cleanup;\n    if (cleanupConfig) {\n      const intervalMs = cleanupConfig.cleanupIntervalMs ?? 60_000;\n      this.cleanupInterval = setInterval(() => {\n        void this.cleanup();\n      }, intervalMs);\n    }\n  }\n\n  // --- Per-task context registration ---\n\n  /**\n   * Register per-task hooks (executor, stream emitter, result injector).\n   * Called internally by createBackgroundTask or directly for advanced usage.\n   */\n  registerTaskContext(taskId: string, context: TaskContext): void {\n    this.taskContexts.set(taskId, context);\n  }\n\n  /**\n   * Remove per-task hooks. Called after task reaches terminal state.\n   */\n  deregisterTaskContext(taskId: string): void {\n    this.taskContexts.delete(taskId);\n  }\n\n  /**\n   * Register a tool executor by tool name. Used for cross-process dispatch:\n   * when a worker in a different process picks up a `task.dispatch` event,\n   * it has no per-task closure (`taskContexts`) for that taskId, but it can\n   * resolve the executor by tool name via this registry.\n   */\n  registerStaticExecutor(toolName: string, executor: ToolExecutor): void {\n    if (this.staticExecutors.has(toolName)) {\n      this.#mastra?.getLogger?.()?.debug?.(`Overwriting existing static executor for tool \"${toolName}\"`);\n    }\n    this.staticExecutors.set(toolName, executor);\n  }\n\n  /**\n   * Symmetric to `registerStaticExecutor`. Called when a tool is removed\n   * from `Mastra`.\n   */\n  unregisterStaticExecutor(toolName: string): void {\n    this.staticExecutors.delete(toolName);\n  }\n\n  /**\n   * Look up an executor by tool name. Read by the workflow-step body in\n   * `workflow.ts:runAttemptStep` as a fallback when no per-task `TaskContext`\n   * is registered (cross-process path).\n   */\n  getStaticExecutor(toolName: string): ToolExecutor | undefined {\n    return this.staticExecutors.get(toolName);\n  }\n\n  // --- Core operations ---\n\n  /**\n   * Enqueue a task for background execution.\n   * Prefer `createBackgroundTask()` which returns a self-contained handle.\n   */\n  async enqueue(payload: TaskPayload, context?: TaskContext): Promise<EnqueueResult> {\n    if (this.shuttingDown) {\n      throw new Error('BackgroundTaskManager is shutting down, cannot enqueue new tasks');\n    }\n\n    // Mastra fires `init` as fire-and-forget. If a caller hits enqueue\n    // before init completes, the dispatch publish fires before the worker\n    // subscribes and the event is dropped (or, worse, lands on a worker\n    // whose Mastra hasn't yet registered the bg-task workflow → \"Workflow\n    // with id __background-task not found\"). Await readiness up front.\n    if (this.initPromise) await this.initPromise;\n\n    const task: BackgroundTask = {\n      id: this.#mastra?.generateId() ?? randomUUID(),\n      status: 'pending',\n      toolName: payload.toolName,\n      toolCallId: payload.toolCallId,\n      args: payload.args,\n      agentId: payload.agentId,\n      threadId: payload.threadId,\n      resourceId: payload.resourceId,\n      runId: payload.runId,\n      retryCount: 0,\n      maxRetries: payload.maxRetries ?? this.config.defaultRetries?.maxRetries ?? 0,\n      timeoutMs: payload.timeoutMs ?? this.config.defaultTimeoutMs,\n      createdAt: new Date(),\n    };\n\n    // Register per-task context if provided\n    if (context) {\n      this.registerTaskContext(task.id, context);\n    }\n\n    const storage = await this.getStorage();\n    await storage.createTask(task);\n\n    const canRun = await this.checkConcurrency(task.agentId);\n\n    if (canRun) {\n      await this.dispatch(task);\n      return { task };\n    }\n\n    // Backpressure\n    switch (this.config.backpressure) {\n      case 'reject':\n        this.deregisterTaskContext(task.id);\n        await storage.deleteTask(task.id);\n        throw new Error(`Concurrency limit reached, cannot enqueue task for tool \"${task.toolName}\"`);\n\n      case 'fallback-sync':\n        this.deregisterTaskContext(task.id);\n        await storage.deleteTask(task.id);\n        return { task, fallbackToSync: true };\n\n      case 'queue':\n      default:\n        // Task stays pending in storage, will be dispatched when a slot opens\n        return { task };\n    }\n  }\n\n  async cancel(taskId: string): Promise<void> {\n    if (this.initPromise) await this.initPromise;\n    const storage = await this.getStorage();\n    const task = await storage.getTask(taskId);\n    if (!task) {\n      throw new Error(`Task not found: ${taskId}`);\n    }\n\n    if (\n      task.status === 'completed' ||\n      task.status === 'failed' ||\n      task.status === 'cancelled' ||\n      task.status === 'timed_out'\n    ) {\n      return; // no-op for terminal states\n    }\n\n    if (task.status === 'pending') {\n      await storage.updateTask(taskId, { status: 'cancelled', completedAt: new Date() });\n      const cancelledTask = await storage.getTask(taskId);\n      if (cancelledTask) await this.publishLifecycleEvent('task.cancelled', cancelledTask);\n      this.deregisterTaskContext(taskId);\n      return;\n    }\n\n    if (task.status === 'suspended') {\n      // No active executor or AbortController to tear down — the task is\n      // sitting on a workflow snapshot. Flip storage, publish, and tell the\n      // workflow run to cancel so the snapshot is cleaned up too.\n      await storage.updateTask(taskId, { status: 'cancelled', completedAt: new Date() });\n      if (this.#mastra) {\n        try {\n          const workflow = this.#mastra.__getInternalWorkflow(BACKGROUND_TASK_WORKFLOW_ID);\n          const wrapper = await workflow.createRun({ runId: taskId });\n          await wrapper.cancel();\n        } catch (err) {\n          this.#mastra?.getLogger?.()?.warn(`background-task workflow cancel failed for ${taskId}:`, err as any);\n        }\n      }\n      const cancelledTask = await storage.getTask(taskId);\n      if (cancelledTask) await this.publishLifecycleEvent('task.cancelled', cancelledTask);\n      this.deregisterTaskContext(taskId);\n      return;\n    }\n\n    if (task.status === 'running') {\n      await storage.updateTask(taskId, { status: 'cancelled', completedAt: new Date() });\n\n      // Abort the running tool\n      const controller = this.activeAbortControllers.get(taskId);\n      if (controller) {\n        controller.abort(new Error('Task cancelled'));\n        this.activeAbortControllers.delete(taskId);\n      }\n\n      // Also cancel the workflow run so workflow storage reflects the\n      // cancellation (run status flips to 'canceled' and the workflow's\n      // abortSignal fires — redundant with the local AbortController above\n      // but keeps run history clean and propagates cross-process via the\n      // workflow.cancel pubsub event).\n      if (this.#mastra) {\n        try {\n          const workflow = this.#mastra.__getInternalWorkflow(BACKGROUND_TASK_WORKFLOW_ID);\n          const wrapper = await workflow.createRun({ runId: taskId });\n          await wrapper.cancel();\n        } catch (err) {\n          this.#mastra?.getLogger?.()?.warn(`background-task workflow cancel failed for ${taskId}:`, err as any);\n        }\n      }\n\n      const cancelledTask = await storage.getTask(taskId);\n      if (cancelledTask) await this.publishLifecycleEvent('task.cancelled', cancelledTask);\n      this.deregisterTaskContext(taskId);\n\n      // Also publish cancel on dispatch topic for distributed worker abort\n      await this.pubsub.publish(TOPIC_DISPATCH, {\n        type: 'task.cancel',\n        data: { taskId },\n        runId: taskId,\n      });\n    }\n  }\n\n  /**\n   * Resume a suspended task. The tool executor must be re-registered via\n   * `registerTaskContext(taskId, ...)` before calling this if the original\n   * registration is gone (e.g. process restart) — the manager doesn't\n   * rehydrate executor closures from storage.\n   *\n   * `resumeData` is forwarded to the tool's `execute` options on the\n   * resumed run.\n   */\n  async resume(taskId: string, resumeData?: unknown): Promise<BackgroundTask> {\n    if (!this.#mastra) {\n      throw new Error('Mastra is not registered with this manager');\n    }\n\n    if (this.initPromise) await this.initPromise;\n\n    const storage = await this.getStorage();\n    const task = await storage.getTask(taskId);\n    if (!task) {\n      throw new Error(`Task not found: ${taskId}`);\n    }\n    if (task.status !== 'suspended') {\n      throw new Error(`Cannot resume task in status '${task.status}' (expected 'suspended')`);\n    }\n\n    const canRun = await this.checkConcurrency(task.agentId);\n    if (!canRun) {\n      // Resume sits outside the queue/fallback-sync paths — there's no\n      // synchronous caller to fall back to, and silently leaving the task\n      // suspended hides the failure from the caller. Throw and let the\n      // caller retry once a slot frees.\n      throw new Error(`Concurrency limit reached, cannot resume task \"${taskId}\" — retry once a slot is available`);\n    }\n\n    // Resume publishes directly (not via dispatch()), so it needs its own\n    // lazy worker start for the library-mode process-restart case.\n    await this.#ensureExecutionWorkersStarted();\n\n    // Hand off to the worker subscriber. `task.resume` rides the same\n    // `TOPIC_DISPATCH` + `WORKER_GROUP` exactly-once channel as\n    // `task.dispatch`, so any worker (including a different process from\n    // the one that suspended the task) can pick it up.\n    await this.pubsub.publish(TOPIC_DISPATCH, {\n      type: 'task.resume',\n      data: { taskId, resumeData },\n      runId: taskId,\n    });\n\n    return task;\n  }\n\n  /**\n   * Restarts a previously running task. The tool executor is re-registered via\n   * `registerTaskContext(taskId, ...)` because the original\n   * registration is gone (e.g. process restart) — the manager doesn't\n   * rehydrate executor closures from storage.\n   *\n   */\n  async restart(taskId: string, context?: TaskContext): Promise<BackgroundTask> {\n    if (!this.#mastra) {\n      throw new Error('Mastra is not registered with this manager');\n    }\n\n    if (this.initPromise) await this.initPromise;\n\n    const storage = await this.getStorage();\n    const task = await storage.getTask(taskId);\n    if (!task) {\n      throw new Error(`Task not found: ${taskId}`);\n    }\n    if (task.status !== 'running') {\n      throw new Error(`Cannot restart task in status '${task.status}' (expected 'running')`);\n    }\n\n    if (context) {\n      this.registerTaskContext(task.id, context);\n    }\n\n    const canRun = await this.checkConcurrency(task.agentId);\n    if (!canRun) {\n      // Restart sits outside the queue/fallback-sync paths — there's no\n      // synchronous caller to fall back to, and silently leaving the task\n      // running hides the failure from the caller. Throw and let the\n      // caller retry once a slot frees.\n      throw new Error(`Concurrency limit reached, cannot restart task \"${taskId}\" — retry once a slot is available`);\n    }\n\n    await this.dispatch(task, true);\n\n    return task;\n  }\n\n  async getTask(taskId: string): Promise<BackgroundTask | null> {\n    const storage = await this.getStorage();\n    return storage.getTask(taskId);\n  }\n\n  async listTasks(filter: TaskFilter = {}): Promise<TaskListResult> {\n    const storage = await this.getStorage();\n    return storage.listTasks(filter);\n  }\n\n  /**\n   * Deletes old completed/failed/cancelled/timed_out task records from storage.\n   */\n  async cleanup(): Promise<void> {\n    const completedTtlMs = this.config.cleanup?.completedTtlMs ?? 3_600_000;\n    const failedTtlMs = this.config.cleanup?.failedTtlMs ?? 86_400_000;\n    const now = Date.now();\n\n    const storage = await this.getStorage();\n    await storage.deleteTasks({\n      status: ['completed'],\n      toDate: new Date(now - completedTtlMs),\n      dateFilterBy: 'completedAt',\n    });\n\n    await storage.deleteTasks({\n      status: ['failed', 'cancelled', 'timed_out'],\n      toDate: new Date(now - failedTtlMs),\n      dateFilterBy: 'completedAt',\n    });\n  }\n\n  /**\n   * Returns a promise that resolves when the next task from the given set\n   * reaches a terminal state.\n   */\n  async waitForNextTask(\n    taskIds: string[],\n    options?: {\n      timeoutMs?: number;\n      onProgress?: (elapsedMs: number) => void;\n      progressIntervalMs?: number;\n    },\n  ): Promise<BackgroundTask> {\n    const storage = await this.getStorage();\n\n    const isTerminal = (status: string) =>\n      status === 'completed' || status === 'failed' || status === 'cancelled' || status === 'timed_out';\n\n    for (const id of taskIds) {\n      const task = await storage.getTask(id);\n      if (task && isTerminal(task.status)) {\n        return task;\n      }\n    }\n\n    return new Promise((resolve, reject) => {\n      const startTime = Date.now();\n\n      const timeout = options?.timeoutMs\n        ? setTimeout(() => {\n            clearInterval(pollInterval);\n            if (progressInterval) clearInterval(progressInterval);\n            reject(new Error('Timed out waiting for background task'));\n          }, options.timeoutMs)\n        : undefined;\n\n      const progressInterval = options?.onProgress\n        ? setInterval(() => {\n            options.onProgress!(Date.now() - startTime);\n          }, options.progressIntervalMs ?? 3000)\n        : undefined;\n\n      const pollInterval = setInterval(async () => {\n        for (const id of taskIds) {\n          const task = await storage.getTask(id);\n          if (task && isTerminal(task.status)) {\n            clearInterval(pollInterval);\n            if (timeout) clearTimeout(timeout);\n            if (progressInterval) clearInterval(progressInterval);\n            resolve(task);\n            return;\n          }\n        }\n      }, 50);\n    });\n  }\n\n  /**\n   * Returns a ReadableStream of all background task lifecycle events,\n   * filtered by optional criteria. Intended to be piped directly to an SSE response.\n   *\n   * On connection, emits the current state of all non-terminal tasks as a snapshot,\n   * then subscribes to live pubsub events for subsequent updates.\n   *\n   * Events include:\n   * - `task.running` (status: 'running') — task picked up by a worker\n   * - `task.completed` (status: 'completed') — task finished successfully\n   * - `task.failed` (status: 'failed' or 'timed_out') — task errored or timed out\n   * - `task.cancelled` (status: 'cancelled') — task was cancelled\n   * - `task.suspended` (status: 'suspended') — task paused via `suspend()` from\n   *   inside its tool executor; resume with `manager.resume(taskId, data)`\n   * - `task.resumed` (status: 'running') — suspended task resumed\n   *\n   * The stream stays open until the caller's AbortSignal fires (client disconnect).\n   */\n  stream(options?: {\n    agentId?: string;\n    runId?: string;\n    threadId?: string;\n    resourceId?: string;\n    taskId?: string;\n    abortSignal?: AbortSignal;\n  }): ReadableStream<Record<string, unknown>> {\n    const manager = this;\n    const pubsub = this.pubsub;\n    const { agentId, runId, threadId, resourceId, abortSignal, taskId } = options ?? {};\n\n    const EVENT_STATUS_MAP: Record<string, BackgroundTaskStatus> = {\n      'task.running': 'running',\n      'task.output': 'running',\n      'task.completed': 'completed',\n      'task.failed': 'failed',\n      'task.cancelled': 'cancelled',\n      'task.suspended': 'suspended',\n      'task.resumed': 'running',\n    };\n\n    const CHUNK_EVENT_MAP: Record<string, string> = {\n      'task.running': 'background-task-running',\n      'task.output': 'background-task-output',\n      'task.completed': 'background-task-completed',\n      'task.failed': 'background-task-failed',\n      'task.cancelled': 'background-task-cancelled',\n      'task.suspended': 'background-task-suspended',\n      'task.resumed': 'background-task-resumed',\n    };\n\n    return new ReadableStream({\n      async start(controller) {\n        // 1. Subscribe to live events first (so we don't miss anything between snapshot and subscribe)\n        const handler = async (event: Event) => {\n          const status = EVENT_STATUS_MAP[event.type];\n          if (!status) return;\n\n          const data = event.data;\n          if (agentId && data.agentId !== agentId) return;\n          if (runId && data.runId !== runId) return;\n          if (threadId && data.threadId !== threadId) return;\n          if (resourceId && data.resourceId !== resourceId) return;\n          if (taskId && data.taskId !== taskId) return;\n\n          const payload: Record<string, unknown> = {\n            taskId: data.taskId,\n            toolName: data.toolName,\n            toolCallId: data.toolCallId,\n            agentId: data.agentId,\n            runId: data.runId,\n          };\n\n          switch (event.type) {\n            case 'task.running':\n              payload.startedAt = data.startedAt;\n              payload.args = data.args;\n              break;\n            case 'task.completed':\n              payload.completedAt = data.completedAt;\n              payload.result = data.result;\n              break;\n            case 'task.failed':\n              payload.completedAt = data.completedAt;\n              payload.error = data.error;\n              break;\n            case 'task.cancelled':\n              payload.completedAt = data.completedAt;\n              break;\n            case 'task.output':\n              payload.payload = data.chunk;\n              break;\n            case 'task.suspended':\n              payload.suspendPayload = data.suspendPayload;\n              payload.suspendedAt = data.suspendedAt;\n              payload.args = data.args;\n              break;\n            case 'task.resumed':\n              payload.startedAt = data.startedAt;\n              payload.args = data.args;\n              break;\n          }\n\n          try {\n            controller.enqueue({\n              type: CHUNK_EVENT_MAP[event.type],\n              payload,\n            });\n          } catch {\n            // Controller closed\n          }\n        };\n\n        void pubsub.subscribe(TOPIC_RESULT, handler);\n\n        abortSignal?.addEventListener('abort', () => {\n          void pubsub.unsubscribe(TOPIC_RESULT, handler);\n          try {\n            controller.close();\n          } catch {\n            // Already closed\n          }\n        });\n\n        // 2. Emit snapshot of existing in-flight tasks (running + suspended).\n        try {\n          const storage = await manager.getStorage();\n          if (taskId) {\n            const task = await storage.getTask(taskId);\n            if (task && task.status === 'running') {\n              controller.enqueue({\n                type: 'background-task-running',\n                payload: {\n                  taskId: task.id,\n                  toolName: task.toolName,\n                  toolCallId: task.toolCallId,\n                  agentId: task.agentId,\n                  runId: task.runId,\n                  startedAt: task.startedAt,\n                  args: task.args,\n                },\n              });\n            }\n          } else {\n            const { tasks: existing } = await storage.listTasks({\n              agentId,\n              runId,\n              threadId,\n              resourceId,\n              status: ['running'],\n            });\n\n            for (const task of existing) {\n              if (abortSignal?.aborted) break;\n              try {\n                controller.enqueue({\n                  type: 'background-task-running',\n                  payload: {\n                    taskId: task.id,\n                    toolName: task.toolName,\n                    toolCallId: task.toolCallId,\n                    agentId: task.agentId,\n                    runId: task.runId,\n                    startedAt: task.startedAt,\n                    args: task.args,\n                  },\n                });\n              } catch {\n                break;\n              }\n            }\n          }\n        } catch {\n          // Storage not available — continue with live events only\n        }\n      },\n    });\n  }\n\n  async shutdown(): Promise<void> {\n    this.shuttingDown = true;\n\n    if (this.cleanupInterval) {\n      clearInterval(this.cleanupInterval);\n      this.cleanupInterval = undefined;\n    }\n\n    if (this.workerCallback) {\n      await this.pubsub.unsubscribe(TOPIC_DISPATCH, this.workerCallback);\n    }\n    if (this.resultCallback) {\n      await this.pubsub.unsubscribe(TOPIC_RESULT, this.resultCallback);\n    }\n\n    this.taskContexts.clear();\n    await this.pubsub.flush();\n  }\n\n  // --- Internal ---\n\n  /**\n   * Lazily start Mastra's execution workers before publishing. In \"library\n   * mode\" nothing ever calls `mastra.startWorkers()`, so the evented\n   * `__background-task` workflow started by `handleDispatch` would publish\n   * to the `workflows` topic with no consumer and the task would sit at\n   * `running` forever (#19339). A no-op once workers are running; honors the\n   * `workers: false` / `MASTRA_WORKERS` opt-outs.\n   *\n   * Startup failures are logged but don't abort the publish — in distributed\n   * topologies a remote worker on the shared broker can still pick the task\n   * up, and throwing here would also abort `drainPending()` /\n   * `recoverStaleTasks()` loops.\n   */\n  async #ensureExecutionWorkersStarted(): Promise<void> {\n    if (!this.#mastra) return;\n    try {\n      await this.#mastra.__ensureExecutionWorkersStarted();\n    } catch (err) {\n      this.#mastra.getLogger?.()?.error('Failed to start execution workers for background task', err as any);\n    }\n  }\n\n  private async dispatch(task: BackgroundTask, isRestart?: boolean): Promise<void> {\n    await this.#ensureExecutionWorkersStarted();\n\n    // Publish `task.dispatch` on `TOPIC_DISPATCH` with `WORKER_GROUP`, so\n    // exactly one worker handles the task. `handleDispatch` flips the\n    // task to running and starts the per-task workflow run.\n    await this.pubsub.publish(TOPIC_DISPATCH, {\n      type: 'task.dispatch',\n      data: {\n        taskId: task.id,\n        toolName: task.toolName,\n        toolCallId: task.toolCallId,\n        args: task.args,\n        agentId: task.agentId,\n        threadId: task.threadId,\n        resourceId: task.resourceId,\n        timeoutMs: task.timeoutMs,\n        maxRetries: task.maxRetries,\n        runId: task.runId,\n        isRestart,\n      },\n      runId: task.id,\n    });\n  }\n\n  /**\n   * Handles a task.dispatch and task.restart events.\n   * Both events are similar, but the latter is used to restart a running task.\n   */\n  private async handleDispatch(event: Event): Promise<void> {\n    const { taskId, isRestart } = event.data;\n    const deliveryAttempt = event.deliveryAttempt ?? 1;\n\n    const storage = await this.getStorage();\n    const task = await storage.getTask(taskId);\n    if (!task || task.status === 'cancelled') {\n      this.deregisterTaskContext(taskId);\n      return;\n    }\n\n    if (isRestart && task.status !== 'running') {\n      // Either gone or already done/cancelled by another worker. Drop the\n      // event silently — the worker group ensures exactly-once delivery, but\n      // the task may have moved on between publish and pickup.\n      return;\n    }\n\n    await storage.updateTask(taskId, { status: 'running', startedAt: new Date(), retryCount: deliveryAttempt - 1 });\n\n    // Publish running lifecycle event (fan-out, for stream consumers)\n    const runningTask = await storage.getTask(taskId);\n    if (runningTask) await this.publishLifecycleEvent('task.running', runningTask);\n\n    // Fire-and-forget the workflow run; the workflow step body owns\n    // executor invocation, retries, and suspend/resume. The local\n    // execution hook still runs here so callers see `onExecution` fire.\n    if (this.#mastra) {\n      if (runningTask) void this.runLocalExecutionHook(runningTask);\n      const workflow = this.#mastra.__getInternalWorkflow(BACKGROUND_TASK_WORKFLOW_ID);\n      const prevWorkflowRun = isRestart ? await workflow.getWorkflowRunById(taskId) : undefined;\n      const shouldRestart = isRestart && prevWorkflowRun?.status === 'running';\n      const run = await workflow.createRun({ runId: taskId });\n      const runPromise = shouldRestart ? run.restart() : run.start({ inputData: { taskId } });\n      void runPromise\n        .then(result => {\n          if (result.status !== 'suspended') {\n            void workflow.deleteWorkflowRunById(taskId);\n          }\n        })\n        .catch(err => {\n          this.#mastra\n            ?.getLogger?.()\n            ?.error(`background-task workflow ${shouldRestart ? 'restart' : 'start'} failed for ${taskId}:`, err);\n        })\n        .finally(() => {\n          // Free the concurrency slot once the run terminates.\n          void this.drainPending();\n        });\n    }\n  }\n\n  /**\n   * Handles a task.resume event. Mirrors the workflow branch of handleDispatch\n   * but resumes an existing run from its suspended snapshot instead of starting\n   * a fresh one. Concurrency gating, suspended-status validation, and the\n   * `task.resumed` lifecycle publish all happen here so a different process\n   * than the one that suspended the task can drive the resume.\n   */\n  private async handleResume(event: Event): Promise<void> {\n    const { taskId, resumeData } = event.data;\n\n    const storage = await this.getStorage();\n    const task = await storage.getTask(taskId);\n    if (!task || task.status !== 'suspended') {\n      // Either gone or already resumed/cancelled by another worker. Drop the\n      // event silently — the worker group ensures exactly-once delivery, but\n      // the task may have moved on between publish and pickup.\n      return;\n    }\n\n    await storage.updateTask(taskId, {\n      status: 'running',\n      startedAt: new Date(),\n      suspendPayload: undefined,\n      suspendedAt: undefined,\n    });\n    const resumedTask = await storage.getTask(taskId);\n    if (resumedTask) {\n      await this.publishLifecycleEvent('task.resumed', resumedTask);\n    }\n\n    if (!this.#mastra) return;\n    const workflow = this.#mastra.__getInternalWorkflow(BACKGROUND_TASK_WORKFLOW_ID);\n    // `createRun({ runId })` reattaches to the existing snapshot when given a\n    // stable runId — we don't want a fresh run.\n    const run = await workflow.createRun({ runId: taskId });\n    void run\n      .resume({ resumeData })\n      .then(result => {\n        if (result.status !== 'suspended') {\n          void workflow.deleteWorkflowRunById(taskId);\n        }\n      })\n      .catch(err => {\n        this.#mastra?.getLogger?.()?.error(`background-task workflow resume failed for ${taskId}:`, err);\n      })\n      .finally(() => {\n        // Mirror dispatch's drain — resuming frees a slot when it terminates.\n        void this.drainPending();\n      });\n  }\n\n  /**\n   * Run per-task hooks (onChunk, onResult, onComplete/onFailed) locally in the\n   * worker path, before publishing the terminal lifecycle event. Ensures\n   * memory / stream state is consistent by the time any pubsub subscriber is\n   * notified. After running, the task context is deregistered so\n   * `handleResult` (which also fires from pubsub) becomes a no-op for this\n   * task in the same process.\n   *\n   * In distributed deployments where the worker runs in a different process\n   * from the dispatcher, `this.taskContexts` won't contain an entry for\n   * `task.id` — this method is a no-op there, and `handleResult` in the\n   * dispatching process runs the hooks instead.\n   */\n  /**\n   * Terminal-state hooks only. Called when a task reaches `'completed'` or\n   * `'failed'`. Suspend is non-terminal — see `runLocalSuspendHooks` for that\n   * path.\n   *\n   * @internal — also called by the workflow-engine step bodies in workflow.ts\n   */\n  async runLocalCompletionHooks(\n    task: BackgroundTask,\n    status: 'completed' | 'failed',\n    extras: { result?: unknown; error?: { message: string; stack?: string } },\n  ): Promise<void> {\n    const ctx = this.taskContexts.get(task.id);\n    if (!ctx) return;\n\n    try {\n      if (status === 'completed') {\n        ctx.onChunk?.({\n          type: 'background-task-completed',\n          payload: {\n            taskId: task.id,\n            toolName: task.toolName,\n            toolCallId: task.toolCallId,\n            runId: task.runId,\n            result: extras.result,\n            completedAt: task.completedAt!,\n            agentId: task.agentId,\n          },\n        });\n\n        await ctx.onResult?.({\n          runId: task.runId,\n          taskId: task.id,\n          toolCallId: task.toolCallId,\n          toolName: task.toolName,\n          agentId: task.agentId,\n          threadId: task.threadId,\n          resourceId: task.resourceId,\n          result: extras.result,\n          status: 'completed',\n          completedAt: task.completedAt!,\n          startedAt: task.startedAt!,\n        });\n\n        // Globals (this.config.onTaskComplete / onTaskFailed) fire from\n        // handleResult via pubsub so they run once per subscribing process\n        // — in distributed deployments that's the dispatching process, which\n        // is where observers/metrics are typically wired.\n        await ctx.onComplete?.(task);\n      } else {\n        ctx.onChunk?.({\n          type: 'background-task-failed',\n          payload: {\n            taskId: task.id,\n            toolName: task.toolName,\n            toolCallId: task.toolCallId,\n            runId: task.runId,\n            error: extras.error ?? { message: 'Unknown error' },\n            completedAt: task.completedAt!,\n            agentId: task.agentId,\n          },\n        });\n\n        await ctx.onResult?.({\n          runId: task.runId,\n          taskId: task.id,\n          toolCallId: task.toolCallId,\n          toolName: task.toolName,\n          agentId: task.agentId,\n          threadId: task.threadId,\n          resourceId: task.resourceId,\n          error: extras.error,\n          status: 'failed',\n          completedAt: task.completedAt!,\n          startedAt: task.startedAt!,\n        });\n\n        // See comment above — globals are handled exclusively by\n        // handleResult so they fire once per subscribing process.\n        await ctx.onFailed?.(task);\n      }\n    } finally {\n      this.deregisterTaskContext(task.id);\n    }\n  }\n\n  /**\n   * Per-task suspend hooks. Fires `ctx.onResult({ status: 'suspended', ... })`\n   * so the message list / memory pick up the suspension as the tool's\n   * current invocation state. Does NOT deregister the task context — resume\n   * needs the executor closure intact.\n   *\n   * @internal — called by the workflow-engine step bodies in workflow.ts\n   */\n  async runLocalSuspendHooks(task: BackgroundTask): Promise<void> {\n    const ctx = this.taskContexts.get(task.id);\n    if (!ctx) return;\n    await ctx.onExecution?.({\n      runId: task.runId,\n      taskId: task.id,\n      toolCallId: task.toolCallId,\n      toolName: task.toolName,\n      agentId: task.agentId,\n      threadId: task.threadId,\n      resourceId: task.resourceId,\n      startedAt: task.startedAt!,\n      suspendedAt: task.suspendedAt,\n    });\n  }\n\n  /** @internal — also called by the workflow-engine step bodies in workflow.ts */\n  async runLocalExecutionHook(task: BackgroundTask): Promise<void> {\n    const ctx = this.taskContexts.get(task.id);\n    if (!ctx) return;\n\n    try {\n      await ctx.onExecution?.({\n        runId: task.runId,\n        taskId: task.id,\n        toolCallId: task.toolCallId,\n        toolName: task.toolName,\n        agentId: task.agentId,\n        threadId: task.threadId,\n        resourceId: task.resourceId,\n        startedAt: task.startedAt!,\n      });\n    } catch {\n      //fail silently\n    }\n  }\n\n  private async handleResult(event: Event): Promise<void> {\n    const { taskId, toolName, toolCallId, threadId, resourceId, runId } = event.data;\n    const storage = await this.getStorage();\n    const task = await storage.getTask(taskId);\n\n    if (task?.completedAt) {\n      // Look up per-task hooks\n      const ctx = this.taskContexts.get(taskId);\n\n      if (event.type === 'task.completed') {\n        ctx?.onChunk?.({\n          type: 'background-task-completed',\n          payload: {\n            taskId,\n            toolName,\n            toolCallId,\n            runId,\n            result: event.data.result,\n            completedAt: task.completedAt,\n            agentId: task.agentId,\n          },\n        });\n\n        await ctx?.onResult?.({\n          runId,\n          taskId,\n          toolCallId,\n          toolName,\n          agentId: event.data.agentId,\n          threadId,\n          resourceId,\n          result: event.data.result,\n          status: 'completed',\n          completedAt: task.completedAt,\n          startedAt: task.startedAt!,\n        });\n\n        if (task) {\n          await Promise.all([ctx?.onComplete?.(task), this.config.onTaskComplete?.(task)]);\n        }\n      }\n\n      if (event.type === 'task.failed') {\n        ctx?.onChunk?.({\n          type: 'background-task-failed',\n          payload: {\n            taskId,\n            toolName,\n            toolCallId,\n            runId,\n            error: event.data.error,\n            completedAt: task.completedAt,\n            agentId: task.agentId,\n          },\n        });\n\n        await ctx?.onResult?.({\n          runId,\n          taskId,\n          toolCallId,\n          toolName,\n          agentId: event.data.agentId,\n          threadId,\n          resourceId,\n          error: event.data.error,\n          status: 'failed',\n          completedAt: task.completedAt,\n          startedAt: task.startedAt!,\n        });\n\n        if (task) {\n          await Promise.all([ctx?.onFailed?.(task), this.config.onTaskFailed?.(task)]);\n        }\n      }\n\n      // Clean up context after terminal result\n      this.deregisterTaskContext(taskId);\n    }\n  }\n\n  private handleCancel(event: Event): void {\n    const { taskId } = event.data;\n    const controller = this.activeAbortControllers.get(taskId);\n    if (controller) {\n      controller.abort(new Error('Task cancelled'));\n      this.activeAbortControllers.delete(taskId);\n    }\n    this.deregisterTaskContext(taskId);\n  }\n\n  /** @internal — also called by the workflow-engine step bodies in workflow.ts */\n  async publishLifecycleEvent(\n    type:\n      | 'task.running'\n      | 'task.completed'\n      | 'task.failed'\n      | 'task.cancelled'\n      | 'task.output'\n      | 'task.suspended'\n      | 'task.resumed',\n    task: BackgroundTaskEvent,\n  ): Promise<void> {\n    await this.pubsub.publish(TOPIC_RESULT, {\n      type,\n      data: {\n        taskId: task.id,\n        toolName: task.toolName,\n        toolCallId: task.toolCallId,\n        runId: task.runId,\n        agentId: task.agentId,\n        threadId: task.threadId,\n        resourceId: task.resourceId,\n        args: task.args,\n        result: task.result,\n        error: task.error,\n        chunk: task.chunk,\n        completedAt: task.completedAt,\n        startedAt: task.startedAt,\n        suspendPayload: task.suspendPayload,\n        suspendedAt: task.suspendedAt,\n      },\n      runId: task.id,\n    });\n  }\n\n  private async checkConcurrency(agentId: string): Promise<boolean> {\n    const storage = await this.getStorage();\n    const globalRunning = await storage.getRunningCount();\n    if (globalRunning >= this.config.globalConcurrency) {\n      return false;\n    }\n\n    const agentRunning = await storage.getRunningCountByAgent(agentId);\n    if (agentRunning >= this.config.perAgentConcurrency) {\n      return false;\n    }\n\n    return true;\n  }\n\n  private async drainPending(): Promise<void> {\n    const storage = await this.getStorage();\n    const { tasks: pending } = await storage.listTasks({\n      status: 'pending',\n      orderBy: 'createdAt',\n      orderDirection: 'asc',\n    });\n\n    for (const task of pending) {\n      if (await this.checkConcurrency(task.agentId)) {\n        await this.dispatch(task);\n      }\n    }\n  }\n\n  /**\n   * Recovers tasks left in 'running' or 'pending' state from a previous process.\n   */\n  private async recoverStaleTasks(): Promise<void> {\n    try {\n      const storage = await this.getStorage();\n      const { tasks: staleTasks } = await storage.listTasks({ status: 'running' });\n      for (const task of staleTasks) {\n        if (task.maxRetries > 0) {\n          await storage.updateTask(task.id, {\n            status: 'pending',\n            startedAt: undefined,\n          });\n        } else {\n          await storage.updateTask(task.id, {\n            status: 'failed',\n            error: { message: 'Worker process terminated before task completed' },\n            completedAt: new Date(),\n          });\n        }\n      }\n\n      const { tasks: pendingTasks } = await storage.listTasks({\n        status: 'pending',\n        orderBy: 'createdAt',\n        orderDirection: 'asc',\n      });\n      for (const task of pendingTasks) {\n        if (await this.checkConcurrency(task.agentId)) {\n          await this.dispatch(task);\n        }\n      }\n    } catch (error) {\n      const logger = this.#mastra?.getLogger();\n      if (logger) {\n        logger.error('Failed to recover stale background tasks', error);\n      }\n    }\n  }\n}\n","import type { BackgroundTaskManager } from './manager';\nimport type {\n  BackgroundTaskHandle,\n  CheckIfRunningPayload,\n  CheckIfSuspendedPayload,\n  CreateBackgroundTaskOptions,\n} from './types';\n\n/**\n * Creates a self-contained background task handle.\n *\n * Bundles the task payload with per-stream hooks (executor, onChunk, onResult)\n * so each dispatch is fully isolated — no shared mutable state on the manager.\n *\n * @example\n * ```ts\n * const bgTask = createBackgroundTask(manager, {\n *   toolName: 'research',\n *   toolCallId: 'call-1',\n *   args: { query: 'solana' },\n *   agentId: 'agent-1',\n *   runId: 'run-1',\n *   context: {\n *     executor: { execute: (args, opts) => tool.execute(args, opts) },\n *     onChunk: (chunk) => controller.enqueue(chunk),\n *     onResult: (params) => messageList.addToolResult(params),\n *   },\n * });\n *\n * const { task, fallbackToSync } = await bgTask.dispatch();\n * const completed = await bgTask.waitForCompletion();\n * await bgTask.cancel();\n * ```\n */\nexport function createBackgroundTask(\n  manager: BackgroundTaskManager,\n  options: CreateBackgroundTaskOptions,\n): BackgroundTaskHandle {\n  const { context, ...payload } = options;\n  let taskId: string | undefined;\n\n  return {\n    get task() {\n      if (!taskId) throw new Error('Task has not been dispatched yet');\n      // Synchronous access to task ID — full task data requires async getTask()\n      return { id: taskId } as any;\n    },\n\n    async dispatch() {\n      const result = await manager.enqueue(payload, context);\n      taskId = result.task.id;\n      return result;\n    },\n\n    async checkIfSuspended(args: CheckIfSuspendedPayload) {\n      const result = await manager.listTasks({\n        toolCallId: args.toolCallId,\n        runId: args.runId,\n        agentId: args.agentId,\n        threadId: args.threadId,\n        resourceId: args.resourceId,\n        toolName: args.toolName,\n        status: 'suspended',\n      });\n      if (result.total > 0) {\n        const task = result.tasks[0];\n        if (task) {\n          taskId = task.id;\n          return true;\n        }\n      }\n\n      return false;\n    },\n\n    async checkIfRunning(args: CheckIfRunningPayload) {\n      const result = await manager.listTasks({\n        toolCallId: args.toolCallId,\n        runId: args.runId,\n        agentId: args.agentId,\n        threadId: args.threadId,\n        resourceId: args.resourceId,\n        toolName: args.toolName,\n        status: 'running',\n      });\n      if (result.total > 0) {\n        const task = result.tasks[0];\n        if (task) {\n          taskId = task.id;\n          return true;\n        }\n      }\n\n      return false;\n    },\n\n    async resume(resumeData?: unknown) {\n      if (!taskId) throw new Error('Task has not been dispatched yet');\n      return manager.resume(taskId, resumeData);\n    },\n\n    async restart() {\n      if (!taskId) throw new Error('Task has not been dispatched yet');\n      return manager.restart(taskId, context);\n    },\n\n    async cancel() {\n      if (!taskId) throw new Error('Task has not been dispatched yet');\n      return manager.cancel(taskId);\n    },\n\n    async waitForCompletion(waitOptions) {\n      if (!taskId) throw new Error('Task has not been dispatched yet');\n      return manager.waitForNextTask([taskId], waitOptions);\n    },\n  };\n}\n","import type {\n  AgentBackgroundConfig,\n  AgentBackgroundToolConfig,\n  BackgroundTaskManagerConfig,\n  LLMBackgroundOverride,\n  ToolBackgroundConfig,\n} from './types';\n\nexport interface ResolvedBackgroundConfig {\n  runInBackground: boolean;\n  timeoutMs: number;\n  maxRetries: number;\n}\n\n/**\n * Resolves whether a tool call should run in the background, and with what config.\n *\n * Resolution order (highest to lowest priority):\n * 1. LLM per-call override (`_background` field in tool args)\n * 2. Agent-level backgroundTasks.tools config\n * 3. Tool-level background config\n * 4. Default: foreground\n *\n * Strips the `_background` field from args (mutates the args object).\n */\nexport function resolveBackgroundConfig({\n  llmBgOverrides,\n  toolName,\n  toolConfig,\n  agentConfig,\n  managerConfig,\n}: {\n  llmBgOverrides: Record<string, unknown>;\n  toolName: string;\n  toolConfig?: ToolBackgroundConfig;\n  agentConfig?: AgentBackgroundConfig;\n  managerConfig?: BackgroundTaskManagerConfig;\n}): ResolvedBackgroundConfig {\n  const llmOverride = llmBgOverrides as LLMBackgroundOverride | undefined;\n\n  // If this agent has background tasks disabled, short-circuit so no tool can\n  // dispatch a background task even if its own config or the LLM override\n  // would otherwise enable it. Default timeoutMs/maxRetries are still returned\n  // so callers can use the shape safely.\n  if (agentConfig?.disabled) {\n    return {\n      runInBackground: false,\n      timeoutMs: managerConfig?.defaultTimeoutMs ?? 300_000,\n      maxRetries: managerConfig?.defaultRetries?.maxRetries ?? 0,\n    };\n  }\n\n  // Resolve agent-level config for this specific tool\n  const agentToolConfig = resolveAgentToolConfig(toolName, agentConfig);\n\n  // --- enabled ---\n  // The LLM `_background` override is a modifier on tools the developer has\n  // already opted in at the tool or agent layer — it is NOT a standalone\n  // opt-in. A foreground-only tool must stay foreground regardless of what\n  // the model emits, so `agent.generate()` / `agent.stream()` keep returning\n  // real tool results for deterministic tools. See issue #16783.\n  const baseEnabled = agentToolConfig?.enabled ?? toolConfig?.enabled ?? false;\n  const enabled = baseEnabled ? (llmOverride?.enabled ?? true) : false;\n\n  // --- timeoutMs ---\n  const timeoutMs =\n    llmOverride?.timeoutMs ??\n    agentToolConfig?.timeoutMs ??\n    toolConfig?.timeoutMs ??\n    managerConfig?.defaultTimeoutMs ??\n    300_000;\n\n  // --- maxRetries ---\n  const maxRetries =\n    llmOverride?.maxRetries ?? toolConfig?.maxRetries ?? managerConfig?.defaultRetries?.maxRetries ?? 0;\n\n  return { runInBackground: enabled, timeoutMs, maxRetries };\n}\n\nfunction resolveAgentToolConfig(\n  toolName: string,\n  agentConfig?: AgentBackgroundConfig,\n): { enabled: boolean; timeoutMs?: number } | undefined {\n  if (!agentConfig?.tools) return undefined;\n\n  if (agentConfig.tools === 'all') {\n    return { enabled: true };\n  }\n\n  if (toolName.startsWith('agent-')) {\n    toolName = toolName.substring('agent-'.length);\n  } else if (toolName.startsWith('workflow-')) {\n    toolName = toolName.substring('workflow-'.length);\n  }\n\n  const entry: AgentBackgroundToolConfig | undefined = agentConfig.tools[toolName];\n  if (entry === undefined) return undefined;\n  if (typeof entry === 'boolean') return { enabled: entry };\n  return entry;\n}\n","import { z } from 'zod/v4';\n\n/**\n * JSON Schema definition for the `_background` override field.\n * Injected into background-eligible tool schemas so the LLM can override behavior per-call.\n */\nexport const backgroundOverrideJsonSchema = {\n  type: 'object' as const,\n  description:\n    'Optional: override background execution behavior for this specific call. ' +\n    'Set enabled=false to force foreground, enabled=true to force background. ' +\n    'Omit entirely to use the default configuration.',\n  properties: {\n    enabled: {\n      type: 'boolean' as const,\n      description: 'Force background (true) or foreground (false) execution for this call.',\n    },\n    timeoutMs: {\n      type: 'number' as const,\n      description: 'Override timeout in milliseconds for this call.',\n    },\n    maxRetries: {\n      type: 'number' as const,\n      description: 'Override maximum retry attempts for this call.',\n    },\n  },\n  additionalProperties: false,\n};\n\nexport const backgroundOverrideZodSchema = z\n  .object({\n    enabled: z.boolean().optional().describe('Force background (true) or foreground (false) execution for this call.'),\n    timeoutMs: z.number().optional().describe('Override timeout in milliseconds for this call.'),\n    maxRetries: z.number().optional().describe('Override maximum retry attempts for this call.'),\n  })\n  .optional()\n  .describe(\n    'Optional: override background execution behavior for this specific call. Set enabled=false to force foreground, enabled=true to force background. Omit entirely to use the default configuration.',\n  );\n","import type { AgentBackgroundConfig, ToolBackgroundConfig } from './types';\n\ninterface ToolEntry {\n  toolName: string;\n  toolConfig?: ToolBackgroundConfig;\n  /** Whether the tool defaults to background execution */\n  defaultBackground: boolean;\n}\n\n/**\n * Generates the system prompt section that tells the LLM about background task capabilities.\n *\n * Returns undefined if no tools are background-eligible (nothing to inject).\n */\nexport function generateBackgroundTaskSystemPrompt(\n  tools: Record<string, { background?: ToolBackgroundConfig; description?: string }>,\n  agentConfig?: AgentBackgroundConfig,\n): string | undefined {\n  const eligibleTools: ToolEntry[] = [];\n\n  const enableAll = agentConfig?.tools === 'all';\n\n  for (const [toolName, tool] of Object.entries(tools)) {\n    const bgEnabledFromAgentConfig =\n      agentConfig?.tools === 'all'\n        ? false\n        : typeof agentConfig?.tools?.[toolName] === 'boolean'\n          ? agentConfig.tools[toolName]\n          : (agentConfig?.tools?.[toolName]?.enabled ?? false);\n    eligibleTools.push({\n      toolName,\n      toolConfig: tool.background,\n      defaultBackground: enableAll ? true : (bgEnabledFromAgentConfig ?? tool.background?.enabled ?? false),\n    });\n  }\n\n  if (eligibleTools.length === 0) {\n    return undefined;\n  }\n\n  const toolLines = eligibleTools\n    .map(t => `- ${t.toolName} (default: ${t.defaultBackground ? 'background' : 'foreground'})`)\n    .join('\\n');\n\n  return `You have the ability to run certain tools in the background while continuing the conversation. The following tools support background execution:\n${toolLines}\n\nFor any of these tools, you can include a \"_background\" field in the tool arguments to override the default:\n  \"_background\": { \"enabled\": true/false, \"timeoutMs\": number, \"maxRetries\": number }\n\nAll fields in \"_background\" are optional. Only include what you want to override.\n\nGuidelines:\n- Use background execution when the user doesn't need the result immediately, or when you're launching multiple independent tasks.\n- Use foreground execution when the user is directly waiting for the result and the conversation can't continue without it.\n- If you don't include \"_background\", the tool's default configuration is used.\n- When a tool runs in the background, you'll receive a placeholder result with a task ID. You can reference this in your response to the user.\n\nIMPORTANT: \"_background\" field is always an object. The fields in the _background field should be inside the _background object, not outside of it.`;\n}\n"],"mappings":"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"}