@dbx-tools/genie 0.9.187 → 0.9.188

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -183,6 +183,35 @@ thrown.
183
183
  - `pollIntervalMs` - fallback polling cadence, default `500`.
184
184
  - `context` - SDK `Context` or `AbortSignal` for cancellation.
185
185
 
186
+ ## Download an original chart
187
+
188
+ After requesting visualizations, select the message attachment with a `viz`
189
+ field and download its PNG using the same conversation and message IDs:
190
+
191
+ ```ts
192
+ import { downloadGenieVisualization } from "@dbx-tools/genie";
193
+
194
+ const visualization = message.attachments?.find((attachment) => attachment.viz);
195
+ if (visualization?.attachment_id) {
196
+ const png = await downloadGenieVisualization(
197
+ {
198
+ space_id: message.space_id,
199
+ conversation_id: message.conversation_id,
200
+ message_id: message.message_id,
201
+ attachment_id: visualization.attachment_id,
202
+ },
203
+ { workspaceClient },
204
+ );
205
+ }
206
+ ```
207
+
208
+ Use the visualization's attachment ID, not its linked query attachment ID.
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 and
211
+ returns the original bytes; it does not replot data or convert images to SVG.
212
+ This endpoint also accepts visualization attachments from Agent Mode
213
+ conversations.
214
+
186
215
  ## Modules
187
216
 
188
217
  - `chat` - `genieChat()` raw snapshot stream and `genieEventChat()` typed event
@@ -190,6 +219,7 @@ thrown.
190
219
  - `agentMode` - `genieAgentModeChat()`, availability classification, and Agent
191
220
  Mode transport options plus Agent Mode conversation history.
192
221
  - `space` - `getGenieSpace()` and `genieSampleQuestions()`.
222
+ - `visualization` - `downloadGenieVisualization()` for original PNG downloads.
193
223
 
194
224
  The AppKit-Mastra package builds its Genie tools on top of this driver. See
195
225
  [@dbx-tools/appkit-mastra](../appkit-mastra) for the agent-level
package/index.ts CHANGED
@@ -3,11 +3,12 @@
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.187";
6
+ export const PACKAGE_VERSION = "0.9.188";
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";
10
10
  export * as space from "./src/space.ts";
11
+ export * as visualization from "./src/visualization.ts";
11
12
  export { genieAgentModeChat, listAgentModeConversation, isAgentModeUnavailable } from "./src/agent-mode.ts";
12
13
  export type { GenieAgentModeOptions } from "./src/agent-mode.ts";
13
14
  export { genieChat, genieEventChat } from "./src/chat.ts";
@@ -16,3 +17,5 @@ export { sendGenieMessageFeedback } from "./src/feedback.ts";
16
17
  export type { SendGenieMessageFeedbackOptions } from "./src/feedback.ts";
17
18
  export { createGenieSpace, getGenieSpace, genieSampleQuestions } from "./src/space.ts";
18
19
  export type { GetGenieSpaceOptions, CreateGenieSpaceOptions } from "./src/space.ts";
20
+ export { downloadGenieVisualization } from "./src/visualization.ts";
21
+ export type { DownloadGenieVisualizationOptions } from "./src/visualization.ts";
package/lib/index.d.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  export declare const PACKAGE_IDENTIFIER = "@dbx-tools/genie";
2
- export declare const PACKAGE_VERSION = "0.9.187";
2
+ export declare const PACKAGE_VERSION = "0.9.188";
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";
6
6
  export * as space from "./src/space.ts";
7
+ export * as visualization from "./src/visualization.ts";
7
8
  export { genieAgentModeChat, listAgentModeConversation, isAgentModeUnavailable } from "./src/agent-mode.ts";
8
9
  export type { GenieAgentModeOptions } from "./src/agent-mode.ts";
9
10
  export { genieChat, genieEventChat } from "./src/chat.ts";
@@ -12,3 +13,5 @@ export { sendGenieMessageFeedback } from "./src/feedback.ts";
12
13
  export type { SendGenieMessageFeedbackOptions } from "./src/feedback.ts";
13
14
  export { createGenieSpace, getGenieSpace, genieSampleQuestions } from "./src/space.ts";
14
15
  export type { GetGenieSpaceOptions, CreateGenieSpaceOptions } from "./src/space.ts";
16
+ export { downloadGenieVisualization } from "./src/visualization.ts";
17
+ export type { DownloadGenieVisualizationOptions } from "./src/visualization.ts";
package/lib/index.js CHANGED
@@ -2,13 +2,15 @@
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.187";
5
+ export const PACKAGE_VERSION = "0.9.188";
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";
9
9
  export * as space from "./src/space.js";
10
+ export * as visualization from "./src/visualization.js";
10
11
  export { genieAgentModeChat, listAgentModeConversation, isAgentModeUnavailable } from "./src/agent-mode.js";
11
12
  export { genieChat, genieEventChat } from "./src/chat.js";
12
13
  export { sendGenieMessageFeedback } from "./src/feedback.js";
13
14
  export { createGenieSpace, getGenieSpace, genieSampleQuestions } from "./src/space.js";
14
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxrQkFBa0IsQ0FBQztBQUNyRCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsU0FBUyxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxTQUFTLE1BQU0scUJBQXFCLENBQUM7QUFDakQsT0FBTyxLQUFLLElBQUksTUFBTSxlQUFlLENBQUM7QUFDdEMsT0FBTyxLQUFLLFFBQVEsTUFBTSxtQkFBbUIsQ0FBQztBQUM5QyxPQUFPLEtBQUssS0FBSyxNQUFNLGdCQUFnQixDQUFDO0FBQ3hDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSx5QkFBeUIsRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRTVHLE9BQU8sRUFBRSxTQUFTLEVBQUUsY0FBYyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRTFELE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRTdELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxhQUFhLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEdFTkVSQVRFRCBieSBwcm9qZW4gd2F0Y2ggLSBETyBOT1QgRURJVC5cbi8vIFJlZ2VuZXJhdGVkIGZyb20gdGhlIGV4cG9ydGluZyBtb2R1bGVzIGluIC4vc3JjLlxuLy8gSGFuZCBlZGl0cyBhcmUgb3ZlcndyaXR0ZW4gb24gdGhlIG5leHQgd2F0Y2g7IHRoaXMgZmlsZSBpcyByZWFkLW9ubHkuXG5cbmV4cG9ydCBjb25zdCBQQUNLQUdFX0lERU5USUZJRVIgPSBcIkBkYngtdG9vbHMvZ2VuaWVcIjtcbmV4cG9ydCBjb25zdCBQQUNLQUdFX1ZFUlNJT04gPSBcIjAuOS4xODdcIjtcbmV4cG9ydCAqIGFzIGFnZW50TW9kZSBmcm9tIFwiLi9zcmMvYWdlbnQtbW9kZS50c1wiO1xuZXhwb3J0ICogYXMgY2hhdCBmcm9tIFwiLi9zcmMvY2hhdC50c1wiO1xuZXhwb3J0ICogYXMgZmVlZGJhY2sgZnJvbSBcIi4vc3JjL2ZlZWRiYWNrLnRzXCI7XG5leHBvcnQgKiBhcyBzcGFjZSBmcm9tIFwiLi9zcmMvc3BhY2UudHNcIjtcbmV4cG9ydCB7IGdlbmllQWdlbnRNb2RlQ2hhdCwgbGlzdEFnZW50TW9kZUNvbnZlcnNhdGlvbiwgaXNBZ2VudE1vZGVVbmF2YWlsYWJsZSB9IGZyb20gXCIuL3NyYy9hZ2VudC1tb2RlLnRzXCI7XG5leHBvcnQgdHlwZSB7IEdlbmllQWdlbnRNb2RlT3B0aW9ucyB9IGZyb20gXCIuL3NyYy9hZ2VudC1tb2RlLnRzXCI7XG5leHBvcnQgeyBnZW5pZUNoYXQsIGdlbmllRXZlbnRDaGF0IH0gZnJvbSBcIi4vc3JjL2NoYXQudHNcIjtcbmV4cG9ydCB0eXBlIHsgR2VuaWVDaGF0T3B0aW9ucyB9IGZyb20gXCIuL3NyYy9jaGF0LnRzXCI7XG5leHBvcnQgeyBzZW5kR2VuaWVNZXNzYWdlRmVlZGJhY2sgfSBmcm9tIFwiLi9zcmMvZmVlZGJhY2sudHNcIjtcbmV4cG9ydCB0eXBlIHsgU2VuZEdlbmllTWVzc2FnZUZlZWRiYWNrT3B0aW9ucyB9IGZyb20gXCIuL3NyYy9mZWVkYmFjay50c1wiO1xuZXhwb3J0IHsgY3JlYXRlR2VuaWVTcGFjZSwgZ2V0R2VuaWVTcGFjZSwgZ2VuaWVTYW1wbGVRdWVzdGlvbnMgfSBmcm9tIFwiLi9zcmMvc3BhY2UudHNcIjtcbmV4cG9ydCB0eXBlIHsgR2V0R2VuaWVTcGFjZU9wdGlvbnMsIENyZWF0ZUdlbmllU3BhY2VPcHRpb25zIH0gZnJvbSBcIi4vc3JjL3NwYWNlLnRzXCI7XG4iXX0=
15
+ export { downloadGenieVisualization } from "./src/visualization.js";
16
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxrQkFBa0IsQ0FBQztBQUNyRCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsU0FBUyxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxTQUFTLE1BQU0scUJBQXFCLENBQUM7QUFDakQsT0FBTyxLQUFLLElBQUksTUFBTSxlQUFlLENBQUM7QUFDdEMsT0FBTyxLQUFLLFFBQVEsTUFBTSxtQkFBbUIsQ0FBQztBQUM5QyxPQUFPLEtBQUssS0FBSyxNQUFNLGdCQUFnQixDQUFDO0FBQ3hDLE9BQU8sS0FBSyxhQUFhLE1BQU0sd0JBQXdCLENBQUM7QUFDeEQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLHlCQUF5QixFQUFFLHNCQUFzQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFFNUcsT0FBTyxFQUFFLFNBQVMsRUFBRSxjQUFjLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFMUQsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFN0QsT0FBTyxFQUFFLGdCQUFnQixFQUFFLGFBQWEsRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRXZGLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSxNQUFNLHdCQUF3QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gR0VORVJBVEVEIGJ5IHByb2plbiB3YXRjaCAtIERPIE5PVCBFRElULlxuLy8gUmVnZW5lcmF0ZWQgZnJvbSB0aGUgZXhwb3J0aW5nIG1vZHVsZXMgaW4gLi9zcmMuXG4vLyBIYW5kIGVkaXRzIGFyZSBvdmVyd3JpdHRlbiBvbiB0aGUgbmV4dCB3YXRjaDsgdGhpcyBmaWxlIGlzIHJlYWQtb25seS5cblxuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfSURFTlRJRklFUiA9IFwiQGRieC10b29scy9nZW5pZVwiO1xuZXhwb3J0IGNvbnN0IFBBQ0tBR0VfVkVSU0lPTiA9IFwiMC45LjE4OFwiO1xuZXhwb3J0ICogYXMgYWdlbnRNb2RlIGZyb20gXCIuL3NyYy9hZ2VudC1tb2RlLnRzXCI7XG5leHBvcnQgKiBhcyBjaGF0IGZyb20gXCIuL3NyYy9jaGF0LnRzXCI7XG5leHBvcnQgKiBhcyBmZWVkYmFjayBmcm9tIFwiLi9zcmMvZmVlZGJhY2sudHNcIjtcbmV4cG9ydCAqIGFzIHNwYWNlIGZyb20gXCIuL3NyYy9zcGFjZS50c1wiO1xuZXhwb3J0ICogYXMgdmlzdWFsaXphdGlvbiBmcm9tIFwiLi9zcmMvdmlzdWFsaXphdGlvbi50c1wiO1xuZXhwb3J0IHsgZ2VuaWVBZ2VudE1vZGVDaGF0LCBsaXN0QWdlbnRNb2RlQ29udmVyc2F0aW9uLCBpc0FnZW50TW9kZVVuYXZhaWxhYmxlIH0gZnJvbSBcIi4vc3JjL2FnZW50LW1vZGUudHNcIjtcbmV4cG9ydCB0eXBlIHsgR2VuaWVBZ2VudE1vZGVPcHRpb25zIH0gZnJvbSBcIi4vc3JjL2FnZW50LW1vZGUudHNcIjtcbmV4cG9ydCB7IGdlbmllQ2hhdCwgZ2VuaWVFdmVudENoYXQgfSBmcm9tIFwiLi9zcmMvY2hhdC50c1wiO1xuZXhwb3J0IHR5cGUgeyBHZW5pZUNoYXRPcHRpb25zIH0gZnJvbSBcIi4vc3JjL2NoYXQudHNcIjtcbmV4cG9ydCB7IHNlbmRHZW5pZU1lc3NhZ2VGZWVkYmFjayB9IGZyb20gXCIuL3NyYy9mZWVkYmFjay50c1wiO1xuZXhwb3J0IHR5cGUgeyBTZW5kR2VuaWVNZXNzYWdlRmVlZGJhY2tPcHRpb25zIH0gZnJvbSBcIi4vc3JjL2ZlZWRiYWNrLnRzXCI7XG5leHBvcnQgeyBjcmVhdGVHZW5pZVNwYWNlLCBnZXRHZW5pZVNwYWNlLCBnZW5pZVNhbXBsZVF1ZXN0aW9ucyB9IGZyb20gXCIuL3NyYy9zcGFjZS50c1wiO1xuZXhwb3J0IHR5cGUgeyBHZXRHZW5pZVNwYWNlT3B0aW9ucywgQ3JlYXRlR2VuaWVTcGFjZU9wdGlvbnMgfSBmcm9tIFwiLi9zcmMvc3BhY2UudHNcIjtcbmV4cG9ydCB7IGRvd25sb2FkR2VuaWVWaXN1YWxpemF0aW9uIH0gZnJvbSBcIi4vc3JjL3Zpc3VhbGl6YXRpb24udHNcIjtcbmV4cG9ydCB0eXBlIHsgRG93bmxvYWRHZW5pZVZpc3VhbGl6YXRpb25PcHRpb25zIH0gZnJvbSBcIi4vc3JjL3Zpc3VhbGl6YXRpb24udHNcIjtcbiJdfQ==
@@ -0,0 +1,15 @@
1
+ import { type WorkspaceClient } from "@databricks/appkit";
2
+ import { type ContextLike } from "@dbx-tools/appkit";
3
+ import { type GenieVisualizationRequest } from "@dbx-tools/shared-genie";
4
+ /** Identity and cancellation for a Genie visualization download. */
5
+ export interface DownloadGenieVisualizationOptions {
6
+ /** Workspace client whose identity owns the conversation. */
7
+ workspaceClient?: WorkspaceClient;
8
+ /** External cancellation for the request and image body. */
9
+ context?: ContextLike;
10
+ }
11
+ /**
12
+ * Download Genie's original PNG bytes without redrawing or transcoding them.
13
+ * The SDK's raw transport preserves binary responses and its normal authentication.
14
+ */
15
+ export declare function downloadGenieVisualization(input: GenieVisualizationRequest, options?: DownloadGenieVisualizationOptions): Promise<Uint8Array>;
@@ -0,0 +1,44 @@
1
+ import { createWorkspaceClient } from "@databricks/appkit";
2
+ import { toContext } from "@dbx-tools/appkit";
3
+ import { isRecord } from "@dbx-tools/shared-core";
4
+ import { genieVisualizationDownloadPath, } from "@dbx-tools/shared-genie";
5
+ function isByteStream(value) {
6
+ return (isRecord(value) && typeof value.getReader === "function" && typeof value.cancel === "function");
7
+ }
8
+ /**
9
+ * Download Genie's original PNG bytes without redrawing or transcoding them.
10
+ * The SDK's raw transport preserves binary responses and its normal authentication.
11
+ */
12
+ export async function downloadGenieVisualization(input, options = {}) {
13
+ const client = options.workspaceClient ?? createWorkspaceClient();
14
+ const response = await client.apiClient.request({
15
+ path: genieVisualizationDownloadPath(input),
16
+ method: "GET",
17
+ headers: new Headers({ accept: "image/png" }),
18
+ responseHeaders: ["content-type"],
19
+ raw: true,
20
+ }, options.context ? toContext(options.context) : undefined);
21
+ if (!isRecord(response) ||
22
+ typeof response["content-type"] !== "string" ||
23
+ response["content-type"].split(";")[0]?.trim().toLowerCase() !== "image/png" ||
24
+ !isByteStream(response.contents)) {
25
+ if (isRecord(response) && isByteStream(response.contents)) {
26
+ await response.contents.cancel().catch(() => undefined);
27
+ }
28
+ throw new TypeError("Genie did not return a PNG visualization");
29
+ }
30
+ const bytes = new Uint8Array(await new Response(response.contents).arrayBuffer());
31
+ if (bytes.length < 8 ||
32
+ bytes[0] !== 0x89 ||
33
+ bytes[1] !== 0x50 ||
34
+ bytes[2] !== 0x4e ||
35
+ bytes[3] !== 0x47 ||
36
+ bytes[4] !== 0x0d ||
37
+ bytes[5] !== 0x0a ||
38
+ bytes[6] !== 0x1a ||
39
+ bytes[7] !== 0x0a) {
40
+ throw new TypeError("Genie returned an invalid PNG visualization");
41
+ }
42
+ return bytes;
43
+ }
44
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlzdWFsaXphdGlvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy92aXN1YWxpemF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxxQkFBcUIsRUFBd0IsTUFBTSxvQkFBb0IsQ0FBQztBQUNqRixPQUFPLEVBQW9CLFNBQVMsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNsRCxPQUFPLEVBRUwsOEJBQThCLEdBQy9CLE1BQU0seUJBQXlCLENBQUM7QUFFakMsU0FBUyxZQUFZLENBQUMsS0FBYztJQUNsQyxPQUFPLENBQ0wsUUFBUSxDQUFDLEtBQUssQ0FBQyxJQUFJLE9BQU8sS0FBSyxDQUFDLFNBQVMsS0FBSyxVQUFVLElBQUksT0FBTyxLQUFLLENBQUMsTUFBTSxLQUFLLFVBQVUsQ0FDL0YsQ0FBQztBQUNKLENBQUM7QUFVRDs7O0dBR0c7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLDBCQUEwQixDQUM5QyxLQUFnQyxFQUNoQyxVQUE2QyxFQUFFO0lBRS9DLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxlQUFlLElBQUkscUJBQXFCLEVBQUUsQ0FBQztJQUNsRSxNQUFNLFFBQVEsR0FBRyxNQUFNLE1BQU0sQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUM3QztRQUNFLElBQUksRUFBRSw4QkFBOEIsQ0FBQyxLQUFLLENBQUM7UUFDM0MsTUFBTSxFQUFFLEtBQUs7UUFDYixPQUFPLEVBQUUsSUFBSSxPQUFPLENBQUMsRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLENBQUM7UUFDN0MsZUFBZSxFQUFFLENBQUMsY0FBYyxDQUFDO1FBQ2pDLEdBQUcsRUFBRSxJQUFJO0tBQ1YsRUFDRCxPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQ3pELENBQUM7SUFDRixJQUNFLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQztRQUNuQixPQUFPLFFBQVEsQ0FBQyxjQUFjLENBQUMsS0FBSyxRQUFRO1FBQzVDLFFBQVEsQ0FBQyxjQUFjLENBQUMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLENBQUMsV0FBVyxFQUFFLEtBQUssV0FBVztRQUM1RSxDQUFDLFlBQVksQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLEVBQ2hDLENBQUM7UUFDRCxJQUFJLFFBQVEsQ0FBQyxRQUFRLENBQUMsSUFBSSxZQUFZLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7WUFDMUQsTUFBTSxRQUFRLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUMxRCxDQUFDO1FBQ0QsTUFBTSxJQUFJLFNBQVMsQ0FBQywwQ0FBMEMsQ0FBQyxDQUFDO0lBQ2xFLENBQUM7SUFDRCxNQUFNLEtBQUssR0FBRyxJQUFJLFVBQVUsQ0FBQyxNQUFNLElBQUksUUFBUSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsQ0FBQyxXQUFXLEVBQUUsQ0FBQyxDQUFDO0lBQ2xGLElBQ0UsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDO1FBQ2hCLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJO1FBQ2pCLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJO1FBQ2pCLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJO1FBQ2pCLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJO1FBQ2pCLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJO1FBQ2pCLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJO1FBQ2pCLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJO1FBQ2pCLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJLEVBQ2pCLENBQUM7UUFDRCxNQUFNLElBQUksU0FBUyxDQUFDLDZDQUE2QyxDQUFDLENBQUM7SUFDckUsQ0FBQztJQUNELE9BQU8sS0FBSyxDQUFDO0FBQ2YsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNyZWF0ZVdvcmtzcGFjZUNsaWVudCwgdHlwZSBXb3Jrc3BhY2VDbGllbnQgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0XCI7XG5pbXBvcnQgeyB0eXBlIENvbnRleHRMaWtlLCB0b0NvbnRleHQgfSBmcm9tIFwiQGRieC10b29scy9hcHBraXRcIjtcbmltcG9ydCB7IGlzUmVjb3JkIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7XG4gIHR5cGUgR2VuaWVWaXN1YWxpemF0aW9uUmVxdWVzdCxcbiAgZ2VuaWVWaXN1YWxpemF0aW9uRG93bmxvYWRQYXRoLFxufSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtZ2VuaWVcIjtcblxuZnVuY3Rpb24gaXNCeXRlU3RyZWFtKHZhbHVlOiB1bmtub3duKTogdmFsdWUgaXMgUmVhZGFibGVTdHJlYW08VWludDhBcnJheT4ge1xuICByZXR1cm4gKFxuICAgIGlzUmVjb3JkKHZhbHVlKSAmJiB0eXBlb2YgdmFsdWUuZ2V0UmVhZGVyID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIHZhbHVlLmNhbmNlbCA9PT0gXCJmdW5jdGlvblwiXG4gICk7XG59XG5cbi8qKiBJZGVudGl0eSBhbmQgY2FuY2VsbGF0aW9uIGZvciBhIEdlbmllIHZpc3VhbGl6YXRpb24gZG93bmxvYWQuICovXG5leHBvcnQgaW50ZXJmYWNlIERvd25sb2FkR2VuaWVWaXN1YWxpemF0aW9uT3B0aW9ucyB7XG4gIC8qKiBXb3Jrc3BhY2UgY2xpZW50IHdob3NlIGlkZW50aXR5IG93bnMgdGhlIGNvbnZlcnNhdGlvbi4gKi9cbiAgd29ya3NwYWNlQ2xpZW50PzogV29ya3NwYWNlQ2xpZW50O1xuICAvKiogRXh0ZXJuYWwgY2FuY2VsbGF0aW9uIGZvciB0aGUgcmVxdWVzdCBhbmQgaW1hZ2UgYm9keS4gKi9cbiAgY29udGV4dD86IENvbnRleHRMaWtlO1xufVxuXG4vKipcbiAqIERvd25sb2FkIEdlbmllJ3Mgb3JpZ2luYWwgUE5HIGJ5dGVzIHdpdGhvdXQgcmVkcmF3aW5nIG9yIHRyYW5zY29kaW5nIHRoZW0uXG4gKiBUaGUgU0RLJ3MgcmF3IHRyYW5zcG9ydCBwcmVzZXJ2ZXMgYmluYXJ5IHJlc3BvbnNlcyBhbmQgaXRzIG5vcm1hbCBhdXRoZW50aWNhdGlvbi5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRvd25sb2FkR2VuaWVWaXN1YWxpemF0aW9uKFxuICBpbnB1dDogR2VuaWVWaXN1YWxpemF0aW9uUmVxdWVzdCxcbiAgb3B0aW9uczogRG93bmxvYWRHZW5pZVZpc3VhbGl6YXRpb25PcHRpb25zID0ge30sXG4pOiBQcm9taXNlPFVpbnQ4QXJyYXk+IHtcbiAgY29uc3QgY2xpZW50ID0gb3B0aW9ucy53b3Jrc3BhY2VDbGllbnQgPz8gY3JlYXRlV29ya3NwYWNlQ2xpZW50KCk7XG4gIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgY2xpZW50LmFwaUNsaWVudC5yZXF1ZXN0KFxuICAgIHtcbiAgICAgIHBhdGg6IGdlbmllVmlzdWFsaXphdGlvbkRvd25sb2FkUGF0aChpbnB1dCksXG4gICAgICBtZXRob2Q6IFwiR0VUXCIsXG4gICAgICBoZWFkZXJzOiBuZXcgSGVhZGVycyh7IGFjY2VwdDogXCJpbWFnZS9wbmdcIiB9KSxcbiAgICAgIHJlc3BvbnNlSGVhZGVyczogW1wiY29udGVudC10eXBlXCJdLFxuICAgICAgcmF3OiB0cnVlLFxuICAgIH0sXG4gICAgb3B0aW9ucy5jb250ZXh0ID8gdG9Db250ZXh0KG9wdGlvbnMuY29udGV4dCkgOiB1bmRlZmluZWQsXG4gICk7XG4gIGlmIChcbiAgICAhaXNSZWNvcmQocmVzcG9uc2UpIHx8XG4gICAgdHlwZW9mIHJlc3BvbnNlW1wiY29udGVudC10eXBlXCJdICE9PSBcInN0cmluZ1wiIHx8XG4gICAgcmVzcG9uc2VbXCJjb250ZW50LXR5cGVcIl0uc3BsaXQoXCI7XCIpWzBdPy50cmltKCkudG9Mb3dlckNhc2UoKSAhPT0gXCJpbWFnZS9wbmdcIiB8fFxuICAgICFpc0J5dGVTdHJlYW0ocmVzcG9uc2UuY29udGVudHMpXG4gICkge1xuICAgIGlmIChpc1JlY29yZChyZXNwb25zZSkgJiYgaXNCeXRlU3RyZWFtKHJlc3BvbnNlLmNvbnRlbnRzKSkge1xuICAgICAgYXdhaXQgcmVzcG9uc2UuY29udGVudHMuY2FuY2VsKCkuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICB9XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmllIGRpZCBub3QgcmV0dXJuIGEgUE5HIHZpc3VhbGl6YXRpb25cIik7XG4gIH1cbiAgY29uc3QgYnl0ZXMgPSBuZXcgVWludDhBcnJheShhd2FpdCBuZXcgUmVzcG9uc2UocmVzcG9uc2UuY29udGVudHMpLmFycmF5QnVmZmVyKCkpO1xuICBpZiAoXG4gICAgYnl0ZXMubGVuZ3RoIDwgOCB8fFxuICAgIGJ5dGVzWzBdICE9PSAweDg5IHx8XG4gICAgYnl0ZXNbMV0gIT09IDB4NTAgfHxcbiAgICBieXRlc1syXSAhPT0gMHg0ZSB8fFxuICAgIGJ5dGVzWzNdICE9PSAweDQ3IHx8XG4gICAgYnl0ZXNbNF0gIT09IDB4MGQgfHxcbiAgICBieXRlc1s1XSAhPT0gMHgwYSB8fFxuICAgIGJ5dGVzWzZdICE9PSAweDFhIHx8XG4gICAgYnl0ZXNbN10gIT09IDB4MGFcbiAgKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmllIHJldHVybmVkIGFuIGludmFsaWQgUE5HIHZpc3VhbGl6YXRpb25cIik7XG4gIH1cbiAgcmV0dXJuIGJ5dGVzO1xufVxuIl19
@@ -1 +1 @@
1
- {"root":["../src/agent-mode.ts","../src/chat.ts","../src/feedback.ts","../src/space.ts","../index.ts"],"version":"5.9.3"}
1
+ {"root":["../src/agent-mode.ts","../src/chat.ts","../src/feedback.ts","../src/space.ts","../src/visualization.ts","../index.ts"],"version":"5.9.3"}
package/package.json CHANGED
@@ -24,9 +24,9 @@
24
24
  },
25
25
  "dependencies": {
26
26
  "@databricks/appkit": "0.81.0",
27
- "@dbx-tools/appkit": "^0.9.187",
28
- "@dbx-tools/shared-core": "^0.9.187",
29
- "@dbx-tools/shared-genie": "^0.9.187"
27
+ "@dbx-tools/appkit": "^0.9.188",
28
+ "@dbx-tools/shared-core": "^0.9.188",
29
+ "@dbx-tools/shared-genie": "^0.9.188"
30
30
  },
31
31
  "main": "./lib/index.js",
32
32
  "license": "Apache-2.0",
@@ -42,7 +42,7 @@
42
42
  "./package.json": "./package.json"
43
43
  }
44
44
  },
45
- "version": "0.9.187",
45
+ "version": "0.9.188",
46
46
  "types": "./lib/index.d.ts",
47
47
  "dbxToolsConfig": {
48
48
  "tags": [
@@ -0,0 +1,68 @@
1
+ import { createWorkspaceClient, type WorkspaceClient } from "@databricks/appkit";
2
+ import { type ContextLike, toContext } from "@dbx-tools/appkit";
3
+ import { isRecord } from "@dbx-tools/shared-core";
4
+ import {
5
+ type GenieVisualizationRequest,
6
+ genieVisualizationDownloadPath,
7
+ } from "@dbx-tools/shared-genie";
8
+
9
+ function isByteStream(value: unknown): value is ReadableStream<Uint8Array> {
10
+ return (
11
+ isRecord(value) && typeof value.getReader === "function" && typeof value.cancel === "function"
12
+ );
13
+ }
14
+
15
+ /** Identity and cancellation for a Genie visualization download. */
16
+ export interface DownloadGenieVisualizationOptions {
17
+ /** Workspace client whose identity owns the conversation. */
18
+ workspaceClient?: WorkspaceClient;
19
+ /** External cancellation for the request and image body. */
20
+ context?: ContextLike;
21
+ }
22
+
23
+ /**
24
+ * Download Genie's original PNG bytes without redrawing or transcoding them.
25
+ * The SDK's raw transport preserves binary responses and its normal authentication.
26
+ */
27
+ export async function downloadGenieVisualization(
28
+ input: GenieVisualizationRequest,
29
+ options: DownloadGenieVisualizationOptions = {},
30
+ ): Promise<Uint8Array> {
31
+ const client = options.workspaceClient ?? createWorkspaceClient();
32
+ const response = await client.apiClient.request(
33
+ {
34
+ path: genieVisualizationDownloadPath(input),
35
+ method: "GET",
36
+ headers: new Headers({ accept: "image/png" }),
37
+ responseHeaders: ["content-type"],
38
+ raw: true,
39
+ },
40
+ options.context ? toContext(options.context) : undefined,
41
+ );
42
+ if (
43
+ !isRecord(response) ||
44
+ typeof response["content-type"] !== "string" ||
45
+ response["content-type"].split(";")[0]?.trim().toLowerCase() !== "image/png" ||
46
+ !isByteStream(response.contents)
47
+ ) {
48
+ if (isRecord(response) && isByteStream(response.contents)) {
49
+ await response.contents.cancel().catch(() => undefined);
50
+ }
51
+ throw new TypeError("Genie did not return a PNG visualization");
52
+ }
53
+ const bytes = new Uint8Array(await new Response(response.contents).arrayBuffer());
54
+ if (
55
+ bytes.length < 8 ||
56
+ bytes[0] !== 0x89 ||
57
+ bytes[1] !== 0x50 ||
58
+ bytes[2] !== 0x4e ||
59
+ bytes[3] !== 0x47 ||
60
+ bytes[4] !== 0x0d ||
61
+ bytes[5] !== 0x0a ||
62
+ bytes[6] !== 0x1a ||
63
+ bytes[7] !== 0x0a
64
+ ) {
65
+ throw new TypeError("Genie returned an invalid PNG visualization");
66
+ }
67
+ return bytes;
68
+ }