@omote/core 0.9.1 → 0.9.2

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/logging/types.ts","../src/logging/formatters.ts","../src/telemetry/exporters/console.ts","../src/telemetry/exporters/otlp.ts","../src/logging/Clock.ts","../src/telemetry/OmoteTelemetry.ts","../src/logging/Logger.ts","../src/logging/ErrorCodes.ts"],"sourcesContent":["/**\n * Logging types for Omote SDK\n *\n * 6-level logging system with structured output:\n * - error: Critical failures that prevent operation\n * - warn: Recoverable issues or degraded performance\n * - info: Key lifecycle events (model loaded, inference complete)\n * - debug: Detailed operational info for development\n * - trace: Fine-grained tracing for performance analysis\n * - verbose: Extremely detailed output (tensor shapes, intermediate values)\n */\n\nexport type LogLevel = 'error' | 'warn' | 'info' | 'debug' | 'trace' | 'verbose';\n\n/**\n * Numeric priority for log levels (lower = more severe)\n */\nexport const LOG_LEVEL_PRIORITY: Record<LogLevel, number> = {\n error: 0,\n warn: 1,\n info: 2,\n debug: 3,\n trace: 4,\n verbose: 5,\n};\n\n/**\n * Structured log entry\n */\nexport interface LogEntry {\n /** Unix timestamp in milliseconds */\n timestamp: number;\n /** Log level */\n level: LogLevel;\n /** Module name (e.g., 'LocalInference', 'ModelCache') */\n module: string;\n /** Human-readable message */\n message: string;\n /** Optional structured error code from ErrorCodes (e.g., 'OMOTE_INF_001') */\n code?: string;\n /** Optional structured data */\n data?: Record<string, unknown>;\n /** Optional error object */\n error?: Error;\n /** Trace ID from active telemetry span (log-to-span correlation) */\n traceId?: string;\n /** Span ID from active telemetry span (log-to-span correlation) */\n spanId?: string;\n}\n\n/**\n * Log output sink interface.\n *\n * **Portability contract**: Replace the default console sink to route logs to\n * any backend — Node.js winston/pino, Unreal UE_LOG, Unity Debug.Log, or a\n * remote telemetry service. Register via `configureLogging({ sink: mySink })`.\n */\nexport interface LogSink {\n (entry: LogEntry): void;\n}\n\n/**\n * Log formatter interface\n */\nexport interface LogFormatter {\n (entry: LogEntry): string;\n}\n\n/**\n * Global logging configuration\n */\nexport interface LoggingConfig {\n /** Minimum log level to output (default: 'info') */\n level: LogLevel;\n /** Enable/disable logging globally (default: true) */\n enabled: boolean;\n /** Output format: 'json' for structured, 'pretty' for human-readable */\n format: 'json' | 'pretty';\n /** Custom output sink (default: console) */\n sink?: LogSink;\n /** Include timestamps in output (default: true) */\n timestamps?: boolean;\n /** Include module name in output (default: true) */\n includeModule?: boolean;\n}\n\n/**\n * Logger interface for module-specific logging.\n *\n * **Portability contract**: All SDK modules depend only on this interface.\n * To integrate with a non-browser runtime (Node.js, Unreal, Unity), either:\n * 1. Use the built-in Logger with a custom `LogSink`, or\n * 2. Provide your own `ILogger` implementation that bridges to the host\n * runtime's logging system (e.g., `console.log`, `UE_LOG`, `Debug.Log`).\n */\nexport interface ILogger {\n error(message: string, data?: Record<string, unknown>): void;\n warn(message: string, data?: Record<string, unknown>): void;\n info(message: string, data?: Record<string, unknown>): void;\n debug(message: string, data?: Record<string, unknown>): void;\n trace(message: string, data?: Record<string, unknown>): void;\n verbose(message: string, data?: Record<string, unknown>): void;\n\n /** Create a child logger with a sub-module name */\n child(subModule: string): ILogger;\n\n /** Get the module name for this logger */\n readonly module: string;\n}\n\n/**\n * Default configuration\n */\nexport const DEFAULT_LOGGING_CONFIG: LoggingConfig = {\n level: 'info',\n enabled: true,\n format: 'pretty',\n timestamps: true,\n includeModule: true,\n};\n","/**\n * Log formatters for different output formats\n */\n\nimport type { LogEntry, LogFormatter, LogLevel } from './types';\n\n/**\n * ANSI color codes for terminal output\n */\nconst COLORS = {\n reset: '\\x1b[0m',\n red: '\\x1b[31m',\n yellow: '\\x1b[33m',\n blue: '\\x1b[34m',\n cyan: '\\x1b[36m',\n gray: '\\x1b[90m',\n white: '\\x1b[37m',\n magenta: '\\x1b[35m',\n};\n\n/**\n * Level-specific colors\n */\nconst LEVEL_COLORS: Record<LogLevel, string> = {\n error: COLORS.red,\n warn: COLORS.yellow,\n info: COLORS.blue,\n debug: COLORS.cyan,\n trace: COLORS.magenta,\n verbose: COLORS.gray,\n};\n\n/**\n * Level display names (padded for alignment)\n */\nconst LEVEL_NAMES: Record<LogLevel, string> = {\n error: 'ERROR ',\n warn: 'WARN ',\n info: 'INFO ',\n debug: 'DEBUG ',\n trace: 'TRACE ',\n verbose: 'VERBOSE',\n};\n\n/**\n * Check if we're in a browser environment\n */\nconst isBrowser = typeof window !== 'undefined';\n\n/**\n * Format timestamp as ISO string or relative time\n */\nfunction formatTimestamp(timestamp: number): string {\n const date = new Date(timestamp);\n return date.toISOString().substring(11, 23); // HH:mm:ss.SSS\n}\n\n/**\n * Safely serialize data to JSON, handling circular references\n */\nfunction safeStringify(data: unknown): string {\n const seen = new WeakSet();\n return JSON.stringify(data, (key, value) => {\n if (typeof value === 'object' && value !== null) {\n if (seen.has(value)) {\n return '[Circular]';\n }\n seen.add(value);\n }\n // Handle special types\n if (value instanceof Error) {\n return {\n name: value.name,\n message: value.message,\n stack: value.stack,\n };\n }\n if (value instanceof Float32Array || value instanceof Int16Array) {\n return `${value.constructor.name}(${value.length})`;\n }\n if (ArrayBuffer.isView(value)) {\n return `${value.constructor.name}(${value.byteLength})`;\n }\n return value;\n });\n}\n\n/**\n * JSON formatter - structured output for machine parsing\n */\nexport const jsonFormatter: LogFormatter = (entry: LogEntry): string => {\n const output: Record<string, unknown> = {\n timestamp: entry.timestamp,\n level: entry.level,\n module: entry.module,\n message: entry.message,\n };\n\n if (entry.data && Object.keys(entry.data).length > 0) {\n output.data = entry.data;\n }\n\n if (entry.error) {\n output.error = {\n name: entry.error.name,\n message: entry.error.message,\n stack: entry.error.stack,\n };\n }\n\n return safeStringify(output);\n};\n\n/**\n * Pretty formatter - human-readable output with colors\n */\nexport const prettyFormatter: LogFormatter = (entry: LogEntry): string => {\n const time = formatTimestamp(entry.timestamp);\n const level = LEVEL_NAMES[entry.level];\n const module = entry.module;\n const message = entry.message;\n\n // Build the base message\n let output: string;\n\n if (isBrowser) {\n // Browser: no ANSI colors, use plain text\n output = `${time} ${level} [${module}] ${message}`;\n } else {\n // Terminal: use ANSI colors\n const color = LEVEL_COLORS[entry.level];\n output = `${COLORS.gray}${time}${COLORS.reset} ${color}${level}${COLORS.reset} ${COLORS.cyan}[${module}]${COLORS.reset} ${message}`;\n }\n\n // Append data if present\n if (entry.data && Object.keys(entry.data).length > 0) {\n const dataStr = safeStringify(entry.data);\n // For pretty format, indent multi-line data\n if (dataStr.length > 80) {\n output += '\\n ' + JSON.stringify(entry.data, null, 2).replace(/\\n/g, '\\n ');\n } else {\n output += ' ' + dataStr;\n }\n }\n\n // Append error if present\n if (entry.error) {\n output += `\\n ${entry.error.name}: ${entry.error.message}`;\n if (entry.error.stack) {\n const stackLines = entry.error.stack.split('\\n').slice(1, 4);\n output += '\\n ' + stackLines.join('\\n ');\n }\n }\n\n return output;\n};\n\n/**\n * Get formatter by name\n */\nexport function getFormatter(format: 'json' | 'pretty'): LogFormatter {\n return format === 'json' ? jsonFormatter : prettyFormatter;\n}\n\n/**\n * Create browser console arguments for styled output\n * Returns [formatString, ...styleArgs] for console.log\n */\nexport function createBrowserConsoleArgs(entry: LogEntry): [string, ...string[]] {\n const time = formatTimestamp(entry.timestamp);\n const level = entry.level.toUpperCase().padEnd(7);\n const module = entry.module;\n const message = entry.message;\n\n // CSS styles for browser console\n const styles = {\n time: 'color: gray;',\n error: 'color: red; font-weight: bold;',\n warn: 'color: orange; font-weight: bold;',\n info: 'color: blue;',\n debug: 'color: cyan;',\n trace: 'color: magenta;',\n verbose: 'color: gray;',\n module: 'color: teal; font-weight: bold;',\n message: 'color: inherit;',\n };\n\n let formatStr = '%c%s %c%s %c[%s]%c %s';\n const args: string[] = [\n styles.time,\n time,\n styles[entry.level],\n level,\n styles.module,\n module,\n styles.message,\n message,\n ];\n\n // Append data\n if (entry.data && Object.keys(entry.data).length > 0) {\n formatStr += ' %o';\n args.push(entry.data as unknown as string);\n }\n\n return [formatStr, ...args];\n}\n","/**\n * Console Exporter\n *\n * Exports telemetry data to the browser console for development/debugging.\n *\n * @category Telemetry\n */\n\nimport type { SpanAttributes } from '../types';\n\n/**\n * Span data structure for export\n */\nexport interface SpanData {\n name: string;\n traceId: string;\n spanId: string;\n parentSpanId?: string;\n startTime: number;\n endTime: number;\n durationMs: number;\n status: 'ok' | 'error';\n attributes: SpanAttributes;\n error?: Error;\n}\n\n/**\n * Metric data structure for export\n */\nexport interface MetricData {\n name: string;\n type: 'counter' | 'histogram';\n value: number;\n attributes: Record<string, string | number | boolean>;\n timestamp: number;\n}\n\n/**\n * Exporter interface that all exporters must implement\n */\nexport interface TelemetryExporterInterface {\n /** Export a completed span */\n exportSpan(span: SpanData): void;\n /** Export a metric */\n exportMetric(metric: MetricData): void;\n /** Flush any buffered data */\n flush(): Promise<void>;\n /** Shutdown the exporter */\n shutdown(): Promise<void>;\n}\n\n/**\n * Console exporter for development/debugging\n *\n * Outputs spans and metrics to the browser console with formatting.\n */\nexport class ConsoleExporter implements TelemetryExporterInterface {\n private enabled: boolean;\n private prefix: string;\n\n constructor(options: { enabled?: boolean; prefix?: string } = {}) {\n this.enabled = options.enabled ?? true;\n this.prefix = options.prefix ?? '[Omote Telemetry]';\n }\n\n exportSpan(span: SpanData): void {\n if (!this.enabled) return;\n\n const statusIcon = span.status === 'ok' ? '✓' : '✗';\n const statusColor = span.status === 'ok' ? 'color: green' : 'color: red';\n\n console.groupCollapsed(\n `%c${this.prefix} %c${statusIcon} ${span.name} %c(${span.durationMs.toFixed(2)}ms)`,\n 'color: gray',\n statusColor,\n 'color: gray'\n );\n\n console.log('Trace ID:', span.traceId);\n console.log('Span ID:', span.spanId);\n if (span.parentSpanId) {\n console.log('Parent Span ID:', span.parentSpanId);\n }\n console.log('Duration:', `${span.durationMs.toFixed(2)}ms`);\n console.log('Status:', span.status);\n\n if (Object.keys(span.attributes).length > 0) {\n console.log('Attributes:', span.attributes);\n }\n\n if (span.error) {\n console.error('Error:', span.error);\n }\n\n console.groupEnd();\n }\n\n exportMetric(metric: MetricData): void {\n if (!this.enabled) return;\n\n const typeIcon = metric.type === 'counter' ? '↑' : '📊';\n\n console.log(\n `%c${this.prefix} %c${typeIcon} ${metric.name}: %c${metric.value}`,\n 'color: gray',\n 'color: blue',\n 'color: black; font-weight: bold',\n metric.attributes\n );\n }\n\n async flush(): Promise<void> {\n // Console exporter doesn't buffer, nothing to flush\n }\n\n async shutdown(): Promise<void> {\n this.enabled = false;\n }\n}\n","/**\n * OTLP Exporter\n *\n * Exports telemetry data to OTLP-compatible backends (Jaeger, Tempo, etc.)\n * using the OTLP/HTTP JSON protocol.\n *\n * @category Telemetry\n */\n\nimport type { OTLPExporterConfig } from '../types';\nimport type { SpanData, MetricData, TelemetryExporterInterface } from './console';\n\n/**\n * OTLP span status codes\n */\nconst StatusCode = {\n UNSET: 0,\n OK: 1,\n ERROR: 2,\n} as const;\n\n/**\n * Convert internal span to OTLP format\n */\nfunction spanToOTLP(span: SpanData, serviceName: string, serviceVersion: string) {\n const attributes = Object.entries(span.attributes)\n .filter(([, v]) => v !== undefined)\n .map(([key, value]) => ({\n key,\n value: typeof value === 'string'\n ? { stringValue: value }\n : typeof value === 'number'\n ? Number.isInteger(value)\n ? { intValue: value }\n : { doubleValue: value }\n : { boolValue: value },\n }));\n\n return {\n resourceSpans: [{\n resource: {\n attributes: [\n { key: 'service.name', value: { stringValue: serviceName } },\n { key: 'service.version', value: { stringValue: serviceVersion } },\n { key: 'telemetry.sdk.name', value: { stringValue: 'omote-sdk' } },\n { key: 'telemetry.sdk.language', value: { stringValue: 'javascript' } },\n ],\n },\n scopeSpans: [{\n scope: {\n name: 'omote-sdk',\n version: serviceVersion,\n },\n spans: [{\n traceId: span.traceId,\n spanId: span.spanId,\n parentSpanId: span.parentSpanId || '',\n name: span.name,\n kind: 1, // INTERNAL\n startTimeUnixNano: String(span.startTime * 1_000_000),\n endTimeUnixNano: String(span.endTime * 1_000_000),\n attributes,\n status: {\n code: span.status === 'ok' ? StatusCode.OK : StatusCode.ERROR,\n message: span.error?.message || '',\n },\n }],\n }],\n }],\n };\n}\n\n/**\n * Convert internal metric to OTLP format\n */\nfunction metricToOTLP(metric: MetricData, serviceName: string, serviceVersion: string) {\n const attributes = Object.entries(metric.attributes)\n .filter(([, v]) => v !== undefined)\n .map(([key, value]) => ({\n key,\n value: typeof value === 'string'\n ? { stringValue: value }\n : typeof value === 'number'\n ? Number.isInteger(value)\n ? { intValue: value }\n : { doubleValue: value }\n : { boolValue: value },\n }));\n\n const dataPoint = {\n attributes,\n timeUnixNano: String(metric.timestamp * 1_000_000),\n ...(metric.type === 'counter'\n ? { asInt: metric.value }\n : { asDouble: metric.value }),\n };\n\n return {\n resourceMetrics: [{\n resource: {\n attributes: [\n { key: 'service.name', value: { stringValue: serviceName } },\n { key: 'service.version', value: { stringValue: serviceVersion } },\n ],\n },\n scopeMetrics: [{\n scope: {\n name: 'omote-sdk',\n version: serviceVersion,\n },\n metrics: [{\n name: metric.name,\n ...(metric.type === 'counter'\n ? {\n sum: {\n dataPoints: [dataPoint],\n aggregationTemporality: 2, // CUMULATIVE\n isMonotonic: true,\n },\n }\n : {\n gauge: {\n dataPoints: [dataPoint],\n },\n }),\n }],\n }],\n }],\n };\n}\n\n/**\n * OTLP exporter for production telemetry\n *\n * Sends spans and metrics to OTLP-compatible backends like:\n * - Jaeger\n * - Grafana Tempo\n * - Honeycomb\n * - Datadog\n * - AWS X-Ray (with collector)\n */\nexport class OTLPExporter implements TelemetryExporterInterface {\n private config: Required<OTLPExporterConfig>;\n private serviceName: string;\n private serviceVersion: string;\n private spanBuffer: SpanData[] = [];\n private metricBuffer: MetricData[] = [];\n private flushIntervalId: ReturnType<typeof setInterval> | null = null;\n private readonly BUFFER_SIZE = 100;\n private readonly FLUSH_INTERVAL_MS = 5000;\n private isShutdown = false;\n\n constructor(\n config: OTLPExporterConfig,\n serviceName: string = 'omote-sdk',\n serviceVersion: string = '0.1.0'\n ) {\n // Validate endpoint URL: must be HTTPS or localhost\n const parsed = new URL(config.endpoint);\n if (parsed.protocol !== 'https:') {\n const isLocalhost = parsed.hostname === 'localhost' || parsed.hostname === '127.0.0.1' || parsed.hostname === '[::1]';\n if (!isLocalhost) {\n throw new Error('OTLP endpoint must use HTTPS (or localhost for development)');\n }\n }\n this.config = {\n endpoint: config.endpoint,\n timeoutMs: config.timeoutMs ?? 10000,\n headers: config.headers ? { ...config.headers } : {},\n };\n this.serviceName = serviceName;\n this.serviceVersion = serviceVersion;\n\n // Start periodic flush\n this.flushIntervalId = setInterval(() => {\n this.flush().catch(console.error);\n }, this.FLUSH_INTERVAL_MS);\n }\n\n exportSpan(span: SpanData): void {\n if (this.isShutdown) return;\n\n this.spanBuffer.push(span);\n\n if (this.spanBuffer.length >= this.BUFFER_SIZE) {\n this.flush().catch(console.error);\n }\n }\n\n exportMetric(metric: MetricData): void {\n if (this.isShutdown) return;\n\n this.metricBuffer.push(metric);\n\n if (this.metricBuffer.length >= this.BUFFER_SIZE) {\n this.flush().catch(console.error);\n }\n }\n\n async flush(): Promise<void> {\n if (this.isShutdown) return;\n\n const spans = this.spanBuffer.splice(0);\n const metrics = this.metricBuffer.splice(0);\n\n const promises: Promise<void>[] = [];\n\n // Export spans\n if (spans.length > 0) {\n promises.push(this.exportSpans(spans));\n }\n\n // Export metrics\n if (metrics.length > 0) {\n promises.push(this.exportMetrics(metrics));\n }\n\n await Promise.all(promises);\n }\n\n async shutdown(): Promise<void> {\n if (this.flushIntervalId) {\n clearInterval(this.flushIntervalId);\n this.flushIntervalId = null;\n }\n\n // Final flush before marking shutdown\n await this.flush();\n\n this.isShutdown = true;\n }\n\n private async exportSpans(spans: SpanData[]): Promise<void> {\n // Combine all spans into a single request\n const resourceSpans = spans.map(span =>\n spanToOTLP(span, this.serviceName, this.serviceVersion).resourceSpans[0]\n );\n\n const body = { resourceSpans };\n const endpoint = this.config.endpoint.replace(/\\/$/, '') + '/v1/traces';\n\n await this.sendRequest(endpoint, body);\n }\n\n private async exportMetrics(metrics: MetricData[]): Promise<void> {\n // Combine all metrics into a single request\n const resourceMetrics = metrics.map(metric =>\n metricToOTLP(metric, this.serviceName, this.serviceVersion).resourceMetrics[0]\n );\n\n const body = { resourceMetrics };\n const endpoint = this.config.endpoint.replace(/\\/$/, '') + '/v1/metrics';\n\n await this.sendRequest(endpoint, body);\n }\n\n private async sendRequest(endpoint: string, body: unknown): Promise<void> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.config.timeoutMs);\n\n try {\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n ...this.config.headers,\n },\n body: JSON.stringify(body),\n signal: controller.signal,\n });\n\n if (!response.ok) {\n console.warn(`[OTLP] Export failed: ${response.status} ${response.statusText}`);\n }\n } catch (error) {\n if ((error as Error).name === 'AbortError') {\n console.warn('[OTLP] Export timed out');\n } else {\n console.warn('[OTLP] Export error:', error);\n }\n } finally {\n clearTimeout(timeoutId);\n }\n }\n}\n","/**\n * Abstract monotonic clock for runtime-agnostic timing.\n *\n * **Portability contract**: To port the SDK to Node.js, Python, Unreal, or Unity,\n * implement this interface with your runtime's high-resolution timer and call\n * `configureClock()` at startup.\n *\n * @example Node.js\n * ```typescript\n * import { configureClock } from '@omote/core';\n * configureClock({\n * now: () => Number(process.hrtime.bigint() / 1_000_000n),\n * timestamp: () => Date.now(),\n * });\n * ```\n *\n * @example Unreal Engine (via wasm-bindgen)\n * ```typescript\n * configureClock({\n * now: () => FPlatformTime.Seconds() * 1000,\n * timestamp: () => FDateTime.UtcNow().ToUnixTimestamp() * 1000,\n * });\n * ```\n *\n * @example Unity (via jslib bridge)\n * ```typescript\n * configureClock({\n * now: () => Time.realtimeSinceStartup * 1000,\n * timestamp: () => Date.now(),\n * });\n * ```\n */\nexport interface Clock {\n /** Monotonic high-resolution milliseconds (for durations, telemetry spans) */\n now(): number;\n /** Wall-clock milliseconds since epoch (for log timestamps) */\n timestamp(): number;\n}\n\nexport const defaultClock: Clock = {\n now: () => performance.now(),\n timestamp: () => Date.now(),\n};\n\nlet activeClock: Clock = defaultClock;\n\n/** Replace the default browser clock with a custom implementation. */\nexport function configureClock(clock: Clock): void {\n activeClock = clock;\n}\n\n/** Get the active clock instance. */\nexport function getClock(): Clock {\n return activeClock;\n}\n","/**\n * Muse Telemetry\n *\n * Main orchestrator for SDK telemetry. Manages spans, metrics, and exporters.\n *\n * @category Telemetry\n */\n\nimport type { TelemetryConfig, SpanAttributes, SamplingConfig } from './types';\nimport type { SpanData, MetricData, TelemetryExporterInterface } from './exporters/console';\nimport { ConsoleExporter } from './exporters/console';\nimport { OTLPExporter } from './exporters/otlp';\nimport { getClock } from '../logging/Clock';\n\n/**\n * Generate a random hex ID\n */\nfunction generateId(length: number = 16): string {\n const bytes = new Uint8Array(length);\n crypto.getRandomValues(bytes);\n return Array.from(bytes)\n .map(b => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\n/**\n * Span context for tracing\n */\ninterface SpanContext {\n traceId: string;\n spanId: string;\n parentSpanId?: string;\n}\n\n/**\n * Active span handle returned by startSpan\n */\nexport interface ActiveSpan {\n /** End the span with success status */\n end(): void;\n /** End the span with error status */\n endWithError(error: Error): void;\n /** Add attributes to the span */\n setAttributes(attrs: Partial<SpanAttributes>): void;\n /** Get the span context */\n getContext(): SpanContext;\n}\n\n/**\n * Global telemetry instance\n */\nlet globalTelemetry: OmoteTelemetry | null = null;\n\n/**\n * Configure global telemetry\n *\n * @example\n * ```typescript\n * // Development\n * configureTelemetry({\n * enabled: true,\n * serviceName: 'omote-dev',\n * exporter: 'console',\n * });\n *\n * // Production\n * configureTelemetry({\n * enabled: true,\n * serviceName: 'omote-prod',\n * exporter: 'otlp',\n * exporterConfig: {\n * endpoint: 'https://tempo.example.com',\n * },\n * sampling: { ratio: 0.1 },\n * });\n * ```\n */\nexport function configureTelemetry(config: TelemetryConfig): OmoteTelemetry {\n if (globalTelemetry) {\n globalTelemetry.shutdown();\n }\n globalTelemetry = new OmoteTelemetry(config);\n return globalTelemetry;\n}\n\n/**\n * Get the global telemetry instance\n */\nexport function getTelemetry(): OmoteTelemetry | null {\n return globalTelemetry;\n}\n\n/**\n * Main telemetry class\n *\n * Manages spans, metrics, and exports to configured backends.\n */\nexport class OmoteTelemetry {\n private config: Required<Omit<TelemetryConfig, 'exporterConfig'>> & { exporterConfig?: TelemetryConfig['exporterConfig'] };\n private exporter: TelemetryExporterInterface | null = null;\n private activeTraceId: string | null = null;\n private metricsIntervalId: ReturnType<typeof setInterval> | null = null;\n\n // Span stack for log-to-span correlation\n private spanStack: Array<{ traceId: string; spanId: string }> = [];\n\n // Metric accumulators\n private counters: Map<string, { value: number; attributes: Record<string, string | number | boolean> }> = new Map();\n private histograms: Map<string, { count: number; sum: number; min: number; max: number; attributes: Record<string, string | number | boolean> }> = new Map();\n\n constructor(config: TelemetryConfig) {\n this.config = {\n enabled: config.enabled ?? false,\n serviceName: config.serviceName ?? 'omote-sdk',\n serviceVersion: config.serviceVersion ?? '0.1.0',\n exporter: config.exporter ?? 'none',\n exporterConfig: config.exporterConfig,\n sampling: config.sampling ?? { ratio: 1.0, alwaysSampleErrors: true },\n metricsEnabled: config.metricsEnabled ?? true,\n metricsIntervalMs: config.metricsIntervalMs ?? 60000,\n };\n\n if (this.config.enabled) {\n this.initExporter();\n this.startMetricsCollection();\n }\n }\n\n /**\n * Initialize the configured exporter\n */\n private initExporter(): void {\n switch (this.config.exporter) {\n case 'console':\n this.exporter = new ConsoleExporter({ enabled: true });\n break;\n case 'otlp':\n if (!this.config.exporterConfig) {\n console.warn('[Telemetry] OTLP exporter requires exporterConfig with endpoint');\n return;\n }\n this.exporter = new OTLPExporter(\n this.config.exporterConfig,\n this.config.serviceName,\n this.config.serviceVersion\n );\n break;\n case 'none':\n default:\n this.exporter = null;\n }\n }\n\n /**\n * Start periodic metrics collection\n */\n private startMetricsCollection(): void {\n if (!this.config.metricsEnabled || !this.exporter) return;\n\n this.metricsIntervalId = setInterval(() => {\n this.flushMetrics();\n }, this.config.metricsIntervalMs);\n }\n\n /**\n * Check if this operation should be sampled\n */\n private shouldSample(isError: boolean = false): boolean {\n if (!this.config.enabled) return false;\n\n const sampling = this.config.sampling as SamplingConfig;\n if (isError && sampling.alwaysSampleErrors) return true;\n\n const ratio = sampling.ratio ?? 1.0;\n return Math.random() < ratio;\n }\n\n /**\n * Start a new span\n *\n * @example\n * ```typescript\n * const span = telemetry.startSpan('Wav2Vec2.infer', {\n * 'inference.input_samples': samples.length,\n * 'model.backend': 'webgpu',\n * });\n *\n * try {\n * const result = await doInference();\n * span.setAttributes({ 'inference.output_frames': result.frames });\n * span.end();\n * } catch (error) {\n * span.endWithError(error);\n * }\n * ```\n */\n startSpan(name: string, attributes: Partial<SpanAttributes> = {}, parentContext?: SpanContext): ActiveSpan {\n const traceId = parentContext?.traceId ?? this.activeTraceId ?? generateId(16);\n const spanId = generateId(8);\n const parentSpanId = parentContext?.spanId;\n const startTime = getClock().now();\n\n // Set active trace if this is a root span\n if (!parentContext && !this.activeTraceId) {\n this.activeTraceId = traceId;\n }\n\n let spanAttributes = { ...attributes };\n let ended = false;\n let sampled = this.shouldSample();\n\n const context: SpanContext = { traceId, spanId, parentSpanId };\n\n // Push to span stack for log-to-span correlation\n this.spanStack.push({ traceId, spanId });\n\n const endSpan = (status: 'ok' | 'error', error?: Error): void => {\n if (ended) return;\n ended = true;\n\n // Pop from span stack\n const idx = this.spanStack.findIndex(s => s.spanId === spanId);\n if (idx !== -1) this.spanStack.splice(idx, 1);\n\n const endTime = getClock().now();\n const durationMs = endTime - startTime;\n\n // Re-check sampling for errors\n if (status === 'error' && !sampled) {\n sampled = this.shouldSample(true);\n }\n\n if (!sampled || !this.exporter) return;\n\n const spanData: SpanData = {\n name,\n traceId,\n spanId,\n parentSpanId,\n startTime,\n endTime,\n durationMs,\n status,\n attributes: spanAttributes as SpanAttributes,\n error,\n };\n\n this.exporter.exportSpan(spanData);\n\n // Clear active trace if this was the root span\n if (!parentSpanId && this.activeTraceId === traceId) {\n this.activeTraceId = null;\n }\n };\n\n return {\n end: () => endSpan('ok'),\n endWithError: (error: Error) => endSpan('error', error),\n setAttributes: (attrs: Partial<SpanAttributes>) => {\n spanAttributes = { ...spanAttributes, ...attrs };\n },\n getContext: () => context,\n };\n }\n\n /**\n * Wrap an async function with a span\n *\n * @example\n * ```typescript\n * const result = await telemetry.withSpan('Model.load', async (span) => {\n * const model = await loadModel();\n * span.setAttributes({ 'model.size_bytes': model.size });\n * return model;\n * });\n * ```\n */\n async withSpan<T>(\n name: string,\n fn: (span: ActiveSpan) => Promise<T>,\n attributes: Partial<SpanAttributes> = {},\n parentContext?: SpanContext\n ): Promise<T> {\n const span = this.startSpan(name, attributes, parentContext);\n\n try {\n const result = await fn(span);\n span.end();\n return result;\n } catch (error) {\n span.endWithError(error as Error);\n throw error;\n }\n }\n\n /**\n * Increment a counter metric\n *\n * @example\n * ```typescript\n * telemetry.incrementCounter('omote.inference.total', 1, {\n * model: 'wav2vec2',\n * backend: 'webgpu',\n * status: 'success',\n * });\n * ```\n */\n incrementCounter(\n name: string,\n value: number = 1,\n attributes: Record<string, string | number | boolean> = {}\n ): void {\n if (!this.config.enabled || !this.config.metricsEnabled) return;\n\n const key = this.getMetricKey(name, attributes);\n const existing = this.counters.get(key);\n\n if (existing) {\n existing.value += value;\n } else {\n this.counters.set(key, { value, attributes });\n }\n }\n\n /**\n * Record a histogram value\n *\n * @example\n * ```typescript\n * telemetry.recordHistogram('omote.inference.latency', durationMs, {\n * model: 'wav2vec2',\n * backend: 'webgpu',\n * });\n * ```\n */\n recordHistogram(\n name: string,\n value: number,\n attributes: Record<string, string | number | boolean> = {}\n ): void {\n if (!this.config.enabled || !this.config.metricsEnabled) return;\n\n const key = this.getMetricKey(name, attributes);\n const existing = this.histograms.get(key);\n\n if (existing) {\n existing.count++;\n existing.sum += value;\n if (value < existing.min) existing.min = value;\n if (value > existing.max) existing.max = value;\n } else {\n this.histograms.set(key, { count: 1, sum: value, min: value, max: value, attributes });\n }\n }\n\n /**\n * Generate unique key for metric with attributes\n */\n private getMetricKey(name: string, attributes: Record<string, string | number | boolean>): string {\n // Fast path: no attributes → return name directly (avoids Object.entries + sort + join)\n const keys = Object.keys(attributes);\n if (keys.length === 0) return name;\n\n const sortedAttrs = Object.entries(attributes)\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([k, v]) => `${k}=${v}`)\n .join(',');\n return `${name}|${sortedAttrs}`;\n }\n\n /**\n * Flush accumulated metrics to exporter\n */\n private flushMetrics(): void {\n if (!this.exporter) return;\n\n const timestamp = getClock().now();\n\n // Export counters (delta temporality — reset after export)\n for (const [key, data] of this.counters) {\n if (data.value === 0) continue;\n const name = key.split('|')[0];\n const metric: MetricData = {\n name,\n type: 'counter',\n value: data.value,\n attributes: data.attributes,\n timestamp,\n };\n this.exporter.exportMetric(metric);\n data.value = 0;\n }\n\n // Export histogram aggregates (O(1) — no array spread)\n for (const [key, data] of this.histograms) {\n const name = key.split('|')[0];\n if (data.count === 0) continue;\n\n const avg = data.sum / data.count;\n\n const metric: MetricData = {\n name,\n type: 'histogram',\n value: avg,\n attributes: {\n ...data.attributes,\n count: data.count,\n sum: data.sum,\n min: data.min,\n max: data.max,\n },\n timestamp,\n };\n this.exporter.exportMetric(metric);\n\n // Reset accumulators after export\n data.count = 0;\n data.sum = 0;\n data.min = Infinity;\n data.max = -Infinity;\n }\n }\n\n /**\n * Force flush all pending data\n */\n async flush(): Promise<void> {\n this.flushMetrics();\n await this.exporter?.flush();\n }\n\n /**\n * Shutdown telemetry\n */\n async shutdown(): Promise<void> {\n if (this.metricsIntervalId) {\n clearInterval(this.metricsIntervalId);\n this.metricsIntervalId = null;\n }\n\n await this.flush();\n await this.exporter?.shutdown();\n this.exporter = null;\n }\n\n /**\n * Check if telemetry is enabled\n */\n isEnabled(): boolean {\n return this.config.enabled;\n }\n\n /**\n * Get current configuration\n */\n getConfig(): TelemetryConfig {\n return { ...this.config };\n }\n\n /**\n * Get the active span context for log-to-span correlation.\n * Returns the most recent (top of stack) active span, or null if none.\n */\n getActiveContext(): { traceId: string; spanId: string } | null {\n return this.spanStack.length > 0 ? this.spanStack[this.spanStack.length - 1] : null;\n }\n}\n","/**\n * Omote SDK Logger\n *\n * Unified logging system with:\n * - 6 log levels (error, warn, info, debug, trace, verbose)\n * - Structured JSON output for machine parsing\n * - Pretty output for human readability\n * - Module-based child loggers\n * - Runtime configuration\n * - Browser and Node.js compatible\n */\n\nimport type {\n LogLevel,\n LogEntry,\n LoggingConfig,\n LogSink,\n ILogger,\n} from './types';\nimport { LOG_LEVEL_PRIORITY, DEFAULT_LOGGING_CONFIG } from './types';\nimport { getFormatter, createBrowserConsoleArgs } from './formatters';\nimport { getTelemetry } from '../telemetry/OmoteTelemetry';\nimport { getClock } from './Clock';\n\n/**\n * Check if running in browser\n */\nconst isBrowser = typeof window !== 'undefined';\n\n/**\n * Global logging configuration\n */\nlet globalConfig: LoggingConfig = { ...DEFAULT_LOGGING_CONFIG };\n\n/**\n * Configure global logging settings\n */\nexport function configureLogging(config: Partial<LoggingConfig>): void {\n globalConfig = { ...globalConfig, ...config };\n}\n\n/**\n * Get current logging configuration\n */\nexport function getLoggingConfig(): LoggingConfig {\n return { ...globalConfig };\n}\n\n/**\n * Reset logging configuration to defaults\n */\nexport function resetLoggingConfig(): void {\n globalConfig = { ...DEFAULT_LOGGING_CONFIG };\n}\n\n/**\n * Set log level at runtime\n */\nexport function setLogLevel(level: LogLevel): void {\n globalConfig.level = level;\n}\n\n/**\n * Enable or disable logging\n */\nexport function setLoggingEnabled(enabled: boolean): void {\n globalConfig.enabled = enabled;\n}\n\n/**\n * Default console sink with browser-optimized output\n */\nconst consoleSink: LogSink = (entry: LogEntry): void => {\n const consoleMethod = entry.level === 'error' ? 'error'\n : entry.level === 'warn' ? 'warn'\n : 'log';\n\n if (globalConfig.format === 'pretty' && isBrowser) {\n // Use styled console output in browser\n const args = createBrowserConsoleArgs(entry);\n (console as Record<string, (...args: unknown[]) => void>)[consoleMethod](...args);\n } else {\n // Use formatter for terminal or JSON output\n const formatter = getFormatter(globalConfig.format);\n const formatted = formatter(entry);\n (console as Record<string, (...args: unknown[]) => void>)[consoleMethod](formatted);\n }\n};\n\n/**\n * Get the active sink (custom or default console)\n */\nfunction getActiveSink(): LogSink {\n return globalConfig.sink || consoleSink;\n}\n\n/**\n * Check if a log level should be output given current config\n */\nfunction shouldLog(level: LogLevel): boolean {\n if (!globalConfig.enabled) return false;\n return LOG_LEVEL_PRIORITY[level] <= LOG_LEVEL_PRIORITY[globalConfig.level];\n}\n\n/**\n * Logger implementation\n */\nclass Logger implements ILogger {\n readonly module: string;\n\n constructor(module: string) {\n this.module = module;\n }\n\n private log(level: LogLevel, message: string, data?: Record<string, unknown>): void {\n if (!shouldLog(level)) return;\n\n const entry: LogEntry = {\n timestamp: getClock().timestamp(),\n level,\n module: this.module,\n message,\n data,\n };\n\n // Attach active span context for log-to-span correlation\n const ctx = getTelemetry()?.getActiveContext();\n if (ctx) {\n entry.traceId = ctx.traceId;\n entry.spanId = ctx.spanId;\n }\n\n // Extract error from data if present\n if (data?.error instanceof Error) {\n entry.error = data.error;\n // Remove from data to avoid duplication\n const { error, ...rest } = data;\n entry.data = Object.keys(rest).length > 0 ? rest : undefined;\n }\n\n getActiveSink()(entry);\n }\n\n error(message: string, data?: Record<string, unknown>): void {\n this.log('error', message, data);\n }\n\n warn(message: string, data?: Record<string, unknown>): void {\n this.log('warn', message, data);\n }\n\n info(message: string, data?: Record<string, unknown>): void {\n this.log('info', message, data);\n }\n\n debug(message: string, data?: Record<string, unknown>): void {\n this.log('debug', message, data);\n }\n\n trace(message: string, data?: Record<string, unknown>): void {\n this.log('trace', message, data);\n }\n\n verbose(message: string, data?: Record<string, unknown>): void {\n this.log('verbose', message, data);\n }\n\n child(subModule: string): ILogger {\n return new Logger(`${this.module}.${subModule}`);\n }\n}\n\n/**\n * Logger cache for reusing instances\n */\nconst loggerCache = new Map<string, Logger>();\n\n/**\n * Create a logger for a specific module\n *\n * @param module - Module name (e.g., 'LocalInference', 'ModelCache')\n * @returns Logger instance\n *\n * @example\n * ```typescript\n * const logger = createLogger('LocalInference');\n * logger.info('Model loaded', { backend: 'webgpu', loadTimeMs: 1234 });\n * ```\n */\nexport function createLogger(module: string): ILogger {\n let logger = loggerCache.get(module);\n if (!logger) {\n logger = new Logger(module);\n loggerCache.set(module, logger);\n }\n return logger;\n}\n\n/**\n * Clear logger cache (useful for testing)\n */\nexport function clearLoggerCache(): void {\n loggerCache.clear();\n}\n\n/**\n * No-op logger for when logging is completely disabled\n */\nexport const noopLogger: ILogger = {\n module: 'noop',\n error: () => {},\n warn: () => {},\n info: () => {},\n debug: () => {},\n trace: () => {},\n verbose: () => {},\n child: () => noopLogger,\n};\n\n/**\n * Get a no-op logger (for production builds that tree-shake logging)\n */\nexport function getNoopLogger(): ILogger {\n return noopLogger;\n}\n","/**\n * Structured error codes for the Omote SDK.\n *\n * Codes follow the pattern `OMOTE_{CATEGORY}_{SEQ}` where:\n * - **INF** = Inference (model loading, session, OOM)\n * - **AUD** = Audio (AudioContext, scheduling, decoding)\n * - **SPH** = Speech (VAD, ASR, microphone)\n * - **TTS** = Text-to-Speech (synthesis, streaming, phonemizer)\n * - **PIP** = Pipeline (state machine, abort)\n * - **CAC** = Cache (IndexedDB quota, eviction, staleness)\n * - **NET** = Network (fetch, timeout, WebSocket)\n *\n * Exported as a const object (not enum) for tree-shaking.\n */\nexport const ErrorCodes = {\n // ── Inference ──────────────────────────────────────────────────────────\n /** Model failed to load (file not found, corrupted, unsupported format) */\n INF_LOAD_FAILED: 'OMOTE_INF_001',\n /** ORT session poisoned after WebGPU device loss — must reload tab */\n INF_SESSION_POISON: 'OMOTE_INF_002',\n /** Inference exceeded timeout threshold */\n INF_TIMEOUT: 'OMOTE_INF_003',\n /** Out-of-memory during inference or model loading */\n INF_OOM: 'OMOTE_INF_004',\n /** WebGPU unavailable, fell back to WASM */\n INF_WEBGPU_FALLBACK: 'OMOTE_INF_005',\n /** Input tensor shape does not match model expectations */\n INF_SHAPE_MISMATCH: 'OMOTE_INF_006',\n\n // ── Audio ──────────────────────────────────────────────────────────────\n /** AudioContext creation or resume failed */\n AUD_CONTEXT_FAILED: 'OMOTE_AUD_001',\n /** Gap detected in audio scheduling (buffer underrun) */\n AUD_SCHEDULE_GAP: 'OMOTE_AUD_002',\n /** Audio buffer decoding failed */\n AUD_DECODE_FAILED: 'OMOTE_AUD_003',\n\n // ── Speech ─────────────────────────────────────────────────────────────\n /** Voice activity detection error */\n SPH_VAD_ERROR: 'OMOTE_SPH_001',\n /** Automatic speech recognition error */\n SPH_ASR_ERROR: 'OMOTE_SPH_002',\n /** Microphone access denied or unavailable */\n SPH_MIC_DENIED: 'OMOTE_SPH_003',\n\n // ── TTS ────────────────────────────────────────────────────────────────\n /** TTS synthesis failed */\n TTS_SYNTH_FAILED: 'OMOTE_TTS_001',\n /** TTS streaming error (chunk delivery failure) */\n TTS_STREAM_ERROR: 'OMOTE_TTS_002',\n /** Phonemizer (eSpeak-NG WASM) ran out of memory */\n TTS_PHONEMIZER_OOM: 'OMOTE_TTS_003',\n\n // ── Pipeline ───────────────────────────────────────────────────────────\n /** Invalid state transition in pipeline state machine */\n PIP_STATE_ERROR: 'OMOTE_PIP_001',\n /** Pipeline operation aborted (user interrupt or signal) */\n PIP_ABORT: 'OMOTE_PIP_002',\n\n // ── Cache ──────────────────────────────────────────────────────────────\n /** IndexedDB storage quota exceeded */\n CAC_QUOTA_EXCEEDED: 'OMOTE_CAC_001',\n /** Cache entry evicted (LRU or manual) */\n CAC_EVICTION: 'OMOTE_CAC_002',\n /** Cached model is stale (version mismatch) */\n CAC_STALE: 'OMOTE_CAC_003',\n\n // ── Network ────────────────────────────────────────────────────────────\n /** HTTP fetch failed (model download, CDN) */\n NET_FETCH_FAILED: 'OMOTE_NET_001',\n /** Network request timed out */\n NET_TIMEOUT: 'OMOTE_NET_002',\n /** WebSocket connection error */\n NET_WEBSOCKET_ERROR: 'OMOTE_NET_003',\n} as const;\n\n/** Union type of all error code string values. */\nexport type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];\n"],"mappings":";AAiBO,IAAM,qBAA+C;AAAA,EAC1D,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,SAAS;AACX;AAyFO,IAAM,yBAAwC;AAAA,EACnD,OAAO;AAAA,EACP,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,eAAe;AACjB;;;AC9GA,IAAM,SAAS;AAAA,EACb,OAAO;AAAA,EACP,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,SAAS;AACX;AAKA,IAAM,eAAyC;AAAA,EAC7C,OAAO,OAAO;AAAA,EACd,MAAM,OAAO;AAAA,EACb,MAAM,OAAO;AAAA,EACb,OAAO,OAAO;AAAA,EACd,OAAO,OAAO;AAAA,EACd,SAAS,OAAO;AAClB;AAKA,IAAM,cAAwC;AAAA,EAC5C,OAAO;AAAA,EACP,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AAAA,EACP,SAAS;AACX;AAKA,IAAM,YAAY,OAAO,WAAW;AAKpC,SAAS,gBAAgB,WAA2B;AAClD,QAAM,OAAO,IAAI,KAAK,SAAS;AAC/B,SAAO,KAAK,YAAY,EAAE,UAAU,IAAI,EAAE;AAC5C;AAKA,SAAS,cAAc,MAAuB;AAC5C,QAAM,OAAO,oBAAI,QAAQ;AACzB,SAAO,KAAK,UAAU,MAAM,CAAC,KAAK,UAAU;AAC1C,QAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,UAAI,KAAK,IAAI,KAAK,GAAG;AACnB,eAAO;AAAA,MACT;AACA,WAAK,IAAI,KAAK;AAAA,IAChB;AAEA,QAAI,iBAAiB,OAAO;AAC1B,aAAO;AAAA,QACL,MAAM,MAAM;AAAA,QACZ,SAAS,MAAM;AAAA,QACf,OAAO,MAAM;AAAA,MACf;AAAA,IACF;AACA,QAAI,iBAAiB,gBAAgB,iBAAiB,YAAY;AAChE,aAAO,GAAG,MAAM,YAAY,IAAI,IAAI,MAAM,MAAM;AAAA,IAClD;AACA,QAAI,YAAY,OAAO,KAAK,GAAG;AAC7B,aAAO,GAAG,MAAM,YAAY,IAAI,IAAI,MAAM,UAAU;AAAA,IACtD;AACA,WAAO;AAAA,EACT,CAAC;AACH;AAKO,IAAM,gBAA8B,CAAC,UAA4B;AACtE,QAAM,SAAkC;AAAA,IACtC,WAAW,MAAM;AAAA,IACjB,OAAO,MAAM;AAAA,IACb,QAAQ,MAAM;AAAA,IACd,SAAS,MAAM;AAAA,EACjB;AAEA,MAAI,MAAM,QAAQ,OAAO,KAAK,MAAM,IAAI,EAAE,SAAS,GAAG;AACpD,WAAO,OAAO,MAAM;AAAA,EACtB;AAEA,MAAI,MAAM,OAAO;AACf,WAAO,QAAQ;AAAA,MACb,MAAM,MAAM,MAAM;AAAA,MAClB,SAAS,MAAM,MAAM;AAAA,MACrB,OAAO,MAAM,MAAM;AAAA,IACrB;AAAA,EACF;AAEA,SAAO,cAAc,MAAM;AAC7B;AAKO,IAAM,kBAAgC,CAAC,UAA4B;AACxE,QAAM,OAAO,gBAAgB,MAAM,SAAS;AAC5C,QAAM,QAAQ,YAAY,MAAM,KAAK;AACrC,QAAM,SAAS,MAAM;AACrB,QAAM,UAAU,MAAM;AAGtB,MAAI;AAEJ,MAAI,WAAW;AAEb,aAAS,GAAG,IAAI,IAAI,KAAK,KAAK,MAAM,KAAK,OAAO;AAAA,EAClD,OAAO;AAEL,UAAM,QAAQ,aAAa,MAAM,KAAK;AACtC,aAAS,GAAG,OAAO,IAAI,GAAG,IAAI,GAAG,OAAO,KAAK,IAAI,KAAK,GAAG,KAAK,GAAG,OAAO,KAAK,IAAI,OAAO,IAAI,IAAI,MAAM,IAAI,OAAO,KAAK,IAAI,OAAO;AAAA,EACnI;AAGA,MAAI,MAAM,QAAQ,OAAO,KAAK,MAAM,IAAI,EAAE,SAAS,GAAG;AACpD,UAAM,UAAU,cAAc,MAAM,IAAI;AAExC,QAAI,QAAQ,SAAS,IAAI;AACvB,gBAAU,SAAS,KAAK,UAAU,MAAM,MAAM,MAAM,CAAC,EAAE,QAAQ,OAAO,MAAM;AAAA,IAC9E,OAAO;AACL,gBAAU,MAAM;AAAA,IAClB;AAAA,EACF;AAGA,MAAI,MAAM,OAAO;AACf,cAAU;AAAA,IAAO,MAAM,MAAM,IAAI,KAAK,MAAM,MAAM,OAAO;AACzD,QAAI,MAAM,MAAM,OAAO;AACrB,YAAM,aAAa,MAAM,MAAM,MAAM,MAAM,IAAI,EAAE,MAAM,GAAG,CAAC;AAC3D,gBAAU,SAAS,WAAW,KAAK,MAAM;AAAA,IAC3C;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,aAAa,QAAyC;AACpE,SAAO,WAAW,SAAS,gBAAgB;AAC7C;AAMO,SAAS,yBAAyB,OAAwC;AAC/E,QAAM,OAAO,gBAAgB,MAAM,SAAS;AAC5C,QAAM,QAAQ,MAAM,MAAM,YAAY,EAAE,OAAO,CAAC;AAChD,QAAM,SAAS,MAAM;AACrB,QAAM,UAAU,MAAM;AAGtB,QAAM,SAAS;AAAA,IACb,MAAM;AAAA,IACN,OAAO;AAAA,IACP,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO;AAAA,IACP,OAAO;AAAA,IACP,SAAS;AAAA,IACT,QAAQ;AAAA,IACR,SAAS;AAAA,EACX;AAEA,MAAI,YAAY;AAChB,QAAM,OAAiB;AAAA,IACrB,OAAO;AAAA,IACP;AAAA,IACA,OAAO,MAAM,KAAK;AAAA,IAClB;AAAA,IACA,OAAO;AAAA,IACP;AAAA,IACA,OAAO;AAAA,IACP;AAAA,EACF;AAGA,MAAI,MAAM,QAAQ,OAAO,KAAK,MAAM,IAAI,EAAE,SAAS,GAAG;AACpD,iBAAa;AACb,SAAK,KAAK,MAAM,IAAyB;AAAA,EAC3C;AAEA,SAAO,CAAC,WAAW,GAAG,IAAI;AAC5B;;;ACtJO,IAAM,kBAAN,MAA4D;AAAA,EAIjE,YAAY,UAAkD,CAAC,GAAG;AAChE,SAAK,UAAU,QAAQ,WAAW;AAClC,SAAK,SAAS,QAAQ,UAAU;AAAA,EAClC;AAAA,EAEA,WAAW,MAAsB;AAC/B,QAAI,CAAC,KAAK,QAAS;AAEnB,UAAM,aAAa,KAAK,WAAW,OAAO,WAAM;AAChD,UAAM,cAAc,KAAK,WAAW,OAAO,iBAAiB;AAE5D,YAAQ;AAAA,MACN,KAAK,KAAK,MAAM,MAAM,UAAU,IAAI,KAAK,IAAI,OAAO,KAAK,WAAW,QAAQ,CAAC,CAAC;AAAA,MAC9E;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,YAAQ,IAAI,aAAa,KAAK,OAAO;AACrC,YAAQ,IAAI,YAAY,KAAK,MAAM;AACnC,QAAI,KAAK,cAAc;AACrB,cAAQ,IAAI,mBAAmB,KAAK,YAAY;AAAA,IAClD;AACA,YAAQ,IAAI,aAAa,GAAG,KAAK,WAAW,QAAQ,CAAC,CAAC,IAAI;AAC1D,YAAQ,IAAI,WAAW,KAAK,MAAM;AAElC,QAAI,OAAO,KAAK,KAAK,UAAU,EAAE,SAAS,GAAG;AAC3C,cAAQ,IAAI,eAAe,KAAK,UAAU;AAAA,IAC5C;AAEA,QAAI,KAAK,OAAO;AACd,cAAQ,MAAM,UAAU,KAAK,KAAK;AAAA,IACpC;AAEA,YAAQ,SAAS;AAAA,EACnB;AAAA,EAEA,aAAa,QAA0B;AACrC,QAAI,CAAC,KAAK,QAAS;AAEnB,UAAM,WAAW,OAAO,SAAS,YAAY,WAAM;AAEnD,YAAQ;AAAA,MACN,KAAK,KAAK,MAAM,MAAM,QAAQ,IAAI,OAAO,IAAI,OAAO,OAAO,KAAK;AAAA,MAChE;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAM,QAAuB;AAAA,EAE7B;AAAA,EAEA,MAAM,WAA0B;AAC9B,SAAK,UAAU;AAAA,EACjB;AACF;;;ACvGA,IAAM,aAAa;AAAA,EACjB,OAAO;AAAA,EACP,IAAI;AAAA,EACJ,OAAO;AACT;AAKA,SAAS,WAAW,MAAgB,aAAqB,gBAAwB;AAC/E,QAAM,aAAa,OAAO,QAAQ,KAAK,UAAU,EAC9C,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,MAAM,MAAS,EACjC,IAAI,CAAC,CAAC,KAAK,KAAK,OAAO;AAAA,IACtB;AAAA,IACA,OAAO,OAAO,UAAU,WACpB,EAAE,aAAa,MAAM,IACrB,OAAO,UAAU,WACf,OAAO,UAAU,KAAK,IACpB,EAAE,UAAU,MAAM,IAClB,EAAE,aAAa,MAAM,IACvB,EAAE,WAAW,MAAM;AAAA,EAC3B,EAAE;AAEJ,SAAO;AAAA,IACL,eAAe,CAAC;AAAA,MACd,UAAU;AAAA,QACR,YAAY;AAAA,UACV,EAAE,KAAK,gBAAgB,OAAO,EAAE,aAAa,YAAY,EAAE;AAAA,UAC3D,EAAE,KAAK,mBAAmB,OAAO,EAAE,aAAa,eAAe,EAAE;AAAA,UACjE,EAAE,KAAK,sBAAsB,OAAO,EAAE,aAAa,YAAY,EAAE;AAAA,UACjE,EAAE,KAAK,0BAA0B,OAAO,EAAE,aAAa,aAAa,EAAE;AAAA,QACxE;AAAA,MACF;AAAA,MACA,YAAY,CAAC;AAAA,QACX,OAAO;AAAA,UACL,MAAM;AAAA,UACN,SAAS;AAAA,QACX;AAAA,QACA,OAAO,CAAC;AAAA,UACN,SAAS,KAAK;AAAA,UACd,QAAQ,KAAK;AAAA,UACb,cAAc,KAAK,gBAAgB;AAAA,UACnC,MAAM,KAAK;AAAA,UACX,MAAM;AAAA;AAAA,UACN,mBAAmB,OAAO,KAAK,YAAY,GAAS;AAAA,UACpD,iBAAiB,OAAO,KAAK,UAAU,GAAS;AAAA,UAChD;AAAA,UACA,QAAQ;AAAA,YACN,MAAM,KAAK,WAAW,OAAO,WAAW,KAAK,WAAW;AAAA,YACxD,SAAS,KAAK,OAAO,WAAW;AAAA,UAClC;AAAA,QACF,CAAC;AAAA,MACH,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AACF;AAKA,SAAS,aAAa,QAAoB,aAAqB,gBAAwB;AACrF,QAAM,aAAa,OAAO,QAAQ,OAAO,UAAU,EAChD,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,MAAM,MAAS,EACjC,IAAI,CAAC,CAAC,KAAK,KAAK,OAAO;AAAA,IACtB;AAAA,IACA,OAAO,OAAO,UAAU,WACpB,EAAE,aAAa,MAAM,IACrB,OAAO,UAAU,WACf,OAAO,UAAU,KAAK,IACpB,EAAE,UAAU,MAAM,IAClB,EAAE,aAAa,MAAM,IACvB,EAAE,WAAW,MAAM;AAAA,EAC3B,EAAE;AAEJ,QAAM,YAAY;AAAA,IAChB;AAAA,IACA,cAAc,OAAO,OAAO,YAAY,GAAS;AAAA,IACjD,GAAI,OAAO,SAAS,YAChB,EAAE,OAAO,OAAO,MAAM,IACtB,EAAE,UAAU,OAAO,MAAM;AAAA,EAC/B;AAEA,SAAO;AAAA,IACL,iBAAiB,CAAC;AAAA,MAChB,UAAU;AAAA,QACR,YAAY;AAAA,UACV,EAAE,KAAK,gBAAgB,OAAO,EAAE,aAAa,YAAY,EAAE;AAAA,UAC3D,EAAE,KAAK,mBAAmB,OAAO,EAAE,aAAa,eAAe,EAAE;AAAA,QACnE;AAAA,MACF;AAAA,MACA,cAAc,CAAC;AAAA,QACb,OAAO;AAAA,UACL,MAAM;AAAA,UACN,SAAS;AAAA,QACX;AAAA,QACA,SAAS,CAAC;AAAA,UACR,MAAM,OAAO;AAAA,UACb,GAAI,OAAO,SAAS,YAChB;AAAA,YACA,KAAK;AAAA,cACH,YAAY,CAAC,SAAS;AAAA,cACtB,wBAAwB;AAAA;AAAA,cACxB,aAAa;AAAA,YACf;AAAA,UACF,IACE;AAAA,YACA,OAAO;AAAA,cACL,YAAY,CAAC,SAAS;AAAA,YACxB;AAAA,UACF;AAAA,QACJ,CAAC;AAAA,MACH,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AACF;AAYO,IAAM,eAAN,MAAyD;AAAA,EAW9D,YACE,QACA,cAAsB,aACtB,iBAAyB,SACzB;AAXF,SAAQ,aAAyB,CAAC;AAClC,SAAQ,eAA6B,CAAC;AACtC,SAAQ,kBAAyD;AACjE,SAAiB,cAAc;AAC/B,SAAiB,oBAAoB;AACrC,SAAQ,aAAa;AAQnB,UAAM,SAAS,IAAI,IAAI,OAAO,QAAQ;AACtC,QAAI,OAAO,aAAa,UAAU;AAChC,YAAM,cAAc,OAAO,aAAa,eAAe,OAAO,aAAa,eAAe,OAAO,aAAa;AAC9G,UAAI,CAAC,aAAa;AAChB,cAAM,IAAI,MAAM,6DAA6D;AAAA,MAC/E;AAAA,IACF;AACA,SAAK,SAAS;AAAA,MACZ,UAAU,OAAO;AAAA,MACjB,WAAW,OAAO,aAAa;AAAA,MAC/B,SAAS,OAAO,UAAU,EAAE,GAAG,OAAO,QAAQ,IAAI,CAAC;AAAA,IACrD;AACA,SAAK,cAAc;AACnB,SAAK,iBAAiB;AAGtB,SAAK,kBAAkB,YAAY,MAAM;AACvC,WAAK,MAAM,EAAE,MAAM,QAAQ,KAAK;AAAA,IAClC,GAAG,KAAK,iBAAiB;AAAA,EAC3B;AAAA,EAEA,WAAW,MAAsB;AAC/B,QAAI,KAAK,WAAY;AAErB,SAAK,WAAW,KAAK,IAAI;AAEzB,QAAI,KAAK,WAAW,UAAU,KAAK,aAAa;AAC9C,WAAK,MAAM,EAAE,MAAM,QAAQ,KAAK;AAAA,IAClC;AAAA,EACF;AAAA,EAEA,aAAa,QAA0B;AACrC,QAAI,KAAK,WAAY;AAErB,SAAK,aAAa,KAAK,MAAM;AAE7B,QAAI,KAAK,aAAa,UAAU,KAAK,aAAa;AAChD,WAAK,MAAM,EAAE,MAAM,QAAQ,KAAK;AAAA,IAClC;AAAA,EACF;AAAA,EAEA,MAAM,QAAuB;AAC3B,QAAI,KAAK,WAAY;AAErB,UAAM,QAAQ,KAAK,WAAW,OAAO,CAAC;AACtC,UAAM,UAAU,KAAK,aAAa,OAAO,CAAC;AAE1C,UAAM,WAA4B,CAAC;AAGnC,QAAI,MAAM,SAAS,GAAG;AACpB,eAAS,KAAK,KAAK,YAAY,KAAK,CAAC;AAAA,IACvC;AAGA,QAAI,QAAQ,SAAS,GAAG;AACtB,eAAS,KAAK,KAAK,cAAc,OAAO,CAAC;AAAA,IAC3C;AAEA,UAAM,QAAQ,IAAI,QAAQ;AAAA,EAC5B;AAAA,EAEA,MAAM,WAA0B;AAC9B,QAAI,KAAK,iBAAiB;AACxB,oBAAc,KAAK,eAAe;AAClC,WAAK,kBAAkB;AAAA,IACzB;AAGA,UAAM,KAAK,MAAM;AAEjB,SAAK,aAAa;AAAA,EACpB;AAAA,EAEA,MAAc,YAAY,OAAkC;AAE1D,UAAM,gBAAgB,MAAM;AAAA,MAAI,UAC9B,WAAW,MAAM,KAAK,aAAa,KAAK,cAAc,EAAE,cAAc,CAAC;AAAA,IACzE;AAEA,UAAM,OAAO,EAAE,cAAc;AAC7B,UAAM,WAAW,KAAK,OAAO,SAAS,QAAQ,OAAO,EAAE,IAAI;AAE3D,UAAM,KAAK,YAAY,UAAU,IAAI;AAAA,EACvC;AAAA,EAEA,MAAc,cAAc,SAAsC;AAEhE,UAAM,kBAAkB,QAAQ;AAAA,MAAI,YAClC,aAAa,QAAQ,KAAK,aAAa,KAAK,cAAc,EAAE,gBAAgB,CAAC;AAAA,IAC/E;AAEA,UAAM,OAAO,EAAE,gBAAgB;AAC/B,UAAM,WAAW,KAAK,OAAO,SAAS,QAAQ,OAAO,EAAE,IAAI;AAE3D,UAAM,KAAK,YAAY,UAAU,IAAI;AAAA,EACvC;AAAA,EAEA,MAAc,YAAY,UAAkB,MAA8B;AACxE,UAAM,aAAa,IAAI,gBAAgB;AACvC,UAAM,YAAY,WAAW,MAAM,WAAW,MAAM,GAAG,KAAK,OAAO,SAAS;AAE5E,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,UAAU;AAAA,QACrC,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,gBAAgB;AAAA,UAChB,GAAG,KAAK,OAAO;AAAA,QACjB;AAAA,QACA,MAAM,KAAK,UAAU,IAAI;AAAA,QACzB,QAAQ,WAAW;AAAA,MACrB,CAAC;AAED,UAAI,CAAC,SAAS,IAAI;AAChB,gBAAQ,KAAK,yBAAyB,SAAS,MAAM,IAAI,SAAS,UAAU,EAAE;AAAA,MAChF;AAAA,IACF,SAAS,OAAO;AACd,UAAK,MAAgB,SAAS,cAAc;AAC1C,gBAAQ,KAAK,yBAAyB;AAAA,MACxC,OAAO;AACL,gBAAQ,KAAK,wBAAwB,KAAK;AAAA,MAC5C;AAAA,IACF,UAAE;AACA,mBAAa,SAAS;AAAA,IACxB;AAAA,EACF;AACF;;;ACrPO,IAAM,eAAsB;AAAA,EACjC,KAAK,MAAM,YAAY,IAAI;AAAA,EAC3B,WAAW,MAAM,KAAK,IAAI;AAC5B;AAEA,IAAI,cAAqB;AAGlB,SAAS,eAAe,OAAoB;AACjD,gBAAc;AAChB;AAGO,SAAS,WAAkB;AAChC,SAAO;AACT;;;ACrCA,SAAS,WAAW,SAAiB,IAAY;AAC/C,QAAM,QAAQ,IAAI,WAAW,MAAM;AACnC,SAAO,gBAAgB,KAAK;AAC5B,SAAO,MAAM,KAAK,KAAK,EACpB,IAAI,OAAK,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EACxC,KAAK,EAAE;AACZ;AA4BA,IAAI,kBAAyC;AA0BtC,SAAS,mBAAmB,QAAyC;AAC1E,MAAI,iBAAiB;AACnB,oBAAgB,SAAS;AAAA,EAC3B;AACA,oBAAkB,IAAI,eAAe,MAAM;AAC3C,SAAO;AACT;AAKO,SAAS,eAAsC;AACpD,SAAO;AACT;AAOO,IAAM,iBAAN,MAAqB;AAAA,EAa1B,YAAY,QAAyB;AAXrC,SAAQ,WAA8C;AACtD,SAAQ,gBAA+B;AACvC,SAAQ,oBAA2D;AAGnE;AAAA,SAAQ,YAAwD,CAAC;AAGjE;AAAA,SAAQ,WAAkG,oBAAI,IAAI;AAClH,SAAQ,aAA2I,oBAAI,IAAI;AAGzJ,SAAK,SAAS;AAAA,MACZ,SAAS,OAAO,WAAW;AAAA,MAC3B,aAAa,OAAO,eAAe;AAAA,MACnC,gBAAgB,OAAO,kBAAkB;AAAA,MACzC,UAAU,OAAO,YAAY;AAAA,MAC7B,gBAAgB,OAAO;AAAA,MACvB,UAAU,OAAO,YAAY,EAAE,OAAO,GAAK,oBAAoB,KAAK;AAAA,MACpE,gBAAgB,OAAO,kBAAkB;AAAA,MACzC,mBAAmB,OAAO,qBAAqB;AAAA,IACjD;AAEA,QAAI,KAAK,OAAO,SAAS;AACvB,WAAK,aAAa;AAClB,WAAK,uBAAuB;AAAA,IAC9B;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAqB;AAC3B,YAAQ,KAAK,OAAO,UAAU;AAAA,MAC5B,KAAK;AACH,aAAK,WAAW,IAAI,gBAAgB,EAAE,SAAS,KAAK,CAAC;AACrD;AAAA,MACF,KAAK;AACH,YAAI,CAAC,KAAK,OAAO,gBAAgB;AAC/B,kBAAQ,KAAK,iEAAiE;AAC9E;AAAA,QACF;AACA,aAAK,WAAW,IAAI;AAAA,UAClB,KAAK,OAAO;AAAA,UACZ,KAAK,OAAO;AAAA,UACZ,KAAK,OAAO;AAAA,QACd;AACA;AAAA,MACF,KAAK;AAAA,MACL;AACE,aAAK,WAAW;AAAA,IACpB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,yBAA+B;AACrC,QAAI,CAAC,KAAK,OAAO,kBAAkB,CAAC,KAAK,SAAU;AAEnD,SAAK,oBAAoB,YAAY,MAAM;AACzC,WAAK,aAAa;AAAA,IACpB,GAAG,KAAK,OAAO,iBAAiB;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA,EAKQ,aAAa,UAAmB,OAAgB;AACtD,QAAI,CAAC,KAAK,OAAO,QAAS,QAAO;AAEjC,UAAM,WAAW,KAAK,OAAO;AAC7B,QAAI,WAAW,SAAS,mBAAoB,QAAO;AAEnD,UAAM,QAAQ,SAAS,SAAS;AAChC,WAAO,KAAK,OAAO,IAAI;AAAA,EACzB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBA,UAAU,MAAc,aAAsC,CAAC,GAAG,eAAyC;AACzG,UAAM,UAAU,eAAe,WAAW,KAAK,iBAAiB,WAAW,EAAE;AAC7E,UAAM,SAAS,WAAW,CAAC;AAC3B,UAAM,eAAe,eAAe;AACpC,UAAM,YAAY,SAAS,EAAE,IAAI;AAGjC,QAAI,CAAC,iBAAiB,CAAC,KAAK,eAAe;AACzC,WAAK,gBAAgB;AAAA,IACvB;AAEA,QAAI,iBAAiB,EAAE,GAAG,WAAW;AACrC,QAAI,QAAQ;AACZ,QAAI,UAAU,KAAK,aAAa;AAEhC,UAAM,UAAuB,EAAE,SAAS,QAAQ,aAAa;AAG7D,SAAK,UAAU,KAAK,EAAE,SAAS,OAAO,CAAC;AAEvC,UAAM,UAAU,CAAC,QAAwB,UAAwB;AAC/D,UAAI,MAAO;AACX,cAAQ;AAGR,YAAM,MAAM,KAAK,UAAU,UAAU,OAAK,EAAE,WAAW,MAAM;AAC7D,UAAI,QAAQ,GAAI,MAAK,UAAU,OAAO,KAAK,CAAC;AAE5C,YAAM,UAAU,SAAS,EAAE,IAAI;AAC/B,YAAM,aAAa,UAAU;AAG7B,UAAI,WAAW,WAAW,CAAC,SAAS;AAClC,kBAAU,KAAK,aAAa,IAAI;AAAA,MAClC;AAEA,UAAI,CAAC,WAAW,CAAC,KAAK,SAAU;AAEhC,YAAM,WAAqB;AAAA,QACzB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,YAAY;AAAA,QACZ;AAAA,MACF;AAEA,WAAK,SAAS,WAAW,QAAQ;AAGjC,UAAI,CAAC,gBAAgB,KAAK,kBAAkB,SAAS;AACnD,aAAK,gBAAgB;AAAA,MACvB;AAAA,IACF;AAEA,WAAO;AAAA,MACL,KAAK,MAAM,QAAQ,IAAI;AAAA,MACvB,cAAc,CAAC,UAAiB,QAAQ,SAAS,KAAK;AAAA,MACtD,eAAe,CAAC,UAAmC;AACjD,yBAAiB,EAAE,GAAG,gBAAgB,GAAG,MAAM;AAAA,MACjD;AAAA,MACA,YAAY,MAAM;AAAA,IACpB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,SACJ,MACA,IACA,aAAsC,CAAC,GACvC,eACY;AACZ,UAAM,OAAO,KAAK,UAAU,MAAM,YAAY,aAAa;AAE3D,QAAI;AACF,YAAM,SAAS,MAAM,GAAG,IAAI;AAC5B,WAAK,IAAI;AACT,aAAO;AAAA,IACT,SAAS,OAAO;AACd,WAAK,aAAa,KAAc;AAChC,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,iBACE,MACA,QAAgB,GAChB,aAAwD,CAAC,GACnD;AACN,QAAI,CAAC,KAAK,OAAO,WAAW,CAAC,KAAK,OAAO,eAAgB;AAEzD,UAAM,MAAM,KAAK,aAAa,MAAM,UAAU;AAC9C,UAAM,WAAW,KAAK,SAAS,IAAI,GAAG;AAEtC,QAAI,UAAU;AACZ,eAAS,SAAS;AAAA,IACpB,OAAO;AACL,WAAK,SAAS,IAAI,KAAK,EAAE,OAAO,WAAW,CAAC;AAAA,IAC9C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,gBACE,MACA,OACA,aAAwD,CAAC,GACnD;AACN,QAAI,CAAC,KAAK,OAAO,WAAW,CAAC,KAAK,OAAO,eAAgB;AAEzD,UAAM,MAAM,KAAK,aAAa,MAAM,UAAU;AAC9C,UAAM,WAAW,KAAK,WAAW,IAAI,GAAG;AAExC,QAAI,UAAU;AACZ,eAAS;AACT,eAAS,OAAO;AAChB,UAAI,QAAQ,SAAS,IAAK,UAAS,MAAM;AACzC,UAAI,QAAQ,SAAS,IAAK,UAAS,MAAM;AAAA,IAC3C,OAAO;AACL,WAAK,WAAW,IAAI,KAAK,EAAE,OAAO,GAAG,KAAK,OAAO,KAAK,OAAO,KAAK,OAAO,WAAW,CAAC;AAAA,IACvF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,aAAa,MAAc,YAA+D;AAEhG,UAAM,OAAO,OAAO,KAAK,UAAU;AACnC,QAAI,KAAK,WAAW,EAAG,QAAO;AAE9B,UAAM,cAAc,OAAO,QAAQ,UAAU,EAC1C,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,EACrC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,EAAE,EAC3B,KAAK,GAAG;AACX,WAAO,GAAG,IAAI,IAAI,WAAW;AAAA,EAC/B;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAqB;AAC3B,QAAI,CAAC,KAAK,SAAU;AAEpB,UAAM,YAAY,SAAS,EAAE,IAAI;AAGjC,eAAW,CAAC,KAAK,IAAI,KAAK,KAAK,UAAU;AACvC,UAAI,KAAK,UAAU,EAAG;AACtB,YAAM,OAAO,IAAI,MAAM,GAAG,EAAE,CAAC;AAC7B,YAAM,SAAqB;AAAA,QACzB;AAAA,QACA,MAAM;AAAA,QACN,OAAO,KAAK;AAAA,QACZ,YAAY,KAAK;AAAA,QACjB;AAAA,MACF;AACA,WAAK,SAAS,aAAa,MAAM;AACjC,WAAK,QAAQ;AAAA,IACf;AAGA,eAAW,CAAC,KAAK,IAAI,KAAK,KAAK,YAAY;AACzC,YAAM,OAAO,IAAI,MAAM,GAAG,EAAE,CAAC;AAC7B,UAAI,KAAK,UAAU,EAAG;AAEtB,YAAM,MAAM,KAAK,MAAM,KAAK;AAE5B,YAAM,SAAqB;AAAA,QACzB;AAAA,QACA,MAAM;AAAA,QACN,OAAO;AAAA,QACP,YAAY;AAAA,UACV,GAAG,KAAK;AAAA,UACR,OAAO,KAAK;AAAA,UACZ,KAAK,KAAK;AAAA,UACV,KAAK,KAAK;AAAA,UACV,KAAK,KAAK;AAAA,QACZ;AAAA,QACA;AAAA,MACF;AACA,WAAK,SAAS,aAAa,MAAM;AAGjC,WAAK,QAAQ;AACb,WAAK,MAAM;AACX,WAAK,MAAM;AACX,WAAK,MAAM;AAAA,IACb;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,QAAuB;AAC3B,SAAK,aAAa;AAClB,UAAM,KAAK,UAAU,MAAM;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAA0B;AAC9B,QAAI,KAAK,mBAAmB;AAC1B,oBAAc,KAAK,iBAAiB;AACpC,WAAK,oBAAoB;AAAA,IAC3B;AAEA,UAAM,KAAK,MAAM;AACjB,UAAM,KAAK,UAAU,SAAS;AAC9B,SAAK,WAAW;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,YAAqB;AACnB,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,YAA6B;AAC3B,WAAO,EAAE,GAAG,KAAK,OAAO;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,mBAA+D;AAC7D,WAAO,KAAK,UAAU,SAAS,IAAI,KAAK,UAAU,KAAK,UAAU,SAAS,CAAC,IAAI;AAAA,EACjF;AACF;;;ACvbA,IAAMA,aAAY,OAAO,WAAW;AAKpC,IAAI,eAA8B,EAAE,GAAG,uBAAuB;AAKvD,SAAS,iBAAiB,QAAsC;AACrE,iBAAe,EAAE,GAAG,cAAc,GAAG,OAAO;AAC9C;AAKO,SAAS,mBAAkC;AAChD,SAAO,EAAE,GAAG,aAAa;AAC3B;AAKO,SAAS,qBAA2B;AACzC,iBAAe,EAAE,GAAG,uBAAuB;AAC7C;AAKO,SAAS,YAAY,OAAuB;AACjD,eAAa,QAAQ;AACvB;AAKO,SAAS,kBAAkB,SAAwB;AACxD,eAAa,UAAU;AACzB;AAKA,IAAM,cAAuB,CAAC,UAA0B;AACtD,QAAM,gBAAgB,MAAM,UAAU,UAAU,UAC5C,MAAM,UAAU,SAAS,SACzB;AAEJ,MAAI,aAAa,WAAW,YAAYA,YAAW;AAEjD,UAAM,OAAO,yBAAyB,KAAK;AAC3C,IAAC,QAAyD,aAAa,EAAE,GAAG,IAAI;AAAA,EAClF,OAAO;AAEL,UAAM,YAAY,aAAa,aAAa,MAAM;AAClD,UAAM,YAAY,UAAU,KAAK;AACjC,IAAC,QAAyD,aAAa,EAAE,SAAS;AAAA,EACpF;AACF;AAKA,SAAS,gBAAyB;AAChC,SAAO,aAAa,QAAQ;AAC9B;AAKA,SAAS,UAAU,OAA0B;AAC3C,MAAI,CAAC,aAAa,QAAS,QAAO;AAClC,SAAO,mBAAmB,KAAK,KAAK,mBAAmB,aAAa,KAAK;AAC3E;AAKA,IAAM,SAAN,MAAM,QAA0B;AAAA,EAG9B,YAAY,QAAgB;AAC1B,SAAK,SAAS;AAAA,EAChB;AAAA,EAEQ,IAAI,OAAiB,SAAiB,MAAsC;AAClF,QAAI,CAAC,UAAU,KAAK,EAAG;AAEvB,UAAM,QAAkB;AAAA,MACtB,WAAW,SAAS,EAAE,UAAU;AAAA,MAChC;AAAA,MACA,QAAQ,KAAK;AAAA,MACb;AAAA,MACA;AAAA,IACF;AAGA,UAAM,MAAM,aAAa,GAAG,iBAAiB;AAC7C,QAAI,KAAK;AACP,YAAM,UAAU,IAAI;AACpB,YAAM,SAAS,IAAI;AAAA,IACrB;AAGA,QAAI,MAAM,iBAAiB,OAAO;AAChC,YAAM,QAAQ,KAAK;AAEnB,YAAM,EAAE,OAAO,GAAG,KAAK,IAAI;AAC3B,YAAM,OAAO,OAAO,KAAK,IAAI,EAAE,SAAS,IAAI,OAAO;AAAA,IACrD;AAEA,kBAAc,EAAE,KAAK;AAAA,EACvB;AAAA,EAEA,MAAM,SAAiB,MAAsC;AAC3D,SAAK,IAAI,SAAS,SAAS,IAAI;AAAA,EACjC;AAAA,EAEA,KAAK,SAAiB,MAAsC;AAC1D,SAAK,IAAI,QAAQ,SAAS,IAAI;AAAA,EAChC;AAAA,EAEA,KAAK,SAAiB,MAAsC;AAC1D,SAAK,IAAI,QAAQ,SAAS,IAAI;AAAA,EAChC;AAAA,EAEA,MAAM,SAAiB,MAAsC;AAC3D,SAAK,IAAI,SAAS,SAAS,IAAI;AAAA,EACjC;AAAA,EAEA,MAAM,SAAiB,MAAsC;AAC3D,SAAK,IAAI,SAAS,SAAS,IAAI;AAAA,EACjC;AAAA,EAEA,QAAQ,SAAiB,MAAsC;AAC7D,SAAK,IAAI,WAAW,SAAS,IAAI;AAAA,EACnC;AAAA,EAEA,MAAM,WAA4B;AAChC,WAAO,IAAI,QAAO,GAAG,KAAK,MAAM,IAAI,SAAS,EAAE;AAAA,EACjD;AACF;AAKA,IAAM,cAAc,oBAAI,IAAoB;AAcrC,SAAS,aAAa,QAAyB;AACpD,MAAI,SAAS,YAAY,IAAI,MAAM;AACnC,MAAI,CAAC,QAAQ;AACX,aAAS,IAAI,OAAO,MAAM;AAC1B,gBAAY,IAAI,QAAQ,MAAM;AAAA,EAChC;AACA,SAAO;AACT;AAKO,SAAS,mBAAyB;AACvC,cAAY,MAAM;AACpB;AAKO,IAAM,aAAsB;AAAA,EACjC,QAAQ;AAAA,EACR,OAAO,MAAM;AAAA,EAAC;AAAA,EACd,MAAM,MAAM;AAAA,EAAC;AAAA,EACb,MAAM,MAAM;AAAA,EAAC;AAAA,EACb,OAAO,MAAM;AAAA,EAAC;AAAA,EACd,OAAO,MAAM;AAAA,EAAC;AAAA,EACd,SAAS,MAAM;AAAA,EAAC;AAAA,EAChB,OAAO,MAAM;AACf;AAKO,SAAS,gBAAyB;AACvC,SAAO;AACT;;;AClNO,IAAM,aAAa;AAAA;AAAA;AAAA,EAGxB,iBAAiB;AAAA;AAAA,EAEjB,oBAAoB;AAAA;AAAA,EAEpB,aAAa;AAAA;AAAA,EAEb,SAAS;AAAA;AAAA,EAET,qBAAqB;AAAA;AAAA,EAErB,oBAAoB;AAAA;AAAA;AAAA,EAIpB,oBAAoB;AAAA;AAAA,EAEpB,kBAAkB;AAAA;AAAA,EAElB,mBAAmB;AAAA;AAAA;AAAA,EAInB,eAAe;AAAA;AAAA,EAEf,eAAe;AAAA;AAAA,EAEf,gBAAgB;AAAA;AAAA;AAAA,EAIhB,kBAAkB;AAAA;AAAA,EAElB,kBAAkB;AAAA;AAAA,EAElB,oBAAoB;AAAA;AAAA;AAAA,EAIpB,iBAAiB;AAAA;AAAA,EAEjB,WAAW;AAAA;AAAA;AAAA,EAIX,oBAAoB;AAAA;AAAA,EAEpB,cAAc;AAAA;AAAA,EAEd,WAAW;AAAA;AAAA;AAAA,EAIX,kBAAkB;AAAA;AAAA,EAElB,aAAa;AAAA;AAAA,EAEb,qBAAqB;AACvB;","names":["isBrowser"]}
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { EventEmitter, OmoteEvents } from './events/index.mjs';
2
2
  export { AnimationEvent, BackendEvent, EmotionEvent, GazeEvent, STTFinalEvent, STTPartialEvent, SessionStateEvent, TTSEndEvent, TTSMarkEvent, TTSStartEvent, VisemeEvent } from './events/index.mjs';
3
- export { D as DEFAULT_LOGGING_CONFIG, I as ILogger, a as LOG_LEVEL_PRIORITY, b as LogEntry, L as LogFormatter, c as LogLevel, d as LogSink, e as LoggingConfig, g as configureLogging, h as createLogger, i as getLoggingConfig, n as noopLogger, r as resetLoggingConfig, s as setLogLevel, k as setLoggingEnabled } from './Logger-BeUI6jG7.mjs';
3
+ export { C as Clock, D as DEFAULT_LOGGING_CONFIG, E as ErrorCode, a as ErrorCodes, I as ILogger, b as LOG_LEVEL_PRIORITY, c as LogEntry, L as LogFormatter, d as LogLevel, e as LogSink, f as LoggingConfig, h as configureClock, i as configureLogging, j as createLogger, l as getClock, m as getLoggingConfig, o as noopLogger, r as resetLoggingConfig, s as setLogLevel, p as setLoggingEnabled } from './ErrorCodes-AX3ADZri.mjs';
4
4
  export { ARKitToFLAMEMapping, ApiError, AudioChunkEvent, AvatarFormat, Character, CharacterAvatar, CharacterMemory, CharacterPersonality, CharacterSpec, CharacterVoice, CreateCharacterRequest, CreateCharacterResponse, CreateLAMJobRequest, CreateLAMJobResponse, CreateSessionRequest, CreateSessionResponse, GSplatConfig, LAMJob, LAMJobStatus, PROTOCOL_VERSION, PaginatedResponse, PlatformSession, ErrorEvent as ProtocolErrorEvent, ProtocolEvent, ResponseChunkEvent, ResponseEndEvent, ResponseStartEvent, SessionMessage, SessionStatus, isProtocolEvent } from '@omote/types';
5
5
 
6
6
  /**
@@ -163,6 +163,8 @@ interface AudioSchedulerOptions {
163
163
  * Default: 0.05 (50ms) for WebGPU, increase to 0.3-0.5 for WASM on iOS.
164
164
  */
165
165
  initialLookaheadSec?: number;
166
+ /** Error callback for critical scheduling issues */
167
+ onError?: (error: Error) => void;
166
168
  }
167
169
  declare class AudioScheduler {
168
170
  private readonly options;
@@ -964,6 +966,8 @@ declare class SenseVoiceInference {
964
966
  private inferenceQueue;
965
967
  private poisoned;
966
968
  private static readonly INFERENCE_TIMEOUT_MS;
969
+ private lastLfrFrames;
970
+ private webgpuShapeWarned;
967
971
  private tokenMap;
968
972
  private negMean;
969
973
  private invStddev;
@@ -1525,7 +1529,10 @@ interface FrameSource {
1525
1529
  blendshapes: Float32Array;
1526
1530
  emotion?: string;
1527
1531
  }) => void): void;
1528
- off?(event: 'frame', callback: (...args: any[]) => void): void;
1532
+ off?(event: 'frame', callback: (frame: {
1533
+ blendshapes: Float32Array;
1534
+ emotion?: string;
1535
+ }) => void): void;
1529
1536
  }
1530
1537
  type VoicePipelineState = 'idle' | 'loading' | 'ready' | 'listening' | 'thinking' | 'speaking' | 'error';
1531
1538
  interface LoadingProgress {
@@ -2036,6 +2043,7 @@ declare class SpeechListener extends EventEmitter<SpeechListenerEvents> {
2036
2043
  private lastProgressiveResult;
2037
2044
  private lastProgressiveSamples;
2038
2045
  private asrErrorCount;
2046
+ private progressiveErrorCount;
2039
2047
  /** Current listener state */
2040
2048
  get state(): SpeechListenerState;
2041
2049
  constructor(config?: SpeechListenerConfig);
@@ -3318,6 +3326,10 @@ declare const KOKORO_VOICES: {
3318
3326
  readonly bm_fable: "bm_fable";
3319
3327
  readonly bm_george: "bm_george";
3320
3328
  readonly bm_lewis: "bm_lewis";
3329
+ readonly ef_dora: "ef_dora";
3330
+ readonly em_alex: "em_alex";
3331
+ readonly em_santa: "em_santa";
3332
+ readonly ff_siwis: "ff_siwis";
3321
3333
  };
3322
3334
  type KokoroVoiceName = keyof typeof KOKORO_VOICES;
3323
3335
  /**
@@ -3325,6 +3337,198 @@ type KokoroVoiceName = keyof typeof KOKORO_VOICES;
3325
3337
  */
3326
3338
  declare function listVoices(): string[];
3327
3339
 
3340
+ /**
3341
+ * ElevenLabs TTS Backend — Cloud text-to-speech via ElevenLabs REST API.
3342
+ *
3343
+ * Implements the TTSBackend interface so it can be used anywhere Kokoro TTS is used
3344
+ * (TTSPlayback, TTSSpeaker, VoicePipeline, PlaybackPipeline, etc.)
3345
+ *
3346
+ * Zero external dependencies — uses fetch() directly.
3347
+ *
3348
+ * @category Inference
3349
+ *
3350
+ * @example Basic usage
3351
+ * ```typescript
3352
+ * import { ElevenLabsTTSBackend } from '@omote/core';
3353
+ *
3354
+ * const tts = new ElevenLabsTTSBackend({
3355
+ * apiKey: 'your-api-key',
3356
+ * voiceId: 'voice-id',
3357
+ * });
3358
+ * await tts.load();
3359
+ *
3360
+ * for await (const chunk of tts.stream("Hello world!")) {
3361
+ * playbackPipeline.feedBuffer(chunk.audio);
3362
+ * }
3363
+ * ```
3364
+ *
3365
+ * @example With PlaybackPipeline
3366
+ * ```typescript
3367
+ * const speaker = new TTSSpeaker();
3368
+ * await speaker.connect(tts, { lam: createA2E() });
3369
+ * await speaker.speak("Hello!");
3370
+ * ```
3371
+ */
3372
+
3373
+ interface ElevenLabsConfig {
3374
+ /** ElevenLabs API key */
3375
+ apiKey: string;
3376
+ /** Voice ID to use */
3377
+ voiceId: string;
3378
+ /** Model ID (default: 'eleven_multilingual_v2') */
3379
+ model?: string;
3380
+ /**
3381
+ * Output format (default: 'pcm_16000').
3382
+ * Use 'pcm_16000' for lip sync compatibility (16kHz matches A2E input).
3383
+ * Other options: 'pcm_22050', 'pcm_24000', 'pcm_44100'
3384
+ */
3385
+ outputFormat?: string;
3386
+ /** Voice stability 0-1 (default: 0.5) */
3387
+ stability?: number;
3388
+ /** Voice similarity boost 0-1 (default: 0.75) */
3389
+ similarityBoost?: number;
3390
+ /** API base URL override (default: 'https://api.elevenlabs.io') */
3391
+ baseUrl?: string;
3392
+ }
3393
+ declare class ElevenLabsTTSBackend implements TTSBackend {
3394
+ private readonly apiKey;
3395
+ private readonly voiceId;
3396
+ private readonly model;
3397
+ private readonly outputFormat;
3398
+ private readonly stability;
3399
+ private readonly similarityBoost;
3400
+ private readonly baseUrl;
3401
+ private readonly _sampleRate;
3402
+ private _isLoaded;
3403
+ constructor(config: ElevenLabsConfig);
3404
+ get sampleRate(): number;
3405
+ get isLoaded(): boolean;
3406
+ /**
3407
+ * No-op for cloud TTS (no model to load).
3408
+ * Marks backend as ready.
3409
+ */
3410
+ load(): Promise<void>;
3411
+ /**
3412
+ * Stream audio from ElevenLabs for the given text.
3413
+ *
3414
+ * Uses the streaming endpoint. Yields a single chunk for non-streaming
3415
+ * or multiple chunks as response data arrives.
3416
+ */
3417
+ stream(text: string, options?: TTSStreamOptions): AsyncGenerator<TTSChunk>;
3418
+ dispose(): Promise<void>;
3419
+ private getHttpErrorMessage;
3420
+ }
3421
+
3422
+ /**
3423
+ * AWS Polly TTS Backend — Cloud text-to-speech via consumer-provided AWS SDK call.
3424
+ *
3425
+ * Implements the TTSBackend interface. Keeps @omote/core free of AWS SDK dependencies
3426
+ * by delegating the actual Polly API call to a consumer-provided function.
3427
+ *
3428
+ * @category Inference
3429
+ *
3430
+ * @example Basic usage with AWS SDK v3
3431
+ * ```typescript
3432
+ * import { PollyTTSBackend } from '@omote/core';
3433
+ * import { PollyClient, SynthesizeSpeechCommand } from '@aws-sdk/client-polly';
3434
+ *
3435
+ * const polly = new PollyClient({ region: 'us-east-1' });
3436
+ *
3437
+ * const tts = new PollyTTSBackend({
3438
+ * synthesizeFn: async (text, voice, sampleRate) => {
3439
+ * const cmd = new SynthesizeSpeechCommand({
3440
+ * Text: text,
3441
+ * VoiceId: voice,
3442
+ * Engine: 'neural',
3443
+ * OutputFormat: 'pcm',
3444
+ * SampleRate: String(sampleRate),
3445
+ * });
3446
+ * const result = await polly.send(cmd);
3447
+ * const stream = result.AudioStream;
3448
+ * // Convert stream to ArrayBuffer (Node or browser)
3449
+ * const chunks: Uint8Array[] = [];
3450
+ * for await (const chunk of stream as AsyncIterable<Uint8Array>) {
3451
+ * chunks.push(chunk);
3452
+ * }
3453
+ * const totalLength = chunks.reduce((sum, c) => sum + c.length, 0);
3454
+ * const merged = new Uint8Array(totalLength);
3455
+ * let offset = 0;
3456
+ * for (const chunk of chunks) {
3457
+ * merged.set(chunk, offset);
3458
+ * offset += chunk.length;
3459
+ * }
3460
+ * return {
3461
+ * audio: merged.buffer,
3462
+ * contentType: result.ContentType ?? 'audio/pcm',
3463
+ * };
3464
+ * },
3465
+ * });
3466
+ *
3467
+ * await tts.load();
3468
+ * for await (const chunk of tts.stream("Hello world!")) {
3469
+ * playbackPipeline.feedBuffer(chunk.audio);
3470
+ * }
3471
+ * ```
3472
+ */
3473
+
3474
+ /**
3475
+ * Result from the consumer-provided synthesize function.
3476
+ */
3477
+ interface PollySynthesizeResult {
3478
+ /** Raw PCM audio bytes (Int16 LE) */
3479
+ audio: ArrayBuffer;
3480
+ /** Content type from Polly response (e.g., 'audio/pcm') */
3481
+ contentType: string;
3482
+ }
3483
+ /**
3484
+ * Configuration for PollyTTSBackend.
3485
+ *
3486
+ * The `synthesizeFn` callback lets consumers use their own AWS SDK setup
3487
+ * (credentials, region, SDK version) without @omote/core depending on `@aws-sdk/client-polly`.
3488
+ */
3489
+ interface PollyConfig {
3490
+ /**
3491
+ * Consumer-provided function that calls AWS Polly.
3492
+ * Must return PCM audio (Int16 LE) at the requested sample rate.
3493
+ *
3494
+ * @param text - Text to synthesize
3495
+ * @param voice - Polly voice ID (e.g., 'Joanna')
3496
+ * @param sampleRate - Requested output sample rate (e.g., 16000)
3497
+ * @returns PCM audio buffer and content type
3498
+ */
3499
+ synthesizeFn: (text: string, voice: string, sampleRate: number) => Promise<PollySynthesizeResult>;
3500
+ /** Polly voice ID (default: 'Joanna') */
3501
+ voice?: string;
3502
+ /** Output sample rate in Hz (default: 16000) */
3503
+ sampleRate?: number;
3504
+ /** Polly engine type (default: 'neural') */
3505
+ engine?: 'neural' | 'standard' | 'generative' | 'long-form';
3506
+ }
3507
+ declare class PollyTTSBackend implements TTSBackend {
3508
+ private readonly synthesizeFn;
3509
+ private readonly voice;
3510
+ private readonly _sampleRate;
3511
+ private readonly engine;
3512
+ private _isLoaded;
3513
+ constructor(config: PollyConfig);
3514
+ get sampleRate(): number;
3515
+ get isLoaded(): boolean;
3516
+ /**
3517
+ * No-op for cloud TTS (no model to load).
3518
+ * Marks backend as ready.
3519
+ */
3520
+ load(): Promise<void>;
3521
+ /**
3522
+ * Synthesize audio via consumer's Polly function.
3523
+ *
3524
+ * Polly's SynthesizeSpeech is request/response (not streaming for PCM),
3525
+ * so this yields a single chunk per call. For long text, consider splitting
3526
+ * into sentences on the consumer side.
3527
+ */
3528
+ stream(text: string, options?: TTSStreamOptions): AsyncGenerator<TTSChunk>;
3529
+ dispose(): Promise<void>;
3530
+ }
3531
+
3328
3532
  /**
3329
3533
  * ORT CDN configuration
3330
3534
  *
@@ -3889,6 +4093,12 @@ declare const MetricNames: {
3889
4093
  readonly CACHE_HITS: "omote.cache.hits";
3890
4094
  /** Counter: Cache misses */
3891
4095
  readonly CACHE_MISSES: "omote.cache.misses";
4096
+ /** Counter: Cache stale (version/etag mismatch) */
4097
+ readonly CACHE_STALE: "omote.cache.stale";
4098
+ /** Counter: Cache quota warning (>90% used) */
4099
+ readonly CACHE_QUOTA_WARNING: "omote.cache.quota_warning";
4100
+ /** Counter: Cache eviction (LRU) */
4101
+ readonly CACHE_EVICTION: "omote.cache.eviction";
3892
4102
  /** Histogram: VoicePipeline turn latency (speech end → transcript ready, excludes playback) */
3893
4103
  readonly VOICE_TURN_LATENCY: "omote.voice.turn.latency";
3894
4104
  /** Histogram: ASR transcription latency in ms */
@@ -5517,6 +5727,7 @@ declare class VoicePipeline extends EventEmitter<VoicePipelineEvents> {
5517
5727
  private lastProgressiveResult;
5518
5728
  private lastProgressiveSamples;
5519
5729
  private asrErrorCount;
5730
+ private progressiveErrorCount;
5520
5731
  private responseAbortController;
5521
5732
  private _unsubChunk;
5522
5733
  private _unsubLevel;
@@ -5645,4 +5856,4 @@ declare class VoiceOrchestrator extends EventEmitter<VoiceOrchestratorEvents> {
5645
5856
  private setState;
5646
5857
  }
5647
5858
 
5648
- export { type A2EBackend, A2EInference, type A2EInferenceConfig, type A2EModelInfo, A2EProcessor, type A2EProcessorConfig, type A2EResult, A2EUnifiedAdapter, ALL_AUS, ARKIT_BLENDSHAPES, type AUActivation, AU_TO_ARKIT, type ActiveSpan, type AnimationClip, type AnimationController, AnimationGraph, type AnimationGraphConfig, type AnimationGraphEvents, type AnimationLayer, type AnimationOutput, type AnimationSource, type AnimationSourceOptions, type AnimationState, type AnimationStateName, type AnimationTrigger, AudioChunkCoalescer, type AudioChunkCoalescerOptions, AudioEnergyAnalyzer, AudioScheduler, type AudioSchedulerOptions, BLENDSHAPE_TO_GROUP, type BackendPreference, type BlendWeight, type BlendshapeGroup, BlendshapeSmoother, type BlendshapeSmootherConfig, type BoneFilterConfig, type CacheConfig, type CacheSpanAttributes, CharacterController, type CharacterControllerConfig, type CharacterProfile, type CharacterUpdateInput, type CharacterUpdateOutput, ConsoleExporter, type ConversationalState, type CreateA2EConfig, type CreateKokoroTTSConfig, type CreateSenseVoiceConfig, type CreateTTSPlayerConfig, DEFAULT_ANIMATION_CONFIG, DEFAULT_BONE_FILTER, DEFAULT_MODEL_URLS, EMOTION_NAMES, EMOTION_TO_AU, EMOTION_VECTOR_SIZE, EXPLICIT_EMOTION_COUNT, type EmotionAnimationMap, EmotionController, type EmotionLabel, type EmotionName, type EmotionPresetName, EmotionPresets, EmotionResolver, type EmotionWeights, EmphasisDetector, type ErrorType, ErrorTypes, EventEmitter, type ExpressionProfile, FaceCompositor, type FaceCompositorConfig, type FaceCompositorInput, type FaceCompositorOutput, type FetchWithCacheOptions, type FrameSource, type FullFaceFrame, HF_CDN_URLS, INFERENCE_LATENCY_BUCKETS, type InferenceFactoryConfig, type InferenceSpanAttributes, type InterruptionConfig, type InterruptionEvents, InterruptionHandler, KOKORO_VOICES, type KokoroStreamChunk, type KokoroTTSConfig, KokoroTTSInference, type KokoroTTSModelInfo, type KokoroTTSResult, KokoroTTSUnifiedAdapter, KokoroTTSWorker, type KokoroVoiceName, LAM_BLENDSHAPES, type LifeLayerConfig, type LifeLayerInput, type LifeLayerOutput, type LoadingProgress, MIXAMO_PREFIX, MODEL_LOAD_TIME_BUCKETS, type MetricData, MetricNames, MicLipSync, type MicLipSyncConfig, type MicLipSyncEvents, type MicLipSyncFrame, type MicLipSyncState, MicrophoneCapture, type MicrophoneCaptureConfig, ModelCache, type ModelSpanAttributes, type ModelUrlKey, OTLPExporter, type OTLPExporterConfig, OmoteEvents, OmoteTelemetry, PRESERVE_POSITION_BONES, PlaybackPipeline, type PlaybackPipelineConfig, type PlaybackPipelineEvents, type PlaybackState, ProceduralLifeLayer, type Quat, type QuotaInfo, type ResolvedEmotion, type ResponseHandler, RingBuffer, type RuntimeBackend, type SafariSpeechConfig, SafariSpeechRecognition, type SamplingConfig, type SenseVoiceBackend, type SenseVoiceConfig, SenseVoiceInference, type SenseVoiceLanguage, type SenseVoiceModelInfo, type SenseVoiceResult, SenseVoiceUnifiedAdapter, SenseVoiceWorker, type SenseVoiceWorkerConfig, type SileroVADBackend, type SileroVADConfig, type SileroVADFactoryConfig, SileroVADInference, SileroVADUnifiedAdapter, SileroVADWorker, type SpanAttributes, type SpanData, type SpeechErrorCallback, SpeechListener, type SpeechListenerConfig, type SpeechListenerEvents, type SpeechListenerState, type SpeechRecognitionResult, type SpeechResultCallback, type SpeechSegment, type SynthesizeOptions, type TTSBackend, type TTSChunk, TTSPlayback, type TTSPlaybackConfig, type TTSPlaybackEvents, TTSPlayer, TTSSpeaker, type TTSSpeakerConfig, type TTSStreamOptions, type TelemetryConfig, type TelemetryExporter, type TelemetryExporterInterface, type TrackDescriptor, type TranscriptResult, type Transition, UnifiedInferenceWorker, type VADBackend, type VADModelInfo, type VADResult, type VADWorkerConfig, type VADWorkerModelInfo, type ValidationResult, type Vec3, VoiceOrchestrator, type VoiceOrchestratorCloudConfig, type VoiceOrchestratorConfig, type VoiceOrchestratorEvents, type VoiceOrchestratorLocalConfig, VoicePipeline, type VoicePipelineCloudConfig, type VoicePipelineConfig, type VoicePipelineEvents, type VoicePipelineLocalConfig, type VoicePipelineState, A2EInference as Wav2Vec2Inference, type WorkerHealthState, analyzeTextEmotion, applyProfile, blendEmotions, calculatePeak, calculateRMS, configureCacheLimit, configureModelUrls, configureOrtCdn, configureTelemetry, createA2E, createEmotionVector, createKokoroTTS, createSenseVoice, createSileroVAD, createTTSPlayer, fetchWithCache, float32ToPcm16, formatBytes, getCacheConfig, getCacheKey, getEmotionPreset, getModelCache, getOptimalWasmThreads, getOrtCdnBase, getRecommendedBackend, getTelemetry, hasWebGPUApi, int16ToFloat32, isAndroid, isIOS, isIOSSafari, isMobile, isSafari, isSpeechRecognitionAvailable, isWebGPUAvailable, lerpBlendshapes, lerpEmotion, listVoices as listKokoroVoices, parseEmotionTags, pcm16ToFloat32, preloadModels, resampleLinear, resetModelUrls, resolveBackend, resolveEmotion, shouldEnableWasmProxy, shouldKeepTrack, shouldUseNativeASR, shouldUseServerA2E, stripMixamoPrefix, supportsVADWorker, ttsToPlaybackFormat, validateTTSInput };
5859
+ export { type A2EBackend, A2EInference, type A2EInferenceConfig, type A2EModelInfo, A2EProcessor, type A2EProcessorConfig, type A2EResult, A2EUnifiedAdapter, ALL_AUS, ARKIT_BLENDSHAPES, type AUActivation, AU_TO_ARKIT, type ActiveSpan, type AnimationClip, type AnimationController, AnimationGraph, type AnimationGraphConfig, type AnimationGraphEvents, type AnimationLayer, type AnimationOutput, type AnimationSource, type AnimationSourceOptions, type AnimationState, type AnimationStateName, type AnimationTrigger, AudioChunkCoalescer, type AudioChunkCoalescerOptions, AudioEnergyAnalyzer, AudioScheduler, type AudioSchedulerOptions, BLENDSHAPE_TO_GROUP, type BackendPreference, type BlendWeight, type BlendshapeGroup, BlendshapeSmoother, type BlendshapeSmootherConfig, type BoneFilterConfig, type CacheConfig, type CacheSpanAttributes, CharacterController, type CharacterControllerConfig, type CharacterProfile, type CharacterUpdateInput, type CharacterUpdateOutput, ConsoleExporter, type ConversationalState, type CreateA2EConfig, type CreateKokoroTTSConfig, type CreateSenseVoiceConfig, type CreateTTSPlayerConfig, DEFAULT_ANIMATION_CONFIG, DEFAULT_BONE_FILTER, DEFAULT_MODEL_URLS, EMOTION_NAMES, EMOTION_TO_AU, EMOTION_VECTOR_SIZE, EXPLICIT_EMOTION_COUNT, type ElevenLabsConfig, ElevenLabsTTSBackend, type EmotionAnimationMap, EmotionController, type EmotionLabel, type EmotionName, type EmotionPresetName, EmotionPresets, EmotionResolver, type EmotionWeights, EmphasisDetector, type ErrorType, ErrorTypes, EventEmitter, type ExpressionProfile, FaceCompositor, type FaceCompositorConfig, type FaceCompositorInput, type FaceCompositorOutput, type FetchWithCacheOptions, type FrameSource, type FullFaceFrame, HF_CDN_URLS, INFERENCE_LATENCY_BUCKETS, type InferenceFactoryConfig, type InferenceSpanAttributes, type InterruptionConfig, type InterruptionEvents, InterruptionHandler, KOKORO_VOICES, type KokoroStreamChunk, type KokoroTTSConfig, KokoroTTSInference, type KokoroTTSModelInfo, type KokoroTTSResult, KokoroTTSUnifiedAdapter, KokoroTTSWorker, type KokoroVoiceName, LAM_BLENDSHAPES, type LifeLayerConfig, type LifeLayerInput, type LifeLayerOutput, type LoadingProgress, MIXAMO_PREFIX, MODEL_LOAD_TIME_BUCKETS, type MetricData, MetricNames, MicLipSync, type MicLipSyncConfig, type MicLipSyncEvents, type MicLipSyncFrame, type MicLipSyncState, MicrophoneCapture, type MicrophoneCaptureConfig, ModelCache, type ModelSpanAttributes, type ModelUrlKey, OTLPExporter, type OTLPExporterConfig, OmoteEvents, OmoteTelemetry, PRESERVE_POSITION_BONES, PlaybackPipeline, type PlaybackPipelineConfig, type PlaybackPipelineEvents, type PlaybackState, type PollyConfig, type PollySynthesizeResult, PollyTTSBackend, ProceduralLifeLayer, type Quat, type QuotaInfo, type ResolvedEmotion, type ResponseHandler, RingBuffer, type RuntimeBackend, type SafariSpeechConfig, SafariSpeechRecognition, type SamplingConfig, type SenseVoiceBackend, type SenseVoiceConfig, SenseVoiceInference, type SenseVoiceLanguage, type SenseVoiceModelInfo, type SenseVoiceResult, SenseVoiceUnifiedAdapter, SenseVoiceWorker, type SenseVoiceWorkerConfig, type SileroVADBackend, type SileroVADConfig, type SileroVADFactoryConfig, SileroVADInference, SileroVADUnifiedAdapter, SileroVADWorker, type SpanAttributes, type SpanData, type SpeechErrorCallback, SpeechListener, type SpeechListenerConfig, type SpeechListenerEvents, type SpeechListenerState, type SpeechRecognitionResult, type SpeechResultCallback, type SpeechSegment, type SynthesizeOptions, type TTSBackend, type TTSChunk, TTSPlayback, type TTSPlaybackConfig, type TTSPlaybackEvents, TTSPlayer, TTSSpeaker, type TTSSpeakerConfig, type TTSStreamOptions, type TelemetryConfig, type TelemetryExporter, type TelemetryExporterInterface, type TrackDescriptor, type TranscriptResult, type Transition, UnifiedInferenceWorker, type VADBackend, type VADModelInfo, type VADResult, type VADWorkerConfig, type VADWorkerModelInfo, type ValidationResult, type Vec3, VoiceOrchestrator, type VoiceOrchestratorCloudConfig, type VoiceOrchestratorConfig, type VoiceOrchestratorEvents, type VoiceOrchestratorLocalConfig, VoicePipeline, type VoicePipelineCloudConfig, type VoicePipelineConfig, type VoicePipelineEvents, type VoicePipelineLocalConfig, type VoicePipelineState, A2EInference as Wav2Vec2Inference, type WorkerHealthState, analyzeTextEmotion, applyProfile, blendEmotions, calculatePeak, calculateRMS, configureCacheLimit, configureModelUrls, configureOrtCdn, configureTelemetry, createA2E, createEmotionVector, createKokoroTTS, createSenseVoice, createSileroVAD, createTTSPlayer, fetchWithCache, float32ToPcm16, formatBytes, getCacheConfig, getCacheKey, getEmotionPreset, getModelCache, getOptimalWasmThreads, getOrtCdnBase, getRecommendedBackend, getTelemetry, hasWebGPUApi, int16ToFloat32, isAndroid, isIOS, isIOSSafari, isMobile, isSafari, isSpeechRecognitionAvailable, isWebGPUAvailable, lerpBlendshapes, lerpEmotion, listVoices as listKokoroVoices, parseEmotionTags, pcm16ToFloat32, preloadModels, resampleLinear, resetModelUrls, resolveBackend, resolveEmotion, shouldEnableWasmProxy, shouldKeepTrack, shouldUseNativeASR, shouldUseServerA2E, stripMixamoPrefix, supportsVADWorker, ttsToPlaybackFormat, validateTTSInput };