@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.
@@ -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 fetchAuthStatus(baseUrl) {
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 fetch(`${base}/oauth2/token`, {
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 fetch(`${base}/oauth2/device/auth`, form(params));
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 fetch(
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(base, clientId, opts.scope ?? DEVICE_SCOPE, opts.audience);
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(base, da.device_code, clientId, (da.interval ?? 5) * 1e3, windowMs);
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(base, clientId, opts.scope ?? DEVICE_SCOPE, opts.audience);
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 fetch(url, {
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(base, da.device_code, clientId, (da.interval ?? 5) * 1e3, windowMs);
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
- // No token = a no-auth platform (no bkn-safe); send no Authorization.
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 (v !== void 0) url.searchParams.set(k, String(v));
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 = () => fetch(url, {
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(ctx.baseUrl, ctx.refresh.refreshToken, ctx.refresh.clientId);
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
- return decodeJwt(token.idToken ?? "")?.sub ?? decodeJwt(token.accessToken)?.sub ?? "default";
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 stored = readToken(normalized);
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 && !stored?.noAuth) {
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 ?? stored?.tlsInsecure ?? false;
568
+ const insecure = opts.insecure ?? false;
513
569
  const refresh = !explicit && stored?.refreshToken ? {
514
570
  refreshToken: stored.refreshToken,
515
571
  persist: (t) => {
516
- writeToken(normalized, {
517
- ...stored,
518
- accessToken: t.accessToken,
519
- refreshToken: t.refreshToken ?? stored.refreshToken,
520
- idToken: t.idToken ?? stored.idToken
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
- () => fetch(`${ctx.baseUrl}${FACTORY}/v1/app/${info.key}/chat/completion`, {
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
- () => fetch(mcpUrl(ctx), {
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
- limit: opts.limit && opts.limit > 0 ? opts.limit : void 0
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 createResource(ctx, opts) {
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
- name: opts.name,
1538
- catalog_id: opts.catalogId,
1539
- category: "table",
1540
- source_identifier: opts.sourceIdentifier
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 (opts.fields && opts.fields.length > 0) body.schema_definition = opts.fields;
1543
- return request(ctx, BASE3, { method: "POST", body });
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 deleteResource(ctx, id) {
1546
- return request(ctx, `${BASE3}/${encodeURIComponent(id)}`, { method: "DELETE" });
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
- () => fetch(url, { method: "POST", headers: buildHeaders(ctx), body: form2 })
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(ctx, () => fetch(url, { method: "GET", headers: buildHeaders(ctx) }));
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
- embedding_fields: z.array(z.string()).optional(),
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
- embedding_fields: z.string().optional(),
2893
- build_key_fields: z.string().optional(),
2894
- embedding_model: z.string().optional(),
2895
- model_dimensions: z.number().optional()
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.embedding_fields?.length ? { embedding_fields: p.embedding_fields.join(",") } : {},
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: { limit: opts.limit, offset: opts.offset }
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(`Creating resources for ${targets.length} table(s)...`);
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
- const created = await createResource(ctx, {
3421
- name: t.name,
3422
- catalogId: opts.catalogId,
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
- () => fetch(`${ctx.baseUrl}${API}/chat/completions`, {
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
- () => fetch(`${ctx.baseUrl}${BASE5}/skills`, {
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
- () => fetch(`${ctx.baseUrl}${BASE5}/skills/${encodeURIComponent(skillId)}/package`, {
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
- () => fetch(`${ctx.baseUrl}${BASE5}/skills/${encodeURIComponent(skillId)}/download`, {
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
- () => fetch(`${ctx.baseUrl}${IMPEX}/export/${encodeURIComponent(type)}/${encodeURIComponent(id)}`, {
4036
- headers: buildHeaders(ctx)
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
- () => fetch(`${ctx.baseUrl}${IMPEX}/import/${encodeURIComponent(type)}`, {
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
- () => fetch(`${ctx.baseUrl}${PATH}/${encodeURIComponent(boxId)}/tool`, {
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-ai/claude-judge.ts
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-ai/diagnose.ts
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-ai/eval-set.ts
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
- () => fetch(url, { method, headers: headersFor(), body, signal: controller.signal })
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 attachNoAuth(baseUrl, opts = {}) {
5182
- const url = normalize(baseUrl);
5183
- writeToken(url, { baseUrl: url, accessToken: "", noAuth: true, tlsInsecure: opts.insecure });
5184
- setActivePlatform(url);
5185
- return { baseUrl: url, noAuth: true };
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 token = readToken(baseUrl);
5491
+ const userId = targetUser(baseUrl, opts.user);
5492
+ const token = readToken(baseUrl, userId);
5191
5493
  return {
5192
5494
  baseUrl,
5193
- userId: activeUserId(baseUrl),
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 token = baseUrl ? readToken(baseUrl) : void 0;
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(baseUrl, {
5218
- ...token,
5219
- accessToken: t.accessToken,
5220
- refreshToken: t.refreshToken ?? token.refreshToken,
5221
- idToken: t.idToken ?? token.idToken
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 token = baseUrl ? readToken(baseUrl) : void 0;
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: baseUrl ? activeUserId(baseUrl) : void 0,
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-SH2KLES5.js.map
5656
+ //# sourceMappingURL=chunk-ISJHU26W.js.map