@bodhiapp/bodhi-js-ext 0.0.15 → 0.0.17

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.
@@ -1,5 +1,5 @@
1
- import { DirectClientBase as U, createStoragePrefixWithBasePath as P, STORAGE_PREFIXES as X, isApiResultOperationError as w, createOperationError as l, isApiResultError as b, isApiResultSuccess as A, generateCodeVerifier as O, generateCodeChallenge as D, PENDING_EXTENSION_READY as f, Logger as N, NOOP_STATE_CALLBACK as M, createExtensionStateNotInitialized as q, BACKEND_SERVER_NOT_REACHABLE as B, createExtensionStateNotFound as $, INITIAL_AUTH_STATE as K, createApiError as V, Chat as H, Models as z, Embeddings as F, isAuthError as Q, BaseFacadeClient as G, refreshAccessToken as W } from "@bodhiapp/bodhi-js-core";
2
- const h = {
1
+ import { DirectClientBase as K, createStoragePrefixWithBasePath as L, STORAGE_PREFIXES as U, isApiResultOperationError as v, createOperationError as d, isApiResultError as M, isApiResultSuccess as O, getMissingToolsetScopeIds as D, getRequestedToolsetScopes as q, generateCodeVerifier as b, generateCodeChallenge as V, PENDING_EXTENSION_READY as w, Logger as P, NOOP_STATE_CALLBACK as F, createExtensionStateNotInitialized as H, BACKEND_SERVER_NOT_REACHABLE as z, createExtensionStateNotFound as Q, INITIAL_AUTH_STATE as G, createApiError as W, Chat as J, Models as Y, Embeddings as j, isAuthError as Z, BaseFacadeClient as ee, refreshAccessToken as te } from "@bodhiapp/bodhi-js-core";
2
+ const c = {
3
3
  EXT2EXT_CLIENT_REQUEST: "EXT2EXT_CLIENT_REQUEST",
4
4
  EXT2EXT_CLIENT_RESPONSE: "EXT2EXT_CLIENT_RESPONSE",
5
5
  EXT2EXT_CLIENT_BROADCAST: "EXT2EXT_CLIENT_BROADCAST",
@@ -11,106 +11,113 @@ const h = {
11
11
  EXT2EXT_CLIENT_STREAM_ERROR: "EXT2EXT_CLIENT_STREAM_ERROR",
12
12
  EXT2EXT_CLIENT_STREAM_API_ERROR: "EXT2EXT_CLIENT_STREAM_API_ERROR",
13
13
  EXT2EXT_CLIENT_STREAM_DONE: "EXT2EXT_CLIENT_STREAM_DONE"
14
- }, k = "ext2ext-client-stream", p = {
14
+ }, $ = "ext2ext-client-stream", m = {
15
15
  LOGIN: "login",
16
16
  LOGOUT: "logout",
17
17
  GET_AUTH_STATE: "getAuthState",
18
18
  DISCOVER_EXTENSION: "discoverBodhiExtension",
19
19
  GET_EXTENSION_ID: "get_extension_id",
20
20
  SET_EXTENSION_ID: "setExtensionId"
21
- }, J = 5e3, Y = 3, Z = 500, j = 500;
22
- function ee(c) {
23
- return "error" in c;
21
+ }, re = 5e3, se = 3, oe = 500, ie = 500, ne = 3e4;
22
+ function ae(a) {
23
+ return "error" in a;
24
24
  }
25
- class te extends U {
25
+ class ce extends K {
26
26
  constructor(e, t) {
27
- const r = P(
27
+ const r = L(
28
28
  e.basePath,
29
- X.EXT_DIRECT
30
- ), o = {
29
+ U.EXT_DIRECT
30
+ ), i = {
31
31
  authClientId: e.authClientId,
32
32
  authServerUrl: e.authServerUrl,
33
33
  userScope: e.userScope,
34
34
  storagePrefix: r,
35
35
  logLevel: e.logLevel,
36
- loggerPrefix: "DirectExtClient"
36
+ loggerPrefix: "DirectExtClient",
37
+ apiTimeoutMs: e.apiTimeoutMs
37
38
  };
38
- super(o, t);
39
+ super(i, t);
39
40
  }
40
41
  // ============================================================================
41
42
  // Authentication (chrome.identity OAuth)
42
43
  // ============================================================================
43
- async login() {
44
- const e = await this.getAuthState();
45
- if (e.status === "authenticated")
46
- return e;
47
- const t = await this.requestResourceAccess();
48
- if (w(t))
49
- throw l(t.error.message, t.error.type);
50
- if (b(t)) {
51
- const { message: u } = t.body.error;
52
- throw l(u, "auth_error");
44
+ async login(e) {
45
+ const t = await this.getAuthState();
46
+ if (t.status === "authenticated")
47
+ return t;
48
+ const r = await this.requestResourceAccess(e?.toolsetScopeIds, e?.version);
49
+ if (v(r))
50
+ throw d(r.error.message, r.error.type);
51
+ if (M(r)) {
52
+ const { message: T } = r.body.error;
53
+ throw d(T, "auth_error");
53
54
  }
54
- if (!A(t))
55
- throw l(`Unexpected HTTP ${t.status}`, "auth_error");
56
- const r = t.body.scope;
57
- await chrome.storage.session.set({ [this.storageKeys.RESOURCE_SCOPE]: r });
58
- const o = `openid profile email roles ${this.userScope} ${r}`, s = O(), n = await D(s), i = O();
55
+ if (!O(r))
56
+ throw d(`Unexpected HTTP ${r.status}`, "auth_error");
57
+ const i = r.body.scope;
58
+ await chrome.storage.session.set({ [this.storageKeys.RESOURCE_SCOPE]: i });
59
+ const s = r.body.toolsets || [], o = D(e?.toolsetScopeIds, s);
60
+ if (o.length > 0)
61
+ throw d(
62
+ `toolsetScopeIds not received back from request-access call: [${o.join(", ")}], check developer console on configuring the toolset scopes correctly`,
63
+ "auth_error"
64
+ );
65
+ const n = q(e?.toolsetScopeIds, s), E = `openid profile email roles ${this.userScope} ${i} ${n}`.trim(), h = b(), l = await V(h), u = b();
59
66
  await chrome.storage.session.set({
60
- [this.storageKeys.CODE_VERIFIER]: s,
61
- [this.storageKeys.STATE]: i
67
+ [this.storageKeys.CODE_VERIFIER]: h,
68
+ [this.storageKeys.STATE]: u
62
69
  });
63
- const d = chrome.identity.getRedirectURL("callback"), a = new URL(this.authEndpoints.authorize);
64
- return a.searchParams.set("client_id", this.authClientId), a.searchParams.set("response_type", "code"), a.searchParams.set("redirect_uri", d), a.searchParams.set("scope", o), a.searchParams.set("code_challenge", n), a.searchParams.set("code_challenge_method", "S256"), a.searchParams.set("state", i), new Promise((u, E) => {
70
+ const p = chrome.identity.getRedirectURL("callback"), g = new URL(this.authEndpoints.authorize);
71
+ return g.searchParams.set("client_id", this.authClientId), g.searchParams.set("response_type", "code"), g.searchParams.set("redirect_uri", p), g.searchParams.set("scope", E), g.searchParams.set("code_challenge", l), g.searchParams.set("code_challenge_method", "S256"), g.searchParams.set("state", u), new Promise((T, _) => {
65
72
  chrome.identity.launchWebAuthFlow(
66
73
  {
67
- url: a.toString(),
74
+ url: g.toString(),
68
75
  interactive: !0
69
76
  },
70
- async (g) => {
77
+ async (R) => {
71
78
  if (chrome.runtime.lastError) {
72
79
  await chrome.storage.session.remove([
73
80
  this.storageKeys.CODE_VERIFIER,
74
81
  this.storageKeys.STATE
75
- ]), E(chrome.runtime.lastError);
82
+ ]), _(chrome.runtime.lastError);
76
83
  return;
77
84
  }
78
- if (!g) {
85
+ if (!R) {
79
86
  await chrome.storage.session.remove([
80
87
  this.storageKeys.CODE_VERIFIER,
81
88
  this.storageKeys.STATE
82
- ]), E(l("No redirect URL received", "oauth-error"));
89
+ ]), _(d("No redirect URL received", "oauth-error"));
83
90
  return;
84
91
  }
85
92
  try {
86
- const _ = new URL(g), T = _.searchParams.get("code"), y = _.searchParams.get("state"), L = (await chrome.storage.session.get(this.storageKeys.STATE))[this.storageKeys.STATE];
87
- if (y !== L) {
93
+ const I = new URL(R), f = I.searchParams.get("code"), x = I.searchParams.get("state"), B = (await chrome.storage.session.get(this.storageKeys.STATE))[this.storageKeys.STATE];
94
+ if (x !== B) {
88
95
  await chrome.storage.session.remove([
89
96
  this.storageKeys.CODE_VERIFIER,
90
97
  this.storageKeys.STATE
91
- ]), E(l("State mismatch - possible CSRF", "oauth-error"));
98
+ ]), _(d("State mismatch - possible CSRF", "oauth-error"));
92
99
  return;
93
100
  }
94
- if (!T) {
101
+ if (!f) {
95
102
  await chrome.storage.session.remove([
96
103
  this.storageKeys.CODE_VERIFIER,
97
104
  this.storageKeys.STATE
98
- ]), E(l("No authorization code received", "oauth-error"));
105
+ ]), _(d("No authorization code received", "oauth-error"));
99
106
  return;
100
107
  }
101
- await this.exchangeCodeForTokens(T);
102
- const R = await this.getAuthState();
103
- if (R.status !== "authenticated")
104
- throw l("Login failed", "oauth-error");
105
- this.setAuthState(R), await chrome.storage.session.remove([
108
+ await this.exchangeCodeForTokens(f);
109
+ const C = await this.getAuthState();
110
+ if (C.status !== "authenticated")
111
+ throw d("Login failed", "oauth-error");
112
+ this.setAuthState(C), await chrome.storage.session.remove([
106
113
  this.storageKeys.CODE_VERIFIER,
107
114
  this.storageKeys.STATE
108
- ]), u(R);
109
- } catch (_) {
115
+ ]), T(C);
116
+ } catch (I) {
110
117
  await chrome.storage.session.remove([
111
118
  this.storageKeys.CODE_VERIFIER,
112
119
  this.storageKeys.STATE
113
- ]), E(_);
120
+ ]), _(I);
114
121
  }
115
122
  }
116
123
  );
@@ -120,7 +127,7 @@ class te extends U {
120
127
  const t = (await chrome.storage.session.get(this.storageKeys.REFRESH_TOKEN))[this.storageKeys.REFRESH_TOKEN];
121
128
  if (t)
122
129
  try {
123
- const o = new URLSearchParams({
130
+ const i = new URLSearchParams({
124
131
  token: t,
125
132
  client_id: this.authClientId,
126
133
  token_type_hint: "refresh_token"
@@ -130,10 +137,10 @@ class te extends U {
130
137
  headers: {
131
138
  "Content-Type": "application/x-www-form-urlencoded"
132
139
  },
133
- body: o
140
+ body: i
134
141
  });
135
- } catch (o) {
136
- this.logger.warn("Token revocation failed:", o);
142
+ } catch (i) {
143
+ this.logger.warn("Token revocation failed:", i);
137
144
  }
138
145
  await chrome.storage.session.remove([
139
146
  this.storageKeys.ACCESS_TOKEN,
@@ -153,7 +160,7 @@ class te extends U {
153
160
  // OAuth Helper Methods
154
161
  // ============================================================================
155
162
  async exchangeCodeForTokens(e) {
156
- const r = (await chrome.storage.session.get(this.storageKeys.CODE_VERIFIER))[this.storageKeys.CODE_VERIFIER], o = chrome.identity.getRedirectURL("callback"), s = await fetch(this.authEndpoints.token, {
163
+ const r = (await chrome.storage.session.get(this.storageKeys.CODE_VERIFIER))[this.storageKeys.CODE_VERIFIER], i = chrome.identity.getRedirectURL("callback"), s = await fetch(this.authEndpoints.token, {
157
164
  method: "POST",
158
165
  headers: {
159
166
  "Content-Type": "application/x-www-form-urlencoded"
@@ -161,20 +168,20 @@ class te extends U {
161
168
  body: new URLSearchParams({
162
169
  grant_type: "authorization_code",
163
170
  code: e,
164
- redirect_uri: o,
171
+ redirect_uri: i,
165
172
  client_id: this.authClientId,
166
173
  code_verifier: r
167
174
  })
168
175
  });
169
176
  if (!s.ok) {
170
- const d = await s.text();
171
- throw new Error(`Token exchange failed: ${s.status} ${d}`);
177
+ const E = await s.text();
178
+ throw new Error(`Token exchange failed: ${s.status} ${E}`);
172
179
  }
173
- const n = await s.json(), i = Date.now() + (n.expires_in || 3600) * 1e3;
180
+ const o = await s.json(), n = Date.now() + (o.expires_in || 3600) * 1e3;
174
181
  await chrome.storage.session.set({
175
- [this.storageKeys.ACCESS_TOKEN]: n.access_token,
176
- [this.storageKeys.REFRESH_TOKEN]: n.refresh_token,
177
- [this.storageKeys.EXPIRES_AT]: i
182
+ [this.storageKeys.ACCESS_TOKEN]: o.access_token,
183
+ [this.storageKeys.REFRESH_TOKEN]: o.refresh_token,
184
+ [this.storageKeys.EXPIRES_AT]: n
178
185
  }), await chrome.storage.session.remove([this.storageKeys.CODE_VERIFIER, this.storageKeys.STATE]);
179
186
  }
180
187
  // ============================================================================
@@ -194,13 +201,13 @@ class te extends U {
194
201
  return chrome.identity.getRedirectURL("callback");
195
202
  }
196
203
  }
197
- function re(c) {
198
- return c !== null && typeof c == "object";
204
+ function he(a) {
205
+ return a !== null && typeof a == "object";
199
206
  }
200
- function se(c) {
201
- return re(c) && "message" in c && typeof c.message == "string" && "type" in c && typeof c.type == "string";
207
+ function Ee(a) {
208
+ return he(a) && "message" in a && typeof a.message == "string" && "type" in a && typeof a.type == "string";
202
209
  }
203
- const m = {
210
+ const S = {
204
211
  API_REQUEST: "BODHI_API_REQUEST",
205
212
  API_RESPONSE: "BODHI_API_RESPONSE",
206
213
  STREAM_REQUEST: "BODHI_STREAM_REQUEST",
@@ -211,36 +218,36 @@ const m = {
211
218
  EXT_REQUEST: "BODHI_EXT_REQUEST",
212
219
  EXT_RESPONSE: "BODHI_EXT_RESPONSE"
213
220
  };
214
- function oe(c) {
215
- return c !== null && typeof c == "object" && typeof c.status == "number" && c.status >= 200 && c.status < 300 && "body" in c;
221
+ function ue(a) {
222
+ return a !== null && typeof a == "object" && typeof a.status == "number" && a.status >= 200 && a.status < 300 && "body" in a;
216
223
  }
217
- function ne(c) {
218
- return c !== null && typeof c == "object" && c.type === m.STREAM_CHUNK;
224
+ function de(a) {
225
+ return a !== null && typeof a == "object" && a.type === S.STREAM_CHUNK;
219
226
  }
220
- function ie(c) {
221
- return c !== null && typeof c == "object" && c.type === m.STREAM_API_ERROR;
227
+ function le(a) {
228
+ return a !== null && typeof a == "object" && a.type === S.STREAM_API_ERROR;
222
229
  }
223
- function ae(c) {
224
- return c !== null && typeof c == "object" && c.type === m.STREAM_ERROR;
230
+ function ge(a) {
231
+ return a !== null && typeof a == "object" && a.type === S.STREAM_ERROR;
225
232
  }
226
- function C(c) {
227
- return c !== null && typeof c == "object" && "error" in c;
233
+ function N(a) {
234
+ return a !== null && typeof a == "object" && "error" in a;
228
235
  }
229
- function ce(c) {
230
- return c instanceof Error && "error" in c && !("response" in c) && se(c.error);
236
+ function Te(a) {
237
+ return a instanceof Error && "error" in a && !("response" in a) && Ee(a.error);
231
238
  }
232
- const he = {
239
+ const _e = {
233
240
  GET_EXTENSION_ID: "get_extension_id",
234
241
  TEST_CONNECTION: "test_connection"
235
- }, Ee = "BODHI_STREAM_PORT";
236
- class ue {
242
+ }, pe = "BODHI_STREAM_PORT";
243
+ class me {
237
244
  constructor(e = {}, t) {
238
245
  this.state = {
239
246
  type: "extension",
240
247
  extension: "not-initialized",
241
248
  extensionId: null,
242
- server: f
243
- }, this.extensionId = null, this.broadcastListenerActive = !1, this.config = e, this.logger = new N("ExtClient", e?.logLevel || "warn"), this.onStateChange = t ?? M;
249
+ server: w
250
+ }, this.extensionId = null, this.broadcastListenerActive = !1, this.config = e, this.logger = new P("ExtClient", e?.logLevel || "warn"), this.onStateChange = t ?? F, this.apiTimeoutMs = e.apiTimeoutMs ?? ne;
244
251
  }
245
252
  /**
246
253
  * Set client state and notify callback
@@ -267,7 +274,7 @@ class ue {
267
274
  setupBroadcastListener() {
268
275
  this.broadcastListenerActive || (this.broadcastListenerActive = !0, chrome.runtime.onMessage.addListener((e) => {
269
276
  const t = e;
270
- return t?.type === h.EXT2EXT_CLIENT_BROADCAST && t.event === "authStateChanged" && this.handleAuthStateChangedBroadcast(), !1;
277
+ return t?.type === c.EXT2EXT_CLIENT_BROADCAST && t.event === "authStateChanged" && this.handleAuthStateChangedBroadcast(), !1;
271
278
  }), this.logger.debug("Broadcast listener setup complete"));
272
279
  }
273
280
  /**
@@ -308,52 +315,52 @@ class ue {
308
315
  async init(e = {}) {
309
316
  if (!e.testConnection && !e.selectedConnection) {
310
317
  this.logger.info("No testConnection or selectedConnection, returning not-initialized state");
311
- const o = q();
312
- return this.setState(o), o;
318
+ const i = H();
319
+ return this.setState(i), i;
313
320
  }
314
321
  if (this.extensionId && !e.testConnection)
315
322
  return this.logger.debug("Already initialized with extensionId, skipping discovery"), this.state;
316
- const t = e.timeoutMs ?? this.config.initParams?.extension?.timeoutMs ?? J, r = e.savedState?.extensionId;
323
+ const t = e.timeoutMs ?? this.config.initParams?.extension?.timeoutMs ?? re, r = e.savedState?.extensionId;
317
324
  try {
318
325
  if (!this.extensionId) {
319
326
  if (r)
320
327
  this.logger.info("Restoring with known extensionId:", r), await this.sendExtMessageWithTimeout(
321
- p.SET_EXTENSION_ID,
328
+ m.SET_EXTENSION_ID,
322
329
  { extensionId: r },
323
330
  t
324
331
  ), this.extensionId = r;
325
332
  else {
326
333
  this.logger.info("Discovering bodhi-browser extension...");
327
- const n = {
334
+ const o = {
328
335
  attempts: this.config.initParams?.extension?.attempts,
329
336
  attemptWaitMs: this.config.initParams?.extension?.attemptWaitMs,
330
337
  attemptTimeout: this.config.initParams?.extension?.attemptTimeout
331
- }, i = await this.sendExtMessageWithTimeout(
332
- p.DISCOVER_EXTENSION,
333
- n,
338
+ }, n = await this.sendExtMessageWithTimeout(
339
+ m.DISCOVER_EXTENSION,
340
+ o,
334
341
  t
335
342
  );
336
- this.extensionId = i.extensionId, this.logger.info("Extension discovered:", this.extensionId);
343
+ this.extensionId = n.extensionId, this.logger.info("Extension discovered:", this.extensionId);
337
344
  }
338
345
  this.setupBroadcastListener();
339
346
  }
340
- const o = {
347
+ const i = {
341
348
  type: "extension",
342
349
  extension: "ready",
343
350
  extensionId: this.extensionId,
344
- server: f
351
+ server: w
345
352
  };
346
- let s = f;
353
+ let s = w;
347
354
  if (e.testConnection)
348
355
  try {
349
356
  s = await this.getServerState(), this.logger.info("Server connectivity tested, state:", s.status);
350
- } catch (n) {
351
- this.logger.error("Failed to get server state:", n), s = B;
357
+ } catch (o) {
358
+ this.logger.error("Failed to get server state:", o), s = z;
352
359
  }
353
- return this.setState({ ...o, server: s }), this.state;
354
- } catch (o) {
355
- this.logger.error("Failed to initialize extension:", o), this.extensionId = null;
356
- const s = $();
360
+ return this.setState({ ...i, server: s }), this.state;
361
+ } catch (i) {
362
+ this.logger.error("Failed to initialize extension:", i), this.extensionId = null;
363
+ const s = Q();
357
364
  return this.setState(s), this.state;
358
365
  }
359
366
  }
@@ -361,10 +368,10 @@ class ue {
361
368
  * Helper method to send ext message with timeout support
362
369
  */
363
370
  async sendExtMessageWithTimeout(e, t, r = 1e4) {
364
- const o = new Promise(
365
- (s, n) => setTimeout(() => n(new Error("Timeout")), r)
371
+ const i = new Promise(
372
+ (s, o) => setTimeout(() => o(new Error("Timeout")), r)
366
373
  );
367
- return Promise.race([this.sendExtRequest(e, t), o]);
374
+ return Promise.race([this.sendExtRequest(e, t), i]);
368
375
  }
369
376
  /**
370
377
  * Send an EXT2EXT_CLIENT_REQUEST message and await EXT2EXT_CLIENT_RESPONSE
@@ -372,29 +379,29 @@ class ue {
372
379
  */
373
380
  async sendExtRequest(e, t) {
374
381
  try {
375
- const r = this.generateRequestId(), o = await chrome.runtime.sendMessage({
376
- type: h.EXT2EXT_CLIENT_REQUEST,
382
+ const r = this.generateRequestId(), i = await chrome.runtime.sendMessage({
383
+ type: c.EXT2EXT_CLIENT_REQUEST,
377
384
  requestId: r,
378
385
  request: {
379
386
  action: e,
380
387
  params: t
381
388
  }
382
389
  });
383
- if (!o)
384
- throw l("No response from background script", "extension_error");
385
- if (o.type !== h.EXT2EXT_CLIENT_RESPONSE)
386
- throw l(
390
+ if (!i)
391
+ throw d("No response from background script", "extension_error");
392
+ if (i.type !== c.EXT2EXT_CLIENT_RESPONSE)
393
+ throw d(
387
394
  "Invalid response type from background script",
388
395
  "extension_error"
389
396
  );
390
- const s = o.response;
391
- if (C(s)) {
392
- const n = s.error.type || "extension_error";
393
- throw l(s.error.message, n);
397
+ const s = i.response;
398
+ if (N(s)) {
399
+ const o = s.error.type || "extension_error";
400
+ throw d(s.error.message, o);
394
401
  }
395
402
  return s;
396
403
  } catch (r) {
397
- throw ce(r) ? r : l(
404
+ throw Te(r) ? r : d(
398
405
  r instanceof Error ? r.message : "Unknown error occurred",
399
406
  "extension_error"
400
407
  );
@@ -404,16 +411,16 @@ class ue {
404
411
  * Send an API_REQUEST message and await API_RESPONSE (internal)
405
412
  * Returns ext2ext-specific ExtClientApiResponseMessage
406
413
  */
407
- async sendRawApiMessage(e, t, r, o, s) {
408
- const n = this.generateRequestId();
414
+ async sendRawApiMessage(e, t, r, i, s) {
415
+ const o = this.generateRequestId();
409
416
  return await chrome.runtime.sendMessage({
410
- type: h.EXT2EXT_CLIENT_API_REQUEST,
411
- requestId: n,
417
+ type: c.EXT2EXT_CLIENT_API_REQUEST,
418
+ requestId: o,
412
419
  request: {
413
420
  method: e,
414
421
  endpoint: t,
415
422
  body: r,
416
- headers: o,
423
+ headers: i,
417
424
  authenticated: s
418
425
  }
419
426
  });
@@ -421,55 +428,71 @@ class ue {
421
428
  /**
422
429
  * Send an API message and convert to protocol-agnostic ApiResponseResult
423
430
  */
424
- async sendApiRequest(e, t, r, o, s) {
425
- const n = await this.sendRawApiMessage(
426
- e,
427
- t,
428
- r,
429
- o,
430
- s
431
- );
432
- if (ee(n)) {
433
- const i = n.error.type || "extension_error";
431
+ async sendApiRequest(e, t, r, i, s) {
432
+ try {
433
+ const o = new Promise(
434
+ (E, h) => setTimeout(
435
+ () => h(
436
+ new Error(
437
+ `[bodhi-js-sdk/ext] network timeout: api request not completed within configured/default timeout of ${this.apiTimeoutMs}ms`
438
+ )
439
+ ),
440
+ this.apiTimeoutMs
441
+ )
442
+ ), n = await Promise.race([
443
+ this.sendRawApiMessage(e, t, r, i, s),
444
+ o
445
+ ]);
446
+ if (ae(n)) {
447
+ const E = n.error.type || "extension_error";
448
+ return {
449
+ error: {
450
+ message: n.error.message,
451
+ type: E
452
+ }
453
+ };
454
+ }
455
+ return n.response;
456
+ } catch (o) {
434
457
  return {
435
458
  error: {
436
- message: n.error.message,
437
- type: i
459
+ message: o instanceof Error ? o.message : String(o),
460
+ type: "network_error"
438
461
  }
439
462
  };
440
463
  }
441
- return n.response;
442
464
  }
443
465
  /**
444
466
  * Login user via OAuth
467
+ * @param options - Optional login parameters including toolsetScopeIds
445
468
  * @throws ExtError if login fails
446
469
  * @returns AuthState with login state and user info
447
470
  */
448
- async login() {
449
- return new Promise((e, t) => {
450
- const r = async (o) => {
451
- if (o && typeof o == "object" && "type" in o && o.type === "EXT2EXT_CLIENT_BROADCAST" && "event" in o && o.event === "authStateChanged") {
452
- chrome.runtime.onMessage.removeListener(r);
471
+ async login(e) {
472
+ return new Promise((t, r) => {
473
+ const i = async (s) => {
474
+ if (s && typeof s == "object" && "type" in s && s.type === "EXT2EXT_CLIENT_BROADCAST" && "event" in s && s.event === "authStateChanged") {
475
+ chrome.runtime.onMessage.removeListener(i);
453
476
  try {
454
- const s = await this.getAuthState();
455
- if (Q(s)) {
456
- t(
457
- l(`Login failed: ${s.error?.message}`, "auth-error")
477
+ const o = await this.getAuthState();
478
+ if (Z(o)) {
479
+ r(
480
+ d(`Login failed: ${o.error?.message}`, "auth-error")
458
481
  );
459
482
  return;
460
483
  }
461
- if (s.status !== "authenticated") {
462
- t(l("Login failed: User is not logged in", "auth-error"));
484
+ if (o.status !== "authenticated") {
485
+ r(d("Login failed: User is not logged in", "auth-error"));
463
486
  return;
464
487
  }
465
- this.setAuthState(s), e(s);
466
- } catch (s) {
467
- t(s);
488
+ this.setAuthState(o), t(o);
489
+ } catch (o) {
490
+ r(o);
468
491
  }
469
492
  }
470
493
  };
471
- chrome.runtime.onMessage.addListener(r), this.sendExtRequest(p.LOGIN).catch((o) => {
472
- chrome.runtime.onMessage.removeListener(r), t(o);
494
+ chrome.runtime.onMessage.addListener(i), this.sendExtRequest(m.LOGIN, e).catch((s) => {
495
+ chrome.runtime.onMessage.removeListener(i), r(s);
473
496
  });
474
497
  });
475
498
  }
@@ -479,7 +502,7 @@ class ue {
479
502
  * @returns AuthLoggedOut with logged out state
480
503
  */
481
504
  async logout() {
482
- await this.sendExtRequest(p.LOGOUT);
505
+ await this.sendExtRequest(m.LOGOUT);
483
506
  const e = {
484
507
  status: "unauthenticated",
485
508
  user: null,
@@ -495,8 +518,8 @@ class ue {
495
518
  */
496
519
  async getAuthState() {
497
520
  return this.isClientInitialized() ? (await this.sendExtRequest(
498
- p.GET_AUTH_STATE
499
- )).authState : K;
521
+ m.GET_AUTH_STATE
522
+ )).authState : G;
500
523
  }
501
524
  /**
502
525
  * Ping bodhi-browser-ext API via /ping endpoint
@@ -510,13 +533,13 @@ class ue {
510
533
  */
511
534
  async getServerState() {
512
535
  const e = await this.sendApiRequest("GET", "/bodhi/v1/info");
513
- if (w(e))
536
+ if (v(e))
514
537
  return {
515
538
  status: "not-reachable",
516
539
  version: null,
517
540
  error: e.error
518
541
  };
519
- if (!A(e))
542
+ if (!O(e))
520
543
  return {
521
544
  status: "not-reachable",
522
545
  version: null,
@@ -558,91 +581,91 @@ class ue {
558
581
  /**
559
582
  * Generic streaming method
560
583
  */
561
- async *stream(e, t, r, o, s = !0) {
562
- const n = this.generateRequestId();
584
+ async *stream(e, t, r, i, s = !0) {
585
+ const o = this.generateRequestId();
563
586
  this.logger.debug("Starting stream", {
564
587
  method: e,
565
588
  endpoint: t,
566
- requestId: n
589
+ requestId: o
567
590
  });
568
- const i = chrome.runtime.connect({ name: k }), a = new ReadableStream({
569
- start: (u) => {
570
- i.onMessage.addListener((E) => {
571
- if (E.requestId === n)
572
- switch (E.type) {
573
- case h.EXT2EXT_CLIENT_STREAM_DONE:
574
- this.logger.debug("Stream complete", { requestId: n }), u.close(), i.disconnect();
591
+ const n = chrome.runtime.connect({ name: $ }), h = new ReadableStream({
592
+ start: (l) => {
593
+ n.onMessage.addListener((u) => {
594
+ if (u.requestId === o)
595
+ switch (u.type) {
596
+ case c.EXT2EXT_CLIENT_STREAM_DONE:
597
+ this.logger.debug("Stream complete", { requestId: o }), l.close(), n.disconnect();
575
598
  break;
576
- case h.EXT2EXT_CLIENT_STREAM_ERROR:
599
+ case c.EXT2EXT_CLIENT_STREAM_ERROR:
577
600
  this.logger.error("Stream error", {
578
- requestId: n,
579
- error: JSON.stringify(E.error)
580
- }), u.error(
581
- l(
582
- E.error.message,
601
+ requestId: o,
602
+ error: JSON.stringify(u.error)
603
+ }), l.error(
604
+ d(
605
+ u.error.message,
583
606
  "extension_error"
584
607
  )
585
- ), i.disconnect();
608
+ ), n.disconnect();
586
609
  break;
587
- case h.EXT2EXT_CLIENT_STREAM_API_ERROR: {
588
- const g = E;
610
+ case c.EXT2EXT_CLIENT_STREAM_API_ERROR: {
611
+ const p = u;
589
612
  this.logger.error("Stream API error", {
590
- requestId: n,
591
- error: g.response.body?.error
592
- }), u.error(
593
- V(
594
- g.response.body?.error?.message || "API error",
595
- g.response.status,
596
- g.response.body
613
+ requestId: o,
614
+ error: p.response.body?.error
615
+ }), l.error(
616
+ W(
617
+ p.response.body?.error?.message || "API error",
618
+ p.response.status,
619
+ p.response.body
597
620
  )
598
- ), i.disconnect();
621
+ ), n.disconnect();
599
622
  break;
600
623
  }
601
- case h.EXT2EXT_CLIENT_STREAM_CHUNK: {
602
- const g = E;
603
- oe(g.response) && u.enqueue(g.response.body);
624
+ case c.EXT2EXT_CLIENT_STREAM_CHUNK: {
625
+ const p = u;
626
+ ue(p.response) && l.enqueue(p.response.body);
604
627
  break;
605
628
  }
606
629
  }
607
- }), i.onDisconnect.addListener(() => {
608
- this.logger.debug("Port disconnected", { requestId: n });
630
+ }), n.onDisconnect.addListener(() => {
631
+ this.logger.debug("Port disconnected", { requestId: o });
609
632
  try {
610
- u.error(
611
- l("Connection closed unexpectedly", "extension_error")
633
+ l.error(
634
+ d("Connection closed unexpectedly", "extension_error")
612
635
  );
613
636
  } catch {
614
637
  }
615
- }), i.postMessage({
616
- type: h.EXT2EXT_CLIENT_STREAM_REQUEST,
617
- requestId: n,
618
- request: { method: e, endpoint: t, body: r, headers: o, authenticated: s }
638
+ }), n.postMessage({
639
+ type: c.EXT2EXT_CLIENT_STREAM_REQUEST,
640
+ requestId: o,
641
+ request: { method: e, endpoint: t, body: r, headers: i, authenticated: s }
619
642
  });
620
643
  }
621
644
  }).getReader();
622
645
  try {
623
646
  for (; ; ) {
624
- const { done: u, value: E } = await a.read();
625
- if (u) {
647
+ const { done: l, value: u } = await h.read();
648
+ if (l) {
626
649
  this.logger.debug("Stream iteration complete");
627
650
  break;
628
651
  }
629
- yield E;
652
+ yield u;
630
653
  }
631
654
  } finally {
632
- a.releaseLock();
655
+ h.releaseLock();
633
656
  }
634
657
  }
635
658
  // ============================================================================
636
659
  // OpenAI-Compatible Namespaced API
637
660
  // ============================================================================
638
661
  get chat() {
639
- return this._chat ??= new H(this);
662
+ return this._chat ??= new J(this);
640
663
  }
641
664
  get models() {
642
- return this._models ??= new z(this);
665
+ return this._models ??= new Y(this);
643
666
  }
644
667
  get embeddings() {
645
- return this._embeddings ??= new F(this);
668
+ return this._embeddings ??= new j(this);
646
669
  }
647
670
  /**
648
671
  * Serialize ext2ext client state for persistence
@@ -661,48 +684,54 @@ class ue {
661
684
  };
662
685
  }
663
686
  }
664
- class Te extends G {
687
+ class Re extends ee {
665
688
  constructor(e, t, r) {
666
- const o = t || {}, s = {
667
- basePath: o.basePath || "/",
668
- authServerUrl: o.authServerUrl || "https://id.getbodhi.app/realms/bodhi",
669
- userScope: o.userScope || "scope_user_user",
670
- logLevel: o.logLevel || "warn",
671
- initParams: o.initParams
689
+ const i = t || {}, s = {
690
+ basePath: i.basePath || "/",
691
+ authServerUrl: i.authServerUrl || "https://id.getbodhi.app/realms/bodhi",
692
+ userScope: i.userScope || "scope_user_user",
693
+ logLevel: i.logLevel || "warn",
694
+ apiTimeoutMs: i.apiTimeoutMs,
695
+ initParams: i.initParams
672
696
  };
673
697
  super(e, s, r);
674
698
  }
675
699
  createLogger(e) {
676
- return new N("ExtUIClient", e.logLevel);
700
+ return new P("ExtUIClient", e.logLevel);
677
701
  }
678
702
  createStoragePrefix(e) {
679
- return P(e.basePath, X.EXT);
703
+ return L(e.basePath, U.EXT);
680
704
  }
681
705
  createExtClient(e, t) {
682
- return new ue(
683
- { logLevel: e.logLevel, initParams: e.initParams },
706
+ return new me(
707
+ {
708
+ logLevel: e.logLevel,
709
+ apiTimeoutMs: e.apiTimeoutMs,
710
+ initParams: e.initParams
711
+ },
684
712
  t
685
713
  );
686
714
  }
687
715
  createDirectClient(e, t, r) {
688
- return new te(
716
+ return new ce(
689
717
  {
690
718
  authClientId: e,
691
719
  authServerUrl: t.authServerUrl,
692
720
  userScope: t.userScope,
693
721
  logLevel: t.logLevel,
694
- basePath: t.basePath
722
+ basePath: t.basePath,
723
+ apiTimeoutMs: t.apiTimeoutMs
695
724
  },
696
725
  r
697
726
  );
698
727
  }
699
728
  }
700
- const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckljjghmjbf"], x = "production", S = class S {
729
+ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Ie = ["bjdjhiombmfbcoeojijpfckljjghmjbf"], A = "production", y = class y {
701
730
  // ============================================================================
702
731
  // Constructor
703
732
  // ============================================================================
704
733
  constructor(e, t) {
705
- this.isAuthenticating = !1, this.state = "setup", this.listenersInitialized = !1, this.refreshPromise = null, this.activeStreamPorts = /* @__PURE__ */ new Map(), this.authClientId = e, this.authServerUrl = t?.authServerUrl || "https://id.getbodhi.app/realms/bodhi", this.userScope = t?.userScope || "scope_user_user", this.extensionId = t?.extensionId, this.logger = new N("BodhiExtClient", t?.logLevel || "warn"), this.attempts = t?.attempts ?? Y, this.attemptWaitMs = t?.attemptWaitMs ?? Z, this.attemptTimeout = t?.attemptTimeout ?? j, this.authEndpoints = {
734
+ this.isAuthenticating = !1, this.state = "setup", this.listenersInitialized = !1, this.refreshPromise = null, this.activeStreamPorts = /* @__PURE__ */ new Map(), this.authClientId = e, this.authServerUrl = t?.authServerUrl || "https://id.getbodhi.app/realms/bodhi", this.userScope = t?.userScope || "scope_user_user", this.extensionId = t?.extensionId, this.logger = new P("BodhiExtClient", t?.logLevel || "warn"), this.attempts = t?.attempts ?? se, this.attemptWaitMs = t?.attemptWaitMs ?? oe, this.attemptTimeout = t?.attemptTimeout ?? ie, this.authEndpoints = {
706
735
  authorize: `${this.authServerUrl}/protocol/openid-connect/auth`,
707
736
  token: `${this.authServerUrl}/protocol/openid-connect/token`,
708
737
  userinfo: `${this.authServerUrl}/protocol/openid-connect/userinfo`,
@@ -720,11 +749,11 @@ const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
720
749
  }
721
750
  static generateCodeVerifier() {
722
751
  const e = new Uint8Array(32);
723
- return crypto.getRandomValues(e), S.base64UrlEncode(e.buffer);
752
+ return crypto.getRandomValues(e), y.base64UrlEncode(e.buffer);
724
753
  }
725
754
  static async generateCodeChallenge(e) {
726
- const r = new TextEncoder().encode(e), o = await crypto.subtle.digest("SHA-256", r);
727
- return S.base64UrlEncode(o);
755
+ const r = new TextEncoder().encode(e), i = await crypto.subtle.digest("SHA-256", r);
756
+ return y.base64UrlEncode(i);
728
757
  }
729
758
  // ============================================================================
730
759
  // State Management
@@ -743,7 +772,7 @@ const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
743
772
  * Get extension IDs for current environment
744
773
  */
745
774
  getExtensionIdsForEnvironment() {
746
- const t = x !== "production" ? de : le;
775
+ const t = A !== "production" ? Se : Ie;
747
776
  return this.logger.info("[Ext2Ext/Registry] Environment: production"), this.logger.debug("[Ext2Ext/Registry] Using extension IDs:", t), t;
748
777
  }
749
778
  /**
@@ -753,34 +782,34 @@ const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
753
782
  return this.logger.debug(
754
783
  `[Ext2Ext/Discovery] Pinging extension: ${e} with timeout ${this.attemptTimeout}ms`
755
784
  ), new Promise((t, r) => {
756
- const o = setTimeout(() => {
785
+ const i = setTimeout(() => {
757
786
  this.logger.debug(`[Ext2Ext/Discovery] Timeout waiting for extension ${e}`), r(new Error("Timeout"));
758
787
  }, this.attemptTimeout);
759
788
  try {
760
789
  const s = {
761
- type: m.EXT_REQUEST,
790
+ type: S.EXT_REQUEST,
762
791
  requestId: crypto.randomUUID(),
763
792
  request: {
764
793
  action: "get_extension_id"
765
794
  }
766
795
  };
767
- this.logger.debug(`[Ext2Ext/Discovery] Sending message to ${e}:`, s), chrome.runtime.sendMessage(e, s, (n) => {
768
- if (clearTimeout(o), chrome.runtime.lastError) {
796
+ this.logger.debug(`[Ext2Ext/Discovery] Sending message to ${e}:`, s), chrome.runtime.sendMessage(e, s, (o) => {
797
+ if (clearTimeout(i), chrome.runtime.lastError) {
769
798
  this.logger.error(
770
799
  `[Ext2Ext/Discovery] Error from extension ${e}:`,
771
800
  chrome.runtime.lastError.message
772
801
  ), r(new Error(chrome.runtime.lastError.message));
773
802
  return;
774
803
  }
775
- this.logger.debug(`[Ext2Ext/Discovery] Response from ${e}:`, n);
776
- const i = n;
777
- i && i.type === m.EXT_RESPONSE ? (this.logger.debug(`[Ext2Ext/Discovery] ✓ Extension ${e} responded`), t(!0)) : (this.logger.error(
804
+ this.logger.debug(`[Ext2Ext/Discovery] Response from ${e}:`, o);
805
+ const n = o;
806
+ n && n.type === S.EXT_RESPONSE ? (this.logger.debug(`[Ext2Ext/Discovery] ✓ Extension ${e} responded`), t(!0)) : (this.logger.error(
778
807
  `[Ext2Ext/Discovery] Invalid response from ${e}:`,
779
- n
808
+ o
780
809
  ), r(new Error("Invalid response")));
781
810
  });
782
811
  } catch (s) {
783
- this.logger.error(`[Ext2Ext/Discovery] Exception pinging ${e}:`, s), clearTimeout(o), r(s);
812
+ this.logger.error(`[Ext2Ext/Discovery] Exception pinging ${e}:`, s), clearTimeout(i), r(s);
784
813
  }
785
814
  });
786
815
  }
@@ -795,39 +824,39 @@ const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
795
824
  * @param params Resolved discovery params
796
825
  */
797
826
  async discoverBodhiExtension(e) {
798
- const { attempts: t, attemptWaitMs: r, attemptTimeout: o } = e;
827
+ const { attempts: t, attemptWaitMs: r, attemptTimeout: i } = e;
799
828
  this.logger.info(
800
- `[Ext2Ext/Discovery] Starting discovery: ${t} attempts per ID, ${o}ms timeout, ${r}ms between attempts`
829
+ `[Ext2Ext/Discovery] Starting discovery: ${t} attempts per ID, ${i}ms timeout, ${r}ms between attempts`
801
830
  );
802
831
  const s = this.getExtensionIdsForEnvironment();
803
832
  this.logger.debug(
804
833
  `[Ext2Ext/Discovery] Will try ${s.length} extension(s):`,
805
834
  s
806
835
  );
807
- for (const d of s) {
808
- for (let a = 1; a <= t; a++) {
836
+ for (const E of s) {
837
+ for (let h = 1; h <= t; h++) {
809
838
  this.logger.debug(
810
- `[Ext2Ext/Discovery] Trying ${d} - attempt ${a}/${t}`
839
+ `[Ext2Ext/Discovery] Trying ${E} - attempt ${h}/${t}`
811
840
  );
812
841
  try {
813
- return await this.pingExtension(d), this.logger.info(`[Ext2Ext/Discovery] ✓ Found: ${d} on attempt ${a}`), {
842
+ return await this.pingExtension(E), this.logger.info(`[Ext2Ext/Discovery] ✓ Found: ${E} on attempt ${h}`), {
814
843
  success: !0,
815
- extensionId: d
844
+ extensionId: E
816
845
  };
817
- } catch (u) {
846
+ } catch (l) {
818
847
  this.logger.debug(
819
- `[Ext2Ext/Discovery] Attempt ${a} failed for ${d}: ${u instanceof Error ? u.message : "Unknown error"}`
820
- ), a < t && await this.sleep(r);
848
+ `[Ext2Ext/Discovery] Attempt ${h} failed for ${E}: ${l instanceof Error ? l.message : "Unknown error"}`
849
+ ), h < t && await this.sleep(r);
821
850
  }
822
851
  }
823
852
  this.logger.warn(
824
- `[Ext2Ext/Discovery] ✗ Not found: ${d} after ${t} attempts`
853
+ `[Ext2Ext/Discovery] ✗ Not found: ${E} after ${t} attempts`
825
854
  );
826
855
  }
827
- const n = s.join(", "), i = `Extension not found. Tried ${s.length} IDs with ${t} attempts each: ${n}`;
828
- return this.logger.error(`[Ext2Ext/Discovery] ${i}`), {
856
+ const o = s.join(", "), n = `Extension not found. Tried ${s.length} IDs with ${t} attempts each: ${o}`;
857
+ return this.logger.error(`[Ext2Ext/Discovery] ${n}`), {
829
858
  success: !1,
830
- error: i
859
+ error: n
831
860
  };
832
861
  }
833
862
  // ============================================================================
@@ -841,8 +870,8 @@ const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
841
870
  this.logger.debug("[BodhiExtClient] Listeners already initialized, skipping");
842
871
  return;
843
872
  }
844
- this.listenersInitialized = !0, chrome.runtime.onMessage.addListener((e, t, r) => e.type !== h.EXT2EXT_CLIENT_REQUEST && e.type !== h.EXT2EXT_CLIENT_API_REQUEST ? !1 : this.state !== "ready" && !(e.type === h.EXT2EXT_CLIENT_REQUEST && e.request.action === p.DISCOVER_EXTENSION) ? (e.type === h.EXT2EXT_CLIENT_REQUEST ? r({
845
- type: h.EXT2EXT_CLIENT_RESPONSE,
873
+ this.listenersInitialized = !0, chrome.runtime.onMessage.addListener((e, t, r) => e.type !== c.EXT2EXT_CLIENT_REQUEST && e.type !== c.EXT2EXT_CLIENT_API_REQUEST ? !1 : this.state !== "ready" && !(e.type === c.EXT2EXT_CLIENT_REQUEST && e.request.action === m.DISCOVER_EXTENSION) ? (e.type === c.EXT2EXT_CLIENT_REQUEST ? r({
874
+ type: c.EXT2EXT_CLIENT_RESPONSE,
846
875
  requestId: e.requestId,
847
876
  response: {
848
877
  error: {
@@ -851,24 +880,24 @@ const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
851
880
  }
852
881
  }
853
882
  }) : r({
854
- type: h.EXT2EXT_CLIENT_API_RESPONSE,
883
+ type: c.EXT2EXT_CLIENT_API_RESPONSE,
855
884
  requestId: e.requestId,
856
885
  error: {
857
886
  message: `Client not initialized. Extension discovery not complete, cannot handle type:${e.type}, message:${JSON.stringify(e)}`,
858
887
  type: "NOT_INITIALIZED"
859
888
  }
860
889
  }), !0) : (this.logger.debug(`[BodhiExtClient] Processing message.type=${e.type}`), (async () => {
861
- const o = await this.handleAction(e);
862
- r(o);
890
+ const i = await this.handleAction(e);
891
+ r(i);
863
892
  })(), !0)), chrome.runtime.onConnect.addListener((e) => {
864
- if (e.name !== k) {
893
+ if (e.name !== $) {
865
894
  this.logger.debug("[BodhiExtClient] Ignoring port with name:", e.name);
866
895
  return;
867
896
  }
868
897
  this.logger.info("[BodhiExtClient] Streaming port connected"), e.onMessage.addListener(async (t) => {
869
- if (t.type !== h.EXT2EXT_CLIENT_STREAM_REQUEST) {
898
+ if (t.type !== c.EXT2EXT_CLIENT_STREAM_REQUEST) {
870
899
  this.logger.warn("[BodhiExtClient] Unknown stream message type:", t.type), e.postMessage({
871
- type: h.EXT2EXT_CLIENT_STREAM_ERROR,
900
+ type: c.EXT2EXT_CLIENT_STREAM_ERROR,
872
901
  requestId: t.requestId,
873
902
  error: {
874
903
  message: "Unknown stream message type",
@@ -911,7 +940,7 @@ const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
911
940
  */
912
941
  broadcastAuthStateChange() {
913
942
  chrome.runtime.sendMessage({
914
- type: h.EXT2EXT_CLIENT_BROADCAST,
943
+ type: c.EXT2EXT_CLIENT_BROADCAST,
915
944
  event: "authStateChanged"
916
945
  }).catch((e) => {
917
946
  this.logger.debug("[BodhiExtClient] No listeners for broadcast:", e.message);
@@ -941,7 +970,7 @@ const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
941
970
  const s = await this._getAccessTokenRaw();
942
971
  if (!s)
943
972
  return {
944
- type: h.EXT2EXT_CLIENT_API_RESPONSE,
973
+ type: c.EXT2EXT_CLIENT_API_RESPONSE,
945
974
  requestId: t,
946
975
  error: {
947
976
  message: "Not authenticated. Please log in first.",
@@ -953,20 +982,20 @@ const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
953
982
  Authorization: `Bearer ${s}`
954
983
  }, this.logger.debug("[BodhiExtClient] Injected auth token for authenticated request");
955
984
  }
956
- const o = await this.sendApiRequest(
985
+ const i = await this.sendApiRequest(
957
986
  e.request.method,
958
987
  e.request.endpoint,
959
988
  e.request.body,
960
989
  r
961
990
  );
962
991
  return {
963
- type: h.EXT2EXT_CLIENT_API_RESPONSE,
992
+ type: c.EXT2EXT_CLIENT_API_RESPONSE,
964
993
  requestId: t,
965
- response: o
994
+ response: i
966
995
  };
967
996
  } catch (r) {
968
997
  return this.logger.error("[BodhiExtClient] API request failed:", r), {
969
- type: h.EXT2EXT_CLIENT_API_RESPONSE,
998
+ type: c.EXT2EXT_CLIENT_API_RESPONSE,
970
999
  requestId: t,
971
1000
  error: {
972
1001
  message: r instanceof Error ? r.message : "Unknown error",
@@ -982,74 +1011,76 @@ const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
982
1011
  * @returns Action response message (success or error)
983
1012
  */
984
1013
  async handleExtClientRequest(e) {
985
- const { requestId: t, request: r } = e, { action: o, params: s } = r;
986
- this.logger.debug(`[BodhiExtClient] Handling action: ${o}`);
1014
+ const { requestId: t, request: r } = e, { action: i, params: s } = r;
1015
+ this.logger.debug(`[BodhiExtClient] Handling action: ${i}`);
987
1016
  try {
988
- let n = {};
989
- switch (o) {
990
- case p.DISCOVER_EXTENSION: {
991
- const i = s;
992
- await this.init(i), this.logger.info("[BodhiExtClient] Discovery successful:", {
1017
+ let o = {};
1018
+ switch (i) {
1019
+ case m.DISCOVER_EXTENSION: {
1020
+ const n = s;
1021
+ await this.init(n), this.logger.info("[BodhiExtClient] Discovery successful:", {
993
1022
  extensionId: this.extensionId,
994
- environment: x
995
- }), n = {
1023
+ environment: A
1024
+ }), o = {
996
1025
  extensionId: this.extensionId,
997
- environment: x
1026
+ environment: A
998
1027
  };
999
1028
  break;
1000
1029
  }
1001
- case p.SET_EXTENSION_ID: {
1002
- const { extensionId: i } = s;
1003
- this.extensionId = i, this.state = "ready", this.logger.info("[BodhiExtClient] Extension ID set:", { extensionId: i }), n = { success: !0 };
1030
+ case m.SET_EXTENSION_ID: {
1031
+ const { extensionId: n } = s;
1032
+ this.extensionId = n, this.state = "ready", this.logger.info("[BodhiExtClient] Extension ID set:", { extensionId: n }), o = { success: !0 };
1004
1033
  break;
1005
1034
  }
1006
- case p.GET_EXTENSION_ID: {
1007
- const i = await this.sendExtRequestRaw(he.GET_EXTENSION_ID, s);
1008
- return C(i.response) ? {
1009
- type: h.EXT2EXT_CLIENT_RESPONSE,
1035
+ case m.GET_EXTENSION_ID: {
1036
+ const n = await this.sendExtRequestRaw(_e.GET_EXTENSION_ID, s);
1037
+ return N(n.response) ? {
1038
+ type: c.EXT2EXT_CLIENT_RESPONSE,
1010
1039
  requestId: t,
1011
1040
  response: {
1012
1041
  error: {
1013
- message: i.response.error.message || `Extension request failed to get extension ID: ${JSON.stringify(i.response)}`,
1014
- type: i.response.error.type
1042
+ message: n.response.error.message || `Extension request failed to get extension ID: ${JSON.stringify(n.response)}`,
1043
+ type: n.response.error.type
1015
1044
  }
1016
1045
  }
1017
1046
  } : {
1018
- type: h.EXT2EXT_CLIENT_RESPONSE,
1047
+ type: c.EXT2EXT_CLIENT_RESPONSE,
1019
1048
  requestId: t,
1020
- response: i.response
1049
+ response: n.response
1021
1050
  };
1022
1051
  }
1023
- case p.LOGIN:
1024
- await this.login(), this.broadcastAuthStateChange();
1052
+ case m.LOGIN: {
1053
+ const n = s;
1054
+ await this.login(n), this.broadcastAuthStateChange();
1025
1055
  break;
1026
- case p.LOGOUT:
1056
+ }
1057
+ case m.LOGOUT:
1027
1058
  await this.logout(), this.broadcastAuthStateChange();
1028
1059
  break;
1029
- case p.GET_AUTH_STATE:
1030
- n = { authState: await this.getAuthState() };
1060
+ case m.GET_AUTH_STATE:
1061
+ o = { authState: await this.getAuthState() };
1031
1062
  break;
1032
1063
  default:
1033
1064
  return {
1034
- type: h.EXT2EXT_CLIENT_RESPONSE,
1065
+ type: c.EXT2EXT_CLIENT_RESPONSE,
1035
1066
  requestId: t,
1036
1067
  response: {
1037
- error: { message: `Unknown action: ${o}`, type: "UNKNOWN_ACTION" }
1068
+ error: { message: `Unknown action: ${i}`, type: "UNKNOWN_ACTION" }
1038
1069
  }
1039
1070
  };
1040
1071
  }
1041
1072
  return {
1042
- type: h.EXT2EXT_CLIENT_RESPONSE,
1073
+ type: c.EXT2EXT_CLIENT_RESPONSE,
1043
1074
  requestId: t,
1044
- response: n
1075
+ response: o
1045
1076
  };
1046
- } catch (n) {
1047
- return this.logger.error("[BodhiExtClient] Unexpected error:", n), {
1048
- type: h.EXT2EXT_CLIENT_RESPONSE,
1077
+ } catch (o) {
1078
+ return this.logger.error("[BodhiExtClient] Unexpected error:", o), {
1079
+ type: c.EXT2EXT_CLIENT_RESPONSE,
1049
1080
  requestId: t,
1050
1081
  response: {
1051
1082
  error: {
1052
- message: n instanceof Error ? n.message : `Unexpected error: ${JSON.stringify(n)}`
1083
+ message: o instanceof Error ? o.message : `Unexpected error: ${JSON.stringify(o)}`
1053
1084
  }
1054
1085
  }
1055
1086
  };
@@ -1058,14 +1089,14 @@ const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
1058
1089
  // Implementation signature (must be compatible with all overloads)
1059
1090
  async handleAction(e) {
1060
1091
  switch (e.type) {
1061
- case h.EXT2EXT_CLIENT_API_REQUEST:
1092
+ case c.EXT2EXT_CLIENT_API_REQUEST:
1062
1093
  return this.handleApiRequest(e);
1063
- case h.EXT2EXT_CLIENT_REQUEST:
1094
+ case c.EXT2EXT_CLIENT_REQUEST:
1064
1095
  return this.handleExtClientRequest(e);
1065
1096
  default: {
1066
1097
  const { requestId: t } = e;
1067
1098
  return this.logger.error("[BodhiExtClient] Unknown message type:", e.type), {
1068
- type: h.EXT2EXT_CLIENT_RESPONSE,
1099
+ type: c.EXT2EXT_CLIENT_RESPONSE,
1069
1100
  requestId: t,
1070
1101
  response: {
1071
1102
  error: {
@@ -1082,58 +1113,65 @@ const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
1082
1113
  // ============================================================================
1083
1114
  /**
1084
1115
  * Login user via OAuth2 + PKCE flow
1116
+ * @param options - Optional login options (toolsetScopeIds, version)
1085
1117
  * @throws Error if login fails
1086
1118
  */
1087
- async login() {
1119
+ async login(e) {
1088
1120
  if (!(this.isAuthenticating || (await this.getAuthState()).status === "authenticated")) {
1089
1121
  this.isAuthenticating = !0;
1090
1122
  try {
1091
1123
  if (!this.extensionId)
1092
1124
  throw new Error("Extension not discovered. Please detect Bodhi extension before login.");
1093
- const t = await this.requestAccess();
1094
- if (w(t))
1095
- throw l(t.error.message, t.error.type);
1096
- if (b(t)) {
1097
- const { message: u } = t.body.error;
1098
- throw l(u, "auth_error");
1125
+ const r = await this.requestAccess(e?.toolsetScopeIds, e?.version);
1126
+ if (v(r))
1127
+ throw d(r.error.message, r.error.type);
1128
+ if (M(r)) {
1129
+ const { message: T } = r.body.error;
1130
+ throw d(T, "auth_error");
1099
1131
  }
1100
- if (!A(t))
1101
- throw l(`Unexpected HTTP ${t.status}`, "auth_error");
1102
- const r = t.body.scope, o = `openid profile email roles ${this.userScope} ${r}`, s = S.generateCodeVerifier(), n = await S.generateCodeChallenge(s), i = S.generateCodeVerifier();
1132
+ if (!O(r))
1133
+ throw d(`Unexpected HTTP ${r.status}`, "auth_error");
1134
+ const i = r.body.scope, s = r.body.toolsets || [], o = D(e?.toolsetScopeIds, s);
1135
+ if (o.length > 0)
1136
+ throw d(
1137
+ `toolsetScopeIds not received back from request-access call: [${o.join(", ")}], check developer console on configuring the toolset scopes correctly`,
1138
+ "auth_error"
1139
+ );
1140
+ const n = q(e?.toolsetScopeIds, s), E = `openid profile email roles ${this.userScope} ${i} ${n}`.trim(), h = y.generateCodeVerifier(), l = await y.generateCodeChallenge(h), u = y.generateCodeVerifier();
1103
1141
  await chrome.storage.session.set({
1104
- codeVerifier: s,
1105
- state: i,
1142
+ codeVerifier: h,
1143
+ state: u,
1106
1144
  authInProgress: !0
1107
1145
  });
1108
- const d = chrome.identity.getRedirectURL("callback"), a = new URL(this.authEndpoints.authorize);
1109
- return a.searchParams.set("client_id", this.authClientId), a.searchParams.set("response_type", "code"), a.searchParams.set("redirect_uri", d), a.searchParams.set("scope", o), a.searchParams.set("code_challenge", n), a.searchParams.set("code_challenge_method", "S256"), a.searchParams.set("state", i), new Promise((u, E) => {
1146
+ const p = chrome.identity.getRedirectURL("callback"), g = new URL(this.authEndpoints.authorize);
1147
+ return g.searchParams.set("client_id", this.authClientId), g.searchParams.set("response_type", "code"), g.searchParams.set("redirect_uri", p), g.searchParams.set("scope", E), g.searchParams.set("code_challenge", l), g.searchParams.set("code_challenge_method", "S256"), g.searchParams.set("state", u), new Promise((T, _) => {
1110
1148
  chrome.identity.launchWebAuthFlow(
1111
1149
  {
1112
- url: a.toString(),
1150
+ url: g.toString(),
1113
1151
  interactive: !0
1114
1152
  },
1115
- async (g) => {
1153
+ async (R) => {
1116
1154
  if (await chrome.storage.session.set({ authInProgress: !1 }), chrome.runtime.lastError) {
1117
- await chrome.storage.session.remove(["codeVerifier", "state"]), E(chrome.runtime.lastError);
1155
+ await chrome.storage.session.remove(["codeVerifier", "state"]), _(chrome.runtime.lastError);
1118
1156
  return;
1119
1157
  }
1120
- if (!g) {
1121
- await chrome.storage.session.remove(["codeVerifier", "state"]), E(new Error("No redirect URL received"));
1158
+ if (!R) {
1159
+ await chrome.storage.session.remove(["codeVerifier", "state"]), _(new Error("No redirect URL received"));
1122
1160
  return;
1123
1161
  }
1124
1162
  try {
1125
- const _ = new URL(g), T = _.searchParams.get("code"), y = _.searchParams.get("state"), { state: I } = await chrome.storage.session.get("state");
1126
- if (y !== I) {
1127
- await chrome.storage.session.remove(["codeVerifier", "state"]), E(new Error("State mismatch - possible CSRF"));
1163
+ const I = new URL(R), f = I.searchParams.get("code"), x = I.searchParams.get("state"), { state: X } = await chrome.storage.session.get("state");
1164
+ if (x !== X) {
1165
+ await chrome.storage.session.remove(["codeVerifier", "state"]), _(new Error("State mismatch - possible CSRF"));
1128
1166
  return;
1129
1167
  }
1130
- if (!T) {
1131
- await chrome.storage.session.remove(["codeVerifier", "state"]), E(new Error("No authorization code received"));
1168
+ if (!f) {
1169
+ await chrome.storage.session.remove(["codeVerifier", "state"]), _(new Error("No authorization code received"));
1132
1170
  return;
1133
1171
  }
1134
- await this.exchangeCodeForTokens(T), await chrome.storage.session.remove(["codeVerifier", "state"]), u();
1135
- } catch (_) {
1136
- await chrome.storage.session.remove(["codeVerifier", "state"]), E(_);
1172
+ await this.exchangeCodeForTokens(f), await chrome.storage.session.remove(["codeVerifier", "state"]), T();
1173
+ } catch (I) {
1174
+ await chrome.storage.session.remove(["codeVerifier", "state"]), _(I);
1137
1175
  }
1138
1176
  }
1139
1177
  );
@@ -1150,7 +1188,7 @@ const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
1150
1188
  async exchangeCodeForTokens(e) {
1151
1189
  if ((await this.getAuthState()).status === "authenticated")
1152
1190
  return;
1153
- const { codeVerifier: r } = await chrome.storage.session.get("codeVerifier"), o = chrome.identity.getRedirectURL("callback"), s = await fetch(this.authEndpoints.token, {
1191
+ const { codeVerifier: r } = await chrome.storage.session.get("codeVerifier"), i = chrome.identity.getRedirectURL("callback"), s = await fetch(this.authEndpoints.token, {
1154
1192
  method: "POST",
1155
1193
  headers: {
1156
1194
  "Content-Type": "application/x-www-form-urlencoded"
@@ -1158,21 +1196,21 @@ const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
1158
1196
  body: new URLSearchParams({
1159
1197
  grant_type: "authorization_code",
1160
1198
  code: e,
1161
- redirect_uri: o,
1199
+ redirect_uri: i,
1162
1200
  client_id: this.authClientId,
1163
1201
  code_verifier: r
1164
1202
  })
1165
1203
  });
1166
1204
  if (!s.ok) {
1167
- const i = await s.text();
1168
- throw new Error(`Token exchange failed: ${s.status} ${i}`);
1205
+ const n = await s.text();
1206
+ throw new Error(`Token exchange failed: ${s.status} ${n}`);
1169
1207
  }
1170
- const n = await s.json();
1208
+ const o = await s.json();
1171
1209
  await this.storeTokens({
1172
- accessToken: n.access_token,
1173
- refreshToken: n.refresh_token,
1174
- idToken: n.id_token,
1175
- expiresIn: n.expires_in
1210
+ accessToken: o.access_token,
1211
+ refreshToken: o.refresh_token,
1212
+ idToken: o.id_token,
1213
+ expiresIn: o.expires_in
1176
1214
  });
1177
1215
  }
1178
1216
  /**
@@ -1236,7 +1274,7 @@ const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
1236
1274
  */
1237
1275
  async sendExtRequest(e, t) {
1238
1276
  const r = await this.sendExtRequestRaw(e, t);
1239
- if (C(r.response))
1277
+ if (N(r.response))
1240
1278
  throw this.logger.error("[BodhiExtClient] Extension error:", r.response.error), new Error(
1241
1279
  r.response.error.message || `Extension request failed: ${JSON.stringify(r.response)}`
1242
1280
  );
@@ -1250,44 +1288,44 @@ const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
1250
1288
  * @param headers Optional headers
1251
1289
  * @returns API response from LLM server via bodhi-browser-ext
1252
1290
  */
1253
- async sendApiRequest(e, t, r, o) {
1291
+ async sendApiRequest(e, t, r, i) {
1254
1292
  if (!this.extensionId)
1255
1293
  throw new Error(this.createErrorClientNotInitialized({ type: "api", method: e, endpoint: t }));
1256
1294
  this.logger.debug(
1257
1295
  `[BodhiExtClient] Sending API_REQUEST: method=${e}, endpoint=${t}`,
1258
1296
  r ? { body: r } : ""
1259
1297
  );
1260
- const s = crypto.randomUUID(), n = {
1261
- type: m.API_REQUEST,
1298
+ const s = crypto.randomUUID(), o = {
1299
+ type: S.API_REQUEST,
1262
1300
  requestId: s,
1263
1301
  request: {
1264
1302
  method: e,
1265
1303
  endpoint: t,
1266
1304
  body: r,
1267
- headers: o
1305
+ headers: i
1268
1306
  }
1269
1307
  };
1270
- return this.logger.debug(`[BodhiExtClient] Request ID: ${s}, Extension: ${this.extensionId}`), new Promise((i, d) => {
1308
+ return this.logger.debug(`[BodhiExtClient] Request ID: ${s}, Extension: ${this.extensionId}`), new Promise((n, E) => {
1271
1309
  try {
1272
- chrome.runtime.sendMessage(this.extensionId, n, (a) => {
1310
+ chrome.runtime.sendMessage(this.extensionId, o, (h) => {
1273
1311
  if (chrome.runtime.lastError) {
1274
1312
  this.logger.error(
1275
1313
  `[BodhiExtClient] Chrome runtime error for request ${s}:`,
1276
1314
  chrome.runtime.lastError
1277
- ), d(new Error(chrome.runtime.lastError.message));
1315
+ ), E(new Error(chrome.runtime.lastError.message));
1278
1316
  return;
1279
1317
  }
1280
- if (this.logger.debug(`[BodhiExtClient] Response for request ${s}:`, a), !a) {
1281
- this.logger.error(`[BodhiExtClient] No response received for request ${s}`), d(new Error("No response from extension"));
1318
+ if (this.logger.debug(`[BodhiExtClient] Response for request ${s}:`, h), !h) {
1319
+ this.logger.error(`[BodhiExtClient] No response received for request ${s}`), E(new Error("No response from extension"));
1282
1320
  return;
1283
1321
  }
1284
- a.type === m.API_RESPONSE && a.requestId === s ? "error" in a ? (this.logger.error(`[BodhiExtClient] API error for ${s}:`, a.error), d(new Error(a.error.message))) : (this.logger.debug(`[BodhiExtClient] ✓ Valid API_RESPONSE for ${s}`), i(a.response)) : (this.logger.error(
1322
+ h.type === S.API_RESPONSE && h.requestId === s ? "error" in h ? (this.logger.error(`[BodhiExtClient] API error for ${s}:`, h.error), E(new Error(h.error.message))) : (this.logger.debug(`[BodhiExtClient] ✓ Valid API_RESPONSE for ${s}`), n(h.response)) : (this.logger.error(
1285
1323
  `[BodhiExtClient] Invalid response format for ${s}:`,
1286
- a
1287
- ), d(new Error("Invalid response format")));
1324
+ h
1325
+ ), E(new Error("Invalid response format")));
1288
1326
  });
1289
- } catch (a) {
1290
- this.logger.error(`[BodhiExtClient] Exception sending message for ${s}:`, a), d(a);
1327
+ } catch (h) {
1328
+ this.logger.error(`[BodhiExtClient] Exception sending message for ${s}:`, h), E(h);
1291
1329
  }
1292
1330
  });
1293
1331
  }
@@ -1304,35 +1342,35 @@ const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
1304
1342
  `[BodhiExtClient] Sending EXT_REQUEST (raw): action=${e}`,
1305
1343
  t ? { params: t } : ""
1306
1344
  );
1307
- const r = crypto.randomUUID(), o = {
1308
- type: m.EXT_REQUEST,
1345
+ const r = crypto.randomUUID(), i = {
1346
+ type: S.EXT_REQUEST,
1309
1347
  requestId: r,
1310
1348
  request: {
1311
1349
  action: e,
1312
1350
  params: t
1313
1351
  }
1314
1352
  };
1315
- return this.logger.debug(`[BodhiExtClient] Request ID: ${r}, Extension: ${this.extensionId}`), new Promise((s, n) => {
1353
+ return this.logger.debug(`[BodhiExtClient] Request ID: ${r}, Extension: ${this.extensionId}`), new Promise((s, o) => {
1316
1354
  try {
1317
- chrome.runtime.sendMessage(this.extensionId, o, (i) => {
1355
+ chrome.runtime.sendMessage(this.extensionId, i, (n) => {
1318
1356
  if (chrome.runtime.lastError) {
1319
1357
  this.logger.error(
1320
1358
  `[BodhiExtClient] Chrome runtime error for request ${r}:`,
1321
1359
  chrome.runtime.lastError
1322
- ), n(new Error(chrome.runtime.lastError.message));
1360
+ ), o(new Error(chrome.runtime.lastError.message));
1323
1361
  return;
1324
1362
  }
1325
- if (this.logger.debug(`[BodhiExtClient] Response for request ${r}:`, i), !i) {
1326
- this.logger.error(`[BodhiExtClient] No response received for request ${r}`), n(new Error("No response from extension"));
1363
+ if (this.logger.debug(`[BodhiExtClient] Response for request ${r}:`, n), !n) {
1364
+ this.logger.error(`[BodhiExtClient] No response received for request ${r}`), o(new Error("No response from extension"));
1327
1365
  return;
1328
1366
  }
1329
- i.type === m.EXT_RESPONSE && i.requestId === r ? (this.logger.debug(`[BodhiExtClient] ✓ Valid EXT_RESPONSE for ${r}`), s(i)) : (this.logger.error(
1367
+ n.type === S.EXT_RESPONSE && n.requestId === r ? (this.logger.debug(`[BodhiExtClient] ✓ Valid EXT_RESPONSE for ${r}`), s(n)) : (this.logger.error(
1330
1368
  `[BodhiExtClient] Invalid response format for ${r}:`,
1331
- i
1332
- ), n(new Error("Invalid response format")));
1369
+ n
1370
+ ), o(new Error("Invalid response format")));
1333
1371
  });
1334
- } catch (i) {
1335
- this.logger.error(`[BodhiExtClient] Exception sending message for ${r}:`, i), n(i);
1372
+ } catch (n) {
1373
+ this.logger.error(`[BodhiExtClient] Exception sending message for ${r}:`, n), o(n);
1336
1374
  }
1337
1375
  });
1338
1376
  }
@@ -1343,14 +1381,14 @@ const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
1343
1381
  * @param message Stream request message from UI
1344
1382
  */
1345
1383
  async handleStreamRequest(e, t) {
1346
- const { requestId: r, request: o } = t, { method: s, endpoint: n, body: i, headers: d, authenticated: a } = o;
1384
+ const { requestId: r, request: i } = t, { method: s, endpoint: o, body: n, headers: E, authenticated: h } = i;
1347
1385
  this.logger.debug("[BodhiExtClient] Processing stream request:", {
1348
1386
  requestId: r,
1349
1387
  method: s,
1350
- endpoint: n,
1351
- authenticated: a
1388
+ endpoint: o,
1389
+ authenticated: h
1352
1390
  }), this.extensionId || e.postMessage({
1353
- type: h.EXT2EXT_CLIENT_STREAM_ERROR,
1391
+ type: c.EXT2EXT_CLIENT_STREAM_ERROR,
1354
1392
  requestId: r,
1355
1393
  error: {
1356
1394
  message: this.createErrorClientNotInitialized(t),
@@ -1358,12 +1396,12 @@ const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
1358
1396
  }
1359
1397
  });
1360
1398
  try {
1361
- let u = { ...d };
1362
- if (a !== !1) {
1399
+ let l = { ...E };
1400
+ if (h !== !1) {
1363
1401
  const T = await this._getAccessTokenRaw();
1364
1402
  if (!T) {
1365
1403
  e.postMessage({
1366
- type: h.EXT2EXT_CLIENT_STREAM_ERROR,
1404
+ type: c.EXT2EXT_CLIENT_STREAM_ERROR,
1367
1405
  requestId: r,
1368
1406
  error: {
1369
1407
  message: "Not authenticated. Please log in first.",
@@ -1372,60 +1410,60 @@ const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
1372
1410
  });
1373
1411
  return;
1374
1412
  }
1375
- u = {
1376
- ...u,
1413
+ l = {
1414
+ ...l,
1377
1415
  Authorization: `Bearer ${T}`
1378
1416
  }, this.logger.debug("[BodhiExtClient] Injected auth token for authenticated request");
1379
1417
  }
1380
- const E = chrome.runtime.connect(this.extensionId, {
1381
- name: Ee
1418
+ const u = chrome.runtime.connect(this.extensionId, {
1419
+ name: pe
1382
1420
  });
1383
- this.activeStreamPorts.set(r, E);
1384
- const g = setTimeout(() => {
1421
+ this.activeStreamPorts.set(r, u);
1422
+ const p = setTimeout(() => {
1385
1423
  this.activeStreamPorts.has(r) && (this.logger.error(`[BodhiExtClient] Stream timeout for ${r}`), e.postMessage({
1386
- type: h.EXT2EXT_CLIENT_STREAM_ERROR,
1424
+ type: c.EXT2EXT_CLIENT_STREAM_ERROR,
1387
1425
  requestId: r,
1388
1426
  error: {
1389
1427
  message: "Stream request timed out",
1390
1428
  type: "timeout_error"
1391
1429
  }
1392
1430
  }), this.cleanupStreamPort(r));
1393
- }, S.STREAM_TIMEOUT);
1394
- E.onMessage.addListener((T) => {
1395
- if (ne(T)) {
1396
- const y = T.response, I = y.body;
1397
- y.status >= 400 ? e.postMessage({
1398
- type: h.EXT2EXT_CLIENT_STREAM_API_ERROR,
1431
+ }, y.STREAM_TIMEOUT);
1432
+ u.onMessage.addListener((T) => {
1433
+ if (de(T)) {
1434
+ const _ = T.response, R = _.body;
1435
+ _.status >= 400 ? e.postMessage({
1436
+ type: c.EXT2EXT_CLIENT_STREAM_API_ERROR,
1399
1437
  requestId: r,
1400
- response: y
1401
- }) : I?.done ? (e.postMessage({
1402
- type: h.EXT2EXT_CLIENT_STREAM_DONE,
1438
+ response: _
1439
+ }) : R?.done ? (e.postMessage({
1440
+ type: c.EXT2EXT_CLIENT_STREAM_DONE,
1403
1441
  requestId: r
1404
- }), this.logger.info(`[BodhiExtClient] Stream complete for ${r}`), clearTimeout(g), this.cleanupStreamPort(r)) : e.postMessage({
1405
- type: h.EXT2EXT_CLIENT_STREAM_CHUNK,
1442
+ }), this.logger.info(`[BodhiExtClient] Stream complete for ${r}`), clearTimeout(p), this.cleanupStreamPort(r)) : e.postMessage({
1443
+ type: c.EXT2EXT_CLIENT_STREAM_CHUNK,
1406
1444
  requestId: r,
1407
- response: y
1445
+ response: _
1408
1446
  });
1409
- } else ie(T) ? (this.logger.error(
1447
+ } else le(T) ? (this.logger.error(
1410
1448
  `[BodhiExtClient] Stream API error for ${r}: ${T.response.status}`
1411
1449
  ), e.postMessage({
1412
- type: h.EXT2EXT_CLIENT_STREAM_API_ERROR,
1450
+ type: c.EXT2EXT_CLIENT_STREAM_API_ERROR,
1413
1451
  requestId: r,
1414
1452
  response: T.response
1415
- })) : ae(T) && (this.logger.error(
1453
+ })) : ge(T) && (this.logger.error(
1416
1454
  `[BodhiExtClient] Stream error for ${r}:`,
1417
1455
  T.error.message
1418
1456
  ), e.postMessage({
1419
- type: h.EXT2EXT_CLIENT_STREAM_ERROR,
1457
+ type: c.EXT2EXT_CLIENT_STREAM_ERROR,
1420
1458
  requestId: r,
1421
1459
  error: {
1422
1460
  message: `stream error: ${JSON.stringify(T)}`,
1423
1461
  type: "extension_error"
1424
1462
  }
1425
- }), clearTimeout(g), this.cleanupStreamPort(r));
1426
- }), E.onDisconnect.addListener(() => {
1427
- clearTimeout(g), this.activeStreamPorts.has(r) && (this.logger.error(`[BodhiExtClient] Bodhi port disconnected for ${r}`), e.postMessage({
1428
- type: h.EXT2EXT_CLIENT_STREAM_ERROR,
1463
+ }), clearTimeout(p), this.cleanupStreamPort(r));
1464
+ }), u.onDisconnect.addListener(() => {
1465
+ clearTimeout(p), this.activeStreamPorts.has(r) && (this.logger.error(`[BodhiExtClient] Bodhi port disconnected for ${r}`), e.postMessage({
1466
+ type: c.EXT2EXT_CLIENT_STREAM_ERROR,
1429
1467
  requestId: r,
1430
1468
  error: {
1431
1469
  message: "Connection to Bodhi extension closed unexpectedly",
@@ -1433,24 +1471,24 @@ const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
1433
1471
  }
1434
1472
  }), this.activeStreamPorts.delete(r));
1435
1473
  });
1436
- const _ = {
1437
- type: m.STREAM_REQUEST,
1474
+ const g = {
1475
+ type: S.STREAM_REQUEST,
1438
1476
  requestId: r,
1439
1477
  request: {
1440
1478
  method: s,
1441
- endpoint: n,
1442
- body: i,
1443
- headers: u
1479
+ endpoint: o,
1480
+ body: n,
1481
+ headers: l
1444
1482
  }
1445
1483
  };
1446
- this.logger.debug("[BodhiExtClient] Sending stream request to bodhi port:", _), E.postMessage(_);
1447
- } catch (u) {
1448
- const E = u;
1449
- this.logger.error("[BodhiExtClient] Stream error:", JSON.stringify(E.message)), e.postMessage({
1450
- type: h.EXT2EXT_CLIENT_STREAM_ERROR,
1484
+ this.logger.debug("[BodhiExtClient] Sending stream request to bodhi port:", g), u.postMessage(g);
1485
+ } catch (l) {
1486
+ const u = l;
1487
+ this.logger.error("[BodhiExtClient] Stream error:", JSON.stringify(u.message)), e.postMessage({
1488
+ type: c.EXT2EXT_CLIENT_STREAM_ERROR,
1451
1489
  requestId: r,
1452
1490
  error: {
1453
- message: `uncaught error: ${JSON.stringify({ error: E, message: E.message })}`,
1491
+ message: `uncaught error: ${JSON.stringify({ error: u, message: u.message })}`,
1454
1492
  type: "extension_error"
1455
1493
  }
1456
1494
  });
@@ -1477,11 +1515,16 @@ const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
1477
1515
  * Required for authenticated API access - token will include aud claim.
1478
1516
  * @returns ApiResponseResult with scope or error
1479
1517
  */
1480
- async requestAccess() {
1518
+ async requestAccess(e, t) {
1519
+ const r = {
1520
+ app_client_id: this.authClientId,
1521
+ ...e && { toolset_scope_ids: e },
1522
+ ...t && { version: t }
1523
+ };
1481
1524
  return this.sendApiRequest(
1482
1525
  "POST",
1483
1526
  "/bodhi/v1/apps/request-access",
1484
- { app_client_id: this.authClientId }
1527
+ r
1485
1528
  );
1486
1529
  }
1487
1530
  // ============================================================================
@@ -1529,7 +1572,7 @@ const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
1529
1572
  async _doRefreshToken(e) {
1530
1573
  this.logger.debug("Refreshing access token");
1531
1574
  try {
1532
- const t = await W(
1575
+ const t = await te(
1533
1576
  this.authEndpoints.token,
1534
1577
  e,
1535
1578
  this.authClientId
@@ -1541,7 +1584,7 @@ const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
1541
1584
  } catch (t) {
1542
1585
  this.logger.warn("Token refresh failed:", t);
1543
1586
  }
1544
- throw this.logger.warn("Token refresh failed, keeping tokens for manual retry"), l(
1587
+ throw this.logger.warn("Token refresh failed, keeping tokens for manual retry"), d(
1545
1588
  "Access token expired and unable to refresh. Try logging out and logging in again.",
1546
1589
  "token_refresh_failed"
1547
1590
  );
@@ -1569,28 +1612,29 @@ const de = ["ggedphdcbekjlomjaidbajglgihbeaon"], le = ["bjdjhiombmfbcoeojijpfckl
1569
1612
  ]);
1570
1613
  }
1571
1614
  parseJwt(e) {
1572
- const r = e.split(".")[1].replace(/-/g, "+").replace(/_/g, "/"), o = decodeURIComponent(
1615
+ const r = e.split(".")[1].replace(/-/g, "+").replace(/_/g, "/"), i = decodeURIComponent(
1573
1616
  atob(r).split("").map((s) => "%" + ("00" + s.charCodeAt(0).toString(16)).slice(-2)).join("")
1574
1617
  );
1575
- return JSON.parse(o);
1618
+ return JSON.parse(i);
1576
1619
  }
1577
1620
  createErrorClientNotInitialized(e) {
1578
1621
  return `Client not initialized. Extension discovery not triggered nor extensionId set, cannot handle request: ${JSON.stringify(e)}`;
1579
1622
  }
1580
1623
  };
1581
- S.STREAM_TIMEOUT = 6e4;
1582
- let v = S;
1583
- const _e = "production";
1624
+ y.STREAM_TIMEOUT = 6e4;
1625
+ let k = y;
1626
+ const fe = "production";
1584
1627
  export {
1585
- v as BodhiExtClient,
1586
- Y as DISCOVERY_ATTEMPTS,
1587
- j as DISCOVERY_ATTEMPT_TIMEOUT,
1588
- Z as DISCOVERY_ATTEMPT_WAIT_MS,
1589
- J as DISCOVERY_TIMEOUT_MS,
1590
- p as EXT2EXT_CLIENT_ACTIONS,
1591
- h as EXT2EXT_CLIENT_MESSAGE_TYPES,
1592
- k as EXT2EXT_CLIENT_STREAM_PORT,
1593
- _e as EXT_BUILD_MODE,
1594
- Te as ExtUIClient,
1595
- ee as isExtClientApiError
1628
+ k as BodhiExtClient,
1629
+ ne as DEFAULT_API_TIMEOUT_MS,
1630
+ se as DISCOVERY_ATTEMPTS,
1631
+ ie as DISCOVERY_ATTEMPT_TIMEOUT,
1632
+ oe as DISCOVERY_ATTEMPT_WAIT_MS,
1633
+ re as DISCOVERY_TIMEOUT_MS,
1634
+ m as EXT2EXT_CLIENT_ACTIONS,
1635
+ c as EXT2EXT_CLIENT_MESSAGE_TYPES,
1636
+ $ as EXT2EXT_CLIENT_STREAM_PORT,
1637
+ fe as EXT_BUILD_MODE,
1638
+ Re as ExtUIClient,
1639
+ ae as isExtClientApiError
1596
1640
  };