@dbx-tools/search 0.9.154 → 0.9.158
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/index.ts +13 -8
- package/lib/index.d.ts +13 -8
- package/lib/index.js +12 -7
- package/lib/src/client.d.ts +1 -2
- package/lib/src/client.js +15 -15
- package/lib/src/config.js +16 -16
- package/lib/src/lakebase-plugin.js +9 -11
- package/lib/src/lakebase.js +9 -11
- package/lib/src/native.js +5 -5
- package/lib/src/plugin.d.ts +5 -5
- package/lib/src/plugin.js +20 -20
- package/lib/src/query.js +4 -4
- package/lib/src/schema.d.ts +0 -66
- package/lib/src/schema.js +7 -20
- package/lib/src/tool.js +14 -16
- package/package.json +9 -105
- package/src/client.ts +14 -17
- package/src/config.ts +16 -44
- package/src/lakebase-plugin.ts +8 -10
- package/src/lakebase.ts +16 -13
- package/src/native.ts +6 -6
- package/src/plugin.ts +31 -24
- package/src/query.ts +3 -3
- package/src/schema.ts +6 -25
- package/src/tool.ts +22 -20
package/src/lakebase.ts
CHANGED
|
@@ -25,7 +25,15 @@
|
|
|
25
25
|
|
|
26
26
|
import { ExecutionError } from "@databricks/appkit";
|
|
27
27
|
import { postgresConnectionOptions } from "@dbx-tools/postgres";
|
|
28
|
-
import {
|
|
28
|
+
import {
|
|
29
|
+
log,
|
|
30
|
+
sleep,
|
|
31
|
+
isRecord,
|
|
32
|
+
tokenizeWithOptions,
|
|
33
|
+
trimToEmpty,
|
|
34
|
+
trimToNull,
|
|
35
|
+
toSlug,
|
|
36
|
+
} from "@dbx-tools/shared-core";
|
|
29
37
|
import type {
|
|
30
38
|
SearchDocument,
|
|
31
39
|
SearchHit,
|
|
@@ -61,12 +69,7 @@ const RESERVED_COLUMNS = new Set(["id", "search_text", "document", "search_vecto
|
|
|
61
69
|
* built.
|
|
62
70
|
*/
|
|
63
71
|
export function toSearchTerms(query: string): string[] {
|
|
64
|
-
return [
|
|
65
|
-
...stringUtils.tokenizeWithOptions(
|
|
66
|
-
{ lowerCase: true, camelCase: false, distinct: true },
|
|
67
|
-
query,
|
|
68
|
-
),
|
|
69
|
-
];
|
|
72
|
+
return [...tokenizeWithOptions({ lowerCase: true, camelCase: false, distinct: true }, query)];
|
|
70
73
|
}
|
|
71
74
|
|
|
72
75
|
/**
|
|
@@ -139,7 +142,7 @@ export class LakebaseSearchBackend {
|
|
|
139
142
|
for (let attempt = 0; attempt < 200; attempt += 1) {
|
|
140
143
|
this.pool = this.poolSource.managedPool() ?? undefined;
|
|
141
144
|
if (this.pool) return this.pool;
|
|
142
|
-
await
|
|
145
|
+
await sleep(50);
|
|
143
146
|
}
|
|
144
147
|
throw new ExecutionError("search (lakebase): managed pool did not initialize", {
|
|
145
148
|
context: { operation: "connect" },
|
|
@@ -179,7 +182,7 @@ export class LakebaseSearchBackend {
|
|
|
179
182
|
query: string,
|
|
180
183
|
options: LakebaseSearchOptions = {},
|
|
181
184
|
): Promise<SearchResult> {
|
|
182
|
-
const text =
|
|
185
|
+
const text = trimToEmpty(query);
|
|
183
186
|
const table = this.tableFor(index);
|
|
184
187
|
const limit = options.limit ?? 10;
|
|
185
188
|
const pool = await this.getPool();
|
|
@@ -359,7 +362,7 @@ export class LakebaseSearchBackend {
|
|
|
359
362
|
signal?: AbortSignal,
|
|
360
363
|
): Promise<void> {
|
|
361
364
|
for (const doc of documents) {
|
|
362
|
-
const id =
|
|
365
|
+
const id = trimToNull(String(doc.id ?? doc.ID ?? "")) ?? undefined;
|
|
363
366
|
if (id === undefined) {
|
|
364
367
|
throw new ExecutionError("search (lakebase): a document is missing an `id`", {
|
|
365
368
|
context: { operation: "addDocuments" },
|
|
@@ -380,7 +383,7 @@ export class LakebaseSearchBackend {
|
|
|
380
383
|
|
|
381
384
|
/** The text a row is indexed by: the text column first, then any other string field. */
|
|
382
385
|
private searchText(doc: SearchDocument, textColumn: string): string {
|
|
383
|
-
const primary =
|
|
386
|
+
const primary = trimToEmpty(String(doc[textColumn] ?? ""));
|
|
384
387
|
const rest = Object.entries(doc)
|
|
385
388
|
.filter(([key, value]) => key !== textColumn && key !== "id" && typeof value === "string")
|
|
386
389
|
.map(([, value]) => value as string);
|
|
@@ -389,7 +392,7 @@ export class LakebaseSearchBackend {
|
|
|
389
392
|
|
|
390
393
|
/** A hit's `fields`: the stored document minus the reserved/internal keys. */
|
|
391
394
|
private toFields(document: unknown): Record<string, unknown> {
|
|
392
|
-
if (!
|
|
395
|
+
if (!isRecord(document)) return {};
|
|
393
396
|
const fields: Record<string, unknown> = {};
|
|
394
397
|
for (const [key, value] of Object.entries(document)) {
|
|
395
398
|
if (RESERVED_COLUMNS.has(key)) continue;
|
|
@@ -429,7 +432,7 @@ export class LakebaseSearchBackend {
|
|
|
429
432
|
/** A safe bare table name derived from an index reference. */
|
|
430
433
|
private bareName(reference: string): string {
|
|
431
434
|
const last = reference.split(".").filter(Boolean).pop() ?? reference;
|
|
432
|
-
const slug =
|
|
435
|
+
const slug = toSlug(last).replace(/-/g, "_");
|
|
433
436
|
return slug.length > 0 ? slug : "documents";
|
|
434
437
|
}
|
|
435
438
|
|
package/src/native.ts
CHANGED
|
@@ -11,14 +11,14 @@ import type {
|
|
|
11
11
|
SearchRequest as AppKitSearchRequest,
|
|
12
12
|
SearchResponse as AppKitSearchResponse,
|
|
13
13
|
} from "@databricks/appkit/beta";
|
|
14
|
-
import {
|
|
14
|
+
import { trimToNull } from "@dbx-tools/shared-core";
|
|
15
15
|
import {
|
|
16
|
-
searchSchemas,
|
|
17
16
|
type SearchDocument,
|
|
18
17
|
type SearchHit,
|
|
19
|
-
type SearchRequest
|
|
18
|
+
type SearchRequest,
|
|
20
19
|
type SearchResult,
|
|
21
20
|
type UpsertResult,
|
|
21
|
+
toAiSearchQueryType,
|
|
22
22
|
} from "@dbx-tools/shared-search";
|
|
23
23
|
import type { SearchOptions, SearchReadBackend } from "./client.ts";
|
|
24
24
|
import { indexConfigFor, type ResolvedSearchConfig } from "./config.ts";
|
|
@@ -30,7 +30,7 @@ export interface AiSearchProvider {
|
|
|
30
30
|
addDocuments?(alias: string, documents: SearchDocument[]): Promise<UpsertResult>;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
function filters(value:
|
|
33
|
+
function filters(value: SearchRequest["filter"]): AppKitSearchFilters | undefined {
|
|
34
34
|
if (!value) return undefined;
|
|
35
35
|
const result: AppKitSearchFilters = {};
|
|
36
36
|
for (const [key, item] of Object.entries(value)) {
|
|
@@ -61,7 +61,7 @@ function hitId(
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
function aliasFor(index: string, config: ResolvedSearchConfig): string {
|
|
64
|
-
const alias = indexConfigFor(config, index)?.alias ??
|
|
64
|
+
const alias = indexConfigFor(config, index)?.alias ?? trimToNull(index);
|
|
65
65
|
if (!alias) throw new ValidationError("AI Search requires a configured index alias");
|
|
66
66
|
return alias;
|
|
67
67
|
}
|
|
@@ -77,7 +77,7 @@ export function nativeAiSearchBackend(
|
|
|
77
77
|
options.signal?.throwIfAborted();
|
|
78
78
|
const known = indexConfigFor(config, index);
|
|
79
79
|
const alias = aliasFor(index, config);
|
|
80
|
-
const resolvedQueryType =
|
|
80
|
+
const resolvedQueryType = toAiSearchQueryType(options.mode);
|
|
81
81
|
const resolvedFilters = filters(options.filter);
|
|
82
82
|
const response = await provider.query(alias, {
|
|
83
83
|
queryText: query,
|
package/src/plugin.ts
CHANGED
|
@@ -22,14 +22,22 @@
|
|
|
22
22
|
|
|
23
23
|
import { toPlugin, type IAppRouter, type PluginManifest } from "@databricks/appkit";
|
|
24
24
|
import { aiSearch, defineTool, type ToolRegistry } from "@databricks/appkit/beta";
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
25
|
+
import { ToolRegistryPlugin, require } from "@dbx-tools/appkit";
|
|
26
|
+
import { log, toError, errorMessage, trimToNull } from "@dbx-tools/shared-core";
|
|
27
27
|
import {
|
|
28
28
|
SEARCH_DEFAULT_BASE_PATH,
|
|
29
29
|
SEARCH_PLUGIN_NAME,
|
|
30
30
|
SEARCH_ROUTES,
|
|
31
|
-
searchSchemas,
|
|
32
31
|
type SearchClientConfig,
|
|
32
|
+
searchRequestSchema,
|
|
33
|
+
universalSearchRequestSchema,
|
|
34
|
+
searchDocumentSchema,
|
|
35
|
+
createIndexRequestSchema,
|
|
36
|
+
syncIndexRequestSchema,
|
|
37
|
+
type SearchRequest,
|
|
38
|
+
type UniversalSearchRequest,
|
|
39
|
+
type CreateIndexRequest,
|
|
40
|
+
type SyncIndexRequest,
|
|
33
41
|
} from "@dbx-tools/shared-search";
|
|
34
42
|
import { toSearchOptions, toUniversalSearchOptions } from "./_search-options.ts";
|
|
35
43
|
import { SEARCH_CONFIG_SCHEMA, resolveSearchConfig, type SearchPluginConfig } from "./config.ts";
|
|
@@ -112,14 +120,14 @@ export class SearchPlugin extends ToolRegistryPlugin<SearchPluginConfig> {
|
|
|
112
120
|
const registry: ToolRegistry = {
|
|
113
121
|
search: defineTool({
|
|
114
122
|
description: SEARCH_TOOL_DESCRIPTION,
|
|
115
|
-
schema:
|
|
123
|
+
schema: searchRequestSchema,
|
|
116
124
|
annotations: { effect: "read", requiresUserContext: true },
|
|
117
125
|
autoInheritable: false,
|
|
118
126
|
execute: async (args, signal) => this.runSearch(args, signal),
|
|
119
127
|
}),
|
|
120
128
|
universal_search: defineTool({
|
|
121
129
|
description: UNIVERSAL_SEARCH_TOOL_DESCRIPTION,
|
|
122
|
-
schema:
|
|
130
|
+
schema: universalSearchRequestSchema,
|
|
123
131
|
annotations: { effect: "read", requiresUserContext: true },
|
|
124
132
|
autoInheritable: false,
|
|
125
133
|
execute: async (args, signal) => this.runUniversalSearch(args, signal),
|
|
@@ -128,9 +136,9 @@ export class SearchPlugin extends ToolRegistryPlugin<SearchPluginConfig> {
|
|
|
128
136
|
if (config.allowWrite) {
|
|
129
137
|
registry.add_documents = defineTool({
|
|
130
138
|
description: ADD_DOCUMENTS_TOOL_DESCRIPTION,
|
|
131
|
-
schema:
|
|
139
|
+
schema: searchRequestSchema
|
|
132
140
|
.pick({ index: true })
|
|
133
|
-
.extend({ documents:
|
|
141
|
+
.extend({ documents: searchDocumentSchema.array() }),
|
|
134
142
|
annotations: { effect: "write", requiresUserContext: true },
|
|
135
143
|
autoInheritable: false,
|
|
136
144
|
execute: async (args, signal) => this.runAddDocuments(args, signal),
|
|
@@ -138,14 +146,14 @@ export class SearchPlugin extends ToolRegistryPlugin<SearchPluginConfig> {
|
|
|
138
146
|
if (readBackend?.supportsLifecycle) {
|
|
139
147
|
registry.create_index = defineTool({
|
|
140
148
|
description: CREATE_INDEX_TOOL_DESCRIPTION,
|
|
141
|
-
schema:
|
|
149
|
+
schema: createIndexRequestSchema,
|
|
142
150
|
annotations: { effect: "write", requiresUserContext: true },
|
|
143
151
|
autoInheritable: false,
|
|
144
152
|
execute: async (args, signal) => this.runCreateIndex(args, signal),
|
|
145
153
|
});
|
|
146
154
|
registry.sync_index = defineTool({
|
|
147
155
|
description: SYNC_INDEX_TOOL_DESCRIPTION,
|
|
148
|
-
schema:
|
|
156
|
+
schema: syncIndexRequestSchema,
|
|
149
157
|
annotations: { effect: "write", requiresUserContext: true },
|
|
150
158
|
autoInheritable: false,
|
|
151
159
|
execute: async (args, signal) => this.runSyncIndex(args, signal),
|
|
@@ -181,7 +189,7 @@ export class SearchPlugin extends ToolRegistryPlugin<SearchPluginConfig> {
|
|
|
181
189
|
|
|
182
190
|
/** Resolve the registered AppKit-compatible AI Search provider. */
|
|
183
191
|
private resolveProviderBackend(): ReturnType<typeof nativeAiSearchBackend> {
|
|
184
|
-
const provider =
|
|
192
|
+
const provider = require(this.context, aiSearch, this).exports();
|
|
185
193
|
return nativeAiSearchBackend(provider, resolveSearchConfig(this.config));
|
|
186
194
|
}
|
|
187
195
|
|
|
@@ -194,7 +202,7 @@ export class SearchPlugin extends ToolRegistryPlugin<SearchPluginConfig> {
|
|
|
194
202
|
private async runEnsureOnSetup(config: SearchRuntime["config"]): Promise<void> {
|
|
195
203
|
const spec = config.ensureOnSetup;
|
|
196
204
|
if (!spec) return;
|
|
197
|
-
const index =
|
|
205
|
+
const index = trimToNull(spec.index) ?? config.defaultIndex;
|
|
198
206
|
if (!index) {
|
|
199
207
|
logger.warn("ensure-skipped", {
|
|
200
208
|
reason: "no index name (set `index` or `ensureOnSetup.index`)",
|
|
@@ -227,7 +235,7 @@ export class SearchPlugin extends ToolRegistryPlugin<SearchPluginConfig> {
|
|
|
227
235
|
rowCount: info.rowCount ?? 0,
|
|
228
236
|
});
|
|
229
237
|
} catch (cause) {
|
|
230
|
-
logger.warn("ensure-failed", { index, error:
|
|
238
|
+
logger.warn("ensure-failed", { index, error: toError(cause) });
|
|
231
239
|
}
|
|
232
240
|
}
|
|
233
241
|
|
|
@@ -272,7 +280,7 @@ export class SearchPlugin extends ToolRegistryPlugin<SearchPluginConfig> {
|
|
|
272
280
|
path: SEARCH_ROUTES.universal,
|
|
273
281
|
handler: async (req, res) => {
|
|
274
282
|
await this.respond(res, "universalSearch", () => {
|
|
275
|
-
const request =
|
|
283
|
+
const request = universalSearchRequestSchema.parse(req.body ?? {});
|
|
276
284
|
return this.asUser(req).runUniversalSearch(request);
|
|
277
285
|
});
|
|
278
286
|
},
|
|
@@ -347,10 +355,10 @@ export class SearchPlugin extends ToolRegistryPlugin<SearchPluginConfig> {
|
|
|
347
355
|
try {
|
|
348
356
|
res.json(await run());
|
|
349
357
|
} catch (cause) {
|
|
350
|
-
const message =
|
|
358
|
+
const message = errorMessage(cause);
|
|
351
359
|
logger.warn("route-failed", {
|
|
352
360
|
operation,
|
|
353
|
-
error:
|
|
361
|
+
error: toError(cause),
|
|
354
362
|
});
|
|
355
363
|
res.status(500).json({ error: message });
|
|
356
364
|
}
|
|
@@ -377,31 +385,30 @@ export class SearchPlugin extends ToolRegistryPlugin<SearchPluginConfig> {
|
|
|
377
385
|
override exports() {
|
|
378
386
|
return {
|
|
379
387
|
/** Search one index (default when omitted). Runs as the current context user. */
|
|
380
|
-
search: (request:
|
|
381
|
-
this.runSearch(request, signal),
|
|
388
|
+
search: (request: SearchRequest, signal?: AbortSignal) => this.runSearch(request, signal),
|
|
382
389
|
/** Search across every configured index and merge the hits. */
|
|
383
|
-
universalSearch: (request:
|
|
390
|
+
universalSearch: (request: UniversalSearchRequest, signal?: AbortSignal) =>
|
|
384
391
|
this.runUniversalSearch(request, signal),
|
|
385
392
|
/** Add or update documents in a direct-access index (throws when writes are disabled). */
|
|
386
393
|
addDocuments: (request: { index?: string; documents: unknown }, signal?: AbortSignal) =>
|
|
387
394
|
this.runAddDocuments(request, signal),
|
|
388
395
|
/** Create a Vector Search index (throws when writes are disabled). */
|
|
389
|
-
createIndex: (request:
|
|
396
|
+
createIndex: (request: CreateIndexRequest, signal?: AbortSignal) =>
|
|
390
397
|
this.runCreateIndex(request, signal),
|
|
391
398
|
/** Sync a Delta Sync index from its source table (throws when writes are disabled). */
|
|
392
|
-
syncIndex: (request:
|
|
399
|
+
syncIndex: (request: SyncIndexRequest, signal?: AbortSignal) =>
|
|
393
400
|
this.runSyncIndex(request, signal),
|
|
394
401
|
};
|
|
395
402
|
}
|
|
396
403
|
|
|
397
404
|
private async runSearch(args: unknown, signal?: AbortSignal) {
|
|
398
|
-
const request =
|
|
405
|
+
const request = searchRequestSchema.parse(args);
|
|
399
406
|
const { client } = this.runtime;
|
|
400
407
|
return client.search(request.query, toSearchOptions(request, signal));
|
|
401
408
|
}
|
|
402
409
|
|
|
403
410
|
private async runUniversalSearch(args: unknown, signal?: AbortSignal) {
|
|
404
|
-
const request =
|
|
411
|
+
const request = universalSearchRequestSchema.parse(args);
|
|
405
412
|
const { client } = this.runtime;
|
|
406
413
|
return client.universalSearch(request.query, toUniversalSearchOptions(request, signal));
|
|
407
414
|
}
|
|
@@ -415,13 +422,13 @@ export class SearchPlugin extends ToolRegistryPlugin<SearchPluginConfig> {
|
|
|
415
422
|
}
|
|
416
423
|
|
|
417
424
|
private async runCreateIndex(args: unknown, signal?: AbortSignal) {
|
|
418
|
-
const request =
|
|
425
|
+
const request = createIndexRequestSchema.parse(args);
|
|
419
426
|
const { client } = this.runtime;
|
|
420
427
|
return client.createIndex(request.name, toCreateIndexOptions(request, signal));
|
|
421
428
|
}
|
|
422
429
|
|
|
423
430
|
private async runSyncIndex(args: unknown, signal?: AbortSignal) {
|
|
424
|
-
const request =
|
|
431
|
+
const request = syncIndexRequestSchema.parse(args);
|
|
425
432
|
const { client, config } = this.runtime;
|
|
426
433
|
const index = request.index ?? config.defaultIndex ?? "";
|
|
427
434
|
await client.syncIndex(index, signal);
|
package/src/query.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** Request-shape helpers for search extension write routes and tools. */
|
|
2
2
|
|
|
3
3
|
import { ValidationError } from "@databricks/appkit";
|
|
4
|
-
import {
|
|
4
|
+
import { parse, isRecord } from "@dbx-tools/shared-core";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Parse a JSON document payload the model / a route supplied for a write.
|
|
@@ -10,10 +10,10 @@ import { json, object } from "@dbx-tools/shared-core";
|
|
|
10
10
|
* {@link ValidationError} on unparseable input so the caller can surface it.
|
|
11
11
|
*/
|
|
12
12
|
export function toDocumentArray(input: unknown): Array<Record<string, unknown>> {
|
|
13
|
-
const value = typeof input === "string" ?
|
|
13
|
+
const value = typeof input === "string" ? parse(input, undefined) : input;
|
|
14
14
|
if (value === undefined) {
|
|
15
15
|
throw new ValidationError("documents must be a JSON object, array, or string");
|
|
16
16
|
}
|
|
17
17
|
const list = Array.isArray(value) ? value : [value];
|
|
18
|
-
return list.filter(
|
|
18
|
+
return list.filter(isRecord);
|
|
19
19
|
}
|
package/src/schema.ts
CHANGED
|
@@ -7,11 +7,10 @@
|
|
|
7
7
|
* @module
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import {
|
|
11
|
-
import { searchSchemas } from "@dbx-tools/shared-search";
|
|
10
|
+
import { toDescription } from "@dbx-tools/shared-core";
|
|
12
11
|
|
|
13
12
|
/** Description the model reads for the `search` tool. */
|
|
14
|
-
export const SEARCH_TOOL_DESCRIPTION =
|
|
13
|
+
export const SEARCH_TOOL_DESCRIPTION = toDescription(`
|
|
15
14
|
Search a Databricks AI Search (Vector Search) index for the documents most
|
|
16
15
|
relevant to a query. Pass a natural-language question or keywords; hybrid
|
|
17
16
|
matching combines semantic similarity with keyword ranking, so exact terms
|
|
@@ -22,7 +21,7 @@ export const SEARCH_TOOL_DESCRIPTION = stringUtils.toDescription(`
|
|
|
22
21
|
`);
|
|
23
22
|
|
|
24
23
|
/** Description the model reads for the `universal_search` tool. */
|
|
25
|
-
export const UNIVERSAL_SEARCH_TOOL_DESCRIPTION =
|
|
24
|
+
export const UNIVERSAL_SEARCH_TOOL_DESCRIPTION = toDescription(`
|
|
26
25
|
Search across every configured AI Search index at once and return the best
|
|
27
26
|
matches from all of them, merged and ranked. Use it when the right index
|
|
28
27
|
isn't known in advance or when an answer may live in any of several
|
|
@@ -30,7 +29,7 @@ export const UNIVERSAL_SEARCH_TOOL_DESCRIPTION = stringUtils.toDescription(`
|
|
|
30
29
|
`);
|
|
31
30
|
|
|
32
31
|
/** Description the model reads for the `add_documents` tool. */
|
|
33
|
-
export const ADD_DOCUMENTS_TOOL_DESCRIPTION =
|
|
32
|
+
export const ADD_DOCUMENTS_TOOL_DESCRIPTION = toDescription(`
|
|
34
33
|
Add or update documents in a direct-access AI Search index. Pass an array of
|
|
35
34
|
documents as JSON objects; each MUST include the index's primary-key column.
|
|
36
35
|
Only available when the app enables the write surface. Use it to index new
|
|
@@ -38,7 +37,7 @@ export const ADD_DOCUMENTS_TOOL_DESCRIPTION = stringUtils.toDescription(`
|
|
|
38
37
|
`);
|
|
39
38
|
|
|
40
39
|
/** Description the model reads for the `create_index` tool. */
|
|
41
|
-
export const CREATE_INDEX_TOOL_DESCRIPTION =
|
|
40
|
+
export const CREATE_INDEX_TOOL_DESCRIPTION = toDescription(`
|
|
42
41
|
Create a Databricks AI Search (Vector Search) index. For the common case pass
|
|
43
42
|
a Delta source table (catalog.schema.table): Databricks computes embeddings
|
|
44
43
|
from its text column and keeps the index synced. To create a direct-access
|
|
@@ -50,26 +49,8 @@ export const CREATE_INDEX_TOOL_DESCRIPTION = stringUtils.toDescription(`
|
|
|
50
49
|
`);
|
|
51
50
|
|
|
52
51
|
/** Description the model reads for the `sync_index` tool. */
|
|
53
|
-
export const SYNC_INDEX_TOOL_DESCRIPTION =
|
|
52
|
+
export const SYNC_INDEX_TOOL_DESCRIPTION = toDescription(`
|
|
54
53
|
Refresh a Delta Sync AI Search index from its source table so newly added or
|
|
55
54
|
changed rows become searchable. Optionally name the index (defaults to the
|
|
56
55
|
app's default index). Only available when the app enables the write surface.
|
|
57
56
|
`);
|
|
58
|
-
|
|
59
|
-
/** Schema for the `search` tool input (the shared request schema). */
|
|
60
|
-
export const searchToolSchema = searchSchemas.searchRequestSchema;
|
|
61
|
-
|
|
62
|
-
/** Schema for the `universal_search` tool input. */
|
|
63
|
-
export const universalSearchToolSchema = searchSchemas.universalSearchRequestSchema;
|
|
64
|
-
|
|
65
|
-
/** Schema for the `search` / `universal_search` tool output. */
|
|
66
|
-
export const searchResultSchema = searchSchemas.searchResultSchema;
|
|
67
|
-
|
|
68
|
-
/** Schema for the `create_index` tool input. */
|
|
69
|
-
export const createIndexToolSchema = searchSchemas.createIndexRequestSchema;
|
|
70
|
-
|
|
71
|
-
/** Schema for the `create_index` tool output (a resolved index definition). */
|
|
72
|
-
export const indexInfoSchema = searchSchemas.indexInfoSchema;
|
|
73
|
-
|
|
74
|
-
/** Schema for the `sync_index` tool input. */
|
|
75
|
-
export const syncIndexToolSchema = searchSchemas.syncIndexRequestSchema;
|
package/src/tool.ts
CHANGED
|
@@ -15,7 +15,17 @@
|
|
|
15
15
|
* @module
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
createIndexRequestSchema,
|
|
20
|
+
indexInfoSchema,
|
|
21
|
+
searchDocumentSchema,
|
|
22
|
+
searchRequestSchema,
|
|
23
|
+
searchResultSchema,
|
|
24
|
+
syncIndexRequestSchema,
|
|
25
|
+
universalSearchRequestSchema,
|
|
26
|
+
upsertResultSchema,
|
|
27
|
+
type UpsertResult,
|
|
28
|
+
} from "@dbx-tools/shared-search";
|
|
19
29
|
import { createTool } from "@mastra/core/tools";
|
|
20
30
|
import { z } from "zod";
|
|
21
31
|
import { toSearchOptions, toUniversalSearchOptions } from "./_search-options.ts";
|
|
@@ -30,12 +40,6 @@ import {
|
|
|
30
40
|
SEARCH_TOOL_DESCRIPTION,
|
|
31
41
|
SYNC_INDEX_TOOL_DESCRIPTION,
|
|
32
42
|
UNIVERSAL_SEARCH_TOOL_DESCRIPTION,
|
|
33
|
-
createIndexToolSchema,
|
|
34
|
-
indexInfoSchema,
|
|
35
|
-
searchResultSchema,
|
|
36
|
-
searchToolSchema,
|
|
37
|
-
syncIndexToolSchema,
|
|
38
|
-
universalSearchToolSchema,
|
|
39
43
|
} from "./schema.ts";
|
|
40
44
|
|
|
41
45
|
/** Options accepted by every standalone tool factory. */
|
|
@@ -84,10 +88,10 @@ export function searchTool(options: SearchToolOptions = {}) {
|
|
|
84
88
|
return createTool({
|
|
85
89
|
id: options.id ?? "search",
|
|
86
90
|
description: SEARCH_TOOL_DESCRIPTION,
|
|
87
|
-
inputSchema:
|
|
91
|
+
inputSchema: searchRequestSchema,
|
|
88
92
|
outputSchema: searchResultSchema,
|
|
89
93
|
execute: async (input, context) => {
|
|
90
|
-
const request =
|
|
94
|
+
const request = searchRequestSchema.parse(input);
|
|
91
95
|
return runtime.client.search(request.query, toSearchOptions(request, context?.abortSignal));
|
|
92
96
|
},
|
|
93
97
|
});
|
|
@@ -99,10 +103,10 @@ export function universalSearchTool(options: SearchToolOptions = {}) {
|
|
|
99
103
|
return createTool({
|
|
100
104
|
id: options.id ?? "universal_search",
|
|
101
105
|
description: UNIVERSAL_SEARCH_TOOL_DESCRIPTION,
|
|
102
|
-
inputSchema:
|
|
106
|
+
inputSchema: universalSearchRequestSchema,
|
|
103
107
|
outputSchema: searchResultSchema,
|
|
104
108
|
execute: async (input, context) => {
|
|
105
|
-
const request =
|
|
109
|
+
const request = universalSearchRequestSchema.parse(input);
|
|
106
110
|
return runtime.client.universalSearch(
|
|
107
111
|
request.query,
|
|
108
112
|
toUniversalSearchOptions(request, context?.abortSignal),
|
|
@@ -117,16 +121,14 @@ export function universalSearchTool(options: SearchToolOptions = {}) {
|
|
|
117
121
|
*/
|
|
118
122
|
export function addDocumentsTool(options: SearchToolOptions = {}) {
|
|
119
123
|
const runtime = toolRuntime(options);
|
|
120
|
-
const inputSchema =
|
|
124
|
+
const inputSchema = searchDocumentSchema
|
|
121
125
|
.array()
|
|
122
126
|
.describe("Documents to add or update. Each must include the index primary key.");
|
|
123
127
|
return createTool({
|
|
124
128
|
id: options.id ?? "add_documents",
|
|
125
129
|
description: ADD_DOCUMENTS_TOOL_DESCRIPTION,
|
|
126
|
-
inputSchema:
|
|
127
|
-
|
|
128
|
-
.extend({ documents: inputSchema }),
|
|
129
|
-
outputSchema: searchSchemas.upsertResultSchema,
|
|
130
|
+
inputSchema: searchRequestSchema.pick({ index: true }).extend({ documents: inputSchema }),
|
|
131
|
+
outputSchema: upsertResultSchema,
|
|
130
132
|
execute: async (input, context): Promise<UpsertResult> => {
|
|
131
133
|
const { client, config } = runtime;
|
|
132
134
|
const record = input as { index?: string; documents: unknown };
|
|
@@ -148,10 +150,10 @@ export function createIndexTool(options: SearchToolOptions = {}) {
|
|
|
148
150
|
return createTool({
|
|
149
151
|
id: options.id ?? "create_index",
|
|
150
152
|
description: CREATE_INDEX_TOOL_DESCRIPTION,
|
|
151
|
-
inputSchema:
|
|
153
|
+
inputSchema: createIndexRequestSchema,
|
|
152
154
|
outputSchema: indexInfoSchema,
|
|
153
155
|
execute: async (input, context) => {
|
|
154
|
-
const request =
|
|
156
|
+
const request = createIndexRequestSchema.parse(input);
|
|
155
157
|
return runtime.client.createIndex(
|
|
156
158
|
request.name,
|
|
157
159
|
toCreateIndexOptions(request, context?.abortSignal),
|
|
@@ -175,10 +177,10 @@ export function syncIndexTool(options: SearchToolOptions = {}) {
|
|
|
175
177
|
return createTool({
|
|
176
178
|
id: options.id ?? "sync_index",
|
|
177
179
|
description: SYNC_INDEX_TOOL_DESCRIPTION,
|
|
178
|
-
inputSchema:
|
|
180
|
+
inputSchema: syncIndexRequestSchema,
|
|
179
181
|
outputSchema: syncIndexResultSchema,
|
|
180
182
|
execute: async (input, context) => {
|
|
181
|
-
const request =
|
|
183
|
+
const request = syncIndexRequestSchema.parse(input);
|
|
182
184
|
const { client, config } = runtime;
|
|
183
185
|
const index = request.index ?? config.defaultIndex ?? "";
|
|
184
186
|
await client.syncIndex(index, context?.abortSignal);
|