@dbx-tools/genie 0.3.43 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ export * as chat from "./src/chat.js";
2
+ export * as space from "./src/space.js";
3
+ export { genieChat, genieEventChat } from "./src/chat.js";
4
+ export type { GenieChatOptions } from "./src/chat.js";
5
+ export { getGenieSpace, genieSampleQuestions } from "./src/space.js";
6
+ export type { GetGenieSpaceOptions } from "./src/space.js";
package/lib/index.js ADDED
@@ -0,0 +1,8 @@
1
+ // GENERATED by projen watch - DO NOT EDIT.
2
+ // Regenerated from the exporting modules in ./src.
3
+ // Hand edits are overwritten on the next watch; this file is read-only.
4
+ export * as chat from "./src/chat.js";
5
+ export * as space from "./src/space.js";
6
+ export { genieChat, genieEventChat } from "./src/chat.js";
7
+ export { getGenieSpace, genieSampleQuestions } from "./src/space.js";
8
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxPQUFPLEtBQUssSUFBSSxNQUFNLFlBQVksQ0FBQztBQUNuQyxPQUFPLEtBQUssS0FBSyxNQUFNLGFBQWEsQ0FBQztBQUNyQyxPQUFPLEVBQUUsU0FBUyxFQUFFLGNBQWMsRUFBRSxNQUFNLFlBQVksQ0FBQztBQUV2RCxPQUFPLEVBQUUsYUFBYSxFQUFFLG9CQUFvQixFQUFFLE1BQU0sYUFBYSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLy8gR0VORVJBVEVEIGJ5IHByb2plbiB3YXRjaCAtIERPIE5PVCBFRElULlxuLy8gUmVnZW5lcmF0ZWQgZnJvbSB0aGUgZXhwb3J0aW5nIG1vZHVsZXMgaW4gLi9zcmMuXG4vLyBIYW5kIGVkaXRzIGFyZSBvdmVyd3JpdHRlbiBvbiB0aGUgbmV4dCB3YXRjaDsgdGhpcyBmaWxlIGlzIHJlYWQtb25seS5cblxuZXhwb3J0ICogYXMgY2hhdCBmcm9tIFwiLi9zcmMvY2hhdFwiO1xuZXhwb3J0ICogYXMgc3BhY2UgZnJvbSBcIi4vc3JjL3NwYWNlXCI7XG5leHBvcnQgeyBnZW5pZUNoYXQsIGdlbmllRXZlbnRDaGF0IH0gZnJvbSBcIi4vc3JjL2NoYXRcIjtcbmV4cG9ydCB0eXBlIHsgR2VuaWVDaGF0T3B0aW9ucyB9IGZyb20gXCIuL3NyYy9jaGF0XCI7XG5leHBvcnQgeyBnZXRHZW5pZVNwYWNlLCBnZW5pZVNhbXBsZVF1ZXN0aW9ucyB9IGZyb20gXCIuL3NyYy9zcGFjZVwiO1xuZXhwb3J0IHR5cGUgeyBHZXRHZW5pZVNwYWNlT3B0aW9ucyB9IGZyb20gXCIuL3NyYy9zcGFjZVwiO1xuIl19
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Genie chat driver.
3
+ *
4
+ * Drives a single turn against a Genie space from one `content` string;
5
+ * multi-turn conversations are the caller's job (thread the `conversation_id`
6
+ * returned on each `GenieMessage` back into the next turn's
7
+ * `options.conversationId`).
8
+ *
9
+ * 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
+ * high-level layer wraps it and emits semantic, deduplicated `{ type, payload }`
15
+ * events (see {@link GenieChatEvent}), always closing a successful turn with a
16
+ * terminal `result` event carrying the final `GenieMessage`; errors propagate
17
+ * by throwing, with no `error` variant. Iterating UI / agent code that wants
18
+ * every message verbatim takes the low-level stream; subscribers reacting to
19
+ * "Genie is thinking about X" or "Genie produced text Y" take the event layer.
20
+ *
21
+ * @module
22
+ */
23
+ import { WorkspaceClient } from "@databricks/sdk-experimental";
24
+ import { databricks } from "@dbx-tools/appkit";
25
+ import { type GenieChatEvent, type GenieMessage } from "@dbx-tools/shared-genie";
26
+ /** Options accepted by both {@link genieChat} and {@link genieEventChat}. */
27
+ export interface GenieChatOptions {
28
+ /**
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.
34
+ */
35
+ conversationId?: string;
36
+ /**
37
+ * Explicit `WorkspaceClient`. Defaults to AppKit's per-request
38
+ * execution-context client when AppKit is installed and we're inside a
39
+ * request; falls back to a fresh `new WorkspaceClient({})` (env-var auth)
40
+ * otherwise.
41
+ */
42
+ workspaceClient?: WorkspaceClient;
43
+ /** Poll cadence in milliseconds between successive `getMessage` calls (default 500). */
44
+ pollIntervalMs?: number;
45
+ /**
46
+ * External cancellation. Accepts a WHATWG `AbortSignal` or a fully-built SDK
47
+ * `Context` (see `databricks.ContextLike`). Aborting it cancels every in-flight
48
+ * SDK call and the next inter-poll sleep.
49
+ */
50
+ context?: databricks.ContextLike;
51
+ }
52
+ /**
53
+ * One turn against a Genie space, yielded as a stream of `GenieMessage`
54
+ * snapshots.
55
+ *
56
+ * Turn lifecycle:
57
+ *
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.
68
+ *
69
+ * Cancellation: a single internal `AbortController` covers the whole turn.
70
+ * `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`.
73
+ *
74
+ * @example
75
+ * // Single turn.
76
+ * for await (const m of genieChat(spaceId, "Top 5 stores?")) {
77
+ * render(m);
78
+ * }
79
+ *
80
+ * @example
81
+ * // Multi-turn: caller threads the conversation id.
82
+ * let conversationId: string | undefined;
83
+ * for (const question of questions) {
84
+ * for await (const m of genieChat(spaceId, question, { conversationId })) {
85
+ * conversationId = m.conversation_id ?? conversationId;
86
+ * render(m);
87
+ * }
88
+ * }
89
+ */
90
+ export declare function genieChat(space_id: string, content: string, options?: GenieChatOptions): AsyncGenerator<GenieMessage, void, void>;
91
+ /**
92
+ * One turn against a Genie space, yielded as a typed {@link GenieChatEvent}
93
+ * stream. Drives {@link genieChat} underneath and decorates each snapshot with
94
+ * the derived events the field-level diff produced. Stream order:
95
+ *
96
+ * 1. `{ type: "message", message }` - the raw `GenieMessage`, once per poll
97
+ * yield.
98
+ * 2. `{ type: "question", content, message_id, ... }` fires exactly once, on
99
+ * the FIRST `message` yield. We read `content` and `message_id` straight
100
+ * off the snapshot so every downstream event for this turn shares the same
101
+ * `message_id` (the question included) - subscribers can group everything
102
+ * for one Genie call under that one key.
103
+ * 3. Any of `status` / `attachment` / `thinking` / `text` / `query` /
104
+ * `statement` / `rows` / `suggested_questions` the diff against the prior
105
+ * snapshot produced.
106
+ * 4. On the terminal snapshot, `{ type: "result", ... }` as the final yield.
107
+ *
108
+ * Errors propagate by the generator throwing - there's no `"error"` variant.
109
+ * Wrap the `for await` in `try/catch` if you need to handle failures.
110
+ *
111
+ * @example
112
+ * for await (const evt of genieEventChat(spaceId, "Top stores?")) {
113
+ * switch (evt.type) {
114
+ * case "thinking":
115
+ * console.log("[thinking]", evt.thought_type, evt.text);
116
+ * break;
117
+ * case "text":
118
+ * console.log("[text]", evt.text);
119
+ * break;
120
+ * case "result":
121
+ * console.log("[done]", evt.status);
122
+ * break;
123
+ * }
124
+ * }
125
+ */
126
+ export declare function genieEventChat(space_id: string, content: string, options?: GenieChatOptions): AsyncGenerator<GenieChatEvent, void, void>;
@@ -0,0 +1,274 @@
1
+ /**
2
+ * Genie chat driver.
3
+ *
4
+ * Drives a single turn against a Genie space from one `content` string;
5
+ * multi-turn conversations are the caller's job (thread the `conversation_id`
6
+ * returned on each `GenieMessage` back into the next turn's
7
+ * `options.conversationId`).
8
+ *
9
+ * 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
+ * high-level layer wraps it and emits semantic, deduplicated `{ type, payload }`
15
+ * events (see {@link GenieChatEvent}), always closing a successful turn with a
16
+ * terminal `result` event carrying the final `GenieMessage`; errors propagate
17
+ * by throwing, with no `error` variant. Iterating UI / agent code that wants
18
+ * every message verbatim takes the low-level stream; subscribers reacting to
19
+ * "Genie is thinking about X" or "Genie produced text Y" take the event layer.
20
+ *
21
+ * @module
22
+ */
23
+ import { WorkspaceClient } from "@databricks/sdk-experimental";
24
+ import { databricks } from "@dbx-tools/appkit";
25
+ import { async, log } from "@dbx-tools/shared-core";
26
+ import { event, genieModel } from "@dbx-tools/shared-genie";
27
+ const logger = log.logger("genie/chat");
28
+ /**
29
+ * Validate a polled wire snapshot against {@link GenieMessageSchema}
30
+ * and return the schema-normalized message. Genie's wire occasionally ships a
31
+ * shape the (SDK-derived) schema doesn't model exactly - e.g. an early poll
32
+ * that omits the SDK-required `message_id` - so a miss degrades to the raw
33
+ * snapshot rather than throwing, keeping a single odd poll from aborting the
34
+ * whole turn.
35
+ */
36
+ function validateMessage(raw) {
37
+ const result = genieModel.GenieMessageSchema.safeParse(raw);
38
+ if (result.success)
39
+ return result.data;
40
+ logger.debug("wire-message:schema-miss", {
41
+ message_id: raw.message_id ?? raw.id,
42
+ issues: result.error.issues.length,
43
+ });
44
+ return raw;
45
+ }
46
+ /* ----------------------- low-level: genieChat ----------------------- */
47
+ /**
48
+ * One turn against a Genie space, yielded as a stream of `GenieMessage`
49
+ * snapshots.
50
+ *
51
+ * Turn lifecycle:
52
+ *
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.
63
+ *
64
+ * Cancellation: a single internal `AbortController` covers the whole turn.
65
+ * `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
+ *
69
+ * @example
70
+ * // Single turn.
71
+ * for await (const m of genieChat(spaceId, "Top 5 stores?")) {
72
+ * render(m);
73
+ * }
74
+ *
75
+ * @example
76
+ * // Multi-turn: caller threads the conversation id.
77
+ * let conversationId: string | undefined;
78
+ * for (const question of questions) {
79
+ * for await (const m of genieChat(spaceId, question, { conversationId })) {
80
+ * conversationId = m.conversation_id ?? conversationId;
81
+ * render(m);
82
+ * }
83
+ * }
84
+ */
85
+ export async function* genieChat(space_id, content, options) {
86
+ const controller = new AbortController();
87
+ try {
88
+ const client = await getWorkspaceClient(options);
89
+ // Build the SDK Context ONCE. Building it inside the poll producer would
90
+ // re-attach an abort listener to `options.context` on every poll iteration
91
+ // (via `databricks.toContext` -> `async.tieAbortSignal`), eventually tripping
92
+ // Node's `MaxListenersExceededWarning`.
93
+ const ctx = databricks.toContext(controller, options?.context);
94
+ let conversationId = options?.conversationId;
95
+ let messageId;
96
+ const pollProducer = async (pollCtx) => {
97
+ if (!conversationId) {
98
+ // First poll: open the conversation. Refuse to retry: if
99
+ // `startConversation` returned a response without a `conversation_id`,
100
+ // retrying would just open conversation after conversation.
101
+ if (pollCtx.attempt > 0) {
102
+ throw new Error("Genie did not return a conversation id; refusing to retry");
103
+ }
104
+ const startResponse = await client.genie.startConversation({ space_id, content }, ctx);
105
+ conversationId = startResponse.conversation_id;
106
+ messageId = startResponse.message_id;
107
+ return startResponse.message;
108
+ }
109
+ if (!messageId) {
110
+ // First poll of a follow-up turn: append to the seeded conversation.
111
+ // `client.genie.createMessage` returns a `Waiter<GenieMessage>`
112
+ // (`{ ...message, wait: async () => ... }`). Strip `wait` here so
113
+ // downstream serializers (e.g. yaml.stringify) don't choke on the
114
+ // AsyncFunction value.
115
+ const { wait: _wait, ...createResponse } = await client.genie.createMessage({ space_id, conversation_id: conversationId, content }, ctx);
116
+ messageId = createResponse.message_id;
117
+ return createResponse;
118
+ }
119
+ // Subsequent polls: re-fetch the current message until its status becomes
120
+ // terminal.
121
+ return client.genie.getMessage({
122
+ space_id,
123
+ conversation_id: conversationId,
124
+ message_id: messageId,
125
+ }, ctx);
126
+ };
127
+ yield* async.poll(async (pollCtx) => validateMessage(await pollProducer(pollCtx)), {
128
+ intervalMs: options?.pollIntervalMs ?? 500,
129
+ // Skip yielding identical consecutive snapshots; Genie often returns
130
+ // the exact same payload twice during quiet periods. `poll` does a deep
131
+ // equal on the previous yield.
132
+ filter: "distinct",
133
+ // Stop after the terminal message is yielded. `poll` checks the
134
+ // predicate AFTER yielding, so the terminal message still reaches the
135
+ // consumer.
136
+ predicate: (m) => !genieModel.isTerminalStatus(m.status),
137
+ // Wake the inter-poll sleep on abort so a `for await` break (or
138
+ // external abort) tears down promptly instead of waiting out the
139
+ // interval.
140
+ signal: controller.signal,
141
+ });
142
+ }
143
+ finally {
144
+ // Cancels any still-pending SDK call and the inter-poll sleep whether we're
145
+ // unwinding from a normal return, a consumer break, or a thrown error.
146
+ // Idempotent.
147
+ controller.abort();
148
+ }
149
+ }
150
+ /* ---------------------- high-level: genieEventChat ------------------ */
151
+ /**
152
+ * One turn against a Genie space, yielded as a typed {@link GenieChatEvent}
153
+ * stream. Drives {@link genieChat} underneath and decorates each snapshot with
154
+ * the derived events the field-level diff produced. Stream order:
155
+ *
156
+ * 1. `{ type: "message", message }` - the raw `GenieMessage`, once per poll
157
+ * yield.
158
+ * 2. `{ type: "question", content, message_id, ... }` fires exactly once, on
159
+ * the FIRST `message` yield. We read `content` and `message_id` straight
160
+ * off the snapshot so every downstream event for this turn shares the same
161
+ * `message_id` (the question included) - subscribers can group everything
162
+ * for one Genie call under that one key.
163
+ * 3. Any of `status` / `attachment` / `thinking` / `text` / `query` /
164
+ * `statement` / `rows` / `suggested_questions` the diff against the prior
165
+ * snapshot produced.
166
+ * 4. On the terminal snapshot, `{ type: "result", ... }` as the final yield.
167
+ *
168
+ * Errors propagate by the generator throwing - there's no `"error"` variant.
169
+ * Wrap the `for await` in `try/catch` if you need to handle failures.
170
+ *
171
+ * @example
172
+ * for await (const evt of genieEventChat(spaceId, "Top stores?")) {
173
+ * switch (evt.type) {
174
+ * case "thinking":
175
+ * console.log("[thinking]", evt.thought_type, evt.text);
176
+ * break;
177
+ * case "text":
178
+ * console.log("[text]", evt.text);
179
+ * break;
180
+ * case "result":
181
+ * console.log("[done]", evt.status);
182
+ * break;
183
+ * }
184
+ * }
185
+ */
186
+ export async function* genieEventChat(space_id, content, options) {
187
+ // Diff source for the current turn. Always `undefined` on the first snapshot
188
+ // so the initial status / attachments emit fresh; updated to the most recent
189
+ // snapshot after each yield.
190
+ let previous;
191
+ // The `question` event is deferred to the first `message` yield so it can
192
+ // carry the assigned `message_id` (subscribers use it as the grouping key for
193
+ // every event in this turn). The first snapshot is the earliest point that id
194
+ // exists.
195
+ let questionEmitted = false;
196
+ for await (const rawMessage of genieChat(space_id, content, options)) {
197
+ // Normalize `message_id` from the legacy `id` field when Genie's wire
198
+ // response only populates one of them. The SDK schema marks both as
199
+ // required, but in practice the `startConversation` / `createMessage` inner
200
+ // `message` payload sometimes ships only `id` while the new `message_id`
201
+ // field lands undefined. Every downstream event detector keys grouping off
202
+ // `message_id`; the fallback keeps one Genie turn's events from splitting
203
+ // across an anon group + the real-id group when subscribers bucket by
204
+ // `message_id`.
205
+ const message = rawMessage.message_id
206
+ ? rawMessage
207
+ : { ...rawMessage, message_id: rawMessage.id };
208
+ yield {
209
+ type: "message",
210
+ space_id: message.space_id,
211
+ message_id: message.message_id,
212
+ message,
213
+ };
214
+ if (!questionEmitted) {
215
+ yield {
216
+ type: "question",
217
+ space_id: message.space_id,
218
+ ...(message.conversation_id ? { conversation_id: message.conversation_id } : {}),
219
+ ...(message.message_id ? { message_id: message.message_id } : {}),
220
+ content: message.content,
221
+ };
222
+ questionEmitted = true;
223
+ }
224
+ yield* event.eventsFromMessage(message, previous, message.space_id);
225
+ const status = message.status;
226
+ if (genieModel.isTerminalStatus(status)) {
227
+ yield {
228
+ type: "result",
229
+ space_id: message.space_id,
230
+ conversation_id: message.conversation_id,
231
+ message_id: message.message_id,
232
+ status,
233
+ message,
234
+ };
235
+ }
236
+ previous = message;
237
+ }
238
+ }
239
+ /* ---------------------- workspace client helper --------------------- */
240
+ /**
241
+ * Resolve a `WorkspaceClient` in this preference order:
242
+ *
243
+ * 1. Caller-supplied `options.workspaceClient`.
244
+ * 2. AppKit's per-request execution-context client, when AppKit is installed
245
+ * AND we're inside a request scope.
246
+ * 3. Fresh `new WorkspaceClient({})` (env-var auth via
247
+ * `DATABRICKS_CONFIG_PROFILE` / `DATABRICKS_HOST` / `DATABRICKS_TOKEN`).
248
+ *
249
+ * AppKit is loaded lazily so this package stays usable in non-AppKit
250
+ * environments.
251
+ */
252
+ async function getWorkspaceClient(options) {
253
+ if (options?.workspaceClient)
254
+ return options.workspaceClient;
255
+ const appkit = await getAppKit();
256
+ if (appkit) {
257
+ try {
258
+ return appkit.getExecutionContext().client;
259
+ }
260
+ catch {
261
+ // Not inside an AppKit request context; fall through to env.
262
+ }
263
+ }
264
+ return new WorkspaceClient({});
265
+ }
266
+ async function getAppKit() {
267
+ try {
268
+ return await import("@databricks/appkit");
269
+ }
270
+ catch {
271
+ return undefined;
272
+ }
273
+ }
274
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2hhdC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jaGF0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FxQkc7QUFFSCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDL0QsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFvQixNQUFNLHdCQUF3QixDQUFDO0FBQ3RFLE9BQU8sRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUEwQyxNQUFNLHlCQUF5QixDQUFDO0FBRXBHLE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUM7QUFFeEM7Ozs7Ozs7R0FPRztBQUNILFNBQVMsZUFBZSxDQUFDLEdBQWlCO0lBQ3hDLE1BQU0sTUFBTSxHQUFHLFVBQVUsQ0FBQyxrQkFBa0IsQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDNUQsSUFBSSxNQUFNLENBQUMsT0FBTztRQUFFLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQztJQUN2QyxNQUFNLENBQUMsS0FBSyxDQUFDLDBCQUEwQixFQUFFO1FBQ3ZDLFVBQVUsRUFBRSxHQUFHLENBQUMsVUFBVSxJQUFJLEdBQUcsQ0FBQyxFQUFFO1FBQ3BDLE1BQU0sRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFNO0tBQ25DLENBQUMsQ0FBQztJQUNILE9BQU8sR0FBRyxDQUFDO0FBQ2IsQ0FBQztBQStCRCwwRUFBMEU7QUFFMUU7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FxQ0c7QUFDSCxNQUFNLENBQUMsS0FBSyxTQUFTLENBQUMsQ0FBQyxTQUFTLENBQzlCLFFBQWdCLEVBQ2hCLE9BQWUsRUFDZixPQUEwQjtJQUUxQixNQUFNLFVBQVUsR0FBRyxJQUFJLGVBQWUs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Q3RCLElBQUksQ0FBQztRQUNILE9BQU8sTUFBTSxNQUFNLENBQUMsb0JBQW9CLENBQUMsQ0FBQztJQUM1QyxDQUFDO0lBQUMsTUFBTSxDQUFDO1FBQ1AsT0FBTyxTQUFTLENBQUM7SUFDbkIsQ0FBQztBQUNILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEdlbmllIGNoYXQgZHJpdmVyLlxuICpcbiAqIERyaXZlcyBhIHNpbmdsZSB0dXJuIGFnYWluc3QgYSBHZW5pZSBzcGFjZSBmcm9tIG9uZSBgY29udGVudGAgc3RyaW5nO1xuICogbXVsdGktdHVybiBjb252ZXJzYXRpb25zIGFyZSB0aGUgY2FsbGVyJ3Mgam9iICh0aHJlYWQgdGhlIGBjb252ZXJzYXRpb25faWRgXG4gKiByZXR1cm5lZCBvbiBlYWNoIGBHZW5pZU1lc3NhZ2VgIGJhY2sgaW50byB0aGUgbmV4dCB0dXJuJ3NcbiAqIGBvcHRpb25zLmNvbnZlcnNhdGlvbklkYCkuXG4gKlxuICogVHdvIGxheWVycyBzZXJ2ZSB0d28ga2luZHMgb2YgY29uc3VtZXIuIFRoZSBsb3ctbGV2ZWwgbGF5ZXIgeWllbGRzIGV2ZXJ5XG4gKiBwb2xsLW9ic2VydmVkIGBHZW5pZU1lc3NhZ2VgICh2YWxpZGF0ZWQgYWdhaW5zdCBgR2VuaWVNZXNzYWdlU2NoZW1hYCxcbiAqIGZhbGxpbmcgYmFjayB0byB0aGUgcmF3IHNuYXBzaG90IG9uIGEgc2NoZW1hIG1pc3MpIGFuZCBvd25zIHRoZSBtZXNzeSBwYXJ0c1xuICogLSBjYW5jZWxsYXRpb24sIGNvbnZlcnNhdGlvbiBzZWVkaW5nLCBkaXN0aW5jdC1maWx0ZXJpbmcsIGFuZCBTREsgcXVpcmtzXG4gKiAoV2FpdGVyIHN0cmlwcGluZyk7IHJlYWNoIGZvciBpdCB3aGVuIHlvdSB3YW50IHRoZSByYXcgc3RyZWFtLiBUaGVcbiAqIGhpZ2gtbGV2ZWwgbGF5ZXIgd3JhcHMgaXQgYW5kIGVtaXRzIHNlbWFudGljLCBkZWR1cGxpY2F0ZWQgYHsgdHlwZSwgcGF5bG9hZCB9YFxuICogZXZlbnRzIChzZWUge0BsaW5rIEdlbmllQ2hhdEV2ZW50fSksIGFsd2F5cyBjbG9zaW5nIGEgc3VjY2Vzc2Z1bCB0dXJuIHdpdGggYVxuICogdGVybWluYWwgYHJlc3VsdGAgZXZlbnQgY2FycnlpbmcgdGhlIGZpbmFsIGBHZW5pZU1lc3NhZ2VgOyBlcnJvcnMgcHJvcGFnYXRlXG4gKiBieSB0aHJvd2luZywgd2l0aCBubyBgZXJyb3JgIHZhcmlhbnQuIEl0ZXJhdGluZyBVSSAvIGFnZW50IGNvZGUgdGhhdCB3YW50c1xuICogZXZlcnkgbWVzc2FnZSB2ZXJiYXRpbSB0YWtlcyB0aGUgbG93LWxldmVsIHN0cmVhbTsgc3Vic2NyaWJlcnMgcmVhY3RpbmcgdG9cbiAqIFwiR2VuaWUgaXMgdGhpbmtpbmcgYWJvdXQgWFwiIG9yIFwiR2VuaWUgcHJvZHVjZWQgdGV4dCBZXCIgdGFrZSB0aGUgZXZlbnQgbGF5ZXIuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IFdvcmtzcGFjZUNsaWVudCB9IGZyb20gXCJAZGF0YWJyaWNrcy9zZGstZXhwZXJpbWVudGFsXCI7XG5pbXBvcnQgeyBkYXRhYnJpY2tzIH0gZnJvbSBcIkBkYngtdG9vbHMvYXBwa2l0XCI7XG5pbXBvcnQgeyBhc3luYywgbG9nLCB0eXBlIFBvbGxDb250ZXh0IH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7IGV2ZW50LCBnZW5pZU1vZGVsLCB0eXBlIEdlbmllQ2hhdEV2ZW50LCB0eXBlIEdlbmllTWVzc2FnZSB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1nZW5pZVwiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwiZ2VuaWUvY2hhdFwiKTtcblxuLyoqXG4gKiBWYWxpZGF0ZSBhIHBvbGxlZCB3aXJlIHNuYXBzaG90IGFnYWluc3Qge0BsaW5rIEdlbmllTWVzc2FnZVNjaGVtYX1cbiAqIGFuZCByZXR1cm4gdGhlIHNjaGVtYS1ub3JtYWxpemVkIG1lc3NhZ2UuIEdlbmllJ3Mgd2lyZSBvY2Nhc2lvbmFsbHkgc2hpcHMgYVxuICogc2hhcGUgdGhlIChTREstZGVyaXZlZCkgc2NoZW1hIGRvZXNuJ3QgbW9kZWwgZXhhY3RseSAtIGUuZy4gYW4gZWFybHkgcG9sbFxuICogdGhhdCBvbWl0cyB0aGUgU0RLLXJlcXVpcmVkIGBtZXNzYWdlX2lkYCAtIHNvIGEgbWlzcyBkZWdyYWRlcyB0byB0aGUgcmF3XG4gKiBzbmFwc2hvdCByYXRoZXIgdGhhbiB0aHJvd2luZywga2VlcGluZyBhIHNpbmdsZSBvZGQgcG9sbCBmcm9tIGFib3J0aW5nIHRoZVxuICogd2hvbGUgdHVybi5cbiAqL1xuZnVuY3Rpb24gdmFsaWRhdGVNZXNzYWdlKHJhdzogR2VuaWVNZXNzYWdlKTogR2VuaWVNZXNzYWdlIHtcbiAgY29uc3QgcmVzdWx0ID0gZ2VuaWVNb2RlbC5HZW5pZU1lc3NhZ2VTY2hlbWEuc2FmZVBhcnNlKHJhdyk7XG4gIGlmIChyZXN1bHQuc3VjY2VzcykgcmV0dXJuIHJlc3VsdC5kYXRhO1xuICBsb2dnZXIuZGVidWcoXCJ3aXJlLW1lc3NhZ2U6c2NoZW1hLW1pc3NcIiwge1xuICAgIG1lc3NhZ2VfaWQ6IHJhdy5tZXNzYWdlX2lkID8/IHJhdy5pZCxcbiAgICBpc3N1ZXM6IHJlc3VsdC5lcnJvci5pc3N1ZXMubGVuZ3RoLFxuICB9KTtcbiAgcmV0dXJuIHJhdztcbn1cblxuLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gc2hhcmVkIG9wdGlvbnMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuLyoqIE9wdGlvbnMgYWNjZXB0ZWQgYnkgYm90aCB7QGxpbmsgZ2VuaWVDaGF0fSBhbmQge0BsaW5rIGdlbmllRXZlbnRDaGF0fS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR2VuaWVDaGF0T3B0aW9ucyB7XG4gIC8qKlxuICAgKiBTZWVkIGNvbnZlcnNhdGlvbiBpZC4gV2hlbiBzZXQsIHRoaXMgdHVybiBhcHBlbmRzIHRvIHRoZSBleGlzdGluZ1xuICAgKiBjb252ZXJzYXRpb24gKHZpYSBgY3JlYXRlTWVzc2FnZWApIGluc3RlYWQgb2Ygb3BlbmluZyBhIG5ldyBvbmUuIFVzZSBpdCB0b1xuICAgKiB0aHJlYWQgYSBtdWx0aS10dXJuIGNvbnZlcnNhdGlvbjogcmVhZCBgY29udmVyc2F0aW9uX2lkYCBvZmYgdGhlIHByaW9yXG4gICAqIHR1cm4ncyB0ZXJtaW5hbCBgR2VuaWVNZXNzYWdlYCAob3IgdGhlIGByZXN1bHRgIGV2ZW50J3NcbiAgICogYHBheWxvYWQuY29udmVyc2F0aW9uX2lkYCkgYW5kIHBhc3MgaXQgaW50byB0aGUgbmV4dCBjYWxsLlxuICAgKi9cbiAgY29udmVyc2F0aW9uSWQ/OiBzdHJpbmc7XG4gIC8qKlxuICAgKiBFeHBsaWNpdCBgV29ya3NwYWNlQ2xpZW50YC4gRGVmYXVsdHMgdG8gQXBwS2l0J3MgcGVyLXJlcXVlc3RcbiAgICogZXhlY3V0aW9uLWNvbnRleHQgY2xpZW50IHdoZW4gQXBwS2l0IGlzIGluc3RhbGxlZCBhbmQgd2UncmUgaW5zaWRlIGFcbiAgICogcmVxdWVzdDsgZmFsbHMgYmFjayB0byBhIGZyZXNoIGBuZXcgV29ya3NwYWNlQ2xpZW50KHt9KWAgKGVudi12YXIgYXV0aClcbiAgICogb3RoZXJ3aXNlLlxuICAgKi9cbiAgd29ya3NwYWNlQ2xpZW50PzogV29ya3NwYWNlQ2xpZW50O1xuICAvKiogUG9sbCBjYWRlbmNlIGluIG1pbGxpc2Vjb25kcyBiZXR3ZWVuIHN1Y2Nlc3NpdmUgYGdldE1lc3NhZ2VgIGNhbGxzIChkZWZhdWx0IDUwMCkuICovXG4gIHBvbGxJbnRlcnZhbE1zPzogbnVtYmVyO1xuICAvKipcbiAgICogRXh0ZXJuYWwgY2FuY2VsbGF0aW9uLiBBY2NlcHRzIGEgV0hBVFdHIGBBYm9ydFNpZ25hbGAgb3IgYSBmdWxseS1idWlsdCBTREtcbiAgICogYENvbnRleHRgIChzZWUgYGRhdGFicmlja3MuQ29udGV4dExpa2VgKS4gQWJvcnRpbmcgaXQgY2FuY2VscyBldmVyeSBpbi1mbGlnaHRcbiAgICogU0RLIGNhbGwgYW5kIHRoZSBuZXh0IGludGVyLXBvbGwgc2xlZXAuXG4gICAqL1xuICBjb250ZXh0PzogZGF0YWJyaWNrcy5Db250ZXh0TGlrZTtcbn1cblxuLyogLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gbG93LWxldmVsOiBnZW5pZUNoYXQgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gKi9cblxuLyoqXG4gKiBPbmUgdHVybiBhZ2FpbnN0IGEgR2VuaWUgc3BhY2UsIHlpZWxkZWQgYXMgYSBzdHJlYW0gb2YgYEdlbmllTWVzc2FnZWBcbiAqIHNuYXBzaG90cy5cbiAqXG4gKiBUdXJuIGxpZmVjeWNsZTpcbiAqXG4gKiAgIC0gTm8gYG9wdGlvbnMuY29udmVyc2F0aW9uSWRgOiBvcGVuIGEgbmV3IGNvbnZlcnNhdGlvbiB2aWFcbiAqICAgICBgY2xpZW50LmdlbmllLnN0YXJ0Q29udmVyc2F0aW9uYC4gVGhlIG9wZW5lZCBjb252ZXJzYXRpb24gaWQgc3VyZmFjZXMgb25cbiAqICAgICBldmVyeSB5aWVsZGVkIGBHZW5pZU1lc3NhZ2VgIChgLmNvbnZlcnNhdGlvbl9pZGApIHNvIHRoZSBjYWxsZXIgY2FuXG4gKiAgICAgdGhyZWFkIGl0IGludG8gYSBmb2xsb3ctdXAgY2FsbC5cbiAqICAgLSBXaXRoIGBvcHRpb25zLmNvbnZlcnNhdGlvbklkYDogYXBwZW5kIHRvIHRoYXQgY29udmVyc2F0aW9uIHZpYVxuICogICAgIGBjbGllbnQuZ2VuaWUuY3JlYXRlTWVzc2FnZWAuXG4gKiAgIC0gSW4gYm90aCBjYXNlcywgYWZ0ZXIgdGhlIGNyZWF0ZS9zdGFydCB0aGUgZHJpdmVyIHBvbGxzXG4gKiAgICAgYGNsaWVudC5nZW5pZS5nZXRNZXNzYWdlYCBldmVyeSBgb3B0aW9ucy5wb2xsSW50ZXJ2YWxNc2AgKGRlZmF1bHQgNTAwbXMpXG4gKiAgICAgdW50aWwgdGhlIG1lc3NhZ2UgcmVhY2hlcyBhIHRlcm1pbmFsIHN0YXR1cywgdGhlbiB5aWVsZHMgdGhlIHRlcm1pbmFsXG4gKiAgICAgc25hcHNob3QgYW5kIHJldHVybnMuXG4gKlxuICogQ2FuY2VsbGF0aW9uOiBhIHNpbmdsZSBpbnRlcm5hbCBgQWJvcnRDb250cm9sbGVyYCBjb3ZlcnMgdGhlIHdob2xlIHR1cm4uXG4gKiBgb3B0aW9ucy5jb250ZXh0YCBpcyB0aWVkIGludG8gdGhhdCBjb250cm9sbGVyIHNvIGFuIGV4dGVybmFsIGFib3J0IHRlYXJzXG4gKiBkb3duIGV2ZXJ5IGluLWZsaWdodCBTREsgY2FsbCBBTkQgdGhlIGludGVyLXBvbGwgc2xlZXAuIEJyZWFraW5nIG91dCBvZiB0aGVcbiAqIGBmb3IgYXdhaXRgIGRvZXMgdGhlIHNhbWUgdmlhIHRoZSBgdHJ5IC8gZmluYWxseWAuXG4gKlxuICogQGV4YW1wbGVcbiAqIC8vIFNpbmdsZSB0dXJuLlxuICogZm9yIGF3YWl0IChjb25zdCBtIG9mIGdlbmllQ2hhdChzcGFjZUlkLCBcIlRvcCA1IHN0b3Jlcz9cIikpIHtcbiAqICAgcmVuZGVyKG0pO1xuICogfVxuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBNdWx0aS10dXJuOiBjYWxsZXIgdGhyZWFkcyB0aGUgY29udmVyc2F0aW9uIGlkLlxuICogbGV0IGNvbnZlcnNhdGlvbklkOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG4gKiBmb3IgKGNvbnN0IHF1ZXN0aW9uIG9mIHF1ZXN0aW9ucykge1xuICogICBmb3IgYXdhaXQgKGNvbnN0IG0gb2YgZ2VuaWVDaGF0KHNwYWNlSWQsIHF1ZXN0aW9uLCB7IGNvbnZlcnNhdGlvbklkIH0pKSB7XG4gKiAgICAgY29udmVyc2F0aW9uSWQgPSBtLmNvbnZlcnNhdGlvbl9pZCA/PyBjb252ZXJzYXRpb25JZDtcbiAqICAgICByZW5kZXIobSk7XG4gKiAgIH1cbiAqIH1cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uKiBnZW5pZUNoYXQoXG4gIHNwYWNlX2lkOiBzdHJpbmcsXG4gIGNvbnRlbnQ6IHN0cmluZyxcbiAgb3B0aW9ucz86IEdlbmllQ2hhdE9wdGlvbnMsXG4pOiBBc3luY0dlbmVyYXRvcjxHZW5pZU1lc3NhZ2UsIHZvaWQsIHZvaWQ+IHtcbiAgY29uc3QgY29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgdHJ5IHtcbiAgICBjb25zdCBjbGllbnQgPSBhd2FpdCBnZXRXb3Jrc3BhY2VDbGllbnQob3B0aW9ucyk7XG4gICAgLy8gQnVpbGQgdGhlIFNESyBDb250ZXh0IE9OQ0UuIEJ1aWxkaW5nIGl0IGluc2lkZSB0aGUgcG9sbCBwcm9kdWNlciB3b3VsZFxuICAgIC8vIHJlLWF0dGFjaCBhbiBhYm9ydCBsaXN0ZW5lciB0byBgb3B0aW9ucy5jb250ZXh0YCBvbiBldmVyeSBwb2xsIGl0ZXJhdGlvblxuICAgIC8vICh2aWEgYGRhdGFicmlja3MudG9Db250ZXh0YCAtPiBgYXN5bmMudGllQWJvcnRTaWduYWxgKSwgZXZlbnR1YWxseSB0cmlwcGluZ1xuICAgIC8vIE5vZGUncyBgTWF4TGlzdGVuZXJzRXhjZWVkZWRXYXJuaW5nYC5cbiAgICBjb25zdCBjdHggPSBkYXRhYnJpY2tzLnRvQ29udGV4dChjb250cm9sbGVyLCBvcHRpb25zPy5jb250ZXh0KTtcbiAgICBsZXQgY29udmVyc2F0aW9uSWQgPSBvcHRpb25zPy5jb252ZXJzYXRpb25JZDtcbiAgICBsZXQgbWVzc2FnZUlkOiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgICBjb25zdCBwb2xsUHJvZHVjZXIgPSBhc3luYyAocG9sbEN0eDogUG9sbENvbnRleHQ8R2VuaWVNZXNzYWdlPik6IFByb21pc2U8R2VuaWVNZXNzYWdlPiA9PiB7XG4gICAgICBpZiAoIWNvbnZlcnNhdGlvbklkKSB7XG4gICAgICAgIC8vIEZpcnN0IHBvbGw6IG9wZW4gdGhlIGNvbnZlcnNhdGlvbi4gUmVmdXNlIHRvIHJldHJ5OiBpZlxuICAgICAgICAvLyBgc3RhcnRDb252ZXJzYXRpb25gIHJldHVybmVkIGEgcmVzcG9uc2Ugd2l0aG91dCBhIGBjb252ZXJzYXRpb25faWRgLFxuICAgICAgICAvLyByZXRyeWluZyB3b3VsZCBqdXN0IG9wZW4gY29udmVyc2F0aW9uIGFmdGVyIGNvbnZlcnNhdGlvbi5cbiAgICAgICAgaWYgKHBvbGxDdHguYXR0ZW1wdCA+IDApIHtcbiAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJHZW5pZSBkaWQgbm90IHJldHVybiBhIGNvbnZlcnNhdGlvbiBpZDsgcmVmdXNpbmcgdG8gcmV0cnlcIik7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3Qgc3RhcnRSZXNwb25zZSA9IGF3YWl0IGNsaWVudC5nZW5pZS5zdGFydENvbnZlcnNhdGlvbih7IHNwYWNlX2lkLCBjb250ZW50IH0sIGN0eCk7XG4gICAgICAgIGNvbnZlcnNhdGlvbklkID0gc3RhcnRSZXNwb25zZS5jb252ZXJzYXRpb25faWQ7XG4gICAgICAgIG1lc3NhZ2VJZCA9IHN0YXJ0UmVzcG9uc2UubWVzc2FnZV9pZDtcbiAgICAgICAgcmV0dXJuIHN0YXJ0UmVzcG9uc2UubWVzc2FnZSE7XG4gICAgICB9XG4gICAgICBpZiAoIW1lc3NhZ2VJZCkge1xuICAgICAgICAvLyBGaXJzdCBwb2xsIG9mIGEgZm9sbG93LXVwIHR1cm46IGFwcGVuZCB0byB0aGUgc2VlZGVkIGNvbnZlcnNhdGlvbi5cbiAgICAgICAgLy8gYGNsaWVudC5nZW5pZS5jcmVhdGVNZXNzYWdlYCByZXR1cm5zIGEgYFdhaXRlcjxHZW5pZU1lc3NhZ2U+YFxuICAgICAgICAvLyAoYHsgLi4ubWVzc2FnZSwgd2FpdDogYXN5bmMgKCkgPT4gLi4uIH1gKS4gU3RyaXAgYHdhaXRgIGhlcmUgc29cbiAgICAgICAgLy8gZG93bnN0cmVhbSBzZXJpYWxpemVycyAoZS5nLiB5YW1sLnN0cmluZ2lmeSkgZG9uJ3QgY2hva2Ugb24gdGhlXG4gICAgICAgIC8vIEFzeW5jRnVuY3Rpb24gdmFsdWUuXG4gICAgICAgIGNvbnN0IHsgd2FpdDogX3dhaXQsIC4uLmNyZWF0ZVJlc3BvbnNlIH0gPSBhd2FpdCBjbGllbnQuZ2VuaWUuY3JlYXRlTWVzc2FnZShcbiAgICAgICAgICB7IHNwYWNlX2lkLCBjb252ZXJzYXRpb25faWQ6IGNvbnZlcnNhdGlvbklkLCBjb250ZW50IH0sXG4gICAgICAgICAgY3R4LFxuICAgICAgICApO1xuICAgICAgICBtZXNzYWdlSWQgPSBjcmVhdGVSZXNwb25zZS5tZXNzYWdlX2lkO1xuICAgICAgICByZXR1cm4gY3JlYXRlUmVzcG9uc2U7XG4gICAgICB9XG4gICAgICAvLyBTdWJzZXF1ZW50IHBvbGxzOiByZS1mZXRjaCB0aGUgY3VycmVudCBtZXNzYWdlIHVudGlsIGl0cyBzdGF0dXMgYmVjb21lc1xuICAgICAgLy8gdGVybWluYWwuXG4gICAgICByZXR1cm4gY2xpZW50LmdlbmllLmdldE1lc3NhZ2UoXG4gICAgICAgIHtcbiAgICAgICAgICBzcGFjZV9pZCxcbiAgICAgICAgICBjb252ZXJzYXRpb25faWQ6IGNvbnZlcnNhdGlvbklkLFxuICAgICAgICAgIG1lc3NhZ2VfaWQ6IG1lc3NhZ2VJZCxcbiAgICAgICAgfSxcbiAgICAgICAgY3R4LFxuICAgICAgKTtcbiAgICB9O1xuXG4gICAgeWllbGQqIGFzeW5jLnBvbGwoXG4gICAgICBhc3luYyAocG9sbEN0eDogUG9sbENvbnRleHQ8R2VuaWVNZXNzYWdlPikgPT4gdmFsaWRhdGVNZXNzYWdlKGF3YWl0IHBvbGxQcm9kdWNlcihwb2xsQ3R4KSksXG4gICAgICB7XG4gICAgICAgIGludGVydmFsTXM6IG9wdGlvbnM/LnBvbGxJbnRlcnZhbE1zID8/IDUwMCxcbiAgICAgICAgLy8gU2tpcCB5aWVsZGluZyBpZGVudGljYWwgY29uc2VjdXRpdmUgc25hcHNob3RzOyBHZW5pZSBvZnRlbiByZXR1cm5zXG4gICAgICAgIC8vIHRoZSBleGFjdCBzYW1lIHBheWxvYWQgdHdpY2UgZHVyaW5nIHF1aWV0IHBlcmlvZHMuIGBwb2xsYCBkb2VzIGEgZGVlcFxuICAgICAgICAvLyBlcXVhbCBvbiB0aGUgcHJldmlvdXMgeWllbGQuXG4gICAgICAgIGZpbHRlcjogXCJkaXN0aW5jdFwiLFxuICAgICAgICAvLyBTdG9wIGFmdGVyIHRoZSB0ZXJtaW5hbCBtZXNzYWdlIGlzIHlpZWxkZWQuIGBwb2xsYCBjaGVja3MgdGhlXG4gICAgICAgIC8vIHByZWRpY2F0ZSBBRlRFUiB5aWVsZGluZywgc28gdGhlIHRlcm1pbmFsIG1lc3NhZ2Ugc3RpbGwgcmVhY2hlcyB0aGVcbiAgICAgICAgLy8gY29uc3VtZXIuXG4gICAgICAgIHByZWRpY2F0ZTogKG0pID0+ICFnZW5pZU1vZGVsLmlzVGVybWluYWxTdGF0dXMobS5zdGF0dXMpLFxuICAgICAgICAvLyBXYWtlIHRoZSBpbnRlci1wb2xsIHNsZWVwIG9uIGFib3J0IHNvIGEgYGZvciBhd2FpdGAgYnJlYWsgKG9yXG4gICAgICAgIC8vIGV4dGVybmFsIGFib3J0KSB0ZWFycyBkb3duIHByb21wdGx5IGluc3RlYWQgb2Ygd2FpdGluZyBvdXQgdGhlXG4gICAgICAgIC8vIGludGVydmFsLlxuICAgICAgICBzaWduYWw6IGNvbnRyb2xsZXIuc2lnbmFsLFxuICAgICAgfSxcbiAgICApO1xuICB9IGZpbmFsbHkge1xuICAgIC8vIENhbmNlbHMgYW55IHN0aWxsLXBlbmRpbmcgU0RLIGNhbGwgYW5kIHRoZSBpbnRlci1wb2xsIHNsZWVwIHdoZXRoZXIgd2UncmVcbiAgICAvLyB1bndpbmRpbmcgZnJvbSBhIG5vcm1hbCByZXR1cm4sIGEgY29uc3VtZXIgYnJlYWssIG9yIGEgdGhyb3duIGVycm9yLlxuICAgIC8vIElkZW1wb3RlbnQuXG4gICAgY29udHJvbGxlci5hYm9ydCgpO1xuICB9XG59XG5cbi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gaGlnaC1sZXZlbDogZ2VuaWVFdmVudENoYXQgLS0tLS0tLS0tLS0tLS0tLS0tICovXG5cbi8qKlxuICogT25lIHR1cm4gYWdhaW5zdCBhIEdlbmllIHNwYWNlLCB5aWVsZGVkIGFzIGEgdHlwZWQge0BsaW5rIEdlbmllQ2hhdEV2ZW50fVxuICogc3RyZWFtLiBEcml2ZXMge0BsaW5rIGdlbmllQ2hhdH0gdW5kZXJuZWF0aCBhbmQgZGVjb3JhdGVzIGVhY2ggc25hcHNob3Qgd2l0aFxuICogdGhlIGRlcml2ZWQgZXZlbnRzIHRoZSBmaWVsZC1sZXZlbCBkaWZmIHByb2R1Y2VkLiBTdHJlYW0gb3JkZXI6XG4gKlxuICogICAxLiBgeyB0eXBlOiBcIm1lc3NhZ2VcIiwgbWVzc2FnZSB9YCAtIHRoZSByYXcgYEdlbmllTWVzc2FnZWAsIG9uY2UgcGVyIHBvbGxcbiAqICAgICAgeWllbGQuXG4gKiAgIDIuIGB7IHR5cGU6IFwicXVlc3Rpb25cIiwgY29udGVudCwgbWVzc2FnZV9pZCwgLi4uIH1gIGZpcmVzIGV4YWN0bHkgb25jZSwgb25cbiAqICAgICAgdGhlIEZJUlNUIGBtZXNzYWdlYCB5aWVsZC4gV2UgcmVhZCBgY29udGVudGAgYW5kIGBtZXNzYWdlX2lkYCBzdHJhaWdodFxuICogICAgICBvZmYgdGhlIHNuYXBzaG90IHNvIGV2ZXJ5IGRvd25zdHJlYW0gZXZlbnQgZm9yIHRoaXMgdHVybiBzaGFyZXMgdGhlIHNhbWVcbiAqICAgICAgYG1lc3NhZ2VfaWRgICh0aGUgcXVlc3Rpb24gaW5jbHVkZWQpIC0gc3Vic2NyaWJlcnMgY2FuIGdyb3VwIGV2ZXJ5dGhpbmdcbiAqICAgICAgZm9yIG9uZSBHZW5pZSBjYWxsIHVuZGVyIHRoYXQgb25lIGtleS5cbiAqICAgMy4gQW55IG9mIGBzdGF0dXNgIC8gYGF0dGFjaG1lbnRgIC8gYHRoaW5raW5nYCAvIGB0ZXh0YCAvIGBxdWVyeWAgL1xuICogICAgICBgc3RhdGVtZW50YCAvIGByb3dzYCAvIGBzdWdnZXN0ZWRfcXVlc3Rpb25zYCB0aGUgZGlmZiBhZ2FpbnN0IHRoZSBwcmlvclxuICogICAgICBzbmFwc2hvdCBwcm9kdWNlZC5cbiAqICAgNC4gT24gdGhlIHRlcm1pbmFsIHNuYXBzaG90LCBgeyB0eXBlOiBcInJlc3VsdFwiLCAuLi4gfWAgYXMgdGhlIGZpbmFsIHlpZWxkLlxuICpcbiAqIEVycm9ycyBwcm9wYWdhdGUgYnkgdGhlIGdlbmVyYXRvciB0aHJvd2luZyAtIHRoZXJlJ3Mgbm8gYFwiZXJyb3JcImAgdmFyaWFudC5cbiAqIFdyYXAgdGhlIGBmb3IgYXdhaXRgIGluIGB0cnkvY2F0Y2hgIGlmIHlvdSBuZWVkIHRvIGhhbmRsZSBmYWlsdXJlcy5cbiAqXG4gKiBAZXhhbXBsZVxuICogZm9yIGF3YWl0IChjb25zdCBldnQgb2YgZ2VuaWVFdmVudENoYXQoc3BhY2VJZCwgXCJUb3Agc3RvcmVzP1wiKSkge1xuICogICBzd2l0Y2ggKGV2dC50eXBlKSB7XG4gKiAgICAgY2FzZSBcInRoaW5raW5nXCI6XG4gKiAgICAgICBjb25zb2xlLmxvZyhcIlt0aGlua2luZ11cIiwgZXZ0LnRob3VnaHRfdHlwZSwgZXZ0LnRleHQpO1xuICogICAgICAgYnJlYWs7XG4gKiAgICAgY2FzZSBcInRleHRcIjpcbiAqICAgICAgIGNvbnNvbGUubG9nKFwiW3RleHRdXCIsIGV2dC50ZXh0KTtcbiAqICAgICAgIGJyZWFrO1xuICogICAgIGNhc2UgXCJyZXN1bHRcIjpcbiAqICAgICAgIGNvbnNvbGUubG9nKFwiW2RvbmVdXCIsIGV2dC5zdGF0dXMpO1xuICogICAgICAgYnJlYWs7XG4gKiAgIH1cbiAqIH1cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uKiBnZW5pZUV2ZW50Q2hhdChcbiAgc3BhY2VfaWQ6IHN0cmluZyxcbiAgY29udGVudDogc3RyaW5nLFxuICBvcHRpb25zPzogR2VuaWVDaGF0T3B0aW9ucyxcbik6IEFzeW5jR2VuZXJhdG9yPEdlbmllQ2hhdEV2ZW50LCB2b2lkLCB2b2lkPiB7XG4gIC8vIERpZmYgc291cmNlIGZvciB0aGUgY3VycmVudCB0dXJuLiBBbHdheXMgYHVuZGVmaW5lZGAgb24gdGhlIGZpcnN0IHNuYXBzaG90XG4gIC8vIHNvIHRoZSBpbml0aWFsIHN0YXR1cyAvIGF0dGFjaG1lbnRzIGVtaXQgZnJlc2g7IHVwZGF0ZWQgdG8gdGhlIG1vc3QgcmVjZW50XG4gIC8vIHNuYXBzaG90IGFmdGVyIGVhY2ggeWllbGQuXG4gIGxldCBwcmV2aW91czogR2VuaWVNZXNzYWdlIHwgdW5kZWZpbmVkO1xuICAvLyBUaGUgYHF1ZXN0aW9uYCBldmVudCBpcyBkZWZlcnJlZCB0byB0aGUgZmlyc3QgYG1lc3NhZ2VgIHlpZWxkIHNvIGl0IGNhblxuICAvLyBjYXJyeSB0aGUgYXNzaWduZWQgYG1lc3NhZ2VfaWRgIChzdWJzY3JpYmVycyB1c2UgaXQgYXMgdGhlIGdyb3VwaW5nIGtleSBmb3JcbiAgLy8gZXZlcnkgZXZlbnQgaW4gdGhpcyB0dXJuKS4gVGhlIGZpcnN0IHNuYXBzaG90IGlzIHRoZSBlYXJsaWVzdCBwb2ludCB0aGF0IGlkXG4gIC8vIGV4aXN0cy5cbiAgbGV0IHF1ZXN0aW9uRW1pdHRlZCA9IGZhbHNlO1xuICBmb3IgYXdhaXQgKGNvbnN0IHJhd01lc3NhZ2Ugb2YgZ2VuaWVDaGF0KHNwYWNlX2lkLCBjb250ZW50LCBvcHRpb25zKSkge1xuICAgIC8vIE5vcm1hbGl6ZSBgbWVzc2FnZV9pZGAgZnJvbSB0aGUgbGVnYWN5IGBpZGAgZmllbGQgd2hlbiBHZW5pZSdzIHdpcmVcbiAgICAvLyByZXNwb25zZSBvbmx5IHBvcHVsYXRlcyBvbmUgb2YgdGhlbS4gVGhlIFNESyBzY2hlbWEgbWFya3MgYm90aCBhc1xuICAgIC8vIHJlcXVpcmVkLCBidXQgaW4gcHJhY3RpY2UgdGhlIGBzdGFydENvbnZlcnNhdGlvbmAgLyBgY3JlYXRlTWVzc2FnZWAgaW5uZXJcbiAgICAvLyBgbWVzc2FnZWAgcGF5bG9hZCBzb21ldGltZXMgc2hpcHMgb25seSBgaWRgIHdoaWxlIHRoZSBuZXcgYG1lc3NhZ2VfaWRgXG4gICAgLy8gZmllbGQgbGFuZHMgdW5kZWZpbmVkLiBFdmVyeSBkb3duc3RyZWFtIGV2ZW50IGRldGVjdG9yIGtleXMgZ3JvdXBpbmcgb2ZmXG4gICAgLy8gYG1lc3NhZ2VfaWRgOyB0aGUgZmFsbGJhY2sga2VlcHMgb25lIEdlbmllIHR1cm4ncyBldmVudHMgZnJvbSBzcGxpdHRpbmdcbiAgICAvLyBhY3Jvc3MgYW4gYW5vbiBncm91cCArIHRoZSByZWFsLWlkIGdyb3VwIHdoZW4gc3Vic2NyaWJlcnMgYnVja2V0IGJ5XG4gICAgLy8gYG1lc3NhZ2VfaWRgLlxuICAgIGNvbnN0IG1lc3NhZ2U6IEdlbmllTWVzc2FnZSA9IHJhd01lc3NhZ2UubWVzc2FnZV9pZFxuICAgICAgPyByYXdNZXNzYWdlXG4gICAgICA6IHsgLi4ucmF3TWVzc2FnZSwgbWVzc2FnZV9pZDogcmF3TWVzc2FnZS5pZCB9O1xuICAgIHlpZWxkIHtcbiAgICAgIHR5cGU6IFwibWVzc2FnZVwiLFxuICAgICAgc3BhY2VfaWQ6IG1lc3NhZ2Uuc3BhY2VfaWQsXG4gICAgICBtZXNzYWdlX2lkOiBtZXNzYWdlLm1lc3NhZ2VfaWQsXG4gICAgICBtZXNzYWdlLFxuICAgIH07XG4gICAgaWYgKCFxdWVzdGlvbkVtaXR0ZWQpIHtcbiAgICAgIHlpZWxkIHtcbiAgICAgICAgdHlwZTogXCJxdWVzdGlvblwiLFxuICAgICAgICBzcGFjZV9pZDogbWVzc2FnZS5zcGFjZV9pZCxcbiAgICAgICAgLi4uKG1lc3NhZ2UuY29udmVyc2F0aW9uX2lkID8geyBjb252ZXJzYXRpb25faWQ6IG1lc3NhZ2UuY29udmVyc2F0aW9uX2lkIH0gOiB7fSksXG4gICAgICAgIC4uLihtZXNzYWdlLm1lc3NhZ2VfaWQgPyB7IG1lc3NhZ2VfaWQ6IG1lc3NhZ2UubWVzc2FnZV9pZCB9IDoge30pLFxuICAgICAgICBjb250ZW50OiBtZXNzYWdlLmNvbnRlbnQsXG4gICAgICB9O1xuICAgICAgcXVlc3Rpb25FbWl0dGVkID0gdHJ1ZTtcbiAgICB9XG4gICAgeWllbGQqIGV2ZW50LmV2ZW50c0Zyb21NZXNzYWdlKG1lc3NhZ2UsIHByZXZpb3VzLCBtZXNzYWdlLnNwYWNlX2lkKTtcbiAgICBjb25zdCBzdGF0dXMgPSBtZXNzYWdlLnN0YXR1cztcbiAgICBpZiAoZ2VuaWVNb2RlbC5pc1Rlcm1pbmFsU3RhdHVzKHN0YXR1cykpIHtcbiAgICAgIHlpZWxkIHtcbiAgICAgICAgdHlwZTogXCJyZXN1bHRcIixcbiAgICAgICAgc3BhY2VfaWQ6IG1lc3NhZ2Uuc3BhY2VfaWQsXG4gICAgICAgIGNvbnZlcnNhdGlvbl9pZDogbWVzc2FnZS5jb252ZXJzYXRpb25faWQsXG4gICAgICAgIG1lc3NhZ2VfaWQ6IG1lc3NhZ2UubWVzc2FnZV9pZCxcbiAgICAgICAgc3RhdHVzLFxuICAgICAgICBtZXNzYWdlLFxuICAgICAgfTtcbiAgICB9XG4gICAgcHJldmlvdXMgPSBtZXNzYWdlO1xuICB9XG59XG5cbi8qIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0gd29ya3NwYWNlIGNsaWVudCBoZWxwZXIgLS0tLS0tLS0tLS0tLS0tLS0tLS0tICovXG5cbi8qKlxuICogUmVzb2x2ZSBhIGBXb3Jrc3BhY2VDbGllbnRgIGluIHRoaXMgcHJlZmVyZW5jZSBvcmRlcjpcbiAqXG4gKiAgIDEuIENhbGxlci1zdXBwbGllZCBgb3B0aW9ucy53b3Jrc3BhY2VDbGllbnRgLlxuICogICAyLiBBcHBLaXQncyBwZXItcmVxdWVzdCBleGVjdXRpb24tY29udGV4dCBjbGllbnQsIHdoZW4gQXBwS2l0IGlzIGluc3RhbGxlZFxuICogICAgICBBTkQgd2UncmUgaW5zaWRlIGEgcmVxdWVzdCBzY29wZS5cbiAqICAgMy4gRnJlc2ggYG5ldyBXb3Jrc3BhY2VDbGllbnQoe30pYCAoZW52LXZhciBhdXRoIHZpYVxuICogICAgICBgREFUQUJSSUNLU19DT05GSUdfUFJPRklMRWAgLyBgREFUQUJSSUNLU19IT1NUYCAvIGBEQVRBQlJJQ0tTX1RPS0VOYCkuXG4gKlxuICogQXBwS2l0IGlzIGxvYWRlZCBsYXppbHkgc28gdGhpcyBwYWNrYWdlIHN0YXlzIHVzYWJsZSBpbiBub24tQXBwS2l0XG4gKiBlbnZpcm9ubWVudHMuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIGdldFdvcmtzcGFjZUNsaWVudChvcHRpb25zPzogR2VuaWVDaGF0T3B0aW9ucyk6IFByb21pc2U8V29ya3NwYWNlQ2xpZW50PiB7XG4gIGlmIChvcHRpb25zPy53b3Jrc3BhY2VDbGllbnQpIHJldHVybiBvcHRpb25zLndvcmtzcGFjZUNsaWVudDtcbiAgY29uc3QgYXBwa2l0ID0gYXdhaXQgZ2V0QXBwS2l0KCk7XG4gIGlmIChhcHBraXQpIHtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGFwcGtpdC5nZXRFeGVjdXRpb25Db250ZXh0KCkuY2xpZW50O1xuICAgIH0gY2F0Y2gge1xuICAgICAgLy8gTm90IGluc2lkZSBhbiBBcHBLaXQgcmVxdWVzdCBjb250ZXh0OyBmYWxsIHRocm91Z2ggdG8gZW52LlxuICAgIH1cbiAgfVxuICByZXR1cm4gbmV3IFdvcmtzcGFjZUNsaWVudCh7fSk7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldEFwcEtpdCgpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gYXdhaXQgaW1wb3J0KFwiQGRhdGFicmlja3MvYXBwa2l0XCIpO1xuICB9IGNhdGNoIHtcbiAgICByZXR1cm4gdW5kZWZpbmVkO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Genie space metadata helpers.
3
+ *
4
+ * Fetches a Genie space's definition (including the opt-in `serialized_space`
5
+ * blob) and extracts the curated starter questions an author configured on the
6
+ * space. The typed SDK `client.genie.getSpace` only returns the
7
+ * directory-listing surface (`title` / `description` / `warehouse_id`); the
8
+ * sample questions live inside `serialized_space`, which the REST API returns
9
+ * only when `include_serialized_space=true`. We hit that endpoint through the
10
+ * workspace client's raw `apiClient` since the typed request shape has no flag
11
+ * for it.
12
+ *
13
+ * @module
14
+ */
15
+ import { WorkspaceClient } from "@databricks/sdk-experimental";
16
+ import { databricks } from "@dbx-tools/appkit";
17
+ import { type GenieSpace } from "@dbx-tools/shared-genie";
18
+ /** Options for {@link getGenieSpace}. */
19
+ export interface GetGenieSpaceOptions {
20
+ /**
21
+ * Explicit `WorkspaceClient`. Defaults to a fresh `new WorkspaceClient({})`
22
+ * (env-var auth). Server callers should pass their OBO-scoped client so the
23
+ * lookup runs as the user.
24
+ */
25
+ workspaceClient?: WorkspaceClient;
26
+ /**
27
+ * Request the `serialized_space` blob (catalogs, tables, sample questions,
28
+ * prompts). Defaults to `true` - the only reason to skip it is when the
29
+ * caller just needs title / description and wants the smaller payload.
30
+ */
31
+ serialized?: boolean;
32
+ /**
33
+ * External cancellation. Accepts a WHATWG `AbortSignal` or a fully-built SDK
34
+ * `Context` (see `databricks.ContextLike`).
35
+ */
36
+ context?: databricks.ContextLike;
37
+ }
38
+ /**
39
+ * Fetch a Genie space by id, optionally including its serialized definition.
40
+ * Hits `GET /api/2.0/genie/spaces/<id>` with `include_serialized_space=true`
41
+ * through the raw `apiClient`, then validates the response against
42
+ * {@link GenieSpaceSchema} (unknown fields like `etag` /
43
+ * `parent_path` are stripped).
44
+ */
45
+ export declare function getGenieSpace(spaceId: string, options?: GetGenieSpaceOptions): Promise<GenieSpace>;
46
+ /**
47
+ * Extract the curated starter questions an author configured on a Genie space.
48
+ * Reads `serialized_space -> config.sample_questions[*].question`. Returns `[]`
49
+ * when the space carries no serialized blob, the blob is unparseable, or no
50
+ * sample questions are configured - so a missing or misconfigured space
51
+ * degrades to "no suggestions" rather than throwing. Order is preserved (the
52
+ * author's ordering) and duplicates are dropped.
53
+ */
54
+ export declare function genieSampleQuestions(space: GenieSpace): string[];
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Genie space metadata helpers.
3
+ *
4
+ * Fetches a Genie space's definition (including the opt-in `serialized_space`
5
+ * blob) and extracts the curated starter questions an author configured on the
6
+ * space. The typed SDK `client.genie.getSpace` only returns the
7
+ * directory-listing surface (`title` / `description` / `warehouse_id`); the
8
+ * sample questions live inside `serialized_space`, which the REST API returns
9
+ * only when `include_serialized_space=true`. We hit that endpoint through the
10
+ * workspace client's raw `apiClient` since the typed request shape has no flag
11
+ * for it.
12
+ *
13
+ * @module
14
+ */
15
+ import { WorkspaceClient } from "@databricks/sdk-experimental";
16
+ import { databricks } from "@dbx-tools/appkit";
17
+ import { json, log, object, string } from "@dbx-tools/shared-core";
18
+ import { genieModel } from "@dbx-tools/shared-genie";
19
+ const logger = log.logger("genie/space");
20
+ /**
21
+ * Fetch a Genie space by id, optionally including its serialized definition.
22
+ * Hits `GET /api/2.0/genie/spaces/<id>` with `include_serialized_space=true`
23
+ * through the raw `apiClient`, then validates the response against
24
+ * {@link GenieSpaceSchema} (unknown fields like `etag` /
25
+ * `parent_path` are stripped).
26
+ */
27
+ export async function getGenieSpace(spaceId, options) {
28
+ const client = options?.workspaceClient ?? new WorkspaceClient({});
29
+ const serialized = options?.serialized !== false;
30
+ const ctx = options?.context ? databricks.toContext(options.context) : undefined;
31
+ const raw = await client.apiClient.request({
32
+ path: `/api/2.0/genie/spaces/${encodeURIComponent(spaceId)}`,
33
+ method: "GET",
34
+ query: serialized ? { include_serialized_space: true } : {},
35
+ headers: new Headers(),
36
+ raw: false,
37
+ }, ctx);
38
+ return genieModel.GenieSpaceSchema.parse(raw);
39
+ }
40
+ /**
41
+ * Extract the curated starter questions an author configured on a Genie space.
42
+ * Reads `serialized_space -> config.sample_questions[*].question`. Returns `[]`
43
+ * when the space carries no serialized blob, the blob is unparseable, or no
44
+ * sample questions are configured - so a missing or misconfigured space
45
+ * degrades to "no suggestions" rather than throwing. Order is preserved (the
46
+ * author's ordering) and duplicates are dropped.
47
+ */
48
+ export function genieSampleQuestions(space) {
49
+ const serialized = space.serialized_space;
50
+ if (!serialized)
51
+ return [];
52
+ const parsed = json.parse(serialized);
53
+ if (parsed === undefined) {
54
+ logger.warn("serialized-space:parse-error", { spaceId: space.space_id });
55
+ return [];
56
+ }
57
+ const sampleQuestions = parsed?.config
58
+ ?.sample_questions;
59
+ if (!Array.isArray(sampleQuestions))
60
+ return [];
61
+ return [
62
+ ...object
63
+ .sequence(sampleQuestions)
64
+ .map((entry) => string.firstNonEmpty(entry?.question))
65
+ .nonNull()
66
+ .distinct(),
67
+ ];
68
+ }
69
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BhY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc3BhY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7R0FhRztBQUVILE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUMvRCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDL0MsT0FBTyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ25FLE9BQU8sRUFBRSxVQUFVLEVBQW1CLE1BQU0seUJBQXlCLENBQUM7QUFFdEUsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQztBQXVCekM7Ozs7OztHQU1HO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxhQUFhLENBQ2pDLE9BQWUsRUFDZixPQUE4QjtJQUU5QixNQUFNLE1BQU0sR0FBRyxPQUFPLEVBQUUsZUFBZSxJQUFJLElBQUksZUFBZSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ25FLE1BQU0sVUFBVSxHQUFHLE9BQU8sRUFBRSxVQUFVLEtBQUssS0FBSyxDQUFDO0lBQ2pELE1BQU0sR0FBRyxHQUFHLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUM7SUFDakYsTUFBTSxHQUFHLEdBQUcsTUFBTSxNQUFNLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FDeEM7UUFDRSxJQUFJLEVBQUUseUJBQXlCLGtCQUFrQixDQUFDLE9BQU8sQ0FBQyxFQUFFO1FBQzVELE1BQU0sRUFBRSxLQUFLO1FBQ2IsS0FBSyxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUMsRUFBRSx3QkFBd0IsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRTtRQUMzRCxPQUFPLEVBQUUsSUFBSSxPQUFPLEVBQUU7UUFDdEIsR0FBRyxFQUFFLEtBQUs7S0FDWCxFQUNELEdBQUcsQ0FDSixDQUFDO0lBQ0YsT0FBTyxVQUFVLENBQUMsZ0JBQWdCLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQ2hELENBQUM7QUFZRDs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxVQUFVLG9CQUFvQixDQUFDLEtBQWlCO0lBQ3BELE1BQU0sVUFBVSxHQUFHLEtBQUssQ0FBQyxnQkFBZ0IsQ0FBQztJQUMxQyxJQUFJLENBQUMsVUFBVTtRQUFFLE9BQU8sRUFBRSxDQUFDO0lBQzNCLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLENBQUM7SUFDdEMsSUFBSSxNQUFNLEtBQUssU0FBUyxFQUFFLENBQUM7UUFDekIsTUFBTSxDQUFDLElBQUksQ0FBQyw4QkFBOEIsRUFBRSxFQUFFLE9BQU8sRUFBRSxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztRQUN6RSxPQUFPLEVBQUUsQ0FBQztJQUNaLENBQUM7SUFDRCxNQUFNLGVBQWUsR0FBSSxNQUE2RCxFQUFFLE1BQU07UUFDNUYsRUFBRSxnQkFBZ0IsQ0FBQztJQUNyQixJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxlQUFlLENBQUM7UUFBRSxPQUFPLEVBQUUsQ0FBQztJQUUvQyxPQUFPO1FBQ0wsR0FBRyxNQUFNO2FBQ04sUUFBUSxDQUFDLGVBQTZDLENBQUM7YUFDdkQsR0FBRyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxRQUFRLENBQUMsQ0FBQzthQUNyRCxPQUFPLEVBQUU7YUFDVCxRQUFRLEVBQUU7S0FDZCxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogR2VuaWUgc3BhY2UgbWV0YWRhdGEgaGVscGVycy5cbiAqXG4gKiBGZXRjaGVzIGEgR2VuaWUgc3BhY2UncyBkZWZpbml0aW9uIChpbmNsdWRpbmcgdGhlIG9wdC1pbiBgc2VyaWFsaXplZF9zcGFjZWBcbiAqIGJsb2IpIGFuZCBleHRyYWN0cyB0aGUgY3VyYXRlZCBzdGFydGVyIHF1ZXN0aW9ucyBhbiBhdXRob3IgY29uZmlndXJlZCBvbiB0aGVcbiAqIHNwYWNlLiBUaGUgdHlwZWQgU0RLIGBjbGllbnQuZ2VuaWUuZ2V0U3BhY2VgIG9ubHkgcmV0dXJucyB0aGVcbiAqIGRpcmVjdG9yeS1saXN0aW5nIHN1cmZhY2UgKGB0aXRsZWAgLyBgZGVzY3JpcHRpb25gIC8gYHdhcmVob3VzZV9pZGApOyB0aGVcbiAqIHNhbXBsZSBxdWVzdGlvbnMgbGl2ZSBpbnNpZGUgYHNlcmlhbGl6ZWRfc3BhY2VgLCB3aGljaCB0aGUgUkVTVCBBUEkgcmV0dXJuc1xuICogb25seSB3aGVuIGBpbmNsdWRlX3NlcmlhbGl6ZWRfc3BhY2U9dHJ1ZWAuIFdlIGhpdCB0aGF0IGVuZHBvaW50IHRocm91Z2ggdGhlXG4gKiB3b3Jrc3BhY2UgY2xpZW50J3MgcmF3IGBhcGlDbGllbnRgIHNpbmNlIHRoZSB0eXBlZCByZXF1ZXN0IHNoYXBlIGhhcyBubyBmbGFnXG4gKiBmb3IgaXQuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IFdvcmtzcGFjZUNsaWVudCB9IGZyb20gXCJAZGF0YWJyaWNrcy9zZGstZXhwZXJpbWVudGFsXCI7XG5pbXBvcnQgeyBkYXRhYnJpY2tzIH0gZnJvbSBcIkBkYngtdG9vbHMvYXBwa2l0XCI7XG5pbXBvcnQgeyBqc29uLCBsb2csIG9iamVjdCwgc3RyaW5nIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7IGdlbmllTW9kZWwsIHR5cGUgR2VuaWVTcGFjZSB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1nZW5pZVwiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwiZ2VuaWUvc3BhY2VcIik7XG5cbi8qKiBPcHRpb25zIGZvciB7QGxpbmsgZ2V0R2VuaWVTcGFjZX0uICovXG5leHBvcnQgaW50ZXJmYWNlIEdldEdlbmllU3BhY2VPcHRpb25zIHtcbiAgLyoqXG4gICAqIEV4cGxpY2l0IGBXb3Jrc3BhY2VDbGllbnRgLiBEZWZhdWx0cyB0byBhIGZyZXNoIGBuZXcgV29ya3NwYWNlQ2xpZW50KHt9KWBcbiAgICogKGVudi12YXIgYXV0aCkuIFNlcnZlciBjYWxsZXJzIHNob3VsZCBwYXNzIHRoZWlyIE9CTy1zY29wZWQgY2xpZW50IHNvIHRoZVxuICAgKiBsb29rdXAgcnVucyBhcyB0aGUgdXNlci5cbiAgICovXG4gIHdvcmtzcGFjZUNsaWVudD86IFdvcmtzcGFjZUNsaWVudDtcbiAgLyoqXG4gICAqIFJlcXVlc3QgdGhlIGBzZXJpYWxpemVkX3NwYWNlYCBibG9iIChjYXRhbG9ncywgdGFibGVzLCBzYW1wbGUgcXVlc3Rpb25zLFxuICAgKiBwcm9tcHRzKS4gRGVmYXVsdHMgdG8gYHRydWVgIC0gdGhlIG9ubHkgcmVhc29uIHRvIHNraXAgaXQgaXMgd2hlbiB0aGVcbiAgICogY2FsbGVyIGp1c3QgbmVlZHMgdGl0bGUgLyBkZXNjcmlwdGlvbiBhbmQgd2FudHMgdGhlIHNtYWxsZXIgcGF5bG9hZC5cbiAgICovXG4gIHNlcmlhbGl6ZWQ/OiBib29sZWFuO1xuICAvKipcbiAgICogRXh0ZXJuYWwgY2FuY2VsbGF0aW9uLiBBY2NlcHRzIGEgV0hBVFdHIGBBYm9ydFNpZ25hbGAgb3IgYSBmdWxseS1idWlsdCBTREtcbiAgICogYENvbnRleHRgIChzZWUgYGRhdGFicmlja3MuQ29udGV4dExpa2VgKS5cbiAgICovXG4gIGNvbnRleHQ/OiBkYXRhYnJpY2tzLkNvbnRleHRMaWtlO1xufVxuXG4vKipcbiAqIEZldGNoIGEgR2VuaWUgc3BhY2UgYnkgaWQsIG9wdGlvbmFsbHkgaW5jbHVkaW5nIGl0cyBzZXJpYWxpemVkIGRlZmluaXRpb24uXG4gKiBIaXRzIGBHRVQgL2FwaS8yLjAvZ2VuaWUvc3BhY2VzLzxpZD5gIHdpdGggYGluY2x1ZGVfc2VyaWFsaXplZF9zcGFjZT10cnVlYFxuICogdGhyb3VnaCB0aGUgcmF3IGBhcGlDbGllbnRgLCB0aGVuIHZhbGlkYXRlcyB0aGUgcmVzcG9uc2UgYWdhaW5zdFxuICoge0BsaW5rIEdlbmllU3BhY2VTY2hlbWF9ICh1bmtub3duIGZpZWxkcyBsaWtlIGBldGFnYCAvXG4gKiBgcGFyZW50X3BhdGhgIGFyZSBzdHJpcHBlZCkuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRHZW5pZVNwYWNlKFxuICBzcGFjZUlkOiBzdHJpbmcsXG4gIG9wdGlvbnM/OiBHZXRHZW5pZVNwYWNlT3B0aW9ucyxcbik6IFByb21pc2U8R2VuaWVTcGFjZT4ge1xuICBjb25zdCBjbGllbnQgPSBvcHRpb25zPy53b3Jrc3BhY2VDbGllbnQgPz8gbmV3IFdvcmtzcGFjZUNsaWVudCh7fSk7XG4gIGNvbnN0IHNlcmlhbGl6ZWQgPSBvcHRpb25zPy5zZXJpYWxpemVkICE9PSBmYWxzZTtcbiAgY29uc3QgY3R4ID0gb3B0aW9ucz8uY29udGV4dCA/IGRhdGFicmlja3MudG9Db250ZXh0KG9wdGlvbnMuY29udGV4dCkgOiB1bmRlZmluZWQ7XG4gIGNvbnN0IHJhdyA9IGF3YWl0IGNsaWVudC5hcGlDbGllbnQucmVxdWVzdChcbiAgICB7XG4gICAgICBwYXRoOiBgL2FwaS8yLjAvZ2VuaWUvc3BhY2VzLyR7ZW5jb2RlVVJJQ29tcG9uZW50KHNwYWNlSWQpfWAsXG4gICAgICBtZXRob2Q6IFwiR0VUXCIsXG4gICAgICBxdWVyeTogc2VyaWFsaXplZCA/IHsgaW5jbHVkZV9zZXJpYWxpemVkX3NwYWNlOiB0cnVlIH0gOiB7fSxcbiAgICAgIGhlYWRlcnM6IG5ldyBIZWFkZXJzKCksXG4gICAgICByYXc6IGZhbHNlLFxuICAgIH0sXG4gICAgY3R4LFxuICApO1xuICByZXR1cm4gZ2VuaWVNb2RlbC5HZW5pZVNwYWNlU2NoZW1hLnBhcnNlKHJhdyk7XG59XG5cbi8qKlxuICogT25lIGVudHJ5IGluIGEgc2VyaWFsaXplZCBzcGFjZSdzIGBjb25maWcuc2FtcGxlX3F1ZXN0aW9uc2AuIFRoZVxuICogYXV0aG9yLWZhY2luZyBmaWVsZCBpcyBgcXVlc3Rpb25gLCB3aGljaCB0aGUgd2lyZSBmb3JtYXQgbW9kZWxzIGFzIGEgc3RyaW5nXG4gKiBhcnJheSAoYSBzaW5nbGUgbXVsdGktbGluZSBxdWVzdGlvbiBpcyBzcGxpdCBhY3Jvc3MgZW50cmllcyk7IHdlIHRyZWF0IHRoZVxuICogZmlyc3Qgbm9uLWVtcHR5IGVudHJ5IGFzIHRoZSBkaXNwbGF5YWJsZSBxdWVzdGlvbiB0ZXh0LlxuICovXG5pbnRlcmZhY2UgU2VyaWFsaXplZFNhbXBsZVF1ZXN0aW9uIHtcbiAgcXVlc3Rpb24/OiB1bmtub3duO1xufVxuXG4vKipcbiAqIEV4dHJhY3QgdGhlIGN1cmF0ZWQgc3RhcnRlciBxdWVzdGlvbnMgYW4gYXV0aG9yIGNvbmZpZ3VyZWQgb24gYSBHZW5pZSBzcGFjZS5cbiAqIFJlYWRzIGBzZXJpYWxpemVkX3NwYWNlIC0+IGNvbmZpZy5zYW1wbGVfcXVlc3Rpb25zWypdLnF1ZXN0aW9uYC4gUmV0dXJucyBgW11gXG4gKiB3aGVuIHRoZSBzcGFjZSBjYXJyaWVzIG5vIHNlcmlhbGl6ZWQgYmxvYiwgdGhlIGJsb2IgaXMgdW5wYXJzZWFibGUsIG9yIG5vXG4gKiBzYW1wbGUgcXVlc3Rpb25zIGFyZSBjb25maWd1cmVkIC0gc28gYSBtaXNzaW5nIG9yIG1pc2NvbmZpZ3VyZWQgc3BhY2VcbiAqIGRlZ3JhZGVzIHRvIFwibm8gc3VnZ2VzdGlvbnNcIiByYXRoZXIgdGhhbiB0aHJvd2luZy4gT3JkZXIgaXMgcHJlc2VydmVkICh0aGVcbiAqIGF1dGhvcidzIG9yZGVyaW5nKSBhbmQgZHVwbGljYXRlcyBhcmUgZHJvcHBlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdlbmllU2FtcGxlUXVlc3Rpb25zKHNwYWNlOiBHZW5pZVNwYWNlKTogc3RyaW5nW10ge1xuICBjb25zdCBzZXJpYWxpemVkID0gc3BhY2Uuc2VyaWFsaXplZF9zcGFjZTtcbiAgaWYgKCFzZXJpYWxpemVkKSByZXR1cm4gW107XG4gIGNvbnN0IHBhcnNlZCA9IGpzb24ucGFyc2Uoc2VyaWFsaXplZCk7XG4gIGlmIChwYXJzZWQgPT09IHVuZGVmaW5lZCkge1xuICAgIGxvZ2dlci53YXJuKFwic2VyaWFsaXplZC1zcGFjZTpwYXJzZS1lcnJvclwiLCB7IHNwYWNlSWQ6IHNwYWNlLnNwYWNlX2lkIH0pO1xuICAgIHJldHVybiBbXTtcbiAgfVxuICBjb25zdCBzYW1wbGVRdWVzdGlvbnMgPSAocGFyc2VkIGFzIHsgY29uZmlnPzogeyBzYW1wbGVfcXVlc3Rpb25zPzogdW5rbm93biB9IH0gfCBudWxsKT8uY29uZmlnXG4gICAgPy5zYW1wbGVfcXVlc3Rpb25zO1xuICBpZiAoIUFycmF5LmlzQXJyYXkoc2FtcGxlUXVlc3Rpb25zKSkgcmV0dXJuIFtdO1xuXG4gIHJldHVybiBbXG4gICAgLi4ub2JqZWN0XG4gICAgICAuc2VxdWVuY2Uoc2FtcGxlUXVlc3Rpb25zIGFzIFNlcmlhbGl6ZWRTYW1wbGVRdWVzdGlvbltdKVxuICAgICAgLm1hcCgoZW50cnkpID0+IHN0cmluZy5maXJzdE5vbkVtcHR5KGVudHJ5Py5xdWVzdGlvbikpXG4gICAgICAubm9uTnVsbCgpXG4gICAgICAuZGlzdGluY3QoKSxcbiAgXTtcbn1cbiJdfQ==
@@ -0,0 +1 @@
1
+ {"root":["../src/chat.ts","../src/space.ts","../index.ts"],"version":"5.9.3"}
package/package.json CHANGED
@@ -16,25 +16,29 @@
16
16
  },
17
17
  "dependencies": {
18
18
  "@databricks/sdk-experimental": "^0.17.0",
19
- "@dbx-tools/appkit": "0.3.43",
20
- "@dbx-tools/shared-genie": "0.3.43",
21
- "@dbx-tools/shared-core": "0.3.43"
19
+ "@dbx-tools/appkit": "0.4.0",
20
+ "@dbx-tools/shared-core": "0.4.0",
21
+ "@dbx-tools/shared-genie": "0.4.0"
22
22
  },
23
- "main": "index.ts",
23
+ "main": "./lib/index.js",
24
24
  "license": "UNLICENSED",
25
25
  "publishConfig": {
26
26
  "access": "public"
27
27
  },
28
- "version": "0.3.43",
29
- "types": "index.ts",
28
+ "version": "0.4.0",
29
+ "types": "./lib/index.d.ts",
30
30
  "type": "module",
31
31
  "exports": {
32
- ".": "./index.ts",
32
+ ".": {
33
+ "types": "./lib/index.d.ts",
34
+ "default": "./lib/index.js"
35
+ },
33
36
  "./package.json": "./package.json"
34
37
  },
35
38
  "files": [
36
39
  "index.ts",
37
- "src"
40
+ "src",
41
+ "lib"
38
42
  ],
39
43
  "peerDependenciesMeta": {
40
44
  "@databricks/appkit": {