@bodhiapp/bodhi-js-ext 0.0.42 → 0.0.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bodhi-ext.cjs.js +1 -1
- package/dist/bodhi-ext.esm.js +294 -286
- package/dist/ext2ext-client.d.ts +2 -0
- package/package.json +4 -4
package/dist/bodhi-ext.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { DirectClientBase as V, createStoragePrefixWithNamespace as X, STORAGE_PREFIXES as N, generateCodeVerifier as w, generateCodeChallenge as z, buildAuthorizeUrl as v, BASE_OAUTH_SCOPE as L, buildErrorUrl as b, AccessRequestBuilder as
|
|
1
|
+
import { DirectClientBase as V, createStoragePrefixWithNamespace as X, STORAGE_PREFIXES as N, generateCodeVerifier as w, generateCodeChallenge as z, buildAuthorizeUrl as v, BASE_OAUTH_SCOPE as L, buildErrorUrl as b, AccessRequestBuilder as k, unwrapResponse as P, buildReviewUrl as O, createOperationError as l, throwAccessRequestDenialError as M, PENDING_EXTENSION_READY as f, Logger as y, NOOP_STATE_CALLBACK as Q, createExtensionStateNotInitialized as G, BACKEND_SERVER_NOT_REACHABLE as K, createExtensionStateNotFound as F, BodhiError as T, INITIAL_AUTH_STATE as H, BodhiApiError as W, Chat as J, Models as Y, Embeddings as j, Mcps as Z, isAuthError as ee, BaseFacadeClient as te, refreshAccessToken as re } from "@bodhiapp/bodhi-js-core";
|
|
2
2
|
import { InMemoryStorage as Ae } from "@bodhiapp/bodhi-js-core";
|
|
3
|
-
import { isExtError as
|
|
3
|
+
import { isExtError as x, isApiSuccessResponse as se, MESSAGE_TYPES as _, EXT_ACTIONS as ie, BODHI_STREAM_PORT as ne, isStreamChunk as oe, isStreamApiError as ae, isStreamError as ce, BODHI_STREAM_TEXT_PORT as he } from "@bodhiapp/bodhi-browser-types";
|
|
4
4
|
const a = {
|
|
5
5
|
EXT2EXT_CLIENT_REQUEST: "EXT2EXT_CLIENT_REQUEST",
|
|
6
6
|
EXT2EXT_CLIENT_RESPONSE: "EXT2EXT_CLIENT_RESPONSE",
|
|
@@ -47,7 +47,7 @@ class me extends V {
|
|
|
47
47
|
const r = X(
|
|
48
48
|
e.basePath,
|
|
49
49
|
N.EXT_DIRECT
|
|
50
|
-
),
|
|
50
|
+
), o = {
|
|
51
51
|
authClientId: e.authClientId,
|
|
52
52
|
authServerUrl: e.authServerUrl,
|
|
53
53
|
storagePrefix: r,
|
|
@@ -57,63 +57,63 @@ class me extends V {
|
|
|
57
57
|
storage: e.storage ?? new _e(),
|
|
58
58
|
initialTokens: e.initialTokens
|
|
59
59
|
};
|
|
60
|
-
super(
|
|
60
|
+
super(o, t);
|
|
61
61
|
}
|
|
62
62
|
// ============================================================================
|
|
63
63
|
// Authentication (chrome.identity OAuth)
|
|
64
64
|
// ============================================================================
|
|
65
65
|
async login(e) {
|
|
66
66
|
const t = await this.getAuthState();
|
|
67
|
-
if (t.status === "authenticated")
|
|
67
|
+
if (t.status === "authenticated" && !e?.exchange)
|
|
68
68
|
return t;
|
|
69
|
-
const r = e?.userRole ?? "scope_user_user",
|
|
69
|
+
const r = e?.userRole ?? "scope_user_user", o = this._getRedirectUri();
|
|
70
70
|
e?.onProgress?.("requesting");
|
|
71
|
-
const s = w(),
|
|
71
|
+
const s = w(), i = await z(s), n = w();
|
|
72
72
|
await this._storageSet({
|
|
73
73
|
[this.storageKeys.CODE_VERIFIER]: s,
|
|
74
74
|
[this.storageKeys.STATE]: n
|
|
75
75
|
});
|
|
76
|
-
const
|
|
76
|
+
const u = v(this.authEndpoints, {
|
|
77
77
|
clientId: this.authClientId,
|
|
78
|
-
redirectUri:
|
|
78
|
+
redirectUri: o,
|
|
79
79
|
scope: L,
|
|
80
80
|
state: n,
|
|
81
|
-
codeChallenge:
|
|
82
|
-
}), c = b(
|
|
83
|
-
e?.requested &&
|
|
84
|
-
const
|
|
81
|
+
codeChallenge: i
|
|
82
|
+
}), c = b(o), h = new k(this.authClientId).requestedRole(r);
|
|
83
|
+
e?.requested && h.requested(e.requested), e?.exchange && h.exchange(!0);
|
|
84
|
+
const E = await this.requestAccess(h.build()), { review_url: d } = P(E), g = O(d, u, c);
|
|
85
85
|
e?.onProgress?.("reviewing");
|
|
86
86
|
const S = await this.launchReview(g);
|
|
87
87
|
return e?.onProgress?.("authenticating"), this.completeOAuthRedirect(S);
|
|
88
88
|
}
|
|
89
89
|
launchReview(e) {
|
|
90
90
|
return new Promise((t, r) => {
|
|
91
|
-
chrome.identity.launchWebAuthFlow({ url: e, interactive: !0 }, (
|
|
91
|
+
chrome.identity.launchWebAuthFlow({ url: e, interactive: !0 }, (o) => {
|
|
92
92
|
if (chrome.runtime.lastError) {
|
|
93
93
|
r(chrome.runtime.lastError);
|
|
94
94
|
return;
|
|
95
95
|
}
|
|
96
|
-
if (!
|
|
97
|
-
r(
|
|
96
|
+
if (!o) {
|
|
97
|
+
r(l("oauth_error", "No redirect URL received"));
|
|
98
98
|
return;
|
|
99
99
|
}
|
|
100
|
-
t(
|
|
100
|
+
t(o);
|
|
101
101
|
});
|
|
102
102
|
});
|
|
103
103
|
}
|
|
104
104
|
async completeOAuthRedirect(e) {
|
|
105
105
|
const t = new URL(e), r = t.searchParams.get("error");
|
|
106
106
|
if (r)
|
|
107
|
-
throw await this._storageRemove([this.storageKeys.CODE_VERIFIER, this.storageKeys.STATE]), t.searchParams.get("error_source") === "bodhi" && M(r === "access_denied" ? "denied" : r),
|
|
108
|
-
const
|
|
109
|
-
if (!s || s !==
|
|
110
|
-
throw await this._storageRemove([this.storageKeys.CODE_VERIFIER, this.storageKeys.STATE]),
|
|
111
|
-
if (!
|
|
112
|
-
throw await this._storageRemove([this.storageKeys.CODE_VERIFIER, this.storageKeys.STATE]),
|
|
113
|
-
await this.exchangeCodeForTokens(
|
|
107
|
+
throw await this._storageRemove([this.storageKeys.CODE_VERIFIER, this.storageKeys.STATE]), t.searchParams.get("error_source") === "bodhi" && M(r === "access_denied" ? "denied" : r), l("oauth_error", t.searchParams.get("error_description") ?? r);
|
|
108
|
+
const o = t.searchParams.get("code"), s = t.searchParams.get("state"), i = await this._storageGet(this.storageKeys.STATE);
|
|
109
|
+
if (!s || s !== i)
|
|
110
|
+
throw await this._storageRemove([this.storageKeys.CODE_VERIFIER, this.storageKeys.STATE]), l("oauth_error", "State mismatch");
|
|
111
|
+
if (!o)
|
|
112
|
+
throw await this._storageRemove([this.storageKeys.CODE_VERIFIER, this.storageKeys.STATE]), l("oauth_error", "No authorization code");
|
|
113
|
+
await this.exchangeCodeForTokens(o);
|
|
114
114
|
const n = await this.getAuthState();
|
|
115
115
|
if (n.status !== "authenticated")
|
|
116
|
-
throw await this._storageRemove([this.storageKeys.CODE_VERIFIER, this.storageKeys.STATE]),
|
|
116
|
+
throw await this._storageRemove([this.storageKeys.CODE_VERIFIER, this.storageKeys.STATE]), l("oauth_error", "Login failed");
|
|
117
117
|
return this.setAuthState(n), n;
|
|
118
118
|
}
|
|
119
119
|
_getRedirectUri() {
|
|
@@ -127,7 +127,7 @@ class pe {
|
|
|
127
127
|
extension: "not-initialized",
|
|
128
128
|
extensionId: null,
|
|
129
129
|
server: f
|
|
130
|
-
}, this.extensionId = null, this.broadcastListenerActive = !1, this.config = e, this.logger = new
|
|
130
|
+
}, this.extensionId = null, this.broadcastListenerActive = !1, this.config = e, this.logger = new y("ExtClient", e?.logLevel || "warn"), this.onStateChange = t ?? Q, this.apiTimeoutMs = e.apiTimeoutMs ?? Te, this.authClientId = e.authClientId ?? "";
|
|
131
131
|
}
|
|
132
132
|
/**
|
|
133
133
|
* Set client state and notify callback
|
|
@@ -195,8 +195,8 @@ class pe {
|
|
|
195
195
|
async init(e = {}) {
|
|
196
196
|
if (!e.testConnection && !e.selectedConnection) {
|
|
197
197
|
this.logger.info("No testConnection or selectedConnection, returning not-initialized state");
|
|
198
|
-
const
|
|
199
|
-
return this.setState(
|
|
198
|
+
const o = G();
|
|
199
|
+
return this.setState(o), o;
|
|
200
200
|
}
|
|
201
201
|
if (this.extensionId && !e.testConnection)
|
|
202
202
|
return this.logger.debug("Already initialized with extensionId, skipping discovery"), this.state;
|
|
@@ -211,20 +211,20 @@ class pe {
|
|
|
211
211
|
), this.extensionId = r;
|
|
212
212
|
else {
|
|
213
213
|
this.logger.info("Discovering bodhi-browser extension...");
|
|
214
|
-
const
|
|
214
|
+
const i = {
|
|
215
215
|
attempts: this.config.initParams?.extension?.attempts,
|
|
216
216
|
attemptWaitMs: this.config.initParams?.extension?.attemptWaitMs,
|
|
217
217
|
attemptTimeout: this.config.initParams?.extension?.attemptTimeout
|
|
218
218
|
}, n = await this.sendExtMessageWithTimeout(
|
|
219
219
|
m.DISCOVER_EXTENSION,
|
|
220
|
-
|
|
220
|
+
i,
|
|
221
221
|
t
|
|
222
222
|
);
|
|
223
223
|
this.extensionId = n.extensionId, this.logger.info("Extension discovered:", this.extensionId);
|
|
224
224
|
}
|
|
225
225
|
this.setupBroadcastListener();
|
|
226
226
|
}
|
|
227
|
-
const
|
|
227
|
+
const o = {
|
|
228
228
|
type: "extension",
|
|
229
229
|
extension: "ready",
|
|
230
230
|
extensionId: this.extensionId,
|
|
@@ -234,12 +234,12 @@ class pe {
|
|
|
234
234
|
if (e.testConnection)
|
|
235
235
|
try {
|
|
236
236
|
s = await this.getServerState(), this.logger.info("Server connectivity tested, state:", s.status);
|
|
237
|
-
} catch (
|
|
238
|
-
this.logger.error("Failed to get server state:",
|
|
237
|
+
} catch (i) {
|
|
238
|
+
this.logger.error("Failed to get server state:", i), s = K;
|
|
239
239
|
}
|
|
240
|
-
return this.setState({ ...
|
|
241
|
-
} catch (
|
|
242
|
-
this.logger.error("Failed to initialize extension:",
|
|
240
|
+
return this.setState({ ...o, server: s }), this.state;
|
|
241
|
+
} catch (o) {
|
|
242
|
+
this.logger.error("Failed to initialize extension:", o), this.extensionId = null;
|
|
243
243
|
const s = F();
|
|
244
244
|
return this.setState(s), this.state;
|
|
245
245
|
}
|
|
@@ -248,10 +248,10 @@ class pe {
|
|
|
248
248
|
* Helper method to send ext message with timeout support
|
|
249
249
|
*/
|
|
250
250
|
async sendExtMessageWithTimeout(e, t, r = 1e4) {
|
|
251
|
-
const
|
|
252
|
-
(s,
|
|
251
|
+
const o = new Promise(
|
|
252
|
+
(s, i) => setTimeout(() => i(new Error("Timeout")), r)
|
|
253
253
|
);
|
|
254
|
-
return Promise.race([this.sendExtRequest(e, t),
|
|
254
|
+
return Promise.race([this.sendExtRequest(e, t), o]);
|
|
255
255
|
}
|
|
256
256
|
/**
|
|
257
257
|
* Send an EXT2EXT_CLIENT_REQUEST message and await EXT2EXT_CLIENT_RESPONSE
|
|
@@ -259,7 +259,7 @@ class pe {
|
|
|
259
259
|
*/
|
|
260
260
|
async sendExtRequest(e, t) {
|
|
261
261
|
try {
|
|
262
|
-
const r = this.generateRequestId(),
|
|
262
|
+
const r = this.generateRequestId(), o = await chrome.runtime.sendMessage({
|
|
263
263
|
type: a.EXT2EXT_CLIENT_REQUEST,
|
|
264
264
|
requestId: r,
|
|
265
265
|
request: {
|
|
@@ -267,21 +267,21 @@ class pe {
|
|
|
267
267
|
params: t
|
|
268
268
|
}
|
|
269
269
|
});
|
|
270
|
-
if (!
|
|
271
|
-
throw
|
|
272
|
-
if (
|
|
273
|
-
throw
|
|
270
|
+
if (!o)
|
|
271
|
+
throw l("extension_error", "No response from background script");
|
|
272
|
+
if (o.type !== a.EXT2EXT_CLIENT_RESPONSE)
|
|
273
|
+
throw l(
|
|
274
274
|
"extension_error",
|
|
275
275
|
"Invalid response type from background script"
|
|
276
276
|
);
|
|
277
|
-
const s =
|
|
278
|
-
if (
|
|
279
|
-
const
|
|
280
|
-
throw
|
|
277
|
+
const s = o.response;
|
|
278
|
+
if (x(s)) {
|
|
279
|
+
const i = s.error.type || "extension_error";
|
|
280
|
+
throw l(i, s.error.message);
|
|
281
281
|
}
|
|
282
282
|
return s;
|
|
283
283
|
} catch (r) {
|
|
284
|
-
throw r instanceof T ? r :
|
|
284
|
+
throw r instanceof T ? r : l(
|
|
285
285
|
"extension_error",
|
|
286
286
|
r instanceof Error ? r.message : "Unknown error occurred"
|
|
287
287
|
);
|
|
@@ -291,16 +291,16 @@ class pe {
|
|
|
291
291
|
* Send an API_REQUEST message and await API_RESPONSE (internal)
|
|
292
292
|
* Returns ext2ext-specific ExtClientApiResponseMessage
|
|
293
293
|
*/
|
|
294
|
-
async sendRawApiMessage(e, t, r,
|
|
295
|
-
const
|
|
294
|
+
async sendRawApiMessage(e, t, r, o, s) {
|
|
295
|
+
const i = this.generateRequestId();
|
|
296
296
|
return await chrome.runtime.sendMessage({
|
|
297
297
|
type: a.EXT2EXT_CLIENT_API_REQUEST,
|
|
298
|
-
requestId:
|
|
298
|
+
requestId: i,
|
|
299
299
|
request: {
|
|
300
300
|
method: e,
|
|
301
301
|
endpoint: t,
|
|
302
302
|
body: r,
|
|
303
|
-
headers:
|
|
303
|
+
headers: o,
|
|
304
304
|
authenticated: s
|
|
305
305
|
}
|
|
306
306
|
});
|
|
@@ -309,10 +309,10 @@ class pe {
|
|
|
309
309
|
* Send an API message and return ApiResponse
|
|
310
310
|
* @throws BodhiError on operational errors (network, timeout, extension-level)
|
|
311
311
|
*/
|
|
312
|
-
async sendApiRequest(e, t, r,
|
|
312
|
+
async sendApiRequest(e, t, r, o, s) {
|
|
313
313
|
try {
|
|
314
|
-
const
|
|
315
|
-
(
|
|
314
|
+
const i = new Promise(
|
|
315
|
+
(u, c) => setTimeout(
|
|
316
316
|
() => c(
|
|
317
317
|
new Error(
|
|
318
318
|
`[bodhi-js-sdk/ext] network timeout: api request not completed within configured/default timeout of ${this.apiTimeoutMs}ms`
|
|
@@ -321,18 +321,18 @@ class pe {
|
|
|
321
321
|
this.apiTimeoutMs
|
|
322
322
|
)
|
|
323
323
|
), n = await Promise.race([
|
|
324
|
-
this.sendRawApiMessage(e, t, r,
|
|
325
|
-
|
|
324
|
+
this.sendRawApiMessage(e, t, r, o, s),
|
|
325
|
+
i
|
|
326
326
|
]);
|
|
327
327
|
if (ge(n)) {
|
|
328
|
-
const
|
|
329
|
-
throw new T(
|
|
328
|
+
const u = n.error.type || "extension_error";
|
|
329
|
+
throw new T(u, n.error.message);
|
|
330
330
|
}
|
|
331
331
|
return n.response;
|
|
332
|
-
} catch (
|
|
333
|
-
if (
|
|
334
|
-
throw
|
|
335
|
-
const n =
|
|
332
|
+
} catch (i) {
|
|
333
|
+
if (i instanceof T)
|
|
334
|
+
throw i;
|
|
335
|
+
const n = i instanceof Error ? i.message : String(i);
|
|
336
336
|
throw new T("network_error", n);
|
|
337
337
|
}
|
|
338
338
|
}
|
|
@@ -344,29 +344,29 @@ class pe {
|
|
|
344
344
|
*/
|
|
345
345
|
async login(e) {
|
|
346
346
|
return new Promise((t, r) => {
|
|
347
|
-
const
|
|
347
|
+
const o = async (s) => {
|
|
348
348
|
if (s && typeof s == "object" && "type" in s && s.type === "EXT2EXT_CLIENT_BROADCAST" && "event" in s && s.event === "authStateChanged") {
|
|
349
|
-
chrome.runtime.onMessage.removeListener(
|
|
349
|
+
chrome.runtime.onMessage.removeListener(o);
|
|
350
350
|
try {
|
|
351
|
-
const
|
|
352
|
-
if (ee(
|
|
351
|
+
const i = await this.getAuthState();
|
|
352
|
+
if (ee(i)) {
|
|
353
353
|
r(
|
|
354
|
-
|
|
354
|
+
l("auth_error", `Login failed: ${i.error?.message}`)
|
|
355
355
|
);
|
|
356
356
|
return;
|
|
357
357
|
}
|
|
358
|
-
if (
|
|
359
|
-
r(
|
|
358
|
+
if (i.status !== "authenticated") {
|
|
359
|
+
r(l("auth_error", "Login failed: User is not logged in"));
|
|
360
360
|
return;
|
|
361
361
|
}
|
|
362
|
-
this.setAuthState(
|
|
363
|
-
} catch (
|
|
364
|
-
r(
|
|
362
|
+
this.setAuthState(i), t(i);
|
|
363
|
+
} catch (i) {
|
|
364
|
+
r(i);
|
|
365
365
|
}
|
|
366
366
|
}
|
|
367
367
|
};
|
|
368
|
-
chrome.runtime.onMessage.addListener(
|
|
369
|
-
chrome.runtime.onMessage.removeListener(
|
|
368
|
+
chrome.runtime.onMessage.addListener(o), this.sendExtRequest(m.LOGIN, e).catch((s) => {
|
|
369
|
+
chrome.runtime.onMessage.removeListener(o), r(s);
|
|
370
370
|
});
|
|
371
371
|
});
|
|
372
372
|
}
|
|
@@ -413,11 +413,11 @@ class pe {
|
|
|
413
413
|
try {
|
|
414
414
|
e = await this.sendApiRequest("GET", "/bodhi/v1/info");
|
|
415
415
|
} catch (s) {
|
|
416
|
-
const
|
|
416
|
+
const i = s instanceof Error ? s.message : "Connection failed", n = s instanceof T ? s.code : "extension_error";
|
|
417
417
|
return {
|
|
418
418
|
status: "not-reachable",
|
|
419
419
|
version: null,
|
|
420
|
-
error: { message:
|
|
420
|
+
error: { message: i, type: n }
|
|
421
421
|
};
|
|
422
422
|
}
|
|
423
423
|
if (e.status >= 400)
|
|
@@ -426,30 +426,30 @@ class pe {
|
|
|
426
426
|
version: null,
|
|
427
427
|
error: { message: "API error from server", type: "extension_error" }
|
|
428
428
|
};
|
|
429
|
-
const t = e.body, r = t.version || "unknown",
|
|
429
|
+
const t = e.body, r = t.version || "unknown", o = { deployment: t.deployment ?? null, client_id: t.client_id ?? null };
|
|
430
430
|
switch (t.status) {
|
|
431
431
|
case "ready":
|
|
432
|
-
return { status: "ready", version: r, error: null, ...
|
|
432
|
+
return { status: "ready", version: r, error: null, ...o };
|
|
433
433
|
case "setup":
|
|
434
434
|
return {
|
|
435
435
|
status: "setup",
|
|
436
436
|
version: r,
|
|
437
437
|
error: t.error ? { message: t.error.message, type: t.error.type } : { message: "Setup required", type: "extension_error" },
|
|
438
|
-
...
|
|
438
|
+
...o
|
|
439
439
|
};
|
|
440
440
|
case "resource_admin":
|
|
441
441
|
return {
|
|
442
442
|
status: "resource_admin",
|
|
443
443
|
version: r,
|
|
444
444
|
error: t.error ? { message: t.error.message, type: t.error.type } : { message: "Resource admin required", type: "extension_error" },
|
|
445
|
-
...
|
|
445
|
+
...o
|
|
446
446
|
};
|
|
447
447
|
case "error":
|
|
448
448
|
return {
|
|
449
449
|
status: "error",
|
|
450
450
|
version: r,
|
|
451
451
|
error: t.error ? { message: t.error.message, type: t.error.type } : { message: "Server error", type: "extension_error" },
|
|
452
|
-
...
|
|
452
|
+
...o
|
|
453
453
|
};
|
|
454
454
|
default:
|
|
455
455
|
return {
|
|
@@ -465,73 +465,73 @@ class pe {
|
|
|
465
465
|
/**
|
|
466
466
|
* Generic streaming method
|
|
467
467
|
*/
|
|
468
|
-
async *stream(e, t, r,
|
|
469
|
-
const
|
|
468
|
+
async *stream(e, t, r, o, s = !0) {
|
|
469
|
+
const i = this.generateRequestId();
|
|
470
470
|
this.logger.debug("Starting stream", {
|
|
471
471
|
method: e,
|
|
472
472
|
endpoint: t,
|
|
473
|
-
requestId:
|
|
473
|
+
requestId: i
|
|
474
474
|
});
|
|
475
475
|
const n = chrome.runtime.connect({ name: U }), c = new ReadableStream({
|
|
476
|
-
start: (
|
|
477
|
-
n.onMessage.addListener((
|
|
478
|
-
if (
|
|
479
|
-
switch (
|
|
476
|
+
start: (h) => {
|
|
477
|
+
n.onMessage.addListener((E) => {
|
|
478
|
+
if (E.requestId === i)
|
|
479
|
+
switch (E.type) {
|
|
480
480
|
case a.EXT2EXT_CLIENT_STREAM_DONE:
|
|
481
|
-
this.logger.debug("Stream complete", { requestId:
|
|
481
|
+
this.logger.debug("Stream complete", { requestId: i }), h.close(), n.disconnect();
|
|
482
482
|
break;
|
|
483
483
|
case a.EXT2EXT_CLIENT_STREAM_ERROR:
|
|
484
484
|
this.logger.error("Stream error", {
|
|
485
|
-
requestId:
|
|
486
|
-
error: JSON.stringify(
|
|
487
|
-
}),
|
|
485
|
+
requestId: i,
|
|
486
|
+
error: JSON.stringify(E.error)
|
|
487
|
+
}), h.error(
|
|
488
488
|
new T(
|
|
489
489
|
"extension_error",
|
|
490
|
-
|
|
490
|
+
E.error.message
|
|
491
491
|
)
|
|
492
492
|
), n.disconnect();
|
|
493
493
|
break;
|
|
494
494
|
case a.EXT2EXT_CLIENT_STREAM_API_ERROR: {
|
|
495
|
-
const
|
|
495
|
+
const d = E;
|
|
496
496
|
this.logger.error("Stream API error", {
|
|
497
|
-
requestId:
|
|
498
|
-
error:
|
|
499
|
-
}),
|
|
497
|
+
requestId: i,
|
|
498
|
+
error: d.response.body?.error
|
|
499
|
+
}), h.error(
|
|
500
500
|
new W(
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
501
|
+
d.response.status,
|
|
502
|
+
d.response.body,
|
|
503
|
+
d.response.body?.error?.message || "API error"
|
|
504
504
|
)
|
|
505
505
|
), n.disconnect();
|
|
506
506
|
break;
|
|
507
507
|
}
|
|
508
508
|
case a.EXT2EXT_CLIENT_STREAM_CHUNK: {
|
|
509
|
-
const
|
|
510
|
-
se(
|
|
509
|
+
const d = E;
|
|
510
|
+
se(d.response) && h.enqueue(d.response.body);
|
|
511
511
|
break;
|
|
512
512
|
}
|
|
513
513
|
}
|
|
514
514
|
}), n.onDisconnect.addListener(() => {
|
|
515
|
-
this.logger.debug("Port disconnected", { requestId:
|
|
515
|
+
this.logger.debug("Port disconnected", { requestId: i });
|
|
516
516
|
try {
|
|
517
|
-
|
|
517
|
+
h.error(new T("connection_closed", "Connection closed unexpectedly"));
|
|
518
518
|
} catch {
|
|
519
519
|
}
|
|
520
520
|
}), n.postMessage({
|
|
521
521
|
type: a.EXT2EXT_CLIENT_STREAM_REQUEST,
|
|
522
|
-
requestId:
|
|
523
|
-
request: { method: e, endpoint: t, body: r, headers:
|
|
522
|
+
requestId: i,
|
|
523
|
+
request: { method: e, endpoint: t, body: r, headers: o, authenticated: s }
|
|
524
524
|
});
|
|
525
525
|
}
|
|
526
526
|
}).getReader();
|
|
527
527
|
try {
|
|
528
528
|
for (; ; ) {
|
|
529
|
-
const { done:
|
|
530
|
-
if (
|
|
529
|
+
const { done: h, value: E } = await c.read();
|
|
530
|
+
if (h) {
|
|
531
531
|
this.logger.debug("Stream iteration complete");
|
|
532
532
|
break;
|
|
533
533
|
}
|
|
534
|
-
yield
|
|
534
|
+
yield E;
|
|
535
535
|
}
|
|
536
536
|
} finally {
|
|
537
537
|
c.releaseLock();
|
|
@@ -541,20 +541,20 @@ class pe {
|
|
|
541
541
|
* Raw text streaming method - no SSE/JSON parsing
|
|
542
542
|
* Returns status, headers, and async generator of raw text chunks
|
|
543
543
|
*/
|
|
544
|
-
async streamText(e, t, r,
|
|
545
|
-
const
|
|
546
|
-
return new Promise((n,
|
|
547
|
-
let c,
|
|
548
|
-
const
|
|
544
|
+
async streamText(e, t, r, o, s = !0) {
|
|
545
|
+
const i = this.generateRequestId();
|
|
546
|
+
return new Promise((n, u) => {
|
|
547
|
+
let c, h = !1;
|
|
548
|
+
const E = new ReadableStream({
|
|
549
549
|
start: (g) => {
|
|
550
550
|
c = g;
|
|
551
551
|
}
|
|
552
|
-
}),
|
|
553
|
-
|
|
554
|
-
if (g.requestId ===
|
|
552
|
+
}), d = chrome.runtime.connect({ name: D });
|
|
553
|
+
d.onMessage.addListener((g) => {
|
|
554
|
+
if (g.requestId === i)
|
|
555
555
|
switch (g.type) {
|
|
556
556
|
case a.EXT2EXT_CLIENT_STREAM_TEXT_START: {
|
|
557
|
-
|
|
557
|
+
h = !0;
|
|
558
558
|
async function* S(q) {
|
|
559
559
|
const C = q.getReader();
|
|
560
560
|
try {
|
|
@@ -570,7 +570,7 @@ class pe {
|
|
|
570
570
|
n({
|
|
571
571
|
status: g.status,
|
|
572
572
|
headers: g.headers,
|
|
573
|
-
body: S(
|
|
573
|
+
body: S(E)
|
|
574
574
|
});
|
|
575
575
|
break;
|
|
576
576
|
}
|
|
@@ -578,28 +578,28 @@ class pe {
|
|
|
578
578
|
c.enqueue(g.chunk);
|
|
579
579
|
break;
|
|
580
580
|
case a.EXT2EXT_CLIENT_STREAM_TEXT_DONE:
|
|
581
|
-
c.close(),
|
|
581
|
+
c.close(), d.disconnect();
|
|
582
582
|
break;
|
|
583
583
|
case a.EXT2EXT_CLIENT_STREAM_TEXT_ERROR: {
|
|
584
|
-
const S =
|
|
585
|
-
|
|
584
|
+
const S = l("extension_error", g.error.message);
|
|
585
|
+
h ? c.error(S) : u(S), d.disconnect();
|
|
586
586
|
break;
|
|
587
587
|
}
|
|
588
588
|
}
|
|
589
|
-
}),
|
|
590
|
-
if (!
|
|
591
|
-
|
|
589
|
+
}), d.onDisconnect.addListener(() => {
|
|
590
|
+
if (!h)
|
|
591
|
+
u(l("extension_error", "Connection closed unexpectedly"));
|
|
592
592
|
else
|
|
593
593
|
try {
|
|
594
594
|
c.error(
|
|
595
|
-
|
|
595
|
+
l("extension_error", "Connection closed unexpectedly")
|
|
596
596
|
);
|
|
597
597
|
} catch {
|
|
598
598
|
}
|
|
599
|
-
}),
|
|
599
|
+
}), d.postMessage({
|
|
600
600
|
type: a.EXT2EXT_CLIENT_STREAM_TEXT_REQUEST,
|
|
601
|
-
requestId:
|
|
602
|
-
request: { method: e, endpoint: t, body: r, headers:
|
|
601
|
+
requestId: i,
|
|
602
|
+
request: { method: e, endpoint: t, body: r, headers: o, authenticated: s }
|
|
603
603
|
});
|
|
604
604
|
});
|
|
605
605
|
}
|
|
@@ -647,21 +647,21 @@ class pe {
|
|
|
647
647
|
};
|
|
648
648
|
}
|
|
649
649
|
}
|
|
650
|
-
class
|
|
650
|
+
class xe extends te {
|
|
651
651
|
constructor(e, t, r) {
|
|
652
|
-
const
|
|
653
|
-
basePath:
|
|
654
|
-
authServerUrl:
|
|
655
|
-
logLevel:
|
|
656
|
-
apiTimeoutMs:
|
|
657
|
-
storage:
|
|
658
|
-
initialTokens:
|
|
659
|
-
initParams:
|
|
652
|
+
const o = t || {}, s = {
|
|
653
|
+
basePath: o.basePath || "/",
|
|
654
|
+
authServerUrl: o.authServerUrl || "https://id.getbodhi.app/realms/bodhi",
|
|
655
|
+
logLevel: o.logLevel || "warn",
|
|
656
|
+
apiTimeoutMs: o.apiTimeoutMs,
|
|
657
|
+
storage: o.storage,
|
|
658
|
+
initialTokens: o.initialTokens,
|
|
659
|
+
initParams: o.initParams
|
|
660
660
|
};
|
|
661
661
|
super(e, s, r);
|
|
662
662
|
}
|
|
663
663
|
createLogger(e) {
|
|
664
|
-
return new
|
|
664
|
+
return new y("ExtUIClient", e.logLevel);
|
|
665
665
|
}
|
|
666
666
|
createStoragePrefix(e) {
|
|
667
667
|
return X(e.basePath, N.EXT);
|
|
@@ -697,7 +697,7 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
697
697
|
// Constructor
|
|
698
698
|
// ============================================================================
|
|
699
699
|
constructor(e, t) {
|
|
700
|
-
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.extensionId = t?.extensionId, this.logger = new
|
|
700
|
+
this.isAuthenticating = !1, this.isExchanging = !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.extensionId = t?.extensionId, this.logger = new y("BodhiExtClient", t?.logLevel || "warn"), this.attempts = t?.attempts ?? ue, this.attemptWaitMs = t?.attemptWaitMs ?? de, this.attemptTimeout = t?.attemptTimeout ?? le, this.authEndpoints = {
|
|
701
701
|
authorize: `${this.authServerUrl}/protocol/openid-connect/auth`,
|
|
702
702
|
token: `${this.authServerUrl}/protocol/openid-connect/token`,
|
|
703
703
|
userinfo: `${this.authServerUrl}/protocol/openid-connect/userinfo`,
|
|
@@ -718,8 +718,8 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
718
718
|
return crypto.getRandomValues(e), p.base64UrlEncode(e.buffer);
|
|
719
719
|
}
|
|
720
720
|
static async generateCodeChallenge(e) {
|
|
721
|
-
const r = new TextEncoder().encode(e),
|
|
722
|
-
return p.base64UrlEncode(
|
|
721
|
+
const r = new TextEncoder().encode(e), o = await crypto.subtle.digest("SHA-256", r);
|
|
722
|
+
return p.base64UrlEncode(o);
|
|
723
723
|
}
|
|
724
724
|
// ============================================================================
|
|
725
725
|
// State Management
|
|
@@ -748,7 +748,7 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
748
748
|
return this.logger.debug(
|
|
749
749
|
`[Ext2Ext/Discovery] Pinging extension: ${e} with timeout ${this.attemptTimeout}ms`
|
|
750
750
|
), new Promise((t, r) => {
|
|
751
|
-
const
|
|
751
|
+
const o = setTimeout(() => {
|
|
752
752
|
this.logger.debug(`[Ext2Ext/Discovery] Timeout waiting for extension ${e}`), r(new Error("Timeout"));
|
|
753
753
|
}, this.attemptTimeout);
|
|
754
754
|
try {
|
|
@@ -759,23 +759,23 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
759
759
|
action: "get_extension_id"
|
|
760
760
|
}
|
|
761
761
|
};
|
|
762
|
-
this.logger.debug(`[Ext2Ext/Discovery] Sending message to ${e}:`, s), chrome.runtime.sendMessage(e, s, (
|
|
763
|
-
if (clearTimeout(
|
|
762
|
+
this.logger.debug(`[Ext2Ext/Discovery] Sending message to ${e}:`, s), chrome.runtime.sendMessage(e, s, (i) => {
|
|
763
|
+
if (clearTimeout(o), chrome.runtime.lastError) {
|
|
764
764
|
this.logger.error(
|
|
765
765
|
`[Ext2Ext/Discovery] Error from extension ${e}:`,
|
|
766
766
|
chrome.runtime.lastError.message
|
|
767
767
|
), r(new Error(chrome.runtime.lastError.message));
|
|
768
768
|
return;
|
|
769
769
|
}
|
|
770
|
-
this.logger.debug(`[Ext2Ext/Discovery] Response from ${e}:`,
|
|
771
|
-
const n =
|
|
770
|
+
this.logger.debug(`[Ext2Ext/Discovery] Response from ${e}:`, i);
|
|
771
|
+
const n = i;
|
|
772
772
|
n && n.type === _.EXT_RESPONSE ? (this.logger.debug(`[Ext2Ext/Discovery] ✓ Extension ${e} responded`), t(!0)) : (this.logger.error(
|
|
773
773
|
`[Ext2Ext/Discovery] Invalid response from ${e}:`,
|
|
774
|
-
|
|
774
|
+
i
|
|
775
775
|
), r(new Error("Invalid response")));
|
|
776
776
|
});
|
|
777
777
|
} catch (s) {
|
|
778
|
-
this.logger.error(`[Ext2Ext/Discovery] Exception pinging ${e}:`, s), clearTimeout(
|
|
778
|
+
this.logger.error(`[Ext2Ext/Discovery] Exception pinging ${e}:`, s), clearTimeout(o), r(s);
|
|
779
779
|
}
|
|
780
780
|
});
|
|
781
781
|
}
|
|
@@ -790,36 +790,36 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
790
790
|
* @param params Resolved discovery params
|
|
791
791
|
*/
|
|
792
792
|
async discoverBodhiExtension(e) {
|
|
793
|
-
const { attempts: t, attemptWaitMs: r, attemptTimeout:
|
|
793
|
+
const { attempts: t, attemptWaitMs: r, attemptTimeout: o } = e;
|
|
794
794
|
this.logger.info(
|
|
795
|
-
`[Ext2Ext/Discovery] Starting discovery: ${t} attempts per ID, ${
|
|
795
|
+
`[Ext2Ext/Discovery] Starting discovery: ${t} attempts per ID, ${o}ms timeout, ${r}ms between attempts`
|
|
796
796
|
);
|
|
797
797
|
const s = this.getExtensionIdsForEnvironment();
|
|
798
798
|
this.logger.debug(
|
|
799
799
|
`[Ext2Ext/Discovery] Will try ${s.length} extension(s):`,
|
|
800
800
|
s
|
|
801
801
|
);
|
|
802
|
-
for (const
|
|
802
|
+
for (const u of s) {
|
|
803
803
|
for (let c = 1; c <= t; c++) {
|
|
804
804
|
this.logger.debug(
|
|
805
|
-
`[Ext2Ext/Discovery] Trying ${
|
|
805
|
+
`[Ext2Ext/Discovery] Trying ${u} - attempt ${c}/${t}`
|
|
806
806
|
);
|
|
807
807
|
try {
|
|
808
|
-
return await this.pingExtension(
|
|
808
|
+
return await this.pingExtension(u), this.logger.info(`[Ext2Ext/Discovery] ✓ Found: ${u} on attempt ${c}`), {
|
|
809
809
|
success: !0,
|
|
810
|
-
extensionId:
|
|
810
|
+
extensionId: u
|
|
811
811
|
};
|
|
812
|
-
} catch (
|
|
812
|
+
} catch (h) {
|
|
813
813
|
this.logger.debug(
|
|
814
|
-
`[Ext2Ext/Discovery] Attempt ${c} failed for ${
|
|
814
|
+
`[Ext2Ext/Discovery] Attempt ${c} failed for ${u}: ${h instanceof Error ? h.message : "Unknown error"}`
|
|
815
815
|
), c < t && await this.sleep(r);
|
|
816
816
|
}
|
|
817
817
|
}
|
|
818
818
|
this.logger.warn(
|
|
819
|
-
`[Ext2Ext/Discovery] ✗ Not found: ${
|
|
819
|
+
`[Ext2Ext/Discovery] ✗ Not found: ${u} after ${t} attempts`
|
|
820
820
|
);
|
|
821
821
|
}
|
|
822
|
-
const
|
|
822
|
+
const i = s.join(", "), n = `Extension not found. Tried ${s.length} IDs with ${t} attempts each: ${i}`;
|
|
823
823
|
return this.logger.error(`[Ext2Ext/Discovery] ${n}`), {
|
|
824
824
|
success: !1,
|
|
825
825
|
error: n
|
|
@@ -853,8 +853,8 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
853
853
|
type: "NOT_INITIALIZED"
|
|
854
854
|
}
|
|
855
855
|
}), !0) : (this.logger.debug(`[BodhiExtClient] Processing message.type=${e.type}`), (async () => {
|
|
856
|
-
const
|
|
857
|
-
r(
|
|
856
|
+
const o = await this.handleAction(e);
|
|
857
|
+
r(o);
|
|
858
858
|
})(), !0)), this.registerStreamPortListener(
|
|
859
859
|
U,
|
|
860
860
|
a.EXT2EXT_CLIENT_STREAM_REQUEST,
|
|
@@ -937,7 +937,7 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
937
937
|
Authorization: `Bearer ${s}`
|
|
938
938
|
}, this.logger.debug("[BodhiExtClient] Injected auth token for authenticated request");
|
|
939
939
|
}
|
|
940
|
-
const
|
|
940
|
+
const o = await this.sendApiRequest(
|
|
941
941
|
e.request.method,
|
|
942
942
|
e.request.endpoint,
|
|
943
943
|
e.request.body,
|
|
@@ -946,7 +946,7 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
946
946
|
return {
|
|
947
947
|
type: a.EXT2EXT_CLIENT_API_RESPONSE,
|
|
948
948
|
requestId: t,
|
|
949
|
-
response:
|
|
949
|
+
response: o
|
|
950
950
|
};
|
|
951
951
|
} catch (r) {
|
|
952
952
|
return this.logger.error("[BodhiExtClient] API request failed:", r), {
|
|
@@ -966,17 +966,17 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
966
966
|
* @returns Action response message (success or error)
|
|
967
967
|
*/
|
|
968
968
|
async handleExtClientRequest(e) {
|
|
969
|
-
const { requestId: t, request: r } = e, { action:
|
|
970
|
-
this.logger.debug(`[BodhiExtClient] Handling action: ${
|
|
969
|
+
const { requestId: t, request: r } = e, { action: o, params: s } = r;
|
|
970
|
+
this.logger.debug(`[BodhiExtClient] Handling action: ${o}`);
|
|
971
971
|
try {
|
|
972
|
-
let
|
|
973
|
-
switch (
|
|
972
|
+
let i = {};
|
|
973
|
+
switch (o) {
|
|
974
974
|
case m.DISCOVER_EXTENSION: {
|
|
975
975
|
const n = s;
|
|
976
976
|
await this.init(n), this.logger.info("[BodhiExtClient] Discovery successful:", {
|
|
977
977
|
extensionId: this.extensionId,
|
|
978
978
|
environment: I
|
|
979
|
-
}),
|
|
979
|
+
}), i = {
|
|
980
980
|
extensionId: this.extensionId,
|
|
981
981
|
environment: I
|
|
982
982
|
};
|
|
@@ -984,12 +984,12 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
984
984
|
}
|
|
985
985
|
case m.SET_EXTENSION_ID: {
|
|
986
986
|
const { extensionId: n } = s;
|
|
987
|
-
this.extensionId = n, this.state = "ready", this.logger.info("[BodhiExtClient] Extension ID set:", { extensionId: n }),
|
|
987
|
+
this.extensionId = n, this.state = "ready", this.logger.info("[BodhiExtClient] Extension ID set:", { extensionId: n }), i = { success: !0 };
|
|
988
988
|
break;
|
|
989
989
|
}
|
|
990
990
|
case m.GET_EXTENSION_ID: {
|
|
991
|
-
const n = await this.sendExtRequestRaw(
|
|
992
|
-
return
|
|
991
|
+
const n = await this.sendExtRequestRaw(ie.GET_EXTENSION_ID, s);
|
|
992
|
+
return x(n.response) ? {
|
|
993
993
|
type: a.EXT2EXT_CLIENT_RESPONSE,
|
|
994
994
|
requestId: t,
|
|
995
995
|
response: {
|
|
@@ -1013,29 +1013,29 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1013
1013
|
await this.logout(), this.broadcastAuthStateChange();
|
|
1014
1014
|
break;
|
|
1015
1015
|
case m.GET_AUTH_STATE:
|
|
1016
|
-
|
|
1016
|
+
i = { authState: await this.getAuthState() };
|
|
1017
1017
|
break;
|
|
1018
1018
|
default:
|
|
1019
1019
|
return {
|
|
1020
1020
|
type: a.EXT2EXT_CLIENT_RESPONSE,
|
|
1021
1021
|
requestId: t,
|
|
1022
1022
|
response: {
|
|
1023
|
-
error: { message: `Unknown action: ${
|
|
1023
|
+
error: { message: `Unknown action: ${o}`, type: "UNKNOWN_ACTION" }
|
|
1024
1024
|
}
|
|
1025
1025
|
};
|
|
1026
1026
|
}
|
|
1027
1027
|
return {
|
|
1028
1028
|
type: a.EXT2EXT_CLIENT_RESPONSE,
|
|
1029
1029
|
requestId: t,
|
|
1030
|
-
response:
|
|
1030
|
+
response: i
|
|
1031
1031
|
};
|
|
1032
|
-
} catch (
|
|
1033
|
-
return this.logger.error("[BodhiExtClient] Unexpected error:",
|
|
1032
|
+
} catch (i) {
|
|
1033
|
+
return this.logger.error("[BodhiExtClient] Unexpected error:", i), {
|
|
1034
1034
|
type: a.EXT2EXT_CLIENT_RESPONSE,
|
|
1035
1035
|
requestId: t,
|
|
1036
1036
|
response: {
|
|
1037
1037
|
error: {
|
|
1038
|
-
message:
|
|
1038
|
+
message: i instanceof Error ? i.message : `Unexpected error: ${JSON.stringify(i)}`
|
|
1039
1039
|
}
|
|
1040
1040
|
}
|
|
1041
1041
|
};
|
|
@@ -1072,25 +1072,25 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1072
1072
|
* @throws Error if login fails
|
|
1073
1073
|
*/
|
|
1074
1074
|
async login(e) {
|
|
1075
|
-
if (!(this.isAuthenticating || (await this.getAuthState()).status === "authenticated")) {
|
|
1076
|
-
this.isAuthenticating = !0;
|
|
1075
|
+
if (!(this.isAuthenticating || (await this.getAuthState()).status === "authenticated" && !e?.exchange)) {
|
|
1076
|
+
this.isAuthenticating = !0, this.isExchanging = e?.exchange ?? !1;
|
|
1077
1077
|
try {
|
|
1078
1078
|
if (!this.extensionId)
|
|
1079
1079
|
throw new Error("Extension not discovered. Please detect Bodhi extension before login.");
|
|
1080
|
-
const r = e?.userRole ?? "scope_user_user",
|
|
1080
|
+
const r = e?.userRole ?? "scope_user_user", o = chrome.identity.getRedirectURL("callback"), s = p.generateCodeVerifier(), i = await p.generateCodeChallenge(s), n = p.generateCodeVerifier();
|
|
1081
1081
|
await chrome.storage.session.set({ codeVerifier: s, state: n, authInProgress: !0 });
|
|
1082
|
-
const
|
|
1082
|
+
const u = v(this.authEndpoints, {
|
|
1083
1083
|
clientId: this.authClientId,
|
|
1084
|
-
redirectUri:
|
|
1084
|
+
redirectUri: o,
|
|
1085
1085
|
scope: L,
|
|
1086
1086
|
state: n,
|
|
1087
|
-
codeChallenge:
|
|
1088
|
-
}), c = b(
|
|
1089
|
-
e?.requested &&
|
|
1090
|
-
const
|
|
1087
|
+
codeChallenge: i
|
|
1088
|
+
}), c = b(o), h = new k(this.authClientId).requestedRole(r);
|
|
1089
|
+
e?.requested && h.requested(e.requested), e?.exchange && h.exchange(!0);
|
|
1090
|
+
const E = await this.requestAccess(h.build()), { review_url: d } = P(E), g = O(d, u, c), S = await this.launchReview(g);
|
|
1091
1091
|
await this.completeOAuthRedirect(S);
|
|
1092
1092
|
} finally {
|
|
1093
|
-
this.isAuthenticating = !1;
|
|
1093
|
+
this.isAuthenticating = !1, this.isExchanging = !1;
|
|
1094
1094
|
}
|
|
1095
1095
|
}
|
|
1096
1096
|
}
|
|
@@ -1099,9 +1099,9 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1099
1099
|
* @param code Authorization code from OAuth callback
|
|
1100
1100
|
*/
|
|
1101
1101
|
async exchangeCodeForTokens(e) {
|
|
1102
|
-
if ((await this.getAuthState()).status === "authenticated")
|
|
1102
|
+
if ((await this.getAuthState()).status === "authenticated" && !this.isExchanging)
|
|
1103
1103
|
return;
|
|
1104
|
-
const { codeVerifier: r } = await chrome.storage.session.get("codeVerifier"),
|
|
1104
|
+
const { codeVerifier: r } = await chrome.storage.session.get("codeVerifier"), o = chrome.identity.getRedirectURL("callback"), s = await fetch(this.authEndpoints.token, {
|
|
1105
1105
|
method: "POST",
|
|
1106
1106
|
headers: {
|
|
1107
1107
|
"Content-Type": "application/x-www-form-urlencoded"
|
|
@@ -1109,7 +1109,7 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1109
1109
|
body: new URLSearchParams({
|
|
1110
1110
|
grant_type: "authorization_code",
|
|
1111
1111
|
code: e,
|
|
1112
|
-
redirect_uri:
|
|
1112
|
+
redirect_uri: o,
|
|
1113
1113
|
client_id: this.authClientId,
|
|
1114
1114
|
code_verifier: r
|
|
1115
1115
|
})
|
|
@@ -1118,12 +1118,12 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1118
1118
|
const n = await s.text();
|
|
1119
1119
|
throw new Error(`Token exchange failed: ${s.status} ${n}`);
|
|
1120
1120
|
}
|
|
1121
|
-
const
|
|
1121
|
+
const i = await s.json();
|
|
1122
1122
|
await this.storeTokens({
|
|
1123
|
-
accessToken:
|
|
1124
|
-
refreshToken:
|
|
1125
|
-
idToken:
|
|
1126
|
-
expiresIn:
|
|
1123
|
+
accessToken: i.access_token,
|
|
1124
|
+
refreshToken: i.refresh_token,
|
|
1125
|
+
idToken: i.id_token,
|
|
1126
|
+
expiresIn: i.expires_in
|
|
1127
1127
|
});
|
|
1128
1128
|
}
|
|
1129
1129
|
/**
|
|
@@ -1203,35 +1203,37 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1203
1203
|
return this.sendApiRequest(
|
|
1204
1204
|
"POST",
|
|
1205
1205
|
"/bodhi/v1/apps/request-access",
|
|
1206
|
-
e
|
|
1206
|
+
e,
|
|
1207
|
+
void 0,
|
|
1208
|
+
!0
|
|
1207
1209
|
);
|
|
1208
1210
|
}
|
|
1209
1211
|
launchReview(e) {
|
|
1210
1212
|
return new Promise((t, r) => {
|
|
1211
|
-
chrome.identity.launchWebAuthFlow({ url: e, interactive: !0 }, async (
|
|
1213
|
+
chrome.identity.launchWebAuthFlow({ url: e, interactive: !0 }, async (o) => {
|
|
1212
1214
|
if (await chrome.storage.session.set({ authInProgress: !1 }), chrome.runtime.lastError) {
|
|
1213
1215
|
await chrome.storage.session.remove(["codeVerifier", "state"]), r(chrome.runtime.lastError);
|
|
1214
1216
|
return;
|
|
1215
1217
|
}
|
|
1216
|
-
if (!
|
|
1217
|
-
await chrome.storage.session.remove(["codeVerifier", "state"]), r(
|
|
1218
|
+
if (!o) {
|
|
1219
|
+
await chrome.storage.session.remove(["codeVerifier", "state"]), r(l("oauth_error", "No redirect URL received"));
|
|
1218
1220
|
return;
|
|
1219
1221
|
}
|
|
1220
|
-
t(
|
|
1222
|
+
t(o);
|
|
1221
1223
|
});
|
|
1222
1224
|
});
|
|
1223
1225
|
}
|
|
1224
1226
|
async completeOAuthRedirect(e) {
|
|
1225
1227
|
const t = new URL(e), r = t.searchParams.get("error");
|
|
1226
1228
|
if (r)
|
|
1227
|
-
throw await chrome.storage.session.remove(["codeVerifier", "state"]), t.searchParams.get("error_source") === "bodhi" && M(r === "access_denied" ? "denied" : r),
|
|
1228
|
-
const
|
|
1229
|
-
if (!s || s !==
|
|
1230
|
-
throw await chrome.storage.session.remove(["codeVerifier", "state"]),
|
|
1231
|
-
if (!
|
|
1232
|
-
throw await chrome.storage.session.remove(["codeVerifier", "state"]),
|
|
1233
|
-
if (await this.exchangeCodeForTokens(
|
|
1234
|
-
throw
|
|
1229
|
+
throw await chrome.storage.session.remove(["codeVerifier", "state"]), t.searchParams.get("error_source") === "bodhi" && M(r === "access_denied" ? "denied" : r), l("oauth_error", t.searchParams.get("error_description") ?? r);
|
|
1230
|
+
const o = t.searchParams.get("code"), s = t.searchParams.get("state"), { state: i } = await chrome.storage.session.get("state");
|
|
1231
|
+
if (!s || s !== i)
|
|
1232
|
+
throw await chrome.storage.session.remove(["codeVerifier", "state"]), l("oauth_error", "State mismatch");
|
|
1233
|
+
if (!o)
|
|
1234
|
+
throw await chrome.storage.session.remove(["codeVerifier", "state"]), l("oauth_error", "No authorization code");
|
|
1235
|
+
if (await this.exchangeCodeForTokens(o), await chrome.storage.session.remove(["codeVerifier", "state"]), (await this.getAuthState()).status !== "authenticated")
|
|
1236
|
+
throw l("oauth_error", "Login failed");
|
|
1235
1237
|
}
|
|
1236
1238
|
// Ext2Ext Communication (Private Methods)
|
|
1237
1239
|
// ============================================================================
|
|
@@ -1243,7 +1245,7 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1243
1245
|
*/
|
|
1244
1246
|
async sendExtRequest(e, t) {
|
|
1245
1247
|
const r = await this.sendExtRequestRaw(e, t);
|
|
1246
|
-
if (
|
|
1248
|
+
if (x(r.response))
|
|
1247
1249
|
throw this.logger.error("[BodhiExtClient] Extension error:", r.response.error), new Error(
|
|
1248
1250
|
r.response.error.message || `Extension request failed: ${JSON.stringify(r.response)}`
|
|
1249
1251
|
);
|
|
@@ -1255,9 +1257,10 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1255
1257
|
* @param endpoint API endpoint path
|
|
1256
1258
|
* @param body Optional request body
|
|
1257
1259
|
* @param headers Optional headers
|
|
1260
|
+
* @param authenticated Attach the current token when one exists (safe: skipped if none)
|
|
1258
1261
|
* @returns API response from LLM server via bodhi-browser-ext
|
|
1259
1262
|
*/
|
|
1260
|
-
async sendApiRequest(e, t, r,
|
|
1263
|
+
async sendApiRequest(e, t, r, o, s = !1) {
|
|
1261
1264
|
if (!this.extensionId)
|
|
1262
1265
|
throw new T(
|
|
1263
1266
|
"not_initialized",
|
|
@@ -1267,9 +1270,14 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1267
1270
|
`[BodhiExtClient] Sending API_REQUEST: method=${e}, endpoint=${t}`,
|
|
1268
1271
|
r ? { body: r } : ""
|
|
1269
1272
|
);
|
|
1270
|
-
|
|
1273
|
+
let i = o;
|
|
1274
|
+
if (s) {
|
|
1275
|
+
const c = await this._getAccessTokenRaw();
|
|
1276
|
+
c && (i = { ...o, Authorization: `Bearer ${c}` });
|
|
1277
|
+
}
|
|
1278
|
+
const n = crypto.randomUUID(), u = {
|
|
1271
1279
|
type: _.API_REQUEST,
|
|
1272
|
-
requestId:
|
|
1280
|
+
requestId: n,
|
|
1273
1281
|
request: {
|
|
1274
1282
|
method: e,
|
|
1275
1283
|
endpoint: t,
|
|
@@ -1277,12 +1285,12 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1277
1285
|
headers: i
|
|
1278
1286
|
}
|
|
1279
1287
|
};
|
|
1280
|
-
return this.logger.debug(`[BodhiExtClient] Request ID: ${
|
|
1288
|
+
return this.logger.debug(`[BodhiExtClient] Request ID: ${n}, Extension: ${this.extensionId}`), new Promise((c, h) => {
|
|
1281
1289
|
try {
|
|
1282
|
-
chrome.runtime.sendMessage(this.extensionId,
|
|
1290
|
+
chrome.runtime.sendMessage(this.extensionId, u, (E) => {
|
|
1283
1291
|
if (chrome.runtime.lastError) {
|
|
1284
1292
|
this.logger.error(
|
|
1285
|
-
`[BodhiExtClient] Chrome runtime error for request ${
|
|
1293
|
+
`[BodhiExtClient] Chrome runtime error for request ${n}:`,
|
|
1286
1294
|
chrome.runtime.lastError
|
|
1287
1295
|
), h(
|
|
1288
1296
|
new T(
|
|
@@ -1292,19 +1300,19 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1292
1300
|
);
|
|
1293
1301
|
return;
|
|
1294
1302
|
}
|
|
1295
|
-
if (this.logger.debug(`[BodhiExtClient] Response for request ${
|
|
1296
|
-
this.logger.error(`[BodhiExtClient] No response received for request ${
|
|
1303
|
+
if (this.logger.debug(`[BodhiExtClient] Response for request ${n}:`, E), !E) {
|
|
1304
|
+
this.logger.error(`[BodhiExtClient] No response received for request ${n}`), h(new T("extension_error", "No response from extension"));
|
|
1297
1305
|
return;
|
|
1298
1306
|
}
|
|
1299
|
-
|
|
1300
|
-
new T(
|
|
1301
|
-
)) : (this.logger.debug(`[BodhiExtClient] ✓ Valid API_RESPONSE for ${
|
|
1302
|
-
`[BodhiExtClient] Invalid response format for ${
|
|
1303
|
-
|
|
1307
|
+
E.type === _.API_RESPONSE && E.requestId === n ? "error" in E ? (this.logger.error(`[BodhiExtClient] API error for ${n}:`, E.error), h(
|
|
1308
|
+
new T(E.error.type || "extension_error", E.error.message)
|
|
1309
|
+
)) : (this.logger.debug(`[BodhiExtClient] ✓ Valid API_RESPONSE for ${n}`), c(E.response)) : (this.logger.error(
|
|
1310
|
+
`[BodhiExtClient] Invalid response format for ${n}:`,
|
|
1311
|
+
E
|
|
1304
1312
|
), h(new T("extension_error", "Invalid response format")));
|
|
1305
1313
|
});
|
|
1306
|
-
} catch (
|
|
1307
|
-
this.logger.error(`[BodhiExtClient] Exception sending message for ${
|
|
1314
|
+
} catch (E) {
|
|
1315
|
+
this.logger.error(`[BodhiExtClient] Exception sending message for ${n}:`, E), h(E);
|
|
1308
1316
|
}
|
|
1309
1317
|
});
|
|
1310
1318
|
}
|
|
@@ -1324,7 +1332,7 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1324
1332
|
`[BodhiExtClient] Sending EXT_REQUEST (raw): action=${e}`,
|
|
1325
1333
|
t ? { params: t } : ""
|
|
1326
1334
|
);
|
|
1327
|
-
const r = crypto.randomUUID(),
|
|
1335
|
+
const r = crypto.randomUUID(), o = {
|
|
1328
1336
|
type: _.EXT_REQUEST,
|
|
1329
1337
|
requestId: r,
|
|
1330
1338
|
request: {
|
|
@@ -1332,27 +1340,27 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1332
1340
|
params: t
|
|
1333
1341
|
}
|
|
1334
1342
|
};
|
|
1335
|
-
return this.logger.debug(`[BodhiExtClient] Request ID: ${r}, Extension: ${this.extensionId}`), new Promise((s,
|
|
1343
|
+
return this.logger.debug(`[BodhiExtClient] Request ID: ${r}, Extension: ${this.extensionId}`), new Promise((s, i) => {
|
|
1336
1344
|
try {
|
|
1337
|
-
chrome.runtime.sendMessage(this.extensionId,
|
|
1345
|
+
chrome.runtime.sendMessage(this.extensionId, o, (n) => {
|
|
1338
1346
|
if (chrome.runtime.lastError) {
|
|
1339
1347
|
this.logger.error(
|
|
1340
1348
|
`[BodhiExtClient] Chrome runtime error for request ${r}:`,
|
|
1341
1349
|
chrome.runtime.lastError
|
|
1342
|
-
),
|
|
1350
|
+
), i(new Error(chrome.runtime.lastError.message));
|
|
1343
1351
|
return;
|
|
1344
1352
|
}
|
|
1345
1353
|
if (this.logger.debug(`[BodhiExtClient] Response for request ${r}:`, n), !n) {
|
|
1346
|
-
this.logger.error(`[BodhiExtClient] No response received for request ${r}`),
|
|
1354
|
+
this.logger.error(`[BodhiExtClient] No response received for request ${r}`), i(new Error("No response from extension"));
|
|
1347
1355
|
return;
|
|
1348
1356
|
}
|
|
1349
1357
|
n.type === _.EXT_RESPONSE && n.requestId === r ? (this.logger.debug(`[BodhiExtClient] ✓ Valid EXT_RESPONSE for ${r}`), s(n)) : (this.logger.error(
|
|
1350
1358
|
`[BodhiExtClient] Invalid response format for ${r}:`,
|
|
1351
1359
|
n
|
|
1352
|
-
),
|
|
1360
|
+
), i(new T("extension_error", "Invalid response format")));
|
|
1353
1361
|
});
|
|
1354
1362
|
} catch (n) {
|
|
1355
|
-
this.logger.error(`[BodhiExtClient] Exception sending message for ${r}:`, n),
|
|
1363
|
+
this.logger.error(`[BodhiExtClient] Exception sending message for ${r}:`, n), i(n);
|
|
1356
1364
|
}
|
|
1357
1365
|
});
|
|
1358
1366
|
}
|
|
@@ -1360,18 +1368,18 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1360
1368
|
* Register a chrome.runtime.onConnect listener for a streaming port.
|
|
1361
1369
|
* Validates port name and message type, then delegates to handler.
|
|
1362
1370
|
*/
|
|
1363
|
-
registerStreamPortListener(e, t, r,
|
|
1371
|
+
registerStreamPortListener(e, t, r, o) {
|
|
1364
1372
|
chrome.runtime.onConnect.addListener((s) => {
|
|
1365
|
-
s.name === e && (this.logger.info(`[BodhiExtClient] Port connected: ${e}`), s.onMessage.addListener(async (
|
|
1366
|
-
if (
|
|
1367
|
-
this.logger.warn(`[BodhiExtClient] Unknown message type on ${e}:`,
|
|
1373
|
+
s.name === e && (this.logger.info(`[BodhiExtClient] Port connected: ${e}`), s.onMessage.addListener(async (i) => {
|
|
1374
|
+
if (i.type !== t) {
|
|
1375
|
+
this.logger.warn(`[BodhiExtClient] Unknown message type on ${e}:`, i.type), s.postMessage({
|
|
1368
1376
|
type: r,
|
|
1369
|
-
requestId:
|
|
1377
|
+
requestId: i.requestId,
|
|
1370
1378
|
error: { message: "Unknown message type", type: "extension_error" }
|
|
1371
1379
|
});
|
|
1372
1380
|
return;
|
|
1373
1381
|
}
|
|
1374
|
-
await
|
|
1382
|
+
await o(s, i);
|
|
1375
1383
|
}), s.onDisconnect.addListener(() => {
|
|
1376
1384
|
this.logger.info(`[BodhiExtClient] Port disconnected: ${e}`);
|
|
1377
1385
|
}));
|
|
@@ -1385,48 +1393,48 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1385
1393
|
* @param onBodhiMessage Called for each message from bodhi-browser-ext.
|
|
1386
1394
|
* Returns true if the stream is complete (triggers cleanup).
|
|
1387
1395
|
*/
|
|
1388
|
-
async handleGenericStreamRelay(e, t, r,
|
|
1396
|
+
async handleGenericStreamRelay(e, t, r, o, s, i, n) {
|
|
1389
1397
|
if (this.logger.debug("[BodhiExtClient] Processing stream relay:", {
|
|
1390
1398
|
requestId: t,
|
|
1391
1399
|
method: r.method,
|
|
1392
1400
|
endpoint: r.endpoint,
|
|
1393
|
-
bodhiPortName:
|
|
1401
|
+
bodhiPortName: o
|
|
1394
1402
|
}), !this.extensionId) {
|
|
1395
1403
|
e.postMessage({
|
|
1396
|
-
type:
|
|
1404
|
+
type: i,
|
|
1397
1405
|
requestId: t,
|
|
1398
1406
|
error: { message: "Client not initialized (no extensionId)", type: "extension_error" }
|
|
1399
1407
|
});
|
|
1400
1408
|
return;
|
|
1401
1409
|
}
|
|
1402
1410
|
try {
|
|
1403
|
-
let
|
|
1411
|
+
let u = { ...r.headers };
|
|
1404
1412
|
if (r.authenticated !== !1) {
|
|
1405
|
-
const
|
|
1406
|
-
if (!
|
|
1413
|
+
const d = await this._getAccessTokenRaw();
|
|
1414
|
+
if (!d) {
|
|
1407
1415
|
e.postMessage({
|
|
1408
|
-
type:
|
|
1416
|
+
type: i,
|
|
1409
1417
|
requestId: t,
|
|
1410
1418
|
error: { message: "Not authenticated. Please log in first.", type: "extension_error" }
|
|
1411
1419
|
});
|
|
1412
1420
|
return;
|
|
1413
1421
|
}
|
|
1414
|
-
|
|
1422
|
+
u = { ...u, Authorization: `Bearer ${d}` }, this.logger.debug("[BodhiExtClient] Injected auth token for stream relay");
|
|
1415
1423
|
}
|
|
1416
|
-
const c = chrome.runtime.connect(this.extensionId, { name:
|
|
1424
|
+
const c = chrome.runtime.connect(this.extensionId, { name: o });
|
|
1417
1425
|
this.activeStreamPorts.set(t, c);
|
|
1418
|
-
const
|
|
1426
|
+
const h = setTimeout(() => {
|
|
1419
1427
|
this.activeStreamPorts.has(t) && (this.logger.error(`[BodhiExtClient] Stream timeout for ${t}`), e.postMessage({
|
|
1420
|
-
type:
|
|
1428
|
+
type: i,
|
|
1421
1429
|
requestId: t,
|
|
1422
1430
|
error: { message: "Stream request timed out", type: "timeout_error" }
|
|
1423
1431
|
}), this.cleanupStreamPort(t));
|
|
1424
1432
|
}, p.STREAM_TIMEOUT);
|
|
1425
|
-
c.onMessage.addListener((
|
|
1426
|
-
n(
|
|
1433
|
+
c.onMessage.addListener((d) => {
|
|
1434
|
+
n(d, e, t) && (clearTimeout(h), this.cleanupStreamPort(t));
|
|
1427
1435
|
}), c.onDisconnect.addListener(() => {
|
|
1428
|
-
clearTimeout(
|
|
1429
|
-
type:
|
|
1436
|
+
clearTimeout(h), this.activeStreamPorts.has(t) && (this.logger.error(`[BodhiExtClient] Bodhi port disconnected for ${t}`), e.postMessage({
|
|
1437
|
+
type: i,
|
|
1430
1438
|
requestId: t,
|
|
1431
1439
|
error: {
|
|
1432
1440
|
message: "Connection to Bodhi extension closed unexpectedly",
|
|
@@ -1434,21 +1442,21 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1434
1442
|
}
|
|
1435
1443
|
}), this.activeStreamPorts.delete(t));
|
|
1436
1444
|
});
|
|
1437
|
-
const
|
|
1445
|
+
const E = {
|
|
1438
1446
|
type: s,
|
|
1439
1447
|
requestId: t,
|
|
1440
1448
|
request: {
|
|
1441
1449
|
method: r.method,
|
|
1442
1450
|
endpoint: r.endpoint,
|
|
1443
1451
|
body: r.body,
|
|
1444
|
-
headers:
|
|
1452
|
+
headers: u
|
|
1445
1453
|
}
|
|
1446
1454
|
};
|
|
1447
|
-
this.logger.debug("[BodhiExtClient] Sending stream request to bodhi port:",
|
|
1448
|
-
} catch (
|
|
1449
|
-
const c =
|
|
1455
|
+
this.logger.debug("[BodhiExtClient] Sending stream request to bodhi port:", E), c.postMessage(E);
|
|
1456
|
+
} catch (u) {
|
|
1457
|
+
const c = u;
|
|
1450
1458
|
this.logger.error("[BodhiExtClient] Stream relay error:", JSON.stringify(c.message)), e.postMessage({
|
|
1451
|
-
type:
|
|
1459
|
+
type: i,
|
|
1452
1460
|
requestId: t,
|
|
1453
1461
|
error: {
|
|
1454
1462
|
message: `uncaught error: ${JSON.stringify({ error: c, message: c.message })}`,
|
|
@@ -1474,34 +1482,34 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1474
1482
|
* Handle SSE-parsed streaming request — translates STREAM_* messages to EXT2EXT_CLIENT_STREAM_*
|
|
1475
1483
|
*/
|
|
1476
1484
|
async handleStreamRequest(e, t) {
|
|
1477
|
-
const { requestId: r, request:
|
|
1485
|
+
const { requestId: r, request: o } = t;
|
|
1478
1486
|
await this.handleGenericStreamRelay(
|
|
1479
1487
|
e,
|
|
1480
1488
|
r,
|
|
1481
|
-
|
|
1482
|
-
|
|
1489
|
+
o,
|
|
1490
|
+
ne,
|
|
1483
1491
|
_.STREAM_REQUEST,
|
|
1484
1492
|
a.EXT2EXT_CLIENT_STREAM_ERROR,
|
|
1485
|
-
(s,
|
|
1486
|
-
if (
|
|
1487
|
-
const
|
|
1488
|
-
return
|
|
1493
|
+
(s, i, n) => {
|
|
1494
|
+
if (oe(s)) {
|
|
1495
|
+
const u = s.response, c = u.body;
|
|
1496
|
+
return u.status >= 400 ? (i.postMessage({
|
|
1489
1497
|
type: a.EXT2EXT_CLIENT_STREAM_API_ERROR,
|
|
1490
1498
|
requestId: n,
|
|
1491
|
-
response:
|
|
1492
|
-
}), !1) : c?.done ? (
|
|
1499
|
+
response: u
|
|
1500
|
+
}), !1) : c?.done ? (i.postMessage({
|
|
1493
1501
|
type: a.EXT2EXT_CLIENT_STREAM_DONE,
|
|
1494
1502
|
requestId: n
|
|
1495
|
-
}), this.logger.info(`[BodhiExtClient] Stream complete for ${n}`), !0) : (
|
|
1503
|
+
}), this.logger.info(`[BodhiExtClient] Stream complete for ${n}`), !0) : (i.postMessage({
|
|
1496
1504
|
type: a.EXT2EXT_CLIENT_STREAM_CHUNK,
|
|
1497
1505
|
requestId: n,
|
|
1498
|
-
response:
|
|
1506
|
+
response: u
|
|
1499
1507
|
}), !1);
|
|
1500
1508
|
} else {
|
|
1501
1509
|
if (ae(s))
|
|
1502
1510
|
return this.logger.error(
|
|
1503
1511
|
`[BodhiExtClient] Stream API error for ${n}: ${s.response.status}`
|
|
1504
|
-
),
|
|
1512
|
+
), i.postMessage({
|
|
1505
1513
|
type: a.EXT2EXT_CLIENT_STREAM_API_ERROR,
|
|
1506
1514
|
requestId: n,
|
|
1507
1515
|
response: s.response
|
|
@@ -1510,7 +1518,7 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1510
1518
|
return this.logger.error(
|
|
1511
1519
|
`[BodhiExtClient] Stream error for ${n}:`,
|
|
1512
1520
|
s.error.message
|
|
1513
|
-
),
|
|
1521
|
+
), i.postMessage({
|
|
1514
1522
|
type: a.EXT2EXT_CLIENT_STREAM_ERROR,
|
|
1515
1523
|
requestId: n,
|
|
1516
1524
|
error: {
|
|
@@ -1527,31 +1535,31 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1527
1535
|
* Handle raw text streaming request — translates STREAM_TEXT_* messages to EXT2EXT_CLIENT_STREAM_TEXT_*
|
|
1528
1536
|
*/
|
|
1529
1537
|
async handleStreamTextRequest(e, t) {
|
|
1530
|
-
const { requestId: r, request:
|
|
1538
|
+
const { requestId: r, request: o } = t;
|
|
1531
1539
|
await this.handleGenericStreamRelay(
|
|
1532
1540
|
e,
|
|
1533
1541
|
r,
|
|
1534
|
-
|
|
1542
|
+
o,
|
|
1535
1543
|
he,
|
|
1536
1544
|
_.STREAM_TEXT_REQUEST,
|
|
1537
1545
|
a.EXT2EXT_CLIENT_STREAM_TEXT_ERROR,
|
|
1538
|
-
(s,
|
|
1546
|
+
(s, i, n) => {
|
|
1539
1547
|
switch (s.type) {
|
|
1540
1548
|
case _.STREAM_TEXT_START:
|
|
1541
|
-
return
|
|
1549
|
+
return i.postMessage({
|
|
1542
1550
|
type: a.EXT2EXT_CLIENT_STREAM_TEXT_START,
|
|
1543
1551
|
requestId: n,
|
|
1544
1552
|
status: s.status,
|
|
1545
1553
|
headers: s.headers
|
|
1546
1554
|
}), !1;
|
|
1547
1555
|
case _.STREAM_TEXT_CHUNK:
|
|
1548
|
-
return
|
|
1556
|
+
return i.postMessage({
|
|
1549
1557
|
type: a.EXT2EXT_CLIENT_STREAM_TEXT_CHUNK,
|
|
1550
1558
|
requestId: n,
|
|
1551
1559
|
chunk: s.chunk
|
|
1552
1560
|
}), !1;
|
|
1553
1561
|
case _.STREAM_TEXT_DONE:
|
|
1554
|
-
return this.logger.info(`[BodhiExtClient] Stream text complete for ${n}`),
|
|
1562
|
+
return this.logger.info(`[BodhiExtClient] Stream text complete for ${n}`), i.postMessage({
|
|
1555
1563
|
type: a.EXT2EXT_CLIENT_STREAM_TEXT_DONE,
|
|
1556
1564
|
requestId: n
|
|
1557
1565
|
}), !0;
|
|
@@ -1559,7 +1567,7 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1559
1567
|
return this.logger.error(
|
|
1560
1568
|
`[BodhiExtClient] Stream text error for ${n}:`,
|
|
1561
1569
|
s.error.message
|
|
1562
|
-
),
|
|
1570
|
+
), i.postMessage({
|
|
1563
1571
|
type: a.EXT2EXT_CLIENT_STREAM_TEXT_ERROR,
|
|
1564
1572
|
requestId: n,
|
|
1565
1573
|
error: s.error
|
|
@@ -1626,7 +1634,7 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1626
1634
|
} catch (t) {
|
|
1627
1635
|
this.logger.warn("Token refresh failed:", t);
|
|
1628
1636
|
}
|
|
1629
|
-
throw this.logger.warn("Token refresh failed, keeping tokens for manual retry"),
|
|
1637
|
+
throw this.logger.warn("Token refresh failed, keeping tokens for manual retry"), l(
|
|
1630
1638
|
"auth_error",
|
|
1631
1639
|
"Access token expired and unable to refresh. Try logging out and logging in again."
|
|
1632
1640
|
);
|
|
@@ -1654,10 +1662,10 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1654
1662
|
]);
|
|
1655
1663
|
}
|
|
1656
1664
|
parseJwt(e) {
|
|
1657
|
-
const r = e.split(".")[1].replace(/-/g, "+").replace(/_/g, "/"),
|
|
1665
|
+
const r = e.split(".")[1].replace(/-/g, "+").replace(/_/g, "/"), o = decodeURIComponent(
|
|
1658
1666
|
atob(r).split("").map((s) => "%" + ("00" + s.charCodeAt(0).toString(16)).slice(-2)).join("")
|
|
1659
1667
|
);
|
|
1660
|
-
return JSON.parse(
|
|
1668
|
+
return JSON.parse(o);
|
|
1661
1669
|
}
|
|
1662
1670
|
createErrorClientNotInitialized(e) {
|
|
1663
1671
|
return `Client not initialized. Extension discovery not triggered nor extensionId set, cannot handle request: ${JSON.stringify(e)}`;
|
|
@@ -1665,7 +1673,7 @@ const Se = ["ggedphdcbekjlomjaidbajglgihbeaon"], Re = ["bjdjhiombmfbcoeojijpfckl
|
|
|
1665
1673
|
};
|
|
1666
1674
|
p.STREAM_TIMEOUT = 6e4;
|
|
1667
1675
|
let A = p;
|
|
1668
|
-
const
|
|
1676
|
+
const ye = "production";
|
|
1669
1677
|
export {
|
|
1670
1678
|
A as BodhiExtClient,
|
|
1671
1679
|
_e as ChromeSessionStorageAdapter,
|
|
@@ -1678,8 +1686,8 @@ export {
|
|
|
1678
1686
|
a as EXT2EXT_CLIENT_MESSAGE_TYPES,
|
|
1679
1687
|
U as EXT2EXT_CLIENT_STREAM_PORT,
|
|
1680
1688
|
D as EXT2EXT_CLIENT_STREAM_TEXT_PORT,
|
|
1681
|
-
|
|
1682
|
-
|
|
1689
|
+
ye as EXT_BUILD_MODE,
|
|
1690
|
+
xe as ExtUIClient,
|
|
1683
1691
|
Ae as InMemoryStorage,
|
|
1684
1692
|
ge as isExtClientApiError
|
|
1685
1693
|
};
|