@openbkn/bkn-sdk 0.1.1-alpha.16 → 0.1.1-alpha.19
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 -132
- package/NOTICE +6 -16
- package/README.md +5 -9
- package/README.zh.md +5 -8
- package/dist/{chunk-SH2KLES5.js → chunk-ISJHU26W.js} +454 -147
- package/dist/cli.js +196 -96
- package/dist/index.d.ts +266 -58
- package/dist/index.js +1 -1
- package/package.json +6 -5
- package/dist/chunk-SH2KLES5.js.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/index.js.map +0 -1
|
@@ -78,6 +78,23 @@ function truncate(s, n) {
|
|
|
78
78
|
|
|
79
79
|
// src/auth/oauth.ts
|
|
80
80
|
import { spawn } from "child_process";
|
|
81
|
+
|
|
82
|
+
// src/api/tls.ts
|
|
83
|
+
import { Agent, fetch as undiciFetch } from "undici";
|
|
84
|
+
var insecureAgent;
|
|
85
|
+
function insecureDispatcher() {
|
|
86
|
+
insecureAgent ??= new Agent({ connect: { rejectUnauthorized: false } });
|
|
87
|
+
return insecureAgent;
|
|
88
|
+
}
|
|
89
|
+
function tlsFetch(insecure, url, init) {
|
|
90
|
+
if (!insecure) return fetch(url, init);
|
|
91
|
+
return undiciFetch(url, {
|
|
92
|
+
...init,
|
|
93
|
+
dispatcher: insecureDispatcher()
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// src/auth/oauth.ts
|
|
81
98
|
function normalizeBaseUrl(value) {
|
|
82
99
|
return value.replace(/\/+$/, "");
|
|
83
100
|
}
|
|
@@ -118,22 +135,9 @@ function mergeCookies(existing, res) {
|
|
|
118
135
|
for (const sc of setCookies) add(sc.split(";")[0]?.trim() ?? "");
|
|
119
136
|
return [...map.entries()].map(([k, v]) => `${k}=${v}`).join("; ");
|
|
120
137
|
}
|
|
121
|
-
async function
|
|
122
|
-
try {
|
|
123
|
-
const res = await fetch(`${normalizeBaseUrl(baseUrl)}/install-status.json`, {
|
|
124
|
-
headers: { Accept: "application/json" }
|
|
125
|
-
});
|
|
126
|
-
if (!res.ok) return null;
|
|
127
|
-
const j = await res.json();
|
|
128
|
-
if (!j.auth) return null;
|
|
129
|
-
return { enabled: Boolean(j.auth.enabled), stack: j.auth.stack };
|
|
130
|
-
} catch {
|
|
131
|
-
return null;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
async function refreshAccessToken(baseUrl, refreshToken, clientId = "openbkn-sdk") {
|
|
138
|
+
async function refreshAccessToken(baseUrl, refreshToken, clientId = "openbkn-sdk", insecure) {
|
|
135
139
|
const base = normalizeBaseUrl(baseUrl);
|
|
136
|
-
const res = await
|
|
140
|
+
const res = await tlsFetch(insecure, `${base}/oauth2/token`, {
|
|
137
141
|
method: "POST",
|
|
138
142
|
headers: {
|
|
139
143
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
@@ -163,10 +167,10 @@ var form = (body) => ({
|
|
|
163
167
|
},
|
|
164
168
|
body: new URLSearchParams(body).toString()
|
|
165
169
|
});
|
|
166
|
-
async function requestDeviceCode(base, clientId, scope, audience) {
|
|
170
|
+
async function requestDeviceCode(base, clientId, scope, audience, insecure) {
|
|
167
171
|
const params = { client_id: clientId, scope };
|
|
168
172
|
if (audience) params.audience = audience;
|
|
169
|
-
const res = await
|
|
173
|
+
const res = await tlsFetch(insecure, `${base}/oauth2/device/auth`, form(params));
|
|
170
174
|
if (!res.ok) {
|
|
171
175
|
throw new Error(`Device auth failed (${res.status}): ${await res.text() || res.statusText}`);
|
|
172
176
|
}
|
|
@@ -178,12 +182,13 @@ async function requestDeviceCode(base, clientId, scope, audience) {
|
|
|
178
182
|
}
|
|
179
183
|
return da;
|
|
180
184
|
}
|
|
181
|
-
async function pollDeviceToken(base, deviceCode, clientId, intervalMs, windowMs) {
|
|
185
|
+
async function pollDeviceToken(base, deviceCode, clientId, intervalMs, windowMs, insecure) {
|
|
182
186
|
let interval = intervalMs;
|
|
183
187
|
const deadline = Date.now() + windowMs;
|
|
184
188
|
while (Date.now() < deadline) {
|
|
185
189
|
await new Promise((r) => setTimeout(r, interval));
|
|
186
|
-
const tokRes = await
|
|
190
|
+
const tokRes = await tlsFetch(
|
|
191
|
+
insecure,
|
|
187
192
|
`${base}/oauth2/token`,
|
|
188
193
|
form({ grant_type: DEVICE_GRANT, device_code: deviceCode, client_id: clientId })
|
|
189
194
|
);
|
|
@@ -209,14 +214,27 @@ async function pollDeviceToken(base, deviceCode, clientId, intervalMs, windowMs)
|
|
|
209
214
|
async function deviceLogin(baseUrl, opts = {}) {
|
|
210
215
|
const base = normalizeBaseUrl(baseUrl);
|
|
211
216
|
const clientId = opts.clientId ?? DEFAULT_DEVICE_CLIENT_ID;
|
|
212
|
-
const da = await requestDeviceCode(
|
|
217
|
+
const da = await requestDeviceCode(
|
|
218
|
+
base,
|
|
219
|
+
clientId,
|
|
220
|
+
opts.scope ?? DEVICE_SCOPE,
|
|
221
|
+
opts.audience,
|
|
222
|
+
opts.insecure
|
|
223
|
+
);
|
|
213
224
|
opts.onPrompt?.({
|
|
214
225
|
userCode: da.user_code,
|
|
215
226
|
verificationUri: onBaseHost(base, da.verification_uri),
|
|
216
227
|
verificationUriComplete: da.verification_uri_complete ? onBaseHost(base, da.verification_uri_complete) : void 0
|
|
217
228
|
});
|
|
218
229
|
const windowMs = Math.min(opts.timeoutMs ?? Number.POSITIVE_INFINITY, da.expires_in * 1e3);
|
|
219
|
-
return pollDeviceToken(
|
|
230
|
+
return pollDeviceToken(
|
|
231
|
+
base,
|
|
232
|
+
da.device_code,
|
|
233
|
+
clientId,
|
|
234
|
+
(da.interval ?? 5) * 1e3,
|
|
235
|
+
windowMs,
|
|
236
|
+
opts.insecure
|
|
237
|
+
);
|
|
220
238
|
}
|
|
221
239
|
function onBaseHost(base, uri) {
|
|
222
240
|
try {
|
|
@@ -230,10 +248,16 @@ function onBaseHost(base, uri) {
|
|
|
230
248
|
async function credentialDeviceLogin(baseUrl, username, password, opts = {}) {
|
|
231
249
|
const base = normalizeBaseUrl(baseUrl);
|
|
232
250
|
const clientId = opts.clientId ?? DEFAULT_DEVICE_CLIENT_ID;
|
|
233
|
-
const da = await requestDeviceCode(
|
|
251
|
+
const da = await requestDeviceCode(
|
|
252
|
+
base,
|
|
253
|
+
clientId,
|
|
254
|
+
opts.scope ?? DEVICE_SCOPE,
|
|
255
|
+
opts.audience,
|
|
256
|
+
opts.insecure
|
|
257
|
+
);
|
|
234
258
|
let jar = "";
|
|
235
259
|
const hop = async (url, init) => {
|
|
236
|
-
const r = await
|
|
260
|
+
const r = await tlsFetch(opts.insecure, url, {
|
|
237
261
|
method: init?.method ?? "GET",
|
|
238
262
|
headers: { Cookie: jar, Accept: "text/html,*/*;q=0.8", ...init?.headers ?? {} },
|
|
239
263
|
body: init?.body,
|
|
@@ -271,38 +295,40 @@ async function credentialDeviceLogin(baseUrl, username, password, opts = {}) {
|
|
|
271
295
|
loc = r.headers.get("location");
|
|
272
296
|
}
|
|
273
297
|
const windowMs = Math.min(opts.timeoutMs ?? Number.POSITIVE_INFINITY, da.expires_in * 1e3);
|
|
274
|
-
return pollDeviceToken(
|
|
298
|
+
return pollDeviceToken(
|
|
299
|
+
base,
|
|
300
|
+
da.device_code,
|
|
301
|
+
clientId,
|
|
302
|
+
(da.interval ?? 5) * 1e3,
|
|
303
|
+
windowMs,
|
|
304
|
+
opts.insecure
|
|
305
|
+
);
|
|
275
306
|
}
|
|
276
307
|
|
|
277
308
|
// src/api/headers.ts
|
|
278
309
|
function buildHeaders(ctx, extra) {
|
|
279
310
|
return {
|
|
280
|
-
|
|
281
|
-
...ctx.token ? { authorization: `Bearer ${ctx.token}`, token: ctx.token } : {},
|
|
311
|
+
authorization: `Bearer ${ctx.token}`,
|
|
282
312
|
"x-business-domain": ctx.businessDomain,
|
|
283
313
|
...extra
|
|
284
314
|
};
|
|
285
315
|
}
|
|
286
316
|
|
|
287
|
-
// src/api/tls.ts
|
|
288
|
-
function applyTls(ctx) {
|
|
289
|
-
if (ctx.insecure && process.env.NODE_TLS_REJECT_UNAUTHORIZED !== "0") {
|
|
290
|
-
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
317
|
// src/api/http.ts
|
|
295
318
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
296
319
|
async function request(ctx, path, init = {}) {
|
|
297
320
|
const url = new URL(path.startsWith("http") ? path : `${ctx.baseUrl}${path}`);
|
|
298
321
|
for (const [k, v] of Object.entries(init.query ?? {})) {
|
|
299
|
-
if (
|
|
322
|
+
if (Array.isArray(v)) {
|
|
323
|
+
for (const item of v) url.searchParams.append(k, String(item));
|
|
324
|
+
} else if (v !== void 0) {
|
|
325
|
+
url.searchParams.set(k, String(v));
|
|
326
|
+
}
|
|
300
327
|
}
|
|
301
|
-
applyTls(ctx);
|
|
302
328
|
const hasBody = init.body !== void 0;
|
|
303
329
|
const controller = new AbortController();
|
|
304
330
|
const timer = setTimeout(() => controller.abort(), init.timeoutMs ?? DEFAULT_TIMEOUT_MS);
|
|
305
|
-
const send = () =>
|
|
331
|
+
const send = () => tlsFetch(ctx.insecure, url, {
|
|
306
332
|
method: init.method ?? (hasBody ? "POST" : "GET"),
|
|
307
333
|
headers: buildHeaders(ctx, {
|
|
308
334
|
...hasBody ? { "content-type": "application/json" } : {},
|
|
@@ -332,7 +358,12 @@ function hintFor(ctx, status2) {
|
|
|
332
358
|
async function tryRefresh(ctx) {
|
|
333
359
|
if (!ctx.refresh) return false;
|
|
334
360
|
try {
|
|
335
|
-
const t = await refreshAccessToken(
|
|
361
|
+
const t = await refreshAccessToken(
|
|
362
|
+
ctx.baseUrl,
|
|
363
|
+
ctx.refresh.refreshToken,
|
|
364
|
+
ctx.refresh.clientId,
|
|
365
|
+
ctx.insecure
|
|
366
|
+
);
|
|
336
367
|
ctx.token = t.accessToken;
|
|
337
368
|
if (t.refreshToken) ctx.refresh.refreshToken = t.refreshToken;
|
|
338
369
|
ctx.refresh.persist(t);
|
|
@@ -377,6 +408,7 @@ function isExpired(claims, nowMs = Date.now()) {
|
|
|
377
408
|
|
|
378
409
|
// src/config/store.ts
|
|
379
410
|
var PROFILE_RE = /^[A-Za-z0-9_-]{1,64}$/;
|
|
411
|
+
var USER_ID_RE = /^[A-Za-z0-9._@-]{1,128}$/;
|
|
380
412
|
var IS_WIN = process.platform === "win32";
|
|
381
413
|
function configDir() {
|
|
382
414
|
return process.env.BKN_CONFIG_DIR ?? join(homedir(), ".bkn");
|
|
@@ -403,7 +435,14 @@ function userDir(baseUrl, userId) {
|
|
|
403
435
|
return join(platformDir(baseUrl), "users", userId);
|
|
404
436
|
}
|
|
405
437
|
function userIdFromToken(token) {
|
|
406
|
-
|
|
438
|
+
const sub = decodeJwt(token.idToken ?? "")?.sub ?? decodeJwt(token.accessToken)?.sub;
|
|
439
|
+
if (sub === void 0) return "default";
|
|
440
|
+
if (typeof sub !== "string" || !USER_ID_RE.test(sub) || sub === "." || sub === "..") {
|
|
441
|
+
throw new Error(
|
|
442
|
+
`Token subject '${String(sub)}' is not a usable user id (expected 1-128 chars from [A-Za-z0-9._@-]). Refusing to store this token.`
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
return sub;
|
|
407
446
|
}
|
|
408
447
|
function readState() {
|
|
409
448
|
return readJson(statePath()) ?? {};
|
|
@@ -428,10 +467,10 @@ function readToken(baseUrl, userId = activeUserId(baseUrl)) {
|
|
|
428
467
|
if (!userId) return void 0;
|
|
429
468
|
return readJson(join(userDir(baseUrl, userId), "token.json")) ?? void 0;
|
|
430
469
|
}
|
|
431
|
-
function writeToken(baseUrl, token) {
|
|
470
|
+
function writeToken(baseUrl, token, opts = {}) {
|
|
432
471
|
const userId = userIdFromToken(token);
|
|
433
472
|
writeJson(join(userDir(baseUrl, userId), "token.json"), token, 384);
|
|
434
|
-
setActiveUser(baseUrl, userId);
|
|
473
|
+
if (opts.setActive !== false) setActiveUser(baseUrl, userId);
|
|
435
474
|
return userId;
|
|
436
475
|
}
|
|
437
476
|
function deleteToken(baseUrl, userId = activeUserId(baseUrl)) {
|
|
@@ -470,6 +509,14 @@ function listPlatforms() {
|
|
|
470
509
|
}
|
|
471
510
|
return out;
|
|
472
511
|
}
|
|
512
|
+
function findUserId(baseUrl, userOrName) {
|
|
513
|
+
const users = listPlatforms().find((p) => p.baseUrl === baseUrl)?.users ?? [];
|
|
514
|
+
const match = users.find((u) => u.userId === userOrName) ?? users.find((u) => (u.username ?? u.displayName) === userOrName);
|
|
515
|
+
return match?.userId ?? null;
|
|
516
|
+
}
|
|
517
|
+
function usersOfPlatform(baseUrl) {
|
|
518
|
+
return listPlatforms().find((p) => p.baseUrl === baseUrl)?.users ?? [];
|
|
519
|
+
}
|
|
473
520
|
function decodeKey(key) {
|
|
474
521
|
try {
|
|
475
522
|
const b64 = key.replace(/-/g, "+").replace(/_/g, "/");
|
|
@@ -495,6 +542,14 @@ function writeJson(path, value, mode = 384) {
|
|
|
495
542
|
}
|
|
496
543
|
|
|
497
544
|
// src/config/resolve.ts
|
|
545
|
+
function resolveUserId(baseUrl, userOrName) {
|
|
546
|
+
const id = findUserId(baseUrl, userOrName);
|
|
547
|
+
if (id) return id;
|
|
548
|
+
const known = usersOfPlatform(baseUrl).map((u) => u.username ?? u.userId).join(", ");
|
|
549
|
+
throw new InputError(
|
|
550
|
+
`No saved user '${userOrName}' on ${baseUrl}. Saved: ${known || "(none)"}. See \`openbkn auth users ${baseUrl}\`.`
|
|
551
|
+
);
|
|
552
|
+
}
|
|
498
553
|
function resolveContext(opts = {}) {
|
|
499
554
|
const baseUrl = opts.baseUrl ?? process.env.BKN_BASE_URL ?? activePlatform();
|
|
500
555
|
if (!baseUrl) {
|
|
@@ -503,22 +558,29 @@ function resolveContext(opts = {}) {
|
|
|
503
558
|
);
|
|
504
559
|
}
|
|
505
560
|
const normalized = baseUrl.replace(/\/+$/, "");
|
|
506
|
-
const
|
|
561
|
+
const user = opts.user ?? process.env.BKN_USER;
|
|
562
|
+
const stored = user ? readToken(normalized, resolveUserId(normalized, user)) : readToken(normalized);
|
|
507
563
|
const explicit = opts.token ?? process.env.BKN_TOKEN;
|
|
508
564
|
const token = explicit ?? stored?.accessToken ?? "";
|
|
509
|
-
if (!token
|
|
565
|
+
if (!token) {
|
|
510
566
|
throw new InputError("No access token. Set BKN_TOKEN or run `openbkn auth login`.");
|
|
511
567
|
}
|
|
512
|
-
const insecure = opts.insecure ??
|
|
568
|
+
const insecure = opts.insecure ?? false;
|
|
513
569
|
const refresh = !explicit && stored?.refreshToken ? {
|
|
514
570
|
refreshToken: stored.refreshToken,
|
|
515
571
|
persist: (t) => {
|
|
516
|
-
writeToken(
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
572
|
+
writeToken(
|
|
573
|
+
normalized,
|
|
574
|
+
{
|
|
575
|
+
...stored,
|
|
576
|
+
accessToken: t.accessToken,
|
|
577
|
+
refreshToken: t.refreshToken ?? stored.refreshToken,
|
|
578
|
+
idToken: t.idToken ?? stored.idToken
|
|
579
|
+
},
|
|
580
|
+
// `--user` picks an identity for this command only; a refresh
|
|
581
|
+
// must not promote it to the default for the next one.
|
|
582
|
+
{ setActive: !user }
|
|
583
|
+
);
|
|
522
584
|
}
|
|
523
585
|
} : void 0;
|
|
524
586
|
return {
|
|
@@ -581,6 +643,13 @@ async function setUserPasswordSafe(ctx, userId, password) {
|
|
|
581
643
|
});
|
|
582
644
|
return { ok: true };
|
|
583
645
|
}
|
|
646
|
+
async function changePasswordSafe(ctx, account, oldPassword, newPassword) {
|
|
647
|
+
await request(ctx, "/api/safe/v1/auth/change-password", {
|
|
648
|
+
method: "POST",
|
|
649
|
+
body: { account, old_password: oldPassword, new_password: newPassword }
|
|
650
|
+
});
|
|
651
|
+
return { ok: true };
|
|
652
|
+
}
|
|
584
653
|
function getUserRolesSafe(ctx, userId) {
|
|
585
654
|
return request(ctx, `${ADMIN}/role-bindings`, { query: { accessor_id: userId } });
|
|
586
655
|
}
|
|
@@ -694,6 +763,43 @@ async function setRolePermissionSafe(ctx, roleId, grant, perm) {
|
|
|
694
763
|
});
|
|
695
764
|
return { ok: true };
|
|
696
765
|
}
|
|
766
|
+
function getLicenseSafe(ctx) {
|
|
767
|
+
return request(ctx, `${ADMIN}/license`);
|
|
768
|
+
}
|
|
769
|
+
async function importLicenseSafe(ctx, licenseText, opts = {}) {
|
|
770
|
+
const text = licenseText.trim();
|
|
771
|
+
if (!text) throw new InputError("license text is empty");
|
|
772
|
+
try {
|
|
773
|
+
return await request(ctx, `${ADMIN}/license/${opts.receipt ? "receipt" : "import"}`, {
|
|
774
|
+
method: "POST",
|
|
775
|
+
body: { license: text }
|
|
776
|
+
});
|
|
777
|
+
} catch (err) {
|
|
778
|
+
if (err instanceof HttpError) {
|
|
779
|
+
const stored = storedImport(err.body);
|
|
780
|
+
if (stored) return stored;
|
|
781
|
+
}
|
|
782
|
+
throw err;
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
function storedImport(body) {
|
|
786
|
+
try {
|
|
787
|
+
const parsed = JSON.parse(body);
|
|
788
|
+
if (parsed && parsed.stored === true) return parsed;
|
|
789
|
+
} catch {
|
|
790
|
+
}
|
|
791
|
+
return null;
|
|
792
|
+
}
|
|
793
|
+
function activateLicenseSafe(ctx) {
|
|
794
|
+
return request(ctx, `${ADMIN}/license/activate`, { method: "POST" });
|
|
795
|
+
}
|
|
796
|
+
async function removeLicenseSafe(ctx) {
|
|
797
|
+
await request(ctx, `${ADMIN}/license`, { method: "DELETE" });
|
|
798
|
+
return { ok: true };
|
|
799
|
+
}
|
|
800
|
+
function getLicenseFingerprintSafe(ctx) {
|
|
801
|
+
return request(ctx, `${ADMIN}/license/fingerprint`);
|
|
802
|
+
}
|
|
697
803
|
|
|
698
804
|
// src/resources/admin.ts
|
|
699
805
|
var DEFAULT_NEW_USER_PASSWORD = "openbkn";
|
|
@@ -754,7 +860,13 @@ function admin(ctx) {
|
|
|
754
860
|
roleUpdate: (roleId, input) => updateRoleSafe(ctx, roleId, input),
|
|
755
861
|
roleDelete: (roleId) => deleteRoleSafe(ctx, roleId),
|
|
756
862
|
rolePermission: (roleId, grant, resourceType, resourceId, operations) => setRolePermissionSafe(ctx, roleId, grant, { resourceType, resourceId, operations }),
|
|
757
|
-
auditList: (_opts) => notOnSafe("audit list")
|
|
863
|
+
auditList: (_opts) => notOnSafe("audit list"),
|
|
864
|
+
// ── license (cluster license hub; weak judgements — display/ops only) ──
|
|
865
|
+
licenseGet: () => getLicenseSafe(ctx),
|
|
866
|
+
licenseImport: (licenseText, opts) => importLicenseSafe(ctx, licenseText, opts),
|
|
867
|
+
licenseActivate: () => activateLicenseSafe(ctx),
|
|
868
|
+
licenseRemove: () => removeLicenseSafe(ctx),
|
|
869
|
+
licenseFingerprint: () => getLicenseFingerprintSafe(ctx)
|
|
758
870
|
};
|
|
759
871
|
}
|
|
760
872
|
|
|
@@ -826,7 +938,6 @@ function extractText(result) {
|
|
|
826
938
|
return "";
|
|
827
939
|
}
|
|
828
940
|
async function sendChat(ctx, info, query, opts = {}) {
|
|
829
|
-
applyTls(ctx);
|
|
830
941
|
const body = {
|
|
831
942
|
agent_id: info.id,
|
|
832
943
|
agent_key: info.key,
|
|
@@ -837,7 +948,7 @@ async function sendChat(ctx, info, query, opts = {}) {
|
|
|
837
948
|
if (opts.conversationId) body.conversation_id = opts.conversationId;
|
|
838
949
|
const res = await authFetch(
|
|
839
950
|
ctx,
|
|
840
|
-
() =>
|
|
951
|
+
() => tlsFetch(ctx.insecure, `${ctx.baseUrl}${FACTORY}/v1/app/${info.key}/chat/completion`, {
|
|
841
952
|
method: "POST",
|
|
842
953
|
headers: {
|
|
843
954
|
...buildHeaders(ctx),
|
|
@@ -1063,10 +1174,9 @@ function parseBody(text) {
|
|
|
1063
1174
|
}
|
|
1064
1175
|
}
|
|
1065
1176
|
async function post(ctx, knId, sessionId, body) {
|
|
1066
|
-
applyTls(ctx);
|
|
1067
1177
|
const res = await authFetch(
|
|
1068
1178
|
ctx,
|
|
1069
|
-
() =>
|
|
1179
|
+
() => tlsFetch(ctx.insecure, mcpUrl(ctx), {
|
|
1070
1180
|
method: "POST",
|
|
1071
1181
|
headers: headers(ctx, knId, sessionId),
|
|
1072
1182
|
body: JSON.stringify(body)
|
|
@@ -1522,7 +1632,16 @@ function listResources2(ctx, opts = {}) {
|
|
|
1522
1632
|
catalog_id: opts.datasourceId || void 0,
|
|
1523
1633
|
name: opts.name || void 0,
|
|
1524
1634
|
category: opts.category || void 0,
|
|
1525
|
-
|
|
1635
|
+
status: opts.status || void 0,
|
|
1636
|
+
database: opts.database || void 0,
|
|
1637
|
+
limit: opts.limit && opts.limit > 0 ? opts.limit : void 0,
|
|
1638
|
+
offset: opts.offset,
|
|
1639
|
+
sort: opts.sort,
|
|
1640
|
+
direction: opts.direction,
|
|
1641
|
+
include_extensions: opts.includeExtensions === void 0 ? void 0 : String(opts.includeExtensions),
|
|
1642
|
+
include_extension_keys: opts.includeExtensionKeys || void 0,
|
|
1643
|
+
extension_key: opts.extensionPairs?.map((p) => p.key),
|
|
1644
|
+
extension_value: opts.extensionPairs?.map((p) => p.value)
|
|
1526
1645
|
}
|
|
1527
1646
|
});
|
|
1528
1647
|
}
|
|
@@ -1532,18 +1651,103 @@ function getResource(ctx, id) {
|
|
|
1532
1651
|
function createResourceRaw(ctx, body) {
|
|
1533
1652
|
return request(ctx, BASE3, { method: "POST", body });
|
|
1534
1653
|
}
|
|
1535
|
-
function
|
|
1654
|
+
function updateResourceRaw(ctx, id, body) {
|
|
1655
|
+
return request(ctx, `${BASE3}/${encodeURIComponent(id)}`, { method: "PUT", body });
|
|
1656
|
+
}
|
|
1657
|
+
async function updateResource(ctx, id, patch) {
|
|
1658
|
+
const current = firstResource(await getResource(ctx, id));
|
|
1659
|
+
return updateResourceRaw(ctx, id, resourceUpdateBody(id, current, patch));
|
|
1660
|
+
}
|
|
1661
|
+
async function configureResourceIndex(ctx, id, opts) {
|
|
1662
|
+
const current = firstResource(await getResource(ctx, id));
|
|
1663
|
+
const schema = (current.schema_definition ?? []).map((prop) => ({ ...prop }));
|
|
1664
|
+
const indexConfig = {
|
|
1665
|
+
...current.index_config ?? {},
|
|
1666
|
+
...opts.buildKeyFields?.length ? { build_key_fields: opts.buildKeyFields } : {},
|
|
1667
|
+
...opts.embeddingModel ? { default_embedding_model: opts.embeddingModel } : {},
|
|
1668
|
+
...opts.fulltextAnalyzer ? { default_fulltext_analyzer: opts.fulltextAnalyzer } : {}
|
|
1669
|
+
};
|
|
1670
|
+
for (const field of opts.embeddingFields ?? []) {
|
|
1671
|
+
ensureFeature(
|
|
1672
|
+
schema,
|
|
1673
|
+
field,
|
|
1674
|
+
"vector",
|
|
1675
|
+
opts.embeddingModel ? { embedding_model: opts.embeddingModel } : void 0
|
|
1676
|
+
);
|
|
1677
|
+
}
|
|
1678
|
+
for (const field of opts.fulltextFields ?? []) {
|
|
1679
|
+
ensureFeature(
|
|
1680
|
+
schema,
|
|
1681
|
+
field,
|
|
1682
|
+
"fulltext",
|
|
1683
|
+
opts.fulltextAnalyzer ? { analyzer: opts.fulltextAnalyzer } : void 0
|
|
1684
|
+
);
|
|
1685
|
+
}
|
|
1686
|
+
return updateResourceRaw(
|
|
1687
|
+
ctx,
|
|
1688
|
+
id,
|
|
1689
|
+
resourceUpdateBody(id, current, { schemaDefinition: schema, indexConfig })
|
|
1690
|
+
);
|
|
1691
|
+
}
|
|
1692
|
+
function resourceUpdateBody(id, current, patch) {
|
|
1536
1693
|
const body = {
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1694
|
+
id,
|
|
1695
|
+
name: patch.name ?? current.name,
|
|
1696
|
+
catalog_id: patch.catalogId ?? current.catalog_id,
|
|
1697
|
+
tags: patch.tags ?? current.tags ?? [],
|
|
1698
|
+
description: patch.description ?? current.description ?? "",
|
|
1699
|
+
category: patch.category ?? current.category,
|
|
1700
|
+
status: patch.status ?? current.status,
|
|
1701
|
+
database: patch.database ?? current.database,
|
|
1702
|
+
source_identifier: patch.sourceIdentifier ?? current.source_identifier,
|
|
1703
|
+
source_metadata: patch.sourceMetadata ?? current.source_metadata,
|
|
1704
|
+
schema_definition: patch.schemaDefinition ?? current.schema_definition,
|
|
1705
|
+
index_config: patch.indexConfig === void 0 ? current.index_config : patch.indexConfig,
|
|
1706
|
+
logic_definition: patch.logicDefinition ?? current.logic_definition
|
|
1541
1707
|
};
|
|
1542
|
-
if (
|
|
1543
|
-
|
|
1708
|
+
if (patch.extensions !== void 0 || current.extensions !== void 0) {
|
|
1709
|
+
body.extensions = patch.extensions ?? current.extensions;
|
|
1710
|
+
}
|
|
1711
|
+
return body;
|
|
1712
|
+
}
|
|
1713
|
+
function ensureFeature(schema, field, featureType, config) {
|
|
1714
|
+
const prop = schema.find((p) => p.name === field);
|
|
1715
|
+
if (!prop) throw new Error(`resource field '${field}' not found in schema_definition`);
|
|
1716
|
+
const features = [...prop.features ?? []];
|
|
1717
|
+
const existing = features.find(
|
|
1718
|
+
(f) => f.feature_type === featureType && (f.ref_property || field) === field
|
|
1719
|
+
);
|
|
1720
|
+
if (existing) {
|
|
1721
|
+
existing.ref_property = existing.ref_property || field;
|
|
1722
|
+
existing.config = { ...existing.config ?? {}, ...config ?? {} };
|
|
1723
|
+
} else {
|
|
1724
|
+
features.push({
|
|
1725
|
+
name: `${field}_${featureType}`,
|
|
1726
|
+
feature_type: featureType,
|
|
1727
|
+
ref_property: field,
|
|
1728
|
+
is_default: false,
|
|
1729
|
+
is_native: false,
|
|
1730
|
+
...config ? { config } : {}
|
|
1731
|
+
});
|
|
1732
|
+
}
|
|
1733
|
+
prop.features = features;
|
|
1544
1734
|
}
|
|
1545
|
-
function
|
|
1546
|
-
|
|
1735
|
+
function firstResource(result) {
|
|
1736
|
+
if (result && typeof result === "object") {
|
|
1737
|
+
const o = result;
|
|
1738
|
+
if (Array.isArray(o.entries)) return o.entries[0] ?? {};
|
|
1739
|
+
return o;
|
|
1740
|
+
}
|
|
1741
|
+
return {};
|
|
1742
|
+
}
|
|
1743
|
+
function deleteResource(ctx, id, opts = {}) {
|
|
1744
|
+
const ids = Array.isArray(id) ? id : [id];
|
|
1745
|
+
return request(ctx, `${BASE3}/${ids.map(encodeURIComponent).join(",")}`, {
|
|
1746
|
+
method: "DELETE",
|
|
1747
|
+
query: {
|
|
1748
|
+
ignore_missing: opts.ignoreMissing === void 0 ? void 0 : String(opts.ignoreMissing)
|
|
1749
|
+
}
|
|
1750
|
+
});
|
|
1547
1751
|
}
|
|
1548
1752
|
async function findResource(ctx, name, opts = {}) {
|
|
1549
1753
|
const result = await listResources2(ctx, { name, datasourceId: opts.datasourceId });
|
|
@@ -2765,7 +2969,6 @@ function knPath(knId, path) {
|
|
|
2765
2969
|
return `${BASE4}/${encodeURIComponent(knId)}/${path}`;
|
|
2766
2970
|
}
|
|
2767
2971
|
async function uploadBkn(ctx, tarBuffer, opts = {}) {
|
|
2768
|
-
applyTls(ctx);
|
|
2769
2972
|
const url = new URL(`${ctx.baseUrl}${BKNS}`);
|
|
2770
2973
|
url.searchParams.set("branch", opts.branch ?? "main");
|
|
2771
2974
|
const form2 = new FormData();
|
|
@@ -2776,17 +2979,19 @@ async function uploadBkn(ctx, tarBuffer, opts = {}) {
|
|
|
2776
2979
|
);
|
|
2777
2980
|
const res = await authFetch(
|
|
2778
2981
|
ctx,
|
|
2779
|
-
() =>
|
|
2982
|
+
() => tlsFetch(ctx.insecure, url, { method: "POST", headers: buildHeaders(ctx), body: form2 })
|
|
2780
2983
|
);
|
|
2781
2984
|
const text = await res.text();
|
|
2782
2985
|
if (!res.ok) throw new HttpError(res.status, res.statusText, text);
|
|
2783
2986
|
return text ? JSON.parse(text) : void 0;
|
|
2784
2987
|
}
|
|
2785
2988
|
async function downloadBkn(ctx, knId, opts = {}) {
|
|
2786
|
-
applyTls(ctx);
|
|
2787
2989
|
const url = new URL(`${ctx.baseUrl}${BKNS}/${encodeURIComponent(knId)}`);
|
|
2788
2990
|
url.searchParams.set("branch", opts.branch ?? "main");
|
|
2789
|
-
const res = await authFetch(
|
|
2991
|
+
const res = await authFetch(
|
|
2992
|
+
ctx,
|
|
2993
|
+
() => tlsFetch(ctx.insecure, url, { method: "GET", headers: buildHeaders(ctx) })
|
|
2994
|
+
);
|
|
2790
2995
|
if (!res.ok) throw new HttpError(res.status, res.statusText, await res.text());
|
|
2791
2996
|
return Buffer.from(await res.arrayBuffer());
|
|
2792
2997
|
}
|
|
@@ -2875,10 +3080,7 @@ var BuildMode = z.enum(["batch", "streaming"]);
|
|
|
2875
3080
|
var CreateBuildTaskRequest = z.object({
|
|
2876
3081
|
resource_id: z.string().min(1),
|
|
2877
3082
|
mode: BuildMode,
|
|
2878
|
-
|
|
2879
|
-
build_key_fields: z.array(z.string()).optional(),
|
|
2880
|
-
embedding_model: z.string().optional(),
|
|
2881
|
-
model_dimensions: z.number().int().positive().optional()
|
|
3083
|
+
execute_type: z.enum(["incremental", "full"]).optional()
|
|
2882
3084
|
});
|
|
2883
3085
|
var BuildTask = z.object({
|
|
2884
3086
|
id: z.string(),
|
|
@@ -2889,34 +3091,83 @@ var BuildTask = z.object({
|
|
|
2889
3091
|
total_count: z.number().optional(),
|
|
2890
3092
|
synced_count: z.number().optional(),
|
|
2891
3093
|
vectorized_count: z.number().optional(),
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
3094
|
+
index_config: z.unknown().optional(),
|
|
3095
|
+
catalog_id: z.string().optional(),
|
|
3096
|
+
index_health: z.object({
|
|
3097
|
+
embedding: z.string(),
|
|
3098
|
+
fulltext: z.string(),
|
|
3099
|
+
usable: z.boolean()
|
|
3100
|
+
}).passthrough().optional()
|
|
2896
3101
|
}).passthrough();
|
|
2897
3102
|
async function createBuildTask(ctx, req) {
|
|
2898
3103
|
const p = CreateBuildTaskRequest.parse(req);
|
|
2899
3104
|
const body = {
|
|
2900
3105
|
resource_id: p.resource_id,
|
|
2901
3106
|
mode: p.mode,
|
|
2902
|
-
...p.
|
|
2903
|
-
...p.build_key_fields?.length ? { build_key_fields: p.build_key_fields.join(",") } : {},
|
|
2904
|
-
...p.embedding_model ? { embedding_model: p.embedding_model } : {},
|
|
2905
|
-
...p.model_dimensions ? { model_dimensions: p.model_dimensions } : {}
|
|
3107
|
+
...p.execute_type ? { execute_type: p.execute_type } : {}
|
|
2906
3108
|
};
|
|
2907
3109
|
const res = await request(ctx, `${VEGA_BASE}/build-tasks`, { method: "POST", body });
|
|
2908
3110
|
return BuildTask.parse(res);
|
|
2909
3111
|
}
|
|
3112
|
+
function listBuildTasks(ctx, opts = {}) {
|
|
3113
|
+
return request(ctx, `${VEGA_BASE}/build-tasks`, {
|
|
3114
|
+
query: {
|
|
3115
|
+
limit: opts.limit,
|
|
3116
|
+
offset: opts.offset,
|
|
3117
|
+
resource_id: opts.resourceId || void 0,
|
|
3118
|
+
catalog_id: opts.catalogId || void 0,
|
|
3119
|
+
status: Array.isArray(opts.status) ? opts.status.join(",") : opts.status || void 0,
|
|
3120
|
+
active: opts.active === void 0 ? void 0 : String(opts.active),
|
|
3121
|
+
mode: opts.mode,
|
|
3122
|
+
order_by: opts.orderBy,
|
|
3123
|
+
order: opts.order
|
|
3124
|
+
}
|
|
3125
|
+
});
|
|
3126
|
+
}
|
|
2910
3127
|
async function getBuildTask(ctx, taskId) {
|
|
2911
3128
|
const res = await request(ctx, `${VEGA_BASE}/build-tasks/${encodeURIComponent(taskId)}`);
|
|
2912
3129
|
return BuildTask.parse(res);
|
|
2913
3130
|
}
|
|
3131
|
+
function deleteBuildTasks(ctx, ids, opts = {}) {
|
|
3132
|
+
return request(ctx, `${VEGA_BASE}/build-tasks/${ids.map(encodeURIComponent).join(",")}`, {
|
|
3133
|
+
method: "DELETE",
|
|
3134
|
+
query: {
|
|
3135
|
+
ignore_missing: opts.ignoreMissing === void 0 ? void 0 : String(opts.ignoreMissing),
|
|
3136
|
+
delete_active_index: opts.deleteActiveIndex === void 0 ? void 0 : String(opts.deleteActiveIndex)
|
|
3137
|
+
}
|
|
3138
|
+
});
|
|
3139
|
+
}
|
|
3140
|
+
function startBuildTask(ctx, taskId, opts = {}) {
|
|
3141
|
+
return request(ctx, `${VEGA_BASE}/build-tasks/${encodeURIComponent(taskId)}/start`, {
|
|
3142
|
+
method: "POST",
|
|
3143
|
+
body: opts.reset === void 0 ? {} : { reset: opts.reset }
|
|
3144
|
+
});
|
|
3145
|
+
}
|
|
3146
|
+
function stopBuildTask(ctx, taskId) {
|
|
3147
|
+
return request(ctx, `${VEGA_BASE}/build-tasks/${encodeURIComponent(taskId)}/stop`, {
|
|
3148
|
+
method: "POST"
|
|
3149
|
+
});
|
|
3150
|
+
}
|
|
2914
3151
|
function runSql(ctx, body) {
|
|
2915
3152
|
return request(ctx, `${VEGA_BASE}/resources/query`, { method: "POST", body });
|
|
2916
3153
|
}
|
|
2917
3154
|
async function listCatalogs(ctx, opts = {}) {
|
|
2918
3155
|
return request(ctx, `${VEGA_BASE}/catalogs`, {
|
|
2919
|
-
query: {
|
|
3156
|
+
query: {
|
|
3157
|
+
limit: opts.limit,
|
|
3158
|
+
offset: opts.offset,
|
|
3159
|
+
name: opts.name || void 0,
|
|
3160
|
+
tag: opts.tag || void 0,
|
|
3161
|
+
type: opts.type || void 0,
|
|
3162
|
+
enabled: opts.enabled === void 0 ? void 0 : String(opts.enabled),
|
|
3163
|
+
health_check_status: opts.healthCheckStatus || void 0,
|
|
3164
|
+
include_extensions: opts.includeExtensions === void 0 ? void 0 : String(opts.includeExtensions),
|
|
3165
|
+
include_extension_keys: opts.includeExtensionKeys || void 0,
|
|
3166
|
+
extension_key: opts.extensionPairs?.map((p) => p.key),
|
|
3167
|
+
extension_value: opts.extensionPairs?.map((p) => p.value),
|
|
3168
|
+
sort: opts.sort,
|
|
3169
|
+
direction: opts.direction
|
|
3170
|
+
}
|
|
2920
3171
|
});
|
|
2921
3172
|
}
|
|
2922
3173
|
function getCatalog(ctx, id) {
|
|
@@ -2926,18 +3177,49 @@ function createCatalog(ctx, req) {
|
|
|
2926
3177
|
return request(ctx, `${VEGA_BASE}/catalogs`, {
|
|
2927
3178
|
method: "POST",
|
|
2928
3179
|
body: {
|
|
3180
|
+
...req.id ? { id: req.id } : {},
|
|
2929
3181
|
name: req.name,
|
|
2930
3182
|
connector_type: req.connectorType,
|
|
2931
3183
|
connector_config: req.connectorConfig,
|
|
2932
3184
|
...req.tags ? { tags: req.tags } : {},
|
|
2933
3185
|
...req.description ? { description: req.description } : {},
|
|
2934
|
-
...req.enabled !== void 0 ? { enabled: req.enabled } : {}
|
|
3186
|
+
...req.enabled !== void 0 ? { enabled: req.enabled } : {},
|
|
3187
|
+
...req.internal !== void 0 ? { internal: req.internal } : {},
|
|
3188
|
+
...req.extensions ? { extensions: req.extensions } : {}
|
|
3189
|
+
}
|
|
3190
|
+
});
|
|
3191
|
+
}
|
|
3192
|
+
function updateCatalog(ctx, id, req) {
|
|
3193
|
+
return request(ctx, `${VEGA_BASE}/catalogs/${encodeURIComponent(id)}`, {
|
|
3194
|
+
method: "PUT",
|
|
3195
|
+
body: {
|
|
3196
|
+
...req.id ? { id: req.id } : {},
|
|
3197
|
+
...req.name ? { name: req.name } : {},
|
|
3198
|
+
...req.connectorType ? { connector_type: req.connectorType } : {},
|
|
3199
|
+
...req.connectorConfig !== void 0 ? { connector_config: req.connectorConfig } : {},
|
|
3200
|
+
...req.tags ? { tags: req.tags } : {},
|
|
3201
|
+
...req.description !== void 0 ? { description: req.description } : {},
|
|
3202
|
+
...req.enabled !== void 0 ? { enabled: req.enabled } : {},
|
|
3203
|
+
...req.extensions ? { extensions: req.extensions } : {}
|
|
2935
3204
|
}
|
|
2936
3205
|
});
|
|
2937
3206
|
}
|
|
2938
3207
|
function enableCatalog(ctx, id) {
|
|
2939
3208
|
return request(ctx, `${VEGA_BASE}/catalogs/${encodeURIComponent(id)}/enable`, { method: "POST" });
|
|
2940
3209
|
}
|
|
3210
|
+
function disableCatalog(ctx, id) {
|
|
3211
|
+
return request(ctx, `${VEGA_BASE}/catalogs/${encodeURIComponent(id)}/disable`, {
|
|
3212
|
+
method: "POST"
|
|
3213
|
+
});
|
|
3214
|
+
}
|
|
3215
|
+
function deleteCatalog(ctx, id) {
|
|
3216
|
+
return request(ctx, `${VEGA_BASE}/catalogs/${encodeURIComponent(id)}`, { method: "DELETE" });
|
|
3217
|
+
}
|
|
3218
|
+
function testCatalogConnection(ctx, id) {
|
|
3219
|
+
return request(ctx, `${VEGA_BASE}/catalogs/${encodeURIComponent(id)}/test-connection`, {
|
|
3220
|
+
method: "POST"
|
|
3221
|
+
});
|
|
3222
|
+
}
|
|
2941
3223
|
function discoverCatalog(ctx, id, wait = true) {
|
|
2942
3224
|
return request(ctx, `${VEGA_BASE}/catalogs/${encodeURIComponent(id)}/discover`, {
|
|
2943
3225
|
method: "POST",
|
|
@@ -3407,7 +3689,7 @@ async function createFromCatalog(ctx, opts) {
|
|
|
3407
3689
|
}
|
|
3408
3690
|
tablePk[t.name] = res.pk;
|
|
3409
3691
|
}
|
|
3410
|
-
log(`
|
|
3692
|
+
log(`Resolving discovered resources for ${targets.length} table(s)...`);
|
|
3411
3693
|
const viewMap = {};
|
|
3412
3694
|
for (const t of targets) {
|
|
3413
3695
|
const found = asArray(
|
|
@@ -3417,13 +3699,9 @@ async function createFromCatalog(ctx, opts) {
|
|
|
3417
3699
|
if (existingId) {
|
|
3418
3700
|
viewMap[t.name] = existingId;
|
|
3419
3701
|
} else {
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
sourceIdentifier: t.name,
|
|
3424
|
-
fields: t.columns.map((c) => ({ name: c.name, type: c.type }))
|
|
3425
|
-
});
|
|
3426
|
-
viewMap[t.name] = String(created.id ?? "");
|
|
3702
|
+
throw new Error(
|
|
3703
|
+
`Table '${t.name}' has no discovered Vega resource. Run catalog discover and retry.`
|
|
3704
|
+
);
|
|
3427
3705
|
}
|
|
3428
3706
|
}
|
|
3429
3707
|
const knCreated = await createKnowledgeNetwork(ctx, { name: opts.name });
|
|
@@ -3455,12 +3733,14 @@ async function createFromCatalog(ctx, opts) {
|
|
|
3455
3733
|
log("Submitting build tasks...");
|
|
3456
3734
|
for (const t of targets) {
|
|
3457
3735
|
const embedding = opts.embeddingFields?.[t.name];
|
|
3736
|
+
await configureResourceIndex(ctx, viewMap[t.name], {
|
|
3737
|
+
buildKeyFields: [tablePk[t.name]],
|
|
3738
|
+
...embedding && embedding.length > 0 ? { embeddingFields: embedding } : {},
|
|
3739
|
+
...opts.embeddingModel ? { embeddingModel: opts.embeddingModel } : {}
|
|
3740
|
+
});
|
|
3458
3741
|
const task = await createBuildTask(ctx, {
|
|
3459
3742
|
resource_id: viewMap[t.name],
|
|
3460
|
-
mode: "batch"
|
|
3461
|
-
build_key_fields: [tablePk[t.name]],
|
|
3462
|
-
...embedding && embedding.length > 0 ? { embedding_fields: embedding } : {},
|
|
3463
|
-
...opts.embeddingModel ? { embedding_model: opts.embeddingModel } : {}
|
|
3743
|
+
mode: "batch"
|
|
3464
3744
|
});
|
|
3465
3745
|
builds.push({ table: t.name, taskId: String(task.id ?? "") });
|
|
3466
3746
|
}
|
|
@@ -3638,12 +3918,19 @@ function kn(ctx) {
|
|
|
3638
3918
|
const targets = collectIndexTargets(dir);
|
|
3639
3919
|
const buildTasks = [];
|
|
3640
3920
|
for (const t of targets) {
|
|
3921
|
+
if (!t.buildKey) {
|
|
3922
|
+
throw new Error(
|
|
3923
|
+
`Object type '${t.objectType}' declares a vector index but no build key; batch Vega builds require resource index_config.build_key_fields.`
|
|
3924
|
+
);
|
|
3925
|
+
}
|
|
3926
|
+
await configureResourceIndex(ctx, t.resourceId, {
|
|
3927
|
+
buildKeyFields: [t.buildKey],
|
|
3928
|
+
embeddingFields: t.embeddingFields,
|
|
3929
|
+
...t.embeddingModel ?? opts.embeddingModel ? { embeddingModel: t.embeddingModel ?? opts.embeddingModel } : {}
|
|
3930
|
+
});
|
|
3641
3931
|
const task = await createBuildTask(ctx, {
|
|
3642
3932
|
resource_id: t.resourceId,
|
|
3643
|
-
mode: "batch"
|
|
3644
|
-
embedding_fields: t.embeddingFields,
|
|
3645
|
-
...t.buildKey ? { build_key_fields: [t.buildKey] } : {},
|
|
3646
|
-
...t.embeddingModel ?? opts.embeddingModel ? { embedding_model: t.embeddingModel ?? opts.embeddingModel } : {}
|
|
3933
|
+
mode: "batch"
|
|
3647
3934
|
});
|
|
3648
3935
|
buildTasks.push({
|
|
3649
3936
|
objectType: t.objectType,
|
|
@@ -3698,10 +3985,9 @@ function deltaContent(chunk) {
|
|
|
3698
3985
|
return typeof c === "string" ? c : "";
|
|
3699
3986
|
}
|
|
3700
3987
|
async function chatCompletionsStream(ctx, model, messages, onDelta) {
|
|
3701
|
-
applyTls(ctx);
|
|
3702
3988
|
const res = await authFetch(
|
|
3703
3989
|
ctx,
|
|
3704
|
-
() =>
|
|
3990
|
+
() => tlsFetch(ctx.insecure, `${ctx.baseUrl}${API}/chat/completions`, {
|
|
3705
3991
|
method: "POST",
|
|
3706
3992
|
headers: {
|
|
3707
3993
|
...buildHeaders(ctx),
|
|
@@ -3822,6 +4108,8 @@ function resources(ctx) {
|
|
|
3822
4108
|
list: (opts) => listResources2(ctx, opts),
|
|
3823
4109
|
get: (id) => getResource(ctx, id),
|
|
3824
4110
|
delete: (id) => deleteResource(ctx, id),
|
|
4111
|
+
update: (id, patch) => updateResource(ctx, id, patch),
|
|
4112
|
+
configureIndex: (id, opts) => configureResourceIndex(ctx, id, opts),
|
|
3825
4113
|
find: (name, opts) => findResource(ctx, name, opts),
|
|
3826
4114
|
query: (id, opts) => queryResource(ctx, id, opts)
|
|
3827
4115
|
};
|
|
@@ -3834,7 +4122,6 @@ import { basename as basename2, dirname as dirname3, resolve as resolve5 } from
|
|
|
3834
4122
|
// src/api/skills.ts
|
|
3835
4123
|
var BASE5 = "/api/agent-operator-integration/v1";
|
|
3836
4124
|
async function registerSkillZip(ctx, bytes, opts = {}) {
|
|
3837
|
-
applyTls(ctx);
|
|
3838
4125
|
const form2 = new FormData();
|
|
3839
4126
|
form2.set("file_type", "zip");
|
|
3840
4127
|
form2.set("file", new Blob([bytes]), opts.filename ?? "skill.zip");
|
|
@@ -3842,7 +4129,7 @@ async function registerSkillZip(ctx, bytes, opts = {}) {
|
|
|
3842
4129
|
if (opts.extendInfo) form2.set("extend_info", JSON.stringify(opts.extendInfo));
|
|
3843
4130
|
const res = await authFetch(
|
|
3844
4131
|
ctx,
|
|
3845
|
-
() =>
|
|
4132
|
+
() => tlsFetch(ctx.insecure, `${ctx.baseUrl}${BASE5}/skills`, {
|
|
3846
4133
|
method: "POST",
|
|
3847
4134
|
headers: buildHeaders(ctx),
|
|
3848
4135
|
body: form2
|
|
@@ -3853,13 +4140,12 @@ async function registerSkillZip(ctx, bytes, opts = {}) {
|
|
|
3853
4140
|
return text ? JSON.parse(text) : void 0;
|
|
3854
4141
|
}
|
|
3855
4142
|
async function updateSkillPackageZip(ctx, skillId, bytes, filename = "skill.zip") {
|
|
3856
|
-
applyTls(ctx);
|
|
3857
4143
|
const form2 = new FormData();
|
|
3858
4144
|
form2.set("file_type", "zip");
|
|
3859
4145
|
form2.set("file", new Blob([bytes]), filename);
|
|
3860
4146
|
const res = await authFetch(
|
|
3861
4147
|
ctx,
|
|
3862
|
-
() =>
|
|
4148
|
+
() => tlsFetch(ctx.insecure, `${ctx.baseUrl}${BASE5}/skills/${encodeURIComponent(skillId)}/package`, {
|
|
3863
4149
|
method: "PUT",
|
|
3864
4150
|
headers: buildHeaders(ctx),
|
|
3865
4151
|
body: form2
|
|
@@ -3870,10 +4156,9 @@ async function updateSkillPackageZip(ctx, skillId, bytes, filename = "skill.zip"
|
|
|
3870
4156
|
return text ? JSON.parse(text) : void 0;
|
|
3871
4157
|
}
|
|
3872
4158
|
async function downloadSkill(ctx, skillId) {
|
|
3873
|
-
applyTls(ctx);
|
|
3874
4159
|
const res = await authFetch(
|
|
3875
4160
|
ctx,
|
|
3876
|
-
() =>
|
|
4161
|
+
() => tlsFetch(ctx.insecure, `${ctx.baseUrl}${BASE5}/skills/${encodeURIComponent(skillId)}/download`, {
|
|
3877
4162
|
headers: buildHeaders(ctx)
|
|
3878
4163
|
})
|
|
3879
4164
|
);
|
|
@@ -4029,25 +4314,27 @@ import { basename as basename3 } from "path";
|
|
|
4029
4314
|
var PATH = "/api/agent-operator-integration/v1/tool-box";
|
|
4030
4315
|
var IMPEX = "/api/agent-operator-integration/v1/impex";
|
|
4031
4316
|
async function exportConfig(ctx, id, type = "toolbox") {
|
|
4032
|
-
applyTls(ctx);
|
|
4033
4317
|
const res = await authFetch(
|
|
4034
4318
|
ctx,
|
|
4035
|
-
() =>
|
|
4036
|
-
|
|
4037
|
-
|
|
4319
|
+
() => tlsFetch(
|
|
4320
|
+
ctx.insecure,
|
|
4321
|
+
`${ctx.baseUrl}${IMPEX}/export/${encodeURIComponent(type)}/${encodeURIComponent(id)}`,
|
|
4322
|
+
{
|
|
4323
|
+
headers: buildHeaders(ctx)
|
|
4324
|
+
}
|
|
4325
|
+
)
|
|
4038
4326
|
);
|
|
4039
4327
|
const buf = new Uint8Array(await res.arrayBuffer());
|
|
4040
4328
|
if (!res.ok) throw new HttpError(res.status, res.statusText, new TextDecoder().decode(buf));
|
|
4041
4329
|
return buf;
|
|
4042
4330
|
}
|
|
4043
4331
|
async function importConfig(ctx, filePath, type = "toolbox") {
|
|
4044
|
-
applyTls(ctx);
|
|
4045
4332
|
const buf = await readFile2(filePath);
|
|
4046
4333
|
const form2 = new FormData();
|
|
4047
4334
|
form2.append("data", new Blob([new Uint8Array(buf)]), basename3(filePath));
|
|
4048
4335
|
const res = await authFetch(
|
|
4049
4336
|
ctx,
|
|
4050
|
-
() =>
|
|
4337
|
+
() => tlsFetch(ctx.insecure, `${ctx.baseUrl}${IMPEX}/import/${encodeURIComponent(type)}`, {
|
|
4051
4338
|
method: "POST",
|
|
4052
4339
|
headers: buildHeaders(ctx),
|
|
4053
4340
|
body: form2
|
|
@@ -4058,14 +4345,13 @@ async function importConfig(ctx, filePath, type = "toolbox") {
|
|
|
4058
4345
|
return text ? JSON.parse(text) : text;
|
|
4059
4346
|
}
|
|
4060
4347
|
async function uploadTool(ctx, boxId, filePath, metadataType = "openapi") {
|
|
4061
|
-
applyTls(ctx);
|
|
4062
4348
|
const buf = await readFile2(filePath);
|
|
4063
4349
|
const form2 = new FormData();
|
|
4064
4350
|
form2.append("metadata_type", metadataType);
|
|
4065
4351
|
form2.append("data", new Blob([new Uint8Array(buf)]), basename3(filePath));
|
|
4066
4352
|
const res = await authFetch(
|
|
4067
4353
|
ctx,
|
|
4068
|
-
() =>
|
|
4354
|
+
() => tlsFetch(ctx.insecure, `${ctx.baseUrl}${PATH}/${encodeURIComponent(boxId)}/tool`, {
|
|
4069
4355
|
method: "POST",
|
|
4070
4356
|
headers: buildHeaders(ctx),
|
|
4071
4357
|
body: form2
|
|
@@ -4234,7 +4520,7 @@ async function getSpansByConversation(ctx, conversationId, opts = {}) {
|
|
|
4234
4520
|
return (spans.hits?.hits ?? []).map((h) => h._source ?? {});
|
|
4235
4521
|
}
|
|
4236
4522
|
|
|
4237
|
-
// src/trace
|
|
4523
|
+
// src/bkn-trace/claude-judge.ts
|
|
4238
4524
|
import { spawn as spawn2, spawnSync as spawnSync2 } from "child_process";
|
|
4239
4525
|
var ClaudeJudgeError = class extends Error {
|
|
4240
4526
|
constructor(message, reason) {
|
|
@@ -4316,7 +4602,7 @@ async function judgeJson(prompt, opts = {}) {
|
|
|
4316
4602
|
return JSON.parse(extractJsonObject(text));
|
|
4317
4603
|
}
|
|
4318
4604
|
|
|
4319
|
-
// src/trace
|
|
4605
|
+
// src/bkn-trace/diagnose.ts
|
|
4320
4606
|
var KIND_MAP = {
|
|
4321
4607
|
chat: "llm",
|
|
4322
4608
|
text_completion: "llm",
|
|
@@ -4710,7 +4996,7 @@ function renderReportMarkdown(r) {
|
|
|
4710
4996
|
return lines.join("\n");
|
|
4711
4997
|
}
|
|
4712
4998
|
|
|
4713
|
-
// src/trace
|
|
4999
|
+
// src/bkn-trace/eval-set.ts
|
|
4714
5000
|
function hashId(s) {
|
|
4715
5001
|
let h = 5381;
|
|
4716
5002
|
for (let i = 0; i < s.length; i++) h = h * 33 ^ s.charCodeAt(i);
|
|
@@ -4974,7 +5260,11 @@ function vega(ctx) {
|
|
|
4974
5260
|
catalogs: (opts) => listCatalogs(ctx, opts),
|
|
4975
5261
|
getCatalog: (id) => getCatalog(ctx, id),
|
|
4976
5262
|
createCatalog: (req) => createCatalog(ctx, req),
|
|
5263
|
+
updateCatalog: (id, req) => updateCatalog(ctx, id, req),
|
|
4977
5264
|
enableCatalog: (id) => enableCatalog(ctx, id),
|
|
5265
|
+
disableCatalog: (id) => disableCatalog(ctx, id),
|
|
5266
|
+
deleteCatalog: (id) => deleteCatalog(ctx, id),
|
|
5267
|
+
testCatalogConnection: (id) => testCatalogConnection(ctx, id),
|
|
4978
5268
|
discoverCatalog: (id, wait = false) => discoverCatalog(ctx, id, wait),
|
|
4979
5269
|
catalogResources: (id, category) => listCatalogResources(ctx, id, category),
|
|
4980
5270
|
catalogHealth: (ids) => catalogHealthStatus(ctx, ids),
|
|
@@ -4988,7 +5278,11 @@ function vega(ctx) {
|
|
|
4988
5278
|
if (!opts.wait) return task;
|
|
4989
5279
|
return pollBuildTask(ctx, task.id, opts.timeoutMs ?? 3e5, opts.intervalMs ?? 2e3);
|
|
4990
5280
|
},
|
|
4991
|
-
buildStatus: (taskId) => getBuildTask(ctx, taskId)
|
|
5281
|
+
buildStatus: (taskId) => getBuildTask(ctx, taskId),
|
|
5282
|
+
buildTasks: (opts) => listBuildTasks(ctx, opts),
|
|
5283
|
+
deleteBuildTasks: (ids, opts) => deleteBuildTasks(ctx, ids, opts),
|
|
5284
|
+
startBuildTask: (taskId, opts) => startBuildTask(ctx, taskId, opts),
|
|
5285
|
+
stopBuildTask: (taskId) => stopBuildTask(ctx, taskId)
|
|
4992
5286
|
};
|
|
4993
5287
|
}
|
|
4994
5288
|
async function pollBuildTask(ctx, taskId, timeoutMs, intervalMs) {
|
|
@@ -5024,7 +5318,6 @@ function resolveUrl(ctx, path) {
|
|
|
5024
5318
|
return path.startsWith("http") ? path : `${ctx.baseUrl}${path.startsWith("/") ? "" : "/"}${path}`;
|
|
5025
5319
|
}
|
|
5026
5320
|
async function rawCall(ctx, path, opts = {}) {
|
|
5027
|
-
applyTls(ctx);
|
|
5028
5321
|
const url = resolveUrl(ctx, path);
|
|
5029
5322
|
const extra = {};
|
|
5030
5323
|
for (const h of opts.header ?? []) {
|
|
@@ -5053,7 +5346,12 @@ async function rawCall(ctx, path, opts = {}) {
|
|
|
5053
5346
|
try {
|
|
5054
5347
|
const res = await authFetch(
|
|
5055
5348
|
ctx,
|
|
5056
|
-
() =>
|
|
5349
|
+
() => tlsFetch(ctx.insecure, url, {
|
|
5350
|
+
method,
|
|
5351
|
+
headers: headersFor(),
|
|
5352
|
+
body,
|
|
5353
|
+
signal: controller.signal
|
|
5354
|
+
})
|
|
5057
5355
|
);
|
|
5058
5356
|
return { status: res.status, statusText: res.statusText, body: await res.text() };
|
|
5059
5357
|
} finally {
|
|
@@ -5132,7 +5430,6 @@ function createClient(opts = {}) {
|
|
|
5132
5430
|
// src/resources/auth.ts
|
|
5133
5431
|
var auth_exports = {};
|
|
5134
5432
|
__export(auth_exports, {
|
|
5135
|
-
attachNoAuth: () => attachNoAuth,
|
|
5136
5433
|
attachToken: () => attachToken,
|
|
5137
5434
|
currentToken: () => currentToken,
|
|
5138
5435
|
currentTokenFresh: () => currentTokenFresh,
|
|
@@ -5170,7 +5467,6 @@ function attachToken(baseUrl, accessToken, opts = {}) {
|
|
|
5170
5467
|
accessToken,
|
|
5171
5468
|
refreshToken: opts.refreshToken,
|
|
5172
5469
|
idToken: opts.idToken,
|
|
5173
|
-
tlsInsecure: opts.insecure,
|
|
5174
5470
|
// Prefer the account the user typed (-u); device tokens carry no username.
|
|
5175
5471
|
username: opts.username ?? decodeJwt(opts.idToken ?? accessToken)?.preferred_username
|
|
5176
5472
|
};
|
|
@@ -5178,33 +5474,40 @@ function attachToken(baseUrl, accessToken, opts = {}) {
|
|
|
5178
5474
|
setActivePlatform(url);
|
|
5179
5475
|
return { baseUrl: url, userId, username: usernameOf(token) };
|
|
5180
5476
|
}
|
|
5181
|
-
function
|
|
5182
|
-
|
|
5183
|
-
|
|
5184
|
-
|
|
5185
|
-
|
|
5477
|
+
function targetUser(baseUrl, userOrName) {
|
|
5478
|
+
if (!userOrName) return activeUserId(baseUrl);
|
|
5479
|
+
const id = findUserId(baseUrl, userOrName);
|
|
5480
|
+
if (!id) {
|
|
5481
|
+
const known = usersOfPlatform(baseUrl).map((u) => u.username ?? u.userId).join(", ");
|
|
5482
|
+
throw new InputError(
|
|
5483
|
+
`No saved user '${userOrName}' on ${baseUrl}. Saved: ${known || "(none)"}.`
|
|
5484
|
+
);
|
|
5485
|
+
}
|
|
5486
|
+
return id;
|
|
5186
5487
|
}
|
|
5187
|
-
function status() {
|
|
5488
|
+
function status(opts = {}) {
|
|
5188
5489
|
const baseUrl = activePlatform();
|
|
5189
5490
|
if (!baseUrl) return { hasToken: false };
|
|
5190
|
-
const
|
|
5491
|
+
const userId = targetUser(baseUrl, opts.user);
|
|
5492
|
+
const token = readToken(baseUrl, userId);
|
|
5191
5493
|
return {
|
|
5192
5494
|
baseUrl,
|
|
5193
|
-
userId
|
|
5495
|
+
userId,
|
|
5194
5496
|
hasToken: token !== void 0,
|
|
5195
5497
|
username: usernameOf(token),
|
|
5196
5498
|
expired: token ? isExpired(decodeJwt(token.accessToken)) : void 0
|
|
5197
5499
|
};
|
|
5198
5500
|
}
|
|
5199
|
-
function currentToken() {
|
|
5501
|
+
function currentToken(opts = {}) {
|
|
5200
5502
|
const baseUrl = activePlatform();
|
|
5201
|
-
const token = baseUrl ? readToken(baseUrl) : void 0;
|
|
5503
|
+
const token = baseUrl ? readToken(baseUrl, targetUser(baseUrl, opts.user)) : void 0;
|
|
5202
5504
|
if (!token) throw new InputError("Not logged in. Run `openbkn auth login <url> --token <t>`.");
|
|
5203
5505
|
return token.accessToken;
|
|
5204
5506
|
}
|
|
5205
|
-
async function currentTokenFresh() {
|
|
5507
|
+
async function currentTokenFresh(opts = {}) {
|
|
5206
5508
|
const baseUrl = activePlatform();
|
|
5207
|
-
const
|
|
5509
|
+
const userId = baseUrl ? targetUser(baseUrl, opts.user) : void 0;
|
|
5510
|
+
const token = baseUrl ? readToken(baseUrl, userId) : void 0;
|
|
5208
5511
|
if (!baseUrl || !token) {
|
|
5209
5512
|
throw new InputError("Not logged in. Run `openbkn auth login <url> --token <t>`.");
|
|
5210
5513
|
}
|
|
@@ -5213,22 +5516,27 @@ async function currentTokenFresh() {
|
|
|
5213
5516
|
const needsRefresh = decodable ? isExpired(claims) : true;
|
|
5214
5517
|
if (token.refreshToken && needsRefresh) {
|
|
5215
5518
|
try {
|
|
5216
|
-
const t = await refreshAccessToken(baseUrl, token.refreshToken);
|
|
5217
|
-
writeToken(
|
|
5218
|
-
|
|
5219
|
-
|
|
5220
|
-
|
|
5221
|
-
|
|
5222
|
-
|
|
5519
|
+
const t = await refreshAccessToken(baseUrl, token.refreshToken, void 0, opts.insecure);
|
|
5520
|
+
writeToken(
|
|
5521
|
+
baseUrl,
|
|
5522
|
+
{
|
|
5523
|
+
...token,
|
|
5524
|
+
accessToken: t.accessToken,
|
|
5525
|
+
refreshToken: t.refreshToken ?? token.refreshToken,
|
|
5526
|
+
idToken: t.idToken ?? token.idToken
|
|
5527
|
+
},
|
|
5528
|
+
{ setActive: !opts.user }
|
|
5529
|
+
);
|
|
5223
5530
|
return t.accessToken;
|
|
5224
5531
|
} catch {
|
|
5225
5532
|
}
|
|
5226
5533
|
}
|
|
5227
5534
|
return token.accessToken;
|
|
5228
5535
|
}
|
|
5229
|
-
function whoami() {
|
|
5536
|
+
function whoami(opts = {}) {
|
|
5230
5537
|
const baseUrl = activePlatform();
|
|
5231
|
-
const
|
|
5538
|
+
const userId = baseUrl ? targetUser(baseUrl, opts.user) : void 0;
|
|
5539
|
+
const token = baseUrl ? readToken(baseUrl, userId) : void 0;
|
|
5232
5540
|
const claims = decodeJwt(token?.idToken ?? "") ?? decodeJwt(token?.accessToken ?? "");
|
|
5233
5541
|
if (!claims) {
|
|
5234
5542
|
throw new InputError(
|
|
@@ -5238,7 +5546,7 @@ function whoami() {
|
|
|
5238
5546
|
return {
|
|
5239
5547
|
...claims,
|
|
5240
5548
|
baseUrl: baseUrl ?? void 0,
|
|
5241
|
-
userId
|
|
5549
|
+
userId,
|
|
5242
5550
|
username: usernameOf(token)
|
|
5243
5551
|
};
|
|
5244
5552
|
}
|
|
@@ -5302,7 +5610,6 @@ export {
|
|
|
5302
5610
|
formatError,
|
|
5303
5611
|
isHeadless,
|
|
5304
5612
|
openBrowser,
|
|
5305
|
-
fetchAuthStatus,
|
|
5306
5613
|
deviceLogin,
|
|
5307
5614
|
credentialDeviceLogin,
|
|
5308
5615
|
request,
|
|
@@ -5317,6 +5624,7 @@ export {
|
|
|
5317
5624
|
writePlatformConfig,
|
|
5318
5625
|
resolveContext,
|
|
5319
5626
|
getUserSafe,
|
|
5627
|
+
changePasswordSafe,
|
|
5320
5628
|
admin,
|
|
5321
5629
|
agents,
|
|
5322
5630
|
context,
|
|
@@ -5333,7 +5641,6 @@ export {
|
|
|
5333
5641
|
vega,
|
|
5334
5642
|
createClient,
|
|
5335
5643
|
attachToken,
|
|
5336
|
-
attachNoAuth,
|
|
5337
5644
|
status,
|
|
5338
5645
|
currentToken,
|
|
5339
5646
|
currentTokenFresh,
|
|
@@ -5346,4 +5653,4 @@ export {
|
|
|
5346
5653
|
exportCreds,
|
|
5347
5654
|
auth_exports
|
|
5348
5655
|
};
|
|
5349
|
-
//# sourceMappingURL=chunk-
|
|
5656
|
+
//# sourceMappingURL=chunk-ISJHU26W.js.map
|