@dbx-tools/genie 0.1.20 → 0.1.21

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.
Files changed (2) hide show
  1. package/README.md +177 -0
  2. package/package.json +3 -3
package/README.md ADDED
@@ -0,0 +1,177 @@
1
+ # @dbx-tools/genie
2
+
3
+ Server-side Genie chat drivers. Two async generators that take a
4
+ `space_id` + a single `content` string for one turn against a Genie
5
+ space and yield either the raw `GenieMessage` snapshots
6
+ (`genieChat`) or a typed `GenieChatEvent` stream of flat
7
+ `{ type, ...fields }` records (`genieEventChat`).
8
+
9
+ Multi-turn conversations are caller-driven: read `conversation_id`
10
+ off the prior turn's terminal `GenieMessage` (or the `result`
11
+ event's `conversation_id`) and thread it into the next call's
12
+ `options.conversationId`.
13
+
14
+ ```ts
15
+ import { genieEventChat } from "@dbx-tools/genie";
16
+
17
+ for await (const event of genieEventChat(spaceId, "Top 5 stores?")) {
18
+ switch (event.type) {
19
+ case "thinking":
20
+ console.log("[think]", event.thought_type, event.text);
21
+ break;
22
+ case "query":
23
+ console.log("[sql]", event.title, "\n", event.sql);
24
+ break;
25
+ case "result":
26
+ console.log("[done]", event.status);
27
+ break;
28
+ }
29
+ }
30
+ ```
31
+
32
+ Browser safety: `chat.ts` pulls in `WorkspaceClient` from
33
+ `@databricks/sdk-experimental` and is Node-only. Browser bundles
34
+ should import from [`@dbx-tools/genie-shared`](../genie-shared)
35
+ directly - the protocol types, the `GenieChatEvent` union, the pure
36
+ detectors, and `eventsFromMessage` all live there and are also
37
+ re-exported from `@dbx-tools/genie` for server-side convenience.
38
+
39
+ ## `genieChat` - low-level snapshot stream
40
+
41
+ Yields every poll-observed `GenieMessage` for a single turn. Use it
42
+ when you want the raw stream (e.g. to drive a custom UI off the wire
43
+ shape, or to derive events yourself with the detectors in
44
+ `@dbx-tools/genie-shared`).
45
+
46
+ ```ts
47
+ import { genieChat } from "@dbx-tools/genie";
48
+
49
+ // Single turn.
50
+ for await (const m of genieChat(spaceId, "Top 5 stores?")) {
51
+ render(m);
52
+ }
53
+
54
+ // Multi-turn: caller threads the conversation id.
55
+ let conversationId: string | undefined;
56
+ for (const question of questions) {
57
+ for await (const m of genieChat(spaceId, question, { conversationId })) {
58
+ conversationId = m.conversation_id ?? conversationId;
59
+ render(m);
60
+ }
61
+ }
62
+ ```
63
+
64
+ Turn lifecycle:
65
+
66
+ - **No `options.conversationId`**: opens a new conversation via
67
+ `client.genie.startConversation`. The assigned id surfaces on
68
+ every yielded `GenieMessage.conversation_id`.
69
+ - **With `options.conversationId`**: appends to that conversation
70
+ via `client.genie.createMessage`.
71
+ - In both cases, after the create/start the driver polls
72
+ `client.genie.getMessage` every `options.pollIntervalMs` (default
73
+ 500ms) until the message hits a terminal status
74
+ (`COMPLETED` / `FAILED` / `CANCELLED`), then yields the terminal
75
+ snapshot and returns.
76
+
77
+ Identical consecutive snapshots are filtered out (deep equal)
78
+ because Genie often returns the exact same payload twice during
79
+ quiet periods.
80
+
81
+ ## `genieEventChat` - high-level typed events
82
+
83
+ Wraps `genieChat` and yields a `GenieChatEvent` discriminated union.
84
+ Stream order per turn:
85
+
86
+ 1. `{ type: "message", message }` - the raw `GenieMessage`, once
87
+ per poll yield.
88
+ 2. `{ type: "question", content, message_id, ... }` - fires
89
+ exactly once, on the first `message` yield. Carries the prompt
90
+ text Genie echoed back and the assigned `message_id` so
91
+ subscribers can group everything for one Genie call under that
92
+ one key.
93
+ 3. Any of `status` / `attachment` / `thinking` / `text` / `query` /
94
+ `statement` / `rows` / `suggested_questions` the diff against
95
+ the prior snapshot produced.
96
+ 4. On the terminal snapshot, `{ type: "result", status, message }`
97
+ as the final yield.
98
+
99
+ See [`@dbx-tools/genie-shared`](../genie-shared) for the full event
100
+ catalogue, field shapes, and the pure detectors that derive each
101
+ event from a snapshot diff.
102
+
103
+ Errors propagate by the generator throwing - there is no `error`
104
+ variant. Wrap the `for await` in `try / catch` if you need to handle
105
+ failures.
106
+
107
+ ## Options
108
+
109
+ `GenieChatOptions` is the same shape for both drivers:
110
+
111
+ | Option | Default | Description |
112
+ | ----------------- | ------------------------------------------ | -------------------------------------------------------------------------------------------------------------------- |
113
+ | `conversationId` | `undefined` | Seed conversation id. When set, this turn appends to the existing conversation via `createMessage`. |
114
+ | `workspaceClient` | resolved (see below) | Explicit `WorkspaceClient`. Defaults to AppKit's per-request client when available; otherwise env-var auth. |
115
+ | `pollIntervalMs` | `500` | Cadence between successive `getMessage` calls. |
116
+ | `context` | new internal `AbortController` per call | External cancellation. Accepts an `AbortSignal` or a fully-built SDK `Context` (`apiUtils.ContextLike`). |
117
+
118
+ ### Workspace client resolution
119
+
120
+ Resolved in priority order:
121
+
122
+ 1. Caller-supplied `options.workspaceClient`.
123
+ 2. AppKit's per-request execution-context client, when
124
+ `@databricks/appkit` is installed AND we're inside an active
125
+ request scope. OBO auth is preserved automatically.
126
+ 3. Fresh `new WorkspaceClient({})` (env-var auth via
127
+ `DATABRICKS_CONFIG_PROFILE` / `DATABRICKS_HOST` /
128
+ `DATABRICKS_TOKEN`).
129
+
130
+ AppKit is loaded lazily, so this package is usable from non-AppKit
131
+ environments (smoke scripts, batch jobs, tests, ...).
132
+
133
+ ### Cancellation
134
+
135
+ A single internal `AbortController` covers each call. `options.context`
136
+ ties into that controller, so an external abort tears down every
137
+ in-flight SDK call AND the inter-poll sleep. Breaking out of the
138
+ `for await` does the same via the `try / finally`.
139
+
140
+ ```ts
141
+ const ac = new AbortController();
142
+ setTimeout(() => ac.abort(), 30_000); // hard 30s ceiling
143
+
144
+ try {
145
+ for await (const event of genieEventChat(spaceId, content, { context: ac.signal })) {
146
+ handle(event);
147
+ }
148
+ } catch (err) {
149
+ if (ac.signal.aborted) console.log("timed out");
150
+ else throw err;
151
+ }
152
+ ```
153
+
154
+ ## Smoke test
155
+
156
+ [`test/poll-chat.ts`](test/poll-chat.ts) drives `genieEventChat` from
157
+ argv / stdin / a REPL and writes every emitted event to a per-run tmp
158
+ directory so you can inspect deltas after the fact. One subdirectory
159
+ per `GenieChatEvent` variant, plus a `rows-data/` directory for paired
160
+ SQL fetches on terminals that carry a `query_result.statement_id`.
161
+
162
+ ```bash
163
+ # Required env (already in repo .env):
164
+ # DATABRICKS_GENIE_SPACE_ID
165
+ # DATABRICKS_CONFIG_PROFILE (or any SDK auth env)
166
+
167
+ bun packages/genie/test/poll-chat.ts # REPL
168
+ bun packages/genie/test/poll-chat.ts "Top 5 stores by revenue?"
169
+ echo "Top 5 stores by revenue?" | bun packages/genie/test/poll-chat.ts
170
+ ```
171
+
172
+ Stdout carries a one-line summary per event with the relative path;
173
+ the per-run directory is printed at the top.
174
+
175
+ ## License
176
+
177
+ Apache-2.0
package/package.json CHANGED
@@ -9,11 +9,11 @@
9
9
  }
10
10
  },
11
11
  "name": "@dbx-tools/genie",
12
- "version": "0.1.20",
12
+ "version": "0.1.21",
13
13
  "dependencies": {
14
14
  "@databricks/sdk-experimental": "^0.17",
15
- "@dbx-tools/genie-shared": "0.1.20",
16
- "@dbx-tools/shared": "0.1.20"
15
+ "@dbx-tools/genie-shared": "0.1.21",
16
+ "@dbx-tools/shared": "0.1.21"
17
17
  },
18
18
  "module": "index.ts",
19
19
  "type": "module",