@dbx-tools/genie 0.1.34 → 0.1.35

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/dist/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * `@dbx-tools/genie` public surface.
3
3
  *
4
- * Bundles the package's Node-side chat driver with a re-export of
5
- * the pure `@dbx-tools/genie-shared` wire vocabulary so a single
4
+ * Bundles the package's Node-side drivers (live chat plus space
5
+ * metadata / curated-question lookup) with a re-export of the pure
6
+ * `@dbx-tools/genie-shared` wire vocabulary so a single
6
7
  * `from "@dbx-tools/genie"` import serves server-side consumers
7
8
  * that need both the live driver and the protocol types.
8
9
  *
@@ -13,3 +14,4 @@
13
14
  */
14
15
  export * from "@dbx-tools/genie-shared";
15
16
  export * from "./src/chat.js";
17
+ export * from "./src/space.js";
package/dist/index.js CHANGED
@@ -1,8 +1,9 @@
1
1
  /**
2
2
  * `@dbx-tools/genie` public surface.
3
3
  *
4
- * Bundles the package's Node-side chat driver with a re-export of
5
- * the pure `@dbx-tools/genie-shared` wire vocabulary so a single
4
+ * Bundles the package's Node-side drivers (live chat plus space
5
+ * metadata / curated-question lookup) with a re-export of the pure
6
+ * `@dbx-tools/genie-shared` wire vocabulary so a single
6
7
  * `from "@dbx-tools/genie"` import serves server-side consumers
7
8
  * that need both the live driver and the protocol types.
8
9
  *
@@ -13,3 +14,4 @@
13
14
  */
14
15
  export * from "@dbx-tools/genie-shared";
15
16
  export * from "./src/chat.js";
17
+ export * from "./src/space.js";
@@ -0,0 +1,55 @@
1
+ /**
2
+ * `@dbx-tools/genie` space metadata helpers.
3
+ *
4
+ * Fetches a Genie space's definition (including the opt-in
5
+ * `serialized_space` blob) and extracts the curated starter
6
+ * questions an author configured on the space. The typed SDK
7
+ * `client.genie.getSpace` only returns the directory-listing surface
8
+ * (`title` / `description` / `warehouse_id`); the sample questions
9
+ * live inside `serialized_space`, which the REST API returns only
10
+ * when `include_serialized_space=true`. We hit that endpoint through
11
+ * the workspace client's raw `apiClient` since the typed request
12
+ * shape has no flag for it.
13
+ */
14
+ import { WorkspaceClient } from "@databricks/sdk-experimental";
15
+ import { type GenieSpace } from "@dbx-tools/genie-shared";
16
+ import { apiUtils } from "@dbx-tools/shared";
17
+ /** Options for {@link getGenieSpace}. */
18
+ export interface GetGenieSpaceOptions {
19
+ /**
20
+ * Explicit `WorkspaceClient`. Defaults to a fresh
21
+ * `new WorkspaceClient({})` (env-var auth). Server callers should
22
+ * pass their OBO-scoped client so the lookup runs as the user.
23
+ */
24
+ workspaceClient?: WorkspaceClient;
25
+ /**
26
+ * Request the `serialized_space` blob (catalogs, tables, sample
27
+ * questions, prompts). Defaults to `true` - the only reason to
28
+ * skip it is when the caller just needs title / description and
29
+ * wants the smaller payload.
30
+ */
31
+ serialized?: boolean;
32
+ /**
33
+ * External cancellation. Accepts a WHATWG `AbortSignal` or a
34
+ * fully-built SDK `Context` (see `apiUtils.ContextLike`).
35
+ */
36
+ context?: apiUtils.ContextLike;
37
+ }
38
+ /**
39
+ * Fetch a Genie space by id, optionally including its serialized
40
+ * definition. Hits `GET /api/2.0/genie/spaces/<id>` with
41
+ * `include_serialized_space=true` through the raw `apiClient`, then
42
+ * validates the response against {@link GenieSpaceSchema} (unknown
43
+ * fields like `etag` / `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
48
+ * Genie space. Reads `serialized_space -> config.sample_questions[*]
49
+ * .question`. Returns `[]` when the space carries no serialized blob,
50
+ * the blob is unparseable, or no sample questions are configured -
51
+ * so a missing or misconfigured space degrades to "no suggestions"
52
+ * rather than throwing. Order is preserved (the author's ordering)
53
+ * and duplicates are dropped.
54
+ */
55
+ export declare function genieSampleQuestions(space: GenieSpace): string[];
@@ -0,0 +1,90 @@
1
+ /**
2
+ * `@dbx-tools/genie` space metadata helpers.
3
+ *
4
+ * Fetches a Genie space's definition (including the opt-in
5
+ * `serialized_space` blob) and extracts the curated starter
6
+ * questions an author configured on the space. The typed SDK
7
+ * `client.genie.getSpace` only returns the directory-listing surface
8
+ * (`title` / `description` / `warehouse_id`); the sample questions
9
+ * live inside `serialized_space`, which the REST API returns only
10
+ * when `include_serialized_space=true`. We hit that endpoint through
11
+ * the workspace client's raw `apiClient` since the typed request
12
+ * shape has no flag for it.
13
+ */
14
+ import { WorkspaceClient } from "@databricks/sdk-experimental";
15
+ import { GenieSpaceSchema } from "@dbx-tools/genie-shared";
16
+ import { apiUtils, commonUtils, logUtils } from "@dbx-tools/shared";
17
+ const log = logUtils.logger("genie/space");
18
+ /**
19
+ * Fetch a Genie space by id, optionally including its serialized
20
+ * definition. Hits `GET /api/2.0/genie/spaces/<id>` with
21
+ * `include_serialized_space=true` through the raw `apiClient`, then
22
+ * validates the response against {@link GenieSpaceSchema} (unknown
23
+ * fields like `etag` / `parent_path` are stripped).
24
+ */
25
+ export async function getGenieSpace(spaceId, options) {
26
+ const client = options?.workspaceClient ?? new WorkspaceClient({});
27
+ const serialized = options?.serialized !== false;
28
+ const context = options?.context ? apiUtils.toContext(options.context) : undefined;
29
+ const raw = await client.apiClient.request({
30
+ path: `/api/2.0/genie/spaces/${encodeURIComponent(spaceId)}`,
31
+ method: "GET",
32
+ query: serialized ? { include_serialized_space: true } : {},
33
+ headers: new Headers(),
34
+ raw: false,
35
+ }, context);
36
+ return GenieSpaceSchema.parse(raw);
37
+ }
38
+ /** Pull the first non-empty string out of a `question` field (string | string[]). */
39
+ function questionText(question) {
40
+ if (typeof question === "string") {
41
+ const trimmed = question.trim();
42
+ return trimmed.length > 0 ? trimmed : undefined;
43
+ }
44
+ if (Array.isArray(question)) {
45
+ for (const part of question) {
46
+ if (typeof part === "string" && part.trim().length > 0)
47
+ return part.trim();
48
+ }
49
+ }
50
+ return undefined;
51
+ }
52
+ /**
53
+ * Extract the curated starter questions an author configured on a
54
+ * Genie space. Reads `serialized_space -> config.sample_questions[*]
55
+ * .question`. Returns `[]` when the space carries no serialized blob,
56
+ * the blob is unparseable, or no sample questions are configured -
57
+ * so a missing or misconfigured space degrades to "no suggestions"
58
+ * rather than throwing. Order is preserved (the author's ordering)
59
+ * and duplicates are dropped.
60
+ */
61
+ export function genieSampleQuestions(space) {
62
+ const serialized = space.serialized_space;
63
+ if (!serialized)
64
+ return [];
65
+ let parsed;
66
+ try {
67
+ parsed = JSON.parse(serialized);
68
+ }
69
+ catch (err) {
70
+ log.warn("serialized-space:parse-error", {
71
+ spaceId: space.space_id,
72
+ error: commonUtils.errorMessage(err),
73
+ });
74
+ return [];
75
+ }
76
+ const sampleQuestions = parsed
77
+ ?.config?.sample_questions;
78
+ if (!Array.isArray(sampleQuestions))
79
+ return [];
80
+ const seen = new Set();
81
+ const out = [];
82
+ for (const entry of sampleQuestions) {
83
+ const text = questionText(entry?.question);
84
+ if (!text || seen.has(text))
85
+ continue;
86
+ seen.add(text);
87
+ out.push(text);
88
+ }
89
+ return out;
90
+ }