@pipeline-builder/api-server 4.4.2 → 4.4.4

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.
@@ -24,6 +24,7 @@ export interface MetricHelpers {
24
24
  incCounter(name: string, labels?: Record<string, string>, value?: number): void;
25
25
  observe(name: string, labels: Record<string, string>, value: number): void;
26
26
  setGauge(name: string, labels: Record<string, string>, value: number): void;
27
+ resetGauge(name: string): void;
27
28
  }
28
29
  /**
29
30
  * Build `incCounter` / `observe` / `setGauge` over a caller-supplied registry.
@@ -45,12 +46,19 @@ export declare function createMetricHelpers(registry: Registry | (() => Registry
45
46
  /**
46
47
  * Increment a business counter, creating it on first use.
47
48
  *
49
+ * Every example below is a call that EXISTS, with the labels it really passes. That is
50
+ * deliberate: an invented example reads as an inventory of what the system measures, and
51
+ * a metrics survey later counted three names from this block — `pipelines_generated_total`,
52
+ * `quota_threshold_crossed_total`, `compliance_violations_found_total` — as live metrics
53
+ * missing a dashboard panel. Nothing emitted any of them. Illustrative names in a docstring
54
+ * about metric naming are indistinguishable from real ones, so there are none here.
55
+ *
48
56
  * @example
49
57
  * ```typescript
50
- * incCounter('pipelines_generated_total', { provider: 'anthropic' });
51
- * incCounter('plugin_builds_total', { status: 'completed' });
52
- * incCounter('quota_threshold_crossed_total', { type: 'aiCalls', tier: 'pro' });
53
- * incCounter('compliance_violations_found_total', { severity: 'critical' });
58
+ * incCounter('plugin_builds_total', { status: 'success', org_id: orgId });
59
+ * incCounter('compliance_scans_total', { outcome: 'started' });
60
+ * incCounter('plugin_vuln_findings_total', { trigger, severity }, count);
61
+ * incCounter('ai_tokens_total', { route: 'agent', kind: 'input' }, inputTokens);
54
62
  * ```
55
63
  */
56
64
  export declare function incCounter(name: string, labels?: Record<string, string>, value?: number): void;
@@ -60,8 +68,8 @@ export declare function incCounter(name: string, labels?: Record<string, string>
60
68
  *
61
69
  * @example
62
70
  * ```typescript
63
- * observe('ai_generation_duration_seconds', { provider: 'anthropic', model: 'sonnet' }, durationSec);
64
- * observe('plugin_build_duration_seconds', { buildType: 'docker' }, durationSec);
71
+ * observe('ai_generation_duration_seconds', { route, provider: providerLabel }, durationSec);
72
+ * observe('plugin_build_duration_seconds', { org_id: orgId }, durationSec);
65
73
  * ```
66
74
  */
67
75
  export declare function observe(name: string, labels: Record<string, string>, value: number): void;
@@ -77,3 +85,11 @@ export declare function observe(name: string, labels: Record<string, string>, va
77
85
  * ```
78
86
  */
79
87
  export declare function setGauge(name: string, labels: Record<string, string>, value: number): void;
88
+ /**
89
+ * Drop EVERY series of a business gauge. For a gauge that describes a SET — one
90
+ * series per configured entry — and is re-published whole: without the reset, a
91
+ * series for an entry that has since been deleted keeps its last value forever,
92
+ * and an alert on it keeps firing for something that no longer exists. Call it
93
+ * immediately before re-setting the current set. A gauge never set is a no-op.
94
+ */
95
+ export declare function resetGauge(name: string): void;
@@ -155,6 +155,77 @@ export function metricsHandler() {
155
155
  res.end(await register.metrics());
156
156
  };
157
157
  }
158
+ // ---------------------------------------------------------------------------
159
+ // Business / domain metrics
160
+ //
161
+ // Services should emit counters for the things operators actually care about
162
+ // (pipelines generated, plugin builds completed, compliance violations,
163
+ // AI tokens consumed) — not just HTTP traffic. The helpers below register
164
+ // counters lazily on the shared registry so multiple services can call
165
+ // `incCounter('plugin_builds_total', { status: 'completed' })` without
166
+ // worrying about double-registration.
167
+ //
168
+ // Naming convention: `<domain>_<noun>_total` for counters, `_seconds` for
169
+ // histograms — matches Prometheus best-practice.
170
+ // ---------------------------------------------------------------------------
171
+ /**
172
+ * Bucket distributions for histograms whose observations are nowhere near the
173
+ * sub-second-to-minutes default.
174
+ *
175
+ * THIS TABLE EXISTS BECAUSE THE DEFAULT SILENTLY BREAKS ALERTS. The default set
176
+ * below ends at a 300-second bucket, and `histogram_quantile` cannot interpolate
177
+ * past the last FINITE boundary — everything above it lands in `+Inf` and the
178
+ * quantile reads back as 300 forever. An alert of the form `> 300` on such a
179
+ * histogram can therefore never fire, and a p90 panel flat-lines at five
180
+ * minutes however bad things get. Nothing errors, nothing is missing from the
181
+ * scrape, and the dashboard looks healthy: the only symptom is an alert that
182
+ * stays quiet through an outage. `support_first_response_seconds` measures hours
183
+ * to days and had a threshold of twelve hours sitting above a ceiling of five
184
+ * minutes.
185
+ *
186
+ * So a histogram whose natural range is minutes-to-days declares its buckets
187
+ * here, and ALERT THRESHOLDS ARE PUT ON BOUNDARIES: a threshold inside a wide
188
+ * bucket is served by linear interpolation across that bucket, which is a guess,
189
+ * while a threshold ON a boundary is exact. For support that means 6h (the alert)
190
+ * and 8h (the sold target) are both boundaries, 24h is the operational guard
191
+ * from the standard/priority rule, and 96h covers the longest legitimate wait a
192
+ * business-day target allows — a priority case raised at 17:01 on a Friday.
193
+ *
194
+ * Add a metric here when its observations can exceed five minutes. The table is
195
+ * read on FIRST USE of each name by `createMetricHelpers`, so both registries
196
+ * (api-server's and platform's own) get the same distribution, which is the
197
+ * drift the factory exists to prevent.
198
+ */
199
+ const HISTOGRAM_BUCKETS = {
200
+ // 15m, 1h, 2h, 4h, 6h, 8h, 12h, 24h, 48h, 96h.
201
+ support_first_response_seconds: [900, 3600, 7200, 14400, 21600, 28800, 43200, 86400, 172800, 345600],
202
+ // Submission-to-decision latency is a human review queue: hours to days.
203
+ // 15m, 1h, 4h, 12h, 1d, 2d, 4d, 7d, 14d.
204
+ ecosystem_decision_latency_seconds: [900, 3600, 14400, 43200, 86400, 172800, 345600, 604800, 1209600],
205
+ // Queue wait. `PluginQueueProcessingSlow` asserts p95 > 300, which the default
206
+ // ceiling of 300 made unfireable; 300 is a boundary here so the comparison is
207
+ // exact rather than interpolated.
208
+ plugin_job_wait_seconds: [1, 5, 15, 30, 60, 120, 300, 600, 1800, 3600],
209
+ // A container build. Minutes normally, far longer for a cold base image.
210
+ plugin_build_duration_seconds: [10, 30, 60, 120, 300, 600, 1200, 1800, 3600],
211
+ // A full image scan, which routinely passes five minutes on a large image.
212
+ plugin_vuln_scan_duration_seconds: [1, 5, 15, 30, 60, 120, 300, 600, 1200],
213
+ // Time from an incident being raised to a human acknowledging it. The default
214
+ // buckets end at 300s, and `histogram_quantile` cannot interpolate past the
215
+ // last finite boundary — so with them, any threshold above five minutes could
216
+ // never fire, which is every threshold worth setting here. Boundaries at 1m,
217
+ // 2m, 5m, 10m, 15m, 30m, 1h, 2h, 4h: 15m is exact because that is the
218
+ // escalation delay the alert compares against, and the range reaches 4h so a
219
+ // page nobody ever picked up is still counted rather than clipped.
220
+ oncall_page_ack_seconds: [60, 120, 300, 600, 900, 1800, 3600, 7200, 14400],
221
+ // CSAT, 1-5. Not a duration at all, and listed here for the same reason as
222
+ // the others: the default buckets are sub-second, so every rating would land
223
+ // in the same bucket and the quantile would be meaningless. One boundary per
224
+ // possible score makes `_sum / _count` an exact average and each bucket a
225
+ // real count. It rides the histogram rather than a counter-per-score so the
226
+ // average needs no PromQL arithmetic over five series.
227
+ support_satisfaction: [1, 2, 3, 4, 5],
228
+ };
158
229
  /**
159
230
  * Build `incCounter` / `observe` / `setGauge` over a caller-supplied registry.
160
231
  *
@@ -197,10 +268,12 @@ export function createMetricHelpers(registry) {
197
268
  name,
198
269
  help: humanizeName(name),
199
270
  labelNames: Object.keys(labels),
200
- // Default buckets target sub-second through several-minute observations.
201
- // Override by registering the histogram explicitly before first call
202
- // if you need a different bucket distribution.
203
- buckets: [0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30, 60, 120, 300],
271
+ // Default buckets target sub-second through several-minute
272
+ // observations. Anything that can exceed five minutes MUST declare its
273
+ // own distribution in `HISTOGRAM_BUCKETS` above — past the last finite
274
+ // boundary a quantile reads back as that boundary, so a threshold
275
+ // beyond it never fires.
276
+ buckets: [...(HISTOGRAM_BUCKETS[name] ?? [0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10, 30, 60, 120, 300])],
204
277
  registers: [registryOf()],
205
278
  });
206
279
  histograms.set(name, hist);
@@ -220,6 +293,9 @@ export function createMetricHelpers(registry) {
220
293
  }
221
294
  gauge.set(labels, value);
222
295
  },
296
+ resetGauge(name) {
297
+ gauges.get(name)?.reset();
298
+ },
223
299
  };
224
300
  }
225
301
  /** This service's own helpers, over the shared module-level registry. */
@@ -227,12 +303,19 @@ const businessMetrics = createMetricHelpers(register);
227
303
  /**
228
304
  * Increment a business counter, creating it on first use.
229
305
  *
306
+ * Every example below is a call that EXISTS, with the labels it really passes. That is
307
+ * deliberate: an invented example reads as an inventory of what the system measures, and
308
+ * a metrics survey later counted three names from this block — `pipelines_generated_total`,
309
+ * `quota_threshold_crossed_total`, `compliance_violations_found_total` — as live metrics
310
+ * missing a dashboard panel. Nothing emitted any of them. Illustrative names in a docstring
311
+ * about metric naming are indistinguishable from real ones, so there are none here.
312
+ *
230
313
  * @example
231
314
  * ```typescript
232
- * incCounter('pipelines_generated_total', { provider: 'anthropic' });
233
- * incCounter('plugin_builds_total', { status: 'completed' });
234
- * incCounter('quota_threshold_crossed_total', { type: 'aiCalls', tier: 'pro' });
235
- * incCounter('compliance_violations_found_total', { severity: 'critical' });
315
+ * incCounter('plugin_builds_total', { status: 'success', org_id: orgId });
316
+ * incCounter('compliance_scans_total', { outcome: 'started' });
317
+ * incCounter('plugin_vuln_findings_total', { trigger, severity }, count);
318
+ * incCounter('ai_tokens_total', { route: 'agent', kind: 'input' }, inputTokens);
236
319
  * ```
237
320
  */
238
321
  export function incCounter(name, labels = {}, value = 1) {
@@ -244,8 +327,8 @@ export function incCounter(name, labels = {}, value = 1) {
244
327
  *
245
328
  * @example
246
329
  * ```typescript
247
- * observe('ai_generation_duration_seconds', { provider: 'anthropic', model: 'sonnet' }, durationSec);
248
- * observe('plugin_build_duration_seconds', { buildType: 'docker' }, durationSec);
330
+ * observe('ai_generation_duration_seconds', { route, provider: providerLabel }, durationSec);
331
+ * observe('plugin_build_duration_seconds', { org_id: orgId }, durationSec);
249
332
  * ```
250
333
  */
251
334
  export function observe(name, labels, value) {
@@ -265,10 +348,20 @@ export function observe(name, labels, value) {
265
348
  export function setGauge(name, labels, value) {
266
349
  businessMetrics.setGauge(name, labels, value);
267
350
  }
351
+ /**
352
+ * Drop EVERY series of a business gauge. For a gauge that describes a SET — one
353
+ * series per configured entry — and is re-published whole: without the reset, a
354
+ * series for an entry that has since been deleted keeps its last value forever,
355
+ * and an alert on it keeps firing for something that no longer exists. Call it
356
+ * immediately before re-setting the current set. A gauge never set is a no-op.
357
+ */
358
+ export function resetGauge(name) {
359
+ businessMetrics.resetGauge(name);
360
+ }
268
361
  function humanizeName(metricName) {
269
- // `pipelines_generated_total` → "Pipelines generated total"
362
+ // `plugin_builds_total` → "Plugin builds total"
270
363
  return metricName
271
364
  .replace(/_/g, ' ')
272
365
  .replace(/^./, (c) => c.toUpperCase());
273
366
  }
274
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hcGkvbWV0cmljcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSw4QkFBOEIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ2xHLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUV6RCxPQUFPLEVBQUUsUUFBUSxFQUFFLHFCQUFxQixFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRXpGLE1BQU0sWUFBWSxHQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsZUFBZSxDQUE2QixDQUFDLFdBQVcsQ0FBQztBQUU3RixpQ0FBaUM7QUFDakMsTUFBTSxRQUFRLEdBQUcsSUFBSSxRQUFRLEVBQUUsQ0FBQztBQUVoQyxxQ0FBcUM7QUFDckMsUUFBUSxDQUFDLGdCQUFnQixDQUFDLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUM7QUFFckQsa0ZBQWtGO0FBQ2xGLHFCQUFxQixDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztBQUVwQzs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUsMkJBQTJCLENBQUMsUUFBa0I7SUFDNUQsT0FBTyxJQUFJLEtBQUssQ0FBQztRQUNmLElBQUksRUFBRSw4QkFBOEI7UUFDcEMsSUFBSSxFQUFFLGtLQUFrSztRQUN4SyxVQUFVLEVBQUUsQ0FBQyxRQUFRLENBQVU7UUFDL0IsU0FBUyxFQUFFLENBQUMsUUFBUSxDQUFDO1FBQ3JCLE9BQU87WUFDTCxLQUFLLE1BQU0sRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLElBQUksb0JBQW9CLEVBQUUsRUFBRSxDQUFDO2dCQUM3RCxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsTUFBTSxFQUFFLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQyxD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O0FBQ0gsTUFBTSxVQUFVLFVBQVUsQ0FBQyxJQUFZLEVBQUUsTUFBTSxHQUEyQixFQUFFLEVBQUUsS0FBSyxHQUFHLENBQUM7SUFDckYsZUFBZSxDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQ2xELENBQUM7QUFFRDs7Ozs7Ozs7O0dBU0c7QUFDSCxNQUFNLFVBQVUsT0FBTyxDQUFDLElBQVksRUFBRSxNQUE4QixFQUFFLEtBQWE7SUFDakYsZUFBZSxDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQy9DLENBQUM7QUFFRDs7Ozs7Ozs7OztHQVVHO0FBQ0gsTUFBTSxVQUFVLFFBQVEsQ0FBQyxJQUFZLEVBQUUsTUFBOEIsRUFBRSxLQUFhO0lBQ2xGLGVBQWUsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLE1BQU0sRUFBRSxLQUFLLENBQUMsQ0FBQztBQUNoRCxDQUFDO0FBRUQsU0FBUyxZQUFZLENBQUMsVUFBa0I7SUFDdEMsNERBQTREO0lBQzVELE9BQU8sVUFBVTtTQUNkLE9BQU8sQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDO1NBQ2xCLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO0FBQzNDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHsgcHJldmlvdXNTZWNyZXRTdGF0ZXMsIFNFQ1JFVF9ST1RBVElPTl9QUkVWSU9VU19HQVVHRSB9IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL2FwaS1jb3JlJztcbmltcG9ydCB7IENvbmZpZyB9IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL3BpcGVsaW5lLWNvcmUnO1xuaW1wb3J0IHR5cGUgeyBSZXF1ZXN0LCBSZXNwb25zZSwgTmV4dEZ1bmN0aW9uIH0gZnJvbSAnZXhwcmVzcyc7XG5pbXBvcnQgeyBSZWdpc3RyeSwgY29sbGVjdERlZmF1bHRNZXRyaWNzLCBDb3VudGVyLCBIaXN0b2dyYW0sIEdhdWdlIH0gZnJvbSAncHJvbS1jbGllbnQnO1xuXG5jb25zdCBTRVJWSUNFX05BTUUgPSAoQ29uZmlnLmdldEFueSgnb2JzZXJ2YWJpbGl0eScpIGFzIHsgc2VydmljZU5hbWU6IHN0cmluZyB9KS5zZXJ2aWNlTmFtZTtcblxuLyoqIFNoYXJlZCBQcm9tZXRoZXVzIHJlZ2lzdHJ5ICovXG5jb25zdCByZWdpc3RlciA9IG5ldyBSZWdpc3RyeSgpO1xuXG4vLyBTZXQgZGVmYXVsdCBsYWJlbHMgZm9yIGFsbCBtZXRyaWNzXG5yZWdpc3Rlci5zZXREZWZhdWx0TGFiZWxzKHsgc2VydmljZTogU0VSVklDRV9OQU1FIH0pO1xuXG4vLyBDb2xsZWN0IGRlZmF1bHQgTm9kZS5qcyBwcm9jZXNzIG1ldHJpY3MgKENQVSwgbWVtb3J5LCBoZWFwLCBldmVudCBsb29wIGxhZywgR0MpXG5jb2xsZWN0RGVmYXVsdE1ldHJpY3MoeyByZWdpc3RlciB9KTtcblxuLyoqXG4gKiBSZWdpc3RlciB0aGUgYHNlY3JldF9yb3RhdGlvbl9wcmV2aW91c19zZXR7c2VjcmV0fWAgZ2F1Z2Ugb24gYHJlZ2lzdHJ5YDogMVxuICogd2hpbGUgYSBzZWNyZXQncyBgKl9QUkVWSU9VU2Agcm90YXRpb24gdmFsdWUgaXMgc3RpbGwgc2V0LCAwIG90aGVyd2lzZS4gVGhlXG4gKiB2YWx1ZSBpcyByZWFkIGZyb20gYXBpLWNvcmUncyBwcm9iZSByZWdpc3RyeSBhdCBzY3JhcGUgdGltZSwgc28gaXQgYWx3YXlzXG4gKiByZWZsZWN0cyB0aGUgbGl2ZSBwcm9jZXNzLiBFeHBvcnRlZCBzbyBwbGF0Zm9ybSAob3duIHJlZ2lzdHJ5KSBleHBvc2VzIHRoZVxuICogaWRlbnRpY2FsIHNlcmllczsgdGhlIGBTZWNyZXRSb3RhdGlvblByZXZpb3VzTGluZ2VyaW5nYCBhbGVydCBrZXlzIG9uIGl0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJTZWNyZXRSb3RhdGlvbkdhdWdlKHJlZ2lzdHJ5OiBSZWdpc3RyeSk6IEdhdWdlPCdzZWNyZXQnPiB7XG4gIHJldHVybiBuZXcgR2F1Z2Uoe1xuICAgIG5hbWU6IFNFQ1JFVF9ST1RBVElPTl9QUkVWSU9VU19HQVVHRSxcbiAgICBoZWxwOiAnMSB3aGlsZSBhIHNlY3JldCByb3RhdGlvbiBwcmV2aW91cyB2YWx1ZSAoZS5nLiBTRUNSRVRfRU5DUllQVElPTl9LRVlfUFJFVklPVVMpIG9yIGEgcmV0aXJpbmcgc2lnbmluZyBrZXkgaXMgc3RpbGwgYWNjZXB0ZWQ7IHNlZSBkb2NzL3J1bmJvb2tzL3NlY3JldC1yb3RhdGlvbi5tZCcsXG4gICAgbGFiZWxOYW1lczogWydzZWNyZXQnXSBhcyBjb25zdCxcbiAgICByZWdpc3RlcnM6IFtyZWdpc3RyeV0sXG4gICAgY29sbGVjdCgpIHtcbiAgICAgIGZvciAoY29uc3QgeyBzZWNyZXQsIHByZXZpb3VzU2V0IH0gb2YgcHJldmlvdXNTZWNyZXRTdGF0ZXMoKSkge1xuICAgICAgICB0aGlzLnNldCh7IHNlY3JldCB9LCBwcmV2aW91c1NldCA/IDEgOiAwKTtcbiAgICAgIH1cbiAgICB9LFxuICB9KTtcbn1cblxucmVnaXN0ZXJTZWNyZXRSb3RhdGlvbkdhdWdlKHJlZ2lzdGVyKTtcblxuLyoqIEhUVFAgcmVxdWVzdCBkdXJhdGlvbiBoaXN0b2dyYW0gKHNlY29uZHMpICovXG5jb25zdCBodHRwUmVxdWVzdER1cmF0aW9uID0gbmV3IEhpc3RvZ3JhbSh7XG4gIG5hbWU6ICdodHRwX3JlcXVlc3RfZHVyYXRpb25fc2Vjb25kcycsXG4gIGhlbHA6ICdEdXJhdGlvbiBvZiBIVFRQIHJlcXVlc3RzIGluIHNlY29uZHMnLFxuICBsYWJlbE5hbWVzOiBbJ21ldGhvZCcsICdyb3V0ZScsICdzdGF0dXNfY29kZSddIGFzIGNvbnN0LFxuICBidWNrZXRzOiBbMC4wMDUsIDAuMDEsIDAuMDI1LCAwLjA1LCAwLjEsIDAuMjUsIDAuNSwgMSwgMi41LCA1LCAxMF0sXG4gIHJlZ2lzdGVyczogW3JlZ2lzdGVyXSxcbn0pO1xuXG4vKiogSFRUUCByZXF1ZXN0IGNvdW50ZXIgKi9cbmNvbnN0IGh0dHBSZXF1ZXN0c1RvdGFsID0gbmV3IENvdW50ZXIoe1xuICBuYW1lOiAnaHR0cF9yZXF1ZXN0c190b3RhbCcsXG4gIGhlbHA6ICdUb3RhbCBudW1iZXIgb2YgSFRUUCByZXF1ZXN0cycsXG4gIGxhYmVsTmFtZXM6IFsnbWV0aG9kJywgJ3JvdXRlJywgJ3N0YXR1c19jb2RlJ10gYXMgY29uc3QsXG4gIHJlZ2lzdGVyczogW3JlZ2lzdGVyXSxcbn0pO1xuXG4vKipcbiAqIFBlci1vcmcgSFRUUCByZXF1ZXN0IGNvdW50ZXIg4oCUIFNBTVBMRUQgdG8ga2VlcCBQcm9tZXRoZXVzIGNhcmRpbmFsaXR5XG4gKiB1bmRlciBjb250cm9sLiBDYXJkaW5hbGl0eSBvZiBgb3JnX2lkICogbWV0aG9kICogcm91dGUgKiBzdGF0dXNfY29kZWBcbiAqIGdyb3dzIG11bHRpcGxpY2F0aXZlbHk7IHdpdGggTiBvcmdzICogNTAgcm91dGVzICogNSBzdGF0dXNfY29kZXMgdGhhdCdzXG4gKiAyNTDDl04gc2VyaWVzLiBXZSBzYW1wbGUgMS1pbi1OIHJlcXVlc3RzIChjb25maWd1cmFibGUgdmlhXG4gKiBgSFRUUF9NRVRSSUNTX09SR19TQU1QTEVfUkFURWAsIGRlZmF1bHQgMCA9IG9mZikuXG4gKlxuICogT3BlcmF0b3JzIGFuc3dlciBcIndoYXQncyBvcmcgWCdzIHA5OT9cIiB2aWEgc2VwYXJhdGUgcGVyLW9yZyBoaXN0b2dyYW1zXG4gKiBzY3JhcGVkIGF0IGEgbG93ZXIgcmF0ZSwgT1IgdmlhIExva2kgTG9nUUwgcXVlcmllcyBhZ2FpbnN0IHRoZVxuICogdW5zYW1wbGVkIGFjY2Vzcy1sb2cgc3RyZWFtLiBUaGlzIGNvdW50ZXIgaXMgdGhlIGZhc3QtcGF0aCBcIm5vaXN5XG4gKiBuZWlnaGJvciBkZXRlY3Rpb25cIiDigJQgb3BlcmF0b3JzIGFsZXJ0IHdoZW4gb25lIG9yZydzIHJlcXVlc3QgcmF0ZVxuICogZGV2aWF0ZXMgZnJvbSB0aGUgZmxlZXQgbWVkaWFuLlxuICpcbiAqIE5PVCBhIGhpc3RvZ3JhbTogaGlzdG9ncmFtIGxhYmVsIGNhcmRpbmFsaXR5IGlzIGV2ZW4gbW9yZSBzZW5zaXRpdmVcbiAqIChlYWNoIGJ1Y2tldCBpcyBhIHNlcGFyYXRlIHNlcmllcykuIElmIHBlci1vcmcgbGF0ZW5jeSBwZXJjZW50aWxlcyBhcmVcbiAqIG5lZWRlZCBsYXRlciwgYWRkIGEgc2VwYXJhdGUgaGlzdG9ncmFtIHdpdGggYSBjb2Fyc2VyIGJ1Y2tldCBzZXQgYW5kXG4gKiBsb3dlciBzYW1wbGUgcmF0ZS5cbiAqL1xuY29uc3QgaHR0cFJlcXVlc3RzQnlPcmdUb3RhbCA9IG5ldyBDb3VudGVyKHtcbiAgbmFtZTogJ2h0dHBfcmVxdWVzdHNfYnlfb3JnX3RvdGFsJyxcbiAgaGVscDogJ1NhbXBsZWQgcGVyLW9yZyBIVFRQIHJlcXVlc3QgY291bnQgKHNhbXBsZSByYXRlIHZpYSBIVFRQX01FVFJJQ1NfT1JHX1NBTVBMRV9SQVRFKScsXG4gIGxhYmVsTmFtZXM6IFsnbWV0aG9kJywgJ3JvdXRlJywgJ3N0YXR1c19jb2RlJywgJ29yZ19pZCddIGFzIGNvbnN0LFxuICByZWdpc3RlcnM6IFtyZWdpc3Rlcl0sXG59KTtcblxuLyoqXG4gKiBTYW1wbGUgcmF0ZSBmb3IgdGhlIHBlci1vcmcgY291bnRlci4gMS4wID0gZXZlcnkgcmVxdWVzdCwgMC4wID0gZGlzYWJsZWQuXG4gKiBQYXJzZWQgb25jZSBhdCBtb2R1bGUgbG9hZCDigJQgb3BlcmF0b3JzIHR1bmUgYnkgcmVzdGFydGluZyB0aGUgc2VydmljZS5cbiAqXG4gKiBEZWZhdWx0cyB0byAwIChPRkYpLiBgb3JnX2lkYCBpcyBhbiBVTkJPVU5ERUQsIHRlbmFudC1pZGVudGlmeWluZyBsYWJlbCBhbmRcbiAqIHByb20tY2xpZW50IGNvdW50ZXJzIG5ldmVyIGV4cGlyZSwgc28gYXQgMS4wIGV2ZXJ5IHNlcnZpY2UgYWNjdW11bGF0ZXMgYVxuICogc2VyaWVzIHBlciAob3JnIMOXIHJvdXRlIMOXIHN0YXR1cykgZm9yIHRoZSBwcm9jZXNzIGxpZmV0aW1lLCBhbmQgYC9tZXRyaWNzYCDigJRcbiAqIHdoaWNoIGlzIG5vdCBhdXRoLWdhdGVkIOKAlCBlbnVtZXJhdGVzIGV2ZXJ5IHRlbmFudCBpZCBhbG9uZyB3aXRoIGl0cyByZXF1ZXN0XG4gKiB2b2x1bWUgYW5kIGVycm9yIHJhdGUgdG8gYW55b25lIHdobyBjYW4gcmVhY2ggdGhlIHBvcnQuXG4gKlxuICogVHVybiBpdCBvbiBkZWxpYmVyYXRlbHkgKGFuZCBpZGVhbGx5IHdpdGggYSBzYW1wbGUgcmF0ZSB3ZWxsIHVuZGVyIDEuMCwgcGx1c1xuICogYE1FVFJJQ1NfU0NSQVBFX1RPS0VOYCBzZXQpIHdoZW4geW91IGFjdHVhbGx5IHdhbnQgcGVyLW9yZyBub2lzeS1uZWlnaGJvdXJcbiAqIGRldGVjdGlvbiBmcm9tIG1ldHJpY3MgcmF0aGVyIHRoYW4gZnJvbSB0aGUgYWNjZXNzLWxvZyBzdHJlYW0uXG4gKi9cbmNvbnN0IE9SR19TQU1QTEVfUkFURSA9ICgoKSA9PiB7XG4gIGNvbnN0IHJhdyA9IHByb2Nlc3MuZW52LkhUVFBfTUVUUklDU19PUkdfU0FNUExFX1JBVEU7XG4gIGlmIChyYXcgPT09IHVuZGVmaW5lZCB8fCByYXcgPT09ICcnKSByZXR1cm4gMDtcbiAgY29uc3QgcGFyc2VkID0gcGFyc2VGbG9hdChyYXcpO1xuICBpZiAoTnVtYmVyLmlzTmFOKHBhcnNlZCkgfHwgcGFyc2VkIDwgMCB8fCBwYXJzZWQgPiAxKSByZXR1cm4gMDtcbiAgcmV0dXJuIHBhcnNlZDtcbn0pKCk7XG5cbi8qKlxuICogTm9ybWFsaXplIGFuIEV4cHJlc3Mgcm91dGUgcGF0aCB0byBwcmV2ZW50IGxhYmVsIGNhcmRpbmFsaXR5IGV4cGxvc2lvbi5cbiAqXG4gKiBVc2VzIEV4cHJlc3MncyBtYXRjaGVkIHJvdXRlIHBhdHRlcm4gKGUuZy4gYC9wbHVnaW5zLzppZGApIHdoZW4gYXZhaWxhYmxlLFxuICogb3RoZXJ3aXNlIGZhbGxzIGJhY2sgdG8gdGhlIHJhdyBwYXRoIHdpdGggVVVJRC9udW1lcmljIHNlZ21lbnRzIHJlcGxhY2VkLlxuICovXG5mdW5jdGlvbiBub3JtYWxpemVSb3V0ZShyZXE6IFJlcXVlc3QpOiBzdHJpbmcge1xuICAvLyBQcmVmZXIgRXhwcmVzcyBtYXRjaGVkIHJvdXRlIHBhdHRlcm5cbiAgaWYgKHJlcS5yb3V0ZT8ucGF0aCkge1xuICAgIHJldHVybiByZXEuYmFzZVVybCArIHJlcS5yb3V0ZS5wYXRoO1xuICB9XG5cbiAgLy8gRmFsbGJhY2s6IHJlcGxhY2UgVVVJRHMgYW5kIG51bWVyaWMgSURzIHdpdGggOmlkXG4gIHJldHVybiByZXEucGF0aFxuICAgIC5yZXBsYWNlKC9bMC05YS1mXXs4fS1bMC05YS1mXXs0fS1bMC05YS1mXXs0fS1bMC05YS1mXXs0fS1bMC05YS1mXXsxMn0vZ2ksICc6aWQnKVxuICAgIC5yZXBsYWNlKC9cXC9cXGQrKD89XFwvfCQpL2csICcvOmlkJyk7XG59XG5cbi8qKlxuICogRXhwcmVzcyBtaWRkbGV3YXJlIHRoYXQgcmVjb3JkcyByZXF1ZXN0IGR1cmF0aW9uIGFuZCBjb3VudC5cbiAqXG4gKiBNdXN0IGJlIHJlZ2lzdGVyZWQgYmVmb3JlIHJvdXRlIGhhbmRsZXJzIHNvIGByZXMub24oJ2ZpbmlzaCcpYCBmaXJlc1xuICogYWZ0ZXIgdGhlIHJlc3BvbnNlIGlzIHNlbnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtZXRyaWNzTWlkZGxld2FyZSgpIHtcbiAgcmV0dXJuIChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UsIG5leHQ6IE5leHRGdW5jdGlvbik6IHZvaWQgPT4ge1xuICAgIC8vIE5PVEU6IG5vIC9tZXRyaWNzIG9yIC9oZWFsdGggc2tpcCBuZWVkZWQgaGVyZSDigJQgYm90aCBlbmRwb2ludHMgYXJlXG4gICAgLy8gcmVnaXN0ZXJlZCBpbiBhcHAtZmFjdG9yeSBCRUZPUkUgdGhpcyBtaWRkbGV3YXJlIChjcmVhdGVIZWFsdGhSb3V0ZXIgYW5kXG4gICAgLy8gYXBwLmdldCgnL21ldHJpY3MnKSBib3RoIHRlcm1pbmF0ZSB0aGUgcmVzcG9uc2UpLCBzbyBuZWl0aGVyIGV2ZXIgcmVhY2hlc1xuICAgIC8vIHRoaXMgaGFuZGxlci5cbiAgICBjb25zdCBlbmQgPSBodHRwUmVxdWVzdER1cmF0aW9uLnN0YXJ0VGltZXIoKTtcblxuICAgIHJlcy5vbignZmluaXNoJywgKCkgPT4ge1xuICAgICAgY29uc3Qgcm91dGUgPSBub3JtYWxpemVSb3V0ZShyZXEpO1xuICAgICAgY29uc3QgbGFiZWxzID0ge1xuICAgICAgICBtZXRob2Q6IHJlcS5tZXRob2QsXG4gICAgICAgIHJvdXRlLFxuICAgICAgICBzdGF0dXNfY29kZTogU3RyaW5nKHJlcy5zdGF0dXNDb2RlKSxcbiAgICAgIH07XG5cbiAgICAgIGVuZChsYWJlbHMpO1xuICAgICAgaHR0cFJlcXVlc3RzVG90YWwuaW5jKGxhYmVscyk7XG5cbiAgICAgIC8vIFBlci1vcmcgc2FtcGxlZCBjb3VudGVyLiBTa2lwIHdoZW46XG4gICAgICAvLyAgIC0gbm8gb3JnIGNvbnRleHQgb24gdGhlIHJlcXVlc3QgKGFub255bW91cyAvIGhlYWx0aCBlbmRwb2ludHMpXG4gICAgICAvLyAgIC0gc2FtcGxlIHJhdGUgaXMgMCAoZGlzYWJsZWQpXG4gICAgICAvLyAgIC0gZGljZSByb2xsIGZhaWxzXG4gICAgICAvLyBVc2luZyBNYXRoLnJhbmRvbSBmb3IgdGhlIHNhbXBsZXIg4oCUIGZvciB1bmJpYXNlZCBsb3ctcmF0ZSBzYW1wbGluZ1xuICAgICAgLy8gYSBkZXRlcm1pbmlzdGljIHBlci1yZXF1ZXN0IGhhc2ggd291bGQgYmUgbW9yZSB1bmlmb3JtLCBidXQgYXQgdGhlXG4gICAgICAvLyBkZWZhdWx0IHJhdGUgb2YgMS4wIGV2ZXJ5IHJlcXVlc3QgbGFuZHMgc28gdGhpcyBpcyBmaW5lLlxuICAgICAgY29uc3Qgb3JnSWQgPSByZXEudXNlcj8ub3JnYW5pemF0aW9uSWQ7XG4gICAgICBpZiAob3JnSWQgJiYgT1JHX1NBTVBMRV9SQVRFID4gMCAmJiBNYXRoLnJhbmRvbSgpIDwgT1JHX1NBTVBMRV9SQVRFKSB7XG4gICAgICAgIGh0dHBSZXF1ZXN0c0J5T3JnVG90YWwuaW5jKHsgLi4ubGFiZWxzLCBvcmdfaWQ6IG9yZ0lkIH0pO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgbmV4dCgpO1xuICB9O1xufVxuXG4vKipcbiAqIEV4cHJlc3MgaGFuZGxlciB0aGF0IHJldHVybnMgUHJvbWV0aGV1cyBtZXRyaWNzIGluIHRleHQgZXhwb3NpdGlvbiBmb3JtYXQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtZXRyaWNzSGFuZGxlcigpIHtcbiAgcmV0dXJuIGFzeW5jIChfcmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgcmVzLnNldCgnQ29udGVudC1UeXBlJywgcmVnaXN0ZXIuY29udGVudFR5cGUpO1xuICAgIHJlcy5lbmQoYXdhaXQgcmVnaXN0ZXIubWV0cmljcygpKTtcbiAgfTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBCdXNpbmVzcyAvIGRvbWFpbiBtZXRyaWNzXG4vL1xuLy8gU2VydmljZXMgc2hvdWxkIGVtaXQgY291bnRlcnMgZm9yIHRoZSB0aGluZ3Mgb3BlcmF0b3JzIGFjdHVhbGx5IGNhcmUgYWJvdXRcbi8vIChwaXBlbGluZXMgZ2VuZXJhdGVkLCBwbHVnaW4gYnVpbGRzIGNvbXBsZXRlZCwgY29tcGxpYW5jZSB2aW9sYXRpb25zLFxuLy8gQUkgdG9rZW5zIGNvbnN1bWVkKSDigJQgbm90IGp1c3QgSFRUUCB0cmFmZmljLiBUaGUgaGVscGVycyBiZWxvdyByZWdpc3RlclxuLy8gY291bnRlcnMgbGF6aWx5IG9uIHRoZSBzaGFyZWQgcmVnaXN0cnkgc28gbXVsdGlwbGUgc2VydmljZXMgY2FuIGNhbGxcbi8vIGBpbmNDb3VudGVyKCdwbHVnaW5fYnVpbGRzX3RvdGFsJywgeyBzdGF0dXM6ICdjb21wbGV0ZWQnIH0pYCB3aXRob3V0XG4vLyB3b3JyeWluZyBhYm91dCBkb3VibGUtcmVnaXN0cmF0aW9uLlxuLy9cbi8vIE5hbWluZyBjb252ZW50aW9uOiBgPGRvbWFpbj5fPG5vdW4+X3RvdGFsYCBmb3IgY291bnRlcnMsIGBfc2Vjb25kc2AgZm9yXG4vLyBoaXN0b2dyYW1zIOKAlCBtYXRjaGVzIFByb21ldGhldXMgYmVzdC1wcmFjdGljZS5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKiogVGhlIGxhenkgYnVzaW5lc3MtbWV0cmljIGhlbHBlcnMsIGJvdW5kIHRvIG9uZSByZWdpc3RyeS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTWV0cmljSGVscGVycyB7XG4gIGluY0NvdW50ZXIobmFtZTogc3RyaW5nLCBsYWJlbHM/OiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LCB2YWx1ZT86IG51bWJlcik6IHZvaWQ7XG4gIG9ic2VydmUobmFtZTogc3RyaW5nLCBsYWJlbHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4sIHZhbHVlOiBudW1iZXIpOiB2b2lkO1xuICBzZXRHYXVnZShuYW1lOiBzdHJpbmcsIGxhYmVsczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiwgdmFsdWU6IG51bWJlcik6IHZvaWQ7XG59XG5cbi8qKlxuICogQnVpbGQgYGluY0NvdW50ZXJgIC8gYG9ic2VydmVgIC8gYHNldEdhdWdlYCBvdmVyIGEgY2FsbGVyLXN1cHBsaWVkIHJlZ2lzdHJ5LlxuICpcbiAqIFRIRSBvbmUgaW1wbGVtZW50YXRpb24gb2YgdGhlIGxhenkgY291bnRlci9oaXN0b2dyYW0vZ2F1Z2UgbWFwcy4gYXBpLXNlcnZlcidzXG4gKiBvd24gZXhwb3J0cyBiZWxvdyBhcmUgdGhpcyBmYWN0b3J5IG92ZXIgaXRzIG1vZHVsZS1sZXZlbCBgcmVnaXN0ZXJgOyB0aGVcbiAqIHBsYXRmb3JtIHNlcnZpY2Ug4oCUIHdoaWNoIHJ1bnMgaXRzIG93biBFeHByZXNzIHNldHVwIGluc3RlYWQgb2YgYGNyZWF0ZUFwcGAsXG4gKiBhbmQgdGhlcmVmb3JlIG93bnMgYSBkaWZmZXJlbnQgcmVnaXN0cnkg4oCUIGJ1aWxkcyB0aGUgaWRlbnRpY2FsIGhlbHBlcnMgb3ZlclxuICogaXRzIG93bi4gV2l0aG91dCB0aGUgZmFjdG9yeSB0aGUgdHdvIGRyaWZ0OiB0aGV5IGRpZmZlciB0b2RheSBvbmx5IGluIHRoZVxuICogaGlzdG9ncmFtIGJ1Y2tldHMsIHdoaWNoIGlzIGV4YWN0bHkgdGhlIGtpbmQgb2YgZGlmZmVyZW5jZSBub2JvZHkgbm90aWNlc1xuICogdW50aWwgYSBkYXNoYm9hcmQgcmVhZHMgd3Jvbmcgb24gb25lIHNlcnZpY2UuXG4gKlxuICogYHJlZ2lzdHJ5YCBtYXkgYmUgYSB0aHVuaywgZm9yIGEgcmVnaXN0cnkgdGhhdCBpcyBpbmplY3RlZCBhZnRlciBtb2R1bGUgbG9hZFxuICogKHBsYXRmb3JtIHdpcmVzIGl0cyBvd24gb24gYXBwIGJvb3QpLiBUaGUgdGh1bmsgaXMgY2FsbGVkIG9uIHRoZSBGSVJTVCB1c2Ugb2ZcbiAqIGVhY2ggbWV0cmljIG5hbWUsIG5ldmVyIGF0IGltcG9ydCB0aW1lLCBzbyBidWlsZGluZyB0aGUgaGVscGVycyBoYXMgbm8gc2lkZVxuICogZWZmZWN0IG9mIGl0cyBvd24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVNZXRyaWNIZWxwZXJzKHJlZ2lzdHJ5OiBSZWdpc3RyeSB8ICgoKSA9PiBSZWdpc3RyeSkpOiBNZXRyaWNIZWxwZXJzIHtcbiAgY29uc3QgcmVnaXN0cnlPZiA9ICgpOiBSZWdpc3RyeSA9PiAodHlwZW9mIHJlZ2lzdHJ5ID09PSAnZnVuY3Rpb24nID8gcmVnaXN0cnkoKSA6IHJlZ2lzdHJ5KTtcbiAgY29uc3QgY291bnRlcnMgPSBuZXcgTWFwPHN0cmluZywgQ291bnRlcjxzdHJpbmc+PigpO1xuICBjb25zdCBoaXN0b2dyYW1zID0gbmV3IE1hcDxzdHJpbmcsIEhpc3RvZ3JhbTxzdHJpbmc+PigpO1xuICBjb25zdCBnYXVnZXMgPSBuZXcgTWFwPHN0cmluZywgR2F1Z2U8c3RyaW5nPj4oKTtcblxuICByZXR1cm4ge1xuICAgIGluY0NvdW50ZXIobmFtZSwgbGFiZWxzID0ge30sIHZhbHVlID0gMSkge1xuICAgICAgbGV0IGNvdW50ZXIgPSBjb3VudGVycy5nZXQobmFtZSk7XG4gICAgICBpZiAoIWNvdW50ZXIpIHtcbiAgICAgICAgY291bnRlciA9IG5ldyBDb3VudGVyKHtcbiAgICAgICAgICBuYW1lLFxuICAgICAgICAgIGhlbHA6IGh1bWFuaXplTmFtZShuYW1lKSxcbiAgICAgICAgICBsYWJlbE5hbWVzOiBPYmplY3Qua2V5cyhsYWJlbHMpLFxuICAgICAgICAgIHJlZ2lzdGVyczogW3JlZ2lzdHJ5T2YoKV0sXG4gICAgICAgIH0pO1xuICAgICAgICBjb3VudGVycy5zZXQobmFtZSwgY291bnRlcik7XG4gICAgICB9XG4gICAgICBjb3VudGVyLmluYyhsYWJlbHMsIHZhbHVlKTtcbiAgICB9LFxuXG4gICAgb2JzZXJ2ZShuYW1lLCBsYWJlbHMsIHZhbHVlKSB7XG4gICAgICBsZXQgaGlzdCA9IGhpc3RvZ3JhbXMuZ2V0KG5hbWUpO1xuICAgICAgaWYgKCFoaXN0KSB7XG4gICAgICAgIGhpc3QgPSBuZXcgSGlzdG9ncmFtKHtcbiAgICAgICAgICBuYW1lLFxuICAgICAgICAgIGhlbHA6IGh1bWFuaXplTmFtZShuYW1lKSxcbiAgICAgICAgICBsYWJlbE5hbWVzOiBPYmplY3Qua2V5cyhsYWJlbHMpLFxuICAgICAgICAgIC8vIERlZmF1bHQgYnVja2V0cyB0YXJnZXQgc3ViLXNlY29uZCB0aHJvdWdoIHNldmVyYWwtbWludXRlIG9ic2VydmF0aW9ucy5cbiAgICAgICAgICAvLyBPdmVycmlkZSBieSByZWdpc3RlcmluZyB0aGUgaGlzdG9ncmFtIGV4cGxpY2l0bHkgYmVmb3JlIGZpcnN0IGNhbGxcbiAgICAgICAgICAvLyBpZiB5b3UgbmVlZCBhIGRpZmZlcmVudCBidWNrZXQgZGlzdHJpYnV0aW9uLlxuICAgICAgICAgIGJ1Y2tldHM6IFswLjA1LCAwLjEsIDAuMjUsIDAuNSwgMSwgMi41LCA1LCAxMCwgMzAsIDYwLCAxMjAsIDMwMF0sXG4gICAgICAgICAgcmVnaXN0ZXJzOiBbcmVnaXN0cnlPZigpXSxcbiAgICAgICAgfSk7XG4gICAgICAgIGhpc3RvZ3JhbXMuc2V0KG5hbWUsIGhpc3QpO1xuICAgICAgfVxuICAgICAgaGlzdC5vYnNlcnZlKGxhYmVscywgdmFsdWUpO1xuICAgIH0sXG5cbiAgICBzZXRHYXVnZShuYW1lLCBsYWJlbHMsIHZhbHVlKSB7XG4gICAgICBsZXQgZ2F1Z2UgPSBnYXVnZXMuZ2V0KG5hbWUpO1xuICAgICAgaWYgKCFnYXVnZSkge1xuICAgICAgICBnYXVnZSA9IG5ldyBHYXVnZSh7XG4gICAgICAgICAgbmFtZSxcbiAgICAgICAgICBoZWxwOiBodW1hbml6ZU5hbWUobmFtZSksXG4gICAgICAgICAgbGFiZWxOYW1lczogT2JqZWN0LmtleXMobGFiZWxzKSxcbiAgICAgICAgICByZWdpc3RlcnM6IFtyZWdpc3RyeU9mKCldLFxuICAgICAgICB9KTtcbiAgICAgICAgZ2F1Z2VzLnNldChuYW1lLCBnYXVnZSk7XG4gICAgICB9XG4gICAgICBnYXVnZS5zZXQobGFiZWxzLCB2YWx1ZSk7XG4gICAgfSxcbiAgfTtcbn1cblxuLyoqIFRoaXMgc2VydmljZSdzIG93biBoZWxwZXJzLCBvdmVyIHRoZSBzaGFyZWQgbW9kdWxlLWxldmVsIHJlZ2lzdHJ5LiAqL1xuY29uc3QgYnVzaW5lc3NNZXRyaWNzID0gY3JlYXRlTWV0cmljSGVscGVycyhyZWdpc3Rlcik7XG5cbi8qKlxuICogSW5jcmVtZW50IGEgYnVzaW5lc3MgY291bnRlciwgY3JlYXRpbmcgaXQgb24gZmlyc3QgdXNlLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBpbmNDb3VudGVyKCdwaXBlbGluZXNfZ2VuZXJhdGVkX3RvdGFsJywgeyBwcm92aWRlcjogJ2FudGhyb3BpYycgfSk7XG4gKiBpbmNDb3VudGVyKCdwbHVnaW5fYnVpbGRzX3RvdGFsJywgeyBzdGF0dXM6ICdjb21wbGV0ZWQnIH0pO1xuICogaW5jQ291bnRlcigncXVvdGFfdGhyZXNob2xkX2Nyb3NzZWRfdG90YWwnLCB7IHR5cGU6ICdhaUNhbGxzJywgdGllcjogJ3BybycgfSk7XG4gKiBpbmNDb3VudGVyKCdjb21wbGlhbmNlX3Zpb2xhdGlvbnNfZm91bmRfdG90YWwnLCB7IHNldmVyaXR5OiAnY3JpdGljYWwnIH0pO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbmNDb3VudGVyKG5hbWU6IHN0cmluZywgbGFiZWxzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge30sIHZhbHVlID0gMSk6IHZvaWQge1xuICBidXNpbmVzc01ldHJpY3MuaW5jQ291bnRlcihuYW1lLCBsYWJlbHMsIHZhbHVlKTtcbn1cblxuLyoqXG4gKiBSZWNvcmQgYW4gb2JzZXJ2YXRpb24gb24gYSBidXNpbmVzcyBoaXN0b2dyYW0sIGNyZWF0aW5nIGl0IG9uIGZpcnN0IHVzZS5cbiAqIFVzZSBmb3IgZHVyYXRpb25zLCBzaXplcywgYW55dGhpbmcgd2hlcmUgcGVyY2VudGlsZXMgbWF0dGVyLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBvYnNlcnZlKCdhaV9nZW5lcmF0aW9uX2R1cmF0aW9uX3NlY29uZHMnLCB7IHByb3ZpZGVyOiAnYW50aHJvcGljJywgbW9kZWw6ICdzb25uZXQnIH0sIGR1cmF0aW9uU2VjKTtcbiAqIG9ic2VydmUoJ3BsdWdpbl9idWlsZF9kdXJhdGlvbl9zZWNvbmRzJywgeyBidWlsZFR5cGU6ICdkb2NrZXInIH0sIGR1cmF0aW9uU2VjKTtcbiAqIGBgYFxuICovXG5leHBvcnQgZnVuY3Rpb24gb2JzZXJ2ZShuYW1lOiBzdHJpbmcsIGxhYmVsczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiwgdmFsdWU6IG51bWJlcik6IHZvaWQge1xuICBidXNpbmVzc01ldHJpY3Mub2JzZXJ2ZShuYW1lLCBsYWJlbHMsIHZhbHVlKTtcbn1cblxuLyoqXG4gKiBTZXQgdGhlIHZhbHVlIG9mIGEgYnVzaW5lc3MgZ2F1Z2UsIGNyZWF0aW5nIGl0IG9uIGZpcnN0IHVzZS4gVXNlIGZvclxuICogcG9pbnQtaW4tdGltZSBvYnNlcnZhdGlvbnMgc2FtcGxlZCBieSBhIHNjcmFwZXIg4oCUIHF1ZXVlIGRlcHRoLCBhY3RpdmVcbiAqIGNvbm5lY3Rpb24gY291bnRzLCBpbi1mbGlnaHQgcmVxdWVzdHMuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIHNldEdhdWdlKCdwbHVnaW5fcXVldWVfam9icycsIHsgcXVldWU6ICdwbHVnaW4tYnVpbGQnLCBzdGF0ZTogJ3dhaXRpbmcnIH0sIDEyKTtcbiAqIHNldEdhdWdlKCdwbHVnaW5fcXVldWVfam9icycsIHsgcXVldWU6ICdwbHVnaW4tYnVpbGQnLCBzdGF0ZTogJ2FjdGl2ZScgfSwgMyk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldEdhdWdlKG5hbWU6IHN0cmluZywgbGFiZWxzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LCB2YWx1ZTogbnVtYmVyKTogdm9pZCB7XG4gIGJ1c2luZXNzTWV0cmljcy5zZXRHYXVnZShuYW1lLCBsYWJlbHMsIHZhbHVlKTtcbn1cblxuZnVuY3Rpb24gaHVtYW5pemVOYW1lKG1ldHJpY05hbWU6IHN0cmluZyk6IHN0cmluZyB7XG4gIC8vIGBwaXBlbGluZXNfZ2VuZXJhdGVkX3RvdGFsYCDihpIgXCJQaXBlbGluZXMgZ2VuZXJhdGVkIHRvdGFsXCJcbiAgcmV0dXJuIG1ldHJpY05hbWVcbiAgICAucmVwbGFjZSgvXy9nLCAnICcpXG4gICAgLnJlcGxhY2UoL14uLywgKGMpID0+IGMudG9VcHBlckNhc2UoKSk7XG59XG4iXX0=
367
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hcGkvbWV0cmljcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSw4QkFBOEIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ2xHLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUV6RCxPQUFPLEVBQUUsUUFBUSxFQUFFLHFCQUFxQixFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRXpGLE1BQU0sWUFBWSxHQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsZUFBZSxDQUE2QixDQUFDLFdBQVcsQ0FBQztBQUU3RixpQ0FBaUM7QUFDakMsTUFBTSxRQUFRLEdBQUcsSUFBSSxRQUFRLEVBQUUsQ0FBQztBQUVoQyxxQ0FBcUM7QUFDckMsUUFBUSxDQUFDLGdCQUFnQixDQUFDLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxDQUFDLENBQUM7QUFFckQsa0ZBQWtGO0FBQ2xGLHFCQUFxQixDQUFDLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztBQUVwQzs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUsMkJBQTJCLENBQUMsUUFBa0I7SUFDNUQsT0FBTyxJQUFJLEtBQUssQ0FBQztRQUNmLElBQUksRUFBRSw4QkFBOEI7UUFDcEMsSUFBSSxFQUFFLGtLQUFrSztRQUN4SyxVQUFVLEVBQUUsQ0FBQyxRQUFRLENBQVU7UUFDL0IsU0FBUyxFQUFFLENBQUMsUUFBUSxDQUFDO1FBQ3JCLE9BQU87WUFDTCxLQUFLLE1BQU0sRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLElBQUksb0JBQW9CLEVBQUUsRUFBRSxDQUFDO2dCQUM3RCxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsTUFBTSxFQUFFLEVBQUUsV0FBVyxDQUFDLENBQUMsQ0FBQyxD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LEtBQWE7SUFDbEYsZUFBZSxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFDO0FBQ2hELENBQUM7QUFFRDs7Ozs7O0dBTUc7QUFDSCxNQUFNLFVBQVUsVUFBVSxDQUFDLElBQVk7SUFDckMsZUFBZSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUNuQyxDQUFDO0FBRUQsU0FBUyxZQUFZLENBQUMsVUFBa0I7SUFDdEMsZ0RBQWdEO0lBQ2hELE9BQU8sVUFBVTtTQUNkLE9BQU8sQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDO1NBQ2xCLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO0FBQzNDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHsgcHJldmlvdXNTZWNyZXRTdGF0ZXMsIFNFQ1JFVF9ST1RBVElPTl9QUkVWSU9VU19HQVVHRSB9IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL2FwaS1jb3JlJztcbmltcG9ydCB7IENvbmZpZyB9IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL3BpcGVsaW5lLWNvcmUnO1xuaW1wb3J0IHR5cGUgeyBSZXF1ZXN0LCBSZXNwb25zZSwgTmV4dEZ1bmN0aW9uIH0gZnJvbSAnZXhwcmVzcyc7XG5pbXBvcnQgeyBSZWdpc3RyeSwgY29sbGVjdERlZmF1bHRNZXRyaWNzLCBDb3VudGVyLCBIaXN0b2dyYW0sIEdhdWdlIH0gZnJvbSAncHJvbS1jbGllbnQnO1xuXG5jb25zdCBTRVJWSUNFX05BTUUgPSAoQ29uZmlnLmdldEFueSgnb2JzZXJ2YWJpbGl0eScpIGFzIHsgc2VydmljZU5hbWU6IHN0cmluZyB9KS5zZXJ2aWNlTmFtZTtcblxuLyoqIFNoYXJlZCBQcm9tZXRoZXVzIHJlZ2lzdHJ5ICovXG5jb25zdCByZWdpc3RlciA9IG5ldyBSZWdpc3RyeSgpO1xuXG4vLyBTZXQgZGVmYXVsdCBsYWJlbHMgZm9yIGFsbCBtZXRyaWNzXG5yZWdpc3Rlci5zZXREZWZhdWx0TGFiZWxzKHsgc2VydmljZTogU0VSVklDRV9OQU1FIH0pO1xuXG4vLyBDb2xsZWN0IGRlZmF1bHQgTm9kZS5qcyBwcm9jZXNzIG1ldHJpY3MgKENQVSwgbWVtb3J5LCBoZWFwLCBldmVudCBsb29wIGxhZywgR0MpXG5jb2xsZWN0RGVmYXVsdE1ldHJpY3MoeyByZWdpc3RlciB9KTtcblxuLyoqXG4gKiBSZWdpc3RlciB0aGUgYHNlY3JldF9yb3RhdGlvbl9wcmV2aW91c19zZXR7c2VjcmV0fWAgZ2F1Z2Ugb24gYHJlZ2lzdHJ5YDogMVxuICogd2hpbGUgYSBzZWNyZXQncyBgKl9QUkVWSU9VU2Agcm90YXRpb24gdmFsdWUgaXMgc3RpbGwgc2V0LCAwIG90aGVyd2lzZS4gVGhlXG4gKiB2YWx1ZSBpcyByZWFkIGZyb20gYXBpLWNvcmUncyBwcm9iZSByZWdpc3RyeSBhdCBzY3JhcGUgdGltZSwgc28gaXQgYWx3YXlzXG4gKiByZWZsZWN0cyB0aGUgbGl2ZSBwcm9jZXNzLiBFeHBvcnRlZCBzbyBwbGF0Zm9ybSAob3duIHJlZ2lzdHJ5KSBleHBvc2VzIHRoZVxuICogaWRlbnRpY2FsIHNlcmllczsgdGhlIGBTZWNyZXRSb3RhdGlvblByZXZpb3VzTGluZ2VyaW5nYCBhbGVydCBrZXlzIG9uIGl0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJTZWNyZXRSb3RhdGlvbkdhdWdlKHJlZ2lzdHJ5OiBSZWdpc3RyeSk6IEdhdWdlPCdzZWNyZXQnPiB7XG4gIHJldHVybiBuZXcgR2F1Z2Uoe1xuICAgIG5hbWU6IFNFQ1JFVF9ST1RBVElPTl9QUkVWSU9VU19HQVVHRSxcbiAgICBoZWxwOiAnMSB3aGlsZSBhIHNlY3JldCByb3RhdGlvbiBwcmV2aW91cyB2YWx1ZSAoZS5nLiBTRUNSRVRfRU5DUllQVElPTl9LRVlfUFJFVklPVVMpIG9yIGEgcmV0aXJpbmcgc2lnbmluZyBrZXkgaXMgc3RpbGwgYWNjZXB0ZWQ7IHNlZSBkb2NzL3J1bmJvb2tzL3NlY3JldC1yb3RhdGlvbi5tZCcsXG4gICAgbGFiZWxOYW1lczogWydzZWNyZXQnXSBhcyBjb25zdCxcbiAgICByZWdpc3RlcnM6IFtyZWdpc3RyeV0sXG4gICAgY29sbGVjdCgpIHtcbiAgICAgIGZvciAoY29uc3QgeyBzZWNyZXQsIHByZXZpb3VzU2V0IH0gb2YgcHJldmlvdXNTZWNyZXRTdGF0ZXMoKSkge1xuICAgICAgICB0aGlzLnNldCh7IHNlY3JldCB9LCBwcmV2aW91c1NldCA/IDEgOiAwKTtcbiAgICAgIH1cbiAgICB9LFxuICB9KTtcbn1cblxucmVnaXN0ZXJTZWNyZXRSb3RhdGlvbkdhdWdlKHJlZ2lzdGVyKTtcblxuLyoqIEhUVFAgcmVxdWVzdCBkdXJhdGlvbiBoaXN0b2dyYW0gKHNlY29uZHMpICovXG5jb25zdCBodHRwUmVxdWVzdER1cmF0aW9uID0gbmV3IEhpc3RvZ3JhbSh7XG4gIG5hbWU6ICdodHRwX3JlcXVlc3RfZHVyYXRpb25fc2Vjb25kcycsXG4gIGhlbHA6ICdEdXJhdGlvbiBvZiBIVFRQIHJlcXVlc3RzIGluIHNlY29uZHMnLFxuICBsYWJlbE5hbWVzOiBbJ21ldGhvZCcsICdyb3V0ZScsICdzdGF0dXNfY29kZSddIGFzIGNvbnN0LFxuICBidWNrZXRzOiBbMC4wMDUsIDAuMDEsIDAuMDI1LCAwLjA1LCAwLjEsIDAuMjUsIDAuNSwgMSwgMi41LCA1LCAxMF0sXG4gIHJlZ2lzdGVyczogW3JlZ2lzdGVyXSxcbn0pO1xuXG4vKiogSFRUUCByZXF1ZXN0IGNvdW50ZXIgKi9cbmNvbnN0IGh0dHBSZXF1ZXN0c1RvdGFsID0gbmV3IENvdW50ZXIoe1xuICBuYW1lOiAnaHR0cF9yZXF1ZXN0c190b3RhbCcsXG4gIGhlbHA6ICdUb3RhbCBudW1iZXIgb2YgSFRUUCByZXF1ZXN0cycsXG4gIGxhYmVsTmFtZXM6IFsnbWV0aG9kJywgJ3JvdXRlJywgJ3N0YXR1c19jb2RlJ10gYXMgY29uc3QsXG4gIHJlZ2lzdGVyczogW3JlZ2lzdGVyXSxcbn0pO1xuXG4vKipcbiAqIFBlci1vcmcgSFRUUCByZXF1ZXN0IGNvdW50ZXIg4oCUIFNBTVBMRUQgdG8ga2VlcCBQcm9tZXRoZXVzIGNhcmRpbmFsaXR5XG4gKiB1bmRlciBjb250cm9sLiBDYXJkaW5hbGl0eSBvZiBgb3JnX2lkICogbWV0aG9kICogcm91dGUgKiBzdGF0dXNfY29kZWBcbiAqIGdyb3dzIG11bHRpcGxpY2F0aXZlbHk7IHdpdGggTiBvcmdzICogNTAgcm91dGVzICogNSBzdGF0dXNfY29kZXMgdGhhdCdzXG4gKiAyNTDDl04gc2VyaWVzLiBXZSBzYW1wbGUgMS1pbi1OIHJlcXVlc3RzIChjb25maWd1cmFibGUgdmlhXG4gKiBgSFRUUF9NRVRSSUNTX09SR19TQU1QTEVfUkFURWAsIGRlZmF1bHQgMCA9IG9mZikuXG4gKlxuICogT3BlcmF0b3JzIGFuc3dlciBcIndoYXQncyBvcmcgWCdzIHA5OT9cIiB2aWEgc2VwYXJhdGUgcGVyLW9yZyBoaXN0b2dyYW1zXG4gKiBzY3JhcGVkIGF0IGEgbG93ZXIgcmF0ZSwgT1IgdmlhIExva2kgTG9nUUwgcXVlcmllcyBhZ2FpbnN0IHRoZVxuICogdW5zYW1wbGVkIGFjY2Vzcy1sb2cgc3RyZWFtLiBUaGlzIGNvdW50ZXIgaXMgdGhlIGZhc3QtcGF0aCBcIm5vaXN5XG4gKiBuZWlnaGJvciBkZXRlY3Rpb25cIiDigJQgb3BlcmF0b3JzIGFsZXJ0IHdoZW4gb25lIG9yZydzIHJlcXVlc3QgcmF0ZVxuICogZGV2aWF0ZXMgZnJvbSB0aGUgZmxlZXQgbWVkaWFuLlxuICpcbiAqIE5PVCBhIGhpc3RvZ3JhbTogaGlzdG9ncmFtIGxhYmVsIGNhcmRpbmFsaXR5IGlzIGV2ZW4gbW9yZSBzZW5zaXRpdmVcbiAqIChlYWNoIGJ1Y2tldCBpcyBhIHNlcGFyYXRlIHNlcmllcykuIElmIHBlci1vcmcgbGF0ZW5jeSBwZXJjZW50aWxlcyBhcmVcbiAqIG5lZWRlZCBsYXRlciwgYWRkIGEgc2VwYXJhdGUgaGlzdG9ncmFtIHdpdGggYSBjb2Fyc2VyIGJ1Y2tldCBzZXQgYW5kXG4gKiBsb3dlciBzYW1wbGUgcmF0ZS5cbiAqL1xuY29uc3QgaHR0cFJlcXVlc3RzQnlPcmdUb3RhbCA9IG5ldyBDb3VudGVyKHtcbiAgbmFtZTogJ2h0dHBfcmVxdWVzdHNfYnlfb3JnX3RvdGFsJyxcbiAgaGVscDogJ1NhbXBsZWQgcGVyLW9yZyBIVFRQIHJlcXVlc3QgY291bnQgKHNhbXBsZSByYXRlIHZpYSBIVFRQX01FVFJJQ1NfT1JHX1NBTVBMRV9SQVRFKScsXG4gIGxhYmVsTmFtZXM6IFsnbWV0aG9kJywgJ3JvdXRlJywgJ3N0YXR1c19jb2RlJywgJ29yZ19pZCddIGFzIGNvbnN0LFxuICByZWdpc3RlcnM6IFtyZWdpc3Rlcl0sXG59KTtcblxuLyoqXG4gKiBTYW1wbGUgcmF0ZSBmb3IgdGhlIHBlci1vcmcgY291bnRlci4gMS4wID0gZXZlcnkgcmVxdWVzdCwgMC4wID0gZGlzYWJsZWQuXG4gKiBQYXJzZWQgb25jZSBhdCBtb2R1bGUgbG9hZCDigJQgb3BlcmF0b3JzIHR1bmUgYnkgcmVzdGFydGluZyB0aGUgc2VydmljZS5cbiAqXG4gKiBEZWZhdWx0cyB0byAwIChPRkYpLiBgb3JnX2lkYCBpcyBhbiBVTkJPVU5ERUQsIHRlbmFudC1pZGVudGlmeWluZyBsYWJlbCBhbmRcbiAqIHByb20tY2xpZW50IGNvdW50ZXJzIG5ldmVyIGV4cGlyZSwgc28gYXQgMS4wIGV2ZXJ5IHNlcnZpY2UgYWNjdW11bGF0ZXMgYVxuICogc2VyaWVzIHBlciAob3JnIMOXIHJvdXRlIMOXIHN0YXR1cykgZm9yIHRoZSBwcm9jZXNzIGxpZmV0aW1lLCBhbmQgYC9tZXRyaWNzYCDigJRcbiAqIHdoaWNoIGlzIG5vdCBhdXRoLWdhdGVkIOKAlCBlbnVtZXJhdGVzIGV2ZXJ5IHRlbmFudCBpZCBhbG9uZyB3aXRoIGl0cyByZXF1ZXN0XG4gKiB2b2x1bWUgYW5kIGVycm9yIHJhdGUgdG8gYW55b25lIHdobyBjYW4gcmVhY2ggdGhlIHBvcnQuXG4gKlxuICogVHVybiBpdCBvbiBkZWxpYmVyYXRlbHkgKGFuZCBpZGVhbGx5IHdpdGggYSBzYW1wbGUgcmF0ZSB3ZWxsIHVuZGVyIDEuMCwgcGx1c1xuICogYE1FVFJJQ1NfU0NSQVBFX1RPS0VOYCBzZXQpIHdoZW4geW91IGFjdHVhbGx5IHdhbnQgcGVyLW9yZyBub2lzeS1uZWlnaGJvdXJcbiAqIGRldGVjdGlvbiBmcm9tIG1ldHJpY3MgcmF0aGVyIHRoYW4gZnJvbSB0aGUgYWNjZXNzLWxvZyBzdHJlYW0uXG4gKi9cbmNvbnN0IE9SR19TQU1QTEVfUkFURSA9ICgoKSA9PiB7XG4gIGNvbnN0IHJhdyA9IHByb2Nlc3MuZW52LkhUVFBfTUVUUklDU19PUkdfU0FNUExFX1JBVEU7XG4gIGlmIChyYXcgPT09IHVuZGVmaW5lZCB8fCByYXcgPT09ICcnKSByZXR1cm4gMDtcbiAgY29uc3QgcGFyc2VkID0gcGFyc2VGbG9hdChyYXcpO1xuICBpZiAoTnVtYmVyLmlzTmFOKHBhcnNlZCkgfHwgcGFyc2VkIDwgMCB8fCBwYXJzZWQgPiAxKSByZXR1cm4gMDtcbiAgcmV0dXJuIHBhcnNlZDtcbn0pKCk7XG5cbi8qKlxuICogTm9ybWFsaXplIGFuIEV4cHJlc3Mgcm91dGUgcGF0aCB0byBwcmV2ZW50IGxhYmVsIGNhcmRpbmFsaXR5IGV4cGxvc2lvbi5cbiAqXG4gKiBVc2VzIEV4cHJlc3MncyBtYXRjaGVkIHJvdXRlIHBhdHRlcm4gKGUuZy4gYC9wbHVnaW5zLzppZGApIHdoZW4gYXZhaWxhYmxlLFxuICogb3RoZXJ3aXNlIGZhbGxzIGJhY2sgdG8gdGhlIHJhdyBwYXRoIHdpdGggVVVJRC9udW1lcmljIHNlZ21lbnRzIHJlcGxhY2VkLlxuICovXG5mdW5jdGlvbiBub3JtYWxpemVSb3V0ZShyZXE6IFJlcXVlc3QpOiBzdHJpbmcge1xuICAvLyBQcmVmZXIgRXhwcmVzcyBtYXRjaGVkIHJvdXRlIHBhdHRlcm5cbiAgaWYgKHJlcS5yb3V0ZT8ucGF0aCkge1xuICAgIHJldHVybiByZXEuYmFzZVVybCArIHJlcS5yb3V0ZS5wYXRoO1xuICB9XG5cbiAgLy8gRmFsbGJhY2s6IHJlcGxhY2UgVVVJRHMgYW5kIG51bWVyaWMgSURzIHdpdGggOmlkXG4gIHJldHVybiByZXEucGF0aFxuICAgIC5yZXBsYWNlKC9bMC05YS1mXXs4fS1bMC05YS1mXXs0fS1bMC05YS1mXXs0fS1bMC05YS1mXXs0fS1bMC05YS1mXXsxMn0vZ2ksICc6aWQnKVxuICAgIC5yZXBsYWNlKC9cXC9cXGQrKD89XFwvfCQpL2csICcvOmlkJyk7XG59XG5cbi8qKlxuICogRXhwcmVzcyBtaWRkbGV3YXJlIHRoYXQgcmVjb3JkcyByZXF1ZXN0IGR1cmF0aW9uIGFuZCBjb3VudC5cbiAqXG4gKiBNdXN0IGJlIHJlZ2lzdGVyZWQgYmVmb3JlIHJvdXRlIGhhbmRsZXJzIHNvIGByZXMub24oJ2ZpbmlzaCcpYCBmaXJlc1xuICogYWZ0ZXIgdGhlIHJlc3BvbnNlIGlzIHNlbnQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtZXRyaWNzTWlkZGxld2FyZSgpIHtcbiAgcmV0dXJuIChyZXE6IFJlcXVlc3QsIHJlczogUmVzcG9uc2UsIG5leHQ6IE5leHRGdW5jdGlvbik6IHZvaWQgPT4ge1xuICAgIC8vIE5PVEU6IG5vIC9tZXRyaWNzIG9yIC9oZWFsdGggc2tpcCBuZWVkZWQgaGVyZSDigJQgYm90aCBlbmRwb2ludHMgYXJlXG4gICAgLy8gcmVnaXN0ZXJlZCBpbiBhcHAtZmFjdG9yeSBCRUZPUkUgdGhpcyBtaWRkbGV3YXJlIChjcmVhdGVIZWFsdGhSb3V0ZXIgYW5kXG4gICAgLy8gYXBwLmdldCgnL21ldHJpY3MnKSBib3RoIHRlcm1pbmF0ZSB0aGUgcmVzcG9uc2UpLCBzbyBuZWl0aGVyIGV2ZXIgcmVhY2hlc1xuICAgIC8vIHRoaXMgaGFuZGxlci5cbiAgICBjb25zdCBlbmQgPSBodHRwUmVxdWVzdER1cmF0aW9uLnN0YXJ0VGltZXIoKTtcblxuICAgIHJlcy5vbignZmluaXNoJywgKCkgPT4ge1xuICAgICAgY29uc3Qgcm91dGUgPSBub3JtYWxpemVSb3V0ZShyZXEpO1xuICAgICAgY29uc3QgbGFiZWxzID0ge1xuICAgICAgICBtZXRob2Q6IHJlcS5tZXRob2QsXG4gICAgICAgIHJvdXRlLFxuICAgICAgICBzdGF0dXNfY29kZTogU3RyaW5nKHJlcy5zdGF0dXNDb2RlKSxcbiAgICAgIH07XG5cbiAgICAgIGVuZChsYWJlbHMpO1xuICAgICAgaHR0cFJlcXVlc3RzVG90YWwuaW5jKGxhYmVscyk7XG5cbiAgICAgIC8vIFBlci1vcmcgc2FtcGxlZCBjb3VudGVyLiBTa2lwIHdoZW46XG4gICAgICAvLyAgIC0gbm8gb3JnIGNvbnRleHQgb24gdGhlIHJlcXVlc3QgKGFub255bW91cyAvIGhlYWx0aCBlbmRwb2ludHMpXG4gICAgICAvLyAgIC0gc2FtcGxlIHJhdGUgaXMgMCAoZGlzYWJsZWQpXG4gICAgICAvLyAgIC0gZGljZSByb2xsIGZhaWxzXG4gICAgICAvLyBVc2luZyBNYXRoLnJhbmRvbSBmb3IgdGhlIHNhbXBsZXIg4oCUIGZvciB1bmJpYXNlZCBsb3ctcmF0ZSBzYW1wbGluZ1xuICAgICAgLy8gYSBkZXRlcm1pbmlzdGljIHBlci1yZXF1ZXN0IGhhc2ggd291bGQgYmUgbW9yZSB1bmlmb3JtLCBidXQgYXQgdGhlXG4gICAgICAvLyBkZWZhdWx0IHJhdGUgb2YgMS4wIGV2ZXJ5IHJlcXVlc3QgbGFuZHMgc28gdGhpcyBpcyBmaW5lLlxuICAgICAgY29uc3Qgb3JnSWQgPSByZXEudXNlcj8ub3JnYW5pemF0aW9uSWQ7XG4gICAgICBpZiAob3JnSWQgJiYgT1JHX1NBTVBMRV9SQVRFID4gMCAmJiBNYXRoLnJhbmRvbSgpIDwgT1JHX1NBTVBMRV9SQVRFKSB7XG4gICAgICAgIGh0dHBSZXF1ZXN0c0J5T3JnVG90YWwuaW5jKHsgLi4ubGFiZWxzLCBvcmdfaWQ6IG9yZ0lkIH0pO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgbmV4dCgpO1xuICB9O1xufVxuXG4vKipcbiAqIEV4cHJlc3MgaGFuZGxlciB0aGF0IHJldHVybnMgUHJvbWV0aGV1cyBtZXRyaWNzIGluIHRleHQgZXhwb3NpdGlvbiBmb3JtYXQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBtZXRyaWNzSGFuZGxlcigpIHtcbiAgcmV0dXJuIGFzeW5jIChfcmVxOiBSZXF1ZXN0LCByZXM6IFJlc3BvbnNlKTogUHJvbWlzZTx2b2lkPiA9PiB7XG4gICAgcmVzLnNldCgnQ29udGVudC1UeXBlJywgcmVnaXN0ZXIuY29udGVudFR5cGUpO1xuICAgIHJlcy5lbmQoYXdhaXQgcmVnaXN0ZXIubWV0cmljcygpKTtcbiAgfTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyBCdXNpbmVzcyAvIGRvbWFpbiBtZXRyaWNzXG4vL1xuLy8gU2VydmljZXMgc2hvdWxkIGVtaXQgY291bnRlcnMgZm9yIHRoZSB0aGluZ3Mgb3BlcmF0b3JzIGFjdHVhbGx5IGNhcmUgYWJvdXRcbi8vIChwaXBlbGluZXMgZ2VuZXJhdGVkLCBwbHVnaW4gYnVpbGRzIGNvbXBsZXRlZCwgY29tcGxpYW5jZSB2aW9sYXRpb25zLFxuLy8gQUkgdG9rZW5zIGNvbnN1bWVkKSDigJQgbm90IGp1c3QgSFRUUCB0cmFmZmljLiBUaGUgaGVscGVycyBiZWxvdyByZWdpc3RlclxuLy8gY291bnRlcnMgbGF6aWx5IG9uIHRoZSBzaGFyZWQgcmVnaXN0cnkgc28gbXVsdGlwbGUgc2VydmljZXMgY2FuIGNhbGxcbi8vIGBpbmNDb3VudGVyKCdwbHVnaW5fYnVpbGRzX3RvdGFsJywgeyBzdGF0dXM6ICdjb21wbGV0ZWQnIH0pYCB3aXRob3V0XG4vLyB3b3JyeWluZyBhYm91dCBkb3VibGUtcmVnaXN0cmF0aW9uLlxuLy9cbi8vIE5hbWluZyBjb252ZW50aW9uOiBgPGRvbWFpbj5fPG5vdW4+X3RvdGFsYCBmb3IgY291bnRlcnMsIGBfc2Vjb25kc2AgZm9yXG4vLyBoaXN0b2dyYW1zIOKAlCBtYXRjaGVzIFByb21ldGhldXMgYmVzdC1wcmFjdGljZS5cbi8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuXG4vKipcbiAqIEJ1Y2tldCBkaXN0cmlidXRpb25zIGZvciBoaXN0b2dyYW1zIHdob3NlIG9ic2VydmF0aW9ucyBhcmUgbm93aGVyZSBuZWFyIHRoZVxuICogc3ViLXNlY29uZC10by1taW51dGVzIGRlZmF1bHQuXG4gKlxuICogVEhJUyBUQUJMRSBFWElTVFMgQkVDQVVTRSBUSEUgREVGQVVMVCBTSUxFTlRMWSBCUkVBS1MgQUxFUlRTLiBUaGUgZGVmYXVsdCBzZXRcbiAqIGJlbG93IGVuZHMgYXQgYSAzMDAtc2Vjb25kIGJ1Y2tldCwgYW5kIGBoaXN0b2dyYW1fcXVhbnRpbGVgIGNhbm5vdCBpbnRlcnBvbGF0ZVxuICogcGFzdCB0aGUgbGFzdCBGSU5JVEUgYm91bmRhcnkg4oCUIGV2ZXJ5dGhpbmcgYWJvdmUgaXQgbGFuZHMgaW4gYCtJbmZgIGFuZCB0aGVcbiAqIHF1YW50aWxlIHJlYWRzIGJhY2sgYXMgMzAwIGZvcmV2ZXIuIEFuIGFsZXJ0IG9mIHRoZSBmb3JtIGA+IDMwMGAgb24gc3VjaCBhXG4gKiBoaXN0b2dyYW0gY2FuIHRoZXJlZm9yZSBuZXZlciBmaXJlLCBhbmQgYSBwOTAgcGFuZWwgZmxhdC1saW5lcyBhdCBmaXZlXG4gKiBtaW51dGVzIGhvd2V2ZXIgYmFkIHRoaW5ncyBnZXQuIE5vdGhpbmcgZXJyb3JzLCBub3RoaW5nIGlzIG1pc3NpbmcgZnJvbSB0aGVcbiAqIHNjcmFwZSwgYW5kIHRoZSBkYXNoYm9hcmQgbG9va3MgaGVhbHRoeTogdGhlIG9ubHkgc3ltcHRvbSBpcyBhbiBhbGVydCB0aGF0XG4gKiBzdGF5cyBxdWlldCB0aHJvdWdoIGFuIG91dGFnZS4gYHN1cHBvcnRfZmlyc3RfcmVzcG9uc2Vfc2Vjb25kc2AgbWVhc3VyZXMgaG91cnNcbiAqIHRvIGRheXMgYW5kIGhhZCBhIHRocmVzaG9sZCBvZiB0d2VsdmUgaG91cnMgc2l0dGluZyBhYm92ZSBhIGNlaWxpbmcgb2YgZml2ZVxuICogbWludXRlcy5cbiAqXG4gKiBTbyBhIGhpc3RvZ3JhbSB3aG9zZSBuYXR1cmFsIHJhbmdlIGlzIG1pbnV0ZXMtdG8tZGF5cyBkZWNsYXJlcyBpdHMgYnVja2V0c1xuICogaGVyZSwgYW5kIEFMRVJUIFRIUkVTSE9MRFMgQVJFIFBVVCBPTiBCT1VOREFSSUVTOiBhIHRocmVzaG9sZCBpbnNpZGUgYSB3aWRlXG4gKiBidWNrZXQgaXMgc2VydmVkIGJ5IGxpbmVhciBpbnRlcnBvbGF0aW9uIGFjcm9zcyB0aGF0IGJ1Y2tldCwgd2hpY2ggaXMgYSBndWVzcyxcbiAqIHdoaWxlIGEgdGhyZXNob2xkIE9OIGEgYm91bmRhcnkgaXMgZXhhY3QuIEZvciBzdXBwb3J0IHRoYXQgbWVhbnMgNmggKHRoZSBhbGVydClcbiAqIGFuZCA4aCAodGhlIHNvbGQgdGFyZ2V0KSBhcmUgYm90aCBib3VuZGFyaWVzLCAyNGggaXMgdGhlIG9wZXJhdGlvbmFsIGd1YXJkXG4gKiBmcm9tIHRoZSBzdGFuZGFyZC9wcmlvcml0eSBydWxlLCBhbmQgOTZoIGNvdmVycyB0aGUgbG9uZ2VzdCBsZWdpdGltYXRlIHdhaXQgYVxuICogYnVzaW5lc3MtZGF5IHRhcmdldCBhbGxvd3Mg4oCUIGEgcHJpb3JpdHkgY2FzZSByYWlzZWQgYXQgMTc6MDEgb24gYSBGcmlkYXkuXG4gKlxuICogQWRkIGEgbWV0cmljIGhlcmUgd2hlbiBpdHMgb2JzZXJ2YXRpb25zIGNhbiBleGNlZWQgZml2ZSBtaW51dGVzLiBUaGUgdGFibGUgaXNcbiAqIHJlYWQgb24gRklSU1QgVVNFIG9mIGVhY2ggbmFtZSBieSBgY3JlYXRlTWV0cmljSGVscGVyc2AsIHNvIGJvdGggcmVnaXN0cmllc1xuICogKGFwaS1zZXJ2ZXIncyBhbmQgcGxhdGZvcm0ncyBvd24pIGdldCB0aGUgc2FtZSBkaXN0cmlidXRpb24sIHdoaWNoIGlzIHRoZVxuICogZHJpZnQgdGhlIGZhY3RvcnkgZXhpc3RzIHRvIHByZXZlbnQuXG4gKi9cbmNvbnN0IEhJU1RPR1JBTV9CVUNLRVRTOiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCByZWFkb25seSBudW1iZXJbXT4+ID0ge1xuICAvLyAxNW0sIDFoLCAyaCwgNGgsIDZoLCA4aCwgMTJoLCAyNGgsIDQ4aCwgOTZoLlxuICBzdXBwb3J0X2ZpcnN0X3Jlc3BvbnNlX3NlY29uZHM6IFs5MDAsIDM2MDAsIDcyMDAsIDE0NDAwLCAyMTYwMCwgMjg4MDAsIDQzMjAwLCA4NjQwMCwgMTcyODAwLCAzNDU2MDBdLFxuICAvLyBTdWJtaXNzaW9uLXRvLWRlY2lzaW9uIGxhdGVuY3kgaXMgYSBodW1hbiByZXZpZXcgcXVldWU6IGhvdXJzIHRvIGRheXMuXG4gIC8vIDE1bSwgMWgsIDRoLCAxMmgsIDFkLCAyZCwgNGQsIDdkLCAxNGQuXG4gIGVjb3N5c3RlbV9kZWNpc2lvbl9sYXRlbmN5X3NlY29uZHM6IFs5MDAsIDM2MDAsIDE0NDAwLCA0MzIwMCwgODY0MDAsIDE3MjgwMCwgMzQ1NjAwLCA2MDQ4MDAsIDEyMDk2MDBdLFxuICAvLyBRdWV1ZSB3YWl0LiBgUGx1Z2luUXVldWVQcm9jZXNzaW5nU2xvd2AgYXNzZXJ0cyBwOTUgPiAzMDAsIHdoaWNoIHRoZSBkZWZhdWx0XG4gIC8vIGNlaWxpbmcgb2YgMzAwIG1hZGUgdW5maXJlYWJsZTsgMzAwIGlzIGEgYm91bmRhcnkgaGVyZSBzbyB0aGUgY29tcGFyaXNvbiBpc1xuICAvLyBleGFjdCByYXRoZXIgdGhhbiBpbnRlcnBvbGF0ZWQuXG4gIHBsdWdpbl9qb2Jfd2FpdF9zZWNvbmRzOiBbMSwgNSwgMTUsIDMwLCA2MCwgMTIwLCAzMDAsIDYwMCwgMTgwMCwgMzYwMF0sXG4gIC8vIEEgY29udGFpbmVyIGJ1aWxkLiBNaW51dGVzIG5vcm1hbGx5LCBmYXIgbG9uZ2VyIGZvciBhIGNvbGQgYmFzZSBpbWFnZS5cbiAgcGx1Z2luX2J1aWxkX2R1cmF0aW9uX3NlY29uZHM6IFsxMCwgMzAsIDYwLCAxMjAsIDMwMCwgNjAwLCAxMjAwLCAxODAwLCAzNjAwXSxcbiAgLy8gQSBmdWxsIGltYWdlIHNjYW4sIHdoaWNoIHJvdXRpbmVseSBwYXNzZXMgZml2ZSBtaW51dGVzIG9uIGEgbGFyZ2UgaW1hZ2UuXG4gIHBsdWdpbl92dWxuX3NjYW5fZHVyYXRpb25fc2Vjb25kczogWzEsIDUsIDE1LCAzMCwgNjAsIDEyMCwgMzAwLCA2MDAsIDEyMDBdLFxuICAvLyBUaW1lIGZyb20gYW4gaW5jaWRlbnQgYmVpbmcgcmFpc2VkIHRvIGEgaHVtYW4gYWNrbm93bGVkZ2luZyBpdC4gVGhlIGRlZmF1bHRcbiAgLy8gYnVja2V0cyBlbmQgYXQgMzAwcywgYW5kIGBoaXN0b2dyYW1fcXVhbnRpbGVgIGNhbm5vdCBpbnRlcnBvbGF0ZSBwYXN0IHRoZVxuICAvLyBsYXN0IGZpbml0ZSBib3VuZGFyeSDigJQgc28gd2l0aCB0aGVtLCBhbnkgdGhyZXNob2xkIGFib3ZlIGZpdmUgbWludXRlcyBjb3VsZFxuICAvLyBuZXZlciBmaXJlLCB3aGljaCBpcyBldmVyeSB0aHJlc2hvbGQgd29ydGggc2V0dGluZyBoZXJlLiBCb3VuZGFyaWVzIGF0IDFtLFxuICAvLyAybSwgNW0sIDEwbSwgMTVtLCAzMG0sIDFoLCAyaCwgNGg6IDE1bSBpcyBleGFjdCBiZWNhdXNlIHRoYXQgaXMgdGhlXG4gIC8vIGVzY2FsYXRpb24gZGVsYXkgdGhlIGFsZXJ0IGNvbXBhcmVzIGFnYWluc3QsIGFuZCB0aGUgcmFuZ2UgcmVhY2hlcyA0aCBzbyBhXG4gIC8vIHBhZ2Ugbm9ib2R5IGV2ZXIgcGlja2VkIHVwIGlzIHN0aWxsIGNvdW50ZWQgcmF0aGVyIHRoYW4gY2xpcHBlZC5cbiAgb25jYWxsX3BhZ2VfYWNrX3NlY29uZHM6IFs2MCwgMTIwLCAzMDAsIDYwMCwgOTAwLCAxODAwLCAzNjAwLCA3MjAwLCAxNDQwMF0sXG4gIC8vIENTQVQsIDEtNS4gTm90IGEgZHVyYXRpb24gYXQgYWxsLCBhbmQgbGlzdGVkIGhlcmUgZm9yIHRoZSBzYW1lIHJlYXNvbiBhc1xuICAvLyB0aGUgb3RoZXJzOiB0aGUgZGVmYXVsdCBidWNrZXRzIGFyZSBzdWItc2Vjb25kLCBzbyBldmVyeSByYXRpbmcgd291bGQgbGFuZFxuICAvLyBpbiB0aGUgc2FtZSBidWNrZXQgYW5kIHRoZSBxdWFudGlsZSB3b3VsZCBiZSBtZWFuaW5nbGVzcy4gT25lIGJvdW5kYXJ5IHBlclxuICAvLyBwb3NzaWJsZSBzY29yZSBtYWtlcyBgX3N1bSAvIF9jb3VudGAgYW4gZXhhY3QgYXZlcmFnZSBhbmQgZWFjaCBidWNrZXQgYVxuICAvLyByZWFsIGNvdW50LiBJdCByaWRlcyB0aGUgaGlzdG9ncmFtIHJhdGhlciB0aGFuIGEgY291bnRlci1wZXItc2NvcmUgc28gdGhlXG4gIC8vIGF2ZXJhZ2UgbmVlZHMgbm8gUHJvbVFMIGFyaXRobWV0aWMgb3ZlciBmaXZlIHNlcmllcy5cbiAgc3VwcG9ydF9zYXRpc2ZhY3Rpb246IFsxLCAyLCAzLCA0LCA1XSxcbn07XG5cbi8qKiBUaGUgbGF6eSBidXNpbmVzcy1tZXRyaWMgaGVscGVycywgYm91bmQgdG8gb25lIHJlZ2lzdHJ5LiAqL1xuZXhwb3J0IGludGVyZmFjZSBNZXRyaWNIZWxwZXJzIHtcbiAgaW5jQ291bnRlcihuYW1lOiBzdHJpbmcsIGxhYmVscz86IFJlY29yZDxzdHJpbmcsIHN0cmluZz4sIHZhbHVlPzogbnVtYmVyKTogdm9pZDtcbiAgb2JzZXJ2ZShuYW1lOiBzdHJpbmcsIGxhYmVsczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiwgdmFsdWU6IG51bWJlcik6IHZvaWQ7XG4gIHNldEdhdWdlKG5hbWU6IHN0cmluZywgbGFiZWxzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+LCB2YWx1ZTogbnVtYmVyKTogdm9pZDtcbiAgcmVzZXRHYXVnZShuYW1lOiBzdHJpbmcpOiB2b2lkO1xufVxuXG4vKipcbiAqIEJ1aWxkIGBpbmNDb3VudGVyYCAvIGBvYnNlcnZlYCAvIGBzZXRHYXVnZWAgb3ZlciBhIGNhbGxlci1zdXBwbGllZCByZWdpc3RyeS5cbiAqXG4gKiBUSEUgb25lIGltcGxlbWVudGF0aW9uIG9mIHRoZSBsYXp5IGNvdW50ZXIvaGlzdG9ncmFtL2dhdWdlIG1hcHMuIGFwaS1zZXJ2ZXInc1xuICogb3duIGV4cG9ydHMgYmVsb3cgYXJlIHRoaXMgZmFjdG9yeSBvdmVyIGl0cyBtb2R1bGUtbGV2ZWwgYHJlZ2lzdGVyYDsgdGhlXG4gKiBwbGF0Zm9ybSBzZXJ2aWNlIOKAlCB3aGljaCBydW5zIGl0cyBvd24gRXhwcmVzcyBzZXR1cCBpbnN0ZWFkIG9mIGBjcmVhdGVBcHBgLFxuICogYW5kIHRoZXJlZm9yZSBvd25zIGEgZGlmZmVyZW50IHJlZ2lzdHJ5IOKAlCBidWlsZHMgdGhlIGlkZW50aWNhbCBoZWxwZXJzIG92ZXJcbiAqIGl0cyBvd24uIFdpdGhvdXQgdGhlIGZhY3RvcnkgdGhlIHR3byBkcmlmdDogdGhleSBkaWZmZXIgdG9kYXkgb25seSBpbiB0aGVcbiAqIGhpc3RvZ3JhbSBidWNrZXRzLCB3aGljaCBpcyBleGFjdGx5IHRoZSBraW5kIG9mIGRpZmZlcmVuY2Ugbm9ib2R5IG5vdGljZXNcbiAqIHVudGlsIGEgZGFzaGJvYXJkIHJlYWRzIHdyb25nIG9uIG9uZSBzZXJ2aWNlLlxuICpcbiAqIGByZWdpc3RyeWAgbWF5IGJlIGEgdGh1bmssIGZvciBhIHJlZ2lzdHJ5IHRoYXQgaXMgaW5qZWN0ZWQgYWZ0ZXIgbW9kdWxlIGxvYWRcbiAqIChwbGF0Zm9ybSB3aXJlcyBpdHMgb3duIG9uIGFwcCBib290KS4gVGhlIHRodW5rIGlzIGNhbGxlZCBvbiB0aGUgRklSU1QgdXNlIG9mXG4gKiBlYWNoIG1ldHJpYyBuYW1lLCBuZXZlciBhdCBpbXBvcnQgdGltZSwgc28gYnVpbGRpbmcgdGhlIGhlbHBlcnMgaGFzIG5vIHNpZGVcbiAqIGVmZmVjdCBvZiBpdHMgb3duLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlTWV0cmljSGVscGVycyhyZWdpc3RyeTogUmVnaXN0cnkgfCAoKCkgPT4gUmVnaXN0cnkpKTogTWV0cmljSGVscGVycyB7XG4gIGNvbnN0IHJlZ2lzdHJ5T2YgPSAoKTogUmVnaXN0cnkgPT4gKHR5cGVvZiByZWdpc3RyeSA9PT0gJ2Z1bmN0aW9uJyA/IHJlZ2lzdHJ5KCkgOiByZWdpc3RyeSk7XG4gIGNvbnN0IGNvdW50ZXJzID0gbmV3IE1hcDxzdHJpbmcsIENvdW50ZXI8c3RyaW5nPj4oKTtcbiAgY29uc3QgaGlzdG9ncmFtcyA9IG5ldyBNYXA8c3RyaW5nLCBIaXN0b2dyYW08c3RyaW5nPj4oKTtcbiAgY29uc3QgZ2F1Z2VzID0gbmV3IE1hcDxzdHJpbmcsIEdhdWdlPHN0cmluZz4+KCk7XG5cbiAgcmV0dXJuIHtcbiAgICBpbmNDb3VudGVyKG5hbWUsIGxhYmVscyA9IHt9LCB2YWx1ZSA9IDEpIHtcbiAgICAgIGxldCBjb3VudGVyID0gY291bnRlcnMuZ2V0KG5hbWUpO1xuICAgICAgaWYgKCFjb3VudGVyKSB7XG4gICAgICAgIGNvdW50ZXIgPSBuZXcgQ291bnRlcih7XG4gICAgICAgICAgbmFtZSxcbiAgICAgICAgICBoZWxwOiBodW1hbml6ZU5hbWUobmFtZSksXG4gICAgICAgICAgbGFiZWxOYW1lczogT2JqZWN0LmtleXMobGFiZWxzKSxcbiAgICAgICAgICByZWdpc3RlcnM6IFtyZWdpc3RyeU9mKCldLFxuICAgICAgICB9KTtcbiAgICAgICAgY291bnRlcnMuc2V0KG5hbWUsIGNvdW50ZXIpO1xuICAgICAgfVxuICAgICAgY291bnRlci5pbmMobGFiZWxzLCB2YWx1ZSk7XG4gICAgfSxcblxuICAgIG9ic2VydmUobmFtZSwgbGFiZWxzLCB2YWx1ZSkge1xuICAgICAgbGV0IGhpc3QgPSBoaXN0b2dyYW1zLmdldChuYW1lKTtcbiAgICAgIGlmICghaGlzdCkge1xuICAgICAgICBoaXN0ID0gbmV3IEhpc3RvZ3JhbSh7XG4gICAgICAgICAgbmFtZSxcbiAgICAgICAgICBoZWxwOiBodW1hbml6ZU5hbWUobmFtZSksXG4gICAgICAgICAgbGFiZWxOYW1lczogT2JqZWN0LmtleXMobGFiZWxzKSxcbiAgICAgICAgICAvLyBEZWZhdWx0IGJ1Y2tldHMgdGFyZ2V0IHN1Yi1zZWNvbmQgdGhyb3VnaCBzZXZlcmFsLW1pbnV0ZVxuICAgICAgICAgIC8vIG9ic2VydmF0aW9ucy4gQW55dGhpbmcgdGhhdCBjYW4gZXhjZWVkIGZpdmUgbWludXRlcyBNVVNUIGRlY2xhcmUgaXRzXG4gICAgICAgICAgLy8gb3duIGRpc3RyaWJ1dGlvbiBpbiBgSElTVE9HUkFNX0JVQ0tFVFNgIGFib3ZlIOKAlCBwYXN0IHRoZSBsYXN0IGZpbml0ZVxuICAgICAgICAgIC8vIGJvdW5kYXJ5IGEgcXVhbnRpbGUgcmVhZHMgYmFjayBhcyB0aGF0IGJvdW5kYXJ5LCBzbyBhIHRocmVzaG9sZFxuICAgICAgICAgIC8vIGJleW9uZCBpdCBuZXZlciBmaXJlcy5cbiAgICAgICAgICBidWNrZXRzOiBbLi4uKEhJU1RPR1JBTV9CVUNLRVRTW25hbWVdID8/IFswLjA1LCAwLjEsIDAuMjUsIDAuNSwgMSwgMi41LCA1LCAxMCwgMzAsIDYwLCAxMjAsIDMwMF0pXSxcbiAgICAgICAgICByZWdpc3RlcnM6IFtyZWdpc3RyeU9mKCldLFxuICAgICAgICB9KTtcbiAgICAgICAgaGlzdG9ncmFtcy5zZXQobmFtZSwgaGlzdCk7XG4gICAgICB9XG4gICAgICBoaXN0Lm9ic2VydmUobGFiZWxzLCB2YWx1ZSk7XG4gICAgfSxcblxuICAgIHNldEdhdWdlKG5hbWUsIGxhYmVscywgdmFsdWUpIHtcbiAgICAgIGxldCBnYXVnZSA9IGdhdWdlcy5nZXQobmFtZSk7XG4gICAgICBpZiAoIWdhdWdlKSB7XG4gICAgICAgIGdhdWdlID0gbmV3IEdhdWdlKHtcbiAgICAgICAgICBuYW1lLFxuICAgICAgICAgIGhlbHA6IGh1bWFuaXplTmFtZShuYW1lKSxcbiAgICAgICAgICBsYWJlbE5hbWVzOiBPYmplY3Qua2V5cyhsYWJlbHMpLFxuICAgICAgICAgIHJlZ2lzdGVyczogW3JlZ2lzdHJ5T2YoKV0sXG4gICAgICAgIH0pO1xuICAgICAgICBnYXVnZXMuc2V0KG5hbWUsIGdhdWdlKTtcbiAgICAgIH1cbiAgICAgIGdhdWdlLnNldChsYWJlbHMsIHZhbHVlKTtcbiAgICB9LFxuXG4gICAgcmVzZXRHYXVnZShuYW1lKSB7XG4gICAgICBnYXVnZXMuZ2V0KG5hbWUpPy5yZXNldCgpO1xuICAgIH0sXG4gIH07XG59XG5cbi8qKiBUaGlzIHNlcnZpY2UncyBvd24gaGVscGVycywgb3ZlciB0aGUgc2hhcmVkIG1vZHVsZS1sZXZlbCByZWdpc3RyeS4gKi9cbmNvbnN0IGJ1c2luZXNzTWV0cmljcyA9IGNyZWF0ZU1ldHJpY0hlbHBlcnMocmVnaXN0ZXIpO1xuXG4vKipcbiAqIEluY3JlbWVudCBhIGJ1c2luZXNzIGNvdW50ZXIsIGNyZWF0aW5nIGl0IG9uIGZpcnN0IHVzZS5cbiAqXG4gKiBFdmVyeSBleGFtcGxlIGJlbG93IGlzIGEgY2FsbCB0aGF0IEVYSVNUUywgd2l0aCB0aGUgbGFiZWxzIGl0IHJlYWxseSBwYXNzZXMuIFRoYXQgaXNcbiAqIGRlbGliZXJhdGU6IGFuIGludmVudGVkIGV4YW1wbGUgcmVhZHMgYXMgYW4gaW52ZW50b3J5IG9mIHdoYXQgdGhlIHN5c3RlbSBtZWFzdXJlcywgYW5kXG4gKiBhIG1ldHJpY3Mgc3VydmV5IGxhdGVyIGNvdW50ZWQgdGhyZWUgbmFtZXMgZnJvbSB0aGlzIGJsb2NrIOKAlCBgcGlwZWxpbmVzX2dlbmVyYXRlZF90b3RhbGAsXG4gKiBgcXVvdGFfdGhyZXNob2xkX2Nyb3NzZWRfdG90YWxgLCBgY29tcGxpYW5jZV92aW9sYXRpb25zX2ZvdW5kX3RvdGFsYCDigJQgYXMgbGl2ZSBtZXRyaWNzXG4gKiBtaXNzaW5nIGEgZGFzaGJvYXJkIHBhbmVsLiBOb3RoaW5nIGVtaXR0ZWQgYW55IG9mIHRoZW0uIElsbHVzdHJhdGl2ZSBuYW1lcyBpbiBhIGRvY3N0cmluZ1xuICogYWJvdXQgbWV0cmljIG5hbWluZyBhcmUgaW5kaXN0aW5ndWlzaGFibGUgZnJvbSByZWFsIG9uZXMsIHNvIHRoZXJlIGFyZSBub25lIGhlcmUuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGluY0NvdW50ZXIoJ3BsdWdpbl9idWlsZHNfdG90YWwnLCB7IHN0YXR1czogJ3N1Y2Nlc3MnLCBvcmdfaWQ6IG9yZ0lkIH0pO1xuICogaW5jQ291bnRlcignY29tcGxpYW5jZV9zY2Fuc190b3RhbCcsIHsgb3V0Y29tZTogJ3N0YXJ0ZWQnIH0pO1xuICogaW5jQ291bnRlcigncGx1Z2luX3Z1bG5fZmluZGluZ3NfdG90YWwnLCB7IHRyaWdnZXIsIHNldmVyaXR5IH0sIGNvdW50KTtcbiAqIGluY0NvdW50ZXIoJ2FpX3Rva2Vuc190b3RhbCcsIHsgcm91dGU6ICdhZ2VudCcsIGtpbmQ6ICdpbnB1dCcgfSwgaW5wdXRUb2tlbnMpO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbmNDb3VudGVyKG5hbWU6IHN0cmluZywgbGFiZWxzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge30sIHZhbHVlID0gMSk6IHZvaWQge1xuICBidXNpbmVzc01ldHJpY3MuaW5jQ291bnRlcihuYW1lLCBsYWJlbHMsIHZhbHVlKTtcbn1cblxuLyoqXG4gKiBSZWNvcmQgYW4gb2JzZXJ2YXRpb24gb24gYSBidXNpbmVzcyBoaXN0b2dyYW0sIGNyZWF0aW5nIGl0IG9uIGZpcnN0IHVzZS5cbiAqIFVzZSBmb3IgZHVyYXRpb25zLCBzaXplcywgYW55dGhpbmcgd2hlcmUgcGVyY2VudGlsZXMgbWF0dGVyLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBvYnNlcnZlKCdhaV9nZW5lcmF0aW9uX2R1cmF0aW9uX3NlY29uZHMnLCB7IHJvdXRlLCBwcm92aWRlcjogcHJvdmlkZXJMYWJlbCB9LCBkdXJhdGlvblNlYyk7XG4gKiBvYnNlcnZlKCdwbHVnaW5fYnVpbGRfZHVyYXRpb25fc2Vjb25kcycsIHsgb3JnX2lkOiBvcmdJZCB9LCBkdXJhdGlvblNlYyk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG9ic2VydmUobmFtZTogc3RyaW5nLCBsYWJlbHM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4sIHZhbHVlOiBudW1iZXIpOiB2b2lkIHtcbiAgYnVzaW5lc3NNZXRyaWNzLm9ic2VydmUobmFtZSwgbGFiZWxzLCB2YWx1ZSk7XG59XG5cbi8qKlxuICogU2V0IHRoZSB2YWx1ZSBvZiBhIGJ1c2luZXNzIGdhdWdlLCBjcmVhdGluZyBpdCBvbiBmaXJzdCB1c2UuIFVzZSBmb3JcbiAqIHBvaW50LWluLXRpbWUgb2JzZXJ2YXRpb25zIHNhbXBsZWQgYnkgYSBzY3JhcGVyIOKAlCBxdWV1ZSBkZXB0aCwgYWN0aXZlXG4gKiBjb25uZWN0aW9uIGNvdW50cywgaW4tZmxpZ2h0IHJlcXVlc3RzLlxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0eXBlc2NyaXB0XG4gKiBzZXRHYXVnZSgncGx1Z2luX3F1ZXVlX2pvYnMnLCB7IHF1ZXVlOiAncGx1Z2luLWJ1aWxkJywgc3RhdGU6ICd3YWl0aW5nJyB9LCAxMik7XG4gKiBzZXRHYXVnZSgncGx1Z2luX3F1ZXVlX2pvYnMnLCB7IHF1ZXVlOiAncGx1Z2luLWJ1aWxkJywgc3RhdGU6ICdhY3RpdmUnIH0sIDMpO1xuICogYGBgXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRHYXVnZShuYW1lOiBzdHJpbmcsIGxhYmVsczogUmVjb3JkPHN0cmluZywgc3RyaW5nPiwgdmFsdWU6IG51bWJlcik6IHZvaWQge1xuICBidXNpbmVzc01ldHJpY3Muc2V0R2F1Z2UobmFtZSwgbGFiZWxzLCB2YWx1ZSk7XG59XG5cbi8qKlxuICogRHJvcCBFVkVSWSBzZXJpZXMgb2YgYSBidXNpbmVzcyBnYXVnZS4gRm9yIGEgZ2F1Z2UgdGhhdCBkZXNjcmliZXMgYSBTRVQg4oCUIG9uZVxuICogc2VyaWVzIHBlciBjb25maWd1cmVkIGVudHJ5IOKAlCBhbmQgaXMgcmUtcHVibGlzaGVkIHdob2xlOiB3aXRob3V0IHRoZSByZXNldCwgYVxuICogc2VyaWVzIGZvciBhbiBlbnRyeSB0aGF0IGhhcyBzaW5jZSBiZWVuIGRlbGV0ZWQga2VlcHMgaXRzIGxhc3QgdmFsdWUgZm9yZXZlcixcbiAqIGFuZCBhbiBhbGVydCBvbiBpdCBrZWVwcyBmaXJpbmcgZm9yIHNvbWV0aGluZyB0aGF0IG5vIGxvbmdlciBleGlzdHMuIENhbGwgaXRcbiAqIGltbWVkaWF0ZWx5IGJlZm9yZSByZS1zZXR0aW5nIHRoZSBjdXJyZW50IHNldC4gQSBnYXVnZSBuZXZlciBzZXQgaXMgYSBuby1vcC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc2V0R2F1Z2UobmFtZTogc3RyaW5nKTogdm9pZCB7XG4gIGJ1c2luZXNzTWV0cmljcy5yZXNldEdhdWdlKG5hbWUpO1xufVxuXG5mdW5jdGlvbiBodW1hbml6ZU5hbWUobWV0cmljTmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgLy8gYHBsdWdpbl9idWlsZHNfdG90YWxgIOKGkiBcIlBsdWdpbiBidWlsZHMgdG90YWxcIlxuICByZXR1cm4gbWV0cmljTmFtZVxuICAgIC5yZXBsYWNlKC9fL2csICcgJylcbiAgICAucmVwbGFjZSgvXi4vLCAoYykgPT4gYy50b1VwcGVyQ2FzZSgpKTtcbn1cbiJdfQ==
@@ -1,4 +1,4 @@
1
- import { type QuotaReserveResult, type QuotaService, type QuotaType } from '@pipeline-builder/api-core';
1
+ import { type QuotaReserveResult, type QuotaService, type QuotaType, type QuotaUsageAttribution } from '@pipeline-builder/api-core';
2
2
  import type { Response } from 'express';
3
3
  /** The reserved quota slot, handed to the guarded body. */
4
4
  export interface QuotaSlot {
@@ -10,13 +10,27 @@ export interface QuotaSlot {
10
10
  * responding). From here on a failure KEEPS the slot — the cost was incurred.
11
11
  */
12
12
  markConsumed(): void;
13
- /** Give the slot back now. Idempotent: refunds at most once. */
13
+ /**
14
+ * Give the slot back now. Idempotent: refunds at most once — and a NO-OP once
15
+ * {@link markConsumed} was called. A paid provider round-trip is never refunded,
16
+ * whatever path (a client abort, a later failure, an empty answer) asks for it
17
+ * afterwards; callers no longer need to guard `refund()` with their own
18
+ * "was the provider contacted" flag.
19
+ */
14
20
  refund(): void;
15
21
  }
16
22
  export interface QuotaReservationOptions {
17
23
  quotaService: QuotaService;
18
24
  orgId: string;
19
25
  type: QuotaType;
26
+ /** Units to reserve (default 1) — e.g. an AI model's weight. Refunds give back the same amount. */
27
+ amount?: number;
28
+ /**
29
+ * Usage-ledger attribution for the reserve AND its refund. Defaults to the
30
+ * ambient request context (principal + request id, no route) — pass it
31
+ * explicitly to record the route, the feature and the model.
32
+ */
33
+ attribution?: QuotaUsageAttribution;
20
34
  /** Signer of the quota service token. Defaults to this process (`SERVICE_NAME`). */
21
35
  serviceName?: string;
22
36
  logWarn: (message: string, data?: unknown) => void;
@@ -35,12 +49,37 @@ export type QuotaReservationOutcome<T> = {
35
49
  status: 'failed';
36
50
  error: unknown;
37
51
  };
52
+ /** What {@link reserveQuotaSlot} hands back: a live slot, or the denial. */
53
+ export type QuotaSlotReservation = {
54
+ status: 'denied';
55
+ reservation: QuotaReserveResult;
56
+ } | {
57
+ status: 'reserved';
58
+ slot: QuotaSlot;
59
+ };
60
+ /**
61
+ * Reserve one slot (of `amount` units) and return its handle, WITHOUT running
62
+ * anything. The primitive under {@link withQuotaReservation}, for a caller whose
63
+ * gated work does not fit one callback — e.g. a tool inside an agent turn that
64
+ * settles its own slot. The caller owns settlement: `markConsumed()` once the
65
+ * resource is spent, `refund()` on every path that fails before that.
66
+ *
67
+ * Denied → `{ status: 'denied' }`, answered on `res` when given.
68
+ */
69
+ export declare function reserveQuotaSlot(opts: QuotaReservationOptions): Promise<QuotaSlotReservation>;
70
+ /**
71
+ * Run `body` against a reserved slot and settle it by ONE rule: keep it once
72
+ * the resource was consumed; refund it if the body fails first. Shared by
73
+ * {@link withQuotaReservation} and api-server's AI reservation.
74
+ */
75
+ export declare function runWithSlot<T, S extends QuotaSlot>(slot: S, body: (slot: S) => Promise<T>, onError?: (error: unknown) => void | Promise<void>): Promise<QuotaReservationOutcome<T>>;
38
76
  /**
39
77
  * Reserve one quota slot, run `body`, and settle the slot by ONE rule:
40
78
  * keep it once the resource was consumed; refund it if the body fails first.
41
79
  *
42
80
  * - Denied → `{ status: 'denied' }` (answered on `res` when given); `body` never runs.
43
- * - `body` resolves → the slot is kept (unless `body` called `slot.refund()`).
81
+ * - `body` resolves → the slot is kept (unless `body` called `slot.refund()`
82
+ * BEFORE marking it consumed — a refund after `markConsumed()` is ignored).
44
83
  * - `body` throws → refunded unless consumed — marked via `slot.markConsumed()`
45
84
  * or signalled by the error itself carrying `providerContacted === true`
46
85
  * (an AI round-trip that completed but produced nothing usable). The error is
@@ -2,25 +2,22 @@
2
2
  // SPDX-License-Identifier: Apache-2.0
3
3
  import { decrementQuota, getServiceAuthHeader, reserveQuota, sendQuotaReserveDenied, serviceIdentity, } from '@pipeline-builder/api-core';
4
4
  /**
5
- * Reserve one quota slot, run `body`, and settle the slot by ONE rule:
6
- * keep it once the resource was consumed; refund it if the body fails first.
7
- *
8
- * - Denied → `{ status: 'denied' }` (answered on `res` when given); `body` never runs.
9
- * - `body` resolves → the slot is kept (unless `body` called `slot.refund()`).
10
- * - `body` throws → refunded unless consumed — marked via `slot.markConsumed()`
11
- * or signalled by the error itself carrying `providerContacted === true`
12
- * (an AI round-trip that completed but produced nothing usable). The error is
13
- * then passed to `onError`, or rethrown when there is none.
5
+ * Reserve one slot (of `amount` units) and return its handle, WITHOUT running
6
+ * anything. The primitive under {@link withQuotaReservation}, for a caller whose
7
+ * gated work does not fit one callback — e.g. a tool inside an agent turn that
8
+ * settles its own slot. The caller owns settlement: `markConsumed()` once the
9
+ * resource is spent, `refund()` on every path that fails before that.
14
10
  *
15
- * The reserve and refund authenticate with a minted service token, never the
16
- * end-user bearer: the quota increment endpoint rejects user principals.
11
+ * Denied → `{ status: 'denied' }`, answered on `res` when given.
17
12
  */
18
- export async function withQuotaReservation(opts, body, onError) {
19
- const { quotaService, orgId, type, logWarn } = opts;
13
+ export async function reserveQuotaSlot(opts) {
14
+ const { quotaService, orgId, type, logWarn, attribution } = opts;
15
+ const amount = opts.amount ?? 1;
20
16
  const serviceAuth = getServiceAuthHeader({ serviceName: opts.serviceName ?? serviceIdentity(), orgId, role: 'member' });
21
17
  // Reserve atomically BEFORE any work: two concurrent requests at the limit
22
- // can't both pass.
23
- const reservation = await reserveQuota(quotaService, orgId, type, serviceAuth);
18
+ // can't both pass. Attribution defaults to the ambient request context
19
+ // (principal + request id) inside the quota client.
20
+ const reservation = await reserveQuota(quotaService, orgId, type, serviceAuth, amount, attribution);
24
21
  if (reservation.exceeded) {
25
22
  if (opts.res)
26
23
  sendQuotaReserveDenied(opts.res, type, reservation);
@@ -33,19 +30,28 @@ export async function withQuotaReservation(opts, body, onError) {
33
30
  reservation,
34
31
  markConsumed: () => { consumed = true; },
35
32
  refund: () => {
36
- if (refunded)
33
+ if (refunded || consumed)
37
34
  return;
38
35
  refunded = true;
39
36
  // The reserved resetAt keeps a period rollover from being double-charged.
40
- decrementQuota(quotaService, orgId, type, serviceAuth, logWarn, 1, reservation.quota.resetAt);
37
+ decrementQuota(quotaService, orgId, type, serviceAuth, logWarn, amount, reservation.quota.resetAt, attribution);
41
38
  },
42
39
  };
40
+ return { status: 'reserved', slot };
41
+ }
42
+ /**
43
+ * Run `body` against a reserved slot and settle it by ONE rule: keep it once
44
+ * the resource was consumed; refund it if the body fails first. Shared by
45
+ * {@link withQuotaReservation} and api-server's AI reservation.
46
+ */
47
+ export async function runWithSlot(slot, body, onError) {
43
48
  try {
44
49
  return { status: 'done', value: await body(slot) };
45
50
  }
46
51
  catch (error) {
52
+ // `refund()` is itself a no-op once the slot was marked consumed.
47
53
  const errorSaysConsumed = error?.providerContacted === true;
48
- if (!consumed && !errorSaysConsumed)
54
+ if (!errorSaysConsumed)
49
55
  slot.refund();
50
56
  if (!onError)
51
57
  throw error;
@@ -53,4 +59,25 @@ export async function withQuotaReservation(opts, body, onError) {
53
59
  return { status: 'failed', error };
54
60
  }
55
61
  }
56
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVvdGEtcmVzZXJ2YXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXBpL3F1b3RhLXJlc2VydmF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxFQUNMLGNBQWMsRUFDZCxvQkFBb0IsRUFDcEIsWUFBWSxFQUNaLHNCQUFzQixFQUN0QixlQUFlLEdBSWhCLE1BQU0sNEJBQTRCLENBQUM7QUFrQ3BDOzs7Ozs7Ozs7Ozs7O0dBYUc7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLG9CQUFvQixDQUN4QyxJQUE2QixFQUM3QixJQUFxQyxFQUNyQyxPQUFrRDtJQUVsRCxNQUFNLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLEdBQUcsSUFBSSxDQUFDO0lBQ3BELE1BQU0sV0FBVyxHQUFHLG9CQUFvQixDQUFDLEVBQUUsV0FBVyxFQUFFLElBQUksQ0FBQyxXQUFXLElBQUksZUFBZSxFQUFFLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO0lBRXhILDJFQUEyRTtJQUMzRSxtQkFBbUI7SUFDbkIsTUFBTSxXQUFXLEdBQUcsTUFBTSxZQUFZLENBQUMsWUFBWSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsV0FBVyxDQUFDLENBQUM7SUFDL0UsSUFBSSxXQUFXLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDekIsSUFBSSxJQUFJLENBQUMsR0FBRztZQUFFLHNCQUFzQixDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsSUFBSSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1FBQ2xFLE9BQU8sRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLFdBQVcsRUFBRSxDQUFDO0lBQzNDLENBQUM7SUFFRCxJQUFJLFFBQVEsR0FBRyxLQUFLLENBQUM7SUFDckIsSUFBSSxRQUFRLEdBQUcsS0FBSyxDQUFDO0lBQ3JCLE1BQU0sSUFBSSxHQUFjO1FBQ3RCLFdBQVc7UUFDWCxXQUFXO1FBQ1gsWUFBWSxFQUFFLEdBQUcsRUFBRSxHQUFHLFFBQVEsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ3hDLE1BQU0sRUFBRSxHQUFHLEVBQUU7WUFDWCxJQUFJLFFBQVE7Z0JBQUUsT0FBTztZQUNyQixRQUFRLEdBQUcsSUFBSSxDQUFDO1lBQ2hCLDBFQUEwRTtZQUMxRSxjQUFjLENBQUMsWUFBWSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsV0FBVyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUNoRyxDQUFDO0tBQ0YsQ0FBQztJQUVGLElBQUksQ0FBQztRQUNILE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO0lBQ3JELENBQUM7SUFBQyxPQUFPLEtBQUssRUFBRSxDQUFDO1FBQ2YsTUFBTSxpQkFBaUIsR0FBSSxLQUFnRCxFQUFFLGlCQUFpQixLQUFLLElBQUksQ0FBQztRQUN4RyxJQUFJLENBQUMsUUFBUSxJQUFJLENBQUMsaUJBQWlCO1lBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ25ELElBQUksQ0FBQyxPQUFPO1lBQUUsTUFBTSxLQUFLLENBQUM7UUFDMUIsTUFBTSxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDckIsT0FBTyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLENBQUM7SUFDckMsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHtcbiAgZGVjcmVtZW50UXVvdGEsXG4gIGdldFNlcnZpY2VBdXRoSGVhZGVyLFxuICByZXNlcnZlUXVvdGEsXG4gIHNlbmRRdW90YVJlc2VydmVEZW5pZWQsXG4gIHNlcnZpY2VJZGVudGl0eSxcbiAgdHlwZSBRdW90YVJlc2VydmVSZXN1bHQsXG4gIHR5cGUgUXVvdGFTZXJ2aWNlLFxuICB0eXBlIFF1b3RhVHlwZSxcbn0gZnJvbSAnQHBpcGVsaW5lLWJ1aWxkZXIvYXBpLWNvcmUnO1xuaW1wb3J0IHR5cGUgeyBSZXNwb25zZSB9IGZyb20gJ2V4cHJlc3MnO1xuXG4vKiogVGhlIHJlc2VydmVkIHF1b3RhIHNsb3QsIGhhbmRlZCB0byB0aGUgZ3VhcmRlZCBib2R5LiAqL1xuZXhwb3J0IGludGVyZmFjZSBRdW90YVNsb3Qge1xuICAvKiogTWludGVkIHNlcnZpY2UgdG9rZW4gdGhlIHJlc2VydmF0aW9uIHVzZWQg4oCUIHJldXNlIGl0IGZvciB0aGUgYm9keSdzIG93biBTMlMgY2FsbHMuICovXG4gIHJlYWRvbmx5IHNlcnZpY2VBdXRoOiBzdHJpbmc7XG4gIHJlYWRvbmx5IHJlc2VydmF0aW9uOiBRdW90YVJlc2VydmVSZXN1bHQ7XG4gIC8qKlxuICAgKiBUaGUgcmVzZXJ2ZWQgcmVzb3VyY2UgaGFzIGJlZW4gY29uc3VtZWQgKGUuZy4gdGhlIEFJIHByb3ZpZGVyIHN0YXJ0ZWRcbiAgICogcmVzcG9uZGluZykuIEZyb20gaGVyZSBvbiBhIGZhaWx1cmUgS0VFUFMgdGhlIHNsb3Qg4oCUIHRoZSBjb3N0IHdhcyBpbmN1cnJlZC5cbiAgICovXG4gIG1hcmtDb25zdW1lZCgpOiB2b2lkO1xuICAvKiogR2l2ZSB0aGUgc2xvdCBiYWNrIG5vdy4gSWRlbXBvdGVudDogcmVmdW5kcyBhdCBtb3N0IG9uY2UuICovXG4gIHJlZnVuZCgpOiB2b2lkO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFF1b3RhUmVzZXJ2YXRpb25PcHRpb25zIHtcbiAgcXVvdGFTZXJ2aWNlOiBRdW90YVNlcnZpY2U7XG4gIG9yZ0lkOiBzdHJpbmc7XG4gIHR5cGU6IFF1b3RhVHlwZTtcbiAgLyoqIFNpZ25lciBvZiB0aGUgcXVvdGEgc2VydmljZSB0b2tlbi4gRGVmYXVsdHMgdG8gdGhpcyBwcm9jZXNzIChgU0VSVklDRV9OQU1FYCkuICovXG4gIHNlcnZpY2VOYW1lPzogc3RyaW5nO1xuICBsb2dXYXJuOiAobWVzc2FnZTogc3RyaW5nLCBkYXRhPzogdW5rbm93bikgPT4gdm9pZDtcbiAgLyoqIFdoZW4gc2V0LCBhIGRlbmllZCByZXNlcnZhdGlvbiBpcyBhbnN3ZXJlZCBvbiBpdCAoNDI5LCBvciA1MDMgd2hlbiB1bmNvbmZpcm1hYmxlKS4gKi9cbiAgcmVzPzogUmVzcG9uc2U7XG59XG5cbmV4cG9ydCB0eXBlIFF1b3RhUmVzZXJ2YXRpb25PdXRjb21lPFQ+ID1cbiAgfCB7IHN0YXR1czogJ2RlbmllZCc7IHJlc2VydmF0aW9uOiBRdW90YVJlc2VydmVSZXN1bHQgfVxuICB8IHsgc3RhdHVzOiAnZG9uZSc7IHZhbHVlOiBUIH1cbiAgLyoqIE9ubHkgd2l0aCBhbiBgb25FcnJvcmAgaGFuZGxlcjogdGhlIGJvZHkgdGhyZXcgYW5kIHRoZSBoYW5kbGVyIGFuc3dlcmVkLiAqL1xuICB8IHsgc3RhdHVzOiAnZmFpbGVkJzsgZXJyb3I6IHVua25vd24gfTtcblxuLyoqXG4gKiBSZXNlcnZlIG9uZSBxdW90YSBzbG90LCBydW4gYGJvZHlgLCBhbmQgc2V0dGxlIHRoZSBzbG90IGJ5IE9ORSBydWxlOlxuICoga2VlcCBpdCBvbmNlIHRoZSByZXNvdXJjZSB3YXMgY29uc3VtZWQ7IHJlZnVuZCBpdCBpZiB0aGUgYm9keSBmYWlscyBmaXJzdC5cbiAqXG4gKiAtIERlbmllZCDihpIgYHsgc3RhdHVzOiAnZGVuaWVkJyB9YCAoYW5zd2VyZWQgb24gYHJlc2Agd2hlbiBnaXZlbik7IGBib2R5YCBuZXZlciBydW5zLlxuICogLSBgYm9keWAgcmVzb2x2ZXMg4oaSIHRoZSBzbG90IGlzIGtlcHQgKHVubGVzcyBgYm9keWAgY2FsbGVkIGBzbG90LnJlZnVuZCgpYCkuXG4gKiAtIGBib2R5YCB0aHJvd3Mg4oaSIHJlZnVuZGVkIHVubGVzcyBjb25zdW1lZCDigJQgbWFya2VkIHZpYSBgc2xvdC5tYXJrQ29uc3VtZWQoKWBcbiAqICAgb3Igc2lnbmFsbGVkIGJ5IHRoZSBlcnJvciBpdHNlbGYgY2FycnlpbmcgYHByb3ZpZGVyQ29udGFjdGVkID09PSB0cnVlYFxuICogICAoYW4gQUkgcm91bmQtdHJpcCB0aGF0IGNvbXBsZXRlZCBidXQgcHJvZHVjZWQgbm90aGluZyB1c2FibGUpLiBUaGUgZXJyb3IgaXNcbiAqICAgdGhlbiBwYXNzZWQgdG8gYG9uRXJyb3JgLCBvciByZXRocm93biB3aGVuIHRoZXJlIGlzIG5vbmUuXG4gKlxuICogVGhlIHJlc2VydmUgYW5kIHJlZnVuZCBhdXRoZW50aWNhdGUgd2l0aCBhIG1pbnRlZCBzZXJ2aWNlIHRva2VuLCBuZXZlciB0aGVcbiAqIGVuZC11c2VyIGJlYXJlcjogdGhlIHF1b3RhIGluY3JlbWVudCBlbmRwb2ludCByZWplY3RzIHVzZXIgcHJpbmNpcGFscy5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHdpdGhRdW90YVJlc2VydmF0aW9uPFQ+KFxuICBvcHRzOiBRdW90YVJlc2VydmF0aW9uT3B0aW9ucyxcbiAgYm9keTogKHNsb3Q6IFF1b3RhU2xvdCkgPT4gUHJvbWlzZTxUPixcbiAgb25FcnJvcj86IChlcnJvcjogdW5rbm93bikgPT4gdm9pZCB8IFByb21pc2U8dm9pZD4sXG4pOiBQcm9taXNlPFF1b3RhUmVzZXJ2YXRpb25PdXRjb21lPFQ+PiB7XG4gIGNvbnN0IHsgcXVvdGFTZXJ2aWNlLCBvcmdJZCwgdHlwZSwgbG9nV2FybiB9ID0gb3B0cztcbiAgY29uc3Qgc2VydmljZUF1dGggPSBnZXRTZXJ2aWNlQXV0aEhlYWRlcih7IHNlcnZpY2VOYW1lOiBvcHRzLnNlcnZpY2VOYW1lID8/IHNlcnZpY2VJZGVudGl0eSgpLCBvcmdJZCwgcm9sZTogJ21lbWJlcicgfSk7XG5cbiAgLy8gUmVzZXJ2ZSBhdG9taWNhbGx5IEJFRk9SRSBhbnkgd29yazogdHdvIGNvbmN1cnJlbnQgcmVxdWVzdHMgYXQgdGhlIGxpbWl0XG4gIC8vIGNhbid0IGJvdGggcGFzcy5cbiAgY29uc3QgcmVzZXJ2YXRpb24gPSBhd2FpdCByZXNlcnZlUXVvdGEocXVvdGFTZXJ2aWNlLCBvcmdJZCwgdHlwZSwgc2VydmljZUF1dGgpO1xuICBpZiAocmVzZXJ2YXRpb24uZXhjZWVkZWQpIHtcbiAgICBpZiAob3B0cy5yZXMpIHNlbmRRdW90YVJlc2VydmVEZW5pZWQob3B0cy5yZXMsIHR5cGUsIHJlc2VydmF0aW9uKTtcbiAgICByZXR1cm4geyBzdGF0dXM6ICdkZW5pZWQnLCByZXNlcnZhdGlvbiB9O1xuICB9XG5cbiAgbGV0IGNvbnN1bWVkID0gZmFsc2U7XG4gIGxldCByZWZ1bmRlZCA9IGZhbHNlO1xuICBjb25zdCBzbG90OiBRdW90YVNsb3QgPSB7XG4gICAgc2VydmljZUF1dGgsXG4gICAgcmVzZXJ2YXRpb24sXG4gICAgbWFya0NvbnN1bWVkOiAoKSA9PiB7IGNvbnN1bWVkID0gdHJ1ZTsgfSxcbiAgICByZWZ1bmQ6ICgpID0+IHtcbiAgICAgIGlmIChyZWZ1bmRlZCkgcmV0dXJuO1xuICAgICAgcmVmdW5kZWQgPSB0cnVlO1xuICAgICAgLy8gVGhlIHJlc2VydmVkIHJlc2V0QXQga2VlcHMgYSBwZXJpb2Qgcm9sbG92ZXIgZnJvbSBiZWluZyBkb3VibGUtY2hhcmdlZC5cbiAgICAgIGRlY3JlbWVudFF1b3RhKHF1b3RhU2VydmljZSwgb3JnSWQsIHR5cGUsIHNlcnZpY2VBdXRoLCBsb2dXYXJuLCAxLCByZXNlcnZhdGlvbi5xdW90YS5yZXNldEF0KTtcbiAgICB9LFxuICB9O1xuXG4gIHRyeSB7XG4gICAgcmV0dXJuIHsgc3RhdHVzOiAnZG9uZScsIHZhbHVlOiBhd2FpdCBib2R5KHNsb3QpIH07XG4gIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgY29uc3QgZXJyb3JTYXlzQ29uc3VtZWQgPSAoZXJyb3IgYXMgeyBwcm92aWRlckNvbnRhY3RlZD86IHVua25vd24gfSB8IG51bGwpPy5wcm92aWRlckNvbnRhY3RlZCA9PT0gdHJ1ZTtcbiAgICBpZiAoIWNvbnN1bWVkICYmICFlcnJvclNheXNDb25zdW1lZCkgc2xvdC5yZWZ1bmQoKTtcbiAgICBpZiAoIW9uRXJyb3IpIHRocm93IGVycm9yO1xuICAgIGF3YWl0IG9uRXJyb3IoZXJyb3IpO1xuICAgIHJldHVybiB7IHN0YXR1czogJ2ZhaWxlZCcsIGVycm9yIH07XG4gIH1cbn1cbiJdfQ==
62
+ /**
63
+ * Reserve one quota slot, run `body`, and settle the slot by ONE rule:
64
+ * keep it once the resource was consumed; refund it if the body fails first.
65
+ *
66
+ * - Denied → `{ status: 'denied' }` (answered on `res` when given); `body` never runs.
67
+ * - `body` resolves → the slot is kept (unless `body` called `slot.refund()`
68
+ * BEFORE marking it consumed — a refund after `markConsumed()` is ignored).
69
+ * - `body` throws → refunded unless consumed — marked via `slot.markConsumed()`
70
+ * or signalled by the error itself carrying `providerContacted === true`
71
+ * (an AI round-trip that completed but produced nothing usable). The error is
72
+ * then passed to `onError`, or rethrown when there is none.
73
+ *
74
+ * The reserve and refund authenticate with a minted service token, never the
75
+ * end-user bearer: the quota increment endpoint rejects user principals.
76
+ */
77
+ export async function withQuotaReservation(opts, body, onError) {
78
+ const reserved = await reserveQuotaSlot(opts);
79
+ if (reserved.status === 'denied')
80
+ return reserved;
81
+ return runWithSlot(reserved.slot, body, onError);
82
+ }
83
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVvdGEtcmVzZXJ2YXRpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvYXBpL3F1b3RhLXJlc2VydmF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEMsT0FBTyxFQUNMLGNBQWMsRUFDZCxvQkFBb0IsRUFDcEIsWUFBWSxFQUNaLHNCQUFzQixFQUN0QixlQUFlLEdBS2hCLE1BQU0sNEJBQTRCLENBQUM7QUFxRHBDOzs7Ozs7OztHQVFHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxnQkFBZ0IsQ0FBQyxJQUE2QjtJQUNsRSxNQUFNLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLFdBQVcsRUFBRSxHQUFHLElBQUksQ0FBQztJQUNqRSxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMsQ0FBQztJQUNoQyxNQUFNLFdBQVcsR0FBRyxvQkFBb0IsQ0FBQyxFQUFFLFdBQVcsRUFBRSxJQUFJLENBQUMsV0FBVyxJQUFJLGVBQWUsRUFBRSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQztJQUV4SCwyRUFBMkU7SUFDM0UsdUVBQXVFO0lBQ3ZFLG9EQUFvRDtJQUNwRCxNQUFNLFdBQVcsR0FBRyxNQUFNLFlBQVksQ0FBQyxZQUFZLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsTUFBTSxFQUFFLFdBQVcsQ0FBQyxDQUFDO0lBQ3BHLElBQUksV0FBVyxDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ3pCLElBQUksSUFBSSxDQUFDLEdBQUc7WUFBRSxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLElBQUksRUFBRSxXQUFXLENBQUMsQ0FBQztRQUNsRSxPQUFPLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxXQUFXLEVBQUUsQ0FBQztJQUMzQyxDQUFDO0lBRUQsSUFBSSxRQUFRLEdBQUcsS0FBSyxDQUFDO0lBQ3JCLElBQUksUUFBUSxHQUFHLEtBQUssQ0FBQztJQUNyQixNQUFNLElBQUksR0FBYztRQUN0QixXQUFXO1FBQ1gsV0FBVztRQUNYLFlBQVksRUFBRSxHQUFHLEVBQUUsR0FBRyxRQUFRLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUN4QyxNQUFNLEVBQUUsR0FBRyxFQUFFO1lBQ1gsSUFBSSxRQUFRLElBQUksUUFBUTtnQkFBRSxPQUFPO1lBQ2pDLFFBQVEsR0FBRyxJQUFJLENBQUM7WUFDaEIsMEVBQTBFO1lBQzFFLGNBQWMsQ0FBQyxZQUFZLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxXQUFXLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxXQUFXLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxXQUFXLENBQUMsQ0FBQztRQUNsSCxDQUFDO0tBQ0YsQ0FBQztJQUNGLE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUFDO0FBQ3RDLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxXQUFXLENBQy9CLElBQU8sRUFDUCxJQUE2QixFQUM3QixPQUFrRDtJQUVsRCxJQUFJLENBQUM7UUFDSCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztJQUNyRCxDQUFDO0lBQUMsT0FBTyxLQUFLLEVBQUUsQ0FBQztRQUNmLGtFQUFrRTtRQUNsRSxNQUFNLGlCQUFpQixHQUFJLEtBQWdELEVBQUUsaUJBQWlCLEtBQUssSUFBSSxDQUFDO1FBQ3hHLElBQUksQ0FBQyxpQkFBaUI7WUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDdEMsSUFBSSxDQUFDLE9BQU87WUFBRSxNQUFNLEtBQUssQ0FBQztRQUMxQixNQUFNLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNyQixPQUFPLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsQ0FBQztJQUNyQyxDQUFDO0FBQ0gsQ0FBQztBQUVEOzs7Ozs7Ozs7Ozs7OztHQWNHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxvQkFBb0IsQ0FDeEMsSUFBNkIsRUFDN0IsSUFBcUMsRUFDckMsT0FBa0Q7SUFFbEQsTUFBTSxRQUFRLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM5QyxJQUFJLFFBQVEsQ0FBQyxNQUFNLEtBQUssUUFBUTtRQUFFLE9BQU8sUUFBUSxDQUFDO0lBQ2xELE9BQU8sV0FBVyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLE9BQU8sQ0FBQyxDQUFDO0FBQ25ELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuaW1wb3J0IHtcbiAgZGVjcmVtZW50UXVvdGEsXG4gIGdldFNlcnZpY2VBdXRoSGVhZGVyLFxuICByZXNlcnZlUXVvdGEsXG4gIHNlbmRRdW90YVJlc2VydmVEZW5pZWQsXG4gIHNlcnZpY2VJZGVudGl0eSxcbiAgdHlwZSBRdW90YVJlc2VydmVSZXN1bHQsXG4gIHR5cGUgUXVvdGFTZXJ2aWNlLFxuICB0eXBlIFF1b3RhVHlwZSxcbiAgdHlwZSBRdW90YVVzYWdlQXR0cmlidXRpb24sXG59IGZyb20gJ0BwaXBlbGluZS1idWlsZGVyL2FwaS1jb3JlJztcbmltcG9ydCB0eXBlIHsgUmVzcG9uc2UgfSBmcm9tICdleHByZXNzJztcblxuLyoqIFRoZSByZXNlcnZlZCBxdW90YSBzbG90LCBoYW5kZWQgdG8gdGhlIGd1YXJkZWQgYm9keS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUXVvdGFTbG90IHtcbiAgLyoqIE1pbnRlZCBzZXJ2aWNlIHRva2VuIHRoZSByZXNlcnZhdGlvbiB1c2VkIOKAlCByZXVzZSBpdCBmb3IgdGhlIGJvZHkncyBvd24gUzJTIGNhbGxzLiAqL1xuICByZWFkb25seSBzZXJ2aWNlQXV0aDogc3RyaW5nO1xuICByZWFkb25seSByZXNlcnZhdGlvbjogUXVvdGFSZXNlcnZlUmVzdWx0O1xuICAvKipcbiAgICogVGhlIHJlc2VydmVkIHJlc291cmNlIGhhcyBiZWVuIGNvbnN1bWVkIChlLmcuIHRoZSBBSSBwcm92aWRlciBzdGFydGVkXG4gICAqIHJlc3BvbmRpbmcpLiBGcm9tIGhlcmUgb24gYSBmYWlsdXJlIEtFRVBTIHRoZSBzbG90IOKAlCB0aGUgY29zdCB3YXMgaW5jdXJyZWQuXG4gICAqL1xuICBtYXJrQ29uc3VtZWQoKTogdm9pZDtcbiAgLyoqXG4gICAqIEdpdmUgdGhlIHNsb3QgYmFjayBub3cuIElkZW1wb3RlbnQ6IHJlZnVuZHMgYXQgbW9zdCBvbmNlIOKAlCBhbmQgYSBOTy1PUCBvbmNlXG4gICAqIHtAbGluayBtYXJrQ29uc3VtZWR9IHdhcyBjYWxsZWQuIEEgcGFpZCBwcm92aWRlciByb3VuZC10cmlwIGlzIG5ldmVyIHJlZnVuZGVkLFxuICAgKiB3aGF0ZXZlciBwYXRoIChhIGNsaWVudCBhYm9ydCwgYSBsYXRlciBmYWlsdXJlLCBhbiBlbXB0eSBhbnN3ZXIpIGFza3MgZm9yIGl0XG4gICAqIGFmdGVyd2FyZHM7IGNhbGxlcnMgbm8gbG9uZ2VyIG5lZWQgdG8gZ3VhcmQgYHJlZnVuZCgpYCB3aXRoIHRoZWlyIG93blxuICAgKiBcIndhcyB0aGUgcHJvdmlkZXIgY29udGFjdGVkXCIgZmxhZy5cbiAgICovXG4gIHJlZnVuZCgpOiB2b2lkO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFF1b3RhUmVzZXJ2YXRpb25PcHRpb25zIHtcbiAgcXVvdGFTZXJ2aWNlOiBRdW90YVNlcnZpY2U7XG4gIG9yZ0lkOiBzdHJpbmc7XG4gIHR5cGU6IFF1b3RhVHlwZTtcbiAgLyoqIFVuaXRzIHRvIHJlc2VydmUgKGRlZmF1bHQgMSkg4oCUIGUuZy4gYW4gQUkgbW9kZWwncyB3ZWlnaHQuIFJlZnVuZHMgZ2l2ZSBiYWNrIHRoZSBzYW1lIGFtb3VudC4gKi9cbiAgYW1vdW50PzogbnVtYmVyO1xuICAvKipcbiAgICogVXNhZ2UtbGVkZ2VyIGF0dHJpYnV0aW9uIGZvciB0aGUgcmVzZXJ2ZSBBTkQgaXRzIHJlZnVuZC4gRGVmYXVsdHMgdG8gdGhlXG4gICAqIGFtYmllbnQgcmVxdWVzdCBjb250ZXh0IChwcmluY2lwYWwgKyByZXF1ZXN0IGlkLCBubyByb3V0ZSkg4oCUIHBhc3MgaXRcbiAgICogZXhwbGljaXRseSB0byByZWNvcmQgdGhlIHJvdXRlLCB0aGUgZmVhdHVyZSBhbmQgdGhlIG1vZGVsLlxuICAgKi9cbiAgYXR0cmlidXRpb24/OiBRdW90YVVzYWdlQXR0cmlidXRpb247XG4gIC8qKiBTaWduZXIgb2YgdGhlIHF1b3RhIHNlcnZpY2UgdG9rZW4uIERlZmF1bHRzIHRvIHRoaXMgcHJvY2VzcyAoYFNFUlZJQ0VfTkFNRWApLiAqL1xuICBzZXJ2aWNlTmFtZT86IHN0cmluZztcbiAgbG9nV2FybjogKG1lc3NhZ2U6IHN0cmluZywgZGF0YT86IHVua25vd24pID0+IHZvaWQ7XG4gIC8qKiBXaGVuIHNldCwgYSBkZW5pZWQgcmVzZXJ2YXRpb24gaXMgYW5zd2VyZWQgb24gaXQgKDQyOSwgb3IgNTAzIHdoZW4gdW5jb25maXJtYWJsZSkuICovXG4gIHJlcz86IFJlc3BvbnNlO1xufVxuXG5leHBvcnQgdHlwZSBRdW90YVJlc2VydmF0aW9uT3V0Y29tZTxUPiA9XG4gIHwgeyBzdGF0dXM6ICdkZW5pZWQnOyByZXNlcnZhdGlvbjogUXVvdGFSZXNlcnZlUmVzdWx0IH1cbiAgfCB7IHN0YXR1czogJ2RvbmUnOyB2YWx1ZTogVCB9XG4gIC8qKiBPbmx5IHdpdGggYW4gYG9uRXJyb3JgIGhhbmRsZXI6IHRoZSBib2R5IHRocmV3IGFuZCB0aGUgaGFuZGxlciBhbnN3ZXJlZC4gKi9cbiAgfCB7IHN0YXR1czogJ2ZhaWxlZCc7IGVycm9yOiB1bmtub3duIH07XG5cbi8qKiBXaGF0IHtAbGluayByZXNlcnZlUXVvdGFTbG90fSBoYW5kcyBiYWNrOiBhIGxpdmUgc2xvdCwgb3IgdGhlIGRlbmlhbC4gKi9cbmV4cG9ydCB0eXBlIFF1b3RhU2xvdFJlc2VydmF0aW9uID1cbiAgfCB7IHN0YXR1czogJ2RlbmllZCc7IHJlc2VydmF0aW9uOiBRdW90YVJlc2VydmVSZXN1bHQgfVxuICB8IHsgc3RhdHVzOiAncmVzZXJ2ZWQnOyBzbG90OiBRdW90YVNsb3QgfTtcblxuLyoqXG4gKiBSZXNlcnZlIG9uZSBzbG90IChvZiBgYW1vdW50YCB1bml0cykgYW5kIHJldHVybiBpdHMgaGFuZGxlLCBXSVRIT1VUIHJ1bm5pbmdcbiAqIGFueXRoaW5nLiBUaGUgcHJpbWl0aXZlIHVuZGVyIHtAbGluayB3aXRoUXVvdGFSZXNlcnZhdGlvbn0sIGZvciBhIGNhbGxlciB3aG9zZVxuICogZ2F0ZWQgd29yayBkb2VzIG5vdCBmaXQgb25lIGNhbGxiYWNrIOKAlCBlLmcuIGEgdG9vbCBpbnNpZGUgYW4gYWdlbnQgdHVybiB0aGF0XG4gKiBzZXR0bGVzIGl0cyBvd24gc2xvdC4gVGhlIGNhbGxlciBvd25zIHNldHRsZW1lbnQ6IGBtYXJrQ29uc3VtZWQoKWAgb25jZSB0aGVcbiAqIHJlc291cmNlIGlzIHNwZW50LCBgcmVmdW5kKClgIG9uIGV2ZXJ5IHBhdGggdGhhdCBmYWlscyBiZWZvcmUgdGhhdC5cbiAqXG4gKiBEZW5pZWQg4oaSIGB7IHN0YXR1czogJ2RlbmllZCcgfWAsIGFuc3dlcmVkIG9uIGByZXNgIHdoZW4gZ2l2ZW4uXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXNlcnZlUXVvdGFTbG90KG9wdHM6IFF1b3RhUmVzZXJ2YXRpb25PcHRpb25zKTogUHJvbWlzZTxRdW90YVNsb3RSZXNlcnZhdGlvbj4ge1xuICBjb25zdCB7IHF1b3RhU2VydmljZSwgb3JnSWQsIHR5cGUsIGxvZ1dhcm4sIGF0dHJpYnV0aW9uIH0gPSBvcHRzO1xuICBjb25zdCBhbW91bnQgPSBvcHRzLmFtb3VudCA/PyAxO1xuICBjb25zdCBzZXJ2aWNlQXV0aCA9IGdldFNlcnZpY2VBdXRoSGVhZGVyKHsgc2VydmljZU5hbWU6IG9wdHMuc2VydmljZU5hbWUgPz8gc2VydmljZUlkZW50aXR5KCksIG9yZ0lkLCByb2xlOiAnbWVtYmVyJyB9KTtcblxuICAvLyBSZXNlcnZlIGF0b21pY2FsbHkgQkVGT1JFIGFueSB3b3JrOiB0d28gY29uY3VycmVudCByZXF1ZXN0cyBhdCB0aGUgbGltaXRcbiAgLy8gY2FuJ3QgYm90aCBwYXNzLiBBdHRyaWJ1dGlvbiBkZWZhdWx0cyB0byB0aGUgYW1iaWVudCByZXF1ZXN0IGNvbnRleHRcbiAgLy8gKHByaW5jaXBhbCArIHJlcXVlc3QgaWQpIGluc2lkZSB0aGUgcXVvdGEgY2xpZW50LlxuICBjb25zdCByZXNlcnZhdGlvbiA9IGF3YWl0IHJlc2VydmVRdW90YShxdW90YVNlcnZpY2UsIG9yZ0lkLCB0eXBlLCBzZXJ2aWNlQXV0aCwgYW1vdW50LCBhdHRyaWJ1dGlvbik7XG4gIGlmIChyZXNlcnZhdGlvbi5leGNlZWRlZCkge1xuICAgIGlmIChvcHRzLnJlcykgc2VuZFF1b3RhUmVzZXJ2ZURlbmllZChvcHRzLnJlcywgdHlwZSwgcmVzZXJ2YXRpb24pO1xuICAgIHJldHVybiB7IHN0YXR1czogJ2RlbmllZCcsIHJlc2VydmF0aW9uIH07XG4gIH1cblxuICBsZXQgY29uc3VtZWQgPSBmYWxzZTtcbiAgbGV0IHJlZnVuZGVkID0gZmFsc2U7XG4gIGNvbnN0IHNsb3Q6IFF1b3RhU2xvdCA9IHtcbiAgICBzZXJ2aWNlQXV0aCxcbiAgICByZXNlcnZhdGlvbixcbiAgICBtYXJrQ29uc3VtZWQ6ICgpID0+IHsgY29uc3VtZWQgPSB0cnVlOyB9LFxuICAgIHJlZnVuZDogKCkgPT4ge1xuICAgICAgaWYgKHJlZnVuZGVkIHx8IGNvbnN1bWVkKSByZXR1cm47XG4gICAgICByZWZ1bmRlZCA9IHRydWU7XG4gICAgICAvLyBUaGUgcmVzZXJ2ZWQgcmVzZXRBdCBrZWVwcyBhIHBlcmlvZCByb2xsb3ZlciBmcm9tIGJlaW5nIGRvdWJsZS1jaGFyZ2VkLlxuICAgICAgZGVjcmVtZW50UXVvdGEocXVvdGFTZXJ2aWNlLCBvcmdJZCwgdHlwZSwgc2VydmljZUF1dGgsIGxvZ1dhcm4sIGFtb3VudCwgcmVzZXJ2YXRpb24ucXVvdGEucmVzZXRBdCwgYXR0cmlidXRpb24pO1xuICAgIH0sXG4gIH07XG4gIHJldHVybiB7IHN0YXR1czogJ3Jlc2VydmVkJywgc2xvdCB9O1xufVxuXG4vKipcbiAqIFJ1biBgYm9keWAgYWdhaW5zdCBhIHJlc2VydmVkIHNsb3QgYW5kIHNldHRsZSBpdCBieSBPTkUgcnVsZToga2VlcCBpdCBvbmNlXG4gKiB0aGUgcmVzb3VyY2Ugd2FzIGNvbnN1bWVkOyByZWZ1bmQgaXQgaWYgdGhlIGJvZHkgZmFpbHMgZmlyc3QuIFNoYXJlZCBieVxuICoge0BsaW5rIHdpdGhRdW90YVJlc2VydmF0aW9ufSBhbmQgYXBpLXNlcnZlcidzIEFJIHJlc2VydmF0aW9uLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcnVuV2l0aFNsb3Q8VCwgUyBleHRlbmRzIFF1b3RhU2xvdD4oXG4gIHNsb3Q6IFMsXG4gIGJvZHk6IChzbG90OiBTKSA9PiBQcm9taXNlPFQ+LFxuICBvbkVycm9yPzogKGVycm9yOiB1bmtub3duKSA9PiB2b2lkIHwgUHJvbWlzZTx2b2lkPixcbik6IFByb21pc2U8UXVvdGFSZXNlcnZhdGlvbk91dGNvbWU8VD4+IHtcbiAgdHJ5IHtcbiAgICByZXR1cm4geyBzdGF0dXM6ICdkb25lJywgdmFsdWU6IGF3YWl0IGJvZHkoc2xvdCkgfTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAvLyBgcmVmdW5kKClgIGlzIGl0c2VsZiBhIG5vLW9wIG9uY2UgdGhlIHNsb3Qgd2FzIG1hcmtlZCBjb25zdW1lZC5cbiAgICBjb25zdCBlcnJvclNheXNDb25zdW1lZCA9IChlcnJvciBhcyB7IHByb3ZpZGVyQ29udGFjdGVkPzogdW5rbm93biB9IHwgbnVsbCk/LnByb3ZpZGVyQ29udGFjdGVkID09PSB0cnVlO1xuICAgIGlmICghZXJyb3JTYXlzQ29uc3VtZWQpIHNsb3QucmVmdW5kKCk7XG4gICAgaWYgKCFvbkVycm9yKSB0aHJvdyBlcnJvcjtcbiAgICBhd2FpdCBvbkVycm9yKGVycm9yKTtcbiAgICByZXR1cm4geyBzdGF0dXM6ICdmYWlsZWQnLCBlcnJvciB9O1xuICB9XG59XG5cbi8qKlxuICogUmVzZXJ2ZSBvbmUgcXVvdGEgc2xvdCwgcnVuIGBib2R5YCwgYW5kIHNldHRsZSB0aGUgc2xvdCBieSBPTkUgcnVsZTpcbiAqIGtlZXAgaXQgb25jZSB0aGUgcmVzb3VyY2Ugd2FzIGNvbnN1bWVkOyByZWZ1bmQgaXQgaWYgdGhlIGJvZHkgZmFpbHMgZmlyc3QuXG4gKlxuICogLSBEZW5pZWQg4oaSIGB7IHN0YXR1czogJ2RlbmllZCcgfWAgKGFuc3dlcmVkIG9uIGByZXNgIHdoZW4gZ2l2ZW4pOyBgYm9keWAgbmV2ZXIgcnVucy5cbiAqIC0gYGJvZHlgIHJlc29sdmVzIOKGkiB0aGUgc2xvdCBpcyBrZXB0ICh1bmxlc3MgYGJvZHlgIGNhbGxlZCBgc2xvdC5yZWZ1bmQoKWBcbiAqICAgQkVGT1JFIG1hcmtpbmcgaXQgY29uc3VtZWQg4oCUIGEgcmVmdW5kIGFmdGVyIGBtYXJrQ29uc3VtZWQoKWAgaXMgaWdub3JlZCkuXG4gKiAtIGBib2R5YCB0aHJvd3Mg4oaSIHJlZnVuZGVkIHVubGVzcyBjb25zdW1lZCDigJQgbWFya2VkIHZpYSBgc2xvdC5tYXJrQ29uc3VtZWQoKWBcbiAqICAgb3Igc2lnbmFsbGVkIGJ5IHRoZSBlcnJvciBpdHNlbGYgY2FycnlpbmcgYHByb3ZpZGVyQ29udGFjdGVkID09PSB0cnVlYFxuICogICAoYW4gQUkgcm91bmQtdHJpcCB0aGF0IGNvbXBsZXRlZCBidXQgcHJvZHVjZWQgbm90aGluZyB1c2FibGUpLiBUaGUgZXJyb3IgaXNcbiAqICAgdGhlbiBwYXNzZWQgdG8gYG9uRXJyb3JgLCBvciByZXRocm93biB3aGVuIHRoZXJlIGlzIG5vbmUuXG4gKlxuICogVGhlIHJlc2VydmUgYW5kIHJlZnVuZCBhdXRoZW50aWNhdGUgd2l0aCBhIG1pbnRlZCBzZXJ2aWNlIHRva2VuLCBuZXZlciB0aGVcbiAqIGVuZC11c2VyIGJlYXJlcjogdGhlIHF1b3RhIGluY3JlbWVudCBlbmRwb2ludCByZWplY3RzIHVzZXIgcHJpbmNpcGFscy5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHdpdGhRdW90YVJlc2VydmF0aW9uPFQ+KFxuICBvcHRzOiBRdW90YVJlc2VydmF0aW9uT3B0aW9ucyxcbiAgYm9keTogKHNsb3Q6IFF1b3RhU2xvdCkgPT4gUHJvbWlzZTxUPixcbiAgb25FcnJvcj86IChlcnJvcjogdW5rbm93bikgPT4gdm9pZCB8IFByb21pc2U8dm9pZD4sXG4pOiBQcm9taXNlPFF1b3RhUmVzZXJ2YXRpb25PdXRjb21lPFQ+PiB7XG4gIGNvbnN0IHJlc2VydmVkID0gYXdhaXQgcmVzZXJ2ZVF1b3RhU2xvdChvcHRzKTtcbiAgaWYgKHJlc2VydmVkLnN0YXR1cyA9PT0gJ2RlbmllZCcpIHJldHVybiByZXNlcnZlZDtcbiAgcmV0dXJuIHJ1bldpdGhTbG90KHJlc2VydmVkLnNsb3QsIGJvZHksIG9uRXJyb3IpO1xufVxuIl19