@dbx-tools/genie 0.6.212 → 0.6.213

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
@@ -13,9 +13,14 @@ Pure Genie schemas and event detector helpers live in
13
13
 
14
14
  Key features:
15
15
 
16
+ - Streams the Genie Agent Mode API by default, including reasoning, SQL calls,
17
+ query output, and the synthesized answer.
16
18
  - Starts new Genie conversations or continues an existing `conversationId`.
17
- - Polls Databricks Genie until terminal status while filtering unchanged
18
- snapshots.
19
+ - Projects Agent Mode response items onto the existing `GenieMessage` snapshot
20
+ and semantic-event contracts.
21
+ - Retains the Conversation API polling driver behind `agentMode: false` and as
22
+ an automatic pre-stream fallback for `FEATURE_DISABLED` or preview-toggle
23
+ errors.
19
24
  - Converts raw Genie messages into semantic events for thinking text, generated
20
25
  SQL, row counts, final results, and errors.
21
26
  - Preserves AppKit OBO auth when called during an AppKit request, but also works
@@ -82,10 +87,13 @@ for await (const message of chat.genieChat(spaceId, "Top stores by revenue?")) {
82
87
  }
83
88
  ```
84
89
 
85
- `chat.genieChat()` starts a conversation or appends to an existing one, polls
86
- `client.genie.getMessage`, filters identical consecutive payloads, and stops
87
- after a terminal status. Use it when you want to run your own diffing or persist
88
- the raw Genie wire shape.
90
+ `chat.genieChat()` starts an Agent Mode response or continues an existing
91
+ conversation, projects SSE output into `GenieMessage` snapshots, filters
92
+ identical consecutive payloads, and stops after a terminal response. Set
93
+ `agentMode: false` to force the legacy start/create/get-message polling flow.
94
+ Use it when you want to run your own diffing or persist the normalized wire
95
+ shape. Agent Mode returns query output inline as Markdown; use polling when a
96
+ consumer specifically requires the legacy `statement_id`.
89
97
 
90
98
  ## Continue A Conversation
91
99
 
@@ -126,8 +134,8 @@ Client resolution order:
126
134
  2. AppKit execution-context client, when present;
127
135
  3. `createWorkspaceClient()` using AppKit's normal Databricks auth chain.
128
136
 
129
- Pass `options.context` as an `AbortSignal` or SDK context to cancel SDK calls and
130
- the polling sleep.
137
+ Pass `options.context` as an `AbortSignal` or SDK context to cancel the Agent
138
+ Mode stream, SDK calls, and any polling fallback sleep.
131
139
 
132
140
  ## Read Space Metadata And Starter Questions
133
141
 
@@ -155,14 +163,18 @@ thrown.
155
163
  `chat.GenieChatOptions` is shared by both drivers:
156
164
 
157
165
  - `conversationId` - append to an existing Genie conversation.
166
+ - `agentMode` - use Agent Mode SSE, default `true`; `false` forces polling.
167
+ - `enableVisualization` - request Agent Mode visualization generation.
158
168
  - `workspaceClient` - explicit Databricks SDK client.
159
- - `pollIntervalMs` - polling cadence, default `500`.
169
+ - `pollIntervalMs` - legacy fallback polling cadence, default `500`.
160
170
  - `context` - SDK `Context` or `AbortSignal` for cancellation.
161
171
 
162
172
  ## Modules
163
173
 
164
174
  - `chat` - `genieChat()` raw snapshot stream and `genieEventChat()` typed event
165
175
  stream.
176
+ - `agentMode` - `genieAgentModeChat()`, availability classification, and Agent
177
+ Mode transport options.
166
178
  - `space` - `getGenieSpace()` and `genieSampleQuestions()`.
167
179
 
168
180
  The AppKit-Mastra package builds its Genie tools on top of this driver; see
package/index.ts CHANGED
@@ -3,8 +3,10 @@
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.6.212";
6
+ export const PACKAGE_VERSION = "0.6.213";
7
+ export * as agentMode from "./src/agent-mode.ts";
7
8
  export * as chat from "./src/chat.ts";
8
9
  export * as space from "./src/space.ts";
10
+ export type { GenieAgentModeOptions } from "./src/agent-mode.ts";
9
11
  export type { GenieChatOptions } from "./src/chat.ts";
10
12
  export type { GetGenieSpaceOptions } from "./src/space.ts";
package/lib/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  export declare const PACKAGE_IDENTIFIER = "@dbx-tools/genie";
2
- export declare const PACKAGE_VERSION = "0.6.212";
2
+ export declare const PACKAGE_VERSION = "0.6.213";
3
+ export * as agentMode from "./src/agent-mode.ts";
3
4
  export * as chat from "./src/chat.ts";
4
5
  export * as space from "./src/space.ts";
6
+ export type { GenieAgentModeOptions } from "./src/agent-mode.ts";
5
7
  export type { GenieChatOptions } from "./src/chat.ts";
6
8
  export type { GetGenieSpaceOptions } from "./src/space.ts";
package/lib/index.js CHANGED
@@ -2,7 +2,8 @@
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.6.212";
5
+ export const PACKAGE_VERSION = "0.6.213";
6
+ export * as agentMode from "./src/agent-mode.js";
6
7
  export * as chat from "./src/chat.js";
7
8
  export * as space from "./src/space.js";
8
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxrQkFBa0IsQ0FBQztBQUNyRCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsU0FBUyxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxJQUFJLE1BQU0sZUFBZSxDQUFDO0FBQ3RDLE9BQU8sS0FBSyxLQUFLLE1BQU0sZ0JBQWdCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBHRU5FUkFURUQgYnkgcHJvamVuIHdhdGNoIC0gRE8gTk9UIEVESVQuXG4vLyBSZWdlbmVyYXRlZCBmcm9tIHRoZSBleHBvcnRpbmcgbW9kdWxlcyBpbiAuL3NyYy5cbi8vIEhhbmQgZWRpdHMgYXJlIG92ZXJ3cml0dGVuIG9uIHRoZSBuZXh0IHdhdGNoOyB0aGlzIGZpbGUgaXMgcmVhZC1vbmx5LlxuXG5leHBvcnQgY29uc3QgUEFDS0FHRV9JREVOVElGSUVSID0gXCJAZGJ4LXRvb2xzL2dlbmllXCI7XG5leHBvcnQgY29uc3QgUEFDS0FHRV9WRVJTSU9OID0gXCIwLjYuMjEyXCI7XG5leHBvcnQgKiBhcyBjaGF0IGZyb20gXCIuL3NyYy9jaGF0LnRzXCI7XG5leHBvcnQgKiBhcyBzcGFjZSBmcm9tIFwiLi9zcmMvc3BhY2UudHNcIjtcbmV4cG9ydCB0eXBlIHsgR2VuaWVDaGF0T3B0aW9ucyB9IGZyb20gXCIuL3NyYy9jaGF0LnRzXCI7XG5leHBvcnQgdHlwZSB7IEdldEdlbmllU3BhY2VPcHRpb25zIH0gZnJvbSBcIi4vc3JjL3NwYWNlLnRzXCI7XG4iXX0=
9
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxrQkFBa0IsQ0FBQztBQUNyRCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsU0FBUyxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxTQUFTLE1BQU0scUJBQXFCLENBQUM7QUFDakQsT0FBTyxLQUFLLElBQUksTUFBTSxlQUFlLENBQUM7QUFDdEMsT0FBTyxLQUFLLEtBQUssTUFBTSxnQkFBZ0IsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEdFTkVSQVRFRCBieSBwcm9qZW4gd2F0Y2ggLSBETyBOT1QgRURJVC5cbi8vIFJlZ2VuZXJhdGVkIGZyb20gdGhlIGV4cG9ydGluZyBtb2R1bGVzIGluIC4vc3JjLlxuLy8gSGFuZCBlZGl0cyBhcmUgb3ZlcndyaXR0ZW4gb24gdGhlIG5leHQgd2F0Y2g7IHRoaXMgZmlsZSBpcyByZWFkLW9ubHkuXG5cbmV4cG9ydCBjb25zdCBQQUNLQUdFX0lERU5USUZJRVIgPSBcIkBkYngtdG9vbHMvZ2VuaWVcIjtcbmV4cG9ydCBjb25zdCBQQUNLQUdFX1ZFUlNJT04gPSBcIjAuNi4yMTNcIjtcbmV4cG9ydCAqIGFzIGFnZW50TW9kZSBmcm9tIFwiLi9zcmMvYWdlbnQtbW9kZS50c1wiO1xuZXhwb3J0ICogYXMgY2hhdCBmcm9tIFwiLi9zcmMvY2hhdC50c1wiO1xuZXhwb3J0ICogYXMgc3BhY2UgZnJvbSBcIi4vc3JjL3NwYWNlLnRzXCI7XG5leHBvcnQgdHlwZSB7IEdlbmllQWdlbnRNb2RlT3B0aW9ucyB9IGZyb20gXCIuL3NyYy9hZ2VudC1tb2RlLnRzXCI7XG5leHBvcnQgdHlwZSB7IEdlbmllQ2hhdE9wdGlvbnMgfSBmcm9tIFwiLi9zcmMvY2hhdC50c1wiO1xuZXhwb3J0IHR5cGUgeyBHZXRHZW5pZVNwYWNlT3B0aW9ucyB9IGZyb20gXCIuL3NyYy9zcGFjZS50c1wiO1xuIl19
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Genie Agent Mode SSE transport.
3
+ *
4
+ * Streams the Responses-shaped Agent Mode API and projects its reasoning, SQL,
5
+ * query output, and final answer items onto the existing `GenieMessage`
6
+ * contract so callers can keep one semantic event pipeline across Agent Mode
7
+ * and the legacy polling API.
8
+ *
9
+ * @module
10
+ */
11
+ import type { WorkspaceClient } from "@databricks/appkit";
12
+ import { databricks } from "@dbx-tools/appkit";
13
+ import { type GenieMessage } from "@dbx-tools/shared-genie";
14
+ /** Inputs for one Agent Mode response stream. */
15
+ export interface GenieAgentModeOptions {
16
+ conversationId?: string;
17
+ enableVisualization?: boolean;
18
+ context?: databricks.ContextLike;
19
+ }
20
+ /** Stream one Agent Mode response as `GenieMessage` snapshots. */
21
+ export declare function genieAgentModeChat(client: WorkspaceClient, agentId: string, content: string, options?: GenieAgentModeOptions): AsyncGenerator<GenieMessage, void, void>;
22
+ /** Return whether Agent Mode is disabled or its preview toggle is unavailable. */
23
+ export declare function isAgentModeUnavailable(value: unknown): boolean;
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Genie Agent Mode SSE transport.
3
+ *
4
+ * Streams the Responses-shaped Agent Mode API and projects its reasoning, SQL,
5
+ * query output, and final answer items onto the existing `GenieMessage`
6
+ * contract so callers can keep one semantic event pipeline across Agent Mode
7
+ * and the legacy polling API.
8
+ *
9
+ * @module
10
+ */
11
+ import { databricks } from "@dbx-tools/appkit";
12
+ import { error, json, log, object } from "@dbx-tools/shared-core";
13
+ import { agentMode as agentModeWire, } from "@dbx-tools/shared-genie";
14
+ const logger = log.logger("genie/agent-mode");
15
+ const CANCEL_TIMEOUT_MS = 5_000;
16
+ /** Stream one Agent Mode response as `GenieMessage` snapshots. */
17
+ export async function* genieAgentModeChat(client, agentId, content, options = {}) {
18
+ const ownedController = options.context ? undefined : new AbortController();
19
+ const projection = new agentModeWire.GenieAgentModeProjection(agentId, content);
20
+ try {
21
+ const context = options.context
22
+ ? databricks.toContext(options.context)
23
+ : databricks.toContext(ownedController);
24
+ const response = await client.apiClient.request({
25
+ path: `/api/2.0/genie/agents/${encodeURIComponent(agentId)}/responses`,
26
+ method: "POST",
27
+ headers: new Headers({
28
+ accept: "text/event-stream",
29
+ "content-type": "application/json",
30
+ }),
31
+ raw: true,
32
+ payload: {
33
+ input: [
34
+ {
35
+ type: "message",
36
+ role: "user",
37
+ content: [{ type: "input_text", text: content }],
38
+ },
39
+ ],
40
+ ...(options.conversationId ? { conversation_id: options.conversationId } : {}),
41
+ ...(options.enableVisualization ? { enable_viz: true } : {}),
42
+ },
43
+ }, context);
44
+ const stream = object.isRecord(response) ? response.contents : undefined;
45
+ if (!isReadableStream(stream)) {
46
+ throw new TypeError("Genie Agent Mode did not return an SSE stream");
47
+ }
48
+ let previous;
49
+ for await (const event of parseSse(stream)) {
50
+ const message = projection.apply(event);
51
+ if (!message)
52
+ continue;
53
+ if (!object.deepEqual(message, previous)) {
54
+ yield message;
55
+ previous = message;
56
+ }
57
+ }
58
+ if (!projection.terminal) {
59
+ throw new Error("Genie Agent Mode stream ended before a terminal response");
60
+ }
61
+ }
62
+ finally {
63
+ ownedController?.abort();
64
+ if (!projection.terminal && projection.responseId && projection.conversationId) {
65
+ await cancelResponse(client, agentId, projection.conversationId, projection.responseId);
66
+ }
67
+ }
68
+ }
69
+ /** Return whether Agent Mode is disabled or its preview toggle is unavailable. */
70
+ export function isAgentModeUnavailable(value) {
71
+ const context = error.errorContext(value);
72
+ return context.hasMessage("feature", "disabled") || context.hasMessage("preview", "toggle");
73
+ }
74
+ function isReadableStream(value) {
75
+ return object.isRecord(value) && typeof value.getReader === "function";
76
+ }
77
+ async function cancelResponse(client, agentId, conversationId, responseId) {
78
+ const controller = new AbortController();
79
+ const timeout = setTimeout(() => controller.abort(), CANCEL_TIMEOUT_MS);
80
+ try {
81
+ await client.apiClient.request({
82
+ path: `/api/2.0/genie/agents/${encodeURIComponent(agentId)}/conversations/${encodeURIComponent(conversationId)}/responses/${encodeURIComponent(responseId)}/cancel`,
83
+ method: "POST",
84
+ headers: new Headers({
85
+ accept: "application/json",
86
+ "content-type": "application/json",
87
+ }),
88
+ raw: false,
89
+ }, databricks.toContext(controller));
90
+ }
91
+ catch (err) {
92
+ logger.debug("response:cancel-failed", {
93
+ agentId,
94
+ conversationId,
95
+ responseId,
96
+ error: error.errorMessage(err),
97
+ });
98
+ }
99
+ finally {
100
+ clearTimeout(timeout);
101
+ }
102
+ }
103
+ async function* parseSse(stream) {
104
+ const reader = stream.getReader();
105
+ const decoder = new TextDecoder();
106
+ let buffer = "";
107
+ try {
108
+ while (true) {
109
+ const { done, value } = await reader.read();
110
+ buffer += decoder.decode(value, { stream: !done });
111
+ const frames = buffer.split(/\r?\n\r?\n/);
112
+ buffer = frames.pop() ?? "";
113
+ for (const frame of frames) {
114
+ const event = parseSseFrame(frame);
115
+ if (event)
116
+ yield event;
117
+ }
118
+ if (done) {
119
+ const event = parseSseFrame(buffer);
120
+ if (event)
121
+ yield event;
122
+ break;
123
+ }
124
+ }
125
+ }
126
+ finally {
127
+ await reader.cancel().catch(() => undefined);
128
+ reader.releaseLock();
129
+ }
130
+ }
131
+ function parseSseFrame(frame) {
132
+ const data = frame
133
+ .split(/\r?\n/)
134
+ .filter((line) => line.startsWith("data:"))
135
+ .map((line) => line.slice(5).trimStart())
136
+ .join("\n");
137
+ if (!data || data === "[DONE]")
138
+ return undefined;
139
+ return agentModeWire.GenieAgentModeEventSchema.parse(json.parse(data));
140
+ }
141
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWdlbnQtbW9kZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9hZ2VudC1tb2RlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7R0FTRztBQUdILE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDbEUsT0FBTyxFQUNMLFNBQVMsSUFBSSxhQUFhLEdBRzNCLE1BQU0seUJBQXlCLENBQUM7QUFFakMsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0FBQzlDLE1BQU0saUJBQWlCLEdBQUcsS0FBSyxDQUFDO0FBU2hDLGtFQUFrRTtBQUNsRSxNQUFNLENBQUMsS0FBSyxTQUFTLENBQUMsQ0FBQyxrQkFBa0IsQ0FDdkMsTUFBdUIsRUFDdkIsT0FBZSxFQUNmLE9BQWUsRUFDZixVQUFpQyxFQUFFO0lBRW5DLE1BQU0sZUFBZSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsSUFBSSxlQUFlLEVBQUUsQ0FBQztJQUM1RSxNQUFNLFVBQVUsR0FBRyxJQUFJLGFBQWEsQ0FBQyx3QkFBd0IsQ0FBQyxPQUFPLEVBQUUsT0FBTyxDQUFDLENBQUM7SUFDaEYsSUFBSSxDQUFDO1FBQ0gsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU87WUFDN0IsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQztZQUN2QyxDQUFDLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxlQUFnQixDQUFDLENBQUM7UUFDM0MsTUFBTSxRQUFRLEdBQUcsTUFBTSxNQUFNLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FDN0M7WUFDRSxJQUFJLEVBQUUseUJBQXlCLGtC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QUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsRUFBRSxDQUFDO1NBQ3hDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNkLElBQUksQ0FBQyxJQUFJLElBQUksSUFBSSxLQUFLLFFBQVE7UUFBRSxPQUFPLFNBQVMsQ0FBQztJQUNqRCxPQUFPLGFBQWEsQ0FBQyx5QkFBeUIsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0FBQ3pFLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEdlbmllIEFnZW50IE1vZGUgU1NFIHRyYW5zcG9ydC5cbiAqXG4gKiBTdHJlYW1zIHRoZSBSZXNwb25zZXMtc2hhcGVkIEFnZW50IE1vZGUgQVBJIGFuZCBwcm9qZWN0cyBpdHMgcmVhc29uaW5nLCBTUUwsXG4gKiBxdWVyeSBvdXRwdXQsIGFuZCBmaW5hbCBhbnN3ZXIgaXRlbXMgb250byB0aGUgZXhpc3RpbmcgYEdlbmllTWVzc2FnZWBcbiAqIGNvbnRyYWN0IHNvIGNhbGxlcnMgY2FuIGtlZXAgb25lIHNlbWFudGljIGV2ZW50IHBpcGVsaW5lIGFjcm9zcyBBZ2VudCBNb2RlXG4gKiBhbmQgdGhlIGxlZ2FjeSBwb2xsaW5nIEFQSS5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHR5cGUgeyBXb3Jrc3BhY2VDbGllbnQgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0XCI7XG5pbXBvcnQgeyBkYXRhYnJpY2tzIH0gZnJvbSBcIkBkYngtdG9vbHMvYXBwa2l0XCI7XG5pbXBvcnQgeyBlcnJvciwganNvbiwgbG9nLCBvYmplY3QgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHtcbiAgYWdlbnRNb2RlIGFzIGFnZW50TW9kZVdpcmUsXG4gIHR5cGUgR2VuaWVBZ2VudE1vZGVFdmVudCxcbiAgdHlwZSBHZW5pZU1lc3NhZ2UsXG59IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1nZW5pZVwiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwiZ2VuaWUvYWdlbnQtbW9kZVwiKTtcbmNvbnN0IENBTkNFTF9USU1FT1VUX01TID0gNV8wMDA7XG5cbi8qKiBJbnB1dHMgZm9yIG9uZSBBZ2VudCBNb2RlIHJlc3BvbnNlIHN0cmVhbS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR2VuaWVBZ2VudE1vZGVPcHRpb25zIHtcbiAgY29udmVyc2F0aW9uSWQ/OiBzdHJpbmc7XG4gIGVuYWJsZVZpc3VhbGl6YXRpb24/OiBib29sZWFuO1xuICBjb250ZXh0PzogZGF0YWJyaWNrcy5Db250ZXh0TGlrZTtcbn1cblxuLyoqIFN0cmVhbSBvbmUgQWdlbnQgTW9kZSByZXNwb25zZSBhcyBgR2VuaWVNZXNzYWdlYCBzbmFwc2hvdHMuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24qIGdlbmllQWdlbnRNb2RlQ2hhdChcbiAgY2xpZW50OiBXb3Jrc3BhY2VDbGllbnQsXG4gIGFnZW50SWQ6IHN0cmluZyxcbiAgY29udGVudDogc3RyaW5nLFxuICBvcHRpb25zOiBHZW5pZUFnZW50TW9kZU9wdGlvbnMgPSB7fSxcbik6IEFzeW5jR2VuZXJhdG9yPEdlbmllTWVzc2FnZSwgdm9pZCwgdm9pZD4ge1xuICBjb25zdCBvd25lZENvbnRyb2xsZXIgPSBvcHRpb25zLmNvbnRleHQgPyB1bmRlZmluZWQgOiBuZXcgQWJvcnRDb250cm9sbGVyKCk7XG4gIGNvbnN0IHByb2plY3Rpb24gPSBuZXcgYWdlbnRNb2RlV2lyZS5HZW5pZUFnZW50TW9kZVByb2plY3Rpb24oYWdlbnRJZCwgY29udGVudCk7XG4gIHRyeSB7XG4gICAgY29uc3QgY29udGV4dCA9IG9wdGlvbnMuY29udGV4dFxuICAgICAgPyBkYXRhYnJpY2tzLnRvQ29udGV4dChvcHRpb25zLmNvbnRleHQpXG4gICAgICA6IGRhdGFicmlja3MudG9Db250ZXh0KG93bmVkQ29udHJvbGxlciEpO1xuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgY2xpZW50LmFwaUNsaWVudC5yZXF1ZXN0KFxuICAgICAge1xuICAgICAgICBwYXRoOiBgL2FwaS8yLjAvZ2VuaWUvYWdlbnRzLyR7ZW5jb2RlVVJJQ29tcG9uZW50KGFnZW50SWQpfS9yZXNwb25zZXNgLFxuICAgICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgICBoZWFkZXJzOiBuZXcgSGVhZGVycyh7XG4gICAgICAgICAgYWNjZXB0OiBcInRleHQvZXZlbnQtc3RyZWFtXCIsXG4gICAgICAgICAgXCJjb250ZW50LXR5cGVcIjogXCJhcHBsaWNhdGlvbi9qc29uXCIsXG4gICAgICAgIH0pLFxuICAgICAgICByYXc6IHRydWUsXG4gICAgICAgIHBheWxvYWQ6IHtcbiAgICAgICAgICBpbnB1dDogW1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICB0eXBlOiBcIm1lc3NhZ2VcIixcbiAgICAgICAgICAgICAgcm9sZTogXCJ1c2VyXCIsXG4gICAgICAgICAgICAgIGNvbnRlbnQ6IFt7IHR5cGU6IFwiaW5wdXRfdGV4dFwiLCB0ZXh0OiBjb250ZW50IH1dLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICBdLFxuICAgICAgICAgIC4uLihvcHRpb25zLmNvbnZlcnNhdGlvbklkID8geyBjb252ZXJzYXRpb25faWQ6IG9wdGlvbnMuY29udmVyc2F0aW9uSWQgfSA6IHt9KSxcbiAgICAgICAgICAuLi4ob3B0aW9ucy5lbmFibGVWaXN1YWxpemF0aW9uID8geyBlbmFibGVfdml6OiB0cnVlIH0gOiB7fSksXG4gICAgICAgIH0sXG4gICAgICB9LFxuICAgICAgY29udGV4dCxcbiAgICApO1xuICAgIGNvbnN0IHN0cmVhbSA9IG9iamVjdC5pc1JlY29yZChyZXNwb25zZSkgPyByZXNwb25zZS5jb250ZW50cyA6IHVuZGVmaW5lZDtcbiAgICBpZiAoIWlzUmVhZGFibGVTdHJlYW0oc3RyZWFtKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmllIEFnZW50IE1vZGUgZGlkIG5vdCByZXR1cm4gYW4gU1NFIHN0cmVhbVwiKTtcbiAgICB9XG5cbiAgICBsZXQgcHJldmlvdXM6IEdlbmllTWVzc2FnZSB8IHVuZGVmaW5lZDtcbiAgICBmb3IgYXdhaXQgKGNvbnN0IGV2ZW50IG9mIHBhcnNlU3NlKHN0cmVhbSkpIHtcbiAgICAgIGNvbnN0IG1lc3NhZ2UgPSBwcm9qZWN0aW9uLmFwcGx5KGV2ZW50KTtcbiAgICAgIGlmICghbWVzc2FnZSkgY29udGludWU7XG4gICAgICBpZiAoIW9iamVjdC5kZWVwRXF1YWwobWVzc2FnZSwgcHJldmlvdXMpKSB7XG4gICAgICAgIHlpZWxkIG1lc3NhZ2U7XG4gICAgICAgIHByZXZpb3VzID0gbWVzc2FnZTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKCFwcm9qZWN0aW9uLnRlcm1pbmFsKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJHZW5pZSBBZ2VudCBNb2RlIHN0cmVhbSBlbmRlZCBiZWZvcmUgYSB0ZXJtaW5hbCByZXNwb25zZVwiKTtcbiAgICB9XG4gIH0gZmluYWxseSB7XG4gICAgb3duZWRDb250cm9sbGVyPy5hYm9ydCgpO1xuICAgIGlmICghcHJvamVjdGlvbi50ZXJtaW5hbCAmJiBwcm9qZWN0aW9uLnJlc3BvbnNlSWQgJiYgcHJvamVjdGlvbi5jb252ZXJzYXRpb25JZCkge1xuICAgICAgYXdhaXQgY2FuY2VsUmVzcG9uc2UoY2xpZW50LCBhZ2VudElkLCBwcm9qZWN0aW9uLmNvbnZlcnNhdGlvbklkLCBwcm9qZWN0aW9uLnJlc3BvbnNlSWQpO1xuICAgIH1cbiAgfVxufVxuXG4vKiogUmV0dXJuIHdoZXRoZXIgQWdlbnQgTW9kZSBpcyBkaXNhYmxlZCBvciBpdHMgcHJldmlldyB0b2dnbGUgaXMgdW5hdmFpbGFibGUuICovXG5leHBvcnQgZnVuY3Rpb24gaXNBZ2VudE1vZGVVbmF2YWlsYWJsZSh2YWx1ZTogdW5rbm93bik6IGJvb2xlYW4ge1xuICBjb25zdCBjb250ZXh0ID0gZXJyb3IuZXJyb3JDb250ZXh0KHZhbHVlKTtcbiAgcmV0dXJuIGNvbnRleHQuaGFzTWVzc2FnZShcImZlYXR1cmVcIiwgXCJkaXNhYmxlZFwiKSB8fCBjb250ZXh0Lmhhc01lc3NhZ2UoXCJwcmV2aWV3XCIsIFwidG9nZ2xlXCIpO1xufVxuXG5mdW5jdGlvbiBpc1JlYWRhYmxlU3RyZWFtKHZhbHVlOiB1bmtub3duKTogdmFsdWUgaXMgUmVhZGFibGVTdHJlYW08VWludDhBcnJheT4ge1xuICByZXR1cm4gb2JqZWN0LmlzUmVjb3JkKHZhbHVlKSAmJiB0eXBlb2YgdmFsdWUuZ2V0UmVhZGVyID09PSBcImZ1bmN0aW9uXCI7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGNhbmNlbFJlc3BvbnNlKFxuICBjbGllbnQ6IFdvcmtzcGFjZUNsaWVudCxcbiAgYWdlbnRJZDogc3RyaW5nLFxuICBjb252ZXJzYXRpb25JZDogc3RyaW5nLFxuICByZXNwb25zZUlkOiBzdHJpbmcsXG4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgY29uc3QgY29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgY29uc3QgdGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4gY29udHJvbGxlci5hYm9ydCgpLCBDQU5DRUxfVElNRU9VVF9NUyk7XG4gIHRyeSB7XG4gICAgYXdhaXQgY2xpZW50LmFwaUNsaWVudC5yZXF1ZXN0KFxuICAgICAge1xuICAgICAgICBwYXRoOiBgL2FwaS8yLjAvZ2VuaWUvYWdlbnRzLyR7ZW5jb2RlVVJJQ29tcG9uZW50KGFnZW50SWQpfS9jb252ZXJzYXRpb25zLyR7ZW5jb2RlVVJJQ29tcG9uZW50KGNvbnZlcnNhdGlvbklkKX0vcmVzcG9uc2VzLyR7ZW5jb2RlVVJJQ29tcG9uZW50KHJlc3BvbnNlSWQpfS9jYW5jZWxgLFxuICAgICAgICBtZXRob2Q6IFwiUE9TVFwiLFxuICAgICAgICBoZWFkZXJzOiBuZXcgSGVhZGVycyh7XG4gICAgICAgICAgYWNjZXB0OiBcImFwcGxpY2F0aW9uL2pzb25cIixcbiAgICAgICAgICBcImNvbnRlbnQtdHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb25cIixcbiAgICAgICAgfSksXG4gICAgICAgIHJhdzogZmFsc2UsXG4gICAgICB9LFxuICAgICAgZGF0YWJyaWNrcy50b0NvbnRleHQoY29udHJvbGxlciksXG4gICAgKTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgbG9nZ2VyLmRlYnVnKFwicmVzcG9uc2U6Y2FuY2VsLWZhaWxlZFwiLCB7XG4gICAgICBhZ2VudElkLFxuICAgICAgY29udmVyc2F0aW9uSWQsXG4gICAgICByZXNwb25zZUlkLFxuICAgICAgZXJyb3I6IGVycm9yLmVycm9yTWVzc2FnZShlcnIpLFxuICAgIH0pO1xuICB9IGZpbmFsbHkge1xuICAgIGNsZWFyVGltZW91dCh0aW1lb3V0KTtcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiogcGFyc2VTc2UoXG4gIHN0cmVhbTogUmVhZGFibGVTdHJlYW08VWludDhBcnJheT4sXG4pOiBBc3luY0dlbmVyYXRvcjxHZW5pZUFnZW50TW9kZUV2ZW50LCB2b2lkLCB2b2lkPiB7XG4gIGNvbnN0IHJlYWRlciA9IHN0cmVhbS5nZXRSZWFkZXIoKTtcbiAgY29uc3QgZGVjb2RlciA9IG5ldyBUZXh0RGVjb2RlcigpO1xuICBsZXQgYnVmZmVyID0gXCJcIjtcbiAgdHJ5IHtcbiAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgY29uc3QgeyBkb25lLCB2YWx1ZSB9ID0gYXdhaXQgcmVhZGVyLnJlYWQoKTtcbiAgICAgIGJ1ZmZlciArPSBkZWNvZGVyLmRlY29kZSh2YWx1ZSwgeyBzdHJlYW06ICFkb25lIH0pO1xuICAgICAgY29uc3QgZnJhbWVzID0gYnVmZmVyLnNwbGl0KC9cXHI/XFxuXFxyP1xcbi8pO1xuICAgICAgYnVmZmVyID0gZnJhbWVzLnBvcCgpID8/IFwiXCI7XG4gICAgICBmb3IgKGNvbnN0IGZyYW1lIG9mIGZyYW1lcykge1xuICAgICAgICBjb25zdCBldmVudCA9IHBhcnNlU3NlRnJhbWUoZnJhbWUpO1xuICAgICAgICBpZiAoZXZlbnQpIHlpZWxkIGV2ZW50O1xuICAgICAgfVxuICAgICAgaWYgKGRvbmUpIHtcbiAgICAgICAgY29uc3QgZXZlbnQgPSBwYXJzZVNzZUZyYW1lKGJ1ZmZlcik7XG4gICAgICAgIGlmIChldmVudCkgeWllbGQgZXZlbnQ7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgfSBmaW5hbGx5IHtcbiAgICBhd2FpdCByZWFkZXIuY2FuY2VsKCkuY2F0Y2goKCkgPT4gdW5kZWZpbmVkKTtcbiAgICByZWFkZXIucmVsZWFzZUxvY2soKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBwYXJzZVNzZUZyYW1lKGZyYW1lOiBzdHJpbmcpOiBHZW5pZUFnZW50TW9kZUV2ZW50IHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgZGF0YSA9IGZyYW1lXG4gICAgLnNwbGl0KC9cXHI/XFxuLylcbiAgICAuZmlsdGVyKChsaW5lKSA9PiBsaW5lLnN0YXJ0c1dpdGgoXCJkYXRhOlwiKSlcbiAgICAubWFwKChsaW5lKSA9PiBsaW5lLnNsaWNlKDUpLnRyaW1TdGFydCgpKVxuICAgIC5qb2luKFwiXFxuXCIpO1xuICBpZiAoIWRhdGEgfHwgZGF0YSA9PT0gXCJbRE9ORV1cIikgcmV0dXJuIHVuZGVmaW5lZDtcbiAgcmV0dXJuIGFnZW50TW9kZVdpcmUuR2VuaWVBZ2VudE1vZGVFdmVudFNjaGVtYS5wYXJzZShqc29uLnBhcnNlKGRhdGEpKTtcbn1cbiJdfQ==
package/lib/src/chat.d.ts CHANGED
@@ -6,11 +6,15 @@
6
6
  * returned on each `GenieMessage` back into the next turn's
7
7
  * `options.conversationId`).
8
8
  *
9
+ * Agent Mode SSE is the default transport. Its Responses-style reasoning, SQL,
10
+ * query output, and final answer items are projected into `GenieMessage`
11
+ * snapshots; `agentMode: false` retains the Conversation API polling path.
12
+ *
9
13
  * Two layers serve two kinds of consumer. The low-level layer yields every
10
- * poll-observed `GenieMessage` (validated against `GenieMessageSchema`,
11
- * falling back to the raw snapshot on a schema miss) and owns the messy parts
12
- * - cancellation, conversation seeding, distinct-filtering, and SDK quirks
13
- * (Waiter stripping); reach for it when you want the raw stream. The
14
+ * observed `GenieMessage` (validated against `GenieMessageSchema`, falling back
15
+ * to the raw snapshot on a schema miss) and owns cancellation, conversation
16
+ * seeding, distinct-filtering, and SDK quirks; reach for it when you want the
17
+ * raw stream. The
14
18
  * high-level layer wraps it and emits semantic, deduplicated `{ type, payload }`
15
19
  * events (see {@link GenieChatEvent}), always closing a successful turn with a
16
20
  * terminal `result` event carrying the final `GenieMessage`; errors propagate
@@ -26,11 +30,16 @@ import { type GenieChatEvent, type GenieMessage } from "@dbx-tools/shared-genie"
26
30
  /** Options accepted by both {@link genieChat} and {@link genieEventChat}. */
27
31
  export interface GenieChatOptions {
28
32
  /**
29
- * Seed conversation id. When set, this turn appends to the existing
30
- * conversation (via `createMessage`) instead of opening a new one. Use it to
31
- * thread a multi-turn conversation: read `conversation_id` off the prior
32
- * turn's terminal `GenieMessage` (or the `result` event's
33
- * `payload.conversation_id`) and pass it into the next call.
33
+ * Use the streaming Genie Agent Mode API. Defaults to `true`; set `false` to
34
+ * force the legacy start/create/get-message polling flow.
35
+ */
36
+ agentMode?: boolean;
37
+ /** Ask Agent Mode to generate visualizations when appropriate. */
38
+ enableVisualization?: boolean;
39
+ /**
40
+ * Continue an existing conversation. Agent Mode sends it as
41
+ * `conversation_id`; legacy polling passes it to `createMessage`. Read the id
42
+ * from the prior turn's terminal `GenieMessage` or `result` event.
34
43
  */
35
44
  conversationId?: string;
36
45
  /**
@@ -40,12 +49,12 @@ export interface GenieChatOptions {
40
49
  * otherwise.
41
50
  */
42
51
  workspaceClient?: WorkspaceClient;
43
- /** Poll cadence in milliseconds between successive `getMessage` calls (default 500). */
52
+ /** Legacy fallback cadence between successive `getMessage` calls (default 500ms). */
44
53
  pollIntervalMs?: number;
45
54
  /**
46
55
  * External cancellation. Accepts a WHATWG `AbortSignal` or a fully-built SDK
47
56
  * `Context` (see `databricks.ContextLike`). Aborting it cancels every in-flight
48
- * SDK call and the next inter-poll sleep.
57
+ * Agent Mode stream, SDK call, and the next inter-poll sleep.
49
58
  */
50
59
  context?: databricks.ContextLike;
51
60
  }
@@ -55,21 +64,19 @@ export interface GenieChatOptions {
55
64
  *
56
65
  * Turn lifecycle:
57
66
  *
58
- * - No `options.conversationId`: open a new conversation via
59
- * `client.genie.startConversation`. The opened conversation id surfaces on
60
- * every yielded `GenieMessage` (`.conversation_id`) so the caller can
61
- * thread it into a follow-up call.
62
- * - With `options.conversationId`: append to that conversation via
63
- * `client.genie.createMessage`.
64
- * - In both cases, after the create/start the driver polls
65
- * `client.genie.getMessage` every `options.pollIntervalMs` (default 500ms)
66
- * until the message reaches a terminal status, then yields the terminal
67
- * snapshot and returns.
67
+ * - Agent Mode (default): POST one Responses-style message to
68
+ * `/api/2.0/genie/agents/{id}/responses` and yield projected snapshots from
69
+ * its SSE events.
70
+ * - Legacy polling (`agentMode: false`): start/create a Conversation API
71
+ * message and poll `getMessage` until terminal.
72
+ * - A pre-stream `FEATURE_DISABLED` or preview-toggle response falls back to
73
+ * legacy polling automatically.
68
74
  *
69
75
  * Cancellation: a single internal `AbortController` covers the whole turn.
70
76
  * `options.context` is tied into that controller so an external abort tears
71
- * down every in-flight SDK call AND the inter-poll sleep. Breaking out of the
72
- * `for await` does the same via the `try / finally`.
77
+ * down the Agent Mode SSE connection, SDK calls, and any inter-poll sleep.
78
+ * Breaking out of the `for await` also invokes the Agent Mode server-side
79
+ * cancel endpoint before the generator closes.
73
80
  *
74
81
  * @example
75
82
  * // Single turn.
package/lib/src/chat.js CHANGED
@@ -6,11 +6,15 @@
6
6
  * returned on each `GenieMessage` back into the next turn's
7
7
  * `options.conversationId`).
8
8
  *
9
+ * Agent Mode SSE is the default transport. Its Responses-style reasoning, SQL,
10
+ * query output, and final answer items are projected into `GenieMessage`
11
+ * snapshots; `agentMode: false` retains the Conversation API polling path.
12
+ *
9
13
  * Two layers serve two kinds of consumer. The low-level layer yields every
10
- * poll-observed `GenieMessage` (validated against `GenieMessageSchema`,
11
- * falling back to the raw snapshot on a schema miss) and owns the messy parts
12
- * - cancellation, conversation seeding, distinct-filtering, and SDK quirks
13
- * (Waiter stripping); reach for it when you want the raw stream. The
14
+ * observed `GenieMessage` (validated against `GenieMessageSchema`, falling back
15
+ * to the raw snapshot on a schema miss) and owns cancellation, conversation
16
+ * seeding, distinct-filtering, and SDK quirks; reach for it when you want the
17
+ * raw stream. The
14
18
  * high-level layer wraps it and emits semantic, deduplicated `{ type, payload }`
15
19
  * events (see {@link GenieChatEvent}), always closing a successful turn with a
16
20
  * terminal `result` event carrying the final `GenieMessage`; errors propagate
@@ -22,8 +26,9 @@
22
26
  */
23
27
  import { createWorkspaceClient, getExecutionContext, } from "@databricks/appkit";
24
28
  import { databricks } from "@dbx-tools/appkit";
25
- import { async, log } from "@dbx-tools/shared-core";
29
+ import { async, error, log } from "@dbx-tools/shared-core";
26
30
  import { event, genieModel } from "@dbx-tools/shared-genie";
31
+ import { genieAgentModeChat, isAgentModeUnavailable } from "./agent-mode.js";
27
32
  const logger = log.logger("genie/chat");
28
33
  /**
29
34
  * Validate a polled wire snapshot against {@link GenieMessageSchema}
@@ -50,21 +55,19 @@ function validateMessage(raw) {
50
55
  *
51
56
  * Turn lifecycle:
52
57
  *
53
- * - No `options.conversationId`: open a new conversation via
54
- * `client.genie.startConversation`. The opened conversation id surfaces on
55
- * every yielded `GenieMessage` (`.conversation_id`) so the caller can
56
- * thread it into a follow-up call.
57
- * - With `options.conversationId`: append to that conversation via
58
- * `client.genie.createMessage`.
59
- * - In both cases, after the create/start the driver polls
60
- * `client.genie.getMessage` every `options.pollIntervalMs` (default 500ms)
61
- * until the message reaches a terminal status, then yields the terminal
62
- * snapshot and returns.
58
+ * - Agent Mode (default): POST one Responses-style message to
59
+ * `/api/2.0/genie/agents/{id}/responses` and yield projected snapshots from
60
+ * its SSE events.
61
+ * - Legacy polling (`agentMode: false`): start/create a Conversation API
62
+ * message and poll `getMessage` until terminal.
63
+ * - A pre-stream `FEATURE_DISABLED` or preview-toggle response falls back to
64
+ * legacy polling automatically.
63
65
  *
64
66
  * Cancellation: a single internal `AbortController` covers the whole turn.
65
67
  * `options.context` is tied into that controller so an external abort tears
66
- * down every in-flight SDK call AND the inter-poll sleep. Breaking out of the
67
- * `for await` does the same via the `try / finally`.
68
+ * down the Agent Mode SSE connection, SDK calls, and any inter-poll sleep.
69
+ * Breaking out of the `for await` also invokes the Agent Mode server-side
70
+ * cancel endpoint before the generator closes.
68
71
  *
69
72
  * @example
70
73
  * // Single turn.
@@ -91,6 +94,28 @@ export async function* genieChat(space_id, content, options) {
91
94
  // (via `databricks.toContext` -> `async.tieAbortSignal`), eventually tripping
92
95
  // Node's `MaxListenersExceededWarning`.
93
96
  const ctx = databricks.toContext(controller, options?.context);
97
+ if (options?.agentMode !== false) {
98
+ let yielded = false;
99
+ try {
100
+ for await (const message of genieAgentModeChat(client, space_id, content, {
101
+ ...(options?.conversationId ? { conversationId: options.conversationId } : {}),
102
+ ...(options?.enableVisualization ? { enableVisualization: true } : {}),
103
+ context: ctx,
104
+ })) {
105
+ yielded = true;
106
+ yield validateMessage(message);
107
+ }
108
+ return;
109
+ }
110
+ catch (err) {
111
+ if (yielded || !isAgentModeUnavailable(err))
112
+ throw err;
113
+ logger.warn("agent-mode:unavailable, falling back to polling", {
114
+ space_id,
115
+ error: error.errorMessage(err),
116
+ });
117
+ }
118
+ }
94
119
  let conversationId = options?.conversationId;
95
120
  let messageId;
96
121
  const pollProducer = async (pollCtx) => {
@@ -257,4 +282,4 @@ async function getWorkspaceClient(options) {
257
282
  }
258
283
  return createWorkspaceClient();
259
284
  }
260
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jaGF0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FxQkc7QUFFSCxPQUFPLEVBQ0wscUJBQXFCLEVBQ3JCLG1CQUFtQixHQUVwQixNQUFNLG9CQUFvQixDQUFDO0FBQzVCLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQUMvQyxPQUFPLEVBQUUsS0FBSyxFQUFFLEdBQUcsRUFBb0IsTUFBTSx3QkFBd0IsQ0FBQztBQUN0RSxPQUFPLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBMEMsTUFBTSx5QkFBeUIsQ0FBQztBQUVwRyxNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxDQUFDO0FBRXhDOzs7Ozs7O0dBT0c7QUFDSCxTQUFTLGVBQWUsQ0FBQyxHQUFpQjtJQUN4QyxNQUFNLE1BQU0sR0FBRyxVQUFVLENBQUMsa0JBQWtCLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQzVELElBQUksTUFBTSxDQUFDLE9BQU87UUFBRSxPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUM7SUFDdkMsTUFBTSxDQUFDLEtBQUssQ0FBQywwQkFBMEIsRUFBRTtRQUN2QyxVQUFVLEVBQUUsR0FBRyxDQUFDLFVBQVUsSUFBSSxHQUFHLENBQUMsRUFBRTtRQUNwQyxNQUFNLEVBQUUsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsTUFBTTtLQUNuQyxDQUFDLENBQUM7SUFDSCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUM7QUErQkQsMEVBQTBFO0FBRTFFOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBcUNHO0FBQ0gsTUFBTSxDQUFDLEtBQUssU0FBUyxDQUFDLENBQUMsU0FBUyxDQUM5QixRQUFnQixFQUNoQixPQUFlLEVBQ2YsT0FBMEI7SUFFMUIsTUFBTSxVQUFV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RSxVQUFVLEVBQUUsT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7Z0JBQ2pFLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTzthQUN6QixDQUFDO1lBQ0YsZUFBZSxHQUFHLElBQUksQ0FBQztRQUN6QixDQUFDO1FBQ0QsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLGlCQUFpQixDQUFDLE9BQU8sRUFBRSxRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3BFLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUM7UUFDOUIsSUFBSSxVQUFVLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztZQUN4QyxNQUFNO2dCQUNKLElBQUksRUFBRSxRQUFRO2dCQUNkLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUTtnQkFDMUIsZUFBZSxFQUFFLE9BQU8sQ0FBQyxlQUFlO2dCQUN4QyxVQUFVLEVBQUUsT0FBTyxDQUFDLFVBQVU7Z0JBQzlCLE1BQU07Z0JBQ04sT0FBTzthQUNSLENBQUM7UUFDSixDQUFDO1FBQ0QsUUFBUSxHQUFHLE9BQU8sQ0FBQztJQUNyQixDQUFDO0FBQ0gsQ0FBQztBQUVELDBFQUEwRTtBQUUxRTs7Ozs7Ozs7R0FRRztBQUNILEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUEwQjtJQUMxRCxJQUFJLE9BQU8sRUFBRSxlQUFlO1FBQUUsT0FBTyxPQUFPLENBQUMsZUFBZSxDQUFDO0lBQzdELElBQUksQ0FBQztRQUNILE9BQU8sbUJBQW1CLEVBQUUsQ0FBQyxNQUFNLENBQUM7SUFDdEMsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLHNFQUFzRTtJQUN4RSxDQUFDO0lBQ0QsT0FBTyxxQkFBcUIsRUFBRSxDQUFDO0FBQ2pDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEdlbmllIGNoYXQgZHJpdmVyLlxuICpcbiAqIERyaXZlcyBhIHNpbmdsZSB0dXJuIGFnYWluc3QgYSBHZW5pZSBzcGFjZSBmcm9tIG9uZSBgY29udGVudGAgc3RyaW5nO1xuICogbXVsdGktdHVybiBjb252ZXJzYXRpb25zIGFyZSB0aGUgY2FsbGVyJ3Mgam9iICh0aHJlYWQgdGhlIGBjb252ZXJzYXRpb25faWRgXG4gKiByZXR1cm5lZCBvbiBlYWNoIGBHZW5pZU1lc3NhZ2VgIGJhY2sgaW50byB0aGUgbmV4dCB0dXJuJ3NcbiAqIGBvcHRpb25zLmNvbnZlcnNhdGlvbklkYCkuXG4gKlxuICogVHdvIGxheWVycyBzZXJ2ZSB0d28ga2luZHMgb2YgY29uc3VtZXIuIFRoZSBsb3ctbGV2ZWwgbGF5ZXIgeWllbGRzIGV2ZXJ5XG4gKiBwb2xsLW9ic2VydmVkIGBHZW5pZU1lc3NhZ2VgICh2YWxpZGF0ZWQgYWdhaW5zdCBgR2VuaWVNZXNzYWdlU2NoZW1hYCxcbiAqIGZhbGxpbmcgYmFjayB0byB0aGUgcmF3IHNuYXBzaG90IG9uIGEgc2NoZW1hIG1pc3MpIGFuZCBvd25zIHRoZSBtZXNzeSBwYXJ0c1xuICogLSBjYW5jZWxsYXRpb24sIGNvbnZlcnNhdGlvbiBzZWVkaW5nLCBkaXN0aW5jdC1maWx0ZXJpbmcsIGFuZCBTREsgcXVpcmtzXG4gKiAoV2FpdGVyIHN0cmlwcGluZyk7IHJlYWNoIGZvciBpdCB3aGVuIHlvdSB3YW50IHRoZSByYXcgc3RyZWFtLiBUaGVcbiAqIGhpZ2gtbGV2ZWwgbGF5ZXIgd3JhcHMgaXQgYW5kIGVtaXRzIHNlbWFudGljLCBkZWR1cGxpY2F0ZWQgYHsgdHlwZSwgcGF5bG9hZCB9YFxuICogZXZlbnRzIChzZWUge0BsaW5rIEdlbmllQ2hhdEV2ZW50fSksIGFsd2F5cyBjbG9zaW5nIGEgc3VjY2Vzc2Z1bCB0dXJuIHdpdGggYVxuICogdGVybWluYWwgYHJlc3VsdGAgZXZlbnQgY2FycnlpbmcgdGhlIGZpbmFsIGBHZW5pZU1lc3NhZ2VgOyBlcnJvcnMgcHJvcGFnYXRlXG4gKiBieSB0aHJvd2luZywgd2l0aCBubyBgZXJyb3JgIHZhcmlhbnQuIEl0ZXJhdGluZyBVSSAvIGFnZW50IGNvZGUgdGhhdCB3YW50c1xuICogZXZlcnkgbWVzc2FnZSB2ZXJiYXRpbSB0YWtlcyB0aGUgbG93LWxldmVsIHN0cmVhbTsgc3Vic2NyaWJlcnMgcmVhY3RpbmcgdG9cbiAqIFwiR2VuaWUgaXMgdGhpbmtpbmcgYWJvdXQgWFwiIG9yIFwiR2VuaWUgcHJvZHVjZWQgdGV4dCBZXCIgdGFrZSB0aGUgZXZlbnQgbGF5ZXIuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7XG4gIGNyZWF0ZVdvcmtzcGFjZUNsaWVudCxcbiAgZ2V0RXhlY3V0aW9uQ29udGV4dCxcbiAgdHlwZSBXb3Jrc3BhY2VDbGllbnQsXG59IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbmltcG9ydCB7IGRhdGFicmlja3MgfSBmcm9tIFwiQGRieC10b29scy9hcHBraXRcIjtcbmltcG9ydCB7IGFzeW5jLCBsb2csIHR5cGUgUG9sbENvbnRleHQgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHsgZXZlbnQsIGdlbmllTW9kZWwsIHR5cGUgR2VuaWVDaGF0RXZlbnQsIHR5cGUgR2VuaWVNZXNzYWdlIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWdlbmllXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGxvZy5sb2dnZXIoXCJnZW5pZS9jaGF0XCIpO1xuXG4vKipcbiAqIFZhbGlkYXRlIGEgcG9sbGVkIHdpcmUgc25hcHNob3QgYWdhaW5zdCB7QGxpbmsgR2VuaWVNZXNzYWdlU2NoZW1hfVxuICogYW5kIHJldHVybiB0aGUgc2NoZW1hLW5vcm1hbGl6ZWQgbWVzc2FnZS4gR2VuaWUncyB3aXJlIG9jY2FzaW9uYWxseSBzaGlwcyBhXG4gKiBzaGFwZSB0aGUgKFNESy1kZXJpdmVkKSBzY2hlbWEgZG9lc24ndCBtb2RlbCBleGFjdGx5IC0gZS5nLiBhbiBlYXJseSBwb2xsXG4gKiB0aGF0IG9taXRzIHRoZSBTREstcmVxdWlyZWQgYG1lc3NhZ2VfaWRgIC0gc28gYSBtaXNzIGRlZ3JhZGVzIHRvIHRoZSByYXdcbiAqIHNuYXBzaG90IHJhdGhlciB0aGFuIHRocm93aW5nLCBrZWVwaW5nIGEgc2luZ2xlIG9kZCBwb2xsIGZyb20gYWJvcnRpbmcgdGhlXG4gKiB3aG9sZSB0dXJuLlxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZU1lc3NhZ2UocmF3OiBHZW5pZU1lc3NhZ2UpOiBHZW5pZU1lc3NhZ2Uge1xuICBjb25zdCByZXN1bHQgPSBnZW5pZU1vZGVsLkdlbmllTWVzc2FnZVNjaGVtYS5zYWZlUGFyc2UocmF3KTtcbiAgaWYgKHJlc3VsdC5zdWNjZXNzKSByZXR1cm4gcmVzdWx0LmRhdGE7XG4gIGxvZ2dlci5kZWJ1ZyhcIndpcmUtbWVzc2FnZTpzY2hlbWEtbWlzc1wiLCB7XG4gICAgbWVzc2FnZV9pZDogcmF3Lm1lc3NhZ2VfaWQgPz8gcmF3LmlkLFxuICAgIGlzc3VlczogcmVzdWx0LmVycm9yLmlzc3Vlcy5sZW5ndGgsXG4gIH0pO1xuICByZXR1cm4gcmF3O1xufVxuXG4vKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBzaGFyZWQgb3B0aW9ucyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG4vKiogT3B0aW9ucyBhY2NlcHRlZCBieSBib3RoIHtAbGluayBnZW5pZUNoYXR9IGFuZCB7QGxpbmsgZ2VuaWVFdmVudENoYXR9LiAqL1xuZXhwb3J0IGludGVyZmFjZSBHZW5pZUNoYXRPcHRpb25zIHtcbiAgLyoqXG4gICAqIFNlZWQgY29udmVyc2F0aW9uIGlkLiBXaGVuIHNldCwgdGhpcyB0dXJuIGFwcGVuZHMgdG8gdGhlIGV4aXN0aW5nXG4gICAqIGNvbnZlcnNhdGlvbiAodmlhIGBjcmVhdGVNZXNzYWdlYCkgaW5zdGVhZCBvZiBvcGVuaW5nIGEgbmV3IG9uZS4gVXNlIGl0IHRvXG4gICAqIHRocmVhZCBhIG11bHRpLXR1cm4gY29udmVyc2F0aW9uOiByZWFkIGBjb252ZXJzYXRpb25faWRgIG9mZiB0aGUgcHJpb3JcbiAgICogdHVybidzIHRlcm1pbmFsIGBHZW5pZU1lc3NhZ2VgIChvciB0aGUgYHJlc3VsdGAgZXZlbnQnc1xuICAgKiBgcGF5bG9hZC5jb252ZXJzYXRpb25faWRgKSBhbmQgcGFzcyBpdCBpbnRvIHRoZSBuZXh0IGNhbGwuXG4gICAqL1xuICBjb252ZXJzYXRpb25JZD86IHN0cmluZztcbiAgLyoqXG4gICAqIEV4cGxpY2l0IGBXb3Jrc3BhY2VDbGllbnRgLiBEZWZhdWx0cyB0byBBcHBLaXQncyBwZXItcmVxdWVzdFxuICAgKiBleGVjdXRpb24tY29udGV4dCBjbGllbnQgd2hlbiBBcHBLaXQgaXMgaW5zdGFsbGVkIGFuZCB3ZSdyZSBpbnNpZGUgYVxuICAgKiByZXF1ZXN0OyBmYWxscyBiYWNrIHRvIGBjcmVhdGVXb3Jrc3BhY2VDbGllbnQoKWAgKGRlZmF1bHQgYXV0aClcbiAgICogb3RoZXJ3aXNlLlxuICAgKi9cbiAgd29ya3NwYWNlQ2xpZW50PzogV29ya3NwYWNlQ2xpZW50O1xuICAvKiogUG9sbCBjYWRlbmNlIGluIG1pbGxpc2Vjb25kcyBiZXR3ZWVuIHN1Y2Nlc3NpdmUgYGdldE1lc3NhZ2VgIGNhbGxzIChkZWZhdWx0IDUwMCkuICovXG4gIHBvbGxJbnRlcnZhbE1zPzogbnVtYmVyO1xuICAvKipcbiAgICogRXh0ZXJuYWwgY2FuY2VsbGF0aW9uLiBBY2NlcHRzIGEgV0hBVFdHIGBBYm9ydFNpZ25hbGAgb3IgYSBmdWxseS1idWlsdCBTREtcbiAgICogYENvbnRleHRgIChzZWUgYGRhdGFicmlja3MuQ29udGV4dExpa2VgKS4gQWJvcnRpbmcgaXQgY2FuY2VscyBldmVyeSBpbi1mbGlnaHRcbiAgICogU0RLIGNhbGwgYW5kIHRoZSBuZXh0IGludGVyLXBvbGwgc2xlZXAuXG4gICAqL1xuICBjb250ZXh0PzogZGF0YWJyaWNrcy5Db250ZXh0TGlrZTtcbn1cblxuLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gbG93LWxldmVsOiBnZW5pZUNoYXQgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuLyoqXG4gKiBPbmUgdHVybiBhZ2FpbnN0IGEgR2VuaWUgc3BhY2UsIHlpZWxkZWQgYXMgYSBzdHJlYW0gb2YgYEdlbmllTWVzc2FnZWBcbiAqIHNuYXBzaG90cy5cbiAqXG4gKiBUdXJuIGxpZmVjeWNsZTpcbiAqXG4gKiAgIC0gTm8gYG9wdGlvbnMuY29udmVyc2F0aW9uSWRgOiBvcGVuIGEgbmV3IGNvbnZlcnNhdGlvbiB2aWFcbiAqICAgICBgY2xpZW50LmdlbmllLnN0YXJ0Q29udmVyc2F0aW9uYC4gVGhlIG9wZW5lZCBjb252ZXJzYXRpb24gaWQgc3VyZmFjZXMgb25cbiAqICAgICBldmVyeSB5aWVsZGVkIGBHZW5pZU1lc3NhZ2VgIChgLmNvbnZlcnNhdGlvbl9pZGApIHNvIHRoZSBjYWxsZXIgY2FuXG4gKiAgICAgdGhyZWFkIGl0IGludG8gYSBmb2xsb3ctdXAgY2FsbC5cbiAqICAgLSBXaXRoIGBvcHRpb25zLmNvbnZlcnNhdGlvbklkYDogYXBwZW5kIHRvIHRoYXQgY29udmVyc2F0aW9uIHZpYVxuICogICAgIGBjbGllbnQuZ2VuaWUuY3JlYXRlTWVzc2FnZWAuXG4gKiAgIC0gSW4gYm90aCBjYXNlcywgYWZ0ZXIgdGhlIGNyZWF0ZS9zdGFydCB0aGUgZHJpdmVyIHBvbGxzXG4gKiAgICAgYGNsaWVudC5nZW5pZS5nZXRNZXNzYWdlYCBldmVyeSBgb3B0aW9ucy5wb2xsSW50ZXJ2YWxNc2AgKGRlZmF1bHQgNTAwbXMpXG4gKiAgICAgdW50aWwgdGhlIG1lc3NhZ2UgcmVhY2hlcyBhIHRlcm1pbmFsIHN0YXR1cywgdGhlbiB5aWVsZHMgdGhlIHRlcm1pbmFsXG4gKiAgICAgc25hcHNob3QgYW5kIHJldHVybnMuXG4gKlxuICogQ2FuY2VsbGF0aW9uOiBhIHNpbmdsZSBpbnRlcm5hbCBgQWJvcnRDb250cm9sbGVyYCBjb3ZlcnMgdGhlIHdob2xlIHR1cm4uXG4gKiBgb3B0aW9ucy5jb250ZXh0YCBpcyB0aWVkIGludG8gdGhhdCBjb250cm9sbGVyIHNvIGFuIGV4dGVybmFsIGFib3J0IHRlYXJzXG4gKiBkb3duIGV2ZXJ5IGluLWZsaWdodCBTREsgY2FsbCBBTkQgdGhlIGludGVyLXBvbGwgc2xlZXAuIEJyZWFraW5nIG91dCBvZiB0aGVcbiAqIGBmb3IgYXdhaXRgIGRvZXMgdGhlIHNhbWUgdmlhIHRoZSBgdHJ5IC8gZmluYWxseWAuXG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIFNpbmdsZSB0dXJuLlxuICogZm9yIGF3YWl0IChjb25zdCBtIG9mIGdlbmllQ2hhdChzcGFjZUlkLCBcIlRvcCA1IHN0b3Jlcz9cIikpIHtcbiAqICAgcmVuZGVyKG0pO1xuICogfVxuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBNdWx0aS10dXJuOiBjYWxsZXIgdGhyZWFkcyB0aGUgY29udmVyc2F0aW9uIGlkLlxuICogbGV0IGNvbnZlcnNhdGlvbklkOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gKiBmb3IgKGNvbnN0IHF1ZXN0aW9uIG9mIHF1ZXN0aW9ucykge1xuICogICBmb3IgYXdhaXQgKGNvbnN0IG0gb2YgZ2VuaWVDaGF0KHNwYWNlSWQsIHF1ZXN0aW9uLCB7IGNvbnZlcnNhdGlvbklkIH0pKSB7XG4gKiAgICAgY29udmVyc2F0aW9uSWQgPSBtLmNvbnZlcnNhdGlvbl9pZCA/PyBjb252ZXJzYXRpb25JZDtcbiAqICAgICByZW5kZXIobSk7XG4gKiAgIH1cbiAqIH1cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uKiBnZW5pZUNoYXQoXG4gIHNwYWNlX2lkOiBzdHJpbmcsXG4gIGNvbnRlbnQ6IHN0cmluZyxcbiAgb3B0aW9ucz86IEdlbmllQ2hhdE9wdGlvbnMsXG4pOiBBc3luY0dlbmVyYXRvcjxHZW5pZU1lc3NhZ2UsIHZvaWQsIHZvaWQ+IHtcbiAgY29uc3QgY29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgdHJ5IHtcbiAgICBjb25zdCBjbGllbnQgPSBhd2FpdCBnZXRXb3Jrc3BhY2VDbGllbnQob3B0aW9ucyk7XG4gICAgLy8gQnVpbGQgdGhlIFNESyBDb250ZXh0IE9OQ0UuIEJ1aWxkaW5nIGl0IGluc2lkZSB0aGUgcG9sbCBwcm9kdWNlciB3b3VsZFxuICAgIC8vIHJlLWF0dGFjaCBhbiBhYm9ydCBsaXN0ZW5lciB0byBgb3B0aW9ucy5jb250ZXh0YCBvbiBldmVyeSBwb2xsIGl0ZXJhdGlvblxuICAgIC8vICh2aWEgYGRhdGFicmlja3MudG9Db250ZXh0YCAtPiBgYXN5bmMudGllQWJvcnRTaWduYWxgKSwgZXZlbnR1YWxseSB0cmlwcGluZ1xuICAgIC8vIE5vZGUncyBgTWF4TGlzdGVuZXJzRXhjZWVkZWRXYXJuaW5nYC5cbiAgICBjb25zdCBjdHggPSBkYXRhYnJpY2tzLnRvQ29udGV4dChjb250cm9sbGVyLCBvcHRpb25zPy5jb250ZXh0KTtcbiAgICBsZXQgY29udmVyc2F0aW9uSWQgPSBvcHRpb25zPy5jb252ZXJzYXRpb25JZDtcbiAgICBsZXQgbWVzc2FnZUlkOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgICBjb25zdCBwb2xsUHJvZHVjZXIgPSBhc3luYyAocG9sbEN0eDogUG9sbENvbnRleHQ8R2VuaWVNZXNzYWdlPik6IFByb21pc2U8R2VuaWVNZXNzYWdlPiA9PiB7XG4gICAgICBpZiAoIWNvbnZlcnNhdGlvbklkKSB7XG4gICAgICAgIC8vIEZpcnN0IHBvbGw6IG9wZW4gdGhlIGNvbnZlcnNhdGlvbi4gUmVmdXNlIHRvIHJldHJ5OiBpZlxuICAgICAgICAvLyBgc3RhcnRDb252ZXJzYXRpb25gIHJldHVybmVkIGEgcmVzcG9uc2Ugd2l0aG91dCBhIGBjb252ZXJzYXRpb25faWRgLFxuICAgICAgICAvLyByZXRyeWluZyB3b3VsZCBqdXN0IG9wZW4gY29udmVyc2F0aW9uIGFmdGVyIGNvbnZlcnNhdGlvbi5cbiAgICAgICAgaWYgKHBvbGxDdHguYXR0ZW1wdCA+IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJHZW5pZSBkaWQgbm90IHJldHVybiBhIGNvbnZlcnNhdGlvbiBpZDsgcmVmdXNpbmcgdG8gcmV0cnlcIik7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgc3RhcnRSZXNwb25zZSA9IGF3YWl0IGNsaWVudC5nZW5pZS5zdGFydENvbnZlcnNhdGlvbih7IHNwYWNlX2lkLCBjb250ZW50IH0sIGN0eCk7XG4gICAgICAgIGNvbnZlcnNhdGlvbklkID0gc3RhcnRSZXNwb25zZS5jb252ZXJzYXRpb25faWQ7XG4gICAgICAgIG1lc3NhZ2VJZCA9IHN0YXJ0UmVzcG9uc2UubWVzc2FnZV9pZDtcbiAgICAgICAgcmV0dXJuIHN0YXJ0UmVzcG9uc2UubWVzc2FnZSE7XG4gICAgICB9XG4gICAgICBpZiAoIW1lc3NhZ2VJZCkge1xuICAgICAgICAvLyBGaXJzdCBwb2xsIG9mIGEgZm9sbG93LXVwIHR1cm46IGFwcGVuZCB0byB0aGUgc2VlZGVkIGNvbnZlcnNhdGlvbi5cbiAgICAgICAgLy8gYGNsaWVudC5nZW5pZS5jcmVhdGVNZXNzYWdlYCByZXR1cm5zIGEgYFdhaXRlcjxHZW5pZU1lc3NhZ2U+YFxuICAgICAgICAvLyAoYHsgLi4ubWVzc2FnZSwgd2FpdDogYXN5bmMgKCkgPT4gLi4uIH1gKS4gU3RyaXAgYHdhaXRgIGhlcmUgc29cbiAgICAgICAgLy8gZG93bnN0cmVhbSBzZXJpYWxpemVycyAoZS5nLiB5YW1sLnN0cmluZ2lmeSkgZG9uJ3QgY2hva2Ugb24gdGhlXG4gICAgICAgIC8vIEFzeW5jRnVuY3Rpb24gdmFsdWUuXG4gICAgICAgIGNvbnN0IHsgd2FpdDogX3dhaXQsIC4uLmNyZWF0ZVJlc3BvbnNlIH0gPSBhd2FpdCBjbGllbnQuZ2VuaWUuY3JlYXRlTWVzc2FnZShcbiAgICAgICAgICB7IHNwYWNlX2lkLCBjb252ZXJzYXRpb25faWQ6IGNvbnZlcnNhdGlvbklkLCBjb250ZW50IH0sXG4gICAgICAgICAgY3R4LFxuICAgICAgICApO1xuICAgICAgICBtZXNzYWdlSWQgPSBjcmVhdGVSZXNwb25zZS5tZXNzYWdlX2lkO1xuICAgICAgICByZXR1cm4gY3JlYXRlUmVzcG9uc2U7XG4gICAgICB9XG4gICAgICAvLyBTdWJzZXF1ZW50IHBvbGxzOiByZS1mZXRjaCB0aGUgY3VycmVudCBtZXNzYWdlIHVudGlsIGl0cyBzdGF0dXMgYmVjb21lc1xuICAgICAgLy8gdGVybWluYWwuXG4gICAgICByZXR1cm4gY2xpZW50LmdlbmllLmdldE1lc3NhZ2UoXG4gICAgICAgIHtcbiAgICAgICAgICBzcGFjZV9pZCxcbiAgICAgICAgICBjb252ZXJzYXRpb25faWQ6IGNvbnZlcnNhdGlvbklkLFxuICAgICAgICAgIG1lc3NhZ2VfaWQ6IG1lc3NhZ2VJZCxcbiAgICAgICAgfSxcbiAgICAgICAgY3R4LFxuICAgICAgKTtcbiAgICB9O1xuXG4gICAgeWllbGQqIGFzeW5jLnBvbGwoXG4gICAgICBhc3luYyAocG9sbEN0eDogUG9sbENvbnRleHQ8R2VuaWVNZXNzYWdlPikgPT4gdmFsaWRhdGVNZXNzYWdlKGF3YWl0IHBvbGxQcm9kdWNlcihwb2xsQ3R4KSksXG4gICAgICB7XG4gICAgICAgIGludGVydmFsTXM6IG9wdGlvbnM/LnBvbGxJbnRlcnZhbE1zID8/IDUwMCxcbiAgICAgICAgLy8gU2tpcCB5aWVsZGluZyBpZGVudGljYWwgY29uc2VjdXRpdmUgc25hcHNob3RzOyBHZW5pZSBvZnRlbiByZXR1cm5zXG4gICAgICAgIC8vIHRoZSBleGFjdCBzYW1lIHBheWxvYWQgdHdpY2UgZHVyaW5nIHF1aWV0IHBlcmlvZHMuIGBwb2xsYCBkb2VzIGEgZGVlcFxuICAgICAgICAvLyBlcXVhbCBvbiB0aGUgcHJldmlvdXMgeWllbGQuXG4gICAgICAgIGZpbHRlcjogXCJkaXN0aW5jdFwiLFxuICAgICAgICAvLyBTdG9wIGFmdGVyIHRoZSB0ZXJtaW5hbCBtZXNzYWdlIGlzIHlpZWxkZWQuIGBwb2xsYCBjaGVja3MgdGhlXG4gICAgICAgIC8vIHByZWRpY2F0ZSBBRlRFUiB5aWVsZGluZywgc28gdGhlIHRlcm1pbmFsIG1lc3NhZ2Ugc3RpbGwgcmVhY2hlcyB0aGVcbiAgICAgICAgLy8gY29uc3VtZXIuXG4gICAgICAgIHByZWRpY2F0ZTogKG0pID0+ICFnZW5pZU1vZGVsLmlzVGVybWluYWxTdGF0dXMobS5zdGF0dXMpLFxuICAgICAgICAvLyBXYWtlIHRoZSBpbnRlci1wb2xsIHNsZWVwIG9uIGFib3J0IHNvIGEgYGZvciBhd2FpdGAgYnJlYWsgKG9yXG4gICAgICAgIC8vIGV4dGVybmFsIGFib3J0KSB0ZWFycyBkb3duIHByb21wdGx5IGluc3RlYWQgb2Ygd2FpdGluZyBvdXQgdGhlXG4gICAgICAgIC8vIGludGVydmFsLlxuICAgICAgICBzaWduYWw6IGNvbnRyb2xsZXIuc2lnbmFsLFxuICAgICAgfSxcbiAgICApO1xuICB9IGZpbmFsbHkge1xuICAgIC8vIENhbmNlbHMgYW55IHN0aWxsLXBlbmRpbmcgU0RLIGNhbGwgYW5kIHRoZSBpbnRlci1wb2xsIHNsZWVwIHdoZXRoZXIgd2UncmVcbiAgICAvLyB1bndpbmRpbmcgZnJvbSBhIG5vcm1hbCByZXR1cm4sIGEgY29uc3VtZXIgYnJlYWssIG9yIGEgdGhyb3duIGVycm9yLlxuICAgIC8vIElkZW1wb3RlbnQuXG4gICAgY29udHJvbGxlci5hYm9ydCgpO1xuICB9XG59XG5cbi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gaGlnaC1sZXZlbDogZ2VuaWVFdmVudENoYXQgLS0tLS0tLS0tLS0tLS0tLS0tICovXG5cbi8qKlxuICogT25lIHR1cm4gYWdhaW5zdCBhIEdlbmllIHNwYWNlLCB5aWVsZGVkIGFzIGEgdHlwZWQge0BsaW5rIEdlbmllQ2hhdEV2ZW50fVxuICogc3RyZWFtLiBEcml2ZXMge0BsaW5rIGdlbmllQ2hhdH0gdW5kZXJuZWF0aCBhbmQgZGVjb3JhdGVzIGVhY2ggc25hcHNob3Qgd2l0aFxuICogdGhlIGRlcml2ZWQgZXZlbnRzIHRoZSBmaWVsZC1sZXZlbCBkaWZmIHByb2R1Y2VkLiBTdHJlYW0gb3JkZXI6XG4gKlxuICogICAxLiBgeyB0eXBlOiBcIm1lc3NhZ2VcIiwgbWVzc2FnZSB9YCAtIHRoZSByYXcgYEdlbmllTWVzc2FnZWAsIG9uY2UgcGVyIHBvbGxcbiAqICAgICAgeWllbGQuXG4gKiAgIDIuIGB7IHR5cGU6IFwicXVlc3Rpb25cIiwgY29udGVudCwgbWVzc2FnZV9pZCwgLi4uIH1gIGZpcmVzIGV4YWN0bHkgb25jZSwgb25cbiAqICAgICAgdGhlIEZJUlNUIGBtZXNzYWdlYCB5aWVsZC4gV2UgcmVhZCBgY29udGVudGAgYW5kIGBtZXNzYWdlX2lkYCBzdHJhaWdodFxuICogICAgICBvZmYgdGhlIHNuYXBzaG90IHNvIGV2ZXJ5IGRvd25zdHJlYW0gZXZlbnQgZm9yIHRoaXMgdHVybiBzaGFyZXMgdGhlIHNhbWVcbiAqICAgICAgYG1lc3NhZ2VfaWRgICh0aGUgcXVlc3Rpb24gaW5jbHVkZWQpIC0gc3Vic2NyaWJlcnMgY2FuIGdyb3VwIGV2ZXJ5dGhpbmdcbiAqICAgICAgZm9yIG9uZSBHZW5pZSBjYWxsIHVuZGVyIHRoYXQgb25lIGtleS5cbiAqICAgMy4gQW55IG9mIGBzdGF0dXNgIC8gYGF0dGFjaG1lbnRgIC8gYHRoaW5raW5nYCAvIGB0ZXh0YCAvIGBxdWVyeWAgL1xuICogICAgICBgc3RhdGVtZW50YCAvIGByb3dzYCAvIGBzdWdnZXN0ZWRfcXVlc3Rpb25zYCB0aGUgZGlmZiBhZ2FpbnN0IHRoZSBwcmlvclxuICogICAgICBzbmFwc2hvdCBwcm9kdWNlZC5cbiAqICAgNC4gT24gdGhlIHRlcm1pbmFsIHNuYXBzaG90LCBgeyB0eXBlOiBcInJlc3VsdFwiLCAuLi4gfWAgYXMgdGhlIGZpbmFsIHlpZWxkLlxuICpcbiAqIEVycm9ycyBwcm9wYWdhdGUgYnkgdGhlIGdlbmVyYXRvciB0aHJvd2luZyAtIHRoZXJlJ3Mgbm8gYFwiZXJyb3JcImAgdmFyaWFudC5cbiAqIFdyYXAgdGhlIGBmb3IgYXdhaXRgIGluIGB0cnkvY2F0Y2hgIGlmIHlvdSBuZWVkIHRvIGhhbmRsZSBmYWlsdXJlcy5cbiAqXG4gKiBAZXhhbXBsZVxuICogZm9yIGF3YWl0IChjb25zdCBldnQgb2YgZ2VuaWVFdmVudENoYXQoc3BhY2VJZCwgXCJUb3Agc3RvcmVzP1wiKSkge1xuICogICBzd2l0Y2ggKGV2dC50eXBlKSB7XG4gKiAgICAgY2FzZSBcInRoaW5raW5nXCI6XG4gKiAgICAgICBjb25zb2xlLmxvZyhcIlt0aGlua2luZ11cIiwgZXZ0LnRob3VnaHRfdHlwZSwgZXZ0LnRleHQpO1xuICogICAgICAgYnJlYWs7XG4gKiAgICAgY2FzZSBcInRleHRcIjpcbiAqICAgICAgIGNvbnNvbGUubG9nKFwiW3RleHRdXCIsIGV2dC50ZXh0KTtcbiAqICAgICAgIGJyZWFrO1xuICogICAgIGNhc2UgXCJyZXN1bHRcIjpcbiAqICAgICAgIGNvbnNvbGUubG9nKFwiW2RvbmVdXCIsIGV2dC5zdGF0dXMpO1xuICogICAgICAgYnJlYWs7XG4gKiAgIH1cbiAqIH1cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uKiBnZW5pZUV2ZW50Q2hhdChcbiAgc3BhY2VfaWQ6IHN0cmluZyxcbiAgY29udGVudDogc3RyaW5nLFxuICBvcHRpb25zPzogR2VuaWVDaGF0T3B0aW9ucyxcbik6IEFzeW5jR2VuZXJhdG9yPEdlbmllQ2hhdEV2ZW50LCB2b2lkLCB2b2lkPiB7XG4gIC8vIERpZmYgc291cmNlIGZvciB0aGUgY3VycmVudCB0dXJuLiBBbHdheXMgYHVuZGVmaW5lZGAgb24gdGhlIGZpcnN0IHNuYXBzaG90XG4gIC8vIHNvIHRoZSBpbml0aWFsIHN0YXR1cyAvIGF0dGFjaG1lbnRzIGVtaXQgZnJlc2g7IHVwZGF0ZWQgdG8gdGhlIG1vc3QgcmVjZW50XG4gIC8vIHNuYXBzaG90IGFmdGVyIGVhY2ggeWllbGQuXG4gIGxldCBwcmV2aW91czogR2VuaWVNZXNzYWdlIHwgdW5kZWZpbmVkO1xuICAvLyBUaGUgYHF1ZXN0aW9uYCBldmVudCBpcyBkZWZlcnJlZCB0byB0aGUgZmlyc3QgYG1lc3NhZ2VgIHlpZWxkIHNvIGl0IGNhblxuICAvLyBjYXJyeSB0aGUgYXNzaWduZWQgYG1lc3NhZ2VfaWRgIChzdWJzY3JpYmVycyB1c2UgaXQgYXMgdGhlIGdyb3VwaW5nIGtleSBmb3JcbiAgLy8gZXZlcnkgZXZlbnQgaW4gdGhpcyB0dXJuKS4gVGhlIGZpcnN0IHNuYXBzaG90IGlzIHRoZSBlYXJsaWVzdCBwb2ludCB0aGF0IGlkXG4gIC8vIGV4aXN0cy5cbiAgbGV0IHF1ZXN0aW9uRW1pdHRlZCA9IGZhbHNlO1xuICBmb3IgYXdhaXQgKGNvbnN0IHJhd01lc3NhZ2Ugb2YgZ2VuaWVDaGF0KHNwYWNlX2lkLCBjb250ZW50LCBvcHRpb25zKSkge1xuICAgIC8vIE5vcm1hbGl6ZSBgbWVzc2FnZV9pZGAgZnJvbSB0aGUgbGVnYWN5IGBpZGAgZmllbGQgd2hlbiBHZW5pZSdzIHdpcmVcbiAgICAvLyByZXNwb25zZSBvbmx5IHBvcHVsYXRlcyBvbmUgb2YgdGhlbS4gVGhlIFNESyBzY2hlbWEgbWFya3MgYm90aCBhc1xuICAgIC8vIHJlcXVpcmVkLCBidXQgaW4gcHJhY3RpY2UgdGhlIGBzdGFydENvbnZlcnNhdGlvbmAgLyBgY3JlYXRlTWVzc2FnZWAgaW5uZXJcbiAgICAvLyBgbWVzc2FnZWAgcGF5bG9hZCBzb21ldGltZXMgc2hpcHMgb25seSBgaWRgIHdoaWxlIHRoZSBuZXcgYG1lc3NhZ2VfaWRgXG4gICAgLy8gZmllbGQgbGFuZHMgdW5kZWZpbmVkLiBFdmVyeSBkb3duc3RyZWFtIGV2ZW50IGRldGVjdG9yIGtleXMgZ3JvdXBpbmcgb2ZmXG4gICAgLy8gYG1lc3NhZ2VfaWRgOyB0aGUgZmFsbGJhY2sga2VlcHMgb25lIEdlbmllIHR1cm4ncyBldmVudHMgZnJvbSBzcGxpdHRpbmdcbiAgICAvLyBhY3Jvc3MgYW4gYW5vbiBncm91cCArIHRoZSByZWFsLWlkIGdyb3VwIHdoZW4gc3Vic2NyaWJlcnMgYnVja2V0IGJ5XG4gICAgLy8gYG1lc3NhZ2VfaWRgLlxuICAgIGNvbnN0IG1lc3NhZ2U6IEdlbmllTWVzc2FnZSA9IHJhd01lc3NhZ2UubWVzc2FnZV9pZFxuICAgICAgPyByYXdNZXNzYWdlXG4gICAgICA6IHsgLi4ucmF3TWVzc2FnZSwgbWVzc2FnZV9pZDogcmF3TWVzc2FnZS5pZCB9O1xuICAgIHlpZWxkIHtcbiAgICAgIHR5cGU6IFwibWVzc2FnZVwiLFxuICAgICAgc3BhY2VfaWQ6IG1lc3NhZ2Uuc3BhY2VfaWQsXG4gICAgICBtZXNzYWdlX2lkOiBtZXNzYWdlLm1lc3NhZ2VfaWQsXG4gICAgICBtZXNzYWdlLFxuICAgIH07XG4gICAgaWYgKCFxdWVzdGlvbkVtaXR0ZWQpIHtcbiAgICAgIHlpZWxkIHtcbiAgICAgICAgdHlwZTogXCJxdWVzdGlvblwiLFxuICAgICAgICBzcGFjZV9pZDogbWVzc2FnZS5zcGFjZV9pZCxcbiAgICAgICAgLi4uKG1lc3NhZ2UuY29udmVyc2F0aW9uX2lkID8geyBjb252ZXJzYXRpb25faWQ6IG1lc3NhZ2UuY29udmVyc2F0aW9uX2lkIH0gOiB7fSksXG4gICAgICAgIC4uLihtZXNzYWdlLm1lc3NhZ2VfaWQgPyB7IG1lc3NhZ2VfaWQ6IG1lc3NhZ2UubWVzc2FnZV9pZCB9IDoge30pLFxuICAgICAgICBjb250ZW50OiBtZXNzYWdlLmNvbnRlbnQsXG4gICAgICB9O1xuICAgICAgcXVlc3Rpb25FbWl0dGVkID0gdHJ1ZTtcbiAgICB9XG4gICAgeWllbGQqIGV2ZW50LmV2ZW50c0Zyb21NZXNzYWdlKG1lc3NhZ2UsIHByZXZpb3VzLCBtZXNzYWdlLnNwYWNlX2lkKTtcbiAgICBjb25zdCBzdGF0dXMgPSBtZXNzYWdlLnN0YXR1cztcbiAgICBpZiAoZ2VuaWVNb2RlbC5pc1Rlcm1pbmFsU3RhdHVzKHN0YXR1cykpIHtcbiAgICAgIHlpZWxkIHtcbiAgICAgICAgdHlwZTogXCJyZXN1bHRcIixcbiAgICAgICAgc3BhY2VfaWQ6IG1lc3NhZ2Uuc3BhY2VfaWQsXG4gICAgICAgIGNvbnZlcnNhdGlvbl9pZDogbWVzc2FnZS5jb252ZXJzYXRpb25faWQsXG4gICAgICAgIG1lc3NhZ2VfaWQ6IG1lc3NhZ2UubWVzc2FnZV9pZCxcbiAgICAgICAgc3RhdHVzLFxuICAgICAgICBtZXNzYWdlLFxuICAgICAgfTtcbiAgICB9XG4gICAgcHJldmlvdXMgPSBtZXNzYWdlO1xuICB9XG59XG5cbi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gd29ya3NwYWNlIGNsaWVudCBoZWxwZXIgLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovXG5cbi8qKlxuICogUmVzb2x2ZSBhIGBXb3Jrc3BhY2VDbGllbnRgIGluIHRoaXMgcHJlZmVyZW5jZSBvcmRlcjpcbiAqXG4gKiAgIDEuIENhbGxlci1zdXBwbGllZCBgb3B0aW9ucy53b3Jrc3BhY2VDbGllbnRgLlxuICogICAyLiBBcHBLaXQncyBwZXItcmVxdWVzdCBleGVjdXRpb24tY29udGV4dCBjbGllbnQgaW5zaWRlIGEgcmVxdWVzdCBzY29wZS5cbiAqICAgMy4gRnJlc2ggYGNyZWF0ZVdvcmtzcGFjZUNsaWVudCgpYCAoZW52LXZhciBhdXRoIHZpYVxuICogICAgICBgREFUQUJSSUNLU19DT05GSUdfUFJPRklMRWAgLyBgREFUQUJSSUNLU19IT1NUYCAvIGBEQVRBQlJJQ0tTX1RPS0VOYCkuXG4gKlxuICovXG5hc3luYyBmdW5jdGlvbiBnZXRXb3Jrc3BhY2VDbGllbnQob3B0aW9ucz86IEdlbmllQ2hhdE9wdGlvbnMpOiBQcm9taXNlPFdvcmtzcGFjZUNsaWVudD4ge1xuICBpZiAob3B0aW9ucz8ud29ya3NwYWNlQ2xpZW50KSByZXR1cm4gb3B0aW9ucy53b3Jrc3BhY2VDbGllbnQ7XG4gIHRyeSB7XG4gICAgcmV0dXJuIGdldEV4ZWN1dGlvbkNvbnRleHQoKS5jbGllbnQ7XG4gIH0gY2F0Y2gge1xuICAgIC8vIE5vdCBpbnNpZGUgYW4gQXBwS2l0IHJlcXVlc3QgY29udGV4dDsgZmFsbCB0aHJvdWdoIHRvIGRlZmF1bHQgYXV0aC5cbiAgfVxuICByZXR1cm4gY3JlYXRlV29ya3NwYWNlQ2xpZW50KCk7XG59XG4iXX0=
285
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jaGF0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBeUJHO0FBRUgsT0FBTyxFQUNMLHFCQUFxQixFQUNyQixtQkFBbUIsR0FFcEIsTUFBTSxvQkFBb0IsQ0FBQztBQUM1QixPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDL0MsT0FBTyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFvQixNQUFNLHdCQUF3QixDQUFDO0FBQzdFLE9BQU8sRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUEwQyxNQUFNLHlCQUF5QixDQUFDO0FBRXBHLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxzQkFBc0IsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRTdFLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUM7QUFFeEM7Ozs7Ozs7R0FPRztBQUNILFNBQVMsZUFBZSxDQUFDLEdBQWlCO0lBQ3hDLE1BQU0sTUFBTSxHQUFHLFVBQVUsQ0FBQyxrQkFBa0IsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDNUQsSUFBSSxNQUFNLENBQUMsT0FBTztRQUFFLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQztJQUN2QyxNQUFNLENBQUMsS0FBSyxDQUFDLDBCQUEwQixFQUFFO1FBQ3ZDLFVBQVUsRUFBRSxHQUFHLENBQUMsVUFBVSxJQUFJLEdBQUcsQ0FBQyxFQUFFO1FBQ3BDLE1BQU0sRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFNO0tBQ25DLENBQUMsQ0FBQztJQUNILE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQztBQW9DRCwwRUFBMEU7QUFFMUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUNHO0FBQ0gsTUFBTSxDQUFDLEtBQUss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TzthQUN6QixDQUFDO1lBQ0YsZUFBZSxHQUFHLElBQUksQ0FBQztRQUN6QixDQUFDO1FBQ0QsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLGlCQUFpQixDQUFDLE9BQU8sRUFBRSxRQUFRLEVBQUUsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ3BFLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxNQUFNLENBQUM7UUFDOUIsSUFBSSxVQUFVLENBQUMsZ0JBQWdCLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztZQUN4QyxNQUFNO2dCQUNKLElBQUksRUFBRSxRQUFRO2dCQUNkLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUTtnQkFDMUIsZUFBZSxFQUFFLE9BQU8sQ0FBQyxlQUFlO2dCQUN4QyxVQUFVLEVBQUUsT0FBTyxDQUFDLFVBQVU7Z0JBQzlCLE1BQU07Z0JBQ04sT0FBTzthQUNSLENBQUM7UUFDSixDQUFDO1FBQ0QsUUFBUSxHQUFHLE9BQU8sQ0FBQztJQUNyQixDQUFDO0FBQ0gsQ0FBQztBQUVELDBFQUEwRTtBQUUxRTs7Ozs7Ozs7R0FRRztBQUNILEtBQUssVUFBVSxrQkFBa0IsQ0FBQyxPQUEwQjtJQUMxRCxJQUFJLE9BQU8sRUFBRSxlQUFlO1FBQUUsT0FBTyxPQUFPLENBQUMsZUFBZSxDQUFDO0lBQzdELElBQUksQ0FBQztRQUNILE9BQU8sbUJBQW1CLEVBQUUsQ0FBQyxNQUFNLENBQUM7SUFDdEMsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLHNFQUFzRTtJQUN4RSxDQUFDO0lBQ0QsT0FBTyxxQkFBcUIsRUFBRSxDQUFDO0FBQ2pDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEdlbmllIGNoYXQgZHJpdmVyLlxuICpcbiAqIERyaXZlcyBhIHNpbmdsZSB0dXJuIGFnYWluc3QgYSBHZW5pZSBzcGFjZSBmcm9tIG9uZSBgY29udGVudGAgc3RyaW5nO1xuICogbXVsdGktdHVybiBjb252ZXJzYXRpb25zIGFyZSB0aGUgY2FsbGVyJ3Mgam9iICh0aHJlYWQgdGhlIGBjb252ZXJzYXRpb25faWRgXG4gKiByZXR1cm5lZCBvbiBlYWNoIGBHZW5pZU1lc3NhZ2VgIGJhY2sgaW50byB0aGUgbmV4dCB0dXJuJ3NcbiAqIGBvcHRpb25zLmNvbnZlcnNhdGlvbklkYCkuXG4gKlxuICogQWdlbnQgTW9kZSBTU0UgaXMgdGhlIGRlZmF1bHQgdHJhbnNwb3J0LiBJdHMgUmVzcG9uc2VzLXN0eWxlIHJlYXNvbmluZywgU1FMLFxuICogcXVlcnkgb3V0cHV0LCBhbmQgZmluYWwgYW5zd2VyIGl0ZW1zIGFyZSBwcm9qZWN0ZWQgaW50byBgR2VuaWVNZXNzYWdlYFxuICogc25hcHNob3RzOyBgYWdlbnRNb2RlOiBmYWxzZWAgcmV0YWlucyB0aGUgQ29udmVyc2F0aW9uIEFQSSBwb2xsaW5nIHBhdGguXG4gKlxuICogVHdvIGxheWVycyBzZXJ2ZSB0d28ga2luZHMgb2YgY29uc3VtZXIuIFRoZSBsb3ctbGV2ZWwgbGF5ZXIgeWllbGRzIGV2ZXJ5XG4gKiBvYnNlcnZlZCBgR2VuaWVNZXNzYWdlYCAodmFsaWRhdGVkIGFnYWluc3QgYEdlbmllTWVzc2FnZVNjaGVtYWAsIGZhbGxpbmcgYmFja1xuICogdG8gdGhlIHJhdyBzbmFwc2hvdCBvbiBhIHNjaGVtYSBtaXNzKSBhbmQgb3ducyBjYW5jZWxsYXRpb24sIGNvbnZlcnNhdGlvblxuICogc2VlZGluZywgZGlzdGluY3QtZmlsdGVyaW5nLCBhbmQgU0RLIHF1aXJrczsgcmVhY2ggZm9yIGl0IHdoZW4geW91IHdhbnQgdGhlXG4gKiByYXcgc3RyZWFtLiBUaGVcbiAqIGhpZ2gtbGV2ZWwgbGF5ZXIgd3JhcHMgaXQgYW5kIGVtaXRzIHNlbWFudGljLCBkZWR1cGxpY2F0ZWQgYHsgdHlwZSwgcGF5bG9hZCB9YFxuICogZXZlbnRzIChzZWUge0BsaW5rIEdlbmllQ2hhdEV2ZW50fSksIGFsd2F5cyBjbG9zaW5nIGEgc3VjY2Vzc2Z1bCB0dXJuIHdpdGggYVxuICogdGVybWluYWwgYHJlc3VsdGAgZXZlbnQgY2FycnlpbmcgdGhlIGZpbmFsIGBHZW5pZU1lc3NhZ2VgOyBlcnJvcnMgcHJvcGFnYXRlXG4gKiBieSB0aHJvd2luZywgd2l0aCBubyBgZXJyb3JgIHZhcmlhbnQuIEl0ZXJhdGluZyBVSSAvIGFnZW50IGNvZGUgdGhhdCB3YW50c1xuICogZXZlcnkgbWVzc2FnZSB2ZXJiYXRpbSB0YWtlcyB0aGUgbG93LWxldmVsIHN0cmVhbTsgc3Vic2NyaWJlcnMgcmVhY3RpbmcgdG9cbiAqIFwiR2VuaWUgaXMgdGhpbmtpbmcgYWJvdXQgWFwiIG9yIFwiR2VuaWUgcHJvZHVjZWQgdGV4dCBZXCIgdGFrZSB0aGUgZXZlbnQgbGF5ZXIuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7XG4gIGNyZWF0ZVdvcmtzcGFjZUNsaWVudCxcbiAgZ2V0RXhlY3V0aW9uQ29udGV4dCxcbiAgdHlwZSBXb3Jrc3BhY2VDbGllbnQsXG59IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbmltcG9ydCB7IGRhdGFicmlja3MgfSBmcm9tIFwiQGRieC10b29scy9hcHBraXRcIjtcbmltcG9ydCB7IGFzeW5jLCBlcnJvciwgbG9nLCB0eXBlIFBvbGxDb250ZXh0IH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7IGV2ZW50LCBnZW5pZU1vZGVsLCB0eXBlIEdlbmllQ2hhdEV2ZW50LCB0eXBlIEdlbmllTWVzc2FnZSB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1nZW5pZVwiO1xuXG5pbXBvcnQgeyBnZW5pZUFnZW50TW9kZUNoYXQsIGlzQWdlbnRNb2RlVW5hdmFpbGFibGUgfSBmcm9tIFwiLi9hZ2VudC1tb2RlLnRzXCI7XG5cbmNvbnN0IGxvZ2dlciA9IGxvZy5sb2dnZXIoXCJnZW5pZS9jaGF0XCIpO1xuXG4vKipcbiAqIFZhbGlkYXRlIGEgcG9sbGVkIHdpcmUgc25hcHNob3QgYWdhaW5zdCB7QGxpbmsgR2VuaWVNZXNzYWdlU2NoZW1hfVxuICogYW5kIHJldHVybiB0aGUgc2NoZW1hLW5vcm1hbGl6ZWQgbWVzc2FnZS4gR2VuaWUncyB3aXJlIG9jY2FzaW9uYWxseSBzaGlwcyBhXG4gKiBzaGFwZSB0aGUgKFNESy1kZXJpdmVkKSBzY2hlbWEgZG9lc24ndCBtb2RlbCBleGFjdGx5IC0gZS5nLiBhbiBlYXJseSBwb2xsXG4gKiB0aGF0IG9taXRzIHRoZSBTREstcmVxdWlyZWQgYG1lc3NhZ2VfaWRgIC0gc28gYSBtaXNzIGRlZ3JhZGVzIHRvIHRoZSByYXdcbiAqIHNuYXBzaG90IHJhdGhlciB0aGFuIHRocm93aW5nLCBrZWVwaW5nIGEgc2luZ2xlIG9kZCBwb2xsIGZyb20gYWJvcnRpbmcgdGhlXG4gKiB3aG9sZSB0dXJuLlxuICovXG5mdW5jdGlvbiB2YWxpZGF0ZU1lc3NhZ2UocmF3OiBHZW5pZU1lc3NhZ2UpOiBHZW5pZU1lc3NhZ2Uge1xuICBjb25zdCByZXN1bHQgPSBnZW5pZU1vZGVsLkdlbmllTWVzc2FnZVNjaGVtYS5zYWZlUGFyc2UocmF3KTtcbiAgaWYgKHJlc3VsdC5zdWNjZXNzKSByZXR1cm4gcmVzdWx0LmRhdGE7XG4gIGxvZ2dlci5kZWJ1ZyhcIndpcmUtbWVzc2FnZTpzY2hlbWEtbWlzc1wiLCB7XG4gICAgbWVzc2FnZV9pZDogcmF3Lm1lc3NhZ2VfaWQgPz8gcmF3LmlkLFxuICAgIGlzc3VlczogcmVzdWx0LmVycm9yLmlzc3Vlcy5sZW5ndGgsXG4gIH0pO1xuICByZXR1cm4gcmF3O1xufVxuXG4vKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSBzaGFyZWQgb3B0aW9ucyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG4vKiogT3B0aW9ucyBhY2NlcHRlZCBieSBib3RoIHtAbGluayBnZW5pZUNoYXR9IGFuZCB7QGxpbmsgZ2VuaWVFdmVudENoYXR9LiAqL1xuZXhwb3J0IGludGVyZmFjZSBHZW5pZUNoYXRPcHRpb25zIHtcbiAgLyoqXG4gICAqIFVzZSB0aGUgc3RyZWFtaW5nIEdlbmllIEFnZW50IE1vZGUgQVBJLiBEZWZhdWx0cyB0byBgdHJ1ZWA7IHNldCBgZmFsc2VgIHRvXG4gICAqIGZvcmNlIHRoZSBsZWdhY3kgc3RhcnQvY3JlYXRlL2dldC1tZXNzYWdlIHBvbGxpbmcgZmxvdy5cbiAgICovXG4gIGFnZW50TW9kZT86IGJvb2xlYW47XG4gIC8qKiBBc2sgQWdlbnQgTW9kZSB0byBnZW5lcmF0ZSB2aXN1YWxpemF0aW9ucyB3aGVuIGFwcHJvcHJpYXRlLiAqL1xuICBlbmFibGVWaXN1YWxpemF0aW9uPzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIENvbnRpbnVlIGFuIGV4aXN0aW5nIGNvbnZlcnNhdGlvbi4gQWdlbnQgTW9kZSBzZW5kcyBpdCBhc1xuICAgKiBgY29udmVyc2F0aW9uX2lkYDsgbGVnYWN5IHBvbGxpbmcgcGFzc2VzIGl0IHRvIGBjcmVhdGVNZXNzYWdlYC4gUmVhZCB0aGUgaWRcbiAgICogZnJvbSB0aGUgcHJpb3IgdHVybidzIHRlcm1pbmFsIGBHZW5pZU1lc3NhZ2VgIG9yIGByZXN1bHRgIGV2ZW50LlxuICAgKi9cbiAgY29udmVyc2F0aW9uSWQ/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBFeHBsaWNpdCBgV29ya3NwYWNlQ2xpZW50YC4gRGVmYXVsdHMgdG8gQXBwS2l0J3MgcGVyLXJlcXVlc3RcbiAgICogZXhlY3V0aW9uLWNvbnRleHQgY2xpZW50IHdoZW4gQXBwS2l0IGlzIGluc3RhbGxlZCBhbmQgd2UncmUgaW5zaWRlIGFcbiAgICogcmVxdWVzdDsgZmFsbHMgYmFjayB0byBgY3JlYXRlV29ya3NwYWNlQ2xpZW50KClgIChkZWZhdWx0IGF1dGgpXG4gICAqIG90aGVyd2lzZS5cbiAgICovXG4gIHdvcmtzcGFjZUNsaWVudD86IFdvcmtzcGFjZUNsaWVudDtcbiAgLyoqIExlZ2FjeSBmYWxsYmFjayBjYWRlbmNlIGJldHdlZW4gc3VjY2Vzc2l2ZSBgZ2V0TWVzc2FnZWAgY2FsbHMgKGRlZmF1bHQgNTAwbXMpLiAqL1xuICBwb2xsSW50ZXJ2YWxNcz86IG51bWJlcjtcbiAgLyoqXG4gICAqIEV4dGVybmFsIGNhbmNlbGxhdGlvbi4gQWNjZXB0cyBhIFdIQVRXRyBgQWJvcnRTaWduYWxgIG9yIGEgZnVsbHktYnVpbHQgU0RLXG4gICAqIGBDb250ZXh0YCAoc2VlIGBkYXRhYnJpY2tzLkNvbnRleHRMaWtlYCkuIEFib3J0aW5nIGl0IGNhbmNlbHMgZXZlcnkgaW4tZmxpZ2h0XG4gICAqIEFnZW50IE1vZGUgc3RyZWFtLCBTREsgY2FsbCwgYW5kIHRoZSBuZXh0IGludGVyLXBvbGwgc2xlZXAuXG4gICAqL1xuICBjb250ZXh0PzogZGF0YWJyaWNrcy5Db250ZXh0TGlrZTtcbn1cblxuLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gbG93LWxldmVsOiBnZW5pZUNoYXQgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuLyoqXG4gKiBPbmUgdHVybiBhZ2FpbnN0IGEgR2VuaWUgc3BhY2UsIHlpZWxkZWQgYXMgYSBzdHJlYW0gb2YgYEdlbmllTWVzc2FnZWBcbiAqIHNuYXBzaG90cy5cbiAqXG4gKiBUdXJuIGxpZmVjeWNsZTpcbiAqXG4gKiAgIC0gQWdlbnQgTW9kZSAoZGVmYXVsdCk6IFBPU1Qgb25lIFJlc3BvbnNlcy1zdHlsZSBtZXNzYWdlIHRvXG4gKiAgICAgYC9hcGkvMi4wL2dlbmllL2FnZW50cy97aWR9L3Jlc3BvbnNlc2AgYW5kIHlpZWxkIHByb2plY3RlZCBzbmFwc2hvdHMgZnJvbVxuICogICAgIGl0cyBTU0UgZXZlbnRzLlxuICogICAtIExlZ2FjeSBwb2xsaW5nIChgYWdlbnRNb2RlOiBmYWxzZWApOiBzdGFydC9jcmVhdGUgYSBDb252ZXJzYXRpb24gQVBJXG4gKiAgICAgbWVzc2FnZSBhbmQgcG9sbCBgZ2V0TWVzc2FnZWAgdW50aWwgdGVybWluYWwuXG4gKiAgIC0gQSBwcmUtc3RyZWFtIGBGRUFUVVJFX0RJU0FCTEVEYCBvciBwcmV2aWV3LXRvZ2dsZSByZXNwb25zZSBmYWxscyBiYWNrIHRvXG4gKiAgICAgbGVnYWN5IHBvbGxpbmcgYXV0b21hdGljYWxseS5cbiAqXG4gKiBDYW5jZWxsYXRpb246IGEgc2luZ2xlIGludGVybmFsIGBBYm9ydENvbnRyb2xsZXJgIGNvdmVycyB0aGUgd2hvbGUgdHVybi5cbiAqIGBvcHRpb25zLmNvbnRleHRgIGlzIHRpZWQgaW50byB0aGF0IGNvbnRyb2xsZXIgc28gYW4gZXh0ZXJuYWwgYWJvcnQgdGVhcnNcbiAqIGRvd24gdGhlIEFnZW50IE1vZGUgU1NFIGNvbm5lY3Rpb24sIFNESyBjYWxscywgYW5kIGFueSBpbnRlci1wb2xsIHNsZWVwLlxuICogQnJlYWtpbmcgb3V0IG9mIHRoZSBgZm9yIGF3YWl0YCBhbHNvIGludm9rZXMgdGhlIEFnZW50IE1vZGUgc2VydmVyLXNpZGVcbiAqIGNhbmNlbCBlbmRwb2ludCBiZWZvcmUgdGhlIGdlbmVyYXRvciBjbG9zZXMuXG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIFNpbmdsZSB0dXJuLlxuICogZm9yIGF3YWl0IChjb25zdCBtIG9mIGdlbmllQ2hhdChzcGFjZUlkLCBcIlRvcCA1IHN0b3Jlcz9cIikpIHtcbiAqICAgcmVuZGVyKG0pO1xuICogfVxuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBNdWx0aS10dXJuOiBjYWxsZXIgdGhyZWFkcyB0aGUgY29udmVyc2F0aW9uIGlkLlxuICogbGV0IGNvbnZlcnNhdGlvbklkOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gKiBmb3IgKGNvbnN0IHF1ZXN0aW9uIG9mIHF1ZXN0aW9ucykge1xuICogICBmb3IgYXdhaXQgKGNvbnN0IG0gb2YgZ2VuaWVDaGF0KHNwYWNlSWQsIHF1ZXN0aW9uLCB7IGNvbnZlcnNhdGlvbklkIH0pKSB7XG4gKiAgICAgY29udmVyc2F0aW9uSWQgPSBtLmNvbnZlcnNhdGlvbl9pZCA/PyBjb252ZXJzYXRpb25JZDtcbiAqICAgICByZW5kZXIobSk7XG4gKiAgIH1cbiAqIH1cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uKiBnZW5pZUNoYXQoXG4gIHNwYWNlX2lkOiBzdHJpbmcsXG4gIGNvbnRlbnQ6IHN0cmluZyxcbiAgb3B0aW9ucz86IEdlbmllQ2hhdE9wdGlvbnMsXG4pOiBBc3luY0dlbmVyYXRvcjxHZW5pZU1lc3NhZ2UsIHZvaWQsIHZvaWQ+IHtcbiAgY29uc3QgY29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgdHJ5IHtcbiAgICBjb25zdCBjbGllbnQgPSBhd2FpdCBnZXRXb3Jrc3BhY2VDbGllbnQob3B0aW9ucyk7XG4gICAgLy8gQnVpbGQgdGhlIFNESyBDb250ZXh0IE9OQ0UuIEJ1aWxkaW5nIGl0IGluc2lkZSB0aGUgcG9sbCBwcm9kdWNlciB3b3VsZFxuICAgIC8vIHJlLWF0dGFjaCBhbiBhYm9ydCBsaXN0ZW5lciB0byBgb3B0aW9ucy5jb250ZXh0YCBvbiBldmVyeSBwb2xsIGl0ZXJhdGlvblxuICAgIC8vICh2aWEgYGRhdGFicmlja3MudG9Db250ZXh0YCAtPiBgYXN5bmMudGllQWJvcnRTaWduYWxgKSwgZXZlbnR1YWxseSB0cmlwcGluZ1xuICAgIC8vIE5vZGUncyBgTWF4TGlzdGVuZXJzRXhjZWVkZWRXYXJuaW5nYC5cbiAgICBjb25zdCBjdHggPSBkYXRhYnJpY2tzLnRvQ29udGV4dChjb250cm9sbGVyLCBvcHRpb25zPy5jb250ZXh0KTtcbiAgICBpZiAob3B0aW9ucz8uYWdlbnRNb2RlICE9PSBmYWxzZSkge1xuICAgICAgbGV0IHlpZWxkZWQgPSBmYWxzZTtcbiAgICAgIHRyeSB7XG4gICAgICAgIGZvciBhd2FpdCAoY29uc3QgbWVzc2FnZSBvZiBnZW5pZUFnZW50TW9kZUNoYXQoY2xpZW50LCBzcGFjZV9pZCwgY29udGVudCwge1xuICAgICAgICAgIC4uLihvcHRpb25zPy5jb252ZXJzYXRpb25JZCA/IHsgY29udmVyc2F0aW9uSWQ6IG9wdGlvbnMuY29udmVyc2F0aW9uSWQgfSA6IHt9KSxcbiAgICAgICAgICAuLi4ob3B0aW9ucz8uZW5hYmxlVmlzdWFsaXphdGlvbiA/IHsgZW5hYmxlVmlzdWFsaXphdGlvbjogdHJ1ZSB9IDoge30pLFxuICAgICAgICAgIGNvbnRleHQ6IGN0eCxcbiAgICAgICAgfSkpIHtcbiAgICAgICAgICB5aWVsZGVkID0gdHJ1ZTtcbiAgICAgICAgICB5aWVsZCB2YWxpZGF0ZU1lc3NhZ2UobWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGlmICh5aWVsZGVkIHx8ICFpc0FnZW50TW9kZVVuYXZhaWxhYmxlKGVycikpIHRocm93IGVycjtcbiAgICAgICAgbG9nZ2VyLndhcm4oXCJhZ2VudC1tb2RlOnVuYXZhaWxhYmxlLCBmYWxsaW5nIGJhY2sgdG8gcG9sbGluZ1wiLCB7XG4gICAgICAgICAgc3BhY2VfaWQsXG4gICAgICAgICAgZXJyb3I6IGVycm9yLmVycm9yTWVzc2FnZShlcnIpLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gICAgbGV0IGNvbnZlcnNhdGlvbklkID0gb3B0aW9ucz8uY29udmVyc2F0aW9uSWQ7XG4gICAgbGV0IG1lc3NhZ2VJZDogc3RyaW5nIHwgdW5kZWZpbmVkO1xuXG4gICAgY29uc3QgcG9sbFByb2R1Y2VyID0gYXN5bmMgKHBvbGxDdHg6IFBvbGxDb250ZXh0PEdlbmllTWVzc2FnZT4pOiBQcm9taXNlPEdlbmllTWVzc2FnZT4gPT4ge1xuICAgICAgaWYgKCFjb252ZXJzYXRpb25JZCkge1xuICAgICAgICAvLyBGaXJzdCBwb2xsOiBvcGVuIHRoZSBjb252ZXJzYXRpb24uIFJlZnVzZSB0byByZXRyeTogaWZcbiAgICAgICAgLy8gYHN0YXJ0Q29udmVyc2F0aW9uYCByZXR1cm5lZCBhIHJlc3BvbnNlIHdpdGhvdXQgYSBgY29udmVyc2F0aW9uX2lkYCxcbiAgICAgICAgLy8gcmV0cnlpbmcgd291bGQganVzdCBvcGVuIGNvbnZlcnNhdGlvbiBhZnRlciBjb252ZXJzYXRpb24uXG4gICAgICAgIGlmIChwb2xsQ3R4LmF0dGVtcHQgPiAwKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiR2VuaWUgZGlkIG5vdCByZXR1cm4gYSBjb252ZXJzYXRpb24gaWQ7IHJlZnVzaW5nIHRvIHJldHJ5XCIpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHN0YXJ0UmVzcG9uc2UgPSBhd2FpdCBjbGllbnQuZ2VuaWUuc3RhcnRDb252ZXJzYXRpb24oeyBzcGFjZV9pZCwgY29udGVudCB9LCBjdHgpO1xuICAgICAgICBjb252ZXJzYXRpb25JZCA9IHN0YXJ0UmVzcG9uc2UuY29udmVyc2F0aW9uX2lkO1xuICAgICAgICBtZXNzYWdlSWQgPSBzdGFydFJlc3BvbnNlLm1lc3NhZ2VfaWQ7XG4gICAgICAgIHJldHVybiBzdGFydFJlc3BvbnNlLm1lc3NhZ2UhO1xuICAgICAgfVxuICAgICAgaWYgKCFtZXNzYWdlSWQpIHtcbiAgICAgICAgLy8gRmlyc3QgcG9sbCBvZiBhIGZvbGxvdy11cCB0dXJuOiBhcHBlbmQgdG8gdGhlIHNlZWRlZCBjb252ZXJzYXRpb24uXG4gICAgICAgIC8vIGBjbGllbnQuZ2VuaWUuY3JlYXRlTWVzc2FnZWAgcmV0dXJucyBhIGBXYWl0ZXI8R2VuaWVNZXNzYWdlPmBcbiAgICAgICAgLy8gKGB7IC4uLm1lc3NhZ2UsIHdhaXQ6IGFzeW5jICgpID0+IC4uLiB9YCkuIFN0cmlwIGB3YWl0YCBoZXJlIHNvXG4gICAgICAgIC8vIGRvd25zdHJlYW0gc2VyaWFsaXplcnMgKGUuZy4geWFtbC5zdHJpbmdpZnkpIGRvbid0IGNob2tlIG9uIHRoZVxuICAgICAgICAvLyBBc3luY0Z1bmN0aW9uIHZhbHVlLlxuICAgICAgICBjb25zdCB7IHdhaXQ6IF93YWl0LCAuLi5jcmVhdGVSZXNwb25zZSB9ID0gYXdhaXQgY2xpZW50LmdlbmllLmNyZWF0ZU1lc3NhZ2UoXG4gICAgICAgICAgeyBzcGFjZV9pZCwgY29udmVyc2F0aW9uX2lkOiBjb252ZXJzYXRpb25JZCwgY29udGVudCB9LFxuICAgICAgICAgIGN0eCxcbiAgICAgICAgKTtcbiAgICAgICAgbWVzc2FnZUlkID0gY3JlYXRlUmVzcG9uc2UubWVzc2FnZV9pZDtcbiAgICAgICAgcmV0dXJuIGNyZWF0ZVJlc3BvbnNlO1xuICAgICAgfVxuICAgICAgLy8gU3Vic2VxdWVudCBwb2xsczogcmUtZmV0Y2ggdGhlIGN1cnJlbnQgbWVzc2FnZSB1bnRpbCBpdHMgc3RhdHVzIGJlY29tZXNcbiAgICAgIC8vIHRlcm1pbmFsLlxuICAgICAgcmV0dXJuIGNsaWVudC5nZW5pZS5nZXRNZXNzYWdlKFxuICAgICAgICB7XG4gICAgICAgICAgc3BhY2VfaWQsXG4gICAgICAgICAgY29udmVyc2F0aW9uX2lkOiBjb252ZXJzYXRpb25JZCxcbiAgICAgICAgICBtZXNzYWdlX2lkOiBtZXNzYWdlSWQsXG4gICAgICAgIH0sXG4gICAgICAgIGN0eCxcbiAgICAgICk7XG4gICAgfTtcblxuICAgIHlpZWxkKiBhc3luYy5wb2xsKFxuICAgICAgYXN5bmMgKHBvbGxDdHg6IFBvbGxDb250ZXh0PEdlbmllTWVzc2FnZT4pID0+IHZhbGlkYXRlTWVzc2FnZShhd2FpdCBwb2xsUHJvZHVjZXIocG9sbEN0eCkpLFxuICAgICAge1xuICAgICAgICBpbnRlcnZhbE1zOiBvcHRpb25zPy5wb2xsSW50ZXJ2YWxNcyA/PyA1MDAsXG4gICAgICAgIC8vIFNraXAgeWllbGRpbmcgaWRlbnRpY2FsIGNvbnNlY3V0aXZlIHNuYXBzaG90czsgR2VuaWUgb2Z0ZW4gcmV0dXJuc1xuICAgICAgICAvLyB0aGUgZXhhY3Qgc2FtZSBwYXlsb2FkIHR3aWNlIGR1cmluZyBxdWlldCBwZXJpb2RzLiBgcG9sbGAgZG9lcyBhIGRlZXBcbiAgICAgICAgLy8gZXF1YWwgb24gdGhlIHByZXZpb3VzIHlpZWxkLlxuICAgICAgICBmaWx0ZXI6IFwiZGlzdGluY3RcIixcbiAgICAgICAgLy8gU3RvcCBhZnRlciB0aGUgdGVybWluYWwgbWVzc2FnZSBpcyB5aWVsZGVkLiBgcG9sbGAgY2hlY2tzIHRoZVxuICAgICAgICAvLyBwcmVkaWNhdGUgQUZURVIgeWllbGRpbmcsIHNvIHRoZSB0ZXJtaW5hbCBtZXNzYWdlIHN0aWxsIHJlYWNoZXMgdGhlXG4gICAgICAgIC8vIGNvbnN1bWVyLlxuICAgICAgICBwcmVkaWNhdGU6IChtKSA9PiAhZ2VuaWVNb2RlbC5pc1Rlcm1pbmFsU3RhdHVzKG0uc3RhdHVzKSxcbiAgICAgICAgLy8gV2FrZSB0aGUgaW50ZXItcG9sbCBzbGVlcCBvbiBhYm9ydCBzbyBhIGBmb3IgYXdhaXRgIGJyZWFrIChvclxuICAgICAgICAvLyBleHRlcm5hbCBhYm9ydCkgdGVhcnMgZG93biBwcm9tcHRseSBpbnN0ZWFkIG9mIHdhaXRpbmcgb3V0IHRoZVxuICAgICAgICAvLyBpbnRlcnZhbC5cbiAgICAgICAgc2lnbmFsOiBjb250cm9sbGVyLnNpZ25hbCxcbiAgICAgIH0sXG4gICAgKTtcbiAgfSBmaW5hbGx5IHtcbiAgICAvLyBDYW5jZWxzIGFueSBzdGlsbC1wZW5kaW5nIFNESyBjYWxsIGFuZCB0aGUgaW50ZXItcG9sbCBzbGVlcCB3aGV0aGVyIHdlJ3JlXG4gICAgLy8gdW53aW5kaW5nIGZyb20gYSBub3JtYWwgcmV0dXJuLCBhIGNvbnN1bWVyIGJyZWFrLCBvciBhIHRocm93biBlcnJvci5cbiAgICAvLyBJZGVtcG90ZW50LlxuICAgIGNvbnRyb2xsZXIuYWJvcnQoKTtcbiAgfVxufVxuXG4vKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tIGhpZ2gtbGV2ZWw6IGdlbmllRXZlbnRDaGF0IC0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG4vKipcbiAqIE9uZSB0dXJuIGFnYWluc3QgYSBHZW5pZSBzcGFjZSwgeWllbGRlZCBhcyBhIHR5cGVkIHtAbGluayBHZW5pZUNoYXRFdmVudH1cbiAqIHN0cmVhbS4gRHJpdmVzIHtAbGluayBnZW5pZUNoYXR9IHVuZGVybmVhdGggYW5kIGRlY29yYXRlcyBlYWNoIHNuYXBzaG90IHdpdGhcbiAqIHRoZSBkZXJpdmVkIGV2ZW50cyB0aGUgZmllbGQtbGV2ZWwgZGlmZiBwcm9kdWNlZC4gU3RyZWFtIG9yZGVyOlxuICpcbiAqICAgMS4gYHsgdHlwZTogXCJtZXNzYWdlXCIsIG1lc3NhZ2UgfWAgLSB0aGUgcmF3IGBHZW5pZU1lc3NhZ2VgLCBvbmNlIHBlciBwb2xsXG4gKiAgICAgIHlpZWxkLlxuICogICAyLiBgeyB0eXBlOiBcInF1ZXN0aW9uXCIsIGNvbnRlbnQsIG1lc3NhZ2VfaWQsIC4uLiB9YCBmaXJlcyBleGFjdGx5IG9uY2UsIG9uXG4gKiAgICAgIHRoZSBGSVJTVCBgbWVzc2FnZWAgeWllbGQuIFdlIHJlYWQgYGNvbnRlbnRgIGFuZCBgbWVzc2FnZV9pZGAgc3RyYWlnaHRcbiAqICAgICAgb2ZmIHRoZSBzbmFwc2hvdCBzbyBldmVyeSBkb3duc3RyZWFtIGV2ZW50IGZvciB0aGlzIHR1cm4gc2hhcmVzIHRoZSBzYW1lXG4gKiAgICAgIGBtZXNzYWdlX2lkYCAodGhlIHF1ZXN0aW9uIGluY2x1ZGVkKSAtIHN1YnNjcmliZXJzIGNhbiBncm91cCBldmVyeXRoaW5nXG4gKiAgICAgIGZvciBvbmUgR2VuaWUgY2FsbCB1bmRlciB0aGF0IG9uZSBrZXkuXG4gKiAgIDMuIEFueSBvZiBgc3RhdHVzYCAvIGBhdHRhY2htZW50YCAvIGB0aGlua2luZ2AgLyBgdGV4dGAgLyBgcXVlcnlgIC9cbiAqICAgICAgYHN0YXRlbWVudGAgLyBgcm93c2AgLyBgc3VnZ2VzdGVkX3F1ZXN0aW9uc2AgdGhlIGRpZmYgYWdhaW5zdCB0aGUgcHJpb3JcbiAqICAgICAgc25hcHNob3QgcHJvZHVjZWQuXG4gKiAgIDQuIE9uIHRoZSB0ZXJtaW5hbCBzbmFwc2hvdCwgYHsgdHlwZTogXCJyZXN1bHRcIiwgLi4uIH1gIGFzIHRoZSBmaW5hbCB5aWVsZC5cbiAqXG4gKiBFcnJvcnMgcHJvcGFnYXRlIGJ5IHRoZSBnZW5lcmF0b3IgdGhyb3dpbmcgLSB0aGVyZSdzIG5vIGBcImVycm9yXCJgIHZhcmlhbnQuXG4gKiBXcmFwIHRoZSBgZm9yIGF3YWl0YCBpbiBgdHJ5L2NhdGNoYCBpZiB5b3UgbmVlZCB0byBoYW5kbGUgZmFpbHVyZXMuXG4gKlxuICogQGV4YW1wbGVcbiAqIGZvciBhd2FpdCAoY29uc3QgZXZ0IG9mIGdlbmllRXZlbnRDaGF0KHNwYWNlSWQsIFwiVG9wIHN0b3Jlcz9cIikpIHtcbiAqICAgc3dpdGNoIChldnQudHlwZSkge1xuICogICAgIGNhc2UgXCJ0aGlua2luZ1wiOlxuICogICAgICAgY29uc29sZS5sb2coXCJbdGhpbmtpbmddXCIsIGV2dC50aG91Z2h0X3R5cGUsIGV2dC50ZXh0KTtcbiAqICAgICAgIGJyZWFrO1xuICogICAgIGNhc2UgXCJ0ZXh0XCI6XG4gKiAgICAgICBjb25zb2xlLmxvZyhcIlt0ZXh0XVwiLCBldnQudGV4dCk7XG4gKiAgICAgICBicmVhaztcbiAqICAgICBjYXNlIFwicmVzdWx0XCI6XG4gKiAgICAgICBjb25zb2xlLmxvZyhcIltkb25lXVwiLCBldnQuc3RhdHVzKTtcbiAqICAgICAgIGJyZWFrO1xuICogICB9XG4gKiB9XG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiogZ2VuaWVFdmVudENoYXQoXG4gIHNwYWNlX2lkOiBzdHJpbmcsXG4gIGNvbnRlbnQ6IHN0cmluZyxcbiAgb3B0aW9ucz86IEdlbmllQ2hhdE9wdGlvbnMsXG4pOiBBc3luY0dlbmVyYXRvcjxHZW5pZUNoYXRFdmVudCwgdm9pZCwgdm9pZD4ge1xuICAvLyBEaWZmIHNvdXJjZSBmb3IgdGhlIGN1cnJlbnQgdHVybi4gQWx3YXlzIGB1bmRlZmluZWRgIG9uIHRoZSBmaXJzdCBzbmFwc2hvdFxuICAvLyBzbyB0aGUgaW5pdGlhbCBzdGF0dXMgLyBhdHRhY2htZW50cyBlbWl0IGZyZXNoOyB1cGRhdGVkIHRvIHRoZSBtb3N0IHJlY2VudFxuICAvLyBzbmFwc2hvdCBhZnRlciBlYWNoIHlpZWxkLlxuICBsZXQgcHJldmlvdXM6IEdlbmllTWVzc2FnZSB8IHVuZGVmaW5lZDtcbiAgLy8gVGhlIGBxdWVzdGlvbmAgZXZlbnQgaXMgZGVmZXJyZWQgdG8gdGhlIGZpcnN0IGBtZXNzYWdlYCB5aWVsZCBzbyBpdCBjYW5cbiAgLy8gY2FycnkgdGhlIGFzc2lnbmVkIGBtZXNzYWdlX2lkYCAoc3Vic2NyaWJlcnMgdXNlIGl0IGFzIHRoZSBncm91cGluZyBrZXkgZm9yXG4gIC8vIGV2ZXJ5IGV2ZW50IGluIHRoaXMgdHVybikuIFRoZSBmaXJzdCBzbmFwc2hvdCBpcyB0aGUgZWFybGllc3QgcG9pbnQgdGhhdCBpZFxuICAvLyBleGlzdHMuXG4gIGxldCBxdWVzdGlvbkVtaXR0ZWQgPSBmYWxzZTtcbiAgZm9yIGF3YWl0IChjb25zdCByYXdNZXNzYWdlIG9mIGdlbmllQ2hhdChzcGFjZV9pZCwgY29udGVudCwgb3B0aW9ucykpIHtcbiAgICAvLyBOb3JtYWxpemUgYG1lc3NhZ2VfaWRgIGZyb20gdGhlIGxlZ2FjeSBgaWRgIGZpZWxkIHdoZW4gR2VuaWUncyB3aXJlXG4gICAgLy8gcmVzcG9uc2Ugb25seSBwb3B1bGF0ZXMgb25lIG9mIHRoZW0uIFRoZSBTREsgc2NoZW1hIG1hcmtzIGJvdGggYXNcbiAgICAvLyByZXF1aXJlZCwgYnV0IGluIHByYWN0aWNlIHRoZSBgc3RhcnRDb252ZXJzYXRpb25gIC8gYGNyZWF0ZU1lc3NhZ2VgIGlubmVyXG4gICAgLy8gYG1lc3NhZ2VgIHBheWxvYWQgc29tZXRpbWVzIHNoaXBzIG9ubHkgYGlkYCB3aGlsZSB0aGUgbmV3IGBtZXNzYWdlX2lkYFxuICAgIC8vIGZpZWxkIGxhbmRzIHVuZGVmaW5lZC4gRXZlcnkgZG93bnN0cmVhbSBldmVudCBkZXRlY3RvciBrZXlzIGdyb3VwaW5nIG9mZlxuICAgIC8vIGBtZXNzYWdlX2lkYDsgdGhlIGZhbGxiYWNrIGtlZXBzIG9uZSBHZW5pZSB0dXJuJ3MgZXZlbnRzIGZyb20gc3BsaXR0aW5nXG4gICAgLy8gYWNyb3NzIGFuIGFub24gZ3JvdXAgKyB0aGUgcmVhbC1pZCBncm91cCB3aGVuIHN1YnNjcmliZXJzIGJ1Y2tldCBieVxuICAgIC8vIGBtZXNzYWdlX2lkYC5cbiAgICBjb25zdCBtZXNzYWdlOiBHZW5pZU1lc3NhZ2UgPSByYXdNZXNzYWdlLm1lc3NhZ2VfaWRcbiAgICAgID8gcmF3TWVzc2FnZVxuICAgICAgOiB7IC4uLnJhd01lc3NhZ2UsIG1lc3NhZ2VfaWQ6IHJhd01lc3NhZ2UuaWQgfTtcbiAgICB5aWVsZCB7XG4gICAgICB0eXBlOiBcIm1lc3NhZ2VcIixcbiAgICAgIHNwYWNlX2lkOiBtZXNzYWdlLnNwYWNlX2lkLFxuICAgICAgbWVzc2FnZV9pZDogbWVzc2FnZS5tZXNzYWdlX2lkLFxuICAgICAgbWVzc2FnZSxcbiAgICB9O1xuICAgIGlmICghcXVlc3Rpb25FbWl0dGVkKSB7XG4gICAgICB5aWVsZCB7XG4gICAgICAgIHR5cGU6IFwicXVlc3Rpb25cIixcbiAgICAgICAgc3BhY2VfaWQ6IG1lc3NhZ2Uuc3BhY2VfaWQsXG4gICAgICAgIC4uLihtZXNzYWdlLmNvbnZlcnNhdGlvbl9pZCA/IHsgY29udmVyc2F0aW9uX2lkOiBtZXNzYWdlLmNvbnZlcnNhdGlvbl9pZCB9IDoge30pLFxuICAgICAgICAuLi4obWVzc2FnZS5tZXNzYWdlX2lkID8geyBtZXNzYWdlX2lkOiBtZXNzYWdlLm1lc3NhZ2VfaWQgfSA6IHt9KSxcbiAgICAgICAgY29udGVudDogbWVzc2FnZS5jb250ZW50LFxuICAgICAgfTtcbiAgICAgIHF1ZXN0aW9uRW1pdHRlZCA9IHRydWU7XG4gICAgfVxuICAgIHlpZWxkKiBldmVudC5ldmVudHNGcm9tTWVzc2FnZShtZXNzYWdlLCBwcmV2aW91cywgbWVzc2FnZS5zcGFjZV9pZCk7XG4gICAgY29uc3Qgc3RhdHVzID0gbWVzc2FnZS5zdGF0dXM7XG4gICAgaWYgKGdlbmllTW9kZWwuaXNUZXJtaW5hbFN0YXR1cyhzdGF0dXMpKSB7XG4gICAgICB5aWVsZCB7XG4gICAgICAgIHR5cGU6IFwicmVzdWx0XCIsXG4gICAgICAgIHNwYWNlX2lkOiBtZXNzYWdlLnNwYWNlX2lkLFxuICAgICAgICBjb252ZXJzYXRpb25faWQ6IG1lc3NhZ2UuY29udmVyc2F0aW9uX2lkLFxuICAgICAgICBtZXNzYWdlX2lkOiBtZXNzYWdlLm1lc3NhZ2VfaWQsXG4gICAgICAgIHN0YXR1cyxcbiAgICAgICAgbWVzc2FnZSxcbiAgICAgIH07XG4gICAgfVxuICAgIHByZXZpb3VzID0gbWVzc2FnZTtcbiAgfVxufVxuXG4vKiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tIHdvcmtzcGFjZSBjbGllbnQgaGVscGVyIC0tLS0tLS0tLS0tLS0tLS0tLS0tLSAqL1xuXG4vKipcbiAqIFJlc29sdmUgYSBgV29ya3NwYWNlQ2xpZW50YCBpbiB0aGlzIHByZWZlcmVuY2Ugb3JkZXI6XG4gKlxuICogICAxLiBDYWxsZXItc3VwcGxpZWQgYG9wdGlvbnMud29ya3NwYWNlQ2xpZW50YC5cbiAqICAgMi4gQXBwS2l0J3MgcGVyLXJlcXVlc3QgZXhlY3V0aW9uLWNvbnRleHQgY2xpZW50IGluc2lkZSBhIHJlcXVlc3Qgc2NvcGUuXG4gKiAgIDMuIEZyZXNoIGBjcmVhdGVXb3Jrc3BhY2VDbGllbnQoKWAgKGVudi12YXIgYXV0aCB2aWFcbiAqICAgICAgYERBVEFCUklDS1NfQ09ORklHX1BST0ZJTEVgIC8gYERBVEFCUklDS1NfSE9TVGAgLyBgREFUQUJSSUNLU19UT0tFTmApLlxuICpcbiAqL1xuYXN5bmMgZnVuY3Rpb24gZ2V0V29ya3NwYWNlQ2xpZW50KG9wdGlvbnM/OiBHZW5pZUNoYXRPcHRpb25zKTogUHJvbWlzZTxXb3Jrc3BhY2VDbGllbnQ+IHtcbiAgaWYgKG9wdGlvbnM/LndvcmtzcGFjZUNsaWVudCkgcmV0dXJuIG9wdGlvbnMud29ya3NwYWNlQ2xpZW50O1xuICB0cnkge1xuICAgIHJldHVybiBnZXRFeGVjdXRpb25Db250ZXh0KCkuY2xpZW50O1xuICB9IGNhdGNoIHtcbiAgICAvLyBOb3QgaW5zaWRlIGFuIEFwcEtpdCByZXF1ZXN0IGNvbnRleHQ7IGZhbGwgdGhyb3VnaCB0byBkZWZhdWx0IGF1dGguXG4gIH1cbiAgcmV0dXJuIGNyZWF0ZVdvcmtzcGFjZUNsaWVudCgpO1xufVxuIl19
@@ -1 +1 @@
1
- {"root":["../src/chat.ts","../src/space.ts","../index.ts"],"version":"5.9.3"}
1
+ {"root":["../src/agent-mode.ts","../src/chat.ts","../src/space.ts","../index.ts"],"version":"5.9.3"}
package/package.json CHANGED
@@ -25,9 +25,9 @@
25
25
  },
26
26
  "dependencies": {
27
27
  "@databricks/appkit": "^0.60.0",
28
- "@dbx-tools/appkit": "0.6.212",
29
- "@dbx-tools/shared-core": "0.6.212",
30
- "@dbx-tools/shared-genie": "0.6.212"
28
+ "@dbx-tools/appkit": "0.6.213",
29
+ "@dbx-tools/shared-core": "0.6.213",
30
+ "@dbx-tools/shared-genie": "0.6.213"
31
31
  },
32
32
  "main": "./lib/index.js",
33
33
  "license": "Apache-2.0",
@@ -43,7 +43,7 @@
43
43
  "./package.json": "./package.json"
44
44
  }
45
45
  },
46
- "version": "0.6.212",
46
+ "version": "0.6.213",
47
47
  "types": "./lib/index.d.ts",
48
48
  "type": "module",
49
49
  "exports": {
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Genie Agent Mode SSE transport.
3
+ *
4
+ * Streams the Responses-shaped Agent Mode API and projects its reasoning, SQL,
5
+ * query output, and final answer items onto the existing `GenieMessage`
6
+ * contract so callers can keep one semantic event pipeline across Agent Mode
7
+ * and the legacy polling API.
8
+ *
9
+ * @module
10
+ */
11
+
12
+ import type { WorkspaceClient } from "@databricks/appkit";
13
+ import { databricks } from "@dbx-tools/appkit";
14
+ import { error, json, log, object } from "@dbx-tools/shared-core";
15
+ import {
16
+ agentMode as agentModeWire,
17
+ type GenieAgentModeEvent,
18
+ type GenieMessage,
19
+ } from "@dbx-tools/shared-genie";
20
+
21
+ const logger = log.logger("genie/agent-mode");
22
+ const CANCEL_TIMEOUT_MS = 5_000;
23
+
24
+ /** Inputs for one Agent Mode response stream. */
25
+ export interface GenieAgentModeOptions {
26
+ conversationId?: string;
27
+ enableVisualization?: boolean;
28
+ context?: databricks.ContextLike;
29
+ }
30
+
31
+ /** Stream one Agent Mode response as `GenieMessage` snapshots. */
32
+ export async function* genieAgentModeChat(
33
+ client: WorkspaceClient,
34
+ agentId: string,
35
+ content: string,
36
+ options: GenieAgentModeOptions = {},
37
+ ): AsyncGenerator<GenieMessage, void, void> {
38
+ const ownedController = options.context ? undefined : new AbortController();
39
+ const projection = new agentModeWire.GenieAgentModeProjection(agentId, content);
40
+ try {
41
+ const context = options.context
42
+ ? databricks.toContext(options.context)
43
+ : databricks.toContext(ownedController!);
44
+ const response = await client.apiClient.request(
45
+ {
46
+ path: `/api/2.0/genie/agents/${encodeURIComponent(agentId)}/responses`,
47
+ method: "POST",
48
+ headers: new Headers({
49
+ accept: "text/event-stream",
50
+ "content-type": "application/json",
51
+ }),
52
+ raw: true,
53
+ payload: {
54
+ input: [
55
+ {
56
+ type: "message",
57
+ role: "user",
58
+ content: [{ type: "input_text", text: content }],
59
+ },
60
+ ],
61
+ ...(options.conversationId ? { conversation_id: options.conversationId } : {}),
62
+ ...(options.enableVisualization ? { enable_viz: true } : {}),
63
+ },
64
+ },
65
+ context,
66
+ );
67
+ const stream = object.isRecord(response) ? response.contents : undefined;
68
+ if (!isReadableStream(stream)) {
69
+ throw new TypeError("Genie Agent Mode did not return an SSE stream");
70
+ }
71
+
72
+ let previous: GenieMessage | undefined;
73
+ for await (const event of parseSse(stream)) {
74
+ const message = projection.apply(event);
75
+ if (!message) continue;
76
+ if (!object.deepEqual(message, previous)) {
77
+ yield message;
78
+ previous = message;
79
+ }
80
+ }
81
+ if (!projection.terminal) {
82
+ throw new Error("Genie Agent Mode stream ended before a terminal response");
83
+ }
84
+ } finally {
85
+ ownedController?.abort();
86
+ if (!projection.terminal && projection.responseId && projection.conversationId) {
87
+ await cancelResponse(client, agentId, projection.conversationId, projection.responseId);
88
+ }
89
+ }
90
+ }
91
+
92
+ /** Return whether Agent Mode is disabled or its preview toggle is unavailable. */
93
+ export function isAgentModeUnavailable(value: unknown): boolean {
94
+ const context = error.errorContext(value);
95
+ return context.hasMessage("feature", "disabled") || context.hasMessage("preview", "toggle");
96
+ }
97
+
98
+ function isReadableStream(value: unknown): value is ReadableStream<Uint8Array> {
99
+ return object.isRecord(value) && typeof value.getReader === "function";
100
+ }
101
+
102
+ async function cancelResponse(
103
+ client: WorkspaceClient,
104
+ agentId: string,
105
+ conversationId: string,
106
+ responseId: string,
107
+ ): Promise<void> {
108
+ const controller = new AbortController();
109
+ const timeout = setTimeout(() => controller.abort(), CANCEL_TIMEOUT_MS);
110
+ try {
111
+ await client.apiClient.request(
112
+ {
113
+ path: `/api/2.0/genie/agents/${encodeURIComponent(agentId)}/conversations/${encodeURIComponent(conversationId)}/responses/${encodeURIComponent(responseId)}/cancel`,
114
+ method: "POST",
115
+ headers: new Headers({
116
+ accept: "application/json",
117
+ "content-type": "application/json",
118
+ }),
119
+ raw: false,
120
+ },
121
+ databricks.toContext(controller),
122
+ );
123
+ } catch (err) {
124
+ logger.debug("response:cancel-failed", {
125
+ agentId,
126
+ conversationId,
127
+ responseId,
128
+ error: error.errorMessage(err),
129
+ });
130
+ } finally {
131
+ clearTimeout(timeout);
132
+ }
133
+ }
134
+
135
+ async function* parseSse(
136
+ stream: ReadableStream<Uint8Array>,
137
+ ): AsyncGenerator<GenieAgentModeEvent, void, void> {
138
+ const reader = stream.getReader();
139
+ const decoder = new TextDecoder();
140
+ let buffer = "";
141
+ try {
142
+ while (true) {
143
+ const { done, value } = await reader.read();
144
+ buffer += decoder.decode(value, { stream: !done });
145
+ const frames = buffer.split(/\r?\n\r?\n/);
146
+ buffer = frames.pop() ?? "";
147
+ for (const frame of frames) {
148
+ const event = parseSseFrame(frame);
149
+ if (event) yield event;
150
+ }
151
+ if (done) {
152
+ const event = parseSseFrame(buffer);
153
+ if (event) yield event;
154
+ break;
155
+ }
156
+ }
157
+ } finally {
158
+ await reader.cancel().catch(() => undefined);
159
+ reader.releaseLock();
160
+ }
161
+ }
162
+
163
+ function parseSseFrame(frame: string): GenieAgentModeEvent | undefined {
164
+ const data = frame
165
+ .split(/\r?\n/)
166
+ .filter((line) => line.startsWith("data:"))
167
+ .map((line) => line.slice(5).trimStart())
168
+ .join("\n");
169
+ if (!data || data === "[DONE]") return undefined;
170
+ return agentModeWire.GenieAgentModeEventSchema.parse(json.parse(data));
171
+ }
package/src/chat.ts CHANGED
@@ -6,11 +6,15 @@
6
6
  * returned on each `GenieMessage` back into the next turn's
7
7
  * `options.conversationId`).
8
8
  *
9
+ * Agent Mode SSE is the default transport. Its Responses-style reasoning, SQL,
10
+ * query output, and final answer items are projected into `GenieMessage`
11
+ * snapshots; `agentMode: false` retains the Conversation API polling path.
12
+ *
9
13
  * Two layers serve two kinds of consumer. The low-level layer yields every
10
- * poll-observed `GenieMessage` (validated against `GenieMessageSchema`,
11
- * falling back to the raw snapshot on a schema miss) and owns the messy parts
12
- * - cancellation, conversation seeding, distinct-filtering, and SDK quirks
13
- * (Waiter stripping); reach for it when you want the raw stream. The
14
+ * observed `GenieMessage` (validated against `GenieMessageSchema`, falling back
15
+ * to the raw snapshot on a schema miss) and owns cancellation, conversation
16
+ * seeding, distinct-filtering, and SDK quirks; reach for it when you want the
17
+ * raw stream. The
14
18
  * high-level layer wraps it and emits semantic, deduplicated `{ type, payload }`
15
19
  * events (see {@link GenieChatEvent}), always closing a successful turn with a
16
20
  * terminal `result` event carrying the final `GenieMessage`; errors propagate
@@ -27,9 +31,11 @@ import {
27
31
  type WorkspaceClient,
28
32
  } from "@databricks/appkit";
29
33
  import { databricks } from "@dbx-tools/appkit";
30
- import { async, log, type PollContext } from "@dbx-tools/shared-core";
34
+ import { async, error, log, type PollContext } from "@dbx-tools/shared-core";
31
35
  import { event, genieModel, type GenieChatEvent, type GenieMessage } from "@dbx-tools/shared-genie";
32
36
 
37
+ import { genieAgentModeChat, isAgentModeUnavailable } from "./agent-mode.ts";
38
+
33
39
  const logger = log.logger("genie/chat");
34
40
 
35
41
  /**
@@ -55,11 +61,16 @@ function validateMessage(raw: GenieMessage): GenieMessage {
55
61
  /** Options accepted by both {@link genieChat} and {@link genieEventChat}. */
56
62
  export interface GenieChatOptions {
57
63
  /**
58
- * Seed conversation id. When set, this turn appends to the existing
59
- * conversation (via `createMessage`) instead of opening a new one. Use it to
60
- * thread a multi-turn conversation: read `conversation_id` off the prior
61
- * turn's terminal `GenieMessage` (or the `result` event's
62
- * `payload.conversation_id`) and pass it into the next call.
64
+ * Use the streaming Genie Agent Mode API. Defaults to `true`; set `false` to
65
+ * force the legacy start/create/get-message polling flow.
66
+ */
67
+ agentMode?: boolean;
68
+ /** Ask Agent Mode to generate visualizations when appropriate. */
69
+ enableVisualization?: boolean;
70
+ /**
71
+ * Continue an existing conversation. Agent Mode sends it as
72
+ * `conversation_id`; legacy polling passes it to `createMessage`. Read the id
73
+ * from the prior turn's terminal `GenieMessage` or `result` event.
63
74
  */
64
75
  conversationId?: string;
65
76
  /**
@@ -69,12 +80,12 @@ export interface GenieChatOptions {
69
80
  * otherwise.
70
81
  */
71
82
  workspaceClient?: WorkspaceClient;
72
- /** Poll cadence in milliseconds between successive `getMessage` calls (default 500). */
83
+ /** Legacy fallback cadence between successive `getMessage` calls (default 500ms). */
73
84
  pollIntervalMs?: number;
74
85
  /**
75
86
  * External cancellation. Accepts a WHATWG `AbortSignal` or a fully-built SDK
76
87
  * `Context` (see `databricks.ContextLike`). Aborting it cancels every in-flight
77
- * SDK call and the next inter-poll sleep.
88
+ * Agent Mode stream, SDK call, and the next inter-poll sleep.
78
89
  */
79
90
  context?: databricks.ContextLike;
80
91
  }
@@ -87,21 +98,19 @@ export interface GenieChatOptions {
87
98
  *
88
99
  * Turn lifecycle:
89
100
  *
90
- * - No `options.conversationId`: open a new conversation via
91
- * `client.genie.startConversation`. The opened conversation id surfaces on
92
- * every yielded `GenieMessage` (`.conversation_id`) so the caller can
93
- * thread it into a follow-up call.
94
- * - With `options.conversationId`: append to that conversation via
95
- * `client.genie.createMessage`.
96
- * - In both cases, after the create/start the driver polls
97
- * `client.genie.getMessage` every `options.pollIntervalMs` (default 500ms)
98
- * until the message reaches a terminal status, then yields the terminal
99
- * snapshot and returns.
101
+ * - Agent Mode (default): POST one Responses-style message to
102
+ * `/api/2.0/genie/agents/{id}/responses` and yield projected snapshots from
103
+ * its SSE events.
104
+ * - Legacy polling (`agentMode: false`): start/create a Conversation API
105
+ * message and poll `getMessage` until terminal.
106
+ * - A pre-stream `FEATURE_DISABLED` or preview-toggle response falls back to
107
+ * legacy polling automatically.
100
108
  *
101
109
  * Cancellation: a single internal `AbortController` covers the whole turn.
102
110
  * `options.context` is tied into that controller so an external abort tears
103
- * down every in-flight SDK call AND the inter-poll sleep. Breaking out of the
104
- * `for await` does the same via the `try / finally`.
111
+ * down the Agent Mode SSE connection, SDK calls, and any inter-poll sleep.
112
+ * Breaking out of the `for await` also invokes the Agent Mode server-side
113
+ * cancel endpoint before the generator closes.
105
114
  *
106
115
  * @example
107
116
  * // Single turn.
@@ -132,6 +141,26 @@ export async function* genieChat(
132
141
  // (via `databricks.toContext` -> `async.tieAbortSignal`), eventually tripping
133
142
  // Node's `MaxListenersExceededWarning`.
134
143
  const ctx = databricks.toContext(controller, options?.context);
144
+ if (options?.agentMode !== false) {
145
+ let yielded = false;
146
+ try {
147
+ for await (const message of genieAgentModeChat(client, space_id, content, {
148
+ ...(options?.conversationId ? { conversationId: options.conversationId } : {}),
149
+ ...(options?.enableVisualization ? { enableVisualization: true } : {}),
150
+ context: ctx,
151
+ })) {
152
+ yielded = true;
153
+ yield validateMessage(message);
154
+ }
155
+ return;
156
+ } catch (err) {
157
+ if (yielded || !isAgentModeUnavailable(err)) throw err;
158
+ logger.warn("agent-mode:unavailable, falling back to polling", {
159
+ space_id,
160
+ error: error.errorMessage(err),
161
+ });
162
+ }
163
+ }
135
164
  let conversationId = options?.conversationId;
136
165
  let messageId: string | undefined;
137
166