@omote/core 0.10.5 → 0.10.6

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,782 @@
1
+ // src/logging/types.ts
2
+ var LOG_LEVEL_PRIORITY = {
3
+ error: 0,
4
+ warn: 1,
5
+ info: 2,
6
+ debug: 3,
7
+ trace: 4,
8
+ verbose: 5
9
+ };
10
+ var DEFAULT_LOGGING_CONFIG = {
11
+ level: "info",
12
+ enabled: true,
13
+ format: "pretty",
14
+ timestamps: true,
15
+ includeModule: true
16
+ };
17
+
18
+ // src/logging/formatters.ts
19
+ var COLORS = {
20
+ reset: "\x1B[0m",
21
+ red: "\x1B[31m",
22
+ yellow: "\x1B[33m",
23
+ blue: "\x1B[34m",
24
+ cyan: "\x1B[36m",
25
+ gray: "\x1B[90m",
26
+ white: "\x1B[37m",
27
+ magenta: "\x1B[35m"
28
+ };
29
+ var LEVEL_COLORS = {
30
+ error: COLORS.red,
31
+ warn: COLORS.yellow,
32
+ info: COLORS.blue,
33
+ debug: COLORS.cyan,
34
+ trace: COLORS.magenta,
35
+ verbose: COLORS.gray
36
+ };
37
+ var LEVEL_NAMES = {
38
+ error: "ERROR ",
39
+ warn: "WARN ",
40
+ info: "INFO ",
41
+ debug: "DEBUG ",
42
+ trace: "TRACE ",
43
+ verbose: "VERBOSE"
44
+ };
45
+ var isBrowser = typeof window !== "undefined";
46
+ function formatTimestamp(timestamp) {
47
+ const date = new Date(timestamp);
48
+ return date.toISOString().substring(11, 23);
49
+ }
50
+ function safeStringify(data) {
51
+ const seen = /* @__PURE__ */ new WeakSet();
52
+ return JSON.stringify(data, (key, value) => {
53
+ if (typeof value === "object" && value !== null) {
54
+ if (seen.has(value)) {
55
+ return "[Circular]";
56
+ }
57
+ seen.add(value);
58
+ }
59
+ if (value instanceof Error) {
60
+ return {
61
+ name: value.name,
62
+ message: value.message,
63
+ stack: value.stack
64
+ };
65
+ }
66
+ if (value instanceof Float32Array || value instanceof Int16Array) {
67
+ return `${value.constructor.name}(${value.length})`;
68
+ }
69
+ if (ArrayBuffer.isView(value)) {
70
+ return `${value.constructor.name}(${value.byteLength})`;
71
+ }
72
+ return value;
73
+ });
74
+ }
75
+ var jsonFormatter = (entry) => {
76
+ const output = {
77
+ timestamp: entry.timestamp,
78
+ level: entry.level,
79
+ module: entry.module,
80
+ message: entry.message
81
+ };
82
+ if (entry.data && Object.keys(entry.data).length > 0) {
83
+ output.data = entry.data;
84
+ }
85
+ if (entry.traceId) output.traceId = entry.traceId;
86
+ if (entry.spanId) output.spanId = entry.spanId;
87
+ if (entry.error) {
88
+ output.error = {
89
+ name: entry.error.name,
90
+ message: entry.error.message,
91
+ stack: entry.error.stack
92
+ };
93
+ }
94
+ return safeStringify(output);
95
+ };
96
+ var prettyFormatter = (entry) => {
97
+ const time = formatTimestamp(entry.timestamp);
98
+ const level = LEVEL_NAMES[entry.level];
99
+ const module = entry.module;
100
+ const message = entry.message;
101
+ let output;
102
+ if (isBrowser) {
103
+ output = `${time} ${level} [${module}] ${message}`;
104
+ } else {
105
+ const color = LEVEL_COLORS[entry.level];
106
+ output = `${COLORS.gray}${time}${COLORS.reset} ${color}${level}${COLORS.reset} ${COLORS.cyan}[${module}]${COLORS.reset} ${message}`;
107
+ }
108
+ if (entry.traceId) {
109
+ output += ` [trace:${entry.traceId.slice(0, 8)}]`;
110
+ }
111
+ if (entry.data && Object.keys(entry.data).length > 0) {
112
+ const dataStr = safeStringify(entry.data);
113
+ if (dataStr.length > 80) {
114
+ output += "\n " + JSON.stringify(entry.data, null, 2).replace(/\n/g, "\n ");
115
+ } else {
116
+ output += " " + dataStr;
117
+ }
118
+ }
119
+ if (entry.error) {
120
+ output += `
121
+ ${entry.error.name}: ${entry.error.message}`;
122
+ if (entry.error.stack) {
123
+ const stackLines = entry.error.stack.split("\n").slice(1, 4);
124
+ output += "\n " + stackLines.join("\n ");
125
+ }
126
+ }
127
+ return output;
128
+ };
129
+ function getFormatter(format) {
130
+ return format === "json" ? jsonFormatter : prettyFormatter;
131
+ }
132
+ function createBrowserConsoleArgs(entry) {
133
+ const time = formatTimestamp(entry.timestamp);
134
+ const level = entry.level.toUpperCase().padEnd(7);
135
+ const module = entry.module;
136
+ const message = entry.message;
137
+ const styles = {
138
+ time: "color: gray;",
139
+ error: "color: red; font-weight: bold;",
140
+ warn: "color: orange; font-weight: bold;",
141
+ info: "color: blue;",
142
+ debug: "color: cyan;",
143
+ trace: "color: magenta;",
144
+ verbose: "color: gray;",
145
+ module: "color: teal; font-weight: bold;",
146
+ message: "color: inherit;"
147
+ };
148
+ let formatStr = "%c%s %c%s %c[%s]%c %s";
149
+ const args = [
150
+ styles.time,
151
+ time,
152
+ styles[entry.level],
153
+ level,
154
+ styles.module,
155
+ module,
156
+ styles.message,
157
+ message
158
+ ];
159
+ if (entry.data && Object.keys(entry.data).length > 0) {
160
+ formatStr += " %o";
161
+ args.push(entry.data);
162
+ }
163
+ return [formatStr, ...args];
164
+ }
165
+
166
+ // src/telemetry/exporters/console.ts
167
+ var ConsoleExporter = class {
168
+ constructor(options = {}) {
169
+ this.enabled = options.enabled ?? true;
170
+ this.prefix = options.prefix ?? "[Omote Telemetry]";
171
+ }
172
+ exportSpan(span) {
173
+ if (!this.enabled) return;
174
+ const statusIcon = span.status === "ok" ? "\u2713" : "\u2717";
175
+ const statusColor = span.status === "ok" ? "color: green" : "color: red";
176
+ console.groupCollapsed(
177
+ `%c${this.prefix} %c${statusIcon} ${span.name} %c(${span.durationMs.toFixed(2)}ms)`,
178
+ "color: gray",
179
+ statusColor,
180
+ "color: gray"
181
+ );
182
+ console.log("Trace ID:", span.traceId);
183
+ console.log("Span ID:", span.spanId);
184
+ if (span.parentSpanId) {
185
+ console.log("Parent Span ID:", span.parentSpanId);
186
+ }
187
+ console.log("Duration:", `${span.durationMs.toFixed(2)}ms`);
188
+ console.log("Status:", span.status);
189
+ if (Object.keys(span.attributes).length > 0) {
190
+ console.log("Attributes:", span.attributes);
191
+ }
192
+ if (span.error) {
193
+ console.error("Error:", span.error);
194
+ }
195
+ console.groupEnd();
196
+ }
197
+ exportMetric(metric) {
198
+ if (!this.enabled) return;
199
+ const typeIcon = metric.type === "counter" ? "\u2191" : "\u{1F4CA}";
200
+ console.log(
201
+ `%c${this.prefix} %c${typeIcon} ${metric.name}: %c${metric.value}`,
202
+ "color: gray",
203
+ "color: blue",
204
+ "color: black; font-weight: bold",
205
+ metric.attributes
206
+ );
207
+ }
208
+ async flush() {
209
+ }
210
+ async shutdown() {
211
+ this.enabled = false;
212
+ }
213
+ };
214
+
215
+ // src/logging/Clock.ts
216
+ var defaultClock = {
217
+ now: () => performance.now(),
218
+ timestamp: () => Date.now()
219
+ };
220
+ var activeClock = defaultClock;
221
+ function configureClock(clock) {
222
+ activeClock = clock;
223
+ }
224
+ function getClock() {
225
+ return activeClock;
226
+ }
227
+
228
+ // src/telemetry/OmoteTelemetry.ts
229
+ var DEFAULT_HISTOGRAM_BUCKETS = [1, 5, 10, 25, 50, 100, 250, 500, 1e3, 2500, 5e3, 1e4, 3e4, 6e4];
230
+ function generateId(length = 16) {
231
+ const bytes = new Uint8Array(length);
232
+ crypto.getRandomValues(bytes);
233
+ return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
234
+ }
235
+ var globalTelemetry = null;
236
+ function configureTelemetry(config) {
237
+ if (globalTelemetry) {
238
+ globalTelemetry.shutdown();
239
+ }
240
+ globalTelemetry = new OmoteTelemetry(config);
241
+ return globalTelemetry;
242
+ }
243
+ function getTelemetry() {
244
+ return globalTelemetry;
245
+ }
246
+ var OmoteTelemetry = class {
247
+ constructor(config) {
248
+ this.exporter = null;
249
+ this.exporterReady = null;
250
+ this.activeTraceId = null;
251
+ this.metricsIntervalId = null;
252
+ // Span stack for log-to-span correlation
253
+ this.spanStack = [];
254
+ // Metric accumulators
255
+ this.counters = /* @__PURE__ */ new Map();
256
+ this.histograms = /* @__PURE__ */ new Map();
257
+ this.config = {
258
+ enabled: config.enabled ?? false,
259
+ serviceName: config.serviceName ?? "omote-sdk",
260
+ serviceVersion: config.serviceVersion ?? "0.1.0",
261
+ exporter: config.exporter ?? "none",
262
+ exporterConfig: config.exporterConfig,
263
+ sampling: config.sampling ?? { ratio: 1, alwaysSampleErrors: true },
264
+ metricsEnabled: config.metricsEnabled ?? true,
265
+ metricsIntervalMs: config.metricsIntervalMs ?? 6e4
266
+ };
267
+ if (this.config.enabled) {
268
+ if (config.customExporter) {
269
+ this.exporter = config.customExporter;
270
+ this.startMetricsCollection();
271
+ } else {
272
+ this.exporterReady = this.initExporter();
273
+ }
274
+ }
275
+ }
276
+ /**
277
+ * Initialize the configured exporter
278
+ */
279
+ async initExporter() {
280
+ switch (this.config.exporter) {
281
+ case "console":
282
+ this.exporter = new ConsoleExporter({ enabled: true });
283
+ break;
284
+ case "otlp":
285
+ if (!this.config.exporterConfig) {
286
+ console.warn("[Telemetry] OTLP exporter requires exporterConfig with endpoint");
287
+ return;
288
+ }
289
+ {
290
+ const { OTLPExporter } = await import("./otlp-2BML6FIK.mjs");
291
+ this.exporter = new OTLPExporter(
292
+ this.config.exporterConfig,
293
+ this.config.serviceName,
294
+ this.config.serviceVersion
295
+ );
296
+ }
297
+ break;
298
+ case "none":
299
+ default:
300
+ this.exporter = null;
301
+ }
302
+ this.startMetricsCollection();
303
+ }
304
+ /**
305
+ * Start periodic metrics collection
306
+ */
307
+ startMetricsCollection() {
308
+ if (!this.config.metricsEnabled || !this.exporter) return;
309
+ this.metricsIntervalId = setInterval(() => {
310
+ this.flushMetrics();
311
+ }, this.config.metricsIntervalMs);
312
+ }
313
+ /**
314
+ * Check if this operation should be sampled
315
+ */
316
+ shouldSample(isError = false) {
317
+ if (!this.config.enabled) return false;
318
+ const sampling = this.config.sampling;
319
+ if (isError && sampling.alwaysSampleErrors) return true;
320
+ const ratio = sampling.ratio ?? 1;
321
+ return Math.random() < ratio;
322
+ }
323
+ /**
324
+ * Start a new span
325
+ *
326
+ * @example
327
+ * ```typescript
328
+ * const span = telemetry.startSpan('Wav2Vec2.infer', {
329
+ * 'inference.input_samples': samples.length,
330
+ * 'model.backend': 'webgpu',
331
+ * });
332
+ *
333
+ * try {
334
+ * const result = await doInference();
335
+ * span.setAttributes({ 'inference.output_frames': result.frames });
336
+ * span.end();
337
+ * } catch (error) {
338
+ * span.endWithError(error);
339
+ * }
340
+ * ```
341
+ */
342
+ startSpan(name, attributes = {}, parentContext) {
343
+ const traceId = parentContext?.traceId ?? this.activeTraceId ?? generateId(16);
344
+ const spanId = generateId(8);
345
+ const parentSpanId = parentContext?.spanId;
346
+ const startTime = getClock().now();
347
+ const epochMs = Date.now();
348
+ if (!parentContext && !this.activeTraceId) {
349
+ this.activeTraceId = traceId;
350
+ }
351
+ let spanAttributes = { ...attributes };
352
+ let ended = false;
353
+ let sampled = this.shouldSample();
354
+ const context = { traceId, spanId, parentSpanId };
355
+ this.spanStack.push({ traceId, spanId });
356
+ const endSpan = (status, error) => {
357
+ if (ended) return;
358
+ ended = true;
359
+ const idx = this.spanStack.findIndex((s) => s.spanId === spanId);
360
+ if (idx !== -1) this.spanStack.splice(idx, 1);
361
+ const endTime = getClock().now();
362
+ const durationMs = endTime - startTime;
363
+ const endEpochMs = epochMs + (endTime - startTime);
364
+ if (status === "error" && !sampled) {
365
+ sampled = this.shouldSample(true);
366
+ }
367
+ if (!sampled || !this.exporter) return;
368
+ const spanData = {
369
+ name,
370
+ traceId,
371
+ spanId,
372
+ parentSpanId,
373
+ startTime,
374
+ endTime,
375
+ durationMs,
376
+ epochMs,
377
+ endEpochMs,
378
+ status,
379
+ attributes: spanAttributes,
380
+ error
381
+ };
382
+ this.exporter.exportSpan(spanData);
383
+ if (!parentSpanId && this.activeTraceId === traceId) {
384
+ this.activeTraceId = null;
385
+ }
386
+ };
387
+ return {
388
+ end: () => endSpan("ok"),
389
+ endWithError: (error) => endSpan("error", error),
390
+ setAttributes: (attrs) => {
391
+ spanAttributes = { ...spanAttributes, ...attrs };
392
+ },
393
+ getContext: () => context
394
+ };
395
+ }
396
+ /**
397
+ * Wrap an async function with a span
398
+ *
399
+ * @example
400
+ * ```typescript
401
+ * const result = await telemetry.withSpan('Model.load', async (span) => {
402
+ * const model = await loadModel();
403
+ * span.setAttributes({ 'model.size_bytes': model.size });
404
+ * return model;
405
+ * });
406
+ * ```
407
+ */
408
+ async withSpan(name, fn, attributes = {}, parentContext) {
409
+ const span = this.startSpan(name, attributes, parentContext);
410
+ try {
411
+ const result = await fn(span);
412
+ span.end();
413
+ return result;
414
+ } catch (error) {
415
+ span.endWithError(error);
416
+ throw error;
417
+ }
418
+ }
419
+ /**
420
+ * Increment a counter metric
421
+ *
422
+ * @example
423
+ * ```typescript
424
+ * telemetry.incrementCounter('omote.inference.total', 1, {
425
+ * model: 'wav2vec2',
426
+ * backend: 'webgpu',
427
+ * status: 'success',
428
+ * });
429
+ * ```
430
+ */
431
+ incrementCounter(name, value = 1, attributes = {}) {
432
+ if (!this.config.enabled || !this.config.metricsEnabled) return;
433
+ const key = this.getMetricKey(name, attributes);
434
+ const existing = this.counters.get(key);
435
+ if (existing) {
436
+ existing.value += value;
437
+ } else {
438
+ this.counters.set(key, { value, attributes });
439
+ }
440
+ }
441
+ /**
442
+ * Record a histogram value
443
+ *
444
+ * @example
445
+ * ```typescript
446
+ * telemetry.recordHistogram('omote.inference.latency', durationMs, {
447
+ * model: 'wav2vec2',
448
+ * backend: 'webgpu',
449
+ * });
450
+ * ```
451
+ */
452
+ recordHistogram(name, value, attributes = {}, bucketBoundaries = DEFAULT_HISTOGRAM_BUCKETS) {
453
+ if (!this.config.enabled || !this.config.metricsEnabled) return;
454
+ const key = this.getMetricKey(name, attributes);
455
+ const existing = this.histograms.get(key);
456
+ if (existing) {
457
+ existing.count++;
458
+ existing.sum += value;
459
+ if (value < existing.min) existing.min = value;
460
+ if (value > existing.max) existing.max = value;
461
+ let placed = false;
462
+ for (let i = 0; i < existing.bucketBoundaries.length; i++) {
463
+ if (value <= existing.bucketBoundaries[i]) {
464
+ existing.bucketCounts[i]++;
465
+ placed = true;
466
+ break;
467
+ }
468
+ }
469
+ if (!placed) existing.bucketCounts[existing.bucketCounts.length - 1]++;
470
+ } else {
471
+ const bucketCounts = new Array(bucketBoundaries.length + 1).fill(0);
472
+ let placed = false;
473
+ for (let i = 0; i < bucketBoundaries.length; i++) {
474
+ if (value <= bucketBoundaries[i]) {
475
+ bucketCounts[i]++;
476
+ placed = true;
477
+ break;
478
+ }
479
+ }
480
+ if (!placed) bucketCounts[bucketCounts.length - 1]++;
481
+ this.histograms.set(key, { count: 1, sum: value, min: value, max: value, bucketBoundaries, bucketCounts, attributes });
482
+ }
483
+ }
484
+ /**
485
+ * Generate unique key for metric with attributes
486
+ */
487
+ getMetricKey(name, attributes) {
488
+ const keys = Object.keys(attributes);
489
+ if (keys.length === 0) return name;
490
+ const sortedAttrs = Object.entries(attributes).sort(([a], [b]) => a.localeCompare(b)).map(([k, v]) => `${k}=${v}`).join(",");
491
+ return `${name}|${sortedAttrs}`;
492
+ }
493
+ /**
494
+ * Flush accumulated metrics to exporter
495
+ */
496
+ flushMetrics() {
497
+ if (!this.exporter) return;
498
+ const timestamp = Date.now();
499
+ for (const [key, data] of this.counters) {
500
+ if (data.value === 0) continue;
501
+ const name = key.split("|")[0];
502
+ const metric = {
503
+ name,
504
+ type: "counter",
505
+ value: data.value,
506
+ attributes: data.attributes,
507
+ timestamp
508
+ };
509
+ this.exporter.exportMetric(metric);
510
+ data.value = 0;
511
+ }
512
+ for (const [key, data] of this.histograms) {
513
+ const name = key.split("|")[0];
514
+ if (data.count === 0) continue;
515
+ const avg = data.sum / data.count;
516
+ const metric = {
517
+ name,
518
+ type: "histogram",
519
+ value: avg,
520
+ attributes: {
521
+ ...data.attributes,
522
+ count: data.count,
523
+ sum: data.sum,
524
+ min: data.min,
525
+ max: data.max
526
+ },
527
+ timestamp,
528
+ histogramData: {
529
+ count: data.count,
530
+ sum: data.sum,
531
+ min: data.min,
532
+ max: data.max,
533
+ bucketBoundaries: [...data.bucketBoundaries],
534
+ bucketCounts: [...data.bucketCounts]
535
+ }
536
+ };
537
+ this.exporter.exportMetric(metric);
538
+ data.count = 0;
539
+ data.sum = 0;
540
+ data.min = Infinity;
541
+ data.max = -Infinity;
542
+ data.bucketCounts.fill(0);
543
+ }
544
+ }
545
+ /**
546
+ * Force flush all pending data
547
+ */
548
+ async flush() {
549
+ if (this.exporterReady) await this.exporterReady;
550
+ this.flushMetrics();
551
+ await this.exporter?.flush();
552
+ }
553
+ /**
554
+ * Shutdown telemetry
555
+ */
556
+ async shutdown() {
557
+ if (this.metricsIntervalId) {
558
+ clearInterval(this.metricsIntervalId);
559
+ this.metricsIntervalId = null;
560
+ }
561
+ await this.flush();
562
+ await this.exporter?.shutdown();
563
+ this.exporter = null;
564
+ }
565
+ /**
566
+ * Check if telemetry is enabled
567
+ */
568
+ isEnabled() {
569
+ return this.config.enabled;
570
+ }
571
+ /**
572
+ * Get current configuration
573
+ */
574
+ getConfig() {
575
+ return { ...this.config };
576
+ }
577
+ /**
578
+ * Get the active span context for log-to-span correlation.
579
+ * Returns the most recent (top of stack) active span, or null if none.
580
+ */
581
+ getActiveContext() {
582
+ return this.spanStack.length > 0 ? this.spanStack[this.spanStack.length - 1] : null;
583
+ }
584
+ };
585
+
586
+ // src/logging/Logger.ts
587
+ var isBrowser2 = typeof window !== "undefined";
588
+ var globalConfig = { ...DEFAULT_LOGGING_CONFIG };
589
+ function configureLogging(config) {
590
+ globalConfig = { ...globalConfig, ...config };
591
+ }
592
+ function getLoggingConfig() {
593
+ return { ...globalConfig };
594
+ }
595
+ function resetLoggingConfig() {
596
+ globalConfig = { ...DEFAULT_LOGGING_CONFIG };
597
+ }
598
+ function setLogLevel(level) {
599
+ globalConfig.level = level;
600
+ }
601
+ function setLoggingEnabled(enabled) {
602
+ globalConfig.enabled = enabled;
603
+ }
604
+ var consoleSink = (entry) => {
605
+ const consoleMethod = entry.level === "error" ? "error" : entry.level === "warn" ? "warn" : "log";
606
+ if (globalConfig.format === "pretty" && isBrowser2) {
607
+ const args = createBrowserConsoleArgs(entry);
608
+ console[consoleMethod](...args);
609
+ } else {
610
+ const formatter = getFormatter(globalConfig.format);
611
+ const formatted = formatter(entry);
612
+ console[consoleMethod](formatted);
613
+ }
614
+ };
615
+ function getActiveSink() {
616
+ return globalConfig.sink || consoleSink;
617
+ }
618
+ function shouldLog(level) {
619
+ if (!globalConfig.enabled) return false;
620
+ return LOG_LEVEL_PRIORITY[level] <= LOG_LEVEL_PRIORITY[globalConfig.level];
621
+ }
622
+ var Logger = class _Logger {
623
+ constructor(module) {
624
+ this.module = module;
625
+ }
626
+ log(level, message, data) {
627
+ if (!shouldLog(level)) return;
628
+ const entry = {
629
+ timestamp: getClock().timestamp(),
630
+ level,
631
+ module: this.module,
632
+ message,
633
+ data
634
+ };
635
+ const ctx = getTelemetry()?.getActiveContext();
636
+ if (ctx) {
637
+ entry.traceId = ctx.traceId;
638
+ entry.spanId = ctx.spanId;
639
+ }
640
+ if (data?.error instanceof Error) {
641
+ entry.error = data.error;
642
+ const { error, ...rest } = data;
643
+ entry.data = Object.keys(rest).length > 0 ? rest : void 0;
644
+ }
645
+ getActiveSink()(entry);
646
+ }
647
+ error(message, data) {
648
+ this.log("error", message, data);
649
+ }
650
+ warn(message, data) {
651
+ this.log("warn", message, data);
652
+ }
653
+ info(message, data) {
654
+ this.log("info", message, data);
655
+ }
656
+ debug(message, data) {
657
+ this.log("debug", message, data);
658
+ }
659
+ trace(message, data) {
660
+ this.log("trace", message, data);
661
+ }
662
+ verbose(message, data) {
663
+ this.log("verbose", message, data);
664
+ }
665
+ child(subModule) {
666
+ return new _Logger(`${this.module}.${subModule}`);
667
+ }
668
+ };
669
+ var loggerCache = /* @__PURE__ */ new Map();
670
+ function createLogger(module) {
671
+ let logger = loggerCache.get(module);
672
+ if (!logger) {
673
+ logger = new Logger(module);
674
+ loggerCache.set(module, logger);
675
+ }
676
+ return logger;
677
+ }
678
+ function clearLoggerCache() {
679
+ loggerCache.clear();
680
+ }
681
+ var noopLogger = {
682
+ module: "noop",
683
+ error: () => {
684
+ },
685
+ warn: () => {
686
+ },
687
+ info: () => {
688
+ },
689
+ debug: () => {
690
+ },
691
+ trace: () => {
692
+ },
693
+ verbose: () => {
694
+ },
695
+ child: () => noopLogger
696
+ };
697
+ function getNoopLogger() {
698
+ return noopLogger;
699
+ }
700
+
701
+ // src/logging/ErrorCodes.ts
702
+ var ErrorCodes = {
703
+ // ── Inference ──────────────────────────────────────────────────────────
704
+ /** Model failed to load (file not found, corrupted, unsupported format) */
705
+ INF_LOAD_FAILED: "OMOTE_INF_001",
706
+ /** ORT session poisoned after WebGPU device loss — must reload tab */
707
+ INF_SESSION_POISON: "OMOTE_INF_002",
708
+ /** Inference exceeded timeout threshold */
709
+ INF_TIMEOUT: "OMOTE_INF_003",
710
+ /** Out-of-memory during inference or model loading */
711
+ INF_OOM: "OMOTE_INF_004",
712
+ /** WebGPU unavailable, fell back to WASM */
713
+ INF_WEBGPU_FALLBACK: "OMOTE_INF_005",
714
+ /** Input tensor shape does not match model expectations */
715
+ INF_SHAPE_MISMATCH: "OMOTE_INF_006",
716
+ // ── Audio ──────────────────────────────────────────────────────────────
717
+ /** AudioContext creation or resume failed */
718
+ AUD_CONTEXT_FAILED: "OMOTE_AUD_001",
719
+ /** Gap detected in audio scheduling (buffer underrun) */
720
+ AUD_SCHEDULE_GAP: "OMOTE_AUD_002",
721
+ /** Audio buffer decoding failed */
722
+ AUD_DECODE_FAILED: "OMOTE_AUD_003",
723
+ // ── Speech ─────────────────────────────────────────────────────────────
724
+ /** Voice activity detection error */
725
+ SPH_VAD_ERROR: "OMOTE_SPH_001",
726
+ /** Automatic speech recognition error */
727
+ SPH_ASR_ERROR: "OMOTE_SPH_002",
728
+ /** Microphone access denied or unavailable */
729
+ SPH_MIC_DENIED: "OMOTE_SPH_003",
730
+ // ── TTS ────────────────────────────────────────────────────────────────
731
+ /** TTS synthesis failed */
732
+ TTS_SYNTH_FAILED: "OMOTE_TTS_001",
733
+ /** TTS streaming error (chunk delivery failure) */
734
+ TTS_STREAM_ERROR: "OMOTE_TTS_002",
735
+ /** Phonemizer (eSpeak-NG WASM) ran out of memory */
736
+ TTS_PHONEMIZER_OOM: "OMOTE_TTS_003",
737
+ // ── Pipeline ───────────────────────────────────────────────────────────
738
+ /** Invalid state transition in pipeline state machine */
739
+ PIP_STATE_ERROR: "OMOTE_PIP_001",
740
+ /** Pipeline operation aborted (user interrupt or signal) */
741
+ PIP_ABORT: "OMOTE_PIP_002",
742
+ // ── Cache ──────────────────────────────────────────────────────────────
743
+ /** IndexedDB storage quota exceeded */
744
+ CAC_QUOTA_EXCEEDED: "OMOTE_CAC_001",
745
+ /** Cache entry evicted (LRU or manual) */
746
+ CAC_EVICTION: "OMOTE_CAC_002",
747
+ /** Cached model is stale (version mismatch) */
748
+ CAC_STALE: "OMOTE_CAC_003",
749
+ // ── Network ────────────────────────────────────────────────────────────
750
+ /** HTTP fetch failed (model download, CDN) */
751
+ NET_FETCH_FAILED: "OMOTE_NET_001",
752
+ /** Network request timed out */
753
+ NET_TIMEOUT: "OMOTE_NET_002",
754
+ /** WebSocket connection error */
755
+ NET_WEBSOCKET_ERROR: "OMOTE_NET_003"
756
+ };
757
+
758
+ export {
759
+ LOG_LEVEL_PRIORITY,
760
+ DEFAULT_LOGGING_CONFIG,
761
+ jsonFormatter,
762
+ prettyFormatter,
763
+ getFormatter,
764
+ ConsoleExporter,
765
+ defaultClock,
766
+ configureClock,
767
+ getClock,
768
+ configureTelemetry,
769
+ getTelemetry,
770
+ OmoteTelemetry,
771
+ configureLogging,
772
+ getLoggingConfig,
773
+ resetLoggingConfig,
774
+ setLogLevel,
775
+ setLoggingEnabled,
776
+ createLogger,
777
+ clearLoggerCache,
778
+ noopLogger,
779
+ getNoopLogger,
780
+ ErrorCodes
781
+ };
782
+ //# sourceMappingURL=chunk-NWZMIQK4.mjs.map