{"version":3,"sources":["../../src/errors.ts","../../src/utils/rate-limit-tracker.ts","../../src/utils/retry.ts","../../src/graphql/client.ts","../../src/graphql/mutations/audio.ts","../../src/graphql/mutations/transcripts.ts","../../src/graphql/mutations/users.ts","../../src/helpers/pagination.ts","../../src/graphql/queries/ai-apps.ts","../../src/graphql/queries/bites.ts","../../src/graphql/queries/meetings.ts","../../src/helpers/action-items.ts","../../src/helpers/action-items-format.ts","../../src/helpers/batch.ts","../../src/helpers/domain-utils.ts","../../src/helpers/markdown.ts","../../src/helpers/export-formats.ts","../../src/helpers/meeting-insights.ts","../../src/helpers/search.ts","../../src/graphql/queries/transcripts.ts","../../src/graphql/queries/users.ts","../../src/realtime/client.ts","../../src/realtime/stream.ts","../../src/realtime/api.ts","../../src/client.ts","../../src/webhooks/verify.ts","../../src/webhooks/parse.ts","../../src/middleware/core.ts","../../src/middleware/express.ts"],"names":["delay","sleep","DEFAULT_OPTIONS","formatDate","getParticipantNames","groupSentencesBySpeaker","formatTimestamp","DEFAULT_TIMEOUT","io","createHmac","timingSafeEqual"],"mappings":"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","file":"express.cjs","sourcesContent":["/**\n * Base error class for all Fireflies API errors.\n * All errors include a code for programmatic handling.\n */\nexport class FirefliesError extends Error {\n  readonly code: string = 'FIREFLIES_ERROR';\n  readonly status?: number;\n\n  constructor(message: string, options?: { status?: number; cause?: unknown }) {\n    super(message, { cause: options?.cause });\n    this.name = 'FirefliesError';\n    this.status = options?.status;\n  }\n}\n\n/**\n * Thrown when the API key is invalid or missing.\n */\nexport class AuthenticationError extends FirefliesError {\n  override readonly code = 'AUTHENTICATION_ERROR';\n\n  constructor(message = 'Invalid or missing API key') {\n    super(message, { status: 401 });\n    this.name = 'AuthenticationError';\n  }\n}\n\n/**\n * Thrown when rate limits are exceeded.\n * Check retryAfter for suggested wait time in milliseconds.\n */\nexport class RateLimitError extends FirefliesError {\n  override readonly code = 'RATE_LIMIT_ERROR';\n  /** Suggested wait time in milliseconds before retrying. */\n  readonly retryAfter?: number;\n\n  constructor(message = 'Rate limit exceeded', retryAfter?: number) {\n    super(message, { status: 429 });\n    this.name = 'RateLimitError';\n    this.retryAfter = retryAfter;\n  }\n}\n\n/**\n * Thrown when a requested resource is not found.\n */\nexport class NotFoundError extends FirefliesError {\n  override readonly code = 'NOT_FOUND';\n\n  constructor(message = 'Resource not found') {\n    super(message, { status: 404 });\n    this.name = 'NotFoundError';\n  }\n}\n\n/**\n * Thrown when request validation fails.\n */\nexport class ValidationError extends FirefliesError {\n  override readonly code = 'VALIDATION_ERROR';\n\n  constructor(message: string) {\n    super(message, { status: 400 });\n    this.name = 'ValidationError';\n  }\n}\n\n/**\n * Thrown when the GraphQL API returns errors.\n */\nexport class GraphQLError extends FirefliesError {\n  override readonly code = 'GRAPHQL_ERROR';\n  readonly errors: GraphQLErrorDetail[];\n\n  constructor(message: string, errors: GraphQLErrorDetail[]) {\n    super(message);\n    this.name = 'GraphQLError';\n    this.errors = errors;\n  }\n}\n\n/**\n * Detail from a GraphQL error response.\n */\nexport interface GraphQLErrorDetail {\n  message: string;\n  path?: string[];\n  extensions?: Record<string, unknown>;\n}\n\n/**\n * Thrown when a request times out.\n */\nexport class TimeoutError extends FirefliesError {\n  override readonly code = 'TIMEOUT_ERROR';\n\n  constructor(message = 'Request timed out') {\n    super(message, { status: 408 });\n    this.name = 'TimeoutError';\n  }\n}\n\n/**\n * Thrown when a network error occurs.\n */\nexport class NetworkError extends FirefliesError {\n  override readonly code = 'NETWORK_ERROR';\n\n  constructor(message: string, cause?: unknown) {\n    super(message, { cause });\n    this.name = 'NetworkError';\n  }\n}\n\n/**\n * Base error for realtime operations.\n */\nexport class RealtimeError extends FirefliesError {\n  override readonly code: string = 'REALTIME_ERROR';\n\n  constructor(message: string, options?: { cause?: unknown }) {\n    super(message, options);\n    this.name = 'RealtimeError';\n  }\n}\n\n/**\n * Thrown when realtime connection fails.\n */\nexport class ConnectionError extends RealtimeError {\n  override readonly code = 'CONNECTION_ERROR';\n\n  constructor(message = 'Failed to establish realtime connection', options?: { cause?: unknown }) {\n    super(message, options);\n    this.name = 'ConnectionError';\n  }\n}\n\n/**\n * Thrown when stream is accessed after close.\n */\nexport class StreamClosedError extends RealtimeError {\n  override readonly code = 'STREAM_CLOSED';\n\n  constructor(message = 'Stream has been closed') {\n    super(message);\n    this.name = 'StreamClosedError';\n  }\n}\n\n/**\n * Thrown when webhook signature verification fails.\n */\nexport class WebhookVerificationError extends FirefliesError {\n  override readonly code = 'WEBHOOK_VERIFICATION_FAILED';\n\n  constructor(message: string) {\n    super(message, { status: 401 });\n    this.name = 'WebhookVerificationError';\n  }\n}\n\n/**\n * Thrown when webhook payload parsing fails.\n */\nexport class WebhookParseError extends FirefliesError {\n  override readonly code = 'WEBHOOK_PARSE_FAILED';\n\n  constructor(message: string) {\n    super(message, { status: 400 });\n    this.name = 'WebhookParseError';\n  }\n}\n\n/**\n * Thrown when no chunks received for configured timeout.\n * Consumer should check if meeting is still active and decide whether to reconnect.\n */\nexport class ChunkTimeoutError extends RealtimeError {\n  override readonly code = 'CHUNK_TIMEOUT';\n  readonly timeoutMs: number;\n\n  constructor(timeoutMs: number) {\n    super(`No chunks received for ${timeoutMs}ms`);\n    this.name = 'ChunkTimeoutError';\n    this.timeoutMs = timeoutMs;\n  }\n}\n\n/**\n * Parse error response and return appropriate error class.\n */\nexport function parseErrorResponse(\n  status: number,\n  body: unknown,\n  defaultMessage: string\n): FirefliesError {\n  const message = extractErrorMessage(body) ?? defaultMessage;\n\n  switch (status) {\n    case 401:\n      return new AuthenticationError(message);\n    case 404:\n      return new NotFoundError(message);\n    case 429: {\n      const retryAfter = extractRetryAfter(body);\n      return new RateLimitError(message, retryAfter);\n    }\n    case 400:\n      return new ValidationError(message);\n    default:\n      return new FirefliesError(message, { status });\n  }\n}\n\ninterface ErrorBody {\n  message?: string;\n  error?: string;\n}\n\ninterface RetryBody {\n  retryAfter?: number;\n}\n\nfunction extractErrorMessage(body: unknown): string | undefined {\n  if (typeof body === 'object' && body !== null) {\n    const obj = body as ErrorBody;\n    if (typeof obj.message === 'string') {\n      return obj.message;\n    }\n    if (typeof obj.error === 'string') {\n      return obj.error;\n    }\n  }\n  return undefined;\n}\n\nfunction extractRetryAfter(body: unknown): number | undefined {\n  if (typeof body === 'object' && body !== null) {\n    const obj = body as RetryBody;\n    if (typeof obj.retryAfter === 'number') {\n      return obj.retryAfter;\n    }\n  }\n  return undefined;\n}\n","import type { RateLimitState, ThrottleConfig } from '../types/config.js';\n\nconst RATE_LIMIT_REMAINING_HEADER = 'x-ratelimit-remaining-api';\nconst RATE_LIMIT_LIMIT_HEADER = 'x-ratelimit-limit-api';\nconst RATE_LIMIT_RESET_HEADER = 'x-ratelimit-reset-api';\n\n/**\n * Tracks rate limit state from API response headers.\n * Provides state management and throttle delay calculation.\n */\nexport class RateLimitTracker {\n  private _remaining: number | undefined;\n  private _limit: number | undefined;\n  private _resetInSeconds: number | undefined;\n  private _updatedAt: number;\n  private readonly warningThreshold: number;\n\n  /**\n   * Create a new RateLimitTracker.\n   * @param warningThreshold - Threshold below which isLow returns true\n   */\n  constructor(warningThreshold = 10) {\n    this._remaining = undefined;\n    this._limit = undefined;\n    this._resetInSeconds = undefined;\n    this._updatedAt = 0;\n    this.warningThreshold = warningThreshold;\n  }\n\n  /**\n   * Get the current rate limit state.\n   */\n  get state(): RateLimitState {\n    return {\n      remaining: this._remaining,\n      limit: this._limit,\n      resetInSeconds: this._resetInSeconds,\n      updatedAt: this._updatedAt,\n    };\n  }\n\n  /**\n   * Check if remaining requests are below the warning threshold.\n   * Returns false if remaining is undefined (header not received).\n   */\n  get isLow(): boolean {\n    return this._remaining !== undefined && this._remaining < this.warningThreshold;\n  }\n\n  /**\n   * Update state from response headers.\n   * Extracts x-ratelimit-remaining-api, x-ratelimit-limit-api, and x-ratelimit-reset-api headers.\n   *\n   * @param headers - Response headers (Headers object or plain object)\n   */\n  update(headers: Headers | Record<string, string>): void {\n    const remaining = this.getHeader(headers, RATE_LIMIT_REMAINING_HEADER);\n    if (remaining !== null) {\n      const parsed = Number.parseInt(remaining, 10);\n      if (!Number.isNaN(parsed) && parsed >= 0) {\n        this._remaining = parsed;\n      }\n    }\n\n    const limit = this.getHeader(headers, RATE_LIMIT_LIMIT_HEADER);\n    if (limit !== null) {\n      const parsed = Number.parseInt(limit, 10);\n      if (!Number.isNaN(parsed) && parsed >= 0) {\n        this._limit = parsed;\n      }\n    }\n\n    const reset = this.getHeader(headers, RATE_LIMIT_RESET_HEADER);\n    if (reset !== null) {\n      const parsed = Number.parseInt(reset, 10);\n      if (!Number.isNaN(parsed) && parsed >= 0) {\n        this._resetInSeconds = parsed;\n      }\n    }\n\n    this._updatedAt = Date.now();\n  }\n\n  /**\n   * Reset the tracker to initial state.\n   */\n  reset(): void {\n    this._remaining = undefined;\n    this._limit = undefined;\n    this._resetInSeconds = undefined;\n    this._updatedAt = 0;\n  }\n\n  /**\n   * Calculate the delay to apply before the next request.\n   * Returns 0 if throttling is disabled or not needed.\n   *\n   * Uses linear interpolation: more delay as remaining approaches 0.\n   * - remaining >= startThreshold: no delay\n   * - remaining = 0: maxDelay\n   * - remaining in between: proportional delay\n   *\n   * @param config - Throttle configuration\n   * @returns Delay in milliseconds\n   */\n  getThrottleDelay(config?: ThrottleConfig): number {\n    if (!config?.enabled) {\n      return 0;\n    }\n\n    if (this._remaining === undefined) {\n      return 0;\n    }\n\n    // Ensure startThreshold is at least 1 to avoid division issues and silent disabling\n    const startThreshold = Math.max(1, config.startThreshold ?? 20);\n    let minDelay = config.minDelay ?? 100;\n    let maxDelay = config.maxDelay ?? 2000;\n\n    // Handle misconfiguration: swap if minDelay > maxDelay\n    if (minDelay > maxDelay) {\n      [minDelay, maxDelay] = [maxDelay, minDelay];\n    }\n\n    if (this._remaining >= startThreshold) {\n      return 0;\n    }\n\n    if (this._remaining <= 0) {\n      return maxDelay;\n    }\n\n    // Linear interpolation: ratio goes from 0 (at threshold) to 1 (at 0)\n    const ratio = 1 - this._remaining / startThreshold;\n    return Math.round(minDelay + ratio * (maxDelay - minDelay));\n  }\n\n  /**\n   * Extract a header value from Headers object or plain object.\n   * For plain objects, performs case-insensitive key lookup.\n   */\n  private getHeader(headers: Headers | Record<string, string>, name: string): string | null {\n    if (headers instanceof Headers) {\n      return headers.get(name);\n    }\n    // Plain object - case-insensitive key lookup\n    const lowerName = name.toLowerCase();\n    for (const key of Object.keys(headers)) {\n      if (key.toLowerCase() === lowerName) {\n        return headers[key] ?? null;\n      }\n    }\n    return null;\n  }\n}\n","import { NetworkError, RateLimitError, TimeoutError } from '../errors.js';\n\n/**\n * Options for retry behavior.\n */\nexport interface RetryOptions {\n  /**\n   * Maximum number of retry attempts.\n   * @default 3\n   */\n  maxRetries?: number;\n\n  /**\n   * Base delay between retries in milliseconds.\n   * @default 1000\n   */\n  baseDelay?: number;\n\n  /**\n   * Maximum delay between retries in milliseconds.\n   * @default 30000\n   */\n  maxDelay?: number;\n\n  /**\n   * Custom predicate to determine if error is retryable.\n   * By default, retries network errors, timeouts, and rate limits.\n   */\n  shouldRetry?: (error: unknown, attempt: number) => boolean;\n}\n\nconst DEFAULT_OPTIONS: Required<Omit<RetryOptions, 'shouldRetry'>> = {\n  maxRetries: 3,\n  baseDelay: 1000,\n  maxDelay: 30000,\n};\n\n/**\n * Execute a function with exponential backoff retry logic.\n *\n * @param fn - The async function to execute\n * @param options - Retry configuration\n * @returns The result of the function\n * @throws The last error if all retries are exhausted\n */\nexport async function retry<T>(fn: () => Promise<T>, options?: RetryOptions): Promise<T> {\n  const maxRetries = options?.maxRetries ?? DEFAULT_OPTIONS.maxRetries;\n  const baseDelay = options?.baseDelay ?? DEFAULT_OPTIONS.baseDelay;\n  const maxDelay = options?.maxDelay ?? DEFAULT_OPTIONS.maxDelay;\n  const shouldRetry = options?.shouldRetry ?? isRetryableError;\n\n  let lastError: unknown;\n\n  for (let attempt = 0; attempt <= maxRetries; attempt++) {\n    try {\n      return await fn();\n    } catch (error) {\n      lastError = error;\n\n      if (attempt >= maxRetries || !shouldRetry(error, attempt)) {\n        throw error;\n      }\n\n      const delay = calculateDelay(error, attempt, baseDelay, maxDelay);\n      await sleep(delay);\n    }\n  }\n\n  // This should never be reached due to the throw in the loop\n  throw lastError;\n}\n\n/**\n * Default predicate for determining if an error is retryable.\n */\nexport function isRetryableError(error: unknown): boolean {\n  if (error instanceof RateLimitError) {\n    return true;\n  }\n  if (error instanceof TimeoutError) {\n    return true;\n  }\n  if (error instanceof NetworkError) {\n    return true;\n  }\n  // Retry on server errors (5xx)\n  if (error instanceof Error && 'status' in error && typeof error.status === 'number') {\n    return error.status >= 500 && error.status < 600;\n  }\n  return false;\n}\n\n/**\n * Calculate delay for the next retry attempt using exponential backoff.\n * Respects rate limit retryAfter if present.\n */\nexport function calculateDelay(\n  error: unknown,\n  attempt: number,\n  baseDelay: number,\n  maxDelay: number\n): number {\n  // Use rate limit's retryAfter if available (already in milliseconds)\n  if (error instanceof RateLimitError && error.retryAfter !== undefined) {\n    return Math.min(error.retryAfter, maxDelay);\n  }\n\n  // Exponential backoff with jitter\n  const exponentialDelay = baseDelay * 2 ** attempt;\n  const jitter = Math.random() * 0.1 * exponentialDelay;\n  return Math.min(exponentialDelay + jitter, maxDelay);\n}\n\nfunction sleep(ms: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import {\n  FirefliesError,\n  GraphQLError,\n  type GraphQLErrorDetail,\n  NetworkError,\n  parseErrorResponse,\n  TimeoutError,\n} from '../errors.js';\nimport type {\n  FirefliesConfig,\n  RateLimitConfig,\n  RateLimitState,\n  RetryConfig,\n} from '../types/config.js';\nimport { RateLimitTracker } from '../utils/rate-limit-tracker.js';\nimport { type RetryOptions, retry } from '../utils/retry.js';\n\nconst DEFAULT_BASE_URL = 'https://api.fireflies.ai/graphql';\nconst DEFAULT_TIMEOUT = 30000;\n\n/**\n * Response structure from GraphQL API.\n */\ninterface GraphQLResponse<T> {\n  data?: T;\n  errors?: GraphQLErrorDetail[];\n}\n\n/**\n * Low-level GraphQL client for Fireflies API.\n * Handles authentication, retries, and error parsing.\n */\nexport class GraphQLClient {\n  private readonly apiKey: string;\n  private readonly baseUrl: string;\n  private readonly timeout: number;\n  private readonly retryOptions: RetryOptions;\n  private readonly rateLimitTracker: RateLimitTracker | null;\n  private readonly rateLimitConfig: RateLimitConfig | null;\n  private lastWarningRemaining: number | undefined;\n\n  constructor(config: FirefliesConfig) {\n    if (!config.apiKey) {\n      throw new FirefliesError('API key is required');\n    }\n\n    this.apiKey = config.apiKey;\n    this.baseUrl = config.baseUrl ?? DEFAULT_BASE_URL;\n    this.timeout = config.timeout ?? DEFAULT_TIMEOUT;\n    this.retryOptions = buildRetryOptions(config.retry);\n\n    // Initialize rate limit tracking if configured\n    if (config.rateLimit) {\n      const warningThreshold = config.rateLimit.warningThreshold ?? 10;\n      this.rateLimitTracker = new RateLimitTracker(warningThreshold);\n      this.rateLimitConfig = config.rateLimit;\n    } else {\n      this.rateLimitTracker = null;\n      this.rateLimitConfig = null;\n    }\n  }\n\n  /**\n   * Get the current rate limit state.\n   * Returns undefined if rate limit tracking is not configured.\n   */\n  get rateLimitState(): RateLimitState | undefined {\n    return this.rateLimitTracker?.state;\n  }\n\n  /**\n   * Execute a GraphQL query or mutation.\n   *\n   * @param query - GraphQL query string\n   * @param variables - Optional query variables\n   * @returns The data from the GraphQL response\n   * @throws GraphQLError if the response contains errors\n   * @throws AuthenticationError if the API key is invalid\n   * @throws RateLimitError if rate limits are exceeded\n   */\n  async execute<T>(query: string, variables?: Record<string, unknown>): Promise<T> {\n    return retry(() => this.executeOnce<T>(query, variables), this.retryOptions);\n  }\n\n  private async executeOnce<T>(query: string, variables?: Record<string, unknown>): Promise<T> {\n    // Apply throttle delay if enabled\n    await this.applyThrottleDelay();\n\n    const controller = new AbortController();\n    const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n    try {\n      const response = await fetch(this.baseUrl, {\n        method: 'POST',\n        headers: {\n          'Content-Type': 'application/json',\n          Authorization: `Bearer ${this.apiKey}`,\n        },\n        body: JSON.stringify({ query, variables }),\n        signal: controller.signal,\n      });\n\n      clearTimeout(timeoutId);\n\n      // Update rate limit tracker from response headers\n      this.updateRateLimitState(response.headers);\n\n      if (!response.ok) {\n        const body = await this.safeParseJson(response);\n\n        // Handle rate limit error specially\n        if (response.status === 429) {\n          const retryAfter = this.parseRetryAfter(response.headers);\n          this.invokeRateLimitedCallback(retryAfter);\n          throw parseErrorResponse(\n            response.status,\n            body,\n            `GraphQL request failed with status ${response.status}`\n          );\n        }\n\n        throw parseErrorResponse(\n          response.status,\n          body,\n          `GraphQL request failed with status ${response.status}`\n        );\n      }\n\n      const json = (await response.json()) as GraphQLResponse<T>;\n\n      if (json.errors && json.errors.length > 0) {\n        throw this.parseGraphQLErrors(json.errors);\n      }\n\n      if (json.data === undefined) {\n        throw new FirefliesError('GraphQL response missing data field');\n      }\n\n      return json.data;\n    } catch (error) {\n      clearTimeout(timeoutId);\n\n      if (error instanceof FirefliesError) {\n        throw error;\n      }\n\n      if (error instanceof Error) {\n        if (error.name === 'AbortError') {\n          throw new TimeoutError(`Request timed out after ${this.timeout}ms`);\n        }\n        throw new NetworkError(`Network request failed: ${error.message}`, error);\n      }\n\n      throw new NetworkError('Unknown network error occurred', error);\n    }\n  }\n\n  private async safeParseJson(response: Response): Promise<unknown> {\n    try {\n      return await response.json();\n    } catch {\n      return null;\n    }\n  }\n\n  /**\n   * Apply throttle delay before request if configured.\n   */\n  private async applyThrottleDelay(): Promise<void> {\n    if (!this.rateLimitTracker || !this.rateLimitConfig?.throttle) {\n      return;\n    }\n\n    const delay = this.rateLimitTracker.getThrottleDelay(this.rateLimitConfig.throttle);\n    if (delay > 0) {\n      await sleep(delay);\n    }\n  }\n\n  /**\n   * Update rate limit state from response headers and invoke callbacks.\n   */\n  private updateRateLimitState(headers: Headers): void {\n    if (!this.rateLimitTracker || !this.rateLimitConfig) {\n      return;\n    }\n\n    const wasLow = this.rateLimitTracker.isLow;\n\n    this.rateLimitTracker.update(headers);\n\n    const state = this.rateLimitTracker.state;\n\n    // Always invoke onUpdate callback\n    this.safeCallback(() => this.rateLimitConfig?.onUpdate?.(state));\n\n    // Invoke onWarning when crossing the threshold (going from above to below)\n    // Also invoke if we haven't warned yet at this level\n    if (this.rateLimitTracker.isLow) {\n      const shouldWarn =\n        !wasLow || // Just crossed threshold\n        (state.remaining !== undefined &&\n          this.lastWarningRemaining !== undefined &&\n          state.remaining < this.lastWarningRemaining); // Dropped further\n\n      if (shouldWarn) {\n        this.lastWarningRemaining = state.remaining;\n        this.safeCallback(() => this.rateLimitConfig?.onWarning?.(state));\n      }\n    }\n  }\n\n  /**\n   * Parse Retry-After header value.\n   */\n  private parseRetryAfter(headers: Headers): number | undefined {\n    const value = headers.get('retry-after');\n    if (!value) return undefined;\n\n    const parsed = Number.parseInt(value, 10);\n    return Number.isNaN(parsed) ? undefined : parsed;\n  }\n\n  /**\n   * Invoke the onRateLimited callback.\n   */\n  private invokeRateLimitedCallback(retryAfter?: number): void {\n    if (!this.rateLimitTracker || !this.rateLimitConfig?.onRateLimited) {\n      return;\n    }\n    const state = this.rateLimitTracker.state;\n    this.safeCallback(() => this.rateLimitConfig?.onRateLimited?.(state, retryAfter));\n  }\n\n  /**\n   * Safely invoke a callback, catching any errors to prevent user code from breaking the SDK.\n   */\n  private safeCallback(fn: () => void): void {\n    try {\n      fn();\n    } catch {\n      // Ignore callback errors\n    }\n  }\n\n  private parseGraphQLErrors(errors: GraphQLErrorDetail[]): FirefliesError {\n    const firstError = errors[0];\n    if (!firstError) {\n      return new GraphQLError('Unknown GraphQL error', errors);\n    }\n\n    const message = firstError.message;\n\n    // Check for specific error types based on message content\n    if (\n      message.toLowerCase().includes('unauthorized') ||\n      message.toLowerCase().includes('authentication')\n    ) {\n      return parseErrorResponse(401, { message }, message);\n    }\n\n    if (message.toLowerCase().includes('not found')) {\n      return parseErrorResponse(404, { message }, message);\n    }\n\n    return new GraphQLError(message, errors);\n  }\n}\n\nfunction buildRetryOptions(config?: RetryConfig): RetryOptions {\n  if (!config) {\n    return {};\n  }\n  return {\n    maxRetries: config.maxRetries,\n    baseDelay: config.baseDelay,\n    maxDelay: config.maxDelay,\n  };\n}\n\nfunction sleep(ms: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import type { UploadAudioParams } from '../../types/params.js';\nimport type { GraphQLClient } from '../client.js';\n\n/**\n * Result from audio upload.\n */\nexport interface UploadAudioResult {\n  success: boolean;\n  title: string;\n  message: string;\n}\n\n/**\n * API for audio operations.\n */\nexport interface AudioAPI {\n  /**\n   * Upload audio/video file for transcription.\n   *\n   * @param params - Upload parameters\n   * @returns Upload result\n   */\n  upload(params: UploadAudioParams): Promise<UploadAudioResult>;\n}\n\n/**\n * Create the audio API bound to a GraphQL client.\n */\nexport function createAudioAPI(client: GraphQLClient): AudioAPI {\n  return {\n    async upload(params: UploadAudioParams): Promise<UploadAudioResult> {\n      const mutation = `\n        mutation UploadAudio($input: AudioUploadInput!) {\n          uploadAudio(input: $input) {\n            success\n            title\n            message\n          }\n        }\n      `;\n      const data = await client.execute<{ uploadAudio: UploadAudioResult }>(mutation, {\n        input: params,\n      });\n      return data.uploadAudio;\n    },\n  };\n}\n","import type { Transcript } from '../../types/transcript.js';\nimport type { GraphQLClient } from '../client.js';\n\n/**\n * API for transcript mutations.\n */\nexport interface TranscriptsMutationsAPI {\n  /**\n   * Delete a transcript.\n   *\n   * Rate limit: 10/min\n   *\n   * @param id - Transcript ID to delete\n   * @returns Deleted transcript (partial fields)\n   */\n  delete(id: string): Promise<Transcript>;\n}\n\n/**\n * Create the transcripts mutations API bound to a GraphQL client.\n */\nexport function createTranscriptsMutationsAPI(client: GraphQLClient): TranscriptsMutationsAPI {\n  return {\n    async delete(id: string): Promise<Transcript> {\n      const mutation = `\n        mutation deleteTranscript($id: String!) {\n          deleteTranscript(id: $id) {\n            id\n            title\n            organizer_email\n            date\n            duration\n          }\n        }\n      `;\n      const data = await client.execute<{ deleteTranscript: Transcript }>(mutation, { id });\n      return data.deleteTranscript;\n    },\n  };\n}\n","import type { UserProfile, UserRole } from '../../types/user.js';\nimport type { GraphQLClient } from '../client.js';\n\n/**\n * API for user mutations.\n */\nexport interface UsersMutationsAPI {\n  /**\n   * Set user role (admin or user).\n   *\n   * @param userId - User ID to update\n   * @param role - New role\n   * @returns Updated user (partial fields)\n   */\n  setRole(userId: string, role: UserRole): Promise<UserProfile>;\n}\n\n/**\n * Create the users mutations API bound to a GraphQL client.\n */\nexport function createUsersMutationsAPI(client: GraphQLClient): UsersMutationsAPI {\n  return {\n    async setRole(userId: string, role: UserRole): Promise<UserProfile> {\n      const mutation = `\n        mutation setUserRole($userId: String!, $role: Role!) {\n          setUserRole(user_id: $userId, role: $role) {\n            id\n            name\n            email\n            role\n          }\n        }\n      `;\n      const data = await client.execute<{ setUserRole: UserProfile }>(mutation, {\n        userId,\n        role,\n      });\n      return data.setUserRole;\n    },\n  };\n}\n","/**\n * Options for parallel pagination.\n */\nexport interface ParallelPaginationOptions {\n  /** Pages to fetch concurrently. @default 3 */\n  concurrency?: number;\n  /** Items per page. @default 50 */\n  pageSize?: number;\n  /** Delay between fetch starts (ms). @default 100 */\n  delayMs?: number;\n}\n\n/**\n * Create an async iterable that paginates through results with concurrent page fetching.\n *\n * Fetches multiple pages in parallel while maintaining item order.\n * Stops when a partial page (< pageSize items) is received.\n *\n * @param fetcher - Function that fetches a page of results\n * @param options - Pagination options\n * @returns Async iterable yielding items one at a time\n *\n * @example\n * ```typescript\n * const items = paginateParallel(\n *   (skip, limit) => client.transcripts.list({ skip, limit }),\n *   { concurrency: 3, pageSize: 50 }\n * );\n *\n * for await (const item of items) {\n *   console.log(item.title);\n * }\n * ```\n */\nexport async function* paginateParallel<T>(\n  fetcher: (skip: number, limit: number) => Promise<T[]>,\n  options: ParallelPaginationOptions = {}\n): AsyncIterable<T> {\n  const { concurrency = 3, pageSize = 50, delayMs = 100 } = options;\n\n  // Track pending page fetches: Map<pageIndex, Promise<T[]>>\n  const pending = new Map<number, Promise<T[]>>();\n  let nextPageToFetch = 0;\n  let nextPageToYield = 0;\n  let foundEnd = false;\n\n  // Helper to delay between fetch starts\n  const delay = (ms: number) =>\n    ms > 0 ? new Promise<void>((resolve) => setTimeout(resolve, ms)) : Promise.resolve();\n\n  // Start fetching a page\n  const startFetch = (pageIndex: number): Promise<T[]> => {\n    const skip = pageIndex * pageSize;\n    return fetcher(skip, pageSize);\n  };\n\n  // Schedule additional page fetches up to concurrency limit\n  // Only schedules if we haven't found the end yet\n  const scheduleFetches = async () => {\n    while (!foundEnd && pending.size < concurrency) {\n      const pageIndex = nextPageToFetch++;\n      // Add delay between starting fetches (except first)\n      if (pageIndex > 0 && delayMs > 0) {\n        await delay(delayMs);\n      }\n      // Don't schedule if we found end during delay\n      if (foundEnd) break;\n      pending.set(pageIndex, startFetch(pageIndex));\n    }\n  };\n\n  // Fetch first page synchronously to determine if there's data\n  pending.set(0, startFetch(0));\n  nextPageToFetch = 1;\n\n  // Yield pages in order\n  while (pending.has(nextPageToYield)) {\n    const pagePromise = pending.get(nextPageToYield);\n    if (!pagePromise) break;\n\n    const page = await pagePromise;\n    pending.delete(nextPageToYield);\n\n    // Check if this was the last page (partial or empty)\n    if (page.length < pageSize) {\n      foundEnd = true;\n      // Yield items from this final page\n      for (const item of page) {\n        yield item;\n      }\n      break;\n    }\n\n    // Page was full, schedule more fetches before yielding\n    // This allows concurrent fetching while we yield items\n    await scheduleFetches();\n\n    // Yield items from this page\n    for (const item of page) {\n      yield item;\n    }\n\n    nextPageToYield++;\n  }\n}\n\n/**\n * Create an async iterable that automatically paginates through results.\n *\n * @param fetcher - Function that fetches a page of results\n * @param pageSize - Number of items per page\n * @returns Async iterable yielding items one at a time\n *\n * @example\n * ```typescript\n * const items = paginate(\n *   (skip, limit) => client.transcripts.list({ skip, limit }),\n *   50\n * );\n *\n * for await (const item of items) {\n *   console.log(item.title);\n * }\n * ```\n */\nexport async function* paginate<T>(\n  fetcher: (skip: number, limit: number) => Promise<T[]>,\n  pageSize = 50\n): AsyncIterable<T> {\n  let skip = 0;\n  let hasMore = true;\n\n  while (hasMore) {\n    const page = await fetcher(skip, pageSize);\n\n    for (const item of page) {\n      yield item;\n    }\n\n    // If we got fewer items than requested, we've reached the end\n    if (page.length < pageSize) {\n      hasMore = false;\n    } else {\n      skip += pageSize;\n    }\n  }\n}\n\n/**\n * Collect all items from an async iterable into an array.\n *\n * @param iterable - Async iterable to collect\n * @returns Array of all items\n */\nexport async function collectAll<T>(iterable: AsyncIterable<T>): Promise<T[]> {\n  const items: T[] = [];\n  for await (const item of iterable) {\n    items.push(item);\n  }\n  return items;\n}\n","import { paginate } from '../../helpers/pagination.js';\nimport type { AIApp } from '../../types/ai-app.js';\nimport type { AIAppsListParams } from '../../types/params.js';\nimport type { GraphQLClient } from '../client.js';\n\nconst AI_APP_OUTPUT_FIELDS = `\n  transcript_id\n  user_id\n  app_id\n  created_at\n  title\n  prompt\n  response\n`;\n\n/**\n * API for AI Apps operations.\n */\nexport interface AIAppsAPI {\n  /**\n   * List AI App outputs.\n   *\n   * @param params - Optional filter and pagination parameters\n   * @returns Array of AI App outputs\n   */\n  list(params?: AIAppsListParams): Promise<AIApp[]>;\n\n  /**\n   * Iterate through all AI App outputs matching the filter.\n   * Automatically handles pagination.\n   *\n   * @param params - Filter options (skip and limit are ignored)\n   * @returns Async iterable of AI App outputs\n   */\n  listAll(params?: Omit<AIAppsListParams, 'skip' | 'limit'>): AsyncIterable<AIApp>;\n}\n\n/**\n * Create the AI Apps API bound to a GraphQL client.\n */\nexport function createAIAppsAPI(client: GraphQLClient): AIAppsAPI {\n  return {\n    async list(params?: AIAppsListParams): Promise<AIApp[]> {\n      const query = `\n        query GetAIAppsOutputs(\n          $appId: String\n          $transcriptId: String\n          $skip: Float\n          $limit: Float\n        ) {\n          apps(\n            app_id: $appId\n            transcript_id: $transcriptId\n            skip: $skip\n            limit: $limit\n          ) {\n            outputs { ${AI_APP_OUTPUT_FIELDS} }\n          }\n        }\n      `;\n      const data = await client.execute<{ apps: { outputs: AIApp[] } }>(query, {\n        appId: params?.app_id,\n        transcriptId: params?.transcript_id,\n        skip: params?.skip,\n        limit: params?.limit ?? 10,\n      });\n      return data.apps.outputs;\n    },\n\n    listAll(params?: Omit<AIAppsListParams, 'skip' | 'limit'>): AsyncIterable<AIApp> {\n      return paginate((skip, limit) => this.list({ ...params, skip, limit }), 10);\n    },\n  };\n}\n","import { paginate } from '../../helpers/pagination.js';\nimport type { Bite } from '../../types/bite.js';\nimport type { BitesListParams, CreateBiteParams } from '../../types/params.js';\nimport type { GraphQLClient } from '../client.js';\n\nconst BITE_FIELDS = `\n  id\n  transcript_id\n  user_id\n  name\n  status\n  summary\n  summary_status\n  media_type\n  start_time\n  end_time\n  created_at\n  thumbnail\n  preview\n  captions {\n    index\n    text\n    start_time\n    end_time\n    speaker_id\n    speaker_name\n  }\n  sources {\n    src\n    type\n  }\n  user {\n    id\n    name\n    first_name\n    last_name\n    picture\n  }\n  created_from {\n    id\n    name\n    type\n    description\n    duration\n  }\n  privacies\n`;\n\n/**\n * API for bite (soundbite/clip) operations.\n */\nexport interface BitesAPI {\n  /**\n   * Get a single bite by ID.\n   *\n   * @param id - Bite ID\n   * @returns Bite details\n   */\n  get(id: string): Promise<Bite>;\n\n  /**\n   * List bites with filtering.\n   *\n   * @param params - Filter and pagination options\n   * @returns Array of bites (max 50 per call)\n   */\n  list(params: BitesListParams): Promise<Bite[]>;\n\n  /**\n   * Iterate through all bites matching the filter.\n   * Automatically handles pagination.\n   *\n   * @param params - Filter options (skip and limit are ignored)\n   * @returns Async iterable of bites\n   */\n  listAll(params: Omit<BitesListParams, 'skip' | 'limit'>): AsyncIterable<Bite>;\n\n  /**\n   * Create a new bite from a transcript.\n   *\n   * @param params - Bite creation parameters\n   * @returns Created bite (partial fields)\n   */\n  create(params: CreateBiteParams): Promise<Bite>;\n}\n\n/**\n * Create the bites API bound to a GraphQL client.\n */\nexport function createBitesAPI(client: GraphQLClient): BitesAPI {\n  return {\n    async get(id: string): Promise<Bite> {\n      const query = `\n        query Bite($biteId: ID!) {\n          bite(id: $biteId) { ${BITE_FIELDS} }\n        }\n      `;\n      const data = await client.execute<{ bite: Bite }>(query, { biteId: id });\n      return data.bite;\n    },\n\n    async list(params: BitesListParams): Promise<Bite[]> {\n      const query = `\n        query Bites(\n          $transcriptId: ID\n          $mine: Boolean\n          $myTeam: Boolean\n          $limit: Int\n          $skip: Int\n        ) {\n          bites(\n            transcript_id: $transcriptId\n            mine: $mine\n            my_team: $myTeam\n            limit: $limit\n            skip: $skip\n          ) { ${BITE_FIELDS} }\n        }\n      `;\n      const data = await client.execute<{ bites: Bite[] }>(query, {\n        transcriptId: params.transcript_id,\n        mine: params.mine,\n        myTeam: params.my_team,\n        limit: params.limit ?? 50,\n        skip: params.skip,\n      });\n      return data.bites;\n    },\n\n    listAll(params: Omit<BitesListParams, 'skip' | 'limit'>): AsyncIterable<Bite> {\n      return paginate((skip, limit) => this.list({ ...params, skip, limit }), 50);\n    },\n\n    async create(params: CreateBiteParams): Promise<Bite> {\n      const mutation = `\n        mutation CreateBite(\n          $transcriptId: ID!\n          $startTime: Float!\n          $endTime: Float!\n          $name: String\n          $mediaType: String\n          $summary: String\n          $privacies: [BitePrivacy!]\n        ) {\n          createBite(\n            transcript_Id: $transcriptId\n            start_time: $startTime\n            end_time: $endTime\n            name: $name\n            media_type: $mediaType\n            summary: $summary\n            privacies: $privacies\n          ) {\n            id\n            name\n            status\n            summary\n          }\n        }\n      `;\n      const data = await client.execute<{ createBite: Bite }>(mutation, {\n        transcriptId: params.transcript_id,\n        startTime: params.start_time,\n        endTime: params.end_time,\n        name: params.name,\n        mediaType: params.media_type,\n        summary: params.summary,\n        privacies: params.privacies,\n      });\n      return data.createBite;\n    },\n  };\n}\n","import type { ActiveMeeting } from '../../types/meeting.js';\nimport type { ActiveMeetingsParams, AddBotParams } from '../../types/params.js';\nimport type { GraphQLClient } from '../client.js';\n\nconst ACTIVE_MEETING_FIELDS = `\n  id\n  title\n  organizer_email\n  meeting_link\n  start_time\n  end_time\n  privacy\n  state\n`;\n\n/**\n * API for meeting operations.\n */\nexport interface MeetingsAPI {\n  /**\n   * List active meetings in progress.\n   *\n   * @param params - Optional filter parameters\n   * @returns Array of active meetings\n   */\n  active(params?: ActiveMeetingsParams): Promise<ActiveMeeting[]>;\n\n  /**\n   * Add Fireflies bot to a live meeting.\n   *\n   * @param params - Meeting parameters\n   * @returns Success result\n   */\n  addBot(params: AddBotParams): Promise<{ success: boolean }>;\n}\n\n/**\n * Create the meetings API bound to a GraphQL client.\n */\nexport function createMeetingsAPI(client: GraphQLClient): MeetingsAPI {\n  return {\n    async active(params?: ActiveMeetingsParams): Promise<ActiveMeeting[]> {\n      const query = `\n        query ActiveMeetings($email: String, $states: [MeetingState!]) {\n          active_meetings(input: { email: $email, states: $states }) {\n            ${ACTIVE_MEETING_FIELDS}\n          }\n        }\n      `;\n      const data = await client.execute<{ active_meetings: ActiveMeeting[] }>(query, {\n        email: params?.email,\n        states: params?.states,\n      });\n      return data.active_meetings;\n    },\n\n    async addBot(params: AddBotParams): Promise<{ success: boolean }> {\n      const mutation = `\n        mutation AddToLiveMeeting(\n          $meetingLink: String!\n          $title: String\n          $meetingPassword: String\n          $duration: Int\n          $language: String\n        ) {\n          addToLiveMeeting(\n            meeting_link: $meetingLink\n            title: $title\n            meeting_password: $meetingPassword\n            duration: $duration\n            language: $language\n          ) {\n            success\n          }\n        }\n      `;\n      const data = await client.execute<{ addToLiveMeeting: { success: boolean } }>(mutation, {\n        meetingLink: params.meeting_link,\n        title: params.title,\n        meetingPassword: params.password,\n        duration: params.duration,\n        language: params.language,\n      });\n      return data.addToLiveMeeting;\n    },\n  };\n}\n","import type { Transcript } from '../types/transcript.js';\n\n/**\n * A single action item extracted from the transcript.\n */\nexport interface ActionItem {\n  /** The action item text */\n  text: string;\n  /** Detected assignee name (if found in text) */\n  assignee?: string;\n  /** Detected due date (if found in text) */\n  dueDate?: string;\n  /** Original line number in action_items string (1-indexed) */\n  lineNumber: number;\n  /** Related sentence from transcript (if AIFilter.task matched) */\n  sourceSentence?: {\n    speakerName: string;\n    text: string;\n    startTime: number;\n  };\n}\n\n/**\n * Result of action item extraction.\n */\nexport interface ActionItemsResult {\n  /** Extracted action items */\n  items: ActionItem[];\n  /** Total count of action items */\n  totalItems: number;\n  /** Items with detected assignees */\n  assignedItems: number;\n  /** Items with detected due dates */\n  datedItems: number;\n  /** Unique assignees found */\n  assignees: string[];\n}\n\n/**\n * Options for action item extraction.\n */\nexport interface ActionItemOptions {\n  /**\n   * Attempt to detect assignees from text patterns (default: true).\n   * Looks for patterns like \"@Alice\", \"Alice:\", \"assigned to Alice\".\n   */\n  detectAssignees?: boolean;\n  /**\n   * Attempt to detect due dates from text patterns (default: true).\n   * Looks for patterns like \"by Friday\", \"due 2024-01-15\", \"EOD\".\n   */\n  detectDueDates?: boolean;\n  /**\n   * Match action items with AIFilter.task in sentences (default: false).\n   * When enabled, correlates summary items with source sentences.\n   */\n  includeSourceSentences?: boolean;\n  /**\n   * Known participant names for better assignee matching (default: []).\n   * Improves accuracy by limiting to actual meeting participants.\n   */\n  participantNames?: string[];\n}\n\n// Assignee detection patterns in priority order (highest first)\nconst ASSIGNEE_PATTERNS: Array<{ pattern: RegExp; group: number }> = [\n  { pattern: /@(\\w+)/i, group: 1 }, // @Alice\n  { pattern: /^(\\w+):/i, group: 1 }, // Alice: at start\n  { pattern: /assigned to (\\w+)/i, group: 1 }, // assigned to Alice\n  { pattern: /(\\w+) will\\b/i, group: 1 }, // Alice will\n  { pattern: /(\\w+) to\\b/i, group: 1 }, // Alice to (do something)\n  { pattern: /\\s-\\s*(\\w+)$/i, group: 1 }, // ... - Alice\n];\n\n// Due date detection patterns\nconst DUE_DATE_PATTERNS: Array<{ pattern: RegExp; group: number }> = [\n  { pattern: /by (monday|tuesday|wednesday|thursday|friday|saturday|sunday)/i, group: 1 },\n  { pattern: /by (tomorrow|today)/i, group: 1 },\n  { pattern: /by (EOD|end of day)/i, group: 1 },\n  { pattern: /by (EOW|end of week)/i, group: 1 },\n  { pattern: /due (\\d{4}-\\d{2}-\\d{2})/i, group: 1 },\n  { pattern: /due (jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\\s+\\d+/i, group: 0 },\n  { pattern: /by (\\d{1,2}\\/\\d{1,2})/i, group: 1 },\n];\n\n// List item prefixes to strip\nconst LIST_PREFIX_PATTERN = /^(?:[-•*]|\\d+\\.)\\s*/;\n\n// Section header pattern: **Name** or **Multiple Words**\n// Used by Fireflies to group action items by assignee\nconst SECTION_HEADER_PATTERN = /^\\*\\*(.+)\\*\\*$/;\n\n/**\n * Extract structured action items from a transcript.\n *\n * Parses the action_items field from the transcript summary into\n * structured data with optional assignee and due date detection.\n *\n * **Note:** These action items are generated by Fireflies' AI processing\n * during transcription. For custom action item extraction or different\n * interpretation logic, consider running your own LLM calls on the\n * transcript sentences directly.\n *\n * @param transcript - The transcript to extract action items from\n * @param options - Extraction options\n * @returns Structured action items with metadata\n *\n * @example\n * ```typescript\n * const result = extractActionItems(transcript);\n * for (const item of result.items) {\n *   console.log(`${item.text} -> ${item.assignee ?? 'unassigned'}`);\n * }\n * ```\n */\nexport function extractActionItems(\n  transcript: Transcript,\n  options: ActionItemOptions = {}\n): ActionItemsResult {\n  const actionItemsText = transcript.summary?.action_items;\n  if (!actionItemsText || actionItemsText.trim().length === 0) {\n    return emptyResult();\n  }\n\n  const config: ParseConfig = {\n    detectAssignees: options.detectAssignees ?? true,\n    detectDueDates: options.detectDueDates ?? true,\n    includeSourceSentences: options.includeSourceSentences ?? false,\n    participantNames: options.participantNames ?? [],\n  };\n\n  const taskSentences = config.includeSourceSentences ? buildTaskSentenceLookup(transcript) : [];\n  const lines = actionItemsText.split(/\\n/);\n\n  return parseAllLines(lines, config, taskSentences);\n}\n\nfunction parseAllLines(\n  lines: string[],\n  config: ParseConfig,\n  taskSentences: TaskSentence[]\n): ActionItemsResult {\n  const items: ActionItem[] = [];\n  const assigneeSet = new Set<string>();\n  let currentSectionAssignee: string | undefined;\n\n  for (let i = 0; i < lines.length; i++) {\n    const result = processLine(lines[i], i + 1, config, taskSentences, currentSectionAssignee);\n    if (result.type === 'header') {\n      currentSectionAssignee = result.assignee;\n    } else if (result.type === 'item' && result.item) {\n      items.push(result.item);\n      if (result.item.assignee) {\n        assigneeSet.add(result.item.assignee);\n      }\n    }\n  }\n\n  return buildResult(items, assigneeSet);\n}\n\ntype LineResult =\n  | { type: 'skip' }\n  | { type: 'header'; assignee: string | undefined }\n  | { type: 'item'; item: ActionItem };\n\nfunction processLine(\n  line: string | undefined,\n  lineNumber: number,\n  config: ParseConfig,\n  taskSentences: TaskSentence[],\n  sectionAssignee: string | undefined\n): LineResult {\n  if (!line) return { type: 'skip' };\n\n  const trimmed = line.trim();\n  if (trimmed.length === 0) return { type: 'skip' };\n\n  // Check for section header (**Name**)\n  const headerMatch = trimmed.match(SECTION_HEADER_PATTERN);\n  if (headerMatch?.[1]) {\n    const headerName = headerMatch[1];\n    const assignee = headerName.toLowerCase() === 'unassigned' ? undefined : headerName;\n    return { type: 'header', assignee };\n  }\n\n  const item = parseLine(line, lineNumber, config, taskSentences, sectionAssignee);\n  if (item) {\n    return { type: 'item', item };\n  }\n\n  return { type: 'skip' };\n}\n\ninterface ParseConfig {\n  detectAssignees: boolean;\n  detectDueDates: boolean;\n  includeSourceSentences: boolean;\n  participantNames: string[];\n}\n\nfunction parseLine(\n  line: string | undefined,\n  lineNumber: number,\n  config: ParseConfig,\n  taskSentences: TaskSentence[],\n  sectionAssignee?: string\n): ActionItem | null {\n  if (!line) return null;\n\n  const trimmed = line.trim();\n  if (trimmed.length === 0) return null;\n\n  const text = trimmed.replace(LIST_PREFIX_PATTERN, '');\n  if (text.length === 0) return null;\n\n  // Inline assignee detection takes priority over section assignee\n  const inlineAssignee = config.detectAssignees\n    ? detectAssignee(text, config.participantNames)\n    : undefined;\n  const assignee = inlineAssignee ?? sectionAssignee;\n\n  const dueDate = config.detectDueDates ? detectDueDate(text) : undefined;\n  const sourceSentence = config.includeSourceSentences\n    ? findSourceSentence(text, taskSentences)\n    : undefined;\n\n  return { text, assignee, dueDate, lineNumber, sourceSentence };\n}\n\nfunction buildResult(items: ActionItem[], assigneeSet: Set<string>): ActionItemsResult {\n  return {\n    items,\n    totalItems: items.length,\n    assignedItems: items.filter((i) => i.assignee !== undefined).length,\n    datedItems: items.filter((i) => i.dueDate !== undefined).length,\n    assignees: Array.from(assigneeSet),\n  };\n}\n\nfunction emptyResult(): ActionItemsResult {\n  return {\n    items: [],\n    totalItems: 0,\n    assignedItems: 0,\n    datedItems: 0,\n    assignees: [],\n  };\n}\n\nfunction detectAssignee(text: string, participantNames: string[]): string | undefined {\n  const participantSet = new Set(participantNames.map((n) => n.toLowerCase()));\n  const filterByParticipants = participantSet.size > 0;\n\n  for (const { pattern, group } of ASSIGNEE_PATTERNS) {\n    const match = text.match(pattern);\n    if (match?.[group]) {\n      const name = match[group];\n      // If participantNames provided, only match against those names\n      if (filterByParticipants) {\n        if (participantSet.has(name.toLowerCase())) {\n          return name;\n        }\n        // Continue checking other patterns\n        continue;\n      }\n      return name;\n    }\n  }\n\n  return undefined;\n}\n\nfunction detectDueDate(text: string): string | undefined {\n  for (const { pattern, group } of DUE_DATE_PATTERNS) {\n    const match = text.match(pattern);\n    if (match) {\n      // For \"due Jan 15\" pattern (group 0), extract the full date part\n      if (group === 0 && match[0]) {\n        const fullMatch = match[0];\n        // Extract just the date portion (e.g., \"Jan 15\" from \"due Jan 15\")\n        const dateMatch = fullMatch.match(\n          /(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)\\s+\\d+/i\n        );\n        if (dateMatch?.[0]) {\n          return dateMatch[0];\n        }\n      }\n      if (match[group]) {\n        return match[group];\n      }\n    }\n  }\n\n  return undefined;\n}\n\ninterface TaskSentence {\n  text: string;\n  task: string;\n  speakerName: string;\n  startTime: number;\n}\n\nfunction buildTaskSentenceLookup(transcript: Transcript): TaskSentence[] {\n  const sentences = transcript.sentences ?? [];\n  const result: TaskSentence[] = [];\n\n  for (const sentence of sentences) {\n    const task = sentence.ai_filters?.task;\n    if (task) {\n      result.push({\n        text: sentence.text,\n        task: task.toLowerCase(),\n        speakerName: sentence.speaker_name,\n        startTime: Number.parseFloat(sentence.start_time),\n      });\n    }\n  }\n\n  return result;\n}\n\nfunction findSourceSentence(\n  actionItemText: string,\n  taskSentences: TaskSentence[]\n): ActionItem['sourceSentence'] | undefined {\n  const normalizedItem = actionItemText.toLowerCase();\n\n  // Look for task sentences that have significant word overlap\n  for (const sentence of taskSentences) {\n    // Check if the task text is contained in the action item or vice versa\n    if (normalizedItem.includes(sentence.task) || sentence.task.includes(normalizedItem)) {\n      return {\n        speakerName: sentence.speakerName,\n        text: sentence.text,\n        startTime: sentence.startTime,\n      };\n    }\n\n    // Also check for significant word overlap\n    const itemWords = new Set(normalizedItem.split(/\\s+/).filter((w) => w.length > 3));\n    const taskWords = sentence.task.split(/\\s+/).filter((w) => w.length > 3);\n    const matchingWords = taskWords.filter((w) => itemWords.has(w));\n\n    if (taskWords.length > 0 && matchingWords.length / taskWords.length >= 0.5) {\n      return {\n        speakerName: sentence.speakerName,\n        text: sentence.text,\n        startTime: sentence.startTime,\n      };\n    }\n  }\n\n  return undefined;\n}\n","import type {\n  ActionItemsFilterOptions,\n  ActionItemsMarkdownOptions,\n  AggregatedActionItem,\n  AggregatedActionItemsResult,\n} from '../types/action-items.js';\nimport type { Transcript } from '../types/transcript.js';\nimport {\n  type ActionItem,\n  type ActionItemOptions,\n  type ActionItemsResult,\n  extractActionItems,\n} from './action-items.js';\n\n/**\n * Filter action items by criteria.\n *\n * Filters can be combined with AND logic - items must match all specified criteria.\n *\n * @param items - Action items to filter\n * @param options - Filter criteria\n * @returns Filtered items preserving original type and order\n *\n * @example\n * ```typescript\n * // Filter to Alice's items with due dates\n * const filtered = filterActionItems(items, {\n *   assignees: ['Alice'],\n *   datedOnly: true,\n * });\n * ```\n */\nexport function filterActionItems<T extends ActionItem>(\n  items: T[],\n  options: ActionItemsFilterOptions\n): T[] {\n  const { assignees, assignedOnly, datedOnly } = options;\n\n  // Normalize assignees to lowercase for case-insensitive matching\n  const normalizedAssignees = assignees?.map((a) => a.toLowerCase());\n\n  return items.filter((item) => {\n    // Assignee filter (case-insensitive)\n    if (normalizedAssignees && normalizedAssignees.length > 0) {\n      if (!item.assignee) return false;\n      if (!normalizedAssignees.includes(item.assignee.toLowerCase())) return false;\n    }\n\n    // Assigned-only filter\n    if (assignedOnly && !item.assignee) {\n      return false;\n    }\n\n    // Dated-only filter\n    if (datedOnly && !item.dueDate) {\n      return false;\n    }\n\n    return true;\n  });\n}\n\n/**\n * Aggregate action items from multiple transcripts.\n *\n * Extracts action items from each transcript and attaches source metadata\n * (transcript ID, title, date) to each item.\n *\n * @param transcripts - Transcripts to extract action items from\n * @param extractionOptions - Options for action item extraction\n * @param filterOptions - Options to filter extracted items\n * @returns Aggregated result with items and statistics\n *\n * @example\n * ```typescript\n * const result = aggregateActionItems(transcripts);\n * console.log(`${result.totalItems} items from ${result.transcriptsProcessed} meetings`);\n * ```\n */\nexport function aggregateActionItems(\n  transcripts: Transcript[],\n  extractionOptions?: ActionItemOptions,\n  filterOptions?: ActionItemsFilterOptions\n): AggregatedActionItemsResult {\n  if (transcripts.length === 0) {\n    return emptyAggregatedResult();\n  }\n\n  const allItems: AggregatedActionItem[] = [];\n  let transcriptsWithItems = 0;\n\n  for (const transcript of transcripts) {\n    const extracted = extractActionItems(transcript, extractionOptions);\n\n    if (extracted.items.length > 0) {\n      transcriptsWithItems++;\n\n      for (const item of extracted.items) {\n        allItems.push({\n          ...item,\n          transcriptId: transcript.id,\n          transcriptTitle: transcript.title,\n          transcriptDate: transcript.dateString,\n        });\n      }\n    }\n  }\n\n  // Apply filter if provided\n  const filteredItems = filterOptions ? filterActionItems(allItems, filterOptions) : allItems;\n\n  return buildAggregatedResult(filteredItems, transcripts.length, transcriptsWithItems);\n}\n\nfunction emptyAggregatedResult(): AggregatedActionItemsResult {\n  return {\n    items: [],\n    totalItems: 0,\n    transcriptsProcessed: 0,\n    transcriptsWithItems: 0,\n    assignedItems: 0,\n    datedItems: 0,\n    assignees: [],\n    dateRange: { earliest: '', latest: '' },\n  };\n}\n\nfunction buildAggregatedResult(\n  items: AggregatedActionItem[],\n  transcriptsProcessed: number,\n  transcriptsWithItems: number\n): AggregatedActionItemsResult {\n  const assigneeSet = new Set<string>();\n  let assignedItems = 0;\n  let datedItems = 0;\n\n  for (const item of items) {\n    if (item.assignee) {\n      assigneeSet.add(item.assignee);\n      assignedItems++;\n    }\n    if (item.dueDate) {\n      datedItems++;\n    }\n  }\n\n  const dates = items\n    .map((i) => i.transcriptDate)\n    .filter(Boolean)\n    .sort();\n\n  return {\n    items,\n    totalItems: items.length,\n    transcriptsProcessed,\n    transcriptsWithItems,\n    assignedItems,\n    datedItems,\n    assignees: Array.from(assigneeSet),\n    dateRange: {\n      earliest: dates[0] ?? '',\n      latest: dates[dates.length - 1] ?? '',\n    },\n  };\n}\n\n/** Check if result is an aggregated result (has transcript metadata) */\nfunction isAggregatedResult(\n  result: ActionItemsResult | AggregatedActionItemsResult\n): result is AggregatedActionItemsResult {\n  return 'transcriptsProcessed' in result;\n}\n\n/** Check if item is an aggregated item (has transcript metadata) */\nfunction isAggregatedItem(item: ActionItem): item is AggregatedActionItem {\n  return 'transcriptId' in item;\n}\n\n/** Escape markdown special characters in text */\nfunction escapeMarkdown(text: string): string {\n  return text\n    .replace(/\\\\/g, '\\\\\\\\')\n    .replace(/\\*/g, '\\\\*')\n    .replace(/#/g, '\\\\#')\n    .replace(/\\[/g, '\\\\[')\n    .replace(/\\]/g, '\\\\]')\n    .replace(/_/g, '\\\\_')\n    .replace(/`/g, '\\\\`');\n}\n\n/** Get preset options */\nfunction getPresetOptions(\n  preset: ActionItemsMarkdownOptions['preset']\n): Partial<ActionItemsMarkdownOptions> {\n  switch (preset) {\n    case 'notion':\n      return {\n        style: 'checkbox',\n        includeAssignee: true,\n        includeDueDate: true,\n      };\n    case 'obsidian':\n      return {\n        style: 'checkbox',\n        includeAssignee: false,\n        includeDueDate: true,\n      };\n    case 'github':\n      return {\n        style: 'checkbox',\n        includeAssignee: true,\n        includeDueDate: true,\n      };\n    default:\n      return {};\n  }\n}\n\n/** Format a single item as markdown */\nfunction formatItem(\n  item: ActionItem | AggregatedActionItem,\n  index: number,\n  options: Required<\n    Pick<\n      ActionItemsMarkdownOptions,\n      'style' | 'includeAssignee' | 'includeDueDate' | 'includeMeetingTitle'\n    >\n  >\n): string {\n  const { style, includeAssignee, includeDueDate, includeMeetingTitle } = options;\n\n  // Build prefix based on style\n  let prefix: string;\n  switch (style) {\n    case 'bullet':\n      prefix = '-';\n      break;\n    case 'numbered':\n      prefix = `${index + 1}.`;\n      break;\n    default:\n      prefix = '- [ ]';\n      break;\n  }\n\n  // Build the item text\n  let text = escapeMarkdown(item.text);\n\n  // Add inline metadata\n  const metadata: string[] = [];\n  if (includeAssignee && item.assignee) {\n    metadata.push(`@${item.assignee}`);\n  }\n  if (includeDueDate && item.dueDate) {\n    metadata.push(`due: ${item.dueDate}`);\n  }\n  if (includeMeetingTitle && isAggregatedItem(item)) {\n    metadata.push(`*${item.transcriptTitle}*`);\n  }\n\n  if (metadata.length > 0) {\n    text += ` (${metadata.join(', ')})`;\n  }\n\n  return `${prefix} ${text}`;\n}\n\n/** Group items by a key function */\nfunction groupBy<T>(items: T[], keyFn: (item: T) => string): Map<string, T[]> {\n  const groups = new Map<string, T[]>();\n  for (const item of items) {\n    const key = keyFn(item);\n    const group = groups.get(key);\n    if (group) {\n      group.push(item);\n    } else {\n      groups.set(key, [item]);\n    }\n  }\n  return groups;\n}\n\n/** Format summary line for aggregated result */\nfunction formatSummaryLine(result: AggregatedActionItemsResult): string {\n  return `**Summary:** ${result.totalItems} items from ${result.transcriptsProcessed} meetings (${result.assignedItems} assigned, ${result.datedItems} with due dates)`;\n}\n\n/** Sort group keys with Unassigned last */\nfunction sortGroupKeys(keys: string[]): string[] {\n  return keys.sort((a, b) => {\n    if (a === 'Unassigned') return 1;\n    if (b === 'Unassigned') return -1;\n    return a.localeCompare(b);\n  });\n}\n\ntype ItemOptions = Required<\n  Pick<\n    ActionItemsMarkdownOptions,\n    'style' | 'includeAssignee' | 'includeDueDate' | 'includeMeetingTitle'\n  >\n>;\n\n/** Format items as grouped markdown sections */\nfunction formatGroupedItems(\n  result: AggregatedActionItemsResult,\n  groupByOption: 'assignee' | 'transcript' | 'date',\n  itemOptions: ItemOptions\n): string[] {\n  const lines: string[] = [];\n  const keyFn = getGroupKeyFn(groupByOption);\n  const groups = groupBy(result.items, keyFn);\n  const sortedKeys = sortGroupKeys(Array.from(groups.keys()));\n\n  for (const key of sortedKeys) {\n    const groupItems = groups.get(key);\n    if (!groupItems) continue;\n\n    lines.push(`### ${key}`);\n    lines.push('');\n    groupItems.forEach((item, index) => {\n      lines.push(formatItem(item, index, itemOptions));\n    });\n    lines.push('');\n  }\n\n  return lines;\n}\n\n/** Format items as flat list */\nfunction formatFlatItems(items: ActionItem[], itemOptions: ItemOptions): string[] {\n  return items.map((item, index) => formatItem(item, index, itemOptions));\n}\n\n/**\n * Format action items as Markdown.\n *\n * Supports multiple styles (checkbox, bullet, numbered), grouping options,\n * inline metadata, and presets for popular tools.\n *\n * @param result - Action items result (single or aggregated)\n * @param options - Formatting options\n * @returns Formatted markdown string\n *\n * @example\n * ```typescript\n * const markdown = formatActionItemsMarkdown(result, {\n *   style: 'checkbox',\n *   groupBy: 'assignee',\n *   includeSummary: true,\n *   preset: 'notion',\n * });\n * ```\n */\nexport function formatActionItemsMarkdown(\n  result: ActionItemsResult | AggregatedActionItemsResult,\n  options: ActionItemsMarkdownOptions = {}\n): string {\n  if (result.items.length === 0) {\n    return '';\n  }\n\n  const presetOptions = getPresetOptions(options.preset);\n  const mergedOptions = { ...presetOptions, ...options };\n\n  const {\n    style = 'checkbox',\n    groupBy: groupByOption = 'none',\n    includeAssignee = false,\n    includeDueDate = false,\n    includeMeetingTitle = false,\n    includeSummary = false,\n  } = mergedOptions;\n\n  const lines: string[] = [];\n\n  if (includeSummary && isAggregatedResult(result)) {\n    lines.push(formatSummaryLine(result));\n    lines.push('');\n  }\n\n  const itemOptions = { style, includeAssignee, includeDueDate, includeMeetingTitle };\n\n  const shouldGroup = groupByOption !== 'none' && isAggregatedResult(result);\n  if (shouldGroup) {\n    lines.push(...formatGroupedItems(result, groupByOption, itemOptions));\n  } else {\n    lines.push(...formatFlatItems(result.items, itemOptions));\n  }\n\n  return lines.join('\\n').trim();\n}\n\n/** Get the grouping key function */\nfunction getGroupKeyFn(\n  groupBy: 'assignee' | 'transcript' | 'date'\n): (item: AggregatedActionItem) => string {\n  switch (groupBy) {\n    case 'assignee':\n      return (item) => item.assignee ?? 'Unassigned';\n    case 'transcript':\n      return (item) => item.transcriptTitle;\n    case 'date':\n      return (item) => item.transcriptDate;\n  }\n}\n","import { RateLimitError } from '../errors.js';\n\n/**\n * Options for batch processing.\n */\nexport interface BatchOptions {\n  /**\n   * Number of concurrent operations.\n   * Currently only sequential (1) is supported.\n   * @default 1\n   */\n  concurrency?: number;\n  /**\n   * Delay in milliseconds between operations.\n   * @default 100\n   */\n  delayMs?: number;\n  /**\n   * Whether to automatically handle rate limit errors.\n   * When true, waits for retryAfter and retries.\n   * @default true\n   */\n  handleRateLimit?: boolean;\n  /**\n   * Maximum number of rate limit retries per item.\n   * @default 3\n   */\n  maxRateLimitRetries?: number;\n}\n\n/**\n * Result of a batch operation on a single item.\n */\nexport type BatchResult<T, R> =\n  | { item: T; result: R; error?: never }\n  | { item: T; result?: never; error: Error };\n\n/**\n * Process items in batch with rate limiting and error handling.\n *\n * Yields results as they complete, allowing streaming processing.\n * On rate limit errors, automatically waits and retries if handleRateLimit is true.\n *\n * @param items - Items to process (sync or async iterable)\n * @param processor - Function to process each item\n * @param options - Batch processing options\n * @returns AsyncIterable yielding results (success or error) for each item\n *\n * @example\n * ```typescript\n * import { batch, FirefliesClient } from 'fireflies-api';\n *\n * const client = new FirefliesClient({ apiKey: 'your-api-key' });\n * const ids = ['id1', 'id2', 'id3'];\n *\n * for await (const result of batch(ids, id => client.transcripts.get(id))) {\n *   if (result.error) {\n *     console.error(`Failed to fetch ${result.item}: ${result.error.message}`);\n *   } else {\n *     console.log(`Got ${result.result.title}`);\n *   }\n * }\n * ```\n */\nexport async function* batch<T, R>(\n  items: Iterable<T> | AsyncIterable<T>,\n  processor: (item: T) => Promise<R>,\n  options: BatchOptions = {}\n): AsyncIterable<BatchResult<T, R>> {\n  const { delayMs = 100, handleRateLimit = true, maxRateLimitRetries = 3 } = options;\n\n  let isFirst = true;\n\n  for await (const item of items) {\n    // Add delay between items (not before first)\n    if (!isFirst && delayMs > 0) {\n      await delay(delayMs);\n    }\n    isFirst = false;\n\n    yield await processWithRetry(item, processor, {\n      handleRateLimit,\n      maxRateLimitRetries,\n    });\n  }\n}\n\n/**\n * Process all items in batch and collect results.\n *\n * Unlike the streaming `batch()`, this waits for all items to complete\n * and returns results as an array.\n *\n * @param items - Array of items to process\n * @param processor - Function to process each item\n * @param options - Batch processing options plus continueOnError\n * @returns Array of successful results. When continueOnError is false, results\n *   match input order. When true, failed items are omitted (array may be shorter).\n * @throws First error encountered if continueOnError is false (default)\n *\n * @example\n * ```typescript\n * import { batchAll, FirefliesClient } from 'fireflies-api';\n *\n * const client = new FirefliesClient({ apiKey: 'your-api-key' });\n * const ids = ['id1', 'id2', 'id3'];\n *\n * // Throws on first error\n * const transcripts = await batchAll(ids, id => client.transcripts.get(id));\n *\n * // Continues on error, collects successful results\n * const results = await batchAll(\n *   ids,\n *   id => client.transcripts.get(id),\n *   { continueOnError: true }\n * );\n * ```\n */\nexport async function batchAll<T, R>(\n  items: T[],\n  processor: (item: T) => Promise<R>,\n  options: BatchOptions & { continueOnError?: boolean } = {}\n): Promise<R[]> {\n  const { continueOnError = false, ...batchOptions } = options;\n  const results: R[] = [];\n  const errors: Error[] = [];\n\n  for await (const batchResult of batch(items, processor, batchOptions)) {\n    if (batchResult.error) {\n      if (!continueOnError) {\n        throw batchResult.error;\n      }\n      errors.push(batchResult.error);\n    } else {\n      results.push(batchResult.result);\n    }\n  }\n\n  return results;\n}\n\n/**\n * Process a single item with rate limit retry logic.\n */\nasync function processWithRetry<T, R>(\n  item: T,\n  processor: (item: T) => Promise<R>,\n  options: { handleRateLimit: boolean; maxRateLimitRetries: number }\n): Promise<BatchResult<T, R>> {\n  const { handleRateLimit, maxRateLimitRetries } = options;\n  let retries = 0;\n\n  while (true) {\n    try {\n      const result = await processor(item);\n      return { item, result };\n    } catch (err) {\n      // Handle rate limit with retry\n      if (handleRateLimit && err instanceof RateLimitError && retries < maxRateLimitRetries) {\n        const waitTime = err.retryAfter ?? 1000;\n        await delay(waitTime);\n        retries++;\n        continue;\n      }\n\n      // Return error for this item\n      return {\n        item,\n        error: err instanceof Error ? err : new Error(String(err)),\n      };\n    }\n  }\n}\n\n/**\n * Delay execution for a specified time.\n */\nfunction delay(ms: number): Promise<void> {\n  return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","/**\n * Extract domain from email address.\n *\n * @param email - Email address\n * @returns Lowercase domain, or empty string if invalid\n *\n * @example\n * ```typescript\n * extractDomain('user@company.com'); // 'company.com'\n * extractDomain('User@EXAMPLE.ORG'); // 'example.org'\n * extractDomain('invalid'); // ''\n * ```\n */\nexport function extractDomain(email: string): string {\n  const atIndex = email.indexOf('@');\n  if (atIndex < 0) return '';\n  const domain = email.slice(atIndex + 1).toLowerCase();\n  return domain || '';\n}\n\n/**\n * Check if any participant has an email outside the given domain.\n *\n * @param participants - List of participant email addresses\n * @param internalDomain - The internal/company domain to check against\n * @returns True if at least one participant has a different domain\n *\n * @example\n * ```typescript\n * hasExternalParticipants(['a@company.com', 'b@external.com'], 'company.com'); // true\n * hasExternalParticipants(['a@company.com', 'b@company.com'], 'company.com'); // false\n * ```\n */\nexport function hasExternalParticipants(participants: string[], internalDomain: string): boolean {\n  const normalizedInternal = internalDomain.toLowerCase();\n  return participants.some((email) => {\n    const domain = extractDomain(email);\n    return domain !== '' && domain !== normalizedInternal;\n  });\n}\n","import type { TranscriptionChunk } from '../realtime/types.js';\nimport type { Sentence, Summary, Transcript } from '../types/transcript.js';\n\n/**\n * Options for transcriptToMarkdown().\n */\nexport interface MarkdownExportOptions {\n  /** Include meeting metadata header (title, date, participants, duration). Default: true */\n  includeMetadata?: boolean;\n  /** Include AI-generated summary sections. Default: true */\n  includeSummary?: boolean;\n  /** Include action items section. Default: true */\n  includeActionItems?: boolean;\n  /** Format for action items: checkbox or plain list. Default: 'checkbox' */\n  actionItemFormat?: 'checkbox' | 'list';\n  /** Include timestamps for each sentence. Default: false */\n  includeTimestamps?: boolean;\n  /** How to format speaker names. Default: 'bold' */\n  speakerFormat?: 'bold' | 'plain';\n  /** Group consecutive sentences by same speaker. Default: true */\n  groupBySpeaker?: boolean;\n  /** Write output to file path (Node.js only). If set, also returns the string. */\n  outputPath?: string;\n}\n\n/**\n * Options for chunksToMarkdown().\n */\nexport interface ChunksExportOptions {\n  /** Meeting title (chunks don't include metadata). Default: 'Live Transcript' */\n  title?: string;\n  /** Include timestamps for each chunk. Default: false */\n  includeTimestamps?: boolean;\n  /** How to format speaker names. Default: 'bold' */\n  speakerFormat?: 'bold' | 'plain';\n  /** Group consecutive chunks by same speaker. Default: true */\n  groupBySpeaker?: boolean;\n  /** Write output to file path (Node.js only). If set, also returns the string. */\n  outputPath?: string;\n}\n\nconst DEFAULT_OPTIONS: Required<Omit<MarkdownExportOptions, 'outputPath'>> = {\n  includeMetadata: true,\n  includeSummary: true,\n  includeActionItems: true,\n  actionItemFormat: 'checkbox',\n  includeTimestamps: false,\n  speakerFormat: 'bold',\n  groupBySpeaker: true,\n};\n\nconst DEFAULT_CHUNKS_OPTIONS: Required<Omit<ChunksExportOptions, 'outputPath'>> = {\n  title: 'Live Transcript',\n  includeTimestamps: false,\n  speakerFormat: 'bold',\n  groupBySpeaker: true,\n};\n\n/**\n * Convert a completed Fireflies transcript to well-formatted Markdown.\n *\n * @param transcript - The transcript to convert\n * @param options - Formatting options\n * @returns Markdown string representation of the transcript\n *\n * @example\n * ```typescript\n * import { FirefliesClient, transcriptToMarkdown } from 'fireflies-api';\n *\n * const client = new FirefliesClient({ apiKey: 'your-api-key' });\n * const transcript = await client.transcripts.get('transcript-id');\n *\n * // Basic usage\n * const markdown = await transcriptToMarkdown(transcript);\n *\n * // With options\n * const markdown = await transcriptToMarkdown(transcript, {\n *   includeTimestamps: true,\n *   actionItemFormat: 'list',\n * });\n *\n * // Write to file\n * const markdown = await transcriptToMarkdown(transcript, {\n *   outputPath: './meeting-notes.md',\n * });\n * ```\n */\nexport async function transcriptToMarkdown(\n  transcript: Transcript,\n  options: MarkdownExportOptions = {}\n): Promise<string> {\n  const opts = { ...DEFAULT_OPTIONS, ...options };\n  const sections: string[] = [];\n\n  if (opts.includeMetadata) {\n    sections.push(formatMetadata(transcript));\n  }\n\n  if (opts.includeSummary && transcript.summary) {\n    sections.push(formatSummary(transcript.summary, opts));\n  }\n\n  if (transcript.sentences && transcript.sentences.length > 0) {\n    sections.push(formatTranscript(transcript.sentences, opts));\n  }\n\n  const content = sections.join('\\n\\n---\\n\\n');\n  await writeIfOutputPath(content, options.outputPath);\n  return content;\n}\n\n/**\n * Convert realtime transcription chunks to well-formatted Markdown.\n *\n * @param chunks - Array of transcription chunks from realtime stream\n * @param options - Formatting options\n * @returns Markdown string representation of the chunks\n *\n * @example\n * ```typescript\n * import { FirefliesClient, chunksToMarkdown } from 'fireflies-api';\n *\n * const client = new FirefliesClient({ apiKey: 'your-api-key' });\n *\n * // Accumulate chunks from realtime stream\n * const chunks: TranscriptionChunk[] = [];\n * for await (const chunk of client.realtime.stream(meetingId)) {\n *   chunks.push(chunk);\n * }\n *\n * // Convert to markdown\n * const markdown = await chunksToMarkdown(chunks);\n *\n * // With options\n * const markdown = await chunksToMarkdown(chunks, {\n *   title: 'Team Standup',\n *   includeTimestamps: true,\n * });\n * ```\n */\nexport async function chunksToMarkdown(\n  chunks: TranscriptionChunk[],\n  options: ChunksExportOptions = {}\n): Promise<string> {\n  const opts = { ...DEFAULT_CHUNKS_OPTIONS, ...options };\n\n  const lines: string[] = [`# ${opts.title}`];\n\n  if (chunks.length === 0) {\n    lines.push('', '## Transcript', '', '*No transcription data*');\n  } else {\n    lines.push('', '## Transcript');\n\n    if (opts.groupBySpeaker) {\n      const groups = groupChunksBySpeaker(chunks);\n      for (const group of groups) {\n        lines.push('', formatChunkGroup(group, opts));\n      }\n    } else {\n      for (const chunk of chunks) {\n        lines.push('', formatChunk(chunk, opts));\n      }\n    }\n  }\n\n  const content = lines.join('\\n');\n  await writeIfOutputPath(content, options.outputPath);\n  return content;\n}\n\n// --- Internal helpers ---\n\nfunction formatMetadata(transcript: Transcript): string {\n  const lines = [`# ${transcript.title || 'Untitled Meeting'}`];\n\n  if (transcript.dateString) {\n    lines.push(`\\n**Date:** ${formatDate(transcript.dateString)}`);\n  }\n\n  // Calculate duration from last sentence end_time (more accurate than duration field)\n  const duration = calculateDuration(transcript);\n  if (duration > 0) {\n    lines.push(`**Duration:** ${formatDuration(duration)}`);\n  }\n\n  const participants = getParticipantNames(transcript);\n  if (participants.length > 0) {\n    lines.push(`**Participants:** ${participants.join(', ')}`);\n  }\n\n  return lines.join('\\n');\n}\n\n/**\n * Calculate actual meeting duration from sentence timestamps.\n * The API's duration field is often inaccurate, so we use the last sentence's end_time.\n */\nfunction calculateDuration(transcript: Transcript): number {\n  if (transcript.sentences && transcript.sentences.length > 0) {\n    const lastSentence = transcript.sentences[transcript.sentences.length - 1];\n    if (lastSentence) {\n      return parseFloat(lastSentence.end_time);\n    }\n  }\n  return transcript.duration || 0;\n}\n\nfunction formatSummary(\n  summary: Summary,\n  opts: Required<Omit<MarkdownExportOptions, 'outputPath'>>\n): string {\n  const sections: string[] = ['## Summary'];\n\n  if (summary.gist) {\n    sections.push('', summary.gist);\n  }\n\n  if (summary.bullet_gist) {\n    const bullets = parseMultilineField(summary.bullet_gist);\n    if (bullets.length > 0) {\n      sections.push('', '### Key Points');\n      sections.push(bullets.map((p) => `- ${p}`).join('\\n'));\n    }\n  }\n\n  if (opts.includeActionItems && summary.action_items) {\n    const items = parseMultilineField(summary.action_items);\n    if (items.length > 0) {\n      sections.push('', '### Action Items');\n      const prefix = opts.actionItemFormat === 'checkbox' ? '- [ ] ' : '- ';\n      sections.push(items.map((a) => `${prefix}${a}`).join('\\n'));\n    }\n  }\n\n  return sections.join('\\n');\n}\n\nfunction formatTranscript(\n  sentences: Sentence[],\n  opts: Required<Omit<MarkdownExportOptions, 'outputPath'>>\n): string {\n  const lines: string[] = ['## Transcript'];\n\n  if (opts.groupBySpeaker) {\n    const groups = groupSentencesBySpeaker(sentences);\n    for (const group of groups) {\n      lines.push('', formatSpeakerGroup(group, opts));\n    }\n  } else {\n    for (const sentence of sentences) {\n      lines.push('', formatSentence(sentence, opts));\n    }\n  }\n\n  return lines.join('\\n');\n}\n\ninterface SpeakerGroup {\n  speakerName: string;\n  sentences: Sentence[];\n}\n\nfunction groupSentencesBySpeaker(sentences: Sentence[]): SpeakerGroup[] {\n  const groups: SpeakerGroup[] = [];\n  let current: SpeakerGroup | null = null;\n\n  for (const sentence of sentences) {\n    if (!current || current.speakerName !== sentence.speaker_name) {\n      current = { speakerName: sentence.speaker_name, sentences: [] };\n      groups.push(current);\n    }\n    current.sentences.push(sentence);\n  }\n\n  return groups;\n}\n\nfunction formatSpeakerGroup(\n  group: SpeakerGroup,\n  opts: Required<Omit<MarkdownExportOptions, 'outputPath'>>\n): string {\n  const speaker = formatSpeakerName(group.speakerName, opts.speakerFormat);\n  const text = group.sentences.map((s) => s.text).join(' ');\n\n  const firstSentence = group.sentences[0];\n  if (opts.includeTimestamps && firstSentence) {\n    const timestamp = formatTimestamp(firstSentence.start_time);\n    return `${timestamp} ${speaker} ${text}`;\n  }\n  return `${speaker} ${text}`;\n}\n\nfunction formatSentence(\n  sentence: Sentence,\n  opts: Required<Omit<MarkdownExportOptions, 'outputPath'>>\n): string {\n  const speaker = formatSpeakerName(sentence.speaker_name, opts.speakerFormat);\n\n  if (opts.includeTimestamps) {\n    const timestamp = formatTimestamp(sentence.start_time);\n    return `${timestamp} ${speaker} ${sentence.text}`;\n  }\n  return `${speaker} ${sentence.text}`;\n}\n\ninterface ChunkGroup {\n  speakerName: string;\n  chunks: TranscriptionChunk[];\n}\n\nfunction groupChunksBySpeaker(chunks: TranscriptionChunk[]): ChunkGroup[] {\n  const groups: ChunkGroup[] = [];\n  let current: ChunkGroup | null = null;\n\n  for (const chunk of chunks) {\n    if (!current || current.speakerName !== chunk.speaker_name) {\n      current = { speakerName: chunk.speaker_name, chunks: [] };\n      groups.push(current);\n    }\n    current.chunks.push(chunk);\n  }\n\n  return groups;\n}\n\nfunction formatChunkGroup(\n  group: ChunkGroup,\n  opts: Required<Omit<ChunksExportOptions, 'outputPath'>>\n): string {\n  const speaker = formatSpeakerName(group.speakerName, opts.speakerFormat);\n  const text = group.chunks.map((c) => c.text).join(' ');\n\n  const firstChunk = group.chunks[0];\n  if (opts.includeTimestamps && firstChunk) {\n    const timestamp = formatTimestamp(firstChunk.start_time.toString());\n    return `${timestamp} ${speaker} ${text}`;\n  }\n  return `${speaker} ${text}`;\n}\n\nfunction formatChunk(\n  chunk: TranscriptionChunk,\n  opts: Required<Omit<ChunksExportOptions, 'outputPath'>>\n): string {\n  const speaker = formatSpeakerName(chunk.speaker_name, opts.speakerFormat);\n\n  if (opts.includeTimestamps) {\n    const timestamp = formatTimestamp(chunk.start_time.toString());\n    return `${timestamp} ${speaker} ${chunk.text}`;\n  }\n  return `${speaker} ${chunk.text}`;\n}\n\nfunction formatSpeakerName(name: string, format: 'bold' | 'plain'): string {\n  switch (format) {\n    case 'bold':\n      return `**${name}:**`;\n    case 'plain':\n      return `${name}:`;\n  }\n}\n\nfunction formatTimestamp(startTime: string): string {\n  const seconds = parseFloat(startTime);\n  const mins = Math.floor(seconds / 60);\n  const secs = Math.floor(seconds % 60);\n  return `[${mins}:${secs.toString().padStart(2, '0')}]`;\n}\n\nfunction formatDuration(seconds: number): string {\n  const hours = Math.floor(seconds / 3600);\n  const mins = Math.floor((seconds % 3600) / 60);\n  if (hours > 0) {\n    return `${hours}h ${mins}m`;\n  }\n  return `${mins} minutes`;\n}\n\nfunction formatDate(isoString: string): string {\n  return new Date(isoString).toLocaleDateString('en-US', {\n    weekday: 'long',\n    year: 'numeric',\n    month: 'long',\n    day: 'numeric',\n  });\n}\n\nfunction getParticipantNames(transcript: Transcript): string[] {\n  if (transcript.meeting_attendees?.length) {\n    return transcript.meeting_attendees\n      .map((a) => a.displayName || a.name || a.email)\n      .filter(Boolean) as string[];\n  }\n  return transcript.speakers?.map((s) => s.name) || [];\n}\n\n/**\n * Parse newline-separated summary fields into an array.\n * Handles both \\n and actual newlines, filters empty lines.\n */\nfunction parseMultilineField(value: string): string[] {\n  return value\n    .split(/\\n/)\n    .map((line) => line.trim())\n    .filter((line) => line.length > 0);\n}\n\nasync function writeIfOutputPath(content: string, outputPath?: string): Promise<void> {\n  if (outputPath) {\n    const { writeFile } = await import('node:fs/promises');\n    await writeFile(outputPath, content, 'utf-8');\n  }\n}\n","import type { Sentence, Transcript } from '../types/transcript.js';\nimport { transcriptToMarkdown } from './markdown.js';\n\n/**\n * Export format types supported by bulk export.\n */\nexport type ExportFormat = 'markdown' | 'json' | 'txt' | 'csv';\n\n/**\n * Options for transcriptToText().\n */\nexport interface TextExportOptions {\n  /** Include timestamps for each speaker turn. Default: false */\n  includeTimestamps?: boolean;\n  /** Include meeting metadata header (title, date, participants). Default: true */\n  includeMetadata?: boolean;\n}\n\n/**\n * Options for transcriptToCsv().\n */\nexport interface CsvExportOptions {\n  /** Include CSV header row. Default: true */\n  includeHeader?: boolean;\n  /** Field delimiter. Default: ',' */\n  delimiter?: string;\n}\n\n/**\n * A file ready for export.\n */\nexport interface ExportFile {\n  /** Filename with extension */\n  filename: string;\n  /** File content as string */\n  content: string;\n}\n\nconst DEFAULT_TEXT_OPTIONS: Required<TextExportOptions> = {\n  includeTimestamps: false,\n  includeMetadata: true,\n};\n\nconst DEFAULT_CSV_OPTIONS: Required<CsvExportOptions> = {\n  includeHeader: true,\n  delimiter: ',',\n};\n\n/**\n * Convert a transcript to plain text format.\n *\n * @param transcript - The transcript to convert\n * @param options - Formatting options\n * @returns Plain text string with speaker labels\n *\n * @example\n * ```typescript\n * import { transcriptToText } from 'fireflies-api';\n *\n * const text = transcriptToText(transcript);\n * await writeFile('meeting.txt', text);\n * ```\n */\nexport function transcriptToText(transcript: Transcript, options: TextExportOptions = {}): string {\n  const opts = { ...DEFAULT_TEXT_OPTIONS, ...options };\n  const sections: string[] = [];\n\n  if (opts.includeMetadata) {\n    sections.push(formatTextMetadata(transcript));\n  }\n\n  if (transcript.sentences && transcript.sentences.length > 0) {\n    sections.push(formatTextTranscript(transcript.sentences, opts));\n  }\n\n  return sections.join('\\n\\n');\n}\n\n/**\n * Convert a transcript to CSV format with one row per sentence.\n *\n * @param transcript - The transcript to convert\n * @param options - CSV formatting options\n * @returns CSV string with headers and properly escaped values\n *\n * @example\n * ```typescript\n * import { transcriptToCsv } from 'fireflies-api';\n *\n * const csv = transcriptToCsv(transcript);\n * await writeFile('meeting.csv', csv);\n * ```\n */\nexport function transcriptToCsv(transcript: Transcript, options: CsvExportOptions = {}): string {\n  const opts = { ...DEFAULT_CSV_OPTIONS, ...options };\n  const d = opts.delimiter;\n  const lines: string[] = [];\n\n  if (opts.includeHeader) {\n    lines.push(`timestamp${d}speaker${d}text${d}is_question${d}is_task`);\n  }\n\n  for (const sentence of transcript.sentences) {\n    const isQuestion = Boolean(sentence.ai_filters?.question);\n    const isTask = Boolean(sentence.ai_filters?.task);\n    const row = [\n      sentence.start_time,\n      escapeCsvField(sentence.speaker_name, d),\n      escapeCsvField(sentence.text, d),\n      String(isQuestion),\n      String(isTask),\n    ];\n    lines.push(row.join(d));\n  }\n\n  return lines.join('\\n');\n}\n\n/**\n * Sanitize a string for use as a filename.\n *\n * @param title - The title to sanitize\n * @returns A filesystem-safe filename\n *\n * @example\n * ```typescript\n * sanitizeFilename('Weekly Team Standup!') // 'weekly-team-standup'\n * ```\n */\nexport function sanitizeFilename(title: string): string {\n  if (!title.trim()) {\n    return 'untitled';\n  }\n  return title\n    .toLowerCase()\n    .replace(/[^a-z0-9]+/g, '-')\n    .replace(/-+/g, '-')\n    .replace(/^-|-$/g, '')\n    .slice(0, 100);\n}\n\n/**\n * Generate an export filename from a transcript.\n *\n * @param transcript - The transcript to generate a filename for\n * @param extension - File extension (without dot)\n * @returns Filename in format: YYYY-MM-DD-title.ext\n *\n * @example\n * ```typescript\n * generateExportFilename(transcript, 'md')\n * // '2024-01-15-weekly-standup.md'\n * ```\n */\nexport function generateExportFilename(transcript: Transcript, extension: string): string {\n  const sanitizedTitle = sanitizeFilename(transcript.title);\n  let datePrefix = '';\n\n  if (transcript.dateString) {\n    try {\n      const date = new Date(transcript.dateString);\n      if (!Number.isNaN(date.getTime())) {\n        datePrefix = `${date.toISOString().slice(0, 10)}-`;\n      }\n    } catch {\n      // Invalid date - skip prefix\n    }\n  }\n\n  return `${datePrefix}${sanitizedTitle}.${extension}`;\n}\n\n/**\n * Export a transcript to the specified format.\n *\n * @param transcript - The transcript to export\n * @param format - Target format (markdown, json, txt, csv)\n * @returns Formatted string content\n *\n * @example\n * ```typescript\n * const content = await exportTranscript(transcript, 'markdown');\n * await writeFile('meeting.md', content);\n * ```\n */\nexport async function exportTranscript(\n  transcript: Transcript,\n  format: ExportFormat\n): Promise<string> {\n  switch (format) {\n    case 'markdown':\n      return transcriptToMarkdown(transcript);\n    case 'json':\n      return JSON.stringify(transcript, null, 2);\n    case 'txt':\n      return transcriptToText(transcript);\n    case 'csv':\n      return transcriptToCsv(transcript);\n  }\n}\n\n/**\n * Create a zip archive from exported files.\n * Pure function - returns Buffer, no I/O.\n *\n * @param files - Array of files to add to the archive\n * @returns Promise resolving to zip Buffer\n *\n * @example\n * ```typescript\n * const files = [\n *   { filename: 'meeting1.md', content: '# Meeting 1' },\n *   { filename: 'meeting2.md', content: '# Meeting 2' },\n * ];\n * const zipBuffer = await createZipArchive(files);\n * await writeFile('exports.zip', zipBuffer);\n * ```\n */\nexport async function createZipArchive(files: ExportFile[]): Promise<Buffer> {\n  // Use archiver for zip creation\n  const archiver = await import('archiver');\n  const { Writable } = await import('node:stream');\n\n  return new Promise((resolve, reject) => {\n    const chunks: Buffer[] = [];\n    const archive = archiver.default('zip', { zlib: { level: 9 } });\n\n    // Collect output chunks\n    const writable = new Writable({\n      write(chunk: Buffer, _encoding, callback) {\n        chunks.push(chunk);\n        callback();\n      },\n    });\n\n    writable.on('finish', () => {\n      resolve(Buffer.concat(chunks));\n    });\n\n    archive.on('error', reject);\n    archive.pipe(writable);\n\n    // Add files to archive\n    for (const file of files) {\n      archive.append(file.content, { name: file.filename });\n    }\n\n    archive.finalize();\n  });\n}\n\n// --- Internal helpers ---\n\nfunction formatTextMetadata(transcript: Transcript): string {\n  const lines: string[] = [];\n\n  lines.push(transcript.title || 'Untitled Meeting');\n\n  if (transcript.dateString) {\n    lines.push(`Date: ${formatDate(transcript.dateString)}`);\n  }\n\n  const participants = getParticipantNames(transcript);\n  if (participants.length > 0) {\n    lines.push(`Participants: ${participants.join(', ')}`);\n  }\n\n  return lines.join('\\n');\n}\n\nfunction formatTextTranscript(sentences: Sentence[], opts: Required<TextExportOptions>): string {\n  const groups = groupSentencesBySpeaker(sentences);\n  const lines: string[] = [];\n\n  for (const group of groups) {\n    const text = group.sentences.map((s) => s.text).join(' ');\n    const speaker = group.speakerName || 'Unknown';\n\n    const firstSentence = group.sentences[0];\n    if (opts.includeTimestamps && firstSentence) {\n      const timestamp = formatTimestamp(firstSentence.start_time);\n      lines.push(`${timestamp} ${speaker}: ${text}`);\n    } else {\n      lines.push(`${speaker}: ${text}`);\n    }\n  }\n\n  return lines.join('\\n');\n}\n\ninterface SpeakerGroup {\n  speakerName: string;\n  sentences: Sentence[];\n}\n\nfunction groupSentencesBySpeaker(sentences: Sentence[]): SpeakerGroup[] {\n  const groups: SpeakerGroup[] = [];\n  let current: SpeakerGroup | null = null;\n\n  for (const sentence of sentences) {\n    if (!current || current.speakerName !== sentence.speaker_name) {\n      current = { speakerName: sentence.speaker_name, sentences: [] };\n      groups.push(current);\n    }\n    current.sentences.push(sentence);\n  }\n\n  return groups;\n}\n\nfunction formatTimestamp(startTime: string): string {\n  const seconds = parseFloat(startTime);\n  const mins = Math.floor(seconds / 60);\n  const secs = Math.floor(seconds % 60);\n  return `[${mins}:${secs.toString().padStart(2, '0')}]`;\n}\n\nfunction formatDate(isoString: string): string {\n  return new Date(isoString).toLocaleDateString('en-US', {\n    weekday: 'long',\n    year: 'numeric',\n    month: 'long',\n    day: 'numeric',\n  });\n}\n\nfunction getParticipantNames(transcript: Transcript): string[] {\n  if (transcript.meeting_attendees?.length) {\n    return transcript.meeting_attendees\n      .map((a) => a.displayName || a.name || a.email)\n      .filter(Boolean) as string[];\n  }\n  return transcript.speakers?.map((s) => s.name) || [];\n}\n\n/**\n * Escape a field for CSV output.\n * If the field contains the delimiter, quotes, or newlines, wrap in quotes.\n * Double any existing quotes.\n */\nfunction escapeCsvField(field: string, delimiter: string): string {\n  if (field.includes('\"') || field.includes(delimiter) || field.includes('\\n')) {\n    return `\"${field.replace(/\"/g, '\"\"')}\"`;\n  }\n  return field;\n}\n","import type { Sentence, Transcript } from '../types/transcript.js';\n\n// Re-export types for convenience\nexport type {\n  DayOfWeekStats,\n  DayStats,\n  MeetingInsights,\n  MeetingInsightsOptions,\n  ParticipantStats,\n  SpeakerInsightStats,\n  TimeGroupStats,\n} from '../types/meeting-insights.js';\n\nimport type {\n  DayOfWeekStats,\n  DayStats,\n  MeetingInsights,\n  MeetingInsightsOptions,\n  ParticipantStats,\n  SpeakerInsightStats,\n  TimeGroupStats,\n} from '../types/meeting-insights.js';\n\n/**\n * Analyze multiple transcripts to compute aggregate meeting statistics.\n *\n * Pure function - no API calls, fully testable. Computes duration totals,\n * day of week distribution, participant counts, speaker talk times, and\n * time-based groupings.\n *\n * @param transcripts - Array of transcripts to analyze\n * @param options - Analysis options for filtering and grouping\n * @returns Aggregate meeting insights\n *\n * @example\n * ```typescript\n * import { FirefliesClient, analyzeMeetings } from 'fireflies-api';\n *\n * const client = new FirefliesClient({ apiKey: 'your-api-key' });\n *\n * // Fetch transcripts\n * const transcripts: Transcript[] = [];\n * for await (const t of client.transcripts.listAll({ mine: true })) {\n *   transcripts.push(t);\n * }\n *\n * // Analyze\n * const insights = analyzeMeetings(transcripts, {\n *   groupBy: 'week',\n *   topSpeakersCount: 5,\n * });\n *\n * console.log(`${insights.totalMeetings} meetings, ${insights.totalDurationMinutes} minutes total`);\n * console.log(`Average: ${insights.averageDurationMinutes} minutes`);\n * ```\n */\nexport function analyzeMeetings(\n  transcripts: Transcript[],\n  options: MeetingInsightsOptions = {}\n): MeetingInsights {\n  const { speakers, groupBy, topSpeakersCount = 10, topParticipantsCount = 10 } = options;\n\n  if (transcripts.length === 0) {\n    return emptyInsights();\n  }\n\n  // Calculate summary stats\n  const totalDurationMinutes = sumDurations(transcripts);\n  const averageDurationMinutes = totalDurationMinutes / transcripts.length;\n\n  // Calculate day of week distribution\n  const byDayOfWeek = calculateDayOfWeekStats(transcripts);\n\n  // Calculate time group stats if requested\n  const byTimeGroup = groupBy ? calculateTimeGroupStats(transcripts, groupBy) : undefined;\n\n  // Calculate participant stats\n  const participantData = aggregateParticipants(transcripts);\n  const totalUniqueParticipants = participantData.uniqueEmails.size;\n  const averageParticipantsPerMeeting = calculateAverageParticipants(transcripts);\n  const topParticipants = buildTopParticipants(participantData.stats, topParticipantsCount);\n\n  // Calculate speaker stats\n  const speakerData = aggregateSpeakers(transcripts, speakers);\n  const totalUniqueSpeakers = speakerData.uniqueNames.size;\n  const topSpeakers = buildTopSpeakers(speakerData.stats, topSpeakersCount);\n\n  // Calculate date range\n  const { earliestMeeting, latestMeeting } = findDateRange(transcripts);\n\n  return {\n    totalMeetings: transcripts.length,\n    totalDurationMinutes,\n    averageDurationMinutes,\n    byDayOfWeek,\n    byTimeGroup,\n    totalUniqueParticipants,\n    averageParticipantsPerMeeting,\n    topParticipants,\n    totalUniqueSpeakers,\n    topSpeakers,\n    earliestMeeting,\n    latestMeeting,\n  };\n}\n\nfunction emptyInsights(): MeetingInsights {\n  return {\n    totalMeetings: 0,\n    totalDurationMinutes: 0,\n    averageDurationMinutes: 0,\n    byDayOfWeek: emptyDayOfWeekStats(),\n    byTimeGroup: undefined,\n    totalUniqueParticipants: 0,\n    averageParticipantsPerMeeting: 0,\n    topParticipants: [],\n    totalUniqueSpeakers: 0,\n    topSpeakers: [],\n    earliestMeeting: '',\n    latestMeeting: '',\n  };\n}\n\nfunction emptyDayOfWeekStats(): DayOfWeekStats {\n  const emptyDay = (): DayStats => ({ count: 0, totalMinutes: 0 });\n  return {\n    monday: emptyDay(),\n    tuesday: emptyDay(),\n    wednesday: emptyDay(),\n    thursday: emptyDay(),\n    friday: emptyDay(),\n    saturday: emptyDay(),\n    sunday: emptyDay(),\n  };\n}\n\nfunction sumDurations(transcripts: Transcript[]): number {\n  return transcripts.reduce((sum, t) => sum + (t.duration ?? 0), 0);\n}\n\nfunction calculateDayOfWeekStats(transcripts: Transcript[]): DayOfWeekStats {\n  const stats = emptyDayOfWeekStats();\n  const dayNames: (keyof DayOfWeekStats)[] = [\n    'sunday',\n    'monday',\n    'tuesday',\n    'wednesday',\n    'thursday',\n    'friday',\n    'saturday',\n  ];\n\n  for (const t of transcripts) {\n    const date = parseDate(t.dateString);\n    if (!date) continue;\n\n    const dayIndex = date.getUTCDay();\n    const dayName = dayNames[dayIndex];\n    if (dayName) {\n      stats[dayName].count++;\n      stats[dayName].totalMinutes += t.duration ?? 0;\n    }\n  }\n\n  return stats;\n}\n\nfunction calculateTimeGroupStats(\n  transcripts: Transcript[],\n  groupBy: 'day' | 'week' | 'month'\n): TimeGroupStats[] {\n  const groups = new Map<string, { count: number; totalMinutes: number }>();\n\n  for (const t of transcripts) {\n    const date = parseDate(t.dateString);\n    if (!date) continue;\n\n    const period = formatPeriod(date, groupBy);\n    const existing = groups.get(period) ?? { count: 0, totalMinutes: 0 };\n    existing.count++;\n    existing.totalMinutes += t.duration ?? 0;\n    groups.set(period, existing);\n  }\n\n  // Convert to array and sort chronologically\n  const result: TimeGroupStats[] = [];\n  for (const [period, data] of groups) {\n    result.push({\n      period,\n      count: data.count,\n      totalMinutes: data.totalMinutes,\n      averageMinutes: data.totalMinutes / data.count,\n    });\n  }\n\n  result.sort((a, b) => a.period.localeCompare(b.period));\n  return result;\n}\n\nfunction formatPeriod(date: Date, groupBy: 'day' | 'week' | 'month'): string {\n  const year = date.getUTCFullYear();\n  const month = String(date.getUTCMonth() + 1).padStart(2, '0');\n  const day = String(date.getUTCDate()).padStart(2, '0');\n\n  switch (groupBy) {\n    case 'day':\n      return `${year}-${month}-${day}`;\n    case 'week':\n      return getISOWeek(date);\n    case 'month':\n      return `${year}-${month}`;\n  }\n}\n\nfunction getISOWeek(date: Date): string {\n  // ISO week calculation\n  const d = new Date(Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate()));\n  // Set to nearest Thursday: current date + 4 - current day number (Sunday = 0, Thursday = 4)\n  d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay() || 7));\n  // Get first day of year\n  const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));\n  // Calculate full weeks to nearest Thursday\n  const weekNumber = Math.ceil(((d.getTime() - yearStart.getTime()) / 86400000 + 1) / 7);\n  return `${d.getUTCFullYear()}-W${String(weekNumber).padStart(2, '0')}`;\n}\n\ninterface ParticipantData {\n  uniqueEmails: Set<string>;\n  stats: Map<string, { meetingCount: number; totalMinutes: number }>;\n}\n\nfunction aggregateParticipants(transcripts: Transcript[]): ParticipantData {\n  const uniqueEmails = new Set<string>();\n  const stats = new Map<string, { meetingCount: number; totalMinutes: number }>();\n\n  for (const t of transcripts) {\n    const participants = t.participants ?? [];\n    const seenInMeeting = new Set<string>();\n\n    for (const email of participants) {\n      const normalizedEmail = email.toLowerCase();\n\n      // Track unique participants\n      uniqueEmails.add(normalizedEmail);\n\n      // Avoid counting same participant twice in one meeting\n      if (seenInMeeting.has(normalizedEmail)) continue;\n      seenInMeeting.add(normalizedEmail);\n\n      // Update stats\n      const existing = stats.get(normalizedEmail) ?? { meetingCount: 0, totalMinutes: 0 };\n      existing.meetingCount++;\n      existing.totalMinutes += t.duration ?? 0;\n      stats.set(normalizedEmail, existing);\n    }\n  }\n\n  return { uniqueEmails, stats };\n}\n\nfunction calculateAverageParticipants(transcripts: Transcript[]): number {\n  if (transcripts.length === 0) return 0;\n\n  let totalParticipants = 0;\n  for (const t of transcripts) {\n    // Deduplicate within each meeting\n    const unique = new Set((t.participants ?? []).map((p) => p.toLowerCase()));\n    totalParticipants += unique.size;\n  }\n\n  return totalParticipants / transcripts.length;\n}\n\nfunction buildTopParticipants(\n  stats: Map<string, { meetingCount: number; totalMinutes: number }>,\n  limit: number\n): ParticipantStats[] {\n  const result: ParticipantStats[] = [];\n\n  for (const [email, data] of stats) {\n    result.push({\n      email,\n      meetingCount: data.meetingCount,\n      totalMinutes: data.totalMinutes,\n    });\n  }\n\n  // Sort by meeting count descending\n  result.sort((a, b) => b.meetingCount - a.meetingCount);\n\n  return result.slice(0, limit);\n}\n\ninterface SpeakerData {\n  uniqueNames: Set<string>;\n  stats: Map<string, { meetingCount: number; totalTalkTimeSeconds: number; meetings: Set<string> }>;\n}\n\nfunction aggregateSpeakers(transcripts: Transcript[], filterSpeakers?: string[]): SpeakerData {\n  const uniqueNames = new Set<string>();\n  const stats = new Map<\n    string,\n    { meetingCount: number; totalTalkTimeSeconds: number; meetings: Set<string> }\n  >();\n\n  const filterSet = filterSpeakers ? new Set(filterSpeakers) : null;\n\n  for (const t of transcripts) {\n    const sentences = t.sentences ?? [];\n\n    for (const sentence of sentences) {\n      const speakerName = sentence.speaker_name;\n\n      // Skip if filtering and speaker not in filter list\n      if (filterSet && !filterSet.has(speakerName)) continue;\n\n      uniqueNames.add(speakerName);\n\n      const existing = stats.get(speakerName) ?? {\n        meetingCount: 0,\n        totalTalkTimeSeconds: 0,\n        meetings: new Set<string>(),\n      };\n\n      // Add talk time\n      const duration = parseSentenceDuration(sentence);\n      existing.totalTalkTimeSeconds += duration;\n\n      // Track unique meetings\n      if (!existing.meetings.has(t.id)) {\n        existing.meetings.add(t.id);\n        existing.meetingCount++;\n      }\n\n      stats.set(speakerName, existing);\n    }\n  }\n\n  return { uniqueNames, stats };\n}\n\nfunction parseSentenceDuration(sentence: Sentence): number {\n  const start = Number.parseFloat(sentence.start_time);\n  const end = Number.parseFloat(sentence.end_time);\n  return Math.max(0, end - start);\n}\n\nfunction buildTopSpeakers(\n  stats: Map<string, { meetingCount: number; totalTalkTimeSeconds: number; meetings: Set<string> }>,\n  limit: number\n): SpeakerInsightStats[] {\n  const result: SpeakerInsightStats[] = [];\n\n  for (const [name, data] of stats) {\n    result.push({\n      name,\n      meetingCount: data.meetingCount,\n      totalTalkTimeSeconds: data.totalTalkTimeSeconds,\n      averageTalkTimeSeconds:\n        data.meetingCount > 0 ? data.totalTalkTimeSeconds / data.meetingCount : 0,\n    });\n  }\n\n  // Sort by total talk time descending\n  result.sort((a, b) => b.totalTalkTimeSeconds - a.totalTalkTimeSeconds);\n\n  return result.slice(0, limit);\n}\n\nfunction findDateRange(transcripts: Transcript[]): {\n  earliestMeeting: string;\n  latestMeeting: string;\n} {\n  let earliest: Date | null = null;\n  let latest: Date | null = null;\n\n  for (const t of transcripts) {\n    const date = parseDate(t.dateString);\n    if (!date) continue;\n\n    if (!earliest || date < earliest) {\n      earliest = date;\n    }\n    if (!latest || date > latest) {\n      latest = date;\n    }\n  }\n\n  return {\n    earliestMeeting: earliest ? formatDateOnly(earliest) : '',\n    latestMeeting: latest ? formatDateOnly(latest) : '',\n  };\n}\n\nfunction parseDate(dateString: string | undefined): Date | null {\n  if (!dateString) return null;\n  const date = new Date(dateString);\n  return Number.isNaN(date.getTime()) ? null : date;\n}\n\nfunction formatDateOnly(date: Date): string {\n  const year = date.getUTCFullYear();\n  const month = String(date.getUTCMonth() + 1).padStart(2, '0');\n  const day = String(date.getUTCDate()).padStart(2, '0');\n  return `${year}-${month}-${day}`;\n}\n","/**\n * Search helper functions for searching transcript content.\n */\n\nimport type { SearchMatch, SearchTranscriptOptions } from '../types/search.js';\nimport type { Sentence, Transcript } from '../types/transcript.js';\n\n/**\n * Escape special regex characters in a string for literal matching.\n */\nfunction escapeRegex(str: string): string {\n  return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Check if a sentence passes the speaker filter.\n */\nfunction matchesSpeaker(sentence: Sentence, speakerSet: Set<string> | null): boolean {\n  if (!speakerSet) return true;\n  return speakerSet.has(sentence.speaker_name.toLowerCase());\n}\n\n/**\n * Check if a sentence passes the AI filter requirements.\n */\nfunction matchesAIFilters(\n  sentence: Sentence,\n  filterQuestions: boolean,\n  filterTasks: boolean\n): boolean {\n  if (!filterQuestions && !filterTasks) return true;\n\n  const hasQuestion = Boolean(sentence.ai_filters?.question);\n  const hasTask = Boolean(sentence.ai_filters?.task);\n\n  // If both filters are set, match either (OR logic)\n  if (filterQuestions && filterTasks) {\n    return hasQuestion || hasTask;\n  }\n\n  if (filterQuestions) return hasQuestion;\n  if (filterTasks) return hasTask;\n\n  return true;\n}\n\n/**\n * Extract context sentences before and after a given index.\n */\nfunction extractContext(\n  sentences: Sentence[],\n  index: number,\n  contextLines: number\n): SearchMatch['context'] {\n  const beforeStart = Math.max(0, index - contextLines);\n  const afterEnd = Math.min(sentences.length, index + contextLines + 1);\n\n  return {\n    before: sentences.slice(beforeStart, index).map((s) => ({\n      speakerName: s.speaker_name,\n      text: s.text,\n    })),\n    after: sentences.slice(index + 1, afterEnd).map((s) => ({\n      speakerName: s.speaker_name,\n      text: s.text,\n    })),\n  };\n}\n\n/**\n * Convert a Sentence to the match result format.\n */\nfunction sentenceToMatch(\n  sentence: Sentence,\n  transcript: Transcript,\n  context: SearchMatch['context']\n): SearchMatch {\n  return {\n    transcriptId: transcript.id,\n    transcriptTitle: transcript.title,\n    transcriptDate: transcript.dateString,\n    transcriptUrl: transcript.transcript_url,\n    sentence: {\n      index: sentence.index,\n      text: sentence.text,\n      speakerName: sentence.speaker_name,\n      startTime: Number.parseFloat(sentence.start_time),\n      endTime: Number.parseFloat(sentence.end_time),\n      isQuestion: Boolean(sentence.ai_filters?.question),\n      isTask: Boolean(sentence.ai_filters?.task),\n    },\n    context,\n  };\n}\n\n/**\n * Search a single transcript for matching sentences.\n *\n * This is a pure function with no API calls, making it fully testable.\n * It searches the transcript's sentences for text matching the query,\n * optionally filtering by speaker, questions, or tasks.\n *\n * @param transcript - The transcript to search\n * @param options - Search options including query, filters, and context settings\n * @returns Array of matches with context\n *\n * @example\n * ```typescript\n * import { searchTranscript } from 'fireflies-api';\n *\n * const matches = searchTranscript(transcript, {\n *   query: 'budget',\n *   speakers: ['Alice'],\n *   filterQuestions: true,\n *   contextLines: 2,\n * });\n *\n * for (const match of matches) {\n *   console.log(`${match.sentence.speakerName}: ${match.sentence.text}`);\n * }\n * ```\n */\nexport function searchTranscript(\n  transcript: Transcript,\n  options: SearchTranscriptOptions\n): SearchMatch[] {\n  const {\n    query,\n    caseSensitive = false,\n    speakers,\n    filterQuestions = false,\n    filterTasks = false,\n    contextLines = 1,\n  } = options;\n\n  // Empty query matches nothing\n  if (!query || query.trim() === '') {\n    return [];\n  }\n\n  const sentences = transcript.sentences ?? [];\n  if (sentences.length === 0) {\n    return [];\n  }\n\n  // Build regex for query matching\n  const escapedQuery = escapeRegex(query);\n  const regex = new RegExp(escapedQuery, caseSensitive ? '' : 'i');\n\n  // Normalize speakers list for case-insensitive comparison\n  const speakerSet = speakers ? new Set(speakers.map((s) => s.toLowerCase())) : null;\n\n  const matches: SearchMatch[] = [];\n\n  for (let i = 0; i < sentences.length; i++) {\n    const sentence = sentences[i];\n    if (!sentence) continue;\n\n    // Check text match\n    if (!regex.test(sentence.text)) continue;\n\n    // Check speaker filter\n    if (!matchesSpeaker(sentence, speakerSet)) continue;\n\n    // Check AI filter requirements\n    if (!matchesAIFilters(sentence, filterQuestions, filterTasks)) continue;\n\n    // Build match result\n    const context = extractContext(sentences, i, contextLines);\n    matches.push(sentenceToMatch(sentence, transcript, context));\n  }\n\n  return matches;\n}\n","import { aggregateActionItems } from '../../helpers/action-items-format.js';\nimport { batch } from '../../helpers/batch.js';\nimport { extractDomain, hasExternalParticipants } from '../../helpers/domain-utils.js';\nimport {\n  createZipArchive,\n  type ExportFormat,\n  exportTranscript,\n  generateExportFilename,\n} from '../../helpers/export-formats.js';\nimport { analyzeMeetings } from '../../helpers/meeting-insights.js';\nimport { paginate } from '../../helpers/pagination.js';\nimport { searchTranscript } from '../../helpers/search.js';\nimport type {\n  AggregatedActionItemsResult,\n  ExportActionItemsParams,\n} from '../../types/action-items.js';\nimport type { BulkExportParams, BulkExportResult, ExportedFile } from '../../types/bulk-export.js';\nimport type { MeetingInsights } from '../../types/meeting-insights.js';\nimport type {\n  TranscriptGetParams,\n  TranscriptsInsightsParams,\n  TranscriptsListParams,\n} from '../../types/params.js';\nimport type { SearchParams, SearchResults } from '../../types/search.js';\nimport type {\n  AppsPreview,\n  Channel,\n  MeetingAnalytics,\n  MeetingAttendance,\n  MeetingAttendee,\n  MeetingInfo,\n  Sentence,\n  Speaker,\n  Summary,\n  Transcript,\n  User,\n} from '../../types/transcript.js';\nimport type { GraphQLClient } from '../client.js';\n\n/**\n * GraphQL fragment for base transcript fields (excludes sentences and summary).\n */\nconst TRANSCRIPT_BASE_FIELDS = `\n  id\n  title\n  organizer_email\n  host_email\n  user {\n    user_id\n    email\n    name\n  }\n  speakers {\n    id\n    name\n  }\n  transcript_url\n  participants\n  meeting_attendees {\n    displayName\n    email\n    phoneNumber\n    name\n    location\n  }\n  meeting_attendance {\n    name\n    join_time\n    leave_time\n  }\n  fireflies_users\n  workspace_users\n  duration\n  dateString\n  date\n  audio_url\n  video_url\n  calendar_id\n  meeting_info {\n    fred_joined\n    silent_meeting\n    summary_status\n  }\n  cal_id\n  calendar_type\n  apps_preview {\n    outputs {\n      transcript_id\n      user_id\n      app_id\n      created_at\n      title\n      prompt\n      response\n    }\n  }\n  meeting_link\n  analytics {\n    sentiments {\n      negative_pct\n      neutral_pct\n      positive_pct\n    }\n  }\n  channels {\n    id\n    title\n    is_private\n    created_at\n    updated_at\n    created_by\n    members {\n      user_id\n      email\n      name\n    }\n  }\n`;\n\n/**\n * GraphQL fragment for sentences field.\n */\nconst SENTENCES_FIELDS = `\n  sentences {\n    index\n    text\n    raw_text\n    start_time\n    end_time\n    speaker_id\n    speaker_name\n    ai_filters {\n      task\n      pricing\n      metric\n      question\n      date_and_time\n      text_cleanup\n      sentiment\n    }\n  }\n`;\n\n/**\n * GraphQL fragment for summary field.\n */\nconst SUMMARY_FIELDS = `\n  summary {\n    action_items\n    keywords\n    outline\n    overview\n    shorthand_bullet\n    notes\n    gist\n    bullet_gist\n    short_summary\n    short_overview\n    meeting_type\n    topics_discussed\n    transcript_chapters\n    extended_sections {\n      title\n      content\n    }\n  }\n`;\n\n/**\n * Build transcript fields based on options.\n */\nfunction buildTranscriptFields(params?: TranscriptGetParams): string {\n  const includeSentences = params?.includeSentences !== false;\n  const includeSummary = params?.includeSummary !== false;\n\n  let fields = TRANSCRIPT_BASE_FIELDS;\n  if (includeSentences) {\n    fields += SENTENCES_FIELDS;\n  }\n  if (includeSummary) {\n    fields += SUMMARY_FIELDS;\n  }\n  return fields;\n}\n\n/**\n * GraphQL fragment for transcript list fields (lighter weight).\n */\nconst TRANSCRIPT_LIST_FIELDS = `\n  id\n  title\n  organizer_email\n  transcript_url\n  participants\n  duration\n  dateString\n  date\n  video_url\n  meeting_info {\n    fred_joined\n    silent_meeting\n    summary_status\n  }\n`;\n\n/**\n * Build list fields based on options.\n * By default returns lightweight fields.\n * When includeSentences or includeSummary is true, uses full base fields + requested content.\n */\nfunction buildListFields(params?: TranscriptsListParams): string {\n  const includeSentences = params?.includeSentences === true;\n  const includeSummary = params?.includeSummary === true;\n\n  // If neither content option is requested, use lightweight fields\n  if (!includeSentences && !includeSummary) {\n    return TRANSCRIPT_LIST_FIELDS;\n  }\n\n  // Use full base fields when requesting content\n  let fields = TRANSCRIPT_BASE_FIELDS;\n\n  if (includeSentences) {\n    fields += SENTENCES_FIELDS;\n  }\n  if (includeSummary) {\n    fields += SUMMARY_FIELDS;\n  }\n\n  return fields;\n}\n\n/**\n * API for transcript operations.\n */\nexport interface TranscriptsAPI {\n  /**\n   * Get a single transcript by ID.\n   *\n   * @param id - Transcript ID\n   * @param params - Optional parameters to exclude heavy fields\n   * @returns Transcript (fields depend on params)\n   * @throws NotFoundError if transcript doesn't exist\n   *\n   * @example\n   * ```typescript\n   * // Full transcript with all fields\n   * const full = await client.transcripts.get('id');\n   *\n   * // Metadata only (faster, smaller response)\n   * const meta = await client.transcripts.get('id', {\n   *   includeSentences: false,\n   *   includeSummary: false,\n   * });\n   * ```\n   */\n  get(id: string, params?: TranscriptGetParams): Promise<Transcript>;\n\n  /**\n   * List transcripts with optional filtering.\n   *\n   * @param params - Filter and pagination options\n   * @returns Array of transcripts (max 50 per call)\n   */\n  list(params?: TranscriptsListParams): Promise<Transcript[]>;\n\n  /**\n   * Get just the summary for a transcript.\n   * Lighter weight than fetching the full transcript.\n   *\n   * @param id - Transcript ID\n   * @returns Summary object\n   */\n  getSummary(id: string): Promise<Summary | null>;\n\n  /**\n   * Iterate through all transcripts matching the filter.\n   * Automatically handles pagination.\n   *\n   * @param params - Filter options (skip and limit are ignored)\n   * @returns Async iterable of transcripts\n   *\n   * @example\n   * ```typescript\n   * for await (const transcript of client.transcripts.listAll({ mine: true })) {\n   *   console.log(transcript.title);\n   * }\n   * ```\n   */\n  listAll(params?: Omit<TranscriptsListParams, 'skip' | 'limit'>): AsyncIterable<Transcript>;\n\n  /**\n   * Search across transcripts for matching sentences.\n   *\n   * This method first queries for transcripts matching the keyword,\n   * then fetches each transcript with sentences and searches locally\n   * for detailed matches with speaker filtering, question/task filtering,\n   * and context extraction.\n   *\n   * @param query - The search query string\n   * @param params - Search options including filters and context settings\n   * @returns Search results with matches grouped by transcript\n   *\n   * @example\n   * ```typescript\n   * const results = await client.transcripts.search('budget', {\n   *   speakers: ['Alice'],\n   *   filterQuestions: true,\n   *   fromDate: '2024-01-01',\n   *   contextLines: 2,\n   * });\n   *\n   * console.log(`Found ${results.totalMatches} matches`);\n   * for (const match of results.matches) {\n   *   console.log(`${match.sentence.speakerName}: ${match.sentence.text}`);\n   * }\n   * ```\n   */\n  search(query: string, params?: SearchParams): Promise<SearchResults>;\n\n  /**\n   * Compute aggregate meeting insights across transcripts.\n   *\n   * Fetches transcripts matching the filter criteria and computes\n   * aggregate statistics including duration totals, day of week\n   * distribution, participant counts, and speaker talk times.\n   *\n   * @param params - Filtering and analysis options\n   * @returns Aggregate meeting insights\n   *\n   * @example\n   * ```typescript\n   * const insights = await client.transcripts.insights({\n   *   fromDate: '2024-01-01',\n   *   toDate: '2024-01-31',\n   *   mine: true,\n   *   groupBy: 'week',\n   * });\n   *\n   * console.log(`${insights.totalMeetings} meetings`);\n   * console.log(`${insights.totalDurationMinutes} total minutes`);\n   * console.log(`Busiest day: ${getBusiestDay(insights.byDayOfWeek)}`);\n   * ```\n   */\n  insights(params?: TranscriptsInsightsParams): Promise<MeetingInsights>;\n\n  /**\n   * Export action items from multiple transcripts.\n   *\n   * Fetches transcripts matching the filter criteria, extracts action\n   * items from each, and aggregates them with source metadata.\n   *\n   * @param params - Filtering options for transcripts and action items\n   * @returns Aggregated action items with statistics\n   *\n   * @example\n   * ```typescript\n   * const result = await client.transcripts.exportActionItems({\n   *   fromDate: '2024-01-01',\n   *   mine: true,\n   *   filterOptions: { assignedOnly: true },\n   * });\n   *\n   * console.log(`${result.totalItems} action items from ${result.transcriptsProcessed} meetings`);\n   * for (const item of result.items) {\n   *   console.log(`${item.text} (${item.transcriptTitle})`);\n   * }\n   * ```\n   */\n  exportActionItems(params?: ExportActionItemsParams): Promise<AggregatedActionItemsResult>;\n\n  /**\n   * Export multiple transcripts to various formats.\n   *\n   * Fetches transcripts matching the filter criteria, converts each to the\n   * specified format, and optionally packages them as a zip archive.\n   *\n   * @param params - Export options including format, filters, and output settings\n   * @returns Export result with files and optional zip buffer\n   *\n   * @example\n   * ```typescript\n   * // Export last week's meetings as markdown\n   * const result = await client.transcripts.bulkExport({\n   *   fromDate: '2024-01-08',\n   *   toDate: '2024-01-15',\n   *   format: 'markdown',\n   *   onProgress: (done, total) => console.log(`${done}/${total}`),\n   * });\n   *\n   * // Write files to disk\n   * for (const file of result.files) {\n   *   await writeFile(`./exports/${file.filename}`, file.content);\n   * }\n   *\n   * // Or get as zip\n   * const zipResult = await client.transcripts.bulkExport({\n   *   fromDate: '2024-01-08',\n   *   format: 'csv',\n   *   asZip: true,\n   * });\n   * await writeFile('exports.zip', zipResult.zip);\n   * ```\n   */\n  bulkExport(params?: BulkExportParams): Promise<BulkExportResult>;\n}\n\n/**\n * Create the transcripts API bound to a GraphQL client.\n */\nexport function createTranscriptsAPI(client: GraphQLClient): TranscriptsAPI {\n  return {\n    async get(id: string, params?: TranscriptGetParams): Promise<Transcript> {\n      const fields = buildTranscriptFields(params);\n      const query = `\n        query GetTranscript($id: String!) {\n          transcript(id: $id) {\n            ${fields}\n          }\n        }\n      `;\n\n      const data = await client.execute<{ transcript: TranscriptResponse }>(query, { id });\n\n      return normalizeTranscript(data.transcript);\n    },\n\n    async list(params?: TranscriptsListParams): Promise<Transcript[]> {\n      const fields = buildListFields(params);\n      const query = `\n        query ListTranscripts(\n          $keyword: String\n          $scope: String\n          $organizers: [String!]\n          $participants: [String!]\n          $user_id: String\n          $mine: Boolean\n          $channel_id: String\n          $fromDate: DateTime\n          $toDate: DateTime\n          $limit: Int\n          $skip: Int\n          $title: String\n          $host_email: String\n          $organizer_email: String\n          $participant_email: String\n          $date: Float\n        ) {\n          transcripts(\n            keyword: $keyword\n            scope: $scope\n            organizers: $organizers\n            participants: $participants\n            user_id: $user_id\n            mine: $mine\n            channel_id: $channel_id\n            fromDate: $fromDate\n            toDate: $toDate\n            limit: $limit\n            skip: $skip\n            title: $title\n            host_email: $host_email\n            organizer_email: $organizer_email\n            participant_email: $participant_email\n            date: $date\n          ) {\n            ${fields}\n          }\n        }\n      `;\n\n      // Get internal domain if filtering for external meetings\n      let internalDomain: string | undefined;\n      if (params?.external) {\n        const userQuery = 'query { user { email } }';\n        const userData = await client.execute<{ user: { email: string } }>(userQuery);\n        internalDomain = extractDomain(userData.user.email);\n      }\n\n      const variables = buildListVariables(params);\n      const data = await client.execute<{ transcripts: TranscriptResponse[] }>(query, variables);\n\n      let results = data.transcripts.map(normalizeTranscript);\n\n      // Client-side filter for external participants\n      if (internalDomain) {\n        results = results.filter((t) => hasExternalParticipants(t.participants, internalDomain));\n      }\n\n      return results;\n    },\n\n    async getSummary(id: string): Promise<Summary | null> {\n      const query = `\n        query GetTranscriptSummary($id: String!) {\n          transcript(id: $id) {\n            summary {\n              action_items\n              keywords\n              outline\n              overview\n              shorthand_bullet\n              notes\n              gist\n              bullet_gist\n              short_summary\n              short_overview\n              meeting_type\n              topics_discussed\n              transcript_chapters\n              extended_sections {\n                title\n                content\n              }\n            }\n          }\n        }\n      `;\n\n      const data = await client.execute<{\n        transcript: { summary: Summary | null };\n      }>(query, { id });\n\n      return data.transcript.summary;\n    },\n\n    listAll(params?: Omit<TranscriptsListParams, 'skip' | 'limit'>): AsyncIterable<Transcript> {\n      return paginate((skip, limit) => this.list({ ...params, skip, limit }), 50);\n    },\n\n    async search(query: string, params: SearchParams = {}): Promise<SearchResults> {\n      const {\n        caseSensitive = false,\n        scope = 'sentences',\n        speakers,\n        filterQuestions,\n        filterTasks,\n        contextLines = 1,\n        limit,\n        ...listParams\n      } = params;\n\n      // Fetch transcripts with sentences in bulk (avoids N+1 queries)\n      const transcripts: Transcript[] = [];\n      for await (const t of this.listAll({\n        ...listParams,\n        keyword: query,\n        scope,\n        includeSentences: true,\n      })) {\n        transcripts.push(t);\n        if (limit && transcripts.length >= limit) break;\n      }\n\n      // Search locally within fetched transcripts\n      const allMatches: SearchResults['matches'] = [];\n      let transcriptsWithMatches = 0;\n\n      for (const t of transcripts) {\n        const matches = searchTranscript(t, {\n          query,\n          caseSensitive,\n          speakers,\n          filterQuestions,\n          filterTasks,\n          contextLines,\n        });\n\n        if (matches.length > 0) {\n          transcriptsWithMatches++;\n          allMatches.push(...matches);\n        }\n      }\n\n      return {\n        query,\n        options: params,\n        totalMatches: allMatches.length,\n        transcriptsSearched: transcripts.length,\n        transcriptsWithMatches,\n        matches: allMatches,\n      };\n    },\n\n    async insights(params: TranscriptsInsightsParams = {}): Promise<MeetingInsights> {\n      const {\n        fromDate,\n        toDate,\n        mine,\n        organizers,\n        participants,\n        user_id,\n        channel_id,\n        limit,\n        external,\n        speakers,\n        groupBy,\n        topSpeakersCount,\n        topParticipantsCount,\n      } = params;\n\n      // Get internal domain if filtering for external meetings\n      let internalDomain: string | undefined;\n      if (external) {\n        const userQuery = 'query { user { email } }';\n        const userData = await client.execute<{ user: { email: string } }>(userQuery);\n        internalDomain = extractDomain(userData.user.email);\n      }\n\n      // Fetch transcripts with sentences in bulk (needed for speaker analysis)\n      const transcripts: Transcript[] = [];\n      for await (const t of this.listAll({\n        fromDate,\n        toDate,\n        mine,\n        organizers,\n        participants,\n        user_id,\n        channel_id,\n        includeSentences: true,\n      })) {\n        // Skip if filtering for external and no external participants\n        if (internalDomain && !hasExternalParticipants(t.participants, internalDomain)) {\n          continue;\n        }\n\n        transcripts.push(t);\n\n        if (limit && transcripts.length >= limit) break;\n      }\n\n      // Analyze with the helper\n      return analyzeMeetings(transcripts, {\n        speakers,\n        groupBy,\n        topSpeakersCount,\n        topParticipantsCount,\n      });\n    },\n\n    async exportActionItems(\n      params: ExportActionItemsParams = {}\n    ): Promise<AggregatedActionItemsResult> {\n      const { fromDate, toDate, mine, organizers, participants, limit, filterOptions } = params;\n\n      // Fetch transcripts with summary in bulk (needed for action items)\n      const transcripts: Transcript[] = [];\n      for await (const t of this.listAll({\n        fromDate,\n        toDate,\n        mine,\n        organizers,\n        participants,\n        includeSummary: true,\n      })) {\n        transcripts.push(t);\n\n        if (limit && transcripts.length >= limit) break;\n      }\n\n      // Aggregate action items using the helper\n      return aggregateActionItems(transcripts, {}, filterOptions);\n    },\n\n    async bulkExport(params: BulkExportParams = {}): Promise<BulkExportResult> {\n      const { format = 'markdown', asZip = false, onProgress } = params;\n\n      // 1. Collect transcript IDs to export\n      const transcriptIds = await collectTranscriptIds(client, this, params);\n\n      // 2. Fetch and convert each transcript\n      const files = await convertTranscripts(this, transcriptIds, format, onProgress);\n\n      // 3. Package as zip if requested\n      const zip = asZip ? await createZipArchive(files) : undefined;\n\n      return { files, zip, format, totalExported: files.length };\n    },\n  };\n}\n\n/**\n * Raw transcript response from GraphQL (may have nulls).\n */\ntype TranscriptResponse = {\n  id: string;\n  title: string | null;\n  organizer_email: string | null;\n  host_email?: string | null;\n  user?: User | null;\n  speakers?: Speaker[] | null;\n  transcript_url: string | null;\n  participants?: string[] | null;\n  meeting_attendees?: MeetingAttendee[] | null;\n  meeting_attendance?: MeetingAttendance[] | null;\n  fireflies_users?: string[] | null;\n  workspace_users?: string[] | null;\n  duration: number | null;\n  dateString: string | null;\n  date: number | null;\n  audio_url?: string | null;\n  video_url?: string | null;\n  sentences?: Sentence[] | null;\n  calendar_id?: string | null;\n  summary?: Summary | null;\n  meeting_info?: MeetingInfo | null;\n  cal_id?: string | null;\n  calendar_type?: string | null;\n  apps_preview?: AppsPreview | null;\n  meeting_link?: string | null;\n  analytics?: MeetingAnalytics | null;\n  channels?: Channel[] | null;\n};\n\n/** Convert null to undefined for optional fields */\nfunction orUndefined<T>(value: T | null | undefined): T | undefined {\n  return value ?? undefined;\n}\n\n/** Convert null to empty array for required array fields */\nfunction orEmptyArray<T>(value: T[] | null | undefined): T[] {\n  return value ?? [];\n}\n\n/** Normalize required string/number fields */\nfunction normalizeRequiredFields(raw: TranscriptResponse) {\n  return {\n    id: raw.id,\n    title: raw.title ?? '',\n    organizer_email: raw.organizer_email ?? '',\n    transcript_url: raw.transcript_url ?? '',\n    duration: raw.duration ?? 0,\n    dateString: raw.dateString ?? '',\n    date: raw.date ?? 0,\n  };\n}\n\n/** Normalize array fields */\nfunction normalizeArrayFields(raw: TranscriptResponse) {\n  return {\n    speakers: orEmptyArray(raw.speakers),\n    participants: orEmptyArray(raw.participants),\n    meeting_attendees: orEmptyArray(raw.meeting_attendees),\n    meeting_attendance: orEmptyArray(raw.meeting_attendance),\n    fireflies_users: orEmptyArray(raw.fireflies_users),\n    workspace_users: orEmptyArray(raw.workspace_users),\n    sentences: orEmptyArray(raw.sentences),\n    channels: orEmptyArray(raw.channels),\n  };\n}\n\n/** Normalize optional fields */\nfunction normalizeOptionalFields(raw: TranscriptResponse) {\n  return {\n    host_email: orUndefined(raw.host_email),\n    user: orUndefined(raw.user),\n    audio_url: orUndefined(raw.audio_url),\n    video_url: orUndefined(raw.video_url),\n    calendar_id: orUndefined(raw.calendar_id),\n    summary: orUndefined(raw.summary),\n    meeting_info: orUndefined(raw.meeting_info),\n    cal_id: orUndefined(raw.cal_id),\n    calendar_type: orUndefined(raw.calendar_type),\n    apps_preview: orUndefined(raw.apps_preview),\n    meeting_link: orUndefined(raw.meeting_link),\n    analytics: orUndefined(raw.analytics),\n  };\n}\n\n/**\n * Normalize a transcript response to ensure consistent types.\n */\nfunction normalizeTranscript(raw: TranscriptResponse): Transcript {\n  return {\n    ...normalizeRequiredFields(raw),\n    ...normalizeArrayFields(raw),\n    ...normalizeOptionalFields(raw),\n  };\n}\n\n/**\n * Build GraphQL variables from list params.\n */\nfunction buildListVariables(params?: TranscriptsListParams): Record<string, unknown> {\n  if (!params) {\n    return { limit: 50 };\n  }\n\n  return {\n    keyword: params.keyword,\n    scope: params.scope,\n    organizers: params.organizers,\n    participants: params.participants,\n    user_id: params.user_id,\n    mine: params.mine,\n    channel_id: params.channel_id,\n    fromDate: params.fromDate,\n    toDate: params.toDate,\n    limit: params.limit ?? 50,\n    skip: params.skip,\n    title: params.title,\n    host_email: params.host_email,\n    organizer_email: params.organizer_email,\n    participant_email: params.participant_email,\n    date: params.date,\n  };\n}\n\n// --- Bulk export helpers ---\n\n/**\n * Collect transcript IDs based on export params.\n * Either uses provided IDs or queries for matching transcripts.\n */\nasync function collectTranscriptIds(\n  client: GraphQLClient,\n  api: TranscriptsAPI,\n  params: BulkExportParams\n): Promise<string[]> {\n  const { ids, fromDate, toDate, mine, organizers, participants, external, limit } = params;\n\n  // If explicit IDs provided, use them directly\n  if (ids?.length) {\n    return ids;\n  }\n\n  // Get internal domain for external filtering\n  let internalDomain: string | undefined;\n  if (external) {\n    const userQuery = 'query { user { email } }';\n    const userData = await client.execute<{ user: { email: string } }>(userQuery);\n    internalDomain = extractDomain(userData.user.email);\n  }\n\n  // Collect matching transcript IDs\n  const result: string[] = [];\n  for await (const t of api.listAll({ fromDate, toDate, mine, organizers, participants })) {\n    // Skip if filtering for external and no external participants\n    if (internalDomain && !hasExternalParticipants(t.participants, internalDomain)) {\n      continue;\n    }\n    result.push(t.id);\n    if (limit && result.length >= limit) break;\n  }\n\n  return result;\n}\n\n/**\n * Fetch and convert transcripts to the specified format.\n */\nasync function convertTranscripts(\n  api: TranscriptsAPI,\n  transcriptIds: string[],\n  format: ExportFormat,\n  onProgress?: (completed: number, total: number) => void\n): Promise<ExportedFile[]> {\n  const files: ExportedFile[] = [];\n  const extension = format === 'markdown' ? 'md' : format;\n  let completed = 0;\n  const total = transcriptIds.length;\n\n  for await (const result of batch(\n    transcriptIds,\n    async (id) => {\n      const transcript = await api.get(id);\n      const content = await exportTranscript(transcript, format);\n      const filename = generateExportFilename(transcript, extension);\n      return { id, title: transcript.title, filename, content };\n    },\n    { delayMs: 100 }\n  )) {\n    if (!result.error) {\n      files.push(result.result);\n    }\n    completed++;\n    onProgress?.(completed, total);\n  }\n\n  return files;\n}\n","import type { UserProfile } from '../../types/user.js';\nimport type { GraphQLClient } from '../client.js';\n\nconst USER_FIELDS = `\n  user_id\n  email\n  name\n  num_transcripts\n  recent_meeting\n  recent_transcript\n  minutes_consumed\n  is_admin\n  integrations\n  user_groups {\n    id\n    name\n    handle\n    members {\n      user_id\n      email\n    }\n  }\n`;\n\n/**\n * API for user operations.\n */\nexport interface UsersAPI {\n  /**\n   * Get current user (API key owner).\n   *\n   * @returns Current user profile\n   */\n  me(): Promise<UserProfile>;\n\n  /**\n   * Get user by ID.\n   *\n   * @param id - User ID\n   * @returns User profile\n   */\n  get(id: string): Promise<UserProfile>;\n\n  /**\n   * List all team users.\n   *\n   * @returns Array of user profiles\n   */\n  list(): Promise<UserProfile[]>;\n}\n\n/**\n * Create the users API bound to a GraphQL client.\n */\nexport function createUsersAPI(client: GraphQLClient): UsersAPI {\n  return {\n    async me(): Promise<UserProfile> {\n      const query = `query { user { ${USER_FIELDS} } }`;\n      const data = await client.execute<{ user: UserProfile }>(query);\n      return data.user;\n    },\n\n    async get(id: string): Promise<UserProfile> {\n      const query = `\n        query User($userId: String!) {\n          user(id: $userId) { ${USER_FIELDS} }\n        }\n      `;\n      const data = await client.execute<{ user: UserProfile }>(query, { userId: id });\n      return data.user;\n    },\n\n    async list(): Promise<UserProfile[]> {\n      const query = `query Users { users { ${USER_FIELDS} } }`;\n      const data = await client.execute<{ users: UserProfile[] }>(query);\n      return data.users;\n    },\n  };\n}\n","import { io, type Socket } from 'socket.io-client';\nimport { AuthenticationError, ConnectionError, TimeoutError } from '../errors.js';\nimport type {\n  RawChunkPayload,\n  RealtimeConfig,\n  ServerToClientEvents,\n  TranscriptionChunk,\n} from './types.js';\n\ntype RealtimeSocket = Socket<ServerToClientEvents, Record<string, never>>;\n\n// Defaults from working fireflies-whiteboard implementation\nconst DEFAULT_WS_URL = 'wss://api.fireflies.ai';\nconst DEFAULT_WS_PATH = '/ws/realtime';\nconst DEFAULT_TIMEOUT = 20000;\nconst DEFAULT_CHUNK_TIMEOUT = 20000;\nconst DEFAULT_RECONNECT_DELAY = 5000; // Start at 5s (proven value)\nconst DEFAULT_MAX_RECONNECT_DELAY = 60000; // Max 60s (proven value)\nconst DEFAULT_MAX_RECONNECT_ATTEMPTS = 10;\n\n/**\n * Internal config with all defaults filled in.\n */\ntype ResolvedConfig = Required<RealtimeConfig>;\n\n/**\n * Low-level realtime connection client.\n * Handles Socket.IO connection lifecycle.\n */\nexport class RealtimeConnection {\n  private socket: RealtimeSocket | null = null;\n  private readonly config: ResolvedConfig;\n\n  constructor(config: RealtimeConfig) {\n    this.config = {\n      wsUrl: DEFAULT_WS_URL,\n      wsPath: DEFAULT_WS_PATH,\n      timeout: DEFAULT_TIMEOUT,\n      chunkTimeout: DEFAULT_CHUNK_TIMEOUT,\n      reconnect: true,\n      maxReconnectAttempts: DEFAULT_MAX_RECONNECT_ATTEMPTS,\n      reconnectDelay: DEFAULT_RECONNECT_DELAY,\n      maxReconnectDelay: DEFAULT_MAX_RECONNECT_DELAY,\n      ...config,\n    };\n  }\n\n  /**\n   * Establish connection and wait for auth success.\n   */\n  async connect(): Promise<void> {\n    if (this.socket?.connected) {\n      return;\n    }\n\n    const socket = io(this.config.wsUrl, {\n      path: this.config.wsPath,\n      auth: {\n        token: `Bearer ${this.config.apiKey}`,\n        transcriptId: this.config.transcriptId,\n      },\n      // Force WebSocket transport (proven more reliable than polling)\n      transports: ['websocket'],\n      reconnection: this.config.reconnect,\n      reconnectionDelay: this.config.reconnectDelay,\n      reconnectionDelayMax: this.config.maxReconnectDelay,\n      reconnectionAttempts: this.config.maxReconnectAttempts,\n      // Exponential backoff factor (default 2x matches our fireflies-whiteboard pattern)\n      randomizationFactor: 0.5,\n      timeout: this.config.timeout,\n      autoConnect: false,\n    });\n\n    this.socket = socket;\n\n    return new Promise((resolve, reject) => {\n      const timeoutId = setTimeout(() => {\n        socket.disconnect();\n        reject(new TimeoutError(`Realtime connection timed out after ${this.config.timeout}ms`));\n      }, this.config.timeout);\n\n      const cleanup = () => clearTimeout(timeoutId);\n\n      socket.once('auth.success', () => {\n        cleanup();\n        resolve();\n      });\n\n      // Handle explicit auth failure event\n      socket.once('auth.failed', (data) => {\n        cleanup();\n        socket.disconnect();\n        reject(new AuthenticationError(`Realtime auth failed: ${formatData(data)}`));\n      });\n\n      // Handle connection errors\n      socket.once('connection.error', (data) => {\n        cleanup();\n        socket.disconnect();\n        reject(new ConnectionError(`Realtime connection error: ${formatData(data)}`));\n      });\n\n      socket.once('connect_error', (error) => {\n        cleanup();\n        socket.disconnect();\n\n        // Parse auth errors from generic connect_error\n        const message = error.message || 'Connection failed';\n        if (\n          message.includes('auth') ||\n          message.includes('401') ||\n          message.includes('unauthorized')\n        ) {\n          reject(new AuthenticationError(`Realtime auth failed: ${message}`));\n        } else {\n          reject(\n            new ConnectionError(`Realtime connection failed: ${message}`, {\n              cause: error,\n            })\n          );\n        }\n      });\n\n      socket.connect();\n    });\n  }\n\n  /**\n   * Register a chunk handler.\n   * Handles both { payload: {...} } and direct payload shapes.\n   */\n  onChunk(handler: (chunk: TranscriptionChunk) => void): void {\n    this.socket?.on('transcription.broadcast', (data: RawChunkPayload | TranscriptionChunk) => {\n      // Handle both payload shapes (learned from fireflies-whiteboard)\n      const chunk = 'payload' in data ? data.payload : data;\n      handler(chunk);\n    });\n  }\n\n  /**\n   * Register a disconnect handler.\n   */\n  onDisconnect(handler: (reason: string) => void): void {\n    this.socket?.on('disconnect', handler);\n  }\n\n  /**\n   * Register a reconnect handler.\n   */\n  onReconnect(handler: () => void): void {\n    this.socket?.io.on('reconnect', handler);\n  }\n\n  /**\n   * Register a reconnect attempt handler.\n   */\n  onReconnectAttempt(handler: (attempt: number) => void): void {\n    this.socket?.io.on('reconnect_attempt', handler);\n  }\n\n  /**\n   * Register an error handler.\n   */\n  onError(handler: (error: Error) => void): void {\n    this.socket?.on('connect_error', handler);\n  }\n\n  /**\n   * Disconnect and cleanup.\n   */\n  disconnect(): void {\n    if (this.socket) {\n      this.socket.disconnect();\n      this.socket = null;\n    }\n  }\n\n  get connected(): boolean {\n    return this.socket?.connected ?? false;\n  }\n}\n\n/**\n * Format unknown data for error messages.\n */\nfunction formatData(data: unknown): string {\n  if (data === undefined || data === null) {\n    return String(data);\n  }\n  try {\n    return JSON.stringify(data);\n  } catch {\n    return String(data);\n  }\n}\n","import { StreamClosedError } from '../errors.js';\nimport { RealtimeConnection } from './client.js';\nimport type { RealtimeConfig, RealtimeEvents, TranscriptionChunk } from './types.js';\n\ntype EventHandler<K extends keyof RealtimeEvents> = RealtimeEvents[K];\n\n// Generic event handler type\ntype AnyEventHandler = (...args: never[]) => void;\n\n/**\n * Realtime transcription stream.\n *\n * Chunks are emitted progressively as speech is transcribed. The same chunk_id\n * will be emitted multiple times with updated text. Use `chunk.isFinal` to\n * determine if a chunk is complete (the next chunk_id has appeared).\n *\n * @example Event-based (all updates)\n * ```typescript\n * stream.on('chunk', (chunk) => {\n *   // Updates display in real-time\n *   updateDisplay(chunk.chunk_id, chunk.text);\n * });\n * ```\n *\n * @example Event-based (final chunks only)\n * ```typescript\n * stream.on('chunk', (chunk) => {\n *   if (chunk.isFinal) {\n *     console.log(`[${chunk.speaker_name}]: ${chunk.text}`);\n *   }\n * });\n * ```\n *\n * @example Async iterator\n * ```typescript\n * for await (const chunk of stream) {\n *   console.log(`[${chunk.speaker_name}]: ${chunk.text}`);\n * }\n * ```\n */\nexport class RealtimeStream implements AsyncIterable<TranscriptionChunk> {\n  private connection: RealtimeConnection;\n  private listeners = new Map<keyof RealtimeEvents, Set<AnyEventHandler>>();\n  private buffer: TranscriptionChunk[] = [];\n  private waiters: Array<(chunk: TranscriptionChunk | null) => void> = [];\n  private closed = false;\n  private lastChunkId: string | null = null;\n  private lastChunk: TranscriptionChunk | null = null;\n\n  constructor(config: RealtimeConfig) {\n    this.connection = new RealtimeConnection(config);\n  }\n\n  /**\n   * Connect to the realtime stream.\n   * @throws AuthenticationError if authentication fails\n   * @throws ConnectionError if connection fails\n   * @throws TimeoutError if connection times out\n   */\n  async connect(): Promise<void> {\n    await this.connection.connect();\n    this.setupHandlers();\n    this.emit('connected');\n  }\n\n  private setupHandlers(): void {\n    this.connection.onChunk((rawChunk) => {\n      // Check if this is a new chunk or an update to the current one\n      const isNewChunk = this.lastChunkId !== null && rawChunk.chunk_id !== this.lastChunkId;\n\n      // If we have a previous chunk and this is a new one, mark previous as final\n      if (isNewChunk && this.lastChunk) {\n        const finalChunk: TranscriptionChunk = { ...this.lastChunk, isFinal: true };\n        this.emitChunk(finalChunk);\n      }\n\n      // Create chunk with isFinal = false (it may get more updates)\n      const chunk: TranscriptionChunk = { ...rawChunk, isFinal: false };\n\n      // Track current chunk\n      this.lastChunkId = chunk.chunk_id;\n      this.lastChunk = chunk;\n\n      // Emit the update\n      this.emit('chunk', chunk);\n    });\n\n    this.connection.onDisconnect((reason) => {\n      // Emit last chunk as final before disconnecting\n      if (this.lastChunk) {\n        const finalChunk: TranscriptionChunk = { ...this.lastChunk, isFinal: true };\n        this.emitChunk(finalChunk);\n        this.lastChunk = null;\n      }\n\n      this.emit('disconnected', reason);\n\n      // Signal end to async iterator\n      if (!this.connection.connected) {\n        this.closed = true;\n        for (const waiter of this.waiters) {\n          waiter(null);\n        }\n        this.waiters = [];\n      }\n    });\n\n    this.connection.onReconnectAttempt((attempt) => {\n      this.emit('reconnecting', attempt);\n    });\n\n    this.connection.onReconnect(() => {\n      this.emit('connected');\n    });\n\n    this.connection.onError((error) => {\n      this.emit('error', error);\n    });\n  }\n\n  /**\n   * Register an event listener.\n   * @param event - Event name\n   * @param handler - Event handler\n   */\n  on<K extends keyof RealtimeEvents>(event: K, handler: EventHandler<K>): this {\n    let handlers = this.listeners.get(event);\n    if (!handlers) {\n      handlers = new Set();\n      this.listeners.set(event, handlers);\n    }\n    handlers.add(handler as AnyEventHandler);\n    return this;\n  }\n\n  /**\n   * Remove an event listener.\n   * @param event - Event name\n   * @param handler - Event handler to remove\n   */\n  off<K extends keyof RealtimeEvents>(event: K, handler: EventHandler<K>): this {\n    this.listeners.get(event)?.delete(handler as AnyEventHandler);\n    return this;\n  }\n\n  /**\n   * Emit a chunk to both event listeners and async iterator buffer.\n   * Used for final chunks that should be yielded by the iterator.\n   */\n  private emitChunk(chunk: TranscriptionChunk): void {\n    this.emit('chunk', chunk);\n\n    // Feed async iterator (only final chunks go to the buffer)\n    if (chunk.isFinal) {\n      if (this.waiters.length > 0) {\n        const waiter = this.waiters.shift();\n        waiter?.(chunk);\n      } else {\n        this.buffer.push(chunk);\n      }\n    }\n  }\n\n  private emit<K extends keyof RealtimeEvents>(\n    event: K,\n    ...args: Parameters<RealtimeEvents[K]>\n  ): void {\n    const handlers = this.listeners.get(event);\n    handlers?.forEach((handler) => {\n      try {\n        (handler as (...args: Parameters<RealtimeEvents[K]>) => void)(...args);\n      } catch {\n        // Ignore listener errors\n      }\n    });\n  }\n\n  /**\n   * AsyncIterable implementation for `for await` loops.\n   */\n  async *[Symbol.asyncIterator](): AsyncIterator<TranscriptionChunk> {\n    if (this.closed) {\n      throw new StreamClosedError();\n    }\n\n    while (!this.closed) {\n      // Return buffered chunks first\n      const buffered = this.buffer.shift();\n      if (buffered) {\n        yield buffered;\n        continue;\n      }\n\n      // Wait for next chunk\n      const chunk = await new Promise<TranscriptionChunk | null>((resolve) => {\n        if (this.closed) {\n          resolve(null);\n          return;\n        }\n        this.waiters.push(resolve);\n      });\n\n      if (chunk === null) {\n        break;\n      }\n\n      yield chunk;\n    }\n  }\n\n  /**\n   * Close the stream and disconnect.\n   */\n  close(): void {\n    // Emit last chunk as final\n    if (this.lastChunk) {\n      const finalChunk: TranscriptionChunk = { ...this.lastChunk, isFinal: true };\n      this.emitChunk(finalChunk);\n      this.lastChunk = null;\n    }\n\n    this.closed = true;\n    this.connection.disconnect();\n    this.buffer = [];\n    this.lastChunkId = null;\n    for (const waiter of this.waiters) {\n      waiter(null);\n    }\n    this.waiters = [];\n  }\n\n  /**\n   * Whether the stream is currently connected.\n   */\n  get connected(): boolean {\n    return this.connection.connected;\n  }\n}\n","import { RealtimeStream } from './stream.js';\nimport type { RealtimeConfig, TranscriptionChunk } from './types.js';\n\n/**\n * API for realtime transcription streaming.\n */\nexport interface RealtimeAPI {\n  /**\n   * Connect to a live transcription stream.\n   *\n   * @param transcriptId - The meeting/transcript ID to stream\n   * @returns Connected RealtimeStream\n   *\n   * @example Event-based\n   * ```typescript\n   * const stream = await client.realtime.connect('meeting-123');\n   * stream.on('chunk', (chunk) => {\n   *   console.log(`[${chunk.speaker_name}]: ${chunk.text}`);\n   * });\n   * ```\n   */\n  connect(transcriptId: string): Promise<RealtimeStream>;\n\n  /**\n   * Stream transcription chunks as an async iterable.\n   * Handles connection automatically.\n   *\n   * @param transcriptId - The meeting/transcript ID to stream\n   * @returns AsyncIterable of transcription chunks\n   *\n   * @example\n   * ```typescript\n   * for await (const chunk of client.realtime.stream('meeting-123')) {\n   *   console.log(`[${chunk.speaker_name}]: ${chunk.text}`);\n   * }\n   * ```\n   */\n  stream(transcriptId: string): AsyncIterable<TranscriptionChunk>;\n}\n\n/**\n * Create the realtime API bound to config.\n * @param apiKey - API key for authentication\n * @param baseConfig - Optional base configuration for all streams\n */\nexport function createRealtimeAPI(\n  apiKey: string,\n  baseConfig?: Partial<Omit<RealtimeConfig, 'apiKey' | 'transcriptId'>>\n): RealtimeAPI {\n  return {\n    async connect(transcriptId: string): Promise<RealtimeStream> {\n      const stream = new RealtimeStream({\n        apiKey,\n        transcriptId,\n        ...baseConfig,\n      });\n      await stream.connect();\n      return stream;\n    },\n\n    async *stream(transcriptId: string): AsyncIterable<TranscriptionChunk> {\n      const stream = new RealtimeStream({\n        apiKey,\n        transcriptId,\n        ...baseConfig,\n      });\n\n      try {\n        await stream.connect();\n        yield* stream;\n      } finally {\n        stream.close();\n      }\n    },\n  };\n}\n","import { GraphQLClient } from './graphql/client.js';\nimport { type AudioAPI, createAudioAPI } from './graphql/mutations/audio.js';\nimport {\n  createTranscriptsMutationsAPI,\n  type TranscriptsMutationsAPI,\n} from './graphql/mutations/transcripts.js';\nimport { createUsersMutationsAPI, type UsersMutationsAPI } from './graphql/mutations/users.js';\nimport { type AIAppsAPI, createAIAppsAPI } from './graphql/queries/ai-apps.js';\nimport { type BitesAPI, createBitesAPI } from './graphql/queries/bites.js';\nimport { createMeetingsAPI, type MeetingsAPI } from './graphql/queries/meetings.js';\nimport { createTranscriptsAPI, type TranscriptsAPI } from './graphql/queries/transcripts.js';\nimport { createUsersAPI, type UsersAPI } from './graphql/queries/users.js';\nimport { createRealtimeAPI, type RealtimeAPI } from './realtime/api.js';\nimport type { FirefliesConfig, RateLimitState } from './types/config.js';\n\n/**\n * Main client for the Fireflies API.\n *\n * @example\n * ```typescript\n * import { FirefliesClient } from 'fireflies-api';\n *\n * const client = new FirefliesClient({\n *   apiKey: process.env.FIREFLIES_API_KEY!,\n * });\n *\n * // List recent transcripts\n * const transcripts = await client.transcripts.list({ limit: 10 });\n *\n * // Get a specific transcript\n * const transcript = await client.transcripts.get('transcript-id');\n *\n * // Get current user\n * const me = await client.users.me();\n *\n * // List team members\n * const team = await client.users.list();\n *\n * // List bites\n * const bites = await client.bites.list({ mine: true });\n *\n * // Check active meetings\n * const meetings = await client.meetings.active();\n *\n * // List AI App outputs\n * const apps = await client.aiApps.list({ transcript_id: 'abc123' });\n * ```\n */\nexport class FirefliesClient {\n  private readonly graphql: GraphQLClient;\n\n  /**\n   * Transcript operations: list, get, search, delete.\n   */\n  readonly transcripts: TranscriptsAPI & TranscriptsMutationsAPI;\n\n  /**\n   * User operations: me, get, list, setRole.\n   */\n  readonly users: UsersAPI & UsersMutationsAPI;\n\n  /**\n   * Bite operations: get, list, create.\n   */\n  readonly bites: BitesAPI;\n\n  /**\n   * Meeting operations: active meetings, add bot.\n   */\n  readonly meetings: MeetingsAPI;\n\n  /**\n   * Audio operations: upload audio for transcription.\n   */\n  readonly audio: AudioAPI;\n\n  /**\n   * AI Apps operations: list outputs.\n   */\n  readonly aiApps: AIAppsAPI;\n\n  /**\n   * Realtime transcription streaming.\n   */\n  readonly realtime: RealtimeAPI;\n\n  /**\n   * Create a new Fireflies client.\n   *\n   * @param config - Client configuration\n   * @throws FirefliesError if API key is missing\n   */\n  constructor(config: FirefliesConfig) {\n    this.graphql = new GraphQLClient(config);\n\n    // Combine queries and mutations for each resource\n    const transcriptsQueries = createTranscriptsAPI(this.graphql);\n    const transcriptsMutations = createTranscriptsMutationsAPI(this.graphql);\n    this.transcripts = { ...transcriptsQueries, ...transcriptsMutations };\n\n    const usersQueries = createUsersAPI(this.graphql);\n    const usersMutations = createUsersMutationsAPI(this.graphql);\n    this.users = { ...usersQueries, ...usersMutations };\n\n    this.bites = createBitesAPI(this.graphql);\n    this.meetings = createMeetingsAPI(this.graphql);\n    this.audio = createAudioAPI(this.graphql);\n    this.aiApps = createAIAppsAPI(this.graphql);\n    this.realtime = createRealtimeAPI(config.apiKey);\n  }\n\n  /**\n   * Get the current rate limit state.\n   * Returns undefined if rate limit tracking is not configured.\n   *\n   * @example\n   * ```typescript\n   * const client = new FirefliesClient({\n   *   apiKey: '...',\n   *   rateLimit: { warningThreshold: 10 }\n   * });\n   *\n   * await client.users.me();\n   * console.log(client.rateLimits);\n   * // { remaining: 59, limit: 60, resetInSeconds: 60, updatedAt: 1706299500000 }\n   * ```\n   */\n  get rateLimits(): RateLimitState | undefined {\n    return this.graphql.rateLimitState;\n  }\n}\n","import { createHmac, timingSafeEqual } from 'node:crypto';\nimport type { VerifyOptions } from './types.js';\n\n/**\n * Verify the authenticity of a Fireflies webhook using HMAC SHA-256.\n *\n * Uses timing-safe comparison to prevent timing attacks.\n *\n * @param options - Verification options\n * @returns true if the signature is valid, false otherwise\n *\n * @example\n * ```typescript\n * const isValid = verifyWebhookSignature({\n *   payload: req.body,\n *   signature: req.headers['x-hub-signature'],\n *   secret: process.env.WEBHOOK_SECRET,\n * });\n *\n * if (!isValid) {\n *   return res.status(401).send('Invalid signature');\n * }\n * ```\n */\nexport function verifyWebhookSignature(options: VerifyOptions): boolean {\n  const { payload, signature, secret } = options;\n\n  if (!signature || !secret) {\n    return false;\n  }\n\n  // Convert payload to string if object\n  const payloadString = typeof payload === 'string' ? payload : JSON.stringify(payload);\n\n  // Compute HMAC SHA-256\n  const computed = createHmac('sha256', secret).update(payloadString).digest('hex');\n\n  // Timing-safe comparison to prevent timing attacks\n  try {\n    return timingSafeEqual(Buffer.from(signature), Buffer.from(computed));\n  } catch {\n    // Different lengths will throw an error\n    return false;\n  }\n}\n","import { WebhookParseError, WebhookVerificationError } from '../errors.js';\nimport type { ParseOptions, WebhookEventType, WebhookPayload } from './types.js';\nimport { verifyWebhookSignature } from './verify.js';\n\n/** Valid webhook event types */\nconst VALID_EVENT_TYPES: WebhookEventType[] = ['Transcription completed'];\n\n/**\n * Check if a value is a valid webhook event type.\n */\nfunction isValidEventType(value: string): value is WebhookEventType {\n  return VALID_EVENT_TYPES.includes(value as WebhookEventType);\n}\n\n/**\n * Type guard to check if a payload is a valid WebhookPayload.\n *\n * @param payload - The payload to validate\n * @returns true if the payload matches the WebhookPayload structure\n *\n * @example\n * ```typescript\n * if (isValidWebhookPayload(req.body)) {\n *   // req.body is now typed as WebhookPayload\n *   console.log(req.body.meetingId);\n * }\n * ```\n */\nexport function isValidWebhookPayload(payload: unknown): payload is WebhookPayload {\n  if (!payload || typeof payload !== 'object') {\n    return false;\n  }\n\n  // biome-ignore lint/complexity/useLiteralKeys: TypeScript requires bracket access for index signatures\n  const meetingId = (payload as Record<string, unknown>)['meetingId'];\n  // biome-ignore lint/complexity/useLiteralKeys: TypeScript requires bracket access for index signatures\n  const eventType = (payload as Record<string, unknown>)['eventType'];\n  // biome-ignore lint/complexity/useLiteralKeys: TypeScript requires bracket access for index signatures\n  const clientReferenceId = (payload as Record<string, unknown>)['clientReferenceId'];\n\n  return (\n    typeof meetingId === 'string' &&\n    typeof eventType === 'string' &&\n    isValidEventType(eventType) &&\n    (clientReferenceId === undefined || typeof clientReferenceId === 'string')\n  );\n}\n\n/**\n * Parse and validate a Fireflies webhook payload.\n *\n * Optionally verifies the webhook signature if signature and secret are provided.\n *\n * @param payload - The webhook payload to parse\n * @param options - Optional verification options\n * @returns The validated WebhookPayload\n * @throws {WebhookVerificationError} If signature verification fails\n * @throws {WebhookParseError} If payload structure is invalid\n *\n * @example\n * ```typescript\n * // Parse without verification\n * const event = parseWebhookPayload(req.body);\n * console.log(event.meetingId);\n *\n * // Parse with verification\n * const event = parseWebhookPayload(req.body, {\n *   signature: req.headers['x-hub-signature'],\n *   secret: process.env.WEBHOOK_SECRET,\n * });\n * ```\n */\nexport function parseWebhookPayload(payload: unknown, options?: ParseOptions): WebhookPayload {\n  // Verify signature if both signature and secret are provided\n  if (options?.signature && options?.secret) {\n    const isValid = verifyWebhookSignature({\n      payload: payload as string | object,\n      signature: options.signature,\n      secret: options.secret,\n    });\n\n    if (!isValid) {\n      throw new WebhookVerificationError('Invalid webhook signature');\n    }\n  }\n\n  // Validate payload structure\n  if (!isValidWebhookPayload(payload)) {\n    throw new WebhookParseError(\n      'Invalid webhook payload: expected meetingId (string), eventType (valid event type), and optional clientReferenceId (string)'\n    );\n  }\n\n  return payload;\n}\n","import { FirefliesClient } from '../client.js';\nimport { WebhookParseError, WebhookVerificationError } from '../errors.js';\nimport type { Transcript } from '../types/transcript.js';\nimport { parseWebhookPayload } from '../webhooks/parse.js';\nimport type { WebhookPayload } from '../webhooks/types.js';\nimport type {\n  WebhookHandlerContext,\n  WebhookMiddlewareOptions,\n  WebhookProcessInput,\n  WebhookProcessResult,\n} from './types.js';\n\n/**\n * Validate webhook middleware options.\n *\n * @param options - The options to validate\n * @throws Error if required options are missing\n */\nexport function validateOptions(options: WebhookMiddlewareOptions): void {\n  if (!options.secret || !options.secret.trim()) {\n    throw new Error('Webhook middleware: secret is required');\n  }\n}\n\n/**\n * Parameters for building a handler context.\n */\nexport interface BuildContextParams {\n  /** The validated webhook payload */\n  payload: WebhookPayload;\n  /** API key for creating client */\n  apiKey?: string;\n  /** Pre-fetched transcript (optional) */\n  transcript?: Transcript;\n}\n\n/**\n * Build a handler context from the given parameters.\n *\n * @param params - The parameters for building the context\n * @returns The handler context\n */\nexport function buildHandlerContext(params: BuildContextParams): WebhookHandlerContext {\n  const { payload, apiKey, transcript } = params;\n\n  const context: WebhookHandlerContext = {\n    payload,\n  };\n\n  if (apiKey) {\n    context.client = new FirefliesClient({ apiKey });\n  }\n\n  if (transcript) {\n    context.transcript = transcript;\n  }\n\n  return context;\n}\n\n/**\n * Parse raw body to string.\n */\nfunction parseRawBody(rawBody: string | Buffer): string {\n  return Buffer.isBuffer(rawBody) ? rawBody.toString('utf-8') : rawBody;\n}\n\n/**\n * Parse and validate the webhook payload from raw input.\n */\nfunction parseAndValidatePayload(\n  rawBody: string | Buffer,\n  signature: string | undefined,\n  secret: string\n): WebhookPayload {\n  if (!signature) {\n    throw new WebhookVerificationError('Missing webhook signature');\n  }\n\n  const bodyString = parseRawBody(rawBody);\n\n  let jsonPayload: unknown;\n  try {\n    jsonPayload = JSON.parse(bodyString);\n  } catch {\n    throw new WebhookParseError('Invalid JSON in webhook body');\n  }\n\n  return parseWebhookPayload(jsonPayload, { signature, secret });\n}\n\n/**\n * Optionally fetch transcript if apiKey provided and autoFetch enabled.\n */\nasync function fetchTranscriptIfEnabled(\n  payload: WebhookPayload,\n  apiKey: string | undefined,\n  autoFetch: boolean | undefined\n): Promise<Transcript | undefined> {\n  if (!apiKey || autoFetch === false) {\n    return undefined;\n  }\n\n  try {\n    const client = new FirefliesClient({ apiKey });\n    return await client.transcripts.get(payload.meetingId);\n  } catch {\n    // Silently ignore fetch errors - transcript will be undefined\n    return undefined;\n  }\n}\n\n/**\n * Execute event handlers with the given context.\n */\nasync function executeHandlers(\n  context: WebhookHandlerContext,\n  options: WebhookMiddlewareOptions\n): Promise<void> {\n  const { onEvent, onTranscriptionCompleted } = options;\n\n  if (onEvent) {\n    await onEvent(context);\n  }\n\n  if (context.payload.eventType === 'Transcription completed' && onTranscriptionCompleted) {\n    await onTranscriptionCompleted(context);\n  }\n}\n\n/**\n * Map an error to an appropriate HTTP response.\n */\nfunction mapErrorToResponse(error: unknown): WebhookProcessResult {\n  if (error instanceof WebhookVerificationError) {\n    return {\n      success: false,\n      statusCode: 401,\n      body: 'Invalid webhook signature',\n      error,\n    };\n  }\n\n  if (error instanceof WebhookParseError) {\n    return {\n      success: false,\n      statusCode: 400,\n      body: 'Invalid webhook payload',\n      error,\n    };\n  }\n\n  if (error instanceof SyntaxError) {\n    return {\n      success: false,\n      statusCode: 400,\n      body: 'Invalid JSON in webhook body',\n      error,\n    };\n  }\n\n  // Handler errors - don't expose internal details\n  return {\n    success: false,\n    statusCode: 500,\n    body: 'Internal server error',\n    error: error instanceof Error ? error : new Error(String(error)),\n  };\n}\n\n/**\n * Process a webhook request.\n *\n * This is the core processing logic used by all framework adapters.\n * It handles:\n * 1. Parsing JSON body\n * 2. Verifying signature\n * 3. Building handler context (optionally with auto-fetched transcript)\n * 4. Calling event handlers\n * 5. Mapping errors to appropriate HTTP responses\n *\n * @param input - The webhook request input\n * @param options - The middleware options\n * @returns The processing result with status code and body\n */\nexport async function processWebhook(\n  input: WebhookProcessInput,\n  options: WebhookMiddlewareOptions\n): Promise<WebhookProcessResult> {\n  const { rawBody, signature } = input;\n  const { secret, apiKey, autoFetch, onError } = options;\n\n  let parsedPayload: WebhookPayload | undefined;\n\n  try {\n    parsedPayload = parseAndValidatePayload(rawBody, signature, secret);\n\n    const transcript = await fetchTranscriptIfEnabled(parsedPayload, apiKey, autoFetch);\n\n    const context = buildHandlerContext({\n      payload: parsedPayload,\n      apiKey,\n      transcript,\n    });\n\n    await executeHandlers(context, options);\n\n    return {\n      success: true,\n      statusCode: 200,\n      body: 'ok',\n      payload: parsedPayload,\n    };\n  } catch (error) {\n    if (onError && error instanceof Error) {\n      await onError(error, parsedPayload);\n    }\n\n    return mapErrorToResponse(error);\n  }\n}\n","import type { Request, RequestHandler, Response } from 'express';\nimport { processWebhook, validateOptions } from './core.js';\nimport type { WebhookMiddlewareOptions } from './types.js';\n\n/**\n * Create an Express middleware handler for Fireflies webhooks.\n *\n * Requires `express.raw({ type: 'application/json' })` middleware before this handler\n * to receive the raw body for signature verification.\n *\n * @param options - Webhook middleware options\n * @returns Express request handler\n *\n * @example\n * ```typescript\n * import express from 'express';\n * import { createWebhookHandler } from 'fireflies-api/express';\n *\n * const app = express();\n *\n * app.post('/webhooks/fireflies',\n *   express.raw({ type: 'application/json' }),\n *   createWebhookHandler({\n *     secret: process.env.WEBHOOK_SECRET!,\n *     apiKey: process.env.FIREFLIES_API_KEY,\n *     onTranscriptionCompleted: async ({ payload, transcript }) => {\n *       console.log(`Transcript ready: ${transcript?.title}`);\n *     },\n *   })\n * );\n * ```\n */\nexport function createWebhookHandler(options: WebhookMiddlewareOptions): RequestHandler {\n  validateOptions(options);\n\n  return async (req: Request, res: Response): Promise<void> => {\n    // Get raw body - should be a Buffer when using express.raw()\n    const rawBody = req.body as Buffer | string;\n\n    // Get signature from header\n    const signature = req.headers['x-hub-signature'] as string | undefined;\n\n    // Process the webhook\n    const result = await processWebhook(\n      {\n        rawBody,\n        signature,\n      },\n      options\n    );\n\n    // Send response\n    res.status(result.statusCode).send(result.body);\n  };\n}\n"]}