@livekit/agents 1.0.22 → 1.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/dist/inference/api_protos.cjs +2 -2
  2. package/dist/inference/api_protos.cjs.map +1 -1
  3. package/dist/inference/api_protos.d.cts +16 -16
  4. package/dist/inference/api_protos.d.ts +16 -16
  5. package/dist/inference/api_protos.js +2 -2
  6. package/dist/inference/api_protos.js.map +1 -1
  7. package/dist/ipc/job_proc_lazy_main.cjs +35 -1
  8. package/dist/ipc/job_proc_lazy_main.cjs.map +1 -1
  9. package/dist/ipc/job_proc_lazy_main.js +13 -1
  10. package/dist/ipc/job_proc_lazy_main.js.map +1 -1
  11. package/dist/job.cjs +52 -6
  12. package/dist/job.cjs.map +1 -1
  13. package/dist/job.d.cts +2 -0
  14. package/dist/job.d.ts +2 -0
  15. package/dist/job.d.ts.map +1 -1
  16. package/dist/job.js +52 -6
  17. package/dist/job.js.map +1 -1
  18. package/dist/llm/llm.cjs +38 -3
  19. package/dist/llm/llm.cjs.map +1 -1
  20. package/dist/llm/llm.d.cts +1 -0
  21. package/dist/llm/llm.d.ts +1 -0
  22. package/dist/llm/llm.d.ts.map +1 -1
  23. package/dist/llm/llm.js +38 -3
  24. package/dist/llm/llm.js.map +1 -1
  25. package/dist/log.cjs +34 -10
  26. package/dist/log.cjs.map +1 -1
  27. package/dist/log.d.cts +7 -0
  28. package/dist/log.d.ts +7 -0
  29. package/dist/log.d.ts.map +1 -1
  30. package/dist/log.js +34 -11
  31. package/dist/log.js.map +1 -1
  32. package/dist/telemetry/index.cjs +23 -2
  33. package/dist/telemetry/index.cjs.map +1 -1
  34. package/dist/telemetry/index.d.cts +4 -1
  35. package/dist/telemetry/index.d.ts +4 -1
  36. package/dist/telemetry/index.d.ts.map +1 -1
  37. package/dist/telemetry/index.js +27 -2
  38. package/dist/telemetry/index.js.map +1 -1
  39. package/dist/telemetry/logging.cjs +65 -0
  40. package/dist/telemetry/logging.cjs.map +1 -0
  41. package/dist/telemetry/logging.d.cts +21 -0
  42. package/dist/telemetry/logging.d.ts +21 -0
  43. package/dist/telemetry/logging.d.ts.map +1 -0
  44. package/dist/telemetry/logging.js +40 -0
  45. package/dist/telemetry/logging.js.map +1 -0
  46. package/dist/telemetry/otel_http_exporter.cjs +144 -0
  47. package/dist/telemetry/otel_http_exporter.cjs.map +1 -0
  48. package/dist/telemetry/otel_http_exporter.d.cts +62 -0
  49. package/dist/telemetry/otel_http_exporter.d.ts +62 -0
  50. package/dist/telemetry/otel_http_exporter.d.ts.map +1 -0
  51. package/dist/telemetry/otel_http_exporter.js +120 -0
  52. package/dist/telemetry/otel_http_exporter.js.map +1 -0
  53. package/dist/telemetry/pino_otel_transport.cjs +217 -0
  54. package/dist/telemetry/pino_otel_transport.cjs.map +1 -0
  55. package/dist/telemetry/pino_otel_transport.d.cts +58 -0
  56. package/dist/telemetry/pino_otel_transport.d.ts +58 -0
  57. package/dist/telemetry/pino_otel_transport.d.ts.map +1 -0
  58. package/dist/telemetry/pino_otel_transport.js +189 -0
  59. package/dist/telemetry/pino_otel_transport.js.map +1 -0
  60. package/dist/telemetry/traces.cjs +225 -16
  61. package/dist/telemetry/traces.cjs.map +1 -1
  62. package/dist/telemetry/traces.d.cts +17 -0
  63. package/dist/telemetry/traces.d.ts +17 -0
  64. package/dist/telemetry/traces.d.ts.map +1 -1
  65. package/dist/telemetry/traces.js +211 -14
  66. package/dist/telemetry/traces.js.map +1 -1
  67. package/dist/tts/tts.cjs +62 -5
  68. package/dist/tts/tts.cjs.map +1 -1
  69. package/dist/tts/tts.d.cts +2 -0
  70. package/dist/tts/tts.d.ts +2 -0
  71. package/dist/tts/tts.d.ts.map +1 -1
  72. package/dist/tts/tts.js +62 -5
  73. package/dist/tts/tts.js.map +1 -1
  74. package/dist/utils.cjs +6 -0
  75. package/dist/utils.cjs.map +1 -1
  76. package/dist/utils.d.cts +1 -0
  77. package/dist/utils.d.ts +1 -0
  78. package/dist/utils.d.ts.map +1 -1
  79. package/dist/utils.js +5 -0
  80. package/dist/utils.js.map +1 -1
  81. package/dist/voice/agent_activity.cjs +93 -7
  82. package/dist/voice/agent_activity.cjs.map +1 -1
  83. package/dist/voice/agent_activity.d.cts +3 -0
  84. package/dist/voice/agent_activity.d.ts +3 -0
  85. package/dist/voice/agent_activity.d.ts.map +1 -1
  86. package/dist/voice/agent_activity.js +93 -7
  87. package/dist/voice/agent_activity.js.map +1 -1
  88. package/dist/voice/agent_session.cjs +122 -27
  89. package/dist/voice/agent_session.cjs.map +1 -1
  90. package/dist/voice/agent_session.d.cts +15 -0
  91. package/dist/voice/agent_session.d.ts +15 -0
  92. package/dist/voice/agent_session.d.ts.map +1 -1
  93. package/dist/voice/agent_session.js +122 -27
  94. package/dist/voice/agent_session.js.map +1 -1
  95. package/dist/voice/audio_recognition.cjs +69 -22
  96. package/dist/voice/audio_recognition.cjs.map +1 -1
  97. package/dist/voice/audio_recognition.d.cts +5 -0
  98. package/dist/voice/audio_recognition.d.ts +5 -0
  99. package/dist/voice/audio_recognition.d.ts.map +1 -1
  100. package/dist/voice/audio_recognition.js +69 -22
  101. package/dist/voice/audio_recognition.js.map +1 -1
  102. package/dist/voice/generation.cjs +43 -3
  103. package/dist/voice/generation.cjs.map +1 -1
  104. package/dist/voice/generation.d.ts.map +1 -1
  105. package/dist/voice/generation.js +43 -3
  106. package/dist/voice/generation.js.map +1 -1
  107. package/dist/voice/report.cjs +3 -2
  108. package/dist/voice/report.cjs.map +1 -1
  109. package/dist/voice/report.d.cts +7 -1
  110. package/dist/voice/report.d.ts +7 -1
  111. package/dist/voice/report.d.ts.map +1 -1
  112. package/dist/voice/report.js +3 -2
  113. package/dist/voice/report.js.map +1 -1
  114. package/package.json +8 -2
  115. package/src/inference/api_protos.ts +2 -2
  116. package/src/ipc/job_proc_lazy_main.ts +12 -1
  117. package/src/job.ts +59 -10
  118. package/src/llm/llm.ts +48 -5
  119. package/src/log.ts +52 -15
  120. package/src/telemetry/index.ts +22 -4
  121. package/src/telemetry/logging.ts +55 -0
  122. package/src/telemetry/otel_http_exporter.ts +191 -0
  123. package/src/telemetry/pino_otel_transport.ts +265 -0
  124. package/src/telemetry/traces.ts +320 -20
  125. package/src/tts/tts.ts +71 -9
  126. package/src/utils.ts +5 -0
  127. package/src/voice/agent_activity.ts +140 -22
  128. package/src/voice/agent_session.ts +174 -34
  129. package/src/voice/audio_recognition.ts +85 -26
  130. package/src/voice/generation.ts +59 -7
  131. package/src/voice/report.ts +10 -4
@@ -0,0 +1,62 @@
1
+ /**
2
+ * OTLP HTTP JSON Log Exporter for LiveKit Cloud
3
+ *
4
+ * This module provides a custom OTLP log exporter that uses HTTP with JSON format
5
+ * instead of the default protobuf format.
6
+ */
7
+ import { SeverityNumber } from '@opentelemetry/api-logs';
8
+ export interface SimpleLogRecord {
9
+ /** Log message body */
10
+ body: string;
11
+ /** Timestamp in milliseconds since epoch */
12
+ timestampMs: number;
13
+ /** Log attributes */
14
+ attributes: Record<string, unknown>;
15
+ /** Severity number (default: UNSPECIFIED) */
16
+ severityNumber?: SeverityNumber;
17
+ /** Severity text (default: 'unspecified') */
18
+ severityText?: string;
19
+ }
20
+ export interface SimpleOTLPHttpLogExporterConfig {
21
+ /** LiveKit Cloud hostname */
22
+ cloudHostname: string;
23
+ /** Resource attributes (e.g., room_id, job_id) */
24
+ resourceAttributes: Record<string, string>;
25
+ /** Scope name for the logger */
26
+ scopeName: string;
27
+ /** Scope attributes */
28
+ scopeAttributes?: Record<string, string>;
29
+ }
30
+ /**
31
+ * Simple OTLP HTTP Log Exporter for direct log export
32
+ *
33
+ * This is a simplified exporter that doesn't require the full SDK infrastructure.
34
+ * Use this when you need to send logs directly without LoggerProvider.
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * const exporter = new SimpleOTLPHttpLogExporter({
39
+ * cloudHostname: 'cloud.livekit.io',
40
+ * resourceAttributes: { room_id: 'xxx', job_id: 'yyy' },
41
+ * scopeName: 'chat_history',
42
+ * });
43
+ *
44
+ * await exporter.export([
45
+ * { body: 'Hello', timestampMs: Date.now(), attributes: { test: true } },
46
+ * ]);
47
+ * ```
48
+ */
49
+ export declare class SimpleOTLPHttpLogExporter {
50
+ private readonly config;
51
+ private jwt;
52
+ constructor(config: SimpleOTLPHttpLogExporterConfig);
53
+ /**
54
+ * Export simple log records
55
+ */
56
+ export(records: SimpleLogRecord[]): Promise<void>;
57
+ private ensureJwt;
58
+ private buildPayload;
59
+ private convertAttributes;
60
+ private convertValue;
61
+ }
62
+ //# sourceMappingURL=otel_http_exporter.d.ts.map
@@ -0,0 +1,62 @@
1
+ /**
2
+ * OTLP HTTP JSON Log Exporter for LiveKit Cloud
3
+ *
4
+ * This module provides a custom OTLP log exporter that uses HTTP with JSON format
5
+ * instead of the default protobuf format.
6
+ */
7
+ import { SeverityNumber } from '@opentelemetry/api-logs';
8
+ export interface SimpleLogRecord {
9
+ /** Log message body */
10
+ body: string;
11
+ /** Timestamp in milliseconds since epoch */
12
+ timestampMs: number;
13
+ /** Log attributes */
14
+ attributes: Record<string, unknown>;
15
+ /** Severity number (default: UNSPECIFIED) */
16
+ severityNumber?: SeverityNumber;
17
+ /** Severity text (default: 'unspecified') */
18
+ severityText?: string;
19
+ }
20
+ export interface SimpleOTLPHttpLogExporterConfig {
21
+ /** LiveKit Cloud hostname */
22
+ cloudHostname: string;
23
+ /** Resource attributes (e.g., room_id, job_id) */
24
+ resourceAttributes: Record<string, string>;
25
+ /** Scope name for the logger */
26
+ scopeName: string;
27
+ /** Scope attributes */
28
+ scopeAttributes?: Record<string, string>;
29
+ }
30
+ /**
31
+ * Simple OTLP HTTP Log Exporter for direct log export
32
+ *
33
+ * This is a simplified exporter that doesn't require the full SDK infrastructure.
34
+ * Use this when you need to send logs directly without LoggerProvider.
35
+ *
36
+ * @example
37
+ * ```typescript
38
+ * const exporter = new SimpleOTLPHttpLogExporter({
39
+ * cloudHostname: 'cloud.livekit.io',
40
+ * resourceAttributes: { room_id: 'xxx', job_id: 'yyy' },
41
+ * scopeName: 'chat_history',
42
+ * });
43
+ *
44
+ * await exporter.export([
45
+ * { body: 'Hello', timestampMs: Date.now(), attributes: { test: true } },
46
+ * ]);
47
+ * ```
48
+ */
49
+ export declare class SimpleOTLPHttpLogExporter {
50
+ private readonly config;
51
+ private jwt;
52
+ constructor(config: SimpleOTLPHttpLogExporterConfig);
53
+ /**
54
+ * Export simple log records
55
+ */
56
+ export(records: SimpleLogRecord[]): Promise<void>;
57
+ private ensureJwt;
58
+ private buildPayload;
59
+ private convertAttributes;
60
+ private convertValue;
61
+ }
62
+ //# sourceMappingURL=otel_http_exporter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"otel_http_exporter.d.ts","sourceRoot":"","sources":["../../src/telemetry/otel_http_exporter.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAGzD,MAAM,WAAW,eAAe;IAC9B,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,qBAAqB;IACrB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpC,6CAA6C;IAC7C,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,6CAA6C;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,+BAA+B;IAC9C,6BAA6B;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC3C,gCAAgC;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,uBAAuB;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,yBAAyB;IACpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;IACzD,OAAO,CAAC,GAAG,CAAuB;gBAEtB,MAAM,EAAE,+BAA+B;IAInD;;OAEG;IACG,MAAM,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;YAyBzC,SAAS;IAevB,OAAO,CAAC,YAAY;IA8CpB,OAAO,CAAC,iBAAiB;IASzB,OAAO,CAAC,YAAY;CA4BrB"}
@@ -0,0 +1,120 @@
1
+ import { SeverityNumber } from "@opentelemetry/api-logs";
2
+ import { AccessToken } from "livekit-server-sdk";
3
+ class SimpleOTLPHttpLogExporter {
4
+ config;
5
+ jwt = null;
6
+ constructor(config) {
7
+ this.config = config;
8
+ }
9
+ /**
10
+ * Export simple log records
11
+ */
12
+ async export(records) {
13
+ if (records.length === 0) return;
14
+ await this.ensureJwt();
15
+ const endpoint = `https://${this.config.cloudHostname}/observability/logs/otlp/v0`;
16
+ const payload = this.buildPayload(records);
17
+ const response = await fetch(endpoint, {
18
+ method: "POST",
19
+ headers: {
20
+ Authorization: `Bearer ${this.jwt}`,
21
+ "Content-Type": "application/json"
22
+ },
23
+ body: JSON.stringify(payload)
24
+ });
25
+ if (!response.ok) {
26
+ const text = await response.text();
27
+ throw new Error(
28
+ `OTLP log export failed: ${response.status} ${response.statusText} - ${text}`
29
+ );
30
+ }
31
+ }
32
+ async ensureJwt() {
33
+ if (this.jwt) return;
34
+ const apiKey = process.env.LIVEKIT_API_KEY;
35
+ const apiSecret = process.env.LIVEKIT_API_SECRET;
36
+ if (!apiKey || !apiSecret) {
37
+ throw new Error("LIVEKIT_API_KEY and LIVEKIT_API_SECRET must be set");
38
+ }
39
+ const token = new AccessToken(apiKey, apiSecret, { ttl: "6h" });
40
+ token.addObservabilityGrant({ write: true });
41
+ this.jwt = await token.toJwt();
42
+ }
43
+ buildPayload(records) {
44
+ const resourceAttrs = Object.entries(this.config.resourceAttributes).map(([key, value]) => ({
45
+ key,
46
+ value: { stringValue: value }
47
+ }));
48
+ if (!this.config.resourceAttributes["service.name"]) {
49
+ resourceAttrs.push({ key: "service.name", value: { stringValue: "livekit-agents" } });
50
+ }
51
+ const scopeAttrs = this.config.scopeAttributes ? Object.entries(this.config.scopeAttributes).map(([key, value]) => ({
52
+ key,
53
+ value: { stringValue: value }
54
+ })) : [];
55
+ const logRecords = records.map((record) => ({
56
+ timeUnixNano: String(BigInt(Math.floor(record.timestampMs * 1e6))),
57
+ observedTimeUnixNano: String(BigInt(Date.now()) * BigInt(1e6)),
58
+ severityNumber: record.severityNumber ?? SeverityNumber.UNSPECIFIED,
59
+ severityText: record.severityText ?? "unspecified",
60
+ body: { stringValue: record.body },
61
+ attributes: this.convertAttributes(record.attributes),
62
+ traceId: "",
63
+ spanId: ""
64
+ }));
65
+ return {
66
+ resourceLogs: [
67
+ {
68
+ resource: { attributes: resourceAttrs },
69
+ scopeLogs: [
70
+ {
71
+ scope: {
72
+ name: this.config.scopeName,
73
+ attributes: scopeAttrs
74
+ },
75
+ logRecords
76
+ }
77
+ ]
78
+ }
79
+ ]
80
+ };
81
+ }
82
+ convertAttributes(attrs) {
83
+ return Object.entries(attrs).map(([key, value]) => ({
84
+ key,
85
+ value: this.convertValue(value)
86
+ }));
87
+ }
88
+ convertValue(value) {
89
+ if (value === null || value === void 0) {
90
+ return { stringValue: "" };
91
+ }
92
+ if (typeof value === "string") {
93
+ return { stringValue: value };
94
+ }
95
+ if (typeof value === "number") {
96
+ return Number.isInteger(value) ? { intValue: String(value) } : { doubleValue: value };
97
+ }
98
+ if (typeof value === "boolean") {
99
+ return { boolValue: value };
100
+ }
101
+ if (Array.isArray(value)) {
102
+ return { arrayValue: { values: value.map((v) => this.convertValue(v)) } };
103
+ }
104
+ if (typeof value === "object") {
105
+ return {
106
+ kvlistValue: {
107
+ values: Object.entries(value).map(([k, v]) => ({
108
+ key: k,
109
+ value: this.convertValue(v)
110
+ }))
111
+ }
112
+ };
113
+ }
114
+ return { stringValue: String(value) };
115
+ }
116
+ }
117
+ export {
118
+ SimpleOTLPHttpLogExporter
119
+ };
120
+ //# sourceMappingURL=otel_http_exporter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/telemetry/otel_http_exporter.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\n\n/**\n * OTLP HTTP JSON Log Exporter for LiveKit Cloud\n *\n * This module provides a custom OTLP log exporter that uses HTTP with JSON format\n * instead of the default protobuf format.\n */\nimport { SeverityNumber } from '@opentelemetry/api-logs';\nimport { AccessToken } from 'livekit-server-sdk';\n\nexport interface SimpleLogRecord {\n /** Log message body */\n body: string;\n /** Timestamp in milliseconds since epoch */\n timestampMs: number;\n /** Log attributes */\n attributes: Record<string, unknown>;\n /** Severity number (default: UNSPECIFIED) */\n severityNumber?: SeverityNumber;\n /** Severity text (default: 'unspecified') */\n severityText?: string;\n}\n\nexport interface SimpleOTLPHttpLogExporterConfig {\n /** LiveKit Cloud hostname */\n cloudHostname: string;\n /** Resource attributes (e.g., room_id, job_id) */\n resourceAttributes: Record<string, string>;\n /** Scope name for the logger */\n scopeName: string;\n /** Scope attributes */\n scopeAttributes?: Record<string, string>;\n}\n\n/**\n * Simple OTLP HTTP Log Exporter for direct log export\n *\n * This is a simplified exporter that doesn't require the full SDK infrastructure.\n * Use this when you need to send logs directly without LoggerProvider.\n *\n * @example\n * ```typescript\n * const exporter = new SimpleOTLPHttpLogExporter({\n * cloudHostname: 'cloud.livekit.io',\n * resourceAttributes: { room_id: 'xxx', job_id: 'yyy' },\n * scopeName: 'chat_history',\n * });\n *\n * await exporter.export([\n * { body: 'Hello', timestampMs: Date.now(), attributes: { test: true } },\n * ]);\n * ```\n */\nexport class SimpleOTLPHttpLogExporter {\n private readonly config: SimpleOTLPHttpLogExporterConfig;\n private jwt: string | null = null;\n\n constructor(config: SimpleOTLPHttpLogExporterConfig) {\n this.config = config;\n }\n\n /**\n * Export simple log records\n */\n async export(records: SimpleLogRecord[]): Promise<void> {\n if (records.length === 0) return;\n\n await this.ensureJwt();\n\n const endpoint = `https://${this.config.cloudHostname}/observability/logs/otlp/v0`;\n const payload = this.buildPayload(records);\n\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${this.jwt}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(payload),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(\n `OTLP log export failed: ${response.status} ${response.statusText} - ${text}`,\n );\n }\n }\n\n private async ensureJwt(): Promise<void> {\n if (this.jwt) return;\n\n const apiKey = process.env.LIVEKIT_API_KEY;\n const apiSecret = process.env.LIVEKIT_API_SECRET;\n\n if (!apiKey || !apiSecret) {\n throw new Error('LIVEKIT_API_KEY and LIVEKIT_API_SECRET must be set');\n }\n\n const token = new AccessToken(apiKey, apiSecret, { ttl: '6h' });\n token.addObservabilityGrant({ write: true });\n this.jwt = await token.toJwt();\n }\n\n private buildPayload(records: SimpleLogRecord[]): object {\n const resourceAttrs = Object.entries(this.config.resourceAttributes).map(([key, value]) => ({\n key,\n value: { stringValue: value },\n }));\n\n if (!this.config.resourceAttributes['service.name']) {\n resourceAttrs.push({ key: 'service.name', value: { stringValue: 'livekit-agents' } });\n }\n\n const scopeAttrs = this.config.scopeAttributes\n ? Object.entries(this.config.scopeAttributes).map(([key, value]) => ({\n key,\n value: { stringValue: value },\n }))\n : [];\n\n const logRecords = records.map((record) => ({\n timeUnixNano: String(BigInt(Math.floor(record.timestampMs * 1_000_000))),\n observedTimeUnixNano: String(BigInt(Date.now()) * BigInt(1_000_000)),\n severityNumber: record.severityNumber ?? SeverityNumber.UNSPECIFIED,\n severityText: record.severityText ?? 'unspecified',\n body: { stringValue: record.body },\n attributes: this.convertAttributes(record.attributes),\n traceId: '',\n spanId: '',\n }));\n\n return {\n resourceLogs: [\n {\n resource: { attributes: resourceAttrs },\n scopeLogs: [\n {\n scope: {\n name: this.config.scopeName,\n attributes: scopeAttrs,\n },\n logRecords,\n },\n ],\n },\n ],\n };\n }\n\n private convertAttributes(\n attrs: Record<string, unknown>,\n ): Array<{ key: string; value: unknown }> {\n return Object.entries(attrs).map(([key, value]) => ({\n key,\n value: this.convertValue(value),\n }));\n }\n\n private convertValue(value: unknown): unknown {\n if (value === null || value === undefined) {\n return { stringValue: '' };\n }\n if (typeof value === 'string') {\n return { stringValue: value };\n }\n if (typeof value === 'number') {\n return Number.isInteger(value) ? { intValue: String(value) } : { doubleValue: value };\n }\n if (typeof value === 'boolean') {\n return { boolValue: value };\n }\n if (Array.isArray(value)) {\n return { arrayValue: { values: value.map((v) => this.convertValue(v)) } };\n }\n if (typeof value === 'object') {\n return {\n kvlistValue: {\n values: Object.entries(value as Record<string, unknown>).map(([k, v]) => ({\n key: k,\n value: this.convertValue(v),\n })),\n },\n };\n }\n return { stringValue: String(value) };\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var pino_otel_transport_exports = {};
20
+ __export(pino_otel_transport_exports, {
21
+ PinoCloudExporter: () => PinoCloudExporter,
22
+ emitToOtel: () => emitToOtel,
23
+ flushPinoLogs: () => flushPinoLogs,
24
+ getPinoCloudExporter: () => getPinoCloudExporter,
25
+ initPinoCloudExporter: () => initPinoCloudExporter
26
+ });
27
+ module.exports = __toCommonJS(pino_otel_transport_exports);
28
+ var import_api_logs = require("@opentelemetry/api-logs");
29
+ var import_livekit_server_sdk = require("livekit-server-sdk");
30
+ function mapPinoLevelToSeverity(pinoLevel) {
31
+ if (pinoLevel <= 10) {
32
+ return { severityNumber: import_api_logs.SeverityNumber.TRACE, severityText: "TRACE" };
33
+ } else if (pinoLevel <= 20) {
34
+ return { severityNumber: import_api_logs.SeverityNumber.DEBUG, severityText: "DEBUG" };
35
+ } else if (pinoLevel <= 30) {
36
+ return { severityNumber: import_api_logs.SeverityNumber.INFO, severityText: "INFO" };
37
+ } else if (pinoLevel <= 40) {
38
+ return { severityNumber: import_api_logs.SeverityNumber.WARN, severityText: "WARN" };
39
+ } else if (pinoLevel <= 50) {
40
+ return { severityNumber: import_api_logs.SeverityNumber.ERROR, severityText: "ERROR" };
41
+ } else {
42
+ return { severityNumber: import_api_logs.SeverityNumber.FATAL, severityText: "FATAL" };
43
+ }
44
+ }
45
+ const EXCLUDE_FIELDS = /* @__PURE__ */ new Set(["level", "time", "msg", "pid", "hostname", "v"]);
46
+ function convertValue(value) {
47
+ if (value === null || value === void 0) {
48
+ return { stringValue: "" };
49
+ }
50
+ if (typeof value === "string") {
51
+ return { stringValue: value };
52
+ }
53
+ if (typeof value === "number") {
54
+ return Number.isInteger(value) ? { intValue: String(value) } : { doubleValue: value };
55
+ }
56
+ if (typeof value === "boolean") {
57
+ return { boolValue: value };
58
+ }
59
+ if (typeof value === "object") {
60
+ return { stringValue: JSON.stringify(value) };
61
+ }
62
+ return { stringValue: String(value) };
63
+ }
64
+ class PinoCloudExporter {
65
+ config;
66
+ loggerName;
67
+ batchSize;
68
+ flushIntervalMs;
69
+ jwt = null;
70
+ pendingLogs = [];
71
+ flushTimer = null;
72
+ constructor(config) {
73
+ this.config = config;
74
+ this.loggerName = config.loggerName || "livekit.agents";
75
+ this.batchSize = config.batchSize || 100;
76
+ this.flushIntervalMs = config.flushIntervalMs || 5e3;
77
+ }
78
+ emit(logObj) {
79
+ const record = this.convertToOtlpRecord(logObj);
80
+ this.pendingLogs.push(record);
81
+ if (!this.flushTimer) {
82
+ this.flushTimer = setTimeout(() => {
83
+ this.flush().catch(console.error);
84
+ }, this.flushIntervalMs);
85
+ }
86
+ if (this.pendingLogs.length >= this.batchSize) {
87
+ this.flush().catch(console.error);
88
+ }
89
+ }
90
+ convertToOtlpRecord(logObj) {
91
+ const { severityNumber, severityText } = mapPinoLevelToSeverity(logObj.level);
92
+ const attributes = [
93
+ { key: "room_id", value: { stringValue: this.config.roomId } },
94
+ { key: "job_id", value: { stringValue: this.config.jobId } },
95
+ { key: "logger.name", value: { stringValue: this.loggerName } }
96
+ ];
97
+ if (logObj.pid !== void 0) {
98
+ attributes.push({ key: "process.pid", value: { intValue: String(logObj.pid) } });
99
+ }
100
+ if (logObj.hostname !== void 0) {
101
+ attributes.push({ key: "host.name", value: { stringValue: logObj.hostname } });
102
+ }
103
+ for (const [key, value] of Object.entries(logObj)) {
104
+ if (!EXCLUDE_FIELDS.has(key)) {
105
+ attributes.push({ key, value: convertValue(value) });
106
+ }
107
+ }
108
+ return {
109
+ timeUnixNano: String(BigInt(logObj.time) * BigInt(1e6)),
110
+ observedTimeUnixNano: String(BigInt(Date.now()) * BigInt(1e6)),
111
+ severityNumber,
112
+ severityText,
113
+ body: { stringValue: logObj.msg || "" },
114
+ attributes,
115
+ traceId: "",
116
+ spanId: ""
117
+ };
118
+ }
119
+ async flush() {
120
+ if (this.flushTimer) {
121
+ clearTimeout(this.flushTimer);
122
+ this.flushTimer = null;
123
+ }
124
+ if (this.pendingLogs.length === 0) {
125
+ return;
126
+ }
127
+ const logs = this.pendingLogs;
128
+ this.pendingLogs = [];
129
+ try {
130
+ await this.sendLogs(logs);
131
+ } catch (error) {
132
+ this.pendingLogs = [...logs, ...this.pendingLogs];
133
+ console.error("[PinoCloudExporter] Failed to flush logs:", error);
134
+ }
135
+ }
136
+ async sendLogs(logRecords) {
137
+ await this.ensureJwt();
138
+ const payload = {
139
+ resourceLogs: [
140
+ {
141
+ resource: {
142
+ attributes: [
143
+ { key: "service.name", value: { stringValue: "livekit-agents" } },
144
+ { key: "room_id", value: { stringValue: this.config.roomId } },
145
+ { key: "job_id", value: { stringValue: this.config.jobId } }
146
+ ]
147
+ },
148
+ scopeLogs: [
149
+ {
150
+ scope: {
151
+ name: this.loggerName,
152
+ attributes: [
153
+ { key: "room_id", value: { stringValue: this.config.roomId } },
154
+ { key: "job_id", value: { stringValue: this.config.jobId } }
155
+ ]
156
+ },
157
+ logRecords
158
+ }
159
+ ]
160
+ }
161
+ ]
162
+ };
163
+ const endpoint = `https://${this.config.cloudHostname}/observability/logs/otlp/v0`;
164
+ const response = await fetch(endpoint, {
165
+ method: "POST",
166
+ headers: {
167
+ Authorization: `Bearer ${this.jwt}`,
168
+ "Content-Type": "application/json"
169
+ },
170
+ body: JSON.stringify(payload)
171
+ });
172
+ if (!response.ok) {
173
+ const text = await response.text();
174
+ throw new Error(`Log export failed: ${response.status} ${response.statusText} - ${text}`);
175
+ }
176
+ }
177
+ async ensureJwt() {
178
+ if (this.jwt) return;
179
+ const apiKey = process.env.LIVEKIT_API_KEY;
180
+ const apiSecret = process.env.LIVEKIT_API_SECRET;
181
+ if (!apiKey || !apiSecret) {
182
+ throw new Error("LIVEKIT_API_KEY and LIVEKIT_API_SECRET must be set");
183
+ }
184
+ const token = new import_livekit_server_sdk.AccessToken(apiKey, apiSecret, { ttl: "6h" });
185
+ token.addObservabilityGrant({ write: true });
186
+ this.jwt = await token.toJwt();
187
+ }
188
+ async shutdown() {
189
+ await this.flush();
190
+ }
191
+ }
192
+ let globalExporter = null;
193
+ function initPinoCloudExporter(config) {
194
+ globalExporter = new PinoCloudExporter(config);
195
+ }
196
+ function getPinoCloudExporter() {
197
+ return globalExporter;
198
+ }
199
+ function emitToOtel(logObj) {
200
+ if (globalExporter) {
201
+ globalExporter.emit(logObj);
202
+ }
203
+ }
204
+ async function flushPinoLogs() {
205
+ if (globalExporter) {
206
+ await globalExporter.flush();
207
+ }
208
+ }
209
+ // Annotate the CommonJS export names for ESM import in node:
210
+ 0 && (module.exports = {
211
+ PinoCloudExporter,
212
+ emitToOtel,
213
+ flushPinoLogs,
214
+ getPinoCloudExporter,
215
+ initPinoCloudExporter
216
+ });
217
+ //# sourceMappingURL=pino_otel_transport.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/telemetry/pino_otel_transport.ts"],"sourcesContent":["// SPDX-FileCopyrightText: 2025 LiveKit, Inc.\n//\n// SPDX-License-Identifier: Apache-2.0\n\n/**\n * Custom Pino OTEL Transport\n *\n * Standalone exporter for Pino logs to LiveKit Cloud.\n * Uses raw HTTP JSON format, bypassing the OTEL SDK.\n */\nimport { SeverityNumber } from '@opentelemetry/api-logs';\nimport { AccessToken } from 'livekit-server-sdk';\n\nexport interface PinoLogObject {\n level: number;\n time: number;\n msg: string;\n pid?: number;\n hostname?: string;\n [key: string]: unknown;\n}\n\nexport interface PinoCloudExporterConfig {\n cloudHostname: string;\n roomId: string;\n jobId: string;\n loggerName?: string;\n batchSize?: number;\n flushIntervalMs?: number;\n}\n\nfunction mapPinoLevelToSeverity(pinoLevel: number): {\n severityNumber: SeverityNumber;\n severityText: string;\n} {\n if (pinoLevel <= 10) {\n return { severityNumber: SeverityNumber.TRACE, severityText: 'TRACE' };\n } else if (pinoLevel <= 20) {\n return { severityNumber: SeverityNumber.DEBUG, severityText: 'DEBUG' };\n } else if (pinoLevel <= 30) {\n return { severityNumber: SeverityNumber.INFO, severityText: 'INFO' };\n } else if (pinoLevel <= 40) {\n return { severityNumber: SeverityNumber.WARN, severityText: 'WARN' };\n } else if (pinoLevel <= 50) {\n return { severityNumber: SeverityNumber.ERROR, severityText: 'ERROR' };\n } else {\n return { severityNumber: SeverityNumber.FATAL, severityText: 'FATAL' };\n }\n}\n\nconst EXCLUDE_FIELDS = new Set(['level', 'time', 'msg', 'pid', 'hostname', 'v']);\n\nfunction convertValue(value: unknown): unknown {\n if (value === null || value === undefined) {\n return { stringValue: '' };\n }\n if (typeof value === 'string') {\n return { stringValue: value };\n }\n if (typeof value === 'number') {\n return Number.isInteger(value) ? { intValue: String(value) } : { doubleValue: value };\n }\n if (typeof value === 'boolean') {\n return { boolValue: value };\n }\n if (typeof value === 'object') {\n return { stringValue: JSON.stringify(value) };\n }\n return { stringValue: String(value) };\n}\n\n/**\n * Standalone Pino log exporter for LiveKit Cloud.\n *\n * Collects Pino logs, batches them, and sends via raw HTTP JSON.\n * No OTEL SDK dependency\n *\n * @example\n * ```typescript\n * const exporter = new PinoCloudExporter({\n * cloudHostname: 'cloud.livekit.io',\n * roomId: 'RM_xxx',\n * jobId: 'AJ_xxx',\n * });\n *\n * // In Pino formatter hook:\n * exporter.emit(logObj);\n *\n * // On session end:\n * await exporter.flush();\n * ```\n */\nexport class PinoCloudExporter {\n private readonly config: PinoCloudExporterConfig;\n private readonly loggerName: string;\n private readonly batchSize: number;\n private readonly flushIntervalMs: number;\n private jwt: string | null = null;\n private pendingLogs: any[] = [];\n private flushTimer: NodeJS.Timeout | null = null;\n\n constructor(config: PinoCloudExporterConfig) {\n this.config = config;\n this.loggerName = config.loggerName || 'livekit.agents';\n this.batchSize = config.batchSize || 100;\n this.flushIntervalMs = config.flushIntervalMs || 5000;\n }\n\n emit(logObj: PinoLogObject): void {\n const record = this.convertToOtlpRecord(logObj);\n this.pendingLogs.push(record);\n\n if (!this.flushTimer) {\n this.flushTimer = setTimeout(() => {\n this.flush().catch(console.error);\n }, this.flushIntervalMs);\n }\n\n if (this.pendingLogs.length >= this.batchSize) {\n this.flush().catch(console.error);\n }\n }\n\n private convertToOtlpRecord(logObj: PinoLogObject): any {\n const { severityNumber, severityText } = mapPinoLevelToSeverity(logObj.level);\n\n const attributes: any[] = [\n { key: 'room_id', value: { stringValue: this.config.roomId } },\n { key: 'job_id', value: { stringValue: this.config.jobId } },\n { key: 'logger.name', value: { stringValue: this.loggerName } },\n ];\n\n if (logObj.pid !== undefined) {\n attributes.push({ key: 'process.pid', value: { intValue: String(logObj.pid) } });\n }\n if (logObj.hostname !== undefined) {\n attributes.push({ key: 'host.name', value: { stringValue: logObj.hostname } });\n }\n\n for (const [key, value] of Object.entries(logObj)) {\n if (!EXCLUDE_FIELDS.has(key)) {\n attributes.push({ key, value: convertValue(value) });\n }\n }\n\n return {\n timeUnixNano: String(BigInt(logObj.time) * BigInt(1_000_000)),\n observedTimeUnixNano: String(BigInt(Date.now()) * BigInt(1_000_000)),\n severityNumber,\n severityText,\n body: { stringValue: logObj.msg || '' },\n attributes,\n traceId: '',\n spanId: '',\n };\n }\n\n async flush(): Promise<void> {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n\n if (this.pendingLogs.length === 0) {\n return;\n }\n\n const logs = this.pendingLogs;\n this.pendingLogs = [];\n\n try {\n await this.sendLogs(logs);\n } catch (error) {\n this.pendingLogs = [...logs, ...this.pendingLogs];\n console.error('[PinoCloudExporter] Failed to flush logs:', error);\n }\n }\n\n private async sendLogs(logRecords: any[]): Promise<void> {\n await this.ensureJwt();\n\n const payload = {\n resourceLogs: [\n {\n resource: {\n attributes: [\n { key: 'service.name', value: { stringValue: 'livekit-agents' } },\n { key: 'room_id', value: { stringValue: this.config.roomId } },\n { key: 'job_id', value: { stringValue: this.config.jobId } },\n ],\n },\n scopeLogs: [\n {\n scope: {\n name: this.loggerName,\n attributes: [\n { key: 'room_id', value: { stringValue: this.config.roomId } },\n { key: 'job_id', value: { stringValue: this.config.jobId } },\n ],\n },\n logRecords,\n },\n ],\n },\n ],\n };\n\n const endpoint = `https://${this.config.cloudHostname}/observability/logs/otlp/v0`;\n\n const response = await fetch(endpoint, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${this.jwt}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify(payload),\n });\n\n if (!response.ok) {\n const text = await response.text();\n throw new Error(`Log export failed: ${response.status} ${response.statusText} - ${text}`);\n }\n }\n\n private async ensureJwt(): Promise<void> {\n if (this.jwt) return;\n\n const apiKey = process.env.LIVEKIT_API_KEY;\n const apiSecret = process.env.LIVEKIT_API_SECRET;\n\n if (!apiKey || !apiSecret) {\n throw new Error('LIVEKIT_API_KEY and LIVEKIT_API_SECRET must be set');\n }\n\n const token = new AccessToken(apiKey, apiSecret, { ttl: '6h' });\n token.addObservabilityGrant({ write: true });\n this.jwt = await token.toJwt();\n }\n\n async shutdown(): Promise<void> {\n await this.flush();\n }\n}\n\nlet globalExporter: PinoCloudExporter | null = null;\n\nexport function initPinoCloudExporter(config: PinoCloudExporterConfig): void {\n globalExporter = new PinoCloudExporter(config);\n}\n\nexport function getPinoCloudExporter(): PinoCloudExporter | null {\n return globalExporter;\n}\n\nexport function emitToOtel(logObj: PinoLogObject): void {\n if (globalExporter) {\n globalExporter.emit(logObj);\n }\n}\n\nexport async function flushPinoLogs(): Promise<void> {\n if (globalExporter) {\n await globalExporter.flush();\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,58 @@
1
+ export interface PinoLogObject {
2
+ level: number;
3
+ time: number;
4
+ msg: string;
5
+ pid?: number;
6
+ hostname?: string;
7
+ [key: string]: unknown;
8
+ }
9
+ export interface PinoCloudExporterConfig {
10
+ cloudHostname: string;
11
+ roomId: string;
12
+ jobId: string;
13
+ loggerName?: string;
14
+ batchSize?: number;
15
+ flushIntervalMs?: number;
16
+ }
17
+ /**
18
+ * Standalone Pino log exporter for LiveKit Cloud.
19
+ *
20
+ * Collects Pino logs, batches them, and sends via raw HTTP JSON.
21
+ * No OTEL SDK dependency
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * const exporter = new PinoCloudExporter({
26
+ * cloudHostname: 'cloud.livekit.io',
27
+ * roomId: 'RM_xxx',
28
+ * jobId: 'AJ_xxx',
29
+ * });
30
+ *
31
+ * // In Pino formatter hook:
32
+ * exporter.emit(logObj);
33
+ *
34
+ * // On session end:
35
+ * await exporter.flush();
36
+ * ```
37
+ */
38
+ export declare class PinoCloudExporter {
39
+ private readonly config;
40
+ private readonly loggerName;
41
+ private readonly batchSize;
42
+ private readonly flushIntervalMs;
43
+ private jwt;
44
+ private pendingLogs;
45
+ private flushTimer;
46
+ constructor(config: PinoCloudExporterConfig);
47
+ emit(logObj: PinoLogObject): void;
48
+ private convertToOtlpRecord;
49
+ flush(): Promise<void>;
50
+ private sendLogs;
51
+ private ensureJwt;
52
+ shutdown(): Promise<void>;
53
+ }
54
+ export declare function initPinoCloudExporter(config: PinoCloudExporterConfig): void;
55
+ export declare function getPinoCloudExporter(): PinoCloudExporter | null;
56
+ export declare function emitToOtel(logObj: PinoLogObject): void;
57
+ export declare function flushPinoLogs(): Promise<void>;
58
+ //# sourceMappingURL=pino_otel_transport.d.ts.map
@@ -0,0 +1,58 @@
1
+ export interface PinoLogObject {
2
+ level: number;
3
+ time: number;
4
+ msg: string;
5
+ pid?: number;
6
+ hostname?: string;
7
+ [key: string]: unknown;
8
+ }
9
+ export interface PinoCloudExporterConfig {
10
+ cloudHostname: string;
11
+ roomId: string;
12
+ jobId: string;
13
+ loggerName?: string;
14
+ batchSize?: number;
15
+ flushIntervalMs?: number;
16
+ }
17
+ /**
18
+ * Standalone Pino log exporter for LiveKit Cloud.
19
+ *
20
+ * Collects Pino logs, batches them, and sends via raw HTTP JSON.
21
+ * No OTEL SDK dependency
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * const exporter = new PinoCloudExporter({
26
+ * cloudHostname: 'cloud.livekit.io',
27
+ * roomId: 'RM_xxx',
28
+ * jobId: 'AJ_xxx',
29
+ * });
30
+ *
31
+ * // In Pino formatter hook:
32
+ * exporter.emit(logObj);
33
+ *
34
+ * // On session end:
35
+ * await exporter.flush();
36
+ * ```
37
+ */
38
+ export declare class PinoCloudExporter {
39
+ private readonly config;
40
+ private readonly loggerName;
41
+ private readonly batchSize;
42
+ private readonly flushIntervalMs;
43
+ private jwt;
44
+ private pendingLogs;
45
+ private flushTimer;
46
+ constructor(config: PinoCloudExporterConfig);
47
+ emit(logObj: PinoLogObject): void;
48
+ private convertToOtlpRecord;
49
+ flush(): Promise<void>;
50
+ private sendLogs;
51
+ private ensureJwt;
52
+ shutdown(): Promise<void>;
53
+ }
54
+ export declare function initPinoCloudExporter(config: PinoCloudExporterConfig): void;
55
+ export declare function getPinoCloudExporter(): PinoCloudExporter | null;
56
+ export declare function emitToOtel(logObj: PinoLogObject): void;
57
+ export declare function flushPinoLogs(): Promise<void>;
58
+ //# sourceMappingURL=pino_otel_transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pino_otel_transport.d.ts","sourceRoot":"","sources":["../../src/telemetry/pino_otel_transport.ts"],"names":[],"mappings":"AAaA,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,uBAAuB;IACtC,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AA0CD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;IACjD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,GAAG,CAAuB;IAClC,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,UAAU,CAA+B;gBAErC,MAAM,EAAE,uBAAuB;IAO3C,IAAI,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAejC,OAAO,CAAC,mBAAmB;IAkCrB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAqBd,QAAQ;YA8CR,SAAS;IAejB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAGhC;AAID,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,uBAAuB,GAAG,IAAI,CAE3E;AAED,wBAAgB,oBAAoB,IAAI,iBAAiB,GAAG,IAAI,CAE/D;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAItD;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAInD"}