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.
- package/LICENSE +21 -0
- package/README.md +64 -0
- package/dist/action-items-CC9yUxHY.d.cts +380 -0
- package/dist/action-items-CC9yUxHY.d.ts +380 -0
- package/dist/cli/index.cjs +3909 -0
- package/dist/cli/index.cjs.map +1 -0
- package/dist/cli/index.d.cts +2 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +3906 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/index.cjs +3389 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +966 -0
- package/dist/index.d.ts +966 -0
- package/dist/index.js +3344 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware/express.cjs +2491 -0
- package/dist/middleware/express.cjs.map +1 -0
- package/dist/middleware/express.d.cts +36 -0
- package/dist/middleware/express.d.ts +36 -0
- package/dist/middleware/express.js +2489 -0
- package/dist/middleware/express.js.map +1 -0
- package/dist/middleware/fastify.cjs +2501 -0
- package/dist/middleware/fastify.cjs.map +1 -0
- package/dist/middleware/fastify.d.cts +66 -0
- package/dist/middleware/fastify.d.ts +66 -0
- package/dist/middleware/fastify.js +2498 -0
- package/dist/middleware/fastify.js.map +1 -0
- package/dist/middleware/hono.cjs +2493 -0
- package/dist/middleware/hono.cjs.map +1 -0
- package/dist/middleware/hono.d.cts +37 -0
- package/dist/middleware/hono.d.ts +37 -0
- package/dist/middleware/hono.js +2490 -0
- package/dist/middleware/hono.js.map +1 -0
- package/dist/schemas/index.cjs +307 -0
- package/dist/schemas/index.cjs.map +1 -0
- package/dist/schemas/index.d.cts +926 -0
- package/dist/schemas/index.d.ts +926 -0
- package/dist/schemas/index.js +268 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/speaker-analytics-Dr46LKyP.d.ts +275 -0
- package/dist/speaker-analytics-l45LXqO1.d.cts +275 -0
- package/dist/types-BX-3JcRI.d.cts +41 -0
- package/dist/types-C_XxdRd1.d.cts +1546 -0
- package/dist/types-CaHcwnKw.d.ts +41 -0
- package/dist/types-DIPZmUl3.d.ts +1546 -0
- 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/helpers/accumulator.ts","../src/helpers/batch.ts","../src/helpers/external-questions.ts","../src/helpers/markdown.ts","../src/utils/dedup.ts","../src/helpers/multi-user.ts","../src/helpers/normalize.ts","../src/helpers/speaker-analytics.ts","../src/helpers/videos.ts","../src/webhooks/verify.ts","../src/webhooks/parse.ts"],"names":["delay","sleep","groupBy","DEFAULT_TIMEOUT","DEFAULT_OPTIONS","normalizeTranscript","calculateDuration"],"mappings":"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","file":"index.js","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 type { TranscriptionChunk } from '../realtime/types.js';\n\n/**\n * A speaker turn containing one or more consecutive chunks from the same speaker.\n */\nexport interface SpeakerTurn {\n /** Name of the speaker */\n speaker: string;\n /** Combined text from all chunks in this turn */\n text: string;\n /** Start time of the first chunk in seconds */\n startTime: number;\n /** End time of the last chunk in seconds */\n endTime: number;\n /** Original chunks that make up this turn */\n chunks: TranscriptionChunk[];\n}\n\n/**\n * The accumulated transcript state.\n */\nexport interface AccumulatedTranscript {\n /** Speaker turns in chronological order */\n turns: SpeakerTurn[];\n /** Unique speaker names in order of first appearance */\n speakers: string[];\n /** Total word count across all turns */\n wordCount: number;\n /** Duration in seconds from first chunk start to last chunk end */\n duration: number;\n /** Total number of final chunks accumulated */\n chunkCount: number;\n}\n\n/**\n * Accumulates streaming transcription chunks into a coherent transcript.\n *\n * Chunks from the same speaker are merged into turns. Statistics like word count\n * and duration are computed on demand.\n *\n * @example\n * ```typescript\n * const accumulator = new TranscriptAccumulator();\n *\n * for await (const chunk of client.realtime.stream(meetingId)) {\n * accumulator.add(chunk);\n * const transcript = accumulator.getTranscript();\n * console.log(`${transcript.speakers.length} speakers, ${transcript.wordCount} words`);\n * }\n *\n * const final = accumulator.getTranscript();\n * ```\n */\nexport class TranscriptAccumulator {\n private turns: SpeakerTurn[] = [];\n private currentTurn: SpeakerTurn | null = null;\n private seenChunkIds = new Set<string>();\n\n /**\n * Add a chunk to the accumulator.\n *\n * Only final chunks are accumulated; non-final chunks are ignored.\n * Duplicate chunk IDs are also ignored.\n *\n * @param chunk - The transcription chunk to add\n */\n add(chunk: TranscriptionChunk): void {\n if (!chunk.isFinal) return;\n if (this.seenChunkIds.has(chunk.chunk_id)) return;\n\n this.seenChunkIds.add(chunk.chunk_id);\n\n if (this.currentTurn && this.currentTurn.speaker === chunk.speaker_name) {\n this.currentTurn.text += ` ${chunk.text}`;\n this.currentTurn.endTime = chunk.end_time;\n this.currentTurn.chunks.push(chunk);\n } else {\n this.currentTurn = {\n speaker: chunk.speaker_name,\n text: chunk.text,\n startTime: chunk.start_time,\n endTime: chunk.end_time,\n chunks: [chunk],\n };\n this.turns.push(this.currentTurn);\n }\n }\n\n /**\n * Get the current accumulated transcript state.\n *\n * Statistics are computed on demand to ensure accuracy.\n *\n * @returns The accumulated transcript with turns, speakers, and statistics\n */\n getTranscript(): AccumulatedTranscript {\n const speakers = this.getUniqueSpeakers();\n const wordCount = this.computeWordCount();\n const duration = this.computeDuration();\n\n return {\n turns: this.turns,\n speakers,\n wordCount,\n duration,\n chunkCount: this.seenChunkIds.size,\n };\n }\n\n /**\n * Clear all accumulated data.\n *\n * Useful for resetting the accumulator between sessions.\n */\n clear(): void {\n this.turns = [];\n this.currentTurn = null;\n this.seenChunkIds.clear();\n }\n\n private getUniqueSpeakers(): string[] {\n const seen = new Set<string>();\n const speakers: string[] = [];\n for (const turn of this.turns) {\n if (!seen.has(turn.speaker)) {\n seen.add(turn.speaker);\n speakers.push(turn.speaker);\n }\n }\n return speakers;\n }\n\n private computeWordCount(): number {\n let count = 0;\n for (const turn of this.turns) {\n if (turn.text.length === 0) continue;\n const words = turn.text.trim().split(/\\s+/);\n count += words.filter((w) => w.length > 0).length;\n }\n return count;\n }\n\n private computeDuration(): number {\n const firstTurn = this.turns[0];\n const lastTurn = this.turns[this.turns.length - 1];\n if (!firstTurn || !lastTurn) return 0;\n const firstChunk = firstTurn.chunks[0];\n if (!firstChunk) return 0;\n return lastTurn.endTime - firstChunk.start_time;\n }\n}\n","import { RateLimitError } from '../errors.js';\n\n/**\n * Options for batch processing.\n */\nexport interface BatchOptions {\n /**\n * Number of concurrent operations.\n * Currently only sequential (1) is supported.\n * @default 1\n */\n concurrency?: number;\n /**\n * Delay in milliseconds between operations.\n * @default 100\n */\n delayMs?: number;\n /**\n * Whether to automatically handle rate limit errors.\n * When true, waits for retryAfter and retries.\n * @default true\n */\n handleRateLimit?: boolean;\n /**\n * Maximum number of rate limit retries per item.\n * @default 3\n */\n maxRateLimitRetries?: number;\n}\n\n/**\n * Result of a batch operation on a single item.\n */\nexport type BatchResult<T, R> =\n | { item: T; result: R; error?: never }\n | { item: T; result?: never; error: Error };\n\n/**\n * Process items in batch with rate limiting and error handling.\n *\n * Yields results as they complete, allowing streaming processing.\n * On rate limit errors, automatically waits and retries if handleRateLimit is true.\n *\n * @param items - Items to process (sync or async iterable)\n * @param processor - Function to process each item\n * @param options - Batch processing options\n * @returns AsyncIterable yielding results (success or error) for each item\n *\n * @example\n * ```typescript\n * import { batch, FirefliesClient } from 'fireflies-api';\n *\n * const client = new FirefliesClient({ apiKey: 'your-api-key' });\n * const ids = ['id1', 'id2', 'id3'];\n *\n * for await (const result of batch(ids, id => client.transcripts.get(id))) {\n * if (result.error) {\n * console.error(`Failed to fetch ${result.item}: ${result.error.message}`);\n * } else {\n * console.log(`Got ${result.result.title}`);\n * }\n * }\n * ```\n */\nexport async function* batch<T, R>(\n items: Iterable<T> | AsyncIterable<T>,\n processor: (item: T) => Promise<R>,\n options: BatchOptions = {}\n): AsyncIterable<BatchResult<T, R>> {\n const { delayMs = 100, handleRateLimit = true, maxRateLimitRetries = 3 } = options;\n\n let isFirst = true;\n\n for await (const item of items) {\n // Add delay between items (not before first)\n if (!isFirst && delayMs > 0) {\n await delay(delayMs);\n }\n isFirst = false;\n\n yield await processWithRetry(item, processor, {\n handleRateLimit,\n maxRateLimitRetries,\n });\n }\n}\n\n/**\n * Process all items in batch and collect results.\n *\n * Unlike the streaming `batch()`, this waits for all items to complete\n * and returns results as an array.\n *\n * @param items - Array of items to process\n * @param processor - Function to process each item\n * @param options - Batch processing options plus continueOnError\n * @returns Array of successful results. When continueOnError is false, results\n * match input order. When true, failed items are omitted (array may be shorter).\n * @throws First error encountered if continueOnError is false (default)\n *\n * @example\n * ```typescript\n * import { batchAll, FirefliesClient } from 'fireflies-api';\n *\n * const client = new FirefliesClient({ apiKey: 'your-api-key' });\n * const ids = ['id1', 'id2', 'id3'];\n *\n * // Throws on first error\n * const transcripts = await batchAll(ids, id => client.transcripts.get(id));\n *\n * // Continues on error, collects successful results\n * const results = await batchAll(\n * ids,\n * id => client.transcripts.get(id),\n * { continueOnError: true }\n * );\n * ```\n */\nexport async function batchAll<T, R>(\n items: T[],\n processor: (item: T) => Promise<R>,\n options: BatchOptions & { continueOnError?: boolean } = {}\n): Promise<R[]> {\n const { continueOnError = false, ...batchOptions } = options;\n const results: R[] = [];\n const errors: Error[] = [];\n\n for await (const batchResult of batch(items, processor, batchOptions)) {\n if (batchResult.error) {\n if (!continueOnError) {\n throw batchResult.error;\n }\n errors.push(batchResult.error);\n } else {\n results.push(batchResult.result);\n }\n }\n\n return results;\n}\n\n/**\n * Process a single item with rate limit retry logic.\n */\nasync function processWithRetry<T, R>(\n item: T,\n processor: (item: T) => Promise<R>,\n options: { handleRateLimit: boolean; maxRateLimitRetries: number }\n): Promise<BatchResult<T, R>> {\n const { handleRateLimit, maxRateLimitRetries } = options;\n let retries = 0;\n\n while (true) {\n try {\n const result = await processor(item);\n return { item, result };\n } catch (err) {\n // Handle rate limit with retry\n if (handleRateLimit && err instanceof RateLimitError && retries < maxRateLimitRetries) {\n const waitTime = err.retryAfter ?? 1000;\n await delay(waitTime);\n retries++;\n continue;\n }\n\n // Return error for this item\n return {\n item,\n error: err instanceof Error ? err : new Error(String(err)),\n };\n }\n }\n}\n\n/**\n * Delay execution for a specified time.\n */\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import type { Transcript } from '../types/transcript.js';\n\n/**\n * A question asked by an external participant.\n */\nexport interface ExternalQuestion {\n /** The question text */\n text: string;\n /** Name of the speaker who asked the question */\n speakerName: string;\n /** Email of the speaker (if available from attendees) */\n speakerEmail?: string;\n /** Index of the sentence in the transcript */\n sentenceIndex: number;\n /** Start time as decimal seconds string */\n startTime: string;\n /** End time as decimal seconds string */\n endTime: string;\n}\n\n/**\n * Result of finding external participant questions.\n */\nexport interface ExternalQuestionsResult {\n /** List of external participants identified */\n externalParticipants: Array<{ name: string; email?: string }>;\n /** Questions asked by external participants */\n questions: ExternalQuestion[];\n /** Total count of questions */\n totalQuestions: number;\n}\n\n/**\n * Find questions asked by external participants in a transcript.\n *\n * This function analyzes a transcript to identify questions from participants\n * whose email domains don't match the specified internal domains.\n *\n * @param transcript - The transcript to analyze\n * @param internalDomains - Internal domain(s) to identify internal participants.\n * Can be a single domain string (e.g., '@mycompany.com' or 'mycompany.com')\n * or an array of domains.\n * @returns Object containing external participants, their questions, and count\n *\n * @example\n * ```typescript\n * const transcript = await client.transcripts.get('id');\n * const result = findExternalParticipantQuestions(transcript, '@mycompany.com');\n *\n * console.log(`Found ${result.totalQuestions} questions from external participants`);\n * for (const q of result.questions) {\n * console.log(`${q.speakerName}: ${q.text}`);\n * }\n * ```\n */\nexport function findExternalParticipantQuestions(\n transcript: Transcript,\n internalDomains: string | string[]\n): ExternalQuestionsResult {\n // Normalize domains to array and ensure they start with @\n const domains = normalizeDomains(internalDomains);\n\n // Build speaker name -> email mapping from meeting_attendees\n const speakerEmailMap = buildSpeakerEmailMap(transcript);\n\n // Classify speakers as internal/external\n const { externalSpeakers } = classifySpeakers(transcript, speakerEmailMap, domains);\n\n // Find questions from external speakers\n const questions: ExternalQuestion[] = [];\n\n for (const sentence of transcript.sentences ?? []) {\n // Check if this is a question\n if (!sentence.ai_filters?.question) {\n continue;\n }\n\n // Check if speaker is external\n if (!externalSpeakers.has(sentence.speaker_name)) {\n continue;\n }\n\n questions.push({\n text: sentence.text,\n speakerName: sentence.speaker_name,\n speakerEmail: speakerEmailMap.get(sentence.speaker_name),\n sentenceIndex: sentence.index,\n startTime: sentence.start_time,\n endTime: sentence.end_time,\n });\n }\n\n // Build external participants list\n const externalParticipants = Array.from(externalSpeakers).map((name) => ({\n name,\n email: speakerEmailMap.get(name),\n }));\n\n return {\n externalParticipants,\n questions,\n totalQuestions: questions.length,\n };\n}\n\n/**\n * Normalize domain input to array of lowercase domains with @ prefix.\n */\nfunction normalizeDomains(input: string | string[]): string[] {\n const raw = Array.isArray(input) ? input : [input];\n return raw.map((d) => {\n const domain = d.toLowerCase().trim();\n return domain.startsWith('@') ? domain : `@${domain}`;\n });\n}\n\n/**\n * Build a map of speaker names to email addresses from meeting_attendees.\n */\nfunction buildSpeakerEmailMap(transcript: Transcript): Map<string, string> {\n const map = new Map<string, string>();\n\n for (const attendee of transcript.meeting_attendees ?? []) {\n // Map by display name\n if (attendee.displayName && attendee.email) {\n map.set(attendee.displayName, attendee.email.toLowerCase());\n }\n // Also map by full name\n if (attendee.name && attendee.email) {\n map.set(attendee.name, attendee.email.toLowerCase());\n }\n }\n\n return map;\n}\n\n/**\n * Classify speakers as internal or external based on their email domain.\n */\nfunction classifySpeakers(\n transcript: Transcript,\n speakerEmailMap: Map<string, string>,\n internalDomains: string[]\n): { internalSpeakers: Set<string>; externalSpeakers: Set<string> } {\n const internalSpeakers = new Set<string>();\n const externalSpeakers = new Set<string>();\n\n // Get unique speaker names from sentences\n const speakerNames = new Set((transcript.sentences ?? []).map((s) => s.speaker_name));\n\n for (const name of speakerNames) {\n const email = speakerEmailMap.get(name);\n\n if (isInternal(email, internalDomains)) {\n internalSpeakers.add(name);\n } else {\n externalSpeakers.add(name);\n }\n }\n\n return { internalSpeakers, externalSpeakers };\n}\n\n/**\n * Check if an email belongs to an internal domain.\n * Speakers without email are considered external (conservative default).\n */\nfunction isInternal(email: string | undefined, internalDomains: string[]): boolean {\n if (!email) {\n return false;\n }\n\n const lowerEmail = email.toLowerCase();\n return internalDomains.some((domain) => lowerEmail.endsWith(domain));\n}\n","import type { TranscriptionChunk } from '../realtime/types.js';\nimport type { Sentence, Summary, Transcript } from '../types/transcript.js';\n\n/**\n * Options for transcriptToMarkdown().\n */\nexport interface MarkdownExportOptions {\n /** Include meeting metadata header (title, date, participants, duration). Default: true */\n includeMetadata?: boolean;\n /** Include AI-generated summary sections. Default: true */\n includeSummary?: boolean;\n /** Include action items section. Default: true */\n includeActionItems?: boolean;\n /** Format for action items: checkbox or plain list. Default: 'checkbox' */\n actionItemFormat?: 'checkbox' | 'list';\n /** Include timestamps for each sentence. Default: false */\n includeTimestamps?: boolean;\n /** How to format speaker names. Default: 'bold' */\n speakerFormat?: 'bold' | 'plain';\n /** Group consecutive sentences by same speaker. Default: true */\n groupBySpeaker?: boolean;\n /** Write output to file path (Node.js only). If set, also returns the string. */\n outputPath?: string;\n}\n\n/**\n * Options for chunksToMarkdown().\n */\nexport interface ChunksExportOptions {\n /** Meeting title (chunks don't include metadata). Default: 'Live Transcript' */\n title?: string;\n /** Include timestamps for each chunk. Default: false */\n includeTimestamps?: boolean;\n /** How to format speaker names. Default: 'bold' */\n speakerFormat?: 'bold' | 'plain';\n /** Group consecutive chunks by same speaker. Default: true */\n groupBySpeaker?: boolean;\n /** Write output to file path (Node.js only). If set, also returns the string. */\n outputPath?: string;\n}\n\nconst DEFAULT_OPTIONS: Required<Omit<MarkdownExportOptions, 'outputPath'>> = {\n includeMetadata: true,\n includeSummary: true,\n includeActionItems: true,\n actionItemFormat: 'checkbox',\n includeTimestamps: false,\n speakerFormat: 'bold',\n groupBySpeaker: true,\n};\n\nconst DEFAULT_CHUNKS_OPTIONS: Required<Omit<ChunksExportOptions, 'outputPath'>> = {\n title: 'Live Transcript',\n includeTimestamps: false,\n speakerFormat: 'bold',\n groupBySpeaker: true,\n};\n\n/**\n * Convert a completed Fireflies transcript to well-formatted Markdown.\n *\n * @param transcript - The transcript to convert\n * @param options - Formatting options\n * @returns Markdown string representation of the transcript\n *\n * @example\n * ```typescript\n * import { FirefliesClient, transcriptToMarkdown } from 'fireflies-api';\n *\n * const client = new FirefliesClient({ apiKey: 'your-api-key' });\n * const transcript = await client.transcripts.get('transcript-id');\n *\n * // Basic usage\n * const markdown = await transcriptToMarkdown(transcript);\n *\n * // With options\n * const markdown = await transcriptToMarkdown(transcript, {\n * includeTimestamps: true,\n * actionItemFormat: 'list',\n * });\n *\n * // Write to file\n * const markdown = await transcriptToMarkdown(transcript, {\n * outputPath: './meeting-notes.md',\n * });\n * ```\n */\nexport async function transcriptToMarkdown(\n transcript: Transcript,\n options: MarkdownExportOptions = {}\n): Promise<string> {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n const sections: string[] = [];\n\n if (opts.includeMetadata) {\n sections.push(formatMetadata(transcript));\n }\n\n if (opts.includeSummary && transcript.summary) {\n sections.push(formatSummary(transcript.summary, opts));\n }\n\n if (transcript.sentences && transcript.sentences.length > 0) {\n sections.push(formatTranscript(transcript.sentences, opts));\n }\n\n const content = sections.join('\\n\\n---\\n\\n');\n await writeIfOutputPath(content, options.outputPath);\n return content;\n}\n\n/**\n * Convert realtime transcription chunks to well-formatted Markdown.\n *\n * @param chunks - Array of transcription chunks from realtime stream\n * @param options - Formatting options\n * @returns Markdown string representation of the chunks\n *\n * @example\n * ```typescript\n * import { FirefliesClient, chunksToMarkdown } from 'fireflies-api';\n *\n * const client = new FirefliesClient({ apiKey: 'your-api-key' });\n *\n * // Accumulate chunks from realtime stream\n * const chunks: TranscriptionChunk[] = [];\n * for await (const chunk of client.realtime.stream(meetingId)) {\n * chunks.push(chunk);\n * }\n *\n * // Convert to markdown\n * const markdown = await chunksToMarkdown(chunks);\n *\n * // With options\n * const markdown = await chunksToMarkdown(chunks, {\n * title: 'Team Standup',\n * includeTimestamps: true,\n * });\n * ```\n */\nexport async function chunksToMarkdown(\n chunks: TranscriptionChunk[],\n options: ChunksExportOptions = {}\n): Promise<string> {\n const opts = { ...DEFAULT_CHUNKS_OPTIONS, ...options };\n\n const lines: string[] = [`# ${opts.title}`];\n\n if (chunks.length === 0) {\n lines.push('', '## Transcript', '', '*No transcription data*');\n } else {\n lines.push('', '## Transcript');\n\n if (opts.groupBySpeaker) {\n const groups = groupChunksBySpeaker(chunks);\n for (const group of groups) {\n lines.push('', formatChunkGroup(group, opts));\n }\n } else {\n for (const chunk of chunks) {\n lines.push('', formatChunk(chunk, opts));\n }\n }\n }\n\n const content = lines.join('\\n');\n await writeIfOutputPath(content, options.outputPath);\n return content;\n}\n\n// --- Internal helpers ---\n\nfunction formatMetadata(transcript: Transcript): string {\n const lines = [`# ${transcript.title || 'Untitled Meeting'}`];\n\n if (transcript.dateString) {\n lines.push(`\\n**Date:** ${formatDate(transcript.dateString)}`);\n }\n\n // Calculate duration from last sentence end_time (more accurate than duration field)\n const duration = calculateDuration(transcript);\n if (duration > 0) {\n lines.push(`**Duration:** ${formatDuration(duration)}`);\n }\n\n const participants = getParticipantNames(transcript);\n if (participants.length > 0) {\n lines.push(`**Participants:** ${participants.join(', ')}`);\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Calculate actual meeting duration from sentence timestamps.\n * The API's duration field is often inaccurate, so we use the last sentence's end_time.\n */\nfunction calculateDuration(transcript: Transcript): number {\n if (transcript.sentences && transcript.sentences.length > 0) {\n const lastSentence = transcript.sentences[transcript.sentences.length - 1];\n if (lastSentence) {\n return parseFloat(lastSentence.end_time);\n }\n }\n return transcript.duration || 0;\n}\n\nfunction formatSummary(\n summary: Summary,\n opts: Required<Omit<MarkdownExportOptions, 'outputPath'>>\n): string {\n const sections: string[] = ['## Summary'];\n\n if (summary.gist) {\n sections.push('', summary.gist);\n }\n\n if (summary.bullet_gist) {\n const bullets = parseMultilineField(summary.bullet_gist);\n if (bullets.length > 0) {\n sections.push('', '### Key Points');\n sections.push(bullets.map((p) => `- ${p}`).join('\\n'));\n }\n }\n\n if (opts.includeActionItems && summary.action_items) {\n const items = parseMultilineField(summary.action_items);\n if (items.length > 0) {\n sections.push('', '### Action Items');\n const prefix = opts.actionItemFormat === 'checkbox' ? '- [ ] ' : '- ';\n sections.push(items.map((a) => `${prefix}${a}`).join('\\n'));\n }\n }\n\n return sections.join('\\n');\n}\n\nfunction formatTranscript(\n sentences: Sentence[],\n opts: Required<Omit<MarkdownExportOptions, 'outputPath'>>\n): string {\n const lines: string[] = ['## Transcript'];\n\n if (opts.groupBySpeaker) {\n const groups = groupSentencesBySpeaker(sentences);\n for (const group of groups) {\n lines.push('', formatSpeakerGroup(group, opts));\n }\n } else {\n for (const sentence of sentences) {\n lines.push('', formatSentence(sentence, opts));\n }\n }\n\n return lines.join('\\n');\n}\n\ninterface SpeakerGroup {\n speakerName: string;\n sentences: Sentence[];\n}\n\nfunction groupSentencesBySpeaker(sentences: Sentence[]): SpeakerGroup[] {\n const groups: SpeakerGroup[] = [];\n let current: SpeakerGroup | null = null;\n\n for (const sentence of sentences) {\n if (!current || current.speakerName !== sentence.speaker_name) {\n current = { speakerName: sentence.speaker_name, sentences: [] };\n groups.push(current);\n }\n current.sentences.push(sentence);\n }\n\n return groups;\n}\n\nfunction formatSpeakerGroup(\n group: SpeakerGroup,\n opts: Required<Omit<MarkdownExportOptions, 'outputPath'>>\n): string {\n const speaker = formatSpeakerName(group.speakerName, opts.speakerFormat);\n const text = group.sentences.map((s) => s.text).join(' ');\n\n const firstSentence = group.sentences[0];\n if (opts.includeTimestamps && firstSentence) {\n const timestamp = formatTimestamp(firstSentence.start_time);\n return `${timestamp} ${speaker} ${text}`;\n }\n return `${speaker} ${text}`;\n}\n\nfunction formatSentence(\n sentence: Sentence,\n opts: Required<Omit<MarkdownExportOptions, 'outputPath'>>\n): string {\n const speaker = formatSpeakerName(sentence.speaker_name, opts.speakerFormat);\n\n if (opts.includeTimestamps) {\n const timestamp = formatTimestamp(sentence.start_time);\n return `${timestamp} ${speaker} ${sentence.text}`;\n }\n return `${speaker} ${sentence.text}`;\n}\n\ninterface ChunkGroup {\n speakerName: string;\n chunks: TranscriptionChunk[];\n}\n\nfunction groupChunksBySpeaker(chunks: TranscriptionChunk[]): ChunkGroup[] {\n const groups: ChunkGroup[] = [];\n let current: ChunkGroup | null = null;\n\n for (const chunk of chunks) {\n if (!current || current.speakerName !== chunk.speaker_name) {\n current = { speakerName: chunk.speaker_name, chunks: [] };\n groups.push(current);\n }\n current.chunks.push(chunk);\n }\n\n return groups;\n}\n\nfunction formatChunkGroup(\n group: ChunkGroup,\n opts: Required<Omit<ChunksExportOptions, 'outputPath'>>\n): string {\n const speaker = formatSpeakerName(group.speakerName, opts.speakerFormat);\n const text = group.chunks.map((c) => c.text).join(' ');\n\n const firstChunk = group.chunks[0];\n if (opts.includeTimestamps && firstChunk) {\n const timestamp = formatTimestamp(firstChunk.start_time.toString());\n return `${timestamp} ${speaker} ${text}`;\n }\n return `${speaker} ${text}`;\n}\n\nfunction formatChunk(\n chunk: TranscriptionChunk,\n opts: Required<Omit<ChunksExportOptions, 'outputPath'>>\n): string {\n const speaker = formatSpeakerName(chunk.speaker_name, opts.speakerFormat);\n\n if (opts.includeTimestamps) {\n const timestamp = formatTimestamp(chunk.start_time.toString());\n return `${timestamp} ${speaker} ${chunk.text}`;\n }\n return `${speaker} ${chunk.text}`;\n}\n\nfunction formatSpeakerName(name: string, format: 'bold' | 'plain'): string {\n switch (format) {\n case 'bold':\n return `**${name}:**`;\n case 'plain':\n return `${name}:`;\n }\n}\n\nfunction formatTimestamp(startTime: string): string {\n const seconds = parseFloat(startTime);\n const mins = Math.floor(seconds / 60);\n const secs = Math.floor(seconds % 60);\n return `[${mins}:${secs.toString().padStart(2, '0')}]`;\n}\n\nfunction formatDuration(seconds: number): string {\n const hours = Math.floor(seconds / 3600);\n const mins = Math.floor((seconds % 3600) / 60);\n if (hours > 0) {\n return `${hours}h ${mins}m`;\n }\n return `${mins} minutes`;\n}\n\nfunction formatDate(isoString: string): string {\n return new Date(isoString).toLocaleDateString('en-US', {\n weekday: 'long',\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n });\n}\n\nfunction getParticipantNames(transcript: Transcript): string[] {\n if (transcript.meeting_attendees?.length) {\n return transcript.meeting_attendees\n .map((a) => a.displayName || a.name || a.email)\n .filter(Boolean) as string[];\n }\n return transcript.speakers?.map((s) => s.name) || [];\n}\n\n/**\n * Parse newline-separated summary fields into an array.\n * Handles both \\n and actual newlines, filters empty lines.\n */\nfunction parseMultilineField(value: string): string[] {\n return value\n .split(/\\n/)\n .map((line) => line.trim())\n .filter((line) => line.length > 0);\n}\n\nasync function writeIfOutputPath(content: string, outputPath?: string): Promise<void> {\n if (outputPath) {\n const { writeFile } = await import('node:fs/promises');\n await writeFile(outputPath, content, 'utf-8');\n }\n}\n","/**\n * Deduplicates items by a key.\n * Uses a sliding window to avoid unbounded memory growth.\n */\nexport class Deduplicator {\n private seen = new Set<string>();\n private queue: string[] = [];\n private maxSize: number;\n\n constructor(maxSize = 1000) {\n this.maxSize = maxSize;\n }\n\n /**\n * Check if item is a duplicate and mark as seen.\n * @param key - Unique key to check\n * @returns true if duplicate, false if new\n */\n isDuplicate(key: string): boolean {\n if (this.seen.has(key)) {\n return true;\n }\n\n this.seen.add(key);\n this.queue.push(key);\n\n // Evict oldest entries if over capacity\n while (this.queue.length > this.maxSize) {\n const oldest = this.queue.shift();\n if (oldest) this.seen.delete(oldest);\n }\n\n return false;\n }\n\n /**\n * Clear all tracked keys.\n */\n clear(): void {\n this.seen.clear();\n this.queue = [];\n }\n\n /**\n * Get current number of tracked keys.\n */\n get size(): number {\n return this.seen.size;\n }\n}\n","import { FirefliesClient } from '../client.js';\nimport type { TranscriptsListParams } from '../types/params.js';\nimport type { Transcript } from '../types/transcript.js';\nimport { Deduplicator } from '../utils/dedup.js';\n\n/**\n * Options for fetching transcripts from multiple users.\n */\nexport interface MultiUserOptions {\n /**\n * Whether to deduplicate transcripts by ID across accounts.\n * Useful when multiple users have access to the same transcripts.\n * @default true\n */\n deduplicate?: boolean;\n /**\n * Filter parameters to apply to each account's transcript listing.\n * Pagination (skip/limit) is handled automatically.\n */\n filter?: Omit<TranscriptsListParams, 'skip' | 'limit'>;\n /**\n * Delay in milliseconds between yielded transcripts.\n * Helps throttle processing and reduce memory pressure.\n * Note: API rate limiting is handled by the underlying client.\n * @default 100\n */\n delayMs?: number;\n}\n\n/**\n * A transcript with source tracking information.\n */\nexport interface MultiUserTranscript {\n /** The transcript object */\n transcript: Transcript;\n /** API key used to fetch this transcript (for attribution) */\n sourceApiKey: string;\n /** Index of the API key in the input array */\n sourceIndex: number;\n}\n\n/**\n * Fetch transcripts from multiple Fireflies accounts with deduplication.\n *\n * This function creates a client for each API key and iterates through\n * all transcripts, optionally deduplicating across accounts.\n *\n * @param apiKeys - Array of Fireflies API keys\n * @param options - Configuration options\n * @returns AsyncIterable yielding transcripts with source tracking\n *\n * @example\n * ```typescript\n * import { getMeetingsForMultipleUsers } from 'fireflies-api';\n *\n * const apiKeys = [\n * process.env.FIREFLIES_API_KEY_USER1!,\n * process.env.FIREFLIES_API_KEY_USER2!,\n * ];\n *\n * for await (const { transcript, sourceIndex } of getMeetingsForMultipleUsers(apiKeys)) {\n * console.log(`[User ${sourceIndex}] ${transcript.title}`);\n * }\n *\n * // With filtering\n * for await (const item of getMeetingsForMultipleUsers(apiKeys, {\n * filter: { fromDate: '2024-01-01' },\n * deduplicate: true,\n * })) {\n * console.log(item.transcript.title);\n * }\n * ```\n */\nexport async function* getMeetingsForMultipleUsers(\n apiKeys: string[],\n options: MultiUserOptions = {}\n): AsyncIterable<MultiUserTranscript> {\n const { deduplicate = true, filter, delayMs = 100 } = options;\n\n // Create deduplicator if enabled\n const dedup = deduplicate ? new Deduplicator() : null;\n\n // Track if we need delay (not before first API call)\n let needsDelay = false;\n\n // Iterate through each API key sequentially\n for (const [sourceIndex, apiKey] of apiKeys.entries()) {\n const client = new FirefliesClient({ apiKey });\n\n // Iterate through all transcripts for this user\n for await (const transcript of client.transcripts.listAll(filter)) {\n // Add delay between API calls\n if (needsDelay && delayMs > 0) {\n await delay(delayMs);\n }\n needsDelay = true;\n\n // Skip duplicates if deduplication is enabled\n if (dedup?.isDuplicate(transcript.id)) {\n continue;\n }\n\n yield {\n transcript,\n sourceApiKey: apiKey,\n sourceIndex,\n };\n }\n }\n}\n\n/**\n * Delay execution for a specified time.\n */\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import type {\n NormalizationOptions,\n NormalizedAnalytics,\n NormalizedAttendee,\n NormalizedChannel,\n NormalizedMeeting,\n NormalizedParticipant,\n NormalizedSentence,\n NormalizedSpeaker,\n NormalizedSummary,\n} from '../types/normalized.js';\nimport type { Sentence, Speaker, Summary, Transcript } from '../types/transcript.js';\nimport type { BatchResult } from './batch.js';\n\n/**\n * Options for batch normalization, extending NormalizationOptions.\n */\nexport interface BatchNormalizationOptions extends NormalizationOptions {\n /**\n * Delay between items in ms.\n * Since normalization is a pure function, this is typically 0.\n * @default 0\n */\n delayMs?: number;\n}\n\n/**\n * Default options for normalization.\n */\nconst DEFAULT_OPTIONS: Required<NormalizationOptions> = {\n timeUnit: 'seconds',\n includeRawData: false,\n includeAIFilters: true,\n includeSummary: true,\n resolveSpeakerName: (speaker: Speaker) => speaker.name,\n enrichParticipant: () => ({}),\n};\n\n/**\n * Normalize a Fireflies transcript to a provider-agnostic format.\n *\n * This function converts Fireflies-specific transcript data to a normalized schema\n * that can be used across multiple meeting intelligence providers.\n *\n * @param transcript - The Fireflies transcript to normalize\n * @param options - Normalization options\n * @returns A normalized meeting object\n *\n * @example\n * ```typescript\n * import { FirefliesClient, normalizeTranscript } from 'fireflies-api';\n *\n * const client = new FirefliesClient({ apiKey: 'your-api-key' });\n * const transcript = await client.transcripts.get({ id: 'transcript-id' });\n *\n * const normalized = normalizeTranscript(transcript, {\n * timeUnit: 'milliseconds',\n * includeRawData: true,\n * });\n *\n * console.log(normalized.id); // \"fireflies:transcript-id\"\n * console.log(normalized.duration); // in seconds\n * ```\n */\nexport function normalizeTranscript(\n transcript: Transcript,\n options?: NormalizationOptions\n): NormalizedMeeting {\n const opts = { ...DEFAULT_OPTIONS, ...options };\n\n const speakers = normalizeSpeakers(transcript.speakers ?? [], transcript, opts);\n const sentences = normalizeSentences(transcript.sentences ?? [], opts);\n const participants = normalizeParticipants(transcript, opts);\n const summary = opts.includeSummary ? normalizeSummary(transcript.summary) : undefined;\n const attendees = normalizeAttendees(transcript.meeting_attendance ?? []);\n const channels = normalizeChannels(transcript.channels ?? []);\n const analytics = normalizeAnalytics(transcript.analytics);\n\n return {\n id: `fireflies:${transcript.id}`,\n title: transcript.title,\n date: new Date(transcript.date),\n duration: transcript.duration * 60, // minutes → seconds\n url: transcript.transcript_url,\n\n speakers,\n sentences,\n participants,\n\n summary,\n attendees,\n channels,\n analytics,\n\n source: {\n provider: 'fireflies',\n originalId: transcript.id,\n rawData: opts.includeRawData ? transcript : undefined,\n },\n };\n}\n\n/**\n * Create a pre-configured normalizer function.\n *\n * Useful when normalizing multiple transcripts with the same options.\n *\n * @param options - Normalization options to apply to all transcripts\n * @returns A function that normalizes transcripts with the configured options\n *\n * @example\n * ```typescript\n * import { createNormalizer } from 'fireflies-api';\n *\n * const normalizer = createNormalizer({\n * timeUnit: 'milliseconds',\n * includeRawData: false,\n * });\n *\n * // Reuse with same config\n * const norm1 = normalizer(transcript1);\n * const norm2 = normalizer(transcript2);\n * ```\n */\nexport function createNormalizer(\n options?: NormalizationOptions\n): (transcript: Transcript) => NormalizedMeeting {\n return (transcript: Transcript) => normalizeTranscript(transcript, options);\n}\n\n/**\n * Normalize speakers from the transcript.\n */\nfunction normalizeSpeakers(\n speakers: Speaker[],\n transcript: Transcript,\n opts: Required<NormalizationOptions>\n): NormalizedSpeaker[] {\n return speakers.map((speaker) => ({\n id: speaker.id,\n name: opts.resolveSpeakerName(speaker, transcript),\n }));\n}\n\n/**\n * Normalize sentences from the transcript.\n */\nfunction normalizeSentences(\n sentences: Sentence[],\n opts: Required<NormalizationOptions>\n): NormalizedSentence[] {\n const timeMultiplier = opts.timeUnit === 'milliseconds' ? 1000 : 1;\n\n return sentences.map((sentence) => {\n const normalized: NormalizedSentence = {\n index: sentence.index,\n speakerId: sentence.speaker_id,\n speakerName: sentence.speaker_name,\n text: sentence.text,\n rawText: sentence.raw_text,\n startTime: parseTime(sentence.start_time) * timeMultiplier,\n endTime: parseTime(sentence.end_time) * timeMultiplier,\n };\n\n if (opts.includeAIFilters && sentence.ai_filters) {\n const sentiment = mapSentiment(sentence.ai_filters.sentiment);\n if (sentiment) {\n normalized.sentiment = sentiment;\n }\n if (sentence.ai_filters.question) {\n normalized.isQuestion = true;\n }\n if (sentence.ai_filters.task) {\n normalized.isActionItem = true;\n }\n }\n\n return normalized;\n });\n}\n\n/**\n * Parse time string to number, handling invalid values.\n */\nfunction parseTime(timeStr: string): number {\n const parsed = Number.parseFloat(timeStr);\n return Number.isNaN(parsed) ? 0 : parsed;\n}\n\n/**\n * Map Fireflies sentiment string to normalized sentiment.\n */\nfunction mapSentiment(\n sentiment: string | undefined\n): 'positive' | 'negative' | 'neutral' | undefined {\n if (!sentiment) return undefined;\n const lower = sentiment.toLowerCase();\n if (lower === 'positive') return 'positive';\n if (lower === 'negative') return 'negative';\n if (lower === 'neutral') return 'neutral';\n return undefined;\n}\n\n/**\n * Normalize participants from the transcript.\n */\nfunction normalizeParticipants(\n transcript: Transcript,\n opts: Required<NormalizationOptions>\n): NormalizedParticipant[] {\n const participants = transcript.participants ?? [];\n const attendeeMap = new Map<string, string>();\n\n // Build email → name mapping from meeting_attendees\n for (const attendee of transcript.meeting_attendees ?? []) {\n if (attendee.email && attendee.name) {\n attendeeMap.set(attendee.email.toLowerCase(), attendee.name);\n }\n }\n\n return participants.map((email) => {\n const isOrganizer = email.toLowerCase() === transcript.organizer_email.toLowerCase();\n const attendeeName = attendeeMap.get(email.toLowerCase());\n const enrichment = opts.enrichParticipant(email, transcript);\n\n return {\n name: enrichment.name ?? attendeeName ?? '',\n email,\n role: enrichment.role ?? (isOrganizer ? 'organizer' : 'attendee'),\n };\n });\n}\n\n/**\n * Normalize summary from the transcript.\n */\nfunction normalizeSummary(summary: Summary | undefined): NormalizedSummary | undefined {\n if (!summary) return undefined;\n\n const keyPoints = parseKeyPoints(summary.shorthand_bullet);\n\n return {\n overview: summary.overview,\n keyPoints: keyPoints.length > 0 ? keyPoints : undefined,\n actionItems: summary.action_items,\n outline: summary.outline,\n topics: summary.topics_discussed,\n };\n}\n\n/**\n * Parse shorthand bullet points into array.\n */\nfunction parseKeyPoints(shorthandBullet: string | undefined): string[] {\n if (!shorthandBullet) return [];\n\n return shorthandBullet\n .split('\\n')\n .map((line) => line.replace(/^[-*•]\\s*/, '').trim())\n .filter((line) => line.length > 0);\n}\n\n/**\n * Normalize meeting attendance to attendees.\n */\nfunction normalizeAttendees(attendance: Transcript['meeting_attendance']): NormalizedAttendee[] {\n return attendance.map((a) => ({\n name: a.name,\n joinTime: a.join_time ? new Date(a.join_time) : undefined,\n leaveTime: a.leave_time ? new Date(a.leave_time) : undefined,\n }));\n}\n\n/**\n * Normalize channels.\n */\nfunction normalizeChannels(channels: Transcript['channels']): NormalizedChannel[] {\n return channels.map((ch) => ({\n id: ch.id,\n title: ch.title,\n isPrivate: ch.is_private ?? false,\n }));\n}\n\n/**\n * Normalize analytics.\n */\nfunction normalizeAnalytics(analytics: Transcript['analytics']): NormalizedAnalytics | undefined {\n if (!analytics?.sentiments) return undefined;\n\n return {\n sentiments: {\n positive: analytics.sentiments.positive_pct ?? 0,\n neutral: analytics.sentiments.neutral_pct ?? 0,\n negative: analytics.sentiments.negative_pct ?? 0,\n },\n };\n}\n\n/**\n * Delay execution for a specified time.\n */\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Normalize multiple transcripts with streaming and error handling.\n *\n * Yields a BatchResult for each transcript, capturing any errors\n * without stopping iteration.\n *\n * @param transcripts - Array or async iterable of transcripts to normalize\n * @param options - Batch normalization options\n * @returns AsyncIterable yielding BatchResult for each transcript\n *\n * @example\n * ```typescript\n * import { normalizeTranscripts } from 'fireflies-api';\n *\n * for await (const result of normalizeTranscripts(transcripts)) {\n * if (result.error) {\n * console.error(`Failed: ${result.item.id}`, result.error);\n * } else {\n * console.log(result.result.id); // \"fireflies:...\"\n * }\n * }\n * ```\n */\nexport async function* normalizeTranscripts(\n transcripts: Transcript[] | AsyncIterable<Transcript>,\n options?: BatchNormalizationOptions\n): AsyncIterable<BatchResult<Transcript, NormalizedMeeting>> {\n const { delayMs = 0, ...normalizationOptions } = options ?? {};\n let isFirst = true;\n\n for await (const transcript of transcripts) {\n // Add delay between items (not before first)\n if (!isFirst && delayMs > 0) {\n await delay(delayMs);\n }\n isFirst = false;\n\n try {\n const result = normalizeTranscript(transcript, normalizationOptions);\n yield { item: transcript, result };\n } catch (err) {\n yield {\n item: transcript,\n error: err instanceof Error ? err : new Error(String(err)),\n };\n }\n }\n}\n\n/**\n * Normalize multiple transcripts and collect all results.\n *\n * Unlike the streaming `normalizeTranscripts()`, this waits for all items\n * to complete and returns results as an array.\n *\n * @param transcripts - Array or async iterable of transcripts to normalize\n * @param options - Batch normalization options\n * @returns Array of BatchResult for each transcript\n *\n * @example\n * ```typescript\n * import { normalizeTranscriptsAll } from 'fireflies-api';\n *\n * const results = await normalizeTranscriptsAll(transcripts, {\n * timeUnit: 'milliseconds',\n * includeRawData: false,\n * });\n *\n * const successful = results.filter(r => !r.error).map(r => r.result);\n * const failed = results.filter(r => r.error);\n * ```\n */\nexport async function normalizeTranscriptsAll(\n transcripts: Transcript[] | AsyncIterable<Transcript>,\n options?: BatchNormalizationOptions\n): Promise<BatchResult<Transcript, NormalizedMeeting>[]> {\n const results: BatchResult<Transcript, NormalizedMeeting>[] = [];\n\n for await (const result of normalizeTranscripts(transcripts, options)) {\n results.push(result);\n }\n\n return results;\n}\n","import type { Sentence, Transcript } from '../types/transcript.js';\n\n/**\n * Statistics for a single speaker in the meeting.\n */\nexport interface SpeakerStats {\n /** Speaker name from transcript */\n name: string;\n /** Speaker ID from transcript */\n id: string;\n /** Total talk time in seconds */\n talkTime: number;\n /** Percentage of total meeting talk time (0-100) */\n talkTimePercentage: number;\n /** Number of sentences spoken */\n sentenceCount: number;\n /** Total words spoken */\n wordCount: number;\n /** Words per minute (based on talk time) */\n wordsPerMinute: number;\n /** Average words per sentence */\n averageSentenceLength: number;\n /** Number of speaking turns (consecutive sentence groups) */\n turnCount: number;\n}\n\n/**\n * Overall meeting speaker analytics.\n */\nexport interface SpeakerAnalytics {\n /** Per-speaker statistics, sorted by talk time descending */\n speakers: SpeakerStats[];\n /** Total meeting duration from sentences (seconds) */\n totalDuration: number;\n /** Total talk time across all speakers (seconds) */\n totalTalkTime: number;\n /** Total sentences in transcript */\n totalSentences: number;\n /** Total words spoken */\n totalWords: number;\n /** Name of speaker with most talk time */\n dominantSpeaker: string;\n /** Talk time percentage of dominant speaker */\n dominantSpeakerPercentage: number;\n /** Balance indicator: balanced, unbalanced, or dominated */\n balance: 'balanced' | 'unbalanced' | 'dominated';\n}\n\n/**\n * Options for speaker analysis.\n */\nexport interface SpeakerAnalyticsOptions {\n /**\n * Merge speakers with identical names into a single entry (default: true).\n *\n * Fireflies' speaker diarization can incorrectly assign multiple speaker IDs\n * to the same person, especially with:\n * - Multiple audio channels/microphones\n * - Short utterances being misattributed\n * - Audio quality issues causing speaker model confusion\n *\n * This commonly manifests as rapid alternation between two IDs for the same\n * speaker name, resulting in inflated turn counts and split statistics.\n *\n * When enabled (default), speakers are grouped by name rather than ID,\n * combining their talk time, word counts, and other metrics. Turn counting\n * uses speaker names, so consecutive sentences from the same person count\n * as one turn regardless of ID changes.\n *\n * Set to `false` to preserve the raw speaker IDs from Fireflies, which may\n * be useful for debugging diarization issues or when you have confirmed that\n * multiple people share the same display name.\n */\n mergeSpeakersByName?: boolean;\n /** Round percentages to integers (default: true) */\n roundPercentages?: boolean;\n /** Threshold for 'unbalanced' classification (default: 40) */\n unbalancedThreshold?: number;\n /** Threshold for 'dominated' classification (default: 60) */\n dominatedThreshold?: number;\n}\n\ninterface SpeakerData {\n id: string;\n name: string;\n sentences: Sentence[];\n talkTime: number;\n wordCount: number;\n turnCount: number;\n}\n\n/**\n * Analyze speaker participation in a transcript.\n *\n * Computes talk time percentages, word counts, and participation metrics\n * for each speaker in the meeting.\n *\n * @param transcript - The transcript to analyze\n * @param options - Analysis options\n * @returns Speaker analytics with per-speaker stats and totals\n *\n * @example\n * ```typescript\n * import { FirefliesClient, analyzeSpeakers } from 'fireflies-api';\n *\n * const client = new FirefliesClient({ apiKey: 'your-api-key' });\n * const transcript = await client.transcripts.get({ id: 'transcript-id' });\n *\n * const analytics = analyzeSpeakers(transcript);\n *\n * console.log(`${analytics.speakers.length} speakers`);\n * console.log(`Dominant: ${analytics.dominantSpeaker} (${analytics.dominantSpeakerPercentage}%)`);\n *\n * for (const speaker of analytics.speakers) {\n * console.log(`${speaker.name}: ${speaker.talkTimePercentage}% talk time, ${speaker.wordCount} words`);\n * }\n * ```\n */\nexport function analyzeSpeakers(\n transcript: Transcript,\n options: SpeakerAnalyticsOptions = {}\n): SpeakerAnalytics {\n const {\n mergeSpeakersByName = true,\n roundPercentages = true,\n unbalancedThreshold = 40,\n dominatedThreshold = 60,\n } = options;\n\n const sentences = transcript.sentences ?? [];\n if (sentences.length === 0) {\n return emptyAnalytics();\n }\n\n // Group sentences by speaker (by name when merging, by ID otherwise)\n const speakerMap = new Map<string, SpeakerData>();\n let prevSpeakerKey: string | null = null;\n\n for (const sentence of sentences) {\n const groupKey = mergeSpeakersByName ? sentence.speaker_name : sentence.speaker_id;\n const data = getOrCreateSpeakerData(speakerMap, groupKey, sentence);\n data.sentences.push(sentence);\n data.talkTime += parseDuration(sentence);\n data.wordCount += countWords(sentence.text);\n\n // Count turns (speaker changes based on grouping key)\n if (groupKey !== prevSpeakerKey) {\n data.turnCount++;\n prevSpeakerKey = groupKey;\n }\n }\n\n // Calculate totals\n const totalTalkTime = sumTalkTime(speakerMap);\n const totalDuration = calculateDuration(sentences);\n const totalWords = sumWords(speakerMap);\n\n // Build speaker stats\n const speakers = buildSpeakerStats(speakerMap, totalTalkTime, roundPercentages);\n\n // Sort by talk time descending\n speakers.sort((a, b) => b.talkTime - a.talkTime);\n\n const dominant = speakers[0];\n\n return {\n speakers,\n totalDuration,\n totalTalkTime,\n totalSentences: sentences.length,\n totalWords,\n dominantSpeaker: dominant?.name ?? '',\n dominantSpeakerPercentage: dominant?.talkTimePercentage ?? 0,\n balance: classifyBalance(speakers, unbalancedThreshold, dominatedThreshold),\n };\n}\n\nfunction emptyAnalytics(): SpeakerAnalytics {\n return {\n speakers: [],\n totalDuration: 0,\n totalTalkTime: 0,\n totalSentences: 0,\n totalWords: 0,\n dominantSpeaker: '',\n dominantSpeakerPercentage: 0,\n balance: 'balanced',\n };\n}\n\nfunction getOrCreateSpeakerData(\n speakerMap: Map<string, SpeakerData>,\n groupKey: string,\n sentence: Sentence\n): SpeakerData {\n let data = speakerMap.get(groupKey);\n if (!data) {\n data = {\n id: sentence.speaker_id, // Use first encountered ID\n name: sentence.speaker_name,\n sentences: [],\n talkTime: 0,\n wordCount: 0,\n turnCount: 0,\n };\n speakerMap.set(groupKey, data);\n }\n return data;\n}\n\nfunction parseDuration(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 countWords(text: string): number {\n if (!text || text.length === 0) return 0;\n return text\n .trim()\n .split(/\\s+/)\n .filter((w) => w.length > 0).length;\n}\n\nfunction sumTalkTime(speakerMap: Map<string, SpeakerData>): number {\n let total = 0;\n for (const data of speakerMap.values()) {\n total += data.talkTime;\n }\n return total;\n}\n\nfunction sumWords(speakerMap: Map<string, SpeakerData>): number {\n let total = 0;\n for (const data of speakerMap.values()) {\n total += data.wordCount;\n }\n return total;\n}\n\nfunction calculateDuration(sentences: Sentence[]): number {\n if (sentences.length === 0) return 0;\n const lastSentence = sentences[sentences.length - 1];\n return Number.parseFloat(lastSentence?.end_time ?? '0');\n}\n\nfunction buildSpeakerStats(\n speakerMap: Map<string, SpeakerData>,\n totalTalkTime: number,\n roundPercentages: boolean\n): SpeakerStats[] {\n const speakers: SpeakerStats[] = [];\n\n for (const data of speakerMap.values()) {\n const percentage = totalTalkTime > 0 ? (data.talkTime / totalTalkTime) * 100 : 0;\n const sentenceCount = data.sentences.length;\n const talkTimeMinutes = data.talkTime / 60;\n const wordsPerMinute = talkTimeMinutes > 0 ? data.wordCount / talkTimeMinutes : 0;\n const averageSentenceLength = sentenceCount > 0 ? data.wordCount / sentenceCount : 0;\n\n speakers.push({\n name: data.name,\n id: data.id,\n talkTime: data.talkTime,\n talkTimePercentage: roundPercentages ? Math.round(percentage) : percentage,\n sentenceCount,\n wordCount: data.wordCount,\n wordsPerMinute: roundPercentages ? Math.round(wordsPerMinute) : wordsPerMinute,\n averageSentenceLength,\n turnCount: data.turnCount,\n });\n }\n\n return speakers;\n}\n\nfunction classifyBalance(\n speakers: SpeakerStats[],\n unbalancedThreshold: number,\n dominatedThreshold: number\n): 'balanced' | 'unbalanced' | 'dominated' {\n if (speakers.length <= 2) return 'balanced';\n const top = speakers[0]?.talkTimePercentage ?? 0;\n if (top > dominatedThreshold) return 'dominated';\n if (top > unbalancedThreshold) return 'unbalanced';\n return 'balanced';\n}\n","import type { FirefliesClient } from '../client.js';\nimport type { TranscriptsListParams } from '../types/params.js';\nimport type { Transcript } from '../types/transcript.js';\n\n/**\n * A transcript with a guaranteed video URL.\n */\nexport interface TranscriptWithVideo {\n /** The full transcript object */\n transcript: Transcript;\n /** URL to download video (expires after 24h) */\n videoUrl: string;\n}\n\n/**\n * Iterate through transcripts that have video recordings.\n *\n * This function filters transcripts to only yield those with video_url set.\n * Video recordings require Business plan or higher.\n *\n * @param client - FirefliesClient instance\n * @param options - Optional filter parameters (pagination is handled automatically)\n * @returns AsyncIterable yielding transcripts with their video URLs\n *\n * @example\n * ```typescript\n * import { FirefliesClient, getMeetingVideos } from 'fireflies-api';\n *\n * const client = new FirefliesClient({ apiKey: 'your-api-key' });\n *\n * for await (const { transcript, videoUrl } of getMeetingVideos(client)) {\n * console.log(`${transcript.title}: ${videoUrl}`);\n * }\n *\n * // With filters\n * for await (const item of getMeetingVideos(client, {\n * fromDate: '2024-01-01',\n * mine: true,\n * })) {\n * console.log(item.videoUrl);\n * }\n * ```\n */\nexport async function* getMeetingVideos(\n client: FirefliesClient,\n options?: Omit<TranscriptsListParams, 'skip' | 'limit'>\n): AsyncIterable<TranscriptWithVideo> {\n for await (const transcript of client.transcripts.listAll(options)) {\n if (transcript.video_url) {\n yield {\n transcript,\n videoUrl: transcript.video_url,\n };\n }\n }\n}\n\n/**\n * Check if a transcript has a video recording.\n *\n * @param transcript - Transcript to check\n * @returns true if the transcript has a video URL\n */\nexport function hasVideo(transcript: Transcript): transcript is Transcript & { video_url: string } {\n return typeof transcript.video_url === 'string' && transcript.video_url.length > 0;\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"]}
|