experimental-agent 0.7.1 → 0.8.0-alpha.2

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.
@@ -0,0 +1,43 @@
1
+ import { F as Framework } from '../framework-c9fvEy0o.mjs';
2
+ import { NextConfig } from 'next';
3
+ import '../types-B3lbsOa7.mjs';
4
+
5
+ /** A Next.js config object or async config function. */
6
+ type NextConfigInput = NextConfig | ((phase: string, ctx: {
7
+ defaultConfig: NextConfig;
8
+ }) => Promise<NextConfig>);
9
+ /** Options for {@link withAgents}. */
10
+ type WithAgentsConfig = {
11
+ /**
12
+ * Path to the agents directory, relative to the project root.
13
+ * When omitted, auto-detected as the first existing directory
14
+ * among `src/agents` and `agents`.
15
+ */
16
+ agentsDir?: string;
17
+ /** Enable verbose logging to stdout. */
18
+ debug?: boolean;
19
+ };
20
+
21
+ /**
22
+ * Next.js config wrapper that discovers agents on the filesystem and
23
+ * generates the route handler + registry files needed to serve them.
24
+ *
25
+ * Call this in `next.config.ts`:
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * import { withAgents } from "experimental-agent/next/agents";
30
+ *
31
+ * export default withAgents({ reactStrictMode: true });
32
+ * ```
33
+ *
34
+ * Debug logs:
35
+ * ```ts
36
+ * import { withAgents } from "experimental-agent/next/agents";
37
+ *
38
+ * export default withAgents({ reactStrictMode: true }, { debug: true });
39
+ * ```
40
+ */
41
+ declare function withAgents(config: NextConfigInput, agentsConfig?: Pick<ConstructorParameters<typeof Framework>[0], "agentsDir" | "debug">): NextConfigInput;
42
+
43
+ export { type NextConfigInput, type WithAgentsConfig, withAgents };
@@ -0,0 +1,43 @@
1
+ import { F as Framework } from '../framework-DH4Z1NLV.js';
2
+ import { NextConfig } from 'next';
3
+ import '../types-B3lbsOa7.js';
4
+
5
+ /** A Next.js config object or async config function. */
6
+ type NextConfigInput = NextConfig | ((phase: string, ctx: {
7
+ defaultConfig: NextConfig;
8
+ }) => Promise<NextConfig>);
9
+ /** Options for {@link withAgents}. */
10
+ type WithAgentsConfig = {
11
+ /**
12
+ * Path to the agents directory, relative to the project root.
13
+ * When omitted, auto-detected as the first existing directory
14
+ * among `src/agents` and `agents`.
15
+ */
16
+ agentsDir?: string;
17
+ /** Enable verbose logging to stdout. */
18
+ debug?: boolean;
19
+ };
20
+
21
+ /**
22
+ * Next.js config wrapper that discovers agents on the filesystem and
23
+ * generates the route handler + registry files needed to serve them.
24
+ *
25
+ * Call this in `next.config.ts`:
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * import { withAgents } from "experimental-agent/next/agents";
30
+ *
31
+ * export default withAgents({ reactStrictMode: true });
32
+ * ```
33
+ *
34
+ * Debug logs:
35
+ * ```ts
36
+ * import { withAgents } from "experimental-agent/next/agents";
37
+ *
38
+ * export default withAgents({ reactStrictMode: true }, { debug: true });
39
+ * ```
40
+ */
41
+ declare function withAgents(config: NextConfigInput, agentsConfig?: Pick<ConstructorParameters<typeof Framework>[0], "agentsDir" | "debug">): NextConfigInput;
42
+
43
+ export { type NextConfigInput, type WithAgentsConfig, withAgents };
@@ -0,0 +1,364 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/framework-next/agents-plugin.ts
31
+ var agents_plugin_exports = {};
32
+ __export(agents_plugin_exports, {
33
+ withAgents: () => withAgents
34
+ });
35
+ module.exports = __toCommonJS(agents_plugin_exports);
36
+
37
+ // src/framework/generate.ts
38
+ var fs = __toESM(require("fs"));
39
+ var path = __toESM(require("path"));
40
+ var TS_IMPORT_EXT = /\.(ts|mts)$/;
41
+ function generateRegistry(opts) {
42
+ const entries = opts.agents.map(
43
+ (agent) => inlineEntry({ agent, outputDir: opts.outputDir })
44
+ );
45
+ return [
46
+ "// Auto-generated by withAgents - do not edit",
47
+ 'import type { AgentRegistry } from "experimental-agent/framework";',
48
+ "",
49
+ "export const agents = {",
50
+ ...entries,
51
+ "} satisfies AgentRegistry;",
52
+ ""
53
+ ].join("\n");
54
+ }
55
+ function inlineEntry(opts) {
56
+ const config = buildConfig(opts.agent);
57
+ const configStr = JSON.stringify(config, null, 2).split("\n").map((line, i) => i === 0 ? line : ` ${line}`).join("\n");
58
+ const parts = [` config: ${configStr}`];
59
+ if (opts.agent.hasAgentConfig) {
60
+ const configPath = findAgentConfigPath(opts.agent.absolutePath);
61
+ const relativePath = relativeImportPath({
62
+ from: opts.outputDir,
63
+ to: configPath
64
+ });
65
+ parts.push(` import: () => import(${JSON.stringify(relativePath)})`);
66
+ }
67
+ return ` ${JSON.stringify(opts.agent.name)}: {
68
+ ${parts.join(",\n")}
69
+ },`;
70
+ }
71
+ function buildConfig(agent) {
72
+ const config = {};
73
+ if (agent.systemPrompt) {
74
+ config.system = agent.systemPrompt;
75
+ }
76
+ if (agent.skills.length > 0) {
77
+ config.skills = agent.skills;
78
+ }
79
+ return config;
80
+ }
81
+ function findAgentConfigPath(agentDir) {
82
+ const extensions = [".ts", ".js", ".mts", ".mjs"];
83
+ for (const ext of extensions) {
84
+ const candidate = path.join(agentDir, `agent${ext}`);
85
+ if (fs.existsSync(candidate)) {
86
+ return candidate;
87
+ }
88
+ }
89
+ return path.join(agentDir, "agent");
90
+ }
91
+ function relativeImportPath(opts) {
92
+ let rel = path.relative(opts.from, opts.to).replace(/\\/g, "/");
93
+ rel = rel.replace(TS_IMPORT_EXT, "");
94
+ if (!rel.startsWith(".")) {
95
+ rel = `./${rel}`;
96
+ }
97
+ return rel;
98
+ }
99
+
100
+ // src/framework/scan.ts
101
+ var fs2 = __toESM(require("fs"));
102
+ var path2 = __toESM(require("path"));
103
+ var AGENT_CONFIG_FILES = ["agent.ts", "agent.js", "agent.mts", "agent.mjs"];
104
+ var MD_EXT = /\.md$/;
105
+ var TS_EXT = /\.(ts|js|mts|mjs)$/;
106
+ function listDir(dir) {
107
+ if (!fs2.existsSync(dir)) {
108
+ return [];
109
+ }
110
+ return fs2.readdirSync(dir);
111
+ }
112
+ function readFile(filePath) {
113
+ return fs2.readFileSync(filePath, "utf-8");
114
+ }
115
+ function fileExists(filePath) {
116
+ return fs2.existsSync(filePath);
117
+ }
118
+ function isDirectory(filePath) {
119
+ return fs2.existsSync(filePath) && fs2.statSync(filePath).isDirectory();
120
+ }
121
+ function discoverAgentDirs(agentsRoot) {
122
+ const entries = listDir(agentsRoot);
123
+ const dirs = [];
124
+ for (const entry of entries) {
125
+ const absolutePath = path2.join(agentsRoot, entry);
126
+ if (!isDirectory(absolutePath)) {
127
+ continue;
128
+ }
129
+ if (entry.startsWith(".")) {
130
+ continue;
131
+ }
132
+ dirs.push({
133
+ name: entry,
134
+ absolutePath,
135
+ hasAgentConfig: hasAgentConfig(absolutePath)
136
+ });
137
+ }
138
+ return dirs;
139
+ }
140
+ function hasAgentConfig(agentDir) {
141
+ return AGENT_CONFIG_FILES.some((f) => fileExists(path2.join(agentDir, f)));
142
+ }
143
+ function getSkills(agentDir) {
144
+ const skillsDir = path2.join(agentDir, "skills");
145
+ const entries = listDir(skillsDir);
146
+ const skills = [];
147
+ const tsSkillImportPaths = [];
148
+ for (const entry of entries.sort()) {
149
+ const absolutePath = path2.join(skillsDir, entry);
150
+ if (MD_EXT.test(entry)) {
151
+ skills.push({
152
+ type: "host",
153
+ path: absolutePath
154
+ });
155
+ } else if (TS_EXT.test(entry)) {
156
+ tsSkillImportPaths.push(absolutePath);
157
+ }
158
+ }
159
+ return { skills, tsSkillImportPaths };
160
+ }
161
+ function getSystemPrompt(agentDir) {
162
+ const systemDir = path2.join(agentDir, "system");
163
+ const entries = listDir(systemDir);
164
+ const mdFiles = entries.filter((e) => MD_EXT.test(e)).sort();
165
+ if (mdFiles.length === 0) {
166
+ return void 0;
167
+ }
168
+ const parts = [];
169
+ for (const file of mdFiles) {
170
+ const content = readFile(path2.join(systemDir, file)).trim();
171
+ if (content) {
172
+ parts.push(content);
173
+ }
174
+ }
175
+ return parts.length > 0 ? parts.join("\n\n") : void 0;
176
+ }
177
+ function scanAgent(agentDir) {
178
+ const { skills, tsSkillImportPaths } = getSkills(agentDir.absolutePath);
179
+ const systemPrompt = getSystemPrompt(agentDir.absolutePath);
180
+ return { ...agentDir, skills, systemPrompt, tsSkillImportPaths };
181
+ }
182
+ function findAgentsRoot(cwd, userDefinedAgentsDir) {
183
+ if (userDefinedAgentsDir) {
184
+ return path2.resolve(cwd, userDefinedAgentsDir);
185
+ }
186
+ const candidates = [
187
+ path2.join(cwd, "src", "agents"),
188
+ path2.join(cwd, "agents")
189
+ ];
190
+ for (const candidate of candidates) {
191
+ if (isDirectory(candidate)) {
192
+ return candidate;
193
+ }
194
+ }
195
+ return null;
196
+ }
197
+
198
+ // src/framework/framework.ts
199
+ var Framework = class {
200
+ cwd;
201
+ agentsDir;
202
+ log;
203
+ constructor(opts) {
204
+ this.cwd = opts.cwd ?? process.cwd();
205
+ this.agentsDir = opts.agentsDir;
206
+ this.log = opts.debug ? console.log.bind(console, "[Framework]") : () => void 0;
207
+ }
208
+ /**
209
+ * Scan the agents directory and return metadata for every agent found.
210
+ * Each subfolder inside the agents directory becomes one agent.
211
+ * Returns an empty array when no agents directory exists.
212
+ */
213
+ discoverAgents() {
214
+ const root = findAgentsRoot(this.cwd, this.agentsDir);
215
+ if (!root) {
216
+ return [];
217
+ }
218
+ const dirs = discoverAgentDirs(root);
219
+ return dirs.map(scanAgent);
220
+ }
221
+ /**
222
+ * Generate the TypeScript source for an agent registry module.
223
+ *
224
+ * @param opts.agents - Scanned agents to include in the registry.
225
+ * @param opts.outputDir - Directory where the registry file will be written
226
+ * (used to compute relative import paths to each agent's config module).
227
+ * @returns The full source text of the generated `_registry.ts` file.
228
+ */
229
+ generateRegistrySource = generateRegistry;
230
+ };
231
+
232
+ // src/framework-next/next.ts
233
+ var fs3 = __toESM(require("fs"));
234
+ var path3 = __toESM(require("path"));
235
+ var Next = class {
236
+ constructor(framework) {
237
+ this.framework = framework;
238
+ }
239
+ get appDir() {
240
+ const cwd = this.framework.cwd;
241
+ const srcAppDir = path3.join(cwd, "src", "app");
242
+ const rootAppDir = path3.join(cwd, "app");
243
+ if (this.hasAppLayout(srcAppDir)) {
244
+ return "src/app";
245
+ }
246
+ if (this.hasAppLayout(rootAppDir)) {
247
+ return "app";
248
+ }
249
+ if (fs3.existsSync(srcAppDir)) {
250
+ return "src/app";
251
+ }
252
+ return "app";
253
+ }
254
+ generateNextRouteHandlerSource(opts) {
255
+ return `// Auto-generated by withAgents - do not edit
256
+ // @ts-nocheck
257
+ // biome-ignore format, lint, lint/style, lint/suspicious, lint/complexity, lint/performance, lint/security, lint/correctness, lint/strict
258
+ // prettier-ignore
259
+
260
+ import { runtime } from "experimental-agent/framework-runtime";
261
+ import { handleRequest } from "experimental-agent";
262
+ import { agents } from ${JSON.stringify(opts.registryImportPath)};
263
+
264
+ async function workflow(agent, sessionId, ...args) {
265
+ "use workflow";
266
+ return agent.session(sessionId).send(...args);
267
+ }
268
+
269
+ async function handler(
270
+ req: Request,
271
+ ctx: { params: Promise<{ agent: string; path?: string[] }> }
272
+ ) {
273
+ const params = await ctx.params;
274
+ const name = params.agent;
275
+ const instance = await runtime.resolveAgent({ name, agents });
276
+
277
+ if (!instance) {
278
+ const available = Object.keys(agents).join(", ");
279
+ const body =
280
+ \`Agent "\${name}" not found.\\n\\n\` +
281
+ \`Available agents: \${available}\\n\\n\` +
282
+ \`hint: each folder inside agents/ becomes an agent.\\n\` +
283
+ \` Create agents/\${name}/ to add this agent.\\n\`;
284
+ return new Response(body, { status: 404 });
285
+ }
286
+
287
+ return handleRequest(instance, { basePath: \`/.well-known/agents/\${name}\`, workflow }).fetch(req);
288
+ }
289
+
290
+ export const GET = handler;
291
+ export const POST = handler;
292
+ `;
293
+ }
294
+ /**
295
+ * Pure codegen step: scan agents and return the generated source
296
+ * strings without touching the filesystem. Useful for adapters that
297
+ * need to control where and how files are written.
298
+ *
299
+ * Returns `null` when no agents are found.
300
+ */
301
+ filesToWrite() {
302
+ const agents = this.framework.discoverAgents();
303
+ if (agents.length === 0) {
304
+ return null;
305
+ }
306
+ this.framework.log(
307
+ "discovered agents:",
308
+ agents.map((a) => a.name)
309
+ );
310
+ const dir = path3.join(
311
+ this.framework.cwd,
312
+ this.appDir,
313
+ ".well-known",
314
+ "agents",
315
+ "[agent]",
316
+ "[[...path]]"
317
+ );
318
+ const registrySource = this.framework.generateRegistrySource({
319
+ agents,
320
+ outputDir: dir
321
+ });
322
+ const routeSource = this.generateNextRouteHandlerSource({
323
+ registryImportPath: "./_registry"
324
+ });
325
+ return { registrySource, routeSource, dir };
326
+ }
327
+ /**
328
+ * Scan for agents, generate source, and write the `_registry.ts` and
329
+ * `route.ts` files into the Next.js app directory.
330
+ */
331
+ writeFiles() {
332
+ const filesToWrite = this.filesToWrite();
333
+ if (!filesToWrite) {
334
+ console.warn("[withAgents] No agents found");
335
+ return;
336
+ }
337
+ const { registrySource, routeSource, dir } = filesToWrite;
338
+ fs3.mkdirSync(dir, { recursive: true });
339
+ fs3.writeFileSync(path3.join(dir, "_registry.ts"), registrySource);
340
+ fs3.writeFileSync(path3.join(dir, "route.ts"), routeSource);
341
+ const gitignorePath = path3.join(dir, ".gitignore");
342
+ if (!fs3.existsSync(gitignorePath)) {
343
+ fs3.writeFileSync(gitignorePath, "*\n");
344
+ }
345
+ }
346
+ hasAppLayout(dir) {
347
+ return ["layout.tsx", "layout.js", "layout.jsx"].some(
348
+ (f) => fs3.existsSync(path3.join(dir, f))
349
+ );
350
+ }
351
+ };
352
+
353
+ // src/framework-next/agents-plugin.ts
354
+ function withAgents(config, agentsConfig = {}) {
355
+ const framework = new Framework(agentsConfig);
356
+ const next = new Next(framework);
357
+ next.writeFiles();
358
+ return config;
359
+ }
360
+ // Annotate the CommonJS export names for ESM import in node:
361
+ 0 && (module.exports = {
362
+ withAgents
363
+ });
364
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2ZyYW1ld29yay1uZXh0L2FnZW50cy1wbHVnaW4udHMiLCAiLi4vLi4vc3JjL2ZyYW1ld29yay9nZW5lcmF0ZS50cyIsICIuLi8uLi9zcmMvZnJhbWV3b3JrL3NjYW4udHMiLCAiLi4vLi4vc3JjL2ZyYW1ld29yay9mcmFtZXdvcmsudHMiLCAiLi4vLi4vc3JjL2ZyYW1ld29yay1uZXh0L25leHQudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCB7IEZyYW1ld29yayB9IGZyb20gXCIuLi9mcmFtZXdvcmsvZnJhbWV3b3JrXCI7XG5pbXBvcnQgeyBOZXh0LCB0eXBlIE5leHRDb25maWdJbnB1dCB9IGZyb20gXCIuL25leHRcIjtcblxuZXhwb3J0IHR5cGUgeyBOZXh0Q29uZmlnSW5wdXQsIFdpdGhBZ2VudHNDb25maWcgfSBmcm9tIFwiLi9uZXh0XCI7XG5cbi8qKlxuICogTmV4dC5qcyBjb25maWcgd3JhcHBlciB0aGF0IGRpc2NvdmVycyBhZ2VudHMgb24gdGhlIGZpbGVzeXN0ZW0gYW5kXG4gKiBnZW5lcmF0ZXMgdGhlIHJvdXRlIGhhbmRsZXIgKyByZWdpc3RyeSBmaWxlcyBuZWVkZWQgdG8gc2VydmUgdGhlbS5cbiAqXG4gKiBDYWxsIHRoaXMgaW4gYG5leHQuY29uZmlnLnRzYDpcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIGltcG9ydCB7IHdpdGhBZ2VudHMgfSBmcm9tIFwiZXhwZXJpbWVudGFsLWFnZW50L25leHQvYWdlbnRzXCI7XG4gKlxuICogZXhwb3J0IGRlZmF1bHQgd2l0aEFnZW50cyh7IHJlYWN0U3RyaWN0TW9kZTogdHJ1ZSB9KTtcbiAqIGBgYFxuICpcbiAqIERlYnVnIGxvZ3M6XG4gKiBgYGB0c1xuICogaW1wb3J0IHsgd2l0aEFnZW50cyB9IGZyb20gXCJleHBlcmltZW50YWwtYWdlbnQvbmV4dC9hZ2VudHNcIjtcbiAqXG4gKiBleHBvcnQgZGVmYXVsdCB3aXRoQWdlbnRzKHsgcmVhY3RTdHJpY3RNb2RlOiB0cnVlIH0sIHsgZGVidWc6IHRydWUgfSk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdpdGhBZ2VudHMoXG4gIGNvbmZpZzogTmV4dENvbmZpZ0lucHV0LFxuICBhZ2VudHNDb25maWc6IFBpY2s8XG4gICAgQ29uc3RydWN0b3JQYXJhbWV0ZXJzPHR5cGVvZiBGcmFtZXdvcms+WzBdLFxuICAgIFwiYWdlbnRzRGlyXCIgfCBcImRlYnVnXCJcbiAgPiA9IHt9XG4pOiBOZXh0Q29uZmlnSW5wdXQge1xuICBjb25zdCBmcmFtZXdvcmsgPSBuZXcgRnJhbWV3b3JrKGFnZW50c0NvbmZpZyk7XG4gIGNvbnN0IG5leHQgPSBuZXcgTmV4dChmcmFtZXdvcmspO1xuICBuZXh0LndyaXRlRmlsZXMoKTtcblxuICByZXR1cm4gY29uZmlnO1xufVxuIiwgImltcG9ydCAqIGFzIGZzIGZyb20gXCJub2RlOmZzXCI7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCB0eXBlIHsgU2Nhbm5lZEFnZW50IH0gZnJvbSBcIi4vc2NhblwiO1xuXG5jb25zdCBUU19JTVBPUlRfRVhUID0gL1xcLih0c3xtdHMpJC87XG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVSZWdpc3RyeShvcHRzOiB7XG4gIGFnZW50czogU2Nhbm5lZEFnZW50W107XG4gIG91dHB1dERpcjogc3RyaW5nO1xufSk6IHN0cmluZyB7XG4gIGNvbnN0IGVudHJpZXMgPSBvcHRzLmFnZW50cy5tYXAoKGFnZW50KSA9PlxuICAgIGlubGluZUVudHJ5KHsgYWdlbnQsIG91dHB1dERpcjogb3B0cy5vdXRwdXREaXIgfSlcbiAgKTtcblxuICByZXR1cm4gW1xuICAgIFwiLy8gQXV0by1nZW5lcmF0ZWQgYnkgd2l0aEFnZW50cyAtIGRvIG5vdCBlZGl0XCIsXG4gICAgJ2ltcG9ydCB0eXBlIHsgQWdlbnRSZWdpc3RyeSB9IGZyb20gXCJleHBlcmltZW50YWwtYWdlbnQvZnJhbWV3b3JrXCI7JyxcbiAgICBcIlwiLFxuICAgIFwiZXhwb3J0IGNvbnN0IGFnZW50cyA9IHtcIixcbiAgICAuLi5lbnRyaWVzLFxuICAgIFwifSBzYXRpc2ZpZXMgQWdlbnRSZWdpc3RyeTtcIixcbiAgICBcIlwiLFxuICBdLmpvaW4oXCJcXG5cIik7XG59XG5cbmZ1bmN0aW9uIGlubGluZUVudHJ5KG9wdHM6IHtcbiAgYWdlbnQ6IFNjYW5uZWRBZ2VudDtcbiAgb3V0cHV0RGlyOiBzdHJpbmc7XG59KTogc3RyaW5nIHtcbiAgY29uc3QgY29uZmlnID0gYnVpbGRDb25maWcob3B0cy5hZ2VudCk7XG4gIGNvbnN0IGNvbmZpZ1N0ciA9IEpTT04uc3RyaW5naWZ5KGNvbmZpZywgbnVsbCwgMilcbiAgICAuc3BsaXQoXCJcXG5cIilcbiAgICAubWFwKChsaW5lLCBpKSA9PiAoaSA9PT0gMCA/IGxpbmUgOiBgICAgICAgJHtsaW5lfWApKVxuICAgIC5qb2luKFwiXFxuXCIpO1xuXG4gIGNvbnN0IHBhcnRzID0gW2AgICAgY29uZmlnOiAke2NvbmZpZ1N0cn1gXTtcblxuICBpZiAob3B0cy5hZ2VudC5oYXNBZ2VudENvbmZpZykge1xuICAgIGNvbnN0IGNvbmZpZ1BhdGggPSBmaW5kQWdlbnRDb25maWdQYXRoKG9wdHMuYWdlbnQuYWJzb2x1dGVQYXRoKTtcbiAgICBjb25zdCByZWxhdGl2ZVBhdGggPSByZWxhdGl2ZUltcG9ydFBhdGgoe1xuICAgICAgZnJvbTogb3B0cy5vdXRwdXREaXIsXG4gICAgICB0bzogY29uZmlnUGF0aCxcbiAgICB9KTtcbiAgICBwYXJ0cy5wdXNoKGAgICAgaW1wb3J0OiAoKSA9PiBpbXBvcnQoJHtKU09OLnN0cmluZ2lmeShyZWxhdGl2ZVBhdGgpfSlgKTtcbiAgfVxuXG4gIHJldHVybiBgICAke0pTT04uc3RyaW5naWZ5KG9wdHMuYWdlbnQubmFtZSl9OiB7XFxuJHtwYXJ0cy5qb2luKFwiLFxcblwiKX1cXG4gIH0sYDtcbn1cblxuZnVuY3Rpb24gYnVpbGRDb25maWcoYWdlbnQ6IFNjYW5uZWRBZ2VudCk6IFJlY29yZDxzdHJpbmcsIHVua25vd24+IHtcbiAgY29uc3QgY29uZmlnOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9IHt9O1xuXG4gIGlmIChhZ2VudC5zeXN0ZW1Qcm9tcHQpIHtcbiAgICBjb25maWcuc3lzdGVtID0gYWdlbnQuc3lzdGVtUHJvbXB0O1xuICB9XG5cbiAgaWYgKGFnZW50LnNraWxscy5sZW5ndGggPiAwKSB7XG4gICAgY29uZmlnLnNraWxscyA9IGFnZW50LnNraWxscztcbiAgfVxuXG4gIHJldHVybiBjb25maWc7XG59XG5cbmZ1bmN0aW9uIGZpbmRBZ2VudENvbmZpZ1BhdGgoYWdlbnREaXI6IHN0cmluZyk6IHN0cmluZyB7XG4gIGNvbnN0IGV4dGVuc2lvbnMgPSBbXCIudHNcIiwgXCIuanNcIiwgXCIubXRzXCIsIFwiLm1qc1wiXTtcbiAgZm9yIChjb25zdCBleHQgb2YgZXh0ZW5zaW9ucykge1xuICAgIGNvbnN0IGNhbmRpZGF0ZSA9IHBhdGguam9pbihhZ2VudERpciwgYGFnZW50JHtleHR9YCk7XG4gICAgaWYgKGZzLmV4aXN0c1N5bmMoY2FuZGlkYXRlKSkge1xuICAgICAgcmV0dXJuIGNhbmRpZGF0ZTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHBhdGguam9pbihhZ2VudERpciwgXCJhZ2VudFwiKTtcbn1cblxuZnVuY3Rpb24gcmVsYXRpdmVJbXBvcnRQYXRoKG9wdHM6IHsgZnJvbTogc3RyaW5nOyB0bzogc3RyaW5nIH0pOiBzdHJpbmcge1xuICBsZXQgcmVsID0gcGF0aC5yZWxhdGl2ZShvcHRzLmZyb20sIG9wdHMudG8pLnJlcGxhY2UoL1xcXFwvZywgXCIvXCIpO1xuICByZWwgPSByZWwucmVwbGFjZShUU19JTVBPUlRfRVhULCBcIlwiKTtcbiAgaWYgKCFyZWwuc3RhcnRzV2l0aChcIi5cIikpIHtcbiAgICByZWwgPSBgLi8ke3JlbH1gO1xuICB9XG4gIHJldHVybiByZWw7XG59XG5cbiIsICJpbXBvcnQgKiBhcyBmcyBmcm9tIFwibm9kZTpmc1wiO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgdHlwZSB7IEhvc3RTa2lsbElucHV0LCBTa2lsbElucHV0IH0gZnJvbSBcIi4uL3NraWxscy90eXBlc1wiO1xuXG5leHBvcnQgdHlwZSBBZ2VudERpciA9IHtcbiAgbmFtZTogc3RyaW5nO1xuICBhYnNvbHV0ZVBhdGg6IHN0cmluZztcbiAgaGFzQWdlbnRDb25maWc6IGJvb2xlYW47XG59O1xuXG5leHBvcnQgdHlwZSBTY2FubmVkQWdlbnQgPSBBZ2VudERpciAmIHtcbiAgc2tpbGxzOiBTa2lsbElucHV0W107XG4gIHN5c3RlbVByb21wdDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICB0c1NraWxsSW1wb3J0UGF0aHM6IHN0cmluZ1tdO1xufTtcblxuY29uc3QgQUdFTlRfQ09ORklHX0ZJTEVTID0gW1wiYWdlbnQudHNcIiwgXCJhZ2VudC5qc1wiLCBcImFnZW50Lm10c1wiLCBcImFnZW50Lm1qc1wiXTtcbmNvbnN0IE1EX0VYVCA9IC9cXC5tZCQvO1xuY29uc3QgVFNfRVhUID0gL1xcLih0c3xqc3xtdHN8bWpzKSQvO1xuXG5leHBvcnQgZnVuY3Rpb24gbGlzdERpcihkaXI6IHN0cmluZyk6IHN0cmluZ1tdIHtcbiAgaWYgKCFmcy5leGlzdHNTeW5jKGRpcikpIHtcbiAgICByZXR1cm4gW107XG4gIH1cbiAgcmV0dXJuIGZzLnJlYWRkaXJTeW5jKGRpcik7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZWFkRmlsZShmaWxlUGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGZzLnJlYWRGaWxlU3luYyhmaWxlUGF0aCwgXCJ1dGYtOFwiKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZpbGVFeGlzdHMoZmlsZVBhdGg6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gZnMuZXhpc3RzU3luYyhmaWxlUGF0aCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBpc0RpcmVjdG9yeShmaWxlUGF0aDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiBmcy5leGlzdHNTeW5jKGZpbGVQYXRoKSAmJiBmcy5zdGF0U3luYyhmaWxlUGF0aCkuaXNEaXJlY3RvcnkoKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGRpc2NvdmVyQWdlbnREaXJzKGFnZW50c1Jvb3Q6IHN0cmluZyk6IEFnZW50RGlyW10ge1xuICBjb25zdCBlbnRyaWVzID0gbGlzdERpcihhZ2VudHNSb290KTtcbiAgY29uc3QgZGlyczogQWdlbnREaXJbXSA9IFtdO1xuXG4gIGZvciAoY29uc3QgZW50cnkgb2YgZW50cmllcykge1xuICAgIGNvbnN0IGFic29sdXRlUGF0aCA9IHBhdGguam9pbihhZ2VudHNSb290LCBlbnRyeSk7XG4gICAgaWYgKCFpc0RpcmVjdG9yeShhYnNvbHV0ZVBhdGgpKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgaWYgKGVudHJ5LnN0YXJ0c1dpdGgoXCIuXCIpKSB7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG5cbiAgICBkaXJzLnB1c2goe1xuICAgICAgbmFtZTogZW50cnksXG4gICAgICBhYnNvbHV0ZVBhdGgsXG4gICAgICBoYXNBZ2VudENvbmZpZzogaGFzQWdlbnRDb25maWcoYWJzb2x1dGVQYXRoKSxcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiBkaXJzO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaGFzQWdlbnRDb25maWcoYWdlbnREaXI6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gQUdFTlRfQ09ORklHX0ZJTEVTLnNvbWUoKGYpID0+IGZpbGVFeGlzdHMocGF0aC5qb2luKGFnZW50RGlyLCBmKSkpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0U2tpbGxzKGFnZW50RGlyOiBzdHJpbmcpOiB7XG4gIHNraWxsczogU2tpbGxJbnB1dFtdO1xuICB0c1NraWxsSW1wb3J0UGF0aHM6IHN0cmluZ1tdO1xufSB7XG4gIGNvbnN0IHNraWxsc0RpciA9IHBhdGguam9pbihhZ2VudERpciwgXCJza2lsbHNcIik7XG4gIGNvbnN0IGVudHJpZXMgPSBsaXN0RGlyKHNraWxsc0Rpcik7XG4gIGNvbnN0IHNraWxsczogU2tpbGxJbnB1dFtdID0gW107XG4gIGNvbnN0IHRzU2tpbGxJbXBvcnRQYXRoczogc3RyaW5nW10gPSBbXTtcblxuICBmb3IgKGNvbnN0IGVudHJ5IG9mIGVudHJpZXMuc29ydCgpKSB7XG4gICAgY29uc3QgYWJzb2x1dGVQYXRoID0gcGF0aC5qb2luKHNraWxsc0RpciwgZW50cnkpO1xuXG4gICAgaWYgKE1EX0VYVC50ZXN0KGVudHJ5KSkge1xuICAgICAgc2tpbGxzLnB1c2goe1xuICAgICAgICB0eXBlOiBcImhvc3RcIixcbiAgICAgICAgcGF0aDogYWJzb2x1dGVQYXRoLFxuICAgICAgfSBzYXRpc2ZpZXMgSG9zdFNraWxsSW5wdXQpO1xuICAgIH0gZWxzZSBpZiAoVFNfRVhULnRlc3QoZW50cnkpKSB7XG4gICAgICB0c1NraWxsSW1wb3J0UGF0aHMucHVzaChhYnNvbHV0ZVBhdGgpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7IHNraWxscywgdHNTa2lsbEltcG9ydFBhdGhzIH07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRTeXN0ZW1Qcm9tcHQoYWdlbnREaXI6IHN0cmluZyk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIGNvbnN0IHN5c3RlbURpciA9IHBhdGguam9pbihhZ2VudERpciwgXCJzeXN0ZW1cIik7XG4gIGNvbnN0IGVudHJpZXMgPSBsaXN0RGlyKHN5c3RlbURpcik7XG4gIGNvbnN0IG1kRmlsZXMgPSBlbnRyaWVzLmZpbHRlcigoZSkgPT4gTURfRVhULnRlc3QoZSkpLnNvcnQoKTtcblxuICBpZiAobWRGaWxlcy5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG5cbiAgY29uc3QgcGFydHM6IHN0cmluZ1tdID0gW107XG4gIGZvciAoY29uc3QgZmlsZSBvZiBtZEZpbGVzKSB7XG4gICAgY29uc3QgY29udGVudCA9IHJlYWRGaWxlKHBhdGguam9pbihzeXN0ZW1EaXIsIGZpbGUpKS50cmltKCk7XG4gICAgaWYgKGNvbnRlbnQpIHtcbiAgICAgIHBhcnRzLnB1c2goY29udGVudCk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHBhcnRzLmxlbmd0aCA+IDAgPyBwYXJ0cy5qb2luKFwiXFxuXFxuXCIpIDogdW5kZWZpbmVkO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2NhbkFnZW50KGFnZW50RGlyOiBBZ2VudERpcik6IFNjYW5uZWRBZ2VudCB7XG4gIGNvbnN0IHsgc2tpbGxzLCB0c1NraWxsSW1wb3J0UGF0aHMgfSA9IGdldFNraWxscyhhZ2VudERpci5hYnNvbHV0ZVBhdGgpO1xuICBjb25zdCBzeXN0ZW1Qcm9tcHQgPSBnZXRTeXN0ZW1Qcm9tcHQoYWdlbnREaXIuYWJzb2x1dGVQYXRoKTtcblxuICByZXR1cm4geyAuLi5hZ2VudERpciwgc2tpbGxzLCBzeXN0ZW1Qcm9tcHQsIHRzU2tpbGxJbXBvcnRQYXRocyB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZmluZEFnZW50c1Jvb3QoXG4gIGN3ZDogc3RyaW5nLFxuICB1c2VyRGVmaW5lZEFnZW50c0Rpcjogc3RyaW5nIHwgdW5kZWZpbmVkXG4pOiBzdHJpbmcgfCBudWxsIHtcbiAgaWYgKHVzZXJEZWZpbmVkQWdlbnRzRGlyKSB7XG4gICAgcmV0dXJuIHBhdGgucmVzb2x2ZShjd2QsIHVzZXJEZWZpbmVkQWdlbnRzRGlyKTtcbiAgfVxuICBjb25zdCBjYW5kaWRhdGVzID0gW1xuICAgIHBhdGguam9pbihjd2QsIFwic3JjXCIsIFwiYWdlbnRzXCIpLFxuICAgIHBhdGguam9pbihjd2QsIFwiYWdlbnRzXCIpLFxuICBdO1xuXG4gIGZvciAoY29uc3QgY2FuZGlkYXRlIG9mIGNhbmRpZGF0ZXMpIHtcbiAgICBpZiAoaXNEaXJlY3RvcnkoY2FuZGlkYXRlKSkge1xuICAgICAgcmV0dXJuIGNhbmRpZGF0ZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gbnVsbDtcbn1cbiIsICJpbXBvcnQgeyBnZW5lcmF0ZVJlZ2lzdHJ5IH0gZnJvbSBcIi4vZ2VuZXJhdGVcIjtcbmltcG9ydCB0eXBlIHsgU2Nhbm5lZEFnZW50IH0gZnJvbSBcIi4vc2NhblwiO1xuaW1wb3J0IHsgZGlzY292ZXJBZ2VudERpcnMsIGZpbmRBZ2VudHNSb290LCBzY2FuQWdlbnQgfSBmcm9tIFwiLi9zY2FuXCI7XG5cbi8qKlxuICogRnJhbWV3b3JrLWFnbm9zdGljIGNvcmUgZm9yIGZpbGVzeXN0ZW0tYmFzZWQgYWdlbnQgZGlzY292ZXJ5IGFuZFxuICogcmVnaXN0cnkgY29kZSBnZW5lcmF0aW9uLiBBZGFwdGVycyBsaWtlIHtAbGluayBOZXh0fSByZWNlaXZlIGFcbiAqIGBGcmFtZXdvcmtgIGluc3RhbmNlIGFuZCB1c2UgaXQgdG8gc2NhbiBhZ2VudHMgYW5kIHByb2R1Y2UgcmVnaXN0cnlcbiAqIHNvdXJjZSBjb2RlLlxuICovXG5leHBvcnQgY2xhc3MgRnJhbWV3b3JrIHtcbiAgcmVhZG9ubHkgY3dkOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGFnZW50c0Rpcjogc3RyaW5nIHwgdW5kZWZpbmVkO1xuICByZWFkb25seSBsb2c6ICguLi5hcmdzOiB1bmtub3duW10pID0+IHZvaWQ7XG5cbiAgY29uc3RydWN0b3Iob3B0czoge1xuICAgIC8qKlxuICAgICAqIFByb2plY3Qgcm9vdCBkaXJlY3RvcnkuXG4gICAgICogQGRlZmF1bHRWYWx1ZSBgcHJvY2Vzcy5jd2QoKWBcbiAgICAgKi9cbiAgICBjd2Q/OiBzdHJpbmc7XG4gICAgLyoqXG4gICAgICogUGF0aCB0byB0aGUgYWdlbnRzIGRpcmVjdG9yeSwgcmVsYXRpdmUgdG8gYGN3ZGAuXG4gICAgICogV2hlbiBvbWl0dGVkLCBhdXRvLWRldGVjdGVkIGFzIHRoZSBmaXJzdCBleGlzdGluZyBkaXJlY3RvcnlcbiAgICAgKiBhbW9uZyBgc3JjL2FnZW50c2AgYW5kIGBhZ2VudHNgLlxuICAgICAqL1xuICAgIGFnZW50c0Rpcj86IHN0cmluZztcbiAgICAvKiogRW5hYmxlIHZlcmJvc2UgbG9nZ2luZyB0byBzdGRvdXQuICovXG4gICAgZGVidWc/OiBib29sZWFuO1xuICB9KSB7XG4gICAgdGhpcy5jd2QgPSBvcHRzLmN3ZCA/PyBwcm9jZXNzLmN3ZCgpO1xuICAgIHRoaXMuYWdlbnRzRGlyID0gb3B0cy5hZ2VudHNEaXI7XG4gICAgdGhpcy5sb2cgPSBvcHRzLmRlYnVnXG4gICAgICA/IGNvbnNvbGUubG9nLmJpbmQoY29uc29sZSwgXCJbRnJhbWV3b3JrXVwiKVxuICAgICAgOiAoKSA9PiB1bmRlZmluZWQ7XG4gIH1cblxuICAvKipcbiAgICogU2NhbiB0aGUgYWdlbnRzIGRpcmVjdG9yeSBhbmQgcmV0dXJuIG1ldGFkYXRhIGZvciBldmVyeSBhZ2VudCBmb3VuZC5cbiAgICogRWFjaCBzdWJmb2xkZXIgaW5zaWRlIHRoZSBhZ2VudHMgZGlyZWN0b3J5IGJlY29tZXMgb25lIGFnZW50LlxuICAgKiBSZXR1cm5zIGFuIGVtcHR5IGFycmF5IHdoZW4gbm8gYWdlbnRzIGRpcmVjdG9yeSBleGlzdHMuXG4gICAqL1xuICBkaXNjb3ZlckFnZW50cygpOiBTY2FubmVkQWdlbnRbXSB7XG4gICAgY29uc3Qgcm9vdCA9IGZpbmRBZ2VudHNSb290KHRoaXMuY3dkLCB0aGlzLmFnZW50c0Rpcik7XG4gICAgaWYgKCFyb290KSB7XG4gICAgICByZXR1cm4gW107XG4gICAgfVxuICAgIGNvbnN0IGRpcnMgPSBkaXNjb3ZlckFnZW50RGlycyhyb290KTtcbiAgICByZXR1cm4gZGlycy5tYXAoc2NhbkFnZW50KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZW5lcmF0ZSB0aGUgVHlwZVNjcmlwdCBzb3VyY2UgZm9yIGFuIGFnZW50IHJlZ2lzdHJ5IG1vZHVsZS5cbiAgICpcbiAgICogQHBhcmFtIG9wdHMuYWdlbnRzIC0gU2Nhbm5lZCBhZ2VudHMgdG8gaW5jbHVkZSBpbiB0aGUgcmVnaXN0cnkuXG4gICAqIEBwYXJhbSBvcHRzLm91dHB1dERpciAtIERpcmVjdG9yeSB3aGVyZSB0aGUgcmVnaXN0cnkgZmlsZSB3aWxsIGJlIHdyaXR0ZW5cbiAgICogICAodXNlZCB0byBjb21wdXRlIHJlbGF0aXZlIGltcG9ydCBwYXRocyB0byBlYWNoIGFnZW50J3MgY29uZmlnIG1vZHVsZSkuXG4gICAqIEByZXR1cm5zIFRoZSBmdWxsIHNvdXJjZSB0ZXh0IG9mIHRoZSBnZW5lcmF0ZWQgYF9yZWdpc3RyeS50c2AgZmlsZS5cbiAgICovXG4gIGdlbmVyYXRlUmVnaXN0cnlTb3VyY2UgPSBnZW5lcmF0ZVJlZ2lzdHJ5O1xufVxuIiwgImltcG9ydCAqIGFzIGZzIGZyb20gXCJub2RlOmZzXCI7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCB0eXBlIHsgTmV4dENvbmZpZyB9IGZyb20gXCJuZXh0XCI7XG5pbXBvcnQgdHlwZSB7IEZyYW1ld29yayB9IGZyb20gXCIuLi9mcmFtZXdvcmsvZnJhbWV3b3JrXCI7XG5cbi8qKiBBIE5leHQuanMgY29uZmlnIG9iamVjdCBvciBhc3luYyBjb25maWcgZnVuY3Rpb24uICovXG5leHBvcnQgdHlwZSBOZXh0Q29uZmlnSW5wdXQgPVxuICB8IE5leHRDb25maWdcbiAgfCAoKFxuICAgICAgcGhhc2U6IHN0cmluZyxcbiAgICAgIGN0eDogeyBkZWZhdWx0Q29uZmlnOiBOZXh0Q29uZmlnIH1cbiAgICApID0+IFByb21pc2U8TmV4dENvbmZpZz4pO1xuXG4vKiogT3B0aW9ucyBmb3Ige0BsaW5rIHdpdGhBZ2VudHN9LiAqL1xuZXhwb3J0IHR5cGUgV2l0aEFnZW50c0NvbmZpZyA9IHtcbiAgLyoqXG4gICAqIFBhdGggdG8gdGhlIGFnZW50cyBkaXJlY3RvcnksIHJlbGF0aXZlIHRvIHRoZSBwcm9qZWN0IHJvb3QuXG4gICAqIFdoZW4gb21pdHRlZCwgYXV0by1kZXRlY3RlZCBhcyB0aGUgZmlyc3QgZXhpc3RpbmcgZGlyZWN0b3J5XG4gICAqIGFtb25nIGBzcmMvYWdlbnRzYCBhbmQgYGFnZW50c2AuXG4gICAqL1xuICBhZ2VudHNEaXI/OiBzdHJpbmc7XG4gIC8qKiBFbmFibGUgdmVyYm9zZSBsb2dnaW5nIHRvIHN0ZG91dC4gKi9cbiAgZGVidWc/OiBib29sZWFuO1xufTtcblxuLyoqXG4gKiBOZXh0LmpzIGFkYXB0ZXIgZm9yIGZpbGVzeXN0ZW0tYmFzZWQgYWdlbnQgcm91dGluZy5cbiAqXG4gKiBSZWNlaXZlcyBhIHtAbGluayBGcmFtZXdvcmt9IGluc3RhbmNlIChjb21wb3NpdGlvbikgYW5kIHVzZXMgaXQgdG9cbiAqIGRpc2NvdmVyIGFnZW50cywgZ2VuZXJhdGUgYSByZWdpc3RyeSwgYW5kIHdyaXRlIHRoZSBOZXh0LmpzIHJvdXRlXG4gKiBoYW5kbGVyIGZpbGVzIHRoYXQgc2VydmUgdGhlbS5cbiAqXG4gKiBNb3N0IHVzZXJzIHNob3VsZCB1c2UgdGhlIHtAbGluayB3aXRoQWdlbnRzfSBoZWxwZXIgaW5zdGVhZCBvZlxuICogY29uc3RydWN0aW5nIHRoaXMgY2xhc3MgZGlyZWN0bHkuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiBpbXBvcnQgeyBGcmFtZXdvcmsgfSBmcm9tIFwiZXhwZXJpbWVudGFsLWFnZW50L2ZyYW1ld29ya1wiO1xuICogaW1wb3J0IHsgTmV4dCB9IGZyb20gXCJleHBlcmltZW50YWwtYWdlbnQvbmV4dC9hZ2VudHNcIjtcbiAqXG4gKiBjb25zdCBmcmFtZXdvcmsgPSBuZXcgRnJhbWV3b3JrKHsgY3dkOiBwcm9jZXNzLmN3ZCgpIH0pO1xuICogbmV3IE5leHQoZnJhbWV3b3JrKS5nZW5lcmF0ZSgpO1xuICogYGBgXG4gKi9cbmV4cG9ydCBjbGFzcyBOZXh0IHtcbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBmcmFtZXdvcms6IEZyYW1ld29yaykge31cblxuICBwcml2YXRlIGdldCBhcHBEaXIoKTogc3RyaW5nIHtcbiAgICBjb25zdCBjd2QgPSB0aGlzLmZyYW1ld29yay5jd2Q7XG4gICAgY29uc3Qgc3JjQXBwRGlyID0gcGF0aC5qb2luKGN3ZCwgXCJzcmNcIiwgXCJhcHBcIik7XG4gICAgY29uc3Qgcm9vdEFwcERpciA9IHBhdGguam9pbihjd2QsIFwiYXBwXCIpO1xuXG4gICAgaWYgKHRoaXMuaGFzQXBwTGF5b3V0KHNyY0FwcERpcikpIHtcbiAgICAgIHJldHVybiBcInNyYy9hcHBcIjtcbiAgICB9XG4gICAgaWYgKHRoaXMuaGFzQXBwTGF5b3V0KHJvb3RBcHBEaXIpKSB7XG4gICAgICByZXR1cm4gXCJhcHBcIjtcbiAgICB9XG4gICAgaWYgKGZzLmV4aXN0c1N5bmMoc3JjQXBwRGlyKSkge1xuICAgICAgcmV0dXJuIFwic3JjL2FwcFwiO1xuICAgIH1cbiAgICByZXR1cm4gXCJhcHBcIjtcbiAgfVxuXG4gIGdlbmVyYXRlTmV4dFJvdXRlSGFuZGxlclNvdXJjZShvcHRzOiB7IHJlZ2lzdHJ5SW1wb3J0UGF0aDogc3RyaW5nIH0pOiBzdHJpbmcge1xuICAgIHJldHVybiBgLy8gQXV0by1nZW5lcmF0ZWQgYnkgd2l0aEFnZW50cyAtIGRvIG5vdCBlZGl0XG4vLyBAdHMtbm9jaGVja1xuLy8gYmlvbWUtaWdub3JlIGZvcm1hdCwgbGludCwgbGludC9zdHlsZSwgbGludC9zdXNwaWNpb3VzLCBsaW50L2NvbXBsZXhpdHksIGxpbnQvcGVyZm9ybWFuY2UsIGxpbnQvc2VjdXJpdHksIGxpbnQvY29ycmVjdG5lc3MsIGxpbnQvc3RyaWN0XG4vLyBwcmV0dGllci1pZ25vcmVcblxuaW1wb3J0IHsgcnVudGltZSB9IGZyb20gXCJleHBlcmltZW50YWwtYWdlbnQvZnJhbWV3b3JrLXJ1bnRpbWVcIjtcbmltcG9ydCB7IGhhbmRsZVJlcXVlc3QgfSBmcm9tIFwiZXhwZXJpbWVudGFsLWFnZW50XCI7XG5pbXBvcnQgeyBhZ2VudHMgfSBmcm9tICR7SlNPTi5zdHJpbmdpZnkob3B0cy5yZWdpc3RyeUltcG9ydFBhdGgpfTtcblxuYXN5bmMgZnVuY3Rpb24gd29ya2Zsb3coYWdlbnQsIHNlc3Npb25JZCwgLi4uYXJncykge1xuICBcInVzZSB3b3JrZmxvd1wiO1xuICByZXR1cm4gYWdlbnQuc2Vzc2lvbihzZXNzaW9uSWQpLnNlbmQoLi4uYXJncyk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGhhbmRsZXIoXG4gIHJlcTogUmVxdWVzdCxcbiAgY3R4OiB7IHBhcmFtczogUHJvbWlzZTx7IGFnZW50OiBzdHJpbmc7IHBhdGg/OiBzdHJpbmdbXSB9PiB9XG4pIHtcbiAgY29uc3QgcGFyYW1zID0gYXdhaXQgY3R4LnBhcmFtcztcbiAgY29uc3QgbmFtZSA9IHBhcmFtcy5hZ2VudDtcbiAgY29uc3QgaW5zdGFuY2UgPSBhd2FpdCBydW50aW1lLnJlc29sdmVBZ2VudCh7IG5hbWUsIGFnZW50cyB9KTtcblxuICBpZiAoIWluc3RhbmNlKSB7XG4gICAgY29uc3QgYXZhaWxhYmxlID0gT2JqZWN0LmtleXMoYWdlbnRzKS5qb2luKFwiLCBcIik7XG4gICAgY29uc3QgYm9keSA9XG4gICAgICBcXGBBZ2VudCBcIlxcJHtuYW1lfVwiIG5vdCBmb3VuZC5cXFxcblxcXFxuXFxgICtcbiAgICAgIFxcYEF2YWlsYWJsZSBhZ2VudHM6IFxcJHthdmFpbGFibGV9XFxcXG5cXFxcblxcYCArXG4gICAgICBcXGBoaW50OiBlYWNoIGZvbGRlciBpbnNpZGUgYWdlbnRzLyBiZWNvbWVzIGFuIGFnZW50LlxcXFxuXFxgICtcbiAgICAgIFxcYCAgICAgIENyZWF0ZSBhZ2VudHMvXFwke25hbWV9LyB0byBhZGQgdGhpcyBhZ2VudC5cXFxcblxcYDtcbiAgICByZXR1cm4gbmV3IFJlc3BvbnNlKGJvZHksIHsgc3RhdHVzOiA0MDQgfSk7XG4gIH1cblxuICByZXR1cm4gaGFuZGxlUmVxdWVzdChpbnN0YW5jZSwgeyBiYXNlUGF0aDogXFxgLy53ZWxsLWtub3duL2FnZW50cy9cXCR7bmFtZX1cXGAsIHdvcmtmbG93IH0pLmZldGNoKHJlcSk7XG59XG5cbmV4cG9ydCBjb25zdCBHRVQgPSBoYW5kbGVyO1xuZXhwb3J0IGNvbnN0IFBPU1QgPSBoYW5kbGVyO1xuYDtcbiAgfVxuXG4gIC8qKlxuICAgKiBQdXJlIGNvZGVnZW4gc3RlcDogc2NhbiBhZ2VudHMgYW5kIHJldHVybiB0aGUgZ2VuZXJhdGVkIHNvdXJjZVxuICAgKiBzdHJpbmdzIHdpdGhvdXQgdG91Y2hpbmcgdGhlIGZpbGVzeXN0ZW0uIFVzZWZ1bCBmb3IgYWRhcHRlcnMgdGhhdFxuICAgKiBuZWVkIHRvIGNvbnRyb2wgd2hlcmUgYW5kIGhvdyBmaWxlcyBhcmUgd3JpdHRlbi5cbiAgICpcbiAgICogUmV0dXJucyBgbnVsbGAgd2hlbiBubyBhZ2VudHMgYXJlIGZvdW5kLlxuICAgKi9cbiAgZmlsZXNUb1dyaXRlKCk6IHtcbiAgICByZWdpc3RyeVNvdXJjZTogc3RyaW5nO1xuICAgIHJvdXRlU291cmNlOiBzdHJpbmc7XG4gICAgZGlyOiBzdHJpbmc7XG4gIH0gfCBudWxsIHtcbiAgICBjb25zdCBhZ2VudHMgPSB0aGlzLmZyYW1ld29yay5kaXNjb3ZlckFnZW50cygpO1xuXG4gICAgaWYgKGFnZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRoaXMuZnJhbWV3b3JrLmxvZyhcbiAgICAgIFwiZGlzY292ZXJlZCBhZ2VudHM6XCIsXG4gICAgICBhZ2VudHMubWFwKChhKSA9PiBhLm5hbWUpXG4gICAgKTtcblxuICAgIGNvbnN0IGRpciA9IHBhdGguam9pbihcbiAgICAgIHRoaXMuZnJhbWV3b3JrLmN3ZCxcbiAgICAgIHRoaXMuYXBwRGlyLFxuICAgICAgXCIud2VsbC1rbm93blwiLFxuICAgICAgXCJhZ2VudHNcIixcbiAgICAgIFwiW2FnZW50XVwiLFxuICAgICAgXCJbWy4uLnBhdGhdXVwiXG4gICAgKTtcblxuICAgIGNvbnN0IHJlZ2lzdHJ5U291cmNlID0gdGhpcy5mcmFtZXdvcmsuZ2VuZXJhdGVSZWdpc3RyeVNvdXJjZSh7XG4gICAgICBhZ2VudHMsXG4gICAgICBvdXRwdXREaXI6IGRpcixcbiAgICB9KTtcbiAgICBjb25zdCByb3V0ZVNvdXJjZSA9IHRoaXMuZ2VuZXJhdGVOZXh0Um91dGVIYW5kbGVyU291cmNlKHtcbiAgICAgIHJlZ2lzdHJ5SW1wb3J0UGF0aDogXCIuL19yZWdpc3RyeVwiLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHsgcmVnaXN0cnlTb3VyY2UsIHJvdXRlU291cmNlLCBkaXIgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTY2FuIGZvciBhZ2VudHMsIGdlbmVyYXRlIHNvdXJjZSwgYW5kIHdyaXRlIHRoZSBgX3JlZ2lzdHJ5LnRzYCBhbmRcbiAgICogYHJvdXRlLnRzYCBmaWxlcyBpbnRvIHRoZSBOZXh0LmpzIGFwcCBkaXJlY3RvcnkuXG4gICAqL1xuICB3cml0ZUZpbGVzKCk6IHZvaWQge1xuICAgIGNvbnN0IGZpbGVzVG9Xcml0ZSA9IHRoaXMuZmlsZXNUb1dyaXRlKCk7XG5cbiAgICBpZiAoIWZpbGVzVG9Xcml0ZSkge1xuICAgICAgY29uc29sZS53YXJuKFwiW3dpdGhBZ2VudHNdIE5vIGFnZW50cyBmb3VuZFwiKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB7IHJlZ2lzdHJ5U291cmNlLCByb3V0ZVNvdXJjZSwgZGlyIH0gPSBmaWxlc1RvV3JpdGU7XG5cbiAgICBmcy5ta2RpclN5bmMoZGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICBmcy53cml0ZUZpbGVTeW5jKHBhdGguam9pbihkaXIsIFwiX3JlZ2lzdHJ5LnRzXCIpLCByZWdpc3RyeVNvdXJjZSk7XG4gICAgZnMud3JpdGVGaWxlU3luYyhwYXRoLmpvaW4oZGlyLCBcInJvdXRlLnRzXCIpLCByb3V0ZVNvdXJjZSk7XG5cbiAgICBjb25zdCBnaXRpZ25vcmVQYXRoID0gcGF0aC5qb2luKGRpciwgXCIuZ2l0aWdub3JlXCIpO1xuICAgIGlmICghZnMuZXhpc3RzU3luYyhnaXRpZ25vcmVQYXRoKSkge1xuICAgICAgZnMud3JpdGVGaWxlU3luYyhnaXRpZ25vcmVQYXRoLCBcIipcXG5cIik7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBoYXNBcHBMYXlvdXQoZGlyOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gW1wibGF5b3V0LnRzeFwiLCBcImxheW91dC5qc1wiLCBcImxheW91dC5qc3hcIl0uc29tZSgoZikgPT5cbiAgICAgIGZzLmV4aXN0c1N5bmMocGF0aC5qb2luKGRpciwgZikpXG4gICAgKTtcbiAgfVxufVxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTs7O0FDQUEsU0FBb0I7QUFDcEIsV0FBc0I7QUFHdEIsSUFBTSxnQkFBZ0I7QUFDZixTQUFTLGlCQUFpQixNQUd0QjtBQUNULFFBQU0sVUFBVSxLQUFLLE9BQU87QUFBQSxJQUFJLENBQUMsVUFDL0IsWUFBWSxFQUFFLE9BQU8sV0FBVyxLQUFLLFVBQVUsQ0FBQztBQUFBLEVBQ2xEO0FBRUEsU0FBTztBQUFBLElBQ0w7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBLEdBQUc7QUFBQSxJQUNIO0FBQUEsSUFDQTtBQUFBLEVBQ0YsRUFBRSxLQUFLLElBQUk7QUFDYjtBQUVBLFNBQVMsWUFBWSxNQUdWO0FBQ1QsUUFBTSxTQUFTLFlBQVksS0FBSyxLQUFLO0FBQ3JDLFFBQU0sWUFBWSxLQUFLLFVBQVUsUUFBUSxNQUFNLENBQUMsRUFDN0MsTUFBTSxJQUFJLEVBQ1YsSUFBSSxDQUFDLE1BQU0sTUFBTyxNQUFNLElBQUksT0FBTyxTQUFTLElBQUksRUFBRyxFQUNuRCxLQUFLLElBQUk7QUFFWixRQUFNLFFBQVEsQ0FBQyxlQUFlLFNBQVMsRUFBRTtBQUV6QyxNQUFJLEtBQUssTUFBTSxnQkFBZ0I7QUFDN0IsVUFBTSxhQUFhLG9CQUFvQixLQUFLLE1BQU0sWUFBWTtBQUM5RCxVQUFNLGVBQWUsbUJBQW1CO0FBQUEsTUFDdEMsTUFBTSxLQUFLO0FBQUEsTUFDWCxJQUFJO0FBQUEsSUFDTixDQUFDO0FBQ0QsVUFBTSxLQUFLLDRCQUE0QixLQUFLLFVBQVUsWUFBWSxDQUFDLEdBQUc7QUFBQSxFQUN4RTtBQUVB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YztBQUMvRCxJQUFHLGtCQUFtQixXQUFLLEtBQUssVUFBVSxHQUFHLFdBQVc7QUFFeEQsVUFBTSxnQkFBcUIsV0FBSyxLQUFLLFlBQVk7QUFDakQsUUFBSSxDQUFJLGVBQVcsYUFBYSxHQUFHO0FBQ2pDLE1BQUcsa0JBQWMsZUFBZSxLQUFLO0FBQUEsSUFDdkM7QUFBQSxFQUNGO0FBQUEsRUFFUSxhQUFhLEtBQXNCO0FBQ3pDLFdBQU8sQ0FBQyxjQUFjLGFBQWEsWUFBWSxFQUFFO0FBQUEsTUFBSyxDQUFDLE1BQ2xELGVBQWdCLFdBQUssS0FBSyxDQUFDLENBQUM7QUFBQSxJQUNqQztBQUFBLEVBQ0Y7QUFDRjs7O0FKeEpPLFNBQVMsV0FDZCxRQUNBLGVBR0ksQ0FBQyxHQUNZO0FBQ2pCLFFBQU0sWUFBWSxJQUFJLFVBQVUsWUFBWTtBQUM1QyxRQUFNLE9BQU8sSUFBSSxLQUFLLFNBQVM7QUFDL0IsT0FBSyxXQUFXO0FBRWhCLFNBQU87QUFDVDsiLAogICJuYW1lcyI6IFsiZnMiLCAicGF0aCIsICJmcyIsICJwYXRoIl0KfQo=
@@ -0,0 +1,137 @@
1
+ import {
2
+ Framework
3
+ } from "../chunk-DO4HKPHR.mjs";
4
+ import "../chunk-BJTO5JO5.mjs";
5
+
6
+ // src/framework-next/next.ts
7
+ import * as fs from "fs";
8
+ import * as path from "path";
9
+ var Next = class {
10
+ constructor(framework) {
11
+ this.framework = framework;
12
+ }
13
+ get appDir() {
14
+ const cwd = this.framework.cwd;
15
+ const srcAppDir = path.join(cwd, "src", "app");
16
+ const rootAppDir = path.join(cwd, "app");
17
+ if (this.hasAppLayout(srcAppDir)) {
18
+ return "src/app";
19
+ }
20
+ if (this.hasAppLayout(rootAppDir)) {
21
+ return "app";
22
+ }
23
+ if (fs.existsSync(srcAppDir)) {
24
+ return "src/app";
25
+ }
26
+ return "app";
27
+ }
28
+ generateNextRouteHandlerSource(opts) {
29
+ return `// Auto-generated by withAgents - do not edit
30
+ // @ts-nocheck
31
+ // biome-ignore format, lint, lint/style, lint/suspicious, lint/complexity, lint/performance, lint/security, lint/correctness, lint/strict
32
+ // prettier-ignore
33
+
34
+ import { runtime } from "experimental-agent/framework-runtime";
35
+ import { handleRequest } from "experimental-agent";
36
+ import { agents } from ${JSON.stringify(opts.registryImportPath)};
37
+
38
+ async function workflow(agent, sessionId, ...args) {
39
+ "use workflow";
40
+ return agent.session(sessionId).send(...args);
41
+ }
42
+
43
+ async function handler(
44
+ req: Request,
45
+ ctx: { params: Promise<{ agent: string; path?: string[] }> }
46
+ ) {
47
+ const params = await ctx.params;
48
+ const name = params.agent;
49
+ const instance = await runtime.resolveAgent({ name, agents });
50
+
51
+ if (!instance) {
52
+ const available = Object.keys(agents).join(", ");
53
+ const body =
54
+ \`Agent "\${name}" not found.\\n\\n\` +
55
+ \`Available agents: \${available}\\n\\n\` +
56
+ \`hint: each folder inside agents/ becomes an agent.\\n\` +
57
+ \` Create agents/\${name}/ to add this agent.\\n\`;
58
+ return new Response(body, { status: 404 });
59
+ }
60
+
61
+ return handleRequest(instance, { basePath: \`/.well-known/agents/\${name}\`, workflow }).fetch(req);
62
+ }
63
+
64
+ export const GET = handler;
65
+ export const POST = handler;
66
+ `;
67
+ }
68
+ /**
69
+ * Pure codegen step: scan agents and return the generated source
70
+ * strings without touching the filesystem. Useful for adapters that
71
+ * need to control where and how files are written.
72
+ *
73
+ * Returns `null` when no agents are found.
74
+ */
75
+ filesToWrite() {
76
+ const agents = this.framework.discoverAgents();
77
+ if (agents.length === 0) {
78
+ return null;
79
+ }
80
+ this.framework.log(
81
+ "discovered agents:",
82
+ agents.map((a) => a.name)
83
+ );
84
+ const dir = path.join(
85
+ this.framework.cwd,
86
+ this.appDir,
87
+ ".well-known",
88
+ "agents",
89
+ "[agent]",
90
+ "[[...path]]"
91
+ );
92
+ const registrySource = this.framework.generateRegistrySource({
93
+ agents,
94
+ outputDir: dir
95
+ });
96
+ const routeSource = this.generateNextRouteHandlerSource({
97
+ registryImportPath: "./_registry"
98
+ });
99
+ return { registrySource, routeSource, dir };
100
+ }
101
+ /**
102
+ * Scan for agents, generate source, and write the `_registry.ts` and
103
+ * `route.ts` files into the Next.js app directory.
104
+ */
105
+ writeFiles() {
106
+ const filesToWrite = this.filesToWrite();
107
+ if (!filesToWrite) {
108
+ console.warn("[withAgents] No agents found");
109
+ return;
110
+ }
111
+ const { registrySource, routeSource, dir } = filesToWrite;
112
+ fs.mkdirSync(dir, { recursive: true });
113
+ fs.writeFileSync(path.join(dir, "_registry.ts"), registrySource);
114
+ fs.writeFileSync(path.join(dir, "route.ts"), routeSource);
115
+ const gitignorePath = path.join(dir, ".gitignore");
116
+ if (!fs.existsSync(gitignorePath)) {
117
+ fs.writeFileSync(gitignorePath, "*\n");
118
+ }
119
+ }
120
+ hasAppLayout(dir) {
121
+ return ["layout.tsx", "layout.js", "layout.jsx"].some(
122
+ (f) => fs.existsSync(path.join(dir, f))
123
+ );
124
+ }
125
+ };
126
+
127
+ // src/framework-next/agents-plugin.ts
128
+ function withAgents(config, agentsConfig = {}) {
129
+ const framework = new Framework(agentsConfig);
130
+ const next = new Next(framework);
131
+ next.writeFiles();
132
+ return config;
133
+ }
134
+ export {
135
+ withAgents
136
+ };
137
+ //# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vc3JjL2ZyYW1ld29yay1uZXh0L25leHQudHMiLCAiLi4vLi4vc3JjL2ZyYW1ld29yay1uZXh0L2FnZW50cy1wbHVnaW4udHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCAqIGFzIGZzIGZyb20gXCJub2RlOmZzXCI7XG5pbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCB0eXBlIHsgTmV4dENvbmZpZyB9IGZyb20gXCJuZXh0XCI7XG5pbXBvcnQgdHlwZSB7IEZyYW1ld29yayB9IGZyb20gXCIuLi9mcmFtZXdvcmsvZnJhbWV3b3JrXCI7XG5cbi8qKiBBIE5leHQuanMgY29uZmlnIG9iamVjdCBvciBhc3luYyBjb25maWcgZnVuY3Rpb24uICovXG5leHBvcnQgdHlwZSBOZXh0Q29uZmlnSW5wdXQgPVxuICB8IE5leHRDb25maWdcbiAgfCAoKFxuICAgICAgcGhhc2U6IHN0cmluZyxcbiAgICAgIGN0eDogeyBkZWZhdWx0Q29uZmlnOiBOZXh0Q29uZmlnIH1cbiAgICApID0+IFByb21pc2U8TmV4dENvbmZpZz4pO1xuXG4vKiogT3B0aW9ucyBmb3Ige0BsaW5rIHdpdGhBZ2VudHN9LiAqL1xuZXhwb3J0IHR5cGUgV2l0aEFnZW50c0NvbmZpZyA9IHtcbiAgLyoqXG4gICAqIFBhdGggdG8gdGhlIGFnZW50cyBkaXJlY3RvcnksIHJlbGF0aXZlIHRvIHRoZSBwcm9qZWN0IHJvb3QuXG4gICAqIFdoZW4gb21pdHRlZCwgYXV0by1kZXRlY3RlZCBhcyB0aGUgZmlyc3QgZXhpc3RpbmcgZGlyZWN0b3J5XG4gICAqIGFtb25nIGBzcmMvYWdlbnRzYCBhbmQgYGFnZW50c2AuXG4gICAqL1xuICBhZ2VudHNEaXI/OiBzdHJpbmc7XG4gIC8qKiBFbmFibGUgdmVyYm9zZSBsb2dnaW5nIHRvIHN0ZG91dC4gKi9cbiAgZGVidWc/OiBib29sZWFuO1xufTtcblxuLyoqXG4gKiBOZXh0LmpzIGFkYXB0ZXIgZm9yIGZpbGVzeXN0ZW0tYmFzZWQgYWdlbnQgcm91dGluZy5cbiAqXG4gKiBSZWNlaXZlcyBhIHtAbGluayBGcmFtZXdvcmt9IGluc3RhbmNlIChjb21wb3NpdGlvbikgYW5kIHVzZXMgaXQgdG9cbiAqIGRpc2NvdmVyIGFnZW50cywgZ2VuZXJhdGUgYSByZWdpc3RyeSwgYW5kIHdyaXRlIHRoZSBOZXh0LmpzIHJvdXRlXG4gKiBoYW5kbGVyIGZpbGVzIHRoYXQgc2VydmUgdGhlbS5cbiAqXG4gKiBNb3N0IHVzZXJzIHNob3VsZCB1c2UgdGhlIHtAbGluayB3aXRoQWdlbnRzfSBoZWxwZXIgaW5zdGVhZCBvZlxuICogY29uc3RydWN0aW5nIHRoaXMgY2xhc3MgZGlyZWN0bHkuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHRzXG4gKiBpbXBvcnQgeyBGcmFtZXdvcmsgfSBmcm9tIFwiZXhwZXJpbWVudGFsLWFnZW50L2ZyYW1ld29ya1wiO1xuICogaW1wb3J0IHsgTmV4dCB9IGZyb20gXCJleHBlcmltZW50YWwtYWdlbnQvbmV4dC9hZ2VudHNcIjtcbiAqXG4gKiBjb25zdCBmcmFtZXdvcmsgPSBuZXcgRnJhbWV3b3JrKHsgY3dkOiBwcm9jZXNzLmN3ZCgpIH0pO1xuICogbmV3IE5leHQoZnJhbWV3b3JrKS5nZW5lcmF0ZSgpO1xuICogYGBgXG4gKi9cbmV4cG9ydCBjbGFzcyBOZXh0IHtcbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBmcmFtZXdvcms6IEZyYW1ld29yaykge31cblxuICBwcml2YXRlIGdldCBhcHBEaXIoKTogc3RyaW5nIHtcbiAgICBjb25zdCBjd2QgPSB0aGlzLmZyYW1ld29yay5jd2Q7XG4gICAgY29uc3Qgc3JjQXBwRGlyID0gcGF0aC5qb2luKGN3ZCwgXCJzcmNcIiwgXCJhcHBcIik7XG4gICAgY29uc3Qgcm9vdEFwcERpciA9IHBhdGguam9pbihjd2QsIFwiYXBwXCIpO1xuXG4gICAgaWYgKHRoaXMuaGFzQXBwTGF5b3V0KHNyY0FwcERpcikpIHtcbiAgICAgIHJldHVybiBcInNyYy9hcHBcIjtcbiAgICB9XG4gICAgaWYgKHRoaXMuaGFzQXBwTGF5b3V0KHJvb3RBcHBEaXIpKSB7XG4gICAgICByZXR1cm4gXCJhcHBcIjtcbiAgICB9XG4gICAgaWYgKGZzLmV4aXN0c1N5bmMoc3JjQXBwRGlyKSkge1xuICAgICAgcmV0dXJuIFwic3JjL2FwcFwiO1xuICAgIH1cbiAgICByZXR1cm4gXCJhcHBcIjtcbiAgfVxuXG4gIGdlbmVyYXRlTmV4dFJvdXRlSGFuZGxlclNvdXJjZShvcHRzOiB7IHJlZ2lzdHJ5SW1wb3J0UGF0aDogc3RyaW5nIH0pOiBzdHJpbmcge1xuICAgIHJldHVybiBgLy8gQXV0by1nZW5lcmF0ZWQgYnkgd2l0aEFnZW50cyAtIGRvIG5vdCBlZGl0XG4vLyBAdHMtbm9jaGVja1xuLy8gYmlvbWUtaWdub3JlIGZvcm1hdCwgbGludCwgbGludC9zdHlsZSwgbGludC9zdXNwaWNpb3VzLCBsaW50L2NvbXBsZXhpdHksIGxpbnQvcGVyZm9ybWFuY2UsIGxpbnQvc2VjdXJpdHksIGxpbnQvY29ycmVjdG5lc3MsIGxpbnQvc3RyaWN0XG4vLyBwcmV0dGllci1pZ25vcmVcblxuaW1wb3J0IHsgcnVudGltZSB9IGZyb20gXCJleHBlcmltZW50YWwtYWdlbnQvZnJhbWV3b3JrLXJ1bnRpbWVcIjtcbmltcG9ydCB7IGhhbmRsZVJlcXVlc3QgfSBmcm9tIFwiZXhwZXJpbWVudGFsLWFnZW50XCI7XG5pbXBvcnQgeyBhZ2VudHMgfSBmcm9tICR7SlNPTi5zdHJpbmdpZnkob3B0cy5yZWdpc3RyeUltcG9ydFBhdGgpfTtcblxuYXN5bmMgZnVuY3Rpb24gd29ya2Zsb3coYWdlbnQsIHNlc3Npb25JZCwgLi4uYXJncykge1xuICBcInVzZSB3b3JrZmxvd1wiO1xuICByZXR1cm4gYWdlbnQuc2Vzc2lvbihzZXNzaW9uSWQpLnNlbmQoLi4uYXJncyk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGhhbmRsZXIoXG4gIHJlcTogUmVxdWVzdCxcbiAgY3R4OiB7IHBhcmFtczogUHJvbWlzZTx7IGFnZW50OiBzdHJpbmc7IHBhdGg/OiBzdHJpbmdbXSB9PiB9XG4pIHtcbiAgY29uc3QgcGFyYW1zID0gYXdhaXQgY3R4LnBhcmFtcztcbiAgY29uc3QgbmFtZSA9IHBhcmFtcy5hZ2VudDtcbiAgY29uc3QgaW5zdGFuY2UgPSBhd2FpdCBydW50aW1lLnJlc29sdmVBZ2VudCh7IG5hbWUsIGFnZW50cyB9KTtcblxuICBpZiAoIWluc3RhbmNlKSB7XG4gICAgY29uc3QgYXZhaWxhYmxlID0gT2JqZWN0LmtleXMoYWdlbnRzKS5qb2luKFwiLCBcIik7XG4gICAgY29uc3QgYm9keSA9XG4gICAgICBcXGBBZ2VudCBcIlxcJHtuYW1lfVwiIG5vdCBmb3VuZC5cXFxcblxcXFxuXFxgICtcbiAgICAgIFxcYEF2YWlsYWJsZSBhZ2VudHM6IFxcJHthdmFpbGFibGV9XFxcXG5cXFxcblxcYCArXG4gICAgICBcXGBoaW50OiBlYWNoIGZvbGRlciBpbnNpZGUgYWdlbnRzLyBiZWNvbWVzIGFuIGFnZW50LlxcXFxuXFxgICtcbiAgICAgIFxcYCAgICAgIENyZWF0ZSBhZ2VudHMvXFwke25hbWV9LyB0byBhZGQgdGhpcyBhZ2VudC5cXFxcblxcYDtcbiAgICByZXR1cm4gbmV3IFJlc3BvbnNlKGJvZHksIHsgc3RhdHVzOiA0MDQgfSk7XG4gIH1cblxuICByZXR1cm4gaGFuZGxlUmVxdWVzdChpbnN0YW5jZSwgeyBiYXNlUGF0aDogXFxgLy53ZWxsLWtub3duL2FnZW50cy9cXCR7bmFtZX1cXGAsIHdvcmtmbG93IH0pLmZldGNoKHJlcSk7XG59XG5cbmV4cG9ydCBjb25zdCBHRVQgPSBoYW5kbGVyO1xuZXhwb3J0IGNvbnN0IFBPU1QgPSBoYW5kbGVyO1xuYDtcbiAgfVxuXG4gIC8qKlxuICAgKiBQdXJlIGNvZGVnZW4gc3RlcDogc2NhbiBhZ2VudHMgYW5kIHJldHVybiB0aGUgZ2VuZXJhdGVkIHNvdXJjZVxuICAgKiBzdHJpbmdzIHdpdGhvdXQgdG91Y2hpbmcgdGhlIGZpbGVzeXN0ZW0uIFVzZWZ1bCBmb3IgYWRhcHRlcnMgdGhhdFxuICAgKiBuZWVkIHRvIGNvbnRyb2wgd2hlcmUgYW5kIGhvdyBmaWxlcyBhcmUgd3JpdHRlbi5cbiAgICpcbiAgICogUmV0dXJucyBgbnVsbGAgd2hlbiBubyBhZ2VudHMgYXJlIGZvdW5kLlxuICAgKi9cbiAgZmlsZXNUb1dyaXRlKCk6IHtcbiAgICByZWdpc3RyeVNvdXJjZTogc3RyaW5nO1xuICAgIHJvdXRlU291cmNlOiBzdHJpbmc7XG4gICAgZGlyOiBzdHJpbmc7XG4gIH0gfCBudWxsIHtcbiAgICBjb25zdCBhZ2VudHMgPSB0aGlzLmZyYW1ld29yay5kaXNjb3ZlckFnZW50cygpO1xuXG4gICAgaWYgKGFnZW50cy5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHRoaXMuZnJhbWV3b3JrLmxvZyhcbiAgICAgIFwiZGlzY292ZXJlZCBhZ2VudHM6XCIsXG4gICAgICBhZ2VudHMubWFwKChhKSA9PiBhLm5hbWUpXG4gICAgKTtcblxuICAgIGNvbnN0IGRpciA9IHBhdGguam9pbihcbiAgICAgIHRoaXMuZnJhbWV3b3JrLmN3ZCxcbiAgICAgIHRoaXMuYXBwRGlyLFxuICAgICAgXCIud2VsbC1rbm93blwiLFxuICAgICAgXCJhZ2VudHNcIixcbiAgICAgIFwiW2FnZW50XVwiLFxuICAgICAgXCJbWy4uLnBhdGhdXVwiXG4gICAgKTtcblxuICAgIGNvbnN0IHJlZ2lzdHJ5U291cmNlID0gdGhpcy5mcmFtZXdvcmsuZ2VuZXJhdGVSZWdpc3RyeVNvdXJjZSh7XG4gICAgICBhZ2VudHMsXG4gICAgICBvdXRwdXREaXI6IGRpcixcbiAgICB9KTtcbiAgICBjb25zdCByb3V0ZVNvdXJjZSA9IHRoaXMuZ2VuZXJhdGVOZXh0Um91dGVIYW5kbGVyU291cmNlKHtcbiAgICAgIHJlZ2lzdHJ5SW1wb3J0UGF0aDogXCIuL19yZWdpc3RyeVwiLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHsgcmVnaXN0cnlTb3VyY2UsIHJvdXRlU291cmNlLCBkaXIgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTY2FuIGZvciBhZ2VudHMsIGdlbmVyYXRlIHNvdXJjZSwgYW5kIHdyaXRlIHRoZSBgX3JlZ2lzdHJ5LnRzYCBhbmRcbiAgICogYHJvdXRlLnRzYCBmaWxlcyBpbnRvIHRoZSBOZXh0LmpzIGFwcCBkaXJlY3RvcnkuXG4gICAqL1xuICB3cml0ZUZpbGVzKCk6IHZvaWQge1xuICAgIGNvbnN0IGZpbGVzVG9Xcml0ZSA9IHRoaXMuZmlsZXNUb1dyaXRlKCk7XG5cbiAgICBpZiAoIWZpbGVzVG9Xcml0ZSkge1xuICAgICAgY29uc29sZS53YXJuKFwiW3dpdGhBZ2VudHNdIE5vIGFnZW50cyBmb3VuZFwiKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB7IHJlZ2lzdHJ5U291cmNlLCByb3V0ZVNvdXJjZSwgZGlyIH0gPSBmaWxlc1RvV3JpdGU7XG5cbiAgICBmcy5ta2RpclN5bmMoZGlyLCB7IHJlY3Vyc2l2ZTogdHJ1ZSB9KTtcbiAgICBmcy53cml0ZUZpbGVTeW5jKHBhdGguam9pbihkaXIsIFwiX3JlZ2lzdHJ5LnRzXCIpLCByZWdpc3RyeVNvdXJjZSk7XG4gICAgZnMud3JpdGVGaWxlU3luYyhwYXRoLmpvaW4oZGlyLCBcInJvdXRlLnRzXCIpLCByb3V0ZVNvdXJjZSk7XG5cbiAgICBjb25zdCBnaXRpZ25vcmVQYXRoID0gcGF0aC5qb2luKGRpciwgXCIuZ2l0aWdub3JlXCIpO1xuICAgIGlmICghZnMuZXhpc3RzU3luYyhnaXRpZ25vcmVQYXRoKSkge1xuICAgICAgZnMud3JpdGVGaWxlU3luYyhnaXRpZ25vcmVQYXRoLCBcIipcXG5cIik7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBoYXNBcHBMYXlvdXQoZGlyOiBzdHJpbmcpOiBib29sZWFuIHtcbiAgICByZXR1cm4gW1wibGF5b3V0LnRzeFwiLCBcImxheW91dC5qc1wiLCBcImxheW91dC5qc3hcIl0uc29tZSgoZikgPT5cbiAgICAgIGZzLmV4aXN0c1N5bmMocGF0aC5qb2luKGRpciwgZikpXG4gICAgKTtcbiAgfVxufVxuIiwgImltcG9ydCB7IEZyYW1ld29yayB9IGZyb20gXCIuLi9mcmFtZXdvcmsvZnJhbWV3b3JrXCI7XG5pbXBvcnQgeyBOZXh0LCB0eXBlIE5leHRDb25maWdJbnB1dCB9IGZyb20gXCIuL25leHRcIjtcblxuZXhwb3J0IHR5cGUgeyBOZXh0Q29uZmlnSW5wdXQsIFdpdGhBZ2VudHNDb25maWcgfSBmcm9tIFwiLi9uZXh0XCI7XG5cbi8qKlxuICogTmV4dC5qcyBjb25maWcgd3JhcHBlciB0aGF0IGRpc2NvdmVycyBhZ2VudHMgb24gdGhlIGZpbGVzeXN0ZW0gYW5kXG4gKiBnZW5lcmF0ZXMgdGhlIHJvdXRlIGhhbmRsZXIgKyByZWdpc3RyeSBmaWxlcyBuZWVkZWQgdG8gc2VydmUgdGhlbS5cbiAqXG4gKiBDYWxsIHRoaXMgaW4gYG5leHQuY29uZmlnLnRzYDpcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHNcbiAqIGltcG9ydCB7IHdpdGhBZ2VudHMgfSBmcm9tIFwiZXhwZXJpbWVudGFsLWFnZW50L25leHQvYWdlbnRzXCI7XG4gKlxuICogZXhwb3J0IGRlZmF1bHQgd2l0aEFnZW50cyh7IHJlYWN0U3RyaWN0TW9kZTogdHJ1ZSB9KTtcbiAqIGBgYFxuICpcbiAqIERlYnVnIGxvZ3M6XG4gKiBgYGB0c1xuICogaW1wb3J0IHsgd2l0aEFnZW50cyB9IGZyb20gXCJleHBlcmltZW50YWwtYWdlbnQvbmV4dC9hZ2VudHNcIjtcbiAqXG4gKiBleHBvcnQgZGVmYXVsdCB3aXRoQWdlbnRzKHsgcmVhY3RTdHJpY3RNb2RlOiB0cnVlIH0sIHsgZGVidWc6IHRydWUgfSk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdpdGhBZ2VudHMoXG4gIGNvbmZpZzogTmV4dENvbmZpZ0lucHV0LFxuICBhZ2VudHNDb25maWc6IFBpY2s8XG4gICAgQ29uc3RydWN0b3JQYXJhbWV0ZXJzPHR5cGVvZiBGcmFtZXdvcms+WzBdLFxuICAgIFwiYWdlbnRzRGlyXCIgfCBcImRlYnVnXCJcbiAgPiA9IHt9XG4pOiBOZXh0Q29uZmlnSW5wdXQge1xuICBjb25zdCBmcmFtZXdvcmsgPSBuZXcgRnJhbWV3b3JrKGFnZW50c0NvbmZpZyk7XG4gIGNvbnN0IG5leHQgPSBuZXcgTmV4dChmcmFtZXdvcmspO1xuICBuZXh0LndyaXRlRmlsZXMoKTtcblxuICByZXR1cm4gY29uZmlnO1xufVxuIl0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7O0FBQUEsWUFBWSxRQUFRO0FBQ3BCLFlBQVksVUFBVTtBQTJDZixJQUFNLE9BQU4sTUFBVztBQUFBLEVBQ2hCLFlBQTZCLFdBQXNCO0FBQXRCO0FBQUEsRUFBdUI7QUFBQSxFQUVwRCxJQUFZLFNBQWlCO0FBQzNCLFVBQU0sTUFBTSxLQUFLLFVBQVU7QUFDM0IsVUFBTSxZQUFpQixVQUFLLEtBQUssT0FBTyxLQUFLO0FBQzdDLFVBQU0sYUFBa0IsVUFBSyxLQUFLLEtBQUs7QUFFdkMsUUFBSSxLQUFLLGFBQWEsU0FBUyxHQUFHO0FBQ2hDLGFBQU87QUFBQSxJQUNUO0FBQ0EsUUFBSSxLQUFLLGFBQWEsVUFBVSxHQUFHO0FBQ2pDLGFBQU87QUFBQSxJQUNUO0FBQ0EsUUFBTyxjQUFXLFNBQVMsR0FBRztBQUM1QixhQUFPO0FBQUEsSUFDVDtBQUNBLFdBQU87QUFBQSxFQUNUO0FBQUEsRUFFQSwrQkFBK0IsTUFBOEM7QUFDM0UsV0FBTztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLHlCQU9jLEtBQUssVUFBVSxLQUFLLGtCQUFrQixDQUFDO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUErQjlEO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQVNBLGVBSVM7QUFDUCxVQUFNLFNBQVMsS0FBSyxVQUFVLGVBQWU7QUFFN0MsUUFBSSxPQUFPLFdBQVcsR0FBRztBQUN2QixhQUFPO0FBQUEsSUFDVDtBQUVBLFNBQUssVUFBVTtBQUFBLE1BQ2I7QUFBQSxNQUNBLE9BQU8sSUFBSSxDQUFDLE1BQU0sRUFBRSxJQUFJO0FBQUEsSUFDMUI7QUFFQSxVQUFNLE1BQVc7QUFBQSxNQUNmLEtBQUssVUFBVTtBQUFBLE1BQ2YsS0FBSztBQUFBLE1BQ0w7QUFBQSxNQUNBO0FBQUEsTUFDQTtBQUFBLE1BQ0E7QUFBQSxJQUNGO0FBRUEsVUFBTSxpQkFBaUIsS0FBSyxVQUFVLHVCQUF1QjtBQUFBLE1BQzNEO0FBQUEsTUFDQSxXQUFXO0FBQUEsSUFDYixDQUFDO0FBQ0QsVUFBTSxjQUFjLEtBQUssK0JBQStCO0FBQUEsTUFDdEQsb0JBQW9CO0FBQUEsSUFDdEIsQ0FBQztBQUVELFdBQU8sRUFBRSxnQkFBZ0IsYUFBYSxJQUFJO0FBQUEsRUFDNUM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBTUEsYUFBbUI7QUFDakIsVUFBTSxlQUFlLEtBQUssYUFBYTtBQUV2QyxRQUFJLENBQUMsY0FBYztBQUNqQixjQUFRLEtBQUssOEJBQThCO0FBQzNDO0FBQUEsSUFDRjtBQUVBLFVBQU0sRUFBRSxnQkFBZ0IsYUFBYSxJQUFJLElBQUk7QUFFN0MsSUFBRyxhQUFVLEtBQUssRUFBRSxXQUFXLEtBQUssQ0FBQztBQUNyQyxJQUFHLGlCQUFtQixVQUFLLEtBQUssY0FBYyxHQUFHLGNBQWM7QUFDL0QsSUFBRyxpQkFBbUIsVUFBSyxLQUFLLFVBQVUsR0FBRyxXQUFXO0FBRXhELFVBQU0sZ0JBQXFCLFVBQUssS0FBSyxZQUFZO0FBQ2pELFFBQUksQ0FBSSxjQUFXLGFBQWEsR0FBRztBQUNqQyxNQUFHLGlCQUFjLGVBQWUsS0FBSztBQUFBLElBQ3ZDO0FBQUEsRUFDRjtBQUFBLEVBRVEsYUFBYSxLQUFzQjtBQUN6QyxXQUFPLENBQUMsY0FBYyxhQUFhLFlBQVksRUFBRTtBQUFBLE1BQUssQ0FBQyxNQUNsRCxjQUFnQixVQUFLLEtBQUssQ0FBQyxDQUFDO0FBQUEsSUFDakM7QUFBQSxFQUNGO0FBQ0Y7OztBQ3hKTyxTQUFTLFdBQ2QsUUFDQSxlQUdJLENBQUMsR0FDWTtBQUNqQixRQUFNLFlBQVksSUFBSSxVQUFVLFlBQVk7QUFDNUMsUUFBTSxPQUFPLElBQUksS0FBSyxTQUFTO0FBQy9CLE9BQUssV0FBVztBQUVoQixTQUFPO0FBQ1Q7IiwKICAibmFtZXMiOiBbXQp9Cg==