@dbx-tools/genie 0.9.188 → 0.9.190
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -6
- package/index.ts +2 -2
- package/lib/index.d.ts +2 -2
- package/lib/index.js +3 -3
- package/lib/src/visualization.d.ts +9 -2
- package/lib/src/visualization.js +55 -5
- package/package.json +13 -4
- package/src/visualization.ts +58 -4
package/README.md
CHANGED
|
@@ -183,7 +183,7 @@ thrown.
|
|
|
183
183
|
- `pollIntervalMs` - fallback polling cadence, default `500`.
|
|
184
184
|
- `context` - SDK `Context` or `AbortSignal` for cancellation.
|
|
185
185
|
|
|
186
|
-
## Download
|
|
186
|
+
## Download a chart image
|
|
187
187
|
|
|
188
188
|
After requesting visualizations, select the message attachment with a `viz`
|
|
189
189
|
field and download its PNG using the same conversation and message IDs:
|
|
@@ -207,10 +207,17 @@ if (visualization?.attachment_id) {
|
|
|
207
207
|
|
|
208
208
|
Use the visualization's attachment ID, not its linked query attachment ID.
|
|
209
209
|
The SDK's `raw: true` transport returns the binary body and keeps normal SDK
|
|
210
|
-
authentication and cancellation. The helper validates the PNG response
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
210
|
+
authentication and cancellation. The helper validates the PNG response, then
|
|
211
|
+
uses the optional `sharp` dependency to resize it to four times its original
|
|
212
|
+
width and height with Lanczos3 and apply a mild unsharp mask. If `sharp` is not
|
|
213
|
+
installed or cannot process the image, the helper returns the validated
|
|
214
|
+
original bytes. Processing happens before the bytes return to callers, so a
|
|
215
|
+
downstream cache stores the enhanced image when enhancement succeeds.
|
|
216
|
+
|
|
217
|
+
This is a raster cleanup fallback. If the source ECharts instance is available,
|
|
218
|
+
prefer `getDataURL({ pixelRatio: 3 })` or SVG so chart text is re-rendered rather
|
|
219
|
+
than enlarged from a screenshot. The endpoint also accepts visualization
|
|
220
|
+
attachments from Agent Mode conversations.
|
|
214
221
|
|
|
215
222
|
## Modules
|
|
216
223
|
|
|
@@ -219,7 +226,7 @@ conversations.
|
|
|
219
226
|
- `agentMode` - `genieAgentModeChat()`, availability classification, and Agent
|
|
220
227
|
Mode transport options plus Agent Mode conversation history.
|
|
221
228
|
- `space` - `getGenieSpace()` and `genieSampleQuestions()`.
|
|
222
|
-
- `visualization` - `downloadGenieVisualization()` for
|
|
229
|
+
- `visualization` - `downloadGenieVisualization()` for validated and optionally enhanced PNG downloads.
|
|
223
230
|
|
|
224
231
|
The AppKit-Mastra package builds its Genie tools on top of this driver. See
|
|
225
232
|
[@dbx-tools/appkit-mastra](../appkit-mastra) for the agent-level
|
package/index.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Hand edits are overwritten on the next watch; this file is read-only.
|
|
4
4
|
|
|
5
5
|
export const PACKAGE_IDENTIFIER = "@dbx-tools/genie";
|
|
6
|
-
export const PACKAGE_VERSION = "0.9.
|
|
6
|
+
export const PACKAGE_VERSION = "0.9.190";
|
|
7
7
|
export * as agentMode from "./src/agent-mode.ts";
|
|
8
8
|
export * as chat from "./src/chat.ts";
|
|
9
9
|
export * as feedback from "./src/feedback.ts";
|
|
@@ -17,5 +17,5 @@ export { sendGenieMessageFeedback } from "./src/feedback.ts";
|
|
|
17
17
|
export type { SendGenieMessageFeedbackOptions } from "./src/feedback.ts";
|
|
18
18
|
export { createGenieSpace, getGenieSpace, genieSampleQuestions } from "./src/space.ts";
|
|
19
19
|
export type { GetGenieSpaceOptions, CreateGenieSpaceOptions } from "./src/space.ts";
|
|
20
|
-
export { downloadGenieVisualization } from "./src/visualization.ts";
|
|
20
|
+
export { upscaleGenieVisualizationPng, downloadGenieVisualization } from "./src/visualization.ts";
|
|
21
21
|
export type { DownloadGenieVisualizationOptions } from "./src/visualization.ts";
|
package/lib/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const PACKAGE_IDENTIFIER = "@dbx-tools/genie";
|
|
2
|
-
export declare const PACKAGE_VERSION = "0.9.
|
|
2
|
+
export declare const PACKAGE_VERSION = "0.9.190";
|
|
3
3
|
export * as agentMode from "./src/agent-mode.ts";
|
|
4
4
|
export * as chat from "./src/chat.ts";
|
|
5
5
|
export * as feedback from "./src/feedback.ts";
|
|
@@ -13,5 +13,5 @@ export { sendGenieMessageFeedback } from "./src/feedback.ts";
|
|
|
13
13
|
export type { SendGenieMessageFeedbackOptions } from "./src/feedback.ts";
|
|
14
14
|
export { createGenieSpace, getGenieSpace, genieSampleQuestions } from "./src/space.ts";
|
|
15
15
|
export type { GetGenieSpaceOptions, CreateGenieSpaceOptions } from "./src/space.ts";
|
|
16
|
-
export { downloadGenieVisualization } from "./src/visualization.ts";
|
|
16
|
+
export { upscaleGenieVisualizationPng, downloadGenieVisualization } from "./src/visualization.ts";
|
|
17
17
|
export type { DownloadGenieVisualizationOptions } from "./src/visualization.ts";
|
package/lib/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Regenerated from the exporting modules in ./src.
|
|
3
3
|
// Hand edits are overwritten on the next watch; this file is read-only.
|
|
4
4
|
export const PACKAGE_IDENTIFIER = "@dbx-tools/genie";
|
|
5
|
-
export const PACKAGE_VERSION = "0.9.
|
|
5
|
+
export const PACKAGE_VERSION = "0.9.190";
|
|
6
6
|
export * as agentMode from "./src/agent-mode.js";
|
|
7
7
|
export * as chat from "./src/chat.js";
|
|
8
8
|
export * as feedback from "./src/feedback.js";
|
|
@@ -12,5 +12,5 @@ export { genieAgentModeChat, listAgentModeConversation, isAgentModeUnavailable }
|
|
|
12
12
|
export { genieChat, genieEventChat } from "./src/chat.js";
|
|
13
13
|
export { sendGenieMessageFeedback } from "./src/feedback.js";
|
|
14
14
|
export { createGenieSpace, getGenieSpace, genieSampleQuestions } from "./src/space.js";
|
|
15
|
-
export { downloadGenieVisualization } from "./src/visualization.js";
|
|
16
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
15
|
+
export { upscaleGenieVisualizationPng, downloadGenieVisualization } from "./src/visualization.js";
|
|
16
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxrQkFBa0IsQ0FBQztBQUNyRCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsU0FBUyxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxTQUFTLE1BQU0scUJBQXFCLENBQUM7QUFDakQsT0FBTyxLQUFLLElBQUksTUFBTSxlQUFlLENBQUM7QUFDdEMsT0FBTyxLQUFLLFFBQVEsTUFBTSxtQkFBbUIsQ0FBQztBQUM5QyxPQUFPLEtBQUssS0FBSyxNQUFNLGdCQUFnQixDQUFDO0FBQ3hDLE9BQU8sS0FBSyxhQUFhLE1BQU0sd0JBQXdCLENBQUM7QUFDeEQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLHlCQUF5QixFQUFFLHNCQUFzQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFNUcsT0FBTyxFQUFFLFNBQVMsRUFBRSxjQUFjLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFMUQsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFN0QsT0FBTyxFQUFFLGdCQUFnQixFQUFFLGFBQWEsRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRXZGLE9BQU8sRUFBRSw0QkFBNEIsRUFBRSwwQkFBMEIsRUFBRSxNQUFNLHdCQUF3QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gR0VORVJBVEVEIGJ5IHByb2plbiB3YXRjaCAtIERPIE5PVCBFRElULlxuLy8gUmVnZW5lcmF0ZWQgZnJvbSB0aGUgZXhwb3J0aW5nIG1vZHVsZXMgaW4gLi9zcmMuXG4vLyBIYW5kIGVkaXRzIGFyZSBvdmVyd3JpdHRlbiBvbiB0aGUgbmV4dCB3YXRjaDsgdGhpcyBmaWxlIGlzIHJlYWQtb25seS5cblxuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfSURFTlRJRklFUiA9IFwiQGRieC10b29scy9nZW5pZVwiO1xuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfVkVSU0lPTiA9IFwiMC45LjE5MFwiO1xuZXhwb3J0ICogYXMgYWdlbnRNb2RlIGZyb20gXCIuL3NyYy9hZ2VudC1tb2RlLnRzXCI7XG5leHBvcnQgKiBhcyBjaGF0IGZyb20gXCIuL3NyYy9jaGF0LnRzXCI7XG5leHBvcnQgKiBhcyBmZWVkYmFjayBmcm9tIFwiLi9zcmMvZmVlZGJhY2sudHNcIjtcbmV4cG9ydCAqIGFzIHNwYWNlIGZyb20gXCIuL3NyYy9zcGFjZS50c1wiO1xuZXhwb3J0ICogYXMgdmlzdWFsaXphdGlvbiBmcm9tIFwiLi9zcmMvdmlzdWFsaXphdGlvbi50c1wiO1xuZXhwb3J0IHsgZ2VuaWVBZ2VudE1vZGVDaGF0LCBsaXN0QWdlbnRNb2RlQ29udmVyc2F0aW9uLCBpc0FnZW50TW9kZVVuYXZhaWxhYmxlIH0gZnJvbSBcIi4vc3JjL2FnZW50LW1vZGUudHNcIjtcbmV4cG9ydCB0eXBlIHsgR2VuaWVBZ2VudE1vZGVPcHRpb25zIH0gZnJvbSBcIi4vc3JjL2FnZW50LW1vZGUudHNcIjtcbmV4cG9ydCB7IGdlbmllQ2hhdCwgZ2VuaWVFdmVudENoYXQgfSBmcm9tIFwiLi9zcmMvY2hhdC50c1wiO1xuZXhwb3J0IHR5cGUgeyBHZW5pZUNoYXRPcHRpb25zIH0gZnJvbSBcIi4vc3JjL2NoYXQudHNcIjtcbmV4cG9ydCB7IHNlbmRHZW5pZU1lc3NhZ2VGZWVkYmFjayB9IGZyb20gXCIuL3NyYy9mZWVkYmFjay50c1wiO1xuZXhwb3J0IHR5cGUgeyBTZW5kR2VuaWVNZXNzYWdlRmVlZGJhY2tPcHRpb25zIH0gZnJvbSBcIi4vc3JjL2ZlZWRiYWNrLnRzXCI7XG5leHBvcnQgeyBjcmVhdGVHZW5pZVNwYWNlLCBnZXRHZW5pZVNwYWNlLCBnZW5pZVNhbXBsZVF1ZXN0aW9ucyB9IGZyb20gXCIuL3NyYy9zcGFjZS50c1wiO1xuZXhwb3J0IHR5cGUgeyBHZXRHZW5pZVNwYWNlT3B0aW9ucywgQ3JlYXRlR2VuaWVTcGFjZU9wdGlvbnMgfSBmcm9tIFwiLi9zcmMvc3BhY2UudHNcIjtcbmV4cG9ydCB7IHVwc2NhbGVHZW5pZVZpc3VhbGl6YXRpb25QbmcsIGRvd25sb2FkR2VuaWVWaXN1YWxpemF0aW9uIH0gZnJvbSBcIi4vc3JjL3Zpc3VhbGl6YXRpb24udHNcIjtcbmV4cG9ydCB0eXBlIHsgRG93bmxvYWRHZW5pZVZpc3VhbGl6YXRpb25PcHRpb25zIH0gZnJvbSBcIi4vc3JjL3Zpc3VhbGl6YXRpb24udHNcIjtcbiJdfQ==
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { type WorkspaceClient } from "@databricks/appkit";
|
|
2
2
|
import { type ContextLike } from "@dbx-tools/appkit";
|
|
3
3
|
import { type GenieVisualizationRequest } from "@dbx-tools/shared-genie";
|
|
4
|
+
/**
|
|
5
|
+
* Resize a Genie screenshot to four times its source dimensions with Lanczos3,
|
|
6
|
+
* then apply a mild unsharp mask. Returns the original bytes when the optional
|
|
7
|
+
* Sharp runtime is unavailable or rejects the image.
|
|
8
|
+
*/
|
|
9
|
+
export declare function upscaleGenieVisualizationPng(inputBytes: Uint8Array): Promise<Uint8Array>;
|
|
4
10
|
/** Identity and cancellation for a Genie visualization download. */
|
|
5
11
|
export interface DownloadGenieVisualizationOptions {
|
|
6
12
|
/** Workspace client whose identity owns the conversation. */
|
|
@@ -9,7 +15,8 @@ export interface DownloadGenieVisualizationOptions {
|
|
|
9
15
|
context?: ContextLike;
|
|
10
16
|
}
|
|
11
17
|
/**
|
|
12
|
-
* Download Genie's
|
|
13
|
-
* The SDK's raw transport preserves binary responses and its normal authentication
|
|
18
|
+
* Download Genie's PNG and apply optional raster cleanup before returning it.
|
|
19
|
+
* The SDK's raw transport preserves binary responses and its normal authentication;
|
|
20
|
+
* source-chart exports should still be preferred when they are available.
|
|
14
21
|
*/
|
|
15
22
|
export declare function downloadGenieVisualization(input: GenieVisualizationRequest, options?: DownloadGenieVisualizationOptions): Promise<Uint8Array>;
|
package/lib/src/visualization.js
CHANGED
|
@@ -1,13 +1,63 @@
|
|
|
1
1
|
import { createWorkspaceClient } from "@databricks/appkit";
|
|
2
2
|
import { toContext } from "@dbx-tools/appkit";
|
|
3
|
-
import { isRecord } from "@dbx-tools/shared-core";
|
|
3
|
+
import { isRecord, log, toError } from "@dbx-tools/shared-core";
|
|
4
4
|
import { genieVisualizationDownloadPath, } from "@dbx-tools/shared-genie";
|
|
5
|
+
const logger = log.logger("genie/visualization");
|
|
6
|
+
const GENIE_PNG_SCALE = 4;
|
|
7
|
+
const GENIE_PNG_SHARPEN = { sigma: 1.1, m1: 0.9, m2: 0.02 };
|
|
8
|
+
let sharpFactoryPromise;
|
|
5
9
|
function isByteStream(value) {
|
|
6
10
|
return (isRecord(value) && typeof value.getReader === "function" && typeof value.cancel === "function");
|
|
7
11
|
}
|
|
12
|
+
async function loadSharp() {
|
|
13
|
+
sharpFactoryPromise ??= import("sharp")
|
|
14
|
+
.then((module) => module.default)
|
|
15
|
+
.catch((error) => {
|
|
16
|
+
logger.debug("PNG enhancement unavailable; serving the original Genie image", {
|
|
17
|
+
error: toError(error),
|
|
18
|
+
});
|
|
19
|
+
return undefined;
|
|
20
|
+
});
|
|
21
|
+
return sharpFactoryPromise;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Resize a Genie screenshot to four times its source dimensions with Lanczos3,
|
|
25
|
+
* then apply a mild unsharp mask. Returns the original bytes when the optional
|
|
26
|
+
* Sharp runtime is unavailable or rejects the image.
|
|
27
|
+
*/
|
|
28
|
+
export async function upscaleGenieVisualizationPng(inputBytes) {
|
|
29
|
+
const sharp = await loadSharp();
|
|
30
|
+
if (!sharp)
|
|
31
|
+
return inputBytes;
|
|
32
|
+
try {
|
|
33
|
+
const input = Buffer.from(inputBytes);
|
|
34
|
+
const metadata = await sharp(input).metadata();
|
|
35
|
+
if (!metadata.width || !metadata.height) {
|
|
36
|
+
throw new Error("Could not read Genie visualization dimensions");
|
|
37
|
+
}
|
|
38
|
+
const output = await sharp(input)
|
|
39
|
+
.resize({
|
|
40
|
+
width: metadata.width * GENIE_PNG_SCALE,
|
|
41
|
+
height: metadata.height * GENIE_PNG_SCALE,
|
|
42
|
+
kernel: sharp.kernel.lanczos3,
|
|
43
|
+
fit: "fill",
|
|
44
|
+
})
|
|
45
|
+
.sharpen(GENIE_PNG_SHARPEN)
|
|
46
|
+
.png()
|
|
47
|
+
.toBuffer();
|
|
48
|
+
return new Uint8Array(output);
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
logger.warn("PNG enhancement failed; serving the original Genie image", {
|
|
52
|
+
error: toError(error),
|
|
53
|
+
});
|
|
54
|
+
return inputBytes;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
8
57
|
/**
|
|
9
|
-
* Download Genie's
|
|
10
|
-
* The SDK's raw transport preserves binary responses and its normal authentication
|
|
58
|
+
* Download Genie's PNG and apply optional raster cleanup before returning it.
|
|
59
|
+
* The SDK's raw transport preserves binary responses and its normal authentication;
|
|
60
|
+
* source-chart exports should still be preferred when they are available.
|
|
11
61
|
*/
|
|
12
62
|
export async function downloadGenieVisualization(input, options = {}) {
|
|
13
63
|
const client = options.workspaceClient ?? createWorkspaceClient();
|
|
@@ -39,6 +89,6 @@ export async function downloadGenieVisualization(input, options = {}) {
|
|
|
39
89
|
bytes[7] !== 0x0a) {
|
|
40
90
|
throw new TypeError("Genie returned an invalid PNG visualization");
|
|
41
91
|
}
|
|
42
|
-
return bytes;
|
|
92
|
+
return upscaleGenieVisualizationPng(bytes);
|
|
43
93
|
}
|
|
44
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlzdWFsaXphdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy92aXN1YWxpemF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxxQkFBcUIsRUFBd0IsTUFBTSxvQkFBb0IsQ0FBQztBQUNqRixPQUFPLEVBQW9CLFNBQVMsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNsRCxPQUFPLEVBRUwsOEJBQThCLEdBQy9CLE1BQU0seUJBQXlCLENBQUM7QUFFakMsU0FBUyxZQUFZLENBQUMsS0FBYztJQUNsQyxPQUFPLENBQ0wsUUFBUSxDQUFDLEtBQUssQ0FBQyxJQUFJLE9BQU8sS0FBSyxDQUFDLFNBQVMsS0FBSyxVQUFVLElBQUksT0FBTyxLQUFLLENBQUMsTUFBTSxLQUFLLFVBQVUsQ0FDL0YsQ0FBQztBQUNKLENBQUM7QUFVRDs7O0dBR0c7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLDBCQUEwQixDQUM5QyxLQUFnQyxFQUNoQyxVQUE2QyxFQUFFO0lBRS9DLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxlQUFlLElBQUkscUJBQXFCLEVBQUUsQ0FBQztJQUNsRSxNQUFNLFFBQVEsR0FBRyxNQUFNLE1BQU0sQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUM3QztRQUNFLElBQUksRUFBRSw4QkFBOEIsQ0FBQyxLQUFLLENBQUM7UUFDM0MsTUFBTSxFQUFFLEtBQUs7UUFDYixPQUFPLEVBQUUsSUFBSSxPQUFPLENBQUMsRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLENBQUM7UUFDN0MsZUFBZSxFQUFFLENBQUMsY0FBYyxDQUFDO1FBQ2pDLEdBQUcsRUFBRSxJQUFJO0tBQ1YsRUFDRCxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQ3pELENBQUM7SUFDRixJQUNFLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQztRQUNuQixPQUFPLFFBQVEsQ0FBQyxjQUFjLENBQUMsS0FBSyxRQUFRO1FBQzVDLFFBQVEsQ0FBQyxjQUFjLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLEtBQUssV0FBVztRQUM1RSxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLEVBQ2hDLENBQUM7UUFDRCxJQUFJLFFBQVEsQ0FBQyxRQUFRLENBQUMsSUFBSSxZQUFZLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7WUFDMUQsTUFBTSxRQUFRLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUMxRCxDQUFDO1FBQ0QsTUFBTSxJQUFJLFNBQVMsQ0FBQywwQ0FBMEMsQ0FBQyxDQUFDO0lBQ2xFLENBQUM7SUFDRCxNQUFNLEtBQUssR0FBRyxJQUFJLFVBQVUsQ0FBQyxNQUFNLElBQUksUUFBUSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO0lBQ2xGLElBQ0UsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDO1FBQ2hCLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJO1FBQ2pCLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJO1FBQ2pCLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJO1FBQ2pCLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJO1FBQ2pCLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJO1FBQ2pCLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJO1FBQ2pCLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJO1FBQ2pCLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJLEVBQ2pCLENBQUM7UUFDRCxNQUFNLElBQUksU0FBUyxDQUFDLDZDQUE2QyxDQUFDLENBQUM7SUFDckUsQ0FBQztJQUNELE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNyZWF0ZVdvcmtzcGFjZUNsaWVudCwgdHlwZSBXb3Jrc3BhY2VDbGllbnQgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0XCI7XG5pbXBvcnQgeyB0eXBlIENvbnRleHRMaWtlLCB0b0NvbnRleHQgfSBmcm9tIFwiQGRieC10b29scy9hcHBraXRcIjtcbmltcG9ydCB7IGlzUmVjb3JkIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7XG4gIHR5cGUgR2VuaWVWaXN1YWxpemF0aW9uUmVxdWVzdCxcbiAgZ2VuaWVWaXN1YWxpemF0aW9uRG93bmxvYWRQYXRoLFxufSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtZ2VuaWVcIjtcblxuZnVuY3Rpb24gaXNCeXRlU3RyZWFtKHZhbHVlOiB1bmtub3duKTogdmFsdWUgaXMgUmVhZGFibGVTdHJlYW08VWludDhBcnJheT4ge1xuICByZXR1cm4gKFxuICAgIGlzUmVjb3JkKHZhbHVlKSAmJiB0eXBlb2YgdmFsdWUuZ2V0UmVhZGVyID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIHZhbHVlLmNhbmNlbCA9PT0gXCJmdW5jdGlvblwiXG4gICk7XG59XG5cbi8qKiBJZGVudGl0eSBhbmQgY2FuY2VsbGF0aW9uIGZvciBhIEdlbmllIHZpc3VhbGl6YXRpb24gZG93bmxvYWQuICovXG5leHBvcnQgaW50ZXJmYWNlIERvd25sb2FkR2VuaWVWaXN1YWxpemF0aW9uT3B0aW9ucyB7XG4gIC8qKiBXb3Jrc3BhY2UgY2xpZW50IHdob3NlIGlkZW50aXR5IG93bnMgdGhlIGNvbnZlcnNhdGlvbi4gKi9cbiAgd29ya3NwYWNlQ2xpZW50PzogV29ya3NwYWNlQ2xpZW50O1xuICAvKiogRXh0ZXJuYWwgY2FuY2VsbGF0aW9uIGZvciB0aGUgcmVxdWVzdCBhbmQgaW1hZ2UgYm9keS4gKi9cbiAgY29udGV4dD86IENvbnRleHRMaWtlO1xufVxuXG4vKipcbiAqIERvd25sb2FkIEdlbmllJ3Mgb3JpZ2luYWwgUE5HIGJ5dGVzIHdpdGhvdXQgcmVkcmF3aW5nIG9yIHRyYW5zY29kaW5nIHRoZW0uXG4gKiBUaGUgU0RLJ3MgcmF3IHRyYW5zcG9ydCBwcmVzZXJ2ZXMgYmluYXJ5IHJlc3BvbnNlcyBhbmQgaXRzIG5vcm1hbCBhdXRoZW50aWNhdGlvbi5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRvd25sb2FkR2VuaWVWaXN1YWxpemF0aW9uKFxuICBpbnB1dDogR2VuaWVWaXN1YWxpemF0aW9uUmVxdWVzdCxcbiAgb3B0aW9uczogRG93bmxvYWRHZW5pZVZpc3VhbGl6YXRpb25PcHRpb25zID0ge30sXG4pOiBQcm9taXNlPFVpbnQ4QXJyYXk+IHtcbiAgY29uc3QgY2xpZW50ID0gb3B0aW9ucy53b3Jrc3BhY2VDbGllbnQgPz8gY3JlYXRlV29ya3NwYWNlQ2xpZW50KCk7XG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgY2xpZW50LmFwaUNsaWVudC5yZXF1ZXN0KFxuICAgIHtcbiAgICAgIHBhdGg6IGdlbmllVmlzdWFsaXphdGlvbkRvd25sb2FkUGF0aChpbnB1dCksXG4gICAgICBtZXRob2Q6IFwiR0VUXCIsXG4gICAgICBoZWFkZXJzOiBuZXcgSGVhZGVycyh7IGFjY2VwdDogXCJpbWFnZS9wbmdcIiB9KSxcbiAgICAgIHJlc3BvbnNlSGVhZGVyczogW1wiY29udGVudC10eXBlXCJdLFxuICAgICAgcmF3OiB0cnVlLFxuICAgIH0sXG4gICAgb3B0aW9ucy5jb250ZXh0ID8gdG9Db250ZXh0KG9wdGlvbnMuY29udGV4dCkgOiB1bmRlZmluZWQsXG4gICk7XG4gIGlmIChcbiAgICAhaXNSZWNvcmQocmVzcG9uc2UpIHx8XG4gICAgdHlwZW9mIHJlc3BvbnNlW1wiY29udGVudC10eXBlXCJdICE9PSBcInN0cmluZ1wiIHx8XG4gICAgcmVzcG9uc2VbXCJjb250ZW50LXR5cGVcIl0uc3BsaXQoXCI7XCIpWzBdPy50cmltKCkudG9Mb3dlckNhc2UoKSAhPT0gXCJpbWFnZS9wbmdcIiB8fFxuICAgICFpc0J5dGVTdHJlYW0ocmVzcG9uc2UuY29udGVudHMpXG4gICkge1xuICAgIGlmIChpc1JlY29yZChyZXNwb25zZSkgJiYgaXNCeXRlU3RyZWFtKHJlc3BvbnNlLmNvbnRlbnRzKSkge1xuICAgICAgYXdhaXQgcmVzcG9uc2UuY29udGVudHMuY2FuY2VsKCkuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB9XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmllIGRpZCBub3QgcmV0dXJuIGEgUE5HIHZpc3VhbGl6YXRpb25cIik7XG4gIH1cbiAgY29uc3QgYnl0ZXMgPSBuZXcgVWludDhBcnJheShhd2FpdCBuZXcgUmVzcG9uc2UocmVzcG9uc2UuY29udGVudHMpLmFycmF5QnVmZmVyKCkpO1xuICBpZiAoXG4gICAgYnl0ZXMubGVuZ3RoIDwgOCB8fFxuICAgIGJ5dGVzWzBdICE9PSAweDg5IHx8XG4gICAgYnl0ZXNbMV0gIT09IDB4NTAgfHxcbiAgICBieXRlc1syXSAhPT0gMHg0ZSB8fFxuICAgIGJ5dGVzWzNdICE9PSAweDQ3IHx8XG4gICAgYnl0ZXNbNF0gIT09IDB4MGQgfHxcbiAgICBieXRlc1s1XSAhPT0gMHgwYSB8fFxuICAgIGJ5dGVzWzZdICE9PSAweDFhIHx8XG4gICAgYnl0ZXNbN10gIT09IDB4MGFcbiAgKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmllIHJldHVybmVkIGFuIGludmFsaWQgUE5HIHZpc3VhbGl6YXRpb25cIik7XG4gIH1cbiAgcmV0dXJuIGJ5dGVzO1xufVxuIl19
|
|
94
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlzdWFsaXphdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy92aXN1YWxpemF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxxQkFBcUIsRUFBd0IsTUFBTSxvQkFBb0IsQ0FBQztBQUNqRixPQUFPLEVBQW9CLFNBQVMsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxRQUFRLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ2hFLE9BQU8sRUFFTCw4QkFBOEIsR0FDL0IsTUFBTSx5QkFBeUIsQ0FBQztBQUVqQyxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLHFCQUFxQixDQUFDLENBQUM7QUFDakQsTUFBTSxlQUFlLEdBQUcsQ0FBQyxDQUFDO0FBQzFCLE1BQU0saUJBQWlCLEdBQUcsRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBVyxDQUFDO0FBSXJFLElBQUksbUJBQWtFLENBQUM7QUFFdkUsU0FBUyxZQUFZLENBQUMsS0FBYztJQUNsQyxPQUFPLENBQ0wsUUFBUSxDQUFDLEtBQUssQ0FBQyxJQUFJLE9BQU8sS0FBSyxDQUFDLFNBQVMsS0FBSyxVQUFVLElBQUksT0FBTyxLQUFLLENBQUMsTUFBTSxLQUFLLFVBQVUsQ0FDL0YsQ0FBQztBQUNKLENBQUM7QUFFRCxLQUFLLFVBQVUsU0FBUztJQUN0QixtQkFBbUIsS0FBSyxNQUFNLENBQUMsT0FBTyxDQUFDO1NBQ3BDLElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQztTQUNoQyxLQUFLLENBQUMsQ0FBQyxLQUFjLEVBQUUsRUFBRTtRQUN4QixNQUFNLENBQUMsS0FBSyxDQUFDLCtEQUErRCxFQUFFO1lBQzVFLEtBQUssRUFBRSxPQUFPLENBQUMsS0FBSyxD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RyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUM7UUFDMUQsQ0FBQztRQUNELE1BQU0sSUFBSSxTQUFTLENBQUMsMENBQTBDLENBQUMsQ0FBQztJQUNsRSxDQUFDO0lBQ0QsTUFBTSxLQUFLLEdBQUcsSUFBSSxVQUFVLENBQUMsTUFBTSxJQUFJLFFBQVEsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUMsV0FBVyxFQUFFLENBQUMsQ0FBQztJQUNsRixJQUNFLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQztRQUNoQixLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSTtRQUNqQixLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSTtRQUNqQixLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSTtRQUNqQixLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSTtRQUNqQixLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSTtRQUNqQixLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSTtRQUNqQixLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSTtRQUNqQixLQUFLLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxFQUNqQixDQUFDO1FBQ0QsTUFBTSxJQUFJLFNBQVMsQ0FBQyw2Q0FBNkMsQ0FBQyxDQUFDO0lBQ3JFLENBQUM7SUFDRCxPQUFPLDRCQUE0QixDQUFDLEtBQUssQ0FBQyxDQUFDO0FBQzdDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBjcmVhdGVXb3Jrc3BhY2VDbGllbnQsIHR5cGUgV29ya3NwYWNlQ2xpZW50IH0gZnJvbSBcIkBkYXRhYnJpY2tzL2FwcGtpdFwiO1xuaW1wb3J0IHsgdHlwZSBDb250ZXh0TGlrZSwgdG9Db250ZXh0IH0gZnJvbSBcIkBkYngtdG9vbHMvYXBwa2l0XCI7XG5pbXBvcnQgeyBpc1JlY29yZCwgbG9nLCB0b0Vycm9yIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7XG4gIHR5cGUgR2VuaWVWaXN1YWxpemF0aW9uUmVxdWVzdCxcbiAgZ2VuaWVWaXN1YWxpemF0aW9uRG93bmxvYWRQYXRoLFxufSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtZ2VuaWVcIjtcblxuY29uc3QgbG9nZ2VyID0gbG9nLmxvZ2dlcihcImdlbmllL3Zpc3VhbGl6YXRpb25cIik7XG5jb25zdCBHRU5JRV9QTkdfU0NBTEUgPSA0O1xuY29uc3QgR0VOSUVfUE5HX1NIQVJQRU4gPSB7IHNpZ21hOiAxLjEsIG0xOiAwLjksIG0yOiAwLjAyIH0gYXMgY29uc3Q7XG5cbnR5cGUgU2hhcnBGYWN0b3J5ID0gKHR5cGVvZiBpbXBvcnQoXCJzaGFycFwiKSlbXCJkZWZhdWx0XCJdO1xuXG5sZXQgc2hhcnBGYWN0b3J5UHJvbWlzZTogUHJvbWlzZTxTaGFycEZhY3RvcnkgfCB1bmRlZmluZWQ+IHwgdW5kZWZpbmVkO1xuXG5mdW5jdGlvbiBpc0J5dGVTdHJlYW0odmFsdWU6IHVua25vd24pOiB2YWx1ZSBpcyBSZWFkYWJsZVN0cmVhbTxVaW50OEFycmF5PiB7XG4gIHJldHVybiAoXG4gICAgaXNSZWNvcmQodmFsdWUpICYmIHR5cGVvZiB2YWx1ZS5nZXRSZWFkZXIgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgdmFsdWUuY2FuY2VsID09PSBcImZ1bmN0aW9uXCJcbiAgKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gbG9hZFNoYXJwKCk6IFByb21pc2U8U2hhcnBGYWN0b3J5IHwgdW5kZWZpbmVkPiB7XG4gIHNoYXJwRmFjdG9yeVByb21pc2UgPz89IGltcG9ydChcInNoYXJwXCIpXG4gICAgLnRoZW4oKG1vZHVsZSkgPT4gbW9kdWxlLmRlZmF1bHQpXG4gICAgLmNhdGNoKChlcnJvcjogdW5rbm93bikgPT4ge1xuICAgICAgbG9nZ2VyLmRlYnVnKFwiUE5HIGVuaGFuY2VtZW50IHVuYXZhaWxhYmxlOyBzZXJ2aW5nIHRoZSBvcmlnaW5hbCBHZW5pZSBpbWFnZVwiLCB7XG4gICAgICAgIGVycm9yOiB0b0Vycm9yKGVycm9yKSxcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICB9KTtcbiAgcmV0dXJuIHNoYXJwRmFjdG9yeVByb21pc2U7XG59XG5cbi8qKlxuICogUmVzaXplIGEgR2VuaWUgc2NyZWVuc2hvdCB0byBmb3VyIHRpbWVzIGl0cyBzb3VyY2UgZGltZW5zaW9ucyB3aXRoIExhbmN6b3MzLFxuICogdGhlbiBhcHBseSBhIG1pbGQgdW5zaGFycCBtYXNrLiBSZXR1cm5zIHRoZSBvcmlnaW5hbCBieXRlcyB3aGVuIHRoZSBvcHRpb25hbFxuICogU2hhcnAgcnVudGltZSBpcyB1bmF2YWlsYWJsZSBvciByZWplY3RzIHRoZSBpbWFnZS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHVwc2NhbGVHZW5pZVZpc3VhbGl6YXRpb25QbmcoaW5wdXRCeXRlczogVWludDhBcnJheSk6IFByb21pc2U8VWludDhBcnJheT4ge1xuICBjb25zdCBzaGFycCA9IGF3YWl0IGxvYWRTaGFycCgpO1xuICBpZiAoIXNoYXJwKSByZXR1cm4gaW5wdXRCeXRlcztcbiAgdHJ5IHtcbiAgICBjb25zdCBpbnB1dCA9IEJ1ZmZlci5mcm9tKGlucHV0Qnl0ZXMpO1xuICAgIGNvbnN0IG1ldGFkYXRhID0gYXdhaXQgc2hhcnAoaW5wdXQpLm1ldGFkYXRhKCk7XG4gICAgaWYgKCFtZXRhZGF0YS53aWR0aCB8fCAhbWV0YWRhdGEuaGVpZ2h0KSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb3VsZCBub3QgcmVhZCBHZW5pZSB2aXN1YWxpemF0aW9uIGRpbWVuc2lvbnNcIik7XG4gICAgfVxuICAgIGNvbnN0IG91dHB1dCA9IGF3YWl0IHNoYXJwKGlucHV0KVxuICAgICAgLnJlc2l6ZSh7XG4gICAgICAgIHdpZHRoOiBtZXRhZGF0YS53aWR0aCAqIEdFTklFX1BOR19TQ0FMRSxcbiAgICAgICAgaGVpZ2h0OiBtZXRhZGF0YS5oZWlnaHQgKiBHRU5JRV9QTkdfU0NBTEUsXG4gICAgICAgIGtlcm5lbDogc2hhcnAua2VybmVsLmxhbmN6b3MzLFxuICAgICAgICBmaXQ6IFwiZmlsbFwiLFxuICAgICAgfSlcbiAgICAgIC5zaGFycGVuKEdFTklFX1BOR19TSEFSUEVOKVxuICAgICAgLnBuZygpXG4gICAgICAudG9CdWZmZXIoKTtcbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkob3V0cHV0KTtcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBsb2dnZXIud2FybihcIlBORyBlbmhhbmNlbWVudCBmYWlsZWQ7IHNlcnZpbmcgdGhlIG9yaWdpbmFsIEdlbmllIGltYWdlXCIsIHtcbiAgICAgIGVycm9yOiB0b0Vycm9yKGVycm9yKSxcbiAgICB9KTtcbiAgICByZXR1cm4gaW5wdXRCeXRlcztcbiAgfVxufVxuXG4vKiogSWRlbnRpdHkgYW5kIGNhbmNlbGxhdGlvbiBmb3IgYSBHZW5pZSB2aXN1YWxpemF0aW9uIGRvd25sb2FkLiAqL1xuZXhwb3J0IGludGVyZmFjZSBEb3dubG9hZEdlbmllVmlzdWFsaXphdGlvbk9wdGlvbnMge1xuICAvKiogV29ya3NwYWNlIGNsaWVudCB3aG9zZSBpZGVudGl0eSBvd25zIHRoZSBjb252ZXJzYXRpb24uICovXG4gIHdvcmtzcGFjZUNsaWVudD86IFdvcmtzcGFjZUNsaWVudDtcbiAgLyoqIEV4dGVybmFsIGNhbmNlbGxhdGlvbiBmb3IgdGhlIHJlcXVlc3QgYW5kIGltYWdlIGJvZHkuICovXG4gIGNvbnRleHQ/OiBDb250ZXh0TGlrZTtcbn1cblxuLyoqXG4gKiBEb3dubG9hZCBHZW5pZSdzIFBORyBhbmQgYXBwbHkgb3B0aW9uYWwgcmFzdGVyIGNsZWFudXAgYmVmb3JlIHJldHVybmluZyBpdC5cbiAqIFRoZSBTREsncyByYXcgdHJhbnNwb3J0IHByZXNlcnZlcyBiaW5hcnkgcmVzcG9uc2VzIGFuZCBpdHMgbm9ybWFsIGF1dGhlbnRpY2F0aW9uO1xuICogc291cmNlLWNoYXJ0IGV4cG9ydHMgc2hvdWxkIHN0aWxsIGJlIHByZWZlcnJlZCB3aGVuIHRoZXkgYXJlIGF2YWlsYWJsZS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRvd25sb2FkR2VuaWVWaXN1YWxpemF0aW9uKFxuICBpbnB1dDogR2VuaWVWaXN1YWxpemF0aW9uUmVxdWVzdCxcbiAgb3B0aW9uczogRG93bmxvYWRHZW5pZVZpc3VhbGl6YXRpb25PcHRpb25zID0ge30sXG4pOiBQcm9taXNlPFVpbnQ4QXJyYXk+IHtcbiAgY29uc3QgY2xpZW50ID0gb3B0aW9ucy53b3Jrc3BhY2VDbGllbnQgPz8gY3JlYXRlV29ya3NwYWNlQ2xpZW50KCk7XG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgY2xpZW50LmFwaUNsaWVudC5yZXF1ZXN0KFxuICAgIHtcbiAgICAgIHBhdGg6IGdlbmllVmlzdWFsaXphdGlvbkRvd25sb2FkUGF0aChpbnB1dCksXG4gICAgICBtZXRob2Q6IFwiR0VUXCIsXG4gICAgICBoZWFkZXJzOiBuZXcgSGVhZGVycyh7IGFjY2VwdDogXCJpbWFnZS9wbmdcIiB9KSxcbiAgICAgIHJlc3BvbnNlSGVhZGVyczogW1wiY29udGVudC10eXBlXCJdLFxuICAgICAgcmF3OiB0cnVlLFxuICAgIH0sXG4gICAgb3B0aW9ucy5jb250ZXh0ID8gdG9Db250ZXh0KG9wdGlvbnMuY29udGV4dCkgOiB1bmRlZmluZWQsXG4gICk7XG4gIGlmIChcbiAgICAhaXNSZWNvcmQocmVzcG9uc2UpIHx8XG4gICAgdHlwZW9mIHJlc3BvbnNlW1wiY29udGVudC10eXBlXCJdICE9PSBcInN0cmluZ1wiIHx8XG4gICAgcmVzcG9uc2VbXCJjb250ZW50LXR5cGVcIl0uc3BsaXQoXCI7XCIpWzBdPy50cmltKCkudG9Mb3dlckNhc2UoKSAhPT0gXCJpbWFnZS9wbmdcIiB8fFxuICAgICFpc0J5dGVTdHJlYW0ocmVzcG9uc2UuY29udGVudHMpXG4gICkge1xuICAgIGlmIChpc1JlY29yZChyZXNwb25zZSkgJiYgaXNCeXRlU3RyZWFtKHJlc3BvbnNlLmNvbnRlbnRzKSkge1xuICAgICAgYXdhaXQgcmVzcG9uc2UuY29udGVudHMuY2FuY2VsKCkuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB9XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmllIGRpZCBub3QgcmV0dXJuIGEgUE5HIHZpc3VhbGl6YXRpb25cIik7XG4gIH1cbiAgY29uc3QgYnl0ZXMgPSBuZXcgVWludDhBcnJheShhd2FpdCBuZXcgUmVzcG9uc2UocmVzcG9uc2UuY29udGVudHMpLmFycmF5QnVmZmVyKCkpO1xuICBpZiAoXG4gICAgYnl0ZXMubGVuZ3RoIDwgOCB8fFxuICAgIGJ5dGVzWzBdICE9PSAweDg5IHx8XG4gICAgYnl0ZXNbMV0gIT09IDB4NTAgfHxcbiAgICBieXRlc1syXSAhPT0gMHg0ZSB8fFxuICAgIGJ5dGVzWzNdICE9PSAweDQ3IHx8XG4gICAgYnl0ZXNbNF0gIT09IDB4MGQgfHxcbiAgICBieXRlc1s1XSAhPT0gMHgwYSB8fFxuICAgIGJ5dGVzWzZdICE9PSAweDFhIHx8XG4gICAgYnl0ZXNbN10gIT09IDB4MGFcbiAgKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmllIHJldHVybmVkIGFuIGludmFsaWQgUE5HIHZpc3VhbGl6YXRpb25cIik7XG4gIH1cbiAgcmV0dXJuIHVwc2NhbGVHZW5pZVZpc3VhbGl6YXRpb25QbmcoYnl0ZXMpO1xufVxuIl19
|
package/package.json
CHANGED
|
@@ -20,13 +20,17 @@
|
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@types/node": "^24.6.0",
|
|
23
|
+
"sharp": "^0.35.5",
|
|
23
24
|
"typescript": "^5.9.3"
|
|
24
25
|
},
|
|
26
|
+
"peerDependencies": {
|
|
27
|
+
"sharp": "^0.35.5"
|
|
28
|
+
},
|
|
25
29
|
"dependencies": {
|
|
26
30
|
"@databricks/appkit": "0.81.0",
|
|
27
|
-
"@dbx-tools/appkit": "
|
|
28
|
-
"@dbx-tools/shared-core": "
|
|
29
|
-
"@dbx-tools/shared-genie": "
|
|
31
|
+
"@dbx-tools/appkit": "0.9.190",
|
|
32
|
+
"@dbx-tools/shared-core": "0.9.190",
|
|
33
|
+
"@dbx-tools/shared-genie": "0.9.190"
|
|
30
34
|
},
|
|
31
35
|
"main": "./lib/index.js",
|
|
32
36
|
"license": "Apache-2.0",
|
|
@@ -42,7 +46,7 @@
|
|
|
42
46
|
"./package.json": "./package.json"
|
|
43
47
|
}
|
|
44
48
|
},
|
|
45
|
-
"version": "0.9.
|
|
49
|
+
"version": "0.9.190",
|
|
46
50
|
"types": "./lib/index.d.ts",
|
|
47
51
|
"dbxToolsConfig": {
|
|
48
52
|
"tags": [
|
|
@@ -62,5 +66,10 @@
|
|
|
62
66
|
"src",
|
|
63
67
|
"lib"
|
|
64
68
|
],
|
|
69
|
+
"peerDependenciesMeta": {
|
|
70
|
+
"sharp": {
|
|
71
|
+
"optional": true
|
|
72
|
+
}
|
|
73
|
+
},
|
|
65
74
|
"//": "~~ Generated by projen. To modify, edit .projenrc.js and run \"bunx projen\"."
|
|
66
75
|
}
|
package/src/visualization.ts
CHANGED
|
@@ -1,17 +1,70 @@
|
|
|
1
1
|
import { createWorkspaceClient, type WorkspaceClient } from "@databricks/appkit";
|
|
2
2
|
import { type ContextLike, toContext } from "@dbx-tools/appkit";
|
|
3
|
-
import { isRecord } from "@dbx-tools/shared-core";
|
|
3
|
+
import { isRecord, log, toError } from "@dbx-tools/shared-core";
|
|
4
4
|
import {
|
|
5
5
|
type GenieVisualizationRequest,
|
|
6
6
|
genieVisualizationDownloadPath,
|
|
7
7
|
} from "@dbx-tools/shared-genie";
|
|
8
8
|
|
|
9
|
+
const logger = log.logger("genie/visualization");
|
|
10
|
+
const GENIE_PNG_SCALE = 4;
|
|
11
|
+
const GENIE_PNG_SHARPEN = { sigma: 1.1, m1: 0.9, m2: 0.02 } as const;
|
|
12
|
+
|
|
13
|
+
type SharpFactory = (typeof import("sharp"))["default"];
|
|
14
|
+
|
|
15
|
+
let sharpFactoryPromise: Promise<SharpFactory | undefined> | undefined;
|
|
16
|
+
|
|
9
17
|
function isByteStream(value: unknown): value is ReadableStream<Uint8Array> {
|
|
10
18
|
return (
|
|
11
19
|
isRecord(value) && typeof value.getReader === "function" && typeof value.cancel === "function"
|
|
12
20
|
);
|
|
13
21
|
}
|
|
14
22
|
|
|
23
|
+
async function loadSharp(): Promise<SharpFactory | undefined> {
|
|
24
|
+
sharpFactoryPromise ??= import("sharp")
|
|
25
|
+
.then((module) => module.default)
|
|
26
|
+
.catch((error: unknown) => {
|
|
27
|
+
logger.debug("PNG enhancement unavailable; serving the original Genie image", {
|
|
28
|
+
error: toError(error),
|
|
29
|
+
});
|
|
30
|
+
return undefined;
|
|
31
|
+
});
|
|
32
|
+
return sharpFactoryPromise;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Resize a Genie screenshot to four times its source dimensions with Lanczos3,
|
|
37
|
+
* then apply a mild unsharp mask. Returns the original bytes when the optional
|
|
38
|
+
* Sharp runtime is unavailable or rejects the image.
|
|
39
|
+
*/
|
|
40
|
+
export async function upscaleGenieVisualizationPng(inputBytes: Uint8Array): Promise<Uint8Array> {
|
|
41
|
+
const sharp = await loadSharp();
|
|
42
|
+
if (!sharp) return inputBytes;
|
|
43
|
+
try {
|
|
44
|
+
const input = Buffer.from(inputBytes);
|
|
45
|
+
const metadata = await sharp(input).metadata();
|
|
46
|
+
if (!metadata.width || !metadata.height) {
|
|
47
|
+
throw new Error("Could not read Genie visualization dimensions");
|
|
48
|
+
}
|
|
49
|
+
const output = await sharp(input)
|
|
50
|
+
.resize({
|
|
51
|
+
width: metadata.width * GENIE_PNG_SCALE,
|
|
52
|
+
height: metadata.height * GENIE_PNG_SCALE,
|
|
53
|
+
kernel: sharp.kernel.lanczos3,
|
|
54
|
+
fit: "fill",
|
|
55
|
+
})
|
|
56
|
+
.sharpen(GENIE_PNG_SHARPEN)
|
|
57
|
+
.png()
|
|
58
|
+
.toBuffer();
|
|
59
|
+
return new Uint8Array(output);
|
|
60
|
+
} catch (error) {
|
|
61
|
+
logger.warn("PNG enhancement failed; serving the original Genie image", {
|
|
62
|
+
error: toError(error),
|
|
63
|
+
});
|
|
64
|
+
return inputBytes;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
15
68
|
/** Identity and cancellation for a Genie visualization download. */
|
|
16
69
|
export interface DownloadGenieVisualizationOptions {
|
|
17
70
|
/** Workspace client whose identity owns the conversation. */
|
|
@@ -21,8 +74,9 @@ export interface DownloadGenieVisualizationOptions {
|
|
|
21
74
|
}
|
|
22
75
|
|
|
23
76
|
/**
|
|
24
|
-
* Download Genie's
|
|
25
|
-
* The SDK's raw transport preserves binary responses and its normal authentication
|
|
77
|
+
* Download Genie's PNG and apply optional raster cleanup before returning it.
|
|
78
|
+
* The SDK's raw transport preserves binary responses and its normal authentication;
|
|
79
|
+
* source-chart exports should still be preferred when they are available.
|
|
26
80
|
*/
|
|
27
81
|
export async function downloadGenieVisualization(
|
|
28
82
|
input: GenieVisualizationRequest,
|
|
@@ -64,5 +118,5 @@ export async function downloadGenieVisualization(
|
|
|
64
118
|
) {
|
|
65
119
|
throw new TypeError("Genie returned an invalid PNG visualization");
|
|
66
120
|
}
|
|
67
|
-
return bytes;
|
|
121
|
+
return upscaleGenieVisualizationPng(bytes);
|
|
68
122
|
}
|