@openbkn/bkn-sdk 0.1.1-alpha.7 → 0.1.1-alpha.9

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.
@@ -4,11 +4,6 @@ var __export = (target, all) => {
4
4
  __defProp(target, name, { get: all[name], enumerable: true });
5
5
  };
6
6
 
7
- // src/types.ts
8
- var DEFAULT_BUSINESS_DOMAIN = "bd_public";
9
- var DEFAULT_LIST_LIMIT = 30;
10
- var DEFAULT_QUERY_LIMIT = 50;
11
-
12
7
  // src/utils/errors.ts
13
8
  var HttpError = class extends Error {
14
9
  status;
@@ -77,189 +72,6 @@ function truncate(s, n) {
77
72
  return s.length > n ? `${s.slice(0, n)}\u2026` : s;
78
73
  }
79
74
 
80
- // src/config/store.ts
81
- import {
82
- chmodSync,
83
- existsSync,
84
- mkdirSync,
85
- readFileSync,
86
- readdirSync,
87
- rmSync,
88
- writeFileSync
89
- } from "fs";
90
- import { homedir } from "os";
91
- import { join } from "path";
92
-
93
- // src/auth/jwt.ts
94
- function decodeJwt(token) {
95
- const parts = token.split(".");
96
- if (parts.length < 2 || !parts[1]) return void 0;
97
- try {
98
- const json = Buffer.from(parts[1], "base64url").toString("utf8");
99
- return JSON.parse(json);
100
- } catch {
101
- return void 0;
102
- }
103
- }
104
- function isExpired(claims, nowMs = Date.now()) {
105
- return claims?.exp !== void 0 && claims.exp * 1e3 < nowMs;
106
- }
107
-
108
- // src/config/store.ts
109
- var PROFILE_RE = /^[A-Za-z0-9_-]{1,64}$/;
110
- var IS_WIN = process.platform === "win32";
111
- function configDir() {
112
- return process.env.BKN_CONFIG_DIR ?? join(homedir(), ".bkn");
113
- }
114
- function profileName() {
115
- const raw = process.env.BKN_PROFILE?.trim();
116
- if (!raw) return null;
117
- if (!PROFILE_RE.test(raw)) {
118
- throw new Error(`BKN_PROFILE='${raw}' is invalid. Use 1-64 chars from [A-Za-z0-9_-].`);
119
- }
120
- return raw;
121
- }
122
- function statePath() {
123
- const profile = profileName();
124
- return profile ? join(configDir(), "profiles", profile, "state.json") : join(configDir(), "state.json");
125
- }
126
- function encodeKey(baseUrl) {
127
- return Buffer.from(baseUrl, "utf8").toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
128
- }
129
- function platformDir(baseUrl) {
130
- return join(configDir(), "platforms", encodeKey(baseUrl));
131
- }
132
- function userDir(baseUrl, userId) {
133
- return join(platformDir(baseUrl), "users", userId);
134
- }
135
- function userIdFromToken(token) {
136
- return decodeJwt(token.idToken ?? "")?.sub ?? decodeJwt(token.accessToken)?.sub ?? "default";
137
- }
138
- function readState() {
139
- return readJson(statePath()) ?? {};
140
- }
141
- function writeState(state) {
142
- writeJson(statePath(), state);
143
- }
144
- function activePlatform() {
145
- return readState().currentPlatform;
146
- }
147
- function setActivePlatform(baseUrl) {
148
- writeState({ ...readState(), currentPlatform: baseUrl });
149
- }
150
- function activeUserId(baseUrl) {
151
- return readState().activeUsers?.[baseUrl];
152
- }
153
- function setActiveUser(baseUrl, userId) {
154
- const state = readState();
155
- writeState({ ...state, activeUsers: { ...state.activeUsers, [baseUrl]: userId } });
156
- }
157
- function readToken(baseUrl, userId = activeUserId(baseUrl)) {
158
- if (!userId) return void 0;
159
- return readJson(join(userDir(baseUrl, userId), "token.json")) ?? void 0;
160
- }
161
- function writeToken(baseUrl, token) {
162
- const userId = userIdFromToken(token);
163
- writeJson(join(userDir(baseUrl, userId), "token.json"), token, 384);
164
- setActiveUser(baseUrl, userId);
165
- return userId;
166
- }
167
- function deleteToken(baseUrl, userId = activeUserId(baseUrl)) {
168
- if (!userId) return false;
169
- const path = join(userDir(baseUrl, userId), "token.json");
170
- if (!existsSync(path)) return false;
171
- rmSync(path, { force: true });
172
- return true;
173
- }
174
- function readPlatformConfig(baseUrl, userId = activeUserId(baseUrl)) {
175
- if (!userId) return {};
176
- return readJson(join(userDir(baseUrl, userId), "config.json")) ?? {};
177
- }
178
- function writePlatformConfig(baseUrl, config) {
179
- const userId = activeUserId(baseUrl) ?? "default";
180
- writeJson(join(userDir(baseUrl, userId), "config.json"), config);
181
- }
182
- function listPlatforms() {
183
- const root = join(configDir(), "platforms");
184
- if (!existsSync(root)) return [];
185
- const state = readState();
186
- const out = [];
187
- for (const key of readdirSync(root)) {
188
- const baseUrl = decodeKey(key);
189
- if (!baseUrl) continue;
190
- const usersRoot = join(root, key, "users");
191
- if (!existsSync(usersRoot)) continue;
192
- const users = [];
193
- for (const userId of readdirSync(usersRoot)) {
194
- const token = readJson(join(usersRoot, userId, "token.json"));
195
- if (token) users.push({ userId, username: token.username, displayName: token.displayName });
196
- }
197
- if (users.length > 0) {
198
- out.push({ baseUrl, users, activeUserId: state.activeUsers?.[baseUrl] });
199
- }
200
- }
201
- return out;
202
- }
203
- function decodeKey(key) {
204
- try {
205
- const b64 = key.replace(/-/g, "+").replace(/_/g, "/");
206
- return Buffer.from(b64, "base64").toString("utf8");
207
- } catch {
208
- return null;
209
- }
210
- }
211
- function readJson(path) {
212
- if (!existsSync(path)) return void 0;
213
- try {
214
- return JSON.parse(readFileSync(path, "utf8"));
215
- } catch {
216
- return void 0;
217
- }
218
- }
219
- function writeJson(path, value, mode = 384) {
220
- const dir = path.slice(0, path.lastIndexOf("/")) || ".";
221
- mkdirSync(dir, { recursive: true, ...IS_WIN ? {} : { mode: 448 } });
222
- writeFileSync(path, `${JSON.stringify(value, null, 2)}
223
- `, IS_WIN ? {} : { mode });
224
- if (!IS_WIN) chmodSync(path, mode);
225
- }
226
-
227
- // src/config/resolve.ts
228
- function resolveContext(opts = {}) {
229
- const baseUrl = opts.baseUrl ?? process.env.BKN_BASE_URL ?? activePlatform();
230
- if (!baseUrl) {
231
- throw new InputError(
232
- "No base URL. Pass --base-url, set BKN_BASE_URL, or run `openbkn auth login`."
233
- );
234
- }
235
- const normalized = baseUrl.replace(/\/+$/, "");
236
- const stored = readToken(normalized);
237
- const explicit = opts.token ?? process.env.BKN_TOKEN;
238
- const token = explicit ?? stored?.accessToken ?? "";
239
- if (!token && !stored?.noAuth) {
240
- throw new InputError("No access token. Set BKN_TOKEN or run `openbkn auth login`.");
241
- }
242
- const insecure = opts.insecure ?? stored?.tlsInsecure ?? false;
243
- const refresh = !explicit && stored?.refreshToken ? {
244
- refreshToken: stored.refreshToken,
245
- persist: (t) => {
246
- writeToken(normalized, {
247
- ...stored,
248
- accessToken: t.accessToken,
249
- refreshToken: t.refreshToken ?? stored.refreshToken,
250
- idToken: t.idToken ?? stored.idToken
251
- });
252
- }
253
- } : void 0;
254
- return {
255
- baseUrl: normalized,
256
- token,
257
- businessDomain: opts.businessDomain ?? readPlatformConfig(normalized).businessDomain ?? DEFAULT_BUSINESS_DOMAIN,
258
- insecure,
259
- ...refresh ? { refresh } : {}
260
- };
261
- }
262
-
263
75
  // src/auth/oauth.ts
264
76
  import { spawn } from "child_process";
265
77
  function normalizeBaseUrl(value) {
@@ -520,6 +332,194 @@ async function tryRefresh(ctx) {
520
332
  }
521
333
  }
522
334
 
335
+ // src/types.ts
336
+ var DEFAULT_BUSINESS_DOMAIN = "bd_public";
337
+ var DEFAULT_LIST_LIMIT = 30;
338
+ var DEFAULT_QUERY_LIMIT = 50;
339
+
340
+ // src/config/store.ts
341
+ import {
342
+ chmodSync,
343
+ existsSync,
344
+ mkdirSync,
345
+ readFileSync,
346
+ readdirSync,
347
+ rmSync,
348
+ writeFileSync
349
+ } from "fs";
350
+ import { homedir } from "os";
351
+ import { join } from "path";
352
+
353
+ // src/auth/jwt.ts
354
+ function decodeJwt(token) {
355
+ const parts = token.split(".");
356
+ if (parts.length < 2 || !parts[1]) return void 0;
357
+ try {
358
+ const json = Buffer.from(parts[1], "base64url").toString("utf8");
359
+ return JSON.parse(json);
360
+ } catch {
361
+ return void 0;
362
+ }
363
+ }
364
+ function isExpired(claims, nowMs = Date.now()) {
365
+ return claims?.exp !== void 0 && claims.exp * 1e3 < nowMs;
366
+ }
367
+
368
+ // src/config/store.ts
369
+ var PROFILE_RE = /^[A-Za-z0-9_-]{1,64}$/;
370
+ var IS_WIN = process.platform === "win32";
371
+ function configDir() {
372
+ return process.env.BKN_CONFIG_DIR ?? join(homedir(), ".bkn");
373
+ }
374
+ function profileName() {
375
+ const raw = process.env.BKN_PROFILE?.trim();
376
+ if (!raw) return null;
377
+ if (!PROFILE_RE.test(raw)) {
378
+ throw new Error(`BKN_PROFILE='${raw}' is invalid. Use 1-64 chars from [A-Za-z0-9_-].`);
379
+ }
380
+ return raw;
381
+ }
382
+ function statePath() {
383
+ const profile = profileName();
384
+ return profile ? join(configDir(), "profiles", profile, "state.json") : join(configDir(), "state.json");
385
+ }
386
+ function encodeKey(baseUrl) {
387
+ return Buffer.from(baseUrl, "utf8").toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
388
+ }
389
+ function platformDir(baseUrl) {
390
+ return join(configDir(), "platforms", encodeKey(baseUrl));
391
+ }
392
+ function userDir(baseUrl, userId) {
393
+ return join(platformDir(baseUrl), "users", userId);
394
+ }
395
+ function userIdFromToken(token) {
396
+ return decodeJwt(token.idToken ?? "")?.sub ?? decodeJwt(token.accessToken)?.sub ?? "default";
397
+ }
398
+ function readState() {
399
+ return readJson(statePath()) ?? {};
400
+ }
401
+ function writeState(state) {
402
+ writeJson(statePath(), state);
403
+ }
404
+ function activePlatform() {
405
+ return readState().currentPlatform;
406
+ }
407
+ function setActivePlatform(baseUrl) {
408
+ writeState({ ...readState(), currentPlatform: baseUrl });
409
+ }
410
+ function activeUserId(baseUrl) {
411
+ return readState().activeUsers?.[baseUrl];
412
+ }
413
+ function setActiveUser(baseUrl, userId) {
414
+ const state = readState();
415
+ writeState({ ...state, activeUsers: { ...state.activeUsers, [baseUrl]: userId } });
416
+ }
417
+ function readToken(baseUrl, userId = activeUserId(baseUrl)) {
418
+ if (!userId) return void 0;
419
+ return readJson(join(userDir(baseUrl, userId), "token.json")) ?? void 0;
420
+ }
421
+ function writeToken(baseUrl, token) {
422
+ const userId = userIdFromToken(token);
423
+ writeJson(join(userDir(baseUrl, userId), "token.json"), token, 384);
424
+ setActiveUser(baseUrl, userId);
425
+ return userId;
426
+ }
427
+ function deleteToken(baseUrl, userId = activeUserId(baseUrl)) {
428
+ if (!userId) return false;
429
+ const path = join(userDir(baseUrl, userId), "token.json");
430
+ if (!existsSync(path)) return false;
431
+ rmSync(path, { force: true });
432
+ return true;
433
+ }
434
+ function readPlatformConfig(baseUrl, userId = activeUserId(baseUrl)) {
435
+ if (!userId) return {};
436
+ return readJson(join(userDir(baseUrl, userId), "config.json")) ?? {};
437
+ }
438
+ function writePlatformConfig(baseUrl, config) {
439
+ const userId = activeUserId(baseUrl) ?? "default";
440
+ writeJson(join(userDir(baseUrl, userId), "config.json"), config);
441
+ }
442
+ function listPlatforms() {
443
+ const root = join(configDir(), "platforms");
444
+ if (!existsSync(root)) return [];
445
+ const state = readState();
446
+ const out = [];
447
+ for (const key of readdirSync(root)) {
448
+ const baseUrl = decodeKey(key);
449
+ if (!baseUrl) continue;
450
+ const usersRoot = join(root, key, "users");
451
+ if (!existsSync(usersRoot)) continue;
452
+ const users = [];
453
+ for (const userId of readdirSync(usersRoot)) {
454
+ const token = readJson(join(usersRoot, userId, "token.json"));
455
+ if (token) users.push({ userId, username: token.username, displayName: token.displayName });
456
+ }
457
+ if (users.length > 0) {
458
+ out.push({ baseUrl, users, activeUserId: state.activeUsers?.[baseUrl] });
459
+ }
460
+ }
461
+ return out;
462
+ }
463
+ function decodeKey(key) {
464
+ try {
465
+ const b64 = key.replace(/-/g, "+").replace(/_/g, "/");
466
+ return Buffer.from(b64, "base64").toString("utf8");
467
+ } catch {
468
+ return null;
469
+ }
470
+ }
471
+ function readJson(path) {
472
+ if (!existsSync(path)) return void 0;
473
+ try {
474
+ return JSON.parse(readFileSync(path, "utf8"));
475
+ } catch {
476
+ return void 0;
477
+ }
478
+ }
479
+ function writeJson(path, value, mode = 384) {
480
+ const dir = path.slice(0, path.lastIndexOf("/")) || ".";
481
+ mkdirSync(dir, { recursive: true, ...IS_WIN ? {} : { mode: 448 } });
482
+ writeFileSync(path, `${JSON.stringify(value, null, 2)}
483
+ `, IS_WIN ? {} : { mode });
484
+ if (!IS_WIN) chmodSync(path, mode);
485
+ }
486
+
487
+ // src/config/resolve.ts
488
+ function resolveContext(opts = {}) {
489
+ const baseUrl = opts.baseUrl ?? process.env.BKN_BASE_URL ?? activePlatform();
490
+ if (!baseUrl) {
491
+ throw new InputError(
492
+ "No base URL. Pass --base-url, set BKN_BASE_URL, or run `openbkn auth login`."
493
+ );
494
+ }
495
+ const normalized = baseUrl.replace(/\/+$/, "");
496
+ const stored = readToken(normalized);
497
+ const explicit = opts.token ?? process.env.BKN_TOKEN;
498
+ const token = explicit ?? stored?.accessToken ?? "";
499
+ if (!token && !stored?.noAuth) {
500
+ throw new InputError("No access token. Set BKN_TOKEN or run `openbkn auth login`.");
501
+ }
502
+ const insecure = opts.insecure ?? stored?.tlsInsecure ?? false;
503
+ const refresh = !explicit && stored?.refreshToken ? {
504
+ refreshToken: stored.refreshToken,
505
+ persist: (t) => {
506
+ writeToken(normalized, {
507
+ ...stored,
508
+ accessToken: t.accessToken,
509
+ refreshToken: t.refreshToken ?? stored.refreshToken,
510
+ idToken: t.idToken ?? stored.idToken
511
+ });
512
+ }
513
+ } : void 0;
514
+ return {
515
+ baseUrl: normalized,
516
+ token,
517
+ businessDomain: opts.businessDomain ?? readPlatformConfig(normalized).businessDomain ?? DEFAULT_BUSINESS_DOMAIN,
518
+ insecure,
519
+ ...refresh ? { refresh } : {}
520
+ };
521
+ }
522
+
523
523
  // src/api/safe.ts
524
524
  var ADMIN = "/api/safe/v1/admin";
525
525
  function notOnSafe(operation) {
@@ -748,6 +748,15 @@ function admin(ctx) {
748
748
  };
749
749
  }
750
750
 
751
+ // src/api/auth-fetch.ts
752
+ async function authFetch(ctx, send) {
753
+ let res = await send();
754
+ if (res.status === 401 && ctx.refresh && await tryRefresh(ctx)) {
755
+ res = await send();
756
+ }
757
+ return res;
758
+ }
759
+
751
760
  // src/api/agent-chat.ts
752
761
  var FACTORY = "/api/agent-factory";
753
762
  async function fetchAgentInfo(ctx, agentId, version = "v0") {
@@ -816,16 +825,19 @@ async function sendChat(ctx, info, query, opts = {}) {
816
825
  stream: Boolean(opts.stream)
817
826
  };
818
827
  if (opts.conversationId) body.conversation_id = opts.conversationId;
819
- const res = await fetch(`${ctx.baseUrl}${FACTORY}/v1/app/${info.key}/chat/completion`, {
820
- method: "POST",
821
- headers: {
822
- ...buildHeaders(ctx),
823
- "content-type": "application/json",
824
- accept: opts.stream ? "text/event-stream" : "application/json",
825
- "x-language": "zh-CN"
826
- },
827
- body: JSON.stringify(body)
828
- });
828
+ const res = await authFetch(
829
+ ctx,
830
+ () => fetch(`${ctx.baseUrl}${FACTORY}/v1/app/${info.key}/chat/completion`, {
831
+ method: "POST",
832
+ headers: {
833
+ ...buildHeaders(ctx),
834
+ "content-type": "application/json",
835
+ accept: opts.stream ? "text/event-stream" : "application/json",
836
+ "x-language": "zh-CN"
837
+ },
838
+ body: JSON.stringify(body)
839
+ })
840
+ );
829
841
  if (!res.ok) throw new HttpError(res.status, res.statusText, await res.text());
830
842
  const contentType = res.headers.get("content-type") ?? "";
831
843
  if (opts.stream && contentType.includes("text/event-stream")) {
@@ -1039,11 +1051,14 @@ function parseBody(text) {
1039
1051
  }
1040
1052
  async function post(ctx, knId, sessionId, body) {
1041
1053
  applyTls(ctx);
1042
- const res = await fetch(mcpUrl(ctx), {
1043
- method: "POST",
1044
- headers: headers(ctx, knId, sessionId),
1045
- body: JSON.stringify(body)
1046
- });
1054
+ const res = await authFetch(
1055
+ ctx,
1056
+ () => fetch(mcpUrl(ctx), {
1057
+ method: "POST",
1058
+ headers: headers(ctx, knId, sessionId),
1059
+ body: JSON.stringify(body)
1060
+ })
1061
+ );
1047
1062
  const text = await res.text();
1048
1063
  if (!res.ok) throw new HttpError(res.status, res.statusText, text);
1049
1064
  return { res, text };
@@ -2727,7 +2742,10 @@ async function uploadBkn(ctx, tarBuffer, opts = {}) {
2727
2742
  new Blob([new Uint8Array(tarBuffer)], { type: "application/octet-stream" }),
2728
2743
  "bkn.tar"
2729
2744
  );
2730
- const res = await fetch(url, { method: "POST", headers: buildHeaders(ctx), body: form2 });
2745
+ const res = await authFetch(
2746
+ ctx,
2747
+ () => fetch(url, { method: "POST", headers: buildHeaders(ctx), body: form2 })
2748
+ );
2731
2749
  const text = await res.text();
2732
2750
  if (!res.ok) throw new HttpError(res.status, res.statusText, text);
2733
2751
  return text ? JSON.parse(text) : void 0;
@@ -2736,7 +2754,7 @@ async function downloadBkn(ctx, knId, opts = {}) {
2736
2754
  applyTls(ctx);
2737
2755
  const url = new URL(`${ctx.baseUrl}${BKNS}/${encodeURIComponent(knId)}`);
2738
2756
  url.searchParams.set("branch", opts.branch ?? "main");
2739
- const res = await fetch(url, { method: "GET", headers: buildHeaders(ctx) });
2757
+ const res = await authFetch(ctx, () => fetch(url, { method: "GET", headers: buildHeaders(ctx) }));
2740
2758
  if (!res.ok) throw new HttpError(res.status, res.statusText, await res.text());
2741
2759
  return Buffer.from(await res.arrayBuffer());
2742
2760
  }
@@ -3646,15 +3664,18 @@ function deltaContent(chunk) {
3646
3664
  }
3647
3665
  async function chatCompletionsStream(ctx, model, messages, onDelta) {
3648
3666
  applyTls(ctx);
3649
- const res = await fetch(`${ctx.baseUrl}${API}/chat/completions`, {
3650
- method: "POST",
3651
- headers: {
3652
- ...buildHeaders(ctx),
3653
- "content-type": "application/json",
3654
- accept: "text/event-stream"
3655
- },
3656
- body: JSON.stringify({ model, messages, stream: true })
3657
- });
3667
+ const res = await authFetch(
3668
+ ctx,
3669
+ () => fetch(`${ctx.baseUrl}${API}/chat/completions`, {
3670
+ method: "POST",
3671
+ headers: {
3672
+ ...buildHeaders(ctx),
3673
+ "content-type": "application/json",
3674
+ accept: "text/event-stream"
3675
+ },
3676
+ body: JSON.stringify({ model, messages, stream: true })
3677
+ })
3678
+ );
3658
3679
  if (!res.ok) throw new HttpError(res.status, res.statusText, await res.text());
3659
3680
  const reader = res.body?.getReader();
3660
3681
  if (!reader) throw new Error("No response body for stream");
@@ -3761,11 +3782,14 @@ async function registerSkillZip(ctx, bytes, opts = {}) {
3761
3782
  form2.set("file", new Blob([bytes]), opts.filename ?? "skill.zip");
3762
3783
  if (opts.source) form2.set("source", opts.source);
3763
3784
  if (opts.extendInfo) form2.set("extend_info", JSON.stringify(opts.extendInfo));
3764
- const res = await fetch(`${ctx.baseUrl}${BASE5}/skills`, {
3765
- method: "POST",
3766
- headers: buildHeaders(ctx),
3767
- body: form2
3768
- });
3785
+ const res = await authFetch(
3786
+ ctx,
3787
+ () => fetch(`${ctx.baseUrl}${BASE5}/skills`, {
3788
+ method: "POST",
3789
+ headers: buildHeaders(ctx),
3790
+ body: form2
3791
+ })
3792
+ );
3769
3793
  const text = await res.text();
3770
3794
  if (!res.ok) throw new HttpError(res.status, res.statusText, text);
3771
3795
  return text ? JSON.parse(text) : void 0;
@@ -3775,20 +3799,26 @@ async function updateSkillPackageZip(ctx, skillId, bytes, filename = "skill.zip"
3775
3799
  const form2 = new FormData();
3776
3800
  form2.set("file_type", "zip");
3777
3801
  form2.set("file", new Blob([bytes]), filename);
3778
- const res = await fetch(`${ctx.baseUrl}${BASE5}/skills/${encodeURIComponent(skillId)}/package`, {
3779
- method: "PUT",
3780
- headers: buildHeaders(ctx),
3781
- body: form2
3782
- });
3802
+ const res = await authFetch(
3803
+ ctx,
3804
+ () => fetch(`${ctx.baseUrl}${BASE5}/skills/${encodeURIComponent(skillId)}/package`, {
3805
+ method: "PUT",
3806
+ headers: buildHeaders(ctx),
3807
+ body: form2
3808
+ })
3809
+ );
3783
3810
  const text = await res.text();
3784
3811
  if (!res.ok) throw new HttpError(res.status, res.statusText, text);
3785
3812
  return text ? JSON.parse(text) : void 0;
3786
3813
  }
3787
3814
  async function downloadSkill(ctx, skillId) {
3788
3815
  applyTls(ctx);
3789
- const res = await fetch(`${ctx.baseUrl}${BASE5}/skills/${encodeURIComponent(skillId)}/download`, {
3790
- headers: buildHeaders(ctx)
3791
- });
3816
+ const res = await authFetch(
3817
+ ctx,
3818
+ () => fetch(`${ctx.baseUrl}${BASE5}/skills/${encodeURIComponent(skillId)}/download`, {
3819
+ headers: buildHeaders(ctx)
3820
+ })
3821
+ );
3792
3822
  if (!res.ok) throw new HttpError(res.status, res.statusText, await res.text());
3793
3823
  return new Uint8Array(await res.arrayBuffer());
3794
3824
  }
@@ -3942,9 +3972,11 @@ var PATH = "/api/agent-operator-integration/v1/tool-box";
3942
3972
  var IMPEX = "/api/agent-operator-integration/v1/impex";
3943
3973
  async function exportConfig(ctx, id, type = "toolbox") {
3944
3974
  applyTls(ctx);
3945
- const res = await fetch(
3946
- `${ctx.baseUrl}${IMPEX}/export/${encodeURIComponent(type)}/${encodeURIComponent(id)}`,
3947
- { headers: buildHeaders(ctx) }
3975
+ const res = await authFetch(
3976
+ ctx,
3977
+ () => fetch(`${ctx.baseUrl}${IMPEX}/export/${encodeURIComponent(type)}/${encodeURIComponent(id)}`, {
3978
+ headers: buildHeaders(ctx)
3979
+ })
3948
3980
  );
3949
3981
  const buf = new Uint8Array(await res.arrayBuffer());
3950
3982
  if (!res.ok) throw new HttpError(res.status, res.statusText, new TextDecoder().decode(buf));
@@ -3955,11 +3987,14 @@ async function importConfig(ctx, filePath, type = "toolbox") {
3955
3987
  const buf = await readFile2(filePath);
3956
3988
  const form2 = new FormData();
3957
3989
  form2.append("data", new Blob([new Uint8Array(buf)]), basename3(filePath));
3958
- const res = await fetch(`${ctx.baseUrl}${IMPEX}/import/${encodeURIComponent(type)}`, {
3959
- method: "POST",
3960
- headers: buildHeaders(ctx),
3961
- body: form2
3962
- });
3990
+ const res = await authFetch(
3991
+ ctx,
3992
+ () => fetch(`${ctx.baseUrl}${IMPEX}/import/${encodeURIComponent(type)}`, {
3993
+ method: "POST",
3994
+ headers: buildHeaders(ctx),
3995
+ body: form2
3996
+ })
3997
+ );
3963
3998
  const text = await res.text();
3964
3999
  if (!res.ok) throw new HttpError(res.status, res.statusText, text);
3965
4000
  return text ? JSON.parse(text) : text;
@@ -3970,11 +4005,14 @@ async function uploadTool(ctx, boxId, filePath, metadataType = "openapi") {
3970
4005
  const form2 = new FormData();
3971
4006
  form2.append("metadata_type", metadataType);
3972
4007
  form2.append("data", new Blob([new Uint8Array(buf)]), basename3(filePath));
3973
- const res = await fetch(`${ctx.baseUrl}${PATH}/${encodeURIComponent(boxId)}/tool`, {
3974
- method: "POST",
3975
- headers: buildHeaders(ctx),
3976
- body: form2
3977
- });
4008
+ const res = await authFetch(
4009
+ ctx,
4010
+ () => fetch(`${ctx.baseUrl}${PATH}/${encodeURIComponent(boxId)}/tool`, {
4011
+ method: "POST",
4012
+ headers: buildHeaders(ctx),
4013
+ body: form2
4014
+ })
4015
+ );
3978
4016
  const text = await res.text();
3979
4017
  if (!res.ok) throw new HttpError(res.status, res.statusText, text);
3980
4018
  return text ? JSON.parse(text) : text;
@@ -4947,16 +4985,16 @@ async function rawCall(ctx, path, opts = {}) {
4947
4985
  if (!extra["content-type"]) extra["content-type"] = "application/json";
4948
4986
  }
4949
4987
  const method = opts.method ?? (body !== void 0 ? "POST" : "GET");
4950
- const headers2 = buildHeaders(
4951
- { ...ctx, businessDomain: opts.businessDomain ?? ctx.businessDomain },
4952
- extra
4953
- );
4988
+ const headersFor = () => buildHeaders({ ...ctx, businessDomain: opts.businessDomain ?? ctx.businessDomain }, extra);
4954
4989
  if (opts.verbose) process.stderr.write(`> ${method} ${url}
4955
4990
  `);
4956
4991
  const controller = new AbortController();
4957
4992
  const timer = setTimeout(() => controller.abort(), opts.timeoutMs ?? 3e4);
4958
4993
  try {
4959
- const res = await fetch(url, { method, headers: headers2, body, signal: controller.signal });
4994
+ const res = await authFetch(
4995
+ ctx,
4996
+ () => fetch(url, { method, headers: headersFor(), body, signal: controller.signal })
4997
+ );
4960
4998
  return { status: res.status, statusText: res.statusText, body: await res.text() };
4961
4999
  } finally {
4962
5000
  clearTimeout(timer);
@@ -4989,6 +5027,7 @@ __export(auth_exports, {
4989
5027
  attachNoAuth: () => attachNoAuth,
4990
5028
  attachToken: () => attachToken,
4991
5029
  currentToken: () => currentToken,
5030
+ currentTokenFresh: () => currentTokenFresh,
4992
5031
  deletePlatform: () => deletePlatform,
4993
5032
  exportCreds: () => exportCreds,
4994
5033
  hostOf: () => hostOf,
@@ -5055,6 +5094,30 @@ function currentToken() {
5055
5094
  if (!token) throw new InputError("Not logged in. Run `openbkn auth login <url> --token <t>`.");
5056
5095
  return token.accessToken;
5057
5096
  }
5097
+ async function currentTokenFresh() {
5098
+ const baseUrl = activePlatform();
5099
+ const token = baseUrl ? readToken(baseUrl) : void 0;
5100
+ if (!baseUrl || !token) {
5101
+ throw new InputError("Not logged in. Run `openbkn auth login <url> --token <t>`.");
5102
+ }
5103
+ const claims = decodeJwt(token.accessToken);
5104
+ const decodable = claims?.exp !== void 0;
5105
+ const needsRefresh = decodable ? isExpired(claims) : true;
5106
+ if (token.refreshToken && needsRefresh) {
5107
+ try {
5108
+ const t = await refreshAccessToken(baseUrl, token.refreshToken);
5109
+ writeToken(baseUrl, {
5110
+ ...token,
5111
+ accessToken: t.accessToken,
5112
+ refreshToken: t.refreshToken ?? token.refreshToken,
5113
+ idToken: t.idToken ?? token.idToken
5114
+ });
5115
+ return t.accessToken;
5116
+ } catch {
5117
+ }
5118
+ }
5119
+ return token.accessToken;
5120
+ }
5058
5121
  function whoami() {
5059
5122
  const baseUrl = activePlatform();
5060
5123
  const token = baseUrl ? readToken(baseUrl) : void 0;
@@ -5125,26 +5188,26 @@ function exportCreds() {
5125
5188
  }
5126
5189
 
5127
5190
  export {
5128
- rawCall,
5129
- DEFAULT_BUSINESS_DOMAIN,
5130
- DEFAULT_LIST_LIMIT,
5131
- DEFAULT_QUERY_LIMIT,
5132
5191
  HttpError,
5133
5192
  InputError,
5134
5193
  toExitCode,
5135
5194
  formatError,
5136
- decodeJwt,
5137
- activePlatform,
5138
- setActivePlatform,
5139
- readPlatformConfig,
5140
- writePlatformConfig,
5141
- resolveContext,
5142
5195
  isHeadless,
5143
5196
  openBrowser,
5144
5197
  fetchAuthStatus,
5145
5198
  deviceLogin,
5146
5199
  credentialDeviceLogin,
5147
5200
  request,
5201
+ rawCall,
5202
+ DEFAULT_BUSINESS_DOMAIN,
5203
+ DEFAULT_LIST_LIMIT,
5204
+ DEFAULT_QUERY_LIMIT,
5205
+ decodeJwt,
5206
+ activePlatform,
5207
+ setActivePlatform,
5208
+ readPlatformConfig,
5209
+ writePlatformConfig,
5210
+ resolveContext,
5148
5211
  getUserSafe,
5149
5212
  admin,
5150
5213
  agents,
@@ -5165,6 +5228,7 @@ export {
5165
5228
  attachNoAuth,
5166
5229
  status,
5167
5230
  currentToken,
5231
+ currentTokenFresh,
5168
5232
  whoami,
5169
5233
  listPlatforms2 as listPlatforms,
5170
5234
  use,
@@ -5174,4 +5238,4 @@ export {
5174
5238
  exportCreds,
5175
5239
  auth_exports
5176
5240
  };
5177
- //# sourceMappingURL=chunk-GAYXY7LP.js.map
5241
+ //# sourceMappingURL=chunk-BFE4SU3V.js.map