@pipeline-builder/api-core 5.2.2 → 5.2.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.
- package/lib/constants/ai-providers.d.ts +3 -22
- package/lib/constants/ai-providers.js +6 -56
- package/lib/errors/app-errors.d.ts +14 -0
- package/lib/errors/app-errors.js +21 -1
- package/lib/helpers/index.d.ts +1 -0
- package/lib/helpers/index.js +2 -1
- package/lib/helpers/sse-helpers.d.ts +33 -3
- package/lib/helpers/sse-helpers.js +91 -19
- package/lib/helpers/support-calendar.d.ts +69 -0
- package/lib/helpers/support-calendar.js +179 -0
- package/lib/middleware/auth.js +6 -3
- package/lib/middleware/deferred-quota-check.d.ts +5 -0
- package/lib/middleware/deferred-quota-check.js +33 -0
- package/lib/middleware/ecosystem-guard.d.ts +3 -3
- package/lib/middleware/ecosystem-guard.js +5 -5
- package/lib/middleware/index.d.ts +5 -2
- package/lib/middleware/index.js +6 -3
- package/lib/middleware/on-behalf.d.ts +37 -0
- package/lib/middleware/on-behalf.js +143 -0
- package/lib/middleware/permission-gates.d.ts +11 -0
- package/lib/middleware/permission-gates.js +7 -1
- package/lib/middleware/quota-exempt-routes.d.ts +36 -0
- package/lib/middleware/quota-exempt-routes.js +47 -0
- package/lib/middleware/route-table.d.ts +104 -0
- package/lib/middleware/route-table.js +72 -2
- package/lib/middleware/service-tokens.d.ts +8 -0
- package/lib/middleware/service-tokens.js +5 -3
- package/lib/middleware/step-up.js +11 -1
- package/lib/services/ai-call-weight.d.ts +24 -0
- package/lib/services/ai-call-weight.js +77 -0
- package/lib/services/alert-delivery.d.ts +99 -0
- package/lib/services/alert-delivery.js +132 -0
- package/lib/services/audit-context.d.ts +105 -0
- package/lib/services/audit-context.js +134 -0
- package/lib/services/index.d.ts +10 -2
- package/lib/services/index.js +10 -2
- package/lib/services/org-ai-client.d.ts +61 -0
- package/lib/services/org-ai-client.js +112 -0
- package/lib/services/pagerduty-inbound.d.ts +101 -0
- package/lib/services/pagerduty-inbound.js +195 -0
- package/lib/services/pagerduty.d.ts +109 -0
- package/lib/services/pagerduty.js +186 -0
- package/lib/services/quota-increment-batcher.d.ts +81 -0
- package/lib/services/quota-increment-batcher.js +166 -0
- package/lib/services/quota.d.ts +158 -14
- package/lib/services/quota.js +252 -22
- package/lib/services/remote-audit-client.d.ts +44 -1
- package/lib/services/remote-audit-client.js +106 -20
- package/lib/services/version-vuln-policy.d.ts +174 -0
- package/lib/services/version-vuln-policy.js +242 -0
- package/lib/types/ai-catalog.d.ts +63 -0
- package/lib/types/ai-catalog.js +82 -0
- package/lib/types/ask-proposals.js +6 -6
- package/lib/types/build-catalog.d.ts +154 -0
- package/lib/types/build-catalog.js +158 -0
- package/lib/types/common.d.ts +37 -3
- package/lib/types/common.js +20 -2
- package/lib/types/ecosystem-notifications.d.ts +5 -5
- package/lib/types/ecosystem-notifications.js +9 -3
- package/lib/types/error-codes.d.ts +13 -6
- package/lib/types/error-codes.js +18 -8
- package/lib/types/feature-flags.d.ts +71 -1
- package/lib/types/feature-flags.js +131 -11
- package/lib/types/index.d.ts +6 -4
- package/lib/types/index.js +12 -5
- package/lib/types/metadata-keys.d.ts +6 -0
- package/lib/types/metadata-keys.js +4 -1
- package/lib/types/permissions.d.ts +351 -3
- package/lib/types/permissions.js +610 -21
- package/lib/types/pipeline.d.ts +39 -0
- package/lib/types/pipeline.js +57 -1
- package/lib/types/plugin-health.d.ts +0 -2
- package/lib/types/plugin-health.js +1 -11
- package/lib/types/plugin-scan.d.ts +192 -42
- package/lib/types/plugin-scan.js +159 -43
- package/lib/types/quota-catalog.d.ts +247 -0
- package/lib/types/quota-catalog.js +122 -0
- package/lib/types/quota-tiers.d.ts +150 -0
- package/lib/types/quota-tiers.js +167 -2
- package/lib/types/remote-audit-actions.d.ts +1 -1
- package/lib/types/remote-audit-actions.js +217 -4
- package/lib/types/wire-vocabulary.js +8 -1
- package/lib/utils/index.d.ts +1 -1
- package/lib/utils/index.js +2 -2
- package/lib/utils/response.d.ts +35 -2
- package/lib/utils/response.js +42 -3
- package/lib/validation/ai-schemas.d.ts +27 -0
- package/lib/validation/ai-schemas.js +31 -5
- package/lib/validation/plugin-schemas.d.ts +15 -0
- package/lib/validation/plugin-schemas.js +28 -1
- package/package.json +31 -2
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* THE vulnerability assessment of one resolved plugin version, for one org (and,
|
|
5
|
+
* optionally, one pipeline's risk acceptance). One function, three callers:
|
|
6
|
+
* `/plugins/lookup` (what synth pins), `/plugins/runtime-check` (what a running
|
|
7
|
+
* pipeline is about to execute) and the pipeline service's save-time contract
|
|
8
|
+
* check. Three copies of these rules drifted once already.
|
|
9
|
+
*
|
|
10
|
+
* Vulnerability state NEVER refuses a pipeline — not its save, its synth, its
|
|
11
|
+
* deploy or its run. What it produces is SEVERITY-GRADED warnings (and, from the
|
|
12
|
+
* callers, notifications to the pipeline's owners). The grades:
|
|
13
|
+
*
|
|
14
|
+
* critical — a finding on the CISA Known Exploited Vulnerabilities list
|
|
15
|
+
* error — the version is FLAGGED (gated Criticals over the platform floor),
|
|
16
|
+
* it has fixable Critical findings, or an org compliance rule on the
|
|
17
|
+
* vulnerability attributes is in BLOCK mode and fails
|
|
18
|
+
* warning — fixable High findings over the org's `warnFixableHigh`, a version
|
|
19
|
+
* never scanned, a scan older than `PLUGIN_SCAN_STALE_HOURS`, or a
|
|
20
|
+
* compliance rule in WARN mode
|
|
21
|
+
* info — what a reader may want to know but need not act on
|
|
22
|
+
*
|
|
23
|
+
* A PIPELINE's active risk acceptance (`plugin_vuln_exposure`, triaged `accepted`
|
|
24
|
+
* with a reason and an expiry) downgrades the warnings about the findings it
|
|
25
|
+
* ACCEPTED to `info` ("accepted until …") — never one about a finding that
|
|
26
|
+
* appeared since, never a KEV one unless the acceptance said `kev: true`, and
|
|
27
|
+
* never the scan-freshness or compliance warnings (neither is about a finding).
|
|
28
|
+
*/
|
|
29
|
+
import { createComplianceClient } from './compliance-client.js';
|
|
30
|
+
import { getServiceAuthHeader } from '../middleware/service-tokens.js';
|
|
31
|
+
import { isSystemOrgId } from '../middleware/system-org.js';
|
|
32
|
+
import { asScanFlag, describeFindings, failOnLabel, isGatedFinding, pluginVulnGateKev, scanFindingKey, } from '../types/plugin-scan.js';
|
|
33
|
+
import { envInt } from '../utils/env.js';
|
|
34
|
+
import { derivePluginImageCompliance, pluginRunsOwnImage } from '../utils/plugin-compliance.js';
|
|
35
|
+
import { errorMessage } from '../utils/response.js';
|
|
36
|
+
/** How loud a warning is, quietest first. */
|
|
37
|
+
export const VULN_SEVERITIES = ['info', 'warning', 'error', 'critical'];
|
|
38
|
+
/** The louder of two severities. */
|
|
39
|
+
export function maxSeverity(a, b) {
|
|
40
|
+
return VULN_SEVERITIES.indexOf(a) >= VULN_SEVERITIES.indexOf(b) ? a : b;
|
|
41
|
+
}
|
|
42
|
+
/** Whether `s` is at least `floor`. */
|
|
43
|
+
export function severityAtLeast(s, floor) {
|
|
44
|
+
return VULN_SEVERITIES.indexOf(s) >= VULN_SEVERITIES.indexOf(floor);
|
|
45
|
+
}
|
|
46
|
+
/** `PLUGIN_SCAN_STALE_HOURS` (default 72): a scan older than this is stale. */
|
|
47
|
+
export function scanStaleHours() {
|
|
48
|
+
return envInt('PLUGIN_SCAN_STALE_HOURS', 72, { min: 1 });
|
|
49
|
+
}
|
|
50
|
+
const toDate = (v) => {
|
|
51
|
+
if (!v)
|
|
52
|
+
return null;
|
|
53
|
+
const d = v instanceof Date ? v : new Date(String(v));
|
|
54
|
+
return Number.isNaN(d.getTime()) ? null : d;
|
|
55
|
+
};
|
|
56
|
+
const summaryOf = (record) => (record.scanSummary && typeof record.scanSummary === 'object' && !Array.isArray(record.scanSummary)
|
|
57
|
+
? record.scanSummary : null);
|
|
58
|
+
/**
|
|
59
|
+
* When the version was last scanned: the later of the build-time `scannedAt` and
|
|
60
|
+
* the nightly rescan's `scan_summary.scannedAt`. Null = never.
|
|
61
|
+
*/
|
|
62
|
+
export function lastScannedAt(record) {
|
|
63
|
+
const build = toDate(record.scannedAt);
|
|
64
|
+
const summary = toDate(summaryOf(record)?.scannedAt);
|
|
65
|
+
if (!build)
|
|
66
|
+
return summary;
|
|
67
|
+
if (!summary)
|
|
68
|
+
return build;
|
|
69
|
+
return summary > build ? summary : build;
|
|
70
|
+
}
|
|
71
|
+
/** Whether the record runs a BUILT image of its own — the only thing a scan applies to. */
|
|
72
|
+
function hasImage(record) {
|
|
73
|
+
return pluginRunsOwnImage(record) && typeof record.imageDigest === 'string' && record.imageDigest.length > 0;
|
|
74
|
+
}
|
|
75
|
+
/** Freshness of a version's scan: `none` (no image to scan), `unscanned`, `stale` or `fresh`. */
|
|
76
|
+
export function scanFreshness(record, now = new Date()) {
|
|
77
|
+
if (!hasImage(record))
|
|
78
|
+
return { state: 'none', scannedAt: null };
|
|
79
|
+
const at = lastScannedAt(record);
|
|
80
|
+
if (!at)
|
|
81
|
+
return { state: 'unscanned', scannedAt: null };
|
|
82
|
+
return { state: now.getTime() - at.getTime() > scanStaleHours() * 3_600_000 ? 'stale' : 'fresh', scannedAt: at };
|
|
83
|
+
}
|
|
84
|
+
/** `UNSCANNED` / `SCAN_STALE` for a resolved version (empty for a fresh scan or an image-less plugin). */
|
|
85
|
+
export function scanWarnings(record, now = new Date()) {
|
|
86
|
+
const ref = `${record.name}@${record.version}`;
|
|
87
|
+
const f = scanFreshness(record, now);
|
|
88
|
+
if (f.state === 'unscanned') {
|
|
89
|
+
return [{ code: 'UNSCANNED', severity: 'warning', message: `Plugin ${ref} has never been scanned for vulnerabilities; nothing is known about what its image contains.` }];
|
|
90
|
+
}
|
|
91
|
+
if (f.state === 'stale') {
|
|
92
|
+
const hours = scanStaleHours();
|
|
93
|
+
return [{
|
|
94
|
+
code: 'SCAN_STALE',
|
|
95
|
+
severity: 'warning',
|
|
96
|
+
message: `Plugin ${ref} was last scanned ${f.scannedAt.toISOString()}, more than ${hours}h ago; findings published since are not reflected.`,
|
|
97
|
+
scannedAt: f.scannedAt.toISOString(),
|
|
98
|
+
staleAfterHours: hours,
|
|
99
|
+
}];
|
|
100
|
+
}
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
/** The normalized scan facts of a resolved record. A summary describing another image is ignored. */
|
|
104
|
+
export function versionScanFacts(record) {
|
|
105
|
+
const flag = record.scanFlaggedAt ? asScanFlag(record.scanFlag) : null;
|
|
106
|
+
const raw = summaryOf(record);
|
|
107
|
+
const digest = typeof raw?.imageDigest === 'string' ? raw.imageDigest : null;
|
|
108
|
+
const summary = raw && (digest === null || !record.imageDigest || digest === record.imageDigest) ? raw : null;
|
|
109
|
+
const findings = summary && Array.isArray(summary.findings)
|
|
110
|
+
? summary.findings.filter((f) => f && typeof f.id === 'string').map((f) => ({ ...f, fixedIn: Array.isArray(f.fixedIn) ? f.fixedIn : [] }))
|
|
111
|
+
: (flag?.findings ?? []);
|
|
112
|
+
const num = (v) => (typeof v === 'number' ? v : null);
|
|
113
|
+
const kevCount = Math.max(num(summary?.kev) ?? 0, flag?.kev ?? 0, findings.filter((f) => f.kev === true).length);
|
|
114
|
+
return {
|
|
115
|
+
flagged: flag !== null,
|
|
116
|
+
flag,
|
|
117
|
+
criticalFixable: num(summary?.criticalFixable),
|
|
118
|
+
highFixable: num(summary?.highFixable) ?? num(record.vulnHighFixable),
|
|
119
|
+
critical: num(summary?.critical),
|
|
120
|
+
high: num(summary?.high),
|
|
121
|
+
kev: kevCount,
|
|
122
|
+
findings,
|
|
123
|
+
truncated: summary?.truncated === true,
|
|
124
|
+
scannedAt: lastScannedAt(record),
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Whether `acceptance` covers EVERY one of `findings` (by finding key), and its
|
|
129
|
+
* KEV ones only when it accepted KEV. An empty set is never "covered": with
|
|
130
|
+
* nothing itemized there is nothing an acceptance can be shown to describe.
|
|
131
|
+
*/
|
|
132
|
+
function covers(acceptance, findings, truncated) {
|
|
133
|
+
if (!acceptance || truncated || findings.length === 0)
|
|
134
|
+
return false;
|
|
135
|
+
const keys = new Set(acceptance.findingKeys);
|
|
136
|
+
return findings.every((f) => keys.has(scanFindingKey(f)) && (f.kev !== true || acceptance.kev));
|
|
137
|
+
}
|
|
138
|
+
/** The loudest severity of `warnings`, or null for none. */
|
|
139
|
+
export function severityOf(warnings) {
|
|
140
|
+
return warnings.reduce((acc, w) => (w.severity ? (acc ? maxSeverity(acc, w.severity) : w.severity) : acc), null);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* The assessment of one resolved version (see the module doc). Never throws and
|
|
144
|
+
* never refuses: a compliance outage adds an `info` `COMPLIANCE_UNAVAILABLE`.
|
|
145
|
+
*/
|
|
146
|
+
export async function assessVersionVulns(input) {
|
|
147
|
+
const { orgId, record, policy, acceptance } = input;
|
|
148
|
+
const now = input.now ?? new Date();
|
|
149
|
+
const ref = `${record.name}@${record.version}`;
|
|
150
|
+
const facts = versionScanFacts(record);
|
|
151
|
+
const warnings = [...scanWarnings(record, now)];
|
|
152
|
+
const accepted = new Set();
|
|
153
|
+
const way = input.suggestedVersion ? ` Move to ${record.name}@${input.suggestedVersion}.` : '';
|
|
154
|
+
const suggested = input.suggestedVersion ? { suggestedVersion: input.suggestedVersion } : {};
|
|
155
|
+
const until = toDate(acceptance?.acceptedUntil)?.toISOString() ?? null;
|
|
156
|
+
/** Push a finding warning — or, when the pipeline accepted exactly those findings, its `info` downgrade. */
|
|
157
|
+
const finding = (code, severity, message, findings, extra = {}) => {
|
|
158
|
+
if (covers(acceptance, findings, facts.truncated)) {
|
|
159
|
+
for (const f of findings)
|
|
160
|
+
accepted.add(scanFindingKey(f));
|
|
161
|
+
warnings.push({
|
|
162
|
+
code: 'VULN_ACCEPTED',
|
|
163
|
+
severity: 'info',
|
|
164
|
+
message: `${message} Accepted for this pipeline${until ? ` until ${until}` : ''}.`,
|
|
165
|
+
findings: findings.map(scanFindingKey),
|
|
166
|
+
acceptedUntil: until,
|
|
167
|
+
kev: acceptance?.kev ?? false,
|
|
168
|
+
covers: code,
|
|
169
|
+
});
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
warnings.push({ code, severity, message: `${message}${way}`, findings: findings.slice(0, 10), ...suggested, ...extra });
|
|
173
|
+
};
|
|
174
|
+
const kevFindings = facts.findings.filter((f) => f.kev === true);
|
|
175
|
+
if (facts.kev > 0) {
|
|
176
|
+
finding('VULN_KEV', 'critical', `${ref} has ${facts.kev} finding${facts.kev === 1 ? '' : 's'} on the CISA Known Exploited Vulnerabilities list${kevFindings.length ? `: ${describeFindings(kevFindings)}` : ''}.`, kevFindings);
|
|
177
|
+
}
|
|
178
|
+
const flag = facts.flag;
|
|
179
|
+
if (flag) {
|
|
180
|
+
const gated = facts.findings.filter((f) => isGatedFinding(f, pluginVulnGateKev(), flag.failOn ?? 'critical'));
|
|
181
|
+
finding('VULN_FLAGGED', 'error', `${ref} is flagged: a rescan found ${flag.gated} gated ${failOnLabel(flag.failOn ?? 'critical')} finding${flag.gated === 1 ? '' : 's'} over the platform limit${flag.findings.length ? ` (fix: ${describeFindings(flag.findings)})` : ''}.`, gated.length > 0 ? gated : flag.findings, { plugin: record.name, version: record.version, gated: flag.gated, high: flag.high });
|
|
182
|
+
}
|
|
183
|
+
else if ((facts.criticalFixable ?? 0) > 0) {
|
|
184
|
+
const crits = facts.findings.filter((f) => f.severity === 'critical' && f.fixedIn.length > 0);
|
|
185
|
+
finding('VULN_CRITICAL_FIXABLE', 'error', `${ref} has ${facts.criticalFixable} fixable Critical finding${facts.criticalFixable === 1 ? '' : 's'}${crits.length ? `: ${describeFindings(crits)}` : ''}.`, crits);
|
|
186
|
+
}
|
|
187
|
+
const highFixable = facts.highFixable ?? 0;
|
|
188
|
+
if (highFixable > 0) {
|
|
189
|
+
const highs = facts.findings.filter((f) => f.severity === 'high' && f.fixedIn.length > 0);
|
|
190
|
+
const over = policy.warnFixableHigh !== null && highFixable > policy.warnFixableHigh;
|
|
191
|
+
finding('VULN_HIGH_FIXABLE', over ? 'warning' : 'info', `${ref} has ${highFixable} fixable High finding${highFixable === 1 ? '' : 's'}${over ? `, over your organization's threshold of ${policy.warnFixableHigh}` : ''}.`, highs);
|
|
192
|
+
}
|
|
193
|
+
if (input.compliance !== false)
|
|
194
|
+
warnings.push(...await complianceVulnWarnings(orgId, record));
|
|
195
|
+
return { severity: severityOf(warnings), warnings, acceptedFindings: [...accepted], facts };
|
|
196
|
+
}
|
|
197
|
+
/** The compliance attributes a plugin's vulnerability rules read. */
|
|
198
|
+
const VULN_RULE_FIELDS = new Set(['scanned', 'vulnCritical', 'vulnHigh', 'vulnMedium', 'vulnLow', 'vulnCriticalFixable', 'vulnHighFixable']);
|
|
199
|
+
const fieldRoot = (field) => field.split(/[.[]/)[0] ?? field;
|
|
200
|
+
let complianceClient = null;
|
|
201
|
+
/** Test hook: replace the compliance client the assessment's compliance layer calls. */
|
|
202
|
+
export function setVulnPolicyComplianceClientForTests(client) {
|
|
203
|
+
complianceClient = client;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* The org's plugin compliance rules on the vulnerability attributes, evaluated
|
|
207
|
+
* against the RESOLVED version — the org's own row, its parent's, a system
|
|
208
|
+
* plugin or an installed marketplace version alike. A BLOCK-mode rule that fails
|
|
209
|
+
* is an `error`, a WARN-mode one a `warning`; neither refuses anything here
|
|
210
|
+
* (vulnerability state never stops a pipeline).
|
|
211
|
+
*
|
|
212
|
+
* Only the vuln / scanned rules count here: the plugin's other rules (tags,
|
|
213
|
+
* secrets, commands …) describe how a plugin is AUTHORED, which is its owner's
|
|
214
|
+
* concern at upload, not the consumer's at resolution — and a system plugin would
|
|
215
|
+
* otherwise fail every tenant's authoring rules.
|
|
216
|
+
*/
|
|
217
|
+
async function complianceVulnWarnings(orgId, record) {
|
|
218
|
+
if (isSystemOrgId(orgId) || !hasImage(record))
|
|
219
|
+
return [];
|
|
220
|
+
const facts = derivePluginImageCompliance(record, null).attributes;
|
|
221
|
+
const attributes = { name: record.name, version: record.version, ...facts };
|
|
222
|
+
try {
|
|
223
|
+
complianceClient ??= createComplianceClient();
|
|
224
|
+
const auth = getServiceAuthHeader({ serviceName: 'plugin', orgId, role: 'member' });
|
|
225
|
+
const result = await complianceClient.dryRunPlugin(orgId, attributes, auth);
|
|
226
|
+
const relevant = (v) => VULN_RULE_FIELDS.has(fieldRoot(v.field));
|
|
227
|
+
const as = (mode) => (v) => ({
|
|
228
|
+
code: 'COMPLIANCE_VULN_RULE',
|
|
229
|
+
severity: mode === 'block' ? 'error' : 'warning',
|
|
230
|
+
message: `${record.name}@${record.version}: ${v.message}`,
|
|
231
|
+
ruleId: v.ruleId,
|
|
232
|
+
ruleName: v.ruleName,
|
|
233
|
+
field: v.field,
|
|
234
|
+
mode,
|
|
235
|
+
});
|
|
236
|
+
return [...result.violations.filter(relevant).map(as('block')), ...result.warnings.filter(relevant).map(as('warn'))];
|
|
237
|
+
}
|
|
238
|
+
catch (err) {
|
|
239
|
+
return [{ code: 'COMPLIANCE_UNAVAILABLE', severity: 'info', message: `Your organization's plugin vulnerability rules could not be checked for ${record.name}@${record.version} (${errorMessage(err)}).` }];
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVyc2lvbi12dWxuLXBvbGljeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zZXJ2aWNlcy92ZXJzaW9uLXZ1bG4tcG9saWN5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUFFdEM7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0F5Qkc7QUFFSCxPQUFPLEVBQUUsc0JBQXNCLEVBQTRCLE1BQU0sd0JBQXdCLENBQUM7QUFDMUYsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDdkUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQzVELE9BQU8sRUFDTCxVQUFVLEVBQUUsZ0JBQWdCLEVBQUUsV0FBVyxFQUFFLGNBQWMsRUFBRSxpQkFBaUIsRUFBRSxjQUFjLEdBRTdGLE1BQU0seUJBQXlCLENBQUM7QUFDakMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3pDLE9BQU8sRUFBRSwyQkFBMkIsRUFBRSxrQkFBa0IsRUFBd0QsTUFBTSwrQkFBK0IsQ0FBQztBQUN0SixPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFFcEQsNkNBQTZDO0FBQzdDLE1BQU0sQ0FBQyxNQUFNLGVBQWUsR0FBRyxDQUFDLE1BQU0sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLFVBQVUsQ0FBVSxDQUFDO0FBR2pGLG9DQUFvQztBQUNwQyxNQUFNLFVBQVUsV0FBVyxDQUFDLENBQWUsRUFBRSxDQUFlO0lBQzFELE9BQU8sZUFBZSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxlQUFlLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUMxRSxDQUFDO0FBRUQsdUNBQXVDO0FBQ3ZDLE1BQU0sVUFBVSxlQUFlLENBQUMsQ0FBZSxF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RUFBRSxHQUFHLEVBQzFRLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsRUFBRSxNQUFNLEVBQUUsTUFBTSxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU8sRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7SUFDcEksQ0FBQztTQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsZUFBZSxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQzVDLE1BQU0sS0FBSyxHQUFHLEtBQUssQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsUUFBUSxLQUFLLFVBQVUsSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztRQUM5RixPQUFPLENBQUMsdUJBQXVCLEVBQUUsT0FBTyxFQUFFLEdBQUcsR0FBRyxRQUFRLEtBQUssQ0FBQyxlQUFlLDRCQUE0QixLQUFLLENBQUMsZUFBZSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQztJQUNsTixDQUFDO0lBQ0QsTUFBTSxXQUFXLEdBQUcsS0FBSyxDQUFDLFdBQVcsSUFBSSxDQUFDLENBQUM7SUFDM0MsSUFBSSxXQUFXLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDcEIsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLEtBQUssTUFBTSxJQUFJLENBQUMsQ0FBQyxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzFGLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxlQUFlLEtBQUssSUFBSSxJQUFJLFdBQVcsR0FBRyxNQUFNLENBQUMsZUFBZSxDQUFDO1FBQ3JGLE9BQU8sQ0FBQyxtQkFBbUIsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUNwRCxHQUFHLEdBQUcsUUFBUSxXQUFXLHdCQUF3QixXQUFXLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLDJDQUEyQyxNQUFNLENBQUMsZUFBZSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQy9LLENBQUM7SUFFRCxJQUFJLEtBQUssQ0FBQyxVQUFVLEtBQUssS0FBSztRQUFFLFFBQVEsQ0FBQyxJQUFJLENBQUMsR0FBRyxNQUFNLHNCQUFzQixDQUFDLEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQzlGLE9BQU8sRUFBRSxRQUFRLEVBQUUsVUFBVSxDQUFDLFFBQVEsQ0FBQyxFQUFFLFFBQVEsRUFBRSxnQkFBZ0IsRUFBRSxDQUFDLEdBQUcsUUFBUSxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUM7QUFDOUYsQ0FBQztBQUVELHFFQUFxRTtBQUNyRSxNQUFNLGdCQUFnQixHQUFHLElBQUksR0FBRyxDQUFDLENBQUMsU0FBUyxFQUFFLGNBQWMsRUFBRSxVQUFVLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxxQkFBcUIsRUFBRSxpQkFBaUIsQ0FBQyxDQUFDLENBQUM7QUFFN0ksTUFBTSxTQUFTLEdBQUcsQ0FBQyxLQUFhLEVBQVUsRUFBRSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxDQUFDO0FBSTdFLElBQUksZ0JBQWdCLEdBQTRCLElBQUksQ0FBQztBQUVyRCx3RkFBd0Y7QUFDeEYsTUFBTSxVQUFVLHFDQUFxQyxDQUFDLE1BQStCO0lBQ25GLGdCQUFnQixHQUFHLE1BQU0sQ0FBQztBQUM1QixDQUFDO0FBRUQ7Ozs7Ozs7Ozs7O0dBV0c7QUFDSCxLQUFLLFVBQVUsc0JBQXNCLENBQUMsS0FBYSxFQUFFLE1BQXFCO0lBQ3hFLElBQUksYUFBYSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQztRQUFFLE9BQU8sRUFBRSxDQUFDO0lBQ3pELE1BQU0sS0FBSyxHQUFHLDJCQUEyQixDQUFDLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQyxVQUFVLENBQUM7SUFDbkUsTUFBTSxVQUFVLEdBQStCLEVBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPLEVBQUUsR0FBRyxLQUFLLEVBQUUsQ0FBQztJQUN4RyxJQUFJLENBQUM7UUFDSCxnQkFBZ0IsS0FBSyxzQkFBc0IsRUFBRSxDQUFDO1FBQzlDLE1BQU0sSUFBSSxHQUFHLG9CQUFvQixDQUFDLEVBQUUsV0FBVyxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUM7UUFDcEYsTUFBTSxNQUFNLEdBQUcsTUFBTSxnQkFBZ0IsQ0FBQyxZQUFZLENBQUMsS0FBSyxFQUFFLFVBQXFDLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDdkcsTUFBTSxRQUFRLEdBQUcsQ0FBQyxDQUFzQixFQUFFLEVBQUUsQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQ3RGLE1BQU0sRUFBRSxHQUFHLENBQUMsSUFBc0IsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFzQixFQUFlLEVBQUUsQ0FBQyxDQUFDO1lBQy9FLElBQUksRUFBRSxzQkFBc0I7WUFDNUIsUUFBUSxFQUFFLElBQUksS0FBSyxPQUFPLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsU0FBUztZQUNoRCxPQUFPLEVBQUUsR0FBRyxNQUFNLENBQUMsSUFBSSxJQUFJLE1BQU0sQ0FBQyxPQUFPLEtBQUssQ0FBQyxDQUFDLE9BQU8sRUFBRTtZQUN6RCxNQUFNLEVBQUUsQ0FBQyxDQUFDLE1BQU07WUFDaEIsUUFBUSxFQUFFLENBQUMsQ0FBQyxRQUFRO1lBQ3BCLEtBQUssRUFBRSxDQUFDLENBQUMsS0FBSztZQUNkLElBQUk7U0FDTCxDQUFDLENBQUM7UUFDSCxPQUFPLENBQUMsR0FBRyxNQUFNLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEVBQUUsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2SCxDQUFDO0lBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNiLE9BQU8sQ0FBQyxFQUFFLElBQUksRUFBRSx3QkFBd0IsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSwyRUFBMkUsTUFBTSxDQUFDLElBQUksSUFBSSxNQUFNLENBQUMsT0FBTyxLQUFLLFlBQVksQ0FBQyxHQUFHLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQztJQUM3TSxDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG4vKipcbiAqIFRIRSB2dWxuZXJhYmlsaXR5IGFzc2Vzc21lbnQgb2Ygb25lIHJlc29sdmVkIHBsdWdpbiB2ZXJzaW9uLCBmb3Igb25lIG9yZyAoYW5kLFxuICogb3B0aW9uYWxseSwgb25lIHBpcGVsaW5lJ3MgcmlzayBhY2NlcHRhbmNlKS4gT25lIGZ1bmN0aW9uLCB0aHJlZSBjYWxsZXJzOlxuICogYC9wbHVnaW5zL2xvb2t1cGAgKHdoYXQgc3ludGggcGlucyksIGAvcGx1Z2lucy9ydW50aW1lLWNoZWNrYCAod2hhdCBhIHJ1bm5pbmdcbiAqIHBpcGVsaW5lIGlzIGFib3V0IHRvIGV4ZWN1dGUpIGFuZCB0aGUgcGlwZWxpbmUgc2VydmljZSdzIHNhdmUtdGltZSBjb250cmFjdFxuICogY2hlY2suIFRocmVlIGNvcGllcyBvZiB0aGVzZSBydWxlcyBkcmlmdGVkIG9uY2UgYWxyZWFkeS5cbiAqXG4gKiBWdWxuZXJhYmlsaXR5IHN0YXRlIE5FVkVSIHJlZnVzZXMgYSBwaXBlbGluZSDigJQgbm90IGl0cyBzYXZlLCBpdHMgc3ludGgsIGl0c1xuICogZGVwbG95IG9yIGl0cyBydW4uIFdoYXQgaXQgcHJvZHVjZXMgaXMgU0VWRVJJVFktR1JBREVEIHdhcm5pbmdzIChhbmQsIGZyb20gdGhlXG4gKiBjYWxsZXJzLCBub3RpZmljYXRpb25zIHRvIHRoZSBwaXBlbGluZSdzIG93bmVycykuIFRoZSBncmFkZXM6XG4gKlxuICogICBjcml0aWNhbCDigJQgYSBmaW5kaW5nIG9uIHRoZSBDSVNBIEtub3duIEV4cGxvaXRlZCBWdWxuZXJhYmlsaXRpZXMgbGlzdFxuICogICBlcnJvciAgICDigJQgdGhlIHZlcnNpb24gaXMgRkxBR0dFRCAoZ2F0ZWQgQ3JpdGljYWxzIG92ZXIgdGhlIHBsYXRmb3JtIGZsb29yKSxcbiAqICAgICAgICAgICAgICBpdCBoYXMgZml4YWJsZSBDcml0aWNhbCBmaW5kaW5ncywgb3IgYW4gb3JnIGNvbXBsaWFuY2UgcnVsZSBvbiB0aGVcbiAqICAgICAgICAgICAgICB2dWxuZXJhYmlsaXR5IGF0dHJpYnV0ZXMgaXMgaW4gQkxPQ0sgbW9kZSBhbmQgZmFpbHNcbiAqICAgd2FybmluZyAg4oCUIGZpeGFibGUgSGlnaCBmaW5kaW5ncyBvdmVyIHRoZSBvcmcncyBgd2FybkZpeGFibGVIaWdoYCwgYSB2ZXJzaW9uXG4gKiAgICAgICAgICAgICAgbmV2ZXIgc2Nhbm5lZCwgYSBzY2FuIG9sZGVyIHRoYW4gYFBMVUdJTl9TQ0FOX1NUQUxFX0hPVVJTYCwgb3IgYVxuICogICAgICAgICAgICAgIGNvbXBsaWFuY2UgcnVsZSBpbiBXQVJOIG1vZGVcbiAqICAgaW5mbyAgICAg4oCUIHdoYXQgYSByZWFkZXIgbWF5IHdhbnQgdG8ga25vdyBidXQgbmVlZCBub3QgYWN0IG9uXG4gKlxuICogQSBQSVBFTElORSdzIGFjdGl2ZSByaXNrIGFjY2VwdGFuY2UgKGBwbHVnaW5fdnVsbl9leHBvc3VyZWAsIHRyaWFnZWQgYGFjY2VwdGVkYFxuICogd2l0aCBhIHJlYXNvbiBhbmQgYW4gZXhwaXJ5KSBkb3duZ3JhZGVzIHRoZSB3YXJuaW5ncyBhYm91dCB0aGUgZmluZGluZ3MgaXRcbiAqIEFDQ0VQVEVEIHRvIGBpbmZvYCAoXCJhY2NlcHRlZCB1bnRpbCDigKZcIikg4oCUIG5ldmVyIG9uZSBhYm91dCBhIGZpbmRpbmcgdGhhdFxuICogYXBwZWFyZWQgc2luY2UsIG5ldmVyIGEgS0VWIG9uZSB1bmxlc3MgdGhlIGFjY2VwdGFuY2Ugc2FpZCBga2V2OiB0cnVlYCwgYW5kXG4gKiBuZXZlciB0aGUgc2Nhbi1mcmVzaG5lc3Mgb3IgY29tcGxpYW5jZSB3YXJuaW5ncyAobmVpdGhlciBpcyBhYm91dCBhIGZpbmRpbmcpLlxuICovXG5cbmltcG9ydCB7IGNyZWF0ZUNvbXBsaWFuY2VDbGllbnQsIHR5cGUgQ29tcGxpYW5jZVZpb2xhdGlvbiB9IGZyb20gJy4vY29tcGxpYW5jZS1jbGllbnQuanMnO1xuaW1wb3J0IHsgZ2V0U2VydmljZUF1dGhIZWFkZXIgfSBmcm9tICcuLi9taWRkbGV3YXJlL3NlcnZpY2UtdG9rZW5zLmpzJztcbmltcG9ydCB7IGlzU3lzdGVtT3JnSWQgfSBmcm9tICcuLi9taWRkbGV3YXJlL3N5c3RlbS1vcmcuanMnO1xuaW1wb3J0IHtcbiAgYXNTY2FuRmxhZywgZGVzY3JpYmVGaW5kaW5ncywgZmFpbE9uTGFiZWwsIGlzR2F0ZWRGaW5kaW5nLCBwbHVnaW5WdWxuR2F0ZUtldiwgc2NhbkZpbmRpbmdLZXksXG4gIHR5cGUgUGx1Z2luU2NhbkZpbmRpbmcsIHR5cGUgUGx1Z2luU2NhbkZsYWcsXG59IGZyb20gJy4uL3R5cGVzL3BsdWdpbi1zY2FuLmpzJztcbmltcG9ydCB7IGVudkludCB9IGZyb20gJy4uL3V0aWxzL2Vudi5qcyc7XG5pbXBvcnQgeyBkZXJpdmVQbHVnaW5JbWFnZUNvbXBsaWFuY2UsIHBsdWdpblJ1bnNPd25JbWFnZSwgdHlwZSBQbHVnaW5Db21wbGlhbmNlQXR0cmlidXRlcywgdHlwZSBQbHVnaW5JbWFnZVJvdyB9IGZyb20gJy4uL3V0aWxzL3BsdWdpbi1jb21wbGlhbmNlLmpzJztcbmltcG9ydCB7IGVycm9yTWVzc2FnZSB9IGZyb20gJy4uL3V0aWxzL3Jlc3BvbnNlLmpzJztcblxuLyoqIEhvdyBsb3VkIGEgd2FybmluZyBpcywgcXVpZXRlc3QgZmlyc3QuICovXG5leHBvcnQgY29uc3QgVlVMTl9TRVZFUklUSUVTID0gWydpbmZvJywgJ3dhcm5pbmcnLCAnZXJyb3InLCAnY3JpdGljYWwnXSBhcyBjb25zdDtcbmV4cG9ydCB0eXBlIFZ1bG5TZXZlcml0eSA9IHR5cGVvZiBWVUxOX1NFVkVSSVRJRVNbbnVtYmVyXTtcblxuLyoqIFRoZSBsb3VkZXIgb2YgdHdvIHNldmVyaXRpZXMuICovXG5leHBvcnQgZnVuY3Rpb24gbWF4U2V2ZXJpdHkoYTogVnVsblNldmVyaXR5LCBiOiBWdWxuU2V2ZXJpdHkpOiBWdWxuU2V2ZXJpdHkge1xuICByZXR1cm4gVlVMTl9TRVZFUklUSUVTLmluZGV4T2YoYSkgPj0gVlVMTl9TRVZFUklUSUVTLmluZGV4T2YoYikgPyBhIDogYjtcbn1cblxuLyoqIFdoZXRoZXIgYHNgIGlzIGF0IGxlYXN0IGBmbG9vcmAuICovXG5leHBvcnQgZnVuY3Rpb24gc2V2ZXJpdHlBdExlYXN0KHM6IFZ1bG5TZXZlcml0eSwgZmxvb3I6IFZ1bG5TZXZlcml0eSk6IGJvb2xlYW4ge1xuICByZXR1cm4gVlVMTl9TRVZFUklUSUVTLmluZGV4T2YocykgPj0gVlVMTl9TRVZFUklUSUVTLmluZGV4T2YoZmxvb3IpO1xufVxuXG4vKiogYFBMVUdJTl9TQ0FOX1NUQUxFX0hPVVJTYCAoZGVmYXVsdCA3Mik6IGEgc2NhbiBvbGRlciB0aGFuIHRoaXMgaXMgc3RhbGUuICovXG5leHBvcnQgZnVuY3Rpb24gc2NhblN0YWxlSG91cnMoKTogbnVtYmVyIHtcbiAgcmV0dXJuIGVudkludCgnUExVR0lOX1NDQU5fU1RBTEVfSE9VUlMnLCA3MiwgeyBtaW46IDEgfSk7XG59XG5cbi8qKiBUaGUgc2Nhbi1yZWxhdGVkIGZpZWxkcyBvZiBhIHJlc29sdmVkIHJlY29yZCAoYW4gb3JnIHJvdyBvciBhIGxpc3RlZCByZWNvcmQpLiAqL1xuZXhwb3J0IGludGVyZmFjZSBTY2FubmVkUmVjb3JkIGV4dGVuZHMgUGx1Z2luSW1hZ2VSb3cge1xuICBuYW1lOiBzdHJpbmc7XG4gIHZlcnNpb246IHN0cmluZztcbiAgc2Nhbm5lZEF0PzogRGF0ZSB8IHN0cmluZyB8IG51bGw7XG4gIHNjYW5TdW1tYXJ5PzogdW5rbm93bjtcbiAgc2NhbkZsYWdnZWRBdD86IERhdGUgfCBzdHJpbmcgfCBudWxsO1xuICBzY2FuRmxhZz86IHVua25vd247XG4gIHZ1bG5IaWdoRml4YWJsZT86IHVua25vd247XG59XG5cbmNvbnN0IHRvRGF0ZSA9ICh2OiB1bmtub3duKTogRGF0ZSB8IG51bGwgPT4ge1xuICBpZiAoIXYpIHJldHVybiBudWxsO1xuICBjb25zdCBkID0gdiBpbnN0YW5jZW9mIERhdGUgPyB2IDogbmV3IERhdGUoU3RyaW5nKHYpKTtcbiAgcmV0dXJuIE51bWJlci5pc05hTihkLmdldFRpbWUoKSkgPyBudWxsIDogZDtcbn07XG5cbmNvbnN0IHN1bW1hcnlPZiA9IChyZWNvcmQ6IFBpY2s8U2Nhbm5lZFJlY29yZCwgJ3NjYW5TdW1tYXJ5Jz4pOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB8IG51bGwgPT5cbiAgKHJlY29yZC5zY2FuU3VtbWFyeSAmJiB0eXBlb2YgcmVjb3JkLnNjYW5TdW1tYXJ5ID09PSAnb2JqZWN0JyAmJiAhQXJyYXkuaXNBcnJheShyZWNvcmQuc2NhblN1bW1hcnkpXG4gICAgPyByZWNvcmQuc2NhblN1bW1hcnkgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4gOiBudWxsKTtcblxuLyoqXG4gKiBXaGVuIHRoZSB2ZXJzaW9uIHdhcyBsYXN0IHNjYW5uZWQ6IHRoZSBsYXRlciBvZiB0aGUgYnVpbGQtdGltZSBgc2Nhbm5lZEF0YCBhbmRcbiAqIHRoZSBuaWdodGx5IHJlc2NhbidzIGBzY2FuX3N1bW1hcnkuc2Nhbm5lZEF0YC4gTnVsbCA9IG5ldmVyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gbGFzdFNjYW5uZWRBdChyZWNvcmQ6IFBpY2s8U2Nhbm5lZFJlY29yZCwgJ3NjYW5uZWRBdCcgfCAnc2NhblN1bW1hcnknPik6IERhdGUgfCBudWxsIHtcbiAgY29uc3QgYnVpbGQgPSB0b0RhdGUocmVjb3JkLnNjYW5uZWRBdCk7XG4gIGNvbnN0IHN1bW1hcnkgPSB0b0RhdGUoc3VtbWFyeU9mKHJlY29yZCk/LnNjYW5uZWRBdCk7XG4gIGlmICghYnVpbGQpIHJldHVybiBzdW1tYXJ5O1xuICBpZiAoIXN1bW1hcnkpIHJldHVybiBidWlsZDtcbiAgcmV0dXJuIHN1bW1hcnkgPiBidWlsZCA/IHN1bW1hcnkgOiBidWlsZDtcbn1cblxuLyoqIFdoZXRoZXIgdGhlIHJlY29yZCBydW5zIGEgQlVJTFQgaW1hZ2Ugb2YgaXRzIG93biDigJQgdGhlIG9ubHkgdGhpbmcgYSBzY2FuIGFwcGxpZXMgdG8uICovXG5mdW5jdGlvbiBoYXNJbWFnZShyZWNvcmQ6IFNjYW5uZWRSZWNvcmQpOiBib29sZWFuIHtcbiAgcmV0dXJuIHBsdWdpblJ1bnNPd25JbWFnZShyZWNvcmQpICYmIHR5cGVvZiByZWNvcmQuaW1hZ2VEaWdlc3QgPT09ICdzdHJpbmcnICYmIHJlY29yZC5pbWFnZURpZ2VzdC5sZW5ndGggPiAwO1xufVxuXG4vKiogRnJlc2huZXNzIG9mIGEgdmVyc2lvbidzIHNjYW46IGBub25lYCAobm8gaW1hZ2UgdG8gc2NhbiksIGB1bnNjYW5uZWRgLCBgc3RhbGVgIG9yIGBmcmVzaGAuICovXG5leHBvcnQgZnVuY3Rpb24gc2NhbkZyZXNobmVzcyhyZWNvcmQ6IFNjYW5uZWRSZWNvcmQsIG5vdyA9IG5ldyBEYXRlKCkpOiB7IHN0YXRlOiAnbm9uZScgfCAndW5zY2FubmVkJyB8ICdzdGFsZScgfCAnZnJlc2gnOyBzY2FubmVkQXQ6IERhdGUgfCBudWxsIH0ge1xuICBpZiAoIWhhc0ltYWdlKHJlY29yZCkpIHJldHVybiB7IHN0YXRlOiAnbm9uZScsIHNjYW5uZWRBdDogbnVsbCB9O1xuICBjb25zdCBhdCA9IGxhc3RTY2FubmVkQXQocmVjb3JkKTtcbiAgaWYgKCFhdCkgcmV0dXJuIHsgc3RhdGU6ICd1bnNjYW5uZWQnLCBzY2FubmVkQXQ6IG51bGwgfTtcbiAgcmV0dXJuIHsgc3RhdGU6IG5vdy5nZXRUaW1lKCkgLSBhdC5nZXRUaW1lKCkgPiBzY2FuU3RhbGVIb3VycygpICogM182MDBfMDAwID8gJ3N0YWxlJyA6ICdmcmVzaCcsIHNjYW5uZWRBdDogYXQgfTtcbn1cblxuLyoqIE9uZSBzZXZlcml0eS1ncmFkZWQgdnVsbmVyYWJpbGl0eSB3YXJuaW5nLiAqL1xuZXhwb3J0IHR5cGUgVnVsbldhcm5pbmcgPVxuICB8IHtcbiAgICBjb2RlOiAnVlVMTl9LRVYnIHwgJ1ZVTE5fRkxBR0dFRCcgfCAnVlVMTl9DUklUSUNBTF9GSVhBQkxFJyB8ICdWVUxOX0hJR0hfRklYQUJMRSc7XG4gICAgc2V2ZXJpdHk6IFZ1bG5TZXZlcml0eTtcbiAgICBtZXNzYWdlOiBzdHJpbmc7XG4gICAgZmluZGluZ3M6IFBsdWdpblNjYW5GaW5kaW5nW107XG4gICAgc3VnZ2VzdGVkVmVyc2lvbj86IHN0cmluZztcbiAgICAvKiogYFZVTE5fRkxBR0dFRGAgY2FycmllcyB0aGUgZmxhZydzIGNvdW50cyAodGhlIHNoYXBlIHRoZSByZXNjYW4tZmxhZyB3YXJuaW5nIGFsd2F5cyBoYWQpLiAqL1xuICAgIHBsdWdpbj86IHN0cmluZztcbiAgICB2ZXJzaW9uPzogc3RyaW5nO1xuICAgIC8qKiBUaGUgZmxhZydzIGdhdGVkIGNvdW50IChmaW5kaW5ncyBhdCBvciBhYm92ZSBpdHMgYGZhaWxPbmApLiAqL1xuICAgIGdhdGVkPzogbnVtYmVyO1xuICAgIGhpZ2g/OiBudW1iZXI7XG4gIH1cbiAgfCB7IGNvZGU6ICdWVUxOX0FDQ0VQVEVEJzsgc2V2ZXJpdHk6ICdpbmZvJzsgbWVzc2FnZTogc3RyaW5nOyBmaW5kaW5nczogc3RyaW5nW107IGFjY2VwdGVkVW50aWw6IHN0cmluZyB8IG51bGw7IGtldjogYm9vbGVhbjsgY292ZXJzOiBzdHJpbmcgfVxuICB8IHsgY29kZTogJ1VOU0NBTk5FRCc7IHNldmVyaXR5OiBWdWxuU2V2ZXJpdHk7IG1lc3NhZ2U6IHN0cmluZyB9XG4gIHwgeyBjb2RlOiAnU0NBTl9TVEFMRSc7IHNldmVyaXR5OiBWdWxuU2V2ZXJpdHk7IG1lc3NhZ2U6IHN0cmluZzsgc2Nhbm5lZEF0OiBzdHJpbmc7IHN0YWxlQWZ0ZXJIb3VyczogbnVtYmVyIH1cbiAgfCB7IGNvZGU6ICdDT01QTElBTkNFX1ZVTE5fUlVMRSc7IHNldmVyaXR5OiBWdWxuU2V2ZXJpdHk7IG1lc3NhZ2U6IHN0cmluZzsgcnVsZUlkOiBzdHJpbmc7IHJ1bGVOYW1lOiBzdHJpbmc7IGZpZWxkOiBzdHJpbmc7IG1vZGU6ICdibG9jaycgfCAnd2FybicgfVxuICB8IHsgY29kZTogJ0NPTVBMSUFOQ0VfVU5BVkFJTEFCTEUnOyBzZXZlcml0eTogVnVsblNldmVyaXR5OyBtZXNzYWdlOiBzdHJpbmcgfTtcblxuLyoqIGBVTlNDQU5ORURgIC8gYFNDQU5fU1RBTEVgIGZvciBhIHJlc29sdmVkIHZlcnNpb24gKGVtcHR5IGZvciBhIGZyZXNoIHNjYW4gb3IgYW4gaW1hZ2UtbGVzcyBwbHVnaW4pLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNjYW5XYXJuaW5ncyhyZWNvcmQ6IFNjYW5uZWRSZWNvcmQsIG5vdyA9IG5ldyBEYXRlKCkpOiBWdWxuV2FybmluZ1tdIHtcbiAgY29uc3QgcmVmID0gYCR7cmVjb3JkLm5hbWV9QCR7cmVjb3JkLnZlcnNpb259YDtcbiAgY29uc3QgZiA9IHNjYW5GcmVzaG5lc3MocmVjb3JkLCBub3cpO1xuICBpZiAoZi5zdGF0ZSA9PT0gJ3Vuc2Nhbm5lZCcpIHtcbiAgICByZXR1cm4gW3sgY29kZTogJ1VOU0NBTk5FRCcsIHNldmVyaXR5OiAnd2FybmluZycsIG1lc3NhZ2U6IGBQbHVnaW4gJHtyZWZ9IGhhcyBuZXZlciBiZWVuIHNjYW5uZWQgZm9yIHZ1bG5lcmFiaWxpdGllczsgbm90aGluZyBpcyBrbm93biBhYm91dCB3aGF0IGl0cyBpbWFnZSBjb250YWlucy5gIH1dO1xuICB9XG4gIGlmIChmLnN0YXRlID09PSAnc3RhbGUnKSB7XG4gICAgY29uc3QgaG91cnMgPSBzY2FuU3RhbGVIb3VycygpO1xuICAgIHJldHVybiBbe1xuICAgICAgY29kZTogJ1NDQU5fU1RBTEUnLFxuICAgICAgc2V2ZXJpdHk6ICd3YXJuaW5nJyxcbiAgICAgIG1lc3NhZ2U6IGBQbHVnaW4gJHtyZWZ9IHdhcyBsYXN0IHNjYW5uZWQgJHtmLnNjYW5uZWRBdCEudG9JU09TdHJpbmcoKX0sIG1vcmUgdGhhbiAke2hvdXJzfWggYWdvOyBmaW5kaW5ncyBwdWJsaXNoZWQgc2luY2UgYXJlIG5vdCByZWZsZWN0ZWQuYCxcbiAgICAgIHNjYW5uZWRBdDogZi5zY2FubmVkQXQhLnRvSVNPU3RyaW5nKCksXG4gICAgICBzdGFsZUFmdGVySG91cnM6IGhvdXJzLFxuICAgIH1dO1xuICB9XG4gIHJldHVybiBbXTtcbn1cblxuLyoqIFRoZSB2dWxuZXJhYmlsaXR5IGZpZWxkcyBvZiBhbiBvcmcncyBjb25zdW1wdGlvbiBwb2xpY3kgKHBpcGVsaW5lLWRhdGEncyBgQ29uc3VtcHRpb25Qb2xpY3lgIHNhdGlzZmllcyBpdCkuICovXG5leHBvcnQgaW50ZXJmYWNlIFZ1bG5Db25zdW1wdGlvblBvbGljeSB7XG4gIC8qKiBGaXhhYmxlIEhpZ2ggZmluZGluZ3MgYWJvdmUgdGhpcyBtYW55IHJhaXNlIGEgYHdhcm5pbmdgOyBudWxsID0gbmV2ZXIgKHRoZXkgc3RheSBgaW5mb2ApLiAqL1xuICB3YXJuRml4YWJsZUhpZ2g6IG51bWJlciB8IG51bGw7XG59XG5cbi8qKlxuICogQSBwaXBlbGluZSdzIEFDVElWRSByaXNrIGFjY2VwdGFuY2Ugb2Ygb25lIHZlcnNpb24gLyBpbWFnZTogdGhlIGZpbmRpbmcga2V5c1xuICogKHtAbGluayBzY2FuRmluZGluZ0tleX0pIGl0IGFjY2VwdGVkLCB3aGV0aGVyIGl0IGFjY2VwdGVkIEtFViBmaW5kaW5ncywgYW5kXG4gKiB1bnRpbCB3aGVuLiBCdWlsdCBieSBwaXBlbGluZS1kYXRhIGZyb20gYHBsdWdpbl92dWxuX2V4cG9zdXJlYC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBWdWxuQWNjZXB0YW5jZSB7XG4gIGZpbmRpbmdLZXlzOiByZWFkb25seSBzdHJpbmdbXTtcbiAga2V2OiBib29sZWFuO1xuICBhY2NlcHRlZFVudGlsOiBEYXRlIHwgc3RyaW5nIHwgbnVsbDtcbn1cblxuLyoqIFdoYXQgYSB2ZXJzaW9uJ3Mgc3RvcmVkIHNjYW4gc2F5cywgbm9ybWFsaXplZCBmcm9tIGBzY2FuX3N1bW1hcnlgIChmb3IgaXRzIGltYWdlKSBhbmQgYHNjYW5fZmxhZ2AuICovXG5leHBvcnQgaW50ZXJmYWNlIFZlcnNpb25TY2FuRmFjdHMge1xuICBmbGFnZ2VkOiBib29sZWFuO1xuICBmbGFnOiBQbHVnaW5TY2FuRmxhZyB8IG51bGw7XG4gIC8qKiBGaXhhYmxlIENyaXRpY2FsIC8gSGlnaCBmaW5kaW5ncyAobnVsbCA9IG5vdCBrbm93bikuICovXG4gIGNyaXRpY2FsRml4YWJsZTogbnVtYmVyIHwgbnVsbDtcbiAgaGlnaEZpeGFibGU6IG51bWJlciB8IG51bGw7XG4gIC8qKiBUb3RhbHMgaW5jbHVkaW5nIHVuZml4YWJsZSBmaW5kaW5ncyAobnVsbCA9IG5vdCBrbm93bikuICovXG4gIGNyaXRpY2FsOiBudW1iZXIgfCBudWxsO1xuICBoaWdoOiBudW1iZXIgfCBudWxsO1xuICAvKiogS0VWLWxpc3RlZCBDcml0aWNhbCArIEhpZ2ggZmluZGluZ3MuICovXG4gIGtldjogbnVtYmVyO1xuICAvKiogRXZlcnkgQ3JpdGljYWwvSGlnaCBmaW5kaW5nIHRoZSBzY2FuIGl0ZW1pemVkICh0aGUgc3VtbWFyeSdzIGxpc3QsIGVsc2UgdGhlIGZsYWcncykuICovXG4gIGZpbmRpbmdzOiBQbHVnaW5TY2FuRmluZGluZ1tdO1xuICAvKiogVGhlIHN1bW1hcnkgY3V0IGl0cyBmaW5kaW5ncyBsaXN0IOKAlCBhIHN1YnNldCBjaGVjayBvdmVyIGl0IGNhbm5vdCBiZSB0cnVzdGVkLiAqL1xuICB0cnVuY2F0ZWQ6IGJvb2xlYW47XG4gIHNjYW5uZWRBdDogRGF0ZSB8IG51bGw7XG59XG5cbi8qKiBUaGUgbm9ybWFsaXplZCBzY2FuIGZhY3RzIG9mIGEgcmVzb2x2ZWQgcmVjb3JkLiBBIHN1bW1hcnkgZGVzY3JpYmluZyBhbm90aGVyIGltYWdlIGlzIGlnbm9yZWQuICovXG5leHBvcnQgZnVuY3Rpb24gdmVyc2lvblNjYW5GYWN0cyhyZWNvcmQ6IFNjYW5uZWRSZWNvcmQpOiBWZXJzaW9uU2NhbkZhY3RzIHtcbiAgY29uc3QgZmxhZyA9IHJlY29yZC5zY2FuRmxhZ2dlZEF0ID8gYXNTY2FuRmxhZyhyZWNvcmQuc2NhbkZsYWcpIDogbnVsbDtcbiAgY29uc3QgcmF3ID0gc3VtbWFyeU9mKHJlY29yZCk7XG4gIGNvbnN0IGRpZ2VzdCA9IHR5cGVvZiByYXc/LmltYWdlRGlnZXN0ID09PSAnc3RyaW5nJyA/IHJhdy5pbWFnZURpZ2VzdCA6IG51bGw7XG4gIGNvbnN0IHN1bW1hcnkgPSByYXcgJiYgKGRpZ2VzdCA9PT0gbnVsbCB8fCAhcmVjb3JkLmltYWdlRGlnZXN0IHx8IGRpZ2VzdCA9PT0gcmVjb3JkLmltYWdlRGlnZXN0KSA/IHJhdyA6IG51bGw7XG4gIGNvbnN0IGZpbmRpbmdzID0gc3VtbWFyeSAmJiBBcnJheS5pc0FycmF5KHN1bW1hcnkuZmluZGluZ3MpXG4gICAgPyAoc3VtbWFyeS5maW5kaW5ncyBhcyBQbHVnaW5TY2FuRmluZGluZ1tdKS5maWx0ZXIoKGYpID0+IGYgJiYgdHlwZW9mIGYuaWQgPT09ICdzdHJpbmcnKS5tYXAoKGYpID0+ICh7IC4uLmYsIGZpeGVkSW46IEFycmF5LmlzQXJyYXkoZi5maXhlZEluKSA/IGYuZml4ZWRJbiA6IFtdIH0pKVxuICAgIDogKGZsYWc/LmZpbmRpbmdzID8/IFtdKTtcbiAgY29uc3QgbnVtID0gKHY6IHVua25vd24pOiBudW1iZXIgfCBudWxsID0+ICh0eXBlb2YgdiA9PT0gJ251bWJlcicgPyB2IDogbnVsbCk7XG4gIGNvbnN0IGtldkNvdW50ID0gTWF0aC5tYXgobnVtKHN1bW1hcnk/LmtldikgPz8gMCwgZmxhZz8ua2V2ID8/IDAsIGZpbmRpbmdzLmZpbHRlcigoZikgPT4gZi5rZXYgPT09IHRydWUpLmxlbmd0aCk7XG4gIHJldHVybiB7XG4gICAgZmxhZ2dlZDogZmxhZyAhPT0gbnVsbCxcbiAgICBmbGFnLFxuICAgIGNyaXRpY2FsRml4YWJsZTogbnVtKHN1bW1hcnk/LmNyaXRpY2FsRml4YWJsZSksXG4gICAgaGlnaEZpeGFibGU6IG51bShzdW1tYXJ5Py5oaWdoRml4YWJsZSkgPz8gbnVtKHJlY29yZC52dWxuSGlnaEZpeGFibGUpLFxuICAgIGNyaXRpY2FsOiBudW0oc3VtbWFyeT8uY3JpdGljYWwpLFxuICAgIGhpZ2g6IG51bShzdW1tYXJ5Py5oaWdoKSxcbiAgICBrZXY6IGtldkNvdW50LFxuICAgIGZpbmRpbmdzLFxuICAgIHRydW5jYXRlZDogc3VtbWFyeT8udHJ1bmNhdGVkID09PSB0cnVlLFxuICAgIHNjYW5uZWRBdDogbGFzdFNjYW5uZWRBdChyZWNvcmQpLFxuICB9O1xufVxuXG4vKipcbiAqIFdoZXRoZXIgYGFjY2VwdGFuY2VgIGNvdmVycyBFVkVSWSBvbmUgb2YgYGZpbmRpbmdzYCAoYnkgZmluZGluZyBrZXkpLCBhbmQgaXRzXG4gKiBLRVYgb25lcyBvbmx5IHdoZW4gaXQgYWNjZXB0ZWQgS0VWLiBBbiBlbXB0eSBzZXQgaXMgbmV2ZXIgXCJjb3ZlcmVkXCI6IHdpdGhcbiAqIG5vdGhpbmcgaXRlbWl6ZWQgdGhlcmUgaXMgbm90aGluZyBhbiBhY2NlcHRhbmNlIGNhbiBiZSBzaG93biB0byBkZXNjcmliZS5cbiAqL1xuZnVuY3Rpb24gY292ZXJzKGFjY2VwdGFuY2U6IFZ1bG5BY2NlcHRhbmNlIHwgbnVsbCB8IHVuZGVmaW5lZCwgZmluZGluZ3M6IHJlYWRvbmx5IFBsdWdpblNjYW5GaW5kaW5nW10sIHRydW5jYXRlZDogYm9vbGVhbik6IGJvb2xlYW4ge1xuICBpZiAoIWFjY2VwdGFuY2UgfHwgdHJ1bmNhdGVkIHx8IGZpbmRpbmdzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIGZhbHNlO1xuICBjb25zdCBrZXlzID0gbmV3IFNldChhY2NlcHRhbmNlLmZpbmRpbmdLZXlzKTtcbiAgcmV0dXJuIGZpbmRpbmdzLmV2ZXJ5KChmKSA9PiBrZXlzLmhhcyhzY2FuRmluZGluZ0tleShmKSkgJiYgKGYua2V2ICE9PSB0cnVlIHx8IGFjY2VwdGFuY2Uua2V2KSk7XG59XG5cbi8qKiBJbnB1dCB0byB7QGxpbmsgYXNzZXNzVmVyc2lvblZ1bG5zfS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVmVyc2lvblZ1bG5JbnB1dCB7XG4gIG9yZ0lkOiBzdHJpbmc7XG4gIHJlY29yZDogU2Nhbm5lZFJlY29yZDtcbiAgcG9saWN5OiBWdWxuQ29uc3VtcHRpb25Qb2xpY3k7XG4gIC8qKiBUaGUgcGlwZWxpbmUncyBhY3RpdmUgYWNjZXB0YW5jZSBvZiB0aGlzIHZlcnNpb24gLyBpbWFnZSwgd2hlbiB0aGUgY2FsbGVyIGhhcyBhIHBpcGVsaW5lLiAqL1xuICBhY2NlcHRhbmNlPzogVnVsbkFjY2VwdGFuY2UgfCBudWxsO1xuICAvKiogVGhlIG5ld2VzdCB1bmZsYWdnZWQgdmVyc2lvbiB0aGUgb3duZXIgY2FuIG1vdmUgdG8sIG5hbWVkIG9uIHRoZSBmaW5kaW5nIHdhcm5pbmdzLiAqL1xuICBzdWdnZXN0ZWRWZXJzaW9uPzogc3RyaW5nIHwgbnVsbDtcbiAgLyoqIFJ1biB0aGUgb3JnJ3MgY29tcGxpYW5jZSBydWxlcyAoYSBuZXR3b3JrIGNhbGwpLiBEZWZhdWx0IHRydWUuICovXG4gIGNvbXBsaWFuY2U/OiBib29sZWFuO1xuICBub3c/OiBEYXRlO1xufVxuXG4vKiogVGhlIGFzc2Vzc21lbnQ6IGV2ZXJ5IHdhcm5pbmcsIHRoZSBsb3VkZXN0IHNldmVyaXR5LCBhbmQgd2hpY2ggYWNjZXB0ZWQgZmluZGluZ3MgaXQgZG93bmdyYWRlZC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVmVyc2lvblZ1bG5Bc3Nlc3NtZW50IHtcbiAgLyoqIGBudWxsYCB3aGVuIHRoZXJlIGlzIG5vdGhpbmcgdG8gc2F5LiAqL1xuICBzZXZlcml0eTogVnVsblNldmVyaXR5IHwgbnVsbDtcbiAgd2FybmluZ3M6IFZ1bG5XYXJuaW5nW107XG4gIC8qKiBGaW5kaW5nIGtleXMgYW4gYWNjZXB0YW5jZSBkb3duZ3JhZGVkIChlbXB0eSA9IG5vIGFjY2VwdGFuY2UgYXBwbGllZCkuICovXG4gIGFjY2VwdGVkRmluZGluZ3M6IHN0cmluZ1tdO1xuICBmYWN0czogVmVyc2lvblNjYW5GYWN0cztcbn1cblxuLyoqIFRoZSBsb3VkZXN0IHNldmVyaXR5IG9mIGB3YXJuaW5nc2AsIG9yIG51bGwgZm9yIG5vbmUuICovXG5leHBvcnQgZnVuY3Rpb24gc2V2ZXJpdHlPZih3YXJuaW5nczogUmVhZG9ubHlBcnJheTx7IHNldmVyaXR5PzogVnVsblNldmVyaXR5IH0+KTogVnVsblNldmVyaXR5IHwgbnVsbCB7XG4gIHJldHVybiB3YXJuaW5ncy5yZWR1Y2U8VnVsblNldmVyaXR5IHwgbnVsbD4oKGFjYywgdykgPT4gKHcuc2V2ZXJpdHkgPyAoYWNjID8gbWF4U2V2ZXJpdHkoYWNjLCB3LnNldmVyaXR5KSA6IHcuc2V2ZXJpdHkpIDogYWNjKSwgbnVsbCk7XG59XG5cbi8qKlxuICogVGhlIGFzc2Vzc21lbnQgb2Ygb25lIHJlc29sdmVkIHZlcnNpb24gKHNlZSB0aGUgbW9kdWxlIGRvYykuIE5ldmVyIHRocm93cyBhbmRcbiAqIG5ldmVyIHJlZnVzZXM6IGEgY29tcGxpYW5jZSBvdXRhZ2UgYWRkcyBhbiBgaW5mb2AgYENPTVBMSUFOQ0VfVU5BVkFJTEFCTEVgLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYXNzZXNzVmVyc2lvblZ1bG5zKGlucHV0OiBWZXJzaW9uVnVsbklucHV0KTogUHJvbWlzZTxWZXJzaW9uVnVsbkFzc2Vzc21lbnQ+IHtcbiAgY29uc3QgeyBvcmdJZCwgcmVjb3JkLCBwb2xpY3ksIGFjY2VwdGFuY2UgfSA9IGlucHV0O1xuICBjb25zdCBub3cgPSBpbnB1dC5ub3cgPz8gbmV3IERhdGUoKTtcbiAgY29uc3QgcmVmID0gYCR7cmVjb3JkLm5hbWV9QCR7cmVjb3JkLnZlcnNpb259YDtcbiAgY29uc3QgZmFjdHMgPSB2ZXJzaW9uU2NhbkZhY3RzKHJlY29yZCk7XG4gIGNvbnN0IHdhcm5pbmdzOiBWdWxuV2FybmluZ1tdID0gWy4uLnNjYW5XYXJuaW5ncyhyZWNvcmQsIG5vdyldO1xuICBjb25zdCBhY2NlcHRlZCA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICBjb25zdCB3YXkgPSBpbnB1dC5zdWdnZXN0ZWRWZXJzaW9uID8gYCBNb3ZlIHRvICR7cmVjb3JkLm5hbWV9QCR7aW5wdXQuc3VnZ2VzdGVkVmVyc2lvbn0uYCA6ICcnO1xuICBjb25zdCBzdWdnZXN0ZWQgPSBpbnB1dC5zdWdnZXN0ZWRWZXJzaW9uID8geyBzdWdnZXN0ZWRWZXJzaW9uOiBpbnB1dC5zdWdnZXN0ZWRWZXJzaW9uIH0gOiB7fTtcbiAgY29uc3QgdW50aWwgPSB0b0RhdGUoYWNjZXB0YW5jZT8uYWNjZXB0ZWRVbnRpbCk/LnRvSVNPU3RyaW5nKCkgPz8gbnVsbDtcblxuICAvKiogUHVzaCBhIGZpbmRpbmcgd2FybmluZyDigJQgb3IsIHdoZW4gdGhlIHBpcGVsaW5lIGFjY2VwdGVkIGV4YWN0bHkgdGhvc2UgZmluZGluZ3MsIGl0cyBgaW5mb2AgZG93bmdyYWRlLiAqL1xuICBjb25zdCBmaW5kaW5nID0gKGNvZGU6ICdWVUxOX0tFVicgfCAnVlVMTl9GTEFHR0VEJyB8ICdWVUxOX0NSSVRJQ0FMX0ZJWEFCTEUnIHwgJ1ZVTE5fSElHSF9GSVhBQkxFJywgc2V2ZXJpdHk6IFZ1bG5TZXZlcml0eSwgbWVzc2FnZTogc3RyaW5nLCBmaW5kaW5nczogUGx1Z2luU2NhbkZpbmRpbmdbXSxcbiAgICBleHRyYTogeyBwbHVnaW4/OiBzdHJpbmc7IHZlcnNpb24/OiBzdHJpbmc7IGdhdGVkPzogbnVtYmVyOyBoaWdoPzogbnVtYmVyIH0gPSB7fSkgPT4ge1xuICAgIGlmIChjb3ZlcnMoYWNjZXB0YW5jZSwgZmluZGluZ3MsIGZhY3RzLnRydW5jYXRlZCkpIHtcbiAgICAgIGZvciAoY29uc3QgZiBvZiBmaW5kaW5ncykgYWNjZXB0ZWQuYWRkKHNjYW5GaW5kaW5nS2V5KGYpKTtcbiAgICAgIHdhcm5pbmdzLnB1c2goe1xuICAgICAgICBjb2RlOiAnVlVMTl9BQ0NFUFRFRCcsXG4gICAgICAgIHNldmVyaXR5OiAnaW5mbycsXG4gICAgICAgIG1lc3NhZ2U6IGAke21lc3NhZ2V9IEFjY2VwdGVkIGZvciB0aGlzIHBpcGVsaW5lJHt1bnRpbCA/IGAgdW50aWwgJHt1bnRpbH1gIDogJyd9LmAsXG4gICAgICAgIGZpbmRpbmdzOiBmaW5kaW5ncy5tYXAoc2NhbkZpbmRpbmdLZXkpLFxuICAgICAgICBhY2NlcHRlZFVudGlsOiB1bnRpbCxcbiAgICAgICAga2V2OiBhY2NlcHRhbmNlPy5rZXYgPz8gZmFsc2UsXG4gICAgICAgIGNvdmVyczogY29kZSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB3YXJuaW5ncy5wdXNoKHsgY29kZSwgc2V2ZXJpdHksIG1lc3NhZ2U6IGAke21lc3NhZ2V9JHt3YXl9YCwgZmluZGluZ3M6IGZpbmRpbmdzLnNsaWNlKDAsIDEwKSwgLi4uc3VnZ2VzdGVkLCAuLi5leHRyYSB9KTtcbiAgfTtcblxuICBjb25zdCBrZXZGaW5kaW5ncyA9IGZhY3RzLmZpbmRpbmdzLmZpbHRlcigoZikgPT4gZi5rZXYgPT09IHRydWUpO1xuICBpZiAoZmFjdHMua2V2ID4gMCkge1xuICAgIGZpbmRpbmcoJ1ZVTE5fS0VWJywgJ2NyaXRpY2FsJywgYCR7cmVmfSBoYXMgJHtmYWN0cy5rZXZ9IGZpbmRpbmcke2ZhY3RzLmtldiA9PT0gMSA/ICcnIDogJ3MnfSBvbiB0aGUgQ0lTQSBLbm93biBFeHBsb2l0ZWQgVnVsbmVyYWJpbGl0aWVzIGxpc3Qke2tldkZpbmRpbmdzLmxlbmd0aCA/IGA6ICR7ZGVzY3JpYmVGaW5kaW5ncyhrZXZGaW5kaW5ncyl9YCA6ICcnfS5gLCBrZXZGaW5kaW5ncyk7XG4gIH1cbiAgY29uc3QgZmxhZyA9IGZhY3RzLmZsYWc7XG4gIGlmIChmbGFnKSB7XG4gICAgY29uc3QgZ2F0ZWQgPSBmYWN0cy5maW5kaW5ncy5maWx0ZXIoKGYpID0+IGlzR2F0ZWRGaW5kaW5nKGYsIHBsdWdpblZ1bG5HYXRlS2V2KCksIGZsYWcuZmFpbE9uID8/ICdjcml0aWNhbCcpKTtcbiAgICBmaW5kaW5nKCdWVUxOX0ZMQUdHRUQnLCAnZXJyb3InLCBgJHtyZWZ9IGlzIGZsYWdnZWQ6IGEgcmVzY2FuIGZvdW5kICR7ZmxhZy5nYXRlZH0gZ2F0ZWQgJHtmYWlsT25MYWJlbChmbGFnLmZhaWxPbiA/PyAnY3JpdGljYWwnKX0gZmluZGluZyR7ZmxhZy5nYXRlZCA9PT0gMSA/ICcnIDogJ3MnfSBvdmVyIHRoZSBwbGF0Zm9ybSBsaW1pdCR7ZmxhZy5maW5kaW5ncy5sZW5ndGggPyBgIChmaXg6ICR7ZGVzY3JpYmVGaW5kaW5ncyhmbGFnLmZpbmRpbmdzKX0pYCA6ICcnfS5gLFxuICAgICAgZ2F0ZWQubGVuZ3RoID4gMCA/IGdhdGVkIDogZmxhZy5maW5kaW5ncywgeyBwbHVnaW46IHJlY29yZC5uYW1lLCB2ZXJzaW9uOiByZWNvcmQudmVyc2lvbiwgZ2F0ZWQ6IGZsYWcuZ2F0ZWQsIGhpZ2g6IGZsYWcuaGlnaCB9KTtcbiAgfSBlbHNlIGlmICgoZmFjdHMuY3JpdGljYWxGaXhhYmxlID8/IDApID4gMCkge1xuICAgIGNvbnN0IGNyaXRzID0gZmFjdHMuZmluZGluZ3MuZmlsdGVyKChmKSA9PiBmLnNldmVyaXR5ID09PSAnY3JpdGljYWwnICYmIGYuZml4ZWRJbi5sZW5ndGggPiAwKTtcbiAgICBmaW5kaW5nKCdWVUxOX0NSSVRJQ0FMX0ZJWEFCTEUnLCAnZXJyb3InLCBgJHtyZWZ9IGhhcyAke2ZhY3RzLmNyaXRpY2FsRml4YWJsZX0gZml4YWJsZSBDcml0aWNhbCBmaW5kaW5nJHtmYWN0cy5jcml0aWNhbEZpeGFibGUgPT09IDEgPyAnJyA6ICdzJ30ke2NyaXRzLmxlbmd0aCA/IGA6ICR7ZGVzY3JpYmVGaW5kaW5ncyhjcml0cyl9YCA6ICcnfS5gLCBjcml0cyk7XG4gIH1cbiAgY29uc3QgaGlnaEZpeGFibGUgPSBmYWN0cy5oaWdoRml4YWJsZSA/PyAwO1xuICBpZiAoaGlnaEZpeGFibGUgPiAwKSB7XG4gICAgY29uc3QgaGlnaHMgPSBmYWN0cy5maW5kaW5ncy5maWx0ZXIoKGYpID0+IGYuc2V2ZXJpdHkgPT09ICdoaWdoJyAmJiBmLmZpeGVkSW4ubGVuZ3RoID4gMCk7XG4gICAgY29uc3Qgb3ZlciA9IHBvbGljeS53YXJuRml4YWJsZUhpZ2ggIT09IG51bGwgJiYgaGlnaEZpeGFibGUgPiBwb2xpY3kud2FybkZpeGFibGVIaWdoO1xuICAgIGZpbmRpbmcoJ1ZVTE5fSElHSF9GSVhBQkxFJywgb3ZlciA/ICd3YXJuaW5nJyA6ICdpbmZvJyxcbiAgICAgIGAke3JlZn0gaGFzICR7aGlnaEZpeGFibGV9IGZpeGFibGUgSGlnaCBmaW5kaW5nJHtoaWdoRml4YWJsZSA9PT0gMSA/ICcnIDogJ3MnfSR7b3ZlciA/IGAsIG92ZXIgeW91ciBvcmdhbml6YXRpb24ncyB0aHJlc2hvbGQgb2YgJHtwb2xpY3kud2FybkZpeGFibGVIaWdofWAgOiAnJ30uYCwgaGlnaHMpO1xuICB9XG5cbiAgaWYgKGlucHV0LmNvbXBsaWFuY2UgIT09IGZhbHNlKSB3YXJuaW5ncy5wdXNoKC4uLmF3YWl0IGNvbXBsaWFuY2VWdWxuV2FybmluZ3Mob3JnSWQsIHJlY29yZCkpO1xuICByZXR1cm4geyBzZXZlcml0eTogc2V2ZXJpdHlPZih3YXJuaW5ncyksIHdhcm5pbmdzLCBhY2NlcHRlZEZpbmRpbmdzOiBbLi4uYWNjZXB0ZWRdLCBmYWN0cyB9O1xufVxuXG4vKiogVGhlIGNvbXBsaWFuY2UgYXR0cmlidXRlcyBhIHBsdWdpbidzIHZ1bG5lcmFiaWxpdHkgcnVsZXMgcmVhZC4gKi9cbmNvbnN0IFZVTE5fUlVMRV9GSUVMRFMgPSBuZXcgU2V0KFsnc2Nhbm5lZCcsICd2dWxuQ3JpdGljYWwnLCAndnVsbkhpZ2gnLCAndnVsbk1lZGl1bScsICd2dWxuTG93JywgJ3Z1bG5Dcml0aWNhbEZpeGFibGUnLCAndnVsbkhpZ2hGaXhhYmxlJ10pO1xuXG5jb25zdCBmaWVsZFJvb3QgPSAoZmllbGQ6IHN0cmluZyk6IHN0cmluZyA9PiBmaWVsZC5zcGxpdCgvWy5bXS8pWzBdID8/IGZpZWxkO1xuXG50eXBlIENvbXBsaWFuY2VDbGllbnQgPSBQaWNrPFJldHVyblR5cGU8dHlwZW9mIGNyZWF0ZUNvbXBsaWFuY2VDbGllbnQ+LCAnZHJ5UnVuUGx1Z2luJz47XG5cbmxldCBjb21wbGlhbmNlQ2xpZW50OiBDb21wbGlhbmNlQ2xpZW50IHwgbnVsbCA9IG51bGw7XG5cbi8qKiBUZXN0IGhvb2s6IHJlcGxhY2UgdGhlIGNvbXBsaWFuY2UgY2xpZW50IHRoZSBhc3Nlc3NtZW50J3MgY29tcGxpYW5jZSBsYXllciBjYWxscy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRWdWxuUG9saWN5Q29tcGxpYW5jZUNsaWVudEZvclRlc3RzKGNsaWVudDogQ29tcGxpYW5jZUNsaWVudCB8IG51bGwpOiB2b2lkIHtcbiAgY29tcGxpYW5jZUNsaWVudCA9IGNsaWVudDtcbn1cblxuLyoqXG4gKiBUaGUgb3JnJ3MgcGx1Z2luIGNvbXBsaWFuY2UgcnVsZXMgb24gdGhlIHZ1bG5lcmFiaWxpdHkgYXR0cmlidXRlcywgZXZhbHVhdGVkXG4gKiBhZ2FpbnN0IHRoZSBSRVNPTFZFRCB2ZXJzaW9uIOKAlCB0aGUgb3JnJ3Mgb3duIHJvdywgaXRzIHBhcmVudCdzLCBhIHN5c3RlbVxuICogcGx1Z2luIG9yIGFuIGluc3RhbGxlZCBtYXJrZXRwbGFjZSB2ZXJzaW9uIGFsaWtlLiBBIEJMT0NLLW1vZGUgcnVsZSB0aGF0IGZhaWxzXG4gKiBpcyBhbiBgZXJyb3JgLCBhIFdBUk4tbW9kZSBvbmUgYSBgd2FybmluZ2A7IG5laXRoZXIgcmVmdXNlcyBhbnl0aGluZyBoZXJlXG4gKiAodnVsbmVyYWJpbGl0eSBzdGF0ZSBuZXZlciBzdG9wcyBhIHBpcGVsaW5lKS5cbiAqXG4gKiBPbmx5IHRoZSB2dWxuIC8gc2Nhbm5lZCBydWxlcyBjb3VudCBoZXJlOiB0aGUgcGx1Z2luJ3Mgb3RoZXIgcnVsZXMgKHRhZ3MsXG4gKiBzZWNyZXRzLCBjb21tYW5kcyDigKYpIGRlc2NyaWJlIGhvdyBhIHBsdWdpbiBpcyBBVVRIT1JFRCwgd2hpY2ggaXMgaXRzIG93bmVyJ3NcbiAqIGNvbmNlcm4gYXQgdXBsb2FkLCBub3QgdGhlIGNvbnN1bWVyJ3MgYXQgcmVzb2x1dGlvbiDigJQgYW5kIGEgc3lzdGVtIHBsdWdpbiB3b3VsZFxuICogb3RoZXJ3aXNlIGZhaWwgZXZlcnkgdGVuYW50J3MgYXV0aG9yaW5nIHJ1bGVzLlxuICovXG5hc3luYyBmdW5jdGlvbiBjb21wbGlhbmNlVnVsbldhcm5pbmdzKG9yZ0lkOiBzdHJpbmcsIHJlY29yZDogU2Nhbm5lZFJlY29yZCk6IFByb21pc2U8VnVsbldhcm5pbmdbXT4ge1xuICBpZiAoaXNTeXN0ZW1PcmdJZChvcmdJZCkgfHwgIWhhc0ltYWdlKHJlY29yZCkpIHJldHVybiBbXTtcbiAgY29uc3QgZmFjdHMgPSBkZXJpdmVQbHVnaW5JbWFnZUNvbXBsaWFuY2UocmVjb3JkLCBudWxsKS5hdHRyaWJ1dGVzO1xuICBjb25zdCBhdHRyaWJ1dGVzOiBQbHVnaW5Db21wbGlhbmNlQXR0cmlidXRlcyA9IHsgbmFtZTogcmVjb3JkLm5hbWUsIHZlcnNpb246IHJlY29yZC52ZXJzaW9uLCAuLi5mYWN0cyB9O1xuICB0cnkge1xuICAgIGNvbXBsaWFuY2VDbGllbnQgPz89IGNyZWF0ZUNvbXBsaWFuY2VDbGllbnQoKTtcbiAgICBjb25zdCBhdXRoID0gZ2V0U2VydmljZUF1dGhIZWFkZXIoeyBzZXJ2aWNlTmFtZTogJ3BsdWdpbicsIG9yZ0lkLCByb2xlOiAnbWVtYmVyJyB9KTtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjb21wbGlhbmNlQ2xpZW50LmRyeVJ1blBsdWdpbihvcmdJZCwgYXR0cmlidXRlcyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiwgYXV0aCk7XG4gICAgY29uc3QgcmVsZXZhbnQgPSAodjogQ29tcGxpYW5jZVZpb2xhdGlvbikgPT4gVlVMTl9SVUxFX0ZJRUxEUy5oYXMoZmllbGRSb290KHYuZmllbGQpKTtcbiAgICBjb25zdCBhcyA9IChtb2RlOiAnYmxvY2snIHwgJ3dhcm4nKSA9PiAodjogQ29tcGxpYW5jZVZpb2xhdGlvbik6IFZ1bG5XYXJuaW5nID0+ICh7XG4gICAgICBjb2RlOiAnQ09NUExJQU5DRV9WVUxOX1JVTEUnLFxuICAgICAgc2V2ZXJpdHk6IG1vZGUgPT09ICdibG9jaycgPyAnZXJyb3InIDogJ3dhcm5pbmcnLFxuICAgICAgbWVzc2FnZTogYCR7cmVjb3JkLm5hbWV9QCR7cmVjb3JkLnZlcnNpb259OiAke3YubWVzc2FnZX1gLFxuICAgICAgcnVsZUlkOiB2LnJ1bGVJZCxcbiAgICAgIHJ1bGVOYW1lOiB2LnJ1bGVOYW1lLFxuICAgICAgZmllbGQ6IHYuZmllbGQsXG4gICAgICBtb2RlLFxuICAgIH0pO1xuICAgIHJldHVybiBbLi4ucmVzdWx0LnZpb2xhdGlvbnMuZmlsdGVyKHJlbGV2YW50KS5tYXAoYXMoJ2Jsb2NrJykpLCAuLi5yZXN1bHQud2FybmluZ3MuZmlsdGVyKHJlbGV2YW50KS5tYXAoYXMoJ3dhcm4nKSldO1xuICB9IGNhdGNoIChlcnIpIHtcbiAgICByZXR1cm4gW3sgY29kZTogJ0NPTVBMSUFOQ0VfVU5BVkFJTEFCTEUnLCBzZXZlcml0eTogJ2luZm8nLCBtZXNzYWdlOiBgWW91ciBvcmdhbml6YXRpb24ncyBwbHVnaW4gdnVsbmVyYWJpbGl0eSBydWxlcyBjb3VsZCBub3QgYmUgY2hlY2tlZCBmb3IgJHtyZWNvcmQubmFtZX1AJHtyZWNvcmQudmVyc2lvbn0gKCR7ZXJyb3JNZXNzYWdlKGVycil9KS5gIH1dO1xuICB9XG59XG4iXX0=
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The AI provider + model catalog, as DATA ONLY.
|
|
3
|
+
*
|
|
4
|
+
* Dependency-free and env-free so the browser imports it directly
|
|
5
|
+
* (`@pipeline-builder/api-core/ai-catalog`) — the frontend's model picker and the
|
|
6
|
+
* backend's provider registry read the one list, instead of the frontend keeping a
|
|
7
|
+
* hand-maintained mirror that drifted every time a model shipped. Anything that
|
|
8
|
+
* reads the environment (the OpenAI-compatible endpoint, provider key env vars)
|
|
9
|
+
* stays in `constants/ai-providers.ts`, which re-exports this.
|
|
10
|
+
*/
|
|
11
|
+
/** Metadata for a single AI model. */
|
|
12
|
+
export interface AIModelInfo {
|
|
13
|
+
/** Model identifier used in API calls (e.g. "claude-sonnet-5-5"). */
|
|
14
|
+
id: string;
|
|
15
|
+
/** Human-readable display name (e.g. "Claude Sonnet 5.5"). */
|
|
16
|
+
name: string;
|
|
17
|
+
}
|
|
18
|
+
/** Metadata for an AI provider with its available models. */
|
|
19
|
+
export interface AIProviderInfo {
|
|
20
|
+
/** Provider identifier (e.g. "anthropic", "openai", "google"). */
|
|
21
|
+
id: string;
|
|
22
|
+
/** Human-readable display name (e.g. "Anthropic"). */
|
|
23
|
+
name: string;
|
|
24
|
+
/** Models available for this provider. */
|
|
25
|
+
models: AIModelInfo[];
|
|
26
|
+
/**
|
|
27
|
+
* The provider authenticates with the DEPLOYMENT's own credentials (an IAM
|
|
28
|
+
* role), not an API key — so there is no key for an organization to bring.
|
|
29
|
+
* Absent = key-based.
|
|
30
|
+
*
|
|
31
|
+
* This is the ONE place that fact is recorded. Everything that asks "can an
|
|
32
|
+
* org hold its own key for this provider?" reads {@link AI_KEY_PROVIDER_IDS}
|
|
33
|
+
* or {@link isKeylessProviderId}: the settings picker that offers the slot,
|
|
34
|
+
* the platform that stores and re-encrypts it, the internal route that serves
|
|
35
|
+
* it, and the model selection that spends it. They disagreed once — the
|
|
36
|
+
* picker offered Amazon Bedrock, the platform encrypted the key and reported
|
|
37
|
+
* it `configured`, and no AI call could ever use it.
|
|
38
|
+
*/
|
|
39
|
+
keyless?: true;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Standard AI provider catalog — single source of truth for all supported
|
|
43
|
+
* providers and their models. The FIRST model of a provider is its default
|
|
44
|
+
* (what a provider-only request resolves to), so order matters.
|
|
45
|
+
*/
|
|
46
|
+
export declare const AI_PROVIDER_CATALOG: Record<string, AIProviderInfo>;
|
|
47
|
+
/**
|
|
48
|
+
* Provider ids an organization CAN hold its own API key for — the catalog minus
|
|
49
|
+
* the keyless providers ({@link AIProviderInfo.keyless}).
|
|
50
|
+
*
|
|
51
|
+
* The single list behind every org-key surface: the settings picker offers these
|
|
52
|
+
* slots, the platform stores and re-encrypts these fields, `GET
|
|
53
|
+
* /internal/ai/keys/:orgId/:provider` serves only these, and org-aware model
|
|
54
|
+
* selection spends only these. A provider absent here has no org key by
|
|
55
|
+
* construction, so no caller needs its own exclusion.
|
|
56
|
+
*/
|
|
57
|
+
export declare const AI_KEY_PROVIDER_IDS: readonly string[];
|
|
58
|
+
/** True when the provider authenticates with the deployment's own credentials rather than a key. */
|
|
59
|
+
export declare function isKeylessProviderId(providerId: string): boolean;
|
|
60
|
+
/** Display names by provider id — the catalog's names, for UI surfaces that list providers. */
|
|
61
|
+
export declare const AI_PROVIDER_NAMES: Record<string, string>;
|
|
62
|
+
/** Model lists by provider id — the catalog's models, for UI surfaces that need only those. */
|
|
63
|
+
export declare const AI_PROVIDER_MODELS: Record<string, AIModelInfo[]>;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Standard AI provider catalog — single source of truth for all supported
|
|
5
|
+
* providers and their models. The FIRST model of a provider is its default
|
|
6
|
+
* (what a provider-only request resolves to), so order matters.
|
|
7
|
+
*/
|
|
8
|
+
export const AI_PROVIDER_CATALOG = {
|
|
9
|
+
'anthropic': {
|
|
10
|
+
id: 'anthropic',
|
|
11
|
+
name: 'Anthropic',
|
|
12
|
+
models: [
|
|
13
|
+
{ id: 'claude-sonnet-5-5', name: 'Claude Sonnet 5.5' },
|
|
14
|
+
{ id: 'claude-opus-5-5', name: 'Claude Opus 5.5' },
|
|
15
|
+
{ id: 'claude-fable-5-1', name: 'Claude Fable 5.1' },
|
|
16
|
+
{ id: 'claude-haiku-4-5-20251001', name: 'Claude Haiku 4.5' },
|
|
17
|
+
],
|
|
18
|
+
},
|
|
19
|
+
'openai': {
|
|
20
|
+
id: 'openai',
|
|
21
|
+
name: 'OpenAI',
|
|
22
|
+
models: [
|
|
23
|
+
{ id: 'gpt-5.6-sol', name: 'GPT-5.6 Sol' },
|
|
24
|
+
{ id: 'gpt-5.6-terra', name: 'GPT-5.6 Terra' },
|
|
25
|
+
{ id: 'gpt-5.6-luna', name: 'GPT-5.6 Luna' },
|
|
26
|
+
],
|
|
27
|
+
},
|
|
28
|
+
'google': {
|
|
29
|
+
id: 'google',
|
|
30
|
+
name: 'Google',
|
|
31
|
+
models: [
|
|
32
|
+
{ id: 'gemini-3.7-flash', name: 'Gemini 3.7 Flash' },
|
|
33
|
+
{ id: 'gemini-3.1-pro-preview', name: 'Gemini 3.1 Pro' },
|
|
34
|
+
],
|
|
35
|
+
},
|
|
36
|
+
'xai': {
|
|
37
|
+
id: 'xai',
|
|
38
|
+
name: 'xAI (Grok)',
|
|
39
|
+
models: [
|
|
40
|
+
{ id: 'grok-4.6', name: 'Grok 4.6' },
|
|
41
|
+
{ id: 'grok-4.5', name: 'Grok 4.5' },
|
|
42
|
+
{ id: 'grok-4.3', name: 'Grok 4.3' },
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
'amazon-bedrock': {
|
|
46
|
+
id: 'amazon-bedrock',
|
|
47
|
+
name: 'Amazon Bedrock',
|
|
48
|
+
// Authenticated by the deployment's IAM role, never an org-supplied key.
|
|
49
|
+
keyless: true,
|
|
50
|
+
// Bedrock ids are region-scoped cross-region inference profiles; the `us.`
|
|
51
|
+
// prefix targets US regions — swap the prefix (eu./apac./…) to match your
|
|
52
|
+
// deploy region, and confirm availability in the Bedrock console.
|
|
53
|
+
models: [
|
|
54
|
+
{ id: 'us.anthropic.claude-sonnet-5-5', name: 'Claude Sonnet 5.5' },
|
|
55
|
+
{ id: 'us.anthropic.claude-opus-5-5', name: 'Claude Opus 5.5' },
|
|
56
|
+
{ id: 'us.anthropic.claude-haiku-4-5-20251001-v1:0', name: 'Claude Haiku 4.5' },
|
|
57
|
+
{ id: 'us.amazon.nova-pro-v1:0', name: 'Amazon Nova Pro' },
|
|
58
|
+
],
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Provider ids an organization CAN hold its own API key for — the catalog minus
|
|
63
|
+
* the keyless providers ({@link AIProviderInfo.keyless}).
|
|
64
|
+
*
|
|
65
|
+
* The single list behind every org-key surface: the settings picker offers these
|
|
66
|
+
* slots, the platform stores and re-encrypts these fields, `GET
|
|
67
|
+
* /internal/ai/keys/:orgId/:provider` serves only these, and org-aware model
|
|
68
|
+
* selection spends only these. A provider absent here has no org key by
|
|
69
|
+
* construction, so no caller needs its own exclusion.
|
|
70
|
+
*/
|
|
71
|
+
export const AI_KEY_PROVIDER_IDS = Object.values(AI_PROVIDER_CATALOG)
|
|
72
|
+
.filter((p) => !p.keyless)
|
|
73
|
+
.map((p) => p.id);
|
|
74
|
+
/** True when the provider authenticates with the deployment's own credentials rather than a key. */
|
|
75
|
+
export function isKeylessProviderId(providerId) {
|
|
76
|
+
return AI_PROVIDER_CATALOG[providerId]?.keyless === true;
|
|
77
|
+
}
|
|
78
|
+
/** Display names by provider id — the catalog's names, for UI surfaces that list providers. */
|
|
79
|
+
export const AI_PROVIDER_NAMES = Object.fromEntries(Object.values(AI_PROVIDER_CATALOG).map((p) => [p.id, p.name]));
|
|
80
|
+
/** Model lists by provider id — the catalog's models, for UI surfaces that need only those. */
|
|
81
|
+
export const AI_PROVIDER_MODELS = Object.fromEntries(Object.values(AI_PROVIDER_CATALOG).map((p) => [p.id, p.models]));
|
|
82
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWktY2F0YWxvZy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90eXBlcy9haS1jYXRhbG9nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLCtDQUErQztBQUMvQyxzQ0FBc0M7QUE2Q3RDOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBbUM7SUFDakUsV0FBVyxFQUFFO1FBQ1gsRUFBRSxFQUFFLFdBQVc7UUFDZixJQUFJLEVBQUUsV0FBVztRQUNqQixNQUFNLEVBQUU7WUFDTixFQUFFLEVBQUUsRUFBRSxtQkFBbUIsRUFBRSxJQUFJLEVBQUUsbUJBQW1CLEVBQUU7WUFDdEQsRUFBRSxFQUFFLEVBQUUsaUJBQWlCLEVBQUUsSUFBSSxFQUFFLGlCQUFpQixFQUFFO1lBQ2xELEVBQUUsRUFBRSxFQUFFLGtCQUFrQixFQUFFLElBQUksRUFBRSxrQkFBa0IsRUFBRTtZQUNwRCxFQUFFLEVBQUUsRUFBRSwyQkFBMkIsRUFBRSxJQUFJLEVBQUUsa0JBQWtCLEVBQUU7U0FDOUQ7S0FDRjtJQUNELFFBQVEsRUFBRTtRQUNSLEVBQUUsRUFBRSxRQUFRO1FBQ1osSUFBSSxFQUFFLFFBQVE7UUFDZCxNQUFNLEVBQUU7WUFDTixFQUFFLEVBQUUsRUFBRSxhQUFhLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRTtZQUMxQyxFQUFFLEVBQUUsRUFBRSxlQUFlLEVBQUUsSUFBSSxFQUFFLGVBQWUsRUFBRTtZQUM5QyxFQUFFLEVBQUUsRUFBRSxjQUFjLEVBQUUsSUFBSSxFQUFFLGNBQWMsRUFBRTtTQUM3QztLQUNGO0lBQ0QsUUFBUSxFQUFFO1FBQ1IsRUFBRSxFQUFFLFFBQVE7UUFDWixJQUFJLEVBQUUsUUFBUTtRQUNkLE1BQU0sRUFBRTtZQUNOLEVBQUUsRUFBRSxFQUFFLGtCQUFrQixFQUFFLElBQUksRUFBRSxrQkFBa0IsRUFBRTtZQUNwRCxFQUFFLEVBQUUsRUFBRSx3QkFBd0IsRUFBRSxJQUFJLEVBQUUsZ0JBQWdCLEVBQUU7U0FDekQ7S0FDRjtJQUNELEtBQUssRUFBRTtRQUNMLEVBQUUsRUFBRSxLQUFLO1FBQ1QsSUFBSSxFQUFFLFlBQVk7UUFDbEIsTUFBTSxFQUFFO1lBQ04sRUFBRSxFQUFFLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUU7WUFDcEMsRUFBRSxFQUFFLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUU7WUFDcEMsRUFBRSxFQUFFLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUU7U0FDckM7S0FDRjtJQUNELGdCQUFnQixFQUFFO1FBQ2hCLEVBQUUsRUFBRSxnQkFBZ0I7UUFDcEIsSUFBSSxFQUFFLGdCQUFnQjtRQUN0Qix5RUFBeUU7UUFDekUsT0FBTyxFQUFFLElBQUk7UUFDYiwyRUFBMkU7UUFDM0UsMEVBQTBFO1FBQzFFLGtFQUFrRTtRQUNsRSxNQUFNLEVBQUU7WUFDTixFQUFFLEVBQUUsRUFBRSxnQ0FBZ0MsRUFBRSxJQUFJLEVBQUUsbUJBQW1CLEVBQUU7WUFDbkUsRUFBRSxFQUFFLEVBQUUsOEJBQThCLEVBQUUsSUFBSSxFQUFFLGlCQUFpQixFQUFFO1lBQy9ELEVBQUUsRUFBRSxFQUFFLDZDQUE2QyxFQUFFLElBQUksRUFBRSxrQkFBa0IsRUFBRTtZQUMvRSxFQUFFLEVBQUUsRUFBRSx5QkFBeUIsRUFBRSxJQUFJLEVBQUUsaUJBQWlCLEVBQUU7U0FDM0Q7S0FDRjtDQUNGLENBQUM7QUFFRjs7Ozs7Ozs7O0dBU0c7QUFDSCxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBc0IsTUFBTSxDQUFDLE1BQU0sQ0FBQyxtQkFBbUIsQ0FBQztLQUNyRixNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztLQUN6QixHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQztBQUVwQixvR0FBb0c7QUFDcEcsTUFBTSxVQUFVLG1CQUFtQixDQUFDLFVBQWtCO0lBQ3BELE9BQU8sbUJBQW1CLENBQUMsVUFBVSxDQUFDLEVBQUUsT0FBTyxLQUFLLElBQUksQ0FBQztBQUMzRCxDQUFDO0FBRUQsK0ZBQStGO0FBQy9GLE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUEyQixNQUFNLENBQUMsV0FBVyxDQUN6RSxNQUFNLENBQUMsTUFBTSxDQUFDLG1CQUFtQixDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQzlELENBQUM7QUFFRiwrRkFBK0Y7QUFDL0YsTUFBTSxDQUFDLE1BQU0sa0JBQWtCLEdBQWtDLE1BQU0sQ0FBQyxXQUFXLENBQ2pGLE1BQU0sQ0FBQyxNQUFNLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FDaEUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG4vKipcbiAqIFRoZSBBSSBwcm92aWRlciArIG1vZGVsIGNhdGFsb2csIGFzIERBVEEgT05MWS5cbiAqXG4gKiBEZXBlbmRlbmN5LWZyZWUgYW5kIGVudi1mcmVlIHNvIHRoZSBicm93c2VyIGltcG9ydHMgaXQgZGlyZWN0bHlcbiAqIChgQHBpcGVsaW5lLWJ1aWxkZXIvYXBpLWNvcmUvYWktY2F0YWxvZ2ApIOKAlCB0aGUgZnJvbnRlbmQncyBtb2RlbCBwaWNrZXIgYW5kIHRoZVxuICogYmFja2VuZCdzIHByb3ZpZGVyIHJlZ2lzdHJ5IHJlYWQgdGhlIG9uZSBsaXN0LCBpbnN0ZWFkIG9mIHRoZSBmcm9udGVuZCBrZWVwaW5nIGFcbiAqIGhhbmQtbWFpbnRhaW5lZCBtaXJyb3IgdGhhdCBkcmlmdGVkIGV2ZXJ5IHRpbWUgYSBtb2RlbCBzaGlwcGVkLiBBbnl0aGluZyB0aGF0XG4gKiByZWFkcyB0aGUgZW52aXJvbm1lbnQgKHRoZSBPcGVuQUktY29tcGF0aWJsZSBlbmRwb2ludCwgcHJvdmlkZXIga2V5IGVudiB2YXJzKVxuICogc3RheXMgaW4gYGNvbnN0YW50cy9haS1wcm92aWRlcnMudHNgLCB3aGljaCByZS1leHBvcnRzIHRoaXMuXG4gKi9cblxuLyoqIE1ldGFkYXRhIGZvciBhIHNpbmdsZSBBSSBtb2RlbC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgQUlNb2RlbEluZm8ge1xuICAvKiogTW9kZWwgaWRlbnRpZmllciB1c2VkIGluIEFQSSBjYWxscyAoZS5nLiBcImNsYXVkZS1zb25uZXQtNS01XCIpLiAqL1xuICBpZDogc3RyaW5nO1xuICAvKiogSHVtYW4tcmVhZGFibGUgZGlzcGxheSBuYW1lIChlLmcuIFwiQ2xhdWRlIFNvbm5ldCA1LjVcIikuICovXG4gIG5hbWU6IHN0cmluZztcbn1cblxuLyoqIE1ldGFkYXRhIGZvciBhbiBBSSBwcm92aWRlciB3aXRoIGl0cyBhdmFpbGFibGUgbW9kZWxzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBBSVByb3ZpZGVySW5mbyB7XG4gIC8qKiBQcm92aWRlciBpZGVudGlmaWVyIChlLmcuIFwiYW50aHJvcGljXCIsIFwib3BlbmFpXCIsIFwiZ29vZ2xlXCIpLiAqL1xuICBpZDogc3RyaW5nO1xuICAvKiogSHVtYW4tcmVhZGFibGUgZGlzcGxheSBuYW1lIChlLmcuIFwiQW50aHJvcGljXCIpLiAqL1xuICBuYW1lOiBzdHJpbmc7XG4gIC8qKiBNb2RlbHMgYXZhaWxhYmxlIGZvciB0aGlzIHByb3ZpZGVyLiAqL1xuICBtb2RlbHM6IEFJTW9kZWxJbmZvW107XG4gIC8qKlxuICAgKiBUaGUgcHJvdmlkZXIgYXV0aGVudGljYXRlcyB3aXRoIHRoZSBERVBMT1lNRU5UJ3Mgb3duIGNyZWRlbnRpYWxzIChhbiBJQU1cbiAgICogcm9sZSksIG5vdCBhbiBBUEkga2V5IOKAlCBzbyB0aGVyZSBpcyBubyBrZXkgZm9yIGFuIG9yZ2FuaXphdGlvbiB0byBicmluZy5cbiAgICogQWJzZW50ID0ga2V5LWJhc2VkLlxuICAgKlxuICAgKiBUaGlzIGlzIHRoZSBPTkUgcGxhY2UgdGhhdCBmYWN0IGlzIHJlY29yZGVkLiBFdmVyeXRoaW5nIHRoYXQgYXNrcyBcImNhbiBhblxuICAgKiBvcmcgaG9sZCBpdHMgb3duIGtleSBmb3IgdGhpcyBwcm92aWRlcj9cIiByZWFkcyB7QGxpbmsgQUlfS0VZX1BST1ZJREVSX0lEU31cbiAgICogb3Ige0BsaW5rIGlzS2V5bGVzc1Byb3ZpZGVySWR9OiB0aGUgc2V0dGluZ3MgcGlja2VyIHRoYXQgb2ZmZXJzIHRoZSBzbG90LFxuICAgKiB0aGUgcGxhdGZvcm0gdGhhdCBzdG9yZXMgYW5kIHJlLWVuY3J5cHRzIGl0LCB0aGUgaW50ZXJuYWwgcm91dGUgdGhhdCBzZXJ2ZXNcbiAgICogaXQsIGFuZCB0aGUgbW9kZWwgc2VsZWN0aW9uIHRoYXQgc3BlbmRzIGl0LiBUaGV5IGRpc2FncmVlZCBvbmNlIOKAlCB0aGVcbiAgICogcGlja2VyIG9mZmVyZWQgQW1hem9uIEJlZHJvY2ssIHRoZSBwbGF0Zm9ybSBlbmNyeXB0ZWQgdGhlIGtleSBhbmQgcmVwb3J0ZWRcbiAgICogaXQgYGNvbmZpZ3VyZWRgLCBhbmQgbm8gQUkgY2FsbCBjb3VsZCBldmVyIHVzZSBpdC5cbiAgICovXG4gIGtleWxlc3M/OiB0cnVlO1xufVxuXG4vKipcbiAqIFN0YW5kYXJkIEFJIHByb3ZpZGVyIGNhdGFsb2cg4oCUIHNpbmdsZSBzb3VyY2Ugb2YgdHJ1dGggZm9yIGFsbCBzdXBwb3J0ZWRcbiAqIHByb3ZpZGVycyBhbmQgdGhlaXIgbW9kZWxzLiBUaGUgRklSU1QgbW9kZWwgb2YgYSBwcm92aWRlciBpcyBpdHMgZGVmYXVsdFxuICogKHdoYXQgYSBwcm92aWRlci1vbmx5IHJlcXVlc3QgcmVzb2x2ZXMgdG8pLCBzbyBvcmRlciBtYXR0ZXJzLlxuICovXG5leHBvcnQgY29uc3QgQUlfUFJPVklERVJfQ0FUQUxPRzogUmVjb3JkPHN0cmluZywgQUlQcm92aWRlckluZm8+ID0ge1xuICAnYW50aHJvcGljJzoge1xuICAgIGlkOiAnYW50aHJvcGljJyxcbiAgICBuYW1lOiAnQW50aHJvcGljJyxcbiAgICBtb2RlbHM6IFtcbiAgICAgIHsgaWQ6ICdjbGF1ZGUtc29ubmV0LTUtNScsIG5hbWU6ICdDbGF1ZGUgU29ubmV0IDUuNScgfSxcbiAgICAgIHsgaWQ6ICdjbGF1ZGUtb3B1cy01LTUnLCBuYW1lOiAnQ2xhdWRlIE9wdXMgNS41JyB9LFxuICAgICAgeyBpZDogJ2NsYXVkZS1mYWJsZS01LTEnLCBuYW1lOiAnQ2xhdWRlIEZhYmxlIDUuMScgfSxcbiAgICAgIHsgaWQ6ICdjbGF1ZGUtaGFpa3UtNC01LTIwMjUxMDAxJywgbmFtZTogJ0NsYXVkZSBIYWlrdSA0LjUnIH0sXG4gICAgXSxcbiAgfSxcbiAgJ29wZW5haSc6IHtcbiAgICBpZDogJ29wZW5haScsXG4gICAgbmFtZTogJ09wZW5BSScsXG4gICAgbW9kZWxzOiBbXG4gICAgICB7IGlkOiAnZ3B0LTUuNi1zb2wnLCBuYW1lOiAnR1BULTUuNiBTb2wnIH0sXG4gICAgICB7IGlkOiAnZ3B0LTUuNi10ZXJyYScsIG5hbWU6ICdHUFQtNS42IFRlcnJhJyB9LFxuICAgICAgeyBpZDogJ2dwdC01LjYtbHVuYScsIG5hbWU6ICdHUFQtNS42IEx1bmEnIH0sXG4gICAgXSxcbiAgfSxcbiAgJ2dvb2dsZSc6IHtcbiAgICBpZDogJ2dvb2dsZScsXG4gICAgbmFtZTogJ0dvb2dsZScsXG4gICAgbW9kZWxzOiBbXG4gICAgICB7IGlkOiAnZ2VtaW5pLTMuNy1mbGFzaCcsIG5hbWU6ICdHZW1pbmkgMy43IEZsYXNoJyB9LFxuICAgICAgeyBpZDogJ2dlbWluaS0zLjEtcHJvLXByZXZpZXcnLCBuYW1lOiAnR2VtaW5pIDMuMSBQcm8nIH0sXG4gICAgXSxcbiAgfSxcbiAgJ3hhaSc6IHtcbiAgICBpZDogJ3hhaScsXG4gICAgbmFtZTogJ3hBSSAoR3JvayknLFxuICAgIG1vZGVsczogW1xuICAgICAgeyBpZDogJ2dyb2stNC42JywgbmFtZTogJ0dyb2sgNC42JyB9LFxuICAgICAgeyBpZDogJ2dyb2stNC41JywgbmFtZTogJ0dyb2sgNC41JyB9LFxuICAgICAgeyBpZDogJ2dyb2stNC4zJywgbmFtZTogJ0dyb2sgNC4zJyB9LFxuICAgIF0sXG4gIH0sXG4gICdhbWF6b24tYmVkcm9jayc6IHtcbiAgICBpZDogJ2FtYXpvbi1iZWRyb2NrJyxcbiAgICBuYW1lOiAnQW1hem9uIEJlZHJvY2snLFxuICAgIC8vIEF1dGhlbnRpY2F0ZWQgYnkgdGhlIGRlcGxveW1lbnQncyBJQU0gcm9sZSwgbmV2ZXIgYW4gb3JnLXN1cHBsaWVkIGtleS5cbiAgICBrZXlsZXNzOiB0cnVlLFxuICAgIC8vIEJlZHJvY2sgaWRzIGFyZSByZWdpb24tc2NvcGVkIGNyb3NzLXJlZ2lvbiBpbmZlcmVuY2UgcHJvZmlsZXM7IHRoZSBgdXMuYFxuICAgIC8vIHByZWZpeCB0YXJnZXRzIFVTIHJlZ2lvbnMg4oCUIHN3YXAgdGhlIHByZWZpeCAoZXUuL2FwYWMuL+KApikgdG8gbWF0Y2ggeW91clxuICAgIC8vIGRlcGxveSByZWdpb24sIGFuZCBjb25maXJtIGF2YWlsYWJpbGl0eSBpbiB0aGUgQmVkcm9jayBjb25zb2xlLlxuICAgIG1vZGVsczogW1xuICAgICAgeyBpZDogJ3VzLmFudGhyb3BpYy5jbGF1ZGUtc29ubmV0LTUtNScsIG5hbWU6ICdDbGF1ZGUgU29ubmV0IDUuNScgfSxcbiAgICAgIHsgaWQ6ICd1cy5hbnRocm9waWMuY2xhdWRlLW9wdXMtNS01JywgbmFtZTogJ0NsYXVkZSBPcHVzIDUuNScgfSxcbiAgICAgIHsgaWQ6ICd1cy5hbnRocm9waWMuY2xhdWRlLWhhaWt1LTQtNS0yMDI1MTAwMS12MTowJywgbmFtZTogJ0NsYXVkZSBIYWlrdSA0LjUnIH0sXG4gICAgICB7IGlkOiAndXMuYW1hem9uLm5vdmEtcHJvLXYxOjAnLCBuYW1lOiAnQW1hem9uIE5vdmEgUHJvJyB9LFxuICAgIF0sXG4gIH0sXG59O1xuXG4vKipcbiAqIFByb3ZpZGVyIGlkcyBhbiBvcmdhbml6YXRpb24gQ0FOIGhvbGQgaXRzIG93biBBUEkga2V5IGZvciDigJQgdGhlIGNhdGFsb2cgbWludXNcbiAqIHRoZSBrZXlsZXNzIHByb3ZpZGVycyAoe0BsaW5rIEFJUHJvdmlkZXJJbmZvLmtleWxlc3N9KS5cbiAqXG4gKiBUaGUgc2luZ2xlIGxpc3QgYmVoaW5kIGV2ZXJ5IG9yZy1rZXkgc3VyZmFjZTogdGhlIHNldHRpbmdzIHBpY2tlciBvZmZlcnMgdGhlc2VcbiAqIHNsb3RzLCB0aGUgcGxhdGZvcm0gc3RvcmVzIGFuZCByZS1lbmNyeXB0cyB0aGVzZSBmaWVsZHMsIGBHRVRcbiAqIC9pbnRlcm5hbC9haS9rZXlzLzpvcmdJZC86cHJvdmlkZXJgIHNlcnZlcyBvbmx5IHRoZXNlLCBhbmQgb3JnLWF3YXJlIG1vZGVsXG4gKiBzZWxlY3Rpb24gc3BlbmRzIG9ubHkgdGhlc2UuIEEgcHJvdmlkZXIgYWJzZW50IGhlcmUgaGFzIG5vIG9yZyBrZXkgYnlcbiAqIGNvbnN0cnVjdGlvbiwgc28gbm8gY2FsbGVyIG5lZWRzIGl0cyBvd24gZXhjbHVzaW9uLlxuICovXG5leHBvcnQgY29uc3QgQUlfS0VZX1BST1ZJREVSX0lEUzogcmVhZG9ubHkgc3RyaW5nW10gPSBPYmplY3QudmFsdWVzKEFJX1BST1ZJREVSX0NBVEFMT0cpXG4gIC5maWx0ZXIoKHApID0+ICFwLmtleWxlc3MpXG4gIC5tYXAoKHApID0+IHAuaWQpO1xuXG4vKiogVHJ1ZSB3aGVuIHRoZSBwcm92aWRlciBhdXRoZW50aWNhdGVzIHdpdGggdGhlIGRlcGxveW1lbnQncyBvd24gY3JlZGVudGlhbHMgcmF0aGVyIHRoYW4gYSBrZXkuICovXG5leHBvcnQgZnVuY3Rpb24gaXNLZXlsZXNzUHJvdmlkZXJJZChwcm92aWRlcklkOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIEFJX1BST1ZJREVSX0NBVEFMT0dbcHJvdmlkZXJJZF0/LmtleWxlc3MgPT09IHRydWU7XG59XG5cbi8qKiBEaXNwbGF5IG5hbWVzIGJ5IHByb3ZpZGVyIGlkIOKAlCB0aGUgY2F0YWxvZydzIG5hbWVzLCBmb3IgVUkgc3VyZmFjZXMgdGhhdCBsaXN0IHByb3ZpZGVycy4gKi9cbmV4cG9ydCBjb25zdCBBSV9QUk9WSURFUl9OQU1FUzogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IE9iamVjdC5mcm9tRW50cmllcyhcbiAgT2JqZWN0LnZhbHVlcyhBSV9QUk9WSURFUl9DQVRBTE9HKS5tYXAoKHApID0+IFtwLmlkLCBwLm5hbWVdKSxcbik7XG5cbi8qKiBNb2RlbCBsaXN0cyBieSBwcm92aWRlciBpZCDigJQgdGhlIGNhdGFsb2cncyBtb2RlbHMsIGZvciBVSSBzdXJmYWNlcyB0aGF0IG5lZWQgb25seSB0aG9zZS4gKi9cbmV4cG9ydCBjb25zdCBBSV9QUk9WSURFUl9NT0RFTFM6IFJlY29yZDxzdHJpbmcsIEFJTW9kZWxJbmZvW10+ID0gT2JqZWN0LmZyb21FbnRyaWVzKFxuICBPYmplY3QudmFsdWVzKEFJX1BST1ZJREVSX0NBVEFMT0cpLm1hcCgocCkgPT4gW3AuaWQsIHAubW9kZWxzXSksXG4pO1xuIl19
|