@dbx-tools/search 0.6.87 → 0.6.89
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/lib/src/client.js +3 -3
- package/lib/src/config.js +11 -11
- package/lib/src/plugin.d.ts +7 -7
- package/lib/src/plugin.js +21 -21
- package/lib/src/tool.js +5 -5
- package/package.json +7 -7
- package/src/client.ts +2 -2
- package/src/config.ts +15 -15
- package/src/plugin.ts +24 -24
- package/src/tool.ts +4 -4
package/src/config.ts
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
25
|
import { ConfigurationError, type BasePluginConfig } from "@databricks/appkit";
|
|
26
|
-
import { config as
|
|
26
|
+
import { config as coreConfig } from "@dbx-tools/core";
|
|
27
27
|
import { object, string } from "@dbx-tools/shared-core";
|
|
28
28
|
import type { SearchDocument, SearchMode } from "@dbx-tools/shared-search";
|
|
29
29
|
import type { JSONSchema7 } from "json-schema";
|
|
@@ -238,7 +238,7 @@ function toResolvedIndex(entry: string | SearchIndexConfig): ResolvedIndexConfig
|
|
|
238
238
|
|
|
239
239
|
/** Parse and validate a {@link SearchMode} from config or an env var. */
|
|
240
240
|
function resolveMode(configured: SearchMode | undefined): SearchMode {
|
|
241
|
-
const raw = configured ??
|
|
241
|
+
const raw = configured ?? coreConfig.text("SEARCH_MODE", coreConfig.ENV_ONLY);
|
|
242
242
|
if (raw === undefined) return DEFAULT_MODE;
|
|
243
243
|
if (raw !== "hybrid" && raw !== "vector" && raw !== "keyword") {
|
|
244
244
|
throw new ConfigurationError(
|
|
@@ -256,10 +256,10 @@ function resolveMode(configured: SearchMode | undefined): SearchMode {
|
|
|
256
256
|
* and a bad mode throws a {@link ConfigurationError} naming the field.
|
|
257
257
|
*/
|
|
258
258
|
export function resolveSearchConfig(config: SearchPluginConfig = {}): ResolvedSearchConfig {
|
|
259
|
-
const defaultIndexRaw =
|
|
259
|
+
const defaultIndexRaw = coreConfig.string(
|
|
260
260
|
config.index,
|
|
261
261
|
[INDEX_ENV, DATABRICKS_INDEX_ENV],
|
|
262
|
-
|
|
262
|
+
coreConfig.ENV_ONLY,
|
|
263
263
|
);
|
|
264
264
|
|
|
265
265
|
const configured = (config.indexes ?? [])
|
|
@@ -268,11 +268,11 @@ export function resolveSearchConfig(config: SearchPluginConfig = {}): ResolvedSe
|
|
|
268
268
|
|
|
269
269
|
// Ensure the default index is represented in the known set.
|
|
270
270
|
if (defaultIndexRaw && !configured.some((i) => i.name === defaultIndexRaw)) {
|
|
271
|
-
const envColumns =
|
|
271
|
+
const envColumns = coreConfig.list(
|
|
272
272
|
undefined,
|
|
273
273
|
"SEARCH_COLUMNS",
|
|
274
274
|
undefined,
|
|
275
|
-
|
|
275
|
+
coreConfig.ENV_ONLY,
|
|
276
276
|
);
|
|
277
277
|
configured.unshift({
|
|
278
278
|
name: defaultIndexRaw,
|
|
@@ -290,11 +290,11 @@ export function resolveSearchConfig(config: SearchPluginConfig = {}): ResolvedSe
|
|
|
290
290
|
});
|
|
291
291
|
|
|
292
292
|
const defaultIndex = defaultIndexRaw ?? indexes[0]?.name;
|
|
293
|
-
const columns =
|
|
293
|
+
const columns = coreConfig.list(
|
|
294
294
|
config.columns,
|
|
295
295
|
"SEARCH_COLUMNS",
|
|
296
296
|
undefined,
|
|
297
|
-
|
|
297
|
+
coreConfig.ENV_ONLY,
|
|
298
298
|
);
|
|
299
299
|
|
|
300
300
|
return {
|
|
@@ -302,29 +302,29 @@ export function resolveSearchConfig(config: SearchPluginConfig = {}): ResolvedSe
|
|
|
302
302
|
indexes,
|
|
303
303
|
...object.optional(
|
|
304
304
|
"endpoint",
|
|
305
|
-
|
|
305
|
+
coreConfig.string(config.endpoint, ENDPOINT_ENV, coreConfig.ENV_ONLY),
|
|
306
306
|
),
|
|
307
307
|
...(columns.length > 0 ? { columns } : {}),
|
|
308
|
-
pageSize:
|
|
308
|
+
pageSize: coreConfig.positiveInt(
|
|
309
309
|
config.pageSize,
|
|
310
310
|
"SEARCH_PAGE_SIZE",
|
|
311
311
|
DEFAULT_PAGE_SIZE,
|
|
312
|
-
|
|
312
|
+
coreConfig.ENV_ONLY,
|
|
313
313
|
),
|
|
314
314
|
mode: resolveMode(config.mode),
|
|
315
315
|
...object.optional(
|
|
316
316
|
"embeddingModel",
|
|
317
|
-
|
|
317
|
+
coreConfig.string(config.embeddingModel, "SEARCH_EMBEDDING_MODEL", coreConfig.ENV_ONLY),
|
|
318
318
|
),
|
|
319
319
|
basePath: DEFAULT_BASE_PATH,
|
|
320
|
-
timeoutMs:
|
|
320
|
+
timeoutMs: coreConfig.positiveInt(
|
|
321
321
|
config.timeoutMs,
|
|
322
322
|
"SEARCH_TIMEOUT_MS",
|
|
323
323
|
DEFAULT_TIMEOUT_MS,
|
|
324
|
-
|
|
324
|
+
coreConfig.ENV_ONLY,
|
|
325
325
|
),
|
|
326
326
|
allowWrite:
|
|
327
|
-
|
|
327
|
+
coreConfig.boolean(config.allowWrite, "SEARCH_WRITE", coreConfig.ENV_ONLY) ?? false,
|
|
328
328
|
...(config.ensureOnSetup ? { ensureOnSetup: config.ensureOnSetup } : {}),
|
|
329
329
|
};
|
|
330
330
|
}
|
package/src/plugin.ts
CHANGED
|
@@ -39,9 +39,9 @@ import {
|
|
|
39
39
|
type ToolProvider,
|
|
40
40
|
type ToolRegistry,
|
|
41
41
|
} from "@databricks/appkit/beta";
|
|
42
|
-
import { plugin as
|
|
43
|
-
import { error as
|
|
44
|
-
import { search as
|
|
42
|
+
import { plugin as appkitPlugin } from "@dbx-tools/appkit";
|
|
43
|
+
import { error as sharedError, log, string } from "@dbx-tools/shared-core";
|
|
44
|
+
import { search as sharedSearch, type SearchClientConfig } from "@dbx-tools/shared-search";
|
|
45
45
|
import {
|
|
46
46
|
SEARCH_CONFIG_SCHEMA,
|
|
47
47
|
DATABRICKS_INDEX_ENV,
|
|
@@ -178,14 +178,14 @@ export class SearchPlugin extends Plugin<SearchPluginConfig> implements ToolProv
|
|
|
178
178
|
const registry: ToolRegistry = {
|
|
179
179
|
search: defineTool({
|
|
180
180
|
description: SEARCH_TOOL_DESCRIPTION,
|
|
181
|
-
schema:
|
|
181
|
+
schema: sharedSearch.searchRequestSchema,
|
|
182
182
|
annotations: { effect: "read", requiresUserContext: true },
|
|
183
183
|
autoInheritable: false,
|
|
184
184
|
execute: async (args, signal) => this.runSearch(args, signal),
|
|
185
185
|
}),
|
|
186
186
|
universal_search: defineTool({
|
|
187
187
|
description: UNIVERSAL_SEARCH_TOOL_DESCRIPTION,
|
|
188
|
-
schema:
|
|
188
|
+
schema: sharedSearch.universalSearchRequestSchema,
|
|
189
189
|
annotations: { effect: "read", requiresUserContext: true },
|
|
190
190
|
autoInheritable: false,
|
|
191
191
|
execute: async (args, signal) => this.runUniversalSearch(args, signal),
|
|
@@ -194,23 +194,23 @@ export class SearchPlugin extends Plugin<SearchPluginConfig> implements ToolProv
|
|
|
194
194
|
if (config.allowWrite) {
|
|
195
195
|
registry.add_documents = defineTool({
|
|
196
196
|
description: ADD_DOCUMENTS_TOOL_DESCRIPTION,
|
|
197
|
-
schema:
|
|
197
|
+
schema: sharedSearch.searchRequestSchema
|
|
198
198
|
.pick({ index: true })
|
|
199
|
-
.extend({ documents:
|
|
199
|
+
.extend({ documents: sharedSearch.searchDocumentSchema.array() }),
|
|
200
200
|
annotations: { effect: "write", requiresUserContext: true },
|
|
201
201
|
autoInheritable: false,
|
|
202
202
|
execute: async (args, signal) => this.runAddDocuments(args, signal),
|
|
203
203
|
});
|
|
204
204
|
registry.create_index = defineTool({
|
|
205
205
|
description: CREATE_INDEX_TOOL_DESCRIPTION,
|
|
206
|
-
schema:
|
|
206
|
+
schema: sharedSearch.createIndexRequestSchema,
|
|
207
207
|
annotations: { effect: "write", requiresUserContext: true },
|
|
208
208
|
autoInheritable: false,
|
|
209
209
|
execute: async (args, signal) => this.runCreateIndex(args, signal),
|
|
210
210
|
});
|
|
211
211
|
registry.sync_index = defineTool({
|
|
212
212
|
description: SYNC_INDEX_TOOL_DESCRIPTION,
|
|
213
|
-
schema:
|
|
213
|
+
schema: sharedSearch.syncIndexRequestSchema,
|
|
214
214
|
annotations: { effect: "write", requiresUserContext: true },
|
|
215
215
|
autoInheritable: false,
|
|
216
216
|
execute: async (args, signal) => this.runSyncIndex(args, signal),
|
|
@@ -266,7 +266,7 @@ export class SearchPlugin extends Plugin<SearchPluginConfig> implements ToolProv
|
|
|
266
266
|
string.trimToNull(process.env[ENDPOINT_ENV]) !== null ||
|
|
267
267
|
string.trimToNull(process.env.DATABRICKS_VECTOR_SEARCH_ENDPOINT) !== null;
|
|
268
268
|
if (hasEndpoint) return undefined;
|
|
269
|
-
const lake =
|
|
269
|
+
const lake = appkitPlugin.instance(this.context, lakebase);
|
|
270
270
|
if (!lake) return undefined;
|
|
271
271
|
logger.info("backend-lakebase", {
|
|
272
272
|
reason: "no Vector Search endpoint configured; using the Lakebase full-text fallback",
|
|
@@ -320,7 +320,7 @@ export class SearchPlugin extends Plugin<SearchPluginConfig> implements ToolProv
|
|
|
320
320
|
rowCount: info.rowCount ?? 0,
|
|
321
321
|
});
|
|
322
322
|
} catch (cause) {
|
|
323
|
-
logger.warn("ensure-failed", { index, message:
|
|
323
|
+
logger.warn("ensure-failed", { index, message: sharedError.errorMessage(cause) });
|
|
324
324
|
}
|
|
325
325
|
}
|
|
326
326
|
|
|
@@ -368,7 +368,7 @@ export class SearchPlugin extends Plugin<SearchPluginConfig> implements ToolProv
|
|
|
368
368
|
path: SEARCH_ROUTE,
|
|
369
369
|
handler: async (req, res) => {
|
|
370
370
|
await this.respond(res, "search", () => {
|
|
371
|
-
const request =
|
|
371
|
+
const request = sharedSearch.searchRequestSchema.parse(req.body ?? {});
|
|
372
372
|
return this.asUser(req).runSearch(request);
|
|
373
373
|
});
|
|
374
374
|
},
|
|
@@ -379,7 +379,7 @@ export class SearchPlugin extends Plugin<SearchPluginConfig> implements ToolProv
|
|
|
379
379
|
path: UNIVERSAL_ROUTE,
|
|
380
380
|
handler: async (req, res) => {
|
|
381
381
|
await this.respond(res, "universalSearch", () => {
|
|
382
|
-
const request =
|
|
382
|
+
const request = sharedSearch.universalSearchRequestSchema.parse(req.body ?? {});
|
|
383
383
|
return this.asUser(req).runUniversalSearch(request);
|
|
384
384
|
});
|
|
385
385
|
},
|
|
@@ -454,7 +454,7 @@ export class SearchPlugin extends Plugin<SearchPluginConfig> implements ToolProv
|
|
|
454
454
|
try {
|
|
455
455
|
res.json(await run());
|
|
456
456
|
} catch (cause) {
|
|
457
|
-
const message =
|
|
457
|
+
const message = sharedError.errorMessage(cause);
|
|
458
458
|
logger.warn("route-failed", { operation, message });
|
|
459
459
|
res.status(500).json({ error: message });
|
|
460
460
|
}
|
|
@@ -491,25 +491,25 @@ export class SearchPlugin extends Plugin<SearchPluginConfig> implements ToolProv
|
|
|
491
491
|
override exports() {
|
|
492
492
|
return {
|
|
493
493
|
/** Search one index (default when omitted). Runs as the current context user. */
|
|
494
|
-
search: (request:
|
|
494
|
+
search: (request: sharedSearch.SearchRequest, signal?: AbortSignal) =>
|
|
495
495
|
this.runSearch(request, signal),
|
|
496
496
|
/** Search across every configured index and merge the hits. */
|
|
497
|
-
universalSearch: (request:
|
|
497
|
+
universalSearch: (request: sharedSearch.UniversalSearchRequest, signal?: AbortSignal) =>
|
|
498
498
|
this.runUniversalSearch(request, signal),
|
|
499
499
|
/** Add or update documents in a direct-access index (throws when writes are disabled). */
|
|
500
500
|
addDocuments: (request: { index?: string; documents: unknown }, signal?: AbortSignal) =>
|
|
501
501
|
this.runAddDocuments(request, signal),
|
|
502
502
|
/** Create a Vector Search index (throws when writes are disabled). */
|
|
503
|
-
createIndex: (request:
|
|
503
|
+
createIndex: (request: sharedSearch.CreateIndexRequest, signal?: AbortSignal) =>
|
|
504
504
|
this.runCreateIndex(request, signal),
|
|
505
505
|
/** Sync a Delta Sync index from its source table (throws when writes are disabled). */
|
|
506
|
-
syncIndex: (request:
|
|
506
|
+
syncIndex: (request: sharedSearch.SyncIndexRequest, signal?: AbortSignal) =>
|
|
507
507
|
this.runSyncIndex(request, signal),
|
|
508
508
|
};
|
|
509
509
|
}
|
|
510
510
|
|
|
511
511
|
private async runSearch(args: unknown, signal?: AbortSignal) {
|
|
512
|
-
const request =
|
|
512
|
+
const request = sharedSearch.searchRequestSchema.parse(args);
|
|
513
513
|
const { client } = getSearchRuntime();
|
|
514
514
|
return client.search(request.query, {
|
|
515
515
|
...(request.index ? { index: request.index } : {}),
|
|
@@ -523,7 +523,7 @@ export class SearchPlugin extends Plugin<SearchPluginConfig> implements ToolProv
|
|
|
523
523
|
}
|
|
524
524
|
|
|
525
525
|
private async runUniversalSearch(args: unknown, signal?: AbortSignal) {
|
|
526
|
-
const request =
|
|
526
|
+
const request = sharedSearch.universalSearchRequestSchema.parse(args);
|
|
527
527
|
const { client } = getSearchRuntime();
|
|
528
528
|
return client.universalSearch(request.query, {
|
|
529
529
|
...(request.indexes ? { indexes: request.indexes } : {}),
|
|
@@ -542,13 +542,13 @@ export class SearchPlugin extends Plugin<SearchPluginConfig> implements ToolProv
|
|
|
542
542
|
}
|
|
543
543
|
|
|
544
544
|
private async runCreateIndex(args: unknown, signal?: AbortSignal) {
|
|
545
|
-
const request =
|
|
545
|
+
const request = sharedSearch.createIndexRequestSchema.parse(args);
|
|
546
546
|
const { client } = getSearchRuntime();
|
|
547
547
|
return client.createIndex(request.name, toCreateIndexOptions(request, signal));
|
|
548
548
|
}
|
|
549
549
|
|
|
550
550
|
private async runSyncIndex(args: unknown, signal?: AbortSignal) {
|
|
551
|
-
const request =
|
|
551
|
+
const request = sharedSearch.syncIndexRequestSchema.parse(args);
|
|
552
552
|
const { client, config } = getSearchRuntime();
|
|
553
553
|
const index = request.index ?? config.defaultIndex ?? "";
|
|
554
554
|
await client.syncIndex(index, signal);
|
|
@@ -562,12 +562,12 @@ export class SearchPlugin extends Plugin<SearchPluginConfig> implements ToolProv
|
|
|
562
562
|
* @example
|
|
563
563
|
* ```ts
|
|
564
564
|
* import { createApp, server } from "@databricks/appkit";
|
|
565
|
-
* import { plugin as searchPlugin, tool as
|
|
565
|
+
* import { plugin as searchPlugin, tool as searchToolApi } from "@dbx-tools/search";
|
|
566
566
|
* import { agents, plugin as mastraPlugin } from "@dbx-tools/appkit-mastra";
|
|
567
567
|
*
|
|
568
568
|
* const support = agents.createAgent({
|
|
569
569
|
* instructions: "Answer from the docs; use `search` to find them.",
|
|
570
|
-
* tools: () => ({ search:
|
|
570
|
+
* tools: () => ({ search: searchToolApi.searchTool() }),
|
|
571
571
|
* });
|
|
572
572
|
*
|
|
573
573
|
* await createApp({
|
package/src/tool.ts
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* @module
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import { search as
|
|
17
|
+
import { search as sharedSearch, type UpsertResult } from "@dbx-tools/shared-search";
|
|
18
18
|
import { createTool } from "@mastra/core/tools";
|
|
19
19
|
import { z } from "zod";
|
|
20
20
|
import { toCreateIndexOptions } from "./index-tools.ts";
|
|
@@ -102,16 +102,16 @@ export function universalSearchTool(options: SearchToolOptions = {}) {
|
|
|
102
102
|
* Only install it when the plugin's write surface is enabled.
|
|
103
103
|
*/
|
|
104
104
|
export function addDocumentsTool(options: SearchToolOptions = {}) {
|
|
105
|
-
const inputSchema =
|
|
105
|
+
const inputSchema = sharedSearch.searchDocumentSchema
|
|
106
106
|
.array()
|
|
107
107
|
.describe("Documents to add or update. Each must include the index primary key.");
|
|
108
108
|
return createTool({
|
|
109
109
|
id: options.id ?? "add_documents",
|
|
110
110
|
description: ADD_DOCUMENTS_TOOL_DESCRIPTION,
|
|
111
|
-
inputSchema:
|
|
111
|
+
inputSchema: sharedSearch.searchRequestSchema
|
|
112
112
|
.pick({ index: true })
|
|
113
113
|
.extend({ documents: inputSchema }),
|
|
114
|
-
outputSchema:
|
|
114
|
+
outputSchema: sharedSearch.upsertResultSchema,
|
|
115
115
|
execute: async (input, context): Promise<UpsertResult> => {
|
|
116
116
|
const { client, config } = getSearchRuntime();
|
|
117
117
|
const record = input as { index?: string; documents: unknown };
|