@dbx-tools/appkit-web-search 0.3.44 → 0.4.1
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 +32 -0
- package/lib/index.js +28 -0
- package/lib/src/allowlist.d.ts +66 -0
- package/lib/src/allowlist.js +113 -0
- package/lib/src/config.d.ts +233 -0
- package/lib/src/config.js +269 -0
- package/lib/src/defaults.d.ts +98 -0
- package/lib/src/defaults.js +96 -0
- package/lib/src/fetch.d.ts +27 -0
- package/lib/src/fetch.js +86 -0
- package/lib/src/html-text.d.ts +30 -0
- package/lib/src/html-text.js +66 -0
- package/lib/src/plugin.d.ts +162 -0
- package/lib/src/plugin.js +225 -0
- package/lib/src/provider.d.ts +62 -0
- package/lib/src/provider.js +89 -0
- package/lib/src/runtime.d.ts +61 -0
- package/lib/src/runtime.js +95 -0
- package/lib/src/schema.d.ts +76 -0
- package/lib/src/schema.js +102 -0
- package/lib/src/scrape.d.ts +29 -0
- package/lib/src/scrape.js +113 -0
- package/lib/src/search.d.ts +49 -0
- package/lib/src/search.js +252 -0
- package/lib/src/tool.d.ts +85 -0
- package/lib/src/tool.js +113 -0
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/package.json +13 -9
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider detection + web-search tool-spec mapping for the Databricks
|
|
3
|
+
* Model Serving native web-search tool.
|
|
4
|
+
*
|
|
5
|
+
* Databricks exposes web search as a first-party tool that runs *inside* a
|
|
6
|
+
* model call: the model searches the web and folds the results into its
|
|
7
|
+
* answer. The tool spec is provider-specific (see the Databricks docs,
|
|
8
|
+
* `machine-learning/model-serving/web-search`):
|
|
9
|
+
*
|
|
10
|
+
* - OpenAI GPT models, via the Responses API (`/serving-endpoints/responses`):
|
|
11
|
+
* `tools: [{ "type": "web_search" }]`
|
|
12
|
+
* - Google Gemini models, via Chat Completions
|
|
13
|
+
* (`/serving-endpoints/chat/completions`): `tools: [{ "google_search": {} }]`
|
|
14
|
+
*
|
|
15
|
+
* (Anthropic exposes it over MCP, which needs a different call shape; only
|
|
16
|
+
* GPT + Gemini are wired here, matching what the platform supports today.)
|
|
17
|
+
*
|
|
18
|
+
* The provider family is detected from the endpoint id the same way
|
|
19
|
+
* `@dbx-tools/shared-model`'s `classifyByFamily` keys off name substrings
|
|
20
|
+
* (`gpt` / `gemini` / `claude`), so a resolved endpoint like
|
|
21
|
+
* `databricks-gpt-5` or `databricks-gemini-3-pro` maps to its API shape.
|
|
22
|
+
*
|
|
23
|
+
* @module
|
|
24
|
+
*/
|
|
25
|
+
/** A web-search-capable model provider family. */
|
|
26
|
+
export type WebSearchProvider = "openai" | "gemini";
|
|
27
|
+
/** How a provider's native web-search call is shaped. */
|
|
28
|
+
export interface WebSearchProviderSpec {
|
|
29
|
+
/**
|
|
30
|
+
* Which serving REST surface to call. `"responses"` posts to
|
|
31
|
+
* `/serving-endpoints/responses` (OpenAI Responses API); `"chat"` posts to
|
|
32
|
+
* `/serving-endpoints/chat/completions`.
|
|
33
|
+
*/
|
|
34
|
+
api: "responses" | "chat";
|
|
35
|
+
/** The tool entry appended to the request's `tools` array. */
|
|
36
|
+
tool: Record<string, unknown>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Built-in provider -> tool-spec map. Operators can override or extend this
|
|
40
|
+
* per provider via the plugin's `webSearchTools` config (env
|
|
41
|
+
* `WEB_SEARCH_TOOLS`), which is merged over these defaults.
|
|
42
|
+
*/
|
|
43
|
+
export declare const WEB_SEARCH_PROVIDERS: Readonly<Record<WebSearchProvider, WebSearchProviderSpec>>;
|
|
44
|
+
/**
|
|
45
|
+
* Detect the web-search provider family for an endpoint id, or `null` when
|
|
46
|
+
* the model is not one of the web-search-capable families. Anthropic
|
|
47
|
+
* (`opus`/`sonnet`/`haiku`) is intentionally excluded - it needs an MCP call
|
|
48
|
+
* shape this module doesn't implement - so a Claude endpoint returns `null`
|
|
49
|
+
* and is treated as unsupported.
|
|
50
|
+
*/
|
|
51
|
+
export declare function detectWebSearchProvider(modelId: string): WebSearchProvider | null;
|
|
52
|
+
/** Whether `modelId` is a web-search-capable model. */
|
|
53
|
+
export declare function supportsWebSearch(modelId: string): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Resolve the effective {@link WebSearchProviderSpec} for a provider: the
|
|
56
|
+
* built-in default, with any operator override (the `webSearchTools` map,
|
|
57
|
+
* keyed by provider) shallow-merged over it. An override may replace just the
|
|
58
|
+
* `tool` (the common case - a new tool type) or also the `api`. An override
|
|
59
|
+
* that is not one of those two fields is a deployment mistake that would
|
|
60
|
+
* otherwise be silently dropped, so it throws.
|
|
61
|
+
*/
|
|
62
|
+
export declare function webSearchToolSpec(provider: WebSearchProvider, overrides?: Record<string, unknown>): WebSearchProviderSpec;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider detection + web-search tool-spec mapping for the Databricks
|
|
3
|
+
* Model Serving native web-search tool.
|
|
4
|
+
*
|
|
5
|
+
* Databricks exposes web search as a first-party tool that runs *inside* a
|
|
6
|
+
* model call: the model searches the web and folds the results into its
|
|
7
|
+
* answer. The tool spec is provider-specific (see the Databricks docs,
|
|
8
|
+
* `machine-learning/model-serving/web-search`):
|
|
9
|
+
*
|
|
10
|
+
* - OpenAI GPT models, via the Responses API (`/serving-endpoints/responses`):
|
|
11
|
+
* `tools: [{ "type": "web_search" }]`
|
|
12
|
+
* - Google Gemini models, via Chat Completions
|
|
13
|
+
* (`/serving-endpoints/chat/completions`): `tools: [{ "google_search": {} }]`
|
|
14
|
+
*
|
|
15
|
+
* (Anthropic exposes it over MCP, which needs a different call shape; only
|
|
16
|
+
* GPT + Gemini are wired here, matching what the platform supports today.)
|
|
17
|
+
*
|
|
18
|
+
* The provider family is detected from the endpoint id the same way
|
|
19
|
+
* `@dbx-tools/shared-model`'s `classifyByFamily` keys off name substrings
|
|
20
|
+
* (`gpt` / `gemini` / `claude`), so a resolved endpoint like
|
|
21
|
+
* `databricks-gpt-5` or `databricks-gemini-3-pro` maps to its API shape.
|
|
22
|
+
*
|
|
23
|
+
* @module
|
|
24
|
+
*/
|
|
25
|
+
import { ValidationError } from "@databricks/appkit";
|
|
26
|
+
import { z } from "zod";
|
|
27
|
+
/**
|
|
28
|
+
* Built-in provider -> tool-spec map. Operators can override or extend this
|
|
29
|
+
* per provider via the plugin's `webSearchTools` config (env
|
|
30
|
+
* `WEB_SEARCH_TOOLS`), which is merged over these defaults.
|
|
31
|
+
*/
|
|
32
|
+
export const WEB_SEARCH_PROVIDERS = {
|
|
33
|
+
openai: { api: "responses", tool: { type: "web_search" } },
|
|
34
|
+
gemini: { api: "chat", tool: { google_search: {} } },
|
|
35
|
+
};
|
|
36
|
+
/**
|
|
37
|
+
* Detect the web-search provider family for an endpoint id, or `null` when
|
|
38
|
+
* the model is not one of the web-search-capable families. Anthropic
|
|
39
|
+
* (`opus`/`sonnet`/`haiku`) is intentionally excluded - it needs an MCP call
|
|
40
|
+
* shape this module doesn't implement - so a Claude endpoint returns `null`
|
|
41
|
+
* and is treated as unsupported.
|
|
42
|
+
*/
|
|
43
|
+
export function detectWebSearchProvider(modelId) {
|
|
44
|
+
const n = modelId.toLowerCase();
|
|
45
|
+
// gpt-oss open-weights don't carry the hosted web-search tool; only the
|
|
46
|
+
// hosted GPT family (Responses API) does. Both contain "gpt", so exclude
|
|
47
|
+
// the open-weights explicitly.
|
|
48
|
+
if (n.includes("gpt") && !n.includes("gpt-oss"))
|
|
49
|
+
return "openai";
|
|
50
|
+
if (n.includes("gemini"))
|
|
51
|
+
return "gemini";
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
/** Whether `modelId` is a web-search-capable model. */
|
|
55
|
+
export function supportsWebSearch(modelId) {
|
|
56
|
+
return detectWebSearchProvider(modelId) !== null;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Runtime shape of one entry in the operator override map. The map arrives as
|
|
60
|
+
* parsed JSON (config or `WEB_SEARCH_TOOLS`), so it is validated rather than
|
|
61
|
+
* asserted.
|
|
62
|
+
*/
|
|
63
|
+
const providerOverrideSchema = z.object({
|
|
64
|
+
api: z.enum(["responses", "chat"]).optional(),
|
|
65
|
+
tool: z.record(z.string(), z.unknown()).optional(),
|
|
66
|
+
});
|
|
67
|
+
/**
|
|
68
|
+
* Resolve the effective {@link WebSearchProviderSpec} for a provider: the
|
|
69
|
+
* built-in default, with any operator override (the `webSearchTools` map,
|
|
70
|
+
* keyed by provider) shallow-merged over it. An override may replace just the
|
|
71
|
+
* `tool` (the common case - a new tool type) or also the `api`. An override
|
|
72
|
+
* that is not one of those two fields is a deployment mistake that would
|
|
73
|
+
* otherwise be silently dropped, so it throws.
|
|
74
|
+
*/
|
|
75
|
+
export function webSearchToolSpec(provider, overrides) {
|
|
76
|
+
const base = WEB_SEARCH_PROVIDERS[provider];
|
|
77
|
+
const raw = overrides?.[provider];
|
|
78
|
+
if (raw === undefined)
|
|
79
|
+
return base;
|
|
80
|
+
const parsed = providerOverrideSchema.safeParse(raw);
|
|
81
|
+
if (!parsed.success) {
|
|
82
|
+
throw ValidationError.invalidValue(`webSearchTools.${provider}`, raw, 'an object with an optional "api" ("responses" | "chat") and an optional "tool" object');
|
|
83
|
+
}
|
|
84
|
+
return {
|
|
85
|
+
api: parsed.data.api ?? base.api,
|
|
86
|
+
tool: parsed.data.tool ?? base.tool,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvdmlkZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcHJvdmlkZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBdUJHO0FBRUgsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3JELE9BQU8sRUFBRSxDQUFDLEVBQUUsTUFBTSxLQUFLLENBQUM7QUFpQnhCOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBK0Q7SUFDOUYsTUFBTSxFQUFFLEVBQUUsR0FBRyxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUFFLEVBQUU7SUFDMUQsTUFBTSxFQUFFLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsRUFBRSxhQUFhLEVBQUUsRUFBRSxFQUFFLEVBQUU7Q0FDckQsQ0FBQztBQUVGOzs7Ozs7R0FNRztBQUNILE1BQU0sVUFBVSx1QkFBdUIsQ0FBQyxPQUFlO0lBQ3JELE1BQU0sQ0FBQyxHQUFHLE9BQU8sQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUNoQyx3RUFBd0U7SUFDeEUseUVBQXlFO0lBQ3pFLCtCQUErQjtJQUMvQixJQUFJLENBQUMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQztRQUFFLE9BQU8sUUFBUSxDQUFDO0lBQ2pFLElBQUksQ0FBQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUM7UUFBRSxPQUFPLFFBQVEsQ0FBQztJQUMxQyxPQUFPLElBQUksQ0FBQztBQUNkLENBQUM7QUFFRCx1REFBdUQ7QUFDdkQsTUFBTSxVQUFVLGlCQUFpQixDQUFDLE9BQWU7SUFDL0MsT0FBTyx1QkFBdUIsQ0FBQyxPQUFPLENBQUMsS0FBSyxJQUFJLENBQUM7QUFDbkQsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLHNCQUFzQixHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUM7SUFDdEMsR0FBRyxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxXQUFXLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxRQUFRLEVBQUU7SUFDN0MsSUFBSSxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLFFBQVEsRUFBRTtDQUNuRCxDQUFDLENBQUM7QUFFSDs7Ozs7OztHQU9HO0FBQ0gsTUFBTSxVQUFVLGlCQUFpQixDQUMvQixRQUEyQixFQUMzQixTQUFtQztJQUVuQyxNQUFNLElBQUksR0FBRyxvQkFBb0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUM1QyxNQUFNLEdBQUcsR0FBRyxTQUFTLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNsQyxJQUFJLEdBQUcsS0FBSyxTQUFTO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFDbkMsTUFBTSxNQUFNLEdBQUcsc0JBQXNCLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDO0lBQ3JELElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDcEIsTUFBTSxlQUFlLENBQUMsWUFBWSxDQUNoQyxrQkFBa0IsUUFBUSxFQUFFLEVBQzVCLEdBQUcsRUFDSCx1RkFBdUYsQ0FDeEYsQ0FBQztJQUNKLENBQUM7SUFDRCxPQUFPO1FBQ0wsR0FBRyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLElBQUksQ0FBQyxHQUFHO1FBQ2hDLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsSUFBSTtLQUNwQyxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogUHJvdmlkZXIgZGV0ZWN0aW9uICsgd2ViLXNlYXJjaCB0b29sLXNwZWMgbWFwcGluZyBmb3IgdGhlIERhdGFicmlja3NcbiAqIE1vZGVsIFNlcnZpbmcgbmF0aXZlIHdlYi1zZWFyY2ggdG9vbC5cbiAqXG4gKiBEYXRhYnJpY2tzIGV4cG9zZXMgd2ViIHNlYXJjaCBhcyBhIGZpcnN0LXBhcnR5IHRvb2wgdGhhdCBydW5zICppbnNpZGUqIGFcbiAqIG1vZGVsIGNhbGw6IHRoZSBtb2RlbCBzZWFyY2hlcyB0aGUgd2ViIGFuZCBmb2xkcyB0aGUgcmVzdWx0cyBpbnRvIGl0c1xuICogYW5zd2VyLiBUaGUgdG9vbCBzcGVjIGlzIHByb3ZpZGVyLXNwZWNpZmljIChzZWUgdGhlIERhdGFicmlja3MgZG9jcyxcbiAqIGBtYWNoaW5lLWxlYXJuaW5nL21vZGVsLXNlcnZpbmcvd2ViLXNlYXJjaGApOlxuICpcbiAqIC0gT3BlbkFJIEdQVCBtb2RlbHMsIHZpYSB0aGUgUmVzcG9uc2VzIEFQSSAoYC9zZXJ2aW5nLWVuZHBvaW50cy9yZXNwb25zZXNgKTpcbiAqICAgYHRvb2xzOiBbeyBcInR5cGVcIjogXCJ3ZWJfc2VhcmNoXCIgfV1gXG4gKiAtIEdvb2dsZSBHZW1pbmkgbW9kZWxzLCB2aWEgQ2hhdCBDb21wbGV0aW9uc1xuICogICAoYC9zZXJ2aW5nLWVuZHBvaW50cy9jaGF0L2NvbXBsZXRpb25zYCk6IGB0b29sczogW3sgXCJnb29nbGVfc2VhcmNoXCI6IHt9IH1dYFxuICpcbiAqIChBbnRocm9waWMgZXhwb3NlcyBpdCBvdmVyIE1DUCwgd2hpY2ggbmVlZHMgYSBkaWZmZXJlbnQgY2FsbCBzaGFwZTsgb25seVxuICogR1BUICsgR2VtaW5pIGFyZSB3aXJlZCBoZXJlLCBtYXRjaGluZyB3aGF0IHRoZSBwbGF0Zm9ybSBzdXBwb3J0cyB0b2RheS4pXG4gKlxuICogVGhlIHByb3ZpZGVyIGZhbWlseSBpcyBkZXRlY3RlZCBmcm9tIHRoZSBlbmRwb2ludCBpZCB0aGUgc2FtZSB3YXlcbiAqIGBAZGJ4LXRvb2xzL3NoYXJlZC1tb2RlbGAncyBgY2xhc3NpZnlCeUZhbWlseWAga2V5cyBvZmYgbmFtZSBzdWJzdHJpbmdzXG4gKiAoYGdwdGAgLyBgZ2VtaW5pYCAvIGBjbGF1ZGVgKSwgc28gYSByZXNvbHZlZCBlbmRwb2ludCBsaWtlXG4gKiBgZGF0YWJyaWNrcy1ncHQtNWAgb3IgYGRhdGFicmlja3MtZ2VtaW5pLTMtcHJvYCBtYXBzIHRvIGl0cyBBUEkgc2hhcGUuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IFZhbGlkYXRpb25FcnJvciB9IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbmltcG9ydCB7IHogfSBmcm9tIFwiem9kXCI7XG5cbi8qKiBBIHdlYi1zZWFyY2gtY2FwYWJsZSBtb2RlbCBwcm92aWRlciBmYW1pbHkuICovXG5leHBvcnQgdHlwZSBXZWJTZWFyY2hQcm92aWRlciA9IFwib3BlbmFpXCIgfCBcImdlbWluaVwiO1xuXG4vKiogSG93IGEgcHJvdmlkZXIncyBuYXRpdmUgd2ViLXNlYXJjaCBjYWxsIGlzIHNoYXBlZC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgV2ViU2VhcmNoUHJvdmlkZXJTcGVjIHtcbiAgLyoqXG4gICAqIFdoaWNoIHNlcnZpbmcgUkVTVCBzdXJmYWNlIHRvIGNhbGwuIGBcInJlc3BvbnNlc1wiYCBwb3N0cyB0b1xuICAgKiBgL3NlcnZpbmctZW5kcG9pbnRzL3Jlc3BvbnNlc2AgKE9wZW5BSSBSZXNwb25zZXMgQVBJKTsgYFwiY2hhdFwiYCBwb3N0cyB0b1xuICAgKiBgL3NlcnZpbmctZW5kcG9pbnRzL2NoYXQvY29tcGxldGlvbnNgLlxuICAgKi9cbiAgYXBpOiBcInJlc3BvbnNlc1wiIHwgXCJjaGF0XCI7XG4gIC8qKiBUaGUgdG9vbCBlbnRyeSBhcHBlbmRlZCB0byB0aGUgcmVxdWVzdCdzIGB0b29sc2AgYXJyYXkuICovXG4gIHRvb2w6IFJlY29yZDxzdHJpbmcsIHVua25vd24+O1xufVxuXG4vKipcbiAqIEJ1aWx0LWluIHByb3ZpZGVyIC0+IHRvb2wtc3BlYyBtYXAuIE9wZXJhdG9ycyBjYW4gb3ZlcnJpZGUgb3IgZXh0ZW5kIHRoaXNcbiAqIHBlciBwcm92aWRlciB2aWEgdGhlIHBsdWdpbidzIGB3ZWJTZWFyY2hUb29sc2AgY29uZmlnIChlbnZcbiAqIGBXRUJfU0VBUkNIX1RPT0xTYCksIHdoaWNoIGlzIG1lcmdlZCBvdmVyIHRoZXNlIGRlZmF1bHRzLlxuICovXG5leHBvcnQgY29uc3QgV0VCX1NFQVJDSF9QUk9WSURFUlM6IFJlYWRvbmx5PFJlY29yZDxXZWJTZWFyY2hQcm92aWRlciwgV2ViU2VhcmNoUHJvdmlkZXJTcGVjPj4gPSB7XG4gIG9wZW5haTogeyBhcGk6IFwicmVzcG9uc2VzXCIsIHRvb2w6IHsgdHlwZTogXCJ3ZWJfc2VhcmNoXCIgfSB9LFxuICBnZW1pbmk6IHsgYXBpOiBcImNoYXRcIiwgdG9vbDogeyBnb29nbGVfc2VhcmNoOiB7fSB9IH0sXG59O1xuXG4vKipcbiAqIERldGVjdCB0aGUgd2ViLXNlYXJjaCBwcm92aWRlciBmYW1pbHkgZm9yIGFuIGVuZHBvaW50IGlkLCBvciBgbnVsbGAgd2hlblxuICogdGhlIG1vZGVsIGlzIG5vdCBvbmUgb2YgdGhlIHdlYi1zZWFyY2gtY2FwYWJsZSBmYW1pbGllcy4gQW50aHJvcGljXG4gKiAoYG9wdXNgL2Bzb25uZXRgL2BoYWlrdWApIGlzIGludGVudGlvbmFsbHkgZXhjbHVkZWQgLSBpdCBuZWVkcyBhbiBNQ1AgY2FsbFxuICogc2hhcGUgdGhpcyBtb2R1bGUgZG9lc24ndCBpbXBsZW1lbnQgLSBzbyBhIENsYXVkZSBlbmRwb2ludCByZXR1cm5zIGBudWxsYFxuICogYW5kIGlzIHRyZWF0ZWQgYXMgdW5zdXBwb3J0ZWQuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBkZXRlY3RXZWJTZWFyY2hQcm92aWRlcihtb2RlbElkOiBzdHJpbmcpOiBXZWJTZWFyY2hQcm92aWRlciB8IG51bGwge1xuICBjb25zdCBuID0gbW9kZWxJZC50b0xvd2VyQ2FzZSgpO1xuICAvLyBncHQtb3NzIG9wZW4td2VpZ2h0cyBkb24ndCBjYXJyeSB0aGUgaG9zdGVkIHdlYi1zZWFyY2ggdG9vbDsgb25seSB0aGVcbiAgLy8gaG9zdGVkIEdQVCBmYW1pbHkgKFJlc3BvbnNlcyBBUEkpIGRvZXMuIEJvdGggY29udGFpbiBcImdwdFwiLCBzbyBleGNsdWRlXG4gIC8vIHRoZSBvcGVuLXdlaWdodHMgZXhwbGljaXRseS5cbiAgaWYgKG4uaW5jbHVkZXMoXCJncHRcIikgJiYgIW4uaW5jbHVkZXMoXCJncHQtb3NzXCIpKSByZXR1cm4gXCJvcGVuYWlcIjtcbiAgaWYgKG4uaW5jbHVkZXMoXCJnZW1pbmlcIikpIHJldHVybiBcImdlbWluaVwiO1xuICByZXR1cm4gbnVsbDtcbn1cblxuLyoqIFdoZXRoZXIgYG1vZGVsSWRgIGlzIGEgd2ViLXNlYXJjaC1jYXBhYmxlIG1vZGVsLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN1cHBvcnRzV2ViU2VhcmNoKG1vZGVsSWQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICByZXR1cm4gZGV0ZWN0V2ViU2VhcmNoUHJvdmlkZXIobW9kZWxJZCkgIT09IG51bGw7XG59XG5cbi8qKlxuICogUnVudGltZSBzaGFwZSBvZiBvbmUgZW50cnkgaW4gdGhlIG9wZXJhdG9yIG92ZXJyaWRlIG1hcC4gVGhlIG1hcCBhcnJpdmVzIGFzXG4gKiBwYXJzZWQgSlNPTiAoY29uZmlnIG9yIGBXRUJfU0VBUkNIX1RPT0xTYCksIHNvIGl0IGlzIHZhbGlkYXRlZCByYXRoZXIgdGhhblxuICogYXNzZXJ0ZWQuXG4gKi9cbmNvbnN0IHByb3ZpZGVyT3ZlcnJpZGVTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIGFwaTogei5lbnVtKFtcInJlc3BvbnNlc1wiLCBcImNoYXRcIl0pLm9wdGlvbmFsKCksXG4gIHRvb2w6IHoucmVjb3JkKHouc3RyaW5nKCksIHoudW5rbm93bigpKS5vcHRpb25hbCgpLFxufSk7XG5cbi8qKlxuICogUmVzb2x2ZSB0aGUgZWZmZWN0aXZlIHtAbGluayBXZWJTZWFyY2hQcm92aWRlclNwZWN9IGZvciBhIHByb3ZpZGVyOiB0aGVcbiAqIGJ1aWx0LWluIGRlZmF1bHQsIHdpdGggYW55IG9wZXJhdG9yIG92ZXJyaWRlICh0aGUgYHdlYlNlYXJjaFRvb2xzYCBtYXAsXG4gKiBrZXllZCBieSBwcm92aWRlcikgc2hhbGxvdy1tZXJnZWQgb3ZlciBpdC4gQW4gb3ZlcnJpZGUgbWF5IHJlcGxhY2UganVzdCB0aGVcbiAqIGB0b29sYCAodGhlIGNvbW1vbiBjYXNlIC0gYSBuZXcgdG9vbCB0eXBlKSBvciBhbHNvIHRoZSBgYXBpYC4gQW4gb3ZlcnJpZGVcbiAqIHRoYXQgaXMgbm90IG9uZSBvZiB0aG9zZSB0d28gZmllbGRzIGlzIGEgZGVwbG95bWVudCBtaXN0YWtlIHRoYXQgd291bGRcbiAqIG90aGVyd2lzZSBiZSBzaWxlbnRseSBkcm9wcGVkLCBzbyBpdCB0aHJvd3MuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB3ZWJTZWFyY2hUb29sU3BlYyhcbiAgcHJvdmlkZXI6IFdlYlNlYXJjaFByb3ZpZGVyLFxuICBvdmVycmlkZXM/OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPixcbik6IFdlYlNlYXJjaFByb3ZpZGVyU3BlYyB7XG4gIGNvbnN0IGJhc2UgPSBXRUJfU0VBUkNIX1BST1ZJREVSU1twcm92aWRlcl07XG4gIGNvbnN0IHJhdyA9IG92ZXJyaWRlcz8uW3Byb3ZpZGVyXTtcbiAgaWYgKHJhdyA9PT0gdW5kZWZpbmVkKSByZXR1cm4gYmFzZTtcbiAgY29uc3QgcGFyc2VkID0gcHJvdmlkZXJPdmVycmlkZVNjaGVtYS5zYWZlUGFyc2UocmF3KTtcbiAgaWYgKCFwYXJzZWQuc3VjY2Vzcykge1xuICAgIHRocm93IFZhbGlkYXRpb25FcnJvci5pbnZhbGlkVmFsdWUoXG4gICAgICBgd2ViU2VhcmNoVG9vbHMuJHtwcm92aWRlcn1gLFxuICAgICAgcmF3LFxuICAgICAgJ2FuIG9iamVjdCB3aXRoIGFuIG9wdGlvbmFsIFwiYXBpXCIgKFwicmVzcG9uc2VzXCIgfCBcImNoYXRcIikgYW5kIGFuIG9wdGlvbmFsIFwidG9vbFwiIG9iamVjdCcsXG4gICAgKTtcbiAgfVxuICByZXR1cm4ge1xuICAgIGFwaTogcGFyc2VkLmRhdGEuYXBpID8/IGJhc2UuYXBpLFxuICAgIHRvb2w6IHBhcnNlZC5kYXRhLnRvb2wgPz8gYmFzZS50b29sLFxuICB9O1xufVxuIl19
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The web-search runtime: a lazily-resolved, process-wide config shared by
|
|
3
|
+
* the plugin and the `web_search` / `web_fetch` tools, so both read one
|
|
4
|
+
* resolved allow-list / cap / timeout set. The first caller (normally the
|
|
5
|
+
* plugin at setup) primes it from the plugin's config; later callers (the
|
|
6
|
+
* tools' `execute`) reuse it.
|
|
7
|
+
*
|
|
8
|
+
* The runtime also carries the {@link WebSearchExecutor} every outbound call
|
|
9
|
+
* runs through. The plugin installs its own `execute()` there at setup, which
|
|
10
|
+
* is how the tools - plain functions with no plugin instance in scope - still
|
|
11
|
+
* get AppKit's cache / retry / timeout / telemetry chain. Without a
|
|
12
|
+
* registered plugin (a direct call from a script or a test) the calls still
|
|
13
|
+
* run, just without interceptors.
|
|
14
|
+
*
|
|
15
|
+
* Unlike the email runtime there is no connection to pool - the backend is
|
|
16
|
+
* stateless HTTP per call - so the runtime holds only the resolved config and
|
|
17
|
+
* that executor.
|
|
18
|
+
*
|
|
19
|
+
* @module
|
|
20
|
+
*/
|
|
21
|
+
import { type ExecutionResult } from "@databricks/appkit";
|
|
22
|
+
import { type ResolvedWebSearchConfig, type WebSearchPluginConfig } from "./config.js";
|
|
23
|
+
import type { WebSearchExecutionSettings } from "./defaults.js";
|
|
24
|
+
/**
|
|
25
|
+
* Runs one outbound call through AppKit's interceptor chain. Matches
|
|
26
|
+
* `Plugin.execute()`, which never throws: a failure comes back as
|
|
27
|
+
* `{ ok: false }`.
|
|
28
|
+
*/
|
|
29
|
+
export type WebSearchExecutor = <T>(fn: (signal?: AbortSignal) => Promise<T>, settings: WebSearchExecutionSettings) => Promise<ExecutionResult<T>>;
|
|
30
|
+
/** The shared resolved config plus the executor outbound calls run through. */
|
|
31
|
+
export interface WebSearchRuntime {
|
|
32
|
+
config: ResolvedWebSearchConfig;
|
|
33
|
+
execute: WebSearchExecutor;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Return the shared runtime, building it on first use from the supplied
|
|
37
|
+
* config layered over environment defaults. Overrides are only read when the
|
|
38
|
+
* runtime is first created, so prime it from the plugin's config at setup;
|
|
39
|
+
* subsequent calls (the tools' `execute`) pass nothing and get the same
|
|
40
|
+
* instance.
|
|
41
|
+
*/
|
|
42
|
+
export declare function getWebSearchRuntime(overrides?: WebSearchPluginConfig): WebSearchRuntime;
|
|
43
|
+
/**
|
|
44
|
+
* Install the executor outbound calls run through. The plugin calls this at
|
|
45
|
+
* setup with its own `execute()`; a second call replaces the previous one, so
|
|
46
|
+
* a re-registered plugin does not leave the tools bound to a dead instance.
|
|
47
|
+
*/
|
|
48
|
+
export declare function setWebSearchExecutor(execute: WebSearchExecutor): void;
|
|
49
|
+
/** Drop the memoized runtime so the next {@link getWebSearchRuntime} rebuilds it. */
|
|
50
|
+
export declare function resetWebSearchRuntime(): void;
|
|
51
|
+
/**
|
|
52
|
+
* Run one idempotent read through the shared executor and unwrap it.
|
|
53
|
+
*
|
|
54
|
+
* `execute()` never throws, so a failed call arrives as `{ ok: false }` with
|
|
55
|
+
* a status the interceptors already sanitized; it is logged here and re-raised
|
|
56
|
+
* as a stable {@link ExecutionError} so an upstream message never becomes the
|
|
57
|
+
* caller's error text. `signal` is the caller's own cancellation (an agent
|
|
58
|
+
* run, a request teardown); it is merged with the signal the timeout
|
|
59
|
+
* interceptor supplies so either one unwinds the I/O.
|
|
60
|
+
*/
|
|
61
|
+
export declare function executeRead<T>(operation: string, settings: WebSearchExecutionSettings, fn: (signal?: AbortSignal) => Promise<T>, signal?: AbortSignal): Promise<T>;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The web-search runtime: a lazily-resolved, process-wide config shared by
|
|
3
|
+
* the plugin and the `web_search` / `web_fetch` tools, so both read one
|
|
4
|
+
* resolved allow-list / cap / timeout set. The first caller (normally the
|
|
5
|
+
* plugin at setup) primes it from the plugin's config; later callers (the
|
|
6
|
+
* tools' `execute`) reuse it.
|
|
7
|
+
*
|
|
8
|
+
* The runtime also carries the {@link WebSearchExecutor} every outbound call
|
|
9
|
+
* runs through. The plugin installs its own `execute()` there at setup, which
|
|
10
|
+
* is how the tools - plain functions with no plugin instance in scope - still
|
|
11
|
+
* get AppKit's cache / retry / timeout / telemetry chain. Without a
|
|
12
|
+
* registered plugin (a direct call from a script or a test) the calls still
|
|
13
|
+
* run, just without interceptors.
|
|
14
|
+
*
|
|
15
|
+
* Unlike the email runtime there is no connection to pool - the backend is
|
|
16
|
+
* stateless HTTP per call - so the runtime holds only the resolved config and
|
|
17
|
+
* that executor.
|
|
18
|
+
*
|
|
19
|
+
* @module
|
|
20
|
+
*/
|
|
21
|
+
import { AppKitError, ExecutionError } from "@databricks/appkit";
|
|
22
|
+
import { async, error, log } from "@dbx-tools/shared-core";
|
|
23
|
+
import { resolveWebSearchConfig, } from "./config.js";
|
|
24
|
+
const logger = log.logger("web-search/runtime");
|
|
25
|
+
/**
|
|
26
|
+
* Executor used until (or unless) the plugin installs its own: run the call
|
|
27
|
+
* directly, mapping a throw onto the same {@link ExecutionResult} shape so
|
|
28
|
+
* call sites branch on `ok` either way.
|
|
29
|
+
*/
|
|
30
|
+
const directExecute = async (fn) => {
|
|
31
|
+
try {
|
|
32
|
+
return { ok: true, data: await fn() };
|
|
33
|
+
}
|
|
34
|
+
catch (err) {
|
|
35
|
+
return {
|
|
36
|
+
ok: false,
|
|
37
|
+
status: err instanceof AppKitError ? err.statusCode : 500,
|
|
38
|
+
message: error.errorMessage(err),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
let runtime;
|
|
43
|
+
/**
|
|
44
|
+
* Return the shared runtime, building it on first use from the supplied
|
|
45
|
+
* config layered over environment defaults. Overrides are only read when the
|
|
46
|
+
* runtime is first created, so prime it from the plugin's config at setup;
|
|
47
|
+
* subsequent calls (the tools' `execute`) pass nothing and get the same
|
|
48
|
+
* instance.
|
|
49
|
+
*/
|
|
50
|
+
export function getWebSearchRuntime(overrides) {
|
|
51
|
+
if (!runtime) {
|
|
52
|
+
runtime = { config: resolveWebSearchConfig(overrides), execute: directExecute };
|
|
53
|
+
}
|
|
54
|
+
return runtime;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Install the executor outbound calls run through. The plugin calls this at
|
|
58
|
+
* setup with its own `execute()`; a second call replaces the previous one, so
|
|
59
|
+
* a re-registered plugin does not leave the tools bound to a dead instance.
|
|
60
|
+
*/
|
|
61
|
+
export function setWebSearchExecutor(execute) {
|
|
62
|
+
getWebSearchRuntime().execute = execute;
|
|
63
|
+
}
|
|
64
|
+
/** Drop the memoized runtime so the next {@link getWebSearchRuntime} rebuilds it. */
|
|
65
|
+
export function resetWebSearchRuntime() {
|
|
66
|
+
runtime = undefined;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Run one idempotent read through the shared executor and unwrap it.
|
|
70
|
+
*
|
|
71
|
+
* `execute()` never throws, so a failed call arrives as `{ ok: false }` with
|
|
72
|
+
* a status the interceptors already sanitized; it is logged here and re-raised
|
|
73
|
+
* as a stable {@link ExecutionError} so an upstream message never becomes the
|
|
74
|
+
* caller's error text. `signal` is the caller's own cancellation (an agent
|
|
75
|
+
* run, a request teardown); it is merged with the signal the timeout
|
|
76
|
+
* interceptor supplies so either one unwinds the I/O.
|
|
77
|
+
*/
|
|
78
|
+
export async function executeRead(operation, settings, fn, signal) {
|
|
79
|
+
const { execute } = getWebSearchRuntime();
|
|
80
|
+
const result = await execute((executeSignal) => fn(async.combineAbortSignals(executeSignal, signal)), settings);
|
|
81
|
+
if (result.ok)
|
|
82
|
+
return result.data;
|
|
83
|
+
// A caller that cancelled is not a failure worth reporting as one.
|
|
84
|
+
if (signal?.aborted)
|
|
85
|
+
throw ExecutionError.canceled();
|
|
86
|
+
logger.warn("execution-failed", {
|
|
87
|
+
operation,
|
|
88
|
+
status: result.status,
|
|
89
|
+
error: result.message,
|
|
90
|
+
});
|
|
91
|
+
throw new ExecutionError(`web-search: ${operation} failed`, {
|
|
92
|
+
context: { operation, status: result.status },
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVudGltZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydW50aW1lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBbUJHO0FBRUgsT0FBTyxFQUFFLFdBQVcsRUFBRSxjQUFjLEVBQXdCLE1BQU0sb0JBQW9CLENBQUM7QUFDdkYsT0FBTyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDM0QsT0FBTyxFQUNMLHNCQUFzQixHQUd2QixNQUFNLFVBQVUsQ0FBQztBQUdsQixNQUFNLE1BQU0sR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDLG9CQUFvQixDQUFDLENBQUM7QUFrQmhEOzs7O0dBSUc7QUFDSCxNQUFNLGFBQWEsR0FBc0IsS0FBSyxFQUFFLEVBQUUsRUFBRSxFQUFFO0lBQ3BELElBQUksQ0FBQztRQUNILE9BQU8sRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDeEMsQ0FBQztJQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7UUFDYixPQUFPO1lBQ0wsRUFBRSxFQUFFLEtBQUs7WUFDVCxNQUFNLEVBQUUsR0FBRyxZQUFZLFdBQVcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsR0FBRztZQUN6RCxPQUFPLEVBQUUsS0FBSyxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUM7U0FDakMsQ0FBQztJQUNKLENBQUM7QUFDSCxDQUFDLENBQUM7QUFFRixJQUFJLE9BQXFDLENBQUM7QUFFMUM7Ozs7OztHQU1HO0FBQ0gsTUFBTSxVQUFVLG1CQUFtQixDQUFDLFNBQWlDO0lBQ25FLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNiLE9BQU8sR0FBRyxFQUFFLE1BQU0sRUFBRSxzQkFBc0IsQ0FBQyxTQUFTLENBQUMsRUFBRSxPQUFPLEVBQUUsYUFBYSxFQUFFLENBQUM7SUFDbEYsQ0FBQztJQUNELE9BQU8sT0FBTyxDQUFDO0FBQ2pCLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLG9CQUFvQixDQUFDLE9BQTBCO0lBQzdELG1CQUFtQixFQUFFLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztBQUMxQyxDQUFDO0FBRUQscUZBQXFGO0FBQ3JGLE1BQU0sVUFBVSxxQkFBcUI7SUFDbkMsT0FBTyxHQUFHLFNBQVMsQ0FBQztBQUN0QixDQUFDO0FBRUQ7Ozs7Ozs7OztHQVNHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxXQUFXLENBQy9CLFNBQWlCLEVBQ2pCLFFBQW9DLEVBQ3BDLEVBQXdDLEVBQ3hDLE1BQW9CO0lBRXBCLE1BQU0sRUFBRSxPQUFPLEVBQUUsR0FBRyxtQkFBbUIsRUFBRSxDQUFDO0lBQzFDLE1BQU0sTUFBTSxHQUFHLE1BQU0sT0FBTyxDQUMxQixDQUFDLGFBQWEsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxtQkFBbUIsQ0FBQyxhQUFhLEVBQUUsTUFBTSxDQUFDLENBQUMsRUFDdkUsUUFBUSxDQUNULENBQUM7SUFDRixJQUFJLE1BQU0sQ0FBQyxFQUFFO1FBQUUsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDO0lBQ2xDLG1FQUFtRTtJQUNuRSxJQUFJLE1BQU0sRUFBRSxPQUFPO1FBQUUsTUFBTSxjQUFjLENBQUMsUUFBUSxFQUFFLENBQUM7SUFDckQsTUFBTSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRTtRQUM5QixTQUFTO1FBQ1QsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNO1FBQ3JCLEtBQUssRUFBRSxNQUFNLENBQUMsT0FBTztLQUN0QixDQUFDLENBQUM7SUFDSCxNQUFNLElBQUksY0FBYyxDQUFDLGVBQWUsU0FBUyxTQUFTLEVBQUU7UUFDMUQsT0FBTyxFQUFFLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxNQUFNLENBQUMsTUFBTSxFQUFFO0tBQzlDLENBQUMsQ0FBQztBQUNMLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFRoZSB3ZWItc2VhcmNoIHJ1bnRpbWU6IGEgbGF6aWx5LXJlc29sdmVkLCBwcm9jZXNzLXdpZGUgY29uZmlnIHNoYXJlZCBieVxuICogdGhlIHBsdWdpbiBhbmQgdGhlIGB3ZWJfc2VhcmNoYCAvIGB3ZWJfZmV0Y2hgIHRvb2xzLCBzbyBib3RoIHJlYWQgb25lXG4gKiByZXNvbHZlZCBhbGxvdy1saXN0IC8gY2FwIC8gdGltZW91dCBzZXQuIFRoZSBmaXJzdCBjYWxsZXIgKG5vcm1hbGx5IHRoZVxuICogcGx1Z2luIGF0IHNldHVwKSBwcmltZXMgaXQgZnJvbSB0aGUgcGx1Z2luJ3MgY29uZmlnOyBsYXRlciBjYWxsZXJzICh0aGVcbiAqIHRvb2xzJyBgZXhlY3V0ZWApIHJldXNlIGl0LlxuICpcbiAqIFRoZSBydW50aW1lIGFsc28gY2FycmllcyB0aGUge0BsaW5rIFdlYlNlYXJjaEV4ZWN1dG9yfSBldmVyeSBvdXRib3VuZCBjYWxsXG4gKiBydW5zIHRocm91Z2guIFRoZSBwbHVnaW4gaW5zdGFsbHMgaXRzIG93biBgZXhlY3V0ZSgpYCB0aGVyZSBhdCBzZXR1cCwgd2hpY2hcbiAqIGlzIGhvdyB0aGUgdG9vbHMgLSBwbGFpbiBmdW5jdGlvbnMgd2l0aCBubyBwbHVnaW4gaW5zdGFuY2UgaW4gc2NvcGUgLSBzdGlsbFxuICogZ2V0IEFwcEtpdCdzIGNhY2hlIC8gcmV0cnkgLyB0aW1lb3V0IC8gdGVsZW1ldHJ5IGNoYWluLiBXaXRob3V0IGFcbiAqIHJlZ2lzdGVyZWQgcGx1Z2luIChhIGRpcmVjdCBjYWxsIGZyb20gYSBzY3JpcHQgb3IgYSB0ZXN0KSB0aGUgY2FsbHMgc3RpbGxcbiAqIHJ1biwganVzdCB3aXRob3V0IGludGVyY2VwdG9ycy5cbiAqXG4gKiBVbmxpa2UgdGhlIGVtYWlsIHJ1bnRpbWUgdGhlcmUgaXMgbm8gY29ubmVjdGlvbiB0byBwb29sIC0gdGhlIGJhY2tlbmQgaXNcbiAqIHN0YXRlbGVzcyBIVFRQIHBlciBjYWxsIC0gc28gdGhlIHJ1bnRpbWUgaG9sZHMgb25seSB0aGUgcmVzb2x2ZWQgY29uZmlnIGFuZFxuICogdGhhdCBleGVjdXRvci5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHsgQXBwS2l0RXJyb3IsIEV4ZWN1dGlvbkVycm9yLCB0eXBlIEV4ZWN1dGlvblJlc3VsdCB9IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbmltcG9ydCB7IGFzeW5jLCBlcnJvciwgbG9nIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7XG4gIHJlc29sdmVXZWJTZWFyY2hDb25maWcsXG4gIHR5cGUgUmVzb2x2ZWRXZWJTZWFyY2hDb25maWcsXG4gIHR5cGUgV2ViU2VhcmNoUGx1Z2luQ29uZmlnLFxufSBmcm9tIFwiLi9jb25maWdcIjtcbmltcG9ydCB0eXBlIHsgV2ViU2VhcmNoRXhlY3V0aW9uU2V0dGluZ3MgfSBmcm9tIFwiLi9kZWZhdWx0c1wiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwid2ViLXNlYXJjaC9ydW50aW1lXCIpO1xuXG4vKipcbiAqIFJ1bnMgb25lIG91dGJvdW5kIGNhbGwgdGhyb3VnaCBBcHBLaXQncyBpbnRlcmNlcHRvciBjaGFpbi4gTWF0Y2hlc1xuICogYFBsdWdpbi5leGVjdXRlKClgLCB3aGljaCBuZXZlciB0aHJvd3M6IGEgZmFpbHVyZSBjb21lcyBiYWNrIGFzXG4gKiBgeyBvazogZmFsc2UgfWAuXG4gKi9cbmV4cG9ydCB0eXBlIFdlYlNlYXJjaEV4ZWN1dG9yID0gPFQ+KFxuICBmbjogKHNpZ25hbD86IEFib3J0U2lnbmFsKSA9PiBQcm9taXNlPFQ+LFxuICBzZXR0aW5nczogV2ViU2VhcmNoRXhlY3V0aW9uU2V0dGluZ3MsXG4pID0+IFByb21pc2U8RXhlY3V0aW9uUmVzdWx0PFQ+PjtcblxuLyoqIFRoZSBzaGFyZWQgcmVzb2x2ZWQgY29uZmlnIHBsdXMgdGhlIGV4ZWN1dG9yIG91dGJvdW5kIGNhbGxzIHJ1biB0aHJvdWdoLiAqL1xuZXhwb3J0IGludGVyZmFjZSBXZWJTZWFyY2hSdW50aW1lIHtcbiAgY29uZmlnOiBSZXNvbHZlZFdlYlNlYXJjaENvbmZpZztcbiAgZXhlY3V0ZTogV2ViU2VhcmNoRXhlY3V0b3I7XG59XG5cbi8qKlxuICogRXhlY3V0b3IgdXNlZCB1bnRpbCAob3IgdW5sZXNzKSB0aGUgcGx1Z2luIGluc3RhbGxzIGl0cyBvd246IHJ1biB0aGUgY2FsbFxuICogZGlyZWN0bHksIG1hcHBpbmcgYSB0aHJvdyBvbnRvIHRoZSBzYW1lIHtAbGluayBFeGVjdXRpb25SZXN1bHR9IHNoYXBlIHNvXG4gKiBjYWxsIHNpdGVzIGJyYW5jaCBvbiBgb2tgIGVpdGhlciB3YXkuXG4gKi9cbmNvbnN0IGRpcmVjdEV4ZWN1dGU6IFdlYlNlYXJjaEV4ZWN1dG9yID0gYXN5bmMgKGZuKSA9PiB7XG4gIHRyeSB7XG4gICAgcmV0dXJuIHsgb2s6IHRydWUsIGRhdGE6IGF3YWl0IGZuKCkgfTtcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG9rOiBmYWxzZSxcbiAgICAgIHN0YXR1czogZXJyIGluc3RhbmNlb2YgQXBwS2l0RXJyb3IgPyBlcnIuc3RhdHVzQ29kZSA6IDUwMCxcbiAgICAgIG1lc3NhZ2U6IGVycm9yLmVycm9yTWVzc2FnZShlcnIpLFxuICAgIH07XG4gIH1cbn07XG5cbmxldCBydW50aW1lOiBXZWJTZWFyY2hSdW50aW1lIHwgdW5kZWZpbmVkO1xuXG4vKipcbiAqIFJldHVybiB0aGUgc2hhcmVkIHJ1bnRpbWUsIGJ1aWxkaW5nIGl0IG9uIGZpcnN0IHVzZSBmcm9tIHRoZSBzdXBwbGllZFxuICogY29uZmlnIGxheWVyZWQgb3ZlciBlbnZpcm9ubWVudCBkZWZhdWx0cy4gT3ZlcnJpZGVzIGFyZSBvbmx5IHJlYWQgd2hlbiB0aGVcbiAqIHJ1bnRpbWUgaXMgZmlyc3QgY3JlYXRlZCwgc28gcHJpbWUgaXQgZnJvbSB0aGUgcGx1Z2luJ3MgY29uZmlnIGF0IHNldHVwO1xuICogc3Vic2VxdWVudCBjYWxscyAodGhlIHRvb2xzJyBgZXhlY3V0ZWApIHBhc3Mgbm90aGluZyBhbmQgZ2V0IHRoZSBzYW1lXG4gKiBpbnN0YW5jZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFdlYlNlYXJjaFJ1bnRpbWUob3ZlcnJpZGVzPzogV2ViU2VhcmNoUGx1Z2luQ29uZmlnKTogV2ViU2VhcmNoUnVudGltZSB7XG4gIGlmICghcnVudGltZSkge1xuICAgIHJ1bnRpbWUgPSB7IGNvbmZpZzogcmVzb2x2ZVdlYlNlYXJjaENvbmZpZyhvdmVycmlkZXMpLCBleGVjdXRlOiBkaXJlY3RFeGVjdXRlIH07XG4gIH1cbiAgcmV0dXJuIHJ1bnRpbWU7XG59XG5cbi8qKlxuICogSW5zdGFsbCB0aGUgZXhlY3V0b3Igb3V0Ym91bmQgY2FsbHMgcnVuIHRocm91Z2guIFRoZSBwbHVnaW4gY2FsbHMgdGhpcyBhdFxuICogc2V0dXAgd2l0aCBpdHMgb3duIGBleGVjdXRlKClgOyBhIHNlY29uZCBjYWxsIHJlcGxhY2VzIHRoZSBwcmV2aW91cyBvbmUsIHNvXG4gKiBhIHJlLXJlZ2lzdGVyZWQgcGx1Z2luIGRvZXMgbm90IGxlYXZlIHRoZSB0b29scyBib3VuZCB0byBhIGRlYWQgaW5zdGFuY2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRXZWJTZWFyY2hFeGVjdXRvcihleGVjdXRlOiBXZWJTZWFyY2hFeGVjdXRvcik6IHZvaWQge1xuICBnZXRXZWJTZWFyY2hSdW50aW1lKCkuZXhlY3V0ZSA9IGV4ZWN1dGU7XG59XG5cbi8qKiBEcm9wIHRoZSBtZW1vaXplZCBydW50aW1lIHNvIHRoZSBuZXh0IHtAbGluayBnZXRXZWJTZWFyY2hSdW50aW1lfSByZWJ1aWxkcyBpdC4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNldFdlYlNlYXJjaFJ1bnRpbWUoKTogdm9pZCB7XG4gIHJ1bnRpbWUgPSB1bmRlZmluZWQ7XG59XG5cbi8qKlxuICogUnVuIG9uZSBpZGVtcG90ZW50IHJlYWQgdGhyb3VnaCB0aGUgc2hhcmVkIGV4ZWN1dG9yIGFuZCB1bndyYXAgaXQuXG4gKlxuICogYGV4ZWN1dGUoKWAgbmV2ZXIgdGhyb3dzLCBzbyBhIGZhaWxlZCBjYWxsIGFycml2ZXMgYXMgYHsgb2s6IGZhbHNlIH1gIHdpdGhcbiAqIGEgc3RhdHVzIHRoZSBpbnRlcmNlcHRvcnMgYWxyZWFkeSBzYW5pdGl6ZWQ7IGl0IGlzIGxvZ2dlZCBoZXJlIGFuZCByZS1yYWlzZWRcbiAqIGFzIGEgc3RhYmxlIHtAbGluayBFeGVjdXRpb25FcnJvcn0gc28gYW4gdXBzdHJlYW0gbWVzc2FnZSBuZXZlciBiZWNvbWVzIHRoZVxuICogY2FsbGVyJ3MgZXJyb3IgdGV4dC4gYHNpZ25hbGAgaXMgdGhlIGNhbGxlcidzIG93biBjYW5jZWxsYXRpb24gKGFuIGFnZW50XG4gKiBydW4sIGEgcmVxdWVzdCB0ZWFyZG93bik7IGl0IGlzIG1lcmdlZCB3aXRoIHRoZSBzaWduYWwgdGhlIHRpbWVvdXRcbiAqIGludGVyY2VwdG9yIHN1cHBsaWVzIHNvIGVpdGhlciBvbmUgdW53aW5kcyB0aGUgSS9PLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZXhlY3V0ZVJlYWQ8VD4oXG4gIG9wZXJhdGlvbjogc3RyaW5nLFxuICBzZXR0aW5nczogV2ViU2VhcmNoRXhlY3V0aW9uU2V0dGluZ3MsXG4gIGZuOiAoc2lnbmFsPzogQWJvcnRTaWduYWwpID0+IFByb21pc2U8VD4sXG4gIHNpZ25hbD86IEFib3J0U2lnbmFsLFxuKTogUHJvbWlzZTxUPiB7XG4gIGNvbnN0IHsgZXhlY3V0ZSB9ID0gZ2V0V2ViU2VhcmNoUnVudGltZSgpO1xuICBjb25zdCByZXN1bHQgPSBhd2FpdCBleGVjdXRlKFxuICAgIChleGVjdXRlU2lnbmFsKSA9PiBmbihhc3luYy5jb21iaW5lQWJvcnRTaWduYWxzKGV4ZWN1dGVTaWduYWwsIHNpZ25hbCkpLFxuICAgIHNldHRpbmdzLFxuICApO1xuICBpZiAocmVzdWx0Lm9rKSByZXR1cm4gcmVzdWx0LmRhdGE7XG4gIC8vIEEgY2FsbGVyIHRoYXQgY2FuY2VsbGVkIGlzIG5vdCBhIGZhaWx1cmUgd29ydGggcmVwb3J0aW5nIGFzIG9uZS5cbiAgaWYgKHNpZ25hbD8uYWJvcnRlZCkgdGhyb3cgRXhlY3V0aW9uRXJyb3IuY2FuY2VsZWQoKTtcbiAgbG9nZ2VyLndhcm4oXCJleGVjdXRpb24tZmFpbGVkXCIsIHtcbiAgICBvcGVyYXRpb24sXG4gICAgc3RhdHVzOiByZXN1bHQuc3RhdHVzLFxuICAgIGVycm9yOiByZXN1bHQubWVzc2FnZSxcbiAgfSk7XG4gIHRocm93IG5ldyBFeGVjdXRpb25FcnJvcihgd2ViLXNlYXJjaDogJHtvcGVyYXRpb259IGZhaWxlZGAsIHtcbiAgICBjb250ZXh0OiB7IG9wZXJhdGlvbiwgc3RhdHVzOiByZXN1bHQuc3RhdHVzIH0sXG4gIH0pO1xufVxuIl19
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire-format contract for the web-search add-on: the two tool inputs a
|
|
3
|
+
* model fills in (`web_search`, `web_fetch`) and the results handed back.
|
|
4
|
+
* Pure zod + inferred types (no Node-only imports) so the tool layer, the
|
|
5
|
+
* plugin, and any future UI validate / type against one definition.
|
|
6
|
+
*
|
|
7
|
+
* `web_search` is backed by the Databricks Model Serving native web-search
|
|
8
|
+
* tool (see `provider.ts`): the model searches the web server-side and
|
|
9
|
+
* returns a synthesized answer plus the sources it used. `web_fetch` reads a
|
|
10
|
+
* single page's contents via got-scraping.
|
|
11
|
+
*
|
|
12
|
+
* Array fields intentionally avoid `.min()` / `.nonempty()`: those emit
|
|
13
|
+
* `minItems` in the JSON schema, which some Model Serving endpoints reject
|
|
14
|
+
* ("array types do not support minItems") when the schema is forwarded as a
|
|
15
|
+
* tool definition - the same constraint the email add-on documents.
|
|
16
|
+
*
|
|
17
|
+
* @module
|
|
18
|
+
*/
|
|
19
|
+
import { z } from "zod";
|
|
20
|
+
/**
|
|
21
|
+
* Description the model reads for `web_search`. Shared by the Mastra tool and
|
|
22
|
+
* the AppKit tool provider so both hosts describe the tool identically.
|
|
23
|
+
*/
|
|
24
|
+
export declare const WEB_SEARCH_TOOL_DESCRIPTION: string;
|
|
25
|
+
/** Description the model reads for `web_fetch`. Shared like {@link WEB_SEARCH_TOOL_DESCRIPTION}. */
|
|
26
|
+
export declare const WEB_FETCH_TOOL_DESCRIPTION: string;
|
|
27
|
+
/** Schema for the `web_search` tool input. */
|
|
28
|
+
export declare const webSearchRequestSchema: z.ZodObject<{
|
|
29
|
+
query: z.ZodString;
|
|
30
|
+
model: z.ZodOptional<z.ZodString>;
|
|
31
|
+
}, z.core.$strip>;
|
|
32
|
+
/** A validated `web_search` request. */
|
|
33
|
+
export type WebSearchRequest = z.infer<typeof webSearchRequestSchema>;
|
|
34
|
+
/** Schema for a single source the model cited while answering. */
|
|
35
|
+
export declare const webSearchCitationSchema: z.ZodObject<{
|
|
36
|
+
url: z.ZodString;
|
|
37
|
+
title: z.ZodOptional<z.ZodString>;
|
|
38
|
+
snippet: z.ZodOptional<z.ZodString>;
|
|
39
|
+
}, z.core.$strip>;
|
|
40
|
+
/** A single cited source ({@link webSearchCitationSchema}). */
|
|
41
|
+
export type WebSearchCitation = z.infer<typeof webSearchCitationSchema>;
|
|
42
|
+
/** Schema for the `web_search` tool output. */
|
|
43
|
+
export declare const webSearchResultSchema: z.ZodObject<{
|
|
44
|
+
query: z.ZodString;
|
|
45
|
+
answer: z.ZodString;
|
|
46
|
+
citations: z.ZodArray<z.ZodObject<{
|
|
47
|
+
url: z.ZodString;
|
|
48
|
+
title: z.ZodOptional<z.ZodString>;
|
|
49
|
+
snippet: z.ZodOptional<z.ZodString>;
|
|
50
|
+
}, z.core.$strip>>;
|
|
51
|
+
model: z.ZodString;
|
|
52
|
+
}, z.core.$strip>;
|
|
53
|
+
/** The outcome of a `web_search` call ({@link webSearchResultSchema}). */
|
|
54
|
+
export type WebSearchResult = z.infer<typeof webSearchResultSchema>;
|
|
55
|
+
/** Schema for the `web_fetch` tool input. */
|
|
56
|
+
export declare const webFetchRequestSchema: z.ZodObject<{
|
|
57
|
+
url: z.ZodString;
|
|
58
|
+
format: z.ZodOptional<z.ZodEnum<{
|
|
59
|
+
text: "text";
|
|
60
|
+
html: "html";
|
|
61
|
+
}>>;
|
|
62
|
+
maxLength: z.ZodOptional<z.ZodNumber>;
|
|
63
|
+
}, z.core.$strip>;
|
|
64
|
+
/** A validated `web_fetch` request. */
|
|
65
|
+
export type WebFetchRequest = z.infer<typeof webFetchRequestSchema>;
|
|
66
|
+
/** Schema for the `web_fetch` tool output. */
|
|
67
|
+
export declare const webFetchResultSchema: z.ZodObject<{
|
|
68
|
+
url: z.ZodString;
|
|
69
|
+
status: z.ZodNumber;
|
|
70
|
+
contentType: z.ZodOptional<z.ZodString>;
|
|
71
|
+
title: z.ZodOptional<z.ZodString>;
|
|
72
|
+
content: z.ZodString;
|
|
73
|
+
truncated: z.ZodBoolean;
|
|
74
|
+
}, z.core.$strip>;
|
|
75
|
+
/** The outcome of a `web_fetch` call ({@link webFetchResultSchema}). */
|
|
76
|
+
export type WebFetchResult = z.infer<typeof webFetchResultSchema>;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire-format contract for the web-search add-on: the two tool inputs a
|
|
3
|
+
* model fills in (`web_search`, `web_fetch`) and the results handed back.
|
|
4
|
+
* Pure zod + inferred types (no Node-only imports) so the tool layer, the
|
|
5
|
+
* plugin, and any future UI validate / type against one definition.
|
|
6
|
+
*
|
|
7
|
+
* `web_search` is backed by the Databricks Model Serving native web-search
|
|
8
|
+
* tool (see `provider.ts`): the model searches the web server-side and
|
|
9
|
+
* returns a synthesized answer plus the sources it used. `web_fetch` reads a
|
|
10
|
+
* single page's contents via got-scraping.
|
|
11
|
+
*
|
|
12
|
+
* Array fields intentionally avoid `.min()` / `.nonempty()`: those emit
|
|
13
|
+
* `minItems` in the JSON schema, which some Model Serving endpoints reject
|
|
14
|
+
* ("array types do not support minItems") when the schema is forwarded as a
|
|
15
|
+
* tool definition - the same constraint the email add-on documents.
|
|
16
|
+
*
|
|
17
|
+
* @module
|
|
18
|
+
*/
|
|
19
|
+
import { string } from "@dbx-tools/shared-core";
|
|
20
|
+
import { z } from "zod";
|
|
21
|
+
/**
|
|
22
|
+
* Description the model reads for `web_search`. Shared by the Mastra tool and
|
|
23
|
+
* the AppKit tool provider so both hosts describe the tool identically.
|
|
24
|
+
*/
|
|
25
|
+
export const WEB_SEARCH_TOOL_DESCRIPTION = string.toDescription(`
|
|
26
|
+
Search the web for current information and get an answer synthesized from
|
|
27
|
+
live results, with the sources it used. Pass a natural-language query;
|
|
28
|
+
the search runs inside a web-search-capable model (chosen independently
|
|
29
|
+
of your own model). Optionally pass a model name to use a specific
|
|
30
|
+
web-search model. Use it whenever a question needs up-to-date or external
|
|
31
|
+
information you don't already have.
|
|
32
|
+
`);
|
|
33
|
+
/** Description the model reads for `web_fetch`. Shared like {@link WEB_SEARCH_TOOL_DESCRIPTION}. */
|
|
34
|
+
export const WEB_FETCH_TOOL_DESCRIPTION = string.toDescription(`
|
|
35
|
+
Fetch a single web page and return its readable contents. Pass an
|
|
36
|
+
absolute URL (including https://); set format to "html" for raw markup
|
|
37
|
+
instead of extracted text. Use it to read a page returned by web_search
|
|
38
|
+
or provided by the user. Content is length-capped; fetching a URL outside
|
|
39
|
+
the configured allow-list is refused.
|
|
40
|
+
`);
|
|
41
|
+
/** Schema for the `web_search` tool input. */
|
|
42
|
+
export const webSearchRequestSchema = z.object({
|
|
43
|
+
query: z
|
|
44
|
+
.string()
|
|
45
|
+
.describe("What to search the web for, phrased as a natural-language question or request. The model searches and answers in one step."),
|
|
46
|
+
model: z
|
|
47
|
+
.string()
|
|
48
|
+
.optional()
|
|
49
|
+
.describe(string.toDescription(`
|
|
50
|
+
Optional web-search-capable model to use (a Databricks serving
|
|
51
|
+
endpoint name like "databricks-gemini-3-pro", a loose name like "gpt"
|
|
52
|
+
or "gemini", or a capability class). Defaults to the plugin's
|
|
53
|
+
configured web-search model. The web-search tool resolves its own
|
|
54
|
+
model independently of the calling agent's chat model, since not
|
|
55
|
+
every chat model supports web search.
|
|
56
|
+
`)),
|
|
57
|
+
});
|
|
58
|
+
/** Schema for a single source the model cited while answering. */
|
|
59
|
+
export const webSearchCitationSchema = z.object({
|
|
60
|
+
url: z.string().describe("The source URL the answer drew on."),
|
|
61
|
+
title: z.string().optional().describe("The source page title, when available."),
|
|
62
|
+
snippet: z.string().optional().describe("A short excerpt from the source, when available."),
|
|
63
|
+
});
|
|
64
|
+
/** Schema for the `web_search` tool output. */
|
|
65
|
+
export const webSearchResultSchema = z.object({
|
|
66
|
+
query: z.string().describe("Echo of the query that was searched."),
|
|
67
|
+
answer: z.string().describe("The model's answer, synthesized from live web results."),
|
|
68
|
+
citations: z
|
|
69
|
+
.array(webSearchCitationSchema)
|
|
70
|
+
.describe("Sources the answer drew on. When an allow-list is configured, citations whose URL is not permitted are silently omitted."),
|
|
71
|
+
model: z.string().describe("The serving endpoint that produced the answer."),
|
|
72
|
+
});
|
|
73
|
+
/** Schema for the `web_fetch` tool input. */
|
|
74
|
+
export const webFetchRequestSchema = z.object({
|
|
75
|
+
url: z
|
|
76
|
+
.string()
|
|
77
|
+
.describe("The absolute URL to fetch (must include the scheme, e.g. https://). When an allow-list is configured, a URL it does not permit is refused."),
|
|
78
|
+
format: z
|
|
79
|
+
.enum(["text", "html"])
|
|
80
|
+
.optional()
|
|
81
|
+
.describe(string.toDescription(`
|
|
82
|
+
Return format: "text" (default) strips the page to readable plain
|
|
83
|
+
text; "html" returns the raw response body. Prefer "text" unless you
|
|
84
|
+
need the markup.
|
|
85
|
+
`)),
|
|
86
|
+
maxLength: z
|
|
87
|
+
.number()
|
|
88
|
+
.int()
|
|
89
|
+
.positive()
|
|
90
|
+
.optional()
|
|
91
|
+
.describe("Truncate the returned content to at most this many characters (the plugin caps this at its configured limit)."),
|
|
92
|
+
});
|
|
93
|
+
/** Schema for the `web_fetch` tool output. */
|
|
94
|
+
export const webFetchResultSchema = z.object({
|
|
95
|
+
url: z.string().describe("The final URL fetched (after redirects)."),
|
|
96
|
+
status: z.number().describe("HTTP status code of the response."),
|
|
97
|
+
contentType: z.string().optional().describe("Response `Content-Type`, when the server sent one."),
|
|
98
|
+
title: z.string().optional().describe("The page <title>, when one was present."),
|
|
99
|
+
content: z.string().describe("The page content in the requested format (text or html)."),
|
|
100
|
+
truncated: z.boolean().describe("True when `content` was cut off at the length cap."),
|
|
101
|
+
});
|
|
102
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NoZW1hLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NjaGVtYS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FpQkc7QUFFSCxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDaEQsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLEtBQUssQ0FBQztBQUV4Qjs7O0dBR0c7QUFDSCxNQUFNLENBQUMsTUFBTSwyQkFBMkIsR0FBRyxNQUFNLENBQUMsYUFBYSxDQUFDOzs7Ozs7O0NBTy9ELENBQUMsQ0FBQztBQUVILG9HQUFvRztBQUNwRyxNQUFNLENBQUMsTUFBTSwwQkFBMEIsR0FBRyxNQUFNLENBQUMsYUFBYSxDQUFDOzs7Ozs7Q0FNOUQsQ0FBQyxDQUFDO0FBRUgsOENBQThDO0FBQzlDLE1BQU0sQ0FBQyxNQUFNLHNCQUFzQixHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUM7SUFDN0MsS0FBSyxFQUFFLENBQUM7U0FDTCxNQUFNLEVBQUU7U0FDUixRQUFRLENBQ1AsNEhBQTRILENBQzdIO0lBQ0gsS0FBSyxFQUFFLENBQUM7U0FDTCxNQUFNLEVBQUU7U0FDUixRQUFRLEVBQUU7U0FDVixRQUFRLENBQ1AsTUFBTSxDQUFDLGFBQWEsQ0FBQzs7Ozs7OztPQU9wQixDQUFDLENBQ0g7Q0FDSixDQUFDLENBQUM7QUFLSCxrRUFBa0U7QUFDbEUsTUFBTSxDQUFDLE1BQU0sdUJBQXVCLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQztJQUM5QyxHQUFHLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxvQ0FBb0MsQ0FBQztJQUM5RCxLQUFLLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFDLFFBQVEsQ0FBQyx3Q0FBd0MsQ0FBQztJQUMvRSxPQUFPLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRSxDQUFDLFFBQVEsQ0FBQyxrREFBa0QsQ0FBQztDQUM1RixDQUFDLENBQUM7QUFLSCwrQ0FBK0M7QUFDL0MsTUFBTSxDQUFDLE1BQU0scUJBQXFCLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQztJQUM1QyxLQUFLLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyxzQ0FBc0MsQ0FBQztJQUNsRSxNQUFNLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsQ0FBQyx3REFBd0QsQ0FBQztJQUNyRixTQUFTLEVBQUUsQ0FBQztTQUNULEtBQUssQ0FBQyx1QkFBdUIsQ0FBQztTQUM5QixRQUFRLENBQ1AsMEhBQTBILENBQzNIO0lBQ0gsS0FBSyxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsZ0RBQWdELENBQUM7Q0FDN0UsQ0FBQyxDQUFDO0FBS0gsNkNBQTZDO0FBQzdDLE1BQU0sQ0FBQyxNQUFNLHFCQUFxQixHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUM7SUFDNUMsR0FBRyxFQUFFLENBQUM7U0FDSCxNQUFNLEVBQUU7U0FDUixRQUFRLENBQ1AsNElBQTRJLENBQzdJO0lBQ0gsTUFBTSxFQUFFLENBQUM7U0FDTixJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUM7U0FDdEIsUUFBUSxFQUFFO1NBQ1YsUUFBUSxDQUNQLE1BQU0sQ0FBQyxhQUFhLENBQUM7Ozs7T0FJcEIsQ0FBQyxDQUNIO0lBQ0gsU0FBUyxFQUFFLENBQUM7U0FDVCxNQUFNLEVBQUU7U0FDUixHQUFHLEVBQUU7U0FDTCxRQUFRLEVBQUU7U0FDVixRQUFRLEVBQUU7U0FDVixRQUFRLENBQ1AsK0dBQStHLENBQ2hIO0NBQ0osQ0FBQyxDQUFDO0FBS0gsOENBQThDO0FBQzlDLE1BQU0sQ0FBQyxNQUFNLG9CQUFvQixHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUM7SUFDM0MsR0FBRyxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsMENBQTBDLENBQUM7SUFDcEUsTUFBTSxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsbUNBQW1DLENBQUM7SUFDaEUsV0FBVyxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxRQUFRLENBQUMsb0RBQW9ELENBQUM7SUFDakcsS0FBSyxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxRQUFRLENBQUMseUNBQXlDLENBQUM7SUFDaEYsT0FBTyxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsMERBQTBELENBQUM7SUFDeEYsU0FBUyxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxRQUFRLENBQUMsb0RBQW9ELENBQUM7Q0FDdEYsQ0FBQyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBXaXJlLWZvcm1hdCBjb250cmFjdCBmb3IgdGhlIHdlYi1zZWFyY2ggYWRkLW9uOiB0aGUgdHdvIHRvb2wgaW5wdXRzIGFcbiAqIG1vZGVsIGZpbGxzIGluIChgd2ViX3NlYXJjaGAsIGB3ZWJfZmV0Y2hgKSBhbmQgdGhlIHJlc3VsdHMgaGFuZGVkIGJhY2suXG4gKiBQdXJlIHpvZCArIGluZmVycmVkIHR5cGVzIChubyBOb2RlLW9ubHkgaW1wb3J0cykgc28gdGhlIHRvb2wgbGF5ZXIsIHRoZVxuICogcGx1Z2luLCBhbmQgYW55IGZ1dHVyZSBVSSB2YWxpZGF0ZSAvIHR5cGUgYWdhaW5zdCBvbmUgZGVmaW5pdGlvbi5cbiAqXG4gKiBgd2ViX3NlYXJjaGAgaXMgYmFja2VkIGJ5IHRoZSBEYXRhYnJpY2tzIE1vZGVsIFNlcnZpbmcgbmF0aXZlIHdlYi1zZWFyY2hcbiAqIHRvb2wgKHNlZSBgcHJvdmlkZXIudHNgKTogdGhlIG1vZGVsIHNlYXJjaGVzIHRoZSB3ZWIgc2VydmVyLXNpZGUgYW5kXG4gKiByZXR1cm5zIGEgc3ludGhlc2l6ZWQgYW5zd2VyIHBsdXMgdGhlIHNvdXJjZXMgaXQgdXNlZC4gYHdlYl9mZXRjaGAgcmVhZHMgYVxuICogc2luZ2xlIHBhZ2UncyBjb250ZW50cyB2aWEgZ290LXNjcmFwaW5nLlxuICpcbiAqIEFycmF5IGZpZWxkcyBpbnRlbnRpb25hbGx5IGF2b2lkIGAubWluKClgIC8gYC5ub25lbXB0eSgpYDogdGhvc2UgZW1pdFxuICogYG1pbkl0ZW1zYCBpbiB0aGUgSlNPTiBzY2hlbWEsIHdoaWNoIHNvbWUgTW9kZWwgU2VydmluZyBlbmRwb2ludHMgcmVqZWN0XG4gKiAoXCJhcnJheSB0eXBlcyBkbyBub3Qgc3VwcG9ydCBtaW5JdGVtc1wiKSB3aGVuIHRoZSBzY2hlbWEgaXMgZm9yd2FyZGVkIGFzIGFcbiAqIHRvb2wgZGVmaW5pdGlvbiAtIHRoZSBzYW1lIGNvbnN0cmFpbnQgdGhlIGVtYWlsIGFkZC1vbiBkb2N1bWVudHMuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IHN0cmluZyB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1jb3JlXCI7XG5pbXBvcnQgeyB6IH0gZnJvbSBcInpvZFwiO1xuXG4vKipcbiAqIERlc2NyaXB0aW9uIHRoZSBtb2RlbCByZWFkcyBmb3IgYHdlYl9zZWFyY2hgLiBTaGFyZWQgYnkgdGhlIE1hc3RyYSB0b29sIGFuZFxuICogdGhlIEFwcEtpdCB0b29sIHByb3ZpZGVyIHNvIGJvdGggaG9zdHMgZGVzY3JpYmUgdGhlIHRvb2wgaWRlbnRpY2FsbHkuXG4gKi9cbmV4cG9ydCBjb25zdCBXRUJfU0VBUkNIX1RPT0xfREVTQ1JJUFRJT04gPSBzdHJpbmcudG9EZXNjcmlwdGlvbihgXG4gIFNlYXJjaCB0aGUgd2ViIGZvciBjdXJyZW50IGluZm9ybWF0aW9uIGFuZCBnZXQgYW4gYW5zd2VyIHN5bnRoZXNpemVkIGZyb21cbiAgbGl2ZSByZXN1bHRzLCB3aXRoIHRoZSBzb3VyY2VzIGl0IHVzZWQuIFBhc3MgYSBuYXR1cmFsLWxhbmd1YWdlIHF1ZXJ5O1xuICB0aGUgc2VhcmNoIHJ1bnMgaW5zaWRlIGEgd2ViLXNlYXJjaC1jYXBhYmxlIG1vZGVsIChjaG9zZW4gaW5kZXBlbmRlbnRseVxuICBvZiB5b3VyIG93biBtb2RlbCkuIE9wdGlvbmFsbHkgcGFzcyBhIG1vZGVsIG5hbWUgdG8gdXNlIGEgc3BlY2lmaWNcbiAgd2ViLXNlYXJjaCBtb2RlbC4gVXNlIGl0IHdoZW5ldmVyIGEgcXVlc3Rpb24gbmVlZHMgdXAtdG8tZGF0ZSBvciBleHRlcm5hbFxuICBpbmZvcm1hdGlvbiB5b3UgZG9uJ3QgYWxyZWFkeSBoYXZlLlxuYCk7XG5cbi8qKiBEZXNjcmlwdGlvbiB0aGUgbW9kZWwgcmVhZHMgZm9yIGB3ZWJfZmV0Y2hgLiBTaGFyZWQgbGlrZSB7QGxpbmsgV0VCX1NFQVJDSF9UT09MX0RFU0NSSVBUSU9OfS4gKi9cbmV4cG9ydCBjb25zdCBXRUJfRkVUQ0hfVE9PTF9ERVNDUklQVElPTiA9IHN0cmluZy50b0Rlc2NyaXB0aW9uKGBcbiAgRmV0Y2ggYSBzaW5nbGUgd2ViIHBhZ2UgYW5kIHJldHVybiBpdHMgcmVhZGFibGUgY29udGVudHMuIFBhc3MgYW5cbiAgYWJzb2x1dGUgVVJMIChpbmNsdWRpbmcgaHR0cHM6Ly8pOyBzZXQgZm9ybWF0IHRvIFwiaHRtbFwiIGZvciByYXcgbWFya3VwXG4gIGluc3RlYWQgb2YgZXh0cmFjdGVkIHRleHQuIFVzZSBpdCB0byByZWFkIGEgcGFnZSByZXR1cm5lZCBieSB3ZWJfc2VhcmNoXG4gIG9yIHByb3ZpZGVkIGJ5IHRoZSB1c2VyLiBDb250ZW50IGlzIGxlbmd0aC1jYXBwZWQ7IGZldGNoaW5nIGEgVVJMIG91dHNpZGVcbiAgdGhlIGNvbmZpZ3VyZWQgYWxsb3ctbGlzdCBpcyByZWZ1c2VkLlxuYCk7XG5cbi8qKiBTY2hlbWEgZm9yIHRoZSBgd2ViX3NlYXJjaGAgdG9vbCBpbnB1dC4gKi9cbmV4cG9ydCBjb25zdCB3ZWJTZWFyY2hSZXF1ZXN0U2NoZW1hID0gei5vYmplY3Qoe1xuICBxdWVyeTogelxuICAgIC5zdHJpbmcoKVxuICAgIC5kZXNjcmliZShcbiAgICAgIFwiV2hhdCB0byBzZWFyY2ggdGhlIHdlYiBmb3IsIHBocmFzZWQgYXMgYSBuYXR1cmFsLWxhbmd1YWdlIHF1ZXN0aW9uIG9yIHJlcXVlc3QuIFRoZSBtb2RlbCBzZWFyY2hlcyBhbmQgYW5zd2VycyBpbiBvbmUgc3RlcC5cIixcbiAgICApLFxuICBtb2RlbDogelxuICAgIC5zdHJpbmcoKVxuICAgIC5vcHRpb25hbCgpXG4gICAgLmRlc2NyaWJlKFxuICAgICAgc3RyaW5nLnRvRGVzY3JpcHRpb24oYFxuICAgICAgICBPcHRpb25hbCB3ZWItc2VhcmNoLWNhcGFibGUgbW9kZWwgdG8gdXNlIChhIERhdGFicmlja3Mgc2VydmluZ1xuICAgICAgICBlbmRwb2ludCBuYW1lIGxpa2UgXCJkYXRhYnJpY2tzLWdlbWluaS0zLXByb1wiLCBhIGxvb3NlIG5hbWUgbGlrZSBcImdwdFwiXG4gICAgICAgIG9yIFwiZ2VtaW5pXCIsIG9yIGEgY2FwYWJpbGl0eSBjbGFzcykuIERlZmF1bHRzIHRvIHRoZSBwbHVnaW4nc1xuICAgICAgICBjb25maWd1cmVkIHdlYi1zZWFyY2ggbW9kZWwuIFRoZSB3ZWItc2VhcmNoIHRvb2wgcmVzb2x2ZXMgaXRzIG93blxuICAgICAgICBtb2RlbCBpbmRlcGVuZGVudGx5IG9mIHRoZSBjYWxsaW5nIGFnZW50J3MgY2hhdCBtb2RlbCwgc2luY2Ugbm90XG4gICAgICAgIGV2ZXJ5IGNoYXQgbW9kZWwgc3VwcG9ydHMgd2ViIHNlYXJjaC5cbiAgICAgIGApLFxuICAgICksXG59KTtcblxuLyoqIEEgdmFsaWRhdGVkIGB3ZWJfc2VhcmNoYCByZXF1ZXN0LiAqL1xuZXhwb3J0IHR5cGUgV2ViU2VhcmNoUmVxdWVzdCA9IHouaW5mZXI8dHlwZW9mIHdlYlNlYXJjaFJlcXVlc3RTY2hlbWE+O1xuXG4vKiogU2NoZW1hIGZvciBhIHNpbmdsZSBzb3VyY2UgdGhlIG1vZGVsIGNpdGVkIHdoaWxlIGFuc3dlcmluZy4gKi9cbmV4cG9ydCBjb25zdCB3ZWJTZWFyY2hDaXRhdGlvblNjaGVtYSA9IHoub2JqZWN0KHtcbiAgdXJsOiB6LnN0cmluZygpLmRlc2NyaWJlKFwiVGhlIHNvdXJjZSBVUkwgdGhlIGFuc3dlciBkcmV3IG9uLlwiKSxcbiAgdGl0bGU6IHouc3RyaW5nKCkub3B0aW9uYWwoKS5kZXNjcmliZShcIlRoZSBzb3VyY2UgcGFnZSB0aXRsZSwgd2hlbiBhdmFpbGFibGUuXCIpLFxuICBzbmlwcGV0OiB6LnN0cmluZygpLm9wdGlvbmFsKCkuZGVzY3JpYmUoXCJBIHNob3J0IGV4Y2VycHQgZnJvbSB0aGUgc291cmNlLCB3aGVuIGF2YWlsYWJsZS5cIiksXG59KTtcblxuLyoqIEEgc2luZ2xlIGNpdGVkIHNvdXJjZSAoe0BsaW5rIHdlYlNlYXJjaENpdGF0aW9uU2NoZW1hfSkuICovXG5leHBvcnQgdHlwZSBXZWJTZWFyY2hDaXRhdGlvbiA9IHouaW5mZXI8dHlwZW9mIHdlYlNlYXJjaENpdGF0aW9uU2NoZW1hPjtcblxuLyoqIFNjaGVtYSBmb3IgdGhlIGB3ZWJfc2VhcmNoYCB0b29sIG91dHB1dC4gKi9cbmV4cG9ydCBjb25zdCB3ZWJTZWFyY2hSZXN1bHRTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIHF1ZXJ5OiB6LnN0cmluZygpLmRlc2NyaWJlKFwiRWNobyBvZiB0aGUgcXVlcnkgdGhhdCB3YXMgc2VhcmNoZWQuXCIpLFxuICBhbnN3ZXI6IHouc3RyaW5nKCkuZGVzY3JpYmUoXCJUaGUgbW9kZWwncyBhbnN3ZXIsIHN5bnRoZXNpemVkIGZyb20gbGl2ZSB3ZWIgcmVzdWx0cy5cIiksXG4gIGNpdGF0aW9uczogelxuICAgIC5hcnJheSh3ZWJTZWFyY2hDaXRhdGlvblNjaGVtYSlcbiAgICAuZGVzY3JpYmUoXG4gICAgICBcIlNvdXJjZXMgdGhlIGFuc3dlciBkcmV3IG9uLiBXaGVuIGFuIGFsbG93LWxpc3QgaXMgY29uZmlndXJlZCwgY2l0YXRpb25zIHdob3NlIFVSTCBpcyBub3QgcGVybWl0dGVkIGFyZSBzaWxlbnRseSBvbWl0dGVkLlwiLFxuICAgICksXG4gIG1vZGVsOiB6LnN0cmluZygpLmRlc2NyaWJlKFwiVGhlIHNlcnZpbmcgZW5kcG9pbnQgdGhhdCBwcm9kdWNlZCB0aGUgYW5zd2VyLlwiKSxcbn0pO1xuXG4vKiogVGhlIG91dGNvbWUgb2YgYSBgd2ViX3NlYXJjaGAgY2FsbCAoe0BsaW5rIHdlYlNlYXJjaFJlc3VsdFNjaGVtYX0pLiAqL1xuZXhwb3J0IHR5cGUgV2ViU2VhcmNoUmVzdWx0ID0gei5pbmZlcjx0eXBlb2Ygd2ViU2VhcmNoUmVzdWx0U2NoZW1hPjtcblxuLyoqIFNjaGVtYSBmb3IgdGhlIGB3ZWJfZmV0Y2hgIHRvb2wgaW5wdXQuICovXG5leHBvcnQgY29uc3Qgd2ViRmV0Y2hSZXF1ZXN0U2NoZW1hID0gei5vYmplY3Qoe1xuICB1cmw6IHpcbiAgICAuc3RyaW5nKClcbiAgICAuZGVzY3JpYmUoXG4gICAgICBcIlRoZSBhYnNvbHV0ZSBVUkwgdG8gZmV0Y2ggKG11c3QgaW5jbHVkZSB0aGUgc2NoZW1lLCBlLmcuIGh0dHBzOi8vKS4gV2hlbiBhbiBhbGxvdy1saXN0IGlzIGNvbmZpZ3VyZWQsIGEgVVJMIGl0IGRvZXMgbm90IHBlcm1pdCBpcyByZWZ1c2VkLlwiLFxuICAgICksXG4gIGZvcm1hdDogelxuICAgIC5lbnVtKFtcInRleHRcIiwgXCJodG1sXCJdKVxuICAgIC5vcHRpb25hbCgpXG4gICAgLmRlc2NyaWJlKFxuICAgICAgc3RyaW5nLnRvRGVzY3JpcHRpb24oYFxuICAgICAgICBSZXR1cm4gZm9ybWF0OiBcInRleHRcIiAoZGVmYXVsdCkgc3RyaXBzIHRoZSBwYWdlIHRvIHJlYWRhYmxlIHBsYWluXG4gICAgICAgIHRleHQ7IFwiaHRtbFwiIHJldHVybnMgdGhlIHJhdyByZXNwb25zZSBib2R5LiBQcmVmZXIgXCJ0ZXh0XCIgdW5sZXNzIHlvdVxuICAgICAgICBuZWVkIHRoZSBtYXJrdXAuXG4gICAgICBgKSxcbiAgICApLFxuICBtYXhMZW5ndGg6IHpcbiAgICAubnVtYmVyKClcbiAgICAuaW50KClcbiAgICAucG9zaXRpdmUoKVxuICAgIC5vcHRpb25hbCgpXG4gICAgLmRlc2NyaWJlKFxuICAgICAgXCJUcnVuY2F0ZSB0aGUgcmV0dXJuZWQgY29udGVudCB0byBhdCBtb3N0IHRoaXMgbWFueSBjaGFyYWN0ZXJzICh0aGUgcGx1Z2luIGNhcHMgdGhpcyBhdCBpdHMgY29uZmlndXJlZCBsaW1pdCkuXCIsXG4gICAgKSxcbn0pO1xuXG4vKiogQSB2YWxpZGF0ZWQgYHdlYl9mZXRjaGAgcmVxdWVzdC4gKi9cbmV4cG9ydCB0eXBlIFdlYkZldGNoUmVxdWVzdCA9IHouaW5mZXI8dHlwZW9mIHdlYkZldGNoUmVxdWVzdFNjaGVtYT47XG5cbi8qKiBTY2hlbWEgZm9yIHRoZSBgd2ViX2ZldGNoYCB0b29sIG91dHB1dC4gKi9cbmV4cG9ydCBjb25zdCB3ZWJGZXRjaFJlc3VsdFNjaGVtYSA9IHoub2JqZWN0KHtcbiAgdXJsOiB6LnN0cmluZygpLmRlc2NyaWJlKFwiVGhlIGZpbmFsIFVSTCBmZXRjaGVkIChhZnRlciByZWRpcmVjdHMpLlwiKSxcbiAgc3RhdHVzOiB6Lm51bWJlcigpLmRlc2NyaWJlKFwiSFRUUCBzdGF0dXMgY29kZSBvZiB0aGUgcmVzcG9uc2UuXCIpLFxuICBjb250ZW50VHlwZTogei5zdHJpbmcoKS5vcHRpb25hbCgpLmRlc2NyaWJlKFwiUmVzcG9uc2UgYENvbnRlbnQtVHlwZWAsIHdoZW4gdGhlIHNlcnZlciBzZW50IG9uZS5cIiksXG4gIHRpdGxlOiB6LnN0cmluZygpLm9wdGlvbmFsKCkuZGVzY3JpYmUoXCJUaGUgcGFnZSA8dGl0bGU+LCB3aGVuIG9uZSB3YXMgcHJlc2VudC5cIiksXG4gIGNvbnRlbnQ6IHouc3RyaW5nKCkuZGVzY3JpYmUoXCJUaGUgcGFnZSBjb250ZW50IGluIHRoZSByZXF1ZXN0ZWQgZm9ybWF0ICh0ZXh0IG9yIGh0bWwpLlwiKSxcbiAgdHJ1bmNhdGVkOiB6LmJvb2xlYW4oKS5kZXNjcmliZShcIlRydWUgd2hlbiBgY29udGVudGAgd2FzIGN1dCBvZmYgYXQgdGhlIGxlbmd0aCBjYXAuXCIpLFxufSk7XG5cbi8qKiBUaGUgb3V0Y29tZSBvZiBhIGB3ZWJfZmV0Y2hgIGNhbGwgKHtAbGluayB3ZWJGZXRjaFJlc3VsdFNjaGVtYX0pLiAqL1xuZXhwb3J0IHR5cGUgV2ViRmV0Y2hSZXN1bHQgPSB6LmluZmVyPHR5cGVvZiB3ZWJGZXRjaFJlc3VsdFNjaGVtYT47XG4iXX0=
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Last-resort scraping fallback for `web_search`, used ONLY when the
|
|
3
|
+
* workspace has no Databricks web-search-capable model deployed (no GPT /
|
|
4
|
+
* Gemini serving endpoint). The native Databricks web-search tool is always
|
|
5
|
+
* preferred (see `search.ts`); this exists so the tool still returns useful
|
|
6
|
+
* results in an environment that can't run it, rather than erroring on every
|
|
7
|
+
* call.
|
|
8
|
+
*
|
|
9
|
+
* It queries DuckDuckGo's no-JS HTML endpoint through `got-scraping`
|
|
10
|
+
* (browser-like fingerprints so the request isn't blocked) via a GET with the
|
|
11
|
+
* query in the query string - a POST to the same endpoint trips DDG's bot
|
|
12
|
+
* challenge (HTTP 202), while the GET returns normal result markup. It then
|
|
13
|
+
* parses the result anchors + snippets. Unlike the native tool there is no
|
|
14
|
+
* model synthesizing an answer, so `answer` is a short lead-in over the top
|
|
15
|
+
* snippets and the substance rides in `citations` - the calling agent reads
|
|
16
|
+
* those and writes its own answer.
|
|
17
|
+
*
|
|
18
|
+
* @module
|
|
19
|
+
*/
|
|
20
|
+
import type { ResolvedWebSearchConfig } from "./config.js";
|
|
21
|
+
import type { WebSearchRequest, WebSearchResult } from "./schema.js";
|
|
22
|
+
/**
|
|
23
|
+
* Run a scraping search over DuckDuckGo. Returns the same
|
|
24
|
+
* {@link WebSearchResult} shape as the native path, with `model` set to
|
|
25
|
+
* `"scrape:duckduckgo"` so callers can tell how the result was produced.
|
|
26
|
+
* Citations are filtered through the configured URL allow-list. `signal`
|
|
27
|
+
* cancels the in-flight request.
|
|
28
|
+
*/
|
|
29
|
+
export declare function runScrapeSearch(request: WebSearchRequest, config: ResolvedWebSearchConfig, signal?: AbortSignal): Promise<WebSearchResult>;
|