{"version":3,"file":"index.cjs","names":["RoomServiceClient","RoomEgress","serializeSessionMetadata","AgentDispatchClient","AccessToken","RoomConfiguration","RoomAgentDispatch","serializeSessionMetadata","z","DEFAULT_DESCRIPTION","z","createTool","createTool","z"],"sources":["../src/recording.ts","../src/dispatch.ts","../src/routes.ts","../src/recording-route.ts","../src/consent.ts","../src/end-call.ts"],"sourcesContent":["import { RoomEgress, RoomServiceClient } from 'livekit-server-sdk';\n\n/**\n * LiveKit auto-egress settings, accepted as a plain object or a RoomEgress instance.\n * Use `room.audioOnly` and `room.fileOutputs` for a single mixed audio recording.\n * Storage credentials belong here on the server, never in session metadata or tokens.\n */\nexport type LiveKitRecordingOptions = NonNullable<ConstructorParameters<typeof RoomEgress>[0]>;\n\n/** A recording-enabled session cannot reuse an existing LiveKit room. */\nexport class LiveKitRecordingRoomConflictError extends Error {\n  readonly roomName: string;\n\n  constructor(roomName: string) {\n    super(\n      `@mastra/livekit: recording requires a new room, but room \"${roomName}\" already exists. Use a fresh room name.`,\n    );\n    this.name = 'LiveKitRecordingRoomConflictError';\n    this.roomName = roomName;\n  }\n}\n\n/** Creates a fresh room with recording configured before any agent or caller joins. */\nexport async function createRecordingRoom(options: {\n  roomName: string;\n  serverUrl: string;\n  apiKey: string;\n  apiSecret: string;\n  recording: LiveKitRecordingOptions;\n}) {\n  const { recording, roomName } = options;\n  if (!recording.room && !recording.participant && !recording.tracks) {\n    throw new Error('@mastra/livekit: recording must configure at least one of room, participant, or tracks.');\n  }\n\n  const client = new RoomServiceClient(options.serverUrl.replace(/^ws/, 'http'), options.apiKey, options.apiSecret);\n  // CreateRoom reuses existing rooms without applying room-composite auto-egress.\n  // This preflight is not atomic: callers must use a fresh name and serialize room creation.\n  const rooms = await client.listRooms([roomName]);\n  if (rooms.length > 0) {\n    throw new LiveKitRecordingRoomConflictError(roomName);\n  }\n\n  return client.createRoom({ name: roomName, egress: new RoomEgress(recording) });\n}\n","import { AgentDispatchClient } from 'livekit-server-sdk';\nimport { DEFAULT_LIVEKIT_AGENT_NAME } from './constants';\nimport { serializeSessionMetadata } from './metadata';\nimport type { LiveKitSessionMetadata } from './metadata';\nimport { createRecordingRoom } from './recording';\nimport type { LiveKitRecordingOptions } from './recording';\n\nexport interface DispatchVoiceSessionOptions {\n  /**\n   * Room to dispatch the agent into (created on demand). With recording enabled, use a unique\n   * name for each call. An existing room throws LiveKitRecordingRoomConflictError.\n   */\n  roomName: string;\n  /** Must match the worker's `agentName`. Defaults to `'mastra-voice'`. */\n  agentName?: string;\n  metadata?: LiveKitSessionMetadata;\n  /** Create a fresh room with automatic recording before dispatch. Omit to keep dispatch-only behavior. */\n  recording?: LiveKitRecordingOptions;\n  /** Defaults to `LIVEKIT_URL`. */\n  serverUrl?: string;\n  /** Defaults to `LIVEKIT_API_KEY`. */\n  apiKey?: string;\n  /** Defaults to `LIVEKIT_API_SECRET`. */\n  apiSecret?: string;\n}\n\nfunction toHttpUrl(url: string): string {\n  return url.replace(/^ws/, 'http');\n}\n\n/**\n * Programmatically dispatches a Mastra voice agent into a LiveKit room — for\n * server-initiated sessions such as outbound calls or joining an existing room.\n */\nexport async function dispatchVoiceSession(options: DispatchVoiceSessionOptions) {\n  const serverUrl = options.serverUrl ?? process.env.LIVEKIT_URL;\n  const apiKey = options.apiKey ?? process.env.LIVEKIT_API_KEY;\n  const apiSecret = options.apiSecret ?? process.env.LIVEKIT_API_SECRET;\n  if (!serverUrl) {\n    throw new Error('@mastra/livekit: set LIVEKIT_URL or pass serverUrl to dispatchVoiceSession.');\n  }\n  if (!apiKey || !apiSecret) {\n    throw new Error(\n      '@mastra/livekit: set LIVEKIT_API_KEY and LIVEKIT_API_SECRET or pass apiKey/apiSecret to dispatchVoiceSession.',\n    );\n  }\n  const metadata = serializeSessionMetadata(options.metadata ?? {});\n  if (options.recording !== undefined) {\n    await createRecordingRoom({\n      roomName: options.roomName,\n      serverUrl,\n      apiKey,\n      apiSecret,\n      recording: options.recording,\n    });\n  }\n  const client = new AgentDispatchClient(toHttpUrl(serverUrl), apiKey, apiSecret);\n  return client.createDispatch(options.roomName, options.agentName ?? DEFAULT_LIVEKIT_AGENT_NAME, {\n    metadata,\n  });\n}\n","import { RoomAgentDispatch, RoomConfiguration } from '@livekit/protocol';\nimport type { ContextWithMastra, ApiRoute } from '@mastra/core/server';\nimport { AccessToken } from 'livekit-server-sdk';\nimport { DEFAULT_LIVEKIT_AGENT_NAME } from './constants';\nimport { dispatchVoiceSession } from './dispatch';\nimport { serializeSessionMetadata } from './metadata';\nimport type { LiveKitSessionMetadata } from './metadata';\nimport { LiveKitRecordingRoomConflictError } from './recording';\nimport type { LiveKitRecordingOptions } from './recording';\n\n/** Response body of the connection-details route. Matches LiveKit's frontend starter contract. */\nexport interface LiveKitConnectionDetails {\n  serverUrl: string;\n  roomName: string;\n  participantName: string;\n  participantToken: string;\n}\n\nexport interface ConnectionRequestArgs {\n  body: Record<string, unknown>;\n  context: ContextWithMastra;\n}\n\nexport interface LiveKitConnectionRouteOptions {\n  /**\n   * Route path. Defaults to `/voice/livekit/connection-details`. Mastra reserves the\n   * `/api` prefix for built-in routes, so custom paths must not start with `/api`.\n   */\n  path?: string;\n  /** LiveKit server URL (`wss://...`). Defaults to `LIVEKIT_URL`. */\n  serverUrl?: string;\n  /** Defaults to `LIVEKIT_API_KEY`. */\n  apiKey?: string;\n  /** Defaults to `LIVEKIT_API_SECRET`. */\n  apiSecret?: string;\n  /** LiveKit agent name for explicit dispatch. Must match the worker's `agentName`. */\n  agentName?: string;\n  /** Token time-to-live. Defaults to `'15m'`. */\n  ttl?: string | number;\n  /** Defaults to `true` (Mastra custom routes require auth unless opted out). */\n  requiresAuth?: boolean;\n  /**\n   * Room name or a function that derives one from the request. Defaults to a generated name.\n   * With recording enabled, use a unique name for each call. An existing room returns HTTP 409\n   * before agent dispatch or token issuance.\n   */\n  roomName?: string | ((args: ConnectionRequestArgs) => string);\n  participantIdentity?: string | ((args: ConnectionRequestArgs) => string);\n  /**\n   * Session metadata delivered to the worker via agent dispatch. Defaults to passing\n   * through `agentId`, `threadId`, and `resourceId` from the request body.\n   */\n  metadata?: (args: ConnectionRequestArgs) => LiveKitSessionMetadata | Promise<LiveKitSessionMetadata>;\n  /**\n   * Create a fresh room with automatic recording and dispatch the agent before returning a token.\n   * The server-side callback receives the resolved room name; return undefined to skip recording.\n   * Recording settings and storage credentials are never included in the participant token.\n   */\n  recording?:\n    | LiveKitRecordingOptions\n    | ((\n        args: ConnectionRequestArgs & { roomName: string },\n      ) => LiveKitRecordingOptions | undefined | Promise<LiveKitRecordingOptions | undefined>);\n}\n\nfunction stringField(body: Record<string, unknown>, key: string): string | undefined {\n  const value = body[key];\n  return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\n/**\n * An ApiRoute for `server.apiRoutes` that mints a LiveKit access token with the Mastra\n * voice agent dispatched into the room. Frontends call it to join a voice session:\n *\n * ```ts\n * export const mastra = new Mastra({\n *   agents: { support },\n *   server: { apiRoutes: [liveKitConnectionRoute({ agentName: 'mastra-voice' })] },\n * });\n * ```\n */\nexport function liveKitConnectionRoute(options: LiveKitConnectionRouteOptions = {}): ApiRoute {\n  const handler = async (c: ContextWithMastra) => {\n    const serverUrl = options.serverUrl ?? process.env.LIVEKIT_URL;\n    const apiKey = options.apiKey ?? process.env.LIVEKIT_API_KEY;\n    const apiSecret = options.apiSecret ?? process.env.LIVEKIT_API_SECRET;\n    if (!serverUrl || !apiKey || !apiSecret) {\n      return c.json(\n        {\n          error:\n            'LiveKit is not configured. Set LIVEKIT_URL, LIVEKIT_API_KEY, and LIVEKIT_API_SECRET ' +\n            '(or pass serverUrl/apiKey/apiSecret to liveKitConnectionRoute).',\n        },\n        500,\n      );\n    }\n\n    const body: Record<string, unknown> = await c.req\n      .json()\n      .then((parsed: unknown) =>\n        parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? (parsed as Record<string, unknown>) : {},\n      )\n      .catch(() => ({}));\n    const args: ConnectionRequestArgs = { body, context: c };\n\n    const metadata: LiveKitSessionMetadata = options.metadata\n      ? await options.metadata(args)\n      : {\n          agentId: stringField(body, 'agentId'),\n          threadId: stringField(body, 'threadId'),\n          resourceId: stringField(body, 'resourceId'),\n        };\n\n    const roomName =\n      typeof options.roomName === 'function'\n        ? options.roomName(args)\n        : (options.roomName ?? `mastra-voice-${globalThis.crypto.randomUUID().slice(0, 8)}`);\n    const identity =\n      typeof options.participantIdentity === 'function'\n        ? options.participantIdentity(args)\n        : (options.participantIdentity ?? metadata.resourceId ?? `user-${globalThis.crypto.randomUUID().slice(0, 8)}`);\n    // One memory thread per room unless the caller pins a thread explicitly.\n    metadata.threadId ??= roomName;\n\n    const recording =\n      typeof options.recording === 'function' ? await options.recording({ ...args, roomName }) : options.recording;\n    if (recording !== undefined) {\n      try {\n        await dispatchVoiceSession({\n          roomName,\n          agentName: options.agentName,\n          metadata,\n          serverUrl,\n          apiKey,\n          apiSecret,\n          recording,\n        });\n      } catch (error) {\n        if (error instanceof LiveKitRecordingRoomConflictError) {\n          return c.json({ error: 'Recording requires a new room. Use a unique roomName for each call.' }, 409);\n        }\n        throw error;\n      }\n    }\n\n    const token = new AccessToken(apiKey, apiSecret, { identity, ttl: options.ttl ?? '15m' });\n    token.addGrant({\n      room: roomName,\n      roomJoin: true,\n      canPublish: true,\n      canSubscribe: true,\n      canPublishData: true,\n      canUpdateOwnMetadata: true,\n    });\n    // A pre-created room needs explicit dispatch; token roomConfig only applies at room creation.\n    if (recording === undefined) {\n      token.roomConfig = new RoomConfiguration({\n        agents: [\n          new RoomAgentDispatch({\n            agentName: options.agentName ?? DEFAULT_LIVEKIT_AGENT_NAME,\n            metadata: serializeSessionMetadata(metadata),\n          }),\n        ],\n      });\n    }\n\n    const details: LiveKitConnectionDetails = {\n      serverUrl,\n      roomName,\n      participantName: identity,\n      participantToken: await token.toJwt(),\n    };\n    return c.json(details);\n  };\n\n  return {\n    // Studio calls this default path and /api/system/packages reports it — change all three together.\n    path: options.path ?? '/voice/livekit/connection-details',\n    method: 'POST',\n    requiresAuth: options.requiresAuth,\n    handler,\n  } as ApiRoute;\n}\n","import type { ApiRoute, ContextWithMastra } from '@mastra/core/server';\nimport type { SpanRecord } from '@mastra/core/storage';\nimport { z } from 'zod/v4';\nimport type { LiveKitRecording, LiveKitRecordingResponse } from './recording-types';\n\nconst traceIdSchema = z.string().min(1).max(256);\nexport const recordingSchema = z.object({\n  url: z.url({ protocol: /^https?$/ }),\n  expiresAt: z.string().datetime().optional(),\n}) satisfies z.ZodType<LiveKitRecording>;\n\nexport interface LiveKitRecordingResolverArgs {\n  traceId: string;\n  /** Taken from the stored voice call span, never from the browser request. */\n  roomName: string;\n  span: SpanRecord;\n  context: ContextWithMastra;\n}\n\nexport interface LiveKitRecordingRouteOptions {\n  /** Studio discovers this route at its default path: /voice/livekit/recordings/:traceId. */\n  path?: string;\n  /** Defaults to true. Only disable for a local demo. */\n  requiresAuth?: boolean;\n  /** Required trace-specific access policy. Only true permits trace lookup and URL resolution. */\n  authorize: (args: { traceId: string; context: ContextWithMastra }) => boolean | Promise<boolean>;\n  /** Return a playable URL, or undefined if the recording is not available yet. */\n  resolveRecording: (args: LiveKitRecordingResolverArgs) => Promise<LiveKitRecording | undefined>;\n}\n\n/** Resolves a voice call trace to a recording without persisting signed URLs in traces. */\nexport function liveKitRecordingRoute(options: LiveKitRecordingRouteOptions): ApiRoute {\n  if (typeof options.authorize !== 'function') {\n    throw new Error('liveKitRecordingRoute requires an authorize callback.');\n  }\n  return {\n    path: options.path ?? '/voice/livekit/recordings/:traceId',\n    method: 'GET',\n    requiresAuth: options.requiresAuth ?? true,\n    handler: async (context: ContextWithMastra) => {\n      context.header('Cache-Control', 'no-store');\n      const input = traceIdSchema.safeParse(context.req.param('traceId'));\n      if (!input.success) return context.json({ error: 'A valid trace ID is required.' }, 400);\n      const traceId = input.data;\n      try {\n        if ((await options.authorize({ traceId, context })) !== true) {\n          return context.json({ error: 'Access to this recording is denied.' }, 403);\n        }\n        const store = await context.get('mastra').getStorage()?.getStore('observability');\n        if (!store) return context.json({ error: 'Trace storage is not configured.' }, 503);\n        const trace = await store.getTrace({ traceId });\n        const calls =\n          trace?.spans.filter(\n            span =>\n              span.name === 'voice call' &&\n              typeof span.metadata?.roomName === 'string' &&\n              span.metadata.roomName.length > 0,\n          ) ?? [];\n        if (!calls.length) return context.json({ error: 'Voice call trace not found.' }, 404);\n        if (calls.length !== 1) return context.json({ error: 'This trace contains multiple voice calls.' }, 409);\n        const span = calls[0]!;\n        const roomName = span.metadata?.roomName;\n        if (typeof roomName !== 'string') return context.json({ error: 'Voice call trace not found.' }, 404);\n        const recording = await options.resolveRecording({ traceId, roomName, span, context });\n        if (!recording) return context.json({ status: 'unavailable' } satisfies LiveKitRecordingResponse);\n        // Validate and strip extra fields so storage credentials cannot accidentally become response fields.\n        const result = recordingSchema.safeParse(recording);\n        if (!result.success) return context.json({ error: 'Unable to load the call recording.' }, 502);\n        return context.json({ status: 'ready', ...result.data } satisfies LiveKitRecordingResponse);\n      } catch {\n        // Storage/provider errors can contain credentials or signed request details.\n        return context.json({ error: 'Unable to load the call recording.' }, 502);\n      }\n    },\n  };\n}\n","// Server-safe: only depends on `@mastra/core` + zod, never the `@livekit/agents` runtime — so it\n// can be added to agents defined in server/shared code and re-exported from the root entry\n// (`index.ts`). `index.test.ts` enforces that boundary.\nimport { createTool } from '@mastra/core/tools';\nimport { z } from 'zod';\n\n/** A consent decision captured from the caller during a call. */\nexport interface ConsentGrant {\n  /**\n   * The consent item, matching a key in the worker's `configuration.consentPolicy` (e.g.\n   * `'summaryStorage'`).\n   */\n  item: string;\n  /** `true` if the caller agreed, `false` if they declined. */\n  granted: boolean;\n  /** The caller the grant belongs to (the memory `resource`), when the call is memory-scoped. */\n  resourceId?: string;\n  /** The call thread the grant was captured on, when the call is memory-scoped. */\n  threadId?: string;\n}\n\nexport interface ConsentToolOptions {\n  /**\n   * Persist the caller's decision to YOUR system of record (database, CRM, consent ledger). Called\n   * each time the caller answers a consent question — keep it quick, it runs inside the turn. This\n   * tool owns extracting the caller's identity from the tool execution context; you own storage, so\n   * consent lives in a durable, compliant place rather than an opaque plugin store. Read those\n   * grants back at `onCallEnd` (or before any consent-gated step) to enforce the requirement.\n   */\n  onGrant: (grant: ConsentGrant) => void | Promise<void>;\n  /** Tool id the agent calls. Defaults to `'recordConsent'`. */\n  id?: string;\n  /** Override the description the model sees when deciding to call the tool. */\n  description?: string;\n  /** Restrict the accepted consent items to this set (becomes an enum). Defaults to any string. */\n  items?: readonly string[];\n}\n\nconst DEFAULT_DESCRIPTION =\n  \"Record the caller's consent decision for a data-processing item (for example, storing a summary \" +\n  'of the call). Call this as soon as the caller answers a consent question: granted = true if they ' +\n  'agree, false if they decline. Do not proceed with an activity that requires consent until you ' +\n  'have recorded the caller granting it.';\n\n/**\n * Builds a Mastra tool that captures the caller's consent decisions at runtime — the companion to\n * the worker's `configuration.consentPolicy`, which only DECLARES which consents a call needs. Add\n * it to the agent that answers the call; on each call the tool reads the caller's `resourceId` /\n * `threadId` from its execution context and hands the decision to your `onGrant` store. The runtime\n * grants live only where `onGrant` put them: enforce consent by reading them back from your own\n * store — at `onCallEnd` or before any consent-gated action — cross-checking against the declared\n * requirements in `VoiceCallEndArgs.configuration.consentPolicy` (the configuration carries the\n * policy, never the grants).\n *\n * ```ts\n * // agent tools\n * recordConsent: createConsentTool({\n *   items: ['summaryStorage'],\n *   onGrant: async ({ item, granted, resourceId }) => {\n *     if (resourceId) await db.saveConsent(resourceId, item, granted);\n *   },\n * }),\n * ```\n */\nexport function createConsentTool(options: ConsentToolOptions) {\n  const items = options.items;\n  const itemSchema = items && items.length > 0 ? z.enum([...items] as [string, ...string[]]) : z.string();\n  return createTool({\n    id: options.id ?? 'recordConsent',\n    description: options.description ?? DEFAULT_DESCRIPTION,\n    inputSchema: z.object({\n      item: itemSchema.describe(\n        \"The consent item the caller is answering for (matches the deployment's required consents).\",\n      ),\n      granted: z.boolean().describe('True if the caller agreed, false if they declined.'),\n    }),\n    execute: async ({ item, granted }, { agent }) => {\n      await options.onGrant({ item, granted, resourceId: agent?.resourceId, threadId: agent?.threadId });\n      return { recorded: true as const, item, granted };\n    },\n  });\n}\n","// Server-safe: only depends on `@mastra/core` + zod, never the `@livekit/agents` runtime — so it\n// can be added to agents defined in server/shared code and re-exported from the root entry\n// (`index.ts`). `index.test.ts` enforces that boundary.\nimport { createTool } from '@mastra/core/tools';\nimport { z } from 'zod';\n\n/** Details of the agent's decision to end the call, handed to {@link EndCallToolOptions.onEndCall}. */\nexport interface EndCallRequest {\n  /** Short reason the agent gave for ending the call, if any (e.g. \"caller said goodbye\"). */\n  reason?: string;\n  /** The caller the call belongs to (the memory `resource`), when the call is memory-scoped. */\n  resourceId?: string;\n  /** The call thread, when the call is memory-scoped. */\n  threadId?: string;\n}\n\nexport interface EndCallToolOptions {\n  /**\n   * Tool id the agent calls to end the call. Must match the worker's\n   * `configuration.endCall.tool` (both default to `'endCall'`), since that's the name the worker\n   * watches for to hang up.\n   */\n  id?: string;\n  /** Override the description the model sees when deciding to call the tool. */\n  description?: string;\n  /**\n   * Optional bookkeeping hook, called when the agent invokes the tool (records the reason, marks\n   * the call resolved in your CRM, …). Runs inside the turn — keep it quick. It does NOT hang up\n   * the call; the worker does that once the agent's final words finish playing. The tool reads the\n   * caller's identity from its execution context and passes it here.\n   */\n  onEndCall?: (request: EndCallRequest) => void | Promise<void>;\n}\n\nconst DEFAULT_DESCRIPTION =\n  'End the phone call. Call this only after you have said goodbye and there is nothing left to do — ' +\n  'for example the caller says goodbye, or the task is complete and you have wrapped up. Say your ' +\n  'closing line first, then call this as your final action; the call hangs up once your words finish ' +\n  'playing. Your closing line must be a final statement, never a question — if you are asking the ' +\n  'caller anything (for example whether they need anything else), do NOT call this in that reply; ' +\n  'wait for their answer. Do not call it if the caller still needs something.';\n\n/**\n * Builds a Mastra tool the agent calls to end the call itself (say goodbye → hang up). It is the\n * agent-visible half of agent-initiated hang-up: the tool only SIGNALS intent (and runs optional\n * bookkeeping) — it can't reach the LiveKit room from inside `agent.stream()`. The worker owns the\n * hang-up: with `configuration.endCall` set, it watches each turn for this tool, waits for the\n * agent's closing words to finish playing, then disconnects (running `onCallEnd` on the way out).\n * Keeping the tool inside the single agent means it stays visible/editable in Studio and works on\n * the agent and workflow reply paths alike.\n *\n * ```ts\n * // agent tools\n * endCall: createEndCallTool({\n *   onEndCall: ({ reason, resourceId }) => log.info('agent ended call', { reason, resourceId }),\n * }),\n * // worker\n * createLiveKitWorker({ mastra, agent: 'support', configuration: { endCall: {} } });\n * ```\n */\nexport function createEndCallTool(options: EndCallToolOptions = {}) {\n  return createTool({\n    id: options.id ?? 'endCall',\n    description: options.description ?? DEFAULT_DESCRIPTION,\n    inputSchema: z.object({\n      reason: z\n        .string()\n        .nullish()\n        .describe('Short reason the call is ending, e.g. \"caller said goodbye\" or \"task complete\".'),\n    }),\n    outputSchema: z.object({ ended: z.boolean() }),\n    execute: async ({ reason }, { agent }) => {\n      try {\n        await options.onEndCall?.({\n          reason: reason ?? undefined,\n          resourceId: agent?.resourceId,\n          threadId: agent?.threadId,\n        });\n      } catch (error) {\n        // Bookkeeping is best-effort — the tool must still signal `{ ended: true }` so the worker's\n        // end-call detector runs and the call actually hangs up.\n        console.warn('@mastra/livekit: onEndCall hook threw', error);\n      }\n      return { ended: true as const };\n    },\n  });\n}\n"],"mappings":"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"}