@dbx-tools/appkit-graphiti 0.6.114 → 0.6.115

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/src/plugin.js CHANGED
@@ -1,16 +1,41 @@
1
1
  /**
2
- * AppKit plugin that supervises Graphiti and a Caddy single-port proxy.
2
+ * AppKit plugin that supervises Graphiti and republishes user-scoped MCP tools.
3
3
  *
4
4
  * @module
5
5
  */
6
+ import { createHash } from "node:crypto";
6
7
  import { createServer } from "node:net";
7
- import { Plugin, lakebase, toPlugin, } from "@databricks/appkit";
8
- import { interceptor as appkitInterceptor, plugin as appkitPlugin } from "@dbx-tools/appkit";
9
- import { exec } from "@dbx-tools/core";
10
- import { async as asyncModule, log } from "@dbx-tools/shared-core";
11
- import { MCPClient } from "@mastra/mcp";
8
+ import { ConfigurationError, Plugin, lakebase, toPlugin, } from "@databricks/appkit";
9
+ import { appkit as dbxAppkit, identity as appkitIdentity, plugin as appkitPlugin, } from "@dbx-tools/appkit";
10
+ import { config as coreConfig } from "@dbx-tools/core";
11
+ import { async as asyncModule, log, object } from "@dbx-tools/shared-core";
12
+ import { createTool } from "@mastra/core/tools";
13
+ import { MCPClient, MCPServer } from "@mastra/mcp";
14
+ import concurrently from "concurrently";
12
15
  import { GRAPHITI_CONFIG_SCHEMA, resolveGraphitiConfig, } from "./config.js";
13
16
  const LAKEBASE_MANIFEST = appkitPlugin.data(lakebase).plugin.manifest;
17
+ const MCP_PATH = "/api/graphiti/mcp";
18
+ const MCP_SERVER_IDLE_MS = 30 * 60 * 1000;
19
+ const MCP_SERVER_SWEEP_MS = 5 * 60 * 1000;
20
+ const SCOPED_TOOL_FIELDS = {
21
+ add_memory: "group_id",
22
+ add_triplet: "group_id",
23
+ build_communities: "group_ids",
24
+ get_episodes: "group_ids",
25
+ get_status: undefined,
26
+ search_memory_facts: "group_ids",
27
+ search_nodes: "group_ids",
28
+ summarize_saga: "group_id",
29
+ };
30
+ const WRITE_TOOLS = new Set(["add_memory", "add_triplet", "build_communities", "summarize_saga"]);
31
+ const UNSCOPED_ARGUMENTS = [
32
+ "center_node_uuid",
33
+ "previous_episode_uuids",
34
+ "saga_previous_episode_uuid",
35
+ "source_node_uuid",
36
+ "target_node_uuid",
37
+ "uuid",
38
+ ];
14
39
  export class GraphitiPlugin extends Plugin {
15
40
  static manifest = {
16
41
  name: "graphiti",
@@ -31,114 +56,130 @@ export class GraphitiPlugin extends Plugin {
31
56
  }));
32
57
  }
33
58
  logger = log.logger(this);
34
- children = [];
59
+ commands = [];
35
60
  mcp;
61
+ mcpServers = new Map();
62
+ mcpServerSweep;
36
63
  mcpTools = {};
37
64
  resolved;
65
+ setupComplete = false;
66
+ supervision;
38
67
  stopping = false;
39
68
  async setup() {
40
69
  const configured = resolveGraphitiConfig(this.config);
41
- const graphitiPort = configured.graphitiPort || (await availablePort());
42
- let litellmPort = configured.litellmPort || (await availablePort());
43
- while (litellmPort === graphitiPort)
44
- litellmPort = await availablePort();
70
+ const [graphitiPort, litellmPort, proxyPort] = await distinctPorts(coreConfig.port(undefined, "DATABRICKS_APP_PORT", 8000, coreConfig.ENV_ONLY), configured.graphitiPort, configured.litellmPort, configured.proxyPort);
45
71
  this.resolved = {
46
72
  ...configured,
47
73
  graphitiPort,
48
74
  litellmPort,
75
+ proxyPort,
49
76
  };
50
- if (!process.env.LAKEBASE_ENDPOINT && !process.env.PGHOST) {
51
- throw new Error("Graphiti requires Lakebase; register lakebase() before graphiti() and bind its Postgres resource");
52
- }
53
- for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"]) {
54
- process.once(signal, () => this.stopGraphiti());
55
- }
56
- const supervisor = appkitInterceptor.createInterceptorContext({});
57
- supervisor.context.onTeardown(() => this.stopGraphiti());
58
- const graphiti = exec.spawn(this.resolved.python, ["-m", "dbx_tools.graphiti", "start"], {
59
- env: {
60
- ...process.env,
61
- GRAPHITI_HOST: "127.0.0.1",
62
- GRAPHITI_PORT: String(this.resolved.graphitiPort),
63
- JOURNAL_NAMESPACE: this.resolved.journalNamespace,
64
- LITELLM_HOST: "127.0.0.1",
65
- LITELLM_PORT: String(this.resolved.litellmPort),
66
- MANAGE_LITELLM: "true",
77
+ this.supervision = concurrently([
78
+ {
79
+ name: "graphiti",
80
+ command: commandLine([this.resolved.python, "-m", "dbx_tools.graphiti", "start"]),
81
+ env: {
82
+ ...process.env,
83
+ GRAPHITI_HOST: "127.0.0.1",
84
+ GRAPHITI_PORT: String(this.resolved.graphitiPort),
85
+ JOURNAL_NAMESPACE: this.resolved.journalNamespace,
86
+ LITELLM_HOST: "127.0.0.1",
87
+ LITELLM_PORT: String(this.resolved.litellmPort),
88
+ MANAGE_LITELLM: "true",
89
+ },
90
+ },
91
+ {
92
+ name: "caddy",
93
+ command: commandLine([
94
+ this.resolved.python,
95
+ "-m",
96
+ "dbx_tools.graphiti.proxy",
97
+ "--proxy-port",
98
+ String(this.resolved.proxyPort),
99
+ "--graphiti-port",
100
+ String(this.resolved.graphitiPort),
101
+ ]),
102
+ env: process.env,
67
103
  },
68
- stdin: "ignore",
69
- stdout: "inherit",
70
- stderr: "inherit",
71
- });
72
- const caddy = exec.spawn(this.resolved.python, [
73
- "-m",
74
- "dbx_tools.graphiti.proxy",
75
- "--public-port",
76
- String(this.resolved.publicPort),
77
- "--app-port",
78
- String(this.resolved.appPort),
79
- "--graphiti-port",
80
- String(this.resolved.graphitiPort),
81
- "--route-prefix",
82
- this.resolved.routePrefix,
83
104
  ], {
84
- env: process.env,
85
- stdin: "ignore",
86
- stdout: "inherit",
87
- stderr: "inherit",
105
+ killOthersOn: ["failure", "success"],
106
+ killSignal: "SIGTERM",
107
+ killTimeout: 12_000,
108
+ prefix: "name",
109
+ prefixColors: false,
88
110
  });
89
- this.children = [graphiti, caddy];
90
- for (const child of this.children)
91
- supervisor.context.bindProcess(child);
92
- await waitForGraphiti(this.resolved.graphitiPort);
93
- this.mcp = new MCPClient({
94
- id: `appkit-graphiti-${this.resolved.graphitiPort}`,
95
- servers: {
96
- graphiti: {
97
- url: new URL(`http://127.0.0.1:${this.resolved.graphitiPort}/mcp`),
98
- },
99
- },
111
+ this.commands = this.supervision.commands;
112
+ void this.supervision.result.then(() => this.onSupervisorExit(), (error) => this.onSupervisorExit(error));
113
+ const supervisionFailure = this.supervision.result.then(() => {
114
+ throw new Error("Graphiti sidecar supervisor exited during startup");
115
+ }, (error) => {
116
+ throw error;
100
117
  });
101
- const discovered = await this.mcp.listTools();
102
- this.mcpTools = Object.fromEntries(Object.entries(discovered).map(([name, tool]) => [
103
- name.replace(/^graphiti_/, ""),
104
- tool,
105
- ]));
118
+ try {
119
+ await Promise.race([
120
+ (async () => {
121
+ await waitForGraphiti(graphitiPort);
122
+ await waitForGraphiti(proxyPort);
123
+ })(),
124
+ supervisionFailure,
125
+ ]);
126
+ this.mcp = new MCPClient({
127
+ id: `appkit-graphiti-${this.resolved.graphitiPort}`,
128
+ servers: {
129
+ graphiti: {
130
+ url: new URL(`http://127.0.0.1:${this.resolved.proxyPort}/mcp`),
131
+ },
132
+ },
133
+ });
134
+ const discovered = await this.mcp.listTools();
135
+ this.mcpTools = Object.fromEntries(Object.entries(discovered)
136
+ .map(([name, tool]) => [name.replace(/^graphiti_/, ""), tool])
137
+ .filter(([name]) => name in SCOPED_TOOL_FIELDS));
138
+ const missing = Object.keys(SCOPED_TOOL_FIELDS).filter((name) => !this.mcpTools[name]);
139
+ if (missing.length > 0) {
140
+ throw new Error(`Graphiti did not publish required scoped tools: ${missing.join(", ")}`);
141
+ }
142
+ }
143
+ catch (error) {
144
+ await this.stopSidecars();
145
+ throw error;
146
+ }
147
+ this.setupComplete = true;
148
+ this.mcpServerSweep = setInterval(() => this.closeIdleMcpServers(), MCP_SERVER_SWEEP_MS);
149
+ this.mcpServerSweep.unref();
106
150
  this.logger.info("ready", {
107
- appPort: this.resolved.appPort,
108
151
  graphitiPort: this.resolved.graphitiPort,
109
152
  litellmPort: this.resolved.litellmPort,
110
- publicPort: this.resolved.publicPort,
111
- mcpPath: `${this.resolved.routePrefix}/mcp/`,
153
+ proxyPort: this.resolved.proxyPort,
154
+ mcpPath: MCP_PATH,
112
155
  tools: Object.keys(this.mcpTools),
113
156
  });
114
157
  }
158
+ injectRoutes(router) {
159
+ for (const method of ["get", "post", "delete"]) {
160
+ this.route(router, {
161
+ name: `${method}Mcp`,
162
+ method,
163
+ path: "/mcp",
164
+ handler: (request, response) => this.forwardMcp(request, response),
165
+ });
166
+ }
167
+ }
115
168
  abortActiveOperations() {
116
169
  super.abortActiveOperations();
117
- this.stopGraphiti();
118
170
  void this.mcp?.disconnect();
119
- this.mcp = undefined;
120
- this.mcpTools = {};
121
- for (const child of this.children) {
122
- if (!child.killed)
123
- child.kill("SIGTERM");
124
- }
125
- this.children = [];
171
+ }
172
+ async shutdown() {
173
+ await this.stopSidecars();
126
174
  }
127
175
  exports() {
128
- const resolved = this.resolved ?? resolveGraphitiConfig(this.config);
129
- return {
130
- appPort: resolved.appPort,
131
- graphitiPort: resolved.graphitiPort,
132
- litellmPort: resolved.litellmPort,
133
- mcpPath: `${resolved.routePrefix}/mcp/`,
134
- publicPort: resolved.publicPort,
135
- routePrefix: resolved.routePrefix,
136
- };
176
+ return { mcpPath: MCP_PATH };
137
177
  }
138
178
  toolkit() {
139
179
  return Object.fromEntries(Object.entries(this.mcpTools).map(([name, tool]) => [
140
180
  name,
141
181
  {
182
+ __toolkitRef: true,
142
183
  pluginName: "graphiti",
143
184
  localName: name,
144
185
  def: {
@@ -146,28 +187,124 @@ export class GraphitiPlugin extends Plugin {
146
187
  description: tool.description,
147
188
  parameters: tool.inputSchema ?? { type: "object", properties: {} },
148
189
  },
190
+ annotations: {
191
+ effect: WRITE_TOOLS.has(name) ? "write" : "read",
192
+ requiresUserContext: true,
193
+ },
149
194
  },
150
195
  ]));
151
196
  }
152
- async executeAgentTool(name, args, signal) {
197
+ async executeAgentTool(name, args, signal, context) {
153
198
  const tool = this.mcpTools[name];
154
199
  if (!tool?.execute)
155
200
  throw new Error(`Unknown Graphiti tool: ${name}`);
156
- return tool.execute(args, { abortSignal: signal });
201
+ const userId = context?.resourceId ?? executionContextUserId();
202
+ return tool.execute(scopedArguments(name, args, userScope(userId)), {
203
+ abortSignal: signal,
204
+ });
157
205
  }
158
- stopGraphiti() {
159
- if (this.stopping || !this.resolved)
206
+ async forwardMcp(request, response) {
207
+ if (!this.resolved) {
208
+ response.status(503).json({ error: "Graphiti is not ready" });
160
209
  return;
161
- this.stopping = true;
162
- void exec.spawn(this.resolved.python, ["-m", "dbx_tools.graphiti", "down"], {
163
- env: process.env,
164
- stdin: "ignore",
165
- stdout: "inherit",
166
- stderr: "inherit",
210
+ }
211
+ const userId = appkitIdentity.requestUserId(request) ?? executionContextUserId();
212
+ const server = this.mcpServer(userId);
213
+ await server.startHTTP({
214
+ url: new URL(request.originalUrl, "http://app.local"),
215
+ httpPath: MCP_PATH,
216
+ req: request,
217
+ res: response,
218
+ });
219
+ }
220
+ mcpServer(userId) {
221
+ const existing = this.mcpServers.get(userId);
222
+ if (existing) {
223
+ existing.lastUsed = Date.now();
224
+ return existing.server;
225
+ }
226
+ const scope = userScope(userId);
227
+ const tools = Object.fromEntries(Object.entries(this.mcpTools).map(([name, tool]) => [
228
+ name,
229
+ createTool({
230
+ id: name,
231
+ description: tool.description ?? name,
232
+ ...(tool.inputSchema ? { inputSchema: tool.inputSchema } : {}),
233
+ execute: (args, context) => {
234
+ if (!tool.execute)
235
+ throw new Error(`Graphiti tool cannot execute: ${name}`);
236
+ return tool.execute(scopedArguments(name, args, scope), context);
237
+ },
238
+ }),
239
+ ]));
240
+ const server = new MCPServer({
241
+ name: "Graphiti",
242
+ version: "1.0.0",
243
+ tools,
167
244
  });
245
+ this.mcpServers.set(userId, { lastUsed: Date.now(), server });
246
+ return server;
247
+ }
248
+ onSupervisorExit(error) {
249
+ if (this.stopping || !this.setupComplete)
250
+ return;
251
+ this.logger.error("sidecar supervisor exited", { error });
252
+ process.kill(process.pid, "SIGTERM");
253
+ }
254
+ async stopSidecars() {
255
+ if (this.stopping)
256
+ return;
257
+ this.stopping = true;
258
+ if (this.mcpServerSweep)
259
+ clearInterval(this.mcpServerSweep);
260
+ this.mcpServerSweep = undefined;
261
+ await Promise.allSettled([...this.mcpServers.values()].map(({ server }) => server.close()));
262
+ this.mcpServers.clear();
263
+ await this.mcp?.disconnect();
264
+ this.mcp = undefined;
265
+ this.mcpTools = {};
266
+ for (const command of this.commands)
267
+ command.kill("SIGTERM");
268
+ if (this.supervision)
269
+ await this.supervision.result.catch(() => undefined);
270
+ this.commands = [];
271
+ this.supervision = undefined;
272
+ }
273
+ closeIdleMcpServers() {
274
+ const cutoff = Date.now() - MCP_SERVER_IDLE_MS;
275
+ for (const [userId, entry] of this.mcpServers) {
276
+ if (entry.lastUsed >= cutoff)
277
+ continue;
278
+ this.mcpServers.delete(userId);
279
+ void entry.server.close().catch((error) => {
280
+ this.logger.warn("idle MCP server close failed", { error });
281
+ });
282
+ }
168
283
  }
169
284
  }
170
285
  export const graphiti = toPlugin(GraphitiPlugin);
286
+ function executionContextUserId() {
287
+ const context = dbxAppkit.tryGetExecutionContext();
288
+ if (!context)
289
+ throw new Error("Graphiti memory requires an AppKit execution context");
290
+ return "userId" in context ? context.userId : context.serviceUserId;
291
+ }
292
+ function userScope(userId) {
293
+ return `user_${createHash("sha256").update(userId).digest("base64url")}`;
294
+ }
295
+ function scopedArguments(name, args, scope) {
296
+ if (!(name in SCOPED_TOOL_FIELDS))
297
+ throw new Error(`Graphiti tool is not user-scoped: ${name}`);
298
+ const scoped = object.isRecord(args) ? { ...args } : {};
299
+ for (const argument of UNSCOPED_ARGUMENTS)
300
+ delete scoped[argument];
301
+ const field = SCOPED_TOOL_FIELDS[name];
302
+ if (field === "group_id")
303
+ scoped.group_id = scope;
304
+ if (field === "group_ids")
305
+ scoped.group_ids = [scope];
306
+ return scoped;
307
+ }
171
308
  async function waitForGraphiti(port) {
172
309
  for await (const ready of asyncModule.poll(async ({ signal }) => {
173
310
  try {
@@ -201,4 +338,20 @@ async function availablePort() {
201
338
  });
202
339
  });
203
340
  }
204
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3BsdWdpbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBQ0gsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLFVBQVUsQ0FBQztBQUN4QyxPQUFPLEVBQ0wsTUFBTSxFQUNOLFFBQVEsRUFDUixRQUFRLEdBR1QsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBQUUsV0FBVyxJQUFJLGlCQUFpQixFQUFFLE1BQU0sSUFBSSxZQUFZLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUM3RixPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDdkMsT0FBTyxFQUFFLEtBQUssSUFBSSxXQUFXLEVBQUUsR0FBRyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFFbkUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUN4QyxPQUFPLEVBQ0wsc0JBQXNCLEVBQ3RCLHFCQUFxQixHQUd0QixNQUFNLGFBQWEsQ0FBQztBQUVyQixNQUFNLGlCQUFpQixHQUFHLFlBQVksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQztBQVl0RSxNQUFNLE9BQU8sY0FBZSxTQUFRLE1BQTRCO0lBQzlELE1BQU0sQ0FBQyxRQUFRLEdBQStCO1FBQzVDLElBQUksRUFBRSxVQUFVO1FBQ2hCLFdBQVcsRUFBRSxVQUFVO1FBQ3ZCLFdBQVcsRUFDVCw0RUFBNEU7WUFDNUUsd0RBQXdEO1FBQzFELFNBQVMsRUFBRSxNQUFNO1FBQ2pCLFNBQVMsRUFBRTtZQUNULFFBQVEsRUFBRSxFQUFFO1lBQ1osUUFBUSxFQUFFLENBQUMsR0FBRyxpQkFBaUIsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDO1NBQ3BEO1FBQ0QsTUFBTSxFQUFFLEVBQUUsTUFBTSxFQUFFLHNCQUFzQixFQUFFO0tBQzNDLENBQUM7SUFFRixNQUFNLENB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SSxDQUFDLE9BQU8sRUFBRSxNQUFNLENBQUMsQ0FBQztRQUM3QixNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxXQUFXLEVBQUUsR0FBRyxFQUFFO1lBQ2pDLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNqQyxJQUFJLENBQUMsT0FBTyxJQUFJLE9BQU8sT0FBTyxLQUFLLFFBQVEsRUFBRSxDQUFDO2dCQUM1QyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ2YsTUFBTSxDQUFDLElBQUksS0FBSyxDQUFDLDZDQUE2QyxDQUFDLENBQUMsQ0FBQztnQkFDakUsT0FBTztZQUNULENBQUM7WUFDRCxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMzRSxDQUFDLENBQUMsQ0FBQztJQUNMLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQXBwS2l0IHBsdWdpbiB0aGF0IHN1cGVydmlzZXMgR3JhcGhpdGkgYW5kIGEgQ2FkZHkgc2luZ2xlLXBvcnQgcHJveHkuXG4gKlxuICogQG1vZHVsZVxuICovXG5pbXBvcnQgeyBjcmVhdGVTZXJ2ZXIgfSBmcm9tIFwibm9kZTpuZXRcIjtcbmltcG9ydCB7XG4gIFBsdWdpbixcbiAgbGFrZWJhc2UsXG4gIHRvUGx1Z2luLFxuICB0eXBlIFBsdWdpbk1hbmlmZXN0LFxuICB0eXBlIFJlc291cmNlUmVxdWlyZW1lbnQsXG59IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbmltcG9ydCB7IGludGVyY2VwdG9yIGFzIGFwcGtpdEludGVyY2VwdG9yLCBwbHVnaW4gYXMgYXBwa2l0UGx1Z2luIH0gZnJvbSBcIkBkYngtdG9vbHMvYXBwa2l0XCI7XG5pbXBvcnQgeyBleGVjIH0gZnJvbSBcIkBkYngtdG9vbHMvY29yZVwiO1xuaW1wb3J0IHsgYXN5bmMgYXMgYXN5bmNNb2R1bGUsIGxvZyB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5pbXBvcnQgdHlwZSB7IFRvb2wgfSBmcm9tIFwiQG1hc3RyYS9jb3JlL3Rvb2xzXCI7XG5pbXBvcnQgeyBNQ1BDbGllbnQgfSBmcm9tIFwiQG1hc3RyYS9tY3BcIjtcbmltcG9ydCB7XG4gIEdSQVBISVRJX0NPTkZJR19TQ0hFTUEsXG4gIHJlc29sdmVHcmFwaGl0aUNvbmZpZyxcbiAgdHlwZSBHcmFwaGl0aVBsdWdpbkNvbmZpZyxcbiAgdHlwZSBSZXNvbHZlZEdyYXBoaXRpUGx1Z2luQ29uZmlnLFxufSBmcm9tIFwiLi9jb25maWcudHNcIjtcblxuY29uc3QgTEFLRUJBU0VfTUFOSUZFU1QgPSBhcHBraXRQbHVnaW4uZGF0YShsYWtlYmFzZSkucGx1Z2luLm1hbmlmZXN0O1xuXG5pbnRlcmZhY2UgVG9vbGtpdEVudHJ5IHtcbiAgcGx1Z2luTmFtZTogc3RyaW5nO1xuICBsb2NhbE5hbWU6IHN0cmluZztcbiAgZGVmOiB7XG4gICAgbmFtZTogc3RyaW5nO1xuICAgIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG4gICAgcGFyYW1ldGVyczogdW5rbm93bjtcbiAgfTtcbn1cblxuZXhwb3J0IGNsYXNzIEdyYXBoaXRpUGx1Z2luIGV4dGVuZHMgUGx1Z2luPEdyYXBoaXRpUGx1Z2luQ29uZmlnPiB7XG4gIHN0YXRpYyBtYW5pZmVzdDogUGx1Z2luTWFuaWZlc3Q8XCJncmFwaGl0aVwiPiA9IHtcbiAgICBuYW1lOiBcImdyYXBoaXRpXCIsXG4gICAgZGlzcGxheU5hbWU6IFwiR3JhcGhpdGlcIixcbiAgICBkZXNjcmlwdGlvbjpcbiAgICAgIFwiUnVucyB0aGUgZGJ4LXRvb2xzIEdyYXBoaXRpIE1DUCBzaWRlY2FyIHdpdGggTGFrZWJhc2UtYmFja2VkIHJlY292ZXJ5IGFuZCBcIiArXG4gICAgICBcInB1Ymxpc2hlcyBpdCB0aHJvdWdoIHRoZSBBcHAncyBzaW5nbGUgcG9ydCB3aXRoIENhZGR5LlwiLFxuICAgIHN0YWJpbGl0eTogXCJiZXRhXCIsXG4gICAgcmVzb3VyY2VzOiB7XG4gICAgICByZXF1aXJlZDogW10sXG4gICAgICBvcHRpb25hbDogWy4uLkxBS0VCQVNFX01BTklGRVNULnJlc291cmNlcy5yZXF1aXJlZF0sXG4gICAgfSxcbiAgICBjb25maWc6IHsgc2NoZW1hOiBHUkFQSElUSV9DT05GSUdfU0NIRU1BIH0sXG4gIH07XG5cbiAgc3RhdGljIGdldFJlc291cmNlUmVxdWlyZW1lbnRzKCk6IFJlc291cmNlUmVxdWlyZW1lbnRbXSB7XG4gICAgcmV0dXJuIExBS0VCQVNFX01BTklGRVNULnJlc291cmNlcy5yZXF1aXJlZC5tYXAoKHJlc291cmNlKSA9PiAoe1xuICAgICAgLi4ucmVzb3VyY2UsXG4gICAgICByZXF1aXJlZDogdHJ1ZSxcbiAgICB9KSk7XG4gIH1cblxuICBwcml2YXRlIHJlYWRvbmx5IGxvZ2dlciA9IGxvZy5sb2dnZXIodGhpcyk7XG4gIHByaXZhdGUgY2hpbGRyZW46IFJldHVyblR5cGU8dHlwZW9mIGV4ZWMuc3Bhd24+W10gPSBbXTtcbiAgcHJpdmF0ZSBtY3A/OiBNQ1BDbGllbnQ7XG4gIHByaXZhdGUgbWNwVG9vbHM6IFJlY29yZDxzdHJpbmcsIFRvb2w+ID0ge307XG4gIHByaXZhdGUgcmVzb2x2ZWQ/OiBSZXNvbHZlZEdyYXBoaXRpUGx1Z2luQ29uZmlnO1xuICBwcml2YXRlIHN0b3BwaW5nID0gZmFsc2U7XG5cbiAgb3ZlcnJpZGUgYXN5bmMgc2V0dXAoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgY29uZmlndXJlZCA9IHJlc29sdmVHcmFwaGl0aUNvbmZpZyh0aGlzLmNvbmZpZyk7XG4gICAgY29uc3QgZ3JhcGhpdGlQb3J0ID0gY29uZmlndXJlZC5ncmFwaGl0aVBvcnQgfHwgKGF3YWl0IGF2YWlsYWJsZVBvcnQoKSk7XG4gICAgbGV0IGxpdGVsbG1Qb3J0ID0gY29uZmlndXJlZC5saXRlbGxtUG9ydCB8fCAoYXdhaXQgYXZhaWxhYmxlUG9ydCgpKTtcbiAgICB3aGlsZSAobGl0ZWxsbVBvcnQgPT09IGdyYXBoaXRpUG9ydCkgbGl0ZWxsbVBvcnQgPSBhd2FpdCBhdmFpbGFibGVQb3J0KCk7XG4gICAgdGhpcy5yZXNvbHZlZCA9IHtcbiAgICAgIC4uLmNvbmZpZ3VyZWQsXG4gICAgICBncmFwaGl0aVBvcnQsXG4gICAgICBsaXRlbGxtUG9ydCxcbiAgICB9O1xuICAgIGlmICghcHJvY2Vzcy5lbnYuTEFLRUJBU0VfRU5EUE9JTlQgJiYgIXByb2Nlc3MuZW52LlBHSE9TVCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICBcIkdyYXBoaXRpIHJlcXVpcmVzIExha2ViYXNlOyByZWdpc3RlciBsYWtlYmFzZSgpIGJlZm9yZSBncmFwaGl0aSgpIGFuZCBiaW5kIGl0cyBQb3N0Z3JlcyByZXNvdXJjZVwiLFxuICAgICAgKTtcbiAgICB9XG4gICAgZm9yIChjb25zdCBzaWduYWwgb2YgW1wiU0lHSU5UXCIsIFwiU0lHVEVSTVwiLCBcIlNJR0hVUFwiXSBhcyBjb25zdCkge1xuICAgICAgcHJvY2Vzcy5vbmNlKHNpZ25hbCwgKCkgPT4gdGhpcy5zdG9wR3JhcGhpdGkoKSk7XG4gICAgfVxuICAgIGNvbnN0IHN1cGVydmlzb3IgPSBhcHBraXRJbnRlcmNlcHRvci5jcmVhdGVJbnRlcmNlcHRvckNvbnRleHQoe30pO1xuICAgIHN1cGVydmlzb3IuY29udGV4dC5vblRlYXJkb3duKCgpID0+IHRoaXMuc3RvcEdyYXBoaXRpKCkpO1xuICAgIGNvbnN0IGdyYXBoaXRpID0gZXhlYy5zcGF3bih0aGlzLnJlc29sdmVkLnB5dGhvbiwgW1wiLW1cIiwgXCJkYnhfdG9vbHMuZ3JhcGhpdGlcIiwgXCJzdGFydFwiXSwge1xuICAgICAgZW52OiB7XG4gICAgICAgIC4uLnByb2Nlc3MuZW52LFxuICAgICAgICBHUkFQSElUSV9IT1NUOiBcIjEyNy4wLjAuMVwiLFxuICAgICAgICBHUkFQSElUSV9QT1JUOiBTdHJpbmcodGhpcy5yZXNvbHZlZC5ncmFwaGl0aVBvcnQpLFxuICAgICAgICBKT1VSTkFMX05BTUVTUEFDRTogdGhpcy5yZXNvbHZlZC5qb3VybmFsTmFtZXNwYWNlLFxuICAgICAgICBMSVRFTExNX0hPU1Q6IFwiMTI3LjAuMC4xXCIsXG4gICAgICAgIExJVEVMTE1fUE9SVDogU3RyaW5nKHRoaXMucmVzb2x2ZWQubGl0ZWxsbVBvcnQpLFxuICAgICAgICBNQU5BR0VfTElURUxMTTogXCJ0cnVlXCIsXG4gICAgICB9LFxuICAgICAgc3RkaW46IFwiaWdub3JlXCIsXG4gICAgICBzdGRvdXQ6IFwiaW5oZXJpdFwiLFxuICAgICAgc3RkZXJyOiBcImluaGVyaXRcIixcbiAgICB9KTtcbiAgICBjb25zdCBjYWRkeSA9IGV4ZWMuc3Bhd24oXG4gICAgICB0aGlzLnJlc29sdmVkLnB5dGhvbixcbiAgICAgIFtcbiAgICAgICAgXCItbVwiLFxuICAgICAgICBcImRieF90b29scy5ncmFwaGl0aS5wcm94eVwiLFxuICAgICAgICBcIi0tcHVibGljLXBvcnRcIixcbiAgICAgICAgU3RyaW5nKHRoaXMucmVzb2x2ZWQucHVibGljUG9ydCksXG4gICAgICAgIFwiLS1hcHAtcG9ydFwiLFxuICAgICAgICBTdHJpbmcodGhpcy5yZXNvbHZlZC5hcHBQb3J0KSxcbiAgICAgICAgXCItLWdyYXBoaXRpLXBvcnRcIixcbiAgICAgICAgU3RyaW5nKHRoaXMucmVzb2x2ZWQuZ3JhcGhpdGlQb3J0KSxcbiAgICAgICAgXCItLXJvdXRlLXByZWZpeFwiLFxuICAgICAgICB0aGlzLnJlc29sdmVkLnJvdXRlUHJlZml4LFxuICAgICAgXSxcbiAgICAgIHtcbiAgICAgICAgZW52OiBwcm9jZXNzLmVudixcbiAgICAgICAgc3RkaW46IFwiaWdub3JlXCIsXG4gICAgICAgIHN0ZG91dDogXCJpbmhlcml0XCIsXG4gICAgICAgIHN0ZGVycjogXCJpbmhlcml0XCIsXG4gICAgICB9LFxuICAgICk7XG4gICAgdGhpcy5jaGlsZHJlbiA9IFtncmFwaGl0aSwgY2FkZHldO1xuICAgIGZvciAoY29uc3QgY2hpbGQgb2YgdGhpcy5jaGlsZHJlbikgc3VwZXJ2aXNvci5jb250ZXh0LmJpbmRQcm9jZXNzKGNoaWxkKTtcbiAgICBhd2FpdCB3YWl0Rm9yR3JhcGhpdGkodGhpcy5yZXNvbHZlZC5ncmFwaGl0aVBvcnQpO1xuICAgIHRoaXMubWNwID0gbmV3IE1DUENsaWVudCh7XG4gICAgICBpZDogYGFwcGtpdC1ncmFwaGl0aS0ke3RoaXMucmVzb2x2ZWQuZ3JhcGhpdGlQb3J0fWAsXG4gICAgICBzZXJ2ZXJzOiB7XG4gICAgICAgIGdyYXBoaXRpOiB7XG4gICAgICAgICAgdXJsOiBuZXcgVVJMKGBodHRwOi8vMTI3LjAuMC4xOiR7dGhpcy5yZXNvbHZlZC5ncmFwaGl0aVBvcnR9L21jcGApLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9KTtcbiAgICBjb25zdCBkaXNjb3ZlcmVkID0gYXdhaXQgdGhpcy5tY3AubGlzdFRvb2xzKCk7XG4gICAgdGhpcy5tY3BUb29scyA9IE9iamVjdC5mcm9tRW50cmllcyhcbiAgICAgIE9iamVjdC5lbnRyaWVzKGRpc2NvdmVyZWQpLm1hcCgoW25hbWUsIHRvb2xdKSA9PiBbXG4gICAgICAgIG5hbWUucmVwbGFjZSgvXmdyYXBoaXRpXy8sIFwiXCIpLFxuICAgICAgICB0b29sIGFzIFRvb2wsXG4gICAgICBdKSxcbiAgICApO1xuICAgIHRoaXMubG9nZ2VyLmluZm8oXCJyZWFkeVwiLCB7XG4gICAgICBhcHBQb3J0OiB0aGlzLnJlc29sdmVkLmFwcFBvcnQsXG4gICAgICBncmFwaGl0aVBvcnQ6IHRoaXMucmVzb2x2ZWQuZ3JhcGhpdGlQb3J0LFxuICAgICAgbGl0ZWxsbVBvcnQ6IHRoaXMucmVzb2x2ZWQubGl0ZWxsbVBvcnQsXG4gICAgICBwdWJsaWNQb3J0OiB0aGlzLnJlc29sdmVkLnB1YmxpY1BvcnQsXG4gICAgICBtY3BQYXRoOiBgJHt0aGlzLnJlc29sdmVkLnJvdXRlUHJlZml4fS9tY3AvYCxcbiAgICAgIHRvb2xzOiBPYmplY3Qua2V5cyh0aGlzLm1jcFRvb2xzKSxcbiAgICB9KTtcbiAgfVxuXG4gIG92ZXJyaWRlIGFib3J0QWN0aXZlT3BlcmF0aW9ucygpOiB2b2lkIHtcbiAgICBzdXBlci5hYm9ydEFjdGl2ZU9wZXJhdGlvbnMoKTtcbiAgICB0aGlzLnN0b3BHcmFwaGl0aSgpO1xuICAgIHZvaWQgdGhpcy5tY3A/LmRpc2Nvbm5lY3QoKTtcbiAgICB0aGlzLm1jcCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLm1jcFRvb2xzID0ge307XG4gICAgZm9yIChjb25zdCBjaGlsZCBvZiB0aGlzLmNoaWxkcmVuKSB7XG4gICAgICBpZiAoIWNoaWxkLmtpbGxlZCkgY2hpbGQua2lsbChcIlNJR1RFUk1cIik7XG4gICAgfVxuICAgIHRoaXMuY2hpbGRyZW4gPSBbXTtcbiAgfVxuXG4gIG92ZXJyaWRlIGV4cG9ydHMoKSB7XG4gICAgY29uc3QgcmVzb2x2ZWQgPSB0aGlzLnJlc29sdmVkID8/IHJlc29sdmVHcmFwaGl0aUNvbmZpZyh0aGlzLmNvbmZpZyk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGFwcFBvcnQ6IHJlc29sdmVkLmFwcFBvcnQsXG4gICAgICBncmFwaGl0aVBvcnQ6IHJlc29sdmVkLmdyYXBoaXRpUG9ydCxcbiAgICAgIGxpdGVsbG1Qb3J0OiByZXNvbHZlZC5saXRlbGxtUG9ydCxcbiAgICAgIG1jcFBhdGg6IGAke3Jlc29sdmVkLnJvdXRlUHJlZml4fS9tY3AvYCxcbiAgICAgIHB1YmxpY1BvcnQ6IHJlc29sdmVkLnB1YmxpY1BvcnQsXG4gICAgICByb3V0ZVByZWZpeDogcmVzb2x2ZWQucm91dGVQcmVmaXgsXG4gICAgfTtcbiAgfVxuXG4gIHRvb2xraXQoKTogUmVjb3JkPHN0cmluZywgVG9vbGtpdEVudHJ5PiB7XG4gICAgcmV0dXJuIE9iamVjdC5mcm9tRW50cmllcyhcbiAgICAgIE9iamVjdC5lbnRyaWVzKHRoaXMubWNwVG9vbHMpLm1hcCgoW25hbWUsIHRvb2xdKSA9PiBbXG4gICAgICAgIG5hbWUsXG4gICAgICAgIHtcbiAgICAgICAgICBwbHVnaW5OYW1lOiBcImdyYXBoaXRpXCIsXG4gICAgICAgICAgbG9jYWxOYW1lOiBuYW1lLFxuICAgICAgICAgIGRlZjoge1xuICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgIGRlc2NyaXB0aW9uOiB0b29sLmRlc2NyaXB0aW9uLFxuICAgICAgICAgICAgcGFyYW1ldGVyczogdG9vbC5pbnB1dFNjaGVtYSA/PyB7IHR5cGU6IFwib2JqZWN0XCIsIHByb3BlcnRpZXM6IHt9IH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIF0pLFxuICAgICk7XG4gIH1cblxuICBhc3luYyBleGVjdXRlQWdlbnRUb29sKG5hbWU6IHN0cmluZywgYXJnczogdW5rbm93biwgc2lnbmFsPzogQWJvcnRTaWduYWwpOiBQcm9taXNlPHVua25vd24+IHtcbiAgICBjb25zdCB0b29sID0gdGhpcy5tY3BUb29sc1tuYW1lXTtcbiAgICBpZiAoIXRvb2w/LmV4ZWN1dGUpIHRocm93IG5ldyBFcnJvcihgVW5rbm93biBHcmFwaGl0aSB0b29sOiAke25hbWV9YCk7XG4gICAgcmV0dXJuIHRvb2wuZXhlY3V0ZShhcmdzLCB7IGFib3J0U2lnbmFsOiBzaWduYWwgfSBhcyBuZXZlcik7XG4gIH1cblxuICBwcml2YXRlIHN0b3BHcmFwaGl0aSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zdG9wcGluZyB8fCAhdGhpcy5yZXNvbHZlZCkgcmV0dXJuO1xuICAgIHRoaXMuc3RvcHBpbmcgPSB0cnVlO1xuICAgIHZvaWQgZXhlYy5zcGF3bih0aGlzLnJlc29sdmVkLnB5dGhvbiwgW1wiLW1cIiwgXCJkYnhfdG9vbHMuZ3JhcGhpdGlcIiwgXCJkb3duXCJdLCB7XG4gICAgICBlbnY6IHByb2Nlc3MuZW52LFxuICAgICAgc3RkaW46IFwiaWdub3JlXCIsXG4gICAgICBzdGRvdXQ6IFwiaW5oZXJpdFwiLFxuICAgICAgc3RkZXJyOiBcImluaGVyaXRcIixcbiAgICB9KTtcbiAgfVxufVxuXG5leHBvcnQgY29uc3QgZ3JhcGhpdGkgPSB0b1BsdWdpbihHcmFwaGl0aVBsdWdpbik7XG5cbmFzeW5jIGZ1bmN0aW9uIHdhaXRGb3JHcmFwaGl0aShwb3J0OiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgZm9yIGF3YWl0IChjb25zdCByZWFkeSBvZiBhc3luY01vZHVsZS5wb2xsKFxuICAgIGFzeW5jICh7IHNpZ25hbCB9KSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKGBodHRwOi8vMTI3LjAuMC4xOiR7cG9ydH0vaGVhbHRoYCwgeyBzaWduYWwgfSk7XG4gICAgICAgIHJldHVybiByZXNwb25zZS5vaztcbiAgICAgIH0gY2F0Y2gge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfSxcbiAgICB7XG4gICAgICBpbnRlcnZhbE1zOiAyNTAsXG4gICAgICB0aW1lb3V0TXM6IDYwXzAwMCxcbiAgICAgIHByZWRpY2F0ZTogKHJlYWR5KSA9PiAhcmVhZHksXG4gICAgfSxcbiAgKSkge1xuICAgIGlmIChyZWFkeSkgcmV0dXJuO1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGF2YWlsYWJsZVBvcnQoKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBjb25zdCBzZXJ2ZXIgPSBjcmVhdGVTZXJ2ZXIoKTtcbiAgICBzZXJ2ZXIub25jZShcImVycm9yXCIsIHJlamVjdCk7XG4gICAgc2VydmVyLmxpc3RlbigwLCBcIjEyNy4wLjAuMVwiLCAoKSA9PiB7XG4gICAgICBjb25zdCBhZGRyZXNzID0gc2VydmVyLmFkZHJlc3MoKTtcbiAgICAgIGlmICghYWRkcmVzcyB8fCB0eXBlb2YgYWRkcmVzcyA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICBzZXJ2ZXIuY2xvc2UoKTtcbiAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihcIkNvdWxkIG5vdCBhbGxvY2F0ZSBhIEdyYXBoaXRpIGxvb3BiYWNrIHBvcnRcIikpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBzZXJ2ZXIuY2xvc2UoKGVycm9yKSA9PiAoZXJyb3IgPyByZWplY3QoZXJyb3IpIDogcmVzb2x2ZShhZGRyZXNzLnBvcnQpKSk7XG4gICAgfSk7XG4gIH0pO1xufVxuIl19
341
+ async function distinctPorts(appPort, graphitiPort, litellmPort, proxyPort) {
342
+ const ports = [appPort];
343
+ for (const configuredPort of [graphitiPort, litellmPort, proxyPort]) {
344
+ if (configuredPort && ports.includes(configuredPort)) {
345
+ throw new ConfigurationError("Graphiti sidecar ports must differ from DATABRICKS_APP_PORT");
346
+ }
347
+ let port = configuredPort || (await availablePort());
348
+ while (ports.includes(port))
349
+ port = await availablePort();
350
+ ports.push(port);
351
+ }
352
+ return ports.slice(1);
353
+ }
354
+ function commandLine(arguments_) {
355
+ return arguments_.map((value) => `'${value.replaceAll("'", "'\\''")}'`).join(" ");
356
+ }
357
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3BsdWdpbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBQ0gsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUN6QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBQ3hDLE9BQU8sRUFDTCxrQkFBa0IsRUFDbEIsTUFBTSxFQUNOLFFBQVEsRUFDUixRQUFRLEdBSVQsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBQ0wsTUFBTSxJQUFJLFNBQVMsRUFDbkIsUUFBUSxJQUFJLGNBQWMsRUFDMUIsTUFBTSxJQUFJLFlBQVksR0FDdkIsTUFBTSxtQkFBbUIsQ0FBQztBQUMzQixPQUFPLEVBQUUsTUFBTSxJQUFJLFVBQVUsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxLQUFLLElBQUksV0FBVyxFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUMzRSxPQUFPLEVBQUUsVUFBVSxFQUFhLE1BQU0sb0JBQW9CLENBQUM7QUFDM0QsT0FBTyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDbkQsT0FBTyxZQUF1RCxNQUFNLGNBQWMsQ0FBQztBQUVuRixPQUFPLEVBQ0wsc0JBQXNCLEVBQ3RCLHFCQUFxQixHQUd0QixNQUFNLGFBQWEsQ0FBQztBQUVyQixNQUFNLGlCQUFpQixHQUFHLFlBQVksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQztBQUN0RSxNQUFNLFFBQVEsR0FBRyxtQkFBbUIsQ0FBQztBQUNyQyxNQUFNLGtCQUFrQixHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFDO0FBQzFDLE1BQU0sbUJBQW1CLEdBQUcsQ0FBQyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUM7QUFD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Y2VzQ29udGVudCI6WyIvKipcbiAqIEFwcEtpdCBwbHVnaW4gdGhhdCBzdXBlcnZpc2VzIEdyYXBoaXRpIGFuZCByZXB1Ymxpc2hlcyB1c2VyLXNjb3BlZCBNQ1AgdG9vbHMuXG4gKlxuICogQG1vZHVsZVxuICovXG5pbXBvcnQgeyBjcmVhdGVIYXNoIH0gZnJvbSBcIm5vZGU6Y3J5cHRvXCI7XG5pbXBvcnQgeyBjcmVhdGVTZXJ2ZXIgfSBmcm9tIFwibm9kZTpuZXRcIjtcbmltcG9ydCB7XG4gIENvbmZpZ3VyYXRpb25FcnJvcixcbiAgUGx1Z2luLFxuICBsYWtlYmFzZSxcbiAgdG9QbHVnaW4sXG4gIHR5cGUgSUFwcFJvdXRlcixcbiAgdHlwZSBQbHVnaW5NYW5pZmVzdCxcbiAgdHlwZSBSZXNvdXJjZVJlcXVpcmVtZW50LFxufSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0XCI7XG5pbXBvcnQge1xuICBhcHBraXQgYXMgZGJ4QXBwa2l0LFxuICBpZGVudGl0eSBhcyBhcHBraXRJZGVudGl0eSxcbiAgcGx1Z2luIGFzIGFwcGtpdFBsdWdpbixcbn0gZnJvbSBcIkBkYngtdG9vbHMvYXBwa2l0XCI7XG5pbXBvcnQgeyBjb25maWcgYXMgY29yZUNvbmZpZyB9IGZyb20gXCJAZGJ4LXRvb2xzL2NvcmVcIjtcbmltcG9ydCB7IGFzeW5jIGFzIGFzeW5jTW9kdWxlLCBsb2csIG9iamVjdCB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5pbXBvcnQgeyBjcmVhdGVUb29sLCB0eXBlIFRvb2wgfSBmcm9tIFwiQG1hc3RyYS9jb3JlL3Rvb2xzXCI7XG5pbXBvcnQgeyBNQ1BDbGllbnQsIE1DUFNlcnZlciB9IGZyb20gXCJAbWFzdHJhL21jcFwiO1xuaW1wb3J0IGNvbmN1cnJlbnRseSwgeyB0eXBlIENvbW1hbmQsIHR5cGUgQ29uY3VycmVudGx5UmVzdWx0IH0gZnJvbSBcImNvbmN1cnJlbnRseVwiO1xuaW1wb3J0IHR5cGUgZXhwcmVzcyBmcm9tIFwiZXhwcmVzc1wiO1xuaW1wb3J0IHtcbiAgR1JBUEhJVElfQ09ORklHX1NDSEVNQSxcbiAgcmVzb2x2ZUdyYXBoaXRpQ29uZmlnLFxuICB0eXBlIEdyYXBoaXRpUGx1Z2luQ29uZmlnLFxuICB0eXBlIFJlc29sdmVkR3JhcGhpdGlQbHVnaW5Db25maWcsXG59IGZyb20gXCIuL2NvbmZpZy50c1wiO1xuXG5jb25zdCBMQUtFQkFTRV9NQU5JRkVTVCA9IGFwcGtpdFBsdWdpbi5kYXRhKGxha2ViYXNlKS5wbHVnaW4ubWFuaWZlc3Q7XG5jb25zdCBNQ1BfUEFUSCA9IFwiL2FwaS9ncmFwaGl0aS9tY3BcIjtcbmNvbnN0IE1DUF9TRVJWRVJfSURMRV9NUyA9IDMwICogNjAgKiAxMDAwO1xuY29uc3QgTUNQX1NFUlZFUl9TV0VFUF9NUyA9IDUgKiA2MCAqIDEwMDA7XG5jb25zdCBTQ09QRURfVE9PTF9GSUVMRFMgPSB7XG4gIGFkZF9tZW1vcnk6IFwiZ3JvdXBfaWRcIixcbiAgYWRkX3RyaXBsZXQ6IFwiZ3JvdXBfaWRcIixcbiAgYnVpbGRfY29tbXVuaXRpZXM6IFwiZ3JvdXBfaWRzXCIsXG4gIGdldF9lcGlzb2RlczogXCJncm91cF9pZHNcIixcbiAgZ2V0X3N0YXR1czogdW5kZWZpbmVkLFxuICBzZWFyY2hfbWVtb3J5X2ZhY3RzOiBcImdyb3VwX2lkc1wiLFxuICBzZWFyY2hfbm9kZXM6IFwiZ3JvdXBfaWRzXCIsXG4gIHN1bW1hcml6ZV9zYWdhOiBcImdyb3VwX2lkXCIsXG59IGFzIGNvbnN0O1xuY29uc3QgV1JJVEVfVE9PTFMgPSBuZXcgU2V0KFtcImFkZF9tZW1vcnlcIiwgXCJhZGRfdHJpcGxldFwiLCBcImJ1aWxkX2NvbW11bml0aWVzXCIsIFwic3VtbWFyaXplX3NhZ2FcIl0pO1xuY29uc3QgVU5TQ09QRURfQVJHVU1FTlRTID0gW1xuICBcImNlbnRlcl9ub2RlX3V1aWRcIixcbiAgXCJwcmV2aW91c19lcGlzb2RlX3V1aWRzXCIsXG4gIFwic2FnYV9wcmV2aW91c19lcGlzb2RlX3V1aWRcIixcbiAgXCJzb3VyY2Vfbm9kZV91dWlkXCIsXG4gIFwidGFyZ2V0X25vZGVfdXVpZFwiLFxuICBcInV1aWRcIixcbl0gYXMgY29uc3Q7XG5cbmludGVyZmFjZSBUb29sa2l0RW50cnkge1xuICByZWFkb25seSBfX3Rvb2xraXRSZWY6IHRydWU7XG4gIHBsdWdpbk5hbWU6IHN0cmluZztcbiAgbG9jYWxOYW1lOiBzdHJpbmc7XG4gIGRlZjoge1xuICAgIG5hbWU6IHN0cmluZztcbiAgICBkZXNjcmlwdGlvbjogc3RyaW5nO1xuICAgIHBhcmFtZXRlcnM6IHVua25vd247XG4gIH07XG4gIGFubm90YXRpb25zOiB7XG4gICAgZWZmZWN0OiBcInJlYWRcIiB8IFwid3JpdGVcIjtcbiAgICByZXF1aXJlc1VzZXJDb250ZXh0OiB0cnVlO1xuICB9O1xufVxuXG5pbnRlcmZhY2UgVXNlck1jcFNlcnZlciB7XG4gIGxhc3RVc2VkOiBudW1iZXI7XG4gIHNlcnZlcjogTUNQU2VydmVyO1xufVxuXG5leHBvcnQgY2xhc3MgR3JhcGhpdGlQbHVnaW4gZXh0ZW5kcyBQbHVnaW48R3JhcGhpdGlQbHVnaW5Db25maWc+IHtcbiAgc3RhdGljIG1hbmlmZXN0OiBQbHVnaW5NYW5pZmVzdDxcImdyYXBoaXRpXCI+ID0ge1xuICAgIG5hbWU6IFwiZ3JhcGhpdGlcIixcbiAgICBkaXNwbGF5TmFtZTogXCJHcmFwaGl0aVwiLFxuICAgIGRlc2NyaXB0aW9uOlxuICAgICAgXCJSdW5zIHRoZSBkYngtdG9vbHMgR3JhcGhpdGkgTUNQIHNpZGVjYXIgd2l0aCBMYWtlYmFzZS1iYWNrZWQgcmVjb3ZlcnkgYW5kIFwiICtcbiAgICAgIFwicHVibGlzaGVzIGl0IHRocm91Z2ggdGhlIEFwcCdzIHNpbmdsZSBwb3J0IHdpdGggQ2FkZHkuXCIsXG4gICAgc3RhYmlsaXR5OiBcImJldGFcIixcbiAgICByZXNvdXJjZXM6IHtcbiAgICAgIHJlcXVpcmVkOiBbXSxcbiAgICAgIG9wdGlvbmFsOiBbLi4uTEFLRUJBU0VfTUFOSUZFU1QucmVzb3VyY2VzLnJlcXVpcmVkXSxcbiAgICB9LFxuICAgIGNvbmZpZzogeyBzY2hlbWE6IEdSQVBISVRJX0NPTkZJR19TQ0hFTUEgfSxcbiAgfTtcblxuICBzdGF0aWMgZ2V0UmVzb3VyY2VSZXF1aXJlbWVudHMoKTogUmVzb3VyY2VSZXF1aXJlbWVudFtdIHtcbiAgICByZXR1cm4gTEFLRUJBU0VfTUFOSUZFU1QucmVzb3VyY2VzLnJlcXVpcmVkLm1hcCgocmVzb3VyY2UpID0+ICh7XG4gICAgICAuLi5yZXNvdXJjZSxcbiAgICAgIHJlcXVpcmVkOiB0cnVlLFxuICAgIH0pKTtcbiAgfVxuXG4gIHByaXZhdGUgcmVhZG9ubHkgbG9nZ2VyID0gbG9nLmxvZ2dlcih0aGlzKTtcbiAgcHJpdmF0ZSBjb21tYW5kczogQ29tbWFuZFtdID0gW107XG4gIHByaXZhdGUgbWNwPzogTUNQQ2xpZW50O1xuICBwcml2YXRlIG1jcFNlcnZlcnMgPSBuZXcgTWFwPHN0cmluZywgVXNlck1jcFNlcnZlcj4oKTtcbiAgcHJpdmF0ZSBtY3BTZXJ2ZXJTd2VlcD86IE5vZGVKUy5UaW1lb3V0O1xuICBwcml2YXRlIG1jcFRvb2xzOiBSZWNvcmQ8c3RyaW5nLCBUb29sPiA9IHt9O1xuICBwcml2YXRlIHJlc29sdmVkPzogUmVzb2x2ZWRHcmFwaGl0aVBsdWdpbkNvbmZpZztcbiAgcHJpdmF0ZSBzZXR1cENvbXBsZXRlID0gZmFsc2U7XG4gIHByaXZhdGUgc3VwZXJ2aXNpb24/OiBDb25jdXJyZW50bHlSZXN1bHQ7XG4gIHByaXZhdGUgc3RvcHBpbmcgPSBmYWxzZTtcblxuICBvdmVycmlkZSBhc3luYyBzZXR1cCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBjb25maWd1cmVkID0gcmVzb2x2ZUdyYXBoaXRpQ29uZmlnKHRoaXMuY29uZmlnKTtcbiAgICBjb25zdCBbZ3JhcGhpdGlQb3J0LCBsaXRlbGxtUG9ydCwgcHJveHlQb3J0XSA9IGF3YWl0IGRpc3RpbmN0UG9ydHMoXG4gICAgICBjb3JlQ29uZmlnLnBvcnQodW5kZWZpbmVkLCBcIkRBVEFCUklDS1NfQVBQX1BPUlRcIiwgODAwMCwgY29yZUNvbmZpZy5FTlZfT05MWSksXG4gICAgICBjb25maWd1cmVkLmdyYXBoaXRpUG9ydCxcbiAgICAgIGNvbmZpZ3VyZWQubGl0ZWxsbVBvcnQsXG4gICAgICBjb25maWd1cmVkLnByb3h5UG9ydCxcbiAgICApO1xuICAgIHRoaXMucmVzb2x2ZWQgPSB7XG4gICAgICAuLi5jb25maWd1cmVkLFxuICAgICAgZ3JhcGhpdGlQb3J0LFxuICAgICAgbGl0ZWxsbVBvcnQsXG4gICAgICBwcm94eVBvcnQsXG4gICAgfTtcbiAgICB0aGlzLnN1cGVydmlzaW9uID0gY29uY3VycmVudGx5KFxuICAgICAgW1xuICAgICAgICB7XG4gICAgICAgICAgbmFtZTogXCJncmFwaGl0aVwiLFxuICAgICAgICAgIGNvbW1hbmQ6IGNvbW1hbmRMaW5lKFt0aGlzLnJlc29sdmVkLnB5dGhvbiwgXCItbVwiLCBcImRieF90b29scy5ncmFwaGl0aVwiLCBcInN0YXJ0XCJdKSxcbiAgICAgICAgICBlbnY6IHtcbiAgICAgICAgICAgIC4uLnByb2Nlc3MuZW52LFxuICAgICAgICAgICAgR1JBUEhJVElfSE9TVDogXCIxMjcuMC4wLjFcIixcbiAgICAgICAgICAgIEdSQVBISVRJX1BPUlQ6IFN0cmluZyh0aGlzLnJlc29sdmVkLmdyYXBoaXRpUG9ydCksXG4gICAgICAgICAgICBKT1VSTkFMX05BTUVTUEFDRTogdGhpcy5yZXNvbHZlZC5qb3VybmFsTmFtZXNwYWNlLFxuICAgICAgICAgICAgTElURUxMTV9IT1NUOiBcIjEyNy4wLjAuMVwiLFxuICAgICAgICAgICAgTElURUxMTV9QT1JUOiBTdHJpbmcodGhpcy5yZXNvbHZlZC5saXRlbGxtUG9ydCksXG4gICAgICAgICAgICBNQU5BR0VfTElURUxMTTogXCJ0cnVlXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwiY2FkZHlcIixcbiAgICAgICAgICBjb21tYW5kOiBjb21tYW5kTGluZShbXG4gICAgICAgICAgICB0aGlzLnJlc29sdmVkLnB5dGhvbixcbiAgICAgICAgICAgIFwiLW1cIixcbiAgICAgICAgICAgIFwiZGJ4X3Rvb2xzLmdyYXBoaXRpLnByb3h5XCIsXG4gICAgICAgICAgICBcIi0tcHJveHktcG9ydFwiLFxuICAgICAgICAgICAgU3RyaW5nKHRoaXMucmVzb2x2ZWQucHJveHlQb3J0KSxcbiAgICAgICAgICAgIFwiLS1ncmFwaGl0aS1wb3J0XCIsXG4gICAgICAgICAgICBTdHJpbmcodGhpcy5yZXNvbHZlZC5ncmFwaGl0aVBvcnQpLFxuICAgICAgICAgIF0pLFxuICAgICAgICAgIGVudjogcHJvY2Vzcy5lbnYsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAge1xuICAgICAgICBraWxsT3RoZXJzT246IFtcImZhaWx1cmVcIiwgXCJzdWNjZXNzXCJdLFxuICAgICAgICBraWxsU2lnbmFsOiBcIlNJR1RFUk1cIixcbiAgICAgICAga2lsbFRpbWVvdXQ6IDEyXzAwMCxcbiAgICAgICAgcHJlZml4OiBcIm5hbWVcIixcbiAgICAgICAgcHJlZml4Q29sb3JzOiBmYWxzZSxcbiAgICAgIH0sXG4gICAgKTtcbiAgICB0aGlzLmNvbW1hbmRzID0gdGhpcy5zdXBlcnZpc2lvbi5jb21tYW5kcztcbiAgICB2b2lkIHRoaXMuc3VwZXJ2aXNpb24ucmVzdWx0LnRoZW4oXG4gICAgICAoKSA9PiB0aGlzLm9uU3VwZXJ2aXNvckV4aXQoKSxcbiAgICAgIChlcnJvcikgPT4gdGhpcy5vblN1cGVydmlzb3JFeGl0KGVycm9yKSxcbiAgICApO1xuICAgIGNvbnN0IHN1cGVydmlzaW9uRmFpbHVyZSA9IHRoaXMuc3VwZXJ2aXNpb24ucmVzdWx0LnRoZW4oXG4gICAgICAoKSA9PiB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIkdyYXBoaXRpIHNpZGVjYXIgc3VwZXJ2aXNvciBleGl0ZWQgZHVyaW5nIHN0YXJ0dXBcIik7XG4gICAgICB9LFxuICAgICAgKGVycm9yKSA9PiB7XG4gICAgICAgIHRocm93IGVycm9yO1xuICAgICAgfSxcbiAgICApO1xuICAgIHRyeSB7XG4gICAgICBhd2FpdCBQcm9taXNlLnJhY2UoW1xuICAgICAgICAoYXN5bmMgKCkgPT4ge1xuICAgICAgICAgIGF3YWl0IHdhaXRGb3JHcmFwaGl0aShncmFwaGl0aVBvcnQpO1xuICAgICAgICAgIGF3YWl0IHdhaXRGb3JHcmFwaGl0aShwcm94eVBvcnQpO1xuICAgICAgICB9KSgpLFxuICAgICAgICBzdXBlcnZpc2lvbkZhaWx1cmUsXG4gICAgICBdKTtcbiAgICAgIHRoaXMubWNwID0gbmV3IE1DUENsaWVudCh7XG4gICAgICAgIGlkOiBgYXBwa2l0LWdyYXBoaXRpLSR7dGhpcy5yZXNvbHZlZC5ncmFwaGl0aVBvcnR9YCxcbiAgICAgICAgc2VydmVyczoge1xuICAgICAgICAgIGdyYXBoaXRpOiB7XG4gICAgICAgICAgICB1cmw6IG5ldyBVUkwoYGh0dHA6Ly8xMjcuMC4wLjE6JHt0aGlzLnJlc29sdmVkLnByb3h5UG9ydH0vbWNwYCksXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICAgICAgY29uc3QgZGlzY292ZXJlZCA9IGF3YWl0IHRoaXMubWNwLmxpc3RUb29scygpO1xuICAgICAgdGhpcy5tY3BUb29scyA9IE9iamVjdC5mcm9tRW50cmllcyhcbiAgICAgICAgT2JqZWN0LmVudHJpZXMoZGlzY292ZXJlZClcbiAgICAgICAgICAubWFwKChbbmFtZSwgdG9vbF0pID0+IFtuYW1lLnJlcGxhY2UoL15ncmFwaGl0aV8vLCBcIlwiKSwgdG9vbCBhcyBUb29sXSBhcyBjb25zdClcbiAgICAgICAgICAuZmlsdGVyKChbbmFtZV0pID0+IG5hbWUgaW4gU0NPUEVEX1RPT0xfRklFTERTKSxcbiAgICAgICk7XG4gICAgICBjb25zdCBtaXNzaW5nID0gT2JqZWN0LmtleXMoU0NPUEVEX1RPT0xfRklFTERTKS5maWx0ZXIoKG5hbWUpID0+ICF0aGlzLm1jcFRvb2xzW25hbWVdKTtcbiAgICAgIGlmIChtaXNzaW5nLmxlbmd0aCA+IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBHcmFwaGl0aSBkaWQgbm90IHB1Ymxpc2ggcmVxdWlyZWQgc2NvcGVkIHRvb2xzOiAke21pc3Npbmcuam9pbihcIiwgXCIpfWApO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBhd2FpdCB0aGlzLnN0b3BTaWRlY2FycygpO1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfVxuICAgIHRoaXMuc2V0dXBDb21wbGV0ZSA9IHRydWU7XG4gICAgdGhpcy5tY3BTZXJ2ZXJTd2VlcCA9IHNldEludGVydmFsKCgpID0+IHRoaXMuY2xvc2VJZGxlTWNwU2VydmVycygpLCBNQ1BfU0VSVkVSX1NXRUVQX01TKTtcbiAgICB0aGlzLm1jcFNlcnZlclN3ZWVwLnVucmVmKCk7XG4gICAgdGhpcy5sb2dnZXIuaW5mbyhcInJlYWR5XCIsIHtcbiAgICAgIGdyYXBoaXRpUG9ydDogdGhpcy5yZXNvbHZlZC5ncmFwaGl0aVBvcnQsXG4gICAgICBsaXRlbGxtUG9ydDogdGhpcy5yZXNvbHZlZC5saXRlbGxtUG9ydCxcbiAgICAgIHByb3h5UG9ydDogdGhpcy5yZXNvbHZlZC5wcm94eVBvcnQsXG4gICAgICBtY3BQYXRoOiBNQ1BfUEFUSCxcbiAgICAgIHRvb2xzOiBPYmplY3Qua2V5cyh0aGlzLm1jcFRvb2xzKSxcbiAgICB9KTtcbiAgfVxuXG4gIG92ZXJyaWRlIGluamVjdFJvdXRlcyhyb3V0ZXI6IElBcHBSb3V0ZXIpOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IG1ldGhvZCBvZiBbXCJnZXRcIiwgXCJwb3N0XCIsIFwiZGVsZXRlXCJdIGFzIGNvbnN0KSB7XG4gICAgICB0aGlzLnJvdXRlKHJvdXRlciwge1xuICAgICAgICBuYW1lOiBgJHttZXRob2R9TWNwYCxcbiAgICAgICAgbWV0aG9kLFxuICAgICAgICBwYXRoOiBcIi9tY3BcIixcbiAgICAgICAgaGFuZGxlcjogKHJlcXVlc3QsIHJlc3BvbnNlKSA9PiB0aGlzLmZvcndhcmRNY3AocmVxdWVzdCwgcmVzcG9uc2UpLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgb3ZlcnJpZGUgYWJvcnRBY3RpdmVPcGVyYXRpb25zKCk6IHZvaWQge1xuICAgIHN1cGVyLmFib3J0QWN0aXZlT3BlcmF0aW9ucygpO1xuICAgIHZvaWQgdGhpcy5tY3A/LmRpc2Nvbm5lY3QoKTtcbiAgfVxuXG4gIGFzeW5jIHNodXRkb3duKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGF3YWl0IHRoaXMuc3RvcFNpZGVjYXJzKCk7XG4gIH1cblxuICBvdmVycmlkZSBleHBvcnRzKCkge1xuICAgIHJldHVybiB7IG1jcFBhdGg6IE1DUF9QQVRIIH07XG4gIH1cblxuICB0b29sa2l0KCk6IFJlY29yZDxzdHJpbmcsIFRvb2xraXRFbnRyeT4ge1xuICAgIHJldHVybiBPYmplY3QuZnJvbUVudHJpZXMoXG4gICAgICBPYmplY3QuZW50cmllcyh0aGlzLm1jcFRvb2xzKS5tYXAoKFtuYW1lLCB0b29sXSkgPT4gW1xuICAgICAgICBuYW1lLFxuICAgICAgICB7XG4gICAgICAgICAgX190b29sa2l0UmVmOiB0cnVlIGFzIGNvbnN0LFxuICAgICAgICAgIHBsdWdpbk5hbWU6IFwiZ3JhcGhpdGlcIixcbiAgICAgICAgICBsb2NhbE5hbWU6IG5hbWUsXG4gICAgICAgICAgZGVmOiB7XG4gICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgZGVzY3JpcHRpb246IHRvb2wuZGVzY3JpcHRpb24sXG4gICAgICAgICAgICBwYXJhbWV0ZXJzOiB0b29sLmlucHV0U2NoZW1hID8/IHsgdHlwZTogXCJvYmplY3RcIiwgcHJvcGVydGllczoge30gfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIGFubm90YXRpb25zOiB7XG4gICAgICAgICAgICBlZmZlY3Q6IFdSSVRFX1RPT0xTLmhhcyhuYW1lKSA/IChcIndyaXRlXCIgYXMgY29uc3QpIDogKFwicmVhZFwiIGFzIGNvbnN0KSxcbiAgICAgICAgICAgIHJlcXVpcmVzVXNlckNvbnRleHQ6IHRydWUgYXMgY29uc3QsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIF0pLFxuICAgICk7XG4gIH1cblxuICBhc3luYyBleGVjdXRlQWdlbnRUb29sKFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBhcmdzOiB1bmtub3duLFxuICAgIHNpZ25hbD86IEFib3J0U2lnbmFsLFxuICAgIGNvbnRleHQ/OiB7IHJlc291cmNlSWQ/OiBzdHJpbmcgfSxcbiAgKTogUHJvbWlzZTx1bmtub3duPiB7XG4gICAgY29uc3QgdG9vbCA9IHRoaXMubWNwVG9vbHNbbmFtZV07XG4gICAgaWYgKCF0b29sPy5leGVjdXRlKSB0aHJvdyBuZXcgRXJyb3IoYFVua25vd24gR3JhcGhpdGkgdG9vbDogJHtuYW1lfWApO1xuICAgIGNvbnN0IHVzZXJJZCA9IGNvbnRleHQ/LnJlc291cmNlSWQgPz8gZXhlY3V0aW9uQ29udGV4dFVzZXJJZCgpO1xuICAgIHJldHVybiB0b29sLmV4ZWN1dGUoc2NvcGVkQXJndW1lbnRzKG5hbWUsIGFyZ3MsIHVzZXJTY29wZSh1c2VySWQpKSwge1xuICAgICAgYWJvcnRTaWduYWw6IHNpZ25hbCxcbiAgICB9IGFzIG5ldmVyKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZm9yd2FyZE1jcChyZXF1ZXN0OiBleHByZXNzLlJlcXVlc3QsIHJlc3BvbnNlOiBleHByZXNzLlJlc3BvbnNlKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKCF0aGlzLnJlc29sdmVkKSB7XG4gICAgICByZXNwb25zZS5zdGF0dXMoNTAzKS5qc29uKHsgZXJyb3I6IFwiR3JhcGhpdGkgaXMgbm90IHJlYWR5XCIgfSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHVzZXJJZCA9IGFwcGtpdElkZW50aXR5LnJlcXVlc3RVc2VySWQocmVxdWVzdCkgPz8gZXhlY3V0aW9uQ29udGV4dFVzZXJJZCgpO1xuICAgIGNvbnN0IHNlcnZlciA9IHRoaXMubWNwU2VydmVyKHVzZXJJZCk7XG4gICAgYXdhaXQgc2VydmVyLnN0YXJ0SFRUUCh7XG4gICAgICB1cmw6IG5ldyBVUkwocmVxdWVzdC5vcmlnaW5hbFVybCwgXCJodHRwOi8vYXBwLmxvY2FsXCIpLFxuICAgICAgaHR0cFBhdGg6IE1DUF9QQVRILFxuICAgICAgcmVxOiByZXF1ZXN0LFxuICAgICAgcmVzOiByZXNwb25zZSxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgbWNwU2VydmVyKHVzZXJJZDogc3RyaW5nKTogTUNQU2VydmVyIHtcbiAgICBjb25zdCBleGlzdGluZyA9IHRoaXMubWNwU2VydmVycy5nZXQodXNlcklkKTtcbiAgICBpZiAoZXhpc3RpbmcpIHtcbiAgICAgIGV4aXN0aW5nLmxhc3RVc2VkID0gRGF0ZS5ub3coKTtcbiAgICAgIHJldHVybiBleGlzdGluZy5zZXJ2ZXI7XG4gICAgfVxuICAgIGNvbnN0IHNjb3BlID0gdXNlclNjb3BlKHVzZXJJZCk7XG4gICAgY29uc3QgdG9vbHMgPSBPYmplY3QuZnJvbUVudHJpZXMoXG4gICAgICBPYmplY3QuZW50cmllcyh0aGlzLm1jcFRvb2xzKS5tYXAoKFtuYW1lLCB0b29sXSkgPT4gW1xuICAgICAgICBuYW1lLFxuICAgICAgICBjcmVhdGVUb29sKHtcbiAgICAgICAgICBpZDogbmFtZSxcbiAgICAgICAgICBkZXNjcmlwdGlvbjogdG9vbC5kZXNjcmlwdGlvbiA/PyBuYW1lLFxuICAgICAgICAgIC4uLih0b29sLmlucHV0U2NoZW1hID8geyBpbnB1dFNjaGVtYTogdG9vbC5pbnB1dFNjaGVtYSBhcyBuZXZlciB9IDoge30pLFxuICAgICAgICAgIGV4ZWN1dGU6IChhcmdzOiB1bmtub3duLCBjb250ZXh0OiB1bmtub3duKSA9PiB7XG4gICAgICAgICAgICBpZiAoIXRvb2wuZXhlY3V0ZSkgdGhyb3cgbmV3IEVycm9yKGBHcmFwaGl0aSB0b29sIGNhbm5vdCBleGVjdXRlOiAke25hbWV9YCk7XG4gICAgICAgICAgICByZXR1cm4gdG9vbC5leGVjdXRlKHNjb3BlZEFyZ3VtZW50cyhuYW1lLCBhcmdzLCBzY29wZSksIGNvbnRleHQgYXMgbmV2ZXIpO1xuICAgICAgICAgIH0sXG4gICAgICAgIH0pLFxuICAgICAgXSksXG4gICAgKTtcbiAgICBjb25zdCBzZXJ2ZXIgPSBuZXcgTUNQU2VydmVyKHtcbiAgICAgIG5hbWU6IFwiR3JhcGhpdGlcIixcbiAgICAgIHZlcnNpb246IFwiMS4wLjBcIixcbiAgICAgIHRvb2xzLFxuICAgIH0pO1xuICAgIHRoaXMubWNwU2VydmVycy5zZXQodXNlcklkLCB7IGxhc3RVc2VkOiBEYXRlLm5vdygpLCBzZXJ2ZXIgfSk7XG4gICAgcmV0dXJuIHNlcnZlcjtcbiAgfVxuXG4gIHByaXZhdGUgb25TdXBlcnZpc29yRXhpdChlcnJvcj86IHVua25vd24pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5zdG9wcGluZyB8fCAhdGhpcy5zZXR1cENvbXBsZXRlKSByZXR1cm47XG4gICAgdGhpcy5sb2dnZXIuZXJyb3IoXCJzaWRlY2FyIHN1cGVydmlzb3IgZXhpdGVkXCIsIHsgZXJyb3IgfSk7XG4gICAgcHJvY2Vzcy5raWxsKHByb2Nlc3MucGlkLCBcIlNJR1RFUk1cIik7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHN0b3BTaWRlY2FycygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5zdG9wcGluZykgcmV0dXJuO1xuICAgIHRoaXMuc3RvcHBpbmcgPSB0cnVlO1xuICAgIGlmICh0aGlzLm1jcFNlcnZlclN3ZWVwKSBjbGVhckludGVydmFsKHRoaXMubWNwU2VydmVyU3dlZXApO1xuICAgIHRoaXMubWNwU2VydmVyU3dlZXAgPSB1bmRlZmluZWQ7XG4gICAgYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKFsuLi50aGlzLm1jcFNlcnZlcnMudmFsdWVzKCldLm1hcCgoeyBzZXJ2ZXIgfSkgPT4gc2VydmVyLmNsb3NlKCkpKTtcbiAgICB0aGlzLm1jcFNlcnZlcnMuY2xlYXIoKTtcbiAgICBhd2FpdCB0aGlzLm1jcD8uZGlzY29ubmVjdCgpO1xuICAgIHRoaXMubWNwID0gdW5kZWZpbmVkO1xuICAgIHRoaXMubWNwVG9vbHMgPSB7fTtcbiAgICBmb3IgKGNvbnN0IGNvbW1hbmQgb2YgdGhpcy5jb21tYW5kcykgY29tbWFuZC5raWxsKFwiU0lHVEVSTVwiKTtcbiAgICBpZiAodGhpcy5zdXBlcnZpc2lvbikgYXdhaXQgdGhpcy5zdXBlcnZpc2lvbi5yZXN1bHQuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB0aGlzLmNvbW1hbmRzID0gW107XG4gICAgdGhpcy5zdXBlcnZpc2lvbiA9IHVuZGVmaW5lZDtcbiAgfVxuXG4gIHByaXZhdGUgY2xvc2VJZGxlTWNwU2VydmVycygpOiB2b2lkIHtcbiAgICBjb25zdCBjdXRvZmYgPSBEYXRlLm5vdygpIC0gTUNQX1NFUlZFUl9JRExFX01TO1xuICAgIGZvciAoY29uc3QgW3VzZXJJZCwgZW50cnldIG9mIHRoaXMubWNwU2VydmVycykge1xuICAgICAgaWYgKGVudHJ5Lmxhc3RVc2VkID49IGN1dG9mZikgY29udGludWU7XG4gICAgICB0aGlzLm1jcFNlcnZlcnMuZGVsZXRlKHVzZXJJZCk7XG4gICAgICB2b2lkIGVudHJ5LnNlcnZlci5jbG9zZSgpLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICB0aGlzLmxvZ2dlci53YXJuKFwiaWRsZSBNQ1Agc2VydmVyIGNsb3NlIGZhaWxlZFwiLCB7IGVycm9yIH0pO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBjb25zdCBncmFwaGl0aSA9IHRvUGx1Z2luKEdyYXBoaXRpUGx1Z2luKTtcblxuZnVuY3Rpb24gZXhlY3V0aW9uQ29udGV4dFVzZXJJZCgpOiBzdHJpbmcge1xuICBjb25zdCBjb250ZXh0ID0gZGJ4QXBwa2l0LnRyeUdldEV4ZWN1dGlvbkNvbnRleHQoKTtcbiAgaWYgKCFjb250ZXh0KSB0aHJvdyBuZXcgRXJyb3IoXCJHcmFwaGl0aSBtZW1vcnkgcmVxdWlyZXMgYW4gQXBwS2l0IGV4ZWN1dGlvbiBjb250ZXh0XCIpO1xuICByZXR1cm4gXCJ1c2VySWRcIiBpbiBjb250ZXh0ID8gY29udGV4dC51c2VySWQgOiBjb250ZXh0LnNlcnZpY2VVc2VySWQ7XG59XG5cbmZ1bmN0aW9uIHVzZXJTY29wZSh1c2VySWQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBgdXNlcl8ke2NyZWF0ZUhhc2goXCJzaGEyNTZcIikudXBkYXRlKHVzZXJJZCkuZGlnZXN0KFwiYmFzZTY0dXJsXCIpfWA7XG59XG5cbmZ1bmN0aW9uIHNjb3BlZEFyZ3VtZW50cyhuYW1lOiBzdHJpbmcsIGFyZ3M6IHVua25vd24sIHNjb3BlOiBzdHJpbmcpOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiB7XG4gIGlmICghKG5hbWUgaW4gU0NPUEVEX1RPT0xfRklFTERTKSkgdGhyb3cgbmV3IEVycm9yKGBHcmFwaGl0aSB0b29sIGlzIG5vdCB1c2VyLXNjb3BlZDogJHtuYW1lfWApO1xuICBjb25zdCBzY29wZWQgPSBvYmplY3QuaXNSZWNvcmQoYXJncykgPyB7IC4uLmFyZ3MgfSA6IHt9O1xuICBmb3IgKGNvbnN0IGFyZ3VtZW50IG9mIFVOU0NPUEVEX0FSR1VNRU5UUykgZGVsZXRlIHNjb3BlZFthcmd1bWVudF07XG4gIGNvbnN0IGZpZWxkID0gU0NPUEVEX1RPT0xfRklFTERTW25hbWUgYXMga2V5b2YgdHlwZW9mIFNDT1BFRF9UT09MX0ZJRUxEU107XG4gIGlmIChmaWVsZCA9PT0gXCJncm91cF9pZFwiKSBzY29wZWQuZ3JvdXBfaWQgPSBzY29wZTtcbiAgaWYgKGZpZWxkID09PSBcImdyb3VwX2lkc1wiKSBzY29wZWQuZ3JvdXBfaWRzID0gW3Njb3BlXTtcbiAgcmV0dXJuIHNjb3BlZDtcbn1cblxuYXN5bmMgZnVuY3Rpb24gd2FpdEZvckdyYXBoaXRpKHBvcnQ6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICBmb3IgYXdhaXQgKGNvbnN0IHJlYWR5IG9mIGFzeW5jTW9kdWxlLnBvbGwoXG4gICAgYXN5bmMgKHsgc2lnbmFsIH0pID0+IHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2goYGh0dHA6Ly8xMjcuMC4wLjE6JHtwb3J0fS9oZWFsdGhgLCB7IHNpZ25hbCB9KTtcbiAgICAgICAgcmV0dXJuIHJlc3BvbnNlLm9rO1xuICAgICAgfSBjYXRjaCB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICB9LFxuICAgIHtcbiAgICAgIGludGVydmFsTXM6IDI1MCxcbiAgICAgIHRpbWVvdXRNczogNjBfMDAwLFxuICAgICAgcHJlZGljYXRlOiAocmVhZHkpID0+ICFyZWFkeSxcbiAgICB9LFxuICApKSB7XG4gICAgaWYgKHJlYWR5KSByZXR1cm47XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gYXZhaWxhYmxlUG9ydCgpOiBQcm9taXNlPG51bWJlcj4ge1xuICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgIGNvbnN0IHNlcnZlciA9IGNyZWF0ZVNlcnZlcigpO1xuICAgIHNlcnZlci5vbmNlKFwiZXJyb3JcIiwgcmVqZWN0KTtcbiAgICBzZXJ2ZXIubGlzdGVuKDAsIFwiMTI3LjAuMC4xXCIsICgpID0+IHtcbiAgICAgIGNvbnN0IGFkZHJlc3MgPSBzZXJ2ZXIuYWRkcmVzcygpO1xuICAgICAgaWYgKCFhZGRyZXNzIHx8IHR5cGVvZiBhZGRyZXNzID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgIHNlcnZlci5jbG9zZSgpO1xuICAgICAgICByZWplY3QobmV3IEVycm9yKFwiQ291bGQgbm90IGFsbG9jYXRlIGEgR3JhcGhpdGkgbG9vcGJhY2sgcG9ydFwiKSk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHNlcnZlci5jbG9zZSgoZXJyb3IpID0+IChlcnJvciA/IHJlamVjdChlcnJvcikgOiByZXNvbHZlKGFkZHJlc3MucG9ydCkpKTtcbiAgICB9KTtcbiAgfSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGRpc3RpbmN0UG9ydHMoXG4gIGFwcFBvcnQ6IG51bWJlcixcbiAgZ3JhcGhpdGlQb3J0OiBudW1iZXIsXG4gIGxpdGVsbG1Qb3J0OiBudW1iZXIsXG4gIHByb3h5UG9ydDogbnVtYmVyLFxuKTogUHJvbWlzZTxbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0+IHtcbiAgY29uc3QgcG9ydHMgPSBbYXBwUG9ydF07XG4gIGZvciAoY29uc3QgY29uZmlndXJlZFBvcnQgb2YgW2dyYXBoaXRpUG9ydCwgbGl0ZWxsbVBvcnQsIHByb3h5UG9ydF0pIHtcbiAgICBpZiAoY29uZmlndXJlZFBvcnQgJiYgcG9ydHMuaW5jbHVkZXMoY29uZmlndXJlZFBvcnQpKSB7XG4gICAgICB0aHJvdyBuZXcgQ29uZmlndXJhdGlvbkVycm9yKFwiR3JhcGhpdGkgc2lkZWNhciBwb3J0cyBtdXN0IGRpZmZlciBmcm9tIERBVEFCUklDS1NfQVBQX1BPUlRcIik7XG4gICAgfVxuICAgIGxldCBwb3J0ID0gY29uZmlndXJlZFBvcnQgfHwgKGF3YWl0IGF2YWlsYWJsZVBvcnQoKSk7XG4gICAgd2hpbGUgKHBvcnRzLmluY2x1ZGVzKHBvcnQpKSBwb3J0ID0gYXdhaXQgYXZhaWxhYmxlUG9ydCgpO1xuICAgIHBvcnRzLnB1c2gocG9ydCk7XG4gIH1cbiAgcmV0dXJuIHBvcnRzLnNsaWNlKDEpIGFzIFtudW1iZXIsIG51bWJlciwgbnVtYmVyXTtcbn1cblxuZnVuY3Rpb24gY29tbWFuZExpbmUoYXJndW1lbnRzXzogc3RyaW5nW10pOiBzdHJpbmcge1xuICByZXR1cm4gYXJndW1lbnRzXy5tYXAoKHZhbHVlKSA9PiBgJyR7dmFsdWUucmVwbGFjZUFsbChcIidcIiwgXCInXFxcXCcnXCIpfSdgKS5qb2luKFwiIFwiKTtcbn1cbiJdfQ==
package/package.json CHANGED
@@ -19,17 +19,19 @@
19
19
  },
20
20
  "devDependencies": {
21
21
  "@types/bun": "^1.3.14",
22
+ "@types/express": "^5.0.5",
22
23
  "@types/json-schema": "^7",
23
24
  "@types/node": "^24.6.0",
24
25
  "typescript": "^5.9.3"
25
26
  },
26
27
  "dependencies": {
27
28
  "@databricks/appkit": "^0.60.0",
28
- "@dbx-tools/appkit": "0.6.114",
29
- "@dbx-tools/core": "0.6.114",
30
- "@dbx-tools/shared-core": "0.6.114",
29
+ "@dbx-tools/appkit": "0.6.115",
30
+ "@dbx-tools/core": "0.6.115",
31
+ "@dbx-tools/shared-core": "0.6.115",
31
32
  "@mastra/core": "1.47.0",
32
- "@mastra/mcp": "1.12.0"
33
+ "@mastra/mcp": "1.12.0",
34
+ "concurrently": "^10.0.3"
33
35
  },
34
36
  "main": "./lib/index.js",
35
37
  "license": "UNLICENSED",
@@ -45,7 +47,7 @@
45
47
  "./package.json": "./package.json"
46
48
  }
47
49
  },
48
- "version": "0.6.114",
50
+ "version": "0.6.115",
49
51
  "types": "./lib/index.d.ts",
50
52
  "type": "module",
51
53
  "exports": {