@xpr-agents/sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +165 -0
- package/dist/AgentRegistry.d.ts +182 -0
- package/dist/AgentRegistry.js +892 -0
- package/dist/EscrowRegistry.d.ts +253 -0
- package/dist/EscrowRegistry.js +731 -0
- package/dist/FeedbackRegistry.d.ts +83 -0
- package/dist/FeedbackRegistry.js +424 -0
- package/dist/ValidationRegistry.d.ts +115 -0
- package/dist/ValidationRegistry.js +638 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +59 -0
- package/dist/types.d.ts +345 -0
- package/dist/types.js +4 -0
- package/dist/utils.d.ts +79 -0
- package/dist/utils.js +235 -0
- package/package.json +65 -0
|
@@ -0,0 +1,892 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AgentRegistry = void 0;
|
|
4
|
+
const utils_1 = require("./utils");
|
|
5
|
+
const DEFAULT_CONTRACT = 'agentcore';
|
|
6
|
+
// Valid protocols for agent endpoints
|
|
7
|
+
const VALID_PROTOCOLS = ['http', 'https', 'grpc', 'websocket', 'mqtt', 'wss'];
|
|
8
|
+
// Valid endpoint URL prefixes
|
|
9
|
+
const VALID_ENDPOINT_PREFIXES = ['http://', 'https://', 'grpc://', 'wss://'];
|
|
10
|
+
/**
|
|
11
|
+
* Validates agent registration/update data before sending to the blockchain.
|
|
12
|
+
* Throws descriptive errors for invalid input.
|
|
13
|
+
*
|
|
14
|
+
* CRITICAL FIX: Validates TRIMMED length to prevent whitespace padding bypass.
|
|
15
|
+
*/
|
|
16
|
+
function validateAgentData(data) {
|
|
17
|
+
// Validate name: 1-64 characters after trimming, non-empty
|
|
18
|
+
if (data.name !== undefined) {
|
|
19
|
+
if (typeof data.name !== 'string') {
|
|
20
|
+
throw new Error('Name must be a string');
|
|
21
|
+
}
|
|
22
|
+
const trimmedName = data.name.trim();
|
|
23
|
+
// CRITICAL FIX: Check trimmed length to prevent whitespace padding bypass
|
|
24
|
+
if (trimmedName.length < 1 || trimmedName.length > 64) {
|
|
25
|
+
throw new Error('Name must be 1-64 characters (after trimming whitespace)');
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// Validate description: 1-256 characters after trimming, non-empty
|
|
29
|
+
if (data.description !== undefined) {
|
|
30
|
+
if (typeof data.description !== 'string') {
|
|
31
|
+
throw new Error('Description must be a string');
|
|
32
|
+
}
|
|
33
|
+
const trimmedDesc = data.description.trim();
|
|
34
|
+
// CRITICAL FIX: Check trimmed length to prevent whitespace padding bypass
|
|
35
|
+
if (trimmedDesc.length < 1 || trimmedDesc.length > 256) {
|
|
36
|
+
throw new Error('Description must be 1-256 characters (after trimming whitespace)');
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// Validate endpoint: 1-256 characters after trimming, must start with valid protocol prefix
|
|
40
|
+
if (data.endpoint !== undefined) {
|
|
41
|
+
if (typeof data.endpoint !== 'string') {
|
|
42
|
+
throw new Error('Endpoint must be a string');
|
|
43
|
+
}
|
|
44
|
+
const trimmedEndpoint = data.endpoint.trim();
|
|
45
|
+
// CRITICAL FIX: Check trimmed length to prevent whitespace padding bypass
|
|
46
|
+
if (trimmedEndpoint.length < 1 || trimmedEndpoint.length > 256) {
|
|
47
|
+
throw new Error('Endpoint must be 1-256 characters and start with http://, https://, grpc://, or wss://');
|
|
48
|
+
}
|
|
49
|
+
const hasValidPrefix = VALID_ENDPOINT_PREFIXES.some(prefix => trimmedEndpoint.toLowerCase().startsWith(prefix));
|
|
50
|
+
if (!hasValidPrefix) {
|
|
51
|
+
throw new Error('Endpoint must be 1-256 characters and start with http://, https://, grpc://, or wss://');
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
// Validate protocol: must be one of the valid protocols (case-insensitive)
|
|
55
|
+
if (data.protocol !== undefined) {
|
|
56
|
+
const normalizedProtocol = data.protocol.toLowerCase();
|
|
57
|
+
if (!VALID_PROTOCOLS.includes(normalizedProtocol)) {
|
|
58
|
+
throw new Error(`Protocol must be one of: ${VALID_PROTOCOLS.join(', ')}`);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
// Validate capabilities: array, when stringified must be <= 2048 characters
|
|
62
|
+
if (data.capabilities !== undefined) {
|
|
63
|
+
if (!Array.isArray(data.capabilities)) {
|
|
64
|
+
throw new Error('Capabilities must be an array with stringified length <= 2048 characters');
|
|
65
|
+
}
|
|
66
|
+
const stringified = JSON.stringify(data.capabilities);
|
|
67
|
+
if (stringified.length > 2048) {
|
|
68
|
+
throw new Error('Capabilities must be an array with stringified length <= 2048 characters');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
class AgentRegistry {
|
|
73
|
+
constructor(rpc, session, contract) {
|
|
74
|
+
this.rpc = rpc;
|
|
75
|
+
this.session = session || null;
|
|
76
|
+
this.contract = contract || DEFAULT_CONTRACT;
|
|
77
|
+
}
|
|
78
|
+
// ============== READ OPERATIONS ==============
|
|
79
|
+
/**
|
|
80
|
+
* Get a single agent by account name
|
|
81
|
+
*/
|
|
82
|
+
async getAgent(account) {
|
|
83
|
+
const result = await this.rpc.get_table_rows({
|
|
84
|
+
json: true,
|
|
85
|
+
code: this.contract,
|
|
86
|
+
scope: this.contract,
|
|
87
|
+
table: 'agents',
|
|
88
|
+
lower_bound: account,
|
|
89
|
+
upper_bound: account,
|
|
90
|
+
limit: 1,
|
|
91
|
+
});
|
|
92
|
+
if (result.rows.length === 0)
|
|
93
|
+
return null;
|
|
94
|
+
return this.parseAgent(result.rows[0]);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* List all agents with optional filters and pagination
|
|
98
|
+
* @returns PaginatedResult with items, hasMore flag, and nextCursor for pagination
|
|
99
|
+
*/
|
|
100
|
+
async listAgents(options = {}) {
|
|
101
|
+
const { limit = 100, cursor, active_only = true } = options;
|
|
102
|
+
const result = await this.rpc.get_table_rows({
|
|
103
|
+
json: true,
|
|
104
|
+
code: this.contract,
|
|
105
|
+
scope: this.contract,
|
|
106
|
+
table: 'agents',
|
|
107
|
+
lower_bound: cursor,
|
|
108
|
+
limit: limit + 1, // Fetch one extra to check if there are more
|
|
109
|
+
});
|
|
110
|
+
const hasMore = result.rows.length > limit;
|
|
111
|
+
const rows = hasMore ? result.rows.slice(0, limit) : result.rows;
|
|
112
|
+
let agents = rows.map((row) => this.parseAgent(row));
|
|
113
|
+
// Apply filters after fetching
|
|
114
|
+
if (active_only) {
|
|
115
|
+
agents = agents.filter((a) => a.active);
|
|
116
|
+
}
|
|
117
|
+
// Note: Agents use system staking (eosio::voters), not contract-managed staking
|
|
118
|
+
// To filter by stake, query system staking separately
|
|
119
|
+
// Get next cursor from the last row if there are more
|
|
120
|
+
const nextCursor = hasMore && rows.length > 0
|
|
121
|
+
? rows[rows.length - 1].account
|
|
122
|
+
: undefined;
|
|
123
|
+
return {
|
|
124
|
+
items: agents,
|
|
125
|
+
hasMore,
|
|
126
|
+
nextCursor,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Iterate through all agents with automatic pagination
|
|
131
|
+
*/
|
|
132
|
+
async *listAgentsIterator(options = {}) {
|
|
133
|
+
let cursor;
|
|
134
|
+
do {
|
|
135
|
+
const result = await this.listAgents({ ...options, cursor });
|
|
136
|
+
for (const agent of result.items) {
|
|
137
|
+
yield agent;
|
|
138
|
+
}
|
|
139
|
+
cursor = result.nextCursor;
|
|
140
|
+
} while (cursor);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Get a plugin by ID
|
|
144
|
+
*/
|
|
145
|
+
async getPlugin(id) {
|
|
146
|
+
const result = await this.rpc.get_table_rows({
|
|
147
|
+
json: true,
|
|
148
|
+
code: this.contract,
|
|
149
|
+
scope: this.contract,
|
|
150
|
+
table: 'plugins',
|
|
151
|
+
lower_bound: String(id),
|
|
152
|
+
upper_bound: String(id),
|
|
153
|
+
limit: 1,
|
|
154
|
+
});
|
|
155
|
+
if (result.rows.length === 0)
|
|
156
|
+
return null;
|
|
157
|
+
return this.parsePlugin(result.rows[0]);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* List all plugins
|
|
161
|
+
*/
|
|
162
|
+
async listPlugins(category) {
|
|
163
|
+
const result = await this.rpc.get_table_rows({
|
|
164
|
+
json: true,
|
|
165
|
+
code: this.contract,
|
|
166
|
+
scope: this.contract,
|
|
167
|
+
table: 'plugins',
|
|
168
|
+
limit: 1000,
|
|
169
|
+
});
|
|
170
|
+
let plugins = result.rows.map((row) => this.parsePlugin(row));
|
|
171
|
+
if (category) {
|
|
172
|
+
plugins = plugins.filter((p) => p.category === category);
|
|
173
|
+
}
|
|
174
|
+
return plugins;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Get plugins assigned to an agent
|
|
178
|
+
*/
|
|
179
|
+
async getAgentPlugins(account) {
|
|
180
|
+
const result = await this.rpc.get_table_rows({
|
|
181
|
+
json: true,
|
|
182
|
+
code: this.contract,
|
|
183
|
+
scope: this.contract,
|
|
184
|
+
table: 'agentplugs',
|
|
185
|
+
index_position: 2,
|
|
186
|
+
key_type: 'name',
|
|
187
|
+
lower_bound: account,
|
|
188
|
+
upper_bound: account,
|
|
189
|
+
limit: 100,
|
|
190
|
+
});
|
|
191
|
+
return result.rows.map((row) => this.parseAgentPlugin(row));
|
|
192
|
+
}
|
|
193
|
+
// Note: Agents use system staking via eosio::voters table, not contract-managed staking
|
|
194
|
+
// There is no unstakes table in agentcore - agents stake/unstake via system resources
|
|
195
|
+
// Use agentcore::getagentinfo action to query an agent's system stake
|
|
196
|
+
/**
|
|
197
|
+
* Get trust score for an agent (0-100)
|
|
198
|
+
* Combines KYC level, stake, reputation, and longevity
|
|
199
|
+
*/
|
|
200
|
+
async getTrustScore(account) {
|
|
201
|
+
// Get agent
|
|
202
|
+
const agent = await this.getAgent(account);
|
|
203
|
+
if (!agent)
|
|
204
|
+
return null;
|
|
205
|
+
// Get agent score from agentfeed
|
|
206
|
+
const feedContract = 'agentfeed'; // Default feed contract
|
|
207
|
+
const scoreResult = await this.rpc.get_table_rows({
|
|
208
|
+
json: true,
|
|
209
|
+
code: feedContract,
|
|
210
|
+
scope: feedContract,
|
|
211
|
+
table: 'agentscores',
|
|
212
|
+
lower_bound: account,
|
|
213
|
+
upper_bound: account,
|
|
214
|
+
limit: 1,
|
|
215
|
+
});
|
|
216
|
+
const agentScore = scoreResult.rows.length > 0
|
|
217
|
+
? {
|
|
218
|
+
agent: scoreResult.rows[0].agent,
|
|
219
|
+
total_score: (0, utils_1.safeParseInt)(scoreResult.rows[0].total_score),
|
|
220
|
+
total_weight: (0, utils_1.safeParseInt)(scoreResult.rows[0].total_weight),
|
|
221
|
+
feedback_count: (0, utils_1.safeParseInt)(scoreResult.rows[0].feedback_count),
|
|
222
|
+
avg_score: (0, utils_1.safeParseInt)(scoreResult.rows[0].avg_score),
|
|
223
|
+
last_updated: (0, utils_1.safeParseInt)(scoreResult.rows[0].last_updated),
|
|
224
|
+
}
|
|
225
|
+
: null;
|
|
226
|
+
// Get KYC level from the OWNER (not the agent)
|
|
227
|
+
// This is the key insight: agents inherit trust from their human sponsor
|
|
228
|
+
let kycLevel = 0;
|
|
229
|
+
if (agent.owner) {
|
|
230
|
+
const kycResult = await this.rpc.get_table_rows({
|
|
231
|
+
json: true,
|
|
232
|
+
code: 'eosio.proton',
|
|
233
|
+
scope: 'eosio.proton',
|
|
234
|
+
table: 'usersinfo',
|
|
235
|
+
lower_bound: agent.owner,
|
|
236
|
+
upper_bound: agent.owner,
|
|
237
|
+
limit: 1,
|
|
238
|
+
});
|
|
239
|
+
if (kycResult.rows.length > 0 && kycResult.rows[0].kyc?.length > 0) {
|
|
240
|
+
// Find the highest KYC level, handling various formats:
|
|
241
|
+
// - number: 3
|
|
242
|
+
// - string number: "3"
|
|
243
|
+
// - provider:level: "metallicus:3"
|
|
244
|
+
// - comma-separated multi-provider: "provA:3,provB:1"
|
|
245
|
+
const levels = [];
|
|
246
|
+
for (const k of kycResult.rows[0].kyc) {
|
|
247
|
+
if (typeof k.kyc_level === 'number') {
|
|
248
|
+
levels.push(k.kyc_level);
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
const levelStr = String(k.kyc_level);
|
|
252
|
+
// Handle comma-separated multi-provider strings (e.g., "provA:3,provB:1")
|
|
253
|
+
const providers = levelStr.split(',');
|
|
254
|
+
for (const provider of providers) {
|
|
255
|
+
const trimmed = provider.trim();
|
|
256
|
+
if (trimmed.includes(':')) {
|
|
257
|
+
// "provider:level" format - take the level part
|
|
258
|
+
const parts = trimmed.split(':');
|
|
259
|
+
const level = parseInt(parts[parts.length - 1], 10);
|
|
260
|
+
if (!isNaN(level))
|
|
261
|
+
levels.push(level);
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
// Plain number string
|
|
265
|
+
const level = parseInt(trimmed, 10);
|
|
266
|
+
if (!isNaN(level))
|
|
267
|
+
levels.push(level);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
// P2 FIX: Safe max - fallback to 0 if no valid levels found
|
|
273
|
+
// Math.max(...[]) returns -Infinity, which would poison trust scores
|
|
274
|
+
kycLevel = levels.length > 0 ? Math.max(...levels) : 0;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
// Get system stake from eosio::voters
|
|
278
|
+
const votersResult = await this.rpc.get_table_rows({
|
|
279
|
+
json: true,
|
|
280
|
+
code: 'eosio',
|
|
281
|
+
scope: 'eosio',
|
|
282
|
+
table: 'voters',
|
|
283
|
+
lower_bound: account,
|
|
284
|
+
upper_bound: account,
|
|
285
|
+
limit: 1,
|
|
286
|
+
});
|
|
287
|
+
let stakeAmount = 0;
|
|
288
|
+
if (votersResult.rows.length > 0 && votersResult.rows[0].staked) {
|
|
289
|
+
stakeAmount = (0, utils_1.safeParseInt)(votersResult.rows[0].staked);
|
|
290
|
+
}
|
|
291
|
+
return (0, utils_1.calculateTrustScore)(agent, agentScore, kycLevel, stakeAmount);
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Get contract configuration
|
|
295
|
+
*/
|
|
296
|
+
async getConfig() {
|
|
297
|
+
const result = await this.rpc.get_table_rows({
|
|
298
|
+
json: true,
|
|
299
|
+
code: this.contract,
|
|
300
|
+
scope: this.contract,
|
|
301
|
+
table: 'config',
|
|
302
|
+
limit: 1,
|
|
303
|
+
});
|
|
304
|
+
if (result.rows.length === 0) {
|
|
305
|
+
throw new Error('Contract not initialized');
|
|
306
|
+
}
|
|
307
|
+
const row = result.rows[0];
|
|
308
|
+
return {
|
|
309
|
+
owner: row.owner,
|
|
310
|
+
min_stake: (0, utils_1.safeParseInt)(row.min_stake),
|
|
311
|
+
registration_fee: (0, utils_1.safeParseInt)(row.registration_fee),
|
|
312
|
+
claim_fee: (0, utils_1.safeParseInt)(row.claim_fee),
|
|
313
|
+
feed_contract: row.feed_contract,
|
|
314
|
+
valid_contract: row.valid_contract,
|
|
315
|
+
escrow_contract: row.escrow_contract,
|
|
316
|
+
paused: row.paused === 1,
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
// ============== WRITE OPERATIONS ==============
|
|
320
|
+
/**
|
|
321
|
+
* Register a new agent
|
|
322
|
+
*/
|
|
323
|
+
async register(data) {
|
|
324
|
+
this.requireSession();
|
|
325
|
+
// Validate input before sending to blockchain
|
|
326
|
+
validateAgentData({
|
|
327
|
+
name: data.name,
|
|
328
|
+
description: data.description,
|
|
329
|
+
endpoint: data.endpoint,
|
|
330
|
+
protocol: data.protocol,
|
|
331
|
+
capabilities: data.capabilities,
|
|
332
|
+
});
|
|
333
|
+
return this.session.link.transact({
|
|
334
|
+
actions: [
|
|
335
|
+
{
|
|
336
|
+
account: this.contract,
|
|
337
|
+
name: 'register',
|
|
338
|
+
authorization: [
|
|
339
|
+
{
|
|
340
|
+
actor: this.session.auth.actor,
|
|
341
|
+
permission: this.session.auth.permission,
|
|
342
|
+
},
|
|
343
|
+
],
|
|
344
|
+
data: {
|
|
345
|
+
account: this.session.auth.actor,
|
|
346
|
+
name: data.name,
|
|
347
|
+
description: data.description,
|
|
348
|
+
endpoint: data.endpoint,
|
|
349
|
+
protocol: data.protocol,
|
|
350
|
+
capabilities: JSON.stringify(data.capabilities),
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
],
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Register a new agent with registration fee in one transaction.
|
|
358
|
+
* Sends the fee deposit and registers in a single tx.
|
|
359
|
+
*
|
|
360
|
+
* @param data - Agent registration data
|
|
361
|
+
* @param amount - The registration fee (e.g., "1.0000 XPR")
|
|
362
|
+
*/
|
|
363
|
+
async registerWithFee(data, amount) {
|
|
364
|
+
this.requireSession();
|
|
365
|
+
validateAgentData({
|
|
366
|
+
name: data.name,
|
|
367
|
+
description: data.description,
|
|
368
|
+
endpoint: data.endpoint,
|
|
369
|
+
protocol: data.protocol,
|
|
370
|
+
capabilities: data.capabilities,
|
|
371
|
+
});
|
|
372
|
+
const actor = this.session.auth.actor;
|
|
373
|
+
return this.session.link.transact({
|
|
374
|
+
actions: [
|
|
375
|
+
{
|
|
376
|
+
account: 'eosio.token',
|
|
377
|
+
name: 'transfer',
|
|
378
|
+
authorization: [{
|
|
379
|
+
actor,
|
|
380
|
+
permission: this.session.auth.permission,
|
|
381
|
+
}],
|
|
382
|
+
data: {
|
|
383
|
+
from: actor,
|
|
384
|
+
to: this.contract,
|
|
385
|
+
quantity: amount,
|
|
386
|
+
memo: `regfee:${actor}`,
|
|
387
|
+
},
|
|
388
|
+
},
|
|
389
|
+
{
|
|
390
|
+
account: this.contract,
|
|
391
|
+
name: 'register',
|
|
392
|
+
authorization: [{
|
|
393
|
+
actor,
|
|
394
|
+
permission: this.session.auth.permission,
|
|
395
|
+
}],
|
|
396
|
+
data: {
|
|
397
|
+
account: actor,
|
|
398
|
+
name: data.name,
|
|
399
|
+
description: data.description,
|
|
400
|
+
endpoint: data.endpoint,
|
|
401
|
+
protocol: data.protocol,
|
|
402
|
+
capabilities: JSON.stringify(data.capabilities),
|
|
403
|
+
},
|
|
404
|
+
},
|
|
405
|
+
],
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Update agent metadata
|
|
410
|
+
*/
|
|
411
|
+
async update(data) {
|
|
412
|
+
this.requireSession();
|
|
413
|
+
// Validate input before sending to blockchain
|
|
414
|
+
// Only validate fields that are provided (UpdateAgentData has optional fields)
|
|
415
|
+
validateAgentData({
|
|
416
|
+
name: data.name,
|
|
417
|
+
description: data.description,
|
|
418
|
+
endpoint: data.endpoint,
|
|
419
|
+
protocol: data.protocol,
|
|
420
|
+
capabilities: data.capabilities,
|
|
421
|
+
});
|
|
422
|
+
// Get current agent data to merge with updates
|
|
423
|
+
const current = await this.getAgent(this.session.auth.actor);
|
|
424
|
+
if (!current) {
|
|
425
|
+
throw new Error('Agent not found');
|
|
426
|
+
}
|
|
427
|
+
return this.session.link.transact({
|
|
428
|
+
actions: [
|
|
429
|
+
{
|
|
430
|
+
account: this.contract,
|
|
431
|
+
name: 'update',
|
|
432
|
+
authorization: [
|
|
433
|
+
{
|
|
434
|
+
actor: this.session.auth.actor,
|
|
435
|
+
permission: this.session.auth.permission,
|
|
436
|
+
},
|
|
437
|
+
],
|
|
438
|
+
data: {
|
|
439
|
+
account: this.session.auth.actor,
|
|
440
|
+
name: data.name ?? current.name,
|
|
441
|
+
description: data.description ?? current.description,
|
|
442
|
+
endpoint: data.endpoint ?? current.endpoint,
|
|
443
|
+
protocol: data.protocol ?? current.protocol,
|
|
444
|
+
capabilities: JSON.stringify(data.capabilities ?? current.capabilities),
|
|
445
|
+
},
|
|
446
|
+
},
|
|
447
|
+
],
|
|
448
|
+
});
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Set agent active status
|
|
452
|
+
*/
|
|
453
|
+
async setStatus(active) {
|
|
454
|
+
this.requireSession();
|
|
455
|
+
return this.session.link.transact({
|
|
456
|
+
actions: [
|
|
457
|
+
{
|
|
458
|
+
account: this.contract,
|
|
459
|
+
name: 'setstatus',
|
|
460
|
+
authorization: [
|
|
461
|
+
{
|
|
462
|
+
actor: this.session.auth.actor,
|
|
463
|
+
permission: this.session.auth.permission,
|
|
464
|
+
},
|
|
465
|
+
],
|
|
466
|
+
data: {
|
|
467
|
+
account: this.session.auth.actor,
|
|
468
|
+
active,
|
|
469
|
+
},
|
|
470
|
+
},
|
|
471
|
+
],
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
// ============== SYSTEM STAKING NOTE ==============
|
|
475
|
+
// Agents use XPR Network's native system staking (eosio::voters table)
|
|
476
|
+
// instead of contract-managed staking. To stake/unstake:
|
|
477
|
+
//
|
|
478
|
+
// 1. Stake: Use system stake action or resources.xprnetwork.org
|
|
479
|
+
// 2. Unstake: Use system unstake action
|
|
480
|
+
// 3. Query stake: Call agentcore::getagentinfo action or query eosio::voters table
|
|
481
|
+
//
|
|
482
|
+
// This design leverages the existing staking infrastructure and allows
|
|
483
|
+
// agents to earn staking rewards while meeting minimum stake requirements.
|
|
484
|
+
/**
|
|
485
|
+
* Add plugin to agent
|
|
486
|
+
*/
|
|
487
|
+
async addPlugin(pluginId, config = {}) {
|
|
488
|
+
this.requireSession();
|
|
489
|
+
return this.session.link.transact({
|
|
490
|
+
actions: [
|
|
491
|
+
{
|
|
492
|
+
account: this.contract,
|
|
493
|
+
name: 'addplugin',
|
|
494
|
+
authorization: [
|
|
495
|
+
{
|
|
496
|
+
actor: this.session.auth.actor,
|
|
497
|
+
permission: this.session.auth.permission,
|
|
498
|
+
},
|
|
499
|
+
],
|
|
500
|
+
data: {
|
|
501
|
+
agent: this.session.auth.actor,
|
|
502
|
+
plugin_id: pluginId,
|
|
503
|
+
pluginConfig: JSON.stringify(config),
|
|
504
|
+
},
|
|
505
|
+
},
|
|
506
|
+
],
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* Remove plugin from agent
|
|
511
|
+
*/
|
|
512
|
+
async removePlugin(agentPluginId) {
|
|
513
|
+
this.requireSession();
|
|
514
|
+
return this.session.link.transact({
|
|
515
|
+
actions: [
|
|
516
|
+
{
|
|
517
|
+
account: this.contract,
|
|
518
|
+
name: 'rmplugin',
|
|
519
|
+
authorization: [
|
|
520
|
+
{
|
|
521
|
+
actor: this.session.auth.actor,
|
|
522
|
+
permission: this.session.auth.permission,
|
|
523
|
+
},
|
|
524
|
+
],
|
|
525
|
+
data: {
|
|
526
|
+
agent: this.session.auth.actor,
|
|
527
|
+
agentplugin_id: agentPluginId,
|
|
528
|
+
},
|
|
529
|
+
},
|
|
530
|
+
],
|
|
531
|
+
});
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Register a new plugin
|
|
535
|
+
*/
|
|
536
|
+
async registerPlugin(name, version, contract, action, schema, category) {
|
|
537
|
+
this.requireSession();
|
|
538
|
+
return this.session.link.transact({
|
|
539
|
+
actions: [
|
|
540
|
+
{
|
|
541
|
+
account: this.contract,
|
|
542
|
+
name: 'regplugin',
|
|
543
|
+
authorization: [
|
|
544
|
+
{
|
|
545
|
+
actor: this.session.auth.actor,
|
|
546
|
+
permission: this.session.auth.permission,
|
|
547
|
+
},
|
|
548
|
+
],
|
|
549
|
+
data: {
|
|
550
|
+
author: this.session.auth.actor,
|
|
551
|
+
name,
|
|
552
|
+
version,
|
|
553
|
+
contract,
|
|
554
|
+
action,
|
|
555
|
+
schema: JSON.stringify(schema),
|
|
556
|
+
category,
|
|
557
|
+
},
|
|
558
|
+
},
|
|
559
|
+
],
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
// ============== OWNERSHIP ==============
|
|
563
|
+
/**
|
|
564
|
+
* Step 1: Agent approves a human to claim them.
|
|
565
|
+
* This is called by the AGENT to give consent.
|
|
566
|
+
*
|
|
567
|
+
* @param newOwner - The KYC'd human being approved to claim
|
|
568
|
+
*/
|
|
569
|
+
async approveClaim(newOwner) {
|
|
570
|
+
this.requireSession();
|
|
571
|
+
// The session holder IS the agent giving consent
|
|
572
|
+
const agent = this.session.auth.actor;
|
|
573
|
+
return this.session.link.transact({
|
|
574
|
+
actions: [
|
|
575
|
+
{
|
|
576
|
+
account: this.contract,
|
|
577
|
+
name: 'approveclaim',
|
|
578
|
+
authorization: [
|
|
579
|
+
{
|
|
580
|
+
actor: agent,
|
|
581
|
+
permission: this.session.auth.permission,
|
|
582
|
+
},
|
|
583
|
+
],
|
|
584
|
+
data: {
|
|
585
|
+
agent,
|
|
586
|
+
new_owner: newOwner,
|
|
587
|
+
},
|
|
588
|
+
},
|
|
589
|
+
],
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
/**
|
|
593
|
+
* Step 2: Human completes the claim after agent approval.
|
|
594
|
+
* Agent must have called approveClaim first.
|
|
595
|
+
*
|
|
596
|
+
* IMPORTANT: Before calling this, you must:
|
|
597
|
+
* 1. Have the agent call approveClaim(yourAccount)
|
|
598
|
+
* 2. Send the claim fee with memo "claim:agentname:yourname"
|
|
599
|
+
*
|
|
600
|
+
* @param agent - The agent account to claim
|
|
601
|
+
*/
|
|
602
|
+
async claim(agent) {
|
|
603
|
+
this.requireSession();
|
|
604
|
+
const owner = this.session.auth.actor;
|
|
605
|
+
return this.session.link.transact({
|
|
606
|
+
actions: [
|
|
607
|
+
{
|
|
608
|
+
account: this.contract,
|
|
609
|
+
name: 'claim',
|
|
610
|
+
authorization: [
|
|
611
|
+
{
|
|
612
|
+
actor: owner,
|
|
613
|
+
permission: this.session.auth.permission,
|
|
614
|
+
},
|
|
615
|
+
],
|
|
616
|
+
data: {
|
|
617
|
+
agent,
|
|
618
|
+
},
|
|
619
|
+
},
|
|
620
|
+
],
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* Send claim fee and complete the claim in one transaction.
|
|
625
|
+
* Agent must have already called approveClaim first.
|
|
626
|
+
*
|
|
627
|
+
* @param agent - The agent account to claim
|
|
628
|
+
* @param amount - The claim fee amount (e.g., "1.0000 XPR")
|
|
629
|
+
*/
|
|
630
|
+
async claimWithFee(agent, amount) {
|
|
631
|
+
this.requireSession();
|
|
632
|
+
const owner = this.session.auth.actor;
|
|
633
|
+
return this.session.link.transact({
|
|
634
|
+
actions: [
|
|
635
|
+
{
|
|
636
|
+
account: 'eosio.token',
|
|
637
|
+
name: 'transfer',
|
|
638
|
+
authorization: [
|
|
639
|
+
{
|
|
640
|
+
actor: owner,
|
|
641
|
+
permission: this.session.auth.permission,
|
|
642
|
+
},
|
|
643
|
+
],
|
|
644
|
+
data: {
|
|
645
|
+
from: owner,
|
|
646
|
+
to: this.contract,
|
|
647
|
+
quantity: amount,
|
|
648
|
+
memo: `claim:${agent}:${owner}`,
|
|
649
|
+
},
|
|
650
|
+
},
|
|
651
|
+
{
|
|
652
|
+
account: this.contract,
|
|
653
|
+
name: 'claim',
|
|
654
|
+
authorization: [
|
|
655
|
+
{
|
|
656
|
+
actor: owner,
|
|
657
|
+
permission: this.session.auth.permission,
|
|
658
|
+
},
|
|
659
|
+
],
|
|
660
|
+
data: {
|
|
661
|
+
agent,
|
|
662
|
+
},
|
|
663
|
+
},
|
|
664
|
+
],
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* Cancel a pending claim approval.
|
|
669
|
+
* Only the agent can cancel their own approval.
|
|
670
|
+
* Any deposit will be refunded to the payer.
|
|
671
|
+
*
|
|
672
|
+
* NOTE: The session holder must be the agent account.
|
|
673
|
+
*/
|
|
674
|
+
async cancelClaim() {
|
|
675
|
+
this.requireSession();
|
|
676
|
+
const agent = this.session.auth.actor;
|
|
677
|
+
return this.session.link.transact({
|
|
678
|
+
actions: [
|
|
679
|
+
{
|
|
680
|
+
account: this.contract,
|
|
681
|
+
name: 'cancelclaim',
|
|
682
|
+
authorization: [
|
|
683
|
+
{
|
|
684
|
+
actor: agent,
|
|
685
|
+
permission: this.session.auth.permission,
|
|
686
|
+
},
|
|
687
|
+
],
|
|
688
|
+
data: {
|
|
689
|
+
agent,
|
|
690
|
+
},
|
|
691
|
+
},
|
|
692
|
+
],
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
/**
|
|
696
|
+
* Transfer ownership of an agent to a new owner.
|
|
697
|
+
*
|
|
698
|
+
* IMPORTANT: The contract requires THREE signatures:
|
|
699
|
+
* 1. Current owner (must authorize)
|
|
700
|
+
* 2. New owner (must authorize)
|
|
701
|
+
* 3. Agent itself (must consent to the transfer)
|
|
702
|
+
*
|
|
703
|
+
* This method includes only the session holder's authorization.
|
|
704
|
+
* It will FAIL unless the session holder controls all three accounts,
|
|
705
|
+
* which is rare in practice.
|
|
706
|
+
*
|
|
707
|
+
* For most use cases, use `buildTransferProposal()` to create a multi-sig
|
|
708
|
+
* proposal that can be signed by all three parties.
|
|
709
|
+
*
|
|
710
|
+
* @param agent - The agent account
|
|
711
|
+
* @param newOwner - The new owner (must have KYC)
|
|
712
|
+
* @throws Will fail if session holder doesn't control all 3 required accounts
|
|
713
|
+
*/
|
|
714
|
+
async transferOwnership(agent, newOwner) {
|
|
715
|
+
this.requireSession();
|
|
716
|
+
// P2 FIX: Warn about the three-signature requirement
|
|
717
|
+
console.warn('transferOwnership requires 3 signatures (current owner, new owner, agent). ' +
|
|
718
|
+
'This will fail unless session controls all accounts. Use buildTransferProposal() for multi-sig.');
|
|
719
|
+
return this.session.link.transact({
|
|
720
|
+
actions: [
|
|
721
|
+
{
|
|
722
|
+
account: this.contract,
|
|
723
|
+
name: 'transfer',
|
|
724
|
+
authorization: [
|
|
725
|
+
{
|
|
726
|
+
actor: this.session.auth.actor,
|
|
727
|
+
permission: this.session.auth.permission,
|
|
728
|
+
},
|
|
729
|
+
],
|
|
730
|
+
data: {
|
|
731
|
+
agent,
|
|
732
|
+
new_owner: newOwner,
|
|
733
|
+
},
|
|
734
|
+
},
|
|
735
|
+
],
|
|
736
|
+
});
|
|
737
|
+
}
|
|
738
|
+
/**
|
|
739
|
+
* Build a transfer ownership action for use in a multi-sig proposal.
|
|
740
|
+
* Returns the action data that can be used with msig.propose.
|
|
741
|
+
*
|
|
742
|
+
* The transfer requires signatures from:
|
|
743
|
+
* 1. Current owner
|
|
744
|
+
* 2. New owner
|
|
745
|
+
* 3. Agent itself
|
|
746
|
+
*
|
|
747
|
+
* @param agent - The agent account
|
|
748
|
+
* @param currentOwner - The current owner account
|
|
749
|
+
* @param newOwner - The new owner account (must have KYC)
|
|
750
|
+
* @returns Action data for multi-sig proposal
|
|
751
|
+
*/
|
|
752
|
+
buildTransferProposal(agent, currentOwner, newOwner) {
|
|
753
|
+
return {
|
|
754
|
+
account: this.contract,
|
|
755
|
+
name: 'transfer',
|
|
756
|
+
authorization: [
|
|
757
|
+
{ actor: currentOwner, permission: 'active' },
|
|
758
|
+
{ actor: newOwner, permission: 'active' },
|
|
759
|
+
{ actor: agent, permission: 'active' },
|
|
760
|
+
],
|
|
761
|
+
data: {
|
|
762
|
+
agent,
|
|
763
|
+
new_owner: newOwner,
|
|
764
|
+
},
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* Release ownership of an agent.
|
|
769
|
+
* Only the current owner can release.
|
|
770
|
+
* Claim deposit is refunded to the owner.
|
|
771
|
+
*
|
|
772
|
+
* @param agent - The agent account to release
|
|
773
|
+
*/
|
|
774
|
+
async release(agent) {
|
|
775
|
+
this.requireSession();
|
|
776
|
+
return this.session.link.transact({
|
|
777
|
+
actions: [
|
|
778
|
+
{
|
|
779
|
+
account: this.contract,
|
|
780
|
+
name: 'release',
|
|
781
|
+
authorization: [
|
|
782
|
+
{
|
|
783
|
+
actor: this.session.auth.actor,
|
|
784
|
+
permission: this.session.auth.permission,
|
|
785
|
+
},
|
|
786
|
+
],
|
|
787
|
+
data: {
|
|
788
|
+
agent,
|
|
789
|
+
},
|
|
790
|
+
},
|
|
791
|
+
],
|
|
792
|
+
});
|
|
793
|
+
}
|
|
794
|
+
/**
|
|
795
|
+
* Verify an agent's owner still has valid KYC.
|
|
796
|
+
* Anyone can call this to trigger re-verification.
|
|
797
|
+
*
|
|
798
|
+
* If the owner's KYC has dropped below level 1, the ownership
|
|
799
|
+
* is removed and the claim deposit is refunded to the former owner.
|
|
800
|
+
*
|
|
801
|
+
* This helps maintain trust score integrity by allowing community
|
|
802
|
+
* enforcement of KYC requirements.
|
|
803
|
+
*
|
|
804
|
+
* @param agent - The agent account to verify
|
|
805
|
+
*/
|
|
806
|
+
async verifyClaim(agent) {
|
|
807
|
+
this.requireSession();
|
|
808
|
+
return this.session.link.transact({
|
|
809
|
+
actions: [
|
|
810
|
+
{
|
|
811
|
+
account: this.contract,
|
|
812
|
+
name: 'verifyclaim',
|
|
813
|
+
authorization: [
|
|
814
|
+
{
|
|
815
|
+
actor: this.session.auth.actor,
|
|
816
|
+
permission: this.session.auth.permission,
|
|
817
|
+
},
|
|
818
|
+
],
|
|
819
|
+
data: {
|
|
820
|
+
agent,
|
|
821
|
+
},
|
|
822
|
+
},
|
|
823
|
+
],
|
|
824
|
+
});
|
|
825
|
+
}
|
|
826
|
+
/**
|
|
827
|
+
* Get agents owned by a specific account
|
|
828
|
+
*/
|
|
829
|
+
async getAgentsByOwner(owner, limit = 100) {
|
|
830
|
+
// Use secondary index to query by owner
|
|
831
|
+
const result = await this.rpc.get_table_rows({
|
|
832
|
+
json: true,
|
|
833
|
+
code: this.contract,
|
|
834
|
+
scope: this.contract,
|
|
835
|
+
table: 'agents',
|
|
836
|
+
index_position: 2, // byOwner secondary index
|
|
837
|
+
key_type: 'name',
|
|
838
|
+
lower_bound: owner,
|
|
839
|
+
upper_bound: owner,
|
|
840
|
+
limit,
|
|
841
|
+
});
|
|
842
|
+
return result.rows.map((row) => this.parseAgent(row));
|
|
843
|
+
}
|
|
844
|
+
// ============== HELPERS ==============
|
|
845
|
+
requireSession() {
|
|
846
|
+
if (!this.session) {
|
|
847
|
+
throw new Error('Session required for write operations');
|
|
848
|
+
}
|
|
849
|
+
}
|
|
850
|
+
parseAgent(raw) {
|
|
851
|
+
return {
|
|
852
|
+
account: raw.account,
|
|
853
|
+
owner: raw.owner || null, // Empty string means no owner
|
|
854
|
+
pending_owner: raw.pending_owner || null,
|
|
855
|
+
name: raw.name,
|
|
856
|
+
description: raw.description,
|
|
857
|
+
endpoint: raw.endpoint,
|
|
858
|
+
protocol: raw.protocol,
|
|
859
|
+
capabilities: (0, utils_1.parseCapabilities)(raw.capabilities),
|
|
860
|
+
total_jobs: (0, utils_1.safeParseInt)(raw.total_jobs),
|
|
861
|
+
registered_at: (0, utils_1.safeParseInt)(raw.registered_at),
|
|
862
|
+
active: raw.active === 1,
|
|
863
|
+
claim_deposit: (0, utils_1.safeParseInt)(raw.claim_deposit),
|
|
864
|
+
deposit_payer: raw.deposit_payer || null,
|
|
865
|
+
// Note: stake is queried from system staking (eosio::voters), not stored here
|
|
866
|
+
};
|
|
867
|
+
}
|
|
868
|
+
parsePlugin(raw) {
|
|
869
|
+
return {
|
|
870
|
+
id: (0, utils_1.safeParseInt)(raw.id),
|
|
871
|
+
name: raw.name,
|
|
872
|
+
version: raw.version,
|
|
873
|
+
contract: raw.contract,
|
|
874
|
+
action: raw.action,
|
|
875
|
+
schema: (0, utils_1.safeJsonParse)(raw.schema, {}),
|
|
876
|
+
category: raw.category,
|
|
877
|
+
author: raw.author,
|
|
878
|
+
verified: raw.verified === 1,
|
|
879
|
+
};
|
|
880
|
+
}
|
|
881
|
+
parseAgentPlugin(raw) {
|
|
882
|
+
return {
|
|
883
|
+
id: (0, utils_1.safeParseInt)(raw.id),
|
|
884
|
+
agent: raw.agent,
|
|
885
|
+
plugin_id: (0, utils_1.safeParseInt)(raw.plugin_id),
|
|
886
|
+
config: (0, utils_1.safeJsonParse)(raw.config, {}),
|
|
887
|
+
enabled: raw.enabled === 1,
|
|
888
|
+
};
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
exports.AgentRegistry = AgentRegistry;
|
|
892
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQWdlbnRSZWdpc3RyeS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9BZ2VudFJlZ2lzdHJ5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQW1CQSxtQ0FBeUc7QUFFekcsTUFBTSxnQkFBZ0IsR0FBRyxXQUFXLENBQUM7QUFFckMsc0NBQXNDO0FBQ3RDLE1BQU0sZUFBZSxHQUFHLENBQUMsTUFBTSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLE1BQU0sRUFBRSxLQUFLLENBQVUsQ0FBQztBQUV2Riw4QkFBOEI7QUFDOUIsTUFBTSx1QkFBdUIsR0FBRyxDQUFDLFNBQVMsRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBRTdFOzs7OztHQUtHO0FBQ0gsU0FBUyxpQkFBaUIsQ0FBQyxJQU0xQjtJQUNDLDJEQUEyRDtJQUMzRCxJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDNUIsSUFBSSxPQUFPLElBQUksQ0FBQyxJQUFJLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDbEMsTUFBTSxJQUFJLEtBQUssQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO1FBQzNDLENBQUM7UUFDRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3JDLDBFQUEwRTtRQUMxRSxJQUFJLFdBQVcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLFdBQVcsQ0FBQyxNQUFNLEdBQUcsRUFBRSxFQUFFLENBQUM7WUFDdEQsTUFBTSxJQUFJLEtBQUssQ0FBQywwREFBMEQsQ0FBQyxDQUFDO1FBQzlFLENBQUM7SUFDSCxDQUFDO0lBRUQsbUVBQW1FO0lBQ25FLElBQUksSUFBSSxDQUFDLFdBQVcsS0FBSyxTQUFTLEVBQUUsQ0FBQztRQUNuQyxJQUFJLE9BQU8sSUFBSSxDQUFDLFdBQVcsS0FBSyxRQUFRLEVBQUUsQ0FBQztZQUN6QyxNQUFNLElBQUksS0FBSyxD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Q0FDRjtBQXQ2QkQsc0NBczZCQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFnZW50LFxuICBBZ2VudFJhdyxcbiAgUGx1Z2luLFxuICBQbHVnaW5SYXcsXG4gIEFnZW50UGx1Z2luLFxuICBBZ2VudFBsdWdpblJhdyxcbiAgQWdlbnRDb3JlQ29uZmlnLFxuICBBZ2VudExpc3RPcHRpb25zLFxuICBSZWdpc3RlckFnZW50RGF0YSxcbiAgVXBkYXRlQWdlbnREYXRhLFxuICBUcmFuc2FjdGlvblJlc3VsdCxcbiAgSnNvblJwYyxcbiAgUHJvdG9uU2Vzc2lvbixcbiAgUGx1Z2luQ2F0ZWdvcnksXG4gIFBhZ2luYXRlZFJlc3VsdCxcbiAgVHJ1c3RTY29yZSxcbiAgQWdlbnRTY29yZSxcbn0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQgeyBwYXJzZUNhcGFiaWxpdGllcywgc2FmZUpzb25QYXJzZSwgZm9ybWF0WHByLCBjYWxjdWxhdGVUcnVzdFNjb3JlLCBzYWZlUGFyc2VJbnQgfSBmcm9tICcuL3V0aWxzJztcblxuY29uc3QgREVGQVVMVF9DT05UUkFDVCA9ICdhZ2VudGNvcmUnO1xuXG4vLyBWYWxpZCBwcm90b2NvbHMgZm9yIGFnZW50IGVuZHBvaW50c1xuY29uc3QgVkFMSURfUFJPVE9DT0xTID0gWydodHRwJywgJ2h0dHBzJywgJ2dycGMnLCAnd2Vic29ja2V0JywgJ21xdHQnLCAnd3NzJ10gYXMgY29uc3Q7XG5cbi8vIFZhbGlkIGVuZHBvaW50IFVSTCBwcmVmaXhlc1xuY29uc3QgVkFMSURfRU5EUE9JTlRfUFJFRklYRVMgPSBbJ2h0dHA6Ly8nLCAnaHR0cHM6Ly8nLCAnZ3JwYzovLycsICd3c3M6Ly8nXTtcblxuLyoqXG4gKiBWYWxpZGF0ZXMgYWdlbnQgcmVnaXN0cmF0aW9uL3VwZGF0ZSBkYXRhIGJlZm9yZSBzZW5kaW5nIHRvIHRoZSBibG9ja2NoYWluLlxuICogVGhyb3dzIGRlc2NyaXB0aXZlIGVycm9ycyBmb3IgaW52YWxpZCBpbnB1dC5cbiAqXG4gKiBDUklUSUNBTCBGSVg6IFZhbGlkYXRlcyBUUklNTUVEIGxlbmd0aCB0byBwcmV2ZW50IHdoaXRlc3BhY2UgcGFkZGluZyBieXBhc3MuXG4gKi9cbmZ1bmN0aW9uIHZhbGlkYXRlQWdlbnREYXRhKGRhdGE6IHtcbiAgbmFtZT86IHN0cmluZztcbiAgZGVzY3JpcHRpb24/OiBzdHJpbmc7XG4gIGVuZHBvaW50Pzogc3RyaW5nO1xuICBwcm90b2NvbD86IHN0cmluZztcbiAgY2FwYWJpbGl0aWVzPzogc3RyaW5nW107XG59KTogdm9pZCB7XG4gIC8vIFZhbGlkYXRlIG5hbWU6IDEtNjQgY2hhcmFjdGVycyBhZnRlciB0cmltbWluZywgbm9uLWVtcHR5XG4gIGlmIChkYXRhLm5hbWUgIT09IHVuZGVmaW5lZCkge1xuICAgIGlmICh0eXBlb2YgZGF0YS5uYW1lICE9PSAnc3RyaW5nJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdOYW1lIG11c3QgYmUgYSBzdHJpbmcnKTtcbiAgICB9XG4gICAgY29uc3QgdHJpbW1lZE5hbWUgPSBkYXRhLm5hbWUudHJpbSgpO1xuICAgIC8vIENSSVRJQ0FMIEZJWDogQ2hlY2sgdHJpbW1lZCBsZW5ndGggdG8gcHJldmVudCB3aGl0ZXNwYWNlIHBhZGRpbmcgYnlwYXNzXG4gICAgaWYgKHRyaW1tZWROYW1lLmxlbmd0aCA8IDEgfHwgdHJpbW1lZE5hbWUubGVuZ3RoID4gNjQpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTmFtZSBtdXN0IGJlIDEtNjQgY2hhcmFjdGVycyAoYWZ0ZXIgdHJpbW1pbmcgd2hpdGVzcGFjZSknKTtcbiAgICB9XG4gIH1cblxuICAvLyBWYWxpZGF0ZSBkZXNjcmlwdGlvbjogMS0yNTYgY2hhcmFjdGVycyBhZnRlciB0cmltbWluZywgbm9uLWVtcHR5XG4gIGlmIChkYXRhLmRlc2NyaXB0aW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICBpZiAodHlwZW9mIGRhdGEuZGVzY3JpcHRpb24gIT09ICdzdHJpbmcnKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Rlc2NyaXB0aW9uIG11c3QgYmUgYSBzdHJpbmcnKTtcbiAgICB9XG4gICAgY29uc3QgdHJpbW1lZERlc2MgPSBkYXRhLmRlc2NyaXB0aW9uLnRyaW0oKTtcbiAgICAvLyBDUklUSUNBTCBGSVg6IENoZWNrIHRyaW1tZWQgbGVuZ3RoIHRvIHByZXZlbnQgd2hpdGVzcGFjZSBwYWRkaW5nIGJ5cGFzc1xuICAgIGlmICh0cmltbWVkRGVzYy5sZW5ndGggPCAxIHx8IHRyaW1tZWREZXNjLmxlbmd0aCA+IDI1Nikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdEZXNjcmlwdGlvbiBtdXN0IGJlIDEtMjU2IGNoYXJhY3RlcnMgKGFmdGVyIHRyaW1taW5nIHdoaXRlc3BhY2UpJyk7XG4gICAgfVxuICB9XG5cbiAgLy8gVmFsaWRhdGUgZW5kcG9pbnQ6IDEtMjU2IGNoYXJhY3RlcnMgYWZ0ZXIgdHJpbW1pbmcsIG11c3Qgc3RhcnQgd2l0aCB2YWxpZCBwcm90b2NvbCBwcmVmaXhcbiAgaWYgKGRhdGEuZW5kcG9pbnQgIT09IHVuZGVmaW5lZCkge1xuICAgIGlmICh0eXBlb2YgZGF0YS5lbmRwb2ludCAhPT0gJ3N0cmluZycpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignRW5kcG9pbnQgbXVzdCBiZSBhIHN0cmluZycpO1xuICAgIH1cbiAgICBjb25zdCB0cmltbWVkRW5kcG9pbnQgPSBkYXRhLmVuZHBvaW50LnRyaW0oKTtcbiAgICAvLyBDUklUSUNBTCBGSVg6IENoZWNrIHRyaW1tZWQgbGVuZ3RoIHRvIHByZXZlbnQgd2hpdGVzcGFjZSBwYWRkaW5nIGJ5cGFzc1xuICAgIGlmICh0cmltbWVkRW5kcG9pbnQubGVuZ3RoIDwgMSB8fCB0cmltbWVkRW5kcG9pbnQubGVuZ3RoID4gMjU2KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0VuZHBvaW50IG11c3QgYmUgMS0yNTYgY2hhcmFjdGVycyBhbmQgc3RhcnQgd2l0aCBodHRwOi8vLCBodHRwczovLywgZ3JwYzovLywgb3Igd3NzOi8vJyk7XG4gICAgfVxuICAgIGNvbnN0IGhhc1ZhbGlkUHJlZml4ID0gVkFMSURfRU5EUE9JTlRfUFJFRklYRVMuc29tZShwcmVmaXggPT5cbiAgICAgIHRyaW1tZWRFbmRwb2ludC50b0xvd2VyQ2FzZSgpLnN0YXJ0c1dpdGgocHJlZml4KVxuICAgICk7XG4gICAgaWYgKCFoYXNWYWxpZFByZWZpeCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdFbmRwb2ludCBtdXN0IGJlIDEtMjU2IGNoYXJhY3RlcnMgYW5kIHN0YXJ0IHdpdGggaHR0cDovLywgaHR0cHM6Ly8sIGdycGM6Ly8sIG9yIHdzczovLycpO1xuICAgIH1cbiAgfVxuXG4gIC8vIFZhbGlkYXRlIHByb3RvY29sOiBtdXN0IGJlIG9uZSBvZiB0aGUgdmFsaWQgcHJvdG9jb2xzIChjYXNlLWluc2Vuc2l0aXZlKVxuICBpZiAoZGF0YS5wcm90b2NvbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgY29uc3Qgbm9ybWFsaXplZFByb3RvY29sID0gZGF0YS5wcm90b2NvbC50b0xvd2VyQ2FzZSgpO1xuICAgIGlmICghVkFMSURfUFJPVE9DT0xTLmluY2x1ZGVzKG5vcm1hbGl6ZWRQcm90b2NvbCBhcyB0eXBlb2YgVkFMSURfUFJPVE9DT0xTW251bWJlcl0pKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFByb3RvY29sIG11c3QgYmUgb25lIG9mOiAke1ZBTElEX1BST1RPQ09MUy5qb2luKCcsICcpfWApO1xuICAgIH1cbiAgfVxuXG4gIC8vIFZhbGlkYXRlIGNhcGFiaWxpdGllczogYXJyYXksIHdoZW4gc3RyaW5naWZpZWQgbXVzdCBiZSA8PSAyMDQ4IGNoYXJhY3RlcnNcbiAgaWYgKGRhdGEuY2FwYWJpbGl0aWVzICE9PSB1bmRlZmluZWQpIHtcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkoZGF0YS5jYXBhYmlsaXRpZXMpKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhcGFiaWxpdGllcyBtdXN0IGJlIGFuIGFycmF5IHdpdGggc3RyaW5naWZpZWQgbGVuZ3RoIDw9IDIwNDggY2hhcmFjdGVycycpO1xuICAgIH1cbiAgICBjb25zdCBzdHJpbmdpZmllZCA9IEpTT04uc3RyaW5naWZ5KGRhdGEuY2FwYWJpbGl0aWVzKTtcbiAgICBpZiAoc3RyaW5naWZpZWQubGVuZ3RoID4gMjA0OCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYXBhYmlsaXRpZXMgbXVzdCBiZSBhbiBhcnJheSB3aXRoIHN0cmluZ2lmaWVkIGxlbmd0aCA8PSAyMDQ4IGNoYXJhY3RlcnMnKTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIEFnZW50UmVnaXN0cnkge1xuICBwcml2YXRlIHJwYzogSnNvblJwYztcbiAgcHJpdmF0ZSBzZXNzaW9uOiBQcm90b25TZXNzaW9uIHwgbnVsbDtcbiAgcHJpdmF0ZSBjb250cmFjdDogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKHJwYzogSnNvblJwYywgc2Vzc2lvbj86IFByb3RvblNlc3Npb24sIGNvbnRyYWN0Pzogc3RyaW5nKSB7XG4gICAgdGhpcy5ycGMgPSBycGM7XG4gICAgdGhpcy5zZXNzaW9uID0gc2Vzc2lvbiB8fCBudWxsO1xuICAgIHRoaXMuY29udHJhY3QgPSBjb250cmFjdCB8fCBERUZBVUxUX0NPTlRSQUNUO1xuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT0gUkVBRCBPUEVSQVRJT05TID09PT09PT09PT09PT09XG5cbiAgLyoqXG4gICAqIEdldCBhIHNpbmdsZSBhZ2VudCBieSBhY2NvdW50IG5hbWVcbiAgICovXG4gIGFzeW5jIGdldEFnZW50KGFjY291bnQ6IHN0cmluZyk6IFByb21pc2U8QWdlbnQgfCBudWxsPiB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5ycGMuZ2V0X3RhYmxlX3Jvd3M8QWdlbnRSYXc+KHtcbiAgICAgIGpzb246IHRydWUsXG4gICAgICBjb2RlOiB0aGlzLmNvbnRyYWN0LFxuICAgICAgc2NvcGU6IHRoaXMuY29udHJhY3QsXG4gICAgICB0YWJsZTogJ2FnZW50cycsXG4gICAgICBsb3dlcl9ib3VuZDogYWNjb3VudCxcbiAgICAgIHVwcGVyX2JvdW5kOiBhY2NvdW50LFxuICAgICAgbGltaXQ6IDEsXG4gICAgfSk7XG5cbiAgICBpZiAocmVzdWx0LnJvd3MubGVuZ3RoID09PSAwKSByZXR1cm4gbnVsbDtcbiAgICByZXR1cm4gdGhpcy5wYXJzZUFnZW50KHJlc3VsdC5yb3dzWzBdKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBMaXN0IGFsbCBhZ2VudHMgd2l0aCBvcHRpb25hbCBmaWx0ZXJzIGFuZCBwYWdpbmF0aW9uXG4gICAqIEByZXR1cm5zIFBhZ2luYXRlZFJlc3VsdCB3aXRoIGl0ZW1zLCBoYXNNb3JlIGZsYWcsIGFuZCBuZXh0Q3Vyc29yIGZvciBwYWdpbmF0aW9uXG4gICAqL1xuICBhc3luYyBsaXN0QWdlbnRzKG9wdGlvbnM6IEFnZW50TGlzdE9wdGlvbnMgPSB7fSk6IFByb21pc2U8UGFnaW5hdGVkUmVzdWx0PEFnZW50Pj4ge1xuICAgIGNvbnN0IHsgbGltaXQgPSAxMDAsIGN1cnNvciwgYWN0aXZlX29ubHkgPSB0cnVlIH0gPSBvcHRpb25zO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5ycGMuZ2V0X3RhYmxlX3Jvd3M8QWdlbnRSYXc+KHtcbiAgICAgIGpzb246IHRydWUsXG4gICAgICBjb2RlOiB0aGlzLmNvbnRyYWN0LFxuICAgICAgc2NvcGU6IHRoaXMuY29udHJhY3QsXG4gICAgICB0YWJsZTogJ2FnZW50cycsXG4gICAgICBsb3dlcl9ib3VuZDogY3Vyc29yLFxuICAgICAgbGltaXQ6IGxpbWl0ICsgMSwgLy8gRmV0Y2ggb25lIGV4dHJhIHRvIGNoZWNrIGlmIHRoZXJlIGFyZSBtb3JlXG4gICAgfSk7XG5cbiAgICBjb25zdCBoYXNNb3JlID0gcmVzdWx0LnJvd3MubGVuZ3RoID4gbGltaXQ7XG4gICAgY29uc3Qgcm93cyA9IGhhc01vcmUgPyByZXN1bHQucm93cy5zbGljZSgwLCBsaW1pdCkgOiByZXN1bHQucm93cztcbiAgICBsZXQgYWdlbnRzID0gcm93cy5tYXAoKHJvdykgPT4gdGhpcy5wYXJzZUFnZW50KHJvdykpO1xuXG4gICAgLy8gQXBwbHkgZmlsdGVycyBhZnRlciBmZXRjaGluZ1xuICAgIGlmIChhY3RpdmVfb25seSkge1xuICAgICAgYWdlbnRzID0gYWdlbnRzLmZpbHRlcigoYSkgPT4gYS5hY3RpdmUpO1xuICAgIH1cblxuICAgIC8vIE5vdGU6IEFnZW50cyB1c2Ugc3lzdGVtIHN0YWtpbmcgKGVvc2lvOjp2b3RlcnMpLCBub3QgY29udHJhY3QtbWFuYWdlZCBzdGFraW5nXG4gICAgLy8gVG8gZmlsdGVyIGJ5IHN0YWtlLCBxdWVyeSBzeXN0ZW0gc3Rha2luZyBzZXBhcmF0ZWx5XG5cbiAgICAvLyBHZXQgbmV4dCBjdXJzb3IgZnJvbSB0aGUgbGFzdCByb3cgaWYgdGhlcmUgYXJlIG1vcmVcbiAgICBjb25zdCBuZXh0Q3Vyc29yID0gaGFzTW9yZSAmJiByb3dzLmxlbmd0aCA+IDBcbiAgICAgID8gcm93c1tyb3dzLmxlbmd0aCAtIDFdLmFjY291bnRcbiAgICAgIDogdW5kZWZpbmVkO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGl0ZW1zOiBhZ2VudHMsXG4gICAgICBoYXNNb3JlLFxuICAgICAgbmV4dEN1cnNvcixcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIEl0ZXJhdGUgdGhyb3VnaCBhbGwgYWdlbnRzIHdpdGggYXV0b21hdGljIHBhZ2luYXRpb25cbiAgICovXG4gIGFzeW5jICpsaXN0QWdlbnRzSXRlcmF0b3Iob3B0aW9uczogT21pdDxBZ2VudExpc3RPcHRpb25zLCAnY3Vyc29yJz4gPSB7fSk6IEFzeW5jR2VuZXJhdG9yPEFnZW50PiB7XG4gICAgbGV0IGN1cnNvcjogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gICAgZG8ge1xuICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5saXN0QWdlbnRzKHsgLi4ub3B0aW9ucywgY3Vyc29yIH0pO1xuICAgICAgZm9yIChjb25zdCBhZ2VudCBvZiByZXN1bHQuaXRlbXMpIHtcbiAgICAgICAgeWllbGQgYWdlbnQ7XG4gICAgICB9XG4gICAgICBjdXJzb3IgPSByZXN1bHQubmV4dEN1cnNvcjtcbiAgICB9IHdoaWxlIChjdXJzb3IpO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldCBhIHBsdWdpbiBieSBJRFxuICAgKi9cbiAgYXN5bmMgZ2V0UGx1Z2luKGlkOiBudW1iZXIpOiBQcm9taXNlPFBsdWdpbiB8IG51bGw+IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnJwYy5nZXRfdGFibGVfcm93czxQbHVnaW5SYXc+KHtcbiAgICAgIGpzb246IHRydWUsXG4gICAgICBjb2RlOiB0aGlzLmNvbnRyYWN0LFxuICAgICAgc2NvcGU6IHRoaXMuY29udHJhY3QsXG4gICAgICB0YWJsZTogJ3BsdWdpbnMnLFxuICAgICAgbG93ZXJfYm91bmQ6IFN0cmluZyhpZCksXG4gICAgICB1cHBlcl9ib3VuZDogU3RyaW5nKGlkKSxcbiAgICAgIGxpbWl0OiAxLFxuICAgIH0pO1xuXG4gICAgaWYgKHJlc3VsdC5yb3dzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIG51bGw7XG4gICAgcmV0dXJuIHRoaXMucGFyc2VQbHVnaW4ocmVzdWx0LnJvd3NbMF0pO1xuICB9XG5cbiAgLyoqXG4gICAqIExpc3QgYWxsIHBsdWdpbnNcbiAgICovXG4gIGFzeW5jIGxpc3RQbHVnaW5zKGNhdGVnb3J5PzogUGx1Z2luQ2F0ZWdvcnkpOiBQcm9taXNlPFBsdWdpbltdPiB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5ycGMuZ2V0X3RhYmxlX3Jvd3M8UGx1Z2luUmF3Pih7XG4gICAgICBqc29uOiB0cnVlLFxuICAgICAgY29kZTogdGhpcy5jb250cmFjdCxcbiAgICAgIHNjb3BlOiB0aGlzLmNvbnRyYWN0LFxuICAgICAgdGFibGU6ICdwbHVnaW5zJyxcbiAgICAgIGxpbWl0OiAxMDAwLFxuICAgIH0pO1xuXG4gICAgbGV0IHBsdWdpbnMgPSByZXN1bHQucm93cy5tYXAoKHJvdykgPT4gdGhpcy5wYXJzZVBsdWdpbihyb3cpKTtcblxuICAgIGlmIChjYXRlZ29yeSkge1xuICAgICAgcGx1Z2lucyA9IHBsdWdpbnMuZmlsdGVyKChwKSA9PiBwLmNhdGVnb3J5ID09PSBjYXRlZ29yeSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHBsdWdpbnM7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHBsdWdpbnMgYXNzaWduZWQgdG8gYW4gYWdlbnRcbiAgICovXG4gIGFzeW5jIGdldEFnZW50UGx1Z2lucyhhY2NvdW50OiBzdHJpbmcpOiBQcm9taXNlPEFnZW50UGx1Z2luW10+IHtcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnJwYy5nZXRfdGFibGVfcm93czxBZ2VudFBsdWdpblJhdz4oe1xuICAgICAganNvbjogdHJ1ZSxcbiAgICAgIGNvZGU6IHRoaXMuY29udHJhY3QsXG4gICAgICBzY29wZTogdGhpcy5jb250cmFjdCxcbiAgICAgIHRhYmxlOiAnYWdlbnRwbHVncycsXG4gICAgICBpbmRleF9wb3NpdGlvbjogMixcbiAgICAgIGtleV90eXBlOiAnbmFtZScsXG4gICAgICBsb3dlcl9ib3VuZDogYWNjb3VudCxcbiAgICAgIHVwcGVyX2JvdW5kOiBhY2NvdW50LFxuICAgICAgbGltaXQ6IDEwMCxcbiAgICB9KTtcblxuICAgIHJldHVybiByZXN1bHQucm93cy5tYXAoKHJvdykgPT4gdGhpcy5wYXJzZUFnZW50UGx1Z2luKHJvdykpO1xuICB9XG5cbiAgLy8gTm90ZTogQWdlbnRzIHVzZSBzeXN0ZW0gc3Rha2luZyB2aWEgZW9zaW86OnZvdGVycyB0YWJsZSwgbm90IGNvbnRyYWN0LW1hbmFnZWQgc3Rha2luZ1xuICAvLyBUaGVyZSBpcyBubyB1bnN0YWtlcyB0YWJsZSBpbiBhZ2VudGNvcmUgLSBhZ2VudHMgc3Rha2UvdW5zdGFrZSB2aWEgc3lzdGVtIHJlc291cmNlc1xuICAvLyBVc2UgYWdlbnRjb3JlOjpnZXRhZ2VudGluZm8gYWN0aW9uIHRvIHF1ZXJ5IGFuIGFnZW50J3Mgc3lzdGVtIHN0YWtlXG5cbiAgLyoqXG4gICAqIEdldCB0cnVzdCBzY29yZSBmb3IgYW4gYWdlbnQgKDAtMTAwKVxuICAgKiBDb21iaW5lcyBLWUMgbGV2ZWwsIHN0YWtlLCByZXB1dGF0aW9uLCBhbmQgbG9uZ2V2aXR5XG4gICAqL1xuICBhc3luYyBnZXRUcnVzdFNjb3JlKGFjY291bnQ6IHN0cmluZyk6IFByb21pc2U8VHJ1c3RTY29yZSB8IG51bGw+IHtcbiAgICAvLyBHZXQgYWdlbnRcbiAgICBjb25zdCBhZ2VudCA9IGF3YWl0IHRoaXMuZ2V0QWdlbnQoYWNjb3VudCk7XG4gICAgaWYgKCFhZ2VudCkgcmV0dXJuIG51bGw7XG5cbiAgICAvLyBHZXQgYWdlbnQgc2NvcmUgZnJvbSBhZ2VudGZlZWRcbiAgICBjb25zdCBmZWVkQ29udHJhY3QgPSAnYWdlbnRmZWVkJzsgLy8gRGVmYXVsdCBmZWVkIGNvbnRyYWN0XG4gICAgY29uc3Qgc2NvcmVSZXN1bHQgPSBhd2FpdCB0aGlzLnJwYy5nZXRfdGFibGVfcm93czx7XG4gICAgICBhZ2VudDogc3RyaW5nO1xuICAgICAgdG90YWxfc2NvcmU6IHN0cmluZztcbiAgICAgIHRvdGFsX3dlaWdodDogc3RyaW5nO1xuICAgICAgZmVlZGJhY2tfY291bnQ6IHN0cmluZztcbiAgICAgIGF2Z19zY29yZTogc3RyaW5nO1xuICAgICAgbGFzdF91cGRhdGVkOiBzdHJpbmc7XG4gICAgfT4oe1xuICAgICAganNvbjogdHJ1ZSxcbiAgICAgIGNvZGU6IGZlZWRDb250cmFjdCxcbiAgICAgIHNjb3BlOiBmZWVkQ29udHJhY3QsXG4gICAgICB0YWJsZTogJ2FnZW50c2NvcmVzJyxcbiAgICAgIGxvd2VyX2JvdW5kOiBhY2NvdW50LFxuICAgICAgdXBwZXJfYm91bmQ6IGFjY291bnQsXG4gICAgICBsaW1pdDogMSxcbiAgICB9KTtcblxuICAgIGNvbnN0IGFnZW50U2NvcmU6IEFnZW50U2NvcmUgfCBudWxsID0gc2NvcmVSZXN1bHQucm93cy5sZW5ndGggPiAwXG4gICAgICA/IHtcbiAgICAgICAgICBhZ2VudDogc2NvcmVSZXN1bHQucm93c1swXS5hZ2VudCxcbiAgICAgICAgICB0b3RhbF9zY29yZTogc2FmZVBhcnNlSW50KHNjb3JlUmVzdWx0LnJvd3NbMF0udG90YWxfc2NvcmUpLFxuICAgICAgICAgIHRvdGFsX3dlaWdodDogc2FmZVBhcnNlSW50KHNjb3JlUmVzdWx0LnJvd3NbMF0udG90YWxfd2VpZ2h0KSxcbiAgICAgICAgICBmZWVkYmFja19jb3VudDogc2FmZVBhcnNlSW50KHNjb3JlUmVzdWx0LnJvd3NbMF0uZmVlZGJhY2tfY291bnQpLFxuICAgICAgICAgIGF2Z19zY29yZTogc2FmZVBhcnNlSW50KHNjb3JlUmVzdWx0LnJvd3NbMF0uYXZnX3Njb3JlKSxcbiAgICAgICAgICBsYXN0X3VwZGF0ZWQ6IHNhZmVQYXJzZUludChzY29yZVJlc3VsdC5yb3dzWzBdLmxhc3RfdXBkYXRlZCksXG4gICAgICAgIH1cbiAgICAgIDogbnVsbDtcblxuICAgIC8vIEdldCBLWUMgbGV2ZWwgZnJvbSB0aGUgT1dORVIgKG5vdCB0aGUgYWdlbnQpXG4gICAgLy8gVGhpcyBpcyB0aGUga2V5IGluc2lnaHQ6IGFnZW50cyBpbmhlcml0IHRydXN0IGZyb20gdGhlaXIgaHVtYW4gc3BvbnNvclxuICAgIGxldCBreWNMZXZlbCA9IDA7XG4gICAgaWYgKGFnZW50Lm93bmVyKSB7XG4gICAgICBjb25zdCBreWNSZXN1bHQgPSBhd2FpdCB0aGlzLnJwYy5nZXRfdGFibGVfcm93czx7XG4gICAgICAgIGFjYzogc3RyaW5nO1xuICAgICAgICBreWM6IEFycmF5PHsga3ljX2xldmVsOiBudW1iZXIgfCBzdHJpbmc7IGt5Y19wcm92aWRlcj86IHN0cmluZyB9PjtcbiAgICAgIH0+KHtcbiAgICAgICAganNvbjogdHJ1ZSxcbiAgICAgICAgY29kZTogJ2Vvc2lvLnByb3RvbicsXG4gICAgICAgIHNjb3BlOiAnZW9zaW8ucHJvdG9uJyxcbiAgICAgICAgdGFibGU6ICd1c2Vyc2luZm8nLFxuICAgICAgICBsb3dlcl9ib3VuZDogYWdlbnQub3duZXIsXG4gICAgICAgIHVwcGVyX2JvdW5kOiBhZ2VudC5vd25lcixcbiAgICAgICAgbGltaXQ6IDEsXG4gICAgICB9KTtcblxuICAgICAgaWYgKGt5Y1Jlc3VsdC5yb3dzLmxlbmd0aCA+IDAgJiYga3ljUmVzdWx0LnJvd3NbMF0ua3ljPy5sZW5ndGggPiAwKSB7XG4gICAgICAgIC8vIEZpbmQgdGhlIGhpZ2hlc3QgS1lDIGxldmVsLCBoYW5kbGluZyB2YXJpb3VzIGZvcm1hdHM6XG4gICAgICAgIC8vIC0gbnVtYmVyOiAzXG4gICAgICAgIC8vIC0gc3RyaW5nIG51bWJlcjogXCIzXCJcbiAgICAgICAgLy8gLSBwcm92aWRlcjpsZXZlbDogXCJtZXRhbGxpY3VzOjNcIlxuICAgICAgICAvLyAtIGNvbW1hLXNlcGFyYXRlZCBtdWx0aS1wcm92aWRlcjogXCJwcm92QTozLHByb3ZCOjFcIlxuICAgICAgICBjb25zdCBsZXZlbHM6IG51bWJlcltdID0gW107XG5cbiAgICAgICAgZm9yIChjb25zdCBrIG9mIGt5Y1Jlc3VsdC5yb3dzWzBdLmt5Yykge1xuICAgICAgICAgIGlmICh0eXBlb2Ygay5reWNfbGV2ZWwgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICBsZXZlbHMucHVzaChrLmt5Y19sZXZlbCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IGxldmVsU3RyID0gU3RyaW5nKGsua3ljX2xldmVsKTtcbiAgICAgICAgICAgIC8vIEhhbmRsZSBjb21tYS1zZXBhcmF0ZWQgbXVsdGktcHJvdmlkZXIgc3RyaW5ncyAoZS5nLiwgXCJwcm92QTozLHByb3ZCOjFcIilcbiAgICAgICAgICAgIGNvbnN0IHByb3ZpZGVycyA9IGxldmVsU3RyLnNwbGl0KCcsJyk7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IHByb3ZpZGVyIG9mIHByb3ZpZGVycykge1xuICAgICAgICAgICAgICBjb25zdCB0cmltbWVkID0gcHJvdmlkZXIudHJpbSgpO1xuICAgICAgICAgICAgICBpZiAodHJpbW1lZC5pbmNsdWRlcygnOicpKSB7XG4gICAgICAgICAgICAgICAgLy8gXCJwcm92aWRlcjpsZXZlbFwiIGZvcm1hdCAtIHRha2UgdGhlIGxldmVsIHBhcnRcbiAgICAgICAgICAgICAgICBjb25zdCBwYXJ0cyA9IHRyaW1tZWQuc3BsaXQoJzonKTtcbiAgICAgICAgICAgICAgICBjb25zdCBsZXZlbCA9IHBhcnNlSW50KHBhcnRzW3BhcnRzLmxlbmd0aCAtIDFdLCAxMCk7XG4gICAgICAgICAgICAgICAgaWYgKCFpc05hTihsZXZlbCkpIGxldmVscy5wdXNoKGxldmVsKTtcbiAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBQbGFpbiBudW1iZXIgc3RyaW5nXG4gICAgICAgICAgICAgICAgY29uc3QgbGV2ZWwgPSBwYXJzZUludCh0cmltbWVkLCAxMCk7XG4gICAgICAgICAgICAgICAgaWYgKCFpc05hTihsZXZlbCkpIGxldmVscy5wdXNoKGxldmVsKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFAyIEZJWDogU2FmZSBtYXggLSBmYWxsYmFjayB0byAwIGlmIG5vIHZhbGlkIGxldmVscyBmb3VuZFxuICAgICAgICAvLyBNYXRoLm1heCguLi5bXSkgcmV0dXJucyAtSW5maW5pdHksIHdoaWNoIHdvdWxkIHBvaXNvbiB0cnVzdCBzY29yZXNcbiAgICAgICAga3ljTGV2ZWwgPSBsZXZlbHMubGVuZ3RoID4gMCA/IE1hdGgubWF4KC4uLmxldmVscykgOiAwO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEdldCBzeXN0ZW0gc3Rha2UgZnJvbSBlb3Npbzo6dm90ZXJzXG4gICAgY29uc3Qgdm90ZXJzUmVzdWx0ID0gYXdhaXQgdGhpcy5ycGMuZ2V0X3RhYmxlX3Jvd3M8e1xuICAgICAgb3duZXI6IHN0cmluZztcbiAgICAgIHN0YWtlZDogc3RyaW5nO1xuICAgIH0+KHtcbiAgICAgIGpzb246IHRydWUsXG4gICAgICBjb2RlOiAnZW9zaW8nLFxuICAgICAgc2NvcGU6ICdlb3NpbycsXG4gICAgICB0YWJsZTogJ3ZvdGVycycsXG4gICAgICBsb3dlcl9ib3VuZDogYWNjb3VudCxcbiAgICAgIHVwcGVyX2JvdW5kOiBhY2NvdW50LFxuICAgICAgbGltaXQ6IDEsXG4gICAgfSk7XG5cbiAgICBsZXQgc3Rha2VBbW91bnQgPSAwO1xuICAgIGlmICh2b3RlcnNSZXN1bHQucm93cy5sZW5ndGggPiAwICYmIHZvdGVyc1Jlc3VsdC5yb3dzWzBdLnN0YWtlZCkge1xuICAgICAgc3Rha2VBbW91bnQgPSBzYWZlUGFyc2VJbnQodm90ZXJzUmVzdWx0LnJvd3NbMF0uc3Rha2VkKTtcbiAgICB9XG5cbiAgICByZXR1cm4gY2FsY3VsYXRlVHJ1c3RTY29yZShhZ2VudCwgYWdlbnRTY29yZSwga3ljTGV2ZWwsIHN0YWtlQW1vdW50KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgY29udHJhY3QgY29uZmlndXJhdGlvblxuICAgKi9cbiAgYXN5bmMgZ2V0Q29uZmlnKCk6IFByb21pc2U8QWdlbnRDb3JlQ29uZmlnPiB7XG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdGhpcy5ycGMuZ2V0X3RhYmxlX3Jvd3M8e1xuICAgICAgb3duZXI6IHN0cmluZztcbiAgICAgIG1pbl9zdGFrZTogc3RyaW5nO1xuICAgICAgcmVnaXN0cmF0aW9uX2ZlZTogc3RyaW5nO1xuICAgICAgY2xhaW1fZmVlOiBzdHJpbmc7XG4gICAgICBmZWVkX2NvbnRyYWN0OiBzdHJpbmc7XG4gICAgICB2YWxpZF9jb250cmFjdDogc3RyaW5nO1xuICAgICAgZXNjcm93X2NvbnRyYWN0OiBzdHJpbmc7XG4gICAgICBwYXVzZWQ6IG51bWJlcjtcbiAgICB9Pih7XG4gICAgICBqc29uOiB0cnVlLFxuICAgICAgY29kZTogdGhpcy5jb250cmFjdCxcbiAgICAgIHNjb3BlOiB0aGlzLmNvbnRyYWN0LFxuICAgICAgdGFibGU6ICdjb25maWcnLFxuICAgICAgbGltaXQ6IDEsXG4gICAgfSk7XG5cbiAgICBpZiAocmVzdWx0LnJvd3MubGVuZ3RoID09PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ0NvbnRyYWN0IG5vdCBpbml0aWFsaXplZCcpO1xuICAgIH1cblxuICAgIGNvbnN0IHJvdyA9IHJlc3VsdC5yb3dzWzBdO1xuICAgIHJldHVybiB7XG4gICAgICBvd25lcjogcm93Lm93bmVyLFxuICAgICAgbWluX3N0YWtlOiBzYWZlUGFyc2VJbnQocm93Lm1pbl9zdGFrZSksXG4gICAgICByZWdpc3RyYXRpb25fZmVlOiBzYWZlUGFyc2VJbnQocm93LnJlZ2lzdHJhdGlvbl9mZWUpLFxuICAgICAgY2xhaW1fZmVlOiBzYWZlUGFyc2VJbnQocm93LmNsYWltX2ZlZSksXG4gICAgICBmZWVkX2NvbnRyYWN0OiByb3cuZmVlZF9jb250cmFjdCxcbiAgICAgIHZhbGlkX2NvbnRyYWN0OiByb3cudmFsaWRfY29udHJhY3QsXG4gICAgICBlc2Nyb3dfY29udHJhY3Q6IHJvdy5lc2Nyb3dfY29udHJhY3QsXG4gICAgICBwYXVzZWQ6IHJvdy5wYXVzZWQgPT09IDEsXG4gICAgfTtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09IFdSSVRFIE9QRVJBVElPTlMgPT09PT09PT09PT09PT1cblxuICAvKipcbiAgICogUmVnaXN0ZXIgYSBuZXcgYWdlbnRcbiAgICovXG4gIGFzeW5jIHJlZ2lzdGVyKGRhdGE6IFJlZ2lzdGVyQWdlbnREYXRhKTogUHJvbWlzZTxUcmFuc2FjdGlvblJlc3VsdD4ge1xuICAgIHRoaXMucmVxdWlyZVNlc3Npb24oKTtcblxuICAgIC8vIFZhbGlkYXRlIGlucHV0IGJlZm9yZSBzZW5kaW5nIHRvIGJsb2NrY2hhaW5cbiAgICB2YWxpZGF0ZUFnZW50RGF0YSh7XG4gICAgICBuYW1lOiBkYXRhLm5hbWUsXG4gICAgICBkZXNjcmlwdGlvbjogZGF0YS5kZXNjcmlwdGlvbixcbiAgICAgIGVuZHBvaW50OiBkYXRhLmVuZHBvaW50LFxuICAgICAgcHJvdG9jb2w6IGRhdGEucHJvdG9jb2wsXG4gICAgICBjYXBhYmlsaXRpZXM6IGRhdGEuY2FwYWJpbGl0aWVzLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHRoaXMuc2Vzc2lvbiEubGluay50cmFuc2FjdCh7XG4gICAgICBhY3Rpb25zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBhY2NvdW50OiB0aGlzLmNvbnRyYWN0LFxuICAgICAgICAgIG5hbWU6ICdyZWdpc3RlcicsXG4gICAgICAgICAgYXV0aG9yaXphdGlvbjogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBhY3RvcjogdGhpcy5zZXNzaW9uIS5hdXRoLmFjdG9yLFxuICAgICAgICAgICAgICBwZXJtaXNzaW9uOiB0aGlzLnNlc3Npb24hLmF1dGgucGVybWlzc2lvbixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICBhY2NvdW50OiB0aGlzLnNlc3Npb24hLmF1dGguYWN0b3IsXG4gICAgICAgICAgICBuYW1lOiBkYXRhLm5hbWUsXG4gICAgICAgICAgICBkZXNjcmlwdGlvbjogZGF0YS5kZXNjcmlwdGlvbixcbiAgICAgICAgICAgIGVuZHBvaW50OiBkYXRhLmVuZHBvaW50LFxuICAgICAgICAgICAgcHJvdG9jb2w6IGRhdGEucHJvdG9jb2wsXG4gICAgICAgICAgICBjYXBhYmlsaXRpZXM6IEpTT04uc3RyaW5naWZ5KGRhdGEuY2FwYWJpbGl0aWVzKSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWdpc3RlciBhIG5ldyBhZ2VudCB3aXRoIHJlZ2lzdHJhdGlvbiBmZWUgaW4gb25lIHRyYW5zYWN0aW9uLlxuICAgKiBTZW5kcyB0aGUgZmVlIGRlcG9zaXQgYW5kIHJlZ2lzdGVycyBpbiBhIHNpbmdsZSB0eC5cbiAgICpcbiAgICogQHBhcmFtIGRhdGEgLSBBZ2VudCByZWdpc3RyYXRpb24gZGF0YVxuICAgKiBAcGFyYW0gYW1vdW50IC0gVGhlIHJlZ2lzdHJhdGlvbiBmZWUgKGUuZy4sIFwiMS4wMDAwIFhQUlwiKVxuICAgKi9cbiAgYXN5bmMgcmVnaXN0ZXJXaXRoRmVlKGRhdGE6IFJlZ2lzdGVyQWdlbnREYXRhLCBhbW91bnQ6IHN0cmluZyk6IFByb21pc2U8VHJhbnNhY3Rpb25SZXN1bHQ+IHtcbiAgICB0aGlzLnJlcXVpcmVTZXNzaW9uKCk7XG5cbiAgICB2YWxpZGF0ZUFnZW50RGF0YSh7XG4gICAgICBuYW1lOiBkYXRhLm5hbWUsXG4gICAgICBkZXNjcmlwdGlvbjogZGF0YS5kZXNjcmlwdGlvbixcbiAgICAgIGVuZHBvaW50OiBkYXRhLmVuZHBvaW50LFxuICAgICAgcHJvdG9jb2w6IGRhdGEucHJvdG9jb2wsXG4gICAgICBjYXBhYmlsaXRpZXM6IGRhdGEuY2FwYWJpbGl0aWVzLFxuICAgIH0pO1xuXG4gICAgY29uc3QgYWN0b3IgPSB0aGlzLnNlc3Npb24hLmF1dGguYWN0b3I7XG5cbiAgICByZXR1cm4gdGhpcy5zZXNzaW9uIS5saW5rLnRyYW5zYWN0KHtcbiAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGFjY291bnQ6ICdlb3Npby50b2tlbicsXG4gICAgICAgICAgbmFtZTogJ3RyYW5zZmVyJyxcbiAgICAgICAgICBhdXRob3JpemF0aW9uOiBbe1xuICAgICAgICAgICAgYWN0b3IsXG4gICAgICAgICAgICBwZXJtaXNzaW9uOiB0aGlzLnNlc3Npb24hLmF1dGgucGVybWlzc2lvbixcbiAgICAgICAgICB9XSxcbiAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICBmcm9tOiBhY3RvcixcbiAgICAgICAgICAgIHRvOiB0aGlzLmNvbnRyYWN0LFxuICAgICAgICAgICAgcXVhbnRpdHk6IGFtb3VudCxcbiAgICAgICAgICAgIG1lbW86IGByZWdmZWU6JHthY3Rvcn1gLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBhY2NvdW50OiB0aGlzLmNvbnRyYWN0LFxuICAgICAgICAgIG5hbWU6ICdyZWdpc3RlcicsXG4gICAgICAgICAgYXV0aG9yaXphdGlvbjogW3tcbiAgICAgICAgICAgIGFjdG9yLFxuICAgICAgICAgICAgcGVybWlzc2lvbjogdGhpcy5zZXNzaW9uIS5hdXRoLnBlcm1pc3Npb24sXG4gICAgICAgICAgfV0sXG4gICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgYWNjb3VudDogYWN0b3IsXG4gICAgICAgICAgICBuYW1lOiBkYXRhLm5hbWUsXG4gICAgICAgICAgICBkZXNjcmlwdGlvbjogZGF0YS5kZXNjcmlwdGlvbixcbiAgICAgICAgICAgIGVuZHBvaW50OiBkYXRhLmVuZHBvaW50LFxuICAgICAgICAgICAgcHJvdG9jb2w6IGRhdGEucHJvdG9jb2wsXG4gICAgICAgICAgICBjYXBhYmlsaXRpZXM6IEpTT04uc3RyaW5naWZ5KGRhdGEuY2FwYWJpbGl0aWVzKSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGUgYWdlbnQgbWV0YWRhdGFcbiAgICovXG4gIGFzeW5jIHVwZGF0ZShkYXRhOiBVcGRhdGVBZ2VudERhdGEpOiBQcm9taXNlPFRyYW5zYWN0aW9uUmVzdWx0PiB7XG4gICAgdGhpcy5yZXF1aXJlU2Vzc2lvbigpO1xuXG4gICAgLy8gVmFsaWRhdGUgaW5wdXQgYmVmb3JlIHNlbmRpbmcgdG8gYmxvY2tjaGFpblxuICAgIC8vIE9ubHkgdmFsaWRhdGUgZmllbGRzIHRoYXQgYXJlIHByb3ZpZGVkIChVcGRhdGVBZ2VudERhdGEgaGFzIG9wdGlvbmFsIGZpZWxkcylcbiAgICB2YWxpZGF0ZUFnZW50RGF0YSh7XG4gICAgICBuYW1lOiBkYXRhLm5hbWUsXG4gICAgICBkZXNjcmlwdGlvbjogZGF0YS5kZXNjcmlwdGlvbixcbiAgICAgIGVuZHBvaW50OiBkYXRhLmVuZHBvaW50LFxuICAgICAgcHJvdG9jb2w6IGRhdGEucHJvdG9jb2wsXG4gICAgICBjYXBhYmlsaXRpZXM6IGRhdGEuY2FwYWJpbGl0aWVzLFxuICAgIH0pO1xuXG4gICAgLy8gR2V0IGN1cnJlbnQgYWdlbnQgZGF0YSB0byBtZXJnZSB3aXRoIHVwZGF0ZXNcbiAgICBjb25zdCBjdXJyZW50ID0gYXdhaXQgdGhpcy5nZXRBZ2VudCh0aGlzLnNlc3Npb24hLmF1dGguYWN0b3IpO1xuICAgIGlmICghY3VycmVudCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdBZ2VudCBub3QgZm91bmQnKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5zZXNzaW9uIS5saW5rLnRyYW5zYWN0KHtcbiAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGFjY291bnQ6IHRoaXMuY29udHJhY3QsXG4gICAgICAgICAgbmFtZTogJ3VwZGF0ZScsXG4gICAgICAgICAgYXV0aG9yaXphdGlvbjogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBhY3RvcjogdGhpcy5zZXNzaW9uIS5hdXRoLmFjdG9yLFxuICAgICAgICAgICAgICBwZXJtaXNzaW9uOiB0aGlzLnNlc3Npb24hLmF1dGgucGVybWlzc2lvbixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICBhY2NvdW50OiB0aGlzLnNlc3Npb24hLmF1dGguYWN0b3IsXG4gICAgICAgICAgICBuYW1lOiBkYXRhLm5hbWUgPz8gY3VycmVudC5uYW1lLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IGRhdGEuZGVzY3JpcHRpb24gPz8gY3VycmVudC5kZXNjcmlwdGlvbixcbiAgICAgICAgICAgIGVuZHBvaW50OiBkYXRhLmVuZHBvaW50ID8/IGN1cnJlbnQuZW5kcG9pbnQsXG4gICAgICAgICAgICBwcm90b2NvbDogZGF0YS5wcm90b2NvbCA/PyBjdXJyZW50LnByb3RvY29sLFxuICAgICAgICAgICAgY2FwYWJpbGl0aWVzOiBKU09OLnN0cmluZ2lmeShkYXRhLmNhcGFiaWxpdGllcyA/PyBjdXJyZW50LmNhcGFiaWxpdGllcyksXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogU2V0IGFnZW50IGFjdGl2ZSBzdGF0dXNcbiAgICovXG4gIGFzeW5jIHNldFN0YXR1cyhhY3RpdmU6IGJvb2xlYW4pOiBQcm9taXNlPFRyYW5zYWN0aW9uUmVzdWx0PiB7XG4gICAgdGhpcy5yZXF1aXJlU2Vzc2lvbigpO1xuXG4gICAgcmV0dXJuIHRoaXMuc2Vzc2lvbiEubGluay50cmFuc2FjdCh7XG4gICAgICBhY3Rpb25zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBhY2NvdW50OiB0aGlzLmNvbnRyYWN0LFxuICAgICAgICAgIG5hbWU6ICdzZXRzdGF0dXMnLFxuICAgICAgICAgIGF1dGhvcml6YXRpb246IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgYWN0b3I6IHRoaXMuc2Vzc2lvbiEuYXV0aC5hY3RvcixcbiAgICAgICAgICAgICAgcGVybWlzc2lvbjogdGhpcy5zZXNzaW9uIS5hdXRoLnBlcm1pc3Npb24sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgYWNjb3VudDogdGhpcy5zZXNzaW9uIS5hdXRoLmFjdG9yLFxuICAgICAgICAgICAgYWN0aXZlLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pO1xuICB9XG5cbiAgLy8gPT09PT09PT09PT09PT0gU1lTVEVNIFNUQUtJTkcgTk9URSA9PT09PT09PT09PT09PVxuICAvLyBBZ2VudHMgdXNlIFhQUiBOZXR3b3JrJ3MgbmF0aXZlIHN5c3RlbSBzdGFraW5nIChlb3Npbzo6dm90ZXJzIHRhYmxlKVxuICAvLyBpbnN0ZWFkIG9mIGNvbnRyYWN0LW1hbmFnZWQgc3Rha2luZy4gVG8gc3Rha2UvdW5zdGFrZTpcbiAgLy9cbiAgLy8gMS4gU3Rha2U6IFVzZSBzeXN0ZW0gc3Rha2UgYWN0aW9uIG9yIHJlc291cmNlcy54cHJuZXR3b3JrLm9yZ1xuICAvLyAyLiBVbnN0YWtlOiBVc2Ugc3lzdGVtIHVuc3Rha2UgYWN0aW9uXG4gIC8vIDMuIFF1ZXJ5IHN0YWtlOiBDYWxsIGFnZW50Y29yZTo6Z2V0YWdlbnRpbmZvIGFjdGlvbiBvciBxdWVyeSBlb3Npbzo6dm90ZXJzIHRhYmxlXG4gIC8vXG4gIC8vIFRoaXMgZGVzaWduIGxldmVyYWdlcyB0aGUgZXhpc3Rpbmcgc3Rha2luZyBpbmZyYXN0cnVjdHVyZSBhbmQgYWxsb3dzXG4gIC8vIGFnZW50cyB0byBlYXJuIHN0YWtpbmcgcmV3YXJkcyB3aGlsZSBtZWV0aW5nIG1pbmltdW0gc3Rha2UgcmVxdWlyZW1lbnRzLlxuXG4gIC8qKlxuICAgKiBBZGQgcGx1Z2luIHRvIGFnZW50XG4gICAqL1xuICBhc3luYyBhZGRQbHVnaW4ocGx1Z2luSWQ6IG51bWJlciwgY29uZmlnOiBvYmplY3QgPSB7fSk6IFByb21pc2U8VHJhbnNhY3Rpb25SZXN1bHQ+IHtcbiAgICB0aGlzLnJlcXVpcmVTZXNzaW9uKCk7XG5cbiAgICByZXR1cm4gdGhpcy5zZXNzaW9uIS5saW5rLnRyYW5zYWN0KHtcbiAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGFjY291bnQ6IHRoaXMuY29udHJhY3QsXG4gICAgICAgICAgbmFtZTogJ2FkZHBsdWdpbicsXG4gICAgICAgICAgYXV0aG9yaXphdGlvbjogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBhY3RvcjogdGhpcy5zZXNzaW9uIS5hdXRoLmFjdG9yLFxuICAgICAgICAgICAgICBwZXJtaXNzaW9uOiB0aGlzLnNlc3Npb24hLmF1dGgucGVybWlzc2lvbixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICBhZ2VudDogdGhpcy5zZXNzaW9uIS5hdXRoLmFjdG9yLFxuICAgICAgICAgICAgcGx1Z2luX2lkOiBwbHVnaW5JZCxcbiAgICAgICAgICAgIHBsdWdpbkNvbmZpZzogSlNPTi5zdHJpbmdpZnkoY29uZmlnKSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmUgcGx1Z2luIGZyb20gYWdlbnRcbiAgICovXG4gIGFzeW5jIHJlbW92ZVBsdWdpbihhZ2VudFBsdWdpbklkOiBudW1iZXIpOiBQcm9taXNlPFRyYW5zYWN0aW9uUmVzdWx0PiB7XG4gICAgdGhpcy5yZXF1aXJlU2Vzc2lvbigpO1xuXG4gICAgcmV0dXJuIHRoaXMuc2Vzc2lvbiEubGluay50cmFuc2FjdCh7XG4gICAgICBhY3Rpb25zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBhY2NvdW50OiB0aGlzLmNvbnRyYWN0LFxuICAgICAgICAgIG5hbWU6ICdybXBsdWdpbicsXG4gICAgICAgICAgYXV0aG9yaXphdGlvbjogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBhY3RvcjogdGhpcy5zZXNzaW9uIS5hdXRoLmFjdG9yLFxuICAgICAgICAgICAgICBwZXJtaXNzaW9uOiB0aGlzLnNlc3Npb24hLmF1dGgucGVybWlzc2lvbixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICBhZ2VudDogdGhpcy5zZXNzaW9uIS5hdXRoLmFjdG9yLFxuICAgICAgICAgICAgYWdlbnRwbHVnaW5faWQ6IGFnZW50UGx1Z2luSWQsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmVnaXN0ZXIgYSBuZXcgcGx1Z2luXG4gICAqL1xuICBhc3luYyByZWdpc3RlclBsdWdpbihcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgdmVyc2lvbjogc3RyaW5nLFxuICAgIGNvbnRyYWN0OiBzdHJpbmcsXG4gICAgYWN0aW9uOiBzdHJpbmcsXG4gICAgc2NoZW1hOiBvYmplY3QsXG4gICAgY2F0ZWdvcnk6IFBsdWdpbkNhdGVnb3J5XG4gICk6IFByb21pc2U8VHJhbnNhY3Rpb25SZXN1bHQ+IHtcbiAgICB0aGlzLnJlcXVpcmVTZXNzaW9uKCk7XG5cbiAgICByZXR1cm4gdGhpcy5zZXNzaW9uIS5saW5rLnRyYW5zYWN0KHtcbiAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGFjY291bnQ6IHRoaXMuY29udHJhY3QsXG4gICAgICAgICAgbmFtZTogJ3JlZ3BsdWdpbicsXG4gICAgICAgICAgYXV0aG9yaXphdGlvbjogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBhY3RvcjogdGhpcy5zZXNzaW9uIS5hdXRoLmFjdG9yLFxuICAgICAgICAgICAgICBwZXJtaXNzaW9uOiB0aGlzLnNlc3Npb24hLmF1dGgucGVybWlzc2lvbixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICBhdXRob3I6IHRoaXMuc2Vzc2lvbiEuYXV0aC5hY3RvcixcbiAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICB2ZXJzaW9uLFxuICAgICAgICAgICAgY29udHJhY3QsXG4gICAgICAgICAgICBhY3Rpb24sXG4gICAgICAgICAgICBzY2hlbWE6IEpTT04uc3RyaW5naWZ5KHNjaGVtYSksXG4gICAgICAgICAgICBjYXRlZ29yeSxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KTtcbiAgfVxuXG4gIC8vID09PT09PT09PT09PT09IE9XTkVSU0hJUCA9PT09PT09PT09PT09PVxuXG4gIC8qKlxuICAgKiBTdGVwIDE6IEFnZW50IGFwcHJvdmVzIGEgaHVtYW4gdG8gY2xhaW0gdGhlbS5cbiAgICogVGhpcyBpcyBjYWxsZWQgYnkgdGhlIEFHRU5UIHRvIGdpdmUgY29uc2VudC5cbiAgICpcbiAgICogQHBhcmFtIG5ld093bmVyIC0gVGhlIEtZQydkIGh1bWFuIGJlaW5nIGFwcHJvdmVkIHRvIGNsYWltXG4gICAqL1xuICBhc3luYyBhcHByb3ZlQ2xhaW0obmV3T3duZXI6IHN0cmluZyk6IFByb21pc2U8VHJhbnNhY3Rpb25SZXN1bHQ+IHtcbiAgICB0aGlzLnJlcXVpcmVTZXNzaW9uKCk7XG5cbiAgICAvLyBUaGUgc2Vzc2lvbiBob2xkZXIgSVMgdGhlIGFnZW50IGdpdmluZyBjb25zZW50XG4gICAgY29uc3QgYWdlbnQgPSB0aGlzLnNlc3Npb24hLmF1dGguYWN0b3I7XG5cbiAgICByZXR1cm4gdGhpcy5zZXNzaW9uIS5saW5rLnRyYW5zYWN0KHtcbiAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGFjY291bnQ6IHRoaXMuY29udHJhY3QsXG4gICAgICAgICAgbmFtZTogJ2FwcHJvdmVjbGFpbScsXG4gICAgICAgICAgYXV0aG9yaXphdGlvbjogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBhY3RvcjogYWdlbnQsXG4gICAgICAgICAgICAgIHBlcm1pc3Npb246IHRoaXMuc2Vzc2lvbiEuYXV0aC5wZXJtaXNzaW9uLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgIGFnZW50LFxuICAgICAgICAgICAgbmV3X293bmVyOiBuZXdPd25lcixcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTdGVwIDI6IEh1bWFuIGNvbXBsZXRlcyB0aGUgY2xhaW0gYWZ0ZXIgYWdlbnQgYXBwcm92YWwuXG4gICAqIEFnZW50IG11c3QgaGF2ZSBjYWxsZWQgYXBwcm92ZUNsYWltIGZpcnN0LlxuICAgKlxuICAgKiBJTVBPUlRBTlQ6IEJlZm9yZSBjYWxsaW5nIHRoaXMsIHlvdSBtdXN0OlxuICAgKiAxLiBIYXZlIHRoZSBhZ2VudCBjYWxsIGFwcHJvdmVDbGFpbSh5b3VyQWNjb3VudClcbiAgICogMi4gU2VuZCB0aGUgY2xhaW0gZmVlIHdpdGggbWVtbyBcImNsYWltOmFnZW50bmFtZTp5b3VybmFtZVwiXG4gICAqXG4gICAqIEBwYXJhbSBhZ2VudCAtIFRoZSBhZ2VudCBhY2NvdW50IHRvIGNsYWltXG4gICAqL1xuICBhc3luYyBjbGFpbShhZ2VudDogc3RyaW5nKTogUHJvbWlzZTxUcmFuc2FjdGlvblJlc3VsdD4ge1xuICAgIHRoaXMucmVxdWlyZVNlc3Npb24oKTtcblxuICAgIGNvbnN0IG93bmVyID0gdGhpcy5zZXNzaW9uIS5hdXRoLmFjdG9yO1xuXG4gICAgcmV0dXJuIHRoaXMuc2Vzc2lvbiEubGluay50cmFuc2FjdCh7XG4gICAgICBhY3Rpb25zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBhY2NvdW50OiB0aGlzLmNvbnRyYWN0LFxuICAgICAgICAgIG5hbWU6ICdjbGFpbScsXG4gICAgICAgICAgYXV0aG9yaXphdGlvbjogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBhY3Rvcjogb3duZXIsXG4gICAgICAgICAgICAgIHBlcm1pc3Npb246IHRoaXMuc2Vzc2lvbiEuYXV0aC5wZXJtaXNzaW9uLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgIGFnZW50LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFNlbmQgY2xhaW0gZmVlIGFuZCBjb21wbGV0ZSB0aGUgY2xhaW0gaW4gb25lIHRyYW5zYWN0aW9uLlxuICAgKiBBZ2VudCBtdXN0IGhhdmUgYWxyZWFkeSBjYWxsZWQgYXBwcm92ZUNsYWltIGZpcnN0LlxuICAgKlxuICAgKiBAcGFyYW0gYWdlbnQgLSBUaGUgYWdlbnQgYWNjb3VudCB0byBjbGFpbVxuICAgKiBAcGFyYW0gYW1vdW50IC0gVGhlIGNsYWltIGZlZSBhbW91bnQgKGUuZy4sIFwiMS4wMDAwIFhQUlwiKVxuICAgKi9cbiAgYXN5bmMgY2xhaW1XaXRoRmVlKGFnZW50OiBzdHJpbmcsIGFtb3VudDogc3RyaW5nKTogUHJvbWlzZTxUcmFuc2FjdGlvblJlc3VsdD4ge1xuICAgIHRoaXMucmVxdWlyZVNlc3Npb24oKTtcblxuICAgIGNvbnN0IG93bmVyID0gdGhpcy5zZXNzaW9uIS5hdXRoLmFjdG9yO1xuXG4gICAgcmV0dXJuIHRoaXMuc2Vzc2lvbiEubGluay50cmFuc2FjdCh7XG4gICAgICBhY3Rpb25zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBhY2NvdW50OiAnZW9zaW8udG9rZW4nLFxuICAgICAgICAgIG5hbWU6ICd0cmFuc2ZlcicsXG4gICAgICAgICAgYXV0aG9yaXphdGlvbjogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBhY3Rvcjogb3duZXIsXG4gICAgICAgICAgICAgIHBlcm1pc3Npb246IHRoaXMuc2Vzc2lvbiEuYXV0aC5wZXJtaXNzaW9uLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgIGZyb206IG93bmVyLFxuICAgICAgICAgICAgdG86IHRoaXMuY29udHJhY3QsXG4gICAgICAgICAgICBxdWFudGl0eTogYW1vdW50LFxuICAgICAgICAgICAgbWVtbzogYGNsYWltOiR7YWdlbnR9OiR7b3duZXJ9YCxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgICB7XG4gICAgICAgICAgYWNjb3VudDogdGhpcy5jb250cmFjdCxcbiAgICAgICAgICBuYW1lOiAnY2xhaW0nLFxuICAgICAgICAgIGF1dGhvcml6YXRpb246IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgYWN0b3I6IG93bmVyLFxuICAgICAgICAgICAgICBwZXJtaXNzaW9uOiB0aGlzLnNlc3Npb24hLmF1dGgucGVybWlzc2lvbixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgXSxcbiAgICAgICAgICBkYXRhOiB7XG4gICAgICAgICAgICBhZ2VudCxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYW5jZWwgYSBwZW5kaW5nIGNsYWltIGFwcHJvdmFsLlxuICAgKiBPbmx5IHRoZSBhZ2VudCBjYW4gY2FuY2VsIHRoZWlyIG93biBhcHByb3ZhbC5cbiAgICogQW55IGRlcG9zaXQgd2lsbCBiZSByZWZ1bmRlZCB0byB0aGUgcGF5ZXIuXG4gICAqXG4gICAqIE5PVEU6IFRoZSBzZXNzaW9uIGhvbGRlciBtdXN0IGJlIHRoZSBhZ2VudCBhY2NvdW50LlxuICAgKi9cbiAgYXN5bmMgY2FuY2VsQ2xhaW0oKTogUHJvbWlzZTxUcmFuc2FjdGlvblJlc3VsdD4ge1xuICAgIHRoaXMucmVxdWlyZVNlc3Npb24oKTtcblxuICAgIGNvbnN0IGFnZW50ID0gdGhpcy5zZXNzaW9uIS5hdXRoLmFjdG9yO1xuXG4gICAgcmV0dXJuIHRoaXMuc2Vzc2lvbiEubGluay50cmFuc2FjdCh7XG4gICAgICBhY3Rpb25zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBhY2NvdW50OiB0aGlzLmNvbnRyYWN0LFxuICAgICAgICAgIG5hbWU6ICdjYW5jZWxjbGFpbScsXG4gICAgICAgICAgYXV0aG9yaXphdGlvbjogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBhY3RvcjogYWdlbnQsXG4gICAgICAgICAgICAgIHBlcm1pc3Npb246IHRoaXMuc2Vzc2lvbiEuYXV0aC5wZXJtaXNzaW9uLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgIGFnZW50LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRyYW5zZmVyIG93bmVyc2hpcCBvZiBhbiBhZ2VudCB0byBhIG5ldyBvd25lci5cbiAgICpcbiAgICogSU1QT1JUQU5UOiBUaGUgY29udHJhY3QgcmVxdWlyZXMgVEhSRUUgc2lnbmF0dXJlczpcbiAgICogMS4gQ3VycmVudCBvd25lciAobXVzdCBhdXRob3JpemUpXG4gICAqIDIuIE5ldyBvd25lciAobXVzdCBhdXRob3JpemUpXG4gICAqIDMuIEFnZW50IGl0c2VsZiAobXVzdCBjb25zZW50IHRvIHRoZSB0cmFuc2ZlcilcbiAgICpcbiAgICogVGhpcyBtZXRob2QgaW5jbHVkZXMgb25seSB0aGUgc2Vzc2lvbiBob2xkZXIncyBhdXRob3JpemF0aW9uLlxuICAgKiBJdCB3aWxsIEZBSUwgdW5sZXNzIHRoZSBzZXNzaW9uIGhvbGRlciBjb250cm9scyBhbGwgdGhyZWUgYWNjb3VudHMsXG4gICAqIHdoaWNoIGlzIHJhcmUgaW4gcHJhY3RpY2UuXG4gICAqXG4gICAqIEZvciBtb3N0IHVzZSBjYXNlcywgdXNlIGBidWlsZFRyYW5zZmVyUHJvcG9zYWwoKWAgdG8gY3JlYXRlIGEgbXVsdGktc2lnXG4gICAqIHByb3Bvc2FsIHRoYXQgY2FuIGJlIHNpZ25lZCBieSBhbGwgdGhyZWUgcGFydGllcy5cbiAgICpcbiAgICogQHBhcmFtIGFnZW50IC0gVGhlIGFnZW50IGFjY291bnRcbiAgICogQHBhcmFtIG5ld093bmVyIC0gVGhlIG5ldyBvd25lciAobXVzdCBoYXZlIEtZQylcbiAgICogQHRocm93cyBXaWxsIGZhaWwgaWYgc2Vzc2lvbiBob2xkZXIgZG9lc24ndCBjb250cm9sIGFsbCAzIHJlcXVpcmVkIGFjY291bnRzXG4gICAqL1xuICBhc3luYyB0cmFuc2Zlck93bmVyc2hpcChhZ2VudDogc3RyaW5nLCBuZXdPd25lcjogc3RyaW5nKTogUHJvbWlzZTxUcmFuc2FjdGlvblJlc3VsdD4ge1xuICAgIHRoaXMucmVxdWlyZVNlc3Npb24oKTtcblxuICAgIC8vIFAyIEZJWDogV2FybiBhYm91dCB0aGUgdGhyZWUtc2lnbmF0dXJlIHJlcXVpcmVtZW50XG4gICAgY29uc29sZS53YXJuKFxuICAgICAgJ3RyYW5zZmVyT3duZXJzaGlwIHJlcXVpcmVzIDMgc2lnbmF0dXJlcyAoY3VycmVudCBvd25lciwgbmV3IG93bmVyLCBhZ2VudCkuICcgK1xuICAgICAgJ1RoaXMgd2lsbCBmYWlsIHVubGVzcyBzZXNzaW9uIGNvbnRyb2xzIGFsbCBhY2NvdW50cy4gVXNlIGJ1aWxkVHJhbnNmZXJQcm9wb3NhbCgpIGZvciBtdWx0aS1zaWcuJ1xuICAgICk7XG5cbiAgICByZXR1cm4gdGhpcy5zZXNzaW9uIS5saW5rLnRyYW5zYWN0KHtcbiAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGFjY291bnQ6IHRoaXMuY29udHJhY3QsXG4gICAgICAgICAgbmFtZTogJ3RyYW5zZmVyJyxcbiAgICAgICAgICBhdXRob3JpemF0aW9uOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGFjdG9yOiB0aGlzLnNlc3Npb24hLmF1dGguYWN0b3IsXG4gICAgICAgICAgICAgIHBlcm1pc3Npb246IHRoaXMuc2Vzc2lvbiEuYXV0aC5wZXJtaXNzaW9uLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgIGFnZW50LFxuICAgICAgICAgICAgbmV3X293bmVyOiBuZXdPd25lcixcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCdWlsZCBhIHRyYW5zZmVyIG93bmVyc2hpcCBhY3Rpb24gZm9yIHVzZSBpbiBhIG11bHRpLXNpZyBwcm9wb3NhbC5cbiAgICogUmV0dXJucyB0aGUgYWN0aW9uIGRhdGEgdGhhdCBjYW4gYmUgdXNlZCB3aXRoIG1zaWcucHJvcG9zZS5cbiAgICpcbiAgICogVGhlIHRyYW5zZmVyIHJlcXVpcmVzIHNpZ25hdHVyZXMgZnJvbTpcbiAgICogMS4gQ3VycmVudCBvd25lclxuICAgKiAyLiBOZXcgb3duZXJcbiAgICogMy4gQWdlbnQgaXRzZWxmXG4gICAqXG4gICAqIEBwYXJhbSBhZ2VudCAtIFRoZSBhZ2VudCBhY2NvdW50XG4gICAqIEBwYXJhbSBjdXJyZW50T3duZXIgLSBUaGUgY3VycmVudCBvd25lciBhY2NvdW50XG4gICAqIEBwYXJhbSBuZXdPd25lciAtIFRoZSBuZXcgb3duZXIgYWNjb3VudCAobXVzdCBoYXZlIEtZQylcbiAgICogQHJldHVybnMgQWN0aW9uIGRhdGEgZm9yIG11bHRpLXNpZyBwcm9wb3NhbFxuICAgKi9cbiAgYnVpbGRUcmFuc2ZlclByb3Bvc2FsKGFnZW50OiBzdHJpbmcsIGN1cnJlbnRPd25lcjogc3RyaW5nLCBuZXdPd25lcjogc3RyaW5nKToge1xuICAgIGFjY291bnQ6IHN0cmluZztcbiAgICBuYW1lOiBzdHJpbmc7XG4gICAgYXV0aG9yaXphdGlvbjogQXJyYXk8eyBhY3Rvcjogc3RyaW5nOyBwZXJtaXNzaW9uOiBzdHJpbmcgfT47XG4gICAgZGF0YTogeyBhZ2VudDogc3RyaW5nOyBuZXdfb3duZXI6IHN0cmluZyB9O1xuICB9IHtcbiAgICByZXR1cm4ge1xuICAgICAgYWNjb3VudDogdGhpcy5jb250cmFjdCxcbiAgICAgIG5hbWU6ICd0cmFuc2ZlcicsXG4gICAgICBhdXRob3JpemF0aW9uOiBbXG4gICAgICAgIHsgYWN0b3I6IGN1cnJlbnRPd25lciwgcGVybWlzc2lvbjogJ2FjdGl2ZScgfSxcbiAgICAgICAgeyBhY3RvcjogbmV3T3duZXIsIHBlcm1pc3Npb246ICdhY3RpdmUnIH0sXG4gICAgICAgIHsgYWN0b3I6IGFnZW50LCBwZXJtaXNzaW9uOiAnYWN0aXZlJyB9LFxuICAgICAgXSxcbiAgICAgIGRhdGE6IHtcbiAgICAgICAgYWdlbnQsXG4gICAgICAgIG5ld19vd25lcjogbmV3T3duZXIsXG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogUmVsZWFzZSBvd25lcnNoaXAgb2YgYW4gYWdlbnQuXG4gICAqIE9ubHkgdGhlIGN1cnJlbnQgb3duZXIgY2FuIHJlbGVhc2UuXG4gICAqIENsYWltIGRlcG9zaXQgaXMgcmVmdW5kZWQgdG8gdGhlIG93bmVyLlxuICAgKlxuICAgKiBAcGFyYW0gYWdlbnQgLSBUaGUgYWdlbnQgYWNjb3VudCB0byByZWxlYXNlXG4gICAqL1xuICBhc3luYyByZWxlYXNlKGFnZW50OiBzdHJpbmcpOiBQcm9taXNlPFRyYW5zYWN0aW9uUmVzdWx0PiB7XG4gICAgdGhpcy5yZXF1aXJlU2Vzc2lvbigpO1xuXG4gICAgcmV0dXJuIHRoaXMuc2Vzc2lvbiEubGluay50cmFuc2FjdCh7XG4gICAgICBhY3Rpb25zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBhY2NvdW50OiB0aGlzLmNvbnRyYWN0LFxuICAgICAgICAgIG5hbWU6ICdyZWxlYXNlJyxcbiAgICAgICAgICBhdXRob3JpemF0aW9uOiBbXG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgIGFjdG9yOiB0aGlzLnNlc3Npb24hLmF1dGguYWN0b3IsXG4gICAgICAgICAgICAgIHBlcm1pc3Npb246IHRoaXMuc2Vzc2lvbiEuYXV0aC5wZXJtaXNzaW9uLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIGRhdGE6IHtcbiAgICAgICAgICAgIGFnZW50LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFZlcmlmeSBhbiBhZ2VudCdzIG93bmVyIHN0aWxsIGhhcyB2YWxpZCBLWUMuXG4gICAqIEFueW9uZSBjYW4gY2FsbCB0aGlzIHRvIHRyaWdnZXIgcmUtdmVyaWZpY2F0aW9uLlxuICAgKlxuICAgKiBJZiB0aGUgb3duZXIncyBLWUMgaGFzIGRyb3BwZWQgYmVsb3cgbGV2ZWwgMSwgdGhlIG93bmVyc2hpcFxuICAgKiBpcyByZW1vdmVkIGFuZCB0aGUgY2xhaW0gZGVwb3NpdCBpcyByZWZ1bmRlZCB0byB0aGUgZm9ybWVyIG93bmVyLlxuICAgKlxuICAgKiBUaGlzIGhlbHBzIG1haW50YWluIHRydXN0IHNjb3JlIGludGVncml0eSBieSBhbGxvd2luZyBjb21tdW5pdHlcbiAgICogZW5mb3JjZW1lbnQgb2YgS1lDIHJlcXVpcmVtZW50cy5cbiAgICpcbiAgICogQHBhcmFtIGFnZW50IC0gVGhlIGFnZW50IGFjY291bnQgdG8gdmVyaWZ5XG4gICAqL1xuICBhc3luYyB2ZXJpZnlDbGFpbShhZ2VudDogc3RyaW5nKTogUHJvbWlzZTxUcmFuc2FjdGlvblJlc3VsdD4ge1xuICAgIHRoaXMucmVxdWlyZVNlc3Npb24oKTtcblxuICAgIHJldHVybiB0aGlzLnNlc3Npb24hLmxpbmsudHJhbnNhY3Qoe1xuICAgICAgYWN0aW9uczogW1xuICAgICAgICB7XG4gICAgICAgICAgYWNjb3VudDogdGhpcy5jb250cmFjdCxcbiAgICAgICAgICBuYW1lOiAndmVyaWZ5Y2xhaW0nLFxuICAgICAgICAgIGF1dGhvcml6YXRpb246IFtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgYWN0b3I6IHRoaXMuc2Vzc2lvbiEuYXV0aC5hY3RvcixcbiAgICAgICAgICAgICAgcGVybWlzc2lvbjogdGhpcy5zZXNzaW9uIS5hdXRoLnBlcm1pc3Npb24sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIF0sXG4gICAgICAgICAgZGF0YToge1xuICAgICAgICAgICAgYWdlbnQsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogR2V0IGFnZW50cyBvd25lZCBieSBhIHNwZWNpZmljIGFjY291bnRcbiAgICovXG4gIGFzeW5jIGdldEFnZW50c0J5T3duZXIob3duZXI6IHN0cmluZywgbGltaXQ6IG51bWJlciA9IDEwMCk6IFByb21pc2U8QWdlbnRbXT4ge1xuICAgIC8vIFVzZSBzZWNvbmRhcnkgaW5kZXggdG8gcXVlcnkgYnkgb3duZXJcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCB0aGlzLnJwYy5nZXRfdGFibGVfcm93czxBZ2VudFJhdz4oe1xuICAgICAganNvbjogdHJ1ZSxcbiAgICAgIGNvZGU6IHRoaXMuY29udHJhY3QsXG4gICAgICBzY29wZTogdGhpcy5jb250cmFjdCxcbiAgICAgIHRhYmxlOiAnYWdlbnRzJyxcbiAgICAgIGluZGV4X3Bvc2l0aW9uOiAyLCAvLyBieU93bmVyIHNlY29uZGFyeSBpbmRleFxuICAgICAga2V5X3R5cGU6ICduYW1lJyxcbiAgICAgIGxvd2VyX2JvdW5kOiBvd25lcixcbiAgICAgIHVwcGVyX2JvdW5kOiBvd25lcixcbiAgICAgIGxpbWl0LFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHJlc3VsdC5yb3dzLm1hcCgocm93KSA9PiB0aGlzLnBhcnNlQWdlbnQocm93KSk7XG4gIH1cblxuICAvLyA9PT09PT09PT09PT09PSBIRUxQRVJTID09PT09PT09PT09PT09XG5cbiAgcHJpdmF0ZSByZXF1aXJlU2Vzc2lvbigpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuc2Vzc2lvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdTZXNzaW9uIHJlcXVpcmVkIGZvciB3cml0ZSBvcGVyYXRpb25zJyk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBwYXJzZUFnZW50KHJhdzogQWdlbnRSYXcpOiBBZ2VudCB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGFjY291bnQ6IHJhdy5hY2NvdW50LFxuICAgICAgb3duZXI6IHJhdy5vd25lciB8fCBudWxsLCAgLy8gRW1wdHkgc3RyaW5nIG1lYW5zIG5vIG93bmVyXG4gICAgICBwZW5kaW5nX293bmVyOiByYXcucGVuZGluZ19vd25lciB8fCBudWxsLFxuICAgICAgbmFtZTogcmF3Lm5hbWUsXG4gICAgICBkZXNjcmlwdGlvbjogcmF3LmRlc2NyaXB0aW9uLFxuICAgICAgZW5kcG9pbnQ6IHJhdy5lbmRwb2ludCxcbiAgICAgIHByb3RvY29sOiByYXcucHJvdG9jb2wsXG4gICAgICBjYXBhYmlsaXRpZXM6IHBhcnNlQ2FwYWJpbGl0aWVzKHJhdy5jYXBhYmlsaXRpZXMpLFxuICAgICAgdG90YWxfam9iczogc2FmZVBhcnNlSW50KHJhdy50b3RhbF9qb2JzKSxcbiAgICAgIHJlZ2lzdGVyZWRfYXQ6IHNhZmVQYXJzZUludChyYXcucmVnaXN0ZXJlZF9hdCksXG4gICAgICBhY3RpdmU6IHJhdy5hY3RpdmUgPT09IDEsXG4gICAgICBjbGFpbV9kZXBvc2l0OiBzYWZlUGFyc2VJbnQocmF3LmNsYWltX2RlcG9zaXQpLFxuICAgICAgZGVwb3NpdF9wYXllcjogcmF3LmRlcG9zaXRfcGF5ZXIgfHwgbnVsbCxcbiAgICAgIC8vIE5vdGU6IHN0YWtlIGlzIHF1ZXJpZWQgZnJvbSBzeXN0ZW0gc3Rha2luZyAoZW9zaW86OnZvdGVycyksIG5vdCBzdG9yZWQgaGVyZVxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIHBhcnNlUGx1Z2luKHJhdzogUGx1Z2luUmF3KTogUGx1Z2luIHtcbiAgICByZXR1cm4ge1xuICAgICAgaWQ6IHNhZmVQYXJzZUludChyYXcuaWQpLFxuICAgICAgbmFtZTogcmF3Lm5hbWUsXG4gICAgICB2ZXJzaW9uOiByYXcudmVyc2lvbixcbiAgICAgIGNvbnRyYWN0OiByYXcuY29udHJhY3QsXG4gICAgICBhY3Rpb246IHJhdy5hY3Rpb24sXG4gICAgICBzY2hlbWE6IHNhZmVKc29uUGFyc2UocmF3LnNjaGVtYSwge30pLFxuICAgICAgY2F0ZWdvcnk6IHJhdy5jYXRlZ29yeSBhcyBQbHVnaW5DYXRlZ29yeSxcbiAgICAgIGF1dGhvcjogcmF3LmF1dGhvcixcbiAgICAgIHZlcmlmaWVkOiByYXcudmVyaWZpZWQgPT09IDEsXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgcGFyc2VBZ2VudFBsdWdpbihyYXc6IEFnZW50UGx1Z2luUmF3KTogQWdlbnRQbHVnaW4ge1xuICAgIHJldHVybiB7XG4gICAgICBpZDogc2FmZVBhcnNlSW50KHJhdy5pZCksXG4gICAgICBhZ2VudDogcmF3LmFnZW50LFxuICAgICAgcGx1Z2luX2lkOiBzYWZlUGFyc2VJbnQocmF3LnBsdWdpbl9pZCksXG4gICAgICBjb25maWc6IHNhZmVKc29uUGFyc2UocmF3LmNvbmZpZywge30pLFxuICAgICAgZW5hYmxlZDogcmF3LmVuYWJsZWQgPT09IDEsXG4gICAgfTtcbiAgfVxufVxuIl19
|