@openbkn/bkn-sdk 0.1.1-alpha.9 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -0
- package/NOTICE +21 -0
- package/README.md +31 -25
- package/README.zh.md +10 -12
- package/dist/{chunk-BFE4SU3V.js → chunk-NC6DZ2AU.js} +568 -151
- package/dist/cli.js +504 -179
- package/dist/index.d.ts +383 -64
- package/dist/index.js +1 -1
- package/package.json +5 -4
- package/dist/chunk-BFE4SU3V.js.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/index.js.map +0 -1
|
@@ -9,12 +9,15 @@ var HttpError = class extends Error {
|
|
|
9
9
|
status;
|
|
10
10
|
statusText;
|
|
11
11
|
body;
|
|
12
|
-
|
|
12
|
+
/** Optional next-step guidance, overriding the status default (e.g. AppKey re-issue). */
|
|
13
|
+
hint;
|
|
14
|
+
constructor(status2, statusText, body, hint) {
|
|
13
15
|
super(`HTTP ${status2} ${statusText}`);
|
|
14
16
|
this.name = "HttpError";
|
|
15
17
|
this.status = status2;
|
|
16
18
|
this.statusText = statusText;
|
|
17
19
|
this.body = body;
|
|
20
|
+
this.hint = hint;
|
|
18
21
|
}
|
|
19
22
|
};
|
|
20
23
|
var InputError = class extends Error {
|
|
@@ -35,7 +38,8 @@ function formatError(err) {
|
|
|
35
38
|
if (err instanceof HttpError) {
|
|
36
39
|
const serverMsg = serverError(err.body);
|
|
37
40
|
if (err.status === 401) {
|
|
38
|
-
|
|
41
|
+
const next = err.hint ?? "Run `openbkn auth login` and retry.";
|
|
42
|
+
return `Not authorized (HTTP 401)${serverMsg ? `: ${serverMsg}` : ""}. ${next}`;
|
|
39
43
|
}
|
|
40
44
|
if (err.status === 403) {
|
|
41
45
|
return `Forbidden (HTTP 403)${serverMsg ? `: ${serverMsg}` : " \u2014 admin privileges required"}.`;
|
|
@@ -74,6 +78,23 @@ function truncate(s, n) {
|
|
|
74
78
|
|
|
75
79
|
// src/auth/oauth.ts
|
|
76
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
|
|
77
98
|
function normalizeBaseUrl(value) {
|
|
78
99
|
return value.replace(/\/+$/, "");
|
|
79
100
|
}
|
|
@@ -114,22 +135,9 @@ function mergeCookies(existing, res) {
|
|
|
114
135
|
for (const sc of setCookies) add(sc.split(";")[0]?.trim() ?? "");
|
|
115
136
|
return [...map.entries()].map(([k, v]) => `${k}=${v}`).join("; ");
|
|
116
137
|
}
|
|
117
|
-
async function
|
|
118
|
-
try {
|
|
119
|
-
const res = await fetch(`${normalizeBaseUrl(baseUrl)}/install-status.json`, {
|
|
120
|
-
headers: { Accept: "application/json" }
|
|
121
|
-
});
|
|
122
|
-
if (!res.ok) return null;
|
|
123
|
-
const j = await res.json();
|
|
124
|
-
if (!j.auth) return null;
|
|
125
|
-
return { enabled: Boolean(j.auth.enabled), stack: j.auth.stack };
|
|
126
|
-
} catch {
|
|
127
|
-
return null;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
async function refreshAccessToken(baseUrl, refreshToken, clientId = "openbkn-sdk") {
|
|
138
|
+
async function refreshAccessToken(baseUrl, refreshToken, clientId = "openbkn-sdk", insecure) {
|
|
131
139
|
const base = normalizeBaseUrl(baseUrl);
|
|
132
|
-
const res = await
|
|
140
|
+
const res = await tlsFetch(insecure, `${base}/oauth2/token`, {
|
|
133
141
|
method: "POST",
|
|
134
142
|
headers: {
|
|
135
143
|
"Content-Type": "application/x-www-form-urlencoded",
|
|
@@ -159,10 +167,10 @@ var form = (body) => ({
|
|
|
159
167
|
},
|
|
160
168
|
body: new URLSearchParams(body).toString()
|
|
161
169
|
});
|
|
162
|
-
async function requestDeviceCode(base, clientId, scope, audience) {
|
|
170
|
+
async function requestDeviceCode(base, clientId, scope, audience, insecure) {
|
|
163
171
|
const params = { client_id: clientId, scope };
|
|
164
172
|
if (audience) params.audience = audience;
|
|
165
|
-
const res = await
|
|
173
|
+
const res = await tlsFetch(insecure, `${base}/oauth2/device/auth`, form(params));
|
|
166
174
|
if (!res.ok) {
|
|
167
175
|
throw new Error(`Device auth failed (${res.status}): ${await res.text() || res.statusText}`);
|
|
168
176
|
}
|
|
@@ -174,12 +182,13 @@ async function requestDeviceCode(base, clientId, scope, audience) {
|
|
|
174
182
|
}
|
|
175
183
|
return da;
|
|
176
184
|
}
|
|
177
|
-
async function pollDeviceToken(base, deviceCode, clientId, intervalMs, windowMs) {
|
|
185
|
+
async function pollDeviceToken(base, deviceCode, clientId, intervalMs, windowMs, insecure) {
|
|
178
186
|
let interval = intervalMs;
|
|
179
187
|
const deadline = Date.now() + windowMs;
|
|
180
188
|
while (Date.now() < deadline) {
|
|
181
189
|
await new Promise((r) => setTimeout(r, interval));
|
|
182
|
-
const tokRes = await
|
|
190
|
+
const tokRes = await tlsFetch(
|
|
191
|
+
insecure,
|
|
183
192
|
`${base}/oauth2/token`,
|
|
184
193
|
form({ grant_type: DEVICE_GRANT, device_code: deviceCode, client_id: clientId })
|
|
185
194
|
);
|
|
@@ -205,14 +214,27 @@ async function pollDeviceToken(base, deviceCode, clientId, intervalMs, windowMs)
|
|
|
205
214
|
async function deviceLogin(baseUrl, opts = {}) {
|
|
206
215
|
const base = normalizeBaseUrl(baseUrl);
|
|
207
216
|
const clientId = opts.clientId ?? DEFAULT_DEVICE_CLIENT_ID;
|
|
208
|
-
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
|
+
);
|
|
209
224
|
opts.onPrompt?.({
|
|
210
225
|
userCode: da.user_code,
|
|
211
226
|
verificationUri: onBaseHost(base, da.verification_uri),
|
|
212
227
|
verificationUriComplete: da.verification_uri_complete ? onBaseHost(base, da.verification_uri_complete) : void 0
|
|
213
228
|
});
|
|
214
229
|
const windowMs = Math.min(opts.timeoutMs ?? Number.POSITIVE_INFINITY, da.expires_in * 1e3);
|
|
215
|
-
return pollDeviceToken(
|
|
230
|
+
return pollDeviceToken(
|
|
231
|
+
base,
|
|
232
|
+
da.device_code,
|
|
233
|
+
clientId,
|
|
234
|
+
(da.interval ?? 5) * 1e3,
|
|
235
|
+
windowMs,
|
|
236
|
+
opts.insecure
|
|
237
|
+
);
|
|
216
238
|
}
|
|
217
239
|
function onBaseHost(base, uri) {
|
|
218
240
|
try {
|
|
@@ -226,10 +248,16 @@ function onBaseHost(base, uri) {
|
|
|
226
248
|
async function credentialDeviceLogin(baseUrl, username, password, opts = {}) {
|
|
227
249
|
const base = normalizeBaseUrl(baseUrl);
|
|
228
250
|
const clientId = opts.clientId ?? DEFAULT_DEVICE_CLIENT_ID;
|
|
229
|
-
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
|
+
);
|
|
230
258
|
let jar = "";
|
|
231
259
|
const hop = async (url, init) => {
|
|
232
|
-
const r = await
|
|
260
|
+
const r = await tlsFetch(opts.insecure, url, {
|
|
233
261
|
method: init?.method ?? "GET",
|
|
234
262
|
headers: { Cookie: jar, Accept: "text/html,*/*;q=0.8", ...init?.headers ?? {} },
|
|
235
263
|
body: init?.body,
|
|
@@ -267,38 +295,40 @@ async function credentialDeviceLogin(baseUrl, username, password, opts = {}) {
|
|
|
267
295
|
loc = r.headers.get("location");
|
|
268
296
|
}
|
|
269
297
|
const windowMs = Math.min(opts.timeoutMs ?? Number.POSITIVE_INFINITY, da.expires_in * 1e3);
|
|
270
|
-
return pollDeviceToken(
|
|
298
|
+
return pollDeviceToken(
|
|
299
|
+
base,
|
|
300
|
+
da.device_code,
|
|
301
|
+
clientId,
|
|
302
|
+
(da.interval ?? 5) * 1e3,
|
|
303
|
+
windowMs,
|
|
304
|
+
opts.insecure
|
|
305
|
+
);
|
|
271
306
|
}
|
|
272
307
|
|
|
273
308
|
// src/api/headers.ts
|
|
274
309
|
function buildHeaders(ctx, extra) {
|
|
275
310
|
return {
|
|
276
|
-
|
|
277
|
-
...ctx.token ? { authorization: `Bearer ${ctx.token}`, token: ctx.token } : {},
|
|
311
|
+
authorization: `Bearer ${ctx.token}`,
|
|
278
312
|
"x-business-domain": ctx.businessDomain,
|
|
279
313
|
...extra
|
|
280
314
|
};
|
|
281
315
|
}
|
|
282
316
|
|
|
283
|
-
// src/api/tls.ts
|
|
284
|
-
function applyTls(ctx) {
|
|
285
|
-
if (ctx.insecure && process.env.NODE_TLS_REJECT_UNAUTHORIZED !== "0") {
|
|
286
|
-
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
|
|
290
317
|
// src/api/http.ts
|
|
291
318
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
292
319
|
async function request(ctx, path, init = {}) {
|
|
293
320
|
const url = new URL(path.startsWith("http") ? path : `${ctx.baseUrl}${path}`);
|
|
294
321
|
for (const [k, v] of Object.entries(init.query ?? {})) {
|
|
295
|
-
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
|
+
}
|
|
296
327
|
}
|
|
297
|
-
applyTls(ctx);
|
|
298
328
|
const hasBody = init.body !== void 0;
|
|
299
329
|
const controller = new AbortController();
|
|
300
330
|
const timer = setTimeout(() => controller.abort(), init.timeoutMs ?? DEFAULT_TIMEOUT_MS);
|
|
301
|
-
const send = () =>
|
|
331
|
+
const send = () => tlsFetch(ctx.insecure, url, {
|
|
302
332
|
method: init.method ?? (hasBody ? "POST" : "GET"),
|
|
303
333
|
headers: buildHeaders(ctx, {
|
|
304
334
|
...hasBody ? { "content-type": "application/json" } : {},
|
|
@@ -313,16 +343,27 @@ async function request(ctx, path, init = {}) {
|
|
|
313
343
|
res = await send();
|
|
314
344
|
}
|
|
315
345
|
const text = await res.text();
|
|
316
|
-
if (!res.ok) throw new HttpError(res.status, res.statusText, text);
|
|
346
|
+
if (!res.ok) throw new HttpError(res.status, res.statusText, text, hintFor(ctx, res.status));
|
|
317
347
|
return text ? JSON.parse(text) : void 0;
|
|
318
348
|
} finally {
|
|
319
349
|
clearTimeout(timer);
|
|
320
350
|
}
|
|
321
351
|
}
|
|
352
|
+
function hintFor(ctx, status2) {
|
|
353
|
+
if (status2 === 401 && ctx.token.startsWith("bak_")) {
|
|
354
|
+
return "AppKey invalid / expired / revoked / owner disabled \u2014 re-issue with `openbkn appkey create` (or `appkey regenerate <id>`). Do not auto-retry.";
|
|
355
|
+
}
|
|
356
|
+
return void 0;
|
|
357
|
+
}
|
|
322
358
|
async function tryRefresh(ctx) {
|
|
323
359
|
if (!ctx.refresh) return false;
|
|
324
360
|
try {
|
|
325
|
-
const t = await refreshAccessToken(
|
|
361
|
+
const t = await refreshAccessToken(
|
|
362
|
+
ctx.baseUrl,
|
|
363
|
+
ctx.refresh.refreshToken,
|
|
364
|
+
ctx.refresh.clientId,
|
|
365
|
+
ctx.insecure
|
|
366
|
+
);
|
|
326
367
|
ctx.token = t.accessToken;
|
|
327
368
|
if (t.refreshToken) ctx.refresh.refreshToken = t.refreshToken;
|
|
328
369
|
ctx.refresh.persist(t);
|
|
@@ -367,6 +408,7 @@ function isExpired(claims, nowMs = Date.now()) {
|
|
|
367
408
|
|
|
368
409
|
// src/config/store.ts
|
|
369
410
|
var PROFILE_RE = /^[A-Za-z0-9_-]{1,64}$/;
|
|
411
|
+
var USER_ID_RE = /^[A-Za-z0-9._@-]{1,128}$/;
|
|
370
412
|
var IS_WIN = process.platform === "win32";
|
|
371
413
|
function configDir() {
|
|
372
414
|
return process.env.BKN_CONFIG_DIR ?? join(homedir(), ".bkn");
|
|
@@ -393,7 +435,14 @@ function userDir(baseUrl, userId) {
|
|
|
393
435
|
return join(platformDir(baseUrl), "users", userId);
|
|
394
436
|
}
|
|
395
437
|
function userIdFromToken(token) {
|
|
396
|
-
|
|
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;
|
|
397
446
|
}
|
|
398
447
|
function readState() {
|
|
399
448
|
return readJson(statePath()) ?? {};
|
|
@@ -418,10 +467,10 @@ function readToken(baseUrl, userId = activeUserId(baseUrl)) {
|
|
|
418
467
|
if (!userId) return void 0;
|
|
419
468
|
return readJson(join(userDir(baseUrl, userId), "token.json")) ?? void 0;
|
|
420
469
|
}
|
|
421
|
-
function writeToken(baseUrl, token) {
|
|
470
|
+
function writeToken(baseUrl, token, opts = {}) {
|
|
422
471
|
const userId = userIdFromToken(token);
|
|
423
472
|
writeJson(join(userDir(baseUrl, userId), "token.json"), token, 384);
|
|
424
|
-
setActiveUser(baseUrl, userId);
|
|
473
|
+
if (opts.setActive !== false) setActiveUser(baseUrl, userId);
|
|
425
474
|
return userId;
|
|
426
475
|
}
|
|
427
476
|
function deleteToken(baseUrl, userId = activeUserId(baseUrl)) {
|
|
@@ -460,6 +509,14 @@ function listPlatforms() {
|
|
|
460
509
|
}
|
|
461
510
|
return out;
|
|
462
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
|
+
}
|
|
463
520
|
function decodeKey(key) {
|
|
464
521
|
try {
|
|
465
522
|
const b64 = key.replace(/-/g, "+").replace(/_/g, "/");
|
|
@@ -485,6 +542,14 @@ function writeJson(path, value, mode = 384) {
|
|
|
485
542
|
}
|
|
486
543
|
|
|
487
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
|
+
}
|
|
488
553
|
function resolveContext(opts = {}) {
|
|
489
554
|
const baseUrl = opts.baseUrl ?? process.env.BKN_BASE_URL ?? activePlatform();
|
|
490
555
|
if (!baseUrl) {
|
|
@@ -493,22 +558,29 @@ function resolveContext(opts = {}) {
|
|
|
493
558
|
);
|
|
494
559
|
}
|
|
495
560
|
const normalized = baseUrl.replace(/\/+$/, "");
|
|
496
|
-
const
|
|
561
|
+
const user = opts.user ?? process.env.BKN_USER;
|
|
562
|
+
const stored = user ? readToken(normalized, resolveUserId(normalized, user)) : readToken(normalized);
|
|
497
563
|
const explicit = opts.token ?? process.env.BKN_TOKEN;
|
|
498
564
|
const token = explicit ?? stored?.accessToken ?? "";
|
|
499
|
-
if (!token
|
|
565
|
+
if (!token) {
|
|
500
566
|
throw new InputError("No access token. Set BKN_TOKEN or run `openbkn auth login`.");
|
|
501
567
|
}
|
|
502
568
|
const insecure = opts.insecure ?? stored?.tlsInsecure ?? false;
|
|
503
569
|
const refresh = !explicit && stored?.refreshToken ? {
|
|
504
570
|
refreshToken: stored.refreshToken,
|
|
505
571
|
persist: (t) => {
|
|
506
|
-
writeToken(
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
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
|
+
);
|
|
512
584
|
}
|
|
513
585
|
} : void 0;
|
|
514
586
|
return {
|
|
@@ -571,6 +643,13 @@ async function setUserPasswordSafe(ctx, userId, password) {
|
|
|
571
643
|
});
|
|
572
644
|
return { ok: true };
|
|
573
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
|
+
}
|
|
574
653
|
function getUserRolesSafe(ctx, userId) {
|
|
575
654
|
return request(ctx, `${ADMIN}/role-bindings`, { query: { accessor_id: userId } });
|
|
576
655
|
}
|
|
@@ -684,6 +763,43 @@ async function setRolePermissionSafe(ctx, roleId, grant, perm) {
|
|
|
684
763
|
});
|
|
685
764
|
return { ok: true };
|
|
686
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
|
+
}
|
|
687
803
|
|
|
688
804
|
// src/resources/admin.ts
|
|
689
805
|
var DEFAULT_NEW_USER_PASSWORD = "openbkn";
|
|
@@ -744,7 +860,13 @@ function admin(ctx) {
|
|
|
744
860
|
roleUpdate: (roleId, input) => updateRoleSafe(ctx, roleId, input),
|
|
745
861
|
roleDelete: (roleId) => deleteRoleSafe(ctx, roleId),
|
|
746
862
|
rolePermission: (roleId, grant, resourceType, resourceId, operations) => setRolePermissionSafe(ctx, roleId, grant, { resourceType, resourceId, operations }),
|
|
747
|
-
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)
|
|
748
870
|
};
|
|
749
871
|
}
|
|
750
872
|
|
|
@@ -816,7 +938,6 @@ function extractText(result) {
|
|
|
816
938
|
return "";
|
|
817
939
|
}
|
|
818
940
|
async function sendChat(ctx, info, query, opts = {}) {
|
|
819
|
-
applyTls(ctx);
|
|
820
941
|
const body = {
|
|
821
942
|
agent_id: info.id,
|
|
822
943
|
agent_key: info.key,
|
|
@@ -827,7 +948,7 @@ async function sendChat(ctx, info, query, opts = {}) {
|
|
|
827
948
|
if (opts.conversationId) body.conversation_id = opts.conversationId;
|
|
828
949
|
const res = await authFetch(
|
|
829
950
|
ctx,
|
|
830
|
-
() =>
|
|
951
|
+
() => tlsFetch(ctx.insecure, `${ctx.baseUrl}${FACTORY}/v1/app/${info.key}/chat/completion`, {
|
|
831
952
|
method: "POST",
|
|
832
953
|
headers: {
|
|
833
954
|
...buildHeaders(ctx),
|
|
@@ -1029,6 +1150,9 @@ function nextId() {
|
|
|
1029
1150
|
function mcpUrl(ctx) {
|
|
1030
1151
|
return `${ctx.baseUrl}${MCP_PATH}`;
|
|
1031
1152
|
}
|
|
1153
|
+
function mcpInfo(ctx) {
|
|
1154
|
+
return request(ctx, `${MCP_PATH}/info`);
|
|
1155
|
+
}
|
|
1032
1156
|
function headers(ctx, knId, sessionId) {
|
|
1033
1157
|
const h = {
|
|
1034
1158
|
"content-type": "application/json",
|
|
@@ -1050,10 +1174,9 @@ function parseBody(text) {
|
|
|
1050
1174
|
}
|
|
1051
1175
|
}
|
|
1052
1176
|
async function post(ctx, knId, sessionId, body) {
|
|
1053
|
-
applyTls(ctx);
|
|
1054
1177
|
const res = await authFetch(
|
|
1055
1178
|
ctx,
|
|
1056
|
-
() =>
|
|
1179
|
+
() => tlsFetch(ctx.insecure, mcpUrl(ctx), {
|
|
1057
1180
|
method: "POST",
|
|
1058
1181
|
headers: headers(ctx, knId, sessionId),
|
|
1059
1182
|
body: JSON.stringify(body)
|
|
@@ -1135,6 +1258,17 @@ function findSkills(ctx, knId, objectTypeId, topK) {
|
|
|
1135
1258
|
if (topK !== void 0) args.top_k = topK;
|
|
1136
1259
|
return callTool(ctx, knId, "find_skills", args);
|
|
1137
1260
|
}
|
|
1261
|
+
function getKnDetail(ctx, knId, detailLevel) {
|
|
1262
|
+
const args = { response_format: "json" };
|
|
1263
|
+
if (detailLevel) args.detail_level = detailLevel;
|
|
1264
|
+
return callTool(ctx, knId, "get_kn_detail", args);
|
|
1265
|
+
}
|
|
1266
|
+
function getObjectTypes(ctx, knId, ids) {
|
|
1267
|
+
return callTool(ctx, knId, "get_object_types", { ids, response_format: "json" });
|
|
1268
|
+
}
|
|
1269
|
+
function getRelationTypes(ctx, knId, ids) {
|
|
1270
|
+
return callTool(ctx, knId, "get_relation_types", { ids, response_format: "json" });
|
|
1271
|
+
}
|
|
1138
1272
|
function listTools(ctx, knId) {
|
|
1139
1273
|
return callMethod(ctx, knId, "tools/list");
|
|
1140
1274
|
}
|
|
@@ -1169,8 +1303,16 @@ function context(ctx) {
|
|
|
1169
1303
|
searchSchema: (knId, query, opts) => searchSchema(ctx, knId, query, opts),
|
|
1170
1304
|
queryObjectInstance: (knId, args) => queryObjectInstance(ctx, knId, args),
|
|
1171
1305
|
findSkills: (knId, objectTypeId, topK) => findSkills(ctx, knId, objectTypeId, topK),
|
|
1306
|
+
// Progressive schema disclosure: skeleton first (summary), then drill down.
|
|
1307
|
+
knDetail: (knId, detailLevel) => getKnDetail(ctx, knId, detailLevel),
|
|
1308
|
+
objectTypes: (knId, ids) => getObjectTypes(ctx, knId, ids),
|
|
1309
|
+
relationTypes: (knId, ids) => getRelationTypes(ctx, knId, ids),
|
|
1310
|
+
info: () => mcpInfo(ctx),
|
|
1172
1311
|
tools: (knId) => listTools(ctx, knId),
|
|
1173
1312
|
toolCall: (knId, name, args) => callTool(ctx, knId, name, args),
|
|
1313
|
+
// Generic MCP method passthrough — covers methods not yet wrapped, so the
|
|
1314
|
+
// surface doesn't have to grow every time the server adds one.
|
|
1315
|
+
callMethod: (knId, method, params) => callMethod(ctx, knId, method, params),
|
|
1174
1316
|
queryInstanceSubgraph: (knId, args) => queryInstanceSubgraph(ctx, knId, args),
|
|
1175
1317
|
logicProperties: (knId, args) => getLogicProperties(ctx, knId, args),
|
|
1176
1318
|
actionInfo: (knId, args) => getActionInfo(ctx, knId, args),
|
|
@@ -1490,7 +1632,16 @@ function listResources2(ctx, opts = {}) {
|
|
|
1490
1632
|
catalog_id: opts.datasourceId || void 0,
|
|
1491
1633
|
name: opts.name || void 0,
|
|
1492
1634
|
category: opts.category || void 0,
|
|
1493
|
-
|
|
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)
|
|
1494
1645
|
}
|
|
1495
1646
|
});
|
|
1496
1647
|
}
|
|
@@ -1500,18 +1651,103 @@ function getResource(ctx, id) {
|
|
|
1500
1651
|
function createResourceRaw(ctx, body) {
|
|
1501
1652
|
return request(ctx, BASE3, { method: "POST", body });
|
|
1502
1653
|
}
|
|
1503
|
-
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) {
|
|
1504
1693
|
const body = {
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
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
|
|
1509
1707
|
};
|
|
1510
|
-
if (
|
|
1511
|
-
|
|
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;
|
|
1512
1734
|
}
|
|
1513
|
-
function
|
|
1514
|
-
|
|
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
|
+
});
|
|
1515
1751
|
}
|
|
1516
1752
|
async function findResource(ctx, name, opts = {}) {
|
|
1517
1753
|
const result = await listResources2(ctx, { name, datasourceId: opts.datasourceId });
|
|
@@ -2733,7 +2969,6 @@ function knPath(knId, path) {
|
|
|
2733
2969
|
return `${BASE4}/${encodeURIComponent(knId)}/${path}`;
|
|
2734
2970
|
}
|
|
2735
2971
|
async function uploadBkn(ctx, tarBuffer, opts = {}) {
|
|
2736
|
-
applyTls(ctx);
|
|
2737
2972
|
const url = new URL(`${ctx.baseUrl}${BKNS}`);
|
|
2738
2973
|
url.searchParams.set("branch", opts.branch ?? "main");
|
|
2739
2974
|
const form2 = new FormData();
|
|
@@ -2744,17 +2979,19 @@ async function uploadBkn(ctx, tarBuffer, opts = {}) {
|
|
|
2744
2979
|
);
|
|
2745
2980
|
const res = await authFetch(
|
|
2746
2981
|
ctx,
|
|
2747
|
-
() =>
|
|
2982
|
+
() => tlsFetch(ctx.insecure, url, { method: "POST", headers: buildHeaders(ctx), body: form2 })
|
|
2748
2983
|
);
|
|
2749
2984
|
const text = await res.text();
|
|
2750
2985
|
if (!res.ok) throw new HttpError(res.status, res.statusText, text);
|
|
2751
2986
|
return text ? JSON.parse(text) : void 0;
|
|
2752
2987
|
}
|
|
2753
2988
|
async function downloadBkn(ctx, knId, opts = {}) {
|
|
2754
|
-
applyTls(ctx);
|
|
2755
2989
|
const url = new URL(`${ctx.baseUrl}${BKNS}/${encodeURIComponent(knId)}`);
|
|
2756
2990
|
url.searchParams.set("branch", opts.branch ?? "main");
|
|
2757
|
-
const res = await authFetch(
|
|
2991
|
+
const res = await authFetch(
|
|
2992
|
+
ctx,
|
|
2993
|
+
() => tlsFetch(ctx.insecure, url, { method: "GET", headers: buildHeaders(ctx) })
|
|
2994
|
+
);
|
|
2758
2995
|
if (!res.ok) throw new HttpError(res.status, res.statusText, await res.text());
|
|
2759
2996
|
return Buffer.from(await res.arrayBuffer());
|
|
2760
2997
|
}
|
|
@@ -2843,10 +3080,7 @@ var BuildMode = z.enum(["batch", "streaming"]);
|
|
|
2843
3080
|
var CreateBuildTaskRequest = z.object({
|
|
2844
3081
|
resource_id: z.string().min(1),
|
|
2845
3082
|
mode: BuildMode,
|
|
2846
|
-
|
|
2847
|
-
build_key_fields: z.array(z.string()).optional(),
|
|
2848
|
-
embedding_model: z.string().optional(),
|
|
2849
|
-
model_dimensions: z.number().int().positive().optional()
|
|
3083
|
+
execute_type: z.enum(["incremental", "full"]).optional()
|
|
2850
3084
|
});
|
|
2851
3085
|
var BuildTask = z.object({
|
|
2852
3086
|
id: z.string(),
|
|
@@ -2857,31 +3091,83 @@ var BuildTask = z.object({
|
|
|
2857
3091
|
total_count: z.number().optional(),
|
|
2858
3092
|
synced_count: z.number().optional(),
|
|
2859
3093
|
vectorized_count: z.number().optional(),
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
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()
|
|
2864
3101
|
}).passthrough();
|
|
2865
3102
|
async function createBuildTask(ctx, req) {
|
|
2866
3103
|
const p = CreateBuildTaskRequest.parse(req);
|
|
2867
3104
|
const body = {
|
|
2868
3105
|
resource_id: p.resource_id,
|
|
2869
3106
|
mode: p.mode,
|
|
2870
|
-
...p.
|
|
2871
|
-
...p.build_key_fields?.length ? { build_key_fields: p.build_key_fields.join(",") } : {},
|
|
2872
|
-
...p.embedding_model ? { embedding_model: p.embedding_model } : {},
|
|
2873
|
-
...p.model_dimensions ? { model_dimensions: p.model_dimensions } : {}
|
|
3107
|
+
...p.execute_type ? { execute_type: p.execute_type } : {}
|
|
2874
3108
|
};
|
|
2875
3109
|
const res = await request(ctx, `${VEGA_BASE}/build-tasks`, { method: "POST", body });
|
|
2876
3110
|
return BuildTask.parse(res);
|
|
2877
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
|
+
}
|
|
2878
3127
|
async function getBuildTask(ctx, taskId) {
|
|
2879
3128
|
const res = await request(ctx, `${VEGA_BASE}/build-tasks/${encodeURIComponent(taskId)}`);
|
|
2880
3129
|
return BuildTask.parse(res);
|
|
2881
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
|
+
}
|
|
3151
|
+
function runSql(ctx, body) {
|
|
3152
|
+
return request(ctx, `${VEGA_BASE}/resources/query`, { method: "POST", body });
|
|
3153
|
+
}
|
|
2882
3154
|
async function listCatalogs(ctx, opts = {}) {
|
|
2883
3155
|
return request(ctx, `${VEGA_BASE}/catalogs`, {
|
|
2884
|
-
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
|
+
}
|
|
2885
3171
|
});
|
|
2886
3172
|
}
|
|
2887
3173
|
function getCatalog(ctx, id) {
|
|
@@ -2891,18 +3177,49 @@ function createCatalog(ctx, req) {
|
|
|
2891
3177
|
return request(ctx, `${VEGA_BASE}/catalogs`, {
|
|
2892
3178
|
method: "POST",
|
|
2893
3179
|
body: {
|
|
3180
|
+
...req.id ? { id: req.id } : {},
|
|
2894
3181
|
name: req.name,
|
|
2895
3182
|
connector_type: req.connectorType,
|
|
2896
3183
|
connector_config: req.connectorConfig,
|
|
2897
3184
|
...req.tags ? { tags: req.tags } : {},
|
|
2898
3185
|
...req.description ? { description: req.description } : {},
|
|
2899
|
-
...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 } : {}
|
|
2900
3204
|
}
|
|
2901
3205
|
});
|
|
2902
3206
|
}
|
|
2903
3207
|
function enableCatalog(ctx, id) {
|
|
2904
3208
|
return request(ctx, `${VEGA_BASE}/catalogs/${encodeURIComponent(id)}/enable`, { method: "POST" });
|
|
2905
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
|
+
}
|
|
2906
3223
|
function discoverCatalog(ctx, id, wait = true) {
|
|
2907
3224
|
return request(ctx, `${VEGA_BASE}/catalogs/${encodeURIComponent(id)}/discover`, {
|
|
2908
3225
|
method: "POST",
|
|
@@ -3372,7 +3689,7 @@ async function createFromCatalog(ctx, opts) {
|
|
|
3372
3689
|
}
|
|
3373
3690
|
tablePk[t.name] = res.pk;
|
|
3374
3691
|
}
|
|
3375
|
-
log(`
|
|
3692
|
+
log(`Resolving discovered resources for ${targets.length} table(s)...`);
|
|
3376
3693
|
const viewMap = {};
|
|
3377
3694
|
for (const t of targets) {
|
|
3378
3695
|
const found = asArray(
|
|
@@ -3382,13 +3699,9 @@ async function createFromCatalog(ctx, opts) {
|
|
|
3382
3699
|
if (existingId) {
|
|
3383
3700
|
viewMap[t.name] = existingId;
|
|
3384
3701
|
} else {
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
sourceIdentifier: t.name,
|
|
3389
|
-
fields: t.columns.map((c) => ({ name: c.name, type: c.type }))
|
|
3390
|
-
});
|
|
3391
|
-
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
|
+
);
|
|
3392
3705
|
}
|
|
3393
3706
|
}
|
|
3394
3707
|
const knCreated = await createKnowledgeNetwork(ctx, { name: opts.name });
|
|
@@ -3420,12 +3733,14 @@ async function createFromCatalog(ctx, opts) {
|
|
|
3420
3733
|
log("Submitting build tasks...");
|
|
3421
3734
|
for (const t of targets) {
|
|
3422
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
|
+
});
|
|
3423
3741
|
const task = await createBuildTask(ctx, {
|
|
3424
3742
|
resource_id: viewMap[t.name],
|
|
3425
|
-
mode: "batch"
|
|
3426
|
-
build_key_fields: [tablePk[t.name]],
|
|
3427
|
-
...embedding && embedding.length > 0 ? { embedding_fields: embedding } : {},
|
|
3428
|
-
...opts.embeddingModel ? { embedding_model: opts.embeddingModel } : {}
|
|
3743
|
+
mode: "batch"
|
|
3429
3744
|
});
|
|
3430
3745
|
builds.push({ table: t.name, taskId: String(task.id ?? "") });
|
|
3431
3746
|
}
|
|
@@ -3603,12 +3918,19 @@ function kn(ctx) {
|
|
|
3603
3918
|
const targets = collectIndexTargets(dir);
|
|
3604
3919
|
const buildTasks = [];
|
|
3605
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
|
+
});
|
|
3606
3931
|
const task = await createBuildTask(ctx, {
|
|
3607
3932
|
resource_id: t.resourceId,
|
|
3608
|
-
mode: "batch"
|
|
3609
|
-
embedding_fields: t.embeddingFields,
|
|
3610
|
-
...t.buildKey ? { build_key_fields: [t.buildKey] } : {},
|
|
3611
|
-
...t.embeddingModel ?? opts.embeddingModel ? { embedding_model: t.embeddingModel ?? opts.embeddingModel } : {}
|
|
3933
|
+
mode: "batch"
|
|
3612
3934
|
});
|
|
3613
3935
|
buildTasks.push({
|
|
3614
3936
|
objectType: t.objectType,
|
|
@@ -3663,10 +3985,9 @@ function deltaContent(chunk) {
|
|
|
3663
3985
|
return typeof c === "string" ? c : "";
|
|
3664
3986
|
}
|
|
3665
3987
|
async function chatCompletionsStream(ctx, model, messages, onDelta) {
|
|
3666
|
-
applyTls(ctx);
|
|
3667
3988
|
const res = await authFetch(
|
|
3668
3989
|
ctx,
|
|
3669
|
-
() =>
|
|
3990
|
+
() => tlsFetch(ctx.insecure, `${ctx.baseUrl}${API}/chat/completions`, {
|
|
3670
3991
|
method: "POST",
|
|
3671
3992
|
headers: {
|
|
3672
3993
|
...buildHeaders(ctx),
|
|
@@ -3725,6 +4046,23 @@ function deleteModels(ctx, kind, modelIds) {
|
|
|
3725
4046
|
function testModel(ctx, kind, body) {
|
|
3726
4047
|
return request(ctx, `${MANAGER}/${kind}/test`, { method: "POST", body });
|
|
3727
4048
|
}
|
|
4049
|
+
function setDefaultLlm(ctx, modelId, isDefault = true) {
|
|
4050
|
+
return request(ctx, `${MANAGER}/llm/default/edit`, {
|
|
4051
|
+
method: "POST",
|
|
4052
|
+
body: { model_id: modelId, default: isDefault }
|
|
4053
|
+
});
|
|
4054
|
+
}
|
|
4055
|
+
function setDefaultSmallModel(ctx, modelId, isDefault = true) {
|
|
4056
|
+
return request(ctx, `${MANAGER}/small-model/set-default`, {
|
|
4057
|
+
method: "POST",
|
|
4058
|
+
body: { model_id: modelId, default: isDefault }
|
|
4059
|
+
});
|
|
4060
|
+
}
|
|
4061
|
+
function getDefaultSmallModel(ctx, modelType = "embedding") {
|
|
4062
|
+
return request(ctx, `${MANAGER}/small-model/get_default`, {
|
|
4063
|
+
query: { model_type: modelType }
|
|
4064
|
+
});
|
|
4065
|
+
}
|
|
3728
4066
|
function rerank(ctx, model, query, documents) {
|
|
3729
4067
|
return request(ctx, `${API}/small-model/reranker`, {
|
|
3730
4068
|
method: "POST",
|
|
@@ -3743,7 +4081,9 @@ function models(ctx) {
|
|
|
3743
4081
|
add: (body) => addModel(ctx, "llm", body),
|
|
3744
4082
|
edit: (body) => editModel(ctx, "llm", body),
|
|
3745
4083
|
delete: (modelIds) => deleteModels(ctx, "llm", modelIds),
|
|
3746
|
-
test: (body) => testModel(ctx, "llm", body)
|
|
4084
|
+
test: (body) => testModel(ctx, "llm", body),
|
|
4085
|
+
/** Set (or clear) the system default LLM. */
|
|
4086
|
+
setDefault: (modelId, isDefault = true) => setDefaultLlm(ctx, modelId, isDefault)
|
|
3747
4087
|
},
|
|
3748
4088
|
small: {
|
|
3749
4089
|
list: (opts) => listSmallModels(ctx, opts),
|
|
@@ -3753,7 +4093,11 @@ function models(ctx) {
|
|
|
3753
4093
|
add: (body) => addModel(ctx, "small-model", body),
|
|
3754
4094
|
edit: (body) => editModel(ctx, "small-model", body),
|
|
3755
4095
|
delete: (modelIds) => deleteModels(ctx, "small-model", modelIds),
|
|
3756
|
-
test: (body) => testModel(ctx, "small-model", body)
|
|
4096
|
+
test: (body) => testModel(ctx, "small-model", body),
|
|
4097
|
+
/** Set (or clear) the system default small model (type inferred from the model). */
|
|
4098
|
+
setDefault: (modelId, isDefault = true) => setDefaultSmallModel(ctx, modelId, isDefault),
|
|
4099
|
+
/** Get the system default small model for a type (default "embedding"). */
|
|
4100
|
+
getDefault: (modelType) => getDefaultSmallModel(ctx, modelType)
|
|
3757
4101
|
}
|
|
3758
4102
|
};
|
|
3759
4103
|
}
|
|
@@ -3764,6 +4108,8 @@ function resources(ctx) {
|
|
|
3764
4108
|
list: (opts) => listResources2(ctx, opts),
|
|
3765
4109
|
get: (id) => getResource(ctx, id),
|
|
3766
4110
|
delete: (id) => deleteResource(ctx, id),
|
|
4111
|
+
update: (id, patch) => updateResource(ctx, id, patch),
|
|
4112
|
+
configureIndex: (id, opts) => configureResourceIndex(ctx, id, opts),
|
|
3767
4113
|
find: (name, opts) => findResource(ctx, name, opts),
|
|
3768
4114
|
query: (id, opts) => queryResource(ctx, id, opts)
|
|
3769
4115
|
};
|
|
@@ -3776,7 +4122,6 @@ import { basename as basename2, dirname as dirname3, resolve as resolve5 } from
|
|
|
3776
4122
|
// src/api/skills.ts
|
|
3777
4123
|
var BASE5 = "/api/agent-operator-integration/v1";
|
|
3778
4124
|
async function registerSkillZip(ctx, bytes, opts = {}) {
|
|
3779
|
-
applyTls(ctx);
|
|
3780
4125
|
const form2 = new FormData();
|
|
3781
4126
|
form2.set("file_type", "zip");
|
|
3782
4127
|
form2.set("file", new Blob([bytes]), opts.filename ?? "skill.zip");
|
|
@@ -3784,7 +4129,7 @@ async function registerSkillZip(ctx, bytes, opts = {}) {
|
|
|
3784
4129
|
if (opts.extendInfo) form2.set("extend_info", JSON.stringify(opts.extendInfo));
|
|
3785
4130
|
const res = await authFetch(
|
|
3786
4131
|
ctx,
|
|
3787
|
-
() =>
|
|
4132
|
+
() => tlsFetch(ctx.insecure, `${ctx.baseUrl}${BASE5}/skills`, {
|
|
3788
4133
|
method: "POST",
|
|
3789
4134
|
headers: buildHeaders(ctx),
|
|
3790
4135
|
body: form2
|
|
@@ -3795,13 +4140,12 @@ async function registerSkillZip(ctx, bytes, opts = {}) {
|
|
|
3795
4140
|
return text ? JSON.parse(text) : void 0;
|
|
3796
4141
|
}
|
|
3797
4142
|
async function updateSkillPackageZip(ctx, skillId, bytes, filename = "skill.zip") {
|
|
3798
|
-
applyTls(ctx);
|
|
3799
4143
|
const form2 = new FormData();
|
|
3800
4144
|
form2.set("file_type", "zip");
|
|
3801
4145
|
form2.set("file", new Blob([bytes]), filename);
|
|
3802
4146
|
const res = await authFetch(
|
|
3803
4147
|
ctx,
|
|
3804
|
-
() =>
|
|
4148
|
+
() => tlsFetch(ctx.insecure, `${ctx.baseUrl}${BASE5}/skills/${encodeURIComponent(skillId)}/package`, {
|
|
3805
4149
|
method: "PUT",
|
|
3806
4150
|
headers: buildHeaders(ctx),
|
|
3807
4151
|
body: form2
|
|
@@ -3812,10 +4156,9 @@ async function updateSkillPackageZip(ctx, skillId, bytes, filename = "skill.zip"
|
|
|
3812
4156
|
return text ? JSON.parse(text) : void 0;
|
|
3813
4157
|
}
|
|
3814
4158
|
async function downloadSkill(ctx, skillId) {
|
|
3815
|
-
applyTls(ctx);
|
|
3816
4159
|
const res = await authFetch(
|
|
3817
4160
|
ctx,
|
|
3818
|
-
() =>
|
|
4161
|
+
() => tlsFetch(ctx.insecure, `${ctx.baseUrl}${BASE5}/skills/${encodeURIComponent(skillId)}/download`, {
|
|
3819
4162
|
headers: buildHeaders(ctx)
|
|
3820
4163
|
})
|
|
3821
4164
|
);
|
|
@@ -3971,25 +4314,27 @@ import { basename as basename3 } from "path";
|
|
|
3971
4314
|
var PATH = "/api/agent-operator-integration/v1/tool-box";
|
|
3972
4315
|
var IMPEX = "/api/agent-operator-integration/v1/impex";
|
|
3973
4316
|
async function exportConfig(ctx, id, type = "toolbox") {
|
|
3974
|
-
applyTls(ctx);
|
|
3975
4317
|
const res = await authFetch(
|
|
3976
4318
|
ctx,
|
|
3977
|
-
() =>
|
|
3978
|
-
|
|
3979
|
-
|
|
4319
|
+
() => tlsFetch(
|
|
4320
|
+
ctx.insecure,
|
|
4321
|
+
`${ctx.baseUrl}${IMPEX}/export/${encodeURIComponent(type)}/${encodeURIComponent(id)}`,
|
|
4322
|
+
{
|
|
4323
|
+
headers: buildHeaders(ctx)
|
|
4324
|
+
}
|
|
4325
|
+
)
|
|
3980
4326
|
);
|
|
3981
4327
|
const buf = new Uint8Array(await res.arrayBuffer());
|
|
3982
4328
|
if (!res.ok) throw new HttpError(res.status, res.statusText, new TextDecoder().decode(buf));
|
|
3983
4329
|
return buf;
|
|
3984
4330
|
}
|
|
3985
4331
|
async function importConfig(ctx, filePath, type = "toolbox") {
|
|
3986
|
-
applyTls(ctx);
|
|
3987
4332
|
const buf = await readFile2(filePath);
|
|
3988
4333
|
const form2 = new FormData();
|
|
3989
4334
|
form2.append("data", new Blob([new Uint8Array(buf)]), basename3(filePath));
|
|
3990
4335
|
const res = await authFetch(
|
|
3991
4336
|
ctx,
|
|
3992
|
-
() =>
|
|
4337
|
+
() => tlsFetch(ctx.insecure, `${ctx.baseUrl}${IMPEX}/import/${encodeURIComponent(type)}`, {
|
|
3993
4338
|
method: "POST",
|
|
3994
4339
|
headers: buildHeaders(ctx),
|
|
3995
4340
|
body: form2
|
|
@@ -4000,14 +4345,13 @@ async function importConfig(ctx, filePath, type = "toolbox") {
|
|
|
4000
4345
|
return text ? JSON.parse(text) : text;
|
|
4001
4346
|
}
|
|
4002
4347
|
async function uploadTool(ctx, boxId, filePath, metadataType = "openapi") {
|
|
4003
|
-
applyTls(ctx);
|
|
4004
4348
|
const buf = await readFile2(filePath);
|
|
4005
4349
|
const form2 = new FormData();
|
|
4006
4350
|
form2.append("metadata_type", metadataType);
|
|
4007
4351
|
form2.append("data", new Blob([new Uint8Array(buf)]), basename3(filePath));
|
|
4008
4352
|
const res = await authFetch(
|
|
4009
4353
|
ctx,
|
|
4010
|
-
() =>
|
|
4354
|
+
() => tlsFetch(ctx.insecure, `${ctx.baseUrl}${PATH}/${encodeURIComponent(boxId)}/tool`, {
|
|
4011
4355
|
method: "POST",
|
|
4012
4356
|
headers: buildHeaders(ctx),
|
|
4013
4357
|
body: form2
|
|
@@ -4176,7 +4520,7 @@ async function getSpansByConversation(ctx, conversationId, opts = {}) {
|
|
|
4176
4520
|
return (spans.hits?.hits ?? []).map((h) => h._source ?? {});
|
|
4177
4521
|
}
|
|
4178
4522
|
|
|
4179
|
-
// src/trace
|
|
4523
|
+
// src/bkn-trace/claude-judge.ts
|
|
4180
4524
|
import { spawn as spawn2, spawnSync as spawnSync2 } from "child_process";
|
|
4181
4525
|
var ClaudeJudgeError = class extends Error {
|
|
4182
4526
|
constructor(message, reason) {
|
|
@@ -4258,7 +4602,7 @@ async function judgeJson(prompt, opts = {}) {
|
|
|
4258
4602
|
return JSON.parse(extractJsonObject(text));
|
|
4259
4603
|
}
|
|
4260
4604
|
|
|
4261
|
-
// src/trace
|
|
4605
|
+
// src/bkn-trace/diagnose.ts
|
|
4262
4606
|
var KIND_MAP = {
|
|
4263
4607
|
chat: "llm",
|
|
4264
4608
|
text_completion: "llm",
|
|
@@ -4652,7 +4996,7 @@ function renderReportMarkdown(r) {
|
|
|
4652
4996
|
return lines.join("\n");
|
|
4653
4997
|
}
|
|
4654
4998
|
|
|
4655
|
-
// src/trace
|
|
4999
|
+
// src/bkn-trace/eval-set.ts
|
|
4656
5000
|
function hashId(s) {
|
|
4657
5001
|
let h = 5381;
|
|
4658
5002
|
for (let i = 0; i < s.length; i++) h = h * 33 ^ s.charCodeAt(i);
|
|
@@ -4916,19 +5260,29 @@ function vega(ctx) {
|
|
|
4916
5260
|
catalogs: (opts) => listCatalogs(ctx, opts),
|
|
4917
5261
|
getCatalog: (id) => getCatalog(ctx, id),
|
|
4918
5262
|
createCatalog: (req) => createCatalog(ctx, req),
|
|
5263
|
+
updateCatalog: (id, req) => updateCatalog(ctx, id, req),
|
|
4919
5264
|
enableCatalog: (id) => enableCatalog(ctx, id),
|
|
5265
|
+
disableCatalog: (id) => disableCatalog(ctx, id),
|
|
5266
|
+
deleteCatalog: (id) => deleteCatalog(ctx, id),
|
|
5267
|
+
testCatalogConnection: (id) => testCatalogConnection(ctx, id),
|
|
4920
5268
|
discoverCatalog: (id, wait = false) => discoverCatalog(ctx, id, wait),
|
|
4921
5269
|
catalogResources: (id, category) => listCatalogResources(ctx, id, category),
|
|
4922
5270
|
catalogHealth: (ids) => catalogHealthStatus(ctx, ids),
|
|
4923
5271
|
connectorTypes: () => listConnectorTypes(ctx),
|
|
4924
5272
|
connectorType: (type) => getConnectorType(ctx, type),
|
|
5273
|
+
/** Run SQL / OpenSearch DSL directly against a data source. */
|
|
5274
|
+
sql: (body) => runSql(ctx, body),
|
|
4925
5275
|
/** Build a resource's index. With `wait`, polls until terminal. */
|
|
4926
5276
|
build: async (req, opts = {}) => {
|
|
4927
5277
|
const task = await createBuildTask(ctx, req);
|
|
4928
5278
|
if (!opts.wait) return task;
|
|
4929
5279
|
return pollBuildTask(ctx, task.id, opts.timeoutMs ?? 3e5, opts.intervalMs ?? 2e3);
|
|
4930
5280
|
},
|
|
4931
|
-
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)
|
|
4932
5286
|
};
|
|
4933
5287
|
}
|
|
4934
5288
|
async function pollBuildTask(ctx, taskId, timeoutMs, intervalMs) {
|
|
@@ -4964,7 +5318,6 @@ function resolveUrl(ctx, path) {
|
|
|
4964
5318
|
return path.startsWith("http") ? path : `${ctx.baseUrl}${path.startsWith("/") ? "" : "/"}${path}`;
|
|
4965
5319
|
}
|
|
4966
5320
|
async function rawCall(ctx, path, opts = {}) {
|
|
4967
|
-
applyTls(ctx);
|
|
4968
5321
|
const url = resolveUrl(ctx, path);
|
|
4969
5322
|
const extra = {};
|
|
4970
5323
|
for (const h of opts.header ?? []) {
|
|
@@ -4993,7 +5346,12 @@ async function rawCall(ctx, path, opts = {}) {
|
|
|
4993
5346
|
try {
|
|
4994
5347
|
const res = await authFetch(
|
|
4995
5348
|
ctx,
|
|
4996
|
-
() =>
|
|
5349
|
+
() => tlsFetch(ctx.insecure, url, {
|
|
5350
|
+
method,
|
|
5351
|
+
headers: headersFor(),
|
|
5352
|
+
body,
|
|
5353
|
+
signal: controller.signal
|
|
5354
|
+
})
|
|
4997
5355
|
);
|
|
4998
5356
|
return { status: res.status, statusText: res.statusText, body: await res.text() };
|
|
4999
5357
|
} finally {
|
|
@@ -5001,6 +5359,53 @@ async function rawCall(ctx, path, opts = {}) {
|
|
|
5001
5359
|
}
|
|
5002
5360
|
}
|
|
5003
5361
|
|
|
5362
|
+
// src/api/app-keys.ts
|
|
5363
|
+
var ME = "/api/safe/v1/me/api-keys";
|
|
5364
|
+
var ADMIN2 = "/api/safe/v1/admin/api-keys";
|
|
5365
|
+
function listMyApiKeys(ctx) {
|
|
5366
|
+
return request(ctx, ME);
|
|
5367
|
+
}
|
|
5368
|
+
function createMyApiKey(ctx, input) {
|
|
5369
|
+
return request(ctx, ME, {
|
|
5370
|
+
method: "POST",
|
|
5371
|
+
body: {
|
|
5372
|
+
name: input.name,
|
|
5373
|
+
...input.expiresAt ? { expires_at: input.expiresAt } : {},
|
|
5374
|
+
...input.neverExpire ? { never_expire: true } : {}
|
|
5375
|
+
}
|
|
5376
|
+
});
|
|
5377
|
+
}
|
|
5378
|
+
async function revokeMyApiKey(ctx, id) {
|
|
5379
|
+
await request(ctx, `${ME}/${encodeURIComponent(id)}`, { method: "DELETE" });
|
|
5380
|
+
}
|
|
5381
|
+
function regenerateMyApiKey(ctx, id) {
|
|
5382
|
+
return request(ctx, `${ME}/${encodeURIComponent(id)}/regenerate`, { method: "POST" });
|
|
5383
|
+
}
|
|
5384
|
+
function listApiKeysAdmin(ctx, ownerId) {
|
|
5385
|
+
return request(ctx, ADMIN2, { query: { owner_id: ownerId || void 0 } });
|
|
5386
|
+
}
|
|
5387
|
+
async function revokeApiKeyAdmin(ctx, id) {
|
|
5388
|
+
await request(ctx, `${ADMIN2}/${encodeURIComponent(id)}`, { method: "DELETE" });
|
|
5389
|
+
}
|
|
5390
|
+
|
|
5391
|
+
// src/resources/app-keys.ts
|
|
5392
|
+
function appKeys(ctx) {
|
|
5393
|
+
return {
|
|
5394
|
+
/** List the caller's own keys (no secrets). */
|
|
5395
|
+
list: () => listMyApiKeys(ctx),
|
|
5396
|
+
/** Issue a key — the result's `key` is the plaintext, shown only once. */
|
|
5397
|
+
create: (input) => createMyApiKey(ctx, input),
|
|
5398
|
+
/** Revoke one of the caller's keys (immediate). */
|
|
5399
|
+
revoke: (id) => revokeMyApiKey(ctx, id),
|
|
5400
|
+
/** Rotate a key in place — new plaintext (shown once); old secret dies now. */
|
|
5401
|
+
regenerate: (id) => regenerateMyApiKey(ctx, id),
|
|
5402
|
+
/** Admin: list all keys, or one owner's (adds `owner_user_id`). */
|
|
5403
|
+
adminList: (ownerId) => listApiKeysAdmin(ctx, ownerId),
|
|
5404
|
+
/** Admin: revoke any key. */
|
|
5405
|
+
adminRevoke: (id) => revokeApiKeyAdmin(ctx, id)
|
|
5406
|
+
};
|
|
5407
|
+
}
|
|
5408
|
+
|
|
5004
5409
|
// src/client.ts
|
|
5005
5410
|
function createClient(opts = {}) {
|
|
5006
5411
|
const ctx = resolveContext(opts);
|
|
@@ -5016,6 +5421,7 @@ function createClient(opts = {}) {
|
|
|
5016
5421
|
toolboxes: toolboxes(ctx),
|
|
5017
5422
|
trace: trace(ctx),
|
|
5018
5423
|
admin: admin(ctx),
|
|
5424
|
+
appKeys: appKeys(ctx),
|
|
5019
5425
|
vega: vega(ctx),
|
|
5020
5426
|
call: (path, callOpts) => rawCall(ctx, path, callOpts)
|
|
5021
5427
|
};
|
|
@@ -5024,7 +5430,6 @@ function createClient(opts = {}) {
|
|
|
5024
5430
|
// src/resources/auth.ts
|
|
5025
5431
|
var auth_exports = {};
|
|
5026
5432
|
__export(auth_exports, {
|
|
5027
|
-
attachNoAuth: () => attachNoAuth,
|
|
5028
5433
|
attachToken: () => attachToken,
|
|
5029
5434
|
currentToken: () => currentToken,
|
|
5030
5435
|
currentTokenFresh: () => currentTokenFresh,
|
|
@@ -5062,7 +5467,8 @@ function attachToken(baseUrl, accessToken, opts = {}) {
|
|
|
5062
5467
|
accessToken,
|
|
5063
5468
|
refreshToken: opts.refreshToken,
|
|
5064
5469
|
idToken: opts.idToken,
|
|
5065
|
-
|
|
5470
|
+
// Remember `-k` so a self-signed platform needn't repeat it every command.
|
|
5471
|
+
tlsInsecure: opts.insecure ? true : void 0,
|
|
5066
5472
|
// Prefer the account the user typed (-u); device tokens carry no username.
|
|
5067
5473
|
username: opts.username ?? decodeJwt(opts.idToken ?? accessToken)?.preferred_username
|
|
5068
5474
|
};
|
|
@@ -5070,33 +5476,40 @@ function attachToken(baseUrl, accessToken, opts = {}) {
|
|
|
5070
5476
|
setActivePlatform(url);
|
|
5071
5477
|
return { baseUrl: url, userId, username: usernameOf(token) };
|
|
5072
5478
|
}
|
|
5073
|
-
function
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5479
|
+
function targetUser(baseUrl, userOrName) {
|
|
5480
|
+
if (!userOrName) return activeUserId(baseUrl);
|
|
5481
|
+
const id = findUserId(baseUrl, userOrName);
|
|
5482
|
+
if (!id) {
|
|
5483
|
+
const known = usersOfPlatform(baseUrl).map((u) => u.username ?? u.userId).join(", ");
|
|
5484
|
+
throw new InputError(
|
|
5485
|
+
`No saved user '${userOrName}' on ${baseUrl}. Saved: ${known || "(none)"}.`
|
|
5486
|
+
);
|
|
5487
|
+
}
|
|
5488
|
+
return id;
|
|
5078
5489
|
}
|
|
5079
|
-
function status() {
|
|
5490
|
+
function status(opts = {}) {
|
|
5080
5491
|
const baseUrl = activePlatform();
|
|
5081
5492
|
if (!baseUrl) return { hasToken: false };
|
|
5082
|
-
const
|
|
5493
|
+
const userId = targetUser(baseUrl, opts.user);
|
|
5494
|
+
const token = readToken(baseUrl, userId);
|
|
5083
5495
|
return {
|
|
5084
5496
|
baseUrl,
|
|
5085
|
-
userId
|
|
5497
|
+
userId,
|
|
5086
5498
|
hasToken: token !== void 0,
|
|
5087
5499
|
username: usernameOf(token),
|
|
5088
5500
|
expired: token ? isExpired(decodeJwt(token.accessToken)) : void 0
|
|
5089
5501
|
};
|
|
5090
5502
|
}
|
|
5091
|
-
function currentToken() {
|
|
5503
|
+
function currentToken(opts = {}) {
|
|
5092
5504
|
const baseUrl = activePlatform();
|
|
5093
|
-
const token = baseUrl ? readToken(baseUrl) : void 0;
|
|
5505
|
+
const token = baseUrl ? readToken(baseUrl, targetUser(baseUrl, opts.user)) : void 0;
|
|
5094
5506
|
if (!token) throw new InputError("Not logged in. Run `openbkn auth login <url> --token <t>`.");
|
|
5095
5507
|
return token.accessToken;
|
|
5096
5508
|
}
|
|
5097
|
-
async function currentTokenFresh() {
|
|
5509
|
+
async function currentTokenFresh(opts = {}) {
|
|
5098
5510
|
const baseUrl = activePlatform();
|
|
5099
|
-
const
|
|
5511
|
+
const userId = baseUrl ? targetUser(baseUrl, opts.user) : void 0;
|
|
5512
|
+
const token = baseUrl ? readToken(baseUrl, userId) : void 0;
|
|
5100
5513
|
if (!baseUrl || !token) {
|
|
5101
5514
|
throw new InputError("Not logged in. Run `openbkn auth login <url> --token <t>`.");
|
|
5102
5515
|
}
|
|
@@ -5105,22 +5518,27 @@ async function currentTokenFresh() {
|
|
|
5105
5518
|
const needsRefresh = decodable ? isExpired(claims) : true;
|
|
5106
5519
|
if (token.refreshToken && needsRefresh) {
|
|
5107
5520
|
try {
|
|
5108
|
-
const t = await refreshAccessToken(baseUrl, token.refreshToken);
|
|
5109
|
-
writeToken(
|
|
5110
|
-
|
|
5111
|
-
|
|
5112
|
-
|
|
5113
|
-
|
|
5114
|
-
|
|
5521
|
+
const t = await refreshAccessToken(baseUrl, token.refreshToken, void 0, opts.insecure);
|
|
5522
|
+
writeToken(
|
|
5523
|
+
baseUrl,
|
|
5524
|
+
{
|
|
5525
|
+
...token,
|
|
5526
|
+
accessToken: t.accessToken,
|
|
5527
|
+
refreshToken: t.refreshToken ?? token.refreshToken,
|
|
5528
|
+
idToken: t.idToken ?? token.idToken
|
|
5529
|
+
},
|
|
5530
|
+
{ setActive: !opts.user }
|
|
5531
|
+
);
|
|
5115
5532
|
return t.accessToken;
|
|
5116
5533
|
} catch {
|
|
5117
5534
|
}
|
|
5118
5535
|
}
|
|
5119
5536
|
return token.accessToken;
|
|
5120
5537
|
}
|
|
5121
|
-
function whoami() {
|
|
5538
|
+
function whoami(opts = {}) {
|
|
5122
5539
|
const baseUrl = activePlatform();
|
|
5123
|
-
const
|
|
5540
|
+
const userId = baseUrl ? targetUser(baseUrl, opts.user) : void 0;
|
|
5541
|
+
const token = baseUrl ? readToken(baseUrl, userId) : void 0;
|
|
5124
5542
|
const claims = decodeJwt(token?.idToken ?? "") ?? decodeJwt(token?.accessToken ?? "");
|
|
5125
5543
|
if (!claims) {
|
|
5126
5544
|
throw new InputError(
|
|
@@ -5130,7 +5548,7 @@ function whoami() {
|
|
|
5130
5548
|
return {
|
|
5131
5549
|
...claims,
|
|
5132
5550
|
baseUrl: baseUrl ?? void 0,
|
|
5133
|
-
userId
|
|
5551
|
+
userId,
|
|
5134
5552
|
username: usernameOf(token)
|
|
5135
5553
|
};
|
|
5136
5554
|
}
|
|
@@ -5194,7 +5612,6 @@ export {
|
|
|
5194
5612
|
formatError,
|
|
5195
5613
|
isHeadless,
|
|
5196
5614
|
openBrowser,
|
|
5197
|
-
fetchAuthStatus,
|
|
5198
5615
|
deviceLogin,
|
|
5199
5616
|
credentialDeviceLogin,
|
|
5200
5617
|
request,
|
|
@@ -5209,6 +5626,7 @@ export {
|
|
|
5209
5626
|
writePlatformConfig,
|
|
5210
5627
|
resolveContext,
|
|
5211
5628
|
getUserSafe,
|
|
5629
|
+
changePasswordSafe,
|
|
5212
5630
|
admin,
|
|
5213
5631
|
agents,
|
|
5214
5632
|
context,
|
|
@@ -5225,7 +5643,6 @@ export {
|
|
|
5225
5643
|
vega,
|
|
5226
5644
|
createClient,
|
|
5227
5645
|
attachToken,
|
|
5228
|
-
attachNoAuth,
|
|
5229
5646
|
status,
|
|
5230
5647
|
currentToken,
|
|
5231
5648
|
currentTokenFresh,
|
|
@@ -5238,4 +5655,4 @@ export {
|
|
|
5238
5655
|
exportCreds,
|
|
5239
5656
|
auth_exports
|
|
5240
5657
|
};
|
|
5241
|
-
//# sourceMappingURL=chunk-
|
|
5658
|
+
//# sourceMappingURL=chunk-NC6DZ2AU.js.map
|