@optimizely-opal/opal-tool-ocp-sdk 0.0.0-OCP-1487.4 → 0.0.0-OCP-1487.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.
package/README.md CHANGED
@@ -7,8 +7,9 @@ A TypeScript SDK for building Opal tools in Optimizely Connect Platform. This SD
7
7
  ## Features
8
8
 
9
9
  - 🎯 **Decorator-based Tool Registration** - Use `@tool` and `@interaction` decorators to easily register functions
10
+ - 🌐 **Global and Regular Tools** - Support for both organization-scoped and global tools
10
11
  - 🔧 **Type-safe Development** - Full TypeScript support with comprehensive type definitions
11
- - 🏗️ **Abstract Base Classes** - Extend `ToolFunction` for standardized request processing
12
+ - 🏗️ **Abstract Base Classes** - Extend `ToolFunction` or `GlobalToolFunction` for standardized request processing
12
13
  - 🔐 **Authentication Support** - OptiID authentication
13
14
  - 🛡️ **Authorization Support** - OptiID token tool authorization
14
15
  - 📝 **Parameter Validation** - Define and validate tool parameters with types
@@ -28,7 +29,14 @@ yarn add @optimizely-opal/opal-tool-ocp-sdk
28
29
 
29
30
  ## Quick Start
30
31
 
31
- Create a tool function class by extending `ToolFunction` and registering your tools and interactions:
32
+ The SDK supports two types of functions:
33
+
34
+ - **Regular Functions** (`ToolFunction`) - Organization-scoped tools that validate customer organization IDs
35
+ - **Global Functions** (`GlobalToolFunction`) - Platform-wide tools that work across all organizations
36
+
37
+ ### Regular Tool Function
38
+
39
+ Create a tool function class by extending `ToolFunction` for organization-scoped tools:
32
40
 
33
41
  ```typescript
34
42
  import { ToolFunction, tool, interaction, ParameterType, InteractionResult, OptiIdAuthData } from '@optimizely-opal/opal-tool-ocp-sdk';
@@ -89,12 +97,12 @@ export class MyToolFunction extends ToolFunction {
89
97
  throw new Error('OptiID authentication required');
90
98
  }
91
99
 
92
- const { customerId, instanceId, accessToken } = authData.credentials;
100
+ const { customer_id, instance_id, access_token } = authData.credentials;
93
101
  return {
94
102
  id: '456',
95
103
  title: params.title,
96
- customerId,
97
- instanceId
104
+ customer_id,
105
+ instance_id
98
106
  };
99
107
  }
100
108
 
@@ -112,7 +120,48 @@ export class MyToolFunction extends ToolFunction {
112
120
  }
113
121
  ```
114
122
 
115
- Your function class inherits a `perform()` method from `ToolFunction` that serves as the main entry point for handling all incoming requests. When called, the SDK automatically:
123
+ ### Global Tool Function
124
+
125
+ Create a global tool function by extending `GlobalToolFunction` for platform-wide tools:
126
+
127
+ ```typescript
128
+ import { GlobalToolFunction, tool, interaction, ParameterType, InteractionResult, OptiIdAuthData } from '@optimizely-opal/opal-tool-ocp-sdk';
129
+
130
+ export class MyGlobalToolFunction extends GlobalToolFunction {
131
+
132
+ @tool({
133
+ name: 'global_utility',
134
+ description: 'A utility tool available to all organizations',
135
+ endpoint: '/global-utility',
136
+ parameters: [
137
+ {
138
+ name: 'operation',
139
+ type: ParameterType.String,
140
+ description: 'The operation to perform',
141
+ required: true
142
+ }
143
+ ],
144
+ isGlobal: true // Mark this tool as global
145
+ })
146
+ async globalUtility(params: { operation: string }, authData?: OptiIdAuthData) {
147
+ return {
148
+ result: `Performed ${params.operation} globally`,
149
+ organizationId: authData?.credentials.customer_id || 'unknown'
150
+ };
151
+ }
152
+ }
153
+ ```
154
+
155
+ ### Function Types and Tool Discovery
156
+
157
+ The SDK provides intelligent tool discovery based on function type:
158
+
159
+ - **Regular Functions** (`ToolFunction`): Can only discover and access non-global tools
160
+ - **Global Functions** (`GlobalToolFunction`): Can only discover and access global tools (marked with `isGlobal: true`)
161
+
162
+ This ensures proper isolation between global platform tools and organization-specific tools.
163
+
164
+ Your function class inherits a `perform()` method from `ToolFunction` or `GlobalToolFunction` that serves as the main entry point for handling all incoming requests. When called, the SDK automatically:
116
165
 
117
166
  - **Routes requests** to your registered tools and interactions based on endpoints
118
167
  - **Handles authentication** and OptiID token validation before calling your methods
@@ -129,6 +178,24 @@ Tools are functions that can be discovered and executed through the OCP platform
129
178
  - Define parameters with types and validation
130
179
  - Can require authentication
131
180
  - Return structured responses
181
+ - Can be **regular tools** (organization-scoped) or **global tools** (platform-wide)
182
+
183
+ #### Regular Tools (Default)
184
+
185
+ Regular tools are scoped to specific organizations and validate that requests come from the same organization:
186
+
187
+ - Validate OptiID organization ID matches the tool's organization
188
+ - Only discoverable by `ToolFunction` instances
189
+ - Default behavior when `isGlobal` is not specified or is `false`
190
+
191
+ #### Global Tools
192
+
193
+ Global tools work across all organizations without organization validation:
194
+
195
+ - Accept OptiID authentication but don't validate organization ID
196
+ - Only discoverable by `GlobalToolFunction` instances
197
+ - Must be explicitly marked with `isGlobal: true` in the `@tool` decorator
198
+ - Useful for platform-wide utilities, shared services, or multi-tenant operations
132
199
 
133
200
  ### Interactions
134
201
 
@@ -175,7 +242,8 @@ The SDK automatically handles OptiID token validation for tool authorization. Op
175
242
 
176
243
  **Token Validation:**
177
244
  - The SDK extracts and validates OptiID tokens from the request body
178
- - Validation includes verifying that requests come from the same organization
245
+ - **Regular Tools**: Validation includes verifying that requests come from the same organization as the tool
246
+ - **Global Tools**: Token validation occurs but organization ID matching is skipped
179
247
  - If validation fails, returns HTTP 403 Unauthorized before reaching your handler methods
180
248
  - No additional configuration needed - validation is handled automatically
181
249
 
@@ -233,6 +301,7 @@ interface ToolConfig {
233
301
  parameters: ParameterConfig[];
234
302
  authRequirements?: AuthRequirementConfig[];
235
303
  endpoint: string;
304
+ isGlobal?: boolean; // Optional: marks tool as global (default: false)
236
305
  }
237
306
  ```
238
307
 
@@ -251,7 +320,7 @@ interface InteractionConfig {
251
320
 
252
321
  #### `ToolFunction`
253
322
 
254
- Abstract base class for OCP functions:
323
+ Abstract base class for organization-scoped OCP functions:
255
324
 
256
325
  ```typescript
257
326
  export abstract class ToolFunction extends Function {
@@ -260,7 +329,20 @@ export abstract class ToolFunction extends Function {
260
329
  }
261
330
  ```
262
331
 
263
- Extend this class and implement your OCP function. The `perform` method automatically routes requests to registered tools.
332
+ Extend this class for regular tools that validate organization IDs. The `perform` method automatically routes requests to registered tools and enforces organization validation.
333
+
334
+ #### `GlobalToolFunction`
335
+
336
+ Abstract base class for global OCP functions:
337
+
338
+ ```typescript
339
+ export abstract class GlobalToolFunction extends Function {
340
+ protected ready(): Promise<boolean>;
341
+ public async perform(): Promise<Response>;
342
+ }
343
+ ```
344
+
345
+ Extend this class for global tools that work across organizations. The `perform` method routes requests to registered tools but skips organization validation for global tools.
264
346
 
265
347
  ### Models
266
348
 
@@ -279,7 +361,14 @@ The SDK automatically provides two important endpoints:
279
361
 
280
362
  ### Discovery Endpoint (`/discovery`)
281
363
 
282
- Returns all registered tools in the proper OCP format for platform integration:
364
+ Returns registered tools in the proper OCP format for platform integration. The discovery endpoint intelligently filters tools based on the function type:
365
+
366
+ - **Regular Functions** (`ToolFunction`): Only returns non-global tools (organization-scoped)
367
+ - **Global Functions** (`GlobalToolFunction`): Only returns global tools (marked with `isGlobal: true`)
368
+
369
+ This ensures proper tool isolation and security boundaries between global and organization-specific tools.
370
+
371
+ Example response for a regular and global function:
283
372
 
284
373
  ```json
285
374
  {
@@ -396,9 +485,9 @@ export class AuthenticatedFunction extends ToolFunction {
396
485
  async secureOperation(params: unknown, authData?: OptiIdAuthData) {
397
486
  if (!authData) throw new Error('OptiID authentication required');
398
487
 
399
- const { customerId, accessToken } = authData.credentials;
488
+ const { customer_id, access_token } = authData.credentials;
400
489
  // Use OptiID credentials for API calls
401
- return { success: true, customerId };
490
+ return { success: true, customer_id };
402
491
  }
403
492
 
404
493
  // Interaction with authentication example
@@ -411,11 +500,11 @@ export class AuthenticatedFunction extends ToolFunction {
411
500
  return new InteractionResult('Authentication required for webhook processing');
412
501
  }
413
502
 
414
- const { customerId } = authData.credentials;
503
+ const { customer_id } = authData.credentials;
415
504
 
416
505
  // Process webhook data with authentication context
417
506
  return new InteractionResult(
418
- `Webhook processed for customer ${customerId}: ${data.eventType}`,
507
+ `Webhook processed for customer ${customer_id}: ${data.eventType}`,
419
508
  `https://app.example.com/events/${data.eventId}`
420
509
  );
421
510
  }
@@ -1,31 +1,15 @@
1
- import { OptiIdAuthData } from '../types/Models';
2
1
  /**
3
- * Common authentication utilities for all function types
2
+ * Authorize a request for regular functions (with organization validation)
3
+ *
4
+ * @param request - The incoming request
5
+ * @returns true if authentication and authorization succeed
4
6
  */
5
- export declare class AuthUtils {
6
- /**
7
- * Validate the OptiID access token
8
- *
9
- * @param accessToken - The access token to validate
10
- * @returns true if the token is valid
11
- */
12
- static validateAccessToken(accessToken: string | undefined): Promise<boolean>;
13
- /**
14
- * Extract and validate basic OptiID authentication data from request
15
- *
16
- * @param request - The incoming request
17
- * @returns object with authData and accessToken, or null if invalid
18
- */
19
- static extractAuthData(request: any): {
20
- authData: OptiIdAuthData;
21
- accessToken: string;
22
- } | null;
23
- /**
24
- * Validate organization ID matches the app context
25
- *
26
- * @param customerId - The customer ID from the auth data
27
- * @returns true if the organization ID is valid
28
- */
29
- static validateOrganizationId(customerId: string | undefined): boolean;
30
- }
7
+ export declare function authorizeRegularRequest(request: any): Promise<boolean>;
8
+ /**
9
+ * Authorize a request for global functions (without organization validation)
10
+ *
11
+ * @param request - The incoming request
12
+ * @returns true if authentication succeeds
13
+ */
14
+ export declare function authorizeGlobalRequest(request: any): Promise<boolean>;
31
15
  //# sourceMappingURL=AuthUtils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AuthUtils.d.ts","sourceRoot":"","sources":["../../src/auth/AuthUtils.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD;;GAEG;AACH,qBAAa,SAAS;IAEpB;;;;;OAKG;WACiB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;IAa1F;;;;;OAKG;WACW,eAAe,CAAC,OAAO,EAAE,GAAG,GAAG;QAAE,QAAQ,EAAE,cAAc,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAWrG;;;;;OAKG;WACW,sBAAsB,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO;CAc9E"}
1
+ {"version":3,"file":"AuthUtils.d.ts","sourceRoot":"","sources":["../../src/auth/AuthUtils.ts"],"names":[],"mappings":"AAkGA;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAE5E;AAED;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAE3E"}
@@ -1,64 +1,108 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AuthUtils = void 0;
3
+ exports.authorizeRegularRequest = authorizeRegularRequest;
4
+ exports.authorizeGlobalRequest = authorizeGlobalRequest;
4
5
  const app_sdk_1 = require("@zaiusinc/app-sdk");
5
6
  const TokenVerifier_1 = require("./TokenVerifier");
6
7
  /**
7
- * Common authentication utilities for all function types
8
+ * Validate the OptiID access token
9
+ *
10
+ * @param accessToken - The access token to validate
11
+ * @returns true if the token is valid
8
12
  */
9
- class AuthUtils {
10
- /**
11
- * Validate the OptiID access token
12
- *
13
- * @param accessToken - The access token to validate
14
- * @returns true if the token is valid
15
- */
16
- static async validateAccessToken(accessToken) {
17
- try {
18
- if (!accessToken) {
19
- return false;
20
- }
21
- const tokenVerifier = await (0, TokenVerifier_1.getTokenVerifier)();
22
- return await tokenVerifier.verify(accessToken);
23
- }
24
- catch (error) {
25
- app_sdk_1.logger.error('OptiID token validation failed:', error);
13
+ async function validateAccessToken(accessToken) {
14
+ try {
15
+ if (!accessToken) {
26
16
  return false;
27
17
  }
18
+ const tokenVerifier = await (0, TokenVerifier_1.getTokenVerifier)();
19
+ return await tokenVerifier.verify(accessToken);
28
20
  }
29
- /**
30
- * Extract and validate basic OptiID authentication data from request
31
- *
32
- * @param request - The incoming request
33
- * @returns object with authData and accessToken, or null if invalid
34
- */
35
- static extractAuthData(request) {
36
- const authData = request?.bodyJSON?.auth;
37
- const accessToken = authData?.credentials?.access_token;
38
- if (!accessToken || authData?.provider?.toLowerCase() !== 'optiid') {
39
- app_sdk_1.logger.error('OptiID token is required but not provided');
40
- return null;
41
- }
42
- return { authData, accessToken };
21
+ catch (error) {
22
+ app_sdk_1.logger.error('OptiID token validation failed:', error);
23
+ return false;
43
24
  }
44
- /**
45
- * Validate organization ID matches the app context
46
- *
47
- * @param customerId - The customer ID from the auth data
48
- * @returns true if the organization ID is valid
49
- */
50
- static validateOrganizationId(customerId) {
51
- if (!customerId) {
52
- app_sdk_1.logger.error('Organisation ID is required but not provided');
53
- return false;
54
- }
55
- const appOrganisationId = (0, app_sdk_1.getAppContext)()?.account?.organizationId;
56
- if (customerId !== appOrganisationId) {
57
- app_sdk_1.logger.error(`Invalid organisation ID: expected ${appOrganisationId}, received ${customerId}`);
58
- return false;
59
- }
25
+ }
26
+ /**
27
+ * Extract and validate basic OptiID authentication data from request
28
+ *
29
+ * @param request - The incoming request
30
+ * @returns object with authData and accessToken, or null if invalid
31
+ */
32
+ function extractAuthData(request) {
33
+ const authData = request?.bodyJSON?.auth;
34
+ const accessToken = authData?.credentials?.access_token;
35
+ if (!accessToken || authData?.provider?.toLowerCase() !== 'optiid') {
36
+ app_sdk_1.logger.error('OptiID token is required but not provided');
37
+ return null;
38
+ }
39
+ return { authData, accessToken };
40
+ }
41
+ /**
42
+ * Validate organization ID matches the app context
43
+ *
44
+ * @param customerId - The customer ID from the auth data
45
+ * @returns true if the organization ID is valid
46
+ */
47
+ function validateOrganizationId(customerId) {
48
+ if (!customerId) {
49
+ app_sdk_1.logger.error('Organisation ID is required but not provided');
50
+ return false;
51
+ }
52
+ const appOrganisationId = (0, app_sdk_1.getAppContext)()?.account?.organizationId;
53
+ if (customerId !== appOrganisationId) {
54
+ app_sdk_1.logger.error(`Invalid organisation ID: expected ${appOrganisationId}, received ${customerId}`);
55
+ return false;
56
+ }
57
+ return true;
58
+ }
59
+ /**
60
+ * Check if a request should skip authentication (discovery/ready endpoints)
61
+ *
62
+ * @param request - The incoming request
63
+ * @returns true if auth should be skipped
64
+ */
65
+ function shouldSkipAuth(request) {
66
+ return request.path === '/discovery' || request.path === '/ready';
67
+ }
68
+ /**
69
+ * Core authentication flow - extracts auth data and validates token
70
+ *
71
+ * @param request - The incoming request
72
+ * @param validateOrg - Whether to validate organization ID
73
+ * @returns true if authentication succeeds
74
+ */
75
+ async function authenticateRequest(request, validateOrg = false) {
76
+ if (shouldSkipAuth(request)) {
60
77
  return true;
61
78
  }
79
+ const authInfo = extractAuthData(request);
80
+ if (!authInfo) {
81
+ return false;
82
+ }
83
+ const { authData, accessToken } = authInfo;
84
+ // Validate organization ID if required
85
+ if (validateOrg && !validateOrganizationId(authData.credentials?.customer_id)) {
86
+ return false;
87
+ }
88
+ return await validateAccessToken(accessToken);
89
+ }
90
+ /**
91
+ * Authorize a request for regular functions (with organization validation)
92
+ *
93
+ * @param request - The incoming request
94
+ * @returns true if authentication and authorization succeed
95
+ */
96
+ async function authorizeRegularRequest(request) {
97
+ return await authenticateRequest(request, true);
98
+ }
99
+ /**
100
+ * Authorize a request for global functions (without organization validation)
101
+ *
102
+ * @param request - The incoming request
103
+ * @returns true if authentication succeeds
104
+ */
105
+ async function authorizeGlobalRequest(request) {
106
+ return await authenticateRequest(request, false);
62
107
  }
63
- exports.AuthUtils = AuthUtils;
64
108
  //# sourceMappingURL=AuthUtils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"AuthUtils.js","sourceRoot":"","sources":["../../src/auth/AuthUtils.ts"],"names":[],"mappings":";;;AAAA,+CAA0D;AAC1D,mDAAmD;AAGnD;;GAEG;AACH,MAAa,SAAS;IAEpB;;;;;OAKG;IACI,MAAM,CAAC,KAAK,CAAC,mBAAmB,CAAC,WAA+B;QACrE,IAAI,CAAC;YACH,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,OAAO,KAAK,CAAC;YACf,CAAC;YACD,MAAM,aAAa,GAAG,MAAM,IAAA,gCAAgB,GAAE,CAAC;YAC/C,OAAO,MAAM,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QACjD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,gBAAM,CAAC,KAAK,CAAC,iCAAiC,EAAE,KAAK,CAAC,CAAC;YACvD,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,eAAe,CAAC,OAAY;QACxC,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,EAAE,IAAsB,CAAC;QAC3D,MAAM,WAAW,GAAG,QAAQ,EAAE,WAAW,EAAE,YAAY,CAAC;QACxD,IAAI,CAAC,WAAW,IAAI,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,QAAQ,EAAE,CAAC;YACnE,gBAAM,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;YAC1D,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;IACnC,CAAC;IAED;;;;;OAKG;IACI,MAAM,CAAC,sBAAsB,CAAC,UAA8B;QACjE,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,gBAAM,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;YAC7D,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,iBAAiB,GAAG,IAAA,uBAAa,GAAE,EAAE,OAAO,EAAE,cAAc,CAAC;QACnE,IAAI,UAAU,KAAK,iBAAiB,EAAE,CAAC;YACrC,gBAAM,CAAC,KAAK,CAAC,qCAAqC,iBAAiB,cAAc,UAAU,EAAE,CAAC,CAAC;YAC/F,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AA1DD,8BA0DC"}
1
+ {"version":3,"file":"AuthUtils.js","sourceRoot":"","sources":["../../src/auth/AuthUtils.ts"],"names":[],"mappings":";;AAwGA,0DAEC;AAQD,wDAEC;AApHD,+CAA0D;AAC1D,mDAAmD;AAGnD;;;;;GAKG;AACH,KAAK,UAAU,mBAAmB,CAAC,WAA+B;IAChE,IAAI,CAAC;QACH,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,aAAa,GAAG,MAAM,IAAA,gCAAgB,GAAE,CAAC;QAC/C,OAAO,MAAM,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACjD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,gBAAM,CAAC,KAAK,CAAC,iCAAiC,EAAE,KAAK,CAAC,CAAC;QACvD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,eAAe,CAAC,OAAY;IACnC,MAAM,QAAQ,GAAG,OAAO,EAAE,QAAQ,EAAE,IAAsB,CAAC;IAC3D,MAAM,WAAW,GAAG,QAAQ,EAAE,WAAW,EAAE,YAAY,CAAC;IACxD,IAAI,CAAC,WAAW,IAAI,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,QAAQ,EAAE,CAAC;QACnE,gBAAM,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC1D,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;AACnC,CAAC;AAED;;;;;GAKG;AACH,SAAS,sBAAsB,CAAC,UAA8B;IAC5D,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,gBAAM,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAC7D,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,iBAAiB,GAAG,IAAA,uBAAa,GAAE,EAAE,OAAO,EAAE,cAAc,CAAC;IACnE,IAAI,UAAU,KAAK,iBAAiB,EAAE,CAAC;QACrC,gBAAM,CAAC,KAAK,CAAC,qCAAqC,iBAAiB,cAAc,UAAU,EAAE,CAAC,CAAC;QAC/F,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,SAAS,cAAc,CAAC,OAAY;IAClC,OAAO,OAAO,CAAC,IAAI,KAAK,YAAY,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC;AACpE,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,mBAAmB,CAAC,OAAY,EAAE,cAAuB,KAAK;IAC3E,IAAI,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IAC1C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,GAAG,QAAQ,CAAC;IAE3C,uCAAuC;IACvC,IAAI,WAAW,IAAI,CAAC,sBAAsB,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC;QAC9E,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,MAAM,mBAAmB,CAAC,WAAW,CAAC,CAAC;AAChD,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,uBAAuB,CAAC,OAAY;IACxD,OAAO,MAAM,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;AAClD,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,sBAAsB,CAAC,OAAY;IACvD,OAAO,MAAM,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;AACnD,CAAC"}