@dbx-tools/model 0.9.99 → 0.9.105
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 +16 -6
- package/index.ts +2 -4
- package/lib/index.d.ts +2 -4
- package/lib/index.js +3 -4
- package/lib/package.json +1 -6
- package/lib/src/invoke.d.ts +8 -0
- package/lib/src/invoke.js +18 -6
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -14
- package/src/invoke.ts +21 -5
- package/lib/src/serving-wire.d.ts +0 -37
- package/lib/src/serving-wire.js +0 -211
- package/src/serving-wire.ts +0 -231
package/README.md
CHANGED
|
@@ -2,12 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
Workspace-aware Databricks Model Serving selection.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
Turn a loose model request such as `"claude sonnet"` or `"chat-fast"` into a
|
|
6
|
+
concrete serving endpoint in the current workspace. The client lists
|
|
7
|
+
`/serving-endpoints`, caches and enriches the
|
|
8
8
|
catalogue, classifies endpoints by capability, fuzzy-matches names, and falls
|
|
9
9
|
back to a small static floor when the live catalogue is unavailable.
|
|
10
10
|
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { createModelClient } from "@dbx-tools/model";
|
|
15
|
+
|
|
16
|
+
const models = await createModelClient();
|
|
17
|
+
const selected = await models.resolveModel({ explicit: "sonnet" });
|
|
18
|
+
console.log(selected.modelId);
|
|
19
|
+
```
|
|
20
|
+
|
|
11
21
|
Browser-safe request/result schemas and endpoint classification types live in
|
|
12
22
|
[`@dbx-tools/shared-model`](../../shared/model).
|
|
13
23
|
|
|
@@ -33,7 +43,7 @@ Key features:
|
|
|
33
43
|
- Provides a small static fallback floor for local tools and degraded workspace
|
|
34
44
|
access.
|
|
35
45
|
|
|
36
|
-
##
|
|
46
|
+
## Use With AppKit Model Serving
|
|
37
47
|
|
|
38
48
|
Native AppKit's Model Serving plugin is the right choice when you already know
|
|
39
49
|
the endpoint alias you want. It gives you authenticated invoke/stream routes,
|
|
@@ -53,7 +63,7 @@ endpoint:
|
|
|
53
63
|
- keep local agents and CLIs working with a static fallback when catalogue
|
|
54
64
|
access is unavailable.
|
|
55
65
|
|
|
56
|
-
##
|
|
66
|
+
## Route Requests
|
|
57
67
|
|
|
58
68
|
```ts
|
|
59
69
|
import { createModelClient } from "@dbx-tools/model";
|
|
@@ -243,7 +253,7 @@ a property of the model (see `isResponsesOnly()` and `responsesUpstreamUrl()`),
|
|
|
243
253
|
so a hard-coded string in one package silently diverges when that routing
|
|
244
254
|
changes. `isResponsesOnly()` covers Codex and GPT 5.4+ endpoints, which reject
|
|
245
255
|
tool-bearing Chat Completions, while keeping GPT-OSS on its supported Chat path.
|
|
246
|
-
The TypeScript helper
|
|
256
|
+
The TypeScript helper applies this policy so every Node consumer shares one version
|
|
247
257
|
threshold without loading a native library.
|
|
248
258
|
|
|
249
259
|
## Read Published Model Metadata
|
package/index.ts
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// Hand edits are overwritten on the next watch; this file is read-only.
|
|
4
4
|
|
|
5
5
|
export const PACKAGE_IDENTIFIER = "@dbx-tools/model";
|
|
6
|
-
export const PACKAGE_VERSION = "0.9.
|
|
6
|
+
export const PACKAGE_VERSION = "0.9.105";
|
|
7
7
|
export * as bindings from "./src/bindings.ts";
|
|
8
8
|
export * as classes from "./src/classes.ts";
|
|
9
9
|
export * as classify from "./src/classify.ts";
|
|
@@ -16,10 +16,9 @@ export * as modelClient from "./src/model-client.ts";
|
|
|
16
16
|
export * as policy from "./src/policy.ts";
|
|
17
17
|
export * as reasoningTranslation from "./src/reasoning-translation.ts";
|
|
18
18
|
export * as resolve from "./src/resolve.ts";
|
|
19
|
-
export * as servingWire from "./src/serving-wire.ts";
|
|
20
19
|
export { CHAT_CLASS_ORDER, MODEL_CLASS_ORDER } from "./src/classes.ts";
|
|
21
20
|
export { FALLBACK_MODEL_IDS } from "./src/fallback.ts";
|
|
22
|
-
export { INVOCATIONS_SUFFIX, RESPONSES_PATH, OPEN_RESPONSES_PATH, CHAT_COMPLETIONS_PATH, AI_GATEWAY_CODEX_RESPONSES_PATH, ANTHROPIC_MESSAGES_PATH } from "./src/invoke.ts";
|
|
21
|
+
export { INVOCATIONS_SUFFIX, SERVING_ENDPOINTS_PATH, RESPONSES_PATH, OPEN_RESPONSES_PATH, CHAT_COMPLETIONS_PATH, AI_GATEWAY_CODEX_RESPONSES_PATH, ANTHROPIC_BASE_PATH, ANTHROPIC_MESSAGES_PATH } from "./src/invoke.ts";
|
|
23
22
|
export type { AuthenticatingClientLike } from "./src/invoke.ts";
|
|
24
23
|
export { MODEL_METADATA_TTL_MS, MODEL_RATE_LIMITS_URL, OPENAI_RESPONSES_MODELS_URL, QUERY_REASON_MODELS_URL, RETIRED_MODELS_URL, WEB_SEARCH_MODELS_URL } from "./src/metadata.ts";
|
|
25
24
|
export type { MetadataCacheRecord, MetadataCacheOptions, MetadataCacheMergeInput, MetadataCache } from "./src/metadata-cache.ts";
|
|
@@ -31,5 +30,4 @@ export { ModelFamily } from "./src/policy.ts";
|
|
|
31
30
|
export { REASONING_LEVELS } from "./src/reasoning-translation.ts";
|
|
32
31
|
export type { ReasoningLevel, ReasoningModelCatalogue, AdaptedRequestReasoning } from "./src/reasoning-translation.ts";
|
|
33
32
|
export type { SelectModelInput, SearchModelsInput } from "./src/resolve.ts";
|
|
34
|
-
export type { ServingChatMessage, RewrittenServingRequest } from "./src/serving-wire.ts";
|
|
35
33
|
export * from "./exports.ts";
|
package/lib/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const PACKAGE_IDENTIFIER = "@dbx-tools/model";
|
|
2
|
-
export declare const PACKAGE_VERSION = "0.9.
|
|
2
|
+
export declare const PACKAGE_VERSION = "0.9.105";
|
|
3
3
|
export * as bindings from "./src/bindings.ts";
|
|
4
4
|
export * as classes from "./src/classes.ts";
|
|
5
5
|
export * as classify from "./src/classify.ts";
|
|
@@ -12,10 +12,9 @@ export * as modelClient from "./src/model-client.ts";
|
|
|
12
12
|
export * as policy from "./src/policy.ts";
|
|
13
13
|
export * as reasoningTranslation from "./src/reasoning-translation.ts";
|
|
14
14
|
export * as resolve from "./src/resolve.ts";
|
|
15
|
-
export * as servingWire from "./src/serving-wire.ts";
|
|
16
15
|
export { CHAT_CLASS_ORDER, MODEL_CLASS_ORDER } from "./src/classes.ts";
|
|
17
16
|
export { FALLBACK_MODEL_IDS } from "./src/fallback.ts";
|
|
18
|
-
export { INVOCATIONS_SUFFIX, RESPONSES_PATH, OPEN_RESPONSES_PATH, CHAT_COMPLETIONS_PATH, AI_GATEWAY_CODEX_RESPONSES_PATH, ANTHROPIC_MESSAGES_PATH } from "./src/invoke.ts";
|
|
17
|
+
export { INVOCATIONS_SUFFIX, SERVING_ENDPOINTS_PATH, RESPONSES_PATH, OPEN_RESPONSES_PATH, CHAT_COMPLETIONS_PATH, AI_GATEWAY_CODEX_RESPONSES_PATH, ANTHROPIC_BASE_PATH, ANTHROPIC_MESSAGES_PATH } from "./src/invoke.ts";
|
|
19
18
|
export type { AuthenticatingClientLike } from "./src/invoke.ts";
|
|
20
19
|
export { MODEL_METADATA_TTL_MS, MODEL_RATE_LIMITS_URL, OPENAI_RESPONSES_MODELS_URL, QUERY_REASON_MODELS_URL, RETIRED_MODELS_URL, WEB_SEARCH_MODELS_URL } from "./src/metadata.ts";
|
|
21
20
|
export type { MetadataCacheRecord, MetadataCacheOptions, MetadataCacheMergeInput, MetadataCache } from "./src/metadata-cache.ts";
|
|
@@ -27,5 +26,4 @@ export { ModelFamily } from "./src/policy.ts";
|
|
|
27
26
|
export { REASONING_LEVELS } from "./src/reasoning-translation.ts";
|
|
28
27
|
export type { ReasoningLevel, ReasoningModelCatalogue, AdaptedRequestReasoning } from "./src/reasoning-translation.ts";
|
|
29
28
|
export type { SelectModelInput, SearchModelsInput } from "./src/resolve.ts";
|
|
30
|
-
export type { ServingChatMessage, RewrittenServingRequest } from "./src/serving-wire.ts";
|
|
31
29
|
export * from "./exports.ts";
|
package/lib/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Regenerated from the exporting modules in ./src.
|
|
3
3
|
// Hand edits are overwritten on the next watch; this file is read-only.
|
|
4
4
|
export const PACKAGE_IDENTIFIER = "@dbx-tools/model";
|
|
5
|
-
export const PACKAGE_VERSION = "0.9.
|
|
5
|
+
export const PACKAGE_VERSION = "0.9.105";
|
|
6
6
|
export * as bindings from "./src/bindings.js";
|
|
7
7
|
export * as classes from "./src/classes.js";
|
|
8
8
|
export * as classify from "./src/classify.js";
|
|
@@ -15,14 +15,13 @@ export * as modelClient from "./src/model-client.js";
|
|
|
15
15
|
export * as policy from "./src/policy.js";
|
|
16
16
|
export * as reasoningTranslation from "./src/reasoning-translation.js";
|
|
17
17
|
export * as resolve from "./src/resolve.js";
|
|
18
|
-
export * as servingWire from "./src/serving-wire.js";
|
|
19
18
|
export { CHAT_CLASS_ORDER, MODEL_CLASS_ORDER } from "./src/classes.js";
|
|
20
19
|
export { FALLBACK_MODEL_IDS } from "./src/fallback.js";
|
|
21
|
-
export { INVOCATIONS_SUFFIX, RESPONSES_PATH, OPEN_RESPONSES_PATH, CHAT_COMPLETIONS_PATH, AI_GATEWAY_CODEX_RESPONSES_PATH, ANTHROPIC_MESSAGES_PATH } from "./src/invoke.js";
|
|
20
|
+
export { INVOCATIONS_SUFFIX, SERVING_ENDPOINTS_PATH, RESPONSES_PATH, OPEN_RESPONSES_PATH, CHAT_COMPLETIONS_PATH, AI_GATEWAY_CODEX_RESPONSES_PATH, ANTHROPIC_BASE_PATH, ANTHROPIC_MESSAGES_PATH } from "./src/invoke.js";
|
|
22
21
|
export { MODEL_METADATA_TTL_MS, MODEL_RATE_LIMITS_URL, OPENAI_RESPONSES_MODELS_URL, QUERY_REASON_MODELS_URL, RETIRED_MODELS_URL, WEB_SEARCH_MODELS_URL } from "./src/metadata.js";
|
|
23
22
|
export { DEFAULT_MODEL_CACHE_TTL_MS, DEFAULT_FUZZY_THRESHOLD } from "./src/model-catalog.js";
|
|
24
23
|
export { DEFAULT_MODEL_CLIENT_CACHE_TTL_MS } from "./src/model-client.js";
|
|
25
24
|
export { ModelFamily } from "./src/policy.js";
|
|
26
25
|
export { REASONING_LEVELS } from "./src/reasoning-translation.js";
|
|
27
26
|
export * from "./exports.js";
|
|
28
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
27
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwyQ0FBMkM7QUFDM0MsbURBQW1EO0FBQ25ELHdFQUF3RTtBQUV4RSxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxrQkFBa0IsQ0FBQztBQUNyRCxNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsU0FBUyxDQUFDO0FBQ3pDLE9BQU8sS0FBSyxRQUFRLE1BQU0sbUJBQW1CLENBQUM7QUFDOUMsT0FBTyxLQUFLLE9BQU8sTUFBTSxrQkFBa0IsQ0FBQztBQUM1QyxPQUFPLEtBQUssUUFBUSxNQUFNLG1CQUFtQixDQUFDO0FBQzlDLE9BQU8sS0FBSyxRQUFRLE1BQU0sbUJBQW1CLENBQUM7QUFDOUMsT0FBTyxLQUFLLE1BQU0sTUFBTSxpQkFBaUIsQ0FBQztBQUMxQyxPQUFPLEtBQUssUUFBUSxNQUFNLG1CQUFtQixDQUFDO0FBQzlDLE9BQU8sS0FBSyxhQUFhLE1BQU0seUJBQXlCLENBQUM7QUFDekQsT0FBTyxLQUFLLFlBQVksTUFBTSx3QkFBd0IsQ0FBQztBQUN2RCxPQUFPLEtBQUssV0FBVyxNQUFNLHVCQUF1QixDQUFDO0FBQ3JELE9BQU8sS0FBSyxNQUFNLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxLQUFLLG9CQUFvQixNQUFNLGdDQUFnQyxDQUFDO0FBQ3ZFLE9BQU8sS0FBSyxPQUFPLE1BQU0sa0JBQWtCLENBQUM7QUFDNUMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLGlCQUFpQixFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDdkUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDdkQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLHNCQUFzQixFQUFFLGNBQWMsRUFBRSxtQkFBbUIsRUFBRSxxQkFBcUIsRUFBRSwrQkFBK0IsRUFBRSxtQkFBbUIsRUFBRSx1QkFBdUIsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRXhOLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxxQkFBcUIsRUFBRSwyQkFBMkIsRUFBRSx1QkFBdUIsRUFBRSxrQkFBa0IsRUFBRSxxQkFBcUIsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRWxMLE9BQU8sRUFBRSwwQkFBMEIsRUFBRSx1QkFBdUIsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRTdGLE9BQU8sRUFBRSxpQ0FBaUMsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBRTFFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUM5QyxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUdsRSxjQUFjLGNBQWMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIEdFTkVSQVRFRCBieSBwcm9qZW4gd2F0Y2ggLSBETyBOT1QgRURJVC5cbi8vIFJlZ2VuZXJhdGVkIGZyb20gdGhlIGV4cG9ydGluZyBtb2R1bGVzIGluIC4vc3JjLlxuLy8gSGFuZCBlZGl0cyBhcmUgb3ZlcndyaXR0ZW4gb24gdGhlIG5leHQgd2F0Y2g7IHRoaXMgZmlsZSBpcyByZWFkLW9ubHkuXG5cbmV4cG9ydCBjb25zdCBQQUNLQUdFX0lERU5USUZJRVIgPSBcIkBkYngtdG9vbHMvbW9kZWxcIjtcbmV4cG9ydCBjb25zdCBQQUNLQUdFX1ZFUlNJT04gPSBcIjAuOS4xMDVcIjtcbmV4cG9ydCAqIGFzIGJpbmRpbmdzIGZyb20gXCIuL3NyYy9iaW5kaW5ncy50c1wiO1xuZXhwb3J0ICogYXMgY2xhc3NlcyBmcm9tIFwiLi9zcmMvY2xhc3Nlcy50c1wiO1xuZXhwb3J0ICogYXMgY2xhc3NpZnkgZnJvbSBcIi4vc3JjL2NsYXNzaWZ5LnRzXCI7XG5leHBvcnQgKiBhcyBmYWxsYmFjayBmcm9tIFwiLi9zcmMvZmFsbGJhY2sudHNcIjtcbmV4cG9ydCAqIGFzIGludm9rZSBmcm9tIFwiLi9zcmMvaW52b2tlLnRzXCI7XG5leHBvcnQgKiBhcyBtZXRhZGF0YSBmcm9tIFwiLi9zcmMvbWV0YWRhdGEudHNcIjtcbmV4cG9ydCAqIGFzIG1ldGFkYXRhQ2FjaGUgZnJvbSBcIi4vc3JjL21ldGFkYXRhLWNhY2hlLnRzXCI7XG5leHBvcnQgKiBhcyBtb2RlbENhdGFsb2cgZnJvbSBcIi4vc3JjL21vZGVsLWNhdGFsb2cudHNcIjtcbmV4cG9ydCAqIGFzIG1vZGVsQ2xpZW50IGZyb20gXCIuL3NyYy9tb2RlbC1jbGllbnQudHNcIjtcbmV4cG9ydCAqIGFzIHBvbGljeSBmcm9tIFwiLi9zcmMvcG9saWN5LnRzXCI7XG5leHBvcnQgKiBhcyByZWFzb25pbmdUcmFuc2xhdGlvbiBmcm9tIFwiLi9zcmMvcmVhc29uaW5nLXRyYW5zbGF0aW9uLnRzXCI7XG5leHBvcnQgKiBhcyByZXNvbHZlIGZyb20gXCIuL3NyYy9yZXNvbHZlLnRzXCI7XG5leHBvcnQgeyBDSEFUX0NMQVNTX09SREVSLCBNT0RFTF9DTEFTU19PUkRFUiB9IGZyb20gXCIuL3NyYy9jbGFzc2VzLnRzXCI7XG5leHBvcnQgeyBGQUxMQkFDS19NT0RFTF9JRFMgfSBmcm9tIFwiLi9zcmMvZmFsbGJhY2sudHNcIjtcbmV4cG9ydCB7IElOVk9DQVRJT05TX1NVRkZJWCwgU0VSVklOR19FTkRQT0lOVFNfUEFUSCwgUkVTUE9OU0VTX1BBVEgsIE9QRU5fUkVTUE9OU0VTX1BBVEgsIENIQVRfQ09NUExFVElPTlNfUEFUSCwgQUlfR0FURVdBWV9DT0RFWF9SRVNQT05TRVNfUEFUSCwgQU5USFJPUElDX0JBU0VfUEFUSCwgQU5USFJPUElDX01FU1NBR0VTX1BBVEggfSBmcm9tIFwiLi9zcmMvaW52b2tlLnRzXCI7XG5leHBvcnQgdHlwZSB7IEF1dGhlbnRpY2F0aW5nQ2xpZW50TGlrZSB9IGZyb20gXCIuL3NyYy9pbnZva2UudHNcIjtcbmV4cG9ydCB7IE1PREVMX01FVEFEQVRBX1RUTF9NUywgTU9ERUxfUkFURV9MSU1JVFNfVVJMLCBPUEVOQUlfUkVTUE9OU0VTX01PREVMU19VUkwsIFFVRVJZX1JFQVNPTl9NT0RFTFNfVVJMLCBSRVRJUkVEX01PREVMU19VUkwsIFdFQl9TRUFSQ0hfTU9ERUxTX1VSTCB9IGZyb20gXCIuL3NyYy9tZXRhZGF0YS50c1wiO1xuZXhwb3J0IHR5cGUgeyBNZXRhZGF0YUNhY2hlUmVjb3JkLCBNZXRhZGF0YUNhY2hlT3B0aW9ucywgTWV0YWRhdGFDYWNoZU1lcmdlSW5wdXQsIE1ldGFkYXRhQ2FjaGUgfSBmcm9tIFwiLi9zcmMvbWV0YWRhdGEtY2FjaGUudHNcIjtcbmV4cG9ydCB7IERFRkFVTFRfTU9ERUxfQ0FDSEVfVFRMX01TLCBERUZBVUxUX0ZVWlpZX1RIUkVTSE9MRCB9IGZyb20gXCIuL3NyYy9tb2RlbC1jYXRhbG9nLnRzXCI7XG5leHBvcnQgdHlwZSB7IFdvcmtzcGFjZUNsaWVudExpa2UsIExpc3RTZXJ2aW5nRW5kcG9pbnRzT3B0aW9ucyB9IGZyb20gXCIuL3NyYy9tb2RlbC1jYXRhbG9nLnRzXCI7XG5leHBvcnQgeyBERUZBVUxUX01PREVMX0NMSUVOVF9DQUNIRV9UVExfTVMgfSBmcm9tIFwiLi9zcmMvbW9kZWwtY2xpZW50LnRzXCI7XG5leHBvcnQgdHlwZSB7IE1vZGVsQXV0aE9wdGlvbnMsIE1vZGVsQ2xpZW50T3B0aW9ucywgTW9kZWxDbGllbnRTdGF0dXMsIE1vZGVsUHJvdG9jb2wsIE1vZGVsUm91dGVJbnB1dCwgTW9kZWxSb3V0ZSwgTW9kZWxDbGllbnQgfSBmcm9tIFwiLi9zcmMvbW9kZWwtY2xpZW50LnRzXCI7XG5leHBvcnQgeyBNb2RlbEZhbWlseSB9IGZyb20gXCIuL3NyYy9wb2xpY3kudHNcIjtcbmV4cG9ydCB7IFJFQVNPTklOR19MRVZFTFMgfSBmcm9tIFwiLi9zcmMvcmVhc29uaW5nLXRyYW5zbGF0aW9uLnRzXCI7XG5leHBvcnQgdHlwZSB7IFJlYXNvbmluZ0xldmVsLCBSZWFzb25pbmdNb2RlbENhdGFsb2d1ZSwgQWRhcHRlZFJlcXVlc3RSZWFzb25pbmcgfSBmcm9tIFwiLi9zcmMvcmVhc29uaW5nLXRyYW5zbGF0aW9uLnRzXCI7XG5leHBvcnQgdHlwZSB7IFNlbGVjdE1vZGVsSW5wdXQsIFNlYXJjaE1vZGVsc0lucHV0IH0gZnJvbSBcIi4vc3JjL3Jlc29sdmUudHNcIjtcbmV4cG9ydCAqIGZyb20gXCIuL2V4cG9ydHMudHNcIjtcbiJdfQ==
|
package/lib/package.json
CHANGED
|
@@ -95,14 +95,10 @@
|
|
|
95
95
|
"types": "./lib/src/resolve.d.ts",
|
|
96
96
|
"default": "./lib/src/resolve.js"
|
|
97
97
|
},
|
|
98
|
-
"./serving-wire": {
|
|
99
|
-
"types": "./lib/src/serving-wire.d.ts",
|
|
100
|
-
"default": "./lib/src/serving-wire.js"
|
|
101
|
-
},
|
|
102
98
|
"./package.json": "./package.json"
|
|
103
99
|
}
|
|
104
100
|
},
|
|
105
|
-
"version": "0.9.
|
|
101
|
+
"version": "0.9.105",
|
|
106
102
|
"types": "index.ts",
|
|
107
103
|
"dbxToolsConfig": {
|
|
108
104
|
"tags": [
|
|
@@ -124,7 +120,6 @@
|
|
|
124
120
|
"./policy": "./src/policy.ts",
|
|
125
121
|
"./reasoning-translation": "./src/reasoning-translation.ts",
|
|
126
122
|
"./resolve": "./src/resolve.ts",
|
|
127
|
-
"./serving-wire": "./src/serving-wire.ts",
|
|
128
123
|
"./package.json": "./package.json"
|
|
129
124
|
},
|
|
130
125
|
"files": [
|
package/lib/src/invoke.d.ts
CHANGED
|
@@ -24,6 +24,8 @@
|
|
|
24
24
|
* models (notably Codex) reject this path and require {@link responsesUrl}.
|
|
25
25
|
*/
|
|
26
26
|
export declare const INVOCATIONS_SUFFIX = "invocations";
|
|
27
|
+
/** Workspace Model Serving root path used by provider base URLs. */
|
|
28
|
+
export declare const SERVING_ENDPOINTS_PATH = "serving-endpoints";
|
|
27
29
|
/**
|
|
28
30
|
* Workspace-level OpenAI Responses API path. Body carries `model` (endpoint
|
|
29
31
|
* id); used by GPT / Codex models that speak Responses natively.
|
|
@@ -43,8 +45,12 @@ export declare const OPEN_RESPONSES_PATH = "serving-endpoints/open-responses";
|
|
|
43
45
|
export declare const CHAT_COMPLETIONS_PATH = "serving-endpoints/chat/completions";
|
|
44
46
|
/** Unity Gateway OpenAI Responses path used by Codex-compatible model services. */
|
|
45
47
|
export declare const AI_GATEWAY_CODEX_RESPONSES_PATH = "ai-gateway/codex/v1/responses";
|
|
48
|
+
/** Workspace Anthropic provider root path. */
|
|
49
|
+
export declare const ANTHROPIC_BASE_PATH = "serving-endpoints/anthropic/v1";
|
|
46
50
|
/** Workspace Anthropic Messages path for native Claude requests. */
|
|
47
51
|
export declare const ANTHROPIC_MESSAGES_PATH = "serving-endpoints/anthropic/v1/messages";
|
|
52
|
+
/** Workspace Model Serving root URL used by OpenAI-compatible providers. */
|
|
53
|
+
export declare function servingEndpointsUrl(host: string): string;
|
|
48
54
|
/**
|
|
49
55
|
* The OpenAI-compatible chat-completions invocations URL for an endpoint id.
|
|
50
56
|
*
|
|
@@ -63,6 +69,8 @@ export declare function chatCompletionsUrl(host: string): string;
|
|
|
63
69
|
export declare function aiGatewayCodexResponsesUrl(host: string): string;
|
|
64
70
|
/** Workspace Anthropic Messages URL (`POST`, model in the body). */
|
|
65
71
|
export declare function anthropicMessagesUrl(host: string): string;
|
|
72
|
+
/** Workspace Anthropic provider base URL used by AI SDK providers. */
|
|
73
|
+
export declare function anthropicBaseUrl(host: string): string;
|
|
66
74
|
/**
|
|
67
75
|
* True when the endpoint is known to reject Chat Completions `/invocations`
|
|
68
76
|
* and require the Responses API (Codex models today). Callers should route
|
package/lib/src/invoke.js
CHANGED
|
@@ -25,27 +25,35 @@ import { isResponsesOnly as isResponsesOnlyByPolicy } from "./policy.js";
|
|
|
25
25
|
* models (notably Codex) reject this path and require {@link responsesUrl}.
|
|
26
26
|
*/
|
|
27
27
|
export const INVOCATIONS_SUFFIX = "invocations";
|
|
28
|
+
/** Workspace Model Serving root path used by provider base URLs. */
|
|
29
|
+
export const SERVING_ENDPOINTS_PATH = "serving-endpoints";
|
|
28
30
|
/**
|
|
29
31
|
* Workspace-level OpenAI Responses API path. Body carries `model` (endpoint
|
|
30
32
|
* id); used by GPT / Codex models that speak Responses natively.
|
|
31
33
|
*/
|
|
32
|
-
export const RESPONSES_PATH =
|
|
34
|
+
export const RESPONSES_PATH = `${SERVING_ENDPOINTS_PATH}/responses`;
|
|
33
35
|
/**
|
|
34
36
|
* Workspace-level Open Responses API path - the cross-provider Responses
|
|
35
37
|
* surface (Claude, Gemini, …) that OpenAI `/responses` does not cover.
|
|
36
38
|
*/
|
|
37
|
-
export const OPEN_RESPONSES_PATH =
|
|
39
|
+
export const OPEN_RESPONSES_PATH = `${SERVING_ENDPOINTS_PATH}/open-responses`;
|
|
38
40
|
/**
|
|
39
41
|
* Workspace-level OpenAI Chat Completions path. Body carries `model` (endpoint
|
|
40
42
|
* id), unlike {@link invocationsUrl} which names the endpoint in the URL. Use
|
|
41
43
|
* this when the caller has a model id rather than a per-endpoint route - e.g.
|
|
42
44
|
* attaching a provider tool spec to whichever endpoint was resolved.
|
|
43
45
|
*/
|
|
44
|
-
export const CHAT_COMPLETIONS_PATH =
|
|
46
|
+
export const CHAT_COMPLETIONS_PATH = `${SERVING_ENDPOINTS_PATH}/chat/completions`;
|
|
45
47
|
/** Unity Gateway OpenAI Responses path used by Codex-compatible model services. */
|
|
46
48
|
export const AI_GATEWAY_CODEX_RESPONSES_PATH = "ai-gateway/codex/v1/responses";
|
|
49
|
+
/** Workspace Anthropic provider root path. */
|
|
50
|
+
export const ANTHROPIC_BASE_PATH = `${SERVING_ENDPOINTS_PATH}/anthropic/v1`;
|
|
47
51
|
/** Workspace Anthropic Messages path for native Claude requests. */
|
|
48
|
-
export const ANTHROPIC_MESSAGES_PATH =
|
|
52
|
+
export const ANTHROPIC_MESSAGES_PATH = `${ANTHROPIC_BASE_PATH}/messages`;
|
|
53
|
+
/** Workspace Model Serving root URL used by OpenAI-compatible providers. */
|
|
54
|
+
export function servingEndpointsUrl(host) {
|
|
55
|
+
return new URL(SERVING_ENDPOINTS_PATH, host).toString().replace(/\/$/, "");
|
|
56
|
+
}
|
|
49
57
|
/**
|
|
50
58
|
* The OpenAI-compatible chat-completions invocations URL for an endpoint id.
|
|
51
59
|
*
|
|
@@ -54,7 +62,7 @@ export const ANTHROPIC_MESSAGES_PATH = "serving-endpoints/anthropic/v1/messages"
|
|
|
54
62
|
* @param endpoint - Endpoint id (already resolved; not fuzzy-matched here).
|
|
55
63
|
*/
|
|
56
64
|
export function invocationsUrl(host, endpoint) {
|
|
57
|
-
return new URL(
|
|
65
|
+
return new URL(`${SERVING_ENDPOINTS_PATH}/${encodeURIComponent(endpoint)}/${INVOCATIONS_SUFFIX}`, host).toString();
|
|
58
66
|
}
|
|
59
67
|
/** Workspace OpenAI Responses API URL (`POST`, model in the body). */
|
|
60
68
|
export function responsesUrl(host) {
|
|
@@ -76,6 +84,10 @@ export function aiGatewayCodexResponsesUrl(host) {
|
|
|
76
84
|
export function anthropicMessagesUrl(host) {
|
|
77
85
|
return new URL(ANTHROPIC_MESSAGES_PATH, host).toString();
|
|
78
86
|
}
|
|
87
|
+
/** Workspace Anthropic provider base URL used by AI SDK providers. */
|
|
88
|
+
export function anthropicBaseUrl(host) {
|
|
89
|
+
return new URL(ANTHROPIC_BASE_PATH, host).toString().replace(/\/$/, "");
|
|
90
|
+
}
|
|
79
91
|
/**
|
|
80
92
|
* True when the endpoint is known to reject Chat Completions `/invocations`
|
|
81
93
|
* and require the Responses API (Codex models today). Callers should route
|
|
@@ -114,4 +126,4 @@ export async function authHeaders(client) {
|
|
|
114
126
|
});
|
|
115
127
|
return out;
|
|
116
128
|
}
|
|
117
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW52b2tlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2ludm9rZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBa0JHO0FBRUgsT0FBTyxFQUFFLGVBQWUsSUFBSSx1QkFBdUIsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUV6RTs7Ozs7R0FLRztBQUNILE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFHLGFBQWEsQ0FBQztBQUVoRDs7O0dBR0c7QUFDSCxNQUFNLENBQUMsTUFBTSxjQUFjLEdBQUcsNkJBQTZCLENBQUM7QUFFNUQ7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLEdBQUcsa0NBQWtDLENBQUM7QUFFdEU7Ozs7O0dBS0c7QUFDSCxNQUFNLENBQUMsTUFBTSxxQkFBcUIsR0FBRyxvQ0FBb0MsQ0FBQztBQUUxRSxtRkFBbUY7QUFDbkYsTUFBTSxDQUFDLE1BQU0sK0JBQStCLEdBQUcsK0JBQStCLENBQUM7QUFFL0Usb0VBQW9FO0FBQ3BFLE1BQU0sQ0FBQyxNQUFNLHVCQUF1QixHQUFHLHlDQUF5QyxDQUFDO0FBRWpGOzs7Ozs7R0FNRztBQUNILE1BQU0sVUFBVSxjQUFjLENBQUMsSUFBWSxFQUFFLFFBQWdCO0lBQzNELE9BQU8sSUFBSSxHQUFHLENBQ1oscUJBQXFCLGtCQUFrQixDQUFDLFFBQVEsQ0FBQyxJQUFJLGtCQUFrQixFQUFFLEVBQ3pFLElBQUksQ0FDTCxDQUFDLFFBQVEsRUFBRSxDQUFDO0FBQ2YsQ0FBQztBQUVELHNFQUFzRTtBQUN0RSxNQUFNLFVBQVUsWUFBWSxDQUFDLElBQVk7SUFDdkMsT0FBTyxJQUFJLEdBQUcsQ0FBQyxjQUFjLEVBQUUsSUFBSSxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUM7QUFDbEQsQ0FBQztBQUVELG9FQUFvRTtBQUNwRSxNQUFNLFVBQVUsZ0JBQWdCLENBQUMsSUFBWTtJQUMzQyxPQUFPLElBQUksR0FBRyxDQUFDLG1CQUFtQixFQUFFLElBQUksQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDO0FBQ3ZELENBQUM7QUFFRCx5RUFBeUU7QUFDekUsTUFBTSxVQUFVLGtCQUFrQixDQUFDLElBQVk7SUFDN0MsT0FBTyxJQUFJLEdBQUcsQ0FBQyxxQkFBcUIsRUFBRSxJQUFJLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQztBQUN6RCxDQUFDO0FBRUQsNkVBQTZFO0FBQzdFLE1BQU0sVUFBVSwwQkFBMEIsQ0FBQyxJQUFZO0lBQ3JELE9BQU8sSUFBSSxHQUFHLENBQUMsK0JBQStCLEVBQUUsSUFBSSxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUM7QUFDbkUsQ0FBQztBQUVELG9FQUFvRTtBQUNwRSxNQUFNLFVBQVUsb0JBQW9CLENBQUMsSUFBWTtJQUMvQyxPQUFPLElBQUksR0FBRyxDQUFDLHVCQUF1QixFQUFFLElBQUksQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDO0FBQzNELENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLGVBQWUsQ0FBQyxRQUFnQjtJQUM5QyxPQUFPLHVCQUF1QixDQUFDLFFBQVEsQ0FBQyxDQUFDO0FBQzNDLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLG9CQUFvQixDQUFDLElBQVksRUFBRSxRQUFnQjtJQUNqRSxPQUFPLGNBQWMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztBQUNoRixDQUFDO0FBRUQsK0VBQStFO0FBQy9FLFNBQVMsY0FBYyxDQUFDLFFBQWdCO0lBQ3RDLE1BQU0sQ0FBQyxHQUFHLFFBQVEsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUNqQyxPQUFPLENBQ0wsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUM7UUFDakIsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUM7UUFDbkIsNEJBQTRCLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztRQUNwQyxDQUFDLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUNyQixDQUFDO0FBQ0osQ0FBQztBQWNEOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsS0FBSyxVQUFVLFdBQVcsQ0FDL0IsTUFBZ0M7SUFFaEMsTUFBTSxPQUFPLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQztJQUM5QixNQUFNLE1BQU0sQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0lBQzFDLE1BQU0sR0FBRyxHQUEyQixFQUFFLENBQUM7SUFDdkMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxHQUFHLEVBQUUsRUFBRTtRQUM3QixHQUFHLENBQUMsR0FBRyxDQUFDLEdBQUcsS0FBSyxDQUFDO0lBQ25CLENBQUMsQ0FBQyxDQUFDO0lBQ0gsT0FBTyxHQUFHLENBQUM7QUFDYixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDYWxsaW5nIGEgTW9kZWwgU2VydmluZyBlbmRwb2ludCBkaXJlY3RseSBvdmVyIEhUVFAuXG4gKlxuICogVGhlIFNESydzIGBzZXJ2aW5nRW5kcG9pbnRzLnF1ZXJ5YCBjb3ZlcnMgdGhlIHR5cGVkIHJlcXVlc3Qgc2hhcGVzLCBidXQgYW5cbiAqIE9wZW5BSS1jb21wYXRpYmxlIGNhbGxlciAoYSBwcm94eSwgYSBwYXNzdGhyb3VnaCByb3V0ZSwgYSBzdHJlYW1pbmcgY2xpZW50KVxuICogbmVlZHMgdG8gaXNzdWUgaXRzIG93biBgZmV0Y2hgIGFnYWluc3QgRGF0YWJyaWNrcycgT3BlbkFJLXNoYXBlZCBVUkxzIHdpdGhcbiAqIGFuIE9wZW5BSSBib2R5LiBUaGF0IG5lZWRzIGV4YWN0bHkgdHdvIHRoaW5ncyB0aGUgU0RLIGRvZXNuJ3QgaGFuZCBvdXRcbiAqIGRpcmVjdGx5OiB0aGUgVVJMICh7QGxpbmsgaW52b2NhdGlvbnNVcmx9IC8ge0BsaW5rIHJlc3BvbnNlc1VybH0gL1xuICoge0BsaW5rIG9wZW5SZXNwb25zZXNVcmx9KSBhbmQgYSBjdXJyZW50bHktdmFsaWQgc2V0IG9mIGF1dGggaGVhZGVyc1xuICogKHtAbGluayBhdXRoSGVhZGVyc30pLlxuICpcbiAqIEF1dGggaXMgZGVsZWdhdGVkIGVudGlyZWx5IHRvIHRoZSBEYXRhYnJpY2tzIFNESzogYGNvbmZpZy5hdXRoZW50aWNhdGVgXG4gKiByZS1ydW5zIHRoZSBjb25maWd1cmVkIGNyZWRlbnRpYWwgcHJvdmlkZXIgb24gZXZlcnkgY2FsbCBhbmQgcmVmcmVzaGVzIHRoZVxuICogdW5kZXJseWluZyBPQXV0aCAvIFBBVCB0b2tlbiB3aGVuIGl0IGlzIGNsb3NlIHRvIGV4cGlyeSwgc28gYSBjYWxsZXIgbmV2ZXJcbiAqIG1hbmFnZXMgdG9rZW4gbGlmZXRpbWVzIGl0c2VsZiAtIG1pbnQgaGVhZGVycyBwZXIgcmVxdWVzdCBhbmQgZWFjaCBvbmUgaXNcbiAqIHNpZ25lZCB3aXRoIGEgdmFsaWQgYmVhcmVyIHRva2VuLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBpc1Jlc3BvbnNlc09ubHkgYXMgaXNSZXNwb25zZXNPbmx5QnlQb2xpY3kgfSBmcm9tIFwiLi9wb2xpY3kudHNcIjtcblxuLyoqXG4gKiBQYXRoIHNlZ21lbnQgYXBwZW5kZWQgdG8gYSBzZXJ2aW5nIGVuZHBvaW50IGZvciBPcGVuQUktY29tcGF0aWJsZSBjaGF0XG4gKiByZXF1ZXN0cy4gRGF0YWJyaWNrcyByb3V0ZXMgYC9zZXJ2aW5nLWVuZHBvaW50cy88bmFtZT4vaW52b2NhdGlvbnNgIHRvIHRoZVxuICogZW5kcG9pbnQncyBDaGF0IENvbXBsZXRpb25zIHN1cmZhY2UgKGBtZXNzYWdlc2AgaW4sIGBjaG9pY2VzYCBvdXQpLiBTb21lXG4gKiBtb2RlbHMgKG5vdGFibHkgQ29kZXgpIHJlamVjdCB0aGlzIHBhdGggYW5kIHJlcXVpcmUge0BsaW5rIHJlc3BvbnNlc1VybH0uXG4gKi9cbmV4cG9ydCBjb25zdCBJTlZPQ0FUSU9OU19TVUZGSVggPSBcImludm9jYXRpb25zXCI7XG5cbi8qKlxuICogV29ya3NwYWNlLWxldmVsIE9wZW5BSSBSZXNwb25zZXMgQVBJIHBhdGguIEJvZHkgY2FycmllcyBgbW9kZWxgIChlbmRwb2ludFxuICogaWQpOyB1c2VkIGJ5IEdQVCAvIENvZGV4IG1vZGVscyB0aGF0IHNwZWFrIFJlc3BvbnNlcyBuYXRpdmVseS5cbiAqL1xuZXhwb3J0IGNvbnN0IFJFU1BPTlNFU19QQVRIID0gXCJzZXJ2aW5nLWVuZHBvaW50cy9yZXNwb25zZXNcIjtcblxuLyoqXG4gKiBXb3Jrc3BhY2UtbGV2ZWwgT3BlbiBSZXNwb25zZXMgQVBJIHBhdGggLSB0aGUgY3Jvc3MtcHJvdmlkZXIgUmVzcG9uc2VzXG4gKiBzdXJmYWNlIChDbGF1ZGUsIEdlbWluaSwg4oCmKSB0aGF0IE9wZW5BSSBgL3Jlc3BvbnNlc2AgZG9lcyBub3QgY292ZXIuXG4gKi9cbmV4cG9ydCBjb25zdCBPUEVOX1JFU1BPTlNFU19QQVRIID0gXCJzZXJ2aW5nLWVuZHBvaW50cy9vcGVuLXJlc3BvbnNlc1wiO1xuXG4vKipcbiAqIFdvcmtzcGFjZS1sZXZlbCBPcGVuQUkgQ2hhdCBDb21wbGV0aW9ucyBwYXRoLiBCb2R5IGNhcnJpZXMgYG1vZGVsYCAoZW5kcG9pbnRcbiAqIGlkKSwgdW5saWtlIHtAbGluayBpbnZvY2F0aW9uc1VybH0gd2hpY2ggbmFtZXMgdGhlIGVuZHBvaW50IGluIHRoZSBVUkwuIFVzZVxuICogdGhpcyB3aGVuIHRoZSBjYWxsZXIgaGFzIGEgbW9kZWwgaWQgcmF0aGVyIHRoYW4gYSBwZXItZW5kcG9pbnQgcm91dGUgLSBlLmcuXG4gKiBhdHRhY2hpbmcgYSBwcm92aWRlciB0b29sIHNwZWMgdG8gd2hpY2hldmVyIGVuZHBvaW50IHdhcyByZXNvbHZlZC5cbiAqL1xuZXhwb3J0IGNvbnN0IENIQVRfQ09NUExFVElPTlNfUEFUSCA9IFwic2VydmluZy1lbmRwb2ludHMvY2hhdC9jb21wbGV0aW9uc1wiO1xuXG4vKiogVW5pdHkgR2F0ZXdheSBPcGVuQUkgUmVzcG9uc2VzIHBhdGggdXNlZCBieSBDb2RleC1jb21wYXRpYmxlIG1vZGVsIHNlcnZpY2VzLiAqL1xuZXhwb3J0IGNvbnN0IEFJX0dBVEVXQVlfQ09ERVhfUkVTUE9OU0VTX1BBVEggPSBcImFpLWdhdGV3YXkvY29kZXgvdjEvcmVzcG9uc2VzXCI7XG5cbi8qKiBXb3Jrc3BhY2UgQW50aHJvcGljIE1lc3NhZ2VzIHBhdGggZm9yIG5hdGl2ZSBDbGF1ZGUgcmVxdWVzdHMuICovXG5leHBvcnQgY29uc3QgQU5USFJPUElDX01FU1NBR0VTX1BBVEggPSBcInNlcnZpbmctZW5kcG9pbnRzL2FudGhyb3BpYy92MS9tZXNzYWdlc1wiO1xuXG4vKipcbiAqIFRoZSBPcGVuQUktY29tcGF0aWJsZSBjaGF0LWNvbXBsZXRpb25zIGludm9jYXRpb25zIFVSTCBmb3IgYW4gZW5kcG9pbnQgaWQuXG4gKlxuICogQHBhcmFtIGhvc3QgLSBXb3Jrc3BhY2UgaG9zdCwgZS5nLiBgaHR0cHM6Ly9teS13b3Jrc3BhY2UuY2xvdWQuZGF0YWJyaWNrcy5jb20vYC5cbiAqICAgUGFzcyB0aGUgdmFsdWUgcmVzb2x2ZWQgZnJvbSBgY2xpZW50LmNvbmZpZy5nZXRIb3N0KClgLlxuICogQHBhcmFtIGVuZHBvaW50IC0gRW5kcG9pbnQgaWQgKGFscmVhZHkgcmVzb2x2ZWQ7IG5vdCBmdXp6eS1tYXRjaGVkIGhlcmUpLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaW52b2NhdGlvbnNVcmwoaG9zdDogc3RyaW5nLCBlbmRwb2ludDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIG5ldyBVUkwoXG4gICAgYHNlcnZpbmctZW5kcG9pbnRzLyR7ZW5jb2RlVVJJQ29tcG9uZW50KGVuZHBvaW50KX0vJHtJTlZPQ0FUSU9OU19TVUZGSVh9YCxcbiAgICBob3N0LFxuICApLnRvU3RyaW5nKCk7XG59XG5cbi8qKiBXb3Jrc3BhY2UgT3BlbkFJIFJlc3BvbnNlcyBBUEkgVVJMIChgUE9TVGAsIG1vZGVsIGluIHRoZSBib2R5KS4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNwb25zZXNVcmwoaG9zdDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIG5ldyBVUkwoUkVTUE9OU0VTX1BBVEgsIGhvc3QpLnRvU3RyaW5nKCk7XG59XG5cbi8qKiBXb3Jrc3BhY2UgT3BlbiBSZXNwb25zZXMgQVBJIFVSTCAoYFBPU1RgLCBtb2RlbCBpbiB0aGUgYm9keSkuICovXG5leHBvcnQgZnVuY3Rpb24gb3BlblJlc3BvbnNlc1VybChob3N0OiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gbmV3IFVSTChPUEVOX1JFU1BPTlNFU19QQVRILCBob3N0KS50b1N0cmluZygpO1xufVxuXG4vKiogV29ya3NwYWNlIE9wZW5BSSBDaGF0IENvbXBsZXRpb25zIFVSTCAoYFBPU1RgLCBtb2RlbCBpbiB0aGUgYm9keSkuICovXG5leHBvcnQgZnVuY3Rpb24gY2hhdENvbXBsZXRpb25zVXJsKGhvc3Q6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBuZXcgVVJMKENIQVRfQ09NUExFVElPTlNfUEFUSCwgaG9zdCkudG9TdHJpbmcoKTtcbn1cblxuLyoqIFVuaXR5IEdhdGV3YXkgQ29kZXggUmVzcG9uc2VzIFVSTCAoYFBPU1RgLCBtb2RlbCBzZXJ2aWNlIGluIHRoZSBib2R5KS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhaUdhdGV3YXlDb2RleFJlc3BvbnNlc1VybChob3N0OiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gbmV3IFVSTChBSV9HQVRFV0FZX0NPREVYX1JFU1BPTlNFU19QQVRILCBob3N0KS50b1N0cmluZygpO1xufVxuXG4vKiogV29ya3NwYWNlIEFudGhyb3BpYyBNZXNzYWdlcyBVUkwgKGBQT1NUYCwgbW9kZWwgaW4gdGhlIGJvZHkpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFudGhyb3BpY01lc3NhZ2VzVXJsKGhvc3Q6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBuZXcgVVJMKEFOVEhST1BJQ19NRVNTQUdFU19QQVRILCBob3N0KS50b1N0cmluZygpO1xufVxuXG4vKipcbiAqIFRydWUgd2hlbiB0aGUgZW5kcG9pbnQgaXMga25vd24gdG8gcmVqZWN0IENoYXQgQ29tcGxldGlvbnMgYC9pbnZvY2F0aW9uc2BcbiAqIGFuZCByZXF1aXJlIHRoZSBSZXNwb25zZXMgQVBJIChDb2RleCBtb2RlbHMgdG9kYXkpLiBDYWxsZXJzIHNob3VsZCByb3V0ZVxuICogdGhvc2UgdG8ge0BsaW5rIHJlc3BvbnNlc1VybH0gaW5zdGVhZCBvZiB7QGxpbmsgaW52b2NhdGlvbnNVcmx9LlxuICovXG5leHBvcnQgZnVuY3Rpb24gaXNSZXNwb25zZXNPbmx5KGVuZHBvaW50OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgcmV0dXJuIGlzUmVzcG9uc2VzT25seUJ5UG9saWN5KGVuZHBvaW50KTtcbn1cblxuLyoqXG4gKiBQaWNrIHRoZSBEYXRhYnJpY2tzIFJlc3BvbnNlcyB1cHN0cmVhbSBmb3IgYW4gZW5kcG9pbnQgaWQ6IE9wZW5BSS1mYW1pbHlcbiAqIG1vZGVscyB1c2UgYC9zZXJ2aW5nLWVuZHBvaW50cy9yZXNwb25zZXNgOyBldmVyeXRoaW5nIGVsc2UgdXNlcyB0aGVcbiAqIGNyb3NzLXByb3ZpZGVyIGAvc2VydmluZy1lbmRwb2ludHMvb3Blbi1yZXNwb25zZXNgLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzcG9uc2VzVXBzdHJlYW1VcmwoaG9zdDogc3RyaW5nLCBlbmRwb2ludDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIGlzT3BlbkFpRmFtaWx5KGVuZHBvaW50KSA/IHJlc3BvbnNlc1VybChob3N0KSA6IG9wZW5SZXNwb25zZXNVcmwoaG9zdCk7XG59XG5cbi8qKiBHUFQgLyBDb2RleCAvIG8tc2VyaWVzIHN0eWxlIGVuZHBvaW50IG5hbWVzIHRoYXQgc3BlYWsgT3BlbkFJIFJlc3BvbnNlcy4gKi9cbmZ1bmN0aW9uIGlzT3BlbkFpRmFtaWx5KGVuZHBvaW50OiBzdHJpbmcpOiBib29sZWFuIHtcbiAgY29uc3QgbiA9IGVuZHBvaW50LnRvTG93ZXJDYXNlKCk7XG4gIHJldHVybiAoXG4gICAgbi5pbmNsdWRlcyhcImdwdFwiKSB8fFxuICAgIG4uaW5jbHVkZXMoXCJjb2RleFwiKSB8fFxuICAgIC8oXnxbXmEtel0pb1sxLTldKFteYS16XXwkKS8udGVzdChuKSB8fFxuICAgIG4uaW5jbHVkZXMoXCJvcGVuYWlcIilcbiAgKTtcbn1cblxuLyoqXG4gKiBNaW5pbWFsIHN0cnVjdHVyYWwgc2hhcGUge0BsaW5rIGF1dGhIZWFkZXJzfSBuZWVkcy4gRGVjbGFyZWQgbmFycm93bHkgcmF0aGVyXG4gKiB0aGFuIGFzIGEgZnVsbCBgV29ya3NwYWNlQ2xpZW50TGlrZWAgc28gYSBjYWxsZXIgaG9sZGluZyBpdHMgb3duXG4gKiBgQGRhdGFicmlja3Mvc2RrLWV4cGVyaW1lbnRhbGAgYFdvcmtzcGFjZUNsaWVudGAgc2F0aXNmaWVzIGl0IHJlZ2FyZGxlc3Mgb2ZcbiAqIHdoaWNoIFNESyB2ZXJzaW9uIHJlc29sdmVkIGluIGl0cyB0cmVlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIEF1dGhlbnRpY2F0aW5nQ2xpZW50TGlrZSB7XG4gIGNvbmZpZzoge1xuICAgIGF1dGhlbnRpY2F0ZShoZWFkZXJzOiBIZWFkZXJzKTogUHJvbWlzZTx2b2lkPjtcbiAgfTtcbn1cblxuLyoqXG4gKiBNaW50IGF1dGggaGVhZGVycyBmb3Igb25lIHVwc3RyZWFtIHJlcXVlc3QgYXMgYSBwbGFpbiBvYmplY3QsIHJlYWR5IHRvIHNwcmVhZFxuICogaW50byBhIGBmZXRjaGAgaW5pdC4gQ2FsbCBpdCBwZXIgcmVxdWVzdDogdGhlIFNESyByZWZyZXNoZXMgdGhlIHVuZGVybHlpbmdcbiAqIHRva2VuIHdoZW4gbmVlZGVkLCBzbyBhIGxvbmctbGl2ZWQgcHJvY2VzcyBuZXZlciBoYXMgdG8gdHJhY2sgZXhwaXJ5IGl0c2VsZi5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGF1dGhIZWFkZXJzKFxuICBjbGllbnQ6IEF1dGhlbnRpY2F0aW5nQ2xpZW50TGlrZSxcbik6IFByb21pc2U8UmVjb3JkPHN0cmluZywgc3RyaW5nPj4ge1xuICBjb25zdCBoZWFkZXJzID0gbmV3IEhlYWRlcnMoKTtcbiAgYXdhaXQgY2xpZW50LmNvbmZpZy5hdXRoZW50aWNhdGUoaGVhZGVycyk7XG4gIGNvbnN0IG91dDogUmVjb3JkPHN0cmluZywgc3RyaW5nPiA9IHt9O1xuICBoZWFkZXJzLmZvckVhY2goKHZhbHVlLCBrZXkpID0+IHtcbiAgICBvdXRba2V5XSA9IHZhbHVlO1xuICB9KTtcbiAgcmV0dXJuIG91dDtcbn1cbiJdfQ==
|
|
129
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW52b2tlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2ludm9rZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBa0JHO0FBRUgsT0FBTyxFQUFFLGVBQWUsSUFBSSx1QkFBdUIsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUV6RTs7Ozs7R0FLRztBQUNILE1BQU0sQ0FBQyxNQUFNLGtCQUFrQixHQUFHLGFBQWEsQ0FBQztBQUVoRCxvRUFBb0U7QUFDcEUsTUFBTSxDQUFDLE1BQU0sc0JBQXNCLEdBQUcsbUJBQW1CLENBQUM7QUFFMUQ7OztHQUdHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sY0FBYyxHQUFHLEdBQUcsc0JBQXNCLFlBQVksQ0FBQztBQUVwRTs7O0dBR0c7QUFDSCxNQUFNLENBQUMsTUFBTSxtQkFBbUIsR0FBRyxHQUFHLHNCQUFzQixpQkFBaUIsQ0FBQztBQUU5RTs7Ozs7R0FLRztBQUNILE1BQU0sQ0FBQyxNQUFNLHFCQUFxQixHQUFHLEdBQUcsc0JBQXNCLG1CQUFtQixDQUFDO0FBRWxGLG1GQUFtRjtBQUNuRixNQUFNLENBQUMsTUFBTSwrQkFBK0IsR0FBRywrQkFBK0IsQ0FBQztBQUUvRSw4Q0FBOEM7QUFDOUMsTUFBTSxDQUFDLE1BQU0sbUJBQW1CLEdBQUcsR0FBRyxzQkFBc0IsZUFBZSxDQUFDO0FBRTVFLG9FQUFvRTtBQUNwRSxNQUFNLENBQUMsTUFBTSx1QkFBdUIsR0FBRyxHQUFHLG1CQUFtQixXQUFXLENBQUM7QUFFekUsNEVBQTRFO0FBQzVFLE1BQU0sVUFBVSxtQkFBbUIsQ0FBQyxJQUFZO0lBQzlDLE9BQU8sSUFBSSxHQUFHLENBQUMsc0JBQXNCLEVBQUUsSUFBSSxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztBQUM3RSxDQUFDO0FBRUQ7Ozs7OztHQU1HO0FBQ0gsTUFBTSxVQUFVLGNBQWMsQ0FBQyxJ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LyoqXG4gKiBDYWxsaW5nIGEgTW9kZWwgU2VydmluZyBlbmRwb2ludCBkaXJlY3RseSBvdmVyIEhUVFAuXG4gKlxuICogVGhlIFNESydzIGBzZXJ2aW5nRW5kcG9pbnRzLnF1ZXJ5YCBjb3ZlcnMgdGhlIHR5cGVkIHJlcXVlc3Qgc2hhcGVzLCBidXQgYW5cbiAqIE9wZW5BSS1jb21wYXRpYmxlIGNhbGxlciAoYSBwcm94eSwgYSBwYXNzdGhyb3VnaCByb3V0ZSwgYSBzdHJlYW1pbmcgY2xpZW50KVxuICogbmVlZHMgdG8gaXNzdWUgaXRzIG93biBgZmV0Y2hgIGFnYWluc3QgRGF0YWJyaWNrcycgT3BlbkFJLXNoYXBlZCBVUkxzIHdpdGhcbiAqIGFuIE9wZW5BSSBib2R5LiBUaGF0IG5lZWRzIGV4YWN0bHkgdHdvIHRoaW5ncyB0aGUgU0RLIGRvZXNuJ3QgaGFuZCBvdXRcbiAqIGRpcmVjdGx5OiB0aGUgVVJMICh7QGxpbmsgaW52b2NhdGlvbnNVcmx9IC8ge0BsaW5rIHJlc3BvbnNlc1VybH0gL1xuICoge0BsaW5rIG9wZW5SZXNwb25zZXNVcmx9KSBhbmQgYSBjdXJyZW50bHktdmFsaWQgc2V0IG9mIGF1dGggaGVhZGVyc1xuICogKHtAbGluayBhdXRoSGVhZGVyc30pLlxuICpcbiAqIEF1dGggaXMgZGVsZWdhdGVkIGVudGlyZWx5IHRvIHRoZSBEYXRhYnJpY2tzIFNESzogYGNvbmZpZy5hdXRoZW50aWNhdGVgXG4gKiByZS1ydW5zIHRoZSBjb25maWd1cmVkIGNyZWRlbnRpYWwgcHJvdmlkZXIgb24gZXZlcnkgY2FsbCBhbmQgcmVmcmVzaGVzIHRoZVxuICogdW5kZXJseWluZyBPQXV0aCAvIFBBVCB0b2tlbiB3aGVuIGl0IGlzIGNsb3NlIHRvIGV4cGlyeSwgc28gYSBjYWxsZXIgbmV2ZXJcbiAqIG1hbmFnZXMgdG9rZW4gbGlmZXRpbWVzIGl0c2VsZiAtIG1pbnQgaGVhZGVycyBwZXIgcmVxdWVzdCBhbmQgZWFjaCBvbmUgaXNcbiAqIHNpZ25lZCB3aXRoIGEgdmFsaWQgYmVhcmVyIHRva2VuLlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBpc1Jlc3BvbnNlc09ubHkgYXMgaXNSZXNwb25zZXNPbmx5QnlQb2xpY3kgfSBmcm9tIFwiLi9wb2xpY3kudHNcIjtcblxuLyoqXG4gKiBQYXRoIHNlZ21lbnQgYXBwZW5kZWQgdG8gYSBzZXJ2aW5nIGVuZHBvaW50IGZvciBPcGVuQUktY29tcGF0aWJsZSBjaGF0XG4gKiByZXF1ZXN0cy4gRGF0YWJyaWNrcyByb3V0ZXMgYC9zZXJ2aW5nLWVuZHBvaW50cy88bmFtZT4vaW52b2NhdGlvbnNgIHRvIHRoZVxuICogZW5kcG9pbnQncyBDaGF0IENvbXBsZXRpb25zIHN1cmZhY2UgKGBtZXNzYWdlc2AgaW4sIGBjaG9pY2VzYCBvdXQpLiBTb21lXG4gKiBtb2RlbHMgKG5vdGFibHkgQ29kZXgpIHJlamVjdCB0aGlzIHBhdGggYW5kIHJlcXVpcmUge0BsaW5rIHJlc3BvbnNlc1VybH0uXG4gKi9cbmV4cG9ydCBjb25zdCBJTlZPQ0FUSU9OU19TVUZGSVggPSBcImludm9jYXRpb25zXCI7XG5cbi8qKiBXb3Jrc3BhY2UgTW9kZWwgU2VydmluZyByb290IHBhdGggdXNlZCBieSBwcm92aWRlciBiYXNlIFVSTHMuICovXG5leHBvcnQgY29uc3QgU0VSVklOR19FTkRQT0lOVFNfUEFUSCA9IFwic2VydmluZy1lbmRwb2ludHNcIjtcblxuLyoqXG4gKiBXb3Jrc3BhY2UtbGV2ZWwgT3BlbkFJIFJlc3BvbnNlcyBBUEkgcGF0aC4gQm9keSBjYXJyaWVzIGBtb2RlbGAgKGVuZHBvaW50XG4gKiBpZCk7IHVzZWQgYnkgR1BUIC8gQ29kZXggbW9kZWxzIHRoYXQgc3BlYWsgUmVzcG9uc2VzIG5hdGl2ZWx5LlxuICovXG5leHBvcnQgY29uc3QgUkVTUE9OU0VTX1BBVEggPSBgJHtTRVJWSU5HX0VORFBPSU5UU19QQVRIfS9yZXNwb25zZXNgO1xuXG4vKipcbiAqIFdvcmtzcGFjZS1sZXZlbCBPcGVuIFJlc3BvbnNlcyBBUEkgcGF0aCAtIHRoZSBjcm9zcy1wcm92aWRlciBSZXNwb25zZXNcbiAqIHN1cmZhY2UgKENsYXVkZSwgR2VtaW5pLCDigKYpIHRoYXQgT3BlbkFJIGAvcmVzcG9uc2VzYCBkb2VzIG5vdCBjb3Zlci5cbiAqL1xuZXhwb3J0IGNvbnN0IE9QRU5fUkVTUE9OU0VTX1BBVEggPSBgJHtTRVJWSU5HX0VORFBPSU5UU19QQVRIfS9vcGVuLXJlc3BvbnNlc2A7XG5cbi8qKlxuICogV29ya3NwYWNlLWxldmVsIE9wZW5BSSBDaGF0IENvbXBsZXRpb25zIHBhdGguIEJvZHkgY2FycmllcyBgbW9kZWxgIChlbmRwb2ludFxuICogaWQpLCB1bmxpa2Uge0BsaW5rIGludm9jYXRpb25zVXJsfSB3aGljaCBuYW1lcyB0aGUgZW5kcG9pbnQgaW4gdGhlIFVSTC4gVXNlXG4gKiB0aGlzIHdoZW4gdGhlIGNhbGxlciBoYXMgYSBtb2RlbCBpZCByYXRoZXIgdGhhbiBhIHBlci1lbmRwb2ludCByb3V0ZSAtIGUuZy5cbiAqIGF0dGFjaGluZyBhIHByb3ZpZGVyIHRvb2wgc3BlYyB0byB3aGljaGV2ZXIgZW5kcG9pbnQgd2FzIHJlc29sdmVkLlxuICovXG5leHBvcnQgY29uc3QgQ0hBVF9DT01QTEVUSU9OU19QQVRIID0gYCR7U0VSVklOR19FTkRQT0lOVFNfUEFUSH0vY2hhdC9jb21wbGV0aW9uc2A7XG5cbi8qKiBVbml0eSBHYXRld2F5IE9wZW5BSSBSZXNwb25zZXMgcGF0aCB1c2VkIGJ5IENvZGV4LWNvbXBhdGlibGUgbW9kZWwgc2VydmljZXMuICovXG5leHBvcnQgY29uc3QgQUlfR0FURVdBWV9DT0RFWF9SRVNQT05TRVNfUEFUSCA9IFwiYWktZ2F0ZXdheS9jb2RleC92MS9yZXNwb25zZXNcIjtcblxuLyoqIFdvcmtzcGFjZSBBbnRocm9waWMgcHJvdmlkZXIgcm9vdCBwYXRoLiAqL1xuZXhwb3J0IGNvbnN0IEFOVEhST1BJQ19CQVNFX1BBVEggPSBgJHtTRVJWSU5HX0VORFBPSU5UU19QQVRIfS9hbnRocm9waWMvdjFgO1xuXG4vKiogV29ya3NwYWNlIEFudGhyb3BpYyBNZXNzYWdlcyBwYXRoIGZvciBuYXRpdmUgQ2xhdWRlIHJlcXVlc3RzLiAqL1xuZXhwb3J0IGNvbnN0IEFOVEhST1BJQ19NRVNTQUdFU19QQVRIID0gYCR7QU5USFJPUElDX0JBU0VfUEFUSH0vbWVzc2FnZXNgO1xuXG4vKiogV29ya3NwYWNlIE1vZGVsIFNlcnZpbmcgcm9vdCBVUkwgdXNlZCBieSBPcGVuQUktY29tcGF0aWJsZSBwcm92aWRlcnMuICovXG5leHBvcnQgZnVuY3Rpb24gc2VydmluZ0VuZHBvaW50c1VybChob3N0OiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gbmV3IFVSTChTRVJWSU5HX0VORFBPSU5UU19QQVRILCBob3N0KS50b1N0cmluZygpLnJlcGxhY2UoL1xcLyQvLCBcIlwiKTtcbn1cblxuLyoqXG4gKiBUaGUgT3BlbkFJLWNvbXBhdGlibGUgY2hhdC1jb21wbGV0aW9ucyBpbnZvY2F0aW9ucyBVUkwgZm9yIGFuIGVuZHBvaW50IGlkLlxuICpcbiAqIEBwYXJhbSBob3N0IC0gV29ya3NwYWNlIGhvc3QsIGUuZy4gYGh0dHBzOi8vbXktd29ya3NwYWNlLmNsb3VkLmRhdGFicmlja3MuY29tL2AuXG4gKiAgIFBhc3MgdGhlIHZhbHVlIHJlc29sdmVkIGZyb20gYGNsaWVudC5jb25maWcuZ2V0SG9zdCgpYC5cbiAqIEBwYXJhbSBlbmRwb2ludCAtIEVuZHBvaW50IGlkIChhbHJlYWR5IHJlc29sdmVkOyBub3QgZnV6enktbWF0Y2hlZCBoZXJlKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGludm9jYXRpb25zVXJsKGhvc3Q6IHN0cmluZywgZW5kcG9pbnQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBuZXcgVVJMKFxuICAgIGAke1NFUlZJTkdfRU5EUE9JTlRTX1BBVEh9LyR7ZW5jb2RlVVJJQ29tcG9uZW50KGVuZHBvaW50KX0vJHtJTlZPQ0FUSU9OU19TVUZGSVh9YCxcbiAgICBob3N0LFxuICApLnRvU3RyaW5nKCk7XG59XG5cbi8qKiBXb3Jrc3BhY2UgT3BlbkFJIFJlc3BvbnNlcyBBUEkgVVJMIChgUE9TVGAsIG1vZGVsIGluIHRoZSBib2R5KS4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXNwb25zZXNVcmwoaG9zdDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIG5ldyBVUkwoUkVTUE9OU0VTX1BBVEgsIGhvc3QpLnRvU3RyaW5nKCk7XG59XG5cbi8qKiBXb3Jrc3BhY2UgT3BlbiBSZXNwb25zZXMgQVBJIFVSTCAoYFBPU1RgLCBtb2RlbCBpbiB0aGUgYm9keSkuICovXG5leHBvcnQgZnVuY3Rpb24gb3BlblJlc3BvbnNlc1VybChob3N0OiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gbmV3IFVSTChPUEVOX1JFU1BPTlNFU19QQVRILCBob3N0KS50b1N0cmluZygpO1xufVxuXG4vKiogV29ya3NwYWNlIE9wZW5BSSBDaGF0IENvbXBsZXRpb25zIFVSTCAoYFBPU1RgLCBtb2RlbCBpbiB0aGUgYm9keSkuICovXG5leHBvcnQgZnVuY3Rpb24gY2hhdENvbXBsZXRpb25zVXJsKGhvc3Q6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBuZXcgVVJMKENIQVRfQ09NUExFVElPTlNfUEFUSCwgaG9zdCkudG9TdHJpbmcoKTtcbn1cblxuLyoqIFVuaXR5IEdhdGV3YXkgQ29kZXggUmVzcG9uc2VzIFVSTCAoYFBPU1RgLCBtb2RlbCBzZXJ2aWNlIGluIHRoZSBib2R5KS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBhaUdhdGV3YXlDb2RleFJlc3BvbnNlc1VybChob3N0OiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gbmV3IFVSTChBSV9HQVRFV0FZX0NPREVYX1JFU1BPTlNFU19QQVRILCBob3N0KS50b1N0cmluZygpO1xufVxuXG4vKiogV29ya3NwYWNlIEFudGhyb3BpYyBNZXNzYWdlcyBVUkwgKGBQT1NUYCwgbW9kZWwgaW4gdGhlIGJvZHkpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFudGhyb3BpY01lc3NhZ2VzVXJsKGhvc3Q6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBuZXcgVVJMKEFOVEhST1BJQ19NRVNTQUdFU19QQVRILCBob3N0KS50b1N0cmluZygpO1xufVxuXG4vKiogV29ya3NwYWNlIEFudGhyb3BpYyBwcm92aWRlciBiYXNlIFVSTCB1c2VkIGJ5IEFJIFNESyBwcm92aWRlcnMuICovXG5leHBvcnQgZnVuY3Rpb24gYW50aHJvcGljQmFzZVVybChob3N0OiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gbmV3IFVSTChBTlRIUk9QSUNfQkFTRV9QQVRILCBob3N0KS50b1N0cmluZygpLnJlcGxhY2UoL1xcLyQvLCBcIlwiKTtcbn1cblxuLyoqXG4gKiBUcnVlIHdoZW4gdGhlIGVuZHBvaW50IGlzIGtub3duIHRvIHJlamVjdCBDaGF0IENvbXBsZXRpb25zIGAvaW52b2NhdGlvbnNgXG4gKiBhbmQgcmVxdWlyZSB0aGUgUmVzcG9uc2VzIEFQSSAoQ29kZXggbW9kZWxzIHRvZGF5KS4gQ2FsbGVycyBzaG91bGQgcm91dGVcbiAqIHRob3NlIHRvIHtAbGluayByZXNwb25zZXNVcmx9IGluc3RlYWQgb2Yge0BsaW5rIGludm9jYXRpb25zVXJsfS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzUmVzcG9uc2VzT25seShlbmRwb2ludDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiBpc1Jlc3BvbnNlc09ubHlCeVBvbGljeShlbmRwb2ludCk7XG59XG5cbi8qKlxuICogUGljayB0aGUgRGF0YWJyaWNrcyBSZXNwb25zZXMgdXBzdHJlYW0gZm9yIGFuIGVuZHBvaW50IGlkOiBPcGVuQUktZmFtaWx5XG4gKiBtb2RlbHMgdXNlIGAvc2VydmluZy1lbmRwb2ludHMvcmVzcG9uc2VzYDsgZXZlcnl0aGluZyBlbHNlIHVzZXMgdGhlXG4gKiBjcm9zcy1wcm92aWRlciBgL3NlcnZpbmctZW5kcG9pbnRzL29wZW4tcmVzcG9uc2VzYC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlc3BvbnNlc1Vwc3RyZWFtVXJsKGhvc3Q6IHN0cmluZywgZW5kcG9pbnQ6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBpc09wZW5BaUZhbWlseShlbmRwb2ludCkgPyByZXNwb25zZXNVcmwoaG9zdCkgOiBvcGVuUmVzcG9uc2VzVXJsKGhvc3QpO1xufVxuXG4vKiogR1BUIC8gQ29kZXggLyBvLXNlcmllcyBzdHlsZSBlbmRwb2ludCBuYW1lcyB0aGF0IHNwZWFrIE9wZW5BSSBSZXNwb25zZXMuICovXG5mdW5jdGlvbiBpc09wZW5BaUZhbWlseShlbmRwb2ludDogc3RyaW5nKTogYm9vbGVhbiB7XG4gIGNvbnN0IG4gPSBlbmRwb2ludC50b0xvd2VyQ2FzZSgpO1xuICByZXR1cm4gKFxuICAgIG4uaW5jbHVkZXMoXCJncHRcIikgfHxcbiAgICBuLmluY2x1ZGVzKFwiY29kZXhcIikgfHxcbiAgICAvKF58W15hLXpdKW9bMS05XShbXmEtel18JCkvLnRlc3QobikgfHxcbiAgICBuLmluY2x1ZGVzKFwib3BlbmFpXCIpXG4gICk7XG59XG5cbi8qKlxuICogTWluaW1hbCBzdHJ1Y3R1cmFsIHNoYXBlIHtAbGluayBhdXRoSGVhZGVyc30gbmVlZHMuIERlY2xhcmVkIG5hcnJvd2x5IHJhdGhlclxuICogdGhhbiBhcyBhIGZ1bGwgYFdvcmtzcGFjZUNsaWVudExpa2VgIHNvIGEgY2FsbGVyIGhvbGRpbmcgaXRzIG93blxuICogYEBkYXRhYnJpY2tzL3Nkay1leHBlcmltZW50YWxgIGBXb3Jrc3BhY2VDbGllbnRgIHNhdGlzZmllcyBpdCByZWdhcmRsZXNzIG9mXG4gKiB3aGljaCBTREsgdmVyc2lvbiByZXNvbHZlZCBpbiBpdHMgdHJlZS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBdXRoZW50aWNhdGluZ0NsaWVudExpa2Uge1xuICBjb25maWc6IHtcbiAgICBhdXRoZW50aWNhdGUoaGVhZGVyczogSGVhZGVycyk6IFByb21pc2U8dm9pZD47XG4gIH07XG59XG5cbi8qKlxuICogTWludCBhdXRoIGhlYWRlcnMgZm9yIG9uZSB1cHN0cmVhbSByZXF1ZXN0IGFzIGEgcGxhaW4gb2JqZWN0LCByZWFkeSB0byBzcHJlYWRcbiAqIGludG8gYSBgZmV0Y2hgIGluaXQuIENhbGwgaXQgcGVyIHJlcXVlc3Q6IHRoZSBTREsgcmVmcmVzaGVzIHRoZSB1bmRlcmx5aW5nXG4gKiB0b2tlbiB3aGVuIG5lZWRlZCwgc28gYSBsb25nLWxpdmVkIHByb2Nlc3MgbmV2ZXIgaGFzIHRvIHRyYWNrIGV4cGlyeSBpdHNlbGYuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhdXRoSGVhZGVycyhcbiAgY2xpZW50OiBBdXRoZW50aWNhdGluZ0NsaWVudExpa2UsXG4pOiBQcm9taXNlPFJlY29yZDxzdHJpbmcsIHN0cmluZz4+IHtcbiAgY29uc3QgaGVhZGVycyA9IG5ldyBIZWFkZXJzKCk7XG4gIGF3YWl0IGNsaWVudC5jb25maWcuYXV0aGVudGljYXRlKGhlYWRlcnMpO1xuICBjb25zdCBvdXQ6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgaGVhZGVycy5mb3JFYWNoKCh2YWx1ZSwga2V5KSA9PiB7XG4gICAgb3V0W2tleV0gPSB2YWx1ZTtcbiAgfSk7XG4gIHJldHVybiBvdXQ7XG59XG4iXX0=
|
package/lib/tsconfig.tsbuildinfo
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../src/_metadata-contract.ts","../src/_metadata-generator.ts","../src/_ranking.ts","../src/_retirement.ts","../src/_selection.ts","../src/bindings.ts","../src/classes.ts","../src/classify.ts","../src/fallback.ts","../src/invoke.ts","../src/metadata-cache.ts","../src/metadata.ts","../src/model-catalog.ts","../src/model-client.ts","../src/policy.ts","../src/reasoning-translation.ts","../src/resolve.ts","../
|
|
1
|
+
{"root":["../src/_metadata-contract.ts","../src/_metadata-generator.ts","../src/_ranking.ts","../src/_retirement.ts","../src/_selection.ts","../src/bindings.ts","../src/classes.ts","../src/classify.ts","../src/fallback.ts","../src/invoke.ts","../src/metadata-cache.ts","../src/metadata.ts","../src/model-catalog.ts","../src/model-client.ts","../src/policy.ts","../src/reasoning-translation.ts","../src/resolve.ts","../scripts/generate-metadata.ts","../index.ts"],"version":"5.9.3"}
|
package/package.json
CHANGED
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@databricks/appkit": "0.81.0",
|
|
29
|
-
"@dbx-tools/appkit": "^0.9.
|
|
30
|
-
"@dbx-tools/auth": "^0.9.
|
|
31
|
-
"@dbx-tools/shared-auth": "^0.9.
|
|
32
|
-
"@dbx-tools/shared-core": "^0.9.
|
|
33
|
-
"@dbx-tools/shared-model": "^0.9.
|
|
29
|
+
"@dbx-tools/appkit": "^0.9.105",
|
|
30
|
+
"@dbx-tools/auth": "^0.9.105",
|
|
31
|
+
"@dbx-tools/shared-auth": "^0.9.105",
|
|
32
|
+
"@dbx-tools/shared-core": "^0.9.105",
|
|
33
|
+
"@dbx-tools/shared-model": "^0.9.105",
|
|
34
34
|
"cacache": "^21.0.1",
|
|
35
35
|
"cheerio": "^1.2.0",
|
|
36
36
|
"env-paths": "^4.0.0",
|
|
@@ -95,14 +95,10 @@
|
|
|
95
95
|
"types": "./lib/src/resolve.d.ts",
|
|
96
96
|
"default": "./lib/src/resolve.js"
|
|
97
97
|
},
|
|
98
|
-
"./serving-wire": {
|
|
99
|
-
"types": "./lib/src/serving-wire.d.ts",
|
|
100
|
-
"default": "./lib/src/serving-wire.js"
|
|
101
|
-
},
|
|
102
98
|
"./package.json": "./package.json"
|
|
103
99
|
}
|
|
104
100
|
},
|
|
105
|
-
"version": "0.9.
|
|
101
|
+
"version": "0.9.105",
|
|
106
102
|
"types": "./lib/index.d.ts",
|
|
107
103
|
"dbxToolsConfig": {
|
|
108
104
|
"tags": [
|
|
@@ -163,10 +159,6 @@
|
|
|
163
159
|
"types": "./lib/src/resolve.d.ts",
|
|
164
160
|
"default": "./lib/src/resolve.js"
|
|
165
161
|
},
|
|
166
|
-
"./serving-wire": {
|
|
167
|
-
"types": "./lib/src/serving-wire.d.ts",
|
|
168
|
-
"default": "./lib/src/serving-wire.js"
|
|
169
|
-
},
|
|
170
162
|
"./package.json": "./package.json"
|
|
171
163
|
},
|
|
172
164
|
"files": [
|
package/src/invoke.ts
CHANGED
|
@@ -28,17 +28,20 @@ import { isResponsesOnly as isResponsesOnlyByPolicy } from "./policy.ts";
|
|
|
28
28
|
*/
|
|
29
29
|
export const INVOCATIONS_SUFFIX = "invocations";
|
|
30
30
|
|
|
31
|
+
/** Workspace Model Serving root path used by provider base URLs. */
|
|
32
|
+
export const SERVING_ENDPOINTS_PATH = "serving-endpoints";
|
|
33
|
+
|
|
31
34
|
/**
|
|
32
35
|
* Workspace-level OpenAI Responses API path. Body carries `model` (endpoint
|
|
33
36
|
* id); used by GPT / Codex models that speak Responses natively.
|
|
34
37
|
*/
|
|
35
|
-
export const RESPONSES_PATH =
|
|
38
|
+
export const RESPONSES_PATH = `${SERVING_ENDPOINTS_PATH}/responses`;
|
|
36
39
|
|
|
37
40
|
/**
|
|
38
41
|
* Workspace-level Open Responses API path - the cross-provider Responses
|
|
39
42
|
* surface (Claude, Gemini, …) that OpenAI `/responses` does not cover.
|
|
40
43
|
*/
|
|
41
|
-
export const OPEN_RESPONSES_PATH =
|
|
44
|
+
export const OPEN_RESPONSES_PATH = `${SERVING_ENDPOINTS_PATH}/open-responses`;
|
|
42
45
|
|
|
43
46
|
/**
|
|
44
47
|
* Workspace-level OpenAI Chat Completions path. Body carries `model` (endpoint
|
|
@@ -46,13 +49,21 @@ export const OPEN_RESPONSES_PATH = "serving-endpoints/open-responses";
|
|
|
46
49
|
* this when the caller has a model id rather than a per-endpoint route - e.g.
|
|
47
50
|
* attaching a provider tool spec to whichever endpoint was resolved.
|
|
48
51
|
*/
|
|
49
|
-
export const CHAT_COMPLETIONS_PATH =
|
|
52
|
+
export const CHAT_COMPLETIONS_PATH = `${SERVING_ENDPOINTS_PATH}/chat/completions`;
|
|
50
53
|
|
|
51
54
|
/** Unity Gateway OpenAI Responses path used by Codex-compatible model services. */
|
|
52
55
|
export const AI_GATEWAY_CODEX_RESPONSES_PATH = "ai-gateway/codex/v1/responses";
|
|
53
56
|
|
|
57
|
+
/** Workspace Anthropic provider root path. */
|
|
58
|
+
export const ANTHROPIC_BASE_PATH = `${SERVING_ENDPOINTS_PATH}/anthropic/v1`;
|
|
59
|
+
|
|
54
60
|
/** Workspace Anthropic Messages path for native Claude requests. */
|
|
55
|
-
export const ANTHROPIC_MESSAGES_PATH =
|
|
61
|
+
export const ANTHROPIC_MESSAGES_PATH = `${ANTHROPIC_BASE_PATH}/messages`;
|
|
62
|
+
|
|
63
|
+
/** Workspace Model Serving root URL used by OpenAI-compatible providers. */
|
|
64
|
+
export function servingEndpointsUrl(host: string): string {
|
|
65
|
+
return new URL(SERVING_ENDPOINTS_PATH, host).toString().replace(/\/$/, "");
|
|
66
|
+
}
|
|
56
67
|
|
|
57
68
|
/**
|
|
58
69
|
* The OpenAI-compatible chat-completions invocations URL for an endpoint id.
|
|
@@ -63,7 +74,7 @@ export const ANTHROPIC_MESSAGES_PATH = "serving-endpoints/anthropic/v1/messages"
|
|
|
63
74
|
*/
|
|
64
75
|
export function invocationsUrl(host: string, endpoint: string): string {
|
|
65
76
|
return new URL(
|
|
66
|
-
|
|
77
|
+
`${SERVING_ENDPOINTS_PATH}/${encodeURIComponent(endpoint)}/${INVOCATIONS_SUFFIX}`,
|
|
67
78
|
host,
|
|
68
79
|
).toString();
|
|
69
80
|
}
|
|
@@ -93,6 +104,11 @@ export function anthropicMessagesUrl(host: string): string {
|
|
|
93
104
|
return new URL(ANTHROPIC_MESSAGES_PATH, host).toString();
|
|
94
105
|
}
|
|
95
106
|
|
|
107
|
+
/** Workspace Anthropic provider base URL used by AI SDK providers. */
|
|
108
|
+
export function anthropicBaseUrl(host: string): string {
|
|
109
|
+
return new URL(ANTHROPIC_BASE_PATH, host).toString().replace(/\/$/, "");
|
|
110
|
+
}
|
|
111
|
+
|
|
96
112
|
/**
|
|
97
113
|
* True when the endpoint is known to reject Chat Completions `/invocations`
|
|
98
114
|
* and require the Responses API (Codex models today). Callers should route
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Framework-neutral repairs for OpenAI Chat traffic sent through Databricks
|
|
3
|
-
* Model Serving.
|
|
4
|
-
*
|
|
5
|
-
* @module
|
|
6
|
-
*/
|
|
7
|
-
import { type ChatMessage, type ChatRole } from "@dbx-tools/shared-model";
|
|
8
|
-
/** Chat message plus provider reasoning fields emitted by Databricks models. */
|
|
9
|
-
export interface ServingChatMessage extends ChatMessage {
|
|
10
|
-
role: ChatRole | "reasoning";
|
|
11
|
-
reasoning?: unknown;
|
|
12
|
-
reasoning_content?: unknown;
|
|
13
|
-
}
|
|
14
|
-
/** Prepared fetch arguments and the sanitized request body. */
|
|
15
|
-
export interface RewrittenServingRequest {
|
|
16
|
-
input: Parameters<typeof fetch>[0];
|
|
17
|
-
init: Parameters<typeof fetch>[1];
|
|
18
|
-
body: string;
|
|
19
|
-
}
|
|
20
|
-
/** Sanitize a serialized Chat Completions request when provider quirks require it. */
|
|
21
|
-
export declare function rewriteServingBody(body: string): string;
|
|
22
|
-
/** Read and sanitize a Chat Completions request without retaining stale byte headers. */
|
|
23
|
-
export declare function rewriteServingRequest(input: Parameters<typeof fetch>[0], init?: Parameters<typeof fetch>[1]): Promise<RewrittenServingRequest>;
|
|
24
|
-
/** Normalize Chat Completions reasoning for GPT tool calls. */
|
|
25
|
-
export declare function applyToolReasoningCompatibility(body: Record<string, unknown>): boolean;
|
|
26
|
-
/** Remove provider reasoning blocks that cannot be replayed safely. */
|
|
27
|
-
export declare function stripReasoningFromServingMessages(messages: ServingChatMessage[]): boolean;
|
|
28
|
-
/** Fold a trailing assistant prefill back into its preceding tool-call turn. */
|
|
29
|
-
export declare function repairAssistantPrefill(messages: ServingChatMessage[]): boolean;
|
|
30
|
-
/** Normalize array-valued content in a non-streaming Chat Completions response. */
|
|
31
|
-
export declare function rewriteServingResponseBody(body: string): string;
|
|
32
|
-
/** Normalize array-valued content in an SSE stream without buffering the stream. */
|
|
33
|
-
export declare function rewriteServingResponseStream(body: ReadableStream<Uint8Array>): ReadableStream<Uint8Array>;
|
|
34
|
-
/** Flatten Chat Completions `choices[].message.content` arrays to strings. */
|
|
35
|
-
export declare function flattenChoiceMessageContent(payload: Record<string, unknown>): boolean;
|
|
36
|
-
/** Flatten Chat Completions `choices[].delta.content` arrays to strings. */
|
|
37
|
-
export declare function flattenChoiceDeltaContent(payload: Record<string, unknown>): boolean;
|
package/lib/src/serving-wire.js
DELETED
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Framework-neutral repairs for OpenAI Chat traffic sent through Databricks
|
|
3
|
-
* Model Serving.
|
|
4
|
-
*
|
|
5
|
-
* @module
|
|
6
|
-
*/
|
|
7
|
-
import { json, stringUtils } from "@dbx-tools/shared-core";
|
|
8
|
-
import { openaiChat } from "@dbx-tools/shared-model";
|
|
9
|
-
import { chatToolReasoningEffort } from "./policy.js";
|
|
10
|
-
const REASONING_PART_TYPES = new Set([
|
|
11
|
-
"reasoning",
|
|
12
|
-
"thinking",
|
|
13
|
-
"redacted_thinking",
|
|
14
|
-
]);
|
|
15
|
-
/** Sanitize a serialized Chat Completions request when provider quirks require it. */
|
|
16
|
-
export function rewriteServingBody(body) {
|
|
17
|
-
const parsed = json.parseRecord(body);
|
|
18
|
-
if (!parsed)
|
|
19
|
-
return body;
|
|
20
|
-
let changed = openaiChat.stripUnsupportedChatFields(parsed).length > 0 ||
|
|
21
|
-
applyToolReasoningCompatibility(parsed);
|
|
22
|
-
if (Array.isArray(parsed.messages)) {
|
|
23
|
-
const messages = parsed.messages;
|
|
24
|
-
const stripped = stripReasoningFromServingMessages(messages);
|
|
25
|
-
const repaired = repairAssistantPrefill(messages);
|
|
26
|
-
changed = changed || stripped || repaired;
|
|
27
|
-
}
|
|
28
|
-
return changed ? JSON.stringify(parsed) : body;
|
|
29
|
-
}
|
|
30
|
-
/** Read and sanitize a Chat Completions request without retaining stale byte headers. */
|
|
31
|
-
export async function rewriteServingRequest(input, init) {
|
|
32
|
-
const request = new Request(input, init);
|
|
33
|
-
const body = await request.clone().text();
|
|
34
|
-
const rewritten = rewriteServingBody(body);
|
|
35
|
-
if (rewritten === body)
|
|
36
|
-
return { input, init, body };
|
|
37
|
-
const headers = new Headers(request.headers);
|
|
38
|
-
headers.delete("content-length");
|
|
39
|
-
headers.delete("content-encoding");
|
|
40
|
-
return {
|
|
41
|
-
input: new Request(request, { body: rewritten, headers }),
|
|
42
|
-
init: undefined,
|
|
43
|
-
body: rewritten,
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
/** Normalize Chat Completions reasoning for GPT tool calls. */
|
|
47
|
-
export function applyToolReasoningCompatibility(body) {
|
|
48
|
-
if (!Array.isArray(body.tools) || body.tools.length === 0)
|
|
49
|
-
return false;
|
|
50
|
-
const model = stringUtils.trimToNull(body.model);
|
|
51
|
-
if (!model || chatToolReasoningEffort(model) !== "none")
|
|
52
|
-
return false;
|
|
53
|
-
if (body.reasoning_effort === "none")
|
|
54
|
-
return false;
|
|
55
|
-
body.reasoning_effort = "none";
|
|
56
|
-
return true;
|
|
57
|
-
}
|
|
58
|
-
/** Remove provider reasoning blocks that cannot be replayed safely. */
|
|
59
|
-
export function stripReasoningFromServingMessages(messages) {
|
|
60
|
-
let changed = false;
|
|
61
|
-
for (let index = messages.length - 1; index >= 0; index--) {
|
|
62
|
-
const message = messages[index];
|
|
63
|
-
if (!message)
|
|
64
|
-
continue;
|
|
65
|
-
if (message.role === "reasoning") {
|
|
66
|
-
messages.splice(index, 1);
|
|
67
|
-
changed = true;
|
|
68
|
-
continue;
|
|
69
|
-
}
|
|
70
|
-
if (message.reasoning !== undefined) {
|
|
71
|
-
delete message.reasoning;
|
|
72
|
-
changed = true;
|
|
73
|
-
}
|
|
74
|
-
if (message.reasoning_content !== undefined) {
|
|
75
|
-
delete message.reasoning_content;
|
|
76
|
-
changed = true;
|
|
77
|
-
}
|
|
78
|
-
const parts = openaiChat.chatContentParts(message.content);
|
|
79
|
-
if (!parts)
|
|
80
|
-
continue;
|
|
81
|
-
const filtered = parts.filter((part) => {
|
|
82
|
-
const type = part?.type;
|
|
83
|
-
if (typeof type !== "string" || !REASONING_PART_TYPES.has(type))
|
|
84
|
-
return true;
|
|
85
|
-
changed = true;
|
|
86
|
-
return false;
|
|
87
|
-
});
|
|
88
|
-
if (filtered.length !== parts.length)
|
|
89
|
-
message.content = filtered;
|
|
90
|
-
const hasToolCalls = Array.isArray(message.tool_calls) && message.tool_calls.length > 0;
|
|
91
|
-
if (message.role === "assistant" && !hasToolCalls && isEmptyServingContent(message.content)) {
|
|
92
|
-
messages.splice(index, 1);
|
|
93
|
-
changed = true;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return changed;
|
|
97
|
-
}
|
|
98
|
-
/** Fold a trailing assistant prefill back into its preceding tool-call turn. */
|
|
99
|
-
export function repairAssistantPrefill(messages) {
|
|
100
|
-
if (messages.length < 2)
|
|
101
|
-
return false;
|
|
102
|
-
const last = messages[messages.length - 1];
|
|
103
|
-
if (!last || last.role !== "assistant" || (last.tool_calls && last.tool_calls.length > 0)) {
|
|
104
|
-
return false;
|
|
105
|
-
}
|
|
106
|
-
let index = messages.length - 2;
|
|
107
|
-
while (index >= 0 && messages[index]?.role === "tool")
|
|
108
|
-
index--;
|
|
109
|
-
const opener = messages[index];
|
|
110
|
-
if (!opener ||
|
|
111
|
-
opener.role !== "assistant" ||
|
|
112
|
-
!opener.tool_calls ||
|
|
113
|
-
opener.tool_calls.length === 0) {
|
|
114
|
-
return false;
|
|
115
|
-
}
|
|
116
|
-
opener.content = [
|
|
117
|
-
stringUtils.trimToNull(textFromServingContent(opener.content)),
|
|
118
|
-
stringUtils.trimToNull(textFromServingContent(last.content)),
|
|
119
|
-
]
|
|
120
|
-
.filter((value) => value !== null)
|
|
121
|
-
.join("\n\n");
|
|
122
|
-
messages.pop();
|
|
123
|
-
return true;
|
|
124
|
-
}
|
|
125
|
-
/** Normalize array-valued content in a non-streaming Chat Completions response. */
|
|
126
|
-
export function rewriteServingResponseBody(body) {
|
|
127
|
-
const parsed = json.parseRecord(body);
|
|
128
|
-
if (!parsed)
|
|
129
|
-
return body;
|
|
130
|
-
return flattenChoiceMessageContent(parsed) ? JSON.stringify(parsed) : body;
|
|
131
|
-
}
|
|
132
|
-
/** Normalize array-valued content in an SSE stream without buffering the stream. */
|
|
133
|
-
export function rewriteServingResponseStream(body) {
|
|
134
|
-
const decoder = new TextDecoder();
|
|
135
|
-
const encoder = new TextEncoder();
|
|
136
|
-
let buffer = "";
|
|
137
|
-
return body.pipeThrough(new TransformStream({
|
|
138
|
-
transform(chunk, controller) {
|
|
139
|
-
buffer += decoder.decode(chunk, { stream: true });
|
|
140
|
-
let newline = buffer.indexOf("\n");
|
|
141
|
-
while (newline >= 0) {
|
|
142
|
-
const line = buffer.slice(0, newline + 1);
|
|
143
|
-
buffer = buffer.slice(newline + 1);
|
|
144
|
-
controller.enqueue(encoder.encode(rewriteServingResponseStreamLine(line)));
|
|
145
|
-
newline = buffer.indexOf("\n");
|
|
146
|
-
}
|
|
147
|
-
},
|
|
148
|
-
flush(controller) {
|
|
149
|
-
buffer += decoder.decode();
|
|
150
|
-
if (buffer)
|
|
151
|
-
controller.enqueue(encoder.encode(rewriteServingResponseStreamLine(buffer)));
|
|
152
|
-
},
|
|
153
|
-
}));
|
|
154
|
-
}
|
|
155
|
-
/** Flatten Chat Completions `choices[].message.content` arrays to strings. */
|
|
156
|
-
export function flattenChoiceMessageContent(payload) {
|
|
157
|
-
return flattenChoiceContent(payload, "message");
|
|
158
|
-
}
|
|
159
|
-
/** Flatten Chat Completions `choices[].delta.content` arrays to strings. */
|
|
160
|
-
export function flattenChoiceDeltaContent(payload) {
|
|
161
|
-
return flattenChoiceContent(payload, "delta");
|
|
162
|
-
}
|
|
163
|
-
function rewriteServingResponseStreamLine(line) {
|
|
164
|
-
const lineEnding = line.endsWith("\r\n") ? "\r\n" : line.endsWith("\n") ? "\n" : "";
|
|
165
|
-
const content = lineEnding ? line.slice(0, -lineEnding.length) : line;
|
|
166
|
-
const match = /^(data:\s*)(.*)$/.exec(content);
|
|
167
|
-
if (!match || match[2] === "[DONE]")
|
|
168
|
-
return line;
|
|
169
|
-
const parsed = json.parseRecord(match[2]);
|
|
170
|
-
if (!parsed || !flattenChoiceDeltaContent(parsed))
|
|
171
|
-
return line;
|
|
172
|
-
return `${match[1]}${JSON.stringify(parsed)}${lineEnding}`;
|
|
173
|
-
}
|
|
174
|
-
function flattenChoiceContent(payload, field) {
|
|
175
|
-
if (!Array.isArray(payload.choices))
|
|
176
|
-
return false;
|
|
177
|
-
let changed = false;
|
|
178
|
-
for (const choice of payload.choices) {
|
|
179
|
-
if (!choice || typeof choice !== "object")
|
|
180
|
-
continue;
|
|
181
|
-
const container = choice[field];
|
|
182
|
-
if (!container || typeof container !== "object")
|
|
183
|
-
continue;
|
|
184
|
-
const target = container;
|
|
185
|
-
const parts = openaiChat.chatContentParts(target.content);
|
|
186
|
-
if (!parts)
|
|
187
|
-
continue;
|
|
188
|
-
target.content = openaiChat.chatContentToText(parts, { types: ["text"] });
|
|
189
|
-
changed = true;
|
|
190
|
-
}
|
|
191
|
-
return changed;
|
|
192
|
-
}
|
|
193
|
-
function textFromServingContent(content) {
|
|
194
|
-
return openaiChat.chatContentToText(content, { separator: "\n\n", types: ["text"] });
|
|
195
|
-
}
|
|
196
|
-
function isEmptyServingContent(content) {
|
|
197
|
-
if (content === undefined)
|
|
198
|
-
return true;
|
|
199
|
-
if (typeof content === "string")
|
|
200
|
-
return content.trim().length === 0;
|
|
201
|
-
const parts = openaiChat.chatContentParts(content);
|
|
202
|
-
if (!parts)
|
|
203
|
-
return true;
|
|
204
|
-
return parts.every((part) => {
|
|
205
|
-
if (part?.type === "text") {
|
|
206
|
-
return typeof part.text !== "string" || part.text.trim().length === 0;
|
|
207
|
-
}
|
|
208
|
-
return false;
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmluZy13aXJlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NlcnZpbmctd2lyZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7R0FLRztBQUVILE9BQU8sRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDM0QsT0FBTyxFQUFtQyxVQUFVLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUV0RixPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFnQnRELE1BQU0sb0JBQW9CLEdBQXdCLElBQUksR0FBRyxDQUFDO0lBQ3hELFdBQVc7SUFDWCxVQUFVO0lBQ1YsbUJBQW1CO0NBQ3BCLENBQUMsQ0FBQztBQUVILHNGQUFzRjtBQUN0RixNQUFNLFVBQVUsa0JBQWtCLENBQUMsSUFBWTtJQUM3QyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3RDLElBQUksQ0FBQyxNQUFNO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFDekIsSUFBSSxPQUFPLEdBQ1QsVUFBVSxDQUFDLDBCQUEwQixDQUFDLE1BQU0sQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDO1FBQ3hELCtCQUErQixDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzFDLElBQUksS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztRQUNuQyxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsUUFBZ0MsQ0FBQztRQUN6RCxNQUFNLFFBQVEsR0FBRyxpQ0FBaUMsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUM3RCxNQUFNLFFBQVEsR0FBRyxzQkFBc0IsQ0FBQyxRQUFRLENBQUMsQ0FBQztRQUNsRCxPQUFPLEdBQUcsT0FBTyxJQUFJLFFBQVEsSUFBSSxRQUFRLENBQUM7SUFDNUMsQ0FBQztJQUNELE9BQU8sT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7QUFDakQsQ0FBQztBQUVELHlGQUF5RjtBQUN6RixNQUFNLENBQUMsS0FBSyxVQUFVLHFCQUFxQixDQUN6QyxLQUFrQyxFQUNsQyxJQUFrQztJQUVsQyxNQUFNLE9BQU8sR0FBRyxJQUFJLE9BQU8sQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDekMsTUFBTSxJQUFJLEdBQUcsTUFBTSxPQUFPLENBQUMsS0FBSyxFQUFFLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDMUMsTUFBTSxTQUFTLEdBQUcsa0JBQWtCLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDM0MsSUFBSSxTQUFTLEtBQUssSUFBSTtRQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxDQUFDO0lBQ3JELE1BQU0sT0FBTyxHQUFHLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUM3QyxPQUFPLENBQUMsTUFBTSxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDakMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0lBQ25DLE9BQU87UUFDTCxLQUFLLEVBQUUsSUFBSSxPQUFPLENBQUMsT0FBTyxFQUFFLEVBQUUsSUFBSSxFQUFFLFNBQVMsRUFBRSxPQUFPLEVBQUUsQ0FBQztRQUN6RCxJQUFJLEVBQUUsU0FBUztRQUNmLElBQUksRUFBRSxTQUFTO0tBQ2hCLENBQUM7QUFDSixDQUFDO0FBRUQsK0RBQStEO0FBQy9ELE1BQU0sVUFBVSwrQkFBK0IsQ0FBQyxJQUE2QjtJQUMzRSxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEtBQUssQ0FBQztRQUFFLE9BQU8sS0FBSyxDQUFDO0lBQ3hFLE1BQU0sS0FBSyxHQUFHLFdBQVcsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ2pELElBQUksQ0FBQyxLQUFLLElBQUksdUJBQXVCLENBQUMsS0FBSyxDQUFDLEtBQUssTUFBTTtRQUFFLE9BQU8sS0FBSyxDQUFDO0lBQ3RFLElBQUksSUFBSSxDQUFDLGdCQUFnQixLQUFLLE1BQU07UUFBRSxPQUFPLEtBQUssQ0FBQztJQUNuRCxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsTUFBTSxDQUFDO0lBQy9CLE9BQU8sSUFBSSxDQUFDO0FBQ2QsQ0FBQztBQUVELHVFQUF1RTtBQUN2RSxNQUFNLFVBQVUsaUNBQWlDLENBQUMsUUFBOEI7SUFDOUUsSUFBSSxPQUFPLEdBQUcsS0FBSyxDQUFDO0lBQ3BCLEtBQUssSUFBSSxLQUFLLEdBQUcsUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsS0FBSyxJQUFJLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUFDO1FBQzFELE1BQU0sT0FBTyxHQUFHLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNoQyxJQUFJLENBQUMsT0FBTztZQUFFLFNBQVM7UUFDdkIsSUFBSSxPQUFPLENBQUMsSUFBSSxLQUFLLFdBQVcsRUFBRSxDQUFDO1lBQ2pDLFFBQVEsQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO1lBQzFCLE9BQU8sR0FBRyxJQUFJLENBQUM7WUFDZixTQUFTO1FBQ1gsQ0FBQztRQUNELElBQUksT0FBTyxDQUFDLFNBQVMsS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUNwQyxPQUFPLE9BQU8sQ0FBQyxTQUFTLENBQUM7WUFDekIsT0FBTyxHQUFHLElBQUksQ0FBQztRQUNqQixDQUFDO1FBQ0QsSUFBSSxPQUFPLENBQUMsaUJBQWlCLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDNUMsT0FBTyxPQUFPLENBQUMsaUJBQWlCLENBQUM7WUFDakMsT0FBTyxHQUFHLElBQUksQ0FBQztRQUNqQixDQUFDO1FBQ0QsTUFBTSxLQUFLLEdBQUcsVUFBVSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMzRCxJQUFJLENBQUMsS0FBSztZQUFFLFNBQVM7UUFDckIsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO1lBQ3JDLE1BQU0sSUFBSSxHQUFHLElBQUksRUFBRSxJQUFJLENBQUM7WUFDeEIsSUFBSSxPQUFPLElBQUksS0FBSyxRQUFRLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDO2dCQUFFLE9BQU8sSUFBSSxDQUFDO1lBQzdFLE9BQU8sR0FBRyxJQUFJLENBQUM7WUFDZixPQUFPLEtBQUssQ0FBQztRQUNmLENBQUMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxRQUFRLENBQUMsTUFBTSxLQUFLLEtBQUssQ0FBQyxNQUFNO1lBQUUsT0FBTyxDQUFDLE9BQU8sR0FBRyxRQUFRLENBQUM7UUFDakUsTUFBTSxZQUFZLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQ3hGLElBQUksT0FBTyxDQUFDLElBQUksS0FBSyxXQUFXLElBQUksQ0FBQyxZQUFZLElBQUkscUJBQXFCLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUM7WUFDNUYsUUFBUSxDQUFDLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUM7WUFDMUIsT0FBTyxHQUFHLElBQUksQ0FBQztRQUNqQixDQUFDO0lBQ0gsQ0FBQztJQUNELE9BQU8sT0FBTyxDQUFDO0FBQ2pCLENBQUM7QUFFRCxnRkFBZ0Y7QUFDaEYsTUFBTSxVQUFVLHNCQUFzQixDQUFDLFFBQThCO0lBQ25FLElBQUksUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDO1FBQUUsT0FBTyxLQUFLLENBQUM7SUFDdEMsTUFBTSxJQUFJLEdBQUcsUUFBUSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDM0MsSUFBSSxDQUFDLElBQUksSUFBSSxJQUFJLENBQUMsSUFBSSxLQUFLLFdBQVcsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLElBQUksSUFBSSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUMxRixPQUFPLEtBQUssQ0FBQztJQUNmLENBQUM7SUFDRCxJQUFJLEtBQUssR0FBRyxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztJQUNoQyxPQUFPLEtBQUssSUFBSSxDQUFDLElBQUksUUFBUSxDQUFDLEtBQUssQ0FBQyxFQUFFLElBQUksS0FBSyxNQUFNO1FBQUUsS0FBSyxFQUFFLENBQUM7SUFDL0QsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQy9CLElBQ0UsQ0FBQyxNQUFNO1FBQ1AsTUFBTSxDQUFDLElBQUksS0FBSyxXQUFXO1FBQzNCLENBQUMsTUFBTSxDQUFDLFVBQVU7UUFDbEIsTUFBTSxDQUFDLFVBQVUsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUM5QixDQUFDO1FBQ0QsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBQ0QsTUFBTSxDQUFDLE9BQU8sR0FBRztRQUNmLFdBQVcsQ0FBQyxVQUFVLENBQUMsc0JBQXNCLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzlELFdBQVcsQ0FBQyxVQUFVLENBQUMsc0JBQXNCLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDO0tBQzdEO1NBQ0UsTUFBTSxDQUFDLENBQUMsS0FBSyxFQUFtQixFQUFFLENBQUMsS0FBSyxLQUFLLElBQUksQ0FBQztTQUNsRCxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDaEIsUUFBUSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQ2YsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDO0FBRUQsbUZBQW1GO0FBQ25GLE1BQU0sVUFBVSwwQkFBMEIsQ0FBQyxJQUFZO0lBQ3JELE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDdEMsSUFBSSxDQUFDLE1BQU07UUFBRSxPQUFPLElBQUksQ0FBQztJQUN6QixPQUFPLDJCQUEyQixDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7QUFDN0UsQ0FBQztBQUVELG9GQUFvRjtBQUNwRixNQUFNLFVBQVUsNEJBQTRCLENBQzFDLElBQWdDO0lBRWhDLE1BQU0sT0FBTyxHQUFHLElBQUksV0FBVyxFQUFFLENBQUM7SUFDbEMsTUFBTSxPQUFPLEdBQUcsSUFBSSxXQUFXLEVBQUUsQ0FBQztJQUNsQyxJQUFJLE1BQU0sR0FBRyxFQUFFLENBQUM7SUFDaEIsT0FBTyxJQUFJLENBQUMsV0FBVyxDQUNyQixJQUFJLGVBQWUsQ0FBeUI7UUFDMUMsU0FBUyxDQUFDLEtBQUssRUFBRSxVQUFVO1lBQ3pCLE1BQU0sSUFBSSxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1lBQ2xELElBQUksT0FBTyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDbkMsT0FBTyxPQUFPLElBQUksQ0FBQyxFQUFFLENBQUM7Z0JBQ3BCLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLE9BQU8sR0FBRyxDQUFDLENBQUMsQ0FBQztnQkFDMUMsTUFBTSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQyxDQUFDO2dCQUNuQyxVQUFVLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsZ0NBQWdDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUMzRSxPQUFPLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNqQyxDQUFDO1FBQ0gsQ0FBQztRQUNELEtBQUssQ0FBQyxVQUFVO1lBQ2QsTUFBTSxJQUFJLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUMzQixJQUFJLE1BQU07Z0JBQUUsVUFBVSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLGdDQUFnQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMzRixDQUFDO0tBQ0YsQ0FBQyxDQUNILENBQUM7QUFDSixDQUFDO0FBRUQsOEVBQThFO0FBQzlFLE1BQU0sVUFBVSwyQkFBMkIsQ0FBQyxPQUFnQztJQUMxRSxPQUFPLG9CQUFvQixDQUFDLE9BQU8sRUFBRSxTQUFTLENBQUMsQ0FBQztBQUNsRCxDQUFDO0FBRUQsNEVBQTRFO0FBQzVFLE1BQU0sVUFBVSx5QkFBeUIsQ0FBQyxPQUFnQztJQUN4RSxPQUFPLG9CQUFvQixDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQztBQUNoRCxDQUFDO0FBRUQsU0FBUyxnQ0FBZ0MsQ0FBQyxJQUFZO0lBQ3BELE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDcEYsTUFBTSxPQUFPLEdBQUcsVUFBVSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0lBQ3RFLE1BQU0sS0FBSyxHQUFHLGtCQUFrQixDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUMvQyxJQUFJLENBQUMsS0FBSyxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUMsS0FBSyxRQUFRO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFDakQsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMxQyxJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMseUJBQXlCLENBQUMsTUFBTSxDQUFDO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFDL0QsT0FBTyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxHQUFHLFVBQVUsRUFBRSxDQUFDO0FBQzdELENBQUM7QUFFRCxTQUFTLG9CQUFvQixDQUMzQixPQUFnQyxFQUNoQyxLQUEwQjtJQUUxQixJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDO1FBQUUsT0FBTyxLQUFLLENBQUM7SUFDbEQsSUFBSSxPQUFPLEdBQUcsS0FBSyxDQUFDO0lBQ3BCLEtBQUssTUFBTSxNQUFNLElBQUksT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3JDLElBQUksQ0FBQyxNQUFNLElBQUksT0FBTyxNQUFNLEtBQUssUUFBUTtZQUFFLFNBQVM7UUFDcEQsTUFBTSxTQUFTLEdBQUksTUFBa0MsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUM3RCxJQUFJLENBQUMsU0FBUyxJQUFJLE9BQU8sU0FBUyxLQUFLLFFBQVE7WUFBRSxTQUFTO1FBQzFELE1BQU0sTUFBTSxHQUFHLFNBQWtDLENBQUM7UUFDbEQsTUFBTSxLQUFLLEdBQUcsVUFBVSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMxRCxJQUFJLENBQUMsS0FBSztZQUFFLFNBQVM7UUFDckIsTUFBTSxDQUFDLE9BQU8sR0FBRyxVQUFVLENBQUMsaUJBQWlCLENBQUMsS0FBSyxFQUFFLEVBQUUsS0FBSyxFQUFFLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQzFFLE9BQU8sR0FBRyxJQUFJLENBQUM7SUFDakIsQ0FBQztJQUNELE9BQU8sT0FBTyxDQUFDO0FBQ2pCLENBQUM7QUFFRCxTQUFTLHNCQUFzQixDQUFDLE9BQXNDO0lBQ3BFLE9BQU8sVUFBVSxDQUFDLGlCQUFpQixDQUFDLE9BQU8sRUFBRSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0FBQ3ZGLENBQUM7QUFFRCxTQUFTLHFCQUFxQixDQUFDLE9BQXNDO0lBQ25FLElBQUksT0FBTyxLQUFLLFNBQVM7UUFBRSxPQUFPLElBQUksQ0FBQztJQUN2QyxJQUFJLE9BQU8sT0FBTyxLQUFLLFFBQVE7UUFBRSxPQUFPLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxNQUFNLEtBQUssQ0FBQyxDQUFDO0lBQ3BFLE1BQU0sS0FBSyxHQUFHLFVBQVUsQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUNuRCxJQUFJLENBQUMsS0FBSztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ3hCLE9BQU8sS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFO1FBQzFCLElBQUksSUFBSSxFQUFFLElBQUksS0FBSyxNQUFNLEVBQUUsQ0FBQztZQUMxQixPQUFPLE9BQU8sSUFBSSxDQUFDLElBQUksS0FBSyxRQUFRLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQyxNQUFNLEtBQUssQ0FBQyxDQUFDO1FBQ3hFLENBQUM7UUFDRCxPQUFPLEtBQUssQ0FBQztJQUNmLENBQUMsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogRnJhbWV3b3JrLW5ldXRyYWwgcmVwYWlycyBmb3IgT3BlbkFJIENoYXQgdHJhZmZpYyBzZW50IHRocm91Z2ggRGF0YWJyaWNrc1xuICogTW9kZWwgU2VydmluZy5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHsganNvbiwgc3RyaW5nVXRpbHMgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuaW1wb3J0IHsgdHlwZSBDaGF0TWVzc2FnZSwgdHlwZSBDaGF0Um9sZSwgb3BlbmFpQ2hhdCB9IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1tb2RlbFwiO1xuXG5pbXBvcnQgeyBjaGF0VG9vbFJlYXNvbmluZ0VmZm9ydCB9IGZyb20gXCIuL3BvbGljeS50c1wiO1xuXG4vKiogQ2hhdCBtZXNzYWdlIHBsdXMgcHJvdmlkZXIgcmVhc29uaW5nIGZpZWxkcyBlbWl0dGVkIGJ5IERhdGFicmlja3MgbW9kZWxzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBTZXJ2aW5nQ2hhdE1lc3NhZ2UgZXh0ZW5kcyBDaGF0TWVzc2FnZSB7XG4gIHJvbGU6IENoYXRSb2xlIHwgXCJyZWFzb25pbmdcIjtcbiAgcmVhc29uaW5nPzogdW5rbm93bjtcbiAgcmVhc29uaW5nX2NvbnRlbnQ/OiB1bmtub3duO1xufVxuXG4vKiogUHJlcGFyZWQgZmV0Y2ggYXJndW1lbnRzIGFuZCB0aGUgc2FuaXRpemVkIHJlcXVlc3QgYm9keS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmV3cml0dGVuU2VydmluZ1JlcXVlc3Qge1xuICBpbnB1dDogUGFyYW1ldGVyczx0eXBlb2YgZmV0Y2g+WzBdO1xuICBpbml0OiBQYXJhbWV0ZXJzPHR5cGVvZiBmZXRjaD5bMV07XG4gIGJvZHk6IHN0cmluZztcbn1cblxuY29uc3QgUkVBU09OSU5HX1BBUlRfVFlQRVM6IFJlYWRvbmx5U2V0PHN0cmluZz4gPSBuZXcgU2V0KFtcbiAgXCJyZWFzb25pbmdcIixcbiAgXCJ0aGlua2luZ1wiLFxuICBcInJlZGFjdGVkX3RoaW5raW5nXCIsXG5dKTtcblxuLyoqIFNhbml0aXplIGEgc2VyaWFsaXplZCBDaGF0IENvbXBsZXRpb25zIHJlcXVlc3Qgd2hlbiBwcm92aWRlciBxdWlya3MgcmVxdWlyZSBpdC4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXdyaXRlU2VydmluZ0JvZHkoYm9keTogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgcGFyc2VkID0ganNvbi5wYXJzZVJlY29yZChib2R5KTtcbiAgaWYgKCFwYXJzZWQpIHJldHVybiBib2R5O1xuICBsZXQgY2hhbmdlZCA9XG4gICAgb3BlbmFpQ2hhdC5zdHJpcFVuc3VwcG9ydGVkQ2hhdEZpZWxkcyhwYXJzZWQpLmxlbmd0aCA+IDAgfHxcbiAgICBhcHBseVRvb2xSZWFzb25pbmdDb21wYXRpYmlsaXR5KHBhcnNlZCk7XG4gIGlmIChBcnJheS5pc0FycmF5KHBhcnNlZC5tZXNzYWdlcykpIHtcbiAgICBjb25zdCBtZXNzYWdlcyA9IHBhcnNlZC5tZXNzYWdlcyBhcyBTZXJ2aW5nQ2hhdE1lc3NhZ2VbXTtcbiAgICBjb25zdCBzdHJpcHBlZCA9IHN0cmlwUmVhc29uaW5nRnJvbVNlcnZpbmdNZXNzYWdlcyhtZXNzYWdlcyk7XG4gICAgY29uc3QgcmVwYWlyZWQgPSByZXBhaXJBc3Npc3RhbnRQcmVmaWxsKG1lc3NhZ2VzKTtcbiAgICBjaGFuZ2VkID0gY2hhbmdlZCB8fCBzdHJpcHBlZCB8fCByZXBhaXJlZDtcbiAgfVxuICByZXR1cm4gY2hhbmdlZCA/IEpTT04uc3RyaW5naWZ5KHBhcnNlZCkgOiBib2R5O1xufVxuXG4vKiogUmVhZCBhbmQgc2FuaXRpemUgYSBDaGF0IENvbXBsZXRpb25zIHJlcXVlc3Qgd2l0aG91dCByZXRhaW5pbmcgc3RhbGUgYnl0ZSBoZWFkZXJzLiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJld3JpdGVTZXJ2aW5nUmVxdWVzdChcbiAgaW5wdXQ6IFBhcmFtZXRlcnM8dHlwZW9mIGZldGNoPlswXSxcbiAgaW5pdD86IFBhcmFtZXRlcnM8dHlwZW9mIGZldGNoPlsxXSxcbik6IFByb21pc2U8UmV3cml0dGVuU2VydmluZ1JlcXVlc3Q+IHtcbiAgY29uc3QgcmVxdWVzdCA9IG5ldyBSZXF1ZXN0KGlucHV0LCBpbml0KTtcbiAgY29uc3QgYm9keSA9IGF3YWl0IHJlcXVlc3QuY2xvbmUoKS50ZXh0KCk7XG4gIGNvbnN0IHJld3JpdHRlbiA9IHJld3JpdGVTZXJ2aW5nQm9keShib2R5KTtcbiAgaWYgKHJld3JpdHRlbiA9PT0gYm9keSkgcmV0dXJuIHsgaW5wdXQsIGluaXQsIGJvZHkgfTtcbiAgY29uc3QgaGVhZGVycyA9IG5ldyBIZWFkZXJzKHJlcXVlc3QuaGVhZGVycyk7XG4gIGhlYWRlcnMuZGVsZXRlKFwiY29udGVudC1sZW5ndGhcIik7XG4gIGhlYWRlcnMuZGVsZXRlKFwiY29udGVudC1lbmNvZGluZ1wiKTtcbiAgcmV0dXJuIHtcbiAgICBpbnB1dDogbmV3IFJlcXVlc3QocmVxdWVzdCwgeyBib2R5OiByZXdyaXR0ZW4sIGhlYWRlcnMgfSksXG4gICAgaW5pdDogdW5kZWZpbmVkLFxuICAgIGJvZHk6IHJld3JpdHRlbixcbiAgfTtcbn1cblxuLyoqIE5vcm1hbGl6ZSBDaGF0IENvbXBsZXRpb25zIHJlYXNvbmluZyBmb3IgR1BUIHRvb2wgY2FsbHMuICovXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlUb29sUmVhc29uaW5nQ29tcGF0aWJpbGl0eShib2R5OiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IGJvb2xlYW4ge1xuICBpZiAoIUFycmF5LmlzQXJyYXkoYm9keS50b29scykgfHwgYm9keS50b29scy5sZW5ndGggPT09IDApIHJldHVybiBmYWxzZTtcbiAgY29uc3QgbW9kZWwgPSBzdHJpbmdVdGlscy50cmltVG9OdWxsKGJvZHkubW9kZWwpO1xuICBpZiAoIW1vZGVsIHx8IGNoYXRUb29sUmVhc29uaW5nRWZmb3J0KG1vZGVsKSAhPT0gXCJub25lXCIpIHJldHVybiBmYWxzZTtcbiAgaWYgKGJvZHkucmVhc29uaW5nX2VmZm9ydCA9PT0gXCJub25lXCIpIHJldHVybiBmYWxzZTtcbiAgYm9keS5yZWFzb25pbmdfZWZmb3J0ID0gXCJub25lXCI7XG4gIHJldHVybiB0cnVlO1xufVxuXG4vKiogUmVtb3ZlIHByb3ZpZGVyIHJlYXNvbmluZyBibG9ja3MgdGhhdCBjYW5ub3QgYmUgcmVwbGF5ZWQgc2FmZWx5LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHN0cmlwUmVhc29uaW5nRnJvbVNlcnZpbmdNZXNzYWdlcyhtZXNzYWdlczogU2VydmluZ0NoYXRNZXNzYWdlW10pOiBib29sZWFuIHtcbiAgbGV0IGNoYW5nZWQgPSBmYWxzZTtcbiAgZm9yIChsZXQgaW5kZXggPSBtZXNzYWdlcy5sZW5ndGggLSAxOyBpbmRleCA+PSAwOyBpbmRleC0tKSB7XG4gICAgY29uc3QgbWVzc2FnZSA9IG1lc3NhZ2VzW2luZGV4XTtcbiAgICBpZiAoIW1lc3NhZ2UpIGNvbnRpbnVlO1xuICAgIGlmIChtZXNzYWdlLnJvbGUgPT09IFwicmVhc29uaW5nXCIpIHtcbiAgICAgIG1lc3NhZ2VzLnNwbGljZShpbmRleCwgMSk7XG4gICAgICBjaGFuZ2VkID0gdHJ1ZTtcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBpZiAobWVzc2FnZS5yZWFzb25pbmcgIT09IHVuZGVmaW5lZCkge1xuICAgICAgZGVsZXRlIG1lc3NhZ2UucmVhc29uaW5nO1xuICAgICAgY2hhbmdlZCA9IHRydWU7XG4gICAgfVxuICAgIGlmIChtZXNzYWdlLnJlYXNvbmluZ19jb250ZW50ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGRlbGV0ZSBtZXNzYWdlLnJlYXNvbmluZ19jb250ZW50O1xuICAgICAgY2hhbmdlZCA9IHRydWU7XG4gICAgfVxuICAgIGNvbnN0IHBhcnRzID0gb3BlbmFpQ2hhdC5jaGF0Q29udGVudFBhcnRzKG1lc3NhZ2UuY29udGVudCk7XG4gICAgaWYgKCFwYXJ0cykgY29udGludWU7XG4gICAgY29uc3QgZmlsdGVyZWQgPSBwYXJ0cy5maWx0ZXIoKHBhcnQpID0+IHtcbiAgICAgIGNvbnN0IHR5cGUgPSBwYXJ0Py50eXBlO1xuICAgICAgaWYgKHR5cGVvZiB0eXBlICE9PSBcInN0cmluZ1wiIHx8ICFSRUFTT05JTkdfUEFSVF9UWVBFUy5oYXModHlwZSkpIHJldHVybiB0cnVlO1xuICAgICAgY2hhbmdlZCA9IHRydWU7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfSk7XG4gICAgaWYgKGZpbHRlcmVkLmxlbmd0aCAhPT0gcGFydHMubGVuZ3RoKSBtZXNzYWdlLmNvbnRlbnQgPSBmaWx0ZXJlZDtcbiAgICBjb25zdCBoYXNUb29sQ2FsbHMgPSBBcnJheS5pc0FycmF5KG1lc3NhZ2UudG9vbF9jYWxscykgJiYgbWVzc2FnZS50b29sX2NhbGxzLmxlbmd0aCA+IDA7XG4gICAgaWYgKG1lc3NhZ2Uucm9sZSA9PT0gXCJhc3Npc3RhbnRcIiAmJiAhaGFzVG9vbENhbGxzICYmIGlzRW1wdHlTZXJ2aW5nQ29udGVudChtZXNzYWdlLmNvbnRlbnQpKSB7XG4gICAgICBtZXNzYWdlcy5zcGxpY2UoaW5kZXgsIDEpO1xuICAgICAgY2hhbmdlZCA9IHRydWU7XG4gICAgfVxuICB9XG4gIHJldHVybiBjaGFuZ2VkO1xufVxuXG4vKiogRm9sZCBhIHRyYWlsaW5nIGFzc2lzdGFudCBwcmVmaWxsIGJhY2sgaW50byBpdHMgcHJlY2VkaW5nIHRvb2wtY2FsbCB0dXJuLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlcGFpckFzc2lzdGFudFByZWZpbGwobWVzc2FnZXM6IFNlcnZpbmdDaGF0TWVzc2FnZVtdKTogYm9vbGVhbiB7XG4gIGlmIChtZXNzYWdlcy5sZW5ndGggPCAyKSByZXR1cm4gZmFsc2U7XG4gIGNvbnN0IGxhc3QgPSBtZXNzYWdlc1ttZXNzYWdlcy5sZW5ndGggLSAxXTtcbiAgaWYgKCFsYXN0IHx8IGxhc3Qucm9sZSAhPT0gXCJhc3Npc3RhbnRcIiB8fCAobGFzdC50b29sX2NhbGxzICYmIGxhc3QudG9vbF9jYWxscy5sZW5ndGggPiAwKSkge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuICBsZXQgaW5kZXggPSBtZXNzYWdlcy5sZW5ndGggLSAyO1xuICB3aGlsZSAoaW5kZXggPj0gMCAmJiBtZXNzYWdlc1tpbmRleF0/LnJvbGUgPT09IFwidG9vbFwiKSBpbmRleC0tO1xuICBjb25zdCBvcGVuZXIgPSBtZXNzYWdlc1tpbmRleF07XG4gIGlmIChcbiAgICAhb3BlbmVyIHx8XG4gICAgb3BlbmVyLnJvbGUgIT09IFwiYXNzaXN0YW50XCIgfHxcbiAgICAhb3BlbmVyLnRvb2xfY2FsbHMgfHxcbiAgICBvcGVuZXIudG9vbF9jYWxscy5sZW5ndGggPT09IDBcbiAgKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIG9wZW5lci5jb250ZW50ID0gW1xuICAgIHN0cmluZ1V0aWxzLnRyaW1Ub051bGwodGV4dEZyb21TZXJ2aW5nQ29udGVudChvcGVuZXIuY29udGVudCkpLFxuICAgIHN0cmluZ1V0aWxzLnRyaW1Ub051bGwodGV4dEZyb21TZXJ2aW5nQ29udGVudChsYXN0LmNvbnRlbnQpKSxcbiAgXVxuICAgIC5maWx0ZXIoKHZhbHVlKTogdmFsdWUgaXMgc3RyaW5nID0+IHZhbHVlICE9PSBudWxsKVxuICAgIC5qb2luKFwiXFxuXFxuXCIpO1xuICBtZXNzYWdlcy5wb3AoKTtcbiAgcmV0dXJuIHRydWU7XG59XG5cbi8qKiBOb3JtYWxpemUgYXJyYXktdmFsdWVkIGNvbnRlbnQgaW4gYSBub24tc3RyZWFtaW5nIENoYXQgQ29tcGxldGlvbnMgcmVzcG9uc2UuICovXG5leHBvcnQgZnVuY3Rpb24gcmV3cml0ZVNlcnZpbmdSZXNwb25zZUJvZHkoYm9keTogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgcGFyc2VkID0ganNvbi5wYXJzZVJlY29yZChib2R5KTtcbiAgaWYgKCFwYXJzZWQpIHJldHVybiBib2R5O1xuICByZXR1cm4gZmxhdHRlbkNob2ljZU1lc3NhZ2VDb250ZW50KHBhcnNlZCkgPyBKU09OLnN0cmluZ2lmeShwYXJzZWQpIDogYm9keTtcbn1cblxuLyoqIE5vcm1hbGl6ZSBhcnJheS12YWx1ZWQgY29udGVudCBpbiBhbiBTU0Ugc3RyZWFtIHdpdGhvdXQgYnVmZmVyaW5nIHRoZSBzdHJlYW0uICovXG5leHBvcnQgZnVuY3Rpb24gcmV3cml0ZVNlcnZpbmdSZXNwb25zZVN0cmVhbShcbiAgYm9keTogUmVhZGFibGVTdHJlYW08VWludDhBcnJheT4sXG4pOiBSZWFkYWJsZVN0cmVhbTxVaW50OEFycmF5PiB7XG4gIGNvbnN0IGRlY29kZXIgPSBuZXcgVGV4dERlY29kZXIoKTtcbiAgY29uc3QgZW5jb2RlciA9IG5ldyBUZXh0RW5jb2RlcigpO1xuICBsZXQgYnVmZmVyID0gXCJcIjtcbiAgcmV0dXJuIGJvZHkucGlwZVRocm91Z2goXG4gICAgbmV3IFRyYW5zZm9ybVN0cmVhbTxVaW50OEFycmF5LCBVaW50OEFycmF5Pih7XG4gICAgICB0cmFuc2Zvcm0oY2h1bmssIGNvbnRyb2xsZXIpIHtcbiAgICAgICAgYnVmZmVyICs9IGRlY29kZXIuZGVjb2RlKGNodW5rLCB7IHN0cmVhbTogdHJ1ZSB9KTtcbiAgICAgICAgbGV0IG5ld2xpbmUgPSBidWZmZXIuaW5kZXhPZihcIlxcblwiKTtcbiAgICAgICAgd2hpbGUgKG5ld2xpbmUgPj0gMCkge1xuICAgICAgICAgIGNvbnN0IGxpbmUgPSBidWZmZXIuc2xpY2UoMCwgbmV3bGluZSArIDEpO1xuICAgICAgICAgIGJ1ZmZlciA9IGJ1ZmZlci5zbGljZShuZXdsaW5lICsgMSk7XG4gICAgICAgICAgY29udHJvbGxlci5lbnF1ZXVlKGVuY29kZXIuZW5jb2RlKHJld3JpdGVTZXJ2aW5nUmVzcG9uc2VTdHJlYW1MaW5lKGxpbmUpKSk7XG4gICAgICAgICAgbmV3bGluZSA9IGJ1ZmZlci5pbmRleE9mKFwiXFxuXCIpO1xuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgZmx1c2goY29udHJvbGxlcikge1xuICAgICAgICBidWZmZXIgKz0gZGVjb2Rlci5kZWNvZGUoKTtcbiAgICAgICAgaWYgKGJ1ZmZlcikgY29udHJvbGxlci5lbnF1ZXVlKGVuY29kZXIuZW5jb2RlKHJld3JpdGVTZXJ2aW5nUmVzcG9uc2VTdHJlYW1MaW5lKGJ1ZmZlcikpKTtcbiAgICAgIH0sXG4gICAgfSksXG4gICk7XG59XG5cbi8qKiBGbGF0dGVuIENoYXQgQ29tcGxldGlvbnMgYGNob2ljZXNbXS5tZXNzYWdlLmNvbnRlbnRgIGFycmF5cyB0byBzdHJpbmdzLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZsYXR0ZW5DaG9pY2VNZXNzYWdlQ29udGVudChwYXlsb2FkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IGJvb2xlYW4ge1xuICByZXR1cm4gZmxhdHRlbkNob2ljZUNvbnRlbnQocGF5bG9hZCwgXCJtZXNzYWdlXCIpO1xufVxuXG4vKiogRmxhdHRlbiBDaGF0IENvbXBsZXRpb25zIGBjaG9pY2VzW10uZGVsdGEuY29udGVudGAgYXJyYXlzIHRvIHN0cmluZ3MuICovXG5leHBvcnQgZnVuY3Rpb24gZmxhdHRlbkNob2ljZURlbHRhQ29udGVudChwYXlsb2FkOiBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPik6IGJvb2xlYW4ge1xuICByZXR1cm4gZmxhdHRlbkNob2ljZUNvbnRlbnQocGF5bG9hZCwgXCJkZWx0YVwiKTtcbn1cblxuZnVuY3Rpb24gcmV3cml0ZVNlcnZpbmdSZXNwb25zZVN0cmVhbUxpbmUobGluZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgbGluZUVuZGluZyA9IGxpbmUuZW5kc1dpdGgoXCJcXHJcXG5cIikgPyBcIlxcclxcblwiIDogbGluZS5lbmRzV2l0aChcIlxcblwiKSA/IFwiXFxuXCIgOiBcIlwiO1xuICBjb25zdCBjb250ZW50ID0gbGluZUVuZGluZyA/IGxpbmUuc2xpY2UoMCwgLWxpbmVFbmRpbmcubGVuZ3RoKSA6IGxpbmU7XG4gIGNvbnN0IG1hdGNoID0gL14oZGF0YTpcXHMqKSguKikkLy5leGVjKGNvbnRlbnQpO1xuICBpZiAoIW1hdGNoIHx8IG1hdGNoWzJdID09PSBcIltET05FXVwiKSByZXR1cm4gbGluZTtcbiAgY29uc3QgcGFyc2VkID0ganNvbi5wYXJzZVJlY29yZChtYXRjaFsyXSk7XG4gIGlmICghcGFyc2VkIHx8ICFmbGF0dGVuQ2hvaWNlRGVsdGFDb250ZW50KHBhcnNlZCkpIHJldHVybiBsaW5lO1xuICByZXR1cm4gYCR7bWF0Y2hbMV19JHtKU09OLnN0cmluZ2lmeShwYXJzZWQpfSR7bGluZUVuZGluZ31gO1xufVxuXG5mdW5jdGlvbiBmbGF0dGVuQ2hvaWNlQ29udGVudChcbiAgcGF5bG9hZDogUmVjb3JkPHN0cmluZywgdW5rbm93bj4sXG4gIGZpZWxkOiBcIm1lc3NhZ2VcIiB8IFwiZGVsdGFcIixcbik6IGJvb2xlYW4ge1xuICBpZiAoIUFycmF5LmlzQXJyYXkocGF5bG9hZC5jaG9pY2VzKSkgcmV0dXJuIGZhbHNlO1xuICBsZXQgY2hhbmdlZCA9IGZhbHNlO1xuICBmb3IgKGNvbnN0IGNob2ljZSBvZiBwYXlsb2FkLmNob2ljZXMpIHtcbiAgICBpZiAoIWNob2ljZSB8fCB0eXBlb2YgY2hvaWNlICE9PSBcIm9iamVjdFwiKSBjb250aW51ZTtcbiAgICBjb25zdCBjb250YWluZXIgPSAoY2hvaWNlIGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KVtmaWVsZF07XG4gICAgaWYgKCFjb250YWluZXIgfHwgdHlwZW9mIGNvbnRhaW5lciAhPT0gXCJvYmplY3RcIikgY29udGludWU7XG4gICAgY29uc3QgdGFyZ2V0ID0gY29udGFpbmVyIGFzIHsgY29udGVudD86IHVua25vd24gfTtcbiAgICBjb25zdCBwYXJ0cyA9IG9wZW5haUNoYXQuY2hhdENvbnRlbnRQYXJ0cyh0YXJnZXQuY29udGVudCk7XG4gICAgaWYgKCFwYXJ0cykgY29udGludWU7XG4gICAgdGFyZ2V0LmNvbnRlbnQgPSBvcGVuYWlDaGF0LmNoYXRDb250ZW50VG9UZXh0KHBhcnRzLCB7IHR5cGVzOiBbXCJ0ZXh0XCJdIH0pO1xuICAgIGNoYW5nZWQgPSB0cnVlO1xuICB9XG4gIHJldHVybiBjaGFuZ2VkO1xufVxuXG5mdW5jdGlvbiB0ZXh0RnJvbVNlcnZpbmdDb250ZW50KGNvbnRlbnQ6IFNlcnZpbmdDaGF0TWVzc2FnZVtcImNvbnRlbnRcIl0pOiBzdHJpbmcge1xuICByZXR1cm4gb3BlbmFpQ2hhdC5jaGF0Q29udGVudFRvVGV4dChjb250ZW50LCB7IHNlcGFyYXRvcjogXCJcXG5cXG5cIiwgdHlwZXM6IFtcInRleHRcIl0gfSk7XG59XG5cbmZ1bmN0aW9uIGlzRW1wdHlTZXJ2aW5nQ29udGVudChjb250ZW50OiBTZXJ2aW5nQ2hhdE1lc3NhZ2VbXCJjb250ZW50XCJdKTogYm9vbGVhbiB7XG4gIGlmIChjb250ZW50ID09PSB1bmRlZmluZWQpIHJldHVybiB0cnVlO1xuICBpZiAodHlwZW9mIGNvbnRlbnQgPT09IFwic3RyaW5nXCIpIHJldHVybiBjb250ZW50LnRyaW0oKS5sZW5ndGggPT09IDA7XG4gIGNvbnN0IHBhcnRzID0gb3BlbmFpQ2hhdC5jaGF0Q29udGVudFBhcnRzKGNvbnRlbnQpO1xuICBpZiAoIXBhcnRzKSByZXR1cm4gdHJ1ZTtcbiAgcmV0dXJuIHBhcnRzLmV2ZXJ5KChwYXJ0KSA9PiB7XG4gICAgaWYgKHBhcnQ/LnR5cGUgPT09IFwidGV4dFwiKSB7XG4gICAgICByZXR1cm4gdHlwZW9mIHBhcnQudGV4dCAhPT0gXCJzdHJpbmdcIiB8fCBwYXJ0LnRleHQudHJpbSgpLmxlbmd0aCA9PT0gMDtcbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9KTtcbn1cbiJdfQ==
|
package/src/serving-wire.ts
DELETED
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Framework-neutral repairs for OpenAI Chat traffic sent through Databricks
|
|
3
|
-
* Model Serving.
|
|
4
|
-
*
|
|
5
|
-
* @module
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { json, stringUtils } from "@dbx-tools/shared-core";
|
|
9
|
-
import { type ChatMessage, type ChatRole, openaiChat } from "@dbx-tools/shared-model";
|
|
10
|
-
|
|
11
|
-
import { chatToolReasoningEffort } from "./policy.ts";
|
|
12
|
-
|
|
13
|
-
/** Chat message plus provider reasoning fields emitted by Databricks models. */
|
|
14
|
-
export interface ServingChatMessage extends ChatMessage {
|
|
15
|
-
role: ChatRole | "reasoning";
|
|
16
|
-
reasoning?: unknown;
|
|
17
|
-
reasoning_content?: unknown;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
/** Prepared fetch arguments and the sanitized request body. */
|
|
21
|
-
export interface RewrittenServingRequest {
|
|
22
|
-
input: Parameters<typeof fetch>[0];
|
|
23
|
-
init: Parameters<typeof fetch>[1];
|
|
24
|
-
body: string;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const REASONING_PART_TYPES: ReadonlySet<string> = new Set([
|
|
28
|
-
"reasoning",
|
|
29
|
-
"thinking",
|
|
30
|
-
"redacted_thinking",
|
|
31
|
-
]);
|
|
32
|
-
|
|
33
|
-
/** Sanitize a serialized Chat Completions request when provider quirks require it. */
|
|
34
|
-
export function rewriteServingBody(body: string): string {
|
|
35
|
-
const parsed = json.parseRecord(body);
|
|
36
|
-
if (!parsed) return body;
|
|
37
|
-
let changed =
|
|
38
|
-
openaiChat.stripUnsupportedChatFields(parsed).length > 0 ||
|
|
39
|
-
applyToolReasoningCompatibility(parsed);
|
|
40
|
-
if (Array.isArray(parsed.messages)) {
|
|
41
|
-
const messages = parsed.messages as ServingChatMessage[];
|
|
42
|
-
const stripped = stripReasoningFromServingMessages(messages);
|
|
43
|
-
const repaired = repairAssistantPrefill(messages);
|
|
44
|
-
changed = changed || stripped || repaired;
|
|
45
|
-
}
|
|
46
|
-
return changed ? JSON.stringify(parsed) : body;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/** Read and sanitize a Chat Completions request without retaining stale byte headers. */
|
|
50
|
-
export async function rewriteServingRequest(
|
|
51
|
-
input: Parameters<typeof fetch>[0],
|
|
52
|
-
init?: Parameters<typeof fetch>[1],
|
|
53
|
-
): Promise<RewrittenServingRequest> {
|
|
54
|
-
const request = new Request(input, init);
|
|
55
|
-
const body = await request.clone().text();
|
|
56
|
-
const rewritten = rewriteServingBody(body);
|
|
57
|
-
if (rewritten === body) return { input, init, body };
|
|
58
|
-
const headers = new Headers(request.headers);
|
|
59
|
-
headers.delete("content-length");
|
|
60
|
-
headers.delete("content-encoding");
|
|
61
|
-
return {
|
|
62
|
-
input: new Request(request, { body: rewritten, headers }),
|
|
63
|
-
init: undefined,
|
|
64
|
-
body: rewritten,
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/** Normalize Chat Completions reasoning for GPT tool calls. */
|
|
69
|
-
export function applyToolReasoningCompatibility(body: Record<string, unknown>): boolean {
|
|
70
|
-
if (!Array.isArray(body.tools) || body.tools.length === 0) return false;
|
|
71
|
-
const model = stringUtils.trimToNull(body.model);
|
|
72
|
-
if (!model || chatToolReasoningEffort(model) !== "none") return false;
|
|
73
|
-
if (body.reasoning_effort === "none") return false;
|
|
74
|
-
body.reasoning_effort = "none";
|
|
75
|
-
return true;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/** Remove provider reasoning blocks that cannot be replayed safely. */
|
|
79
|
-
export function stripReasoningFromServingMessages(messages: ServingChatMessage[]): boolean {
|
|
80
|
-
let changed = false;
|
|
81
|
-
for (let index = messages.length - 1; index >= 0; index--) {
|
|
82
|
-
const message = messages[index];
|
|
83
|
-
if (!message) continue;
|
|
84
|
-
if (message.role === "reasoning") {
|
|
85
|
-
messages.splice(index, 1);
|
|
86
|
-
changed = true;
|
|
87
|
-
continue;
|
|
88
|
-
}
|
|
89
|
-
if (message.reasoning !== undefined) {
|
|
90
|
-
delete message.reasoning;
|
|
91
|
-
changed = true;
|
|
92
|
-
}
|
|
93
|
-
if (message.reasoning_content !== undefined) {
|
|
94
|
-
delete message.reasoning_content;
|
|
95
|
-
changed = true;
|
|
96
|
-
}
|
|
97
|
-
const parts = openaiChat.chatContentParts(message.content);
|
|
98
|
-
if (!parts) continue;
|
|
99
|
-
const filtered = parts.filter((part) => {
|
|
100
|
-
const type = part?.type;
|
|
101
|
-
if (typeof type !== "string" || !REASONING_PART_TYPES.has(type)) return true;
|
|
102
|
-
changed = true;
|
|
103
|
-
return false;
|
|
104
|
-
});
|
|
105
|
-
if (filtered.length !== parts.length) message.content = filtered;
|
|
106
|
-
const hasToolCalls = Array.isArray(message.tool_calls) && message.tool_calls.length > 0;
|
|
107
|
-
if (message.role === "assistant" && !hasToolCalls && isEmptyServingContent(message.content)) {
|
|
108
|
-
messages.splice(index, 1);
|
|
109
|
-
changed = true;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
return changed;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/** Fold a trailing assistant prefill back into its preceding tool-call turn. */
|
|
116
|
-
export function repairAssistantPrefill(messages: ServingChatMessage[]): boolean {
|
|
117
|
-
if (messages.length < 2) return false;
|
|
118
|
-
const last = messages[messages.length - 1];
|
|
119
|
-
if (!last || last.role !== "assistant" || (last.tool_calls && last.tool_calls.length > 0)) {
|
|
120
|
-
return false;
|
|
121
|
-
}
|
|
122
|
-
let index = messages.length - 2;
|
|
123
|
-
while (index >= 0 && messages[index]?.role === "tool") index--;
|
|
124
|
-
const opener = messages[index];
|
|
125
|
-
if (
|
|
126
|
-
!opener ||
|
|
127
|
-
opener.role !== "assistant" ||
|
|
128
|
-
!opener.tool_calls ||
|
|
129
|
-
opener.tool_calls.length === 0
|
|
130
|
-
) {
|
|
131
|
-
return false;
|
|
132
|
-
}
|
|
133
|
-
opener.content = [
|
|
134
|
-
stringUtils.trimToNull(textFromServingContent(opener.content)),
|
|
135
|
-
stringUtils.trimToNull(textFromServingContent(last.content)),
|
|
136
|
-
]
|
|
137
|
-
.filter((value): value is string => value !== null)
|
|
138
|
-
.join("\n\n");
|
|
139
|
-
messages.pop();
|
|
140
|
-
return true;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/** Normalize array-valued content in a non-streaming Chat Completions response. */
|
|
144
|
-
export function rewriteServingResponseBody(body: string): string {
|
|
145
|
-
const parsed = json.parseRecord(body);
|
|
146
|
-
if (!parsed) return body;
|
|
147
|
-
return flattenChoiceMessageContent(parsed) ? JSON.stringify(parsed) : body;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/** Normalize array-valued content in an SSE stream without buffering the stream. */
|
|
151
|
-
export function rewriteServingResponseStream(
|
|
152
|
-
body: ReadableStream<Uint8Array>,
|
|
153
|
-
): ReadableStream<Uint8Array> {
|
|
154
|
-
const decoder = new TextDecoder();
|
|
155
|
-
const encoder = new TextEncoder();
|
|
156
|
-
let buffer = "";
|
|
157
|
-
return body.pipeThrough(
|
|
158
|
-
new TransformStream<Uint8Array, Uint8Array>({
|
|
159
|
-
transform(chunk, controller) {
|
|
160
|
-
buffer += decoder.decode(chunk, { stream: true });
|
|
161
|
-
let newline = buffer.indexOf("\n");
|
|
162
|
-
while (newline >= 0) {
|
|
163
|
-
const line = buffer.slice(0, newline + 1);
|
|
164
|
-
buffer = buffer.slice(newline + 1);
|
|
165
|
-
controller.enqueue(encoder.encode(rewriteServingResponseStreamLine(line)));
|
|
166
|
-
newline = buffer.indexOf("\n");
|
|
167
|
-
}
|
|
168
|
-
},
|
|
169
|
-
flush(controller) {
|
|
170
|
-
buffer += decoder.decode();
|
|
171
|
-
if (buffer) controller.enqueue(encoder.encode(rewriteServingResponseStreamLine(buffer)));
|
|
172
|
-
},
|
|
173
|
-
}),
|
|
174
|
-
);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/** Flatten Chat Completions `choices[].message.content` arrays to strings. */
|
|
178
|
-
export function flattenChoiceMessageContent(payload: Record<string, unknown>): boolean {
|
|
179
|
-
return flattenChoiceContent(payload, "message");
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
/** Flatten Chat Completions `choices[].delta.content` arrays to strings. */
|
|
183
|
-
export function flattenChoiceDeltaContent(payload: Record<string, unknown>): boolean {
|
|
184
|
-
return flattenChoiceContent(payload, "delta");
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
function rewriteServingResponseStreamLine(line: string): string {
|
|
188
|
-
const lineEnding = line.endsWith("\r\n") ? "\r\n" : line.endsWith("\n") ? "\n" : "";
|
|
189
|
-
const content = lineEnding ? line.slice(0, -lineEnding.length) : line;
|
|
190
|
-
const match = /^(data:\s*)(.*)$/.exec(content);
|
|
191
|
-
if (!match || match[2] === "[DONE]") return line;
|
|
192
|
-
const parsed = json.parseRecord(match[2]);
|
|
193
|
-
if (!parsed || !flattenChoiceDeltaContent(parsed)) return line;
|
|
194
|
-
return `${match[1]}${JSON.stringify(parsed)}${lineEnding}`;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
function flattenChoiceContent(
|
|
198
|
-
payload: Record<string, unknown>,
|
|
199
|
-
field: "message" | "delta",
|
|
200
|
-
): boolean {
|
|
201
|
-
if (!Array.isArray(payload.choices)) return false;
|
|
202
|
-
let changed = false;
|
|
203
|
-
for (const choice of payload.choices) {
|
|
204
|
-
if (!choice || typeof choice !== "object") continue;
|
|
205
|
-
const container = (choice as Record<string, unknown>)[field];
|
|
206
|
-
if (!container || typeof container !== "object") continue;
|
|
207
|
-
const target = container as { content?: unknown };
|
|
208
|
-
const parts = openaiChat.chatContentParts(target.content);
|
|
209
|
-
if (!parts) continue;
|
|
210
|
-
target.content = openaiChat.chatContentToText(parts, { types: ["text"] });
|
|
211
|
-
changed = true;
|
|
212
|
-
}
|
|
213
|
-
return changed;
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
function textFromServingContent(content: ServingChatMessage["content"]): string {
|
|
217
|
-
return openaiChat.chatContentToText(content, { separator: "\n\n", types: ["text"] });
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
function isEmptyServingContent(content: ServingChatMessage["content"]): boolean {
|
|
221
|
-
if (content === undefined) return true;
|
|
222
|
-
if (typeof content === "string") return content.trim().length === 0;
|
|
223
|
-
const parts = openaiChat.chatContentParts(content);
|
|
224
|
-
if (!parts) return true;
|
|
225
|
-
return parts.every((part) => {
|
|
226
|
-
if (part?.type === "text") {
|
|
227
|
-
return typeof part.text !== "string" || part.text.trim().length === 0;
|
|
228
|
-
}
|
|
229
|
-
return false;
|
|
230
|
-
});
|
|
231
|
-
}
|