fireflies-api 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +64 -0
  3. package/dist/action-items-CC9yUxHY.d.cts +380 -0
  4. package/dist/action-items-CC9yUxHY.d.ts +380 -0
  5. package/dist/cli/index.cjs +3909 -0
  6. package/dist/cli/index.cjs.map +1 -0
  7. package/dist/cli/index.d.cts +2 -0
  8. package/dist/cli/index.d.ts +2 -0
  9. package/dist/cli/index.js +3906 -0
  10. package/dist/cli/index.js.map +1 -0
  11. package/dist/index.cjs +3389 -0
  12. package/dist/index.cjs.map +1 -0
  13. package/dist/index.d.cts +966 -0
  14. package/dist/index.d.ts +966 -0
  15. package/dist/index.js +3344 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/middleware/express.cjs +2491 -0
  18. package/dist/middleware/express.cjs.map +1 -0
  19. package/dist/middleware/express.d.cts +36 -0
  20. package/dist/middleware/express.d.ts +36 -0
  21. package/dist/middleware/express.js +2489 -0
  22. package/dist/middleware/express.js.map +1 -0
  23. package/dist/middleware/fastify.cjs +2501 -0
  24. package/dist/middleware/fastify.cjs.map +1 -0
  25. package/dist/middleware/fastify.d.cts +66 -0
  26. package/dist/middleware/fastify.d.ts +66 -0
  27. package/dist/middleware/fastify.js +2498 -0
  28. package/dist/middleware/fastify.js.map +1 -0
  29. package/dist/middleware/hono.cjs +2493 -0
  30. package/dist/middleware/hono.cjs.map +1 -0
  31. package/dist/middleware/hono.d.cts +37 -0
  32. package/dist/middleware/hono.d.ts +37 -0
  33. package/dist/middleware/hono.js +2490 -0
  34. package/dist/middleware/hono.js.map +1 -0
  35. package/dist/schemas/index.cjs +307 -0
  36. package/dist/schemas/index.cjs.map +1 -0
  37. package/dist/schemas/index.d.cts +926 -0
  38. package/dist/schemas/index.d.ts +926 -0
  39. package/dist/schemas/index.js +268 -0
  40. package/dist/schemas/index.js.map +1 -0
  41. package/dist/speaker-analytics-Dr46LKyP.d.ts +275 -0
  42. package/dist/speaker-analytics-l45LXqO1.d.cts +275 -0
  43. package/dist/types-BX-3JcRI.d.cts +41 -0
  44. package/dist/types-C_XxdRd1.d.cts +1546 -0
  45. package/dist/types-CaHcwnKw.d.ts +41 -0
  46. package/dist/types-DIPZmUl3.d.ts +1546 -0
  47. package/package.json +126 -0
@@ -0,0 +1 @@
1
+ {"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/domain-utils.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/hono.ts"],"names":["sleep","DEFAULT_TIMEOUT","io","createHmac","timingSafeEqual"],"mappings":"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","file":"hono.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 * 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","/**\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 { 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 { extractDomain, hasExternalParticipants } from '../../helpers/domain-utils.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 { 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 * 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/**\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 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 ${TRANSCRIPT_LIST_FIELDS}\n }\n }\n `;\n\n const variables = buildListVariables(params);\n const data = await client.execute<{ transcripts: TranscriptResponse[] }>(query, variables);\n\n return data.transcripts.map(normalizeTranscript);\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 // Phase 1: Find matching transcripts via server-side search\n const transcripts: Transcript[] = [];\n for await (const t of this.listAll({\n keyword: query,\n scope,\n ...listParams,\n })) {\n transcripts.push(t);\n if (limit && transcripts.length >= limit) break;\n }\n\n // Phase 2: Fetch full transcripts and search locally\n const allMatches: SearchResults['matches'] = [];\n let transcriptsWithMatches = 0;\n\n for (const t of transcripts) {\n const full = await this.get(t.id, { includeSentences: true });\n const matches = searchTranscript(full, {\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 (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 })) {\n // Skip if filtering for external and no external participants\n if (internalDomain && !hasExternalParticipants(t.participants, internalDomain)) {\n continue;\n }\n\n // Fetch full transcript with sentences\n const full = await this.get(t.id, { includeSentences: true, includeSummary: false });\n transcripts.push(full);\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 (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 })) {\n // Fetch summary for action items\n const full = await this.get(t.id, { includeSentences: false, includeSummary: true });\n transcripts.push(full);\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}\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","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 { Context, Handler } from 'hono';\nimport type { ContentfulStatusCode } from 'hono/utils/http-status';\nimport { processWebhook, validateOptions } from './core.js';\nimport type { WebhookMiddlewareOptions } from './types.js';\n\n/**\n * Create a Hono handler for Fireflies webhooks.\n *\n * @param options - Webhook middleware options\n * @returns Hono handler\n *\n * @example\n * ```typescript\n * import { Hono } from 'hono';\n * import { webhookHandler } from 'fireflies-api/hono';\n *\n * const app = new Hono();\n *\n * app.post('/webhooks/fireflies', webhookHandler({\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 */\nexport function webhookHandler(options: WebhookMiddlewareOptions): Handler {\n validateOptions(options);\n\n return async (c: Context): Promise<Response> => {\n // Get raw body as text\n const rawBody = await c.req.text();\n\n // Get signature from header\n const signature = c.req.header('x-hub-signature');\n\n // Process the webhook\n const result = await processWebhook(\n {\n rawBody,\n signature,\n },\n options\n );\n\n // Return response\n return c.text(result.body, result.statusCode as ContentfulStatusCode);\n };\n}\n\n/**\n * Alias for webhookHandler for consistency with other adapters.\n *\n * @param options - Webhook middleware options\n * @returns Hono handler\n */\nexport const createWebhookHandler = webhookHandler;\n"]}
@@ -0,0 +1,37 @@
1
+ import { Handler } from 'hono';
2
+ import { W as WebhookMiddlewareOptions } from '../types-BX-3JcRI.cjs';
3
+ import '../types-C_XxdRd1.cjs';
4
+ import '../action-items-CC9yUxHY.cjs';
5
+
6
+ /**
7
+ * Create a Hono handler for Fireflies webhooks.
8
+ *
9
+ * @param options - Webhook middleware options
10
+ * @returns Hono handler
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { Hono } from 'hono';
15
+ * import { webhookHandler } from 'fireflies-api/hono';
16
+ *
17
+ * const app = new Hono();
18
+ *
19
+ * app.post('/webhooks/fireflies', webhookHandler({
20
+ * secret: process.env.WEBHOOK_SECRET!,
21
+ * apiKey: process.env.FIREFLIES_API_KEY,
22
+ * onTranscriptionCompleted: async ({ payload, transcript }) => {
23
+ * console.log(`Transcript ready: ${transcript?.title}`);
24
+ * },
25
+ * }));
26
+ * ```
27
+ */
28
+ declare function webhookHandler(options: WebhookMiddlewareOptions): Handler;
29
+ /**
30
+ * Alias for webhookHandler for consistency with other adapters.
31
+ *
32
+ * @param options - Webhook middleware options
33
+ * @returns Hono handler
34
+ */
35
+ declare const createWebhookHandler: typeof webhookHandler;
36
+
37
+ export { createWebhookHandler, webhookHandler };
@@ -0,0 +1,37 @@
1
+ import { Handler } from 'hono';
2
+ import { W as WebhookMiddlewareOptions } from '../types-CaHcwnKw.js';
3
+ import '../types-DIPZmUl3.js';
4
+ import '../action-items-CC9yUxHY.js';
5
+
6
+ /**
7
+ * Create a Hono handler for Fireflies webhooks.
8
+ *
9
+ * @param options - Webhook middleware options
10
+ * @returns Hono handler
11
+ *
12
+ * @example
13
+ * ```typescript
14
+ * import { Hono } from 'hono';
15
+ * import { webhookHandler } from 'fireflies-api/hono';
16
+ *
17
+ * const app = new Hono();
18
+ *
19
+ * app.post('/webhooks/fireflies', webhookHandler({
20
+ * secret: process.env.WEBHOOK_SECRET!,
21
+ * apiKey: process.env.FIREFLIES_API_KEY,
22
+ * onTranscriptionCompleted: async ({ payload, transcript }) => {
23
+ * console.log(`Transcript ready: ${transcript?.title}`);
24
+ * },
25
+ * }));
26
+ * ```
27
+ */
28
+ declare function webhookHandler(options: WebhookMiddlewareOptions): Handler;
29
+ /**
30
+ * Alias for webhookHandler for consistency with other adapters.
31
+ *
32
+ * @param options - Webhook middleware options
33
+ * @returns Hono handler
34
+ */
35
+ declare const createWebhookHandler: typeof webhookHandler;
36
+
37
+ export { createWebhookHandler, webhookHandler };