@dbx-tools/appkit-graphiti 0.6.186 → 0.6.191

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,6 +5,8 @@ AppKit process plugin for the Python `dbx-tools-graphiti` MCP runtime.
5
5
  ## Key features
6
6
 
7
7
  - starts Graphiti as a supervised AppKit sidecar;
8
+ - installs the version-matched `dbx-model-proxy` release through the generated
9
+ `@dbx-tools/cli` Rust command registry;
8
10
  - enables the Python Postgres write journal when the app supplies Lakebase or
9
11
  PostgreSQL connection environment;
10
12
  - starts an internal loopback Caddy proxy in front of upstream Graphiti, then
@@ -13,12 +15,12 @@ AppKit process plugin for the Python `dbx-tools-graphiti` MCP runtime.
13
15
  resource id, overriding every caller-supplied group;
14
16
  - exposes only operations that can be constrained to that group and removes
15
17
  UUID arguments that could reference another user's graph objects;
16
- - selects separate free loopback ports for Graphiti, LiteLLM, and Caddy unless
18
+ - selects separate free loopback ports for Graphiti, the model proxy, and Caddy unless
17
19
  they are explicitly configured;
18
20
  - exposes the user-scoped tools through `plugins.graphiti?.toolkit()` for
19
21
  `@dbx-tools/appkit-mastra` agents;
20
22
  - runs Graphiti and Caddy under `concurrently`, while the Python launcher runs
21
- Graphiti and LiteLLM under Honcho;
23
+ Graphiti and `dbx-model-proxy` under Honcho;
22
24
  - propagates termination signals through both supervisors, which escalate
23
25
  unresponsive process groups to `SIGKILL`;
24
26
  - exposes the MCP path through plugin exports.
@@ -26,7 +28,7 @@ AppKit process plugin for the Python `dbx-tools-graphiti` MCP runtime.
26
28
  ## Why use this over native AppKit
27
29
 
28
30
  AppKit has no Graphiti or embedded MCP sidecar. This package owns AppKit routes
29
- and process lifecycle while `dbx-tools-graphiti` owns Graphiti, Neo4j, LiteLLM,
31
+ and process lifecycle while `dbx-tools-graphiti` owns Graphiti, Neo4j, the model proxy,
30
32
  and Postgres recovery.
31
33
 
32
34
  ## Register
@@ -45,7 +47,7 @@ await appkit.createApp({
45
47
  ```
46
48
 
47
49
  AppKit continues to listen on `DATABRICKS_APP_PORT`. The plugin adds a
48
- user-scoped MCP server at `/api/graphiti/mcp`; Graphiti, LiteLLM, and Caddy
50
+ user-scoped MCP server at `/api/graphiti/mcp`; Graphiti, the model proxy, and Caddy
49
51
  remain loopback-only. The plugin's manifest declares the Lakebase resource
50
52
  requirements used by generated deployments, so Graphiti does not require a
51
53
  separate `lakebase()` plugin. Local callers must still supply a Lakebase or
@@ -76,7 +78,7 @@ Plugin config overrides environment values:
76
78
 
77
79
  - `graphitiPort` / `GRAPHITI_PORT`: Graphiti's internal port; a free loopback
78
80
  port is selected automatically when omitted;
79
- - `litellmPort` / `LITELLM_PORT`: the managed LiteLLM port; a separate free
81
+ - `modelProxyPort` / `MODEL_PROXY_PORT`: the managed model-proxy port; a separate free
80
82
  loopback port is selected automatically so another local proxy cannot be
81
83
  mistaken for Graphiti's model backend;
82
84
  - `proxyPort` / `PROXY_PORT`: Caddy's internal port; a third free loopback port
package/index.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  // Hand edits are overwritten on the next watch; this file is read-only.
4
4
 
5
5
  export const PACKAGE_IDENTIFIER = "@dbx-tools/appkit-graphiti";
6
- export const PACKAGE_VERSION = "0.6.186";
6
+ export const PACKAGE_VERSION = "0.6.191";
7
7
  export * as config from "./src/config.ts";
8
8
  export * as plugin from "./src/plugin.ts";
9
9
  export { GRAPHITI_CONFIG_SCHEMA } from "./src/config.ts";
package/lib/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export declare const PACKAGE_IDENTIFIER = "@dbx-tools/appkit-graphiti";
2
- export declare const PACKAGE_VERSION = "0.6.186";
2
+ export declare const PACKAGE_VERSION = "0.6.191";
3
3
  export * as config from "./src/config.ts";
4
4
  export * as plugin from "./src/plugin.ts";
5
5
  export { GRAPHITI_CONFIG_SCHEMA } from "./src/config.ts";
package/lib/index.js CHANGED
@@ -2,9 +2,9 @@
2
2
  // Regenerated from the exporting modules in ./src.
3
3
  // Hand edits are overwritten on the next watch; this file is read-only.
4
4
  export const PACKAGE_IDENTIFIER = "@dbx-tools/appkit-graphiti";
5
- export const PACKAGE_VERSION = "0.6.186";
5
+ export const PACKAGE_VERSION = "0.6.191";
6
6
  export * as config from "./src/config.js";
7
7
  export * as plugin from "./src/plugin.js";
8
8
  export { GRAPHITI_CONFIG_SCHEMA } from "./src/config.js";
9
9
  export { GraphitiPlugin, graphiti } from "./src/plugin.js";
10
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyw0QkFBNEIsQ0FBQztBQUMvRCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsU0FBUyxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxNQUFNLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxLQUFLLE1BQU0sTUFBTSxpQkFBaUIsQ0FBQztBQUMxQyxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUV6RCxPQUFPLEVBQUUsY0FBYyxFQUFFLFFBQVEsRUFBRSxNQUFNLGlCQUFpQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gR0VORVJBVEVEIGJ5IHByb2plbiB3YXRjaCAtIERPIE5PVCBFRElULlxuLy8gUmVnZW5lcmF0ZWQgZnJvbSB0aGUgZXhwb3J0aW5nIG1vZHVsZXMgaW4gLi9zcmMuXG4vLyBIYW5kIGVkaXRzIGFyZSBvdmVyd3JpdHRlbiBvbiB0aGUgbmV4dCB3YXRjaDsgdGhpcyBmaWxlIGlzIHJlYWQtb25seS5cblxuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfSURFTlRJRklFUiA9IFwiQGRieC10b29scy9hcHBraXQtZ3JhcGhpdGlcIjtcbmV4cG9ydCBjb25zdCBQQUNLQUdFX1ZFUlNJT04gPSBcIjAuNi4xODZcIjtcbmV4cG9ydCAqIGFzIGNvbmZpZyBmcm9tIFwiLi9zcmMvY29uZmlnLnRzXCI7XG5leHBvcnQgKiBhcyBwbHVnaW4gZnJvbSBcIi4vc3JjL3BsdWdpbi50c1wiO1xuZXhwb3J0IHsgR1JBUEhJVElfQ09ORklHX1NDSEVNQSB9IGZyb20gXCIuL3NyYy9jb25maWcudHNcIjtcbmV4cG9ydCB0eXBlIHsgR3JhcGhpdGlQbHVnaW5Db25maWcsIFJlc29sdmVkR3JhcGhpdGlQbHVnaW5Db25maWcgfSBmcm9tIFwiLi9zcmMvY29uZmlnLnRzXCI7XG5leHBvcnQgeyBHcmFwaGl0aVBsdWdpbiwgZ3JhcGhpdGkgfSBmcm9tIFwiLi9zcmMvcGx1Z2luLnRzXCI7XG4iXX0=
10
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyw0QkFBNEIsQ0FBQztBQUMvRCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsU0FBUyxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxNQUFNLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxLQUFLLE1BQU0sTUFBTSxpQkFBaUIsQ0FBQztBQUMxQyxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUV6RCxPQUFPLEVBQUUsY0FBYyxFQUFFLFFBQVEsRUFBRSxNQUFNLGlCQUFpQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gR0VORVJBVEVEIGJ5IHByb2plbiB3YXRjaCAtIERPIE5PVCBFRElULlxuLy8gUmVnZW5lcmF0ZWQgZnJvbSB0aGUgZXhwb3J0aW5nIG1vZHVsZXMgaW4gLi9zcmMuXG4vLyBIYW5kIGVkaXRzIGFyZSBvdmVyd3JpdHRlbiBvbiB0aGUgbmV4dCB3YXRjaDsgdGhpcyBmaWxlIGlzIHJlYWQtb25seS5cblxuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfSURFTlRJRklFUiA9IFwiQGRieC10b29scy9hcHBraXQtZ3JhcGhpdGlcIjtcbmV4cG9ydCBjb25zdCBQQUNLQUdFX1ZFUlNJT04gPSBcIjAuNi4xOTFcIjtcbmV4cG9ydCAqIGFzIGNvbmZpZyBmcm9tIFwiLi9zcmMvY29uZmlnLnRzXCI7XG5leHBvcnQgKiBhcyBwbHVnaW4gZnJvbSBcIi4vc3JjL3BsdWdpbi50c1wiO1xuZXhwb3J0IHsgR1JBUEhJVElfQ09ORklHX1NDSEVNQSB9IGZyb20gXCIuL3NyYy9jb25maWcudHNcIjtcbmV4cG9ydCB0eXBlIHsgR3JhcGhpdGlQbHVnaW5Db25maWcsIFJlc29sdmVkR3JhcGhpdGlQbHVnaW5Db25maWcgfSBmcm9tIFwiLi9zcmMvY29uZmlnLnRzXCI7XG5leHBvcnQgeyBHcmFwaGl0aVBsdWdpbiwgZ3JhcGhpdGkgfSBmcm9tIFwiLi9zcmMvcGx1Z2luLnRzXCI7XG4iXX0=
@@ -6,14 +6,14 @@
6
6
  import { type BasePluginConfig } from "@databricks/appkit";
7
7
  export interface GraphitiPluginConfig extends BasePluginConfig {
8
8
  graphitiPort?: number;
9
- litellmPort?: number;
9
+ modelProxyPort?: number;
10
10
  proxyPort?: number;
11
11
  python?: string;
12
12
  journalNamespace?: string;
13
13
  }
14
14
  export interface ResolvedGraphitiPluginConfig extends GraphitiPluginConfig {
15
15
  graphitiPort: number;
16
- litellmPort: number;
16
+ modelProxyPort: number;
17
17
  proxyPort: number;
18
18
  python: string;
19
19
  journalNamespace: string;
@@ -26,7 +26,7 @@ export declare const GRAPHITI_CONFIG_SCHEMA: {
26
26
  minimum: number;
27
27
  maximum: number;
28
28
  };
29
- litellmPort: {
29
+ modelProxyPort: {
30
30
  type: "integer";
31
31
  minimum: number;
32
32
  maximum: number;
package/lib/src/config.js CHANGED
@@ -9,7 +9,7 @@ export const GRAPHITI_CONFIG_SCHEMA = {
9
9
  type: "object",
10
10
  properties: {
11
11
  graphitiPort: { type: "integer", minimum: 1, maximum: 65535 },
12
- litellmPort: { type: "integer", minimum: 1, maximum: 65535 },
12
+ modelProxyPort: { type: "integer", minimum: 1, maximum: 65535 },
13
13
  proxyPort: { type: "integer", minimum: 1, maximum: 65535 },
14
14
  python: { type: "string" },
15
15
  journalNamespace: { type: "string" },
@@ -19,9 +19,9 @@ export const GRAPHITI_CONFIG_SCHEMA = {
19
19
  /** Resolve plugin config over exact environment values and stable defaults. */
20
20
  export function resolveGraphitiConfig(config = {}) {
21
21
  const graphitiPort = coreConfig.port(config.graphitiPort, "GRAPHITI_PORT", 0, coreConfig.ENV_ONLY);
22
- const litellmPort = coreConfig.port(config.litellmPort, "LITELLM_PORT", 0, coreConfig.ENV_ONLY);
22
+ const modelProxyPort = coreConfig.port(config.modelProxyPort, "MODEL_PROXY_PORT", 0, coreConfig.ENV_ONLY);
23
23
  const proxyPort = coreConfig.port(config.proxyPort, "PROXY_PORT", 0, coreConfig.ENV_ONLY);
24
- const configuredPorts = [graphitiPort, litellmPort, proxyPort].filter(Boolean);
24
+ const configuredPorts = [graphitiPort, modelProxyPort, proxyPort].filter(Boolean);
25
25
  if (new Set(configuredPorts).size !== configuredPorts.length) {
26
26
  throw new ConfigurationError("Graphiti sidecar ports must be distinct");
27
27
  }
@@ -33,10 +33,10 @@ export function resolveGraphitiConfig(config = {}) {
33
33
  "default";
34
34
  return {
35
35
  graphitiPort,
36
- litellmPort,
36
+ modelProxyPort,
37
37
  proxyPort,
38
38
  python,
39
39
  journalNamespace,
40
40
  };
41
41
  }
42
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBQ0gsT0FBTyxFQUFFLGtCQUFrQixFQUF5QixNQUFNLG9CQUFvQixDQUFDO0FBQy9FLE9BQU8sRUFBRSxNQUFNLElBQUksVUFBVSxFQUFFLE9BQU8sSUFBSSxXQUFXLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQW1CL0UsTUFBTSxDQUFDLE1BQU0sc0JBQXNCLEdBQUc7SUFDcEMsSUFBSSxFQUFFLFFBQVE7SUFDZCxVQUFVLEVBQUU7UUFDVixZQUFZLEVBQUUsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRTtRQUM3RCxXQUFXLEVBQUUsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRTtRQUM1RCxTQUFTLEVBQUUsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRTtRQUMxRCxNQUFNLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFO1FBQzFCLGdCQUFnQixFQUFFLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRTtLQUNyQztJQUNELG9CQUFvQixFQUFFLEtBQUs7Q0FDTixDQUFDO0FBRXhCLCtFQUErRTtBQUMvRSxNQUFNLFVBQVUscUJBQXFCLENBQ25DLFNBQStCLEVBQUU7SUFFakMsTUFBTSxZQUFZLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FDbEMsTUFBTSxDQUFDLFlBQVksRUFDbkIsZUFBZSxFQUNmLENBQUMsRUFDRCxVQUFVLENBQUMsUUFBUSxDQUNwQixDQUFDO0lBQ0YsTUFBTSxXQUFXLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsV0FBVyxFQUFFLGNBQWMsRUFBRSxDQUFDLEVBQUUsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ2hHLE1BQU0sU0FBUyxHQUFHLFVBQVUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLFNBQVMsRUFBRSxZQUFZLEVBQUUsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUMxRixNQUFNLGVBQWUsR0FBRyxDQUFDLFlBQVksRUFBRSxXQUFXLEVBQUUsU0FBUyxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQy9FLElBQUksSUFBSSxHQUFHLENBQUMsZUFBZSxDQUFDLENBQUMsSUFBSSxLQUFLLGVBQWUsQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUM3RCxNQUFNLElBQUksa0JBQWtCLENBQUMseUNBQXlDLENBQUMsQ0FBQztJQUMxRSxDQUFDO0lBQ0QsTUFBTSxNQUFNLEdBQ1YsTUFBTSxDQUFDLE1BQU0sSUFBSSxVQUFVLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxVQUFVLENBQUMsUUFBUSxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksU0FBUyxDQUFDO0lBQ3ZGLE1BQU0sZ0JBQWdCLEdBQ3BCLE1BQU0sQ0FBQyxnQkFBZ0I7UUFDdkIsVUFBVSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxVQUFVLENBQUMsUUFBUSxDQUFDLEVBQUUsSUFBSSxFQUFFO1FBQ2pFLE9BQU8sQ0FBQyxHQUFHLENBQUMsbUJBQW1CLEVBQUUsSUFBSSxFQUFFO1FBQ3ZDLFdBQVcsQ0FBQyxJQUFJLEVBQUU7UUFDbEIsU0FBUyxDQUFDO0lBQ1osT0FBTztRQUNMLFlBQVk7UUFDWixXQUFXO1FBQ1gsU0FBUztRQUNULE1BQU07UUFDTixnQkFBZ0I7S0FDakIsQ0FBQztBQUNKLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEFwcEtpdCBHcmFwaGl0aSBzaWRlY2FyIHBvcnRzIGFuZCBQeXRob24gY29tbWFuZC5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cbmltcG9ydCB7IENvbmZpZ3VyYXRpb25FcnJvciwgdHlwZSBCYXNlUGx1Z2luQ29uZmlnIH0gZnJvbSBcIkBkYXRhYnJpY2tzL2FwcGtpdFwiO1xuaW1wb3J0IHsgY29uZmlnIGFzIGNvcmVDb25maWcsIHByb2plY3QgYXMgY29yZVByb2plY3QgfSBmcm9tIFwiQGRieC10b29scy9jb3JlXCI7XG5pbXBvcnQgdHlwZSB7IEpTT05TY2hlbWE3IH0gZnJvbSBcImpzb24tc2NoZW1hXCI7XG5cbmV4cG9ydCBpbnRlcmZhY2UgR3JhcGhpdGlQbHVnaW5Db25maWcgZXh0ZW5kcyBCYXNlUGx1Z2luQ29uZmlnIHtcbiAgZ3JhcGhpdGlQb3J0PzogbnVtYmVyO1xuICBsaXRlbGxtUG9ydD86IG51bWJlcjtcbiAgcHJveHlQb3J0PzogbnVtYmVyO1xuICBweXRob24/OiBzdHJpbmc7XG4gIGpvdXJuYWxOYW1lc3BhY2U/OiBzdHJpbmc7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVzb2x2ZWRHcmFwaGl0aVBsdWdpbkNvbmZpZyBleHRlbmRzIEdyYXBoaXRpUGx1Z2luQ29uZmlnIHtcbiAgZ3JhcGhpdGlQb3J0OiBudW1iZXI7XG4gIGxpdGVsbG1Qb3J0OiBudW1iZXI7XG4gIHByb3h5UG9ydDogbnVtYmVyO1xuICBweXRob246IHN0cmluZztcbiAgam91cm5hbE5hbWVzcGFjZTogc3RyaW5nO1xufVxuXG5leHBvcnQgY29uc3QgR1JBUEhJVElfQ09ORklHX1NDSEVNQSA9IHtcbiAgdHlwZTogXCJvYmplY3RcIixcbiAgcHJvcGVydGllczoge1xuICAgIGdyYXBoaXRpUG9ydDogeyB0eXBlOiBcImludGVnZXJcIiwgbWluaW11bTogMSwgbWF4aW11bTogNjU1MzUgfSxcbiAgICBsaXRlbGxtUG9ydDogeyB0eXBlOiBcImludGVnZXJcIiwgbWluaW11bTogMSwgbWF4aW11bTogNjU1MzUgfSxcbiAgICBwcm94eVBvcnQ6IHsgdHlwZTogXCJpbnRlZ2VyXCIsIG1pbmltdW06IDEsIG1heGltdW06IDY1NTM1IH0sXG4gICAgcHl0aG9uOiB7IHR5cGU6IFwic3RyaW5nXCIgfSxcbiAgICBqb3VybmFsTmFtZXNwYWNlOiB7IHR5cGU6IFwic3RyaW5nXCIgfSxcbiAgfSxcbiAgYWRkaXRpb25hbFByb3BlcnRpZXM6IGZhbHNlLFxufSBzYXRpc2ZpZXMgSlNPTlNjaGVtYTc7XG5cbi8qKiBSZXNvbHZlIHBsdWdpbiBjb25maWcgb3ZlciBleGFjdCBlbnZpcm9ubWVudCB2YWx1ZXMgYW5kIHN0YWJsZSBkZWZhdWx0cy4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNvbHZlR3JhcGhpdGlDb25maWcoXG4gIGNvbmZpZzogR3JhcGhpdGlQbHVnaW5Db25maWcgPSB7fSxcbik6IFJlc29sdmVkR3JhcGhpdGlQbHVnaW5Db25maWcge1xuICBjb25zdCBncmFwaGl0aVBvcnQgPSBjb3JlQ29uZmlnLnBvcnQoXG4gICAgY29uZmlnLmdyYXBoaXRpUG9ydCxcbiAgICBcIkdSQVBISVRJX1BPUlRcIixcbiAgICAwLFxuICAgIGNvcmVDb25maWcuRU5WX09OTFksXG4gICk7XG4gIGNvbnN0IGxpdGVsbG1Qb3J0ID0gY29yZUNvbmZpZy5wb3J0KGNvbmZpZy5saXRlbGxtUG9ydCwgXCJMSVRFTExNX1BPUlRcIiwgMCwgY29yZUNvbmZpZy5FTlZfT05MWSk7XG4gIGNvbnN0IHByb3h5UG9ydCA9IGNvcmVDb25maWcucG9ydChjb25maWcucHJveHlQb3J0LCBcIlBST1hZX1BPUlRcIiwgMCwgY29yZUNvbmZpZy5FTlZfT05MWSk7XG4gIGNvbnN0IGNvbmZpZ3VyZWRQb3J0cyA9IFtncmFwaGl0aVBvcnQsIGxpdGVsbG1Qb3J0LCBwcm94eVBvcnRdLmZpbHRlcihCb29sZWFuKTtcbiAgaWYgKG5ldyBTZXQoY29uZmlndXJlZFBvcnRzKS5zaXplICE9PSBjb25maWd1cmVkUG9ydHMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IENvbmZpZ3VyYXRpb25FcnJvcihcIkdyYXBoaXRpIHNpZGVjYXIgcG9ydHMgbXVzdCBiZSBkaXN0aW5jdFwiKTtcbiAgfVxuICBjb25zdCBweXRob24gPVxuICAgIGNvbmZpZy5weXRob24gPz8gY29yZUNvbmZpZy50ZXh0KFwiUFlUSE9OXCIsIGNvcmVDb25maWcuRU5WX09OTFkpPy50cmltKCkgPz8gXCJweXRob24zXCI7XG4gIGNvbnN0IGpvdXJuYWxOYW1lc3BhY2UgPVxuICAgIGNvbmZpZy5qb3VybmFsTmFtZXNwYWNlID8/XG4gICAgY29yZUNvbmZpZy50ZXh0KFwiSk9VUk5BTF9OQU1FU1BBQ0VcIiwgY29yZUNvbmZpZy5FTlZfT05MWSk/LnRyaW0oKSA/P1xuICAgIHByb2Nlc3MuZW52LkRBVEFCUklDS1NfQVBQX05BTUU/LnRyaW0oKSA/P1xuICAgIGNvcmVQcm9qZWN0Lm5hbWUoKSA/P1xuICAgIFwiZGVmYXVsdFwiO1xuICByZXR1cm4ge1xuICAgIGdyYXBoaXRpUG9ydCxcbiAgICBsaXRlbGxtUG9ydCxcbiAgICBwcm94eVBvcnQsXG4gICAgcHl0aG9uLFxuICAgIGpvdXJuYWxOYW1lc3BhY2UsXG4gIH07XG59XG4iXX0=
42
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbmZpZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBQ0gsT0FBTyxFQUFFLGtCQUFrQixFQUF5QixNQUFNLG9CQUFvQixDQUFDO0FBQy9FLE9BQU8sRUFBRSxNQUFNLElBQUksVUFBVSxFQUFFLE9BQU8sSUFBSSxXQUFXLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQW1CL0UsTUFBTSxDQUFDLE1BQU0sc0JBQXNCLEdBQUc7SUFDcEMsSUFBSSxFQUFFLFFBQVE7SUFDZCxVQUFVLEVBQUU7UUFDVixZQUFZLEVBQUUsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRTtRQUM3RCxjQUFjLEVBQUUsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRTtRQUMvRCxTQUFTLEVBQUUsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxDQUFDLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRTtRQUMxRCxNQUFNLEVBQUUsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFO1FBQzFCLGdCQUFnQixFQUFFLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRTtLQUNyQztJQUNELG9CQUFvQixFQUFFLEtBQUs7Q0FDTixDQUFDO0FBRXhCLCtFQUErRTtBQUMvRSxNQUFNLFVBQVUscUJBQXFCLENBQ25DLFNBQStCLEVBQUU7SUFFakMsTUFBTSxZQUFZLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FDbEMsTUFBTSxDQUFDLFlBQVksRUFDbkIsZUFBZSxFQUNmLENBQUMsRUFDRCxVQUFVLENBQUMsUUFBUSxDQUNwQixDQUFDO0lBQ0YsTUFBTSxjQUFjLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FDcEMsTUFBTSxDQUFDLGNBQWMsRUFDckIsa0JBQWtCLEVBQ2xCLENBQUMsRUFDRCxVQUFVLENBQUMsUUFBUSxDQUNwQixDQUFDO0lBQ0YsTUFBTSxTQUFTLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsU0FBUyxFQUFFLFlBQVksRUFBRSxDQUFDLEVBQUUsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQzFGLE1BQU0sZUFBZSxHQUFHLENBQUMsWUFBWSxFQUFFLGNBQWMsRUFBRSxTQUFTLENBQUMsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDbEYsSUFBSSxJQUFJLEdBQUcsQ0FBQyxlQUFlLENBQUMsQ0FBQyxJQUFJLEtBQUssZUFBZSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQzdELE1BQU0sSUFBSSxrQkFBa0IsQ0FBQyx5Q0FBeUMsQ0FBQyxDQUFDO0lBQzFFLENBQUM7SUFDRCxNQUFNLE1BQU0sR0FDVixNQUFNLENBQUMsTUFBTSxJQUFJLFVBQVUsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLFVBQVUsQ0FBQyxRQUFRLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxTQUFTLENBQUM7SUFDdkYsTUFBTSxnQkFBZ0IsR0FDcEIsTUFBTSxDQUFDLGdCQUFnQjtRQUN2QixVQUFVLENBQUMsSUFBSSxDQUFDLG1CQUFtQixFQUFFLFVBQVUsQ0FBQyxRQUFRLENBQUMsRUFBRSxJQUFJLEVBQUU7UUFDakUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxtQkFBbUIsRUFBRSxJQUFJLEVBQUU7UUFDdkMsV0FBVyxDQUFDLElBQUksRUFBRTtRQUNsQixTQUFTLENBQUM7SUFDWixPQUFPO1FBQ0wsWUFBWTtRQUNaLGNBQWM7UUFDZCxTQUFTO1FBQ1QsTUFBTTtRQUNOLGdCQUFnQjtLQUNqQixDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQXBwS2l0IEdyYXBoaXRpIHNpZGVjYXIgcG9ydHMgYW5kIFB5dGhvbiBjb21tYW5kLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuaW1wb3J0IHsgQ29uZmlndXJhdGlvbkVycm9yLCB0eXBlIEJhc2VQbHVnaW5Db25maWcgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0XCI7XG5pbXBvcnQgeyBjb25maWcgYXMgY29yZUNvbmZpZywgcHJvamVjdCBhcyBjb3JlUHJvamVjdCB9IGZyb20gXCJAZGJ4LXRvb2xzL2NvcmVcIjtcbmltcG9ydCB0eXBlIHsgSlNPTlNjaGVtYTcgfSBmcm9tIFwianNvbi1zY2hlbWFcIjtcblxuZXhwb3J0IGludGVyZmFjZSBHcmFwaGl0aVBsdWdpbkNvbmZpZyBleHRlbmRzIEJhc2VQbHVnaW5Db25maWcge1xuICBncmFwaGl0aVBvcnQ/OiBudW1iZXI7XG4gIG1vZGVsUHJveHlQb3J0PzogbnVtYmVyO1xuICBwcm94eVBvcnQ/OiBudW1iZXI7XG4gIHB5dGhvbj86IHN0cmluZztcbiAgam91cm5hbE5hbWVzcGFjZT86IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXNvbHZlZEdyYXBoaXRpUGx1Z2luQ29uZmlnIGV4dGVuZHMgR3JhcGhpdGlQbHVnaW5Db25maWcge1xuICBncmFwaGl0aVBvcnQ6IG51bWJlcjtcbiAgbW9kZWxQcm94eVBvcnQ6IG51bWJlcjtcbiAgcHJveHlQb3J0OiBudW1iZXI7XG4gIHB5dGhvbjogc3RyaW5nO1xuICBqb3VybmFsTmFtZXNwYWNlOiBzdHJpbmc7XG59XG5cbmV4cG9ydCBjb25zdCBHUkFQSElUSV9DT05GSUdfU0NIRU1BID0ge1xuICB0eXBlOiBcIm9iamVjdFwiLFxuICBwcm9wZXJ0aWVzOiB7XG4gICAgZ3JhcGhpdGlQb3J0OiB7IHR5cGU6IFwiaW50ZWdlclwiLCBtaW5pbXVtOiAxLCBtYXhpbXVtOiA2NTUzNSB9LFxuICAgIG1vZGVsUHJveHlQb3J0OiB7IHR5cGU6IFwiaW50ZWdlclwiLCBtaW5pbXVtOiAxLCBtYXhpbXVtOiA2NTUzNSB9LFxuICAgIHByb3h5UG9ydDogeyB0eXBlOiBcImludGVnZXJcIiwgbWluaW11bTogMSwgbWF4aW11bTogNjU1MzUgfSxcbiAgICBweXRob246IHsgdHlwZTogXCJzdHJpbmdcIiB9LFxuICAgIGpvdXJuYWxOYW1lc3BhY2U6IHsgdHlwZTogXCJzdHJpbmdcIiB9LFxuICB9LFxuICBhZGRpdGlvbmFsUHJvcGVydGllczogZmFsc2UsXG59IHNhdGlzZmllcyBKU09OU2NoZW1hNztcblxuLyoqIFJlc29sdmUgcGx1Z2luIGNvbmZpZyBvdmVyIGV4YWN0IGVudmlyb25tZW50IHZhbHVlcyBhbmQgc3RhYmxlIGRlZmF1bHRzLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVHcmFwaGl0aUNvbmZpZyhcbiAgY29uZmlnOiBHcmFwaGl0aVBsdWdpbkNvbmZpZyA9IHt9LFxuKTogUmVzb2x2ZWRHcmFwaGl0aVBsdWdpbkNvbmZpZyB7XG4gIGNvbnN0IGdyYXBoaXRpUG9ydCA9IGNvcmVDb25maWcucG9ydChcbiAgICBjb25maWcuZ3JhcGhpdGlQb3J0LFxuICAgIFwiR1JBUEhJVElfUE9SVFwiLFxuICAgIDAsXG4gICAgY29yZUNvbmZpZy5FTlZfT05MWSxcbiAgKTtcbiAgY29uc3QgbW9kZWxQcm94eVBvcnQgPSBjb3JlQ29uZmlnLnBvcnQoXG4gICAgY29uZmlnLm1vZGVsUHJveHlQb3J0LFxuICAgIFwiTU9ERUxfUFJPWFlfUE9SVFwiLFxuICAgIDAsXG4gICAgY29yZUNvbmZpZy5FTlZfT05MWSxcbiAgKTtcbiAgY29uc3QgcHJveHlQb3J0ID0gY29yZUNvbmZpZy5wb3J0KGNvbmZpZy5wcm94eVBvcnQsIFwiUFJPWFlfUE9SVFwiLCAwLCBjb3JlQ29uZmlnLkVOVl9PTkxZKTtcbiAgY29uc3QgY29uZmlndXJlZFBvcnRzID0gW2dyYXBoaXRpUG9ydCwgbW9kZWxQcm94eVBvcnQsIHByb3h5UG9ydF0uZmlsdGVyKEJvb2xlYW4pO1xuICBpZiAobmV3IFNldChjb25maWd1cmVkUG9ydHMpLnNpemUgIT09IGNvbmZpZ3VyZWRQb3J0cy5sZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgQ29uZmlndXJhdGlvbkVycm9yKFwiR3JhcGhpdGkgc2lkZWNhciBwb3J0cyBtdXN0IGJlIGRpc3RpbmN0XCIpO1xuICB9XG4gIGNvbnN0IHB5dGhvbiA9XG4gICAgY29uZmlnLnB5dGhvbiA/PyBjb3JlQ29uZmlnLnRleHQoXCJQWVRIT05cIiwgY29yZUNvbmZpZy5FTlZfT05MWSk/LnRyaW0oKSA/PyBcInB5dGhvbjNcIjtcbiAgY29uc3Qgam91cm5hbE5hbWVzcGFjZSA9XG4gICAgY29uZmlnLmpvdXJuYWxOYW1lc3BhY2UgPz9cbiAgICBjb3JlQ29uZmlnLnRleHQoXCJKT1VSTkFMX05BTUVTUEFDRVwiLCBjb3JlQ29uZmlnLkVOVl9PTkxZKT8udHJpbSgpID8/XG4gICAgcHJvY2Vzcy5lbnYuREFUQUJSSUNLU19BUFBfTkFNRT8udHJpbSgpID8/XG4gICAgY29yZVByb2plY3QubmFtZSgpID8/XG4gICAgXCJkZWZhdWx0XCI7XG4gIHJldHVybiB7XG4gICAgZ3JhcGhpdGlQb3J0LFxuICAgIG1vZGVsUHJveHlQb3J0LFxuICAgIHByb3h5UG9ydCxcbiAgICBweXRob24sXG4gICAgam91cm5hbE5hbWVzcGFjZSxcbiAgfTtcbn1cbiJdfQ==
@@ -1,4 +1,5 @@
1
1
  import { Plugin, type IAppRouter, type PluginManifest, type ResourceRequirement } from "@databricks/appkit";
2
+ import { ensureRustReleaseBinary } from "@dbx-tools/cli/rust-binary";
2
3
  import { type GraphitiPluginConfig } from "./config.ts";
3
4
  interface ToolkitEntry {
4
5
  readonly __toolkitRef: true;
@@ -50,5 +51,7 @@ export declare class GraphitiPlugin extends Plugin<GraphitiPluginConfig> {
50
51
  type ExecPython = (file: string, args: string[]) => Promise<unknown>;
51
52
  /** Ensure Databricks Apps has the Python sidecar matching this Node package. */
52
53
  export declare function ensureGraphitiPython(python: string, run?: ExecPython): Promise<void>;
54
+ /** Install the model proxy release binary used by the Python sidecar. */
55
+ export declare function ensureGraphitiModelProxy(install?: typeof ensureRustReleaseBinary): Promise<string>;
53
56
  export declare const graphiti: import("@databricks/appkit").ToPlugin<typeof GraphitiPlugin, GraphitiPluginConfig, "graphiti">;
54
57
  export {};
package/lib/src/plugin.js CHANGED
@@ -7,9 +7,11 @@ import { execFile } from "node:child_process";
7
7
  import { createHash } from "node:crypto";
8
8
  import { createRequire } from "node:module";
9
9
  import { createServer } from "node:net";
10
+ import { resolve as resolvePath } from "node:path";
10
11
  import { promisify } from "node:util";
11
12
  import { ConfigurationError, Plugin, lakebase, toPlugin, } from "@databricks/appkit";
12
13
  import { appkit as dbxAppkit, identity as appkitIdentity, plugin as appkitPlugin, } from "@dbx-tools/appkit";
14
+ import { ensureRustReleaseBinary, rustReleaseBinaryCommand } from "@dbx-tools/cli/rust-binary";
13
15
  import { config as coreConfig } from "@dbx-tools/core";
14
16
  import { async as asyncModule, log, object } from "@dbx-tools/shared-core";
15
17
  import { createTool } from "@mastra/core/tools";
@@ -17,6 +19,7 @@ import { MCPClient, MCPServer } from "@mastra/mcp";
17
19
  import concurrently from "concurrently";
18
20
  import { GRAPHITI_CONFIG_SCHEMA, resolveGraphitiConfig, } from "./config.js";
19
21
  const LAKEBASE_MANIFEST = appkitPlugin.data(lakebase).plugin.manifest;
22
+ const MODEL_PROXY_RELEASE_BINARY = rustReleaseBinaryCommand("model-proxy");
20
23
  const PACKAGE_VERSION = createRequire(import.meta.url)("@dbx-tools/appkit-graphiti/package.json").version;
21
24
  const MCP_PATH = "/api/graphiti/mcp";
22
25
  const MCP_SERVER_IDLE_MS = 30 * 60 * 1000;
@@ -83,12 +86,13 @@ export class GraphitiPlugin extends Plugin {
83
86
  }
84
87
  async startSidecars() {
85
88
  const configured = resolveGraphitiConfig(this.config);
86
- const [graphitiPort, litellmPort, proxyPort] = await distinctPorts(coreConfig.port(undefined, "DATABRICKS_APP_PORT", 8000, coreConfig.ENV_ONLY), configured.graphitiPort, configured.litellmPort, configured.proxyPort);
89
+ const [graphitiPort, modelProxyPort, proxyPort] = await distinctPorts(coreConfig.port(undefined, "DATABRICKS_APP_PORT", 8000, coreConfig.ENV_ONLY), configured.graphitiPort, configured.modelProxyPort, configured.proxyPort);
87
90
  await ensureGraphitiPython(configured.python);
91
+ const modelProxyCommand = await ensureGraphitiModelProxy();
88
92
  this.resolved = {
89
93
  ...configured,
90
94
  graphitiPort,
91
- litellmPort,
95
+ modelProxyPort,
92
96
  proxyPort,
93
97
  };
94
98
  this.supervision = concurrently([
@@ -100,9 +104,10 @@ export class GraphitiPlugin extends Plugin {
100
104
  GRAPHITI_HOST: "127.0.0.1",
101
105
  GRAPHITI_PORT: String(this.resolved.graphitiPort),
102
106
  JOURNAL_NAMESPACE: this.resolved.journalNamespace,
103
- LITELLM_HOST: "127.0.0.1",
104
- LITELLM_PORT: String(this.resolved.litellmPort),
105
- MANAGE_LITELLM: "true",
107
+ MANAGE_MODEL_PROXY: "true",
108
+ MODEL_PROXY_COMMAND: modelProxyCommand,
109
+ MODEL_PROXY_HOST: "127.0.0.1",
110
+ MODEL_PROXY_PORT: String(this.resolved.modelProxyPort),
106
111
  },
107
112
  },
108
113
  {
@@ -132,7 +137,7 @@ export class GraphitiPlugin extends Plugin {
132
137
  this.mcpServerSweep.unref();
133
138
  this.logger.info("sidecars launched", {
134
139
  graphitiPort: this.resolved.graphitiPort,
135
- litellmPort: this.resolved.litellmPort,
140
+ modelProxyPort: this.resolved.modelProxyPort,
136
141
  proxyPort: this.resolved.proxyPort,
137
142
  mcpPath: MCP_PATH,
138
143
  });
@@ -327,6 +332,11 @@ export async function ensureGraphitiPython(python, run = (file, args) => promisi
327
332
  ]);
328
333
  }
329
334
  }
335
+ /** Install the model proxy release binary used by the Python sidecar. */
336
+ export async function ensureGraphitiModelProxy(install = ensureRustReleaseBinary) {
337
+ const installed = await install(MODEL_PROXY_RELEASE_BINARY);
338
+ return resolvePath(installed.path);
339
+ }
330
340
  export const graphiti = toPlugin(GraphitiPlugin);
331
341
  function executionContextUserId() {
332
342
  const context = dbxAppkit.tryGetExecutionContext();
@@ -365,9 +375,9 @@ async function availablePort() {
365
375
  });
366
376
  });
367
377
  }
368
- async function distinctPorts(appPort, graphitiPort, litellmPort, proxyPort) {
378
+ async function distinctPorts(appPort, graphitiPort, modelProxyPort, proxyPort) {
369
379
  const ports = [appPort];
370
- for (const configuredPort of [graphitiPort, litellmPort, proxyPort]) {
380
+ for (const configuredPort of [graphitiPort, modelProxyPort, proxyPort]) {
371
381
  if (configuredPort && ports.includes(configuredPort)) {
372
382
  throw new ConfigurationError("Graphiti sidecar ports must differ from DATABRICKS_APP_PORT");
373
383
  }
@@ -381,4 +391,4 @@ async function distinctPorts(appPort, graphitiPort, litellmPort, proxyPort) {
381
391
  function commandLine(arguments_) {
382
392
  return arguments_.map((value) => `'${value.replaceAll("'", "'\\''")}'`).join(" ");
383
393
  }
384
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3BsdWdpbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBQ0gsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDekMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUM1QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDdEMsT0FBTyxFQUNMLGtCQUFrQixFQUNsQixNQUFNLEVBQ04sUUFBUSxFQUNSLFFBQVEsR0FJVCxNQUFNLG9CQUFvQixDQUFDO0FBQzVCLE9BQU8sRUFDTCxNQUFNLElBQUksU0FBUyxFQUNuQixRQUFRLElBQUksY0FBYyxFQUMxQixNQUFNLElBQUksWUFBWSxHQUN2QixNQUFNLG1CQUFtQixDQUFDO0FBQzNCLE9BQU8sRUFBRSxNQUFNLElBQUksVUFBVSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDdkQsT0FBTyxFQUFFLEtBQUssSUFBSSxXQUFXLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQzNFLE9BQU8sRUFBRSxVQUFVLEVBQWEsTUFBTSxvQkFBb0IsQ0FBQztBQUMzRCxPQUFPLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNuRCxPQUFPLFlBQXVELE1BQU0sY0FBYyxDQUFDO0FBRW5GLE9BQU8sRUFDTCxzQkFBc0IsRUFDdEIscUJBQXFCLEdBR3RCLE1BQU0sYUFBYSxDQUFDO0FBRXJCLE1BQU0saUJBQWlCLEdBQUcsWUFBWSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDO0FBQ3RFLE1BQU0sZUFBZSxH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QUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMzRSxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQztBQUVELEtBQUssVUFBVSxhQUFhLENBQzFCLE9BQWUsRUFDZixZQUFvQixFQUNwQixXQUFtQixFQUNuQixTQUFpQjtJQUVqQixNQUFNLEtBQUssR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ3hCLEtBQUssTUFBTSxjQUFjLElBQUksQ0FBQyxZQUFZLEVBQUUsV0FBVyxFQUFFLFNBQVMsQ0FBQyxFQUFFLENBQUM7UUFDcEUsSUFBSSxjQUFjLElBQUksS0FBSyxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUMsRUFBRSxDQUFDO1lBQ3JELE1BQU0sSUFBSSxrQkFBa0IsQ0FBQyw2REFBNkQsQ0FBQyxDQUFDO1FBQzlGLENBQUM7UUFDRCxJQUFJLElBQUksR0FBRyxjQUFjLElBQUksQ0FBQyxNQUFNLGFBQWEsRUFBRSxDQUFDLENBQUM7UUFDckQsT0FBTyxLQUFLLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQztZQUFFLElBQUksR0FBRyxNQUFNLGFBQWEsRUFBRSxDQUFDO1FBQzFELEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDbkIsQ0FBQztJQUNELE9BQU8sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQTZCLENBQUM7QUFDcEQsQ0FBQztBQUVELFNBQVMsV0FBVyxDQUFDLFVBQW9CO0lBQ3ZDLE9BQU8sVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsSUFBSSxLQUFLLENBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQ3BGLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEFwcEtpdCBwbHVnaW4gdGhhdCBzdXBlcnZpc2VzIEdyYXBoaXRpIGFuZCByZXB1Ymxpc2hlcyB1c2VyLXNjb3BlZCBNQ1AgdG9vbHMuXG4gKlxuICogQG1vZHVsZVxuICovXG5pbXBvcnQgeyBleGVjRmlsZSB9IGZyb20gXCJub2RlOmNoaWxkX3Byb2Nlc3NcIjtcbmltcG9ydCB7IGNyZWF0ZUhhc2ggfSBmcm9tIFwibm9kZTpjcnlwdG9cIjtcbmltcG9ydCB7IGNyZWF0ZVJlcXVpcmUgfSBmcm9tIFwibm9kZTptb2R1bGVcIjtcbmltcG9ydCB7IGNyZWF0ZVNlcnZlciB9IGZyb20gXCJub2RlOm5ldFwiO1xuaW1wb3J0IHsgcHJvbWlzaWZ5IH0gZnJvbSBcIm5vZGU6dXRpbFwiO1xuaW1wb3J0IHtcbiAgQ29uZmlndXJhdGlvbkVycm9yLFxuICBQbHVnaW4sXG4gIGxha2ViYXNlLFxuICB0b1BsdWdpbixcbiAgdHlwZSBJQXBwUm91dGVyLFxuICB0eXBlIFBsdWdpbk1hbmlmZXN0LFxuICB0eXBlIFJlc291cmNlUmVxdWlyZW1lbnQsXG59IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbmltcG9ydCB7XG4gIGFwcGtpdCBhcyBkYnhBcHBraXQsXG4gIGlkZW50aXR5IGFzIGFwcGtpdElkZW50aXR5LFxuICBwbHVnaW4gYXMgYXBwa2l0UGx1Z2luLFxufSBmcm9tIFwiQGRieC10b29scy9hcHBraXRcIjtcbmltcG9ydCB7IGNvbmZpZyBhcyBjb3JlQ29uZmlnIH0gZnJvbSBcIkBkYngtdG9vbHMvY29yZVwiO1xuaW1wb3J0IHsgYXN5bmMgYXMgYXN5bmNNb2R1bGUsIGxvZywgb2JqZWN0IH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7IGNyZWF0ZVRvb2wsIHR5cGUgVG9vbCB9IGZyb20gXCJAbWFzdHJhL2NvcmUvdG9vbHNcIjtcbmltcG9ydCB7IE1DUENsaWVudCwgTUNQU2VydmVyIH0gZnJvbSBcIkBtYXN0cmEvbWNwXCI7XG5pbXBvcnQgY29uY3VycmVudGx5LCB7IHR5cGUgQ29tbWFuZCwgdHlwZSBDb25jdXJyZW50bHlSZXN1bHQgfSBmcm9tIFwiY29uY3VycmVudGx5XCI7XG5pbXBvcnQgdHlwZSBleHByZXNzIGZyb20gXCJleHByZXNzXCI7XG5pbXBvcnQge1xuICBHUkFQSElUSV9DT05GSUdfU0NIRU1BLFxuICByZXNvbHZlR3JhcGhpdGlDb25maWcsXG4gIHR5cGUgR3JhcGhpdGlQbHVnaW5Db25maWcsXG4gIHR5cGUgUmVzb2x2ZWRHcmFwaGl0aVBsdWdpbkNvbmZpZyxcbn0gZnJvbSBcIi4vY29uZmlnLnRzXCI7XG5cbmNvbnN0IExBS0VCQVNFX01BTklGRVNUID0gYXBwa2l0UGx1Z2luLmRhdGEobGFrZWJhc2UpLnBsdWdpbi5tYW5pZmVzdDtcbmNvbnN0IFBBQ0tBR0VfVkVSU0lPTiA9IChcbiAgY3JlYXRlUmVxdWlyZShpbXBvcnQubWV0YS51cmwpKFwiQGRieC10b29scy9hcHBraXQtZ3JhcGhpdGkvcGFja2FnZS5qc29uXCIpIGFzIHsgdmVyc2lvbjogc3RyaW5nIH1cbikudmVyc2lvbjtcbmNvbnN0IE1DUF9QQVRIID0gXCIvYXBpL2dyYXBoaXRpL21jcFwiO1xuY29uc3QgTUNQX1NFUlZFUl9JRExFX01TID0gMzAgKiA2MCAqIDEwMDA7XG5jb25zdCBNQ1BfU0VSVkVSX1NXRUVQX01TID0gNSAqIDYwICogMTAwMDtcbmNvbnN0IFNJREVDQVJfU0hVVERPV05fR1JBQ0VfTVMgPSAxMF8wMDA7XG5jb25zdCBTQ09QRURfVE9PTF9GSUVMRFMgPSB7XG4gIGFkZF9tZW1vcnk6IFwiZ3JvdXBfaWRcIixcbiAgYWRkX3RyaXBsZXQ6IFwiZ3JvdXBfaWRcIixcbiAgYnVpbGRfY29tbXVuaXRpZXM6IFwiZ3JvdXBfaWRzXCIsXG4gIGdldF9lcGlzb2RlczogXCJncm91cF9pZHNcIixcbiAgZ2V0X3N0YXR1czogdW5kZWZpbmVkLFxuICBzZWFyY2hfbWVtb3J5X2ZhY3RzOiBcImdyb3VwX2lkc1wiLFxuICBzZWFyY2hfbm9kZXM6IFwiZ3JvdXBfaWRzXCIsXG4gIHN1bW1hcml6ZV9zYWdhOiBcImdyb3VwX2lkXCIsXG59IGFzIGNvbnN0O1xuY29uc3QgV1JJVEVfVE9PTFMgPSBuZXcgU2V0KFtcImFkZF9tZW1vcnlcIiwgXCJhZGRfdHJpcGxldFwiLCBcImJ1aWxkX2NvbW11bml0aWVzXCIsIFwic3VtbWFyaXplX3NhZ2FcIl0pO1xuY29uc3QgVU5TQ09QRURfQVJHVU1FTlRTID0gW1xuICBcImNlbnRlcl9ub2RlX3V1aWRcIixcbiAgXCJwcmV2aW91c19lcGlzb2RlX3V1aWRzXCIsXG4gIFwic2FnYV9wcmV2aW91c19lcGlzb2RlX3V1aWRcIixcbiAgXCJzb3VyY2Vfbm9kZV91dWlkXCIsXG4gIFwidGFyZ2V0X25vZGVfdXVpZFwiLFxuICBcInV1aWRcIixcbl0gYXMgY29uc3Q7XG5cbmludGVyZmFjZSBUb29sa2l0RW50cnkge1xuICByZWFkb25seSBfX3Rvb2xraXRSZWY6IHRydWU7XG4gIHBsdWdpbk5hbWU6IHN0cmluZztcbiAgbG9jYWxOYW1lOiBzdHJpbmc7XG4gIGRlZjoge1xuICAgIG5hbWU6IHN0cmluZztcbiAgICBkZXNjcmlwdGlvbjogc3RyaW5nO1xuICAgIHBhcmFtZXRlcnM6IHVua25vd247XG4gIH07XG4gIGFubm90YXRpb25zOiB7XG4gICAgZWZmZWN0OiBcInJlYWRcIiB8IFwid3JpdGVcIjtcbiAgICByZXF1aXJlc1VzZXJDb250ZXh0OiB0cnVlO1xuICB9O1xufVxuXG5pbnRlcmZhY2UgVXNlck1jcFNlcnZlciB7XG4gIGxhc3RVc2VkOiBudW1iZXI7XG4gIHNlcnZlcjogTUNQU2VydmVyO1xufVxuXG5leHBvcnQgY2xhc3MgR3JhcGhpdGlQbHVnaW4gZXh0ZW5kcyBQbHVnaW48R3JhcGhpdGlQbHVnaW5Db25maWc+IHtcbiAgc3RhdGljIG1hbmlmZXN0OiBQbHVnaW5NYW5pZmVzdDxcImdyYXBoaXRpXCI+ID0ge1xuICAgIG5hbWU6IFwiZ3JhcGhpdGlcIixcbiAgICBkaXNwbGF5TmFtZTogXCJHcmFwaGl0aVwiLFxuICAgIGRlc2NyaXB0aW9uOlxuICAgICAgXCJSdW5zIHRoZSBkYngtdG9vbHMgR3JhcGhpdGkgTUNQIHNpZGVjYXIgd2l0aCBMYWtlYmFzZS1iYWNrZWQgcmVjb3ZlcnkgYW5kIFwiICtcbiAgICAgIFwicHVibGlzaGVzIGl0IHRocm91Z2ggdGhlIEFwcCdzIHNpbmdsZSBwb3J0IHdpdGggQ2FkZHkuXCIsXG4gICAgc3RhYmlsaXR5OiBcImJldGFcIixcbiAgICByZXNvdXJjZXM6IHtcbiAgICAgIHJlcXVpcmVkOiBbXSxcbiAgICAgIG9wdGlvbmFsOiBbLi4uTEFLRUJBU0VfTUFOSUZFU1QucmVzb3VyY2VzLnJlcXVpcmVkXSxcbiAgICB9LFxuICAgIGNvbmZpZzogeyBzY2hlbWE6IEdSQVBISVRJX0NPTkZJR19TQ0hFTUEgfSxcbiAgfTtcblxuICBzdGF0aWMgZ2V0UmVzb3VyY2VSZXF1aXJlbWVudHMoKTogUmVzb3VyY2VSZXF1aXJlbWVudFtdIHtcbiAgICByZXR1cm4gTEFLRUJBU0VfTUFOSUZFU1QucmVzb3VyY2VzLnJlcXVpcmVkLm1hcCgocmVzb3VyY2UpID0+ICh7XG4gICAgICAuLi5yZXNvdXJjZSxcbiAgICAgIHJlcXVpcmVkOiB0cnVlLFxuICAgIH0pKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVhZG9ubHkgbG9nZ2VyID0gbG9nLmxvZ2dlcih0aGlzKTtcbiAgcHJpdmF0ZSBjb21tYW5kczogQ29tbWFuZFtdID0gW107XG4gIHByaXZhdGUgbWNwPzogTUNQQ2xpZW50O1xuICBwcml2YXRlIG1jcFNlcnZlcnMgPSBuZXcgTWFwPHN0cmluZywgVXNlck1jcFNlcnZlcj4oKTtcbiAgcHJpdmF0ZSBtY3BTZXJ2ZXJTd2VlcD86IE5vZGVKUy5UaW1lb3V0O1xuICBwcml2YXRlIG1jcFRvb2xzOiBSZWNvcmQ8c3RyaW5nLCBUb29sPiA9IHt9O1xuICBwcml2YXRlIHJlc29sdmVkPzogUmVzb2x2ZWRHcmFwaGl0aVBsdWdpbkNvbmZpZztcbiAgcHJpdmF0ZSBzZXR1cENvbXBsZXRlID0gZmFsc2U7XG4gIHByaXZhdGUgc3RhcnR1cD86IFByb21pc2U8dm9pZD47XG4gIHByaXZhdGUgc3VwZXJ2aXNpb24/OiBDb25jdXJyZW50bHlSZXN1bHQ7XG4gIHByaXZhdGUgc3RvcHBpbmcgPSBmYWxzZTtcblxuICBvdmVycmlkZSBhc3luYyBzZXR1cCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aGlzLnN0YXJ0dXAgPSB0aGlzLnN0YXJ0U2lkZWNhcnMoKS5jYXRjaCgoZXJyb3I6IHVua25vd24pID0+IHtcbiAgICAgIGlmICh0aGlzLnN0b3BwaW5nKSByZXR1cm47XG4gICAgICB0aGlzLmxvZ2dlci5lcnJvcihcImJhY2tncm91bmQgc3RhcnR1cCBmYWlsZWRcIiwgeyBlcnJvciB9KTtcbiAgICAgIHByb2Nlc3Mua2lsbChwcm9jZXNzLnBpZCwgXCJTSUdURVJNXCIpO1xuICAgIH0pO1xuICAgIHZvaWQgdGhpcy5zdGFydHVwO1xuICAgIHRoaXMubG9nZ2VyLmluZm8oXCJiYWNrZ3JvdW5kIHN0YXJ0dXAgc2NoZWR1bGVkXCIpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBzdGFydFNpZGVjYXJzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGNvbmZpZ3VyZWQgPSByZXNvbHZlR3JhcGhpdGlDb25maWcodGhpcy5jb25maWcpO1xuICAgIGNvbnN0IFtncmFwaGl0aVBvcnQsIGxpdGVsbG1Qb3J0LCBwcm94eVBvcnRdID0gYXdhaXQgZGlzdGluY3RQb3J0cyhcbiAgICAgIGNvcmVDb25maWcucG9ydCh1bmRlZmluZWQsIFwiREFUQUJSSUNLU19BUFBfUE9SVFwiLCA4MDAwLCBjb3JlQ29uZmlnLkVOVl9PTkxZKSxcbiAgICAgIGNvbmZpZ3VyZWQuZ3JhcGhpdGlQb3J0LFxuICAgICAgY29uZmlndXJlZC5saXRlbGxtUG9ydCxcbiAgICAgIGNvbmZpZ3VyZWQucHJveHlQb3J0LFxuICAgICk7XG4gICAgYXdhaXQgZW5zdXJlR3JhcGhpdGlQeXRob24oY29uZmlndXJlZC5weXRob24pO1xuICAgIHRoaXMucmVzb2x2ZWQgPSB7XG4gICAgICAuLi5jb25maWd1cmVkLFxuICAgICAgZ3JhcGhpdGlQb3J0LFxuICAgICAgbGl0ZWxsbVBvcnQsXG4gICAgICBwcm94eVBvcnQsXG4gICAgfTtcbiAgICB0aGlzLnN1cGVydmlzaW9uID0gY29uY3VycmVudGx5KFxuICAgICAgW1xuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogXCJncmFwaGl0aVwiLFxuICAgICAgICAgIGNvbW1hbmQ6IGNvbW1hbmRMaW5lKFt0aGlzLnJlc29sdmVkLnB5dGhvbiwgXCItbVwiLCBcImRieF90b29scy5ncmFwaGl0aVwiLCBcInN0YXJ0XCJdKSxcbiAgICAgICAgICBlbnY6IHtcbiAgICAgICAgICAgIC4uLnByb2Nlc3MuZW52LFxuICAgICAgICAgICAgR1JBUEhJVElfSE9TVDogXCIxMjcuMC4wLjFcIixcbiAgICAgICAgICAgIEdSQVBISVRJX1BPUlQ6IFN0cmluZyh0aGlzLnJlc29sdmVkLmdyYXBoaXRpUG9ydCksXG4gICAgICAgICAgICBKT1VSTkFMX05BTUVTUEFDRTogdGhpcy5yZXNvbHZlZC5qb3VybmFsTmFtZXNwYWNlLFxuICAgICAgICAgICAgTElURUxMTV9IT1NUOiBcIjEyNy4wLjAuMVwiLFxuICAgICAgICAgICAgTElURUxMTV9QT1JUOiBTdHJpbmcodGhpcy5yZXNvbHZlZC5saXRlbGxtUG9ydCksXG4gICAgICAgICAgICBNQU5BR0VfTElURUxMTTogXCJ0cnVlXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwiY2FkZHlcIixcbiAgICAgICAgICBjb21tYW5kOiBjb21tYW5kTGluZShbXG4gICAgICAgICAgICB0aGlzLnJlc29sdmVkLnB5dGhvbixcbiAgICAgICAgICAgIFwiLW1cIixcbiAgICAgICAgICAgIFwiZGJ4X3Rvb2xzLmdyYXBoaXRpLnByb3h5XCIsXG4gICAgICAgICAgICBcIi0tcHJveHktcG9ydFwiLFxuICAgICAgICAgICAgU3RyaW5nKHRoaXMucmVzb2x2ZWQucHJveHlQb3J0KSxcbiAgICAgICAgICAgIFwiLS1ncmFwaGl0aS1wb3J0XCIsXG4gICAgICAgICAgICBTdHJpbmcodGhpcy5yZXNvbHZlZC5ncmFwaGl0aVBvcnQpLFxuICAgICAgICAgIF0pLFxuICAgICAgICAgIGVudjogcHJvY2Vzcy5lbnYsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAge1xuICAgICAgICBraWxsT3RoZXJzT246IFtcImZhaWx1cmVcIiwgXCJzdWNjZXNzXCJdLFxuICAgICAgICBraWxsU2lnbmFsOiBcIlNJR1RFUk1cIixcbiAgICAgICAga2lsbFRpbWVvdXQ6IFNJREVDQVJfU0hVVERPV05fR1JBQ0VfTVMsXG4gICAgICAgIHByZWZpeDogXCJuYW1lXCIsXG4gICAgICAgIHByZWZpeENvbG9yczogZmFsc2UsXG4gICAgICB9LFxuICAgICk7XG4gICAgdGhpcy5jb21tYW5kcyA9IHRoaXMuc3VwZXJ2aXNpb24uY29tbWFuZHM7XG4gICAgdGhpcy5zZXR1cENvbXBsZXRlID0gdHJ1ZTtcbiAgICB2b2lkIHRoaXMuc3VwZXJ2aXNpb24ucmVzdWx0LnRoZW4oXG4gICAgICAoKSA9PiB0aGlzLm9uU3VwZXJ2aXNvckV4aXQoKSxcbiAgICAgIChlcnJvcikgPT4gdGhpcy5vblN1cGVydmlzb3JFeGl0KGVycm9yKSxcbiAgICApO1xuICAgIHRoaXMubWNwU2VydmVyU3dlZXAgPSBzZXRJbnRlcnZhbCgoKSA9PiB0aGlzLmNsb3NlSWRsZU1jcFNlcnZlcnMoKSwgTUNQX1NFUlZFUl9TV0VFUF9NUyk7XG4gICAgdGhpcy5tY3BTZXJ2ZXJTd2VlcC51bnJlZigpO1xuICAgIHRoaXMubG9nZ2VyLmluZm8oXCJzaWRlY2FycyBsYXVuY2hlZFwiLCB7XG4gICAgICBncmFwaGl0aVBvcnQ6IHRoaXMucmVzb2x2ZWQuZ3JhcGhpdGlQb3J0LFxuICAgICAgbGl0ZWxsbVBvcnQ6IHRoaXMucmVzb2x2ZWQubGl0ZWxsbVBvcnQsXG4gICAgICBwcm94eVBvcnQ6IHRoaXMucmVzb2x2ZWQucHJveHlQb3J0LFxuICAgICAgbWNwUGF0aDogTUNQX1BBVEgsXG4gICAgfSk7XG4gIH1cblxuICBvdmVycmlkZSBpbmplY3RSb3V0ZXMocm91dGVyOiBJQXBwUm91dGVyKTogdm9pZCB7XG4gICAgZm9yIChjb25zdCBtZXRob2Qgb2YgW1wiZ2V0XCIsIFwicG9zdFwiLCBcImRlbGV0ZVwiXSBhcyBjb25zdCkge1xuICAgICAgdGhpcy5yb3V0ZShyb3V0ZXIsIHtcbiAgICAgICAgbmFtZTogYCR7bWV0aG9kfU1jcGAsXG4gICAgICAgIG1ldGhvZCxcbiAgICAgICAgcGF0aDogXCIvbWNwXCIsXG4gICAgICAgIGhhbmRsZXI6IChyZXF1ZXN0LCByZXNwb25zZSkgPT4gdGhpcy5mb3J3YXJkTWNwKHJlcXVlc3QsIHJlc3BvbnNlKSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIG92ZXJyaWRlIGFib3J0QWN0aXZlT3BlcmF0aW9ucygpOiB2b2lkIHtcbiAgICBzdXBlci5hYm9ydEFjdGl2ZU9wZXJhdGlvbnMoKTtcbiAgICB2b2lkIHRoaXMubWNwPy5kaXNjb25uZWN0KCk7XG4gIH1cblxuICBhc3luYyBzaHV0ZG93bigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBhd2FpdCB0aGlzLnN0b3BTaWRlY2FycygpO1xuICB9XG5cbiAgb3ZlcnJpZGUgZXhwb3J0cygpIHtcbiAgICByZXR1cm4geyBtY3BQYXRoOiBNQ1BfUEFUSCB9O1xuICB9XG5cbiAgdG9vbGtpdCgpOiBSZWNvcmQ8c3RyaW5nLCBUb29sa2l0RW50cnk+IHtcbiAgICByZXR1cm4gT2JqZWN0LmZyb21FbnRyaWVzKFxuICAgICAgT2JqZWN0LmtleXMoU0NPUEVEX1RPT0xfRklFTERTKS5tYXAoKG5hbWUpID0+IFtcbiAgICAgICAgbmFtZSxcbiAgICAgICAge1xuICAgICAgICAgIF9fdG9vbGtpdFJlZjogdHJ1ZSBhcyBjb25zdCxcbiAgICAgICAgICBwbHVnaW5OYW1lOiBcImdyYXBoaXRpXCIsXG4gICAgICAgICAgbG9jYWxOYW1lOiBuYW1lLFxuICAgICAgICAgIGRlZjoge1xuICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOiBgR3JhcGhpdGkgJHtuYW1lLnJlcGxhY2VBbGwoXCJfXCIsIFwiIFwiKX1gLFxuICAgICAgICAgICAgcGFyYW1ldGVyczogeyB0eXBlOiBcIm9iamVjdFwiLCBwcm9wZXJ0aWVzOiB7fSB9LFxuICAgICAgICAgIH0sXG4gICAgICAgICAgYW5ub3RhdGlvbnM6IHtcbiAgICAgICAgICAgIGVmZmVjdDogV1JJVEVfVE9PTFMuaGFzKG5hbWUpID8gKFwid3JpdGVcIiBhcyBjb25zdCkgOiAoXCJyZWFkXCIgYXMgY29uc3QpLFxuICAgICAgICAgICAgcmVxdWlyZXNVc2VyQ29udGV4dDogdHJ1ZSBhcyBjb25zdCxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgXSksXG4gICAgKTtcbiAgfVxuXG4gIGFzeW5jIGV4ZWN1dGVBZ2VudFRvb2woXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIGFyZ3M6IHVua25vd24sXG4gICAgc2lnbmFsPzogQWJvcnRTaWduYWwsXG4gICAgY29udGV4dD86IHsgcmVzb3VyY2VJZD86IHN0cmluZyB9LFxuICApOiBQcm9taXNlPHVua25vd24+IHtcbiAgICBhd2FpdCB0aGlzLmVuc3VyZU1jcFRvb2xzKCk7XG4gICAgY29uc3QgdG9vbCA9IHRoaXMubWNwVG9vbHNbbmFtZV07XG4gICAgaWYgKCF0b29sPy5leGVjdXRlKSB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gR3JhcGhpdGkgdG9vbDogJHtuYW1lfWApO1xuICAgIGNvbnN0IHVzZXJJZCA9IGNvbnRleHQ/LnJlc291cmNlSWQgPz8gZXhlY3V0aW9uQ29udGV4dFVzZXJJZCgpO1xuICAgIHJldHVybiB0b29sLmV4ZWN1dGUoc2NvcGVkQXJndW1lbnRzKG5hbWUsIGFyZ3MsIHVzZXJTY29wZSh1c2VySWQpKSwge1xuICAgICAgYWJvcnRTaWduYWw6IHNpZ25hbCxcbiAgICB9IGFzIG5ldmVyKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZm9yd2FyZE1jcChyZXF1ZXN0OiBleHByZXNzLlJlcXVlc3QsIHJlc3BvbnNlOiBleHByZXNzLlJlc3BvbnNlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5lbnN1cmVNY3BUb29scygpO1xuICAgIGNvbnN0IHVzZXJJZCA9IGFwcGtpdElkZW50aXR5LnJlcXVlc3RVc2VySWQocmVxdWVzdCkgPz8gZXhlY3V0aW9uQ29udGV4dFVzZXJJZCgpO1xuICAgIGNvbnN0IHNlcnZlciA9IHRoaXMubWNwU2VydmVyKHVzZXJJZCk7XG4gICAgYXdhaXQgc2VydmVyLnN0YXJ0SFRUUCh7XG4gICAgICB1cmw6IG5ldyBVUkwocmVxdWVzdC5vcmlnaW5hbFVybCwgXCJodHRwOi8vYXBwLmxvY2FsXCIpLFxuICAgICAgaHR0cFBhdGg6IE1DUF9QQVRILFxuICAgICAgcmVxOiByZXF1ZXN0LFxuICAgICAgcmVzOiByZXNwb25zZSxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZW5zdXJlTWNwVG9vbHMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKE9iamVjdC5rZXlzKHRoaXMubWNwVG9vbHMpLmxlbmd0aCA+IDApIHJldHVybjtcbiAgICBpZiAoIXRoaXMucmVzb2x2ZWQpIHRocm93IG5ldyBFcnJvcihcIkdyYXBoaXRpIHNpZGVjYXJzIGhhdmUgbm90IGxhdW5jaGVkXCIpO1xuICAgIHRoaXMubWNwID8/PSBuZXcgTUNQQ2xpZW50KHtcbiAgICAgIGlkOiBgYXBwa2l0LWdyYXBoaXRpLSR7dGhpcy5yZXNvbHZlZC5ncmFwaGl0aVBvcnR9YCxcbiAgICAgIHNlcnZlcnM6IHtcbiAgICAgICAgZ3JhcGhpdGk6IHsgdXJsOiBuZXcgVVJMKGBodHRwOi8vMTI3LjAuMC4xOiR7dGhpcy5yZXNvbHZlZC5wcm94eVBvcnR9L21jcGApIH0sXG4gICAgICB9LFxuICAgIH0pO1xuICAgIGNvbnN0IGRpc2NvdmVyZWQgPSBhd2FpdCB0aGlzLm1jcC5saXN0VG9vbHMoKTtcbiAgICB0aGlzLm1jcFRvb2xzID0gT2JqZWN0LmZyb21FbnRyaWVzKFxuICAgICAgT2JqZWN0LmVudHJpZXMoZGlzY292ZXJlZClcbiAgICAgICAgLm1hcCgoW25hbWUsIHRvb2xdKSA9PiBbbmFtZS5yZXBsYWNlKC9eZ3JhcGhpdGlfLywgXCJcIiksIHRvb2wgYXMgVG9vbF0gYXMgY29uc3QpXG4gICAgICAgIC5maWx0ZXIoKFtuYW1lXSkgPT4gbmFtZSBpbiBTQ09QRURfVE9PTF9GSUVMRFMpLFxuICAgICk7XG4gICAgY29uc3QgbWlzc2luZyA9IE9iamVjdC5rZXlzKFNDT1BFRF9UT09MX0ZJRUxEUykuZmlsdGVyKChuYW1lKSA9PiAhdGhpcy5tY3BUb29sc1tuYW1lXSk7XG4gICAgaWYgKG1pc3NpbmcubGVuZ3RoID4gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBHcmFwaGl0aSBkaWQgbm90IHB1Ymxpc2ggcmVxdWlyZWQgc2NvcGVkIHRvb2xzOiAke21pc3Npbmcuam9pbihcIiwgXCIpfWApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbWNwU2VydmVyKHVzZXJJZDogc3RyaW5nKTogTUNQU2VydmVyIHtcbiAgICBjb25zdCBleGlzdGluZyA9IHRoaXMubWNwU2VydmVycy5nZXQodXNlcklkKTtcbiAgICBpZiAoZXhpc3RpbmcpIHtcbiAgICAgIGV4aXN0aW5nLmxhc3RVc2VkID0gRGF0ZS5ub3coKTtcbiAgICAgIHJldHVybiBleGlzdGluZy5zZXJ2ZXI7XG4gICAgfVxuICAgIGNvbnN0IHNjb3BlID0gdXNlclNjb3BlKHVzZXJJZCk7XG4gICAgY29uc3QgdG9vbHMgPSBPYmplY3QuZnJvbUVudHJpZXMoXG4gICAgICBPYmplY3QuZW50cmllcyh0aGlzLm1jcFRvb2xzKS5tYXAoKFtuYW1lLCB0b29sXSkgPT4gW1xuICAgICAgICBuYW1lLFxuICAgICAgICBjcmVhdGVUb29sKHtcbiAgICAgICAgICBpZDogbmFtZSxcbiAgICAgICAgICBkZXNjcmlwdGlvbjogdG9vbC5kZXNjcmlwdGlvbiA/PyBuYW1lLFxuICAgICAgICAgIC4uLih0b29sLmlucHV0U2NoZW1hID8geyBpbnB1dFNjaGVtYTogdG9vbC5pbnB1dFNjaGVtYSBhcyBuZXZlciB9IDoge30pLFxuICAgICAgICAgIGV4ZWN1dGU6IChhcmdzOiB1bmtub3duLCBjb250ZXh0OiB1bmtub3duKSA9PiB7XG4gICAgICAgICAgICBpZiAoIXRvb2wuZXhlY3V0ZSkgdGhyb3cgbmV3IEVycm9yKGBHcmFwaGl0aSB0b29sIGNhbm5vdCBleGVjdXRlOiAke25hbWV9YCk7XG4gICAgICAgICAgICByZXR1cm4gdG9vbC5leGVjdXRlKHNjb3BlZEFyZ3VtZW50cyhuYW1lLCBhcmdzLCBzY29wZSksIGNvbnRleHQgYXMgbmV2ZXIpO1xuICAgICAgICAgIH0sXG4gICAgICAgIH0pLFxuICAgICAgXSksXG4gICAgKTtcbiAgICBjb25zdCBzZXJ2ZXIgPSBuZXcgTUNQU2VydmVyKHtcbiAgICAgIG5hbWU6IFwiR3JhcGhpdGlcIixcbiAgICAgIHZlcnNpb246IFwiMS4wLjBcIixcbiAgICAgIHRvb2xzLFxuICAgIH0pO1xuICAgIHRoaXMubWNwU2VydmVycy5zZXQodXNlcklkLCB7IGxhc3RVc2VkOiBEYXRlLm5vdygpLCBzZXJ2ZXIgfSk7XG4gICAgcmV0dXJuIHNlcnZlcjtcbiAgfVxuXG4gIHByaXZhdGUgb25TdXBlcnZpc29yRXhpdChlcnJvcj86IHVua25vd24pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zdG9wcGluZyB8fCAhdGhpcy5zZXR1cENvbXBsZXRlKSByZXR1cm47XG4gICAgdGhpcy5sb2dnZXIuZXJyb3IoXCJzaWRlY2FyIHN1cGVydmlzb3IgZXhpdGVkXCIsIHsgZXJyb3IgfSk7XG4gICAgcHJvY2Vzcy5raWxsKHByb2Nlc3MucGlkLCBcIlNJR1RFUk1cIik7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHN0b3BTaWRlY2FycygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5zdG9wcGluZykgcmV0dXJuO1xuICAgIHRoaXMuc3RvcHBpbmcgPSB0cnVlO1xuICAgIGlmICh0aGlzLm1jcFNlcnZlclN3ZWVwKSBjbGVhckludGVydmFsKHRoaXMubWNwU2VydmVyU3dlZXApO1xuICAgIHRoaXMubWNwU2VydmVyU3dlZXAgPSB1bmRlZmluZWQ7XG4gICAgY29uc3QgY29tbWFuZHMgPSB0aGlzLmNvbW1hbmRzO1xuICAgIGNvbnN0IHN1cGVydmlzaW9uID0gdGhpcy5zdXBlcnZpc2lvbjtcbiAgICBmb3IgKGNvbnN0IGNvbW1hbmQgb2YgY29tbWFuZHMpIGNvbW1hbmQua2lsbChcIlNJR1RFUk1cIik7XG4gICAgY29uc3QgY2xlYW51cCA9IFByb21pc2UuYWxsU2V0dGxlZChbXG4gICAgICAuLi5bLi4udGhpcy5tY3BTZXJ2ZXJzLnZhbHVlcygpXS5tYXAoKHsgc2VydmVyIH0pID0+IHNlcnZlci5jbG9zZSgpKSxcbiAgICAgIHRoaXMubWNwPy5kaXNjb25uZWN0KCksXG4gICAgICBzdXBlcnZpc2lvbj8ucmVzdWx0LFxuICAgIF0pO1xuICAgIGNvbnN0IGNvbXBsZXRlZCA9IGF3YWl0IFByb21pc2UucmFjZShbXG4gICAgICBjbGVhbnVwLnRoZW4oKCkgPT4gdHJ1ZSksXG4gICAgICBhc3luY01vZHVsZS5zbGVlcChTSURFQ0FSX1NIVVRET1dOX0dSQUNFX01TKS50aGVuKCgpID0+IGZhbHNlKSxcbiAgICBdKTtcbiAgICBpZiAoIWNvbXBsZXRlZCkge1xuICAgICAgdGhpcy5sb2dnZXIud2FybihcInNpZGVjYXJzIGlnbm9yZWQgU0lHVEVSTTsgZXNjYWxhdGluZyB0byBTSUdLSUxMXCIpO1xuICAgICAgZm9yIChjb25zdCBjb21tYW5kIG9mIGNvbW1hbmRzKSBjb21tYW5kLmtpbGwoXCJTSUdLSUxMXCIpO1xuICAgIH1cbiAgICB0aGlzLm1jcFNlcnZlcnMuY2xlYXIoKTtcbiAgICB0aGlzLm1jcCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLm1jcFRvb2xzID0ge307XG4gICAgdGhpcy5jb21tYW5kcyA9IFtdO1xuICAgIHRoaXMuc3VwZXJ2aXNpb24gPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5zdGFydHVwID0gdW5kZWZpbmVkO1xuICB9XG5cbiAgcHJpdmF0ZSBjbG9zZUlkbGVNY3BTZXJ2ZXJzKCk6IHZvaWQge1xuICAgIGNvbnN0IGN1dG9mZiA9IERhdGUubm93KCkgLSBNQ1BfU0VSVkVSX0lETEVfTVM7XG4gICAgZm9yIChjb25zdCBbdXNlcklkLCBlbnRyeV0gb2YgdGhpcy5tY3BTZXJ2ZXJzKSB7XG4gICAgICBpZiAoZW50cnkubGFzdFVzZWQgPj0gY3V0b2ZmKSBjb250aW51ZTtcbiAgICAgIHRoaXMubWNwU2VydmVycy5kZWxldGUodXNlcklkKTtcbiAgICAgIHZvaWQgZW50cnkuc2VydmVyLmNsb3NlKCkuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgIHRoaXMubG9nZ2VyLndhcm4oXCJpZGxlIE1DUCBzZXJ2ZXIgY2xvc2UgZmFpbGVkXCIsIHsgZXJyb3IgfSk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cbn1cblxudHlwZSBFeGVjUHl0aG9uID0gKGZpbGU6IHN0cmluZywgYXJnczogc3RyaW5nW10pID0+IFByb21pc2U8dW5rbm93bj47XG5cbi8qKiBFbnN1cmUgRGF0YWJyaWNrcyBBcHBzIGhhcyB0aGUgUHl0aG9uIHNpZGVjYXIgbWF0Y2hpbmcgdGhpcyBOb2RlIHBhY2thZ2UuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZW5zdXJlR3JhcGhpdGlQeXRob24oXG4gIHB5dGhvbjogc3RyaW5nLFxuICBydW46IEV4ZWNQeXRob24gPSAoZmlsZSwgYXJncykgPT4gcHJvbWlzaWZ5KGV4ZWNGaWxlKShmaWxlLCBhcmdzKSxcbik6IFByb21pc2U8dm9pZD4ge1xuICB0cnkge1xuICAgIGF3YWl0IHJ1bihweXRob24sIFtcbiAgICAgIFwiLWNcIixcbiAgICAgIGBpbXBvcnQgaW1wb3J0bGliLm1ldGFkYXRhOyBhc3NlcnQgaW1wb3J0bGliLm1ldGFkYXRhLnZlcnNpb24oJ2RieC10b29scy1ncmFwaGl0aScpID09ICcke1BBQ0tBR0VfVkVSU0lPTn0nYCxcbiAgICBdKTtcbiAgfSBjYXRjaCB7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHJ1bihweXRob24sIFtcIi1tXCIsIFwicGlwXCIsIFwiLS12ZXJzaW9uXCJdKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIGF3YWl0IHJ1bihweXRob24sIFtcbiAgICAgICAgXCItY1wiLFxuICAgICAgICBcImltcG9ydCB1cmxsaWIucmVxdWVzdDsgZXhlYyh1cmxsaWIucmVxdWVzdC51cmxvcGVuKCdodHRwczovL2Jvb3RzdHJhcC5weXBhLmlvL2dldC1waXAucHknKS5yZWFkKCkpXCIsXG4gICAgICAgIFwiLS11c2VyXCIsXG4gICAgICAgIFwiLS1icmVhay1zeXN0ZW0tcGFja2FnZXNcIixcbiAgICAgIF0pO1xuICAgIH1cbiAgICBhd2FpdCBydW4ocHl0aG9uLCBbXG4gICAgICBcIi1tXCIsXG4gICAgICBcInBpcFwiLFxuICAgICAgXCJpbnN0YWxsXCIsXG4gICAgICBcIi0tZGlzYWJsZS1waXAtdmVyc2lvbi1jaGVja1wiLFxuICAgICAgXCItLXVwZ3JhZGVcIixcbiAgICAgIFwiLS11c2VyXCIsXG4gICAgICBcIi0tYnJlYWstc3lzdGVtLXBhY2thZ2VzXCIsXG4gICAgICBgZGJ4LXRvb2xzLWdyYXBoaXRpPT0ke1BBQ0tBR0VfVkVSU0lPTn1gLFxuICAgIF0pO1xuICB9XG59XG5cbmV4cG9ydCBjb25zdCBncmFwaGl0aSA9IHRvUGx1Z2luKEdyYXBoaXRpUGx1Z2luKTtcblxuZnVuY3Rpb24gZXhlY3V0aW9uQ29udGV4dFVzZXJJZCgpOiBzdHJpbmcge1xuICBjb25zdCBjb250ZXh0ID0gZGJ4QXBwa2l0LnRyeUdldEV4ZWN1dGlvbkNvbnRleHQoKTtcbiAgaWYgKCFjb250ZXh0KSB0aHJvdyBuZXcgRXJyb3IoXCJHcmFwaGl0aSBtZW1vcnkgcmVxdWlyZXMgYW4gQXBwS2l0IGV4ZWN1dGlvbiBjb250ZXh0XCIpO1xuICByZXR1cm4gXCJ1c2VySWRcIiBpbiBjb250ZXh0ID8gY29udGV4dC51c2VySWQgOiBjb250ZXh0LnNlcnZpY2VVc2VySWQ7XG59XG5cbmZ1bmN0aW9uIHVzZXJTY29wZSh1c2VySWQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgdXNlcl8ke2NyZWF0ZUhhc2goXCJzaGEyNTZcIikudXBkYXRlKHVzZXJJZCkuZGlnZXN0KFwiYmFzZTY0dXJsXCIpfWA7XG59XG5cbmZ1bmN0aW9uIHNjb3BlZEFyZ3VtZW50cyhuYW1lOiBzdHJpbmcsIGFyZ3M6IHVua25vd24sIHNjb3BlOiBzdHJpbmcpOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB7XG4gIGlmICghKG5hbWUgaW4gU0NPUEVEX1RPT0xfRklFTERTKSkgdGhyb3cgbmV3IEVycm9yKGBHcmFwaGl0aSB0b29sIGlzIG5vdCB1c2VyLXNjb3BlZDogJHtuYW1lfWApO1xuICBjb25zdCBzY29wZWQgPSBvYmplY3QuaXNSZWNvcmQoYXJncykgPyB7IC4uLmFyZ3MgfSA6IHt9O1xuICBmb3IgKGNvbnN0IGFyZ3VtZW50IG9mIFVOU0NPUEVEX0FSR1VNRU5UUykgZGVsZXRlIHNjb3BlZFthcmd1bWVudF07XG4gIGNvbnN0IGZpZWxkID0gU0NPUEVEX1RPT0xfRklFTERTW25hbWUgYXMga2V5b2YgdHlwZW9mIFNDT1BFRF9UT09MX0ZJRUxEU107XG4gIGlmIChmaWVsZCA9PT0gXCJncm91cF9pZFwiKSBzY29wZWQuZ3JvdXBfaWQgPSBzY29wZTtcbiAgaWYgKGZpZWxkID09PSBcImdyb3VwX2lkc1wiKSBzY29wZWQuZ3JvdXBfaWRzID0gW3Njb3BlXTtcbiAgcmV0dXJuIHNjb3BlZDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gYXZhaWxhYmxlUG9ydCgpOiBQcm9taXNlPG51bWJlcj4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIGNvbnN0IHNlcnZlciA9IGNyZWF0ZVNlcnZlcigpO1xuICAgIHNlcnZlci5vbmNlKFwiZXJyb3JcIiwgcmVqZWN0KTtcbiAgICBzZXJ2ZXIubGlzdGVuKDAsIFwiMTI3LjAuMC4xXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IGFkZHJlc3MgPSBzZXJ2ZXIuYWRkcmVzcygpO1xuICAgICAgaWYgKCFhZGRyZXNzIHx8IHR5cGVvZiBhZGRyZXNzID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIHNlcnZlci5jbG9zZSgpO1xuICAgICAgICByZWplY3QobmV3IEVycm9yKFwiQ291bGQgbm90IGFsbG9jYXRlIGEgR3JhcGhpdGkgbG9vcGJhY2sgcG9ydFwiKSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHNlcnZlci5jbG9zZSgoZXJyb3IpID0+IChlcnJvciA/IHJlamVjdChlcnJvcikgOiByZXNvbHZlKGFkZHJlc3MucG9ydCkpKTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGRpc3RpbmN0UG9ydHMoXG4gIGFwcFBvcnQ6IG51bWJlcixcbiAgZ3JhcGhpdGlQb3J0OiBudW1iZXIsXG4gIGxpdGVsbG1Qb3J0OiBudW1iZXIsXG4gIHByb3h5UG9ydDogbnVtYmVyLFxuKTogUHJvbWlzZTxbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0+IHtcbiAgY29uc3QgcG9ydHMgPSBbYXBwUG9ydF07XG4gIGZvciAoY29uc3QgY29uZmlndXJlZFBvcnQgb2YgW2dyYXBoaXRpUG9ydCwgbGl0ZWxsbVBvcnQsIHByb3h5UG9ydF0pIHtcbiAgICBpZiAoY29uZmlndXJlZFBvcnQgJiYgcG9ydHMuaW5jbHVkZXMoY29uZmlndXJlZFBvcnQpKSB7XG4gICAgICB0aHJvdyBuZXcgQ29uZmlndXJhdGlvbkVycm9yKFwiR3JhcGhpdGkgc2lkZWNhciBwb3J0cyBtdXN0IGRpZmZlciBmcm9tIERBVEFCUklDS1NfQVBQX1BPUlRcIik7XG4gICAgfVxuICAgIGxldCBwb3J0ID0gY29uZmlndXJlZFBvcnQgfHwgKGF3YWl0IGF2YWlsYWJsZVBvcnQoKSk7XG4gICAgd2hpbGUgKHBvcnRzLmluY2x1ZGVzKHBvcnQpKSBwb3J0ID0gYXdhaXQgYXZhaWxhYmxlUG9ydCgpO1xuICAgIHBvcnRzLnB1c2gocG9ydCk7XG4gIH1cbiAgcmV0dXJuIHBvcnRzLnNsaWNlKDEpIGFzIFtudW1iZXIsIG51bWJlciwgbnVtYmVyXTtcbn1cblxuZnVuY3Rpb24gY29tbWFuZExpbmUoYXJndW1lbnRzXzogc3RyaW5nW10pOiBzdHJpbmcge1xuICByZXR1cm4gYXJndW1lbnRzXy5tYXAoKHZhbHVlKSA9PiBgJyR7dmFsdWUucmVwbGFjZUFsbChcIidcIiwgXCInXFxcXCcnXCIpfSdgKS5qb2luKFwiIFwiKTtcbn1cbiJdfQ==
394
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3BsdWdpbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBQ0gsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzlDLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDekMsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUM1QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxPQUFPLElBQUksV0FBVyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQ25ELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFDdEMsT0FBTyxFQUNMLGtCQUFrQixFQUNsQixNQUFNLEVBQ04sUUFBUSxFQUNSLFFBQVEsR0FJVCxNQUFNLG9CQUFvQixDQUFDO0FBQzVCLE9BQU8sRUFDTCxNQUFNLElBQUksU0FBUyxFQUNuQixRQUFRLElBQUksY0FBYyxFQUMxQixNQUFNLElBQUksWUFBWSxHQUN2QixNQUFNLG1CQUFtQixDQUFDO0FBQzNCLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSx3QkFBd0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQy9GLE9BQU8sRUFBRSxNQUFNLElBQUksVUFBVSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDdkQsT0FBTyxFQUFFLEtBQUssSUFBSSxXQUFXLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQzNFLE9BQU8sRUFBRSxVQUFVLEVBQWEsTUFBTSxvQkFBb0IsQ0FBQztBQUMzRCxPQUFPLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUNuRCxPQUFPLFlBQXVELE1BQU0sY0FBYyxDQUFDO0FBRW5GLE9BQU8sRUFDTCxzQkFBc0IsRUFDdEIscUJBQXFCLEdBR3RCLE1BQU0sYUFBYSxDQUFDO0FBRXJCLE1BQU0saUJBQWlCLEdBQUcsWUFBWSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDO0FBQ3RFLE1BQU0sMEJBQTBCLEdBQUcsd0JBQXdCLENBQUMsYUFBYSxDQUFDLENBQUM7QUFDM0UsTUFBTSxlQUFlLEdBQ25CLGFBQWEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLHlDQUF5QyxDQUN6RSxDQUFDLE9BQU8sQ0FBQztBQUNWLE1BQU0sUUFBUSxHQUFHLG1CQUFtQixDQUFDO0FBQ3JDLE1BQU0sa0JBQWtCLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUM7QUFDMUMsTUFBTSxtQkFBbUIsR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQztBQUMxQyxNQUFNLHlCQUF5QixHQUFHLE1BQU0sQ0FBQztBQUN6QyxNQUFNLGtCQUFrQixHQUFHO0lBQ3pCLFVBQVUsRUFBRSxVQUFVO0lBQ3RCLFdBQVcsRUFBRSxVQUFVO0lBQ3ZCLGlCQUFpQixFQUFFLFdBQVc7SUFDOUIsWUFBWSxFQUFFLFdBQVc7SUFDekIsVUFBVSxFQUFFLFNBQVM7SUFDckIsbUJBQW1CLEVBQUUsV0FBVztJQUNoQyxZQUFZLEVBQUUsV0FBVztJQUN6QixjQUFjLEVBQUUsVUFBVTtDQUNsQixDQUFDO0FBQ1gsTUFBTSxXQUFXLEdBQUcsSUFBSSxHQUFHLENBQUMsQ0FBQyxZQUFZLEVBQUUsYUFBYSxFQUFFLG1CQUFtQixFQUFFLGdCQUFnQixDQUFDLENBQUMsQ0FBQztBQUNsRyxNQUFNLGtCQUFrQixHQUFHO0lBQ3pCLGtCQUFrQjtJQUNsQix3QkFBd0I7SUFDeEIsNEJBQTRCO0lBQzVCLGtCQUFrQjtJQUNsQixrQkFBa0I7SUFDbEIsTUFBTTtDQUNFLENBQUM7QUFzQlgsTUFBTSxPQUFPLGNBQWUsU0FBUSxNQUE0QjtJQUM5RCxNQUFNLENBQUMsUUFBUSxHQUErQjtRQUM1QyxJQUFJLEVBQUUsVUFBVTtRQUNoQixXQUFXLEVBQUUsVUFBVTtRQUN2QixXQUFXLEVBQ1QsNEVBQTRFO1lBQzVFLHdEQUF3RDtRQUMxRCxTQUFTLEVBQUUsTUFBTTtRQUNqQixTQUFTLEVBQUU7WUFDVCxRQUFRLEVBQUUsRUFBRTtZQUNaLFFBQVEsRUFBRSxDQUFDLEdBQUcsaUJBQWlCLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQztTQUNwRDtRQUNELE1BQU0sRUFBRSxFQUFFLE1BQU0sRUFBRSxzQkFBc0IsRUFBRTtLQUMzQyxDQUFDO0lBRUYsTUFBTSxDQUFDLHVCQUF1QjtRQUM1QixPQUFPLGlCQUFpQixDQUFDLFNBQVMsQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxDQUFDO1lBQzdELEdBQUcsUUFBUTtZQUNYLFFBQVEsRUFBRSxJQUFJO1NBQ2YsQ0FBQyxDQUFDLENBQUM7SUFDTixDQUFDO0lBRWdCLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ25DLFFBQVEsR0FBYyxFQUFFLENBQUM7SUFDekIsR0FBRyxDQUFhO0lBQ2hCLFVBQVUsR0FBRyxJQUFJLEdBQUcsRUFBeUIsQ0FBQztJQUM5QyxjQUFjLENBQWtCO0lBQ2hDLFFBQVEsR0FBeUIsRUFBRSxDQUFDO0lBQ3BDLFFBQVEsQ0FBZ0M7SUFDeEMsYUFBYSxHQUFHLEtBQUssQ0FBQztJQUN0QixPQUFPLENBQWlCO0lBQ3hCLFdBQVcsQ0FBc0I7SUFDakMsUUFBUSxHQUFHLEtBQUssQ0FBQztJQUVoQixLQUFLLENBQUMsS0FBSztRQUNsQixJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxLQUFjLEVBQUUsRUFBRTtZQUMzRCxJQUFJLElBQUksQ0FBQyxRQUFRO2dCQUFFLE9BQU87WUFDMUIsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsMkJBQTJCLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDO1lBQzFELE9BQU8sQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxTQUFTLENBQUMsQ0FBQztRQUN2QyxDQUFDLENBQUMsQ0FBQztRQUNILEtBQUssSUFBSSxDQUFDLE9BQU8sQ0FBQztRQUNsQixJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyw4QkFBOEIsQ0FBQyxDQUFDO0lBQ25ELENBQUM7SUFFTyxLQUFLLENBQUMsYUFBYTtRQUN6QixNQUFNLFVBQVUsR0FBRyxxQkFBcUIsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDdEQsTUFBTSxDQUFDLFlBQVksRUFBRSxjQUFjLEVBQUUsU0FBUyxDQUFDLEdBQUcsTUFBTSxhQUFhLENBQ25FLFVBQVUsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLHFCQUFxQixFQUFFLElBQUksRUFBRSxVQUFVLENBQUMsUUFBUSxDQUFDLEVBQzVFLFVBQVUsQ0FBQyxZQUFZLEVBQ3ZCLFVBQVUsQ0FBQyxjQUFjLEVBQ3pCLFVBQVUsQ0FBQyxTQUFTLENBQ3JCLENBQUM7UUFDRixNQUFNLG9CQUFvQixDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUM5QyxNQUFNLGlCQUFpQixHQUFHLE1BQU0sd0JBQXdCLEVBQUUsQ0FBQztRQUMzRCxJQUFJLENBQUMsUUFBUSxHQUFHO1lBQ2QsR0FBRyxVQUFVO1lBQ2IsWUFBWTtZQUNaLGNBQWM7WUFDZCxTQUFTO1NBQ1YsQ0FBQztRQUNGLElBQUksQ0FBQyxXQUFXLEdBQUcsWUFBWSxDQUM3QjtZQUNFO2dCQUNFLElBQUksRUFBRSxVQUFVO2dCQUNoQixPQUFPLEVBQUUsV0FBVyxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLG9CQUFvQixFQUFFLE9BQU8sQ0FBQyxDQUFDO2dCQUNqRixHQUFHLEVBQUU7b0JBQ0gsR0FBRyxPQUFPLENBQUMsR0FBRztvQkFDZCxhQUFhLEVBQUUsV0FBVztvQkFDMUIsYUFBYSxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksQ0FBQztvQkFDakQsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0I7b0JBQ2pELGtCQUFrQixFQUFFLE1BQU07b0JBQzFCLG1CQUFtQixFQUFFLGlCQUFpQjtvQkFDdEMsZ0JBQWdCLEVBQUUsV0FBVztvQkFDN0IsZ0JBQWdCLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsY0FBYyxDQUFDO2lCQUN2RDthQUNGO1lBQ0Q7Z0JBQ0UsSUFBSSxFQUFFLE9BQU87Z0JBQ2IsT0FBTyxFQUFFLFdBQVcsQ0FBQztvQkFDbkIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNO29CQUNwQixJQUFJO29CQUNKLDBCQUEwQjtvQkFDMUIsY0FBYztvQkFDZCxNQUFNLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUM7b0JBQy9CLGlCQUFpQjtvQkFDakIsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDO2lCQUNuQyxDQUFDO2dCQUNGLEdBQUcsRUFBRSxPQUFPLENBQUMsR0FBRzthQUNqQjtTQUNGLEVBQ0Q7WUFDRSxZQUFZLEVBQUUsQ0FBQyxTQUFTLEVBQUUsU0FBUyxDQUFDO1lBQ3BDLFVBQVUsRUFBRSxTQUFTO1lBQ3JCLFdBQVcsRUFBRSx5QkFBeUI7WUFDdEMsTUFBTSxFQUFFLE1BQU07WUFDZCxZQUFZLEVBQUUsS0FBSztTQUNwQixDQUNGLENBQUM7UUFDRixJQUFJLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsUUFBUSxDQUFDO1FBQzFDLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDO1FBQzFCLEtBQUssSUFBSSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUMvQixHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsRUFDN0IsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxLQUFLLENBQUMsQ0FDeEMsQ0FBQztRQUNGLElBQUksQ0FBQyxjQUFjLEdBQUcsV0FBVyxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxFQUFFLG1CQUFtQixDQUFDLENBQUM7UUFDekYsSUFBSSxDQUFDLGNBQWMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUM1QixJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsRUFBRTtZQUNwQyxZQUFZLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxZQUFZO1lBQ3hDLGNBQWMsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLGNBQWM7WUFDNUMsU0FBUyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUztZQUNsQyxPQUFPLEVBQUUsUUFBUTtTQUNsQixDQUFDLENBQUM7SUFDTCxDQUFDO0lBRVEsWUFBWSxDQUFDLE1BQWtCO1FBQ3RDLEtBQUssTUFBTSxNQUFNLElBQUksQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLFFBQVEsQ0FBVSxFQUFFLENBQUM7WUFDeEQsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUU7Z0JBQ2pCLElBQUksRUFBRSxHQUFHLE1BQU0sS0FBSztnQkFDcEIsTUFBTTtnQkFDTixJQUFJLEVBQUUsTUFBTTtnQkFDWixPQUFPLEVBQUUsQ0FBQyxPQUFPLEVBQUUsUUFBUSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sRUFBRSxRQUFRLENBQUM7YUFDbkUsQ0FBQyxDQUFDO1FBQ0wsQ0FBQztJQUNILENBQUM7SUFFUSxxQkFBcUI7UUFDNUIsS0FBSyxDQUFDLHFCQUFxQixFQUFFLENBQUM7UUFDOUIsS0FBSyxJQUFJLENBQUMsR0FBRyxFQUFFLFVBQVUsRUFBRSxDQUFDO0lBQzlCLENBQUM7SUFFRCxLQUFLLENBQUMsUUFBUTtRQUNaLE1BQU0sSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQzVCLENBQUM7SUFFUSxPQUFPO1FBQ2QsT0FBTyxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsQ0FBQztJQUMvQixDQUFDO0lBRUQsT0FBTztRQUNMLE9BQU8sTUFBTSxDQUFDLFdBQVcsQ0FDdkIsTUFBTSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUM7WUFDNUMsSUFBSTtZQUNKO2dCQUNFLFlBQVksRUFBRSxJQUFhO2dCQUMzQixVQUFVLEVBQUUsVUFBVTtnQkFDdEIsU0FBUyxFQUFFLElBQUk7Z0JBQ2YsR0FBRyxFQUFFO29CQUNILElBQUk7b0JBQ0osV0FBVyxFQUFFLFlBQVksSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLEVBQUU7b0JBQ3BELFVBQVUsRUFBRSxFQUFFLElBQUksRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLEVBQUUsRUFBRTtpQkFDL0M7Z0JBQ0QsV0FBVyxFQUFFO29CQUNYLE1BQU0sRUFBRSxXQUFXLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBRSxPQUFpQixDQUFDLENBQUMsQ0FBRSxNQUFnQjtvQkFDdEUsbUJBQW1CLEVBQUUsSUFBYTtpQkFDbkM7YUFDRjtTQUNGLENBQUMsQ0FDSCxDQUFDO0lBQ0osQ0FBQztJQUVELEtBQUssQ0FBQyxnQkFBZ0IsQ0FDcEIsSUFBWSxFQUNaLElBQWEsRUFDYixNQUFvQixFQUNwQixPQUFpQztRQUVqQyxNQUFNLElBQUksQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUM1QixNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDO1FBQ2pDLElBQUksQ0FBQyxJQUFJLEVBQUUsT0FBTztZQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMsMEJBQTBCLElBQUksRUFBRSxDQUFDLENBQUM7UUFDdEUsTUFBTSxNQUFNLEdBQUcsT0FBTyxFQUFFLFVBQVUsSUFBSSxzQkFBc0IsRUFBRSxDQUFDO1FBQy9ELE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRTtZQUNsRSxXQUFXLEVBQUUsTUFBTTtTQUNYLENBQUMsQ0FBQztJQUNkLENBQUM7SUFFTyxLQUFLLENBQUMsVUFBVSxDQUFDLE9BQXdCLEVBQUUsUUFBMEI7UUFDM0UsTUFBTSxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDNUIsTUFBTSxNQUFNLEdBQUcsY0FBYyxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsSUFBSSxzQkFBc0IsRUFBRSxDQUFDO1FBQ2pGLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDdEMsTUFBTSxNQUFNLENBQUMsU0FBUyxDQUFDO1lBQ3JCLEdBQUcsRUFBRSxJQUFJLEdBQUcsQ0FBQyxPQUFPLENBQUMsV0FBVyxFQUFFLGtCQUFrQixDQUFDO1lBQ3JELFFBQVEsRUFBRSxRQUFRO1lBQ2xCLEdBQUcsRUFBRSxPQUFPO1lBQ1osR0FBRyxFQUFFLFFBQVE7U0FDZCxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRU8sS0FBSyxDQUFDLGNBQWM7UUFDMUIsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQztZQUFFLE9BQU87UUFDbEQsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRO1lBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyxxQ0FBcUMsQ0FBQyxDQUFDO1FBQzNFLElBQUksQ0FBQyxHQUFHLEtBQUssSUFBSSxTQUFTLENBQUM7WUFDekIsRUFBRSxFQUFFLG1CQUFtQixJQUFJLENBQUMsUUFBUSxDQUFDLFlBQVksRUFBRTtZQUNuRCxPQUFPLEVBQUU7Z0JBQ1AsUUFBUSxFQUFFLEVBQUUsR0FBRyxFQUFFLElBQUksR0FBRyxDQUFDLG9CQUFvQixJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsTUFBTSxDQUFDLEVBQUU7YUFDOUU7U0FDRixDQUFDLENBQUM7UUFDSCxNQUFNLFVBQVUsR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxFQUFFLENBQUM7UUFDOUMsSUFBSSxDQUFDLFFBQVEsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUNoQyxNQUFNLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQzthQUN2QixHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksRUFBRSxFQUFFLENBQUMsRUFBRSxJQUFZLENBQVUsQ0FBQzthQUM5RSxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLEVBQUUsQ0FBQyxJQUFJLElBQUksa0JBQWtCLENBQUMsQ0FDbEQsQ0FBQztRQUNGLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO1FBQ3ZGLElBQUksT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUN2QixNQUFNLElBQUksS0FBSyxDQUFDLG1EQUFtRCxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztRQUMzRixDQUFDO0lBQ0gsQ0FBQztJQUVPLFNBQVMsQ0FBQyxNQUFjO1FBQzlCLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQzdDLElBQUksUUFBUSxFQUFFLENBQUM7WUFDYixRQUFRLENBQUMsUUFBUSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztZQUMvQixPQUFPLFFBQVEsQ0FBQyxNQUFNLENBQUM7UUFDekIsQ0FBQztRQUNELE1BQU0sS0FBSyxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQztRQUNoQyxNQUFNLEtBQUssR0FBRyxNQUFNLENBQUMsV0FBVyxDQUM5QixNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDbEQsSUFBSTtZQUNKLFVBQVUsQ0FBQztnQkFDVCxFQUFFLEVBQUUsSUFBSTtnQkFDUixXQUFXLEVBQUUsSUFBSSxDQUFDLFdBQVcsSUFBSSxJQUFJO2dCQUNyQyxHQUFHLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsRUFBRSxXQUFXLEVBQUUsSUFBSSxDQUFDLFdBQW9CLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO2dCQUN2RSxPQUFPLEVBQUUsQ0FBQyxJQUFhLEVBQUUsT0FBZ0IsRUFBRSxFQUFFO29CQUMzQyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU87d0JBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyxpQ0FBaUMsSUFBSSxFQUFFLENBQUMsQ0FBQztvQkFDNUUsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLEtBQUssQ0FBQyxFQUFFLE9BQWdCLENBQUMsQ0FBQztnQkFDNUUsQ0FBQzthQUNGLENBQUM7U0FDSCxDQUFDLENBQ0gsQ0FBQztRQUNGLE1BQU0sTUFBTSxHQUFHLElBQUksU0FBUyxDQUFDO1lBQzNCLElBQUksRUFBRSxVQUFVO1lBQ2hCLE9BQU8sRUFBRSxPQUFPO1lBQ2hCLEtBQUs7U0FDTixDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsRUFBRSxRQUFRLEVBQUUsSUFBSSxDQUFDLEdBQUcsRUFBRSxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDOUQsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQztJQUVPLGdCQUFnQixDQUFDLEtBQWU7UUFDdEMsSUFBSSxJQUFJLENBQUMsUUFBUSxJQUFJLENBQUMsSUFBSSxDQUFDLGFBQWE7WUFBRSxPQUFPO1FBQ2pELElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLDJCQUEyQixFQUFFLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUMxRCxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsU0FBUyxDQUFDLENBQUM7SUFDdkMsQ0FBQztJQUVPLEtBQUssQ0FBQyxZQUFZO1FBQ3hCLElBQUksSUFBSSxDQUFDLFFBQVE7WUFBRSxPQUFPO1FBQzFCLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxDQUFDO1FBQ3JCLElBQUksSUFBSSxDQUFDLGNBQWM7WUFBRSxhQUFhLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxDQUFDO1FBQzVELElBQUksQ0FBQyxjQUFjLEdBQUcsU0FBUyxDQUFDO1FBQ2hDLE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUM7UUFDL0IsTUFBTSxXQUFXLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQztRQUNyQyxLQUFLLE1BQU0sT0FBTyxJQUFJLFFBQVE7WUFBRSxPQUFPLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDO1FBQ3hELE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUM7WUFDakMsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNwRSxJQUFJLENBQUMsR0FBRyxFQUFFLFVBQVUsRUFBRTtZQUN0QixXQUFXLEVBQUUsTUFBTTtTQUNwQixDQUFDLENBQUM7UUFDSCxNQUFNLFNBQVMsR0FBRyxNQUFNLE9BQU8sQ0FBQyxJQUFJLENBQUM7WUFDbkMsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUM7WUFDeEIsV0FBVyxDQUFDLEtBQUssQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxLQUFLLENBQUM7U0FDL0QsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ2YsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsaURBQWlELENBQUMsQ0FBQztZQUNwRSxLQUFLLE1BQU0sT0FBTyxJQUFJLFFBQVE7Z0JBQUUsT0FBTyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUMxRCxDQUFDO1FBQ0QsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUN4QixJQUFJLENBQUMsR0FBRyxHQUFHLFNBQVMsQ0FBQztRQUNyQixJQUFJLENBQUMsUUFBUSxHQUFHLEVBQUUsQ0FBQztRQUNuQixJQUFJLENBQUMsUUFBUSxHQUFHLEVBQUUsQ0FBQztRQUNuQixJQUFJLENBQUMsV0FBVyxHQUFHLFNBQVMsQ0FBQztRQUM3QixJQUFJLENBQUMsT0FBTyxHQUFHLFNBQVMsQ0FBQztJQUMzQixDQUFDO0lBRU8sbUJBQW1CO1FBQ3pCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxrQkFBa0IsQ0FBQztRQUMvQyxLQUFLLE1BQU0sQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLElBQUksSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQzlDLElBQUksS0FBSyxDQUFDLFFBQVEsSUFBSSxNQUFNO2dCQUFFLFNBQVM7WUFDdkMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUM7WUFDL0IsS0FBSyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO2dCQUN4QyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyw4QkFBOEIsRUFBRSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7WUFDOUQsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDO0lBQ0gsQ0FBQzs7QUFLSCxnRkFBZ0Y7QUFDaEYsTUFBTSxDQUFDLEtBQUssVUFBVSxvQkFBb0IsQ0FDeEMsTUFBYyxFQUNkLE1BQWtCLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxFQUFFLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUM7SUFFakUsSUFBSSxDQUFDO1FBQ0gsTUFBTSxHQUFHLENBQUMsTUFBTSxFQUFFO1lBQ2hCLElBQUk7WUFDSiwwRkFBMEYsZUFBZSxHQUFHO1NBQzdHLENBQUMsQ0FBQztJQUNMLENBQUM7SUFBQyxNQUFNLENBQUM7UUFDUCxJQUFJLENBQUM7WUFDSCxNQUFNLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFLFdBQVcsQ0FBQyxDQUFDLENBQUM7UUFDaEQsQ0FBQztRQUFDLE1BQU0sQ0FBQztZQUNQLE1BQU0sR0FBRyxDQUFDLE1BQU0sRUFBRTtnQkFDaEIsSUFBSTtnQkFDSixvR0FBb0c7Z0JBQ3BHLFFBQVE7Z0JBQ1IseUJBQXlCO2FBQzFCLENBQUMsQ0FBQztRQUNMLENBQUM7UUFDRCxNQUFNLEdBQUcsQ0FBQyxNQUFNLEVBQUU7WUFDaEIsSUFBSTtZQUNKLEtBQUs7WUFDTCxTQUFTO1lBQ1QsNkJBQTZCO1lBQzdCLFdBQVc7WUFDWCxRQUFRO1lBQ1IseUJBQXlCO1lBQ3pCLHVCQUF1QixlQUFlLEVBQUU7U0FDekMsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztBQUNILENBQUM7QUFFRCx5RUFBeUU7QUFDekUsTUFBTSxDQUFDLEtBQUssVUFBVSx3QkFBd0IsQ0FDNUMsVUFBMEMsdUJBQXVCO0lBRWpFLE1BQU0sU0FBUyxHQUFHLE1BQU0sT0FBTyxDQUFDLDBCQUEwQixDQUFDLENBQUM7SUFDNUQsT0FBTyxXQUFXLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQ3JDLENBQUM7QUFFRCxNQUFNLENBQUMsTUFBTSxRQUFRLEdBQUcsUUFBUSxDQUFDLGNBQWMsQ0FBQyxDQUFDO0FBRWpELFNBQVMsc0JBQXNCO0lBQzdCLE1BQU0sT0FBTyxHQUFHLFNBQVMsQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO0lBQ25ELElBQUksQ0FBQyxPQUFPO1FBQUUsTUFBTSxJQUFJLEtBQUssQ0FBQyxzREFBc0QsQ0FBQyxDQUFDO0lBQ3RGLE9BQU8sUUFBUSxJQUFJLE9BQU8sQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQztBQUN0RSxDQUFDO0FBRUQsU0FBUyxTQUFTLENBQUMsTUFBYztJQUMvQixPQUFPLFFBQVEsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLEVBQUUsQ0FBQztBQUMzRSxDQUFDO0FBRUQsU0FBUyxlQUFlLENBQUMsSUFBWSxFQUFFLElBQWEsRUFBRSxLQUFhO0lBQ2pFLElBQUksQ0FBQyxDQUFDLElBQUksSUFBSSxrQkFBa0IsQ0FBQztRQUFFLE1BQU0sSUFBSSxLQUFLLENBQUMscUNBQXFDLElBQUksRUFBRSxDQUFDLENBQUM7SUFDaEcsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDeEQsS0FBSyxNQUFNLFFBQVEsSUFBSSxrQkFBa0I7UUFBRSxPQUFPLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNuRSxNQUFNLEtBQUssR0FBRyxrQkFBa0IsQ0FBQyxJQUF1QyxDQUFDLENBQUM7SUFDMUUsSUFBSSxLQUFLLEtBQUssVUFBVTtRQUFFLE1BQU0sQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDO0lBQ2xELElBQUksS0FBSyxLQUFLLFdBQVc7UUFBRSxNQUFNLENBQUMsU0FBUyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDdEQsT0FBTyxNQUFNLENBQUM7QUFDaEIsQ0FBQztBQUVELEtBQUssVUFBVSxhQUFhO0lBQzFCLE9BQU8sSUFBSSxPQUFPLENBQUMsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUU7UUFDckMsTUFBTSxNQUFNLEdBQUcsWUFBWSxFQUFFLENBQUM7UUFDOUIsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDN0IsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEVBQUUsV0FBVyxFQUFFLEdBQUcsRUFBRTtZQUNqQyxNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDakMsSUFBSSxDQUFDLE9BQU8sSUFBSSxPQUFPLE9BQU8sS0FBSyxRQUFRLEVBQUUsQ0FBQztnQkFDNUMsTUFBTSxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUNmLE1BQU0sQ0FBQyxJQUFJLEtBQUssQ0FBQyw2Q0FBNkMsQ0FBQyxDQUFDLENBQUM7Z0JBQ2pFLE9BQU87WUFDVCxDQUFDO1lBQ0QsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDM0UsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCxLQUFLLFVBQVUsYUFBYSxDQUMxQixPQUFlLEVBQ2YsWUFBb0IsRUFDcEIsY0FBc0IsRUFDdEIsU0FBaUI7SUFFakIsTUFBTSxLQUFLLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUN4QixLQUFLLE1BQU0sY0FBYyxJQUFJLENBQUMsWUFBWSxFQUFFLGNBQWMsRUFBRSxTQUFTLENBQUMsRUFBRSxDQUFDO1FBQ3ZFLElBQUksY0FBYyxJQUFJLEtBQUssQ0FBQyxRQUFRLENBQUMsY0FBYyxDQUFDLEVBQUUsQ0FBQztZQUNyRCxNQUFNLElBQUksa0JBQWtCLENBQUMsNkRBQTZELENBQUMsQ0FBQztRQUM5RixDQUFDO1FBQ0QsSUFBSSxJQUFJLEdBQUcsY0FBYyxJQUFJLENBQUMsTUFBTSxhQUFhLEVBQUUsQ0FBQyxDQUFDO1FBQ3JELE9BQU8sS0FBSyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUM7WUFBRSxJQUFJLEdBQUcsTUFBTSxhQUFhLEVBQUUsQ0FBQztRQUMxRCxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ25CLENBQUM7SUFDRCxPQUFPLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUE2QixDQUFDO0FBQ3BELENBQUM7QUFFRCxTQUFTLFdBQVcsQ0FBQyxVQUFvQjtJQUN2QyxPQUFPLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLElBQUksS0FBSyxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNwRixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBBcHBLaXQgcGx1Z2luIHRoYXQgc3VwZXJ2aXNlcyBHcmFwaGl0aSBhbmQgcmVwdWJsaXNoZXMgdXNlci1zY29wZWQgTUNQIHRvb2xzLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuaW1wb3J0IHsgZXhlY0ZpbGUgfSBmcm9tIFwibm9kZTpjaGlsZF9wcm9jZXNzXCI7XG5pbXBvcnQgeyBjcmVhdGVIYXNoIH0gZnJvbSBcIm5vZGU6Y3J5cHRvXCI7XG5pbXBvcnQgeyBjcmVhdGVSZXF1aXJlIH0gZnJvbSBcIm5vZGU6bW9kdWxlXCI7XG5pbXBvcnQgeyBjcmVhdGVTZXJ2ZXIgfSBmcm9tIFwibm9kZTpuZXRcIjtcbmltcG9ydCB7IHJlc29sdmUgYXMgcmVzb2x2ZVBhdGggfSBmcm9tIFwibm9kZTpwYXRoXCI7XG5pbXBvcnQgeyBwcm9taXNpZnkgfSBmcm9tIFwibm9kZTp1dGlsXCI7XG5pbXBvcnQge1xuICBDb25maWd1cmF0aW9uRXJyb3IsXG4gIFBsdWdpbixcbiAgbGFrZWJhc2UsXG4gIHRvUGx1Z2luLFxuICB0eXBlIElBcHBSb3V0ZXIsXG4gIHR5cGUgUGx1Z2luTWFuaWZlc3QsXG4gIHR5cGUgUmVzb3VyY2VSZXF1aXJlbWVudCxcbn0gZnJvbSBcIkBkYXRhYnJpY2tzL2FwcGtpdFwiO1xuaW1wb3J0IHtcbiAgYXBwa2l0IGFzIGRieEFwcGtpdCxcbiAgaWRlbnRpdHkgYXMgYXBwa2l0SWRlbnRpdHksXG4gIHBsdWdpbiBhcyBhcHBraXRQbHVnaW4sXG59IGZyb20gXCJAZGJ4LXRvb2xzL2FwcGtpdFwiO1xuaW1wb3J0IHsgZW5zdXJlUnVzdFJlbGVhc2VCaW5hcnksIHJ1c3RSZWxlYXNlQmluYXJ5Q29tbWFuZCB9IGZyb20gXCJAZGJ4LXRvb2xzL2NsaS9ydXN0LWJpbmFyeVwiO1xuaW1wb3J0IHsgY29uZmlnIGFzIGNvcmVDb25maWcgfSBmcm9tIFwiQGRieC10b29scy9jb3JlXCI7XG5pbXBvcnQgeyBhc3luYyBhcyBhc3luY01vZHVsZSwgbG9nLCBvYmplY3QgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHsgY3JlYXRlVG9vbCwgdHlwZSBUb29sIH0gZnJvbSBcIkBtYXN0cmEvY29yZS90b29sc1wiO1xuaW1wb3J0IHsgTUNQQ2xpZW50LCBNQ1BTZXJ2ZXIgfSBmcm9tIFwiQG1hc3RyYS9tY3BcIjtcbmltcG9ydCBjb25jdXJyZW50bHksIHsgdHlwZSBDb21tYW5kLCB0eXBlIENvbmN1cnJlbnRseVJlc3VsdCB9IGZyb20gXCJjb25jdXJyZW50bHlcIjtcbmltcG9ydCB0eXBlIGV4cHJlc3MgZnJvbSBcImV4cHJlc3NcIjtcbmltcG9ydCB7XG4gIEdSQVBISVRJX0NPTkZJR19TQ0hFTUEsXG4gIHJlc29sdmVHcmFwaGl0aUNvbmZpZyxcbiAgdHlwZSBHcmFwaGl0aVBsdWdpbkNvbmZpZyxcbiAgdHlwZSBSZXNvbHZlZEdyYXBoaXRpUGx1Z2luQ29uZmlnLFxufSBmcm9tIFwiLi9jb25maWcudHNcIjtcblxuY29uc3QgTEFLRUJBU0VfTUFOSUZFU1QgPSBhcHBraXRQbHVnaW4uZGF0YShsYWtlYmFzZSkucGx1Z2luLm1hbmlmZXN0O1xuY29uc3QgTU9ERUxfUFJPWFlfUkVMRUFTRV9CSU5BUlkgPSBydXN0UmVsZWFzZUJpbmFyeUNvbW1hbmQoXCJtb2RlbC1wcm94eVwiKTtcbmNvbnN0IFBBQ0tBR0VfVkVSU0lPTiA9IChcbiAgY3JlYXRlUmVxdWlyZShpbXBvcnQubWV0YS51cmwpKFwiQGRieC10b29scy9hcHBraXQtZ3JhcGhpdGkvcGFja2FnZS5qc29uXCIpIGFzIHsgdmVyc2lvbjogc3RyaW5nIH1cbikudmVyc2lvbjtcbmNvbnN0IE1DUF9QQVRIID0gXCIvYXBpL2dyYXBoaXRpL21jcFwiO1xuY29uc3QgTUNQX1NFUlZFUl9JRExFX01TID0gMzAgKiA2MCAqIDEwMDA7XG5jb25zdCBNQ1BfU0VSVkVSX1NXRUVQX01TID0gNSAqIDYwICogMTAwMDtcbmNvbnN0IFNJREVDQVJfU0hVVERPV05fR1JBQ0VfTVMgPSAxMF8wMDA7XG5jb25zdCBTQ09QRURfVE9PTF9GSUVMRFMgPSB7XG4gIGFkZF9tZW1vcnk6IFwiZ3JvdXBfaWRcIixcbiAgYWRkX3RyaXBsZXQ6IFwiZ3JvdXBfaWRcIixcbiAgYnVpbGRfY29tbXVuaXRpZXM6IFwiZ3JvdXBfaWRzXCIsXG4gIGdldF9lcGlzb2RlczogXCJncm91cF9pZHNcIixcbiAgZ2V0X3N0YXR1czogdW5kZWZpbmVkLFxuICBzZWFyY2hfbWVtb3J5X2ZhY3RzOiBcImdyb3VwX2lkc1wiLFxuICBzZWFyY2hfbm9kZXM6IFwiZ3JvdXBfaWRzXCIsXG4gIHN1bW1hcml6ZV9zYWdhOiBcImdyb3VwX2lkXCIsXG59IGFzIGNvbnN0O1xuY29uc3QgV1JJVEVfVE9PTFMgPSBuZXcgU2V0KFtcImFkZF9tZW1vcnlcIiwgXCJhZGRfdHJpcGxldFwiLCBcImJ1aWxkX2NvbW11bml0aWVzXCIsIFwic3VtbWFyaXplX3NhZ2FcIl0pO1xuY29uc3QgVU5TQ09QRURfQVJHVU1FTlRTID0gW1xuICBcImNlbnRlcl9ub2RlX3V1aWRcIixcbiAgXCJwcmV2aW91c19lcGlzb2RlX3V1aWRzXCIsXG4gIFwic2FnYV9wcmV2aW91c19lcGlzb2RlX3V1aWRcIixcbiAgXCJzb3VyY2Vfbm9kZV91dWlkXCIsXG4gIFwidGFyZ2V0X25vZGVfdXVpZFwiLFxuICBcInV1aWRcIixcbl0gYXMgY29uc3Q7XG5cbmludGVyZmFjZSBUb29sa2l0RW50cnkge1xuICByZWFkb25seSBfX3Rvb2xraXRSZWY6IHRydWU7XG4gIHBsdWdpbk5hbWU6IHN0cmluZztcbiAgbG9jYWxOYW1lOiBzdHJpbmc7XG4gIGRlZjoge1xuICAgIG5hbWU6IHN0cmluZztcbiAgICBkZXNjcmlwdGlvbjogc3RyaW5nO1xuICAgIHBhcmFtZXRlcnM6IHVua25vd247XG4gIH07XG4gIGFubm90YXRpb25zOiB7XG4gICAgZWZmZWN0OiBcInJlYWRcIiB8IFwid3JpdGVcIjtcbiAgICByZXF1aXJlc1VzZXJDb250ZXh0OiB0cnVlO1xuICB9O1xufVxuXG5pbnRlcmZhY2UgVXNlck1jcFNlcnZlciB7XG4gIGxhc3RVc2VkOiBudW1iZXI7XG4gIHNlcnZlcjogTUNQU2VydmVyO1xufVxuXG5leHBvcnQgY2xhc3MgR3JhcGhpdGlQbHVnaW4gZXh0ZW5kcyBQbHVnaW48R3JhcGhpdGlQbHVnaW5Db25maWc+IHtcbiAgc3RhdGljIG1hbmlmZXN0OiBQbHVnaW5NYW5pZmVzdDxcImdyYXBoaXRpXCI+ID0ge1xuICAgIG5hbWU6IFwiZ3JhcGhpdGlcIixcbiAgICBkaXNwbGF5TmFtZTogXCJHcmFwaGl0aVwiLFxuICAgIGRlc2NyaXB0aW9uOlxuICAgICAgXCJSdW5zIHRoZSBkYngtdG9vbHMgR3JhcGhpdGkgTUNQIHNpZGVjYXIgd2l0aCBMYWtlYmFzZS1iYWNrZWQgcmVjb3ZlcnkgYW5kIFwiICtcbiAgICAgIFwicHVibGlzaGVzIGl0IHRocm91Z2ggdGhlIEFwcCdzIHNpbmdsZSBwb3J0IHdpdGggQ2FkZHkuXCIsXG4gICAgc3RhYmlsaXR5OiBcImJldGFcIixcbiAgICByZXNvdXJjZXM6IHtcbiAgICAgIHJlcXVpcmVkOiBbXSxcbiAgICAgIG9wdGlvbmFsOiBbLi4uTEFLRUJBU0VfTUFOSUZFU1QucmVzb3VyY2VzLnJlcXVpcmVkXSxcbiAgICB9LFxuICAgIGNvbmZpZzogeyBzY2hlbWE6IEdSQVBISVRJX0NPTkZJR19TQ0hFTUEgfSxcbiAgfTtcblxuICBzdGF0aWMgZ2V0UmVzb3VyY2VSZXF1aXJlbWVudHMoKTogUmVzb3VyY2VSZXF1aXJlbWVudFtdIHtcbiAgICByZXR1cm4gTEFLRUJBU0VfTUFOSUZFU1QucmVzb3VyY2VzLnJlcXVpcmVkLm1hcCgocmVzb3VyY2UpID0+ICh7XG4gICAgICAuLi5yZXNvdXJjZSxcbiAgICAgIHJlcXVpcmVkOiB0cnVlLFxuICAgIH0pKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVhZG9ubHkgbG9nZ2VyID0gbG9nLmxvZ2dlcih0aGlzKTtcbiAgcHJpdmF0ZSBjb21tYW5kczogQ29tbWFuZFtdID0gW107XG4gIHByaXZhdGUgbWNwPzogTUNQQ2xpZW50O1xuICBwcml2YXRlIG1jcFNlcnZlcnMgPSBuZXcgTWFwPHN0cmluZywgVXNlck1jcFNlcnZlcj4oKTtcbiAgcHJpdmF0ZSBtY3BTZXJ2ZXJTd2VlcD86IE5vZGVKUy5UaW1lb3V0O1xuICBwcml2YXRlIG1jcFRvb2xzOiBSZWNvcmQ8c3RyaW5nLCBUb29sPiA9IHt9O1xuICBwcml2YXRlIHJlc29sdmVkPzogUmVzb2x2ZWRHcmFwaGl0aVBsdWdpbkNvbmZpZztcbiAgcHJpdmF0ZSBzZXR1cENvbXBsZXRlID0gZmFsc2U7XG4gIHByaXZhdGUgc3RhcnR1cD86IFByb21pc2U8dm9pZD47XG4gIHByaXZhdGUgc3VwZXJ2aXNpb24/OiBDb25jdXJyZW50bHlSZXN1bHQ7XG4gIHByaXZhdGUgc3RvcHBpbmcgPSBmYWxzZTtcblxuICBvdmVycmlkZSBhc3luYyBzZXR1cCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aGlzLnN0YXJ0dXAgPSB0aGlzLnN0YXJ0U2lkZWNhcnMoKS5jYXRjaCgoZXJyb3I6IHVua25vd24pID0+IHtcbiAgICAgIGlmICh0aGlzLnN0b3BwaW5nKSByZXR1cm47XG4gICAgICB0aGlzLmxvZ2dlci5lcnJvcihcImJhY2tncm91bmQgc3RhcnR1cCBmYWlsZWRcIiwgeyBlcnJvciB9KTtcbiAgICAgIHByb2Nlc3Mua2lsbChwcm9jZXNzLnBpZCwgXCJTSUdURVJNXCIpO1xuICAgIH0pO1xuICAgIHZvaWQgdGhpcy5zdGFydHVwO1xuICAgIHRoaXMubG9nZ2VyLmluZm8oXCJiYWNrZ3JvdW5kIHN0YXJ0dXAgc2NoZWR1bGVkXCIpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBzdGFydFNpZGVjYXJzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGNvbmZpZ3VyZWQgPSByZXNvbHZlR3JhcGhpdGlDb25maWcodGhpcy5jb25maWcpO1xuICAgIGNvbnN0IFtncmFwaGl0aVBvcnQsIG1vZGVsUHJveHlQb3J0LCBwcm94eVBvcnRdID0gYXdhaXQgZGlzdGluY3RQb3J0cyhcbiAgICAgIGNvcmVDb25maWcucG9ydCh1bmRlZmluZWQsIFwiREFUQUJSSUNLU19BUFBfUE9SVFwiLCA4MDAwLCBjb3JlQ29uZmlnLkVOVl9PTkxZKSxcbiAgICAgIGNvbmZpZ3VyZWQuZ3JhcGhpdGlQb3J0LFxuICAgICAgY29uZmlndXJlZC5tb2RlbFByb3h5UG9ydCxcbiAgICAgIGNvbmZpZ3VyZWQucHJveHlQb3J0LFxuICAgICk7XG4gICAgYXdhaXQgZW5zdXJlR3JhcGhpdGlQeXRob24oY29uZmlndXJlZC5weXRob24pO1xuICAgIGNvbnN0IG1vZGVsUHJveHlDb21tYW5kID0gYXdhaXQgZW5zdXJlR3JhcGhpdGlNb2RlbFByb3h5KCk7XG4gICAgdGhpcy5yZXNvbHZlZCA9IHtcbiAgICAgIC4uLmNvbmZpZ3VyZWQsXG4gICAgICBncmFwaGl0aVBvcnQsXG4gICAgICBtb2RlbFByb3h5UG9ydCxcbiAgICAgIHByb3h5UG9ydCxcbiAgICB9O1xuICAgIHRoaXMuc3VwZXJ2aXNpb24gPSBjb25jdXJyZW50bHkoXG4gICAgICBbXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiBcImdyYXBoaXRpXCIsXG4gICAgICAgICAgY29tbWFuZDogY29tbWFuZExpbmUoW3RoaXMucmVzb2x2ZWQucHl0aG9uLCBcIi1tXCIsIFwiZGJ4X3Rvb2xzLmdyYXBoaXRpXCIsIFwic3RhcnRcIl0pLFxuICAgICAgICAgIGVudjoge1xuICAgICAgICAgICAgLi4ucHJvY2Vzcy5lbnYsXG4gICAgICAgICAgICBHUkFQSElUSV9IT1NUOiBcIjEyNy4wLjAuMVwiLFxuICAgICAgICAgICAgR1JBUEhJVElfUE9SVDogU3RyaW5nKHRoaXMucmVzb2x2ZWQuZ3JhcGhpdGlQb3J0KSxcbiAgICAgICAgICAgIEpPVVJOQUxfTkFNRVNQQUNFOiB0aGlzLnJlc29sdmVkLmpvdXJuYWxOYW1lc3BhY2UsXG4gICAgICAgICAgICBNQU5BR0VfTU9ERUxfUFJPWFk6IFwidHJ1ZVwiLFxuICAgICAgICAgICAgTU9ERUxfUFJPWFlfQ09NTUFORDogbW9kZWxQcm94eUNvbW1hbmQsXG4gICAgICAgICAgICBNT0RFTF9QUk9YWV9IT1NUOiBcIjEyNy4wLjAuMVwiLFxuICAgICAgICAgICAgTU9ERUxfUFJPWFlfUE9SVDogU3RyaW5nKHRoaXMucmVzb2x2ZWQubW9kZWxQcm94eVBvcnQpLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiBcImNhZGR5XCIsXG4gICAgICAgICAgY29tbWFuZDogY29tbWFuZExpbmUoW1xuICAgICAgICAgICAgdGhpcy5yZXNvbHZlZC5weXRob24sXG4gICAgICAgICAgICBcIi1tXCIsXG4gICAgICAgICAgICBcImRieF90b29scy5ncmFwaGl0aS5wcm94eVwiLFxuICAgICAgICAgICAgXCItLXByb3h5LXBvcnRcIixcbiAgICAgICAgICAgIFN0cmluZyh0aGlzLnJlc29sdmVkLnByb3h5UG9ydCksXG4gICAgICAgICAgICBcIi0tZ3JhcGhpdGktcG9ydFwiLFxuICAgICAgICAgICAgU3RyaW5nKHRoaXMucmVzb2x2ZWQuZ3JhcGhpdGlQb3J0KSxcbiAgICAgICAgICBdKSxcbiAgICAgICAgICBlbnY6IHByb2Nlc3MuZW52LFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIHtcbiAgICAgICAga2lsbE90aGVyc09uOiBbXCJmYWlsdXJlXCIsIFwic3VjY2Vzc1wiXSxcbiAgICAgICAga2lsbFNpZ25hbDogXCJTSUdURVJNXCIsXG4gICAgICAgIGtpbGxUaW1lb3V0OiBTSURFQ0FSX1NIVVRET1dOX0dSQUNFX01TLFxuICAgICAgICBwcmVmaXg6IFwibmFtZVwiLFxuICAgICAgICBwcmVmaXhDb2xvcnM6IGZhbHNlLFxuICAgICAgfSxcbiAgICApO1xuICAgIHRoaXMuY29tbWFuZHMgPSB0aGlzLnN1cGVydmlzaW9uLmNvbW1hbmRzO1xuICAgIHRoaXMuc2V0dXBDb21wbGV0ZSA9IHRydWU7XG4gICAgdm9pZCB0aGlzLnN1cGVydmlzaW9uLnJlc3VsdC50aGVuKFxuICAgICAgKCkgPT4gdGhpcy5vblN1cGVydmlzb3JFeGl0KCksXG4gICAgICAoZXJyb3IpID0+IHRoaXMub25TdXBlcnZpc29yRXhpdChlcnJvciksXG4gICAgKTtcbiAgICB0aGlzLm1jcFNlcnZlclN3ZWVwID0gc2V0SW50ZXJ2YWwoKCkgPT4gdGhpcy5jbG9zZUlkbGVNY3BTZXJ2ZXJzKCksIE1DUF9TRVJWRVJfU1dFRVBfTVMpO1xuICAgIHRoaXMubWNwU2VydmVyU3dlZXAudW5yZWYoKTtcbiAgICB0aGlzLmxvZ2dlci5pbmZvKFwic2lkZWNhcnMgbGF1bmNoZWRcIiwge1xuICAgICAgZ3JhcGhpdGlQb3J0OiB0aGlzLnJlc29sdmVkLmdyYXBoaXRpUG9ydCxcbiAgICAgIG1vZGVsUHJveHlQb3J0OiB0aGlzLnJlc29sdmVkLm1vZGVsUHJveHlQb3J0LFxuICAgICAgcHJveHlQb3J0OiB0aGlzLnJlc29sdmVkLnByb3h5UG9ydCxcbiAgICAgIG1jcFBhdGg6IE1DUF9QQVRILFxuICAgIH0pO1xuICB9XG5cbiAgb3ZlcnJpZGUgaW5qZWN0Um91dGVzKHJvdXRlcjogSUFwcFJvdXRlcik6IHZvaWQge1xuICAgIGZvciAoY29uc3QgbWV0aG9kIG9mIFtcImdldFwiLCBcInBvc3RcIiwgXCJkZWxldGVcIl0gYXMgY29uc3QpIHtcbiAgICAgIHRoaXMucm91dGUocm91dGVyLCB7XG4gICAgICAgIG5hbWU6IGAke21ldGhvZH1NY3BgLFxuICAgICAgICBtZXRob2QsXG4gICAgICAgIHBhdGg6IFwiL21jcFwiLFxuICAgICAgICBoYW5kbGVyOiAocmVxdWVzdCwgcmVzcG9uc2UpID0+IHRoaXMuZm9yd2FyZE1jcChyZXF1ZXN0LCByZXNwb25zZSksXG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICBvdmVycmlkZSBhYm9ydEFjdGl2ZU9wZXJhdGlvbnMoKTogdm9pZCB7XG4gICAgc3VwZXIuYWJvcnRBY3RpdmVPcGVyYXRpb25zKCk7XG4gICAgdm9pZCB0aGlzLm1jcD8uZGlzY29ubmVjdCgpO1xuICB9XG5cbiAgYXN5bmMgc2h1dGRvd24oKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgYXdhaXQgdGhpcy5zdG9wU2lkZWNhcnMoKTtcbiAgfVxuXG4gIG92ZXJyaWRlIGV4cG9ydHMoKSB7XG4gICAgcmV0dXJuIHsgbWNwUGF0aDogTUNQX1BBVEggfTtcbiAgfVxuXG4gIHRvb2xraXQoKTogUmVjb3JkPHN0cmluZywgVG9vbGtpdEVudHJ5PiB7XG4gICAgcmV0dXJuIE9iamVjdC5mcm9tRW50cmllcyhcbiAgICAgIE9iamVjdC5rZXlzKFNDT1BFRF9UT09MX0ZJRUxEUykubWFwKChuYW1lKSA9PiBbXG4gICAgICAgIG5hbWUsXG4gICAgICAgIHtcbiAgICAgICAgICBfX3Rvb2xraXRSZWY6IHRydWUgYXMgY29uc3QsXG4gICAgICAgICAgcGx1Z2luTmFtZTogXCJncmFwaGl0aVwiLFxuICAgICAgICAgIGxvY2FsTmFtZTogbmFtZSxcbiAgICAgICAgICBkZWY6IHtcbiAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICBkZXNjcmlwdGlvbjogYEdyYXBoaXRpICR7bmFtZS5yZXBsYWNlQWxsKFwiX1wiLCBcIiBcIil9YCxcbiAgICAgICAgICAgIHBhcmFtZXRlcnM6IHsgdHlwZTogXCJvYmplY3RcIiwgcHJvcGVydGllczoge30gfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGFubm90YXRpb25zOiB7XG4gICAgICAgICAgICBlZmZlY3Q6IFdSSVRFX1RPT0xTLmhhcyhuYW1lKSA/IChcIndyaXRlXCIgYXMgY29uc3QpIDogKFwicmVhZFwiIGFzIGNvbnN0KSxcbiAgICAgICAgICAgIHJlcXVpcmVzVXNlckNvbnRleHQ6IHRydWUgYXMgY29uc3QsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIF0pLFxuICAgICk7XG4gIH1cblxuICBhc3luYyBleGVjdXRlQWdlbnRUb29sKFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBhcmdzOiB1bmtub3duLFxuICAgIHNpZ25hbD86IEFib3J0U2lnbmFsLFxuICAgIGNvbnRleHQ/OiB7IHJlc291cmNlSWQ/OiBzdHJpbmcgfSxcbiAgKTogUHJvbWlzZTx1bmtub3duPiB7XG4gICAgYXdhaXQgdGhpcy5lbnN1cmVNY3BUb29scygpO1xuICAgIGNvbnN0IHRvb2wgPSB0aGlzLm1jcFRvb2xzW25hbWVdO1xuICAgIGlmICghdG9vbD8uZXhlY3V0ZSkgdGhyb3cgbmV3IEVycm9yKGBVbmtub3duIEdyYXBoaXRpIHRvb2w6ICR7bmFtZX1gKTtcbiAgICBjb25zdCB1c2VySWQgPSBjb250ZXh0Py5yZXNvdXJjZUlkID8/IGV4ZWN1dGlvbkNvbnRleHRVc2VySWQoKTtcbiAgICByZXR1cm4gdG9vbC5leGVjdXRlKHNjb3BlZEFyZ3VtZW50cyhuYW1lLCBhcmdzLCB1c2VyU2NvcGUodXNlcklkKSksIHtcbiAgICAgIGFib3J0U2lnbmFsOiBzaWduYWwsXG4gICAgfSBhcyBuZXZlcik7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGZvcndhcmRNY3AocmVxdWVzdDogZXhwcmVzcy5SZXF1ZXN0LCByZXNwb25zZTogZXhwcmVzcy5SZXNwb25zZSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuZW5zdXJlTWNwVG9vbHMoKTtcbiAgICBjb25zdCB1c2VySWQgPSBhcHBraXRJZGVudGl0eS5yZXF1ZXN0VXNlcklkKHJlcXVlc3QpID8/IGV4ZWN1dGlvbkNvbnRleHRVc2VySWQoKTtcbiAgICBjb25zdCBzZXJ2ZXIgPSB0aGlzLm1jcFNlcnZlcih1c2VySWQpO1xuICAgIGF3YWl0IHNlcnZlci5zdGFydEhUVFAoe1xuICAgICAgdXJsOiBuZXcgVVJMKHJlcXVlc3Qub3JpZ2luYWxVcmwsIFwiaHR0cDovL2FwcC5sb2NhbFwiKSxcbiAgICAgIGh0dHBQYXRoOiBNQ1BfUEFUSCxcbiAgICAgIHJlcTogcmVxdWVzdCxcbiAgICAgIHJlczogcmVzcG9uc2UsXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGVuc3VyZU1jcFRvb2xzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmIChPYmplY3Qua2V5cyh0aGlzLm1jcFRvb2xzKS5sZW5ndGggPiAwKSByZXR1cm47XG4gICAgaWYgKCF0aGlzLnJlc29sdmVkKSB0aHJvdyBuZXcgRXJyb3IoXCJHcmFwaGl0aSBzaWRlY2FycyBoYXZlIG5vdCBsYXVuY2hlZFwiKTtcbiAgICB0aGlzLm1jcCA/Pz0gbmV3IE1DUENsaWVudCh7XG4gICAgICBpZDogYGFwcGtpdC1ncmFwaGl0aS0ke3RoaXMucmVzb2x2ZWQuZ3JhcGhpdGlQb3J0fWAsXG4gICAgICBzZXJ2ZXJzOiB7XG4gICAgICAgIGdyYXBoaXRpOiB7IHVybDogbmV3IFVSTChgaHR0cDovLzEyNy4wLjAuMToke3RoaXMucmVzb2x2ZWQucHJveHlQb3J0fS9tY3BgKSB9LFxuICAgICAgfSxcbiAgICB9KTtcbiAgICBjb25zdCBkaXNjb3ZlcmVkID0gYXdhaXQgdGhpcy5tY3AubGlzdFRvb2xzKCk7XG4gICAgdGhpcy5tY3BUb29scyA9IE9iamVjdC5mcm9tRW50cmllcyhcbiAgICAgIE9iamVjdC5lbnRyaWVzKGRpc2NvdmVyZWQpXG4gICAgICAgIC5tYXAoKFtuYW1lLCB0b29sXSkgPT4gW25hbWUucmVwbGFjZSgvXmdyYXBoaXRpXy8sIFwiXCIpLCB0b29sIGFzIFRvb2xdIGFzIGNvbnN0KVxuICAgICAgICAuZmlsdGVyKChbbmFtZV0pID0+IG5hbWUgaW4gU0NPUEVEX1RPT0xfRklFTERTKSxcbiAgICApO1xuICAgIGNvbnN0IG1pc3NpbmcgPSBPYmplY3Qua2V5cyhTQ09QRURfVE9PTF9GSUVMRFMpLmZpbHRlcigobmFtZSkgPT4gIXRoaXMubWNwVG9vbHNbbmFtZV0pO1xuICAgIGlmIChtaXNzaW5nLmxlbmd0aCA+IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgR3JhcGhpdGkgZGlkIG5vdCBwdWJsaXNoIHJlcXVpcmVkIHNjb3BlZCB0b29sczogJHttaXNzaW5nLmpvaW4oXCIsIFwiKX1gKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG1jcFNlcnZlcih1c2VySWQ6IHN0cmluZyk6IE1DUFNlcnZlciB7XG4gICAgY29uc3QgZXhpc3RpbmcgPSB0aGlzLm1jcFNlcnZlcnMuZ2V0KHVzZXJJZCk7XG4gICAgaWYgKGV4aXN0aW5nKSB7XG4gICAgICBleGlzdGluZy5sYXN0VXNlZCA9IERhdGUubm93KCk7XG4gICAgICByZXR1cm4gZXhpc3Rpbmcuc2VydmVyO1xuICAgIH1cbiAgICBjb25zdCBzY29wZSA9IHVzZXJTY29wZSh1c2VySWQpO1xuICAgIGNvbnN0IHRvb2xzID0gT2JqZWN0LmZyb21FbnRyaWVzKFxuICAgICAgT2JqZWN0LmVudHJpZXModGhpcy5tY3BUb29scykubWFwKChbbmFtZSwgdG9vbF0pID0+IFtcbiAgICAgICAgbmFtZSxcbiAgICAgICAgY3JlYXRlVG9vbCh7XG4gICAgICAgICAgaWQ6IG5hbWUsXG4gICAgICAgICAgZGVzY3JpcHRpb246IHRvb2wuZGVzY3JpcHRpb24gPz8gbmFtZSxcbiAgICAgICAgICAuLi4odG9vbC5pbnB1dFNjaGVtYSA/IHsgaW5wdXRTY2hlbWE6IHRvb2wuaW5wdXRTY2hlbWEgYXMgbmV2ZXIgfSA6IHt9KSxcbiAgICAgICAgICBleGVjdXRlOiAoYXJnczogdW5rbm93biwgY29udGV4dDogdW5rbm93bikgPT4ge1xuICAgICAgICAgICAgaWYgKCF0b29sLmV4ZWN1dGUpIHRocm93IG5ldyBFcnJvcihgR3JhcGhpdGkgdG9vbCBjYW5ub3QgZXhlY3V0ZTogJHtuYW1lfWApO1xuICAgICAgICAgICAgcmV0dXJuIHRvb2wuZXhlY3V0ZShzY29wZWRBcmd1bWVudHMobmFtZSwgYXJncywgc2NvcGUpLCBjb250ZXh0IGFzIG5ldmVyKTtcbiAgICAgICAgICB9LFxuICAgICAgICB9KSxcbiAgICAgIF0pLFxuICAgICk7XG4gICAgY29uc3Qgc2VydmVyID0gbmV3IE1DUFNlcnZlcih7XG4gICAgICBuYW1lOiBcIkdyYXBoaXRpXCIsXG4gICAgICB2ZXJzaW9uOiBcIjEuMC4wXCIsXG4gICAgICB0b29scyxcbiAgICB9KTtcbiAgICB0aGlzLm1jcFNlcnZlcnMuc2V0KHVzZXJJZCwgeyBsYXN0VXNlZDogRGF0ZS5ub3coKSwgc2VydmVyIH0pO1xuICAgIHJldHVybiBzZXJ2ZXI7XG4gIH1cblxuICBwcml2YXRlIG9uU3VwZXJ2aXNvckV4aXQoZXJyb3I/OiB1bmtub3duKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuc3RvcHBpbmcgfHwgIXRoaXMuc2V0dXBDb21wbGV0ZSkgcmV0dXJuO1xuICAgIHRoaXMubG9nZ2VyLmVycm9yKFwic2lkZWNhciBzdXBlcnZpc29yIGV4aXRlZFwiLCB7IGVycm9yIH0pO1xuICAgIHByb2Nlc3Mua2lsbChwcm9jZXNzLnBpZCwgXCJTSUdURVJNXCIpO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBzdG9wU2lkZWNhcnMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMuc3RvcHBpbmcpIHJldHVybjtcbiAgICB0aGlzLnN0b3BwaW5nID0gdHJ1ZTtcbiAgICBpZiAodGhpcy5tY3BTZXJ2ZXJTd2VlcCkgY2xlYXJJbnRlcnZhbCh0aGlzLm1jcFNlcnZlclN3ZWVwKTtcbiAgICB0aGlzLm1jcFNlcnZlclN3ZWVwID0gdW5kZWZpbmVkO1xuICAgIGNvbnN0IGNvbW1hbmRzID0gdGhpcy5jb21tYW5kcztcbiAgICBjb25zdCBzdXBlcnZpc2lvbiA9IHRoaXMuc3VwZXJ2aXNpb247XG4gICAgZm9yIChjb25zdCBjb21tYW5kIG9mIGNvbW1hbmRzKSBjb21tYW5kLmtpbGwoXCJTSUdURVJNXCIpO1xuICAgIGNvbnN0IGNsZWFudXAgPSBQcm9taXNlLmFsbFNldHRsZWQoW1xuICAgICAgLi4uWy4uLnRoaXMubWNwU2VydmVycy52YWx1ZXMoKV0ubWFwKCh7IHNlcnZlciB9KSA9PiBzZXJ2ZXIuY2xvc2UoKSksXG4gICAgICB0aGlzLm1jcD8uZGlzY29ubmVjdCgpLFxuICAgICAgc3VwZXJ2aXNpb24/LnJlc3VsdCxcbiAgICBdKTtcbiAgICBjb25zdCBjb21wbGV0ZWQgPSBhd2FpdCBQcm9taXNlLnJhY2UoW1xuICAgICAgY2xlYW51cC50aGVuKCgpID0+IHRydWUpLFxuICAgICAgYXN5bmNNb2R1bGUuc2xlZXAoU0lERUNBUl9TSFVURE9XTl9HUkFDRV9NUykudGhlbigoKSA9PiBmYWxzZSksXG4gICAgXSk7XG4gICAgaWYgKCFjb21wbGV0ZWQpIHtcbiAgICAgIHRoaXMubG9nZ2VyLndhcm4oXCJzaWRlY2FycyBpZ25vcmVkIFNJR1RFUk07IGVzY2FsYXRpbmcgdG8gU0lHS0lMTFwiKTtcbiAgICAgIGZvciAoY29uc3QgY29tbWFuZCBvZiBjb21tYW5kcykgY29tbWFuZC5raWxsKFwiU0lHS0lMTFwiKTtcbiAgICB9XG4gICAgdGhpcy5tY3BTZXJ2ZXJzLmNsZWFyKCk7XG4gICAgdGhpcy5tY3AgPSB1bmRlZmluZWQ7XG4gICAgdGhpcy5tY3BUb29scyA9IHt9O1xuICAgIHRoaXMuY29tbWFuZHMgPSBbXTtcbiAgICB0aGlzLnN1cGVydmlzaW9uID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuc3RhcnR1cCA9IHVuZGVmaW5lZDtcbiAgfVxuXG4gIHByaXZhdGUgY2xvc2VJZGxlTWNwU2VydmVycygpOiB2b2lkIHtcbiAgICBjb25zdCBjdXRvZmYgPSBEYXRlLm5vdygpIC0gTUNQX1NFUlZFUl9JRExFX01TO1xuICAgIGZvciAoY29uc3QgW3VzZXJJZCwgZW50cnldIG9mIHRoaXMubWNwU2VydmVycykge1xuICAgICAgaWYgKGVudHJ5Lmxhc3RVc2VkID49IGN1dG9mZikgY29udGludWU7XG4gICAgICB0aGlzLm1jcFNlcnZlcnMuZGVsZXRlKHVzZXJJZCk7XG4gICAgICB2b2lkIGVudHJ5LnNlcnZlci5jbG9zZSgpLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICB0aGlzLmxvZ2dlci53YXJuKFwiaWRsZSBNQ1Agc2VydmVyIGNsb3NlIGZhaWxlZFwiLCB7IGVycm9yIH0pO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG59XG5cbnR5cGUgRXhlY1B5dGhvbiA9IChmaWxlOiBzdHJpbmcsIGFyZ3M6IHN0cmluZ1tdKSA9PiBQcm9taXNlPHVua25vd24+O1xuXG4vKiogRW5zdXJlIERhdGFicmlja3MgQXBwcyBoYXMgdGhlIFB5dGhvbiBzaWRlY2FyIG1hdGNoaW5nIHRoaXMgTm9kZSBwYWNrYWdlLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGVuc3VyZUdyYXBoaXRpUHl0aG9uKFxuICBweXRob246IHN0cmluZyxcbiAgcnVuOiBFeGVjUHl0aG9uID0gKGZpbGUsIGFyZ3MpID0+IHByb21pc2lmeShleGVjRmlsZSkoZmlsZSwgYXJncyksXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgdHJ5IHtcbiAgICBhd2FpdCBydW4ocHl0aG9uLCBbXG4gICAgICBcIi1jXCIsXG4gICAgICBgaW1wb3J0IGltcG9ydGxpYi5tZXRhZGF0YTsgYXNzZXJ0IGltcG9ydGxpYi5tZXRhZGF0YS52ZXJzaW9uKCdkYngtdG9vbHMtZ3JhcGhpdGknKSA9PSAnJHtQQUNLQUdFX1ZFUlNJT059J2AsXG4gICAgXSk7XG4gIH0gY2F0Y2gge1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBydW4ocHl0aG9uLCBbXCItbVwiLCBcInBpcFwiLCBcIi0tdmVyc2lvblwiXSk7XG4gICAgfSBjYXRjaCB7XG4gICAgICBhd2FpdCBydW4ocHl0aG9uLCBbXG4gICAgICAgIFwiLWNcIixcbiAgICAgICAgXCJpbXBvcnQgdXJsbGliLnJlcXVlc3Q7IGV4ZWModXJsbGliLnJlcXVlc3QudXJsb3BlbignaHR0cHM6Ly9ib290c3RyYXAucHlwYS5pby9nZXQtcGlwLnB5JykucmVhZCgpKVwiLFxuICAgICAgICBcIi0tdXNlclwiLFxuICAgICAgICBcIi0tYnJlYWstc3lzdGVtLXBhY2thZ2VzXCIsXG4gICAgICBdKTtcbiAgICB9XG4gICAgYXdhaXQgcnVuKHB5dGhvbiwgW1xuICAgICAgXCItbVwiLFxuICAgICAgXCJwaXBcIixcbiAgICAgIFwiaW5zdGFsbFwiLFxuICAgICAgXCItLWRpc2FibGUtcGlwLXZlcnNpb24tY2hlY2tcIixcbiAgICAgIFwiLS11cGdyYWRlXCIsXG4gICAgICBcIi0tdXNlclwiLFxuICAgICAgXCItLWJyZWFrLXN5c3RlbS1wYWNrYWdlc1wiLFxuICAgICAgYGRieC10b29scy1ncmFwaGl0aT09JHtQQUNLQUdFX1ZFUlNJT059YCxcbiAgICBdKTtcbiAgfVxufVxuXG4vKiogSW5zdGFsbCB0aGUgbW9kZWwgcHJveHkgcmVsZWFzZSBiaW5hcnkgdXNlZCBieSB0aGUgUHl0aG9uIHNpZGVjYXIuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZW5zdXJlR3JhcGhpdGlNb2RlbFByb3h5KFxuICBpbnN0YWxsOiB0eXBlb2YgZW5zdXJlUnVzdFJlbGVhc2VCaW5hcnkgPSBlbnN1cmVSdXN0UmVsZWFzZUJpbmFyeSxcbik6IFByb21pc2U8c3RyaW5nPiB7XG4gIGNvbnN0IGluc3RhbGxlZCA9IGF3YWl0IGluc3RhbGwoTU9ERUxfUFJPWFlfUkVMRUFTRV9CSU5BUlkpO1xuICByZXR1cm4gcmVzb2x2ZVBhdGgoaW5zdGFsbGVkLnBhdGgpO1xufVxuXG5leHBvcnQgY29uc3QgZ3JhcGhpdGkgPSB0b1BsdWdpbihHcmFwaGl0aVBsdWdpbik7XG5cbmZ1bmN0aW9uIGV4ZWN1dGlvbkNvbnRleHRVc2VySWQoKTogc3RyaW5nIHtcbiAgY29uc3QgY29udGV4dCA9IGRieEFwcGtpdC50cnlHZXRFeGVjdXRpb25Db250ZXh0KCk7XG4gIGlmICghY29udGV4dCkgdGhyb3cgbmV3IEVycm9yKFwiR3JhcGhpdGkgbWVtb3J5IHJlcXVpcmVzIGFuIEFwcEtpdCBleGVjdXRpb24gY29udGV4dFwiKTtcbiAgcmV0dXJuIFwidXNlcklkXCIgaW4gY29udGV4dCA/IGNvbnRleHQudXNlcklkIDogY29udGV4dC5zZXJ2aWNlVXNlcklkO1xufVxuXG5mdW5jdGlvbiB1c2VyU2NvcGUodXNlcklkOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gYHVzZXJfJHtjcmVhdGVIYXNoKFwic2hhMjU2XCIpLnVwZGF0ZSh1c2VySWQpLmRpZ2VzdChcImJhc2U2NHVybFwiKX1gO1xufVxuXG5mdW5jdGlvbiBzY29wZWRBcmd1bWVudHMobmFtZTogc3RyaW5nLCBhcmdzOiB1bmtub3duLCBzY29wZTogc3RyaW5nKTogUmVjb3JkPHN0cmluZywgdW5rbm93bj4ge1xuICBpZiAoIShuYW1lIGluIFNDT1BFRF9UT09MX0ZJRUxEUykpIHRocm93IG5ldyBFcnJvcihgR3JhcGhpdGkgdG9vbCBpcyBub3QgdXNlci1zY29wZWQ6ICR7bmFtZX1gKTtcbiAgY29uc3Qgc2NvcGVkID0gb2JqZWN0LmlzUmVjb3JkKGFyZ3MpID8geyAuLi5hcmdzIH0gOiB7fTtcbiAgZm9yIChjb25zdCBhcmd1bWVudCBvZiBVTlNDT1BFRF9BUkdVTUVOVFMpIGRlbGV0ZSBzY29wZWRbYXJndW1lbnRdO1xuICBjb25zdCBmaWVsZCA9IFNDT1BFRF9UT09MX0ZJRUxEU1tuYW1lIGFzIGtleW9mIHR5cGVvZiBTQ09QRURfVE9PTF9GSUVMRFNdO1xuICBpZiAoZmllbGQgPT09IFwiZ3JvdXBfaWRcIikgc2NvcGVkLmdyb3VwX2lkID0gc2NvcGU7XG4gIGlmIChmaWVsZCA9PT0gXCJncm91cF9pZHNcIikgc2NvcGVkLmdyb3VwX2lkcyA9IFtzY29wZV07XG4gIHJldHVybiBzY29wZWQ7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGF2YWlsYWJsZVBvcnQoKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBjb25zdCBzZXJ2ZXIgPSBjcmVhdGVTZXJ2ZXIoKTtcbiAgICBzZXJ2ZXIub25jZShcImVycm9yXCIsIHJlamVjdCk7XG4gICAgc2VydmVyLmxpc3RlbigwLCBcIjEyNy4wLjAuMVwiLCAoKSA9PiB7XG4gICAgICBjb25zdCBhZGRyZXNzID0gc2VydmVyLmFkZHJlc3MoKTtcbiAgICAgIGlmICghYWRkcmVzcyB8fCB0eXBlb2YgYWRkcmVzcyA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICBzZXJ2ZXIuY2xvc2UoKTtcbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihcIkNvdWxkIG5vdCBhbGxvY2F0ZSBhIEdyYXBoaXRpIGxvb3BiYWNrIHBvcnRcIikpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBzZXJ2ZXIuY2xvc2UoKGVycm9yKSA9PiAoZXJyb3IgPyByZWplY3QoZXJyb3IpIDogcmVzb2x2ZShhZGRyZXNzLnBvcnQpKSk7XG4gICAgfSk7XG4gIH0pO1xufVxuXG5hc3luYyBmdW5jdGlvbiBkaXN0aW5jdFBvcnRzKFxuICBhcHBQb3J0OiBudW1iZXIsXG4gIGdyYXBoaXRpUG9ydDogbnVtYmVyLFxuICBtb2RlbFByb3h5UG9ydDogbnVtYmVyLFxuICBwcm94eVBvcnQ6IG51bWJlcixcbik6IFByb21pc2U8W251bWJlciwgbnVtYmVyLCBudW1iZXJdPiB7XG4gIGNvbnN0IHBvcnRzID0gW2FwcFBvcnRdO1xuICBmb3IgKGNvbnN0IGNvbmZpZ3VyZWRQb3J0IG9mIFtncmFwaGl0aVBvcnQsIG1vZGVsUHJveHlQb3J0LCBwcm94eVBvcnRdKSB7XG4gICAgaWYgKGNvbmZpZ3VyZWRQb3J0ICYmIHBvcnRzLmluY2x1ZGVzKGNvbmZpZ3VyZWRQb3J0KSkge1xuICAgICAgdGhyb3cgbmV3IENvbmZpZ3VyYXRpb25FcnJvcihcIkdyYXBoaXRpIHNpZGVjYXIgcG9ydHMgbXVzdCBkaWZmZXIgZnJvbSBEQVRBQlJJQ0tTX0FQUF9QT1JUXCIpO1xuICAgIH1cbiAgICBsZXQgcG9ydCA9IGNvbmZpZ3VyZWRQb3J0IHx8IChhd2FpdCBhdmFpbGFibGVQb3J0KCkpO1xuICAgIHdoaWxlIChwb3J0cy5pbmNsdWRlcyhwb3J0KSkgcG9ydCA9IGF3YWl0IGF2YWlsYWJsZVBvcnQoKTtcbiAgICBwb3J0cy5wdXNoKHBvcnQpO1xuICB9XG4gIHJldHVybiBwb3J0cy5zbGljZSgxKSBhcyBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl07XG59XG5cbmZ1bmN0aW9uIGNvbW1hbmRMaW5lKGFyZ3VtZW50c186IHN0cmluZ1tdKTogc3RyaW5nIHtcbiAgcmV0dXJuIGFyZ3VtZW50c18ubWFwKCh2YWx1ZSkgPT4gYCcke3ZhbHVlLnJlcGxhY2VBbGwoXCInXCIsIFwiJ1xcXFwnJ1wiKX0nYCkuam9pbihcIiBcIik7XG59XG4iXX0=
package/package.json CHANGED
@@ -26,9 +26,10 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "@databricks/appkit": "^0.60.0",
29
- "@dbx-tools/appkit": "0.6.186",
30
- "@dbx-tools/core": "0.6.186",
31
- "@dbx-tools/shared-core": "0.6.186",
29
+ "@dbx-tools/appkit": "0.6.191",
30
+ "@dbx-tools/cli": "0.6.191",
31
+ "@dbx-tools/core": "0.6.191",
32
+ "@dbx-tools/shared-core": "0.6.191",
32
33
  "@mastra/core": "1.47.0",
33
34
  "@mastra/mcp": "1.12.0",
34
35
  "concurrently": "^10.0.3"
@@ -47,7 +48,7 @@
47
48
  "./package.json": "./package.json"
48
49
  }
49
50
  },
50
- "version": "0.6.186",
51
+ "version": "0.6.191",
51
52
  "types": "./lib/index.d.ts",
52
53
  "type": "module",
53
54
  "exports": {
package/src/config.ts CHANGED
@@ -9,7 +9,7 @@ import type { JSONSchema7 } from "json-schema";
9
9
 
10
10
  export interface GraphitiPluginConfig extends BasePluginConfig {
11
11
  graphitiPort?: number;
12
- litellmPort?: number;
12
+ modelProxyPort?: number;
13
13
  proxyPort?: number;
14
14
  python?: string;
15
15
  journalNamespace?: string;
@@ -17,7 +17,7 @@ export interface GraphitiPluginConfig extends BasePluginConfig {
17
17
 
18
18
  export interface ResolvedGraphitiPluginConfig extends GraphitiPluginConfig {
19
19
  graphitiPort: number;
20
- litellmPort: number;
20
+ modelProxyPort: number;
21
21
  proxyPort: number;
22
22
  python: string;
23
23
  journalNamespace: string;
@@ -27,7 +27,7 @@ export const GRAPHITI_CONFIG_SCHEMA = {
27
27
  type: "object",
28
28
  properties: {
29
29
  graphitiPort: { type: "integer", minimum: 1, maximum: 65535 },
30
- litellmPort: { type: "integer", minimum: 1, maximum: 65535 },
30
+ modelProxyPort: { type: "integer", minimum: 1, maximum: 65535 },
31
31
  proxyPort: { type: "integer", minimum: 1, maximum: 65535 },
32
32
  python: { type: "string" },
33
33
  journalNamespace: { type: "string" },
@@ -45,9 +45,14 @@ export function resolveGraphitiConfig(
45
45
  0,
46
46
  coreConfig.ENV_ONLY,
47
47
  );
48
- const litellmPort = coreConfig.port(config.litellmPort, "LITELLM_PORT", 0, coreConfig.ENV_ONLY);
48
+ const modelProxyPort = coreConfig.port(
49
+ config.modelProxyPort,
50
+ "MODEL_PROXY_PORT",
51
+ 0,
52
+ coreConfig.ENV_ONLY,
53
+ );
49
54
  const proxyPort = coreConfig.port(config.proxyPort, "PROXY_PORT", 0, coreConfig.ENV_ONLY);
50
- const configuredPorts = [graphitiPort, litellmPort, proxyPort].filter(Boolean);
55
+ const configuredPorts = [graphitiPort, modelProxyPort, proxyPort].filter(Boolean);
51
56
  if (new Set(configuredPorts).size !== configuredPorts.length) {
52
57
  throw new ConfigurationError("Graphiti sidecar ports must be distinct");
53
58
  }
@@ -61,7 +66,7 @@ export function resolveGraphitiConfig(
61
66
  "default";
62
67
  return {
63
68
  graphitiPort,
64
- litellmPort,
69
+ modelProxyPort,
65
70
  proxyPort,
66
71
  python,
67
72
  journalNamespace,
package/src/plugin.ts CHANGED
@@ -7,6 +7,7 @@ import { execFile } from "node:child_process";
7
7
  import { createHash } from "node:crypto";
8
8
  import { createRequire } from "node:module";
9
9
  import { createServer } from "node:net";
10
+ import { resolve as resolvePath } from "node:path";
10
11
  import { promisify } from "node:util";
11
12
  import {
12
13
  ConfigurationError,
@@ -22,6 +23,7 @@ import {
22
23
  identity as appkitIdentity,
23
24
  plugin as appkitPlugin,
24
25
  } from "@dbx-tools/appkit";
26
+ import { ensureRustReleaseBinary, rustReleaseBinaryCommand } from "@dbx-tools/cli/rust-binary";
25
27
  import { config as coreConfig } from "@dbx-tools/core";
26
28
  import { async as asyncModule, log, object } from "@dbx-tools/shared-core";
27
29
  import { createTool, type Tool } from "@mastra/core/tools";
@@ -36,6 +38,7 @@ import {
36
38
  } from "./config.ts";
37
39
 
38
40
  const LAKEBASE_MANIFEST = appkitPlugin.data(lakebase).plugin.manifest;
41
+ const MODEL_PROXY_RELEASE_BINARY = rustReleaseBinaryCommand("model-proxy");
39
42
  const PACKAGE_VERSION = (
40
43
  createRequire(import.meta.url)("@dbx-tools/appkit-graphiti/package.json") as { version: string }
41
44
  ).version;
@@ -129,17 +132,18 @@ export class GraphitiPlugin extends Plugin<GraphitiPluginConfig> {
129
132
 
130
133
  private async startSidecars(): Promise<void> {
131
134
  const configured = resolveGraphitiConfig(this.config);
132
- const [graphitiPort, litellmPort, proxyPort] = await distinctPorts(
135
+ const [graphitiPort, modelProxyPort, proxyPort] = await distinctPorts(
133
136
  coreConfig.port(undefined, "DATABRICKS_APP_PORT", 8000, coreConfig.ENV_ONLY),
134
137
  configured.graphitiPort,
135
- configured.litellmPort,
138
+ configured.modelProxyPort,
136
139
  configured.proxyPort,
137
140
  );
138
141
  await ensureGraphitiPython(configured.python);
142
+ const modelProxyCommand = await ensureGraphitiModelProxy();
139
143
  this.resolved = {
140
144
  ...configured,
141
145
  graphitiPort,
142
- litellmPort,
146
+ modelProxyPort,
143
147
  proxyPort,
144
148
  };
145
149
  this.supervision = concurrently(
@@ -152,9 +156,10 @@ export class GraphitiPlugin extends Plugin<GraphitiPluginConfig> {
152
156
  GRAPHITI_HOST: "127.0.0.1",
153
157
  GRAPHITI_PORT: String(this.resolved.graphitiPort),
154
158
  JOURNAL_NAMESPACE: this.resolved.journalNamespace,
155
- LITELLM_HOST: "127.0.0.1",
156
- LITELLM_PORT: String(this.resolved.litellmPort),
157
- MANAGE_LITELLM: "true",
159
+ MANAGE_MODEL_PROXY: "true",
160
+ MODEL_PROXY_COMMAND: modelProxyCommand,
161
+ MODEL_PROXY_HOST: "127.0.0.1",
162
+ MODEL_PROXY_PORT: String(this.resolved.modelProxyPort),
158
163
  },
159
164
  },
160
165
  {
@@ -189,7 +194,7 @@ export class GraphitiPlugin extends Plugin<GraphitiPluginConfig> {
189
194
  this.mcpServerSweep.unref();
190
195
  this.logger.info("sidecars launched", {
191
196
  graphitiPort: this.resolved.graphitiPort,
192
- litellmPort: this.resolved.litellmPort,
197
+ modelProxyPort: this.resolved.modelProxyPort,
193
198
  proxyPort: this.resolved.proxyPort,
194
199
  mcpPath: MCP_PATH,
195
200
  });
@@ -402,6 +407,14 @@ export async function ensureGraphitiPython(
402
407
  }
403
408
  }
404
409
 
410
+ /** Install the model proxy release binary used by the Python sidecar. */
411
+ export async function ensureGraphitiModelProxy(
412
+ install: typeof ensureRustReleaseBinary = ensureRustReleaseBinary,
413
+ ): Promise<string> {
414
+ const installed = await install(MODEL_PROXY_RELEASE_BINARY);
415
+ return resolvePath(installed.path);
416
+ }
417
+
405
418
  export const graphiti = toPlugin(GraphitiPlugin);
406
419
 
407
420
  function executionContextUserId(): string {
@@ -443,11 +456,11 @@ async function availablePort(): Promise<number> {
443
456
  async function distinctPorts(
444
457
  appPort: number,
445
458
  graphitiPort: number,
446
- litellmPort: number,
459
+ modelProxyPort: number,
447
460
  proxyPort: number,
448
461
  ): Promise<[number, number, number]> {
449
462
  const ports = [appPort];
450
- for (const configuredPort of [graphitiPort, litellmPort, proxyPort]) {
463
+ for (const configuredPort of [graphitiPort, modelProxyPort, proxyPort]) {
451
464
  if (configuredPort && ports.includes(configuredPort)) {
452
465
  throw new ConfigurationError("Graphiti sidecar ports must differ from DATABRICKS_APP_PORT");
453
466
  }