@dbx-tools/cli 0.9.60 → 0.9.61
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 +64 -17
- package/bin/dbx-genie.ts +13 -0
- package/index.ts +13 -1
- package/lib/bin/dbx-genie.d.ts +2 -0
- package/lib/bin/dbx-genie.js +10 -0
- package/lib/index.d.ts +13 -1
- package/lib/index.js +10 -2
- package/lib/src/auth/cli.js +13 -2
- package/lib/src/auth/options.d.ts +4 -0
- package/lib/src/auth/options.js +5 -1
- package/lib/src/cli.js +8 -4
- package/lib/src/genie-code/cli.d.ts +19 -0
- package/lib/src/genie-code/cli.js +36 -0
- package/lib/src/genie-code/config.d.ts +38 -0
- package/lib/src/genie-code/config.js +111 -0
- package/lib/src/genie-code/install.d.ts +21 -0
- package/lib/src/genie-code/install.js +69 -0
- package/lib/src/genie-code/options.d.ts +7 -0
- package/lib/src/genie-code/options.js +7 -0
- package/lib/src/genie-code/runner.d.ts +21 -0
- package/lib/src/genie-code/runner.js +90 -0
- package/lib/src/genie-code/runtime.d.ts +48 -0
- package/lib/src/genie-code/runtime.js +162 -0
- package/lib/src/model-gateway/cli.js +3 -3
- package/lib/src/model-gateway/server.d.ts +3 -0
- package/lib/src/model-gateway/server.js +36 -6
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +40 -18
- package/src/auth/cli.ts +11 -1
- package/src/auth/options.ts +4 -0
- package/src/cli.ts +13 -2
- package/src/genie-code/cli.ts +58 -0
- package/src/genie-code/config.ts +161 -0
- package/src/genie-code/install.ts +103 -0
- package/src/genie-code/options.ts +14 -0
- package/src/genie-code/runner.ts +106 -0
- package/src/genie-code/runtime.ts +212 -0
- package/src/model-gateway/cli.ts +6 -2
- package/src/model-gateway/server.ts +37 -5
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Supervise Genie Code and its authenticated local model gateway.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
import { randomBytes } from "node:crypto";
|
|
7
|
+
import { rm } from "node:fs/promises";
|
|
8
|
+
import { delimiter, dirname } from "node:path";
|
|
9
|
+
import { DatabricksModelRegistry, models } from "@dbx-tools/appkit-model-gateway";
|
|
10
|
+
import * as auth from "@dbx-tools/auth";
|
|
11
|
+
import { resolveServicePackageBin } from "@dbx-tools/cli-service/definition";
|
|
12
|
+
import { workspaceClient } from "@dbx-tools/databricks";
|
|
13
|
+
import { log } from "@dbx-tools/shared-core";
|
|
14
|
+
import { resolveGenieCodeOptions, } from "@dbx-tools/shared-genie-code/options";
|
|
15
|
+
import concurrently from "concurrently";
|
|
16
|
+
import getPort from "get-port";
|
|
17
|
+
import { writeGenieCodeConfig } from "./config.js";
|
|
18
|
+
import { installGenieCode } from "./install.js";
|
|
19
|
+
import { RUNNER_OPTIONS_ENV } from "./runner.js";
|
|
20
|
+
const logger = log.logger("genie-code");
|
|
21
|
+
const DEFAULT_DEPENDENCIES = {
|
|
22
|
+
createAuthClient: auth.client.createAuthClient,
|
|
23
|
+
install: installGenieCode,
|
|
24
|
+
port: ({ host, port }) => getPort({ host, ...(port ? { port } : {}) }),
|
|
25
|
+
resolveBin: resolveServicePackageBin,
|
|
26
|
+
resolveCodexModel,
|
|
27
|
+
supervise: concurrently,
|
|
28
|
+
token: () => randomBytes(32).toString("base64url"),
|
|
29
|
+
writeConfig: writeGenieCodeConfig,
|
|
30
|
+
};
|
|
31
|
+
/** Resolve a Genie `--model` value to the Codex catalogue slug the gateway publishes. */
|
|
32
|
+
async function resolveCodexModel(model, profile) {
|
|
33
|
+
const client = await workspaceClient.createWorkspaceClient({ profile });
|
|
34
|
+
const target = await new DatabricksModelRegistry({ client }).resolve(model, {
|
|
35
|
+
requiresTools: true,
|
|
36
|
+
});
|
|
37
|
+
if (!target)
|
|
38
|
+
throw new Error(`Genie Code model not found: ${model}`);
|
|
39
|
+
return models.codexModelSlug(target);
|
|
40
|
+
}
|
|
41
|
+
/** Resolve auth, installation, listener, and configuration before spawning children. */
|
|
42
|
+
export async function prepareGenieCodeRuntime(input = {}) {
|
|
43
|
+
const dependencies = { ...DEFAULT_DEPENDENCIES, ...input.dependencies };
|
|
44
|
+
const options = resolveGenieCodeOptions(input.options);
|
|
45
|
+
logger.info("resolving Databricks authentication", {
|
|
46
|
+
requestedProfile: options.profile,
|
|
47
|
+
});
|
|
48
|
+
const authClient = await dependencies.createAuthClient(options.profile ? { profile: options.profile } : {});
|
|
49
|
+
const profile = authClient.profile;
|
|
50
|
+
if (!profile) {
|
|
51
|
+
throw new Error("Genie Code requires a configured Databricks profile");
|
|
52
|
+
}
|
|
53
|
+
logger.info("preparing Genie Code runtime", {
|
|
54
|
+
profile,
|
|
55
|
+
model: options.model,
|
|
56
|
+
});
|
|
57
|
+
const installation = await dependencies.install();
|
|
58
|
+
const host = options.gatewayListen.host;
|
|
59
|
+
const requestedPort = options.gatewayListen.port;
|
|
60
|
+
const gatewayPort = await dependencies.port({
|
|
61
|
+
host,
|
|
62
|
+
...(requestedPort > 0 ? { port: requestedPort } : {}),
|
|
63
|
+
});
|
|
64
|
+
if (requestedPort > 0 && gatewayPort !== requestedPort) {
|
|
65
|
+
throw new Error(`Genie Code gateway port ${requestedPort} is already in use`);
|
|
66
|
+
}
|
|
67
|
+
const model = await dependencies.resolveCodexModel(options.model, profile);
|
|
68
|
+
logger.info("resolved Genie Code model", { requested: options.model, model });
|
|
69
|
+
const urlHost = host.includes(":") ? `[${host}]` : host;
|
|
70
|
+
const gatewayBaseUrl = `http://${urlHost}:${gatewayPort}/v1`;
|
|
71
|
+
const gatewayHealthUrl = `http://${urlHost}:${gatewayPort}/api/healthz`;
|
|
72
|
+
const gatewayListen = `tcp://${urlHost}:${gatewayPort}`;
|
|
73
|
+
const bearerToken = dependencies.token();
|
|
74
|
+
const home = await dependencies.writeConfig({
|
|
75
|
+
bearerToken,
|
|
76
|
+
gatewayBaseUrl,
|
|
77
|
+
model,
|
|
78
|
+
profile,
|
|
79
|
+
projectDirectory: input.cwd ?? process.cwd(),
|
|
80
|
+
});
|
|
81
|
+
return {
|
|
82
|
+
bearerToken,
|
|
83
|
+
gatewayBaseUrl,
|
|
84
|
+
gatewayHealthUrl,
|
|
85
|
+
gatewayListen,
|
|
86
|
+
gatewayPort,
|
|
87
|
+
home,
|
|
88
|
+
installation,
|
|
89
|
+
model,
|
|
90
|
+
profile,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
function shellExecutable(path) {
|
|
94
|
+
if (process.platform === "win32")
|
|
95
|
+
return `"${path.replaceAll('"', '""')}"`;
|
|
96
|
+
return `'${path.replaceAll("'", "'\\''")}'`;
|
|
97
|
+
}
|
|
98
|
+
function childPath(...paths) {
|
|
99
|
+
return [...new Set([...paths.map(dirname), process.env.PATH].filter(Boolean))].join(delimiter);
|
|
100
|
+
}
|
|
101
|
+
/** Run Genie Code and the model gateway until either process exits. */
|
|
102
|
+
export async function runGenieCode(input = {}) {
|
|
103
|
+
const dependencies = { ...DEFAULT_DEPENDENCIES, ...input.dependencies };
|
|
104
|
+
const prepared = await prepareGenieCodeRuntime({
|
|
105
|
+
...input,
|
|
106
|
+
dependencies,
|
|
107
|
+
});
|
|
108
|
+
const gatewayBin = dependencies.resolveBin(import.meta.url, "dbx-model-gateway");
|
|
109
|
+
const runnerBin = dependencies.resolveBin(import.meta.url, "dbx-genie");
|
|
110
|
+
const path = childPath(gatewayBin, runnerBin);
|
|
111
|
+
const runnerOptions = {
|
|
112
|
+
executable: prepared.installation.path,
|
|
113
|
+
arguments: ["-p", prepared.home.overlayName, ...(input.genieArgs ?? [])],
|
|
114
|
+
home: prepared.home.home,
|
|
115
|
+
gatewayHealthUrl: prepared.gatewayHealthUrl,
|
|
116
|
+
bearerToken: prepared.bearerToken,
|
|
117
|
+
startupTimeoutMs: 60_000,
|
|
118
|
+
};
|
|
119
|
+
const { result } = dependencies.supervise([
|
|
120
|
+
{
|
|
121
|
+
command: shellExecutable(gatewayBin),
|
|
122
|
+
name: "gateway",
|
|
123
|
+
env: {
|
|
124
|
+
...process.env,
|
|
125
|
+
PATH: path,
|
|
126
|
+
LISTEN: prepared.gatewayListen,
|
|
127
|
+
DATABRICKS_CONFIG_PROFILE: prepared.profile,
|
|
128
|
+
DBX_TOOLS_MODEL_GATEWAY_BEARER_TOKEN: prepared.bearerToken,
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
command: shellExecutable(runnerBin),
|
|
133
|
+
name: "genie",
|
|
134
|
+
env: {
|
|
135
|
+
...process.env,
|
|
136
|
+
PATH: path,
|
|
137
|
+
DATABRICKS_CONFIG_PROFILE: prepared.profile,
|
|
138
|
+
[RUNNER_OPTIONS_ENV]: JSON.stringify(runnerOptions),
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
], {
|
|
142
|
+
cwd: input.cwd ?? process.cwd(),
|
|
143
|
+
raw: true,
|
|
144
|
+
killOthersOn: ["failure", "success"],
|
|
145
|
+
killSignal: "SIGTERM",
|
|
146
|
+
killTimeout: 17_000,
|
|
147
|
+
successCondition: "command-genie",
|
|
148
|
+
});
|
|
149
|
+
logger.info("started Genie Code and model gateway", {
|
|
150
|
+
profile: prepared.profile,
|
|
151
|
+
model: prepared.model,
|
|
152
|
+
gateway: prepared.gatewayBaseUrl,
|
|
153
|
+
home: prepared.home.home,
|
|
154
|
+
});
|
|
155
|
+
try {
|
|
156
|
+
await result;
|
|
157
|
+
}
|
|
158
|
+
finally {
|
|
159
|
+
await rm(prepared.home.overlayPath, { force: true });
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicnVudGltZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9nZW5pZS1jb2RlL3J1bnRpbWUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7R0FJRztBQUVILE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFDMUMsT0FBTyxFQUFFLEVBQUUsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBQ3RDLE9BQU8sRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLE1BQU0sV0FBVyxDQUFDO0FBQy9DLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNsRixPQUFPLEtBQUssSUFBSSxNQUFNLGlCQUFpQixDQUFDO0FBQ3hDLE9BQU8sRUFBRSx3QkFBd0IsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBRTdFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDN0MsT0FBTyxFQUNMLHVCQUF1QixHQUd4QixNQUFNLHNDQUFzQyxDQUFDO0FBQzlDLE9BQU8sWUFBWSxNQUFNLGNBQWMsQ0FBQztBQUN4QyxPQUFPLE9BQU8sTUFBTSxVQUFVLENBQUM7QUFFL0IsT0FBTyxFQUFFLG9CQUFvQixFQUFzQixNQUFNLGFBQWEsQ0FBQztBQUN2RSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDaEQsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBRWpELE1BQU0sTUFBTSxHQUFHLEdBQUcsQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLENBQUM7QUFjeEMsTUFBTSxvQkFBb0IsR0FBaUM7SUFDekQsZ0JBQWdCLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0I7SUFDOUMsT0FBTyxFQUFFLGdCQUFnQjtJQUN6QixJQUFJLEVBQUUsQ0FBQyxF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ekIsS0FBSyxFQUFFLFFBQVEsQ0FBQyxLQUFLO1FBQ3JCLE9BQU8sRUFBRSxRQUFRLENBQUMsY0FBYztRQUNoQyxJQUFJLEVBQUUsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJO0tBQ3pCLENBQUMsQ0FBQztJQUNILElBQUksQ0FBQztRQUNILE1BQU0sTUFBTSxDQUFDO0lBQ2YsQ0FBQztZQUFTLENBQUM7UUFDVCxNQUFNLEVBQUUsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZELENBQUM7QUFDSCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBTdXBlcnZpc2UgR2VuaWUgQ29kZSBhbmQgaXRzIGF1dGhlbnRpY2F0ZWQgbG9jYWwgbW9kZWwgZ2F0ZXdheS5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHsgcmFuZG9tQnl0ZXMgfSBmcm9tIFwibm9kZTpjcnlwdG9cIjtcbmltcG9ydCB7IHJtIH0gZnJvbSBcIm5vZGU6ZnMvcHJvbWlzZXNcIjtcbmltcG9ydCB7IGRlbGltaXRlciwgZGlybmFtZSB9IGZyb20gXCJub2RlOnBhdGhcIjtcbmltcG9ydCB7IERhdGFicmlja3NNb2RlbFJlZ2lzdHJ5LCBtb2RlbHMgfSBmcm9tIFwiQGRieC10b29scy9hcHBraXQtbW9kZWwtZ2F0ZXdheVwiO1xuaW1wb3J0ICogYXMgYXV0aCBmcm9tIFwiQGRieC10b29scy9hdXRoXCI7XG5pbXBvcnQgeyByZXNvbHZlU2VydmljZVBhY2thZ2VCaW4gfSBmcm9tIFwiQGRieC10b29scy9jbGktc2VydmljZS9kZWZpbml0aW9uXCI7XG5pbXBvcnQgdHlwZSB7IEJpbkNvbnRleHQgfSBmcm9tIFwiQGRieC10b29scy9jb3JlL2JpblwiO1xuaW1wb3J0IHsgd29ya3NwYWNlQ2xpZW50IH0gZnJvbSBcIkBkYngtdG9vbHMvZGF0YWJyaWNrc1wiO1xuaW1wb3J0IHsgbG9nIH0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWNvcmVcIjtcbmltcG9ydCB7XG4gIHJlc29sdmVHZW5pZUNvZGVPcHRpb25zLFxuICB0eXBlIEdlbmllQ29kZU9wdGlvbnMsXG4gIHR5cGUgR2VuaWVDb2RlUnVubmVyT3B0aW9ucyxcbn0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLWdlbmllLWNvZGUvb3B0aW9uc1wiO1xuaW1wb3J0IGNvbmN1cnJlbnRseSBmcm9tIFwiY29uY3VycmVudGx5XCI7XG5pbXBvcnQgZ2V0UG9ydCBmcm9tIFwiZ2V0LXBvcnRcIjtcblxuaW1wb3J0IHsgd3JpdGVHZW5pZUNvZGVDb25maWcsIHR5cGUgR2VuaWVDb2RlSG9tZSB9IGZyb20gXCIuL2NvbmZpZy50c1wiO1xuaW1wb3J0IHsgaW5zdGFsbEdlbmllQ29kZSB9IGZyb20gXCIuL2luc3RhbGwudHNcIjtcbmltcG9ydCB7IFJVTk5FUl9PUFRJT05TX0VOViB9IGZyb20gXCIuL3J1bm5lci50c1wiO1xuXG5jb25zdCBsb2dnZXIgPSBsb2cubG9nZ2VyKFwiZ2VuaWUtY29kZVwiKTtcblxuLyoqIEluamVjdGFibGUgb3duZXJzIHVzZWQgdG8gcHJlcGFyZSBhbmQgc3VwZXJ2aXNlIG1hbmFnZWQgR2VuaWUgQ29kZS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgR2VuaWVDb2RlUnVudGltZURlcGVuZGVuY2llcyB7XG4gIGNyZWF0ZUF1dGhDbGllbnQ6IHR5cGVvZiBhdXRoLmNsaWVudC5jcmVhdGVBdXRoQ2xpZW50O1xuICBpbnN0YWxsOiB0eXBlb2YgaW5zdGFsbEdlbmllQ29kZTtcbiAgcG9ydChvcHRpb25zOiB7IGhvc3Q6IHN0cmluZzsgcG9ydD86IG51bWJlciB9KTogUHJvbWlzZTxudW1iZXI+O1xuICByZXNvbHZlQmluKHBhY2thZ2VSZWZlcmVuY2U6IHN0cmluZywgYmluTmFtZTogc3RyaW5nKTogc3RyaW5nO1xuICByZXNvbHZlQ29kZXhNb2RlbChtb2RlbDogc3RyaW5nLCBwcm9maWxlOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz47XG4gIHN1cGVydmlzZTogdHlwZW9mIGNvbmN1cnJlbnRseTtcbiAgdG9rZW4oKTogc3RyaW5nO1xuICB3cml0ZUNvbmZpZzogdHlwZW9mIHdyaXRlR2VuaWVDb2RlQ29uZmlnO1xufVxuXG5jb25zdCBERUZBVUxUX0RFUEVOREVOQ0lFUzogR2VuaWVDb2RlUnVudGltZURlcGVuZGVuY2llcyA9IHtcbiAgY3JlYXRlQXV0aENsaWVudDogYXV0aC5jbGllbnQuY3JlYXRlQXV0aENsaWVudCxcbiAgaW5zdGFsbDogaW5zdGFsbEdlbmllQ29kZSxcbiAgcG9ydDogKHsgaG9zdCwgcG9ydCB9KSA9PiBnZXRQb3J0KHsgaG9zdCwgLi4uKHBvcnQgPyB7IHBvcnQgfSA6IHt9KSB9KSxcbiAgcmVzb2x2ZUJpbjogcmVzb2x2ZVNlcnZpY2VQYWNrYWdlQmluLFxuICByZXNvbHZlQ29kZXhNb2RlbCxcbiAgc3VwZXJ2aXNlOiBjb25jdXJyZW50bHksXG4gIHRva2VuOiAoKSA9PiByYW5kb21CeXRlcygzMikudG9TdHJpbmcoXCJiYXNlNjR1cmxcIiksXG4gIHdyaXRlQ29uZmlnOiB3cml0ZUdlbmllQ29kZUNvbmZpZyxcbn07XG5cbi8qKiBSZXNvbHZlIGEgR2VuaWUgYC0tbW9kZWxgIHZhbHVlIHRvIHRoZSBDb2RleCBjYXRhbG9ndWUgc2x1ZyB0aGUgZ2F0ZXdheSBwdWJsaXNoZXMuICovXG5hc3luYyBmdW5jdGlvbiByZXNvbHZlQ29kZXhNb2RlbChtb2RlbDogc3RyaW5nLCBwcm9maWxlOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICBjb25zdCBjbGllbnQgPSBhd2FpdCB3b3Jrc3BhY2VDbGllbnQuY3JlYXRlV29ya3NwYWNlQ2xpZW50KHsgcHJvZmlsZSB9KTtcbiAgY29uc3QgdGFyZ2V0ID0gYXdhaXQgbmV3IERhdGFicmlja3NNb2RlbFJlZ2lzdHJ5KHsgY2xpZW50IH0pLnJlc29sdmUobW9kZWwsIHtcbiAgICByZXF1aXJlc1Rvb2xzOiB0cnVlLFxuICB9KTtcbiAgaWYgKCF0YXJnZXQpIHRocm93IG5ldyBFcnJvcihgR2VuaWUgQ29kZSBtb2RlbCBub3QgZm91bmQ6ICR7bW9kZWx9YCk7XG4gIHJldHVybiBtb2RlbHMuY29kZXhNb2RlbFNsdWcodGFyZ2V0KTtcbn1cblxuLyoqIElucHV0cyBhY2NlcHRlZCBieSBtYW5hZ2VkIEdlbmllIENvZGUgcHJlcGFyYXRpb24gYW5kIGV4ZWN1dGlvbi4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUnVuR2VuaWVDb2RlT3B0aW9ucyB7XG4gIGN3ZD86IHN0cmluZztcbiAgZGVwZW5kZW5jaWVzPzogUGFydGlhbDxHZW5pZUNvZGVSdW50aW1lRGVwZW5kZW5jaWVzPjtcbiAgZ2VuaWVBcmdzPzogcmVhZG9ubHkgc3RyaW5nW107XG4gIG9wdGlvbnM/OiBHZW5pZUNvZGVPcHRpb25zO1xufVxuXG4vKiogUmVzb2x2ZWQgaW5zdGFsbGF0aW9uLCBhdXRoLCBsaXN0ZW5lciwgYW5kIGhvbWUgZm9yIG9uZSBpbnZvY2F0aW9uLiAqL1xuZXhwb3J0IGludGVyZmFjZSBQcmVwYXJlZEdlbmllQ29kZVJ1bnRpbWUge1xuICBiZWFyZXJUb2tlbjogc3RyaW5nO1xuICBnYXRld2F5QmFzZVVybDogc3RyaW5nO1xuICBnYXRld2F5SGVhbHRoVXJsOiBzdHJpbmc7XG4gIGdhdGV3YXlMaXN0ZW46IHN0cmluZztcbiAgZ2F0ZXdheVBvcnQ6IG51bWJlcjtcbiAgaG9tZTogR2VuaWVDb2RlSG9tZTtcbiAgaW5zdGFsbGF0aW9uOiBCaW5Db250ZXh0O1xuICBtb2RlbDogc3RyaW5nO1xuICBwcm9maWxlOiBzdHJpbmc7XG59XG5cbi8qKiBSZXNvbHZlIGF1dGgsIGluc3RhbGxhdGlvbiwgbGlzdGVuZXIsIGFuZCBjb25maWd1cmF0aW9uIGJlZm9yZSBzcGF3bmluZyBjaGlsZHJlbi4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwcmVwYXJlR2VuaWVDb2RlUnVudGltZShcbiAgaW5wdXQ6IFJ1bkdlbmllQ29kZU9wdGlvbnMgPSB7fSxcbik6IFByb21pc2U8UHJlcGFyZWRHZW5pZUNvZGVSdW50aW1lPiB7XG4gIGNvbnN0IGRlcGVuZGVuY2llcyA9IHsgLi4uREVGQVVMVF9ERVBFTkRFTkNJRVMsIC4uLmlucHV0LmRlcGVuZGVuY2llcyB9O1xuICBjb25zdCBvcHRpb25zID0gcmVzb2x2ZUdlbmllQ29kZU9wdGlvbnMoaW5wdXQub3B0aW9ucyk7XG4gIGxvZ2dlci5pbmZvKFwicmVzb2x2aW5nIERhdGFicmlja3MgYXV0aGVudGljYXRpb25cIiwge1xuICAgIHJlcXVlc3RlZFByb2ZpbGU6IG9wdGlvbnMucHJvZmlsZSxcbiAgfSk7XG4gIGNvbnN0IGF1dGhDbGllbnQgPSBhd2FpdCBkZXBlbmRlbmNpZXMuY3JlYXRlQXV0aENsaWVudChcbiAgICBvcHRpb25zLnByb2ZpbGUgPyB7IHByb2ZpbGU6IG9wdGlvbnMucHJvZmlsZSB9IDoge30sXG4gICk7XG4gIGNvbnN0IHByb2ZpbGUgPSBhdXRoQ2xpZW50LnByb2ZpbGU7XG4gIGlmICghcHJvZmlsZSkge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkdlbmllIENvZGUgcmVxdWlyZXMgYSBjb25maWd1cmVkIERhdGFicmlja3MgcHJvZmlsZVwiKTtcbiAgfVxuICBsb2dnZXIuaW5mbyhcInByZXBhcmluZyBHZW5pZSBDb2RlIHJ1bnRpbWVcIiwge1xuICAgIHByb2ZpbGUsXG4gICAgbW9kZWw6IG9wdGlvbnMubW9kZWwsXG4gIH0pO1xuICBjb25zdCBpbnN0YWxsYXRpb24gPSBhd2FpdCBkZXBlbmRlbmNpZXMuaW5zdGFsbCgpO1xuICBjb25zdCBob3N0ID0gb3B0aW9ucy5nYXRld2F5TGlzdGVuLmhvc3Q7XG4gIGNvbnN0IHJlcXVlc3RlZFBvcnQgPSBvcHRpb25zLmdhdGV3YXlMaXN0ZW4ucG9ydDtcbiAgY29uc3QgZ2F0ZXdheVBvcnQgPSBhd2FpdCBkZXBlbmRlbmNpZXMucG9ydCh7XG4gICAgaG9zdCxcbiAgICAuLi4ocmVxdWVzdGVkUG9ydCA+IDAgPyB7IHBvcnQ6IHJlcXVlc3RlZFBvcnQgfSA6IHt9KSxcbiAgfSk7XG4gIGlmIChyZXF1ZXN0ZWRQb3J0ID4gMCAmJiBnYXRld2F5UG9ydCAhPT0gcmVxdWVzdGVkUG9ydCkge1xuICAgIHRocm93IG5ldyBFcnJvcihgR2VuaWUgQ29kZSBnYXRld2F5IHBvcnQgJHtyZXF1ZXN0ZWRQb3J0fSBpcyBhbHJlYWR5IGluIHVzZWApO1xuICB9XG4gIGNvbnN0IG1vZGVsID0gYXdhaXQgZGVwZW5kZW5jaWVzLnJlc29sdmVDb2RleE1vZGVsKG9wdGlvbnMubW9kZWwsIHByb2ZpbGUpO1xuICBsb2dnZXIuaW5mbyhcInJlc29sdmVkIEdlbmllIENvZGUgbW9kZWxcIiwgeyByZXF1ZXN0ZWQ6IG9wdGlvbnMubW9kZWwsIG1vZGVsIH0pO1xuICBjb25zdCB1cmxIb3N0ID0gaG9zdC5pbmNsdWRlcyhcIjpcIikgPyBgWyR7aG9zdH1dYCA6IGhvc3Q7XG4gIGNvbnN0IGdhdGV3YXlCYXNlVXJsID0gYGh0dHA6Ly8ke3VybEhvc3R9OiR7Z2F0ZXdheVBvcnR9L3YxYDtcbiAgY29uc3QgZ2F0ZXdheUhlYWx0aFVybCA9IGBodHRwOi8vJHt1cmxIb3N0fToke2dhdGV3YXlQb3J0fS9hcGkvaGVhbHRoemA7XG4gIGNvbnN0IGdhdGV3YXlMaXN0ZW4gPSBgdGNwOi8vJHt1cmxIb3N0fToke2dhdGV3YXlQb3J0fWA7XG4gIGNvbnN0IGJlYXJlclRva2VuID0gZGVwZW5kZW5jaWVzLnRva2VuKCk7XG4gIGNvbnN0IGhvbWUgPSBhd2FpdCBkZXBlbmRlbmNpZXMud3JpdGVDb25maWcoe1xuICAgIGJlYXJlclRva2VuLFxuICAgIGdhdGV3YXlCYXNlVXJsLFxuICAgIG1vZGVsLFxuICAgIHByb2ZpbGUsXG4gICAgcHJvamVjdERpcmVjdG9yeTogaW5wdXQuY3dkID8/IHByb2Nlc3MuY3dkKCksXG4gIH0pO1xuICByZXR1cm4ge1xuICAgIGJlYXJlclRva2VuLFxuICAgIGdhdGV3YXlCYXNlVXJsLFxuICAgIGdhdGV3YXlIZWFsdGhVcmwsXG4gICAgZ2F0ZXdheUxpc3RlbixcbiAgICBnYXRld2F5UG9ydCxcbiAgICBob21lLFxuICAgIGluc3RhbGxhdGlvbixcbiAgICBtb2RlbCxcbiAgICBwcm9maWxlLFxuICB9O1xufVxuXG5mdW5jdGlvbiBzaGVsbEV4ZWN1dGFibGUocGF0aDogc3RyaW5nKTogc3RyaW5nIHtcbiAgaWYgKHByb2Nlc3MucGxhdGZvcm0gPT09IFwid2luMzJcIikgcmV0dXJuIGBcIiR7cGF0aC5yZXBsYWNlQWxsKCdcIicsICdcIlwiJyl9XCJgO1xuICByZXR1cm4gYCcke3BhdGgucmVwbGFjZUFsbChcIidcIiwgXCInXFxcXCcnXCIpfSdgO1xufVxuXG5mdW5jdGlvbiBjaGlsZFBhdGgoLi4ucGF0aHM6IHN0cmluZ1tdKTogc3RyaW5nIHtcbiAgcmV0dXJuIFsuLi5uZXcgU2V0KFsuLi5wYXRocy5tYXAoZGlybmFtZSksIHByb2Nlc3MuZW52LlBBVEhdLmZpbHRlcihCb29sZWFuKSldLmpvaW4oZGVsaW1pdGVyKTtcbn1cblxuLyoqIFJ1biBHZW5pZSBDb2RlIGFuZCB0aGUgbW9kZWwgZ2F0ZXdheSB1bnRpbCBlaXRoZXIgcHJvY2VzcyBleGl0cy4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBydW5HZW5pZUNvZGUoaW5wdXQ6IFJ1bkdlbmllQ29kZU9wdGlvbnMgPSB7fSk6IFByb21pc2U8dm9pZD4ge1xuICBjb25zdCBkZXBlbmRlbmNpZXMgPSB7IC4uLkRFRkFVTFRfREVQRU5ERU5DSUVTLCAuLi5pbnB1dC5kZXBlbmRlbmNpZXMgfTtcbiAgY29uc3QgcHJlcGFyZWQgPSBhd2FpdCBwcmVwYXJlR2VuaWVDb2RlUnVudGltZSh7XG4gICAgLi4uaW5wdXQsXG4gICAgZGVwZW5kZW5jaWVzLFxuICB9KTtcbiAgY29uc3QgZ2F0ZXdheUJpbiA9IGRlcGVuZGVuY2llcy5yZXNvbHZlQmluKGltcG9ydC5tZXRhLnVybCwgXCJkYngtbW9kZWwtZ2F0ZXdheVwiKTtcbiAgY29uc3QgcnVubmVyQmluID0gZGVwZW5kZW5jaWVzLnJlc29sdmVCaW4oaW1wb3J0Lm1ldGEudXJsLCBcImRieC1nZW5pZVwiKTtcbiAgY29uc3QgcGF0aCA9IGNoaWxkUGF0aChnYXRld2F5QmluLCBydW5uZXJCaW4pO1xuICBjb25zdCBydW5uZXJPcHRpb25zOiBHZW5pZUNvZGVSdW5uZXJPcHRpb25zID0ge1xuICAgIGV4ZWN1dGFibGU6IHByZXBhcmVkLmluc3RhbGxhdGlvbi5wYXRoLFxuICAgIGFyZ3VtZW50czogW1wiLXBcIiwgcHJlcGFyZWQuaG9tZS5vdmVybGF5TmFtZSwgLi4uKGlucHV0LmdlbmllQXJncyA/PyBbXSldLFxuICAgIGhvbWU6IHByZXBhcmVkLmhvbWUuaG9tZSxcbiAgICBnYXRld2F5SGVhbHRoVXJsOiBwcmVwYXJlZC5nYXRld2F5SGVhbHRoVXJsLFxuICAgIGJlYXJlclRva2VuOiBwcmVwYXJlZC5iZWFyZXJUb2tlbixcbiAgICBzdGFydHVwVGltZW91dE1zOiA2MF8wMDAsXG4gIH07XG4gIGNvbnN0IHsgcmVzdWx0IH0gPSBkZXBlbmRlbmNpZXMuc3VwZXJ2aXNlKFxuICAgIFtcbiAgICAgIHtcbiAgICAgICAgY29tbWFuZDogc2hlbGxFeGVjdXRhYmxlKGdhdGV3YXlCaW4pLFxuICAgICAgICBuYW1lOiBcImdhdGV3YXlcIixcbiAgICAgICAgZW52OiB7XG4gICAgICAgICAgLi4ucHJvY2Vzcy5lbnYsXG4gICAgICAgICAgUEFUSDogcGF0aCxcbiAgICAgICAgICBMSVNURU46IHByZXBhcmVkLmdhdGV3YXlMaXN0ZW4sXG4gICAgICAgICAgREFUQUJSSUNLU19DT05GSUdfUFJPRklMRTogcHJlcGFyZWQucHJvZmlsZSxcbiAgICAgICAgICBEQlhfVE9PTFNfTU9ERUxfR0FURVdBWV9CRUFSRVJfVE9LRU46IHByZXBhcmVkLmJlYXJlclRva2VuLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIHtcbiAgICAgICAgY29tbWFuZDogc2hlbGxFeGVjdXRhYmxlKHJ1bm5lckJpbiksXG4gICAgICAgIG5hbWU6IFwiZ2VuaWVcIixcbiAgICAgICAgZW52OiB7XG4gICAgICAgICAgLi4ucHJvY2Vzcy5lbnYsXG4gICAgICAgICAgUEFUSDogcGF0aCxcbiAgICAgICAgICBEQVRBQlJJQ0tTX0NPTkZJR19QUk9GSUxFOiBwcmVwYXJlZC5wcm9maWxlLFxuICAgICAgICAgIFtSVU5ORVJfT1BUSU9OU19FTlZdOiBKU09OLnN0cmluZ2lmeShydW5uZXJPcHRpb25zKSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgXSxcbiAgICB7XG4gICAgICBjd2Q6IGlucHV0LmN3ZCA/PyBwcm9jZXNzLmN3ZCgpLFxuICAgICAgcmF3OiB0cnVlLFxuICAgICAga2lsbE90aGVyc09uOiBbXCJmYWlsdXJlXCIsIFwic3VjY2Vzc1wiXSxcbiAgICAgIGtpbGxTaWduYWw6IFwiU0lHVEVSTVwiLFxuICAgICAga2lsbFRpbWVvdXQ6IDE3XzAwMCxcbiAgICAgIHN1Y2Nlc3NDb25kaXRpb246IFwiY29tbWFuZC1nZW5pZVwiLFxuICAgIH0sXG4gICk7XG4gIGxvZ2dlci5pbmZvKFwic3RhcnRlZCBHZW5pZSBDb2RlIGFuZCBtb2RlbCBnYXRld2F5XCIsIHtcbiAgICBwcm9maWxlOiBwcmVwYXJlZC5wcm9maWxlLFxuICAgIG1vZGVsOiBwcmVwYXJlZC5tb2RlbCxcbiAgICBnYXRld2F5OiBwcmVwYXJlZC5nYXRld2F5QmFzZVVybCxcbiAgICBob21lOiBwcmVwYXJlZC5ob21lLmhvbWUsXG4gIH0pO1xuICB0cnkge1xuICAgIGF3YWl0IHJlc3VsdDtcbiAgfSBmaW5hbGx5IHtcbiAgICBhd2FpdCBybShwcmVwYXJlZC5ob21lLm92ZXJsYXlQYXRoLCB7IGZvcmNlOiB0cnVlIH0pO1xuICB9XG59XG4iXX0=
|
|
@@ -8,14 +8,14 @@ import { buildServiceCommand } from "@dbx-tools/cli-service/cli";
|
|
|
8
8
|
import { defineService } from "@dbx-tools/cli-service/definition";
|
|
9
9
|
import { ModelGatewayCliOptionsSchema, resolveModelGatewayCliOptions, } from "@dbx-tools/shared-model-gateway/options";
|
|
10
10
|
import { Command } from "commander";
|
|
11
|
-
import { PACKAGE_VERSION } from "../../index.js";
|
|
12
11
|
import { startModelGateway } from "./server.js";
|
|
12
|
+
import { PACKAGE_VERSION } from "../../index.js";
|
|
13
13
|
const DEFAULT_DEPENDENCIES = {
|
|
14
14
|
start: startModelGateway,
|
|
15
15
|
};
|
|
16
16
|
/** Build the tray-only model-gateway service definition. */
|
|
17
17
|
export function modelGatewayServiceDefinition(options = {}) {
|
|
18
|
-
const { runtimeInfo: _, ...resolved } = resolveModelGatewayCliOptions(options);
|
|
18
|
+
const { runtimeInfo: _, bearerToken: _bearerToken, ...resolved } = resolveModelGatewayCliOptions(options);
|
|
19
19
|
const host = urlHost(resolved.listen.host);
|
|
20
20
|
return defineService(import.meta.url, {
|
|
21
21
|
id: "dbx-tools.cli-model-gateway",
|
|
@@ -60,4 +60,4 @@ function modelGatewayOptions(command) {
|
|
|
60
60
|
function urlHost(host) {
|
|
61
61
|
return host.includes(":") ? `[${host}]` : host;
|
|
62
62
|
}
|
|
63
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
63
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL21vZGVsLWdhdGV3YXkvY2xpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7QUFFSCxPQUFPLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxhQUFhLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN4RSxPQUFPLEVBQUUsbUJBQW1CLEVBQWtDLE1BQU0sNEJBQTRCLENBQUM7QUFDakcsT0FBTyxFQUFFLGFBQWEsRUFBNkIsTUFBTSxtQ0FBbUMsQ0FBQztBQUM3RixPQUFPLEVBQ0wsNEJBQTRCLEVBQzVCLDZCQUE2QixHQUc5QixNQUFNLHlDQUF5QyxDQUFDO0FBQ2pELE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFFcEMsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ2hELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQVNqRCxNQUFNLG9CQUFvQixHQUFnQztJQUN4RCxLQUFLLEVBQUUsaUJBQWlCO0NBQ3pCLENBQUM7QUFFRiw0REFBNEQ7QUFDNUQsTUFBTSxVQUFVLDZCQUE2QixDQUMzQyxVQUErQixFQUFFO0lBRWpDLE1BQU0sRUFDSixXQUFXLEVBQUUsQ0FBQyxFQUNkLFdBQVcsRUFBRSxZQUFZLEVBQ3pCLEdBQUcsUUFBUSxFQUNaLEdBQUcsNkJBQTZCLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDM0MsTUFBTSxJQUFJLEdBQUcsT0FBTyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDM0MsT0FBTyxhQUFhLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUU7UUFDcEMsRUFBRSxFQUFFLDZCQUE2QjtRQUNqQyxJQUFJLEVBQUUsbUJBQW1CO1FBQ3pCLE9BQU8sRUFBRTtZQUNQLE9BQU8sRUFBRSxtQkFBbUI7WUFDNUIsU0FBUyxFQUFFLGFBQWEsQ0FBQyxRQUFRLENBQUM7U0FDbkM7UUFDRCxJQUFJLEVBQUU7WUFDSjtnQkFDRSxJQUFJLEVBQUUsS0FBSztnQkFDWCxLQUFLLEVBQUUsUUFBUTtnQkFDZixHQUFHLEVBQUUsVUFBVSxJQUFJLElBQUksUUFBUSxDQUFDLE1BQU0sQ0FBQyxJQUFJLFlBQVk7YUFDeEQ7U0FDRjtLQUNGLENBQUMsQ0FBQztBQUNMLENBQUM7QUFFRCxxRkFBcUY7QUFDckYsTUFBTSxVQUFVLFlBQVksQ0FDMUIsSUFBSSxHQUFHLG1CQUFtQixFQUMxQixlQUE0QyxvQkFBb0I7SUFFaEUsTUFBTSxPQUFPLEdBQUcsZUFBZSxDQUFDO0lBQ2hDLE1BQU0sT0FBTyxHQUFHLE9BQU8sQ0FDckIsSUFBSSxPQUFPLEVBQUU7U0FDVixJQUFJLENBQUMsSUFBSSxDQUFDO1NBQ1YsV0FBVyxDQUFDLG1EQUFtRCxDQUFDO1NBQ2hFLE9BQU8sQ0FBQyxPQUFPLEVBQUUsZUFBZSxDQUFDLEVBQ3BDLDRCQUE0QixDQUM3QixDQUFDLE1BQU0sQ0FBQyxLQUFLLElBQUksRUFBRTtRQUNsQixNQUFNLE9BQU8sR0FBRyxtQkFBbUIsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUM3QyxJQUFJLE9BQU8sQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUN4QixPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsRUFBRSxjQUFjLEVBQUUsbUJBQW1CLEVBQUUsT0FBTyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDOUYsT0FBTztRQUNULENBQUM7UUFDRCxNQUFNLEVBQUUsV0FBVyxFQUFFLENBQUMsRUFBRSxHQUFHLGFBQWEsRUFBRSxHQUFHLE9BQU8sQ0FBQztRQUNyRCxNQUFNLFlBQVksQ0FBQyxLQUFLLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDMUMsQ0FBQyxDQUFDLENBQUM7SUFDSCxNQUFNLGNBQWMsR0FBRyxtQkFBbUIsQ0FBQyxHQUFHLEVBQUU7UUFDOUMsT0FBTyw2QkFBNkIsQ0FBQyxtQkFBbUIsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDO0lBQ3JFLENBQUMsRUFBRSxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDekIsT0FBTyxDQUFDLFVBQVUsQ0FBQyxjQUFjLENBQUMsQ0FBQztJQUNuQyxPQUFPLE9BQU8sQ0FBQztBQUNqQixDQUFDO0FBRUQsU0FBUyxtQkFBbUIsQ0FBQyxPQUFnQjtJQUMzQyxPQUFPLFNBQVMsQ0FBQyxPQUFPLEVBQUUsNEJBQTRCLENBQUMsQ0FBQztBQUMxRCxDQUFDO0FBRUQsU0FBUyxPQUFPLENBQUMsSUFBWTtJQUMzQixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztBQUNqRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBGb3JlZ3JvdW5kIGBkYnggbW9kZWwtZ2F0ZXdheWAgY29tbWFuZC5cbiAqXG4gKiBAbW9kdWxlXG4gKi9cblxuaW1wb3J0IHsgYWRkQXJncywgcGFyc2VBcmdzLCBzZXJpYWxpemVBcmdzIH0gZnJvbSBcIkBkYngtdG9vbHMvY2xpLWFyZ3NcIjtcbmltcG9ydCB7IGJ1aWxkU2VydmljZUNvbW1hbmQsIHR5cGUgQ2xpU2VydmljZUNsaURlcGVuZGVuY2llcyB9IGZyb20gXCJAZGJ4LXRvb2xzL2NsaS1zZXJ2aWNlL2NsaVwiO1xuaW1wb3J0IHsgZGVmaW5lU2VydmljZSwgdHlwZSBDbGlTZXJ2aWNlRGVmaW5pdGlvbiB9IGZyb20gXCJAZGJ4LXRvb2xzL2NsaS1zZXJ2aWNlL2RlZmluaXRpb25cIjtcbmltcG9ydCB7XG4gIE1vZGVsR2F0ZXdheUNsaU9wdGlvbnNTY2hlbWEsXG4gIHJlc29sdmVNb2RlbEdhdGV3YXlDbGlPcHRpb25zLFxuICB0eXBlIE1vZGVsR2F0ZXdheUNsaU9wdGlvbnMsXG4gIHR5cGUgTW9kZWxHYXRld2F5T3B0aW9ucyxcbn0gZnJvbSBcIkBkYngtdG9vbHMvc2hhcmVkLW1vZGVsLWdhdGV3YXkvb3B0aW9uc1wiO1xuaW1wb3J0IHsgQ29tbWFuZCB9IGZyb20gXCJjb21tYW5kZXJcIjtcblxuaW1wb3J0IHsgc3RhcnRNb2RlbEdhdGV3YXkgfSBmcm9tIFwiLi9zZXJ2ZXIudHNcIjtcbmltcG9ydCB7IFBBQ0tBR0VfVkVSU0lPTiB9IGZyb20gXCIuLi8uLi9pbmRleC50c1wiO1xuXG4vKiogSW5qZWN0YWJsZSBmb3JlZ3JvdW5kIGdhdGV3YXkgYm91bmRhcnkgZm9yIENMSSB0ZXN0cy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgTW9kZWxHYXRld2F5Q2xpRGVwZW5kZW5jaWVzIHtcbiAgc3RhcnQob3B0aW9uczogTW9kZWxHYXRld2F5T3B0aW9ucyk6IFByb21pc2U8dm9pZD47XG4gIC8qKiBPcHRpb25hbCBzZXJ2aWNlIENMSSBib3VuZGFyeSBmb3IgdGVzdHMgYW5kIGVtYmVkZGluZy4gKi9cbiAgcmVhZG9ubHkgc2VydmljZT86IENsaVNlcnZpY2VDbGlEZXBlbmRlbmNpZXM7XG59XG5cbmNvbnN0IERFRkFVTFRfREVQRU5ERU5DSUVTOiBNb2RlbEdhdGV3YXlDbGlEZXBlbmRlbmNpZXMgPSB7XG4gIHN0YXJ0OiBzdGFydE1vZGVsR2F0ZXdheSxcbn07XG5cbi8qKiBCdWlsZCB0aGUgdHJheS1vbmx5IG1vZGVsLWdhdGV3YXkgc2VydmljZSBkZWZpbml0aW9uLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1vZGVsR2F0ZXdheVNlcnZpY2VEZWZpbml0aW9uKFxuICBvcHRpb25zOiBNb2RlbEdhdGV3YXlPcHRpb25zID0ge30sXG4pOiBDbGlTZXJ2aWNlRGVmaW5pdGlvbiB7XG4gIGNvbnN0IHtcbiAgICBydW50aW1lSW5mbzogXyxcbiAgICBiZWFyZXJUb2tlbjogX2JlYXJlclRva2VuLFxuICAgIC4uLnJlc29sdmVkXG4gIH0gPSByZXNvbHZlTW9kZWxHYXRld2F5Q2xpT3B0aW9ucyhvcHRpb25zKTtcbiAgY29uc3QgaG9zdCA9IHVybEhvc3QocmVzb2x2ZWQubGlzdGVuLmhvc3QpO1xuICByZXR1cm4gZGVmaW5lU2VydmljZShpbXBvcnQubWV0YS51cmwsIHtcbiAgICBpZDogXCJkYngtdG9vbHMuY2xpLW1vZGVsLWdhdGV3YXlcIixcbiAgICBuYW1lOiBcImRieCBtb2RlbCBnYXRld2F5XCIsXG4gICAgY29tbWFuZDoge1xuICAgICAgYmluTmFtZTogXCJkYngtbW9kZWwtZ2F0ZXdheVwiLFxuICAgICAgYXJndW1lbnRzOiBzZXJpYWxpemVBcmdzKHJlc29sdmVkKSxcbiAgICB9LFxuICAgIG1lbnU6IFtcbiAgICAgIHtcbiAgICAgICAgdHlwZTogXCJ1cmxcIixcbiAgICAgICAgbGFiZWw6IFwiTW9kZWxzXCIsXG4gICAgICAgIHVybDogYGh0dHA6Ly8ke2hvc3R9OiR7cmVzb2x2ZWQubGlzdGVuLnBvcnR9L3YxL21vZGVsc2AsXG4gICAgICB9LFxuICAgIF0sXG4gIH0pO1xufVxuXG4vKiogQnVpbGQgZm9yZWdyb3VuZCBhbmQgc2VydmljZSBtb2RlbC1nYXRld2F5IGNvbW1hbmRzIHdpdGhvdXQgc3RhcnRpbmcgYSBzZXJ2ZXIuICovXG5leHBvcnQgZnVuY3Rpb24gYnVpbGRQcm9ncmFtKFxuICBuYW1lID0gXCJkYnggbW9kZWwtZ2F0ZXdheVwiLFxuICBkZXBlbmRlbmNpZXM6IE1vZGVsR2F0ZXdheUNsaURlcGVuZGVuY2llcyA9IERFRkFVTFRfREVQRU5ERU5DSUVTLFxuKTogQ29tbWFuZCB7XG4gIGNvbnN0IHZlcnNpb24gPSBQQUNLQUdFX1ZFUlNJT047XG4gIGNvbnN0IHByb2dyYW0gPSBhZGRBcmdzKFxuICAgIG5ldyBDb21tYW5kKClcbiAgICAgIC5uYW1lKG5hbWUpXG4gICAgICAuZGVzY3JpcHRpb24oXCJSdW4gb3IgbWFuYWdlIHRoZSBBcHBLaXQgRGF0YWJyaWNrcyBtb2RlbCBnYXRld2F5XCIpXG4gICAgICAudmVyc2lvbih2ZXJzaW9uLCBcIi12LCAtLXZlcnNpb25cIiksXG4gICAgTW9kZWxHYXRld2F5Q2xpT3B0aW9uc1NjaGVtYSxcbiAgKS5hY3Rpb24oYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IG9wdGlvbnMgPSBtb2RlbEdhdGV3YXlPcHRpb25zKHByb2dyYW0pO1xuICAgIGlmIChvcHRpb25zLnJ1bnRpbWVJbmZvKSB7XG4gICAgICBwcm9jZXNzLnN0ZG91dC53cml0ZShgJHtKU09OLnN0cmluZ2lmeSh7IGltcGxlbWVudGF0aW9uOiBcInR5cGVzY3JpcHQtYXBwa2l0XCIsIHZlcnNpb24gfSl9XFxuYCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHsgcnVudGltZUluZm86IF8sIC4uLnNlcnZlck9wdGlvbnMgfSA9IG9wdGlvbnM7XG4gICAgYXdhaXQgZGVwZW5kZW5jaWVzLnN0YXJ0KHNlcnZlck9wdGlvbnMpO1xuICB9KTtcbiAgY29uc3Qgc2VydmljZUNvbW1hbmQgPSBidWlsZFNlcnZpY2VDb21tYW5kKCgpID0+IHtcbiAgICByZXR1cm4gbW9kZWxHYXRld2F5U2VydmljZURlZmluaXRpb24obW9kZWxHYXRld2F5T3B0aW9ucyhwcm9ncmFtKSk7XG4gIH0sIGRlcGVuZGVuY2llcy5zZXJ2aWNlKTtcbiAgcHJvZ3JhbS5hZGRDb21tYW5kKHNlcnZpY2VDb21tYW5kKTtcbiAgcmV0dXJuIHByb2dyYW07XG59XG5cbmZ1bmN0aW9uIG1vZGVsR2F0ZXdheU9wdGlvbnMoY29tbWFuZDogQ29tbWFuZCk6IE1vZGVsR2F0ZXdheUNsaU9wdGlvbnMge1xuICByZXR1cm4gcGFyc2VBcmdzKGNvbW1hbmQsIE1vZGVsR2F0ZXdheUNsaU9wdGlvbnNTY2hlbWEpO1xufVxuXG5mdW5jdGlvbiB1cmxIb3N0KGhvc3Q6IHN0cmluZyk6IHN0cmluZyB7XG4gIHJldHVybiBob3N0LmluY2x1ZGVzKFwiOlwiKSA/IGBbJHtob3N0fV1gIDogaG9zdDtcbn1cbiJdfQ==
|
|
@@ -5,9 +5,12 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { server } from "@databricks/appkit";
|
|
7
7
|
import { type ModelGatewayOptions } from "@dbx-tools/shared-model-gateway/options";
|
|
8
|
+
import type express from "express";
|
|
8
9
|
type AppKitServerOptions = NonNullable<Parameters<typeof server>[0]>;
|
|
9
10
|
/** Resolve AppKit server settings for the loopback model gateway. */
|
|
10
11
|
export declare function modelGatewayServerOptions(options?: ModelGatewayOptions): AppKitServerOptions;
|
|
12
|
+
/** Require one bearer token without retaining or logging request credentials. */
|
|
13
|
+
export declare function gatewayBearerMiddleware(token: string): express.RequestHandler;
|
|
11
14
|
/** Start the foreground model gateway and keep its AppKit server active. */
|
|
12
15
|
export declare function startModelGateway(options?: ModelGatewayOptions): Promise<void>;
|
|
13
16
|
export {};
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @module
|
|
5
5
|
*/
|
|
6
|
+
import { createHash, timingSafeEqual } from "node:crypto";
|
|
6
7
|
import { createApp, server } from "@databricks/appkit";
|
|
7
|
-
import {
|
|
8
|
-
import { sendHealth } from "@dbx-tools/appkit-model-gateway/routes";
|
|
8
|
+
import { ModelGateway } from "@dbx-tools/appkit-model-gateway";
|
|
9
|
+
import { sendHealth, sendInference, sendModels } from "@dbx-tools/appkit-model-gateway/routes";
|
|
9
10
|
import { workspaceClient } from "@dbx-tools/databricks";
|
|
10
11
|
import { resolveModelGatewayOptions, } from "@dbx-tools/shared-model-gateway/options";
|
|
11
12
|
/** Resolve AppKit server settings for the loopback model gateway. */
|
|
@@ -19,22 +20,51 @@ function appKitServerOptions(options) {
|
|
|
19
20
|
port: options.listen.port,
|
|
20
21
|
};
|
|
21
22
|
}
|
|
23
|
+
/** Require one bearer token without retaining or logging request credentials. */
|
|
24
|
+
export function gatewayBearerMiddleware(token) {
|
|
25
|
+
const expected = createHash("sha256").update(token).digest();
|
|
26
|
+
return (request, response, next) => {
|
|
27
|
+
const authorization = request.header("authorization");
|
|
28
|
+
const match = /^Bearer\s+(.+)$/i.exec(authorization ?? "");
|
|
29
|
+
const actual = createHash("sha256")
|
|
30
|
+
.update(match?.[1] ?? "")
|
|
31
|
+
.digest();
|
|
32
|
+
if (match && timingSafeEqual(actual, expected)) {
|
|
33
|
+
next();
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
response
|
|
37
|
+
.status(401)
|
|
38
|
+
.setHeader("www-authenticate", "Bearer")
|
|
39
|
+
.json({
|
|
40
|
+
error: {
|
|
41
|
+
message: "Invalid or missing model-gateway bearer token.",
|
|
42
|
+
type: "authentication_error",
|
|
43
|
+
code: "invalid_bearer_token",
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
}
|
|
22
48
|
/** Start the foreground model gateway and keep its AppKit server active. */
|
|
23
49
|
export async function startModelGateway(options = {}) {
|
|
24
50
|
const resolved = resolveModelGatewayOptions(options);
|
|
51
|
+
const gateway = new ModelGateway();
|
|
25
52
|
const client = await workspaceClient.createWorkspaceClient({
|
|
26
53
|
...(resolved.profile ? { profile: resolved.profile } : {}),
|
|
27
54
|
});
|
|
28
55
|
await createApp({
|
|
29
56
|
client,
|
|
30
|
-
plugins: [
|
|
57
|
+
plugins: [server(appKitServerOptions(resolved))],
|
|
31
58
|
onPluginsReady(appkit) {
|
|
32
59
|
appkit.server.extend((application) => {
|
|
60
|
+
if (resolved.bearerToken) {
|
|
61
|
+
application.use(gatewayBearerMiddleware(resolved.bearerToken));
|
|
62
|
+
}
|
|
33
63
|
application.get("/api/healthz", (_request, response) => {
|
|
34
64
|
sendHealth(response);
|
|
35
65
|
});
|
|
36
66
|
application.get("/v1/models", (request, response) => {
|
|
37
|
-
void
|
|
67
|
+
void sendModels(gateway, request, response);
|
|
38
68
|
});
|
|
39
69
|
for (const [path, protocol] of [
|
|
40
70
|
["/v1/chat/completions", "openai-chat"],
|
|
@@ -43,11 +73,11 @@ export async function startModelGateway(options = {}) {
|
|
|
43
73
|
["/v1/embeddings", "openai-embeddings"],
|
|
44
74
|
]) {
|
|
45
75
|
application.post(path, (request, response) => {
|
|
46
|
-
void
|
|
76
|
+
void sendInference(gateway, protocol, request, response);
|
|
47
77
|
});
|
|
48
78
|
}
|
|
49
79
|
});
|
|
50
80
|
},
|
|
51
81
|
});
|
|
52
82
|
}
|
|
53
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
83
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL21vZGVsLWdhdGV3YXkvc2VydmVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7O0dBSUc7QUFFSCxPQUFPLEVBQUUsVUFBVSxFQUFFLGVBQWUsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUMxRCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3ZELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUMvRCxPQUFPLEVBQUUsVUFBVSxFQUFFLGFBQWEsRUFBRSxVQUFVLEVBQUUsTUFBTSx3Q0FBd0MsQ0FBQztBQUMvRixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDeEQsT0FBTyxFQUNMLDBCQUEwQixHQUczQixNQUFNLHlDQUF5QyxDQUFDO0FBS2pELHFFQUFxRTtBQUNyRSxNQUFNLFVBQVUseUJBQXlCLENBQUMsVUFBK0IsRUFBRTtJQUN6RSxPQUFPLG1CQUFtQixDQUFDLDBCQUEwQixDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7QUFDbEUsQ0FBQztBQUVELFNBQVMsbUJBQW1CLENBQUMsT0FBb0M7SUFDL0QsT0FBTztRQUNMLFNBQVMsRUFBRSxPQUFPLENBQUMsU0FBUztRQUM1QixJQUFJLEVBQUUsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJO1FBQ3pCLElBQUksRUFBRSxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUk7S0FDMUIsQ0FBQztBQUNKLENBQUM7QUFFRCxpRkFBaUY7QUFDakYsTUFBTSxVQUFVLHVCQUF1QixDQUFDLEtBQWE7SUFDbkQsTUFBTSxRQUFRLEdBQUcsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUM3RCxPQUFPLENBQUMsT0FBTyxFQUFFLFFBQVEsRUFBRSxJQUFJLEVBQUUs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TCxDQUFDO1lBQ0gsQ0FBQyxDQUFDLENBQUM7UUFDTCxDQUFDO0tBQ0YsQ0FBQyxDQUFDO0FBQ0wsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogRm9yZWdyb3VuZCBtb2RlbC1nYXRld2F5IHNlcnZlciBvd25lZCBieSB0aGUgQ0xJIHBhY2thZ2UuXG4gKlxuICogQG1vZHVsZVxuICovXG5cbmltcG9ydCB7IGNyZWF0ZUhhc2gsIHRpbWluZ1NhZmVFcXVhbCB9IGZyb20gXCJub2RlOmNyeXB0b1wiO1xuaW1wb3J0IHsgY3JlYXRlQXBwLCBzZXJ2ZXIgfSBmcm9tIFwiQGRhdGFicmlja3MvYXBwa2l0XCI7XG5pbXBvcnQgeyBNb2RlbEdhdGV3YXkgfSBmcm9tIFwiQGRieC10b29scy9hcHBraXQtbW9kZWwtZ2F0ZXdheVwiO1xuaW1wb3J0IHsgc2VuZEhlYWx0aCwgc2VuZEluZmVyZW5jZSwgc2VuZE1vZGVscyB9IGZyb20gXCJAZGJ4LXRvb2xzL2FwcGtpdC1tb2RlbC1nYXRld2F5L3JvdXRlc1wiO1xuaW1wb3J0IHsgd29ya3NwYWNlQ2xpZW50IH0gZnJvbSBcIkBkYngtdG9vbHMvZGF0YWJyaWNrc1wiO1xuaW1wb3J0IHtcbiAgcmVzb2x2ZU1vZGVsR2F0ZXdheU9wdGlvbnMsXG4gIHR5cGUgTW9kZWxHYXRld2F5T3B0aW9ucyxcbiAgdHlwZSBSZXNvbHZlZE1vZGVsR2F0ZXdheU9wdGlvbnMsXG59IGZyb20gXCJAZGJ4LXRvb2xzL3NoYXJlZC1tb2RlbC1nYXRld2F5L29wdGlvbnNcIjtcbmltcG9ydCB0eXBlIGV4cHJlc3MgZnJvbSBcImV4cHJlc3NcIjtcblxudHlwZSBBcHBLaXRTZXJ2ZXJPcHRpb25zID0gTm9uTnVsbGFibGU8UGFyYW1ldGVyczx0eXBlb2Ygc2VydmVyPlswXT47XG5cbi8qKiBSZXNvbHZlIEFwcEtpdCBzZXJ2ZXIgc2V0dGluZ3MgZm9yIHRoZSBsb29wYmFjayBtb2RlbCBnYXRld2F5LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1vZGVsR2F0ZXdheVNlcnZlck9wdGlvbnMob3B0aW9uczogTW9kZWxHYXRld2F5T3B0aW9ucyA9IHt9KTogQXBwS2l0U2VydmVyT3B0aW9ucyB7XG4gIHJldHVybiBhcHBLaXRTZXJ2ZXJPcHRpb25zKHJlc29sdmVNb2RlbEdhdGV3YXlPcHRpb25zKG9wdGlvbnMpKTtcbn1cblxuZnVuY3Rpb24gYXBwS2l0U2VydmVyT3B0aW9ucyhvcHRpb25zOiBSZXNvbHZlZE1vZGVsR2F0ZXdheU9wdGlvbnMpOiBBcHBLaXRTZXJ2ZXJPcHRpb25zIHtcbiAgcmV0dXJuIHtcbiAgICBib2R5TGltaXQ6IG9wdGlvbnMuYm9keUxpbWl0LFxuICAgIGhvc3Q6IG9wdGlvbnMubGlzdGVuLmhvc3QsXG4gICAgcG9ydDogb3B0aW9ucy5saXN0ZW4ucG9ydCxcbiAgfTtcbn1cblxuLyoqIFJlcXVpcmUgb25lIGJlYXJlciB0b2tlbiB3aXRob3V0IHJldGFpbmluZyBvciBsb2dnaW5nIHJlcXVlc3QgY3JlZGVudGlhbHMuICovXG5leHBvcnQgZnVuY3Rpb24gZ2F0ZXdheUJlYXJlck1pZGRsZXdhcmUodG9rZW46IHN0cmluZyk6IGV4cHJlc3MuUmVxdWVzdEhhbmRsZXIge1xuICBjb25zdCBleHBlY3RlZCA9IGNyZWF0ZUhhc2goXCJzaGEyNTZcIikudXBkYXRlKHRva2VuKS5kaWdlc3QoKTtcbiAgcmV0dXJuIChyZXF1ZXN0LCByZXNwb25zZSwgbmV4dCkgPT4ge1xuICAgIGNvbnN0IGF1dGhvcml6YXRpb24gPSByZXF1ZXN0LmhlYWRlcihcImF1dGhvcml6YXRpb25cIik7XG4gICAgY29uc3QgbWF0Y2ggPSAvXkJlYXJlclxccysoLispJC9pLmV4ZWMoYXV0aG9yaXphdGlvbiA/PyBcIlwiKTtcbiAgICBjb25zdCBhY3R1YWwgPSBjcmVhdGVIYXNoKFwic2hhMjU2XCIpXG4gICAgICAudXBkYXRlKG1hdGNoPy5bMV0gPz8gXCJcIilcbiAgICAgIC5kaWdlc3QoKTtcbiAgICBpZiAobWF0Y2ggJiYgdGltaW5nU2FmZUVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQpKSB7XG4gICAgICBuZXh0KCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHJlc3BvbnNlXG4gICAgICAuc3RhdHVzKDQwMSlcbiAgICAgIC5zZXRIZWFkZXIoXCJ3d3ctYXV0aGVudGljYXRlXCIsIFwiQmVhcmVyXCIpXG4gICAgICAuanNvbih7XG4gICAgICAgIGVycm9yOiB7XG4gICAgICAgICAgbWVzc2FnZTogXCJJbnZhbGlkIG9yIG1pc3NpbmcgbW9kZWwtZ2F0ZXdheSBiZWFyZXIgdG9rZW4uXCIsXG4gICAgICAgICAgdHlwZTogXCJhdXRoZW50aWNhdGlvbl9lcnJvclwiLFxuICAgICAgICAgIGNvZGU6IFwiaW52YWxpZF9iZWFyZXJfdG9rZW5cIixcbiAgICAgICAgfSxcbiAgICAgIH0pO1xuICB9O1xufVxuXG4vKiogU3RhcnQgdGhlIGZvcmVncm91bmQgbW9kZWwgZ2F0ZXdheSBhbmQga2VlcCBpdHMgQXBwS2l0IHNlcnZlciBhY3RpdmUuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gc3RhcnRNb2RlbEdhdGV3YXkob3B0aW9uczogTW9kZWxHYXRld2F5T3B0aW9ucyA9IHt9KTogUHJvbWlzZTx2b2lkPiB7XG4gIGNvbnN0IHJlc29sdmVkID0gcmVzb2x2ZU1vZGVsR2F0ZXdheU9wdGlvbnMob3B0aW9ucyk7XG4gIGNvbnN0IGdhdGV3YXkgPSBuZXcgTW9kZWxHYXRld2F5KCk7XG4gIGNvbnN0IGNsaWVudCA9IGF3YWl0IHdvcmtzcGFjZUNsaWVudC5jcmVhdGVXb3Jrc3BhY2VDbGllbnQoe1xuICAgIC4uLihyZXNvbHZlZC5wcm9maWxlID8geyBwcm9maWxlOiByZXNvbHZlZC5wcm9maWxlIH0gOiB7fSksXG4gIH0pO1xuICBhd2FpdCBjcmVhdGVBcHAoe1xuICAgIGNsaWVudCxcbiAgICBwbHVnaW5zOiBbc2VydmVyKGFwcEtpdFNlcnZlck9wdGlvbnMocmVzb2x2ZWQpKV0sXG4gICAgb25QbHVnaW5zUmVhZHkoYXBwa2l0KSB7XG4gICAgICBhcHBraXQuc2VydmVyLmV4dGVuZCgoYXBwbGljYXRpb24pID0+IHtcbiAgICAgICAgaWYgKHJlc29sdmVkLmJlYXJlclRva2VuKSB7XG4gICAgICAgICAgYXBwbGljYXRpb24udXNlKGdhdGV3YXlCZWFyZXJNaWRkbGV3YXJlKHJlc29sdmVkLmJlYXJlclRva2VuKSk7XG4gICAgICAgIH1cbiAgICAgICAgYXBwbGljYXRpb24uZ2V0KFwiL2FwaS9oZWFsdGh6XCIsIChfcmVxdWVzdCwgcmVzcG9uc2UpID0+IHtcbiAgICAgICAgICBzZW5kSGVhbHRoKHJlc3BvbnNlKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGFwcGxpY2F0aW9uLmdldChcIi92MS9tb2RlbHNcIiwgKHJlcXVlc3QsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgdm9pZCBzZW5kTW9kZWxzKGdhdGV3YXksIHJlcXVlc3QsIHJlc3BvbnNlKTtcbiAgICAgICAgfSk7XG4gICAgICAgIGZvciAoY29uc3QgW3BhdGgsIHByb3RvY29sXSBvZiBbXG4gICAgICAgICAgW1wiL3YxL2NoYXQvY29tcGxldGlvbnNcIiwgXCJvcGVuYWktY2hhdFwiXSxcbiAgICAgICAgICBbXCIvdjEvcmVzcG9uc2VzXCIsIFwib3BlbmFpLXJlc3BvbnNlc1wiXSxcbiAgICAgICAgICBbXCIvdjEvbWVzc2FnZXNcIiwgXCJhbnRocm9waWMtbWVzc2FnZXNcIl0sXG4gICAgICAgICAgW1wiL3YxL2VtYmVkZGluZ3NcIiwgXCJvcGVuYWktZW1iZWRkaW5nc1wiXSxcbiAgICAgICAgXSBhcyBjb25zdCkge1xuICAgICAgICAgIGFwcGxpY2F0aW9uLnBvc3QocGF0aCwgKHJlcXVlc3QsIHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgICB2b2lkIHNlbmRJbmZlcmVuY2UoZ2F0ZXdheSwgcHJvdG9jb2wsIHJlcXVlc3QsIHJlc3BvbnNlKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSxcbiAgfSk7XG59XG4iXX0=
|
package/lib/tsconfig.tsbuildinfo
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../src/bootstrap.ts","../src/bun.ts","../src/cli.ts","../src/root.ts","../src/appkit/cli.ts","../src/appkit/env-export.ts","../src/auth/cli.ts","../src/auth/options.ts","../src/graphiti/cli.ts","../src/graphiti/options.ts","../src/lakebase-proxy/cancellation.ts","../src/lakebase-proxy/cli.ts","../src/lakebase-proxy/options.ts","../src/lakebase-proxy/protocol.ts","../src/lakebase-proxy/proxy.ts","../src/model-gateway/cli.ts","../src/model-gateway/server.ts","../src/tunnel/app.ts","../src/tunnel/cli.ts","../src/tunnel/options.ts","../src/tunnel/proxy.ts","../index.ts","../bin/dbx-graphiti.ts","../bin/dbx-lakebase-proxy.ts","../bin/dbx-model-gateway.ts","../bin/dbx-tools.ts"],"version":"5.9.3"}
|
|
1
|
+
{"root":["../src/bootstrap.ts","../src/bun.ts","../src/cli.ts","../src/root.ts","../src/appkit/cli.ts","../src/appkit/env-export.ts","../src/auth/cli.ts","../src/auth/options.ts","../src/genie-code/cli.ts","../src/genie-code/config.ts","../src/genie-code/install.ts","../src/genie-code/options.ts","../src/genie-code/runner.ts","../src/genie-code/runtime.ts","../src/graphiti/cli.ts","../src/graphiti/options.ts","../src/lakebase-proxy/cancellation.ts","../src/lakebase-proxy/cli.ts","../src/lakebase-proxy/options.ts","../src/lakebase-proxy/protocol.ts","../src/lakebase-proxy/proxy.ts","../src/model-gateway/cli.ts","../src/model-gateway/server.ts","../src/tunnel/app.ts","../src/tunnel/cli.ts","../src/tunnel/options.ts","../src/tunnel/proxy.ts","../index.ts","../bin/dbx-genie.ts","../bin/dbx-graphiti.ts","../bin/dbx-lakebase-proxy.ts","../bin/dbx-model-gateway.ts","../bin/dbx-tools.ts"],"version":"5.9.3"}
|
package/package.json
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
},
|
|
9
9
|
"bin": {
|
|
10
10
|
"dbx": "./lib/bin/dbx-tools.js",
|
|
11
|
+
"dbx-genie": "./lib/bin/dbx-genie.js",
|
|
11
12
|
"dbx-graphiti": "./lib/bin/dbx-graphiti.js",
|
|
12
13
|
"dbx-lakebase-proxy": "./lib/bin/dbx-lakebase-proxy.js",
|
|
13
14
|
"dbx-model-gateway": "./lib/bin/dbx-model-gateway.js",
|
|
@@ -33,26 +34,30 @@
|
|
|
33
34
|
"dependencies": {
|
|
34
35
|
"@clack/prompts": "^1.7.0",
|
|
35
36
|
"@databricks/appkit": "0.81.0",
|
|
36
|
-
"@dbx-tools/appkit": "^0.9.
|
|
37
|
-
"@dbx-tools/appkit-model-gateway": "^0.9.
|
|
38
|
-
"@dbx-tools/auth": "^0.9.
|
|
39
|
-
"@dbx-tools/auth-gate": "^0.9.
|
|
40
|
-
"@dbx-tools/cli-args": "^0.9.
|
|
41
|
-
"@dbx-tools/cli-service": "^0.9.
|
|
42
|
-
"@dbx-tools/core": "^0.9.
|
|
43
|
-
"@dbx-tools/databricks": "^0.9.
|
|
44
|
-
"@dbx-tools/email": "^0.9.
|
|
45
|
-
"@dbx-tools/graphiti": "^0.9.
|
|
46
|
-
"@dbx-tools/lakebase": "^0.9.
|
|
47
|
-
"@dbx-tools/postgres": "^0.9.
|
|
48
|
-
"@dbx-tools/shared-auth": "^0.9.
|
|
49
|
-
"@dbx-tools/shared-core": "^0.9.
|
|
50
|
-
"@dbx-tools/shared-email": "^0.9.
|
|
51
|
-
"@dbx-tools/shared-
|
|
52
|
-
"@dbx-tools/
|
|
37
|
+
"@dbx-tools/appkit": "^0.9.61",
|
|
38
|
+
"@dbx-tools/appkit-model-gateway": "^0.9.61",
|
|
39
|
+
"@dbx-tools/auth": "^0.9.61",
|
|
40
|
+
"@dbx-tools/auth-gate": "^0.9.61",
|
|
41
|
+
"@dbx-tools/cli-args": "^0.9.61",
|
|
42
|
+
"@dbx-tools/cli-service": "^0.9.61",
|
|
43
|
+
"@dbx-tools/core": "^0.9.61",
|
|
44
|
+
"@dbx-tools/databricks": "^0.9.61",
|
|
45
|
+
"@dbx-tools/email": "^0.9.61",
|
|
46
|
+
"@dbx-tools/graphiti": "^0.9.61",
|
|
47
|
+
"@dbx-tools/lakebase": "^0.9.61",
|
|
48
|
+
"@dbx-tools/postgres": "^0.9.61",
|
|
49
|
+
"@dbx-tools/shared-auth": "^0.9.61",
|
|
50
|
+
"@dbx-tools/shared-core": "^0.9.61",
|
|
51
|
+
"@dbx-tools/shared-email": "^0.9.61",
|
|
52
|
+
"@dbx-tools/shared-genie-code": "^0.9.61",
|
|
53
|
+
"@dbx-tools/shared-model-gateway": "^0.9.61",
|
|
54
|
+
"@dbx-tools/tunnel": "^0.9.61",
|
|
53
55
|
"commander": "^15.0.0",
|
|
56
|
+
"concurrently": "^10.0.3",
|
|
57
|
+
"get-port": "^7.1.0",
|
|
54
58
|
"http-proxy-3": "^1.23.1",
|
|
55
59
|
"pg": "^8.22.0",
|
|
60
|
+
"smol-toml": "1.8.0",
|
|
56
61
|
"zod": "4.3.6"
|
|
57
62
|
},
|
|
58
63
|
"main": "./lib/index.js",
|
|
@@ -63,6 +68,7 @@
|
|
|
63
68
|
"types": "./lib/index.d.ts",
|
|
64
69
|
"bin": {
|
|
65
70
|
"dbx": "./lib/bin/dbx-tools.js",
|
|
71
|
+
"dbx-genie": "./lib/bin/dbx-genie.js",
|
|
66
72
|
"dbx-graphiti": "./lib/bin/dbx-graphiti.js",
|
|
67
73
|
"dbx-lakebase-proxy": "./lib/bin/dbx-lakebase-proxy.js",
|
|
68
74
|
"dbx-model-gateway": "./lib/bin/dbx-model-gateway.js",
|
|
@@ -113,6 +119,14 @@
|
|
|
113
119
|
"types": "./lib/src/graphiti/options.d.ts",
|
|
114
120
|
"default": "./lib/src/graphiti/options.js"
|
|
115
121
|
},
|
|
122
|
+
"./genie": {
|
|
123
|
+
"types": "./lib/src/genie-code/cli.d.ts",
|
|
124
|
+
"default": "./lib/src/genie-code/cli.js"
|
|
125
|
+
},
|
|
126
|
+
"./genie/options": {
|
|
127
|
+
"types": "./lib/src/genie-code/options.d.ts",
|
|
128
|
+
"default": "./lib/src/genie-code/options.js"
|
|
129
|
+
},
|
|
116
130
|
"./lakebase-proxy": {
|
|
117
131
|
"types": "./lib/src/lakebase-proxy/cli.d.ts",
|
|
118
132
|
"default": "./lib/src/lakebase-proxy/cli.js"
|
|
@@ -140,7 +154,7 @@
|
|
|
140
154
|
"./package.json": "./package.json"
|
|
141
155
|
}
|
|
142
156
|
},
|
|
143
|
-
"version": "0.9.
|
|
157
|
+
"version": "0.9.61",
|
|
144
158
|
"types": "./lib/index.d.ts",
|
|
145
159
|
"dbxToolsConfig": {
|
|
146
160
|
"tags": [
|
|
@@ -193,6 +207,14 @@
|
|
|
193
207
|
"types": "./lib/src/graphiti/options.d.ts",
|
|
194
208
|
"default": "./lib/src/graphiti/options.js"
|
|
195
209
|
},
|
|
210
|
+
"./genie": {
|
|
211
|
+
"types": "./lib/src/genie-code/cli.d.ts",
|
|
212
|
+
"default": "./lib/src/genie-code/cli.js"
|
|
213
|
+
},
|
|
214
|
+
"./genie/options": {
|
|
215
|
+
"types": "./lib/src/genie-code/options.d.ts",
|
|
216
|
+
"default": "./lib/src/genie-code/options.js"
|
|
217
|
+
},
|
|
196
218
|
"./lakebase-proxy": {
|
|
197
219
|
"types": "./lib/src/lakebase-proxy/cli.d.ts",
|
|
198
220
|
"default": "./lib/src/lakebase-proxy/cli.js"
|
package/src/auth/cli.ts
CHANGED
|
@@ -123,10 +123,20 @@ export function buildProgram(
|
|
|
123
123
|
...(tokenOptions.login ? {} : { login: false }),
|
|
124
124
|
...(tokenOptions.forceRefresh ? { refresh: true } : {}),
|
|
125
125
|
});
|
|
126
|
-
dependencies.
|
|
126
|
+
if (tokenOptions.format === "text") dependencies.writeText(token.accessToken);
|
|
127
|
+
else dependencies.writeJson(tokenJson(token));
|
|
127
128
|
});
|
|
128
129
|
});
|
|
129
130
|
|
|
131
|
+
program
|
|
132
|
+
.command("headers")
|
|
133
|
+
.description("Return current Databricks authentication headers")
|
|
134
|
+
.action(async () => {
|
|
135
|
+
await withAuth(options(), dependencies, async ({ auth }) => {
|
|
136
|
+
dependencies.writeJson(await auth.headers());
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
130
140
|
program
|
|
131
141
|
.command("profile")
|
|
132
142
|
.description("Print the configured or automatically detected profile")
|
package/src/auth/options.ts
CHANGED
|
@@ -48,6 +48,10 @@ export const TokenCommandOptionsSchema = z
|
|
|
48
48
|
.object({
|
|
49
49
|
forceRefresh: z.boolean().default(false).describe("Refresh the token before returning it."),
|
|
50
50
|
login: z.boolean().default(true).describe("Log in when credentials are missing or invalid."),
|
|
51
|
+
format: z
|
|
52
|
+
.enum(["json", "text"])
|
|
53
|
+
.default("json")
|
|
54
|
+
.describe("Output structured token metadata or only the access token."),
|
|
51
55
|
})
|
|
52
56
|
.strict()
|
|
53
57
|
.describe("Options for returning a Databricks access token.");
|
package/src/cli.ts
CHANGED
|
@@ -59,8 +59,9 @@ export async function prepareAndRunProjen(projenArgs: string[], startDir?: strin
|
|
|
59
59
|
/**
|
|
60
60
|
* Mount `name` as a command that captures every following token verbatim and
|
|
61
61
|
* hands it to the program `load()` resolves. `helpOption(false)` is what lets
|
|
62
|
-
* `--help` through to the child instead of being answered here, and
|
|
63
|
-
*
|
|
62
|
+
* `--help` through to the child instead of being answered here, and
|
|
63
|
+
* `passThroughOptions()` keeps unknown flags in that token list so the child
|
|
64
|
+
* program owns them.
|
|
64
65
|
*/
|
|
65
66
|
function addForwardedCommand(
|
|
66
67
|
program: Command,
|
|
@@ -73,6 +74,7 @@ function addForwardedCommand(
|
|
|
73
74
|
.description(description)
|
|
74
75
|
.argument("[args...]", `arguments forwarded to ${name}`)
|
|
75
76
|
.allowUnknownOption()
|
|
77
|
+
.passThroughOptions()
|
|
76
78
|
.allowExcessArguments()
|
|
77
79
|
.helpOption(false)
|
|
78
80
|
.action(async (args: string[]) => {
|
|
@@ -88,6 +90,7 @@ export function buildProgram(name: string = PROGRAM_NAMES[0]): Command {
|
|
|
88
90
|
.description(
|
|
89
91
|
"Databricks developer tools: workspace lifecycle, AppKit env, auth, tunnels, and local proxies",
|
|
90
92
|
)
|
|
93
|
+
.enablePositionalOptions()
|
|
91
94
|
.showHelpAfterError()
|
|
92
95
|
.helpOption("-h, --help", `Show ${name} help`);
|
|
93
96
|
|
|
@@ -137,6 +140,13 @@ export function buildProgram(name: string = PROGRAM_NAMES[0]): Command {
|
|
|
137
140
|
async () => (await import("./model-gateway/cli.ts")).buildProgram,
|
|
138
141
|
);
|
|
139
142
|
|
|
143
|
+
addForwardedCommand(
|
|
144
|
+
program,
|
|
145
|
+
"genie",
|
|
146
|
+
"Run managed Genie Code through a local Databricks model gateway",
|
|
147
|
+
async () => (await import("./genie-code/cli.ts")).buildProgram,
|
|
148
|
+
);
|
|
149
|
+
|
|
140
150
|
addForwardedCommand(
|
|
141
151
|
program,
|
|
142
152
|
"graphiti",
|
|
@@ -158,6 +168,7 @@ export async function buildDocumentationProgram(name: string = PROGRAM_NAMES[0])
|
|
|
158
168
|
(await import("./tunnel/cli.ts")).buildProgram("tunnel"),
|
|
159
169
|
(await import("./lakebase-proxy/cli.ts")).buildProgram("lakebase-proxy"),
|
|
160
170
|
(await import("./model-gateway/cli.ts")).buildProgram("model-gateway"),
|
|
171
|
+
(await import("./genie-code/cli.ts")).buildProgram("genie"),
|
|
161
172
|
(await import("./graphiti/cli.ts")).buildProgram("graphiti"),
|
|
162
173
|
);
|
|
163
174
|
return program;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Managed `dbx genie` command.
|
|
3
|
+
*
|
|
4
|
+
* @module
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { addArgs, parseArgs } from "@dbx-tools/cli-args";
|
|
8
|
+
import { Command } from "commander";
|
|
9
|
+
|
|
10
|
+
import { GenieCodeCliOptionsSchema, type GenieCodeCliOptions } from "./options.ts";
|
|
11
|
+
import { runGenieCode } from "./runtime.ts";
|
|
12
|
+
|
|
13
|
+
/** Injectable managed Genie execution boundary for parser tests and embedding. */
|
|
14
|
+
export interface GenieCodeCliDependencies {
|
|
15
|
+
run(input: {
|
|
16
|
+
cwd: string;
|
|
17
|
+
genieArgs: readonly string[];
|
|
18
|
+
options: GenieCodeCliOptions;
|
|
19
|
+
}): Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const DEFAULT_DEPENDENCIES: GenieCodeCliDependencies = {
|
|
23
|
+
run: runGenieCode,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/** Build the managed Genie Code command without executing it. */
|
|
27
|
+
export function buildProgram(
|
|
28
|
+
name = "dbx genie",
|
|
29
|
+
dependencies: GenieCodeCliDependencies = DEFAULT_DEPENDENCIES,
|
|
30
|
+
): Command {
|
|
31
|
+
const program = addArgs(
|
|
32
|
+
new Command()
|
|
33
|
+
.name(name)
|
|
34
|
+
.description("Run Genie Code through an authenticated local Databricks model gateway")
|
|
35
|
+
.argument(
|
|
36
|
+
"[genieArgs...]",
|
|
37
|
+
"arguments and unknown flags forwarded to Genie Code; wrapper options may be separated with --",
|
|
38
|
+
)
|
|
39
|
+
.allowUnknownOption()
|
|
40
|
+
.passThroughOptions()
|
|
41
|
+
.allowExcessArguments()
|
|
42
|
+
.showHelpAfterError(),
|
|
43
|
+
GenieCodeCliOptionsSchema,
|
|
44
|
+
);
|
|
45
|
+
program.action(async (genieArgs: string[]) => {
|
|
46
|
+
await dependencies.run({
|
|
47
|
+
cwd: process.cwd(),
|
|
48
|
+
genieArgs,
|
|
49
|
+
options: parseArgs(program, GenieCodeCliOptionsSchema),
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
return program;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Parse argv and run managed Genie Code. */
|
|
56
|
+
export async function runCli(argv: string[]): Promise<void> {
|
|
57
|
+
await buildProgram().parseAsync(argv);
|
|
58
|
+
}
|