@dbx-tools/appkit-model-gateway 0.9.36
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/LICENSE +202 -0
- package/README.md +63 -0
- package/index.ts +28 -0
- package/lib/index.d.ts +24 -0
- package/lib/index.js +21 -0
- package/lib/scripts/copy-manifest.d.ts +1 -0
- package/lib/scripts/copy-manifest.js +14 -0
- package/lib/src/gateway.d.ts +29 -0
- package/lib/src/gateway.js +127 -0
- package/lib/src/manifest.json +13 -0
- package/lib/src/models.d.ts +10 -0
- package/lib/src/models.js +119 -0
- package/lib/src/plugin.d.ts +32 -0
- package/lib/src/plugin.js +70 -0
- package/lib/src/protocols/decode.d.ts +17 -0
- package/lib/src/protocols/decode.js +262 -0
- package/lib/src/protocols/encode.d.ts +18 -0
- package/lib/src/protocols/encode.js +498 -0
- package/lib/src/reasoning-adapt.d.ts +27 -0
- package/lib/src/reasoning-adapt.js +61 -0
- package/lib/src/registry.d.ts +32 -0
- package/lib/src/registry.js +167 -0
- package/lib/src/router.d.ts +18 -0
- package/lib/src/router.js +139 -0
- package/lib/src/routes.d.ts +14 -0
- package/lib/src/routes.js +158 -0
- package/lib/src/translation.d.ts +8 -0
- package/lib/src/translation.js +156 -0
- package/lib/src/transport.d.ts +19 -0
- package/lib/src/transport.js +168 -0
- package/lib/tsconfig.tsbuildinfo +1 -0
- package/package.json +150 -0
- package/src/gateway.ts +167 -0
- package/src/manifest.json +13 -0
- package/src/models.ts +152 -0
- package/src/plugin.ts +95 -0
- package/src/protocols/decode.ts +281 -0
- package/src/protocols/encode.ts +515 -0
- package/src/reasoning-adapt.ts +87 -0
- package/src/registry.ts +225 -0
- package/src/router.ts +174 -0
- package/src/routes.ts +181 -0
- package/src/translation.ts +178 -0
- package/src/transport.ts +182 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reasoning-effort adaptation for gateway round trips.
|
|
3
|
+
*
|
|
4
|
+
* Proactively remaps client efforts onto the known ladder, then on a single
|
|
5
|
+
* unsupported-value 400 learns from the error and retries once with the
|
|
6
|
+
* updated ladder.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
import { learnReasoningLevelsFromError, modelReasoningLevelsFor, } from "@dbx-tools/model/metadata";
|
|
11
|
+
import { adaptRequestReasoning, parseReasoningLevels, } from "@dbx-tools/model/reasoning-translation";
|
|
12
|
+
import { log } from "@dbx-tools/shared-core";
|
|
13
|
+
const logger = log.logger("appkit/model-gateway/reasoning");
|
|
14
|
+
/** Adapt a request body onto the current known ladder for `model`. */
|
|
15
|
+
export function adaptInferenceReasoning(model, body) {
|
|
16
|
+
const adapted = adaptRequestReasoning(body, modelReasoningLevelsFor(model));
|
|
17
|
+
if (adapted.changed) {
|
|
18
|
+
logger.debug("adapted reasoning effort before upstream", {
|
|
19
|
+
model,
|
|
20
|
+
effort: adapted.wireEffort,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
body: adapted.body,
|
|
25
|
+
wireEffort: adapted.wireEffort,
|
|
26
|
+
changed: adapted.changed,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* On an unsupported-reasoning 400, learn once and optionally produce a
|
|
31
|
+
* remapped retry body. Returns `undefined` when no retry should occur.
|
|
32
|
+
*/
|
|
33
|
+
export async function learnAndAdaptReasoningRetry(input) {
|
|
34
|
+
if (input.response.ok || input.response.status !== 400)
|
|
35
|
+
return undefined;
|
|
36
|
+
let errorBody;
|
|
37
|
+
try {
|
|
38
|
+
errorBody = JSON.parse(await input.response.clone().text());
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return undefined;
|
|
42
|
+
}
|
|
43
|
+
if (parseReasoningLevels(errorBody).length === 0)
|
|
44
|
+
return undefined;
|
|
45
|
+
const levels = await learnReasoningLevelsFromError(input.model, errorBody);
|
|
46
|
+
logger.info("learned reasoning levels from upstream error", {
|
|
47
|
+
model: input.model,
|
|
48
|
+
levels,
|
|
49
|
+
});
|
|
50
|
+
const adapted = adaptRequestReasoning(input.body, levels);
|
|
51
|
+
if (adapted.wireEffort === undefined || adapted.wireEffort === input.previousWireEffort) {
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
logger.info("retrying with adapted reasoning effort", {
|
|
55
|
+
model: input.model,
|
|
56
|
+
from: input.previousWireEffort,
|
|
57
|
+
to: adapted.wireEffort,
|
|
58
|
+
});
|
|
59
|
+
return adapted.body;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVhc29uaW5nLWFkYXB0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3JlYXNvbmluZy1hZGFwdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7R0FRRztBQUVILE9BQU8sRUFDTCw2QkFBNkIsRUFDN0IsdUJBQXVCLEdBQ3hCLE1BQU0sMkJBQTJCLENBQUM7QUFDbkMsT0FBTyxFQUNMLHFCQUFxQixFQUNyQixvQkFBb0IsR0FDckIsTUFBTSx3Q0FBd0MsQ0FBQztBQUNoRCxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFFN0MsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQyxnQ0FBZ0MsQ0FBQyxDQUFDO0FBUzVELHNFQUFzRTtBQUN0RSxNQUFNLFVBQVUsdUJBQXVCLENBQ3JDLEtBQWEsRUFDYixJQUF1QztJQUV2QyxNQUFNLE9BQU8sR0FBRyxxQkFBcUIsQ0FBQyxJQUFJLEVBQUUsdUJBQXVCLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztJQUM1RSxJQUFJLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNwQixNQUFNLENBQUMsS0FBSyxDQUFDLDBDQUEwQyxFQUFFO1lBQ3ZELEtBQUs7WUFDTCxNQUFNLEVBQUUsT0FBTyxDQUFDLFVBQVU7U0FDM0IsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUNELE9BQU87UUFDTCxJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUk7UUFDbEIsVUFBVSxFQUFFLE9BQU8sQ0FBQyxVQUFVO1FBQzlCLE9BQU8sRUFBRSxPQUFPLENBQUMsT0FBTztLQUN6QixDQUFDO0FBQ0osQ0FBQztBQUVEOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxLQUFLLFVBQVUsMkJBQTJCLENBQUMsS0FLakQ7SUFDQyxJQUFJLEtBQUssQ0FBQyxRQUFRLENBQUMsRUFBRSxJQUFJLEtBQUssQ0FBQyxRQUFRLENBQUMsTUFBTSxLQUFLLEdBQUc7UUFBRSxPQUFPLFNBQVMsQ0FBQztJQUV6RSxJQUFJLFNBQWtCLENBQUM7SUFDdkIsSUFBSSxDQUFDO1FBQ0gsU0FBUyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxLQUFLLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7SUFDOUQsQ0FBQztJQUFDLE1BQU0sQ0FBQztRQUNQLE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFRCxJQUFJLG9CQUFvQixDQUFDLFNBQVMsQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQUUsT0FBTyxTQUFTLENBQUM7SUFFbkUsTUFBTSxNQUFNLEdBQUcsTUFBTSw2QkFBNkIsQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQzNFLE1BQU0sQ0FBQyxJQUFJLENBQUMsOENBQThDLEVBQUU7UUFDMUQsS0FBSyxFQUFFLEtBQUssQ0FBQyxLQUFLO1FBQ2xCLE1BQU07S0FDUCxDQUFDLENBQUM7SUFFSCxNQUFNLE9BQU8sR0FBRyxxQkFBcUIsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQzFELElBQUksT0FBTyxDQUFDLFVBQVUsS0FBSyxTQUFTLElBQUksT0FBTyxDQUFDLFVBQVUsS0FBSyxLQUFLLENBQUMsa0JBQWtCLEVBQUUsQ0FBQztRQUN4RixPQUFPLFNBQVMsQ0FBQztJQUNuQixDQUFDO0lBRUQsTUFBTSxDQUFDLElBQUksQ0FBQyx3Q0FBd0MsRUFBRTtRQUNwRCxLQUFLLEVBQUUsS0FBSyxDQUFDLEtBQUs7UUFDbEIsSUFBSSxFQUFFLEtBQUssQ0FBQyxrQkFBa0I7UUFDOUIsRUFBRSxFQUFFLE9BQU8sQ0FBQyxVQUFVO0tBQ3ZCLENBQUMsQ0FBQztJQUNILE9BQU8sT0FBTyxDQUFDLElBQUksQ0FBQztBQUN0QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBSZWFzb25pbmctZWZmb3J0IGFkYXB0YXRpb24gZm9yIGdhdGV3YXkgcm91bmQgdHJpcHMuXG4gKlxuICogUHJvYWN0aXZlbHkgcmVtYXBzIGNsaWVudCBlZmZvcnRzIG9udG8gdGhlIGtub3duIGxhZGRlciwgdGhlbiBvbiBhIHNpbmdsZVxuICogdW5zdXBwb3J0ZWQtdmFsdWUgNDAwIGxlYXJucyBmcm9tIHRoZSBlcnJvciBhbmQgcmV0cmllcyBvbmNlIHdpdGggdGhlXG4gKiB1cGRhdGVkIGxhZGRlci5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHtcbiAgbGVhcm5SZWFzb25pbmdMZXZlbHNGcm9tRXJyb3IsXG4gIG1vZGVsUmVhc29uaW5nTGV2ZWxzRm9yLFxufSBmcm9tIFwiQGRieC10b29scy9tb2RlbC9tZXRhZGF0YVwiO1xuaW1wb3J0IHtcbiAgYWRhcHRSZXF1ZXN0UmVhc29uaW5nLFxuICBwYXJzZVJlYXNvbmluZ0xldmVscyxcbn0gZnJvbSBcIkBkYngtdG9vbHMvbW9kZWwvcmVhc29uaW5nLXRyYW5zbGF0aW9uXCI7XG5pbXBvcnQgeyBsb2cgfSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtY29yZVwiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwiYXBwa2l0L21vZGVsLWdhdGV3YXkvcmVhc29uaW5nXCIpO1xuXG4vKiogUmVzdWx0IG9mIHRoZSBmaXJzdCBwcm9hY3RpdmUgYWRhcHRhdGlvbiBwYXNzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBBZGFwdGVkSW5mZXJlbmNlQm9keSB7XG4gIHJlYWRvbmx5IGJvZHk6IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIHVua25vd24+PjtcbiAgcmVhZG9ubHkgd2lyZUVmZm9ydD86IHN0cmluZztcbiAgcmVhZG9ubHkgY2hhbmdlZDogYm9vbGVhbjtcbn1cblxuLyoqIEFkYXB0IGEgcmVxdWVzdCBib2R5IG9udG8gdGhlIGN1cnJlbnQga25vd24gbGFkZGVyIGZvciBgbW9kZWxgLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFkYXB0SW5mZXJlbmNlUmVhc29uaW5nKFxuICBtb2RlbDogc3RyaW5nLFxuICBib2R5OiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4sXG4pOiBBZGFwdGVkSW5mZXJlbmNlQm9keSB7XG4gIGNvbnN0IGFkYXB0ZWQgPSBhZGFwdFJlcXVlc3RSZWFzb25pbmcoYm9keSwgbW9kZWxSZWFzb25pbmdMZXZlbHNGb3IobW9kZWwpKTtcbiAgaWYgKGFkYXB0ZWQuY2hhbmdlZCkge1xuICAgIGxvZ2dlci5kZWJ1ZyhcImFkYXB0ZWQgcmVhc29uaW5nIGVmZm9ydCBiZWZvcmUgdXBzdHJlYW1cIiwge1xuICAgICAgbW9kZWwsXG4gICAgICBlZmZvcnQ6IGFkYXB0ZWQud2lyZUVmZm9ydCxcbiAgICB9KTtcbiAgfVxuICByZXR1cm4ge1xuICAgIGJvZHk6IGFkYXB0ZWQuYm9keSxcbiAgICB3aXJlRWZmb3J0OiBhZGFwdGVkLndpcmVFZmZvcnQsXG4gICAgY2hhbmdlZDogYWRhcHRlZC5jaGFuZ2VkLFxuICB9O1xufVxuXG4vKipcbiAqIE9uIGFuIHVuc3VwcG9ydGVkLXJlYXNvbmluZyA0MDAsIGxlYXJuIG9uY2UgYW5kIG9wdGlvbmFsbHkgcHJvZHVjZSBhXG4gKiByZW1hcHBlZCByZXRyeSBib2R5LiBSZXR1cm5zIGB1bmRlZmluZWRgIHdoZW4gbm8gcmV0cnkgc2hvdWxkIG9jY3VyLlxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbGVhcm5BbmRBZGFwdFJlYXNvbmluZ1JldHJ5KGlucHV0OiB7XG4gIHJlYWRvbmx5IG1vZGVsOiBzdHJpbmc7XG4gIHJlYWRvbmx5IGJvZHk6IFJlYWRvbmx5PFJlY29yZDxzdHJpbmcsIHVua25vd24+PjtcbiAgcmVhZG9ubHkgcmVzcG9uc2U6IFJlc3BvbnNlO1xuICByZWFkb25seSBwcmV2aW91c1dpcmVFZmZvcnQ/OiBzdHJpbmc7XG59KTogUHJvbWlzZTxSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4gfCB1bmRlZmluZWQ+IHtcbiAgaWYgKGlucHV0LnJlc3BvbnNlLm9rIHx8IGlucHV0LnJlc3BvbnNlLnN0YXR1cyAhPT0gNDAwKSByZXR1cm4gdW5kZWZpbmVkO1xuXG4gIGxldCBlcnJvckJvZHk6IHVua25vd247XG4gIHRyeSB7XG4gICAgZXJyb3JCb2R5ID0gSlNPTi5wYXJzZShhd2FpdCBpbnB1dC5yZXNwb25zZS5jbG9uZSgpLnRleHQoKSk7XG4gIH0gY2F0Y2gge1xuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICBpZiAocGFyc2VSZWFzb25pbmdMZXZlbHMoZXJyb3JCb2R5KS5sZW5ndGggPT09IDApIHJldHVybiB1bmRlZmluZWQ7XG5cbiAgY29uc3QgbGV2ZWxzID0gYXdhaXQgbGVhcm5SZWFzb25pbmdMZXZlbHNGcm9tRXJyb3IoaW5wdXQubW9kZWwsIGVycm9yQm9keSk7XG4gIGxvZ2dlci5pbmZvKFwibGVhcm5lZCByZWFzb25pbmcgbGV2ZWxzIGZyb20gdXBzdHJlYW0gZXJyb3JcIiwge1xuICAgIG1vZGVsOiBpbnB1dC5tb2RlbCxcbiAgICBsZXZlbHMsXG4gIH0pO1xuXG4gIGNvbnN0IGFkYXB0ZWQgPSBhZGFwdFJlcXVlc3RSZWFzb25pbmcoaW5wdXQuYm9keSwgbGV2ZWxzKTtcbiAgaWYgKGFkYXB0ZWQud2lyZUVmZm9ydCA9PT0gdW5kZWZpbmVkIHx8IGFkYXB0ZWQud2lyZUVmZm9ydCA9PT0gaW5wdXQucHJldmlvdXNXaXJlRWZmb3J0KSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgfVxuXG4gIGxvZ2dlci5pbmZvKFwicmV0cnlpbmcgd2l0aCBhZGFwdGVkIHJlYXNvbmluZyBlZmZvcnRcIiwge1xuICAgIG1vZGVsOiBpbnB1dC5tb2RlbCxcbiAgICBmcm9tOiBpbnB1dC5wcmV2aW91c1dpcmVFZmZvcnQsXG4gICAgdG86IGFkYXB0ZWQud2lyZUVmZm9ydCxcbiAgfSk7XG4gIHJldHVybiBhZGFwdGVkLmJvZHk7XG59XG4iXX0=
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request-scoped Databricks model discovery for the AppKit gateway.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { type ResolveModelInput } from "@dbx-tools/shared-model/contracts";
|
|
7
|
+
import type { ModelCapabilityOverride, ModelTarget } from "@dbx-tools/shared-model-gateway";
|
|
8
|
+
/** Resolution controls passed through to the model policy owner. */
|
|
9
|
+
export type ModelRegistryResolveOptions = Pick<ResolveModelInput, "modelClass" | "requiresTools">;
|
|
10
|
+
/** Dynamic model catalogue used by request routing and model-list responses. */
|
|
11
|
+
export interface ModelRegistry {
|
|
12
|
+
list(): Promise<ModelTarget[]>;
|
|
13
|
+
search(query: string): Promise<ModelTarget[]>;
|
|
14
|
+
resolve(model: string, options?: ModelRegistryResolveOptions): Promise<ModelTarget | undefined>;
|
|
15
|
+
refresh(): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
/** Configuration for {@link DatabricksModelRegistry}. */
|
|
18
|
+
export interface ModelRegistryOptions {
|
|
19
|
+
readonly ttlMs?: number;
|
|
20
|
+
readonly overrides?: readonly ModelCapabilityOverride[];
|
|
21
|
+
}
|
|
22
|
+
/** Model registry backed by the active AppKit execution context. */
|
|
23
|
+
export declare class DatabricksModelRegistry implements ModelRegistry {
|
|
24
|
+
private readonly ttlMs;
|
|
25
|
+
private readonly overrides;
|
|
26
|
+
constructor(options?: ModelRegistryOptions);
|
|
27
|
+
list(): Promise<ModelTarget[]>;
|
|
28
|
+
resolve(model: string, options?: ModelRegistryResolveOptions): Promise<ModelTarget | undefined>;
|
|
29
|
+
search(query: string): Promise<ModelTarget[]>;
|
|
30
|
+
refresh(): Promise<void>;
|
|
31
|
+
private target;
|
|
32
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request-scoped Databricks model discovery for the AppKit gateway.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { getExecutionContext } from "@databricks/appkit";
|
|
7
|
+
import { metadata, modelCatalog, policy, resolve as modelResolve } from "@dbx-tools/model";
|
|
8
|
+
import { log } from "@dbx-tools/shared-core";
|
|
9
|
+
import { ModelClass, } from "@dbx-tools/shared-model/contracts";
|
|
10
|
+
const DEFAULT_CACHE_TTL_MS = 60_000;
|
|
11
|
+
const logger = log.logger("appkit/model-gateway/registry");
|
|
12
|
+
/** Model registry backed by the active AppKit execution context. */
|
|
13
|
+
export class DatabricksModelRegistry {
|
|
14
|
+
ttlMs;
|
|
15
|
+
overrides;
|
|
16
|
+
constructor(options = {}) {
|
|
17
|
+
this.ttlMs = positiveTtl(options.ttlMs);
|
|
18
|
+
this.overrides = options.overrides ?? [];
|
|
19
|
+
}
|
|
20
|
+
async list() {
|
|
21
|
+
const context = await registryContext();
|
|
22
|
+
logger.debug("loading catalogue", { host: context.host, ttlMs: this.ttlMs });
|
|
23
|
+
const endpoints = await modelCatalog.listServingEndpoints(context.client, context.host, {
|
|
24
|
+
cacheIdentity: context.identity,
|
|
25
|
+
ttlMs: this.ttlMs,
|
|
26
|
+
});
|
|
27
|
+
const targets = endpoints.map((endpoint) => this.target(endpoint));
|
|
28
|
+
logger.debug("loaded catalogue", {
|
|
29
|
+
endpointCount: endpoints.length,
|
|
30
|
+
host: context.host,
|
|
31
|
+
targetCount: targets.length,
|
|
32
|
+
});
|
|
33
|
+
return targets;
|
|
34
|
+
}
|
|
35
|
+
async resolve(model, options = {}) {
|
|
36
|
+
const requested = unqualifiedModel(model);
|
|
37
|
+
const targets = await this.list();
|
|
38
|
+
const exact = targets.find((target) => target.aliases.some((alias) => alias.localeCompare(requested, undefined, { sensitivity: "accent" }) === 0));
|
|
39
|
+
if (exact && matchesResolveOptions(exact, options)) {
|
|
40
|
+
logger.debug("resolved exact model", { requested, resolved: exact.id });
|
|
41
|
+
return exact;
|
|
42
|
+
}
|
|
43
|
+
const endpoints = targets
|
|
44
|
+
.map((target) => target.endpoint)
|
|
45
|
+
.filter((endpoint) => endpoint !== undefined);
|
|
46
|
+
const resolved = modelResolve.resolveModel(endpoints, {
|
|
47
|
+
explicit: requested,
|
|
48
|
+
...options,
|
|
49
|
+
});
|
|
50
|
+
const target = targets.find((candidate) => candidate.id === resolved.modelId);
|
|
51
|
+
logger.debug("resolved fuzzy model", {
|
|
52
|
+
requested,
|
|
53
|
+
resolved: target?.id,
|
|
54
|
+
source: resolved.source,
|
|
55
|
+
});
|
|
56
|
+
return target;
|
|
57
|
+
}
|
|
58
|
+
async search(query) {
|
|
59
|
+
const targets = await this.list();
|
|
60
|
+
const byId = new Map(targets.map((target) => [target.id, target]));
|
|
61
|
+
const endpoints = targets
|
|
62
|
+
.map((target) => target.endpoint)
|
|
63
|
+
.filter((endpoint) => endpoint !== undefined);
|
|
64
|
+
const ranked = [
|
|
65
|
+
...modelResolve.lookupModels(endpoints, { search: query }),
|
|
66
|
+
...modelResolve.lookupModels(endpoints, {
|
|
67
|
+
search: query,
|
|
68
|
+
modelClass: ModelClass.Embedding,
|
|
69
|
+
}),
|
|
70
|
+
].sort((left, right) => (left.score ?? 0) - (right.score ?? 0));
|
|
71
|
+
return ranked
|
|
72
|
+
.map(({ endpoint }) => byId.get(endpoint.name))
|
|
73
|
+
.filter((target) => target !== undefined)
|
|
74
|
+
.filter((target, index, all) => all.findIndex((candidate) => candidate.id === target.id) === index);
|
|
75
|
+
}
|
|
76
|
+
async refresh() {
|
|
77
|
+
const context = await registryContext();
|
|
78
|
+
logger.debug("clearing catalogue", { host: context.host });
|
|
79
|
+
await modelCatalog.clearServingEndpointsCache(context.host, context.identity);
|
|
80
|
+
await modelCatalog.listServingEndpoints(context.client, context.host, {
|
|
81
|
+
cacheIdentity: context.identity,
|
|
82
|
+
ttlMs: this.ttlMs,
|
|
83
|
+
});
|
|
84
|
+
logger.debug("refreshed catalogue", { host: context.host });
|
|
85
|
+
}
|
|
86
|
+
target(endpoint) {
|
|
87
|
+
const published = metadata.modelCapabilitiesFor(endpoint);
|
|
88
|
+
const family = endpoint.family?.toLowerCase();
|
|
89
|
+
const openAiFamily = family === "gpt" || family === "openai" || endpoint.name.includes("codex");
|
|
90
|
+
const modelServiceName = normalizedModelServiceName(endpoint.modelServiceName);
|
|
91
|
+
const embeddings = endpoint.class === ModelClass.Embedding || endpoint.task === "llm/v1/embeddings";
|
|
92
|
+
const capabilities = {
|
|
93
|
+
responses: !embeddings && (openAiFamily || published.responses),
|
|
94
|
+
openResponses: !embeddings && !openAiFamily,
|
|
95
|
+
chat: !embeddings,
|
|
96
|
+
anthropic: family === "claude",
|
|
97
|
+
embeddings,
|
|
98
|
+
aiGatewayCodex: !embeddings && Boolean(modelServiceName) && family !== "claude" && family !== "gemini",
|
|
99
|
+
tools: endpoint.supportsTools === true,
|
|
100
|
+
reasoning: policy.modelReasoningEfforts(endpoint.name).length > 0,
|
|
101
|
+
streaming: true,
|
|
102
|
+
parallelTools: endpoint.supportsTools === true,
|
|
103
|
+
customTools: published.applyPatch || endpoint.name.includes("codex"),
|
|
104
|
+
structuredOutput: true,
|
|
105
|
+
webSearch: published.webSearch,
|
|
106
|
+
};
|
|
107
|
+
const aliases = new Set([
|
|
108
|
+
endpoint.name,
|
|
109
|
+
endpoint.displayName,
|
|
110
|
+
endpoint.modelServiceName,
|
|
111
|
+
modelServiceName,
|
|
112
|
+
...Object.values(endpoint.serviceNames ?? {}),
|
|
113
|
+
].filter((value) => Boolean(value?.trim())));
|
|
114
|
+
const override = this.overrides.find((candidate) => candidate.model === endpoint.name ||
|
|
115
|
+
[...aliases].some((alias) => alias === candidate.model));
|
|
116
|
+
return {
|
|
117
|
+
id: endpoint.name,
|
|
118
|
+
aliases: [...aliases],
|
|
119
|
+
displayName: endpoint.displayName ?? endpoint.name,
|
|
120
|
+
...(endpoint.family ? { family: endpoint.family } : {}),
|
|
121
|
+
...(modelServiceName ? { modelServiceName } : {}),
|
|
122
|
+
endpoint,
|
|
123
|
+
capabilities: { ...capabilities, ...override?.capabilities },
|
|
124
|
+
reasoningEfforts: endpoint.reasoningEfforts ?? [],
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
async function registryContext() {
|
|
129
|
+
const context = getExecutionContext();
|
|
130
|
+
const host = (await context.client.config.getHost()).toString();
|
|
131
|
+
return {
|
|
132
|
+
client: context.client,
|
|
133
|
+
host,
|
|
134
|
+
identity: "userId" in context ? context.userId : context.serviceUserId,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
function unqualifiedModel(model) {
|
|
138
|
+
return model.trim().replace(/^(?:dbx|databricks)\//i, "");
|
|
139
|
+
}
|
|
140
|
+
function positiveTtl(value = DEFAULT_CACHE_TTL_MS) {
|
|
141
|
+
if (!Number.isFinite(value) || value <= 0) {
|
|
142
|
+
throw new Error("Model registry ttlMs must be a positive finite number");
|
|
143
|
+
}
|
|
144
|
+
return value;
|
|
145
|
+
}
|
|
146
|
+
function normalizedModelServiceName(value) {
|
|
147
|
+
const normalized = value?.trim().replace(/^databricks\//, "");
|
|
148
|
+
if (!normalized)
|
|
149
|
+
return undefined;
|
|
150
|
+
if (normalized.startsWith("system.ai.databricks-")) {
|
|
151
|
+
return `system.ai.${normalized.slice("system.ai.databricks-".length)}`;
|
|
152
|
+
}
|
|
153
|
+
if (normalized.startsWith("databricks-")) {
|
|
154
|
+
return `system.ai.${normalized.slice("databricks-".length)}`;
|
|
155
|
+
}
|
|
156
|
+
return normalized;
|
|
157
|
+
}
|
|
158
|
+
function matchesResolveOptions(target, options) {
|
|
159
|
+
if (options.requiresTools && !target.capabilities.tools)
|
|
160
|
+
return false;
|
|
161
|
+
if (options.modelClass === ModelClass.Embedding)
|
|
162
|
+
return target.capabilities.embeddings;
|
|
163
|
+
if (options.modelClass !== undefined)
|
|
164
|
+
return target.capabilities.chat;
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaXN0cnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcmVnaXN0cnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7R0FJRztBQUVILE9BQU8sRUFBRSxtQkFBbUIsRUFBd0IsTUFBTSxvQkFBb0IsQ0FBQztBQUMvRSxPQUFPLEVBQUUsUUFBUSxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsT0FBTyxJQUFJLFlBQVksRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQzNGLE9BQU8sRUFBRSxHQUFHLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUM3QyxPQUFPLEVBQ0wsVUFBVSxHQUdYLE1BQU0sbUNBQW1DLENBQUM7QUFPM0MsTUFBTSxvQkFBb0IsR0FBRyxNQUFNLENBQUM7QUFDcEMsTUFBTSxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sQ0FBQywrQkFBK0IsQ0FBQyxDQUFDO0FBeUIzRCxvRUFBb0U7QUFDcEUsTUFBTSxPQUFPLHVCQUF1QjtJQUNqQixLQUFLLENBQVM7SUFDZCxTQUFTLENBQXFDO0lBRS9ELFlBQVksVUFBZ0MsRUFBRTtRQUM1QyxJQUFJLENBQUMsS0FBSyxHQUFHLFdBQVcsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDeEMsSUFBSSxDQUFDLFNBQVMsR0FBRyxPQUFPLENBQUMsU0FBUyxJQUFJLEVBQUUsQ0FBQztJQUMzQyxDQUFDO0lBRUQsS0FBSyxDQUFDLElBQUk7UUFDUixNQUFNLE9BQU8sR0FBRyxNQUFNLGVBQWUsRUFBRSxDQUFDO1FBQ3hDLE1BQU0sQ0FBQyxLQUFLLENBQUMsbUJBQW1CLEVBQUUsRUFBRSxJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUksRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDN0UsTUFBTSxTQUFTLEdBQUcsTUFBTSxZQUFZLENBQUMsb0JBQW9CLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsSUFB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bnQiOlsiLyoqXG4gKiBSZXF1ZXN0LXNjb3BlZCBEYXRhYnJpY2tzIG1vZGVsIGRpc2NvdmVyeSBmb3IgdGhlIEFwcEtpdCBnYXRld2F5LlxuICpcbiAqIEBtb2R1bGVcbiAqL1xuXG5pbXBvcnQgeyBnZXRFeGVjdXRpb25Db250ZXh0LCB0eXBlIFdvcmtzcGFjZUNsaWVudCB9IGZyb20gXCJAZGF0YWJyaWNrcy9hcHBraXRcIjtcbmltcG9ydCB7IG1ldGFkYXRhLCBtb2RlbENhdGFsb2csIHBvbGljeSwgcmVzb2x2ZSBhcyBtb2RlbFJlc29sdmUgfSBmcm9tIFwiQGRieC10b29scy9tb2RlbFwiO1xuaW1wb3J0IHsgbG9nIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7XG4gIE1vZGVsQ2xhc3MsXG4gIHR5cGUgUmVzb2x2ZU1vZGVsSW5wdXQsXG4gIHR5cGUgU2VydmluZ0VuZHBvaW50U3VtbWFyeSxcbn0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLW1vZGVsL2NvbnRyYWN0c1wiO1xuaW1wb3J0IHR5cGUge1xuICBNb2RlbENhcGFiaWxpdGllcyxcbiAgTW9kZWxDYXBhYmlsaXR5T3ZlcnJpZGUsXG4gIE1vZGVsVGFyZ2V0LFxufSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtbW9kZWwtZ2F0ZXdheVwiO1xuXG5jb25zdCBERUZBVUxUX0NBQ0hFX1RUTF9NUyA9IDYwXzAwMDtcbmNvbnN0IGxvZ2dlciA9IGxvZy5sb2dnZXIoXCJhcHBraXQvbW9kZWwtZ2F0ZXdheS9yZWdpc3RyeVwiKTtcblxuLyoqIFJlc29sdXRpb24gY29udHJvbHMgcGFzc2VkIHRocm91Z2ggdG8gdGhlIG1vZGVsIHBvbGljeSBvd25lci4gKi9cbmV4cG9ydCB0eXBlIE1vZGVsUmVnaXN0cnlSZXNvbHZlT3B0aW9ucyA9IFBpY2s8UmVzb2x2ZU1vZGVsSW5wdXQsIFwibW9kZWxDbGFzc1wiIHwgXCJyZXF1aXJlc1Rvb2xzXCI+O1xuXG4vKiogRHluYW1pYyBtb2RlbCBjYXRhbG9ndWUgdXNlZCBieSByZXF1ZXN0IHJvdXRpbmcgYW5kIG1vZGVsLWxpc3QgcmVzcG9uc2VzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBNb2RlbFJlZ2lzdHJ5IHtcbiAgbGlzdCgpOiBQcm9taXNlPE1vZGVsVGFyZ2V0W10+O1xuICBzZWFyY2gocXVlcnk6IHN0cmluZyk6IFByb21pc2U8TW9kZWxUYXJnZXRbXT47XG4gIHJlc29sdmUobW9kZWw6IHN0cmluZywgb3B0aW9ucz86IE1vZGVsUmVnaXN0cnlSZXNvbHZlT3B0aW9ucyk6IFByb21pc2U8TW9kZWxUYXJnZXQgfCB1bmRlZmluZWQ+O1xuICByZWZyZXNoKCk6IFByb21pc2U8dm9pZD47XG59XG5cbi8qKiBDb25maWd1cmF0aW9uIGZvciB7QGxpbmsgRGF0YWJyaWNrc01vZGVsUmVnaXN0cnl9LiAqL1xuZXhwb3J0IGludGVyZmFjZSBNb2RlbFJlZ2lzdHJ5T3B0aW9ucyB7XG4gIHJlYWRvbmx5IHR0bE1zPzogbnVtYmVyO1xuICByZWFkb25seSBvdmVycmlkZXM/OiByZWFkb25seSBNb2RlbENhcGFiaWxpdHlPdmVycmlkZVtdO1xufVxuXG5pbnRlcmZhY2UgUmVnaXN0cnlDb250ZXh0IHtcbiAgcmVhZG9ubHkgY2xpZW50OiBXb3Jrc3BhY2VDbGllbnQ7XG4gIHJlYWRvbmx5IGhvc3Q6IHN0cmluZztcbiAgcmVhZG9ubHkgaWRlbnRpdHk6IHN0cmluZztcbn1cblxuLyoqIE1vZGVsIHJlZ2lzdHJ5IGJhY2tlZCBieSB0aGUgYWN0aXZlIEFwcEtpdCBleGVjdXRpb24gY29udGV4dC4gKi9cbmV4cG9ydCBjbGFzcyBEYXRhYnJpY2tzTW9kZWxSZWdpc3RyeSBpbXBsZW1lbnRzIE1vZGVsUmVnaXN0cnkge1xuICBwcml2YXRlIHJlYWRvbmx5IHR0bE1zOiBudW1iZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgb3ZlcnJpZGVzOiByZWFkb25seSBNb2RlbENhcGFiaWxpdHlPdmVycmlkZVtdO1xuXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IE1vZGVsUmVnaXN0cnlPcHRpb25zID0ge30pIHtcbiAgICB0aGlzLnR0bE1zID0gcG9zaXRpdmVUdGwob3B0aW9ucy50dGxNcyk7XG4gICAgdGhpcy5vdmVycmlkZXMgPSBvcHRpb25zLm92ZXJyaWRlcyA/PyBbXTtcbiAgfVxuXG4gIGFzeW5jIGxpc3QoKTogUHJvbWlzZTxNb2RlbFRhcmdldFtdPiB7XG4gICAgY29uc3QgY29udGV4dCA9IGF3YWl0IHJlZ2lzdHJ5Q29udGV4dCgpO1xuICAgIGxvZ2dlci5kZWJ1ZyhcImxvYWRpbmcgY2F0YWxvZ3VlXCIsIHsgaG9zdDogY29udGV4dC5ob3N0LCB0dGxNczogdGhpcy50dGxNcyB9KTtcbiAgICBjb25zdCBlbmRwb2ludHMgPSBhd2FpdCBtb2RlbENhdGFsb2cubGlzdFNlcnZpbmdFbmRwb2ludHMoY29udGV4dC5jbGllbnQsIGNvbnRleHQuaG9zdCwge1xuICAgICAgY2FjaGVJZGVudGl0eTogY29udGV4dC5pZGVudGl0eSxcbiAgICAgIHR0bE1zOiB0aGlzLnR0bE1zLFxuICAgIH0pO1xuICAgIGNvbnN0IHRhcmdldHMgPSBlbmRwb2ludHMubWFwKChlbmRwb2ludCkgPT4gdGhpcy50YXJnZXQoZW5kcG9pbnQpKTtcbiAgICBsb2dnZXIuZGVidWcoXCJsb2FkZWQgY2F0YWxvZ3VlXCIsIHtcbiAgICAgIGVuZHBvaW50Q291bnQ6IGVuZHBvaW50cy5sZW5ndGgsXG4gICAgICBob3N0OiBjb250ZXh0Lmhvc3QsXG4gICAgICB0YXJnZXRDb3VudDogdGFyZ2V0cy5sZW5ndGgsXG4gICAgfSk7XG4gICAgcmV0dXJuIHRhcmdldHM7XG4gIH1cblxuICBhc3luYyByZXNvbHZlKFxuICAgIG1vZGVsOiBzdHJpbmcsXG4gICAgb3B0aW9uczogTW9kZWxSZWdpc3RyeVJlc29sdmVPcHRpb25zID0ge30sXG4gICk6IFByb21pc2U8TW9kZWxUYXJnZXQgfCB1bmRlZmluZWQ+IHtcbiAgICBjb25zdCByZXF1ZXN0ZWQgPSB1bnF1YWxpZmllZE1vZGVsKG1vZGVsKTtcbiAgICBjb25zdCB0YXJnZXRzID0gYXdhaXQgdGhpcy5saXN0KCk7XG4gICAgY29uc3QgZXhhY3QgPSB0YXJnZXRzLmZpbmQoKHRhcmdldCkgPT5cbiAgICAgIHRhcmdldC5hbGlhc2VzLnNvbWUoXG4gICAgICAgIChhbGlhcykgPT4gYWxpYXMubG9jYWxlQ29tcGFyZShyZXF1ZXN0ZWQsIHVuZGVmaW5lZCwgeyBzZW5zaXRpdml0eTogXCJhY2NlbnRcIiB9KSA9PT0gMCxcbiAgICAgICksXG4gICAgKTtcbiAgICBpZiAoZXhhY3QgJiYgbWF0Y2hlc1Jlc29sdmVPcHRpb25zKGV4YWN0LCBvcHRpb25zKSkge1xuICAgICAgbG9nZ2VyLmRlYnVnKFwicmVzb2x2ZWQgZXhhY3QgbW9kZWxcIiwgeyByZXF1ZXN0ZWQsIHJlc29sdmVkOiBleGFjdC5pZCB9KTtcbiAgICAgIHJldHVybiBleGFjdDtcbiAgICB9XG5cbiAgICBjb25zdCBlbmRwb2ludHMgPSB0YXJnZXRzXG4gICAgICAubWFwKCh0YXJnZXQpID0+IHRhcmdldC5lbmRwb2ludClcbiAgICAgIC5maWx0ZXIoKGVuZHBvaW50KTogZW5kcG9pbnQgaXMgU2VydmluZ0VuZHBvaW50U3VtbWFyeSA9PiBlbmRwb2ludCAhPT0gdW5kZWZpbmVkKTtcbiAgICBjb25zdCByZXNvbHZlZCA9IG1vZGVsUmVzb2x2ZS5yZXNvbHZlTW9kZWwoZW5kcG9pbnRzLCB7XG4gICAgICBleHBsaWNpdDogcmVxdWVzdGVkLFxuICAgICAgLi4ub3B0aW9ucyxcbiAgICB9KTtcbiAgICBjb25zdCB0YXJnZXQgPSB0YXJnZXRzLmZpbmQoKGNhbmRpZGF0ZSkgPT4gY2FuZGlkYXRlLmlkID09PSByZXNvbHZlZC5tb2RlbElkKTtcbiAgICBsb2dnZXIuZGVidWcoXCJyZXNvbHZlZCBmdXp6eSBtb2RlbFwiLCB7XG4gICAgICByZXF1ZXN0ZWQsXG4gICAgICByZXNvbHZlZDogdGFyZ2V0Py5pZCxcbiAgICAgIHNvdXJjZTogcmVzb2x2ZWQuc291cmNlLFxuICAgIH0pO1xuICAgIHJldHVybiB0YXJnZXQ7XG4gIH1cblxuICBhc3luYyBzZWFyY2gocXVlcnk6IHN0cmluZyk6IFByb21pc2U8TW9kZWxUYXJnZXRbXT4ge1xuICAgIGNvbnN0IHRhcmdldHMgPSBhd2FpdCB0aGlzLmxpc3QoKTtcbiAgICBjb25zdCBieUlkID0gbmV3IE1hcCh0YXJnZXRzLm1hcCgodGFyZ2V0KSA9PiBbdGFyZ2V0LmlkLCB0YXJnZXRdKSk7XG4gICAgY29uc3QgZW5kcG9pbnRzID0gdGFyZ2V0c1xuICAgICAgLm1hcCgodGFyZ2V0KSA9PiB0YXJnZXQuZW5kcG9pbnQpXG4gICAgICAuZmlsdGVyKChlbmRwb2ludCk6IGVuZHBvaW50IGlzIFNlcnZpbmdFbmRwb2ludFN1bW1hcnkgPT4gZW5kcG9pbnQgIT09IHVuZGVmaW5lZCk7XG4gICAgY29uc3QgcmFua2VkID0gW1xuICAgICAgLi4ubW9kZWxSZXNvbHZlLmxvb2t1cE1vZGVscyhlbmRwb2ludHMsIHsgc2VhcmNoOiBxdWVyeSB9KSxcbiAgICAgIC4uLm1vZGVsUmVzb2x2ZS5sb29rdXBNb2RlbHMoZW5kcG9pbnRzLCB7XG4gICAgICAgIHNlYXJjaDogcXVlcnksXG4gICAgICAgIG1vZGVsQ2xhc3M6IE1vZGVsQ2xhc3MuRW1iZWRkaW5nLFxuICAgICAgfSksXG4gICAgXS5zb3J0KChsZWZ0LCByaWdodCkgPT4gKGxlZnQuc2NvcmUgPz8gMCkgLSAocmlnaHQuc2NvcmUgPz8gMCkpO1xuICAgIHJldHVybiByYW5rZWRcbiAgICAgIC5tYXAoKHsgZW5kcG9pbnQgfSkgPT4gYnlJZC5nZXQoZW5kcG9pbnQubmFtZSkpXG4gICAgICAuZmlsdGVyKCh0YXJnZXQpOiB0YXJnZXQgaXMgTW9kZWxUYXJnZXQgPT4gdGFyZ2V0ICE9PSB1bmRlZmluZWQpXG4gICAgICAuZmlsdGVyKFxuICAgICAgICAodGFyZ2V0LCBpbmRleCwgYWxsKSA9PiBhbGwuZmluZEluZGV4KChjYW5kaWRhdGUpID0+IGNhbmRpZGF0ZS5pZCA9PT0gdGFyZ2V0LmlkKSA9PT0gaW5kZXgsXG4gICAgICApO1xuICB9XG5cbiAgYXN5bmMgcmVmcmVzaCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBjb250ZXh0ID0gYXdhaXQgcmVnaXN0cnlDb250ZXh0KCk7XG4gICAgbG9nZ2VyLmRlYnVnKFwiY2xlYXJpbmcgY2F0YWxvZ3VlXCIsIHsgaG9zdDogY29udGV4dC5ob3N0IH0pO1xuICAgIGF3YWl0IG1vZGVsQ2F0YWxvZy5jbGVhclNlcnZpbmdFbmRwb2ludHNDYWNoZShjb250ZXh0Lmhvc3QsIGNvbnRleHQuaWRlbnRpdHkpO1xuICAgIGF3YWl0IG1vZGVsQ2F0YWxvZy5saXN0U2VydmluZ0VuZHBvaW50cyhjb250ZXh0LmNsaWVudCwgY29udGV4dC5ob3N0LCB7XG4gICAgICBjYWNoZUlkZW50aXR5OiBjb250ZXh0LmlkZW50aXR5LFxuICAgICAgdHRsTXM6IHRoaXMudHRsTXMsXG4gICAgfSk7XG4gICAgbG9nZ2VyLmRlYnVnKFwicmVmcmVzaGVkIGNhdGFsb2d1ZVwiLCB7IGhvc3Q6IGNvbnRleHQuaG9zdCB9KTtcbiAgfVxuXG4gIHByaXZhdGUgdGFyZ2V0KGVuZHBvaW50OiBTZXJ2aW5nRW5kcG9pbnRTdW1tYXJ5KTogTW9kZWxUYXJnZXQge1xuICAgIGNvbnN0IHB1Ymxpc2hlZCA9IG1ldGFkYXRhLm1vZGVsQ2FwYWJpbGl0aWVzRm9yKGVuZHBvaW50KTtcbiAgICBjb25zdCBmYW1pbHkgPSBlbmRwb2ludC5mYW1pbHk/LnRvTG93ZXJDYXNlKCk7XG4gICAgY29uc3Qgb3BlbkFpRmFtaWx5ID0gZmFtaWx5ID09PSBcImdwdFwiIHx8IGZhbWlseSA9PT0gXCJvcGVuYWlcIiB8fCBlbmRwb2ludC5uYW1lLmluY2x1ZGVzKFwiY29kZXhcIik7XG4gICAgY29uc3QgbW9kZWxTZXJ2aWNlTmFtZSA9IG5vcm1hbGl6ZWRNb2RlbFNlcnZpY2VOYW1lKGVuZHBvaW50Lm1vZGVsU2VydmljZU5hbWUpO1xuICAgIGNvbnN0IGVtYmVkZGluZ3MgPVxuICAgICAgZW5kcG9pbnQuY2xhc3MgPT09IE1vZGVsQ2xhc3MuRW1iZWRkaW5nIHx8IGVuZHBvaW50LnRhc2sgPT09IFwibGxtL3YxL2VtYmVkZGluZ3NcIjtcbiAgICBjb25zdCBjYXBhYmlsaXRpZXM6IE1vZGVsQ2FwYWJpbGl0aWVzID0ge1xuICAgICAgcmVzcG9uc2VzOiAhZW1iZWRkaW5ncyAmJiAob3BlbkFpRmFtaWx5IHx8IHB1Ymxpc2hlZC5yZXNwb25zZXMpLFxuICAgICAgb3BlblJlc3BvbnNlczogIWVtYmVkZGluZ3MgJiYgIW9wZW5BaUZhbWlseSxcbiAgICAgIGNoYXQ6ICFlbWJlZGRpbmdzLFxuICAgICAgYW50aHJvcGljOiBmYW1pbHkgPT09IFwiY2xhdWRlXCIsXG4gICAgICBlbWJlZGRpbmdzLFxuICAgICAgYWlHYXRld2F5Q29kZXg6XG4gICAgICAgICFlbWJlZGRpbmdzICYmIEJvb2xlYW4obW9kZWxTZXJ2aWNlTmFtZSkgJiYgZmFtaWx5ICE9PSBcImNsYXVkZVwiICYmIGZhbWlseSAhPT0gXCJnZW1pbmlcIixcbiAgICAgIHRvb2xzOiBlbmRwb2ludC5zdXBwb3J0c1Rvb2xzID09PSB0cnVlLFxuICAgICAgcmVhc29uaW5nOiBwb2xpY3kubW9kZWxSZWFzb25pbmdFZmZvcnRzKGVuZHBvaW50Lm5hbWUpLmxlbmd0aCA+IDAsXG4gICAgICBzdHJlYW1pbmc6IHRydWUsXG4gICAgICBwYXJhbGxlbFRvb2xzOiBlbmRwb2ludC5zdXBwb3J0c1Rvb2xzID09PSB0cnVlLFxuICAgICAgY3VzdG9tVG9vbHM6IHB1Ymxpc2hlZC5hcHBseVBhdGNoIHx8IGVuZHBvaW50Lm5hbWUuaW5jbHVkZXMoXCJjb2RleFwiKSxcbiAgICAgIHN0cnVjdHVyZWRPdXRwdXQ6IHRydWUsXG4gICAgICB3ZWJTZWFyY2g6IHB1Ymxpc2hlZC53ZWJTZWFyY2gsXG4gICAgfTtcbiAgICBjb25zdCBhbGlhc2VzID0gbmV3IFNldChcbiAgICAgIFtcbiAgICAgICAgZW5kcG9pbnQubmFtZSxcbiAgICAgICAgZW5kcG9pbnQuZGlzcGxheU5hbWUsXG4gICAgICAgIGVuZHBvaW50Lm1vZGVsU2VydmljZU5hbWUsXG4gICAgICAgIG1vZGVsU2VydmljZU5hbWUsXG4gICAgICAgIC4uLk9iamVjdC52YWx1ZXMoZW5kcG9pbnQuc2VydmljZU5hbWVzID8/IHt9KSxcbiAgICAgIF0uZmlsdGVyKCh2YWx1ZSk6IHZhbHVlIGlzIHN0cmluZyA9PiBCb29sZWFuKHZhbHVlPy50cmltKCkpKSxcbiAgICApO1xuICAgIGNvbnN0IG92ZXJyaWRlID0gdGhpcy5vdmVycmlkZXMuZmluZChcbiAgICAgIChjYW5kaWRhdGUpID0+XG4gICAgICAgIGNhbmRpZGF0ZS5tb2RlbCA9PT0gZW5kcG9pbnQubmFtZSB8fFxuICAgICAgICBbLi4uYWxpYXNlc10uc29tZSgoYWxpYXMpID0+IGFsaWFzID09PSBjYW5kaWRhdGUubW9kZWwpLFxuICAgICk7XG4gICAgcmV0dXJuIHtcbiAgICAgIGlkOiBlbmRwb2ludC5uYW1lLFxuICAgICAgYWxpYXNlczogWy4uLmFsaWFzZXNdLFxuICAgICAgZGlzcGxheU5hbWU6IGVuZHBvaW50LmRpc3BsYXlOYW1lID8/IGVuZHBvaW50Lm5hbWUsXG4gICAgICAuLi4oZW5kcG9pbnQuZmFtaWx5ID8geyBmYW1pbHk6IGVuZHBvaW50LmZhbWlseSB9IDoge30pLFxuICAgICAgLi4uKG1vZGVsU2VydmljZU5hbWUgPyB7IG1vZGVsU2VydmljZU5hbWUgfSA6IHt9KSxcbiAgICAgIGVuZHBvaW50LFxuICAgICAgY2FwYWJpbGl0aWVzOiB7IC4uLmNhcGFiaWxpdGllcywgLi4ub3ZlcnJpZGU/LmNhcGFiaWxpdGllcyB9LFxuICAgICAgcmVhc29uaW5nRWZmb3J0czogZW5kcG9pbnQucmVhc29uaW5nRWZmb3J0cyA/PyBbXSxcbiAgICB9O1xuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlZ2lzdHJ5Q29udGV4dCgpOiBQcm9taXNlPFJlZ2lzdHJ5Q29udGV4dD4ge1xuICBjb25zdCBjb250ZXh0ID0gZ2V0RXhlY3V0aW9uQ29udGV4dCgpO1xuICBjb25zdCBob3N0ID0gKGF3YWl0IGNvbnRleHQuY2xpZW50LmNvbmZpZy5nZXRIb3N0KCkpLnRvU3RyaW5nKCk7XG4gIHJldHVybiB7XG4gICAgY2xpZW50OiBjb250ZXh0LmNsaWVudCxcbiAgICBob3N0LFxuICAgIGlkZW50aXR5OiBcInVzZXJJZFwiIGluIGNvbnRleHQgPyBjb250ZXh0LnVzZXJJZCA6IGNvbnRleHQuc2VydmljZVVzZXJJZCxcbiAgfTtcbn1cblxuZnVuY3Rpb24gdW5xdWFsaWZpZWRNb2RlbChtb2RlbDogc3RyaW5nKTogc3RyaW5nIHtcbiAgcmV0dXJuIG1vZGVsLnRyaW0oKS5yZXBsYWNlKC9eKD86ZGJ4fGRhdGFicmlja3MpXFwvL2ksIFwiXCIpO1xufVxuXG5mdW5jdGlvbiBwb3NpdGl2ZVR0bCh2YWx1ZSA9IERFRkFVTFRfQ0FDSEVfVFRMX01TKTogbnVtYmVyIHtcbiAgaWYgKCFOdW1iZXIuaXNGaW5pdGUodmFsdWUpIHx8IHZhbHVlIDw9IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJNb2RlbCByZWdpc3RyeSB0dGxNcyBtdXN0IGJlIGEgcG9zaXRpdmUgZmluaXRlIG51bWJlclwiKTtcbiAgfVxuICByZXR1cm4gdmFsdWU7XG59XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZWRNb2RlbFNlcnZpY2VOYW1lKHZhbHVlOiBzdHJpbmcgfCB1bmRlZmluZWQpOiBzdHJpbmcgfCB1bmRlZmluZWQge1xuICBjb25zdCBub3JtYWxpemVkID0gdmFsdWU/LnRyaW0oKS5yZXBsYWNlKC9eZGF0YWJyaWNrc1xcLy8sIFwiXCIpO1xuICBpZiAoIW5vcm1hbGl6ZWQpIHJldHVybiB1bmRlZmluZWQ7XG4gIGlmIChub3JtYWxpemVkLnN0YXJ0c1dpdGgoXCJzeXN0ZW0uYWkuZGF0YWJyaWNrcy1cIikpIHtcbiAgICByZXR1cm4gYHN5c3RlbS5haS4ke25vcm1hbGl6ZWQuc2xpY2UoXCJzeXN0ZW0uYWkuZGF0YWJyaWNrcy1cIi5sZW5ndGgpfWA7XG4gIH1cbiAgaWYgKG5vcm1hbGl6ZWQuc3RhcnRzV2l0aChcImRhdGFicmlja3MtXCIpKSB7XG4gICAgcmV0dXJuIGBzeXN0ZW0uYWkuJHtub3JtYWxpemVkLnNsaWNlKFwiZGF0YWJyaWNrcy1cIi5sZW5ndGgpfWA7XG4gIH1cbiAgcmV0dXJuIG5vcm1hbGl6ZWQ7XG59XG5cbmZ1bmN0aW9uIG1hdGNoZXNSZXNvbHZlT3B0aW9ucyh0YXJnZXQ6IE1vZGVsVGFyZ2V0LCBvcHRpb25zOiBNb2RlbFJlZ2lzdHJ5UmVzb2x2ZU9wdGlvbnMpOiBib29sZWFuIHtcbiAgaWYgKG9wdGlvbnMucmVxdWlyZXNUb29scyAmJiAhdGFyZ2V0LmNhcGFiaWxpdGllcy50b29scykgcmV0dXJuIGZhbHNlO1xuICBpZiAob3B0aW9ucy5tb2RlbENsYXNzID09PSBNb2RlbENsYXNzLkVtYmVkZGluZykgcmV0dXJuIHRhcmdldC5jYXBhYmlsaXRpZXMuZW1iZWRkaW5ncztcbiAgaWYgKG9wdGlvbnMubW9kZWxDbGFzcyAhPT0gdW5kZWZpbmVkKSByZXR1cm4gdGFyZ2V0LmNhcGFiaWxpdGllcy5jaGF0O1xuICByZXR1cm4gdHJ1ZTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure capability-driven route selection for model-gateway requests.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import type { GatewayRoute, RequestedFeatures, ResolveRouteInput } from "@dbx-tools/shared-model-gateway";
|
|
7
|
+
/** Error returned when preserving a requested protocol feature is impossible. */
|
|
8
|
+
export declare class UnsupportedGatewayFeatureError extends Error {
|
|
9
|
+
readonly features: readonly string[];
|
|
10
|
+
readonly status = 400;
|
|
11
|
+
constructor(features: readonly string[]);
|
|
12
|
+
}
|
|
13
|
+
/** Select the lowest-overhead upstream that preserves the client contract. */
|
|
14
|
+
export declare function resolveRoute(input: ResolveRouteInput): GatewayRoute;
|
|
15
|
+
/** Detect route-affecting features from an OpenAI or Anthropic request body. */
|
|
16
|
+
export declare function requestedFeatures(body: Readonly<Record<string, unknown>>): RequestedFeatures;
|
|
17
|
+
/** Return whether an Originator header selects Codex compatibility behavior. */
|
|
18
|
+
export declare function isCodexOriginator(originator: string | undefined): boolean;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure capability-driven route selection for model-gateway requests.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
/** Error returned when preserving a requested protocol feature is impossible. */
|
|
7
|
+
export class UnsupportedGatewayFeatureError extends Error {
|
|
8
|
+
features;
|
|
9
|
+
status = 400;
|
|
10
|
+
constructor(features) {
|
|
11
|
+
super(`The selected model cannot preserve requested features: ${features.join(", ")}`);
|
|
12
|
+
this.features = features;
|
|
13
|
+
this.name = "UnsupportedGatewayFeatureError";
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/** Select the lowest-overhead upstream that preserves the client contract. */
|
|
17
|
+
export function resolveRoute(input) {
|
|
18
|
+
const { clientProtocol, requestedModel, features, target } = input;
|
|
19
|
+
if (clientProtocol === "openai-embeddings") {
|
|
20
|
+
if (!target.capabilities.embeddings) {
|
|
21
|
+
throw new UnsupportedGatewayFeatureError(["embeddings"]);
|
|
22
|
+
}
|
|
23
|
+
return directRoute(input, "databricks-embeddings", target.id);
|
|
24
|
+
}
|
|
25
|
+
if (clientProtocol === "openai-responses") {
|
|
26
|
+
rejectStatefulResponses(features);
|
|
27
|
+
if (isCodexOriginator(input.originator) &&
|
|
28
|
+
targetsModelService(requestedModel, target) &&
|
|
29
|
+
target.capabilities.aiGatewayCodex &&
|
|
30
|
+
supportsDirectResponses(target, features)) {
|
|
31
|
+
return directRoute(input, "databricks-ai-gateway-codex", target.modelServiceName);
|
|
32
|
+
}
|
|
33
|
+
if (target.capabilities.responses && supportsDirectResponses(target, features)) {
|
|
34
|
+
return directRoute(input, "databricks-responses", target.id);
|
|
35
|
+
}
|
|
36
|
+
if (target.capabilities.aiGatewayCodex &&
|
|
37
|
+
target.modelServiceName &&
|
|
38
|
+
supportsDirectResponses(target, features)) {
|
|
39
|
+
return directRoute(input, "databricks-ai-gateway-codex", target.modelServiceName);
|
|
40
|
+
}
|
|
41
|
+
if (target.capabilities.openResponses && supportsOpenResponses(target, features)) {
|
|
42
|
+
return directRoute(input, "databricks-open-responses", target.id);
|
|
43
|
+
}
|
|
44
|
+
return translatedRoute(input);
|
|
45
|
+
}
|
|
46
|
+
if (clientProtocol === "openai-chat") {
|
|
47
|
+
if (target.capabilities.chat && supportsTools(target, features)) {
|
|
48
|
+
return directRoute(input, "databricks-chat", target.id);
|
|
49
|
+
}
|
|
50
|
+
return translatedRoute(input);
|
|
51
|
+
}
|
|
52
|
+
if (target.capabilities.anthropic && supportsTools(target, features)) {
|
|
53
|
+
return directRoute(input, "databricks-anthropic", target.id);
|
|
54
|
+
}
|
|
55
|
+
return translatedRoute(input);
|
|
56
|
+
}
|
|
57
|
+
/** Detect route-affecting features from an OpenAI or Anthropic request body. */
|
|
58
|
+
export function requestedFeatures(body) {
|
|
59
|
+
const tools = Array.isArray(body.tools) ? body.tools : [];
|
|
60
|
+
const toolTypes = tools
|
|
61
|
+
.filter((tool) => isRecord(tool))
|
|
62
|
+
.map((tool) => tool.type);
|
|
63
|
+
const text = isRecord(body.text) ? body.text : {};
|
|
64
|
+
const format = isRecord(text.format) ? text.format.type : text.format;
|
|
65
|
+
return {
|
|
66
|
+
background: body.background === true,
|
|
67
|
+
customTools: toolTypes.some((type) => type === "custom"),
|
|
68
|
+
parallelTools: body.parallel_tool_calls === true,
|
|
69
|
+
previousResponse: typeof body.previous_response_id === "string" && body.previous_response_id.length > 0,
|
|
70
|
+
reasoning: isRecord(body.reasoning) || body.reasoning_effort !== undefined,
|
|
71
|
+
storage: body.store === true,
|
|
72
|
+
structuredOutput: format !== undefined && format !== "text",
|
|
73
|
+
tools: tools.length > 0,
|
|
74
|
+
unsupportedOpenResponsesTools: toolTypes.some((type) => type !== "function" && type !== "web_search" && type !== "web_search_preview"),
|
|
75
|
+
webSearch: toolTypes.some((type) => type === "web_search" || type === "web_search_preview"),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/** Return whether an Originator header selects Codex compatibility behavior. */
|
|
79
|
+
export function isCodexOriginator(originator) {
|
|
80
|
+
return originator?.toLowerCase().includes("codex") === true;
|
|
81
|
+
}
|
|
82
|
+
function directRoute(input, upstreamProtocol, upstreamModel) {
|
|
83
|
+
return {
|
|
84
|
+
clientProtocol: input.clientProtocol,
|
|
85
|
+
upstreamProtocol,
|
|
86
|
+
target: input.target,
|
|
87
|
+
upstreamModel,
|
|
88
|
+
translateRequest: false,
|
|
89
|
+
translateResponse: false,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
function translatedRoute(input) {
|
|
93
|
+
return {
|
|
94
|
+
clientProtocol: input.clientProtocol,
|
|
95
|
+
upstreamProtocol: "ai-sdk",
|
|
96
|
+
target: input.target,
|
|
97
|
+
upstreamModel: input.target.id,
|
|
98
|
+
translateRequest: true,
|
|
99
|
+
translateResponse: true,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function supportsDirectResponses(target, features) {
|
|
103
|
+
return (supportsTools(target, features) &&
|
|
104
|
+
(!features.customTools || target.capabilities.customTools) &&
|
|
105
|
+
(!features.structuredOutput || target.capabilities.structuredOutput));
|
|
106
|
+
}
|
|
107
|
+
function supportsOpenResponses(target, features) {
|
|
108
|
+
return (supportsTools(target, features) &&
|
|
109
|
+
!features.customTools &&
|
|
110
|
+
!features.previousResponse &&
|
|
111
|
+
!features.storage &&
|
|
112
|
+
!features.background &&
|
|
113
|
+
!features.unsupportedOpenResponsesTools &&
|
|
114
|
+
(!features.webSearch || target.capabilities.webSearch) &&
|
|
115
|
+
(!features.structuredOutput || target.capabilities.structuredOutput));
|
|
116
|
+
}
|
|
117
|
+
function supportsTools(target, features) {
|
|
118
|
+
return ((!features.tools || target.capabilities.tools) &&
|
|
119
|
+
(!features.parallelTools || target.capabilities.parallelTools));
|
|
120
|
+
}
|
|
121
|
+
function rejectStatefulResponses(features) {
|
|
122
|
+
const unsupported = [
|
|
123
|
+
...(features.previousResponse ? ["previous_response_id"] : []),
|
|
124
|
+
...(features.storage ? ["store"] : []),
|
|
125
|
+
...(features.background ? ["background"] : []),
|
|
126
|
+
];
|
|
127
|
+
if (unsupported.length > 0)
|
|
128
|
+
throw new UnsupportedGatewayFeatureError(unsupported);
|
|
129
|
+
}
|
|
130
|
+
function targetsModelService(requestedModel, target) {
|
|
131
|
+
if (!target.modelServiceName)
|
|
132
|
+
return false;
|
|
133
|
+
const unqualified = requestedModel.trim().replace(/^(?:dbx|databricks)\//i, "");
|
|
134
|
+
return unqualified === target.modelServiceName;
|
|
135
|
+
}
|
|
136
|
+
function isRecord(value) {
|
|
137
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3JvdXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7OztHQUlHO0FBVUgsaUZBQWlGO0FBQ2pGLE1BQU0sT0FBTyw4QkFBK0IsU0FBUSxLQUFLO0lBR2xDO0lBRlosTUFBTSxHQUFHLEdBQUcsQ0FBQztJQUV0QixZQUFxQixRQUEyQjtRQUM5QyxLQUFLLENBQUMsMERBQTBELFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBRHBFLGFBQVEsR0FBUixRQUFRLENBQW1CO1FBRTlDLElBQUksQ0FBQyxJQUFJLEdBQUcsZ0NBQWdDLENBQUM7SUFDL0MsQ0FBQztDQUNGO0FBRUQsOEVBQThFO0FBQzlFLE1BQU0sVUFBVSxZQUFZLENBQUMsS0FBd0I7SUFDbkQsTUFBTSxFQUFFLGNBQWMsRUFBRSxjQUFjLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQztJQUNuRSxJQUFJLGNBQWMsS0FBSyxtQkFBbUIsRUFBRSxDQUFDO1FBQzNDLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLFVBQVUsRUFBRSxDQUFDO1lBQ3BDLE1BQU0sSUFBSSw4QkFBOEIsQ0FBQyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUM7UUFDM0QsQ0FBQztRQUNELE9BQU8sV0FBVyxDQUFDLEtBQUssRUFBRSx1QkFBdUIsRUFBRSxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDaEUsQ0FBQztJQUNELElBQUksY0FBYyxLQUFLLGtCQUFrQixFQUFFLENBQUM7UUFDMUMsdUJBQXVCLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDbEMsSUFDRSxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDO1lBQ25DLG1CQUFtQixDQUFDLGNBQWMsRUFBRSxNQUFNLENBQUM7WUFDM0MsTUFBTSxDQUFDLFlBQVksQ0FBQyxjQUFjO1lBQ2xDLHVCQUF1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LFFBQVEsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDOUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogUHVyZSBjYXBhYmlsaXR5LWRyaXZlbiByb3V0ZSBzZWxlY3Rpb24gZm9yIG1vZGVsLWdhdGV3YXkgcmVxdWVzdHMuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB0eXBlIHtcbiAgR2F0ZXdheVJvdXRlLFxuICBNb2RlbFRhcmdldCxcbiAgUmVxdWVzdGVkRmVhdHVyZXMsXG4gIFJlc29sdmVSb3V0ZUlucHV0LFxuICBVcHN0cmVhbVByb3RvY29sLFxufSBmcm9tIFwiQGRieC10b29scy9zaGFyZWQtbW9kZWwtZ2F0ZXdheVwiO1xuXG4vKiogRXJyb3IgcmV0dXJuZWQgd2hlbiBwcmVzZXJ2aW5nIGEgcmVxdWVzdGVkIHByb3RvY29sIGZlYXR1cmUgaXMgaW1wb3NzaWJsZS4gKi9cbmV4cG9ydCBjbGFzcyBVbnN1cHBvcnRlZEdhdGV3YXlGZWF0dXJlRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gIHJlYWRvbmx5IHN0YXR1cyA9IDQwMDtcblxuICBjb25zdHJ1Y3RvcihyZWFkb25seSBmZWF0dXJlczogcmVhZG9ubHkgc3RyaW5nW10pIHtcbiAgICBzdXBlcihgVGhlIHNlbGVjdGVkIG1vZGVsIGNhbm5vdCBwcmVzZXJ2ZSByZXF1ZXN0ZWQgZmVhdHVyZXM6ICR7ZmVhdHVyZXMuam9pbihcIiwgXCIpfWApO1xuICAgIHRoaXMubmFtZSA9IFwiVW5zdXBwb3J0ZWRHYXRld2F5RmVhdHVyZUVycm9yXCI7XG4gIH1cbn1cblxuLyoqIFNlbGVjdCB0aGUgbG93ZXN0LW92ZXJoZWFkIHVwc3RyZWFtIHRoYXQgcHJlc2VydmVzIHRoZSBjbGllbnQgY29udHJhY3QuICovXG5leHBvcnQgZnVuY3Rpb24gcmVzb2x2ZVJvdXRlKGlucHV0OiBSZXNvbHZlUm91dGVJbnB1dCk6IEdhdGV3YXlSb3V0ZSB7XG4gIGNvbnN0IHsgY2xpZW50UHJvdG9jb2wsIHJlcXVlc3RlZE1vZGVsLCBmZWF0dXJlcywgdGFyZ2V0IH0gPSBpbnB1dDtcbiAgaWYgKGNsaWVudFByb3RvY29sID09PSBcIm9wZW5haS1lbWJlZGRpbmdzXCIpIHtcbiAgICBpZiAoIXRhcmdldC5jYXBhYmlsaXRpZXMuZW1iZWRkaW5ncykge1xuICAgICAgdGhyb3cgbmV3IFVuc3VwcG9ydGVkR2F0ZXdheUZlYXR1cmVFcnJvcihbXCJlbWJlZGRpbmdzXCJdKTtcbiAgICB9XG4gICAgcmV0dXJuIGRpcmVjdFJvdXRlKGlucHV0LCBcImRhdGFicmlja3MtZW1iZWRkaW5nc1wiLCB0YXJnZXQuaWQpO1xuICB9XG4gIGlmIChjbGllbnRQcm90b2NvbCA9PT0gXCJvcGVuYWktcmVzcG9uc2VzXCIpIHtcbiAgICByZWplY3RTdGF0ZWZ1bFJlc3BvbnNlcyhmZWF0dXJlcyk7XG4gICAgaWYgKFxuICAgICAgaXNDb2RleE9yaWdpbmF0b3IoaW5wdXQub3JpZ2luYXRvcikgJiZcbiAgICAgIHRhcmdldHNNb2RlbFNlcnZpY2UocmVxdWVzdGVkTW9kZWwsIHRhcmdldCkgJiZcbiAgICAgIHRhcmdldC5jYXBhYmlsaXRpZXMuYWlHYXRld2F5Q29kZXggJiZcbiAgICAgIHN1cHBvcnRzRGlyZWN0UmVzcG9uc2VzKHRhcmdldCwgZmVhdHVyZXMpXG4gICAgKSB7XG4gICAgICByZXR1cm4gZGlyZWN0Um91dGUoaW5wdXQsIFwiZGF0YWJyaWNrcy1haS1nYXRld2F5LWNvZGV4XCIsIHRhcmdldC5tb2RlbFNlcnZpY2VOYW1lISk7XG4gICAgfVxuICAgIGlmICh0YXJnZXQuY2FwYWJpbGl0aWVzLnJlc3BvbnNlcyAmJiBzdXBwb3J0c0RpcmVjdFJlc3BvbnNlcyh0YXJnZXQsIGZlYXR1cmVzKSkge1xuICAgICAgcmV0dXJuIGRpcmVjdFJvdXRlKGlucHV0LCBcImRhdGFicmlja3MtcmVzcG9uc2VzXCIsIHRhcmdldC5pZCk7XG4gICAgfVxuICAgIGlmIChcbiAgICAgIHRhcmdldC5jYXBhYmlsaXRpZXMuYWlHYXRld2F5Q29kZXggJiZcbiAgICAgIHRhcmdldC5tb2RlbFNlcnZpY2VOYW1lICYmXG4gICAgICBzdXBwb3J0c0RpcmVjdFJlc3BvbnNlcyh0YXJnZXQsIGZlYXR1cmVzKVxuICAgICkge1xuICAgICAgcmV0dXJuIGRpcmVjdFJvdXRlKGlucHV0LCBcImRhdGFicmlja3MtYWktZ2F0ZXdheS1jb2RleFwiLCB0YXJnZXQubW9kZWxTZXJ2aWNlTmFtZSk7XG4gICAgfVxuICAgIGlmICh0YXJnZXQuY2FwYWJpbGl0aWVzLm9wZW5SZXNwb25zZXMgJiYgc3VwcG9ydHNPcGVuUmVzcG9uc2VzKHRhcmdldCwgZmVhdHVyZXMpKSB7XG4gICAgICByZXR1cm4gZGlyZWN0Um91dGUoaW5wdXQsIFwiZGF0YWJyaWNrcy1vcGVuLXJlc3BvbnNlc1wiLCB0YXJnZXQuaWQpO1xuICAgIH1cbiAgICByZXR1cm4gdHJhbnNsYXRlZFJvdXRlKGlucHV0KTtcbiAgfVxuXG4gIGlmIChjbGllbnRQcm90b2NvbCA9PT0gXCJvcGVuYWktY2hhdFwiKSB7XG4gICAgaWYgKHRhcmdldC5jYXBhYmlsaXRpZXMuY2hhdCAmJiBzdXBwb3J0c1Rvb2xzKHRhcmdldCwgZmVhdHVyZXMpKSB7XG4gICAgICByZXR1cm4gZGlyZWN0Um91dGUoaW5wdXQsIFwiZGF0YWJyaWNrcy1jaGF0XCIsIHRhcmdldC5pZCk7XG4gICAgfVxuICAgIHJldHVybiB0cmFuc2xhdGVkUm91dGUoaW5wdXQpO1xuICB9XG5cbiAgaWYgKHRhcmdldC5jYXBhYmlsaXRpZXMuYW50aHJvcGljICYmIHN1cHBvcnRzVG9vbHModGFyZ2V0LCBmZWF0dXJlcykpIHtcbiAgICByZXR1cm4gZGlyZWN0Um91dGUoaW5wdXQsIFwiZGF0YWJyaWNrcy1hbnRocm9waWNcIiwgdGFyZ2V0LmlkKTtcbiAgfVxuICByZXR1cm4gdHJhbnNsYXRlZFJvdXRlKGlucHV0KTtcbn1cblxuLyoqIERldGVjdCByb3V0ZS1hZmZlY3RpbmcgZmVhdHVyZXMgZnJvbSBhbiBPcGVuQUkgb3IgQW50aHJvcGljIHJlcXVlc3QgYm9keS4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZXF1ZXN0ZWRGZWF0dXJlcyhib2R5OiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4pOiBSZXF1ZXN0ZWRGZWF0dXJlcyB7XG4gIGNvbnN0IHRvb2xzID0gQXJyYXkuaXNBcnJheShib2R5LnRvb2xzKSA/IGJvZHkudG9vbHMgOiBbXTtcbiAgY29uc3QgdG9vbFR5cGVzID0gdG9vbHNcbiAgICAuZmlsdGVyKCh0b29sKTogdG9vbCBpcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPiA9PiBpc1JlY29yZCh0b29sKSlcbiAgICAubWFwKCh0b29sKSA9PiB0b29sLnR5cGUpO1xuICBjb25zdCB0ZXh0ID0gaXNSZWNvcmQoYm9keS50ZXh0KSA/IGJvZHkudGV4dCA6IHt9O1xuICBjb25zdCBmb3JtYXQgPSBpc1JlY29yZCh0ZXh0LmZvcm1hdCkgPyB0ZXh0LmZvcm1hdC50eXBlIDogdGV4dC5mb3JtYXQ7XG4gIHJldHVybiB7XG4gICAgYmFja2dyb3VuZDogYm9keS5iYWNrZ3JvdW5kID09PSB0cnVlLFxuICAgIGN1c3RvbVRvb2xzOiB0b29sVHlwZXMuc29tZSgodHlwZSkgPT4gdHlwZSA9PT0gXCJjdXN0b21cIiksXG4gICAgcGFyYWxsZWxUb29sczogYm9keS5wYXJhbGxlbF90b29sX2NhbGxzID09PSB0cnVlLFxuICAgIHByZXZpb3VzUmVzcG9uc2U6XG4gICAgICB0eXBlb2YgYm9keS5wcmV2aW91c19yZXNwb25zZV9pZCA9PT0gXCJzdHJpbmdcIiAmJiBib2R5LnByZXZpb3VzX3Jlc3BvbnNlX2lkLmxlbmd0aCA+IDAsXG4gICAgcmVhc29uaW5nOiBpc1JlY29yZChib2R5LnJlYXNvbmluZykgfHwgYm9keS5yZWFzb25pbmdfZWZmb3J0ICE9PSB1bmRlZmluZWQsXG4gICAgc3RvcmFnZTogYm9keS5zdG9yZSA9PT0gdHJ1ZSxcbiAgICBzdHJ1Y3R1cmVkT3V0cHV0OiBmb3JtYXQgIT09IHVuZGVmaW5lZCAmJiBmb3JtYXQgIT09IFwidGV4dFwiLFxuICAgIHRvb2xzOiB0b29scy5sZW5ndGggPiAwLFxuICAgIHVuc3VwcG9ydGVkT3BlblJlc3BvbnNlc1Rvb2xzOiB0b29sVHlwZXMuc29tZShcbiAgICAgICh0eXBlKSA9PiB0eXBlICE9PSBcImZ1bmN0aW9uXCIgJiYgdHlwZSAhPT0gXCJ3ZWJfc2VhcmNoXCIgJiYgdHlwZSAhPT0gXCJ3ZWJfc2VhcmNoX3ByZXZpZXdcIixcbiAgICApLFxuICAgIHdlYlNlYXJjaDogdG9vbFR5cGVzLnNvbWUoKHR5cGUpID0+IHR5cGUgPT09IFwid2ViX3NlYXJjaFwiIHx8IHR5cGUgPT09IFwid2ViX3NlYXJjaF9wcmV2aWV3XCIpLFxuICB9O1xufVxuXG4vKiogUmV0dXJuIHdoZXRoZXIgYW4gT3JpZ2luYXRvciBoZWFkZXIgc2VsZWN0cyBDb2RleCBjb21wYXRpYmlsaXR5IGJlaGF2aW9yLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGlzQ29kZXhPcmlnaW5hdG9yKG9yaWdpbmF0b3I6IHN0cmluZyB8IHVuZGVmaW5lZCk6IGJvb2xlYW4ge1xuICByZXR1cm4gb3JpZ2luYXRvcj8udG9Mb3dlckNhc2UoKS5pbmNsdWRlcyhcImNvZGV4XCIpID09PSB0cnVlO1xufVxuXG5mdW5jdGlvbiBkaXJlY3RSb3V0ZShcbiAgaW5wdXQ6IFJlc29sdmVSb3V0ZUlucHV0LFxuICB1cHN0cmVhbVByb3RvY29sOiBFeGNsdWRlPFVwc3RyZWFtUHJvdG9jb2wsIFwiYWktc2RrXCI+LFxuICB1cHN0cmVhbU1vZGVsOiBzdHJpbmcsXG4pOiBHYXRld2F5Um91dGUge1xuICByZXR1cm4ge1xuICAgIGNsaWVudFByb3RvY29sOiBpbnB1dC5jbGllbnRQcm90b2NvbCxcbiAgICB1cHN0cmVhbVByb3RvY29sLFxuICAgIHRhcmdldDogaW5wdXQudGFyZ2V0LFxuICAgIHVwc3RyZWFtTW9kZWwsXG4gICAgdHJhbnNsYXRlUmVxdWVzdDogZmFsc2UsXG4gICAgdHJhbnNsYXRlUmVzcG9uc2U6IGZhbHNlLFxuICB9O1xufVxuXG5mdW5jdGlvbiB0cmFuc2xhdGVkUm91dGUoaW5wdXQ6IFJlc29sdmVSb3V0ZUlucHV0KTogR2F0ZXdheVJvdXRlIHtcbiAgcmV0dXJuIHtcbiAgICBjbGllbnRQcm90b2NvbDogaW5wdXQuY2xpZW50UHJvdG9jb2wsXG4gICAgdXBzdHJlYW1Qcm90b2NvbDogXCJhaS1zZGtcIixcbiAgICB0YXJnZXQ6IGlucHV0LnRhcmdldCxcbiAgICB1cHN0cmVhbU1vZGVsOiBpbnB1dC50YXJnZXQuaWQsXG4gICAgdHJhbnNsYXRlUmVxdWVzdDogdHJ1ZSxcbiAgICB0cmFuc2xhdGVSZXNwb25zZTogdHJ1ZSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gc3VwcG9ydHNEaXJlY3RSZXNwb25zZXModGFyZ2V0OiBNb2RlbFRhcmdldCwgZmVhdHVyZXM6IFJlcXVlc3RlZEZlYXR1cmVzKTogYm9vbGVhbiB7XG4gIHJldHVybiAoXG4gICAgc3VwcG9ydHNUb29scyh0YXJnZXQsIGZlYXR1cmVzKSAmJlxuICAgICghZmVhdHVyZXMuY3VzdG9tVG9vbHMgfHwgdGFyZ2V0LmNhcGFiaWxpdGllcy5jdXN0b21Ub29scykgJiZcbiAgICAoIWZlYXR1cmVzLnN0cnVjdHVyZWRPdXRwdXQgfHwgdGFyZ2V0LmNhcGFiaWxpdGllcy5zdHJ1Y3R1cmVkT3V0cHV0KVxuICApO1xufVxuXG5mdW5jdGlvbiBzdXBwb3J0c09wZW5SZXNwb25zZXModGFyZ2V0OiBNb2RlbFRhcmdldCwgZmVhdHVyZXM6IFJlcXVlc3RlZEZlYXR1cmVzKTogYm9vbGVhbiB7XG4gIHJldHVybiAoXG4gICAgc3VwcG9ydHNUb29scyh0YXJnZXQsIGZlYXR1cmVzKSAmJlxuICAgICFmZWF0dXJlcy5jdXN0b21Ub29scyAmJlxuICAgICFmZWF0dXJlcy5wcmV2aW91c1Jlc3BvbnNlICYmXG4gICAgIWZlYXR1cmVzLnN0b3JhZ2UgJiZcbiAgICAhZmVhdHVyZXMuYmFja2dyb3VuZCAmJlxuICAgICFmZWF0dXJlcy51bnN1cHBvcnRlZE9wZW5SZXNwb25zZXNUb29scyAmJlxuICAgICghZmVhdHVyZXMud2ViU2VhcmNoIHx8IHRhcmdldC5jYXBhYmlsaXRpZXMud2ViU2VhcmNoKSAmJlxuICAgICghZmVhdHVyZXMuc3RydWN0dXJlZE91dHB1dCB8fCB0YXJnZXQuY2FwYWJpbGl0aWVzLnN0cnVjdHVyZWRPdXRwdXQpXG4gICk7XG59XG5cbmZ1bmN0aW9uIHN1cHBvcnRzVG9vbHModGFyZ2V0OiBNb2RlbFRhcmdldCwgZmVhdHVyZXM6IFJlcXVlc3RlZEZlYXR1cmVzKTogYm9vbGVhbiB7XG4gIHJldHVybiAoXG4gICAgKCFmZWF0dXJlcy50b29scyB8fCB0YXJnZXQuY2FwYWJpbGl0aWVzLnRvb2xzKSAmJlxuICAgICghZmVhdHVyZXMucGFyYWxsZWxUb29scyB8fCB0YXJnZXQuY2FwYWJpbGl0aWVzLnBhcmFsbGVsVG9vbHMpXG4gICk7XG59XG5cbmZ1bmN0aW9uIHJlamVjdFN0YXRlZnVsUmVzcG9uc2VzKGZlYXR1cmVzOiBSZXF1ZXN0ZWRGZWF0dXJlcyk6IHZvaWQge1xuICBjb25zdCB1bnN1cHBvcnRlZCA9IFtcbiAgICAuLi4oZmVhdHVyZXMucHJldmlvdXNSZXNwb25zZSA/IFtcInByZXZpb3VzX3Jlc3BvbnNlX2lkXCJdIDogW10pLFxuICAgIC4uLihmZWF0dXJlcy5zdG9yYWdlID8gW1wic3RvcmVcIl0gOiBbXSksXG4gICAgLi4uKGZlYXR1cmVzLmJhY2tncm91bmQgPyBbXCJiYWNrZ3JvdW5kXCJdIDogW10pLFxuICBdO1xuICBpZiAodW5zdXBwb3J0ZWQubGVuZ3RoID4gMCkgdGhyb3cgbmV3IFVuc3VwcG9ydGVkR2F0ZXdheUZlYXR1cmVFcnJvcih1bnN1cHBvcnRlZCk7XG59XG5cbmZ1bmN0aW9uIHRhcmdldHNNb2RlbFNlcnZpY2UocmVxdWVzdGVkTW9kZWw6IHN0cmluZywgdGFyZ2V0OiBNb2RlbFRhcmdldCk6IGJvb2xlYW4ge1xuICBpZiAoIXRhcmdldC5tb2RlbFNlcnZpY2VOYW1lKSByZXR1cm4gZmFsc2U7XG4gIGNvbnN0IHVucXVhbGlmaWVkID0gcmVxdWVzdGVkTW9kZWwudHJpbSgpLnJlcGxhY2UoL14oPzpkYnh8ZGF0YWJyaWNrcylcXC8vaSwgXCJcIik7XG4gIHJldHVybiB1bnF1YWxpZmllZCA9PT0gdGFyZ2V0Lm1vZGVsU2VydmljZU5hbWU7XG59XG5cbmZ1bmN0aW9uIGlzUmVjb3JkKHZhbHVlOiB1bmtub3duKTogdmFsdWUgaXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4ge1xuICByZXR1cm4gdmFsdWUgIT09IG51bGwgJiYgdHlwZW9mIHZhbHVlID09PSBcIm9iamVjdFwiICYmICFBcnJheS5pc0FycmF5KHZhbHVlKTtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Express adapters for the shared model-gateway service.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import type { ClientProtocol } from "@dbx-tools/shared-model-gateway";
|
|
7
|
+
import type express from "express";
|
|
8
|
+
import { ModelGateway } from "./gateway.ts";
|
|
9
|
+
/** Send the lightweight compatibility health response. */
|
|
10
|
+
export declare function sendHealth(response: express.Response): void;
|
|
11
|
+
/** Send the active principal's dynamic model catalogue. */
|
|
12
|
+
export declare function sendModels(gateway: ModelGateway, request: express.Request, response: express.Response): Promise<void>;
|
|
13
|
+
/** Execute and stream one model request through Express with cancellation. */
|
|
14
|
+
export declare function sendInference(gateway: ModelGateway, protocol: ClientProtocol, request: express.Request, response: express.Response): Promise<void>;
|