@arizeai/phoenix-otel 0.2.0 β†’ 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  <h1 align="center" style="border-bottom: none">
2
2
  <div>
3
- <a href="https://phoenix.arize.com/?utm_medium=github&utm_content=header_img&utm_campaign=phoenix-client-ts">
3
+ <a href="https://phoenix.arize.com/?utm_medium=github&utm_content=header_img&utm_campaign=phoenix-otel-ts">
4
4
  <picture>
5
5
  <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/Arize-ai/phoenix-assets/refs/heads/main/logos/Phoenix/phoenix.svg">
6
6
  <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/Arize-ai/phoenix-assets/refs/heads/main/logos/Phoenix/phoenix-white.svg">
@@ -11,8 +11,24 @@
11
11
  @arizeai/phoenix-otel
12
12
  </div>
13
13
  </h1>
14
+ <p align="center">
15
+ <a href="https://www.npmjs.com/package/@arizeai/phoenix-otel">
16
+ <img src="https://img.shields.io/npm/v/@arizeai/phoenix-otel" alt="NPM Version">
17
+ </a>
18
+ <a href="https://arize.com/docs/phoenix">
19
+ <img src="https://img.shields.io/badge/docs-blue?logo=readthedocs&logoColor=white" alt="Documentation">
20
+ </a>
21
+ </p>
14
22
 
15
- A simple wrapper around OpenTelemetry for use with [Arize Phoenix](https://github.com/Arize-ai/phoenix). This package is still under active development and is subject to change.
23
+ A lightweight wrapper around OpenTelemetry for Node.js applications that simplifies sending traces to [Arize Phoenix](https://github.com/Arize-ai/phoenix). This package provides an easy-to-use `register` function that handles all the boilerplate configuration for OpenTelemetry tracing.
24
+
25
+ > **Note**: This package is under active development and APIs may change.
26
+
27
+ ## Features
28
+
29
+ - **Simple Setup** - One-line configuration with sensible defaults
30
+ - **Environment Variables** - Automatic configuration from environment variables
31
+ - **Batch Processing** - Built-in batch span processing for production use
16
32
 
17
33
  ## Installation
18
34
 
@@ -20,12 +36,244 @@ A simple wrapper around OpenTelemetry for use with [Arize Phoenix](https://githu
20
36
  npm install @arizeai/phoenix-otel
21
37
  ```
22
38
 
23
- ## Usage
39
+ ## Quick Start
40
+
41
+ ### Basic Usage
42
+
43
+ The simplest way to get started is to use the `register` function:
44
+
45
+ ```typescript
46
+ import { register } from "@arizeai/phoenix-otel";
47
+
48
+ // Register with default settings (connects to localhost:6006)
49
+ register({
50
+ projectName: "my-app",
51
+ });
52
+ ```
53
+
54
+ ### Production Setup
55
+
56
+ For production use with Phoenix Cloud:
57
+
58
+ ```typescript
59
+ import { register } from "@arizeai/phoenix-otel";
60
+
61
+ register({
62
+ projectName: "my-app",
63
+ url: "https://app.phoenix.arize.com",
64
+ apiKey: process.env.PHOENIX_API_KEY,
65
+ });
66
+ ```
67
+
68
+ ## Configuration
69
+
70
+ ### Environment Variables
71
+
72
+ The `register` function automatically reads from environment variables:
73
+
74
+ ```bash
75
+ # For local Phoenix server (default)
76
+ export PHOENIX_COLLECTOR_ENDPOINT="http://localhost:6006"
77
+
78
+ # For Phoenix Cloud
79
+ export PHOENIX_COLLECTOR_ENDPOINT="https://app.phoenix.arize.com"
80
+ export PHOENIX_API_KEY="your-api-key"
81
+ ```
82
+
83
+ ### Configuration Options
84
+
85
+ The `register` function accepts the following parameters:
86
+
87
+ | Parameter | Type | Default | Description |
88
+ | ------------------ | ------------------------ | ------------------------- | ------------------------------------------------------ |
89
+ | `projectName` | `string` | `"default"` | The project name for organizing traces in Phoenix |
90
+ | `url` | `string` | `"http://localhost:6006"` | The URL to your Phoenix instance |
91
+ | `apiKey` | `string` | `undefined` | API key for Phoenix authentication |
92
+ | `headers` | `Record<string, string>` | `{}` | Custom headers for OTLP requests |
93
+ | `batch` | `boolean` | `true` | Use batch span processing (recommended for production) |
94
+ | `instrumentations` | `Instrumentation[]` | `undefined` | Array of OpenTelemetry instrumentations to register |
95
+ | `global` | `boolean` | `true` | Register the tracer provider globally |
96
+ | `diagLogLevel` | `DiagLogLevel` | `undefined` | Diagnostic logging level for debugging |
97
+
98
+ ## Usage Examples
99
+
100
+ ### With Auto-Instrumentation
101
+
102
+ Automatically instrument common libraries (works best with CommonJS):
24
103
 
25
104
  ```typescript
26
105
  import { register } from "@arizeai/phoenix-otel";
106
+ import { HttpInstrumentation } from "@opentelemetry/instrumentation-http";
107
+ import { ExpressInstrumentation } from "@opentelemetry/instrumentation-express";
27
108
 
28
109
  register({
29
- url: "http://localhost:6006/v1/traces",
110
+ projectName: "my-express-app",
111
+ instrumentations: [new HttpInstrumentation(), new ExpressInstrumentation()],
30
112
  });
31
113
  ```
114
+
115
+ > **Note**: Auto-instrumentation via the `instrumentations` parameter works best with CommonJS projects. ESM projects require manual instrumentation.
116
+
117
+ ### With OpenAI (ESM)
118
+
119
+ For ESM projects, manually instrument libraries:
120
+
121
+ ```typescript
122
+ // instrumentation.ts
123
+ import { register, registerInstrumentations } from "@arizeai/phoenix-otel";
124
+ import OpenAI from "openai";
125
+ import { OpenAIInstrumentation } from "@arizeai/openinference-instrumentation-openai";
126
+
127
+ register({
128
+ projectName: "openai-app",
129
+ });
130
+
131
+ // Manual instrumentation for ESM
132
+ const instrumentation = new OpenAIInstrumentation();
133
+ instrumentation.manuallyInstrument(OpenAI);
134
+
135
+ registerInstrumentations({
136
+ instrumentations: [instrumentation],
137
+ });
138
+ ```
139
+
140
+ ```typescript
141
+ // main.ts
142
+ import "./instrumentation.ts";
143
+ import OpenAI from "openai";
144
+
145
+ const openai = new OpenAI();
146
+
147
+ const response = await openai.chat.completions.create({
148
+ model: "gpt-4o",
149
+ messages: [{ role: "user", content: "Hello!" }],
150
+ });
151
+ ```
152
+
153
+ ### Manual Tracing
154
+
155
+ Create custom spans using the OpenTelemetry API:
156
+
157
+ ```typescript
158
+ import { register, trace } from "@arizeai/phoenix-otel";
159
+
160
+ register({ projectName: "my-app" });
161
+
162
+ const tracer = trace.getTracer("my-service");
163
+
164
+ async function processOrder(orderId: string) {
165
+ return tracer.startActiveSpan("process-order", async (span) => {
166
+ try {
167
+ span.setAttribute("order.id", orderId);
168
+
169
+ // Your business logic here
170
+ const result = await fetchOrderDetails(orderId);
171
+
172
+ span.setAttribute("order.status", result.status);
173
+ return result;
174
+ } catch (error) {
175
+ span.recordException(error as Error);
176
+ span.setStatus({ code: SpanStatusCode.ERROR });
177
+ throw error;
178
+ } finally {
179
+ span.end();
180
+ }
181
+ });
182
+ }
183
+ ```
184
+
185
+ ### Development vs Production
186
+
187
+ **Development** (with debug logging):
188
+
189
+ ```typescript
190
+ import { register } from "@arizeai/phoenix-otel";
191
+ import { DiagLogLevel } from "@opentelemetry/api";
192
+
193
+ register({
194
+ projectName: "my-app-dev",
195
+ url: "http://localhost:6006",
196
+ batch: false, // Immediate span delivery for faster feedback
197
+ diagLogLevel: DiagLogLevel.DEBUG,
198
+ });
199
+ ```
200
+
201
+ **Production** (optimized for performance):
202
+
203
+ ```typescript
204
+ import { register } from "@arizeai/phoenix-otel";
205
+
206
+ register({
207
+ projectName: "my-app-prod",
208
+ url: "https://app.phoenix.arize.com",
209
+ apiKey: process.env.PHOENIX_API_KEY,
210
+ batch: true, // Batch processing for better performance
211
+ });
212
+ ```
213
+
214
+ ### Custom Headers
215
+
216
+ Add custom headers to OTLP requests:
217
+
218
+ ```typescript
219
+ import { register } from "@arizeai/phoenix-otel";
220
+
221
+ register({
222
+ projectName: "my-app",
223
+ url: "https://app.phoenix.arize.com",
224
+ headers: {
225
+ "X-Custom-Header": "custom-value",
226
+ "X-Environment": process.env.NODE_ENV || "development",
227
+ },
228
+ });
229
+ ```
230
+
231
+ ### Non-Global Provider
232
+
233
+ Use the provider explicitly without registering globally:
234
+
235
+ ```typescript
236
+ import { register } from "@arizeai/phoenix-otel";
237
+
238
+ const provider = register({
239
+ projectName: "my-app",
240
+ global: false,
241
+ });
242
+
243
+ // Use the provider explicitly
244
+ const tracer = provider.getTracer("my-tracer");
245
+ ```
246
+
247
+ ## Re-exported APIs
248
+
249
+ For convenience, commonly used OpenTelemetry APIs are re-exported:
250
+
251
+ ```typescript
252
+ import {
253
+ trace, // Main tracing API
254
+ context, // Context API
255
+ SpanStatusCode, // Span status codes
256
+ registerInstrumentations, // Register instrumentations
257
+ type DiagLogLevel, // Diagnostic log levels
258
+ type Tracer, // Tracer type
259
+ type Instrumentation, // Instrumentation type
260
+ type NodeTracerProvider, // Provider type
261
+ } from "@arizeai/phoenix-otel";
262
+ ```
263
+
264
+ ## Documentation
265
+
266
+ - **[Phoenix Documentation](https://arize.com/docs/phoenix)** - Complete Phoenix documentation
267
+ - **[OpenTelemetry JS](https://opentelemetry.io/docs/languages/js/)** - OpenTelemetry for JavaScript
268
+ - **[OpenInference](https://github.com/Arize-ai/openinference)** - OpenInference semantic conventions
269
+
270
+ ## Community
271
+
272
+ Join our community to connect with thousands of AI builders:
273
+
274
+ - 🌍 Join our [Slack community](https://arize-ai.slack.com/join/shared_invite/zt-11t1vbu4x-xkBIHmOREQnYnYDH1GDfCg)
275
+ - πŸ’‘ Ask questions and provide feedback in the _#phoenix-support_ channel
276
+ - 🌟 Leave a star on our [GitHub](https://github.com/Arize-ai/phoenix)
277
+ - 🐞 Report bugs with [GitHub Issues](https://github.com/Arize-ai/phoenix/issues)
278
+ - 𝕏 Follow us on [𝕏](https://twitter.com/ArizePhoenix)
279
+ - πŸ—ΊοΈ Check out our [roadmap](https://github.com/orgs/Arize-ai/projects/45)
@@ -1,6 +1,6 @@
1
- import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
2
- import { Instrumentation } from "@opentelemetry/instrumentation";
3
1
  import { DiagLogLevel } from "@opentelemetry/api";
2
+ import { Instrumentation } from "@opentelemetry/instrumentation";
3
+ import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
4
4
  export type Headers = Record<string, string>;
5
5
  /**
6
6
  * Configuration parameters for registering Phoenix OpenTelemetry tracing
@@ -1 +1 @@
1
- {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/register.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,kBAAkB,EAEnB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EACL,eAAe,EAEhB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAA2B,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE3E,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE7C;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAC;IACrC;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,QAAQ,CAAC,EACvB,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,aAAkB,EAC3B,WAAuB,EACvB,gBAAgB,EAChB,KAAY,EACZ,MAAa,EACb,YAAY,GACb,EAAE,cAAc,GAAG,kBAAkB,CA0CrC;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAK3D"}
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../src/register.ts"],"names":[],"mappings":"AAQA,OAAO,EAA2B,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAE3E,OAAO,EACL,eAAe,EAEhB,MAAM,gCAAgC,CAAC;AAExC,OAAO,EACL,kBAAkB,EAEnB,MAAM,+BAA+B,CAAC;AAEvC,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE7C;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,eAAe,EAAE,CAAC;IACrC;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,QAAQ,CAAC,EACvB,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,aAAkB,EAC3B,WAAuB,EACvB,gBAAgB,EAChB,KAAY,EACZ,MAAa,EACb,YAAY,GACb,EAAE,cAAc,GAAG,kBAAkB,CA0CrC;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAK3D"}
@@ -1,11 +1,11 @@
1
1
  import { SEMRESATTRS_PROJECT_NAME } from "@arizeai/openinference-semantic-conventions";
2
2
  import { OpenInferenceBatchSpanProcessor, OpenInferenceSimpleSpanProcessor, } from "@arizeai/openinference-vercel";
3
+ import { getEnvApiKey, getEnvCollectorURL } from "./config.js";
4
+ import { diag, DiagConsoleLogger } from "@opentelemetry/api";
3
5
  import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
6
+ import { registerInstrumentations, } from "@opentelemetry/instrumentation";
4
7
  import { resourceFromAttributes } from "@opentelemetry/resources";
5
8
  import { NodeTracerProvider, } from "@opentelemetry/sdk-trace-node";
6
- import { getEnvApiKey, getEnvCollectorURL } from "./config.js";
7
- import { registerInstrumentations, } from "@opentelemetry/instrumentation";
8
- import { diag, DiagConsoleLogger } from "@opentelemetry/api";
9
9
  /**
10
10
  * Registers Phoenix OpenTelemetry tracing with the specified configuration
11
11
  *
@@ -1 +1 @@
1
- {"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/register.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,6CAA6C,CAAC;AACvF,OAAO,EACL,+BAA+B,EAC/B,gCAAgC,GACjC,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EACL,kBAAkB,GAEnB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC5D,OAAO,EAEL,wBAAwB,GACzB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,IAAI,EAAE,iBAAiB,EAAgB,MAAM,oBAAoB,CAAC;AAmD3E;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,QAAQ,CAAC,EACvB,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,aAAa,GAAG,EAAE,EAC3B,WAAW,GAAG,SAAS,EACvB,gBAAgB,EAChB,KAAK,GAAG,IAAI,EACZ,MAAM,GAAG,IAAI,EACb,YAAY,GACG;IACf,IAAI,YAAY,EAAE,CAAC;QACjB,IAAI,CAAC,SAAS,CAAC,IAAI,iBAAiB,EAAE,EAAE,YAAY,CAAC,CAAC;IACxD,CAAC;IACD,MAAM,GAAG,GAAG,uBAAuB,CACjC,SAAS,IAAI,kBAAkB,EAAE,IAAI,uBAAuB,CAC7D,CAAC;IACF,MAAM,MAAM,GAAG,YAAY,IAAI,YAAY,EAAE,CAAC;IAC9C,MAAM,OAAO,GAAY,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC;QACnD,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC;QACnC,CAAC,CAAC,aAAa,CAAC;IAClB,MAAM,gBAAgB,GAAG,OAAO,MAAM,IAAI,QAAQ,CAAC;IACnD,IAAI,gBAAgB,EAAE,CAAC;QACrB,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,MAAM,EAAE,CAAC;IAChD,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,iBAAiB,CAAC;QACrC,GAAG;QACH,OAAO;KACR,CAAC,CAAC;IACH,IAAI,aAA4B,CAAC;IACjC,IAAI,KAAK,EAAE,CAAC;QACV,aAAa,GAAG,IAAI,+BAA+B,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;IACpE,CAAC;SAAM,CAAC;QACN,aAAa,GAAG,IAAI,gCAAgC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,kBAAkB,CAAC;QACtC,QAAQ,EAAE,sBAAsB,CAAC;YAC/B,CAAC,wBAAwB,CAAC,EAAE,WAAW;SACxC,CAAC;QACF,cAAc,EAAE,CAAC,aAAa,CAAC;KAChC,CAAC,CAAC;IAEH,IAAI,gBAAgB,EAAE,CAAC;QACrB,wBAAwB,CAAC;YACvB,gBAAgB;YAChB,cAAc,EAAE,QAAQ;SACzB,CAAC,CAAC;IACL,CAAC;IACD,IAAI,MAAM,EAAE,CAAC;QACX,QAAQ,CAAC,QAAQ,EAAE,CAAC;IACtB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CAAC,GAAW;IACjD,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QAChC,OAAO,IAAI,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC/C,CAAC;IACD,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;AACjC,CAAC"}
1
+ {"version":3,"file":"register.js","sourceRoot":"","sources":["../../src/register.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,6CAA6C,CAAC;AACvF,OAAO,EACL,+BAA+B,EAC/B,gCAAgC,GACjC,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAE5D,OAAO,EAAE,IAAI,EAAE,iBAAiB,EAAgB,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAC7E,OAAO,EAEL,wBAAwB,GACzB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EACL,kBAAkB,GAEnB,MAAM,+BAA+B,CAAC;AAmDvC;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,UAAU,QAAQ,CAAC,EACvB,GAAG,EAAE,SAAS,EACd,MAAM,EAAE,YAAY,EACpB,OAAO,EAAE,aAAa,GAAG,EAAE,EAC3B,WAAW,GAAG,SAAS,EACvB,gBAAgB,EAChB,KAAK,GAAG,IAAI,EACZ,MAAM,GAAG,IAAI,EACb,YAAY,GACG;IACf,IAAI,YAAY,EAAE,CAAC;QACjB,IAAI,CAAC,SAAS,CAAC,IAAI,iBAAiB,EAAE,EAAE,YAAY,CAAC,CAAC;IACxD,CAAC;IACD,MAAM,GAAG,GAAG,uBAAuB,CACjC,SAAS,IAAI,kBAAkB,EAAE,IAAI,uBAAuB,CAC7D,CAAC;IACF,MAAM,MAAM,GAAG,YAAY,IAAI,YAAY,EAAE,CAAC;IAC9C,MAAM,OAAO,GAAY,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC;QACnD,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC;QACnC,CAAC,CAAC,aAAa,CAAC;IAClB,MAAM,gBAAgB,GAAG,OAAO,MAAM,IAAI,QAAQ,CAAC;IACnD,IAAI,gBAAgB,EAAE,CAAC;QACrB,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,MAAM,EAAE,CAAC;IAChD,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,iBAAiB,CAAC;QACrC,GAAG;QACH,OAAO;KACR,CAAC,CAAC;IACH,IAAI,aAA4B,CAAC;IACjC,IAAI,KAAK,EAAE,CAAC;QACV,aAAa,GAAG,IAAI,+BAA+B,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;IACpE,CAAC;SAAM,CAAC;QACN,aAAa,GAAG,IAAI,gCAAgC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,kBAAkB,CAAC;QACtC,QAAQ,EAAE,sBAAsB,CAAC;YAC/B,CAAC,wBAAwB,CAAC,EAAE,WAAW;SACxC,CAAC;QACF,cAAc,EAAE,CAAC,aAAa,CAAC;KAChC,CAAC,CAAC;IAEH,IAAI,gBAAgB,EAAE,CAAC;QACrB,wBAAwB,CAAC;YACvB,gBAAgB;YAChB,cAAc,EAAE,QAAQ;SACzB,CAAC,CAAC;IACL,CAAC;IACD,IAAI,MAAM,EAAE,CAAC;QACX,QAAQ,CAAC,QAAQ,EAAE,CAAC;IACtB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CAAC,GAAW;IACjD,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;QAChC,OAAO,IAAI,GAAG,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;IAC/C,CAAC;IACD,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;AACjC,CAAC"}