@dbx-tools/appkit-mastra 0.6.70 → 0.6.72

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.
@@ -8,7 +8,10 @@
8
8
  * **per-agent** namespacing via {@link agentStorageSchemaName} so
9
9
  * conversation history stays isolated between agents in the same
10
10
  * database. `PostgresStore` auto-creates the schema with
11
- * `CREATE SCHEMA IF NOT EXISTS` on init.
11
+ * `CREATE SCHEMA IF NOT EXISTS` on init. A failed migration (common on
12
+ * Lakebase when the connecting role is not the table owner) is logged
13
+ * and skipped via {@link withSoftStorageInit} so existing tables keep
14
+ * serving instead of retrying DDL on every request.
12
15
  * - **Memory** (semantic recall via `PgVector`): defaults to a single
13
16
  * **shared** instance across every agent. Cross-agent recall on one
14
17
  * index is almost always what users want; opt into per-agent recall
@@ -33,6 +36,19 @@ import { PostgresStore } from "@mastra/pg";
33
36
  import { Pool, type PoolConfig } from "pg";
34
37
  import type { MastraAgentDefinition } from "./agents.ts";
35
38
  import type { MastraPluginConfig } from "./config.ts";
39
+ /**
40
+ * Soften {@link PostgresStore.init} so a failed migration (e.g. Lakebase
41
+ * `must be owner of table …` on `ALTER`) is logged once instead of rethrown
42
+ * on every storage call.
43
+ *
44
+ * Mastra's `augmentWithInit` retries init forever when it throws, so the
45
+ * only way to keep serving against an already-usable schema is to treat
46
+ * migration failure as success and mark the store initialized.
47
+ *
48
+ * Concurrent first callers share one soft attempt; `isInitialized` is set
49
+ * before the soft promise settles so later callers skip DDL entirely.
50
+ */
51
+ export declare function withSoftStorageInit(store: PostgresStore): PostgresStore;
36
52
  /**
37
53
  * Build a dedicated **service-principal** Lakebase pool for Mastra
38
54
  * memory from the lakebase plugin's resolved SP pg config.
package/lib/src/memory.js CHANGED
@@ -8,7 +8,10 @@
8
8
  * **per-agent** namespacing via {@link agentStorageSchemaName} so
9
9
  * conversation history stays isolated between agents in the same
10
10
  * database. `PostgresStore` auto-creates the schema with
11
- * `CREATE SCHEMA IF NOT EXISTS` on init.
11
+ * `CREATE SCHEMA IF NOT EXISTS` on init. A failed migration (common on
12
+ * Lakebase when the connecting role is not the table owner) is logged
13
+ * and skipped via {@link withSoftStorageInit} so existing tables keep
14
+ * serving instead of retrying DDL on every request.
12
15
  * - **Memory** (semantic recall via `PgVector`): defaults to a single
13
16
  * **shared** instance across every agent. Cross-agent recall on one
14
17
  * index is almost always what users want; opt into per-agent recall
@@ -29,7 +32,7 @@
29
32
  * @module
30
33
  */
31
34
  import { getUsernameWithApiLookup } from "@databricks/appkit";
32
- import { hash, log } from "@dbx-tools/shared-core";
35
+ import { error, hash, log } from "@dbx-tools/shared-core";
33
36
  import { fastembed } from "@mastra/fastembed";
34
37
  import { Memory } from "@mastra/memory";
35
38
  import { PgVector, PostgresStore } from "@mastra/pg";
@@ -37,6 +40,65 @@ import { Pool } from "pg";
37
40
  import { agentStorageSchemaName } from "./storage-schema.js";
38
41
  import { summaryModel, TITLE_INSTRUCTIONS } from "./summarize.js";
39
42
  const logger = log.logger("mastra/memory");
43
+ /** Process-wide dedupe so instance + per-agent stores share one ownership log. */
44
+ const loggedMigrationErrors = new Set();
45
+ /** Whether `LOG_LEVEL` is currently at or below debug. */
46
+ function isDebugEnabled() {
47
+ return log.isLevelEnabled("debug");
48
+ }
49
+ /**
50
+ * Soften {@link PostgresStore.init} so a failed migration (e.g. Lakebase
51
+ * `must be owner of table …` on `ALTER`) is logged once instead of rethrown
52
+ * on every storage call.
53
+ *
54
+ * Mastra's `augmentWithInit` retries init forever when it throws, so the
55
+ * only way to keep serving against an already-usable schema is to treat
56
+ * migration failure as success and mark the store initialized.
57
+ *
58
+ * Concurrent first callers share one soft attempt; `isInitialized` is set
59
+ * before the soft promise settles so later callers skip DDL entirely.
60
+ */
61
+ export function withSoftStorageInit(store) {
62
+ const soft = store;
63
+ const originalInit = soft.init.bind(soft);
64
+ let softInitPromise;
65
+ soft.init = async () => {
66
+ if (soft.isInitialized)
67
+ return;
68
+ softInitPromise ??= (async () => {
69
+ try {
70
+ await originalInit();
71
+ }
72
+ catch (err) {
73
+ // Mark success-for-serving before logging so a racing caller that
74
+ // passed the `isInitialized` check still joins this promise rather
75
+ // than starting another DDL pass.
76
+ soft.isInitialized = true;
77
+ const message = error.errorMessage(err);
78
+ if (!loggedMigrationErrors.has(message)) {
79
+ loggedMigrationErrors.add(message);
80
+ if (isDebugEnabled()) {
81
+ logger.error("mastra storage migration failed", err);
82
+ }
83
+ else {
84
+ logger.warn("mastra storage migration failed", {
85
+ error: message,
86
+ storeId: soft.id,
87
+ schema: soft.schema,
88
+ });
89
+ }
90
+ }
91
+ }
92
+ })();
93
+ try {
94
+ await softInitPromise;
95
+ }
96
+ finally {
97
+ soft.isInitialized = true;
98
+ }
99
+ };
100
+ return store;
101
+ }
40
102
  /**
41
103
  * Build a dedicated **service-principal** Lakebase pool for Mastra
42
104
  * memory from the lakebase plugin's resolved SP pg config.
@@ -116,13 +178,13 @@ export class MemoryBuilder {
116
178
  if (!setting)
117
179
  return undefined;
118
180
  if (typeof setting === "object") {
119
- return new PostgresStore(withId(setting, "mastra-store__instance"));
181
+ return withSoftStorageInit(new PostgresStore(withId(setting, "mastra-store__instance")));
120
182
  }
121
- return new PostgresStore({
183
+ return withSoftStorageInit(new PostgresStore({
122
184
  id: "mastra-store__instance",
123
185
  schemaName: "mastra_instance",
124
186
  pool: this.servicePrincipalPool,
125
- });
187
+ }));
126
188
  }
127
189
  /**
128
190
  * Build a `Memory` for `agentId` after the plugin/agent cascade.
@@ -172,16 +234,16 @@ export class MemoryBuilder {
172
234
  if (!setting)
173
235
  return undefined;
174
236
  if (typeof setting === "boolean") {
175
- return new PostgresStore({
237
+ return withSoftStorageInit(new PostgresStore({
176
238
  id: `mastra-store__${agentId}`,
177
239
  schemaName: agentStorageSchemaName(agentId),
178
240
  pool: this.servicePrincipalPool,
179
- });
241
+ }));
180
242
  }
181
243
  // Cast: `withId` guarantees `id` is set, but the distributive
182
244
  // Omit + `id?: string` shape doesn't structurally narrow to the
183
245
  // discriminated union members. Runtime shape is identical.
184
- return new PostgresStore(withId(setting, `mastra-store__${agentId}`));
246
+ return withSoftStorageInit(new PostgresStore(withId(setting, `mastra-store__${agentId}`)));
185
247
  }
186
248
  /**
187
249
  * Resolve the agent's vector store. Cascade:
@@ -272,4 +334,4 @@ function collectAgentDefinitions(config) {
272
334
  function withId(value, fallback) {
273
335
  return value.id ? value : { ...value, id: fallback };
274
336
  }
275
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtb3J5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21lbW9yeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0E2Qkc7QUFFSCxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUM5RCxPQUFPLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ25ELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUM5QyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDeEMsT0FBTyxFQUFFLFFBQVEsRUFBRSxhQUFhLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDckQsT0FBTyxFQUFFLElBQUksRUFBbUIsTUFBTSxJQUFJLENBQUM7QUFJM0MsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDN0QsT0FBTyxFQUFFLFlBQVksRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRWxFLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsZUFBZSxDQUFDLENBQUM7QUFFM0M7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQWtCRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsMEJBQTBCLENBQUMsUUFBb0I7SUFDbkUsOERBQThEO0lBQzlELGdFQUFnRTtJQUNoRSxvRUFBb0U7SUFDcEUsbUNBQW1DO0lBQ25DLE1BQU0sSUFBSSxHQUFHLFFBQVEsQ0FBQyxJQUFJLElBQUksQ0FBQyxNQUFNLHdCQUF3QixFQUFFLENBQUMsQ0FBQztJQUNqRSxPQUFPLElBQUksSUFBSSxDQUFDLEVBQUUsR0FBRyxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQztBQUN6QyxDQUFDO0FBTUQ7Ozs7O0dBS0c7QUFDSCxNQUFNLFVBQVUsYUFBYSxDQUFDLE1BQTBCO0lBQ3RE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O0lBQzlDLE9BQU8sTUFBTSxDQUFDO0FBQ2hCLENBQUM7QUFFRCx5RUFBeUU7QUFDekUsU0FBUyxhQUFhLENBQUMsT0FBbUM7SUFDeEQsT0FBTyxJQUFJLFFBQVEsQ0FDakIsTUFBTSxDQUFDLE9BQU8sRUFBRSxjQUFjLElBQUksQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUE4QyxDQUN4RixDQUFDO0FBQ0osQ0FBQztBQUVELGdFQUFnRTtBQUNoRSxTQUFTLHNCQUFzQixDQUFDLE9BQW1EO0lBQ2pGLE9BQU8sT0FBTyxLQUFLLElBQUksQ0FBQztBQUMxQixDQUFDO0FBRUQsaUVBQWlFO0FBQ2pFLFNBQVMsdUJBQXVCLENBQUMsTUFBMEI7SUFDekQsTUFBTSxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQztJQUM3QixJQUFJLENBQUMsTUFBTTtRQUFFLE9BQU8sRUFBRSxDQUFDO0lBQ3ZCLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUM7UUFBRSxPQUFPLE1BQU0sQ0FBQztJQUN6QyxJQUFJLE9BQVEsTUFBZ0MsQ0FBQyxZQUFZLEtBQUssUUFBUSxFQUFFLENBQUM7UUFDdkUsT0FBTyxDQUFDLE1BQStCLENBQUMsQ0FBQztJQUMzQyxDQUFDO0lBQ0QsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQStDLENBQUMsQ0FBQztBQUN4RSxDQUFDO0FBRUQsZ0VBQWdFO0FBQ2hFLFNBQVMsTUFBTSxDQUE0QixLQUFRLEVBQUUsUUFBZ0I7SUFDbkUsT0FBTyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxLQUFLLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxDQUFDO0FBQ3ZELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIExha2ViYXNlLWJhY2tlZCBNYXN0cmEgbWVtb3J5IHdpcmluZy5cbiAqXG4gKiBQcm92aWRlcyBhIHtAbGluayBNZW1vcnlCdWlsZGVyfSB0aGF0IG1pbnRzIG9uZSBgTWVtb3J5YCBwZXIgYWdlbnRcbiAqIHdpdGggdHdvIGluZGVwZW5kZW50IGtub2JzOlxuICpcbiAqIC0gKipTdG9yYWdlKiogKHRocmVhZHMgLyBtZXNzYWdlcyB2aWEgYFBvc3RncmVzU3RvcmVgKTogZGVmYXVsdHMgdG9cbiAqICAgKipwZXItYWdlbnQqKiBuYW1lc3BhY2luZyB2aWEge0BsaW5rIGFnZW50U3RvcmFnZVNjaGVtYU5hbWV9IHNvXG4gKiAgIGNvbnZlcnNhdGlvbiBoaXN0b3J5IHN0YXlzIGlzb2xhdGVkIGJldHdlZW4gYWdlbnRzIGluIHRoZSBzYW1lXG4gKiAgIGRhdGFiYXNlLiBgUG9zdGdyZXNTdG9yZWAgYXV0by1jcmVhdGVzIHRoZSBzY2hlbWEgd2l0aFxuICogICBgQ1JFQVRFIFNDSEVNQSBJRiBOT1QgRVhJU1RTYCBvbiBpbml0LlxuICogLSAqKk1lbW9yeSoqIChzZW1hbnRpYyByZWNhbGwgdmlhIGBQZ1ZlY3RvcmApOiBkZWZhdWx0cyB0byBhIHNpbmdsZVxuICogICAqKnNoYXJlZCoqIGluc3RhbmNlIGFjcm9zcyBldmVyeSBhZ2VudC4gQ3Jvc3MtYWdlbnQgcmVjYWxsIG9uIG9uZVxuICogICBpbmRleCBpcyBhbG1vc3QgYWx3YXlzIHdoYXQgdXNlcnMgd2FudDsgb3B0IGludG8gcGVyLWFnZW50IHJlY2FsbFxuICogICBieSBwYXNzaW5nIGEge0BsaW5rIE1hc3RyYU1lbW9yeUNvbmZpZ092ZXJyaWRlfSBvbiB0aGUgYWdlbnQuXG4gKlxuICogQWRkaXRpb25hbGx5LCB7QGxpbmsgTWVtb3J5QnVpbGRlci5pbnN0YW5jZVN0b3JhZ2V9IHJldHVybnMgYVxuICogKipNYXN0cmEtaW5zdGFuY2UtbGV2ZWwqKiBgUG9zdGdyZXNTdG9yZWAgKHNjaGVtYSBgbWFzdHJhX2luc3RhbmNlYClcbiAqIHVzZWQgZm9yIHdvcmtmbG93IHNuYXBzaG90cyAtIHRoZSBwZXJzaXN0ZW5jZSBsYXllclxuICogYGFnZW50LnJlc3VtZVN0cmVhbSgpYCByZWFkcyBmcm9tIHdoZW4gd2FraW5nIGEgc3VzcGVuZGVkXG4gKiBgcmVxdWlyZUFwcHJvdmFsYCB0b29sIGNhbGwuIFBlci1hZ2VudCBzdG9yZXMgYXJlIG5vdCBlbm91Z2ggZm9yXG4gKiB0aGlzOiB3b3JrZmxvdyBydW5zIGFyZSBzY29wZWQgdG8gdGhlIE1hc3RyYSBpbnN0YW5jZSwgbm90IGFuXG4gKiBpbmRpdmlkdWFsIGFnZW50J3MgYE1lbW9yeWAuXG4gKlxuICogUGx1Z2luLWxldmVsIGBjb25maWcuc3RvcmFnZWAgLyBgY29uZmlnLm1lbW9yeWAgYWN0IGFzIHRoZSBiYXNlbGluZVxuICogKGF1dG8tZGVmYXVsdGVkIHRvIGB0cnVlYCBpbiBgcGx1Z2luLnRzYCB3aGVuIHRoZSBgbGFrZWJhc2VgIHBsdWdpblxuICogaXMgcmVnaXN0ZXJlZCk7IHBlci1hZ2VudCBzZXR0aW5ncyBjYXNjYWRlIG9uIHRvcCBvZiB0aGF0LlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBnZXRVc2VybmFtZVdpdGhBcGlMb29rdXAgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0XCI7XG5pbXBvcnQgeyBoYXNoLCBsb2cgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHsgZmFzdGVtYmVkIH0gZnJvbSBcIkBtYXN0cmEvZmFzdGVtYmVkXCI7XG5pbXBvcnQgeyBNZW1vcnkgfSBmcm9tIFwiQG1hc3RyYS9tZW1vcnlcIjtcbmltcG9ydCB7IFBnVmVjdG9yLCBQb3N0Z3Jlc1N0b3JlIH0gZnJvbSBcIkBtYXN0cmEvcGdcIjtcbmltcG9ydCB7IFBvb2wsIHR5cGUgUG9vbENvbmZpZyB9IGZyb20gXCJwZ1wiO1xuXG5pbXBvcnQgdHlwZSB7IE1hc3RyYUFnZW50RGVmaW5pdGlvbiwgTWFzdHJhTWVtb3J5Q29uZmlnT3ZlcnJpZGUgfSBmcm9tIFwiLi9hZ2VudHMudHNcIjtcbmltcG9ydCB0eXBlIHsgTWFzdHJhUGx1Z2luQ29uZmlnIH0gZnJvbSBcIi4vY29uZmlnLnRzXCI7XG5pbXBvcnQgeyBhZ2VudFN0b3JhZ2VTY2hlbWFOYW1lIH0gZnJvbSBcIi4vc3RvcmFnZS1zY2hlbWEudHNcIjtcbmltcG9ydCB7IHN1bW1hcnlNb2RlbCwgVElUTEVfSU5TVFJVQ1RJT05TIH0gZnJvbSBcIi4vc3VtbWFyaXplLnRzXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGxvZy5sb2dnZXIoXCJtYXN0cmEvbWVtb3J5XCIpO1xuXG4vKipcbiAqIEJ1aWxkIGEgZGVkaWNhdGVkICoqc2VydmljZS1wcmluY2lwYWwqKiBMYWtlYmFzZSBwb29sIGZvciBNYXN0cmFcbiAqIG1lbW9yeSBmcm9tIHRoZSBsYWtlYmFzZSBwbHVnaW4ncyByZXNvbHZlZCBTUCBwZyBjb25maWcuXG4gKlxuICogVGhlIHBsdWdpbidzIGBleHBvcnRzKCkucG9vbGAgaXMgYSBgUm91dGluZ1Bvb2xgIHRoYXQgc3dpdGNoZXMgdG9cbiAqIHRoZSBwZXItdXNlciAoT0JPKSBwb29sIHdoZW5ldmVyIGEgcXVlcnkgcnVucyBpbnNpZGUgYW4gYGFzVXNlcmBcbiAqIHNjb3BlIC0gZXhhY3RseSB0aGUgY29udGV4dCB0aGUgbWFzdHJhIHBsdWdpbiBlc3RhYmxpc2hlcyBhcm91bmRcbiAqIGV2ZXJ5IGNoYXQgdHVybi4gTWVtb3J5ICh0aHJlYWRzIC8gbWVzc2FnZXMgKyBzZW1hbnRpYyByZWNhbGwpIG11c3RcbiAqIGluc3RlYWQgYWx3YXlzIGFjdCBhcyB0aGUgYXBwIHNlcnZpY2UgcHJpbmNpcGFsOiBpdCBvd25zIHRoZVxuICogYXV0by1jcmVhdGVkIGBtYXN0cmFfKmAgc2NoZW1hcyAoYSBwZXItdXNlciByb2xlIHVzdWFsbHkgY2FuJ3RcbiAqIGBDUkVBVEUgU0NIRU1BYCkgYW5kIGlzIHNoYXJlZCBhY3Jvc3MgdXNlcnMsIHNvIGl0IGNhbm5vdCBpbmhlcml0IGFcbiAqIHJlcXVlc3QncyBPQk8gaWRlbnRpdHkuXG4gKlxuICogYHBnQ29uZmlnYCBtdXN0IGJlIHRoZSBwbHVnaW4ncyBgZXhwb3J0cygpLmdldFBnQ29uZmlnKClgIGV2YWx1YXRlZFxuICogKipvdXRzaWRlKiogYW55IGBhc1VzZXJgIHNjb3BlIChpLmUuIGR1cmluZyBzZXR1cCksIHNvIGl0IGNhcnJpZXNcbiAqIHRoZSBTUCBjb25uZWN0aW9uIHRhcmdldCwgT0F1dGggdG9rZW4tcmVmcmVzaCBgcGFzc3dvcmRgIGNhbGxiYWNrLFxuICogYW5kIGFueSBgbGFrZWJhc2UoeyBwb29sIH0pYCB0dW5pbmcgb3ZlcnJpZGVzIC0gYWxsIG9mIHdoaWNoIHRoaXNcbiAqIHBvb2wgaW5oZXJpdHMuIFNlZSB0aGUgY2FsbCBzaXRlIGluIGBwbHVnaW4udHNgLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY3JlYXRlU2VydmljZVByaW5jaXBhbFBvb2wocGdDb25maWc6IFBvb2xDb25maWcpOiBQcm9taXNlPFBvb2w+IHtcbiAgLy8gYGdldFBnQ29uZmlnKClgIHJlc29sdmVzIHRoZSBTUCB1c2VybmFtZSBzeW5jaHJvbm91c2x5IGZyb21cbiAgLy8gYFBHVVNFUmAgLyBgREFUQUJSSUNLU19DTElFTlRfSURgOyBmYWxsIGJhY2sgdG8gdGhlIGFzeW5jIEFQSVxuICAvLyBsb29rdXAgKGUuZy4gbG9jYWwgZGV2IGF1dGhlbnRpY2F0aW5nIHZpYSBQQVQpIHNvIHRoZSBwb29sIGFsd2F5c1xuICAvLyBoYXMgYW4gaWRlbnRpdHkgdG8gY29ubmVjdCB3aXRoLlxuICBjb25zdCB1c2VyID0gcGdDb25maWcudXNlciA/PyAoYXdhaXQgZ2V0VXNlcm5hbWVXaXRoQXBpTG9va3VwKCkpO1xuICByZXR1cm4gbmV3IFBvb2woeyAuLi5wZ0NvbmZpZywgdXNlciB9KTtcbn1cblxuLyoqIEVmZmVjdGl2ZSBwZXIta25vYiBzZXR0aW5nIGFmdGVyIHRoZSBwbHVnaW4vYWdlbnQgY2FzY2FkZS4gKi9cbnR5cGUgU3RvcmFnZVNldHRpbmcgPSBNYXN0cmFBZ2VudERlZmluaXRpb25bXCJzdG9yYWdlXCJdO1xudHlwZSBNZW1vcnlTZXR0aW5nID0gTWFzdHJhQWdlbnREZWZpbml0aW9uW1wibWVtb3J5XCJdO1xuXG4vKipcbiAqIFRydWUgd2hlbiBhbnkgcGx1Z2luLWxldmVsIG9yIHBlci1hZ2VudCBzZXR0aW5nIGNvdWxkIG5lZWQgdGhlXG4gKiBMYWtlYmFzZSBwb29sLiBVc2VkIGJ5IGBwbHVnaW4udHNgIHRvIGdhdGUgY3JlYXRpb24gb2YgdGhlXG4gKiBzZXJ2aWNlLXByaW5jaXBhbCBwb29sIGFuZCB0aGUge0BsaW5rIE1lbW9yeUJ1aWxkZXJ9IHRoYXQgY29uc3VtZXNcbiAqIGl0OyB3aGVuIGZhbHNlIG5laXRoZXIgaXMgYnVpbHQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBuZWVkc0xha2ViYXNlKGNvbmZpZzogTWFzdHJhUGx1Z2luQ29uZmlnKTogYm9vbGVhbiB7XG4gIGlmIChzZXR0aW5nTmVlZHNTaGFyZWRQb29sKGNvbmZpZy5zdG9yYWdlKSkgcmV0dXJuIHRydWU7XG4gIGlmIChzZXR0aW5nTmVlZHNTaGFyZWRQb29sKGNvbmZpZy5tZW1vcnkpKSByZXR1cm4gdHJ1ZTtcbiAgY29uc3QgZGVmcyA9IGNvbGxlY3RBZ2VudERlZmluaXRpb25zKGNvbmZpZyk7XG4gIHJldHVybiBkZWZzLnNvbWUoKGQpID0+IHNldHRpbmdOZWVkc1NoYXJlZFBvb2woZC5zdG9yYWdlKSB8fCBzZXR0aW5nTmVlZHNTaGFyZWRQb29sKGQubWVtb3J5KSk7XG59XG5cbi8qKlxuICogQ29uc3RydWN0IGEgcGVyLWFnZW50IHtAbGluayBNZW1vcnl9IGZhY3RvcnkgYm91bmQgdG8gdGhlIHN1cHBsaWVkXG4gKiBzZXJ2aWNlLXByaW5jaXBhbCBwb29sIChzZWUge0BsaW5rIGNyZWF0ZVNlcnZpY2VQcmluY2lwYWxQb29sfSkuXG4gKiBDYWNoZXMgdGhlIHNoYXJlZCBgUGdWZWN0b3JgIHNpbmdsZXRvbiAoYnVpbHQgb24gZmlyc3QgbmVlZCkgc28gZWFjaFxuICogYWdlbnQgYnVpbGQgaXMgTygxKSBhZnRlciB0aGUgZmlyc3QuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVNZW1vcnlCdWlsZGVyKFxuICBjb25maWc6IE1hc3RyYVBsdWdpbkNvbmZpZyxcbiAgc2VydmljZVByaW5jaXBhbFBvb2w6IFBvb2wsXG4pOiBNZW1vcnlCdWlsZGVyIHtcbiAgcmV0dXJuIG5ldyBNZW1vcnlCdWlsZGVyKGNvbmZpZywgc2VydmljZVByaW5jaXBhbFBvb2wpO1xufVxuXG4vKipcbiAqIEJ1aWxkcyBvbmUgYE1lbW9yeWAgcGVyIGFnZW50IGFnYWluc3QgYSBzaGFyZWQgc2VydmljZS1wcmluY2lwYWxcbiAqIExha2ViYXNlIHBvb2wuIFBlci1pbnN0YW5jZSBzdGF0ZSBrZWVwcyB0aGUgc2hhcmVkIGBQZ1ZlY3RvcmAgYWxpdmVcbiAqIGFjcm9zcyBjYWxscyBzbyByZWdpc3RlcmluZyBOIGFnZW50cyBzdGF5cyBjaGVhcC5cbiAqL1xuZXhwb3J0IGNsYXNzIE1lbW9yeUJ1aWxkZXIge1xuICBwcml2YXRlIHNoYXJlZFZlY3RvcjogUGdWZWN0b3IgfCB1bmRlZmluZWQ7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSByZWFkb25seSBjb25maWc6IE1hc3RyYVBsdWdpbkNvbmZpZyxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHNlcnZpY2VQcmluY2lwYWxQb29sOiBQb29sLFxuICApIHt9XG5cbiAgLyoqXG4gICAqIEJ1aWxkIHRoZSBNYXN0cmEtaW5zdGFuY2UtbGV2ZWwgc3RvcmFnZSB1c2VkIGZvciB3b3JrZmxvd1xuICAgKiBzbmFwc2hvdHMuIFJldHVybnMgYHVuZGVmaW5lZGAgd2hlbiBwbHVnaW4tbGV2ZWwgYHN0b3JhZ2VgIGlzXG4gICAqIGRpc2FibGVkLCBpbiB3aGljaCBjYXNlIGBhZ2VudC5yZXN1bWVTdHJlYW0oKWAgKGFuZCB0aGVyZWZvcmVcbiAgICogdGhlIGByZXF1aXJlQXBwcm92YWxgIGZsb3cpIHdpbGwgbm90IGJlIGF2YWlsYWJsZS5cbiAgICpcbiAgICogVGhlIHN0b3JlIGxpdmVzIGluIGEgZGVkaWNhdGVkIGBtYXN0cmFfaW5zdGFuY2VgIHNjaGVtYSBzbyBpdFxuICAgKiBuZXZlciBjb2xsaWRlcyB3aXRoIHBlci1hZ2VudCB7QGxpbmsgYWdlbnRTdG9yYWdlU2NoZW1hTmFtZX0gbmFtZXNwYWNlcy5cbiAgICogV29ya2Zsb3cgc25hcHNob3RzIGFyZSBub3QgcGVyLWFnZW50IHN0YXRlOyB0aGV5IGJlbG9uZyB0byB0aGVcbiAgICogYE1hc3RyYWAgaW5zdGFuY2UgdGhhdCBvd25zIHRoZSB3b3JrZmxvdyBleGVjdXRpb24uXG4gICAqL1xuICBpbnN0YW5jZVN0b3JhZ2UoKTogUG9zdGdyZXNTdG9yZSB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3Qgc2V0dGluZyA9IHRoaXMuY29uZmlnLnN0b3JhZ2U7XG4gICAgaWYgKCFzZXR0aW5nKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGlmICh0eXBlb2Ygc2V0dGluZyA9PT0gXCJvYmplY3RcIikge1xuICAgICAgcmV0dXJuIG5ldyBQb3N0Z3Jlc1N0b3JlKFxuICAgICAgICB3aXRoSWQoc2V0dGluZywgXCJtYXN0cmEtc3RvcmVfX2luc3RhbmNlXCIpIGFzIENvbnN0cnVjdG9yUGFyYW1ldGVyczx0eXBlb2YgUG9zdGdyZXNTdG9yZT5bMF0sXG4gICAgICApO1xuICAgIH1cbiAgICByZXR1cm4gbmV3IFBvc3RncmVzU3RvcmUoe1xuICAgICAgaWQ6IFwibWFzdHJhLXN0b3JlX19pbnN0YW5jZVwiLFxuICAgICAgc2NoZW1hTmFtZTogXCJtYXN0cmFfaW5zdGFuY2VcIixcbiAgICAgIHBvb2w6IHRoaXMuc2VydmljZVByaW5jaXBhbFBvb2wsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQnVpbGQgYSBgTWVtb3J5YCBmb3IgYGFnZW50SWRgIGFmdGVyIHRoZSBwbHVnaW4vYWdlbnQgY2FzY2FkZS5cbiAgICogUmV0dXJucyBgdW5kZWZpbmVkYCB3aGVuIHRoZSBhZ2VudCBoYXMgbmVpdGhlciBzdG9yYWdlIG5vciBhXG4gICAqIHZlY3RvciBzdG9yZSBlbmFibGVkIC0gTWFzdHJhIGFjY2VwdHMgYSBtaXNzaW5nIGBtZW1vcnlgIGZpZWxkXG4gICAqIGFuZCB0cmVhdHMgdGhlIGFnZW50IGFzIHN0YXRlbGVzcy5cbiAgICovXG4gIGZvckFnZW50KGFnZW50SWQ6IHN0cmluZywgZGVmOiBNYXN0cmFBZ2VudERlZmluaXRpb24pOiBNZW1vcnkgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IHN0b3JhZ2VTZXR0aW5nID0gZGVmLnN0b3JhZ2UgPz8gdGhpcy5jb25maWcuc3RvcmFnZTtcbiAgICBjb25zdCBtZW1vcnlTZXR0aW5nID0gZGVmLm1lbW9yeSA/PyB0aGlzLmNvbmZpZy5tZW1vcnk7XG5cbiAgICBjb25zdCBzdG9yYWdlID0gdGhpcy5idWlsZFN0b3JhZ2UoYWdlbnRJZCwgc3RvcmFnZVNldHRpbmcpO1xuICAgIGNvbnN0IHZlY3RvciA9IHRoaXMuYnVpbGRWZWN0b3IobWVtb3J5U2V0dGluZyk7XG4gICAgaWYgKCFzdG9yYWdlICYmICF2ZWN0b3IpIHtcbiAgICAgIGxvZ2dlci5kZWJ1ZyhcImFnZW50OnN0YXRlbGVzc1wiLCB7IGFnZW50SWQgfSk7XG4gICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGxvZ2dlci5kZWJ1ZyhcImFnZW50OmNvbmZpZ3VyZWRcIiwge1xuICAgICAgYWdlbnRJZCxcbiAgICAgIHN0b3JhZ2U6IHN0b3JhZ2UgIT09IHVuZGVmaW5lZCxcbiAgICAgIHZlY3RvcjogdmVjdG9yICE9PSB1bmRlZmluZWQsXG4gICAgICB2ZWN0b3JNb2RlOlxuICAgICAgICB2ZWN0b3IgPT09IHVuZGVmaW5lZCA/IFwib2ZmXCIgOiB0eXBlb2YgbWVtb3J5U2V0dGluZyA9PT0gXCJvYmplY3RcIiA/IFwiZGVkaWNhdGVkXCIgOiBcInNoYXJlZFwiLFxuICAgIH0pO1xuXG4gICAgcmV0dXJuIG5ldyBNZW1vcnkoe1xuICAgICAgLi4uKHN0b3JhZ2UgPyB7IHN0b3JhZ2UgfSA6IHt9KSxcbiAgICAgIC4uLih2ZWN0b3IgPyB7IHZlY3RvciwgZW1iZWRkZXI6IGZhc3RlbWJlZCB9IDoge30pLFxuICAgICAgb3B0aW9uczoge1xuICAgICAgICBsYXN0TWVzc2FnZXM6IDEwLFxuICAgICAgICAuLi4odmVjdG9yID8geyBzZW1hbnRpY1JlY2FsbDogeyB0b3BLOiAzLCBtZXNzYWdlUmFuZ2U6IDIgfSB9IDoge30pLFxuICAgICAgICAvLyBBdXRvLW5hbWUgZWFjaCB0aHJlYWQgZnJvbSBpdHMgb3BlbmluZyB0dXJuIHNvIHRoZVxuICAgICAgICAvLyBjb252ZXJzYXRpb24gbGlzdCB0aGUgVUkgcmVuZGVycyBzaG93cyBtZWFuaW5nZnVsIHRpdGxlc1xuICAgICAgICAvLyBpbnN0ZWFkIG9mIHJhdyBpZHMuIFRpdGxpbmcgcnVucyBvbiB0aGUgc21hbGwgLyBmYXN0IGNoYXRcbiAgICAgICAgLy8gdGllciAoc2VlIGBzdW1tYXJpemUudHNgKSByYXRoZXIgdGhhbiB0aGUgYWdlbnQncyBwcmltYXJ5XG4gICAgICAgIC8vIG1vZGVsLCBzbyBuYW1pbmcgYSB0aHJlYWQgbmV2ZXIgc3BlbmRzIHRoZSBoZWF2eXdlaWdodCBtb2RlbC5cbiAgICAgICAgLy8gT25seSBtZWFuaW5nZnVsIHdoZW4gc3RvcmFnZSBpcyBvbjsgaGFybWxlc3Mgb3RoZXJ3aXNlLlxuICAgICAgICAuLi4oc3RvcmFnZVxuICAgICAgICAgID8ge1xuICAgICAgICAgICAgICBnZW5lcmF0ZVRpdGxlOiB7XG4gICAgICAgICAgICAgICAgbW9kZWw6IHN1bW1hcnlNb2RlbCh0aGlzLmNvbmZpZyksXG4gICAgICAgICAgICAgICAgaW5zdHJ1Y3Rpb25zOiBUSVRMRV9JTlNUUlVDVElPTlMsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9XG4gICAgICAgICAgOiB7fSksXG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBidWlsZFN0b3JhZ2UoYWdlbnRJZDogc3RyaW5nLCBzZXR0aW5nOiBTdG9yYWdlU2V0dGluZyk6IFBvc3RncmVzU3RvcmUgfCB1bmRlZmluZWQge1xuICAgIGlmICghc2V0dGluZykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBpZiAodHlwZW9mIHNldHRpbmcgPT09IFwiYm9vbGVhblwiKSB7XG4gICAgICByZXR1cm4gbmV3IFBvc3RncmVzU3RvcmUoe1xuICAgICAgICBpZDogYG1hc3RyYS1zdG9yZV9fJHthZ2VudElkfWAsXG4gICAgICAgIHNjaGVtYU5hbWU6IGFnZW50U3RvcmFnZVNjaGVtYU5hbWUoYWdlbnRJZCksXG4gICAgICAgIHBvb2w6IHRoaXMuc2VydmljZVByaW5jaXBhbFBvb2wsXG4gICAgICB9KTtcbiAgICB9XG4gICAgLy8gQ2FzdDogYHdpdGhJZGAgZ3VhcmFudGVlcyBgaWRgIGlzIHNldCwgYnV0IHRoZSBkaXN0cmlidXRpdmVcbiAgICAvLyBPbWl0ICsgYGlkPzogc3RyaW5nYCBzaGFwZSBkb2Vzbid0IHN0cnVjdHVyYWxseSBuYXJyb3cgdG8gdGhlXG4gICAgLy8gZGlzY3JpbWluYXRlZCB1bmlvbiBtZW1iZXJzLiBSdW50aW1lIHNoYXBlIGlzIGlkZW50aWNhbC5cbiAgICByZXR1cm4gbmV3IFBvc3RncmVzU3RvcmUoXG4gICAgICB3aXRoSWQoc2V0dGluZywgYG1hc3RyYS1zdG9yZV9fJHthZ2VudElkfWApIGFzIENvbnN0cnVjdG9yUGFyYW1ldGVyczx0eXBlb2YgUG9zdGdyZXNTdG9yZT5bMF0sXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNvbHZlIHRoZSBhZ2VudCdzIHZlY3RvciBzdG9yZS4gQ2FzY2FkZTpcbiAgICpcbiAgICogLSBmYWxzeTogbm8gdmVjdG9yLlxuICAgKiAtIGBib29sZWFuYCAvIGB1bmRlZmluZWQtaW5oZXJpdGluZy10cnVlYDogcmV0dXJuIHRoZSBzaGFyZWRcbiAgICogICBzaW5nbGV0b24gKGJ1aWx0IGxhemlseSBvbiBmaXJzdCBjYWxsKS4gQWxsIGFnZW50cyB0aGF0XG4gICAqICAgZGVmYXVsdC1lbmFibGUgbWVtb3J5IHdyaXRlIGludG8gYW5kIHJlY2FsbCBmcm9tIG9uZSBpbmRleC5cbiAgICogLSBvYmplY3Q6IGJ1aWxkIGEgZGVkaWNhdGVkIGBQZ1ZlY3RvcmAgZm9yIHRoaXMgYWdlbnQuXG4gICAqL1xuICBwcml2YXRlIGJ1aWxkVmVjdG9yKHNldHRpbmc6IE1lbW9yeVNldHRpbmcpOiBQZ1ZlY3RvciB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCFzZXR0aW5nKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGlmICh0eXBlb2Ygc2V0dGluZyA9PT0gXCJib29sZWFuXCIpIHJldHVybiB0aGlzLmdldFNoYXJlZFZlY3RvcigpO1xuICAgIHJldHVybiBidWlsZFBnVmVjdG9yKHNldHRpbmcpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRTaGFyZWRWZWN0b3IoKTogUGdWZWN0b3Ige1xuICAgIGlmICghdGhpcy5zaGFyZWRWZWN0b3IpIHtcbiAgICAgIHRoaXMuc2hhcmVkVmVjdG9yID0gYnVpbGRTaGFyZWRQZ1ZlY3Rvcih0aGlzLnNlcnZpY2VQcmluY2lwYWxQb29sKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc2hhcmVkVmVjdG9yO1xuICB9XG59XG5cbi8qKlxuICogQnVpbGQgdGhlIHNoYXJlZCBgUGdWZWN0b3JgIHRoYXQgYmFja3MgdGhlIGRlZmF1bHRcbiAqIGBkZWYubWVtb3J5ID09PSB0cnVlYCBjYXNlIGFjcm9zcyBldmVyeSBhZ2VudC5cbiAqXG4gKiBgUGdWZWN0b3JgJ3MgY29uc3RydWN0b3IgYWNjZXB0cyBvbmx5IGNvbm5lY3Rpb24tc3R5bGUgY29uZmlnc1xuICogKGBIb3N0Q29uZmlnYCAvIGBDb25uZWN0aW9uU3RyaW5nQ29uZmlnYCAvIGBDbGllbnRDb25maWdgKTsgdGhlcmUgaXNcbiAqIG5vIGB7IHBvb2wgfWAgc2hvcnRoYW5kIHRoZSB3YXkgYFBvc3RncmVzU3RvcmVgIGhhcyBvbmUuIFdvcnNlLCB0aGVcbiAqIGNvbnN0cnVjdG9yIHN5bmNocm9ub3VzbHkga2lja3Mgb2ZmIGEgYGNhY2hlV2FybXVwUHJvbWlzZWAgSUlGRSB0aGF0XG4gKiBjYWxscyBgdGhpcy5wb29sLmNvbm5lY3QoKWAgYmVmb3JlIHJldHVybmluZywgc28gd2UgY2FuJ3QgY2xlYW5seVxuICogaGFuZCBpdCBhbiBpbmVydCBjb25maWcgYW5kIHBhdGNoIHRoZSBwb29sIGFmdGVyd2FyZHMuXG4gKlxuICogVGhlIHRyaWNrOiBwYXNzIGlsbGVnYWwtYnV0LXZhbGlkYXRpb24tcGFzc2luZyBwbGFjZWhvbGRlcnMgc28gdGhlXG4gKiB3YXJtdXAncyBgbmV0LmNvbm5lY3QoKWAgcmVqZWN0cyBzeW5jaHJvbm91c2x5IHdpdGggYFJhbmdlRXJyb3JgXG4gKiAoTm9kZSB2YWxpZGF0ZXMgYDAgPD0gcG9ydCA8IDY1NTM2YCkuIFRoZSBJSUZFJ3MgYGNhdGNoIHt9YCBzd2FsbG93c1xuICogaXQsIG5vIEROUyBsb29rdXAgb3IgVENQIGF0dGVtcHQgaGFwcGVucywgYW5kIHdlIHRoZW4gc3dhcFxuICogYHBnVmVjdG9yLnBvb2xgIHRvIHRoZSBsYWtlYmFzZSBwb29sLiBFdmVyeSBzdWJzZXF1ZW50IGBQZ1ZlY3RvcmBcbiAqIG1ldGhvZCByZWFkcyBgdGhpcy5wb29sYCBhdCBjYWxsIHRpbWUsIHNvIGFsbCByZWFsIEkvTyBnb2VzIHRocm91Z2hcbiAqIHRoZSBsYWtlYmFzZSBwb29sIGZyb20gdGhlbiBvbi4gVGhlIHBsYWNlaG9sZGVyIHBvb2wgaXMgYC5lbmQoKWAnZFxuICogc28gaXRzIHNvY2tldCBib29rLWtlZXBpbmcgaXMgcmVsZWFzZWQuXG4gKi9cbmZ1bmN0aW9uIGJ1aWxkU2hhcmVkUGdWZWN0b3IocG9vbDogUG9vbCk6IFBnVmVjdG9yIHtcbiAgY29uc3QgdmVjdG9yID0gbmV3IFBnVmVjdG9yKHtcbiAgICBpZDogYHBnJHtoYXNoLmlkKCl9YCxcbiAgICAvLyBLZWVwIHRoZSByZWNhbGwgaW5kZXggb3V0IG9mIGBwdWJsaWNgOiBvbiBhIExha2ViYXNlIGRhdGFiYXNlIHRoZSBhcHBcbiAgICAvLyBzZXJ2aWNlIHByaW5jaXBhbCBoYXMgbm8gQ1JFQVRFIG9uIGBwdWJsaWNgIChQRzE1KyBsb2NrcyBpdCBkb3duKSwgc28gYVxuICAgIC8vIGRlZmF1bHQtc2NoZW1hIFBnVmVjdG9yIGZhaWxzIG9uIENSRUFURSBJTkRFWCB3aXRoIFwicGVybWlzc2lvbiBkZW5pZWQgZm9yXG4gICAgLy8gc2NoZW1hIHB1YmxpY1wiLiBQZ1ZlY3RvciBydW5zIENSRUFURSBTQ0hFTUEgSUYgTk9UIEVYSVNUUyBmb3IgYSBuYW1lZFxuICAgIC8vIHNjaGVtYSwgc28gdGhlIFNQIGNyZWF0ZXMgYW5kIG93bnMgYG1hc3RyYV9pbnN0YW5jZWAgKHRoZSBzYW1lXG4gICAgLy8gaW5zdGFuY2UtbGV2ZWwgc2NoZW1hIHRoZSB3b3JrZmxvdy1zbmFwc2hvdCBzdG9yZSB1c2VzKSBhbmQgdGhlIGluZGV4XG4gICAgLy8gbGFuZHMgdGhlcmUuIFRhYmxlIG5hbWVzIGRvbid0IGNvbGxpZGUgd2l0aCB0aGUgc3RvcmFnZSB0YWJsZXMuXG4gICAgc2NoZW1hTmFtZTogXCJtYXN0cmFfaW5zdGFuY2VcIixcbiAgICBob3N0OiBcIi0xXCIsXG4gICAgcG9ydDogLTEsXG4gICAgZGF0YWJhc2U6IFwiX1wiLFxuICAgIHVzZXI6IFwiX1wiLFxuICAgIHBhc3N3b3JkOiBcIl9cIixcbiAgfSk7XG4gIGNvbnN0IHBsYWNlaG9sZGVyID0gdmVjdG9yLnBvb2w7XG4gIHZlY3Rvci5wb29sID0gcG9vbDtcbiAgdm9pZCBwbGFjZWhvbGRlci5lbmQoKS5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICByZXR1cm4gdmVjdG9yO1xufVxuXG4vKiogUGVyLWFnZW50IGRlZGljYXRlZCBgUGdWZWN0b3JgIChyYXJlOyBvcHQtaW4gdmlhIG9iamVjdCBvdmVycmlkZSkuICovXG5mdW5jdGlvbiBidWlsZFBnVmVjdG9yKHNldHRpbmc6IE1hc3RyYU1lbW9yeUNvbmZpZ092ZXJyaWRlKTogUGdWZWN0b3Ige1xuICByZXR1cm4gbmV3IFBnVmVjdG9yKFxuICAgIHdpdGhJZChzZXR0aW5nLCBgcGctdmVjdG9yX18ke2hhc2guaWQoKX1gKSBhcyBDb25zdHJ1Y3RvclBhcmFtZXRlcnM8dHlwZW9mIFBnVmVjdG9yPlswXSxcbiAgKTtcbn1cblxuLyoqIFRydWUgd2hlbiB0aGlzIHNldHRpbmcgcmVxdWlyZXMgdGhlIHNoYXJlZCBMYWtlYmFzZSBwb29sLiAqL1xuZnVuY3Rpb24gc2V0dGluZ05lZWRzU2hhcmVkUG9vbChzZXR0aW5nOiBTdG9yYWdlU2V0dGluZyB8IE1lbW9yeVNldHRpbmcgfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgcmV0dXJuIHNldHRpbmcgPT09IHRydWU7XG59XG5cbi8qKiBXYWxrIHRoZSB0aHJlZSBzaGFwZXMgb2YgYGNvbmZpZy5hZ2VudHNgIGludG8gYSBmbGF0IGxpc3QuICovXG5mdW5jdGlvbiBjb2xsZWN0QWdlbnREZWZpbml0aW9ucyhjb25maWc6IE1hc3RyYVBsdWdpbkNvbmZpZyk6IE1hc3RyYUFnZW50RGVmaW5pdGlvbltdIHtcbiAgY29uc3QgYWdlbnRzID0gY29uZmlnLmFnZW50cztcbiAgaWYgKCFhZ2VudHMpIHJldHVybiBbXTtcbiAgaWYgKEFycmF5LmlzQXJyYXkoYWdlbnRzKSkgcmV0dXJuIGFnZW50cztcbiAgaWYgKHR5cGVvZiAoYWdlbnRzIGFzIE1hc3RyYUFnZW50RGVmaW5pdGlvbikuaW5zdHJ1Y3Rpb25zID09PSBcInN0cmluZ1wiKSB7XG4gICAgcmV0dXJuIFthZ2VudHMgYXMgTWFzdHJhQWdlbnREZWZpbml0aW9uXTtcbiAgfVxuICByZXR1cm4gT2JqZWN0LnZhbHVlcyhhZ2VudHMgYXMgUmVjb3JkPHN0cmluZywgTWFzdHJhQWdlbnREZWZpbml0aW9uPik7XG59XG5cbi8qKiBGaWxsIGluIGEgZGVmYXVsdCBgaWRgIHdoZW4gdGhlIGNhbGxlciBkaWRuJ3Qgc3VwcGx5IG9uZS4gKi9cbmZ1bmN0aW9uIHdpdGhJZDxUIGV4dGVuZHMgeyBpZD86IHN0cmluZyB9Pih2YWx1ZTogVCwgZmFsbGJhY2s6IHN0cmluZyk6IFQge1xuICByZXR1cm4gdmFsdWUuaWQgPyB2YWx1ZSA6IHsgLi4udmFsdWUsIGlkOiBmYWxsYmFjayB9O1xufVxuIl19
337
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWVtb3J5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL21lbW9yeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnQ0c7QUFFSCxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUM5RCxPQUFPLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUMxRCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDOUMsT0FBTyxFQUFFLE1BQU0sRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3hDLE9BQU8sRUFBRSxRQUFRLEVBQUUsYUFBYSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ3JELE9BQU8sRUFBRSxJQUFJLEVBQW1CLE1BQU0sSUFBSSxDQUFDO0FBSTNDLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQzdELE9BQU8sRUFBRSxZQUFZLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUVsRSxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FBQyxDQUFDO0FBRTNDLGtGQUFrRjtBQUNsRixNQUFNLHFCQUFxQixHQUFHLElBQUksR0FBRyxFQUFVLENBQUM7QUFFaEQsMERBQTBEO0FBQzFELFNBQVMsY0FBYztJQUNyQixPQUFPLEdBQUcsQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLENBQUM7QUFDckMsQ0FBQztBQUVEOzs7Ozs7Ozs7OztHQVdHO0FBQ0gsTUFBTSxVQUFVLG1CQUFtQixDQUFDLEtBQW9CO0lBQ3RELE1BQU0sSUFBSSxHQUFHLEtBS1osQ0FBQztJQUNGLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzFDLElBQUksZUFBMEMsQ0FBQztJQUUvQyxJQUFJLENBQUMsSUFBSSxHQUFHLEtBQUssSUFBSSxFQUFFO1FBQ3JCLElBQUksSUFBSSxDQUFDLGFBQWE7WUFBRSxPQUFPO1FBQy9CLGVBQWUsS0FBSyxDQUFDLEtBQUssSUFBSSxFQUFFO1lBQzlCLElBQUksQ0FBQztnQkFDSCxNQUFNLFlBQVksRUFBRSxDQUFDO1lBQ3ZCLENBQUM7WUFBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO2dCQUNiLGtFQUFrRTtnQkFDbEUsbUVBQW1FO2dCQUNuRSxrQ0FBa0M7Z0JBQ2xDLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDO2dCQUMxQixNQUFNLE9BQU8sR0FBRyxLQUFLLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUN4QyxJQUFJLENBQUMscUJBQXFCLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7b0JBQ3hDLHFCQUFxQixDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQztvQkFDbkMsSUFBSSxjQUFjLEVBQUUsRUFBRSxDQUFDO3dCQUNyQixNQUFNLENBQUMsS0FBSyxDQUFDLGlDQUFpQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO29CQUN2RCxDQUFDO3lCQUFNLENBQUM7d0JBQ04sTUFBTSxDQUFDLElBQUksQ0FBQyxpQ0FBaUMsRUFBRTs0QkFDN0MsS0FBSyxFQUFFLE9BQU87NEJBQ2QsT0FBTyxFQUFFLElBQUksQ0FBQyxFQUFFOzRCQUNoQixNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU07eUJBQ3BCLENBQUMsQ0FBQztvQkFDTCxDQUFDO2dCQUNILENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUNMLElBQUksQ0FBQztZQUNILE1BQU0sZUFBZSxDQUFDO1FBQ3hCLENBQUM7Z0JBQVMsQ0FBQztZQUNULElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDO1FBQzVCLENBQUM7SUFDSCxDQUFDLENBQUM7SUFDRixPQUFPLEtBQUssQ0FBQztBQUNmLENBQUM7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBa0JHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSwwQkFBMEIsQ0FBQyxRQUFvQjtJQUNuRSw4REFBOEQ7SUFDOUQsZ0VBQWdFO0lBQ2hFLG9FQUFvRTtJQUNwRSxtQ0FBbUM7SUFDbkMsTUFBTSxJQUFJLEdBQUcsUUFBUSxDQUFDLElBQUksSUFBSSxDQUFDLE1BQU0sd0JBQXdCLEVBQUUsQ0FBQyxDQUFDO0lBQ2pFLE9BQU8sSUFBSSxJQUFJLENBQUMsRUFBRSxHQUFHLFFBQVEsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0FBQ3pDLENBQUM7QUFNRDs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSxhQUFhLENBQUMsTUFBMEI7SUFDdEQsSUFBSSxzQkFBc0IsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFDeEQsSUFBSSxzQkFBc0IsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFDdkQsTUFBTSxJQUFJLEdBQUcsdUJBQXVCLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDN0MsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksc0JBQXNCLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7QUFDakcsQ0FBQztBQUVEOzs7OztHQUtHO0FBQ0gsTUFBTSxVQUFVLG1CQUFtQixDQUNqQyxNQUEwQixFQUMxQixvQkFBMEI7SUFFMUIsT0FBTyxJQUFJLGFBQWEsQ0FBQyxNQUFNLEVBQUUsb0JBQW9CLENBQUMsQ0FBQztBQUN6RCxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sT0FBTyxhQUFhO0lBSUw7SUFDQTtJQUpYLFlBQVksQ0FBdUI7SUFFM0MsWUFDbUIsTUFBMEIsRUFDMUIsb0JBQTBCO1FBRDFCLFdBQU0sR0FBTixNQUFNLENBQW9CO1FBQzFCLHlCQUFvQixHQUFwQixvQkFBb0IsQ0FBTTtJQUMxQyxDQUFDO0lBRUo7Ozs7Ozs7Ozs7T0FVRztJQUNILGVBQWU7UUFDYixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQztRQUNwQyxJQUFJLENBQUMsT0FBTztZQUFFLE9BQU8sU0FBUyxDQUFDO1FBQy9CLElBQUksT0FBTyxPQUFPLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDaEMsT0FBTyxtQkFBbUIsQ0FDeEIsSUFBSSxhQUFhLENBQ2YsTUFBTSxDQUFDLE9BQU8sRUFBRSx3QkFBd0IsQ0FFcEMsQ0FDTCxDQUNGLENBQUM7UUFDSixDQUFDO1FBQ0QsT0FBTyxtQkFBbUIsQ0FDeEIsSUFBSSxhQUFhLENBQUM7WUFDaEIsRUFBRSxFQUFFLHdCQUF3QjtZQUM1QixVQUFVLEVBQUUsaUJBQWlCO1lBQzdCLElBQUksRUFBRSxJQUFJLENBQUMsb0JBQW9CO1NBQ2hDLENBQUMsQ0FDSCxDQUFDO0lBQ0osQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsUUFBUSxDQUFDLE9BQWUsRUFBRSxHQUEwQjtRQUNsRCxNQUFNLGNBQWMsR0FBRyxHQUFHLENBQUMsT0FBTyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDO1FBQzFELE1BQU0sYUFBYSxHQUFHLEdBQUcsQ0FBQyxNQUFNLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUM7UUFFdkQsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLFlBQVksQ0FBQyxPQUFPLEVBQUUsY0FBYyxDQUFDLENBQUM7UUFDM0QsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUMvQyxJQUFJLENBQUMsT0FBTyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDeEIsTUFBTSxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsRUFBRSxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUM7WUFDN0MsT0FBTyxTQUFTLENBQUM7UUFDbkIsQ0FBQztRQUVELE1BQU0sQ0FBQyxLQUFLLENBQUMsa0JBQWtCLEVBQUU7WUFDL0IsT0FBTztZQUNQLE9BQU8sRUFBRSxPQUFPLEtBQUssU0FBUztZQUM5QixNQUFNLEVBQUUsTUFBTSxLQUFLLFNBQVM7WUFDNUIsVUFBVSxFQUNSLE1BQU0sS0FBSyxTQUFTLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsT0FBTyxhQUFhLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLFFBQVE7U0FDNUYsQ0FBQyxDQUFDO1FBRUgsT0FBTyxJQUFJLE1BQU0sQ0FBQztZQUNoQixHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDL0IsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDbEQsT0FBTyxFQUFFO2dCQUNQLFlBQVksRUFBRSxFQUFFO2dCQUNoQixHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLGNBQWMsRUFBRSxFQUFFLElBQUksRUFBRSxDQUFDLEVBQUUsWUFBWSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztnQkFDbkUscURBQXFEO2dCQUNyRCwyREFBMkQ7Z0JBQzNELDREQUE0RDtnQkFDNUQsNERBQTREO2dCQUM1RCxnRUFBZ0U7Z0JBQ2hFLDBEQUEwRDtnQkFDMUQsR0FBRyxDQUFDLE9BQU87b0JBQ1QsQ0FBQyxDQUFDO3dCQUNFLGFBQWEsRUFBRTs0QkFDYixLQUFLLEVBQUUsWUFBWSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUM7NEJBQ2hDLFlBQVksRUFBRSxrQkFBa0I7eUJBQ2pDO3FCQUNGO29CQUNILENBQUMsQ0FBQyxFQUFFLENBQUM7YUFDUjtTQUNGLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFTyxZQUFZLENBQUMsT0FBZSxFQUFFLE9BQXVCO1FBQzNELElBQUksQ0FBQyxPQUFPO1lBQUUsT0FBTyxTQUFTLENBQUM7UUFDL0IsSUFBSSxPQUFPLE9BQU8sS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUNqQyxPQUFPLG1CQUFtQixDQUN4QixJQUFJLGFBQWEsQ0FBQztnQkFDaEIsRUFBRSxFQUFFLGlCQUFpQixPQUFPLEVBQUU7Z0JBQzlCLFVBQVUsRUFBRSxzQkFBc0IsQ0FBQyxPQUFPLENBQUM7Z0JBQzNDLElBQUksRUFBRSxJQUFJLENBQUMsb0JBQW9CO2FBQ2hDLENBQUMsQ0FDSCxDQUFDO1FBQ0osQ0FBQztRQUNELDhEQUE4RDtRQUM5RCxnRUFBZ0U7UUFDaEUsMkRBQTJEO1FBQzNELE9BQU8sbUJBQW1CLENBQ3hCLElBQUksYUFBYSxDQUNmLE1BQU0sQ0FBQyxPQUFPLEVBQUUsaUJBQWlCLE9BQU8sRUFBRSxDQUV0QyxDQUNMLENBQ0YsQ0FBQztJQUNKLENBQUM7SUFFRDs7Ozs7Ozs7T0FRRztJQUNLLFdBQVcsQ0FBQyxPQUFzQjtRQUN4QyxJQUFJLENBQUMsT0FBTztZQUFFLE9BQU8sU0FBUyxDQUFDO1FBQy9CLElBQUksT0FBTyxPQUFPLEtBQUssU0FBUztZQUFFLE9BQU8sSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBQ2hFLE9BQU8sYUFBYSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQ2hDLENBQUM7SUFFTyxlQUFlO1FBQ3JCLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7WUFDdkIsSUFBSSxDQUFDLFlBQVksR0FBRyxtQkFBbUIsQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsQ0FBQztRQUNyRSxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUMsWUFBWSxDQUFDO0lBQzNCLENBQUM7Q0FDRjtBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUJHO0FBQ0gsU0FBUyxtQkFBbUIsQ0FBQyxJQUFVO0lBQ3JDLE1BQU0sTUFBTSxHQUFHLElBQUksUUFBUSxDQUFDO1FBQzFCLEVBQUUsRUFBRSxLQUFLLElBQUksQ0FBQyxFQUFFLEVBQUUsRUFBRTtRQUNwQix3RUFBd0U7UUFDeEUsMEVBQTBFO1FBQzFFLDRFQUE0RTtRQUM1RSx3RUFBd0U7UUFDeEUsaUVBQWlFO1FBQ2pFLHdFQUF3RTtRQUN4RSxrRUFBa0U7UUFDbEUsVUFBVSxFQUFFLGlCQUFpQjtRQUM3QixJQUFJLEVBQUUsSUFBSTtRQUNWLElBQUksRUFBRSxDQUFDLENBQUM7UUFDUixRQUFRLEVBQUUsR0FBRztRQUNiLElBQUksRUFBRSxHQUFHO1FBQ1QsUUFBUSxFQUFFLEdBQUc7S0FDZCxDQUFDLENBQUM7SUFDSCxNQUFNLFdBQVcsR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDO0lBQ2hDLE1BQU0sQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFDO0lBQ25CLEtBQUssV0FBVyxDQUFDLEdBQUcsRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUM5QyxPQUFPLE1BQU0sQ0FBQztBQUNoQixDQUFDO0FBRUQseUVBQXlFO0FBQ3pFLFNBQVMsYUFBYSxDQUFDLE9BQW1DO0lBQ3hELE9BQU8sSUFBSSxRQUFRLENBQ2pCLE1BQU0sQ0FBQyxPQUFPLEVBQUUsY0FBYyxJQUFJLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBOEMsQ0FDeEYsQ0FBQztBQUNKLENBQUM7QUFFRCxnRUFBZ0U7QUFDaEUsU0FBUyxzQkFBc0IsQ0FBQyxPQUFtRDtJQUNqRixPQUFPLE9BQU8sS0FBSyxJQUFJLENBQUM7QUFDMUIsQ0FBQztBQUVELGlFQUFpRTtBQUNqRSxTQUFTLHVCQUF1QixDQUFDLE1BQTBCO0lBQ3pELE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxNQUFNLENBQUM7SUFDN0IsSUFBSSxDQUFDLE1BQU07UUFBRSxPQUFPLEVBQUUsQ0FBQztJQUN2QixJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDO1FBQUUsT0FBTyxNQUFNLENBQUM7SUFDekMsSUFBSSxPQUFRLE1BQWdDLENBQUMsWUFBWSxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQ3ZFLE9BQU8sQ0FBQyxNQUErQixDQUFDLENBQUM7SUFDM0MsQ0FBQztJQUNELE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUErQyxDQUFDLENBQUM7QUFDeEUsQ0FBQztBQUVELGdFQUFnRTtBQUNoRSxTQUFTLE1BQU0sQ0FBNEIsS0FBUSxFQUFFLFFBQWdCO0lBQ25FLE9BQU8sS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsS0FBSyxFQUFFLEVBQUUsRUFBRSxRQUFRLEVBQUUsQ0FBQztBQUN2RCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBMYWtlYmFzZS1iYWNrZWQgTWFzdHJhIG1lbW9yeSB3aXJpbmcuXG4gKlxuICogUHJvdmlkZXMgYSB7QGxpbmsgTWVtb3J5QnVpbGRlcn0gdGhhdCBtaW50cyBvbmUgYE1lbW9yeWAgcGVyIGFnZW50XG4gKiB3aXRoIHR3byBpbmRlcGVuZGVudCBrbm9iczpcbiAqXG4gKiAtICoqU3RvcmFnZSoqICh0aHJlYWRzIC8gbWVzc2FnZXMgdmlhIGBQb3N0Z3Jlc1N0b3JlYCk6IGRlZmF1bHRzIHRvXG4gKiAgICoqcGVyLWFnZW50KiogbmFtZXNwYWNpbmcgdmlhIHtAbGluayBhZ2VudFN0b3JhZ2VTY2hlbWFOYW1lfSBzb1xuICogICBjb252ZXJzYXRpb24gaGlzdG9yeSBzdGF5cyBpc29sYXRlZCBiZXR3ZWVuIGFnZW50cyBpbiB0aGUgc2FtZVxuICogICBkYXRhYmFzZS4gYFBvc3RncmVzU3RvcmVgIGF1dG8tY3JlYXRlcyB0aGUgc2NoZW1hIHdpdGhcbiAqICAgYENSRUFURSBTQ0hFTUEgSUYgTk9UIEVYSVNUU2Agb24gaW5pdC4gQSBmYWlsZWQgbWlncmF0aW9uIChjb21tb24gb25cbiAqICAgTGFrZWJhc2Ugd2hlbiB0aGUgY29ubmVjdGluZyByb2xlIGlzIG5vdCB0aGUgdGFibGUgb3duZXIpIGlzIGxvZ2dlZFxuICogICBhbmQgc2tpcHBlZCB2aWEge0BsaW5rIHdpdGhTb2Z0U3RvcmFnZUluaXR9IHNvIGV4aXN0aW5nIHRhYmxlcyBrZWVwXG4gKiAgIHNlcnZpbmcgaW5zdGVhZCBvZiByZXRyeWluZyBEREwgb24gZXZlcnkgcmVxdWVzdC5cbiAqIC0gKipNZW1vcnkqKiAoc2VtYW50aWMgcmVjYWxsIHZpYSBgUGdWZWN0b3JgKTogZGVmYXVsdHMgdG8gYSBzaW5nbGVcbiAqICAgKipzaGFyZWQqKiBpbnN0YW5jZSBhY3Jvc3MgZXZlcnkgYWdlbnQuIENyb3NzLWFnZW50IHJlY2FsbCBvbiBvbmVcbiAqICAgaW5kZXggaXMgYWxtb3N0IGFsd2F5cyB3aGF0IHVzZXJzIHdhbnQ7IG9wdCBpbnRvIHBlci1hZ2VudCByZWNhbGxcbiAqICAgYnkgcGFzc2luZyBhIHtAbGluayBNYXN0cmFNZW1vcnlDb25maWdPdmVycmlkZX0gb24gdGhlIGFnZW50LlxuICpcbiAqIEFkZGl0aW9uYWxseSwge0BsaW5rIE1lbW9yeUJ1aWxkZXIuaW5zdGFuY2VTdG9yYWdlfSByZXR1cm5zIGFcbiAqICoqTWFzdHJhLWluc3RhbmNlLWxldmVsKiogYFBvc3RncmVzU3RvcmVgIChzY2hlbWEgYG1hc3RyYV9pbnN0YW5jZWApXG4gKiB1c2VkIGZvciB3b3JrZmxvdyBzbmFwc2hvdHMgLSB0aGUgcGVyc2lzdGVuY2UgbGF5ZXJcbiAqIGBhZ2VudC5yZXN1bWVTdHJlYW0oKWAgcmVhZHMgZnJvbSB3aGVuIHdha2luZyBhIHN1c3BlbmRlZFxuICogYHJlcXVpcmVBcHByb3ZhbGAgdG9vbCBjYWxsLiBQZXItYWdlbnQgc3RvcmVzIGFyZSBub3QgZW5vdWdoIGZvclxuICogdGhpczogd29ya2Zsb3cgcnVucyBhcmUgc2NvcGVkIHRvIHRoZSBNYXN0cmEgaW5zdGFuY2UsIG5vdCBhblxuICogaW5kaXZpZHVhbCBhZ2VudCdzIGBNZW1vcnlgLlxuICpcbiAqIFBsdWdpbi1sZXZlbCBgY29uZmlnLnN0b3JhZ2VgIC8gYGNvbmZpZy5tZW1vcnlgIGFjdCBhcyB0aGUgYmFzZWxpbmVcbiAqIChhdXRvLWRlZmF1bHRlZCB0byBgdHJ1ZWAgaW4gYHBsdWdpbi50c2Agd2hlbiB0aGUgYGxha2ViYXNlYCBwbHVnaW5cbiAqIGlzIHJlZ2lzdGVyZWQpOyBwZXItYWdlbnQgc2V0dGluZ3MgY2FzY2FkZSBvbiB0b3Agb2YgdGhhdC5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHsgZ2V0VXNlcm5hbWVXaXRoQXBpTG9va3VwIH0gZnJvbSBcIkBkYXRhYnJpY2tzL2FwcGtpdFwiO1xuaW1wb3J0IHsgZXJyb3IsIGhhc2gsIGxvZyB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5pbXBvcnQgeyBmYXN0ZW1iZWQgfSBmcm9tIFwiQG1hc3RyYS9mYXN0ZW1iZWRcIjtcbmltcG9ydCB7IE1lbW9yeSB9IGZyb20gXCJAbWFzdHJhL21lbW9yeVwiO1xuaW1wb3J0IHsgUGdWZWN0b3IsIFBvc3RncmVzU3RvcmUgfSBmcm9tIFwiQG1hc3RyYS9wZ1wiO1xuaW1wb3J0IHsgUG9vbCwgdHlwZSBQb29sQ29uZmlnIH0gZnJvbSBcInBnXCI7XG5cbmltcG9ydCB0eXBlIHsgTWFzdHJhQWdlbnREZWZpbml0aW9uLCBNYXN0cmFNZW1vcnlDb25maWdPdmVycmlkZSB9IGZyb20gXCIuL2FnZW50cy50c1wiO1xuaW1wb3J0IHR5cGUgeyBNYXN0cmFQbHVnaW5Db25maWcgfSBmcm9tIFwiLi9jb25maWcudHNcIjtcbmltcG9ydCB7IGFnZW50U3RvcmFnZVNjaGVtYU5hbWUgfSBmcm9tIFwiLi9zdG9yYWdlLXNjaGVtYS50c1wiO1xuaW1wb3J0IHsgc3VtbWFyeU1vZGVsLCBUSVRMRV9JTlNUUlVDVElPTlMgfSBmcm9tIFwiLi9zdW1tYXJpemUudHNcIjtcblxuY29uc3QgbG9nZ2VyID0gbG9nLmxvZ2dlcihcIm1hc3RyYS9tZW1vcnlcIik7XG5cbi8qKiBQcm9jZXNzLXdpZGUgZGVkdXBlIHNvIGluc3RhbmNlICsgcGVyLWFnZW50IHN0b3JlcyBzaGFyZSBvbmUgb3duZXJzaGlwIGxvZy4gKi9cbmNvbnN0IGxvZ2dlZE1pZ3JhdGlvbkVycm9ycyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuXG4vKiogV2hldGhlciBgTE9HX0xFVkVMYCBpcyBjdXJyZW50bHkgYXQgb3IgYmVsb3cgZGVidWcuICovXG5mdW5jdGlvbiBpc0RlYnVnRW5hYmxlZCgpOiBib29sZWFuIHtcbiAgcmV0dXJuIGxvZy5pc0xldmVsRW5hYmxlZChcImRlYnVnXCIpO1xufVxuXG4vKipcbiAqIFNvZnRlbiB7QGxpbmsgUG9zdGdyZXNTdG9yZS5pbml0fSBzbyBhIGZhaWxlZCBtaWdyYXRpb24gKGUuZy4gTGFrZWJhc2VcbiAqIGBtdXN0IGJlIG93bmVyIG9mIHRhYmxlIOKApmAgb24gYEFMVEVSYCkgaXMgbG9nZ2VkIG9uY2UgaW5zdGVhZCBvZiByZXRocm93blxuICogb24gZXZlcnkgc3RvcmFnZSBjYWxsLlxuICpcbiAqIE1hc3RyYSdzIGBhdWdtZW50V2l0aEluaXRgIHJldHJpZXMgaW5pdCBmb3JldmVyIHdoZW4gaXQgdGhyb3dzLCBzbyB0aGVcbiAqIG9ubHkgd2F5IHRvIGtlZXAgc2VydmluZyBhZ2FpbnN0IGFuIGFscmVhZHktdXNhYmxlIHNjaGVtYSBpcyB0byB0cmVhdFxuICogbWlncmF0aW9uIGZhaWx1cmUgYXMgc3VjY2VzcyBhbmQgbWFyayB0aGUgc3RvcmUgaW5pdGlhbGl6ZWQuXG4gKlxuICogQ29uY3VycmVudCBmaXJzdCBjYWxsZXJzIHNoYXJlIG9uZSBzb2Z0IGF0dGVtcHQ7IGBpc0luaXRpYWxpemVkYCBpcyBzZXRcbiAqIGJlZm9yZSB0aGUgc29mdCBwcm9taXNlIHNldHRsZXMgc28gbGF0ZXIgY2FsbGVycyBza2lwIERETCBlbnRpcmVseS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHdpdGhTb2Z0U3RvcmFnZUluaXQoc3RvcmU6IFBvc3RncmVzU3RvcmUpOiBQb3N0Z3Jlc1N0b3JlIHtcbiAgY29uc3Qgc29mdCA9IHN0b3JlIGFzIHVua25vd24gYXMge1xuICAgIGluaXQ6ICgpID0+IFByb21pc2U8dm9pZD47XG4gICAgaWQ6IHN0cmluZztcbiAgICBzY2hlbWE/OiBzdHJpbmc7XG4gICAgaXNJbml0aWFsaXplZDogYm9vbGVhbjtcbiAgfTtcbiAgY29uc3Qgb3JpZ2luYWxJbml0ID0gc29mdC5pbml0LmJpbmQoc29mdCk7XG4gIGxldCBzb2Z0SW5pdFByb21pc2U6IFByb21pc2U8dm9pZD4gfCB1bmRlZmluZWQ7XG5cbiAgc29mdC5pbml0ID0gYXN5bmMgKCkgPT4ge1xuICAgIGlmIChzb2Z0LmlzSW5pdGlhbGl6ZWQpIHJldHVybjtcbiAgICBzb2Z0SW5pdFByb21pc2UgPz89IChhc3luYyAoKSA9PiB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCBvcmlnaW5hbEluaXQoKTtcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAvLyBNYXJrIHN1Y2Nlc3MtZm9yLXNlcnZpbmcgYmVmb3JlIGxvZ2dpbmcgc28gYSByYWNpbmcgY2FsbGVyIHRoYXRcbiAgICAgICAgLy8gcGFzc2VkIHRoZSBgaXNJbml0aWFsaXplZGAgY2hlY2sgc3RpbGwgam9pbnMgdGhpcyBwcm9taXNlIHJhdGhlclxuICAgICAgICAvLyB0aGFuIHN0YXJ0aW5nIGFub3RoZXIgRERMIHBhc3MuXG4gICAgICAgIHNvZnQuaXNJbml0aWFsaXplZCA9IHRydWU7XG4gICAgICAgIGNvbnN0IG1lc3NhZ2UgPSBlcnJvci5lcnJvck1lc3NhZ2UoZXJyKTtcbiAgICAgICAgaWYgKCFsb2dnZWRNaWdyYXRpb25FcnJvcnMuaGFzKG1lc3NhZ2UpKSB7XG4gICAgICAgICAgbG9nZ2VkTWlncmF0aW9uRXJyb3JzLmFkZChtZXNzYWdlKTtcbiAgICAgICAgICBpZiAoaXNEZWJ1Z0VuYWJsZWQoKSkge1xuICAgICAgICAgICAgbG9nZ2VyLmVycm9yKFwibWFzdHJhIHN0b3JhZ2UgbWlncmF0aW9uIGZhaWxlZFwiLCBlcnIpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBsb2dnZXIud2FybihcIm1hc3RyYSBzdG9yYWdlIG1pZ3JhdGlvbiBmYWlsZWRcIiwge1xuICAgICAgICAgICAgICBlcnJvcjogbWVzc2FnZSxcbiAgICAgICAgICAgICAgc3RvcmVJZDogc29mdC5pZCxcbiAgICAgICAgICAgICAgc2NoZW1hOiBzb2Z0LnNjaGVtYSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pKCk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHNvZnRJbml0UHJvbWlzZTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgc29mdC5pc0luaXRpYWxpemVkID0gdHJ1ZTtcbiAgICB9XG4gIH07XG4gIHJldHVybiBzdG9yZTtcbn1cblxuLyoqXG4gKiBCdWlsZCBhIGRlZGljYXRlZCAqKnNlcnZpY2UtcHJpbmNpcGFsKiogTGFrZWJhc2UgcG9vbCBmb3IgTWFzdHJhXG4gKiBtZW1vcnkgZnJvbSB0aGUgbGFrZWJhc2UgcGx1Z2luJ3MgcmVzb2x2ZWQgU1AgcGcgY29uZmlnLlxuICpcbiAqIFRoZSBwbHVnaW4ncyBgZXhwb3J0cygpLnBvb2xgIGlzIGEgYFJvdXRpbmdQb29sYCB0aGF0IHN3aXRjaGVzIHRvXG4gKiB0aGUgcGVyLXVzZXIgKE9CTykgcG9vbCB3aGVuZXZlciBhIHF1ZXJ5IHJ1bnMgaW5zaWRlIGFuIGBhc1VzZXJgXG4gKiBzY29wZSAtIGV4YWN0bHkgdGhlIGNvbnRleHQgdGhlIG1hc3RyYSBwbHVnaW4gZXN0YWJsaXNoZXMgYXJvdW5kXG4gKiBldmVyeSBjaGF0IHR1cm4uIE1lbW9yeSAodGhyZWFkcyAvIG1lc3NhZ2VzICsgc2VtYW50aWMgcmVjYWxsKSBtdXN0XG4gKiBpbnN0ZWFkIGFsd2F5cyBhY3QgYXMgdGhlIGFwcCBzZXJ2aWNlIHByaW5jaXBhbDogaXQgb3ducyB0aGVcbiAqIGF1dG8tY3JlYXRlZCBgbWFzdHJhXypgIHNjaGVtYXMgKGEgcGVyLXVzZXIgcm9sZSB1c3VhbGx5IGNhbid0XG4gKiBgQ1JFQVRFIFNDSEVNQWApIGFuZCBpcyBzaGFyZWQgYWNyb3NzIHVzZXJzLCBzbyBpdCBjYW5ub3QgaW5oZXJpdCBhXG4gKiByZXF1ZXN0J3MgT0JPIGlkZW50aXR5LlxuICpcbiAqIGBwZ0NvbmZpZ2AgbXVzdCBiZSB0aGUgcGx1Z2luJ3MgYGV4cG9ydHMoKS5nZXRQZ0NvbmZpZygpYCBldmFsdWF0ZWRcbiAqICoqb3V0c2lkZSoqIGFueSBgYXNVc2VyYCBzY29wZSAoaS5lLiBkdXJpbmcgc2V0dXApLCBzbyBpdCBjYXJyaWVzXG4gKiB0aGUgU1AgY29ubmVjdGlvbiB0YXJnZXQsIE9BdXRoIHRva2VuLXJlZnJlc2ggYHBhc3N3b3JkYCBjYWxsYmFjayxcbiAqIGFuZCBhbnkgYGxha2ViYXNlKHsgcG9vbCB9KWAgdHVuaW5nIG92ZXJyaWRlcyAtIGFsbCBvZiB3aGljaCB0aGlzXG4gKiBwb29sIGluaGVyaXRzLiBTZWUgdGhlIGNhbGwgc2l0ZSBpbiBgcGx1Z2luLnRzYC5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVNlcnZpY2VQcmluY2lwYWxQb29sKHBnQ29uZmlnOiBQb29sQ29uZmlnKTogUHJvbWlzZTxQb29sPiB7XG4gIC8vIGBnZXRQZ0NvbmZpZygpYCByZXNvbHZlcyB0aGUgU1AgdXNlcm5hbWUgc3luY2hyb25vdXNseSBmcm9tXG4gIC8vIGBQR1VTRVJgIC8gYERBVEFCUklDS1NfQ0xJRU5UX0lEYDsgZmFsbCBiYWNrIHRvIHRoZSBhc3luYyBBUElcbiAgLy8gbG9va3VwIChlLmcuIGxvY2FsIGRldiBhdXRoZW50aWNhdGluZyB2aWEgUEFUKSBzbyB0aGUgcG9vbCBhbHdheXNcbiAgLy8gaGFzIGFuIGlkZW50aXR5IHRvIGNvbm5lY3Qgd2l0aC5cbiAgY29uc3QgdXNlciA9IHBnQ29uZmlnLnVzZXIgPz8gKGF3YWl0IGdldFVzZXJuYW1lV2l0aEFwaUxvb2t1cCgpKTtcbiAgcmV0dXJuIG5ldyBQb29sKHsgLi4ucGdDb25maWcsIHVzZXIgfSk7XG59XG5cbi8qKiBFZmZlY3RpdmUgcGVyLWtub2Igc2V0dGluZyBhZnRlciB0aGUgcGx1Z2luL2FnZW50IGNhc2NhZGUuICovXG50eXBlIFN0b3JhZ2VTZXR0aW5nID0gTWFzdHJhQWdlbnREZWZpbml0aW9uW1wic3RvcmFnZVwiXTtcbnR5cGUgTWVtb3J5U2V0dGluZyA9IE1hc3RyYUFnZW50RGVmaW5pdGlvbltcIm1lbW9yeVwiXTtcblxuLyoqXG4gKiBUcnVlIHdoZW4gYW55IHBsdWdpbi1sZXZlbCBvciBwZXItYWdlbnQgc2V0dGluZyBjb3VsZCBuZWVkIHRoZVxuICogTGFrZWJhc2UgcG9vbC4gVXNlZCBieSBgcGx1Z2luLnRzYCB0byBnYXRlIGNyZWF0aW9uIG9mIHRoZVxuICogc2VydmljZS1wcmluY2lwYWwgcG9vbCBhbmQgdGhlIHtAbGluayBNZW1vcnlCdWlsZGVyfSB0aGF0IGNvbnN1bWVzXG4gKiBpdDsgd2hlbiBmYWxzZSBuZWl0aGVyIGlzIGJ1aWx0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gbmVlZHNMYWtlYmFzZShjb25maWc6IE1hc3RyYVBsdWdpbkNvbmZpZyk6IGJvb2xlYW4ge1xuICBpZiAoc2V0dGluZ05lZWRzU2hhcmVkUG9vbChjb25maWcuc3RvcmFnZSkpIHJldHVybiB0cnVlO1xuICBpZiAoc2V0dGluZ05lZWRzU2hhcmVkUG9vbChjb25maWcubWVtb3J5KSkgcmV0dXJuIHRydWU7XG4gIGNvbnN0IGRlZnMgPSBjb2xsZWN0QWdlbnREZWZpbml0aW9ucyhjb25maWcpO1xuICByZXR1cm4gZGVmcy5zb21lKChkKSA9PiBzZXR0aW5nTmVlZHNTaGFyZWRQb29sKGQuc3RvcmFnZSkgfHwgc2V0dGluZ05lZWRzU2hhcmVkUG9vbChkLm1lbW9yeSkpO1xufVxuXG4vKipcbiAqIENvbnN0cnVjdCBhIHBlci1hZ2VudCB7QGxpbmsgTWVtb3J5fSBmYWN0b3J5IGJvdW5kIHRvIHRoZSBzdXBwbGllZFxuICogc2VydmljZS1wcmluY2lwYWwgcG9vbCAoc2VlIHtAbGluayBjcmVhdGVTZXJ2aWNlUHJpbmNpcGFsUG9vbH0pLlxuICogQ2FjaGVzIHRoZSBzaGFyZWQgYFBnVmVjdG9yYCBzaW5nbGV0b24gKGJ1aWx0IG9uIGZpcnN0IG5lZWQpIHNvIGVhY2hcbiAqIGFnZW50IGJ1aWxkIGlzIE8oMSkgYWZ0ZXIgdGhlIGZpcnN0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gY3JlYXRlTWVtb3J5QnVpbGRlcihcbiAgY29uZmlnOiBNYXN0cmFQbHVnaW5Db25maWcsXG4gIHNlcnZpY2VQcmluY2lwYWxQb29sOiBQb29sLFxuKTogTWVtb3J5QnVpbGRlciB7XG4gIHJldHVybiBuZXcgTWVtb3J5QnVpbGRlcihjb25maWcsIHNlcnZpY2VQcmluY2lwYWxQb29sKTtcbn1cblxuLyoqXG4gKiBCdWlsZHMgb25lIGBNZW1vcnlgIHBlciBhZ2VudCBhZ2FpbnN0IGEgc2hhcmVkIHNlcnZpY2UtcHJpbmNpcGFsXG4gKiBMYWtlYmFzZSBwb29sLiBQZXItaW5zdGFuY2Ugc3RhdGUga2VlcHMgdGhlIHNoYXJlZCBgUGdWZWN0b3JgIGFsaXZlXG4gKiBhY3Jvc3MgY2FsbHMgc28gcmVnaXN0ZXJpbmcgTiBhZ2VudHMgc3RheXMgY2hlYXAuXG4gKi9cbmV4cG9ydCBjbGFzcyBNZW1vcnlCdWlsZGVyIHtcbiAgcHJpdmF0ZSBzaGFyZWRWZWN0b3I6IFBnVmVjdG9yIHwgdW5kZWZpbmVkO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgY29uZmlnOiBNYXN0cmFQbHVnaW5Db25maWcsXG4gICAgcHJpdmF0ZSByZWFkb25seSBzZXJ2aWNlUHJpbmNpcGFsUG9vbDogUG9vbCxcbiAgKSB7fVxuXG4gIC8qKlxuICAgKiBCdWlsZCB0aGUgTWFzdHJhLWluc3RhbmNlLWxldmVsIHN0b3JhZ2UgdXNlZCBmb3Igd29ya2Zsb3dcbiAgICogc25hcHNob3RzLiBSZXR1cm5zIGB1bmRlZmluZWRgIHdoZW4gcGx1Z2luLWxldmVsIGBzdG9yYWdlYCBpc1xuICAgKiBkaXNhYmxlZCwgaW4gd2hpY2ggY2FzZSBgYWdlbnQucmVzdW1lU3RyZWFtKClgIChhbmQgdGhlcmVmb3JlXG4gICAqIHRoZSBgcmVxdWlyZUFwcHJvdmFsYCBmbG93KSB3aWxsIG5vdCBiZSBhdmFpbGFibGUuXG4gICAqXG4gICAqIFRoZSBzdG9yZSBsaXZlcyBpbiBhIGRlZGljYXRlZCBgbWFzdHJhX2luc3RhbmNlYCBzY2hlbWEgc28gaXRcbiAgICogbmV2ZXIgY29sbGlkZXMgd2l0aCBwZXItYWdlbnQge0BsaW5rIGFnZW50U3RvcmFnZVNjaGVtYU5hbWV9IG5hbWVzcGFjZXMuXG4gICAqIFdvcmtmbG93IHNuYXBzaG90cyBhcmUgbm90IHBlci1hZ2VudCBzdGF0ZTsgdGhleSBiZWxvbmcgdG8gdGhlXG4gICAqIGBNYXN0cmFgIGluc3RhbmNlIHRoYXQgb3ducyB0aGUgd29ya2Zsb3cgZXhlY3V0aW9uLlxuICAgKi9cbiAgaW5zdGFuY2VTdG9yYWdlKCk6IFBvc3RncmVzU3RvcmUgfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IHNldHRpbmcgPSB0aGlzLmNvbmZpZy5zdG9yYWdlO1xuICAgIGlmICghc2V0dGluZykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICBpZiAodHlwZW9mIHNldHRpbmcgPT09IFwib2JqZWN0XCIpIHtcbiAgICAgIHJldHVybiB3aXRoU29mdFN0b3JhZ2VJbml0KFxuICAgICAgICBuZXcgUG9zdGdyZXNTdG9yZShcbiAgICAgICAgICB3aXRoSWQoc2V0dGluZywgXCJtYXN0cmEtc3RvcmVfX2luc3RhbmNlXCIpIGFzIENvbnN0cnVjdG9yUGFyYW1ldGVyczxcbiAgICAgICAgICAgIHR5cGVvZiBQb3N0Z3Jlc1N0b3JlXG4gICAgICAgICAgPlswXSxcbiAgICAgICAgKSxcbiAgICAgICk7XG4gICAgfVxuICAgIHJldHVybiB3aXRoU29mdFN0b3JhZ2VJbml0KFxuICAgICAgbmV3IFBvc3RncmVzU3RvcmUoe1xuICAgICAgICBpZDogXCJtYXN0cmEtc3RvcmVfX2luc3RhbmNlXCIsXG4gICAgICAgIHNjaGVtYU5hbWU6IFwibWFzdHJhX2luc3RhbmNlXCIsXG4gICAgICAgIHBvb2w6IHRoaXMuc2VydmljZVByaW5jaXBhbFBvb2wsXG4gICAgICB9KSxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkIGEgYE1lbW9yeWAgZm9yIGBhZ2VudElkYCBhZnRlciB0aGUgcGx1Z2luL2FnZW50IGNhc2NhZGUuXG4gICAqIFJldHVybnMgYHVuZGVmaW5lZGAgd2hlbiB0aGUgYWdlbnQgaGFzIG5laXRoZXIgc3RvcmFnZSBub3IgYVxuICAgKiB2ZWN0b3Igc3RvcmUgZW5hYmxlZCAtIE1hc3RyYSBhY2NlcHRzIGEgbWlzc2luZyBgbWVtb3J5YCBmaWVsZFxuICAgKiBhbmQgdHJlYXRzIHRoZSBhZ2VudCBhcyBzdGF0ZWxlc3MuXG4gICAqL1xuICBmb3JBZ2VudChhZ2VudElkOiBzdHJpbmcsIGRlZjogTWFzdHJhQWdlbnREZWZpbml0aW9uKTogTWVtb3J5IHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBzdG9yYWdlU2V0dGluZyA9IGRlZi5zdG9yYWdlID8/IHRoaXMuY29uZmlnLnN0b3JhZ2U7XG4gICAgY29uc3QgbWVtb3J5U2V0dGluZyA9IGRlZi5tZW1vcnkgPz8gdGhpcy5jb25maWcubWVtb3J5O1xuXG4gICAgY29uc3Qgc3RvcmFnZSA9IHRoaXMuYnVpbGRTdG9yYWdlKGFnZW50SWQsIHN0b3JhZ2VTZXR0aW5nKTtcbiAgICBjb25zdCB2ZWN0b3IgPSB0aGlzLmJ1aWxkVmVjdG9yKG1lbW9yeVNldHRpbmcpO1xuICAgIGlmICghc3RvcmFnZSAmJiAhdmVjdG9yKSB7XG4gICAgICBsb2dnZXIuZGVidWcoXCJhZ2VudDpzdGF0ZWxlc3NcIiwgeyBhZ2VudElkIH0pO1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBsb2dnZXIuZGVidWcoXCJhZ2VudDpjb25maWd1cmVkXCIsIHtcbiAgICAgIGFnZW50SWQsXG4gICAgICBzdG9yYWdlOiBzdG9yYWdlICE9PSB1bmRlZmluZWQsXG4gICAgICB2ZWN0b3I6IHZlY3RvciAhPT0gdW5kZWZpbmVkLFxuICAgICAgdmVjdG9yTW9kZTpcbiAgICAgICAgdmVjdG9yID09PSB1bmRlZmluZWQgPyBcIm9mZlwiIDogdHlwZW9mIG1lbW9yeVNldHRpbmcgPT09IFwib2JqZWN0XCIgPyBcImRlZGljYXRlZFwiIDogXCJzaGFyZWRcIixcbiAgICB9KTtcblxuICAgIHJldHVybiBuZXcgTWVtb3J5KHtcbiAgICAgIC4uLihzdG9yYWdlID8geyBzdG9yYWdlIH0gOiB7fSksXG4gICAgICAuLi4odmVjdG9yID8geyB2ZWN0b3IsIGVtYmVkZGVyOiBmYXN0ZW1iZWQgfSA6IHt9KSxcbiAgICAgIG9wdGlvbnM6IHtcbiAgICAgICAgbGFzdE1lc3NhZ2VzOiAxMCxcbiAgICAgICAgLi4uKHZlY3RvciA/IHsgc2VtYW50aWNSZWNhbGw6IHsgdG9wSzogMywgbWVzc2FnZVJhbmdlOiAyIH0gfSA6IHt9KSxcbiAgICAgICAgLy8gQXV0by1uYW1lIGVhY2ggdGhyZWFkIGZyb20gaXRzIG9wZW5pbmcgdHVybiBzbyB0aGVcbiAgICAgICAgLy8gY29udmVyc2F0aW9uIGxpc3QgdGhlIFVJIHJlbmRlcnMgc2hvd3MgbWVhbmluZ2Z1bCB0aXRsZXNcbiAgICAgICAgLy8gaW5zdGVhZCBvZiByYXcgaWRzLiBUaXRsaW5nIHJ1bnMgb24gdGhlIHNtYWxsIC8gZmFzdCBjaGF0XG4gICAgICAgIC8vIHRpZXIgKHNlZSBgc3VtbWFyaXplLnRzYCkgcmF0aGVyIHRoYW4gdGhlIGFnZW50J3MgcHJpbWFyeVxuICAgICAgICAvLyBtb2RlbCwgc28gbmFtaW5nIGEgdGhyZWFkIG5ldmVyIHNwZW5kcyB0aGUgaGVhdnl3ZWlnaHQgbW9kZWwuXG4gICAgICAgIC8vIE9ubHkgbWVhbmluZ2Z1bCB3aGVuIHN0b3JhZ2UgaXMgb247IGhhcm1sZXNzIG90aGVyd2lzZS5cbiAgICAgICAgLi4uKHN0b3JhZ2VcbiAgICAgICAgICA/IHtcbiAgICAgICAgICAgICAgZ2VuZXJhdGVUaXRsZToge1xuICAgICAgICAgICAgICAgIG1vZGVsOiBzdW1tYXJ5TW9kZWwodGhpcy5jb25maWcpLFxuICAgICAgICAgICAgICAgIGluc3RydWN0aW9uczogVElUTEVfSU5TVFJVQ1RJT05TLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfVxuICAgICAgICAgIDoge30pLFxuICAgICAgfSxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRTdG9yYWdlKGFnZW50SWQ6IHN0cmluZywgc2V0dGluZzogU3RvcmFnZVNldHRpbmcpOiBQb3N0Z3Jlc1N0b3JlIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIXNldHRpbmcpIHJldHVybiB1bmRlZmluZWQ7XG4gICAgaWYgKHR5cGVvZiBzZXR0aW5nID09PSBcImJvb2xlYW5cIikge1xuICAgICAgcmV0dXJuIHdpdGhTb2Z0U3RvcmFnZUluaXQoXG4gICAgICAgIG5ldyBQb3N0Z3Jlc1N0b3JlKHtcbiAgICAgICAgICBpZDogYG1hc3RyYS1zdG9yZV9fJHthZ2VudElkfWAsXG4gICAgICAgICAgc2NoZW1hTmFtZTogYWdlbnRTdG9yYWdlU2NoZW1hTmFtZShhZ2VudElkKSxcbiAgICAgICAgICBwb29sOiB0aGlzLnNlcnZpY2VQcmluY2lwYWxQb29sLFxuICAgICAgICB9KSxcbiAgICAgICk7XG4gICAgfVxuICAgIC8vIENhc3Q6IGB3aXRoSWRgIGd1YXJhbnRlZXMgYGlkYCBpcyBzZXQsIGJ1dCB0aGUgZGlzdHJpYnV0aXZlXG4gICAgLy8gT21pdCArIGBpZD86IHN0cmluZ2Agc2hhcGUgZG9lc24ndCBzdHJ1Y3R1cmFsbHkgbmFycm93IHRvIHRoZVxuICAgIC8vIGRpc2NyaW1pbmF0ZWQgdW5pb24gbWVtYmVycy4gUnVudGltZSBzaGFwZSBpcyBpZGVudGljYWwuXG4gICAgcmV0dXJuIHdpdGhTb2Z0U3RvcmFnZUluaXQoXG4gICAgICBuZXcgUG9zdGdyZXNTdG9yZShcbiAgICAgICAgd2l0aElkKHNldHRpbmcsIGBtYXN0cmEtc3RvcmVfXyR7YWdlbnRJZH1gKSBhcyBDb25zdHJ1Y3RvclBhcmFtZXRlcnM8XG4gICAgICAgICAgdHlwZW9mIFBvc3RncmVzU3RvcmVcbiAgICAgICAgPlswXSxcbiAgICAgICksXG4gICAgKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNvbHZlIHRoZSBhZ2VudCdzIHZlY3RvciBzdG9yZS4gQ2FzY2FkZTpcbiAgICpcbiAgICogLSBmYWxzeTogbm8gdmVjdG9yLlxuICAgKiAtIGBib29sZWFuYCAvIGB1bmRlZmluZWQtaW5oZXJpdGluZy10cnVlYDogcmV0dXJuIHRoZSBzaGFyZWRcbiAgICogICBzaW5nbGV0b24gKGJ1aWx0IGxhemlseSBvbiBmaXJzdCBjYWxsKS4gQWxsIGFnZW50cyB0aGF0XG4gICAqICAgZGVmYXVsdC1lbmFibGUgbWVtb3J5IHdyaXRlIGludG8gYW5kIHJlY2FsbCBmcm9tIG9uZSBpbmRleC5cbiAgICogLSBvYmplY3Q6IGJ1aWxkIGEgZGVkaWNhdGVkIGBQZ1ZlY3RvcmAgZm9yIHRoaXMgYWdlbnQuXG4gICAqL1xuICBwcml2YXRlIGJ1aWxkVmVjdG9yKHNldHRpbmc6IE1lbW9yeVNldHRpbmcpOiBQZ1ZlY3RvciB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKCFzZXR0aW5nKSByZXR1cm4gdW5kZWZpbmVkO1xuICAgIGlmICh0eXBlb2Ygc2V0dGluZyA9PT0gXCJib29sZWFuXCIpIHJldHVybiB0aGlzLmdldFNoYXJlZFZlY3RvcigpO1xuICAgIHJldHVybiBidWlsZFBnVmVjdG9yKHNldHRpbmcpO1xuICB9XG5cbiAgcHJpdmF0ZSBnZXRTaGFyZWRWZWN0b3IoKTogUGdWZWN0b3Ige1xuICAgIGlmICghdGhpcy5zaGFyZWRWZWN0b3IpIHtcbiAgICAgIHRoaXMuc2hhcmVkVmVjdG9yID0gYnVpbGRTaGFyZWRQZ1ZlY3Rvcih0aGlzLnNlcnZpY2VQcmluY2lwYWxQb29sKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc2hhcmVkVmVjdG9yO1xuICB9XG59XG5cbi8qKlxuICogQnVpbGQgdGhlIHNoYXJlZCBgUGdWZWN0b3JgIHRoYXQgYmFja3MgdGhlIGRlZmF1bHRcbiAqIGBkZWYubWVtb3J5ID09PSB0cnVlYCBjYXNlIGFjcm9zcyBldmVyeSBhZ2VudC5cbiAqXG4gKiBgUGdWZWN0b3JgJ3MgY29uc3RydWN0b3IgYWNjZXB0cyBvbmx5IGNvbm5lY3Rpb24tc3R5bGUgY29uZmlnc1xuICogKGBIb3N0Q29uZmlnYCAvIGBDb25uZWN0aW9uU3RyaW5nQ29uZmlnYCAvIGBDbGllbnRDb25maWdgKTsgdGhlcmUgaXNcbiAqIG5vIGB7IHBvb2wgfWAgc2hvcnRoYW5kIHRoZSB3YXkgYFBvc3RncmVzU3RvcmVgIGhhcyBvbmUuIFdvcnNlLCB0aGVcbiAqIGNvbnN0cnVjdG9yIHN5bmNocm9ub3VzbHkga2lja3Mgb2ZmIGEgYGNhY2hlV2FybXVwUHJvbWlzZWAgSUlGRSB0aGF0XG4gKiBjYWxscyBgdGhpcy5wb29sLmNvbm5lY3QoKWAgYmVmb3JlIHJldHVybmluZywgc28gd2UgY2FuJ3QgY2xlYW5seVxuICogaGFuZCBpdCBhbiBpbmVydCBjb25maWcgYW5kIHBhdGNoIHRoZSBwb29sIGFmdGVyd2FyZHMuXG4gKlxuICogVGhlIHRyaWNrOiBwYXNzIGlsbGVnYWwtYnV0LXZhbGlkYXRpb24tcGFzc2luZyBwbGFjZWhvbGRlcnMgc28gdGhlXG4gKiB3YXJtdXAncyBgbmV0LmNvbm5lY3QoKWAgcmVqZWN0cyBzeW5jaHJvbm91c2x5IHdpdGggYFJhbmdlRXJyb3JgXG4gKiAoTm9kZSB2YWxpZGF0ZXMgYDAgPD0gcG9ydCA8IDY1NTM2YCkuIFRoZSBJSUZFJ3MgYGNhdGNoIHt9YCBzd2FsbG93c1xuICogaXQsIG5vIEROUyBsb29rdXAgb3IgVENQIGF0dGVtcHQgaGFwcGVucywgYW5kIHdlIHRoZW4gc3dhcFxuICogYHBnVmVjdG9yLnBvb2xgIHRvIHRoZSBsYWtlYmFzZSBwb29sLiBFdmVyeSBzdWJzZXF1ZW50IGBQZ1ZlY3RvcmBcbiAqIG1ldGhvZCByZWFkcyBgdGhpcy5wb29sYCBhdCBjYWxsIHRpbWUsIHNvIGFsbCByZWFsIEkvTyBnb2VzIHRocm91Z2hcbiAqIHRoZSBsYWtlYmFzZSBwb29sIGZyb20gdGhlbiBvbi4gVGhlIHBsYWNlaG9sZGVyIHBvb2wgaXMgYC5lbmQoKWAnZFxuICogc28gaXRzIHNvY2tldCBib29rLWtlZXBpbmcgaXMgcmVsZWFzZWQuXG4gKi9cbmZ1bmN0aW9uIGJ1aWxkU2hhcmVkUGdWZWN0b3IocG9vbDogUG9vbCk6IFBnVmVjdG9yIHtcbiAgY29uc3QgdmVjdG9yID0gbmV3IFBnVmVjdG9yKHtcbiAgICBpZDogYHBnJHtoYXNoLmlkKCl9YCxcbiAgICAvLyBLZWVwIHRoZSByZWNhbGwgaW5kZXggb3V0IG9mIGBwdWJsaWNgOiBvbiBhIExha2ViYXNlIGRhdGFiYXNlIHRoZSBhcHBcbiAgICAvLyBzZXJ2aWNlIHByaW5jaXBhbCBoYXMgbm8gQ1JFQVRFIG9uIGBwdWJsaWNgIChQRzE1KyBsb2NrcyBpdCBkb3duKSwgc28gYVxuICAgIC8vIGRlZmF1bHQtc2NoZW1hIFBnVmVjdG9yIGZhaWxzIG9uIENSRUFURSBJTkRFWCB3aXRoIFwicGVybWlzc2lvbiBkZW5pZWQgZm9yXG4gICAgLy8gc2NoZW1hIHB1YmxpY1wiLiBQZ1ZlY3RvciBydW5zIENSRUFURSBTQ0hFTUEgSUYgTk9UIEVYSVNUUyBmb3IgYSBuYW1lZFxuICAgIC8vIHNjaGVtYSwgc28gdGhlIFNQIGNyZWF0ZXMgYW5kIG93bnMgYG1hc3RyYV9pbnN0YW5jZWAgKHRoZSBzYW1lXG4gICAgLy8gaW5zdGFuY2UtbGV2ZWwgc2NoZW1hIHRoZSB3b3JrZmxvdy1zbmFwc2hvdCBzdG9yZSB1c2VzKSBhbmQgdGhlIGluZGV4XG4gICAgLy8gbGFuZHMgdGhlcmUuIFRhYmxlIG5hbWVzIGRvbid0IGNvbGxpZGUgd2l0aCB0aGUgc3RvcmFnZSB0YWJsZXMuXG4gICAgc2NoZW1hTmFtZTogXCJtYXN0cmFfaW5zdGFuY2VcIixcbiAgICBob3N0OiBcIi0xXCIsXG4gICAgcG9ydDogLTEsXG4gICAgZGF0YWJhc2U6IFwiX1wiLFxuICAgIHVzZXI6IFwiX1wiLFxuICAgIHBhc3N3b3JkOiBcIl9cIixcbiAgfSk7XG4gIGNvbnN0IHBsYWNlaG9sZGVyID0gdmVjdG9yLnBvb2w7XG4gIHZlY3Rvci5wb29sID0gcG9vbDtcbiAgdm9pZCBwbGFjZWhvbGRlci5lbmQoKS5jYXRjaCgoKSA9PiB1bmRlZmluZWQpO1xuICByZXR1cm4gdmVjdG9yO1xufVxuXG4vKiogUGVyLWFnZW50IGRlZGljYXRlZCBgUGdWZWN0b3JgIChyYXJlOyBvcHQtaW4gdmlhIG9iamVjdCBvdmVycmlkZSkuICovXG5mdW5jdGlvbiBidWlsZFBnVmVjdG9yKHNldHRpbmc6IE1hc3RyYU1lbW9yeUNvbmZpZ092ZXJyaWRlKTogUGdWZWN0b3Ige1xuICByZXR1cm4gbmV3IFBnVmVjdG9yKFxuICAgIHdpdGhJZChzZXR0aW5nLCBgcGctdmVjdG9yX18ke2hhc2guaWQoKX1gKSBhcyBDb25zdHJ1Y3RvclBhcmFtZXRlcnM8dHlwZW9mIFBnVmVjdG9yPlswXSxcbiAgKTtcbn1cblxuLyoqIFRydWUgd2hlbiB0aGlzIHNldHRpbmcgcmVxdWlyZXMgdGhlIHNoYXJlZCBMYWtlYmFzZSBwb29sLiAqL1xuZnVuY3Rpb24gc2V0dGluZ05lZWRzU2hhcmVkUG9vbChzZXR0aW5nOiBTdG9yYWdlU2V0dGluZyB8IE1lbW9yeVNldHRpbmcgfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgcmV0dXJuIHNldHRpbmcgPT09IHRydWU7XG59XG5cbi8qKiBXYWxrIHRoZSB0aHJlZSBzaGFwZXMgb2YgYGNvbmZpZy5hZ2VudHNgIGludG8gYSBmbGF0IGxpc3QuICovXG5mdW5jdGlvbiBjb2xsZWN0QWdlbnREZWZpbml0aW9ucyhjb25maWc6IE1hc3RyYVBsdWdpbkNvbmZpZyk6IE1hc3RyYUFnZW50RGVmaW5pdGlvbltdIHtcbiAgY29uc3QgYWdlbnRzID0gY29uZmlnLmFnZW50cztcbiAgaWYgKCFhZ2VudHMpIHJldHVybiBbXTtcbiAgaWYgKEFycmF5LmlzQXJyYXkoYWdlbnRzKSkgcmV0dXJuIGFnZW50cztcbiAgaWYgKHR5cGVvZiAoYWdlbnRzIGFzIE1hc3RyYUFnZW50RGVmaW5pdGlvbikuaW5zdHJ1Y3Rpb25zID09PSBcInN0cmluZ1wiKSB7XG4gICAgcmV0dXJuIFthZ2VudHMgYXMgTWFzdHJhQWdlbnREZWZpbml0aW9uXTtcbiAgfVxuICByZXR1cm4gT2JqZWN0LnZhbHVlcyhhZ2VudHMgYXMgUmVjb3JkPHN0cmluZywgTWFzdHJhQWdlbnREZWZpbml0aW9uPik7XG59XG5cbi8qKiBGaWxsIGluIGEgZGVmYXVsdCBgaWRgIHdoZW4gdGhlIGNhbGxlciBkaWRuJ3Qgc3VwcGx5IG9uZS4gKi9cbmZ1bmN0aW9uIHdpdGhJZDxUIGV4dGVuZHMgeyBpZD86IHN0cmluZyB9Pih2YWx1ZTogVCwgZmFsbGJhY2s6IHN0cmluZyk6IFQge1xuICByZXR1cm4gdmFsdWUuaWQgPyB2YWx1ZSA6IHsgLi4udmFsdWUsIGlkOiBmYWxsYmFjayB9O1xufVxuIl19
package/package.json CHANGED
@@ -31,18 +31,18 @@
31
31
  "dependencies": {
32
32
  "@databricks/appkit": "^0.43.0",
33
33
  "@databricks/sdk-experimental": "^0.17.0",
34
- "@dbx-tools/appkit": "0.6.70",
35
- "@dbx-tools/core": "0.6.70",
36
- "@dbx-tools/databricks": "0.6.70",
37
- "@dbx-tools/fs": "0.6.70",
38
- "@dbx-tools/genie": "0.6.70",
39
- "@dbx-tools/model": "0.6.70",
40
- "@dbx-tools/path": "0.6.70",
41
- "@dbx-tools/shared-core": "0.6.70",
42
- "@dbx-tools/shared-fs": "0.6.70",
43
- "@dbx-tools/shared-genie": "0.6.70",
44
- "@dbx-tools/shared-mastra": "0.6.70",
45
- "@dbx-tools/shared-model": "0.6.70",
34
+ "@dbx-tools/appkit": "0.6.72",
35
+ "@dbx-tools/core": "0.6.72",
36
+ "@dbx-tools/databricks": "0.6.72",
37
+ "@dbx-tools/fs": "0.6.72",
38
+ "@dbx-tools/genie": "0.6.72",
39
+ "@dbx-tools/model": "0.6.72",
40
+ "@dbx-tools/path": "0.6.72",
41
+ "@dbx-tools/shared-core": "0.6.72",
42
+ "@dbx-tools/shared-fs": "0.6.72",
43
+ "@dbx-tools/shared-genie": "0.6.72",
44
+ "@dbx-tools/shared-mastra": "0.6.72",
45
+ "@dbx-tools/shared-model": "0.6.72",
46
46
  "@mastra/ai-sdk": "^1.6.0",
47
47
  "@mastra/core": "^1.47.0",
48
48
  "@mastra/express": "^1.4.2",
@@ -71,7 +71,7 @@
71
71
  "./package.json": "./package.json"
72
72
  }
73
73
  },
74
- "version": "0.6.70",
74
+ "version": "0.6.72",
75
75
  "types": "./lib/index.d.ts",
76
76
  "type": "module",
77
77
  "exports": {
package/src/memory.ts CHANGED
@@ -8,7 +8,10 @@
8
8
  * **per-agent** namespacing via {@link agentStorageSchemaName} so
9
9
  * conversation history stays isolated between agents in the same
10
10
  * database. `PostgresStore` auto-creates the schema with
11
- * `CREATE SCHEMA IF NOT EXISTS` on init.
11
+ * `CREATE SCHEMA IF NOT EXISTS` on init. A failed migration (common on
12
+ * Lakebase when the connecting role is not the table owner) is logged
13
+ * and skipped via {@link withSoftStorageInit} so existing tables keep
14
+ * serving instead of retrying DDL on every request.
12
15
  * - **Memory** (semantic recall via `PgVector`): defaults to a single
13
16
  * **shared** instance across every agent. Cross-agent recall on one
14
17
  * index is almost always what users want; opt into per-agent recall
@@ -30,7 +33,7 @@
30
33
  */
31
34
 
32
35
  import { getUsernameWithApiLookup } from "@databricks/appkit";
33
- import { hash, log } from "@dbx-tools/shared-core";
36
+ import { error, hash, log } from "@dbx-tools/shared-core";
34
37
  import { fastembed } from "@mastra/fastembed";
35
38
  import { Memory } from "@mastra/memory";
36
39
  import { PgVector, PostgresStore } from "@mastra/pg";
@@ -43,6 +46,70 @@ import { summaryModel, TITLE_INSTRUCTIONS } from "./summarize.ts";
43
46
 
44
47
  const logger = log.logger("mastra/memory");
45
48
 
49
+ /** Process-wide dedupe so instance + per-agent stores share one ownership log. */
50
+ const loggedMigrationErrors = new Set<string>();
51
+
52
+ /** Whether `LOG_LEVEL` is currently at or below debug. */
53
+ function isDebugEnabled(): boolean {
54
+ return log.isLevelEnabled("debug");
55
+ }
56
+
57
+ /**
58
+ * Soften {@link PostgresStore.init} so a failed migration (e.g. Lakebase
59
+ * `must be owner of table …` on `ALTER`) is logged once instead of rethrown
60
+ * on every storage call.
61
+ *
62
+ * Mastra's `augmentWithInit` retries init forever when it throws, so the
63
+ * only way to keep serving against an already-usable schema is to treat
64
+ * migration failure as success and mark the store initialized.
65
+ *
66
+ * Concurrent first callers share one soft attempt; `isInitialized` is set
67
+ * before the soft promise settles so later callers skip DDL entirely.
68
+ */
69
+ export function withSoftStorageInit(store: PostgresStore): PostgresStore {
70
+ const soft = store as unknown as {
71
+ init: () => Promise<void>;
72
+ id: string;
73
+ schema?: string;
74
+ isInitialized: boolean;
75
+ };
76
+ const originalInit = soft.init.bind(soft);
77
+ let softInitPromise: Promise<void> | undefined;
78
+
79
+ soft.init = async () => {
80
+ if (soft.isInitialized) return;
81
+ softInitPromise ??= (async () => {
82
+ try {
83
+ await originalInit();
84
+ } catch (err) {
85
+ // Mark success-for-serving before logging so a racing caller that
86
+ // passed the `isInitialized` check still joins this promise rather
87
+ // than starting another DDL pass.
88
+ soft.isInitialized = true;
89
+ const message = error.errorMessage(err);
90
+ if (!loggedMigrationErrors.has(message)) {
91
+ loggedMigrationErrors.add(message);
92
+ if (isDebugEnabled()) {
93
+ logger.error("mastra storage migration failed", err);
94
+ } else {
95
+ logger.warn("mastra storage migration failed", {
96
+ error: message,
97
+ storeId: soft.id,
98
+ schema: soft.schema,
99
+ });
100
+ }
101
+ }
102
+ }
103
+ })();
104
+ try {
105
+ await softInitPromise;
106
+ } finally {
107
+ soft.isInitialized = true;
108
+ }
109
+ };
110
+ return store;
111
+ }
112
+
46
113
  /**
47
114
  * Build a dedicated **service-principal** Lakebase pool for Mastra
48
115
  * memory from the lakebase plugin's resolved SP pg config.
@@ -129,15 +196,21 @@ export class MemoryBuilder {
129
196
  const setting = this.config.storage;
130
197
  if (!setting) return undefined;
131
198
  if (typeof setting === "object") {
132
- return new PostgresStore(
133
- withId(setting, "mastra-store__instance") as ConstructorParameters<typeof PostgresStore>[0],
199
+ return withSoftStorageInit(
200
+ new PostgresStore(
201
+ withId(setting, "mastra-store__instance") as ConstructorParameters<
202
+ typeof PostgresStore
203
+ >[0],
204
+ ),
134
205
  );
135
206
  }
136
- return new PostgresStore({
137
- id: "mastra-store__instance",
138
- schemaName: "mastra_instance",
139
- pool: this.servicePrincipalPool,
140
- });
207
+ return withSoftStorageInit(
208
+ new PostgresStore({
209
+ id: "mastra-store__instance",
210
+ schemaName: "mastra_instance",
211
+ pool: this.servicePrincipalPool,
212
+ }),
213
+ );
141
214
  }
142
215
 
143
216
  /**
@@ -192,17 +265,23 @@ export class MemoryBuilder {
192
265
  private buildStorage(agentId: string, setting: StorageSetting): PostgresStore | undefined {
193
266
  if (!setting) return undefined;
194
267
  if (typeof setting === "boolean") {
195
- return new PostgresStore({
196
- id: `mastra-store__${agentId}`,
197
- schemaName: agentStorageSchemaName(agentId),
198
- pool: this.servicePrincipalPool,
199
- });
268
+ return withSoftStorageInit(
269
+ new PostgresStore({
270
+ id: `mastra-store__${agentId}`,
271
+ schemaName: agentStorageSchemaName(agentId),
272
+ pool: this.servicePrincipalPool,
273
+ }),
274
+ );
200
275
  }
201
276
  // Cast: `withId` guarantees `id` is set, but the distributive
202
277
  // Omit + `id?: string` shape doesn't structurally narrow to the
203
278
  // discriminated union members. Runtime shape is identical.
204
- return new PostgresStore(
205
- withId(setting, `mastra-store__${agentId}`) as ConstructorParameters<typeof PostgresStore>[0],
279
+ return withSoftStorageInit(
280
+ new PostgresStore(
281
+ withId(setting, `mastra-store__${agentId}`) as ConstructorParameters<
282
+ typeof PostgresStore
283
+ >[0],
284
+ ),
206
285
  );
207
286
  }
208
287